core: simplify System.Contract.Call* parameter handling

This commit is contained in:
Evgenii Stratonikov 2020-07-29 11:24:06 +03:00
parent f40aba4cd0
commit 3c99393bef
2 changed files with 18 additions and 19 deletions

View file

@ -457,16 +457,16 @@ func storageContextAsReadOnly(ic *interop.Context, v *vm.VM) error {
// contractCall calls a contract.
func contractCall(ic *interop.Context, v *vm.VM) error {
h := v.Estack().Pop().Bytes()
method := v.Estack().Pop().Item()
args := v.Estack().Pop().Item()
method := v.Estack().Pop().String()
args := v.Estack().Pop().Array()
return contractCallExInternal(ic, v, h, method, args, smartcontract.All)
}
// contractCallEx calls a contract with flags.
func contractCallEx(ic *interop.Context, v *vm.VM) error {
h := v.Estack().Pop().Bytes()
method := v.Estack().Pop().Item()
args := v.Estack().Pop().Item()
method := v.Estack().Pop().String()
args := v.Estack().Pop().Array()
flags := smartcontract.CallFlag(int32(v.Estack().Pop().BigInt().Int64()))
if flags&^smartcontract.All != 0 {
return errors.New("call flags out of range")
@ -474,7 +474,7 @@ func contractCallEx(ic *interop.Context, v *vm.VM) error {
return contractCallExInternal(ic, v, h, method, args, flags)
}
func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stackitem.Item, args stackitem.Item, f smartcontract.CallFlag) error {
func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, name string, args []stackitem.Item, f smartcontract.CallFlag) error {
u, err := util.Uint160DecodeBytesBE(h)
if err != nil {
return errors.New("invalid contract hash")
@ -483,10 +483,6 @@ func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stac
if err != nil {
return errors.New("contract not found")
}
name, err := stackitem.ToString(method)
if err != nil {
return err
}
if strings.HasPrefix(name, "_") {
return errors.New("invalid method name (starts with '_')")
}
@ -501,12 +497,8 @@ func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stac
}
}
arr, ok := args.Value().([]stackitem.Item)
if !ok {
return errors.New("second argument must be an array")
}
if len(arr) != len(md.Parameters) {
return fmt.Errorf("invalid argument count: %d (expected %d)", len(arr), len(md.Parameters))
if len(args) != len(md.Parameters) {
return fmt.Errorf("invalid argument count: %d (expected %d)", len(args), len(md.Parameters))
}
ic.Invocations[u]++
@ -520,10 +512,10 @@ func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stac
}
if isNative {
v.Estack().PushVal(args)
v.Estack().PushVal(method)
v.Estack().PushVal(name)
} else {
for i := len(arr) - 1; i >= 0; i-- {
v.Estack().PushVal(arr[i])
for i := len(args) - 1; i >= 0; i-- {
v.Estack().PushVal(args[i])
}
// use Jump not Call here because context was loaded in LoadScript above.
v.Jump(v.Context(), md.Offset)

View file

@ -443,7 +443,14 @@ func TestContractCall(t *testing.T) {
for i := range args {
v.Estack().PushVal(args[i])
}
require.Error(t, contractCall(ic, v))
// interops can both return error and panic,
// we don't care which kind of error has occured
require.Panics(t, func() {
err := contractCall(ic, v)
if err != nil {
panic(err)
}
})
}
}