vm: simplify NEF loading by providing a special method
Offsets are still handled outside of VM to avoid introducing manifest dependency (that's likely to be circular).
This commit is contained in:
parent
82d2231ea6
commit
29cda5112a
3 changed files with 34 additions and 20 deletions
|
@ -2185,14 +2185,14 @@ func (bc *Blockchain) InitVerificationVM(v *vm.VM, getContract func(util.Uint160
|
|||
if md == nil || md.ReturnType != smartcontract.BoolType {
|
||||
return ErrInvalidVerificationContract
|
||||
}
|
||||
initMD := cs.Manifest.ABI.GetMethod(manifest.MethodInit, 0)
|
||||
v.LoadScriptWithHash(cs.NEF.Script, hash, callflag.ReadOnly)
|
||||
v.Context().NEF = &cs.NEF
|
||||
v.Context().Jump(md.Offset)
|
||||
|
||||
if initMD != nil {
|
||||
v.Call(initMD.Offset)
|
||||
verifyOffset := md.Offset
|
||||
initOffset := -1
|
||||
md = cs.Manifest.ABI.GetMethod(manifest.MethodInit, 0)
|
||||
if md != nil {
|
||||
initOffset = md.Offset
|
||||
}
|
||||
v.LoadNEFMethod(&cs.NEF, util.Uint160{}, hash, callflag.ReadOnly,
|
||||
true, verifyOffset, initOffset)
|
||||
}
|
||||
if len(witness.InvocationScript) != 0 {
|
||||
err := vm.IsScriptCorrect(witness.InvocationScript, nil)
|
||||
|
|
|
@ -112,20 +112,19 @@ func callExFromNative(ic *interop.Context, caller util.Uint160, cs *state.Contra
|
|||
return fmt.Errorf("invalid argument count: %d (expected %d)", len(args), len(md.Parameters))
|
||||
}
|
||||
|
||||
methodOff := md.Offset
|
||||
initOff := -1
|
||||
md = cs.Manifest.ABI.GetMethod(manifest.MethodInit, 0)
|
||||
if md != nil {
|
||||
initOff = md.Offset
|
||||
}
|
||||
ic.VM.Invocations[cs.Hash]++
|
||||
ic.VM.LoadScriptWithCallingHash(caller, cs.NEF.Script, cs.Hash, ic.VM.Context().GetCallFlags()&f, hasReturn)
|
||||
ic.VM.Context().NEF = &cs.NEF
|
||||
ic.VM.LoadNEFMethod(&cs.NEF, caller, cs.Hash, ic.VM.Context().GetCallFlags()&f,
|
||||
hasReturn, methodOff, initOff)
|
||||
|
||||
for e, i := ic.VM.Estack(), len(args)-1; i >= 0; i-- {
|
||||
e.PushItem(args[i])
|
||||
}
|
||||
// Move IP to the target method.
|
||||
ic.VM.Context().Jump(md.Offset)
|
||||
|
||||
md = cs.Manifest.ABI.GetMethod(manifest.MethodInit, 0)
|
||||
if md != nil {
|
||||
ic.VM.Call(md.Offset)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
21
pkg/vm/vm.go
21
pkg/vm/vm.go
|
@ -297,12 +297,27 @@ func (v *VM) LoadScriptWithFlags(b []byte, f callflag.CallFlag) {
|
|||
// each other.
|
||||
func (v *VM) LoadScriptWithHash(b []byte, hash util.Uint160, f callflag.CallFlag) {
|
||||
shash := v.GetCurrentScriptHash()
|
||||
v.LoadScriptWithCallingHash(shash, b, hash, f, true)
|
||||
v.loadScriptWithCallingHash(shash, b, hash, f, true)
|
||||
}
|
||||
|
||||
// LoadScriptWithCallingHash is similar to LoadScriptWithHash but sets calling hash explicitly.
|
||||
// LoadNEFMethod allows to create a context to execute a method from the NEF
|
||||
// file with specified caller and executing hash, call flags, return value,
|
||||
// method and _initialize offsets.
|
||||
func (v *VM) LoadNEFMethod(exe *nef.File, caller util.Uint160, hash util.Uint160, f callflag.CallFlag,
|
||||
hasReturn bool, methodOff int, initOff int) {
|
||||
v.loadScriptWithCallingHash(caller, exe.Script, hash, f, hasReturn)
|
||||
ctx := v.Context()
|
||||
ctx.NEF = exe
|
||||
// Move IP to the target method.
|
||||
ctx.Jump(methodOff)
|
||||
if initOff >= 0 {
|
||||
v.Call(initOff)
|
||||
}
|
||||
}
|
||||
|
||||
// loadScriptWithCallingHash is similar to LoadScriptWithHash but sets calling hash explicitly.
|
||||
// It should be used for calling from native contracts.
|
||||
func (v *VM) LoadScriptWithCallingHash(caller util.Uint160, b []byte, hash util.Uint160,
|
||||
func (v *VM) loadScriptWithCallingHash(caller util.Uint160, b []byte, hash util.Uint160,
|
||||
f callflag.CallFlag, hasReturn bool) {
|
||||
v.LoadScriptWithFlags(b, f)
|
||||
ctx := v.Context()
|
||||
|
|
Loading…
Reference in a new issue