core: introduce CheckReturnState constants

At the moment we should have 3 possible options to check return state
during vm context unloading:
	* no check
	* ensure the stack is empty
	* ensure the stack is not empty

It is necessary to distinguish them because new _deploy method shouldn't
left anything on stack. Example: if we use _deploy method before some
ordinary contract method which returns one value. Without these changes
the contract invocation will fail due to 2 elements on stack left after
invocation (the first `null` element is from _deploy, the second element
is return-value from the ordinary contract method).
This commit is contained in:
Anna Shaleva 2020-10-12 14:32:27 +03:00
parent 659fb89beb
commit fe1f0a7245
5 changed files with 29 additions and 9 deletions

View file

@ -10,6 +10,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
)
@ -51,12 +52,12 @@ func callExInternal(ic *interop.Context, h []byte, name string, args []stackitem
return errors.New("disallowed method call")
}
}
return CallExInternal(ic, cs, name, args, f)
return CallExInternal(ic, cs, name, args, f, vm.EnsureNotEmpty)
}
// CallExInternal calls a contract with flags and can't be invoked directly by user.
func CallExInternal(ic *interop.Context, cs *state.Contract,
name string, args []stackitem.Item, f smartcontract.CallFlag) error {
name string, args []stackitem.Item, f smartcontract.CallFlag, checkReturn vm.CheckReturnState) error {
md := cs.Manifest.ABI.GetMethod(name)
if md == nil {
return fmt.Errorf("method '%s' not found", name)
@ -86,7 +87,7 @@ func CallExInternal(ic *interop.Context, cs *state.Contract,
// use Jump not Call here because context was loaded in LoadScript above.
ic.VM.Jump(ic.VM.Context(), md.Offset)
}
ic.VM.Context().CheckReturn = true
ic.VM.Context().CheckReturn = checkReturn
md = cs.Manifest.ABI.GetMethod(manifest.MethodInit)
if md != nil {