core: make SpawnVM a method of context

spawnVMWithInterops is rather long too type and
it doesn't use Blockchain in any way.
This commit is contained in:
Evgenii Stratonikov 2020-04-07 12:54:43 +03:00
parent a71cd0961e
commit ee0ba9b1b4
3 changed files with 23 additions and 21 deletions

View file

@ -657,7 +657,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
} }
case *transaction.InvocationTX: case *transaction.InvocationTX:
systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx) systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx)
v := bc.spawnVMWithInterops(systemInterop) v := systemInterop.SpawnVM()
v.SetCheckedHash(tx.VerificationHash().BytesBE()) v.SetCheckedHash(tx.VerificationHash().BytesBE())
v.LoadScript(t.Script) v.LoadScript(t.Script)
v.SetPriceGetter(getPrice) 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. // GetTestVM returns a VM and a Store setup for a test run of some sort of code.
func (bc *Blockchain) GetTestVM() *vm.VM { func (bc *Blockchain) GetTestVM() *vm.VM {
systemInterop := bc.newInteropContext(trigger.Application, bc.dao, nil, nil) systemInterop := bc.newInteropContext(trigger.Application, bc.dao, nil, nil)
vm := bc.spawnVMWithInterops(systemInterop) vm := systemInterop.SpawnVM()
vm.SetPriceGetter(getPrice) vm.SetPriceGetter(getPrice)
return vm return vm
} }
@ -2047,7 +2030,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
return err return err
} }
vm := bc.spawnVMWithInterops(interopCtx) vm := interopCtx.SpawnVM()
vm.SetCheckedHash(checkedHash.BytesBE()) vm.SetCheckedHash(checkedHash.BytesBE())
vm.LoadScript(verification) vm.LoadScript(verification)
vm.LoadScript(witness.InvocationScript) vm.LoadScript(witness.InvocationScript)

View file

@ -19,7 +19,7 @@ func TestGetPrice(t *testing.T) {
sdao := dao.NewSimple(storage.NewMemoryStore()) sdao := dao.NewSimple(storage.NewMemoryStore())
systemInterop := bc.newInteropContext(trigger.Application, sdao, nil, nil) systemInterop := bc.newInteropContext(trigger.Application, sdao, nil, nil)
v := bc.spawnVMWithInterops(systemInterop) v := systemInterop.SpawnVM()
v.SetPriceGetter(getPrice) v.SetPriceGetter(getPrice)
t.Run("Neo.Asset.Create", func(t *testing.T) { t.Run("Neo.Asset.Create", func(t *testing.T) {

View file

@ -14,7 +14,9 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/dao" "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/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "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/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
"go.uber.org/zap" "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} 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, // 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 // it's supposed to be inited once for all interopContexts, so it doesn't use
// vm.InteropFuncPrice directly. // vm.InteropFuncPrice directly.