*: support invoking methods by offset
Allow to invoke methods by offset: 1. Every invoked contract must have manifest. 2. Check arguments count on invocation. 3. Change AppCall to a regular syscall. 4. Add test suite for `System.Contract.Call`.
This commit is contained in:
parent
e87eba51f9
commit
d2ddf7b7cb
14 changed files with 272 additions and 117 deletions
166
pkg/rpc/server/testdata/test_contract.go
vendored
166
pkg/rpc/server/testdata/test_contract.go
vendored
|
@ -11,83 +11,91 @@ const (
|
|||
)
|
||||
|
||||
func Main(operation string, args []interface{}) interface{} {
|
||||
runtime.Notify("contract call", operation, args)
|
||||
switch operation {
|
||||
case "Put":
|
||||
ctx := storage.GetContext()
|
||||
storage.Put(ctx, args[0].([]byte), args[1].([]byte))
|
||||
return true
|
||||
case "totalSupply":
|
||||
return totalSupply
|
||||
case "decimals":
|
||||
return decimals
|
||||
case "name":
|
||||
return "Rubl"
|
||||
case "symbol":
|
||||
return "RUB"
|
||||
case "balanceOf":
|
||||
ctx := storage.GetContext()
|
||||
addr := args[0].([]byte)
|
||||
if len(addr) != 20 {
|
||||
runtime.Log("invalid address")
|
||||
return false
|
||||
}
|
||||
var amount int
|
||||
val := storage.Get(ctx, addr)
|
||||
if val != nil {
|
||||
amount = val.(int)
|
||||
}
|
||||
runtime.Notify("balanceOf", addr, amount)
|
||||
return amount
|
||||
case "transfer":
|
||||
ctx := storage.GetContext()
|
||||
from := args[0].([]byte)
|
||||
if len(from) != 20 {
|
||||
runtime.Log("invalid 'from' address")
|
||||
return false
|
||||
}
|
||||
to := args[1].([]byte)
|
||||
if len(to) != 20 {
|
||||
runtime.Log("invalid 'to' address")
|
||||
return false
|
||||
}
|
||||
amount := args[2].(int)
|
||||
if amount < 0 {
|
||||
runtime.Log("invalid amount")
|
||||
return false
|
||||
}
|
||||
|
||||
var fromBalance int
|
||||
val := storage.Get(ctx, from)
|
||||
if val != nil {
|
||||
fromBalance = val.(int)
|
||||
}
|
||||
if fromBalance < amount {
|
||||
runtime.Log("insufficient funds")
|
||||
return false
|
||||
}
|
||||
fromBalance -= amount
|
||||
storage.Put(ctx, from, fromBalance)
|
||||
|
||||
var toBalance int
|
||||
val = storage.Get(ctx, to)
|
||||
if val != nil {
|
||||
toBalance = val.(int)
|
||||
}
|
||||
toBalance += amount
|
||||
storage.Put(ctx, to, toBalance)
|
||||
|
||||
runtime.Notify("transfer", from, to, amount)
|
||||
|
||||
return true
|
||||
case "init":
|
||||
ctx := storage.GetContext()
|
||||
h := runtime.GetExecutingScriptHash()
|
||||
amount := totalSupply
|
||||
storage.Put(ctx, h, amount)
|
||||
runtime.Notify("transfer", []byte{}, h, amount)
|
||||
return true
|
||||
default:
|
||||
panic("invalid operation")
|
||||
}
|
||||
panic("invoking via Main is no longer supported") // catch possible bugs
|
||||
}
|
||||
|
||||
func Init() bool {
|
||||
ctx := storage.GetContext()
|
||||
h := runtime.GetExecutingScriptHash()
|
||||
amount := totalSupply
|
||||
storage.Put(ctx, h, amount)
|
||||
runtime.Notify("transfer", []byte{}, h, amount)
|
||||
return true
|
||||
}
|
||||
|
||||
func Transfer(from, to []byte, amount int) bool {
|
||||
ctx := storage.GetContext()
|
||||
if len(from) != 20 {
|
||||
runtime.Log("invalid 'from' address")
|
||||
return false
|
||||
}
|
||||
if len(to) != 20 {
|
||||
runtime.Log("invalid 'to' address")
|
||||
return false
|
||||
}
|
||||
if amount < 0 {
|
||||
runtime.Log("invalid amount")
|
||||
return false
|
||||
}
|
||||
|
||||
var fromBalance int
|
||||
val := storage.Get(ctx, from)
|
||||
if val != nil {
|
||||
fromBalance = val.(int)
|
||||
}
|
||||
if fromBalance < amount {
|
||||
runtime.Log("insufficient funds")
|
||||
return false
|
||||
}
|
||||
fromBalance -= amount
|
||||
storage.Put(ctx, from, fromBalance)
|
||||
|
||||
var toBalance int
|
||||
val = storage.Get(ctx, to)
|
||||
if val != nil {
|
||||
toBalance = val.(int)
|
||||
}
|
||||
toBalance += amount
|
||||
storage.Put(ctx, to, toBalance)
|
||||
|
||||
runtime.Notify("transfer", from, to, amount)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func BalanceOf(addr []byte) int {
|
||||
ctx := storage.GetContext()
|
||||
if len(addr) != 20 {
|
||||
runtime.Log("invalid address")
|
||||
return 0
|
||||
}
|
||||
var amount int
|
||||
val := storage.Get(ctx, addr)
|
||||
if val != nil {
|
||||
amount = val.(int)
|
||||
}
|
||||
runtime.Notify("balanceOf", addr, amount)
|
||||
return amount
|
||||
}
|
||||
|
||||
func Name() string {
|
||||
return "Rubl"
|
||||
}
|
||||
|
||||
func Symbol() string {
|
||||
return "RUB"
|
||||
}
|
||||
|
||||
func Decimals() int {
|
||||
return decimals
|
||||
}
|
||||
|
||||
func TotalSupply() int {
|
||||
return totalSupply
|
||||
}
|
||||
|
||||
func PutValue(key []byte, value []byte) bool {
|
||||
ctx := storage.GetContext()
|
||||
storage.Put(ctx, key, value)
|
||||
return true
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue