diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 1f05e4fa8..c9e82bf3e 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -657,7 +657,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { } case *transaction.InvocationTX: systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx) - v := bc.spawnVMWithInterops(systemInterop) + v := systemInterop.SpawnVM() v.SetCheckedHash(tx.VerificationHash().BytesBE()) v.LoadScript(t.Script) v.SetPriceGetter(getPrice) @@ -1999,27 +1999,10 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([ } -// spawnVMWithInterops returns a VM with script getter and interop functions set -// up for current blockchain. -func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM { - vm := vm.New() - vm.SetScriptGetter(func(hash util.Uint160) ([]byte, bool) { - cs, err := interopCtx.dao.GetContractState(hash) - if err != nil { - return nil, false - } - hasDynamicInvoke := (cs.Properties & smartcontract.HasDynamicInvoke) != 0 - return cs.Script, hasDynamicInvoke - }) - vm.RegisterInteropGetter(interopCtx.getSystemInterop) - vm.RegisterInteropGetter(interopCtx.getNeoInterop) - return vm -} - // GetTestVM returns a VM and a Store setup for a test run of some sort of code. func (bc *Blockchain) GetTestVM() *vm.VM { systemInterop := bc.newInteropContext(trigger.Application, bc.dao, nil, nil) - vm := bc.spawnVMWithInterops(systemInterop) + vm := systemInterop.SpawnVM() vm.SetPriceGetter(getPrice) return vm } @@ -2047,7 +2030,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa return err } - vm := bc.spawnVMWithInterops(interopCtx) + vm := interopCtx.SpawnVM() vm.SetCheckedHash(checkedHash.BytesBE()) vm.LoadScript(verification) vm.LoadScript(witness.InvocationScript) diff --git a/pkg/core/gas_price_test.go b/pkg/core/gas_price_test.go index fc9f8983f..a8bc2a52b 100644 --- a/pkg/core/gas_price_test.go +++ b/pkg/core/gas_price_test.go @@ -19,7 +19,7 @@ func TestGetPrice(t *testing.T) { sdao := dao.NewSimple(storage.NewMemoryStore()) systemInterop := bc.newInteropContext(trigger.Application, sdao, nil, nil) - v := bc.spawnVMWithInterops(systemInterop) + v := systemInterop.SpawnVM() v.SetPriceGetter(getPrice) t.Run("Neo.Asset.Create", func(t *testing.T) { diff --git a/pkg/core/interops.go b/pkg/core/interops.go index d17382721..445be4d76 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -14,7 +14,9 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/dao" "github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/transaction" + "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" + "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" "go.uber.org/zap" ) @@ -35,6 +37,23 @@ func newInteropContext(trigger trigger.Type, bc Blockchainer, d dao.DAO, block * return &interopContext{bc, trigger, block, tx, dao, nes, log} } +// SpawnVM returns a VM with script getter and interop functions set +// up for current blockchain. +func (ic *interopContext) SpawnVM() *vm.VM { + vm := vm.New() + vm.SetScriptGetter(func(hash util.Uint160) ([]byte, bool) { + cs, err := ic.dao.GetContractState(hash) + if err != nil { + return nil, false + } + hasDynamicInvoke := (cs.Properties & smartcontract.HasDynamicInvoke) != 0 + return cs.Script, hasDynamicInvoke + }) + vm.RegisterInteropGetter(ic.getSystemInterop) + vm.RegisterInteropGetter(ic.getNeoInterop) + return vm +} + // interopedFunction binds function name, id with the function itself and price, // it's supposed to be inited once for all interopContexts, so it doesn't use // vm.InteropFuncPrice directly.