core: remove interop methods from interopContext

If interops are defined as a separate functions
they can be implemented in a separate packages
which can help us to structure core.
This commit is contained in:
Evgenii Stratonikov 2020-04-08 13:29:15 +03:00
parent 6d9c59f7fe
commit efddcf3bfe
7 changed files with 390 additions and 389 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 := systemInterop.SpawnVM() v := SpawnVM(systemInterop)
v.SetCheckedHash(tx.VerificationHash().BytesBE()) v.SetCheckedHash(tx.VerificationHash().BytesBE())
v.LoadScript(t.Script) v.LoadScript(t.Script)
v.SetPriceGetter(getPrice) v.SetPriceGetter(getPrice)
@ -2002,7 +2002,7 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
// 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 := systemInterop.SpawnVM() vm := SpawnVM(systemInterop)
vm.SetPriceGetter(getPrice) vm.SetPriceGetter(getPrice)
return vm return vm
} }
@ -2030,7 +2030,7 @@ func (bc *Blockchain) verifyHashAgainstScript(hash util.Uint160, witness *transa
return err return err
} }
vm := interopCtx.SpawnVM() vm := SpawnVM(interopCtx)
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 := systemInterop.SpawnVM() v := SpawnVM(systemInterop)
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

@ -37,7 +37,7 @@ const (
) )
// headerGetVersion returns version from the header. // headerGetVersion returns version from the header.
func (ic *interopContext) headerGetVersion(v *vm.VM) error { func headerGetVersion(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -47,7 +47,7 @@ func (ic *interopContext) headerGetVersion(v *vm.VM) error {
} }
// headerGetConsensusData returns consensus data from the header. // headerGetConsensusData returns consensus data from the header.
func (ic *interopContext) headerGetConsensusData(v *vm.VM) error { func headerGetConsensusData(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -57,7 +57,7 @@ func (ic *interopContext) headerGetConsensusData(v *vm.VM) error {
} }
// headerGetMerkleRoot returns version from the header. // headerGetMerkleRoot returns version from the header.
func (ic *interopContext) headerGetMerkleRoot(v *vm.VM) error { func headerGetMerkleRoot(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -67,7 +67,7 @@ func (ic *interopContext) headerGetMerkleRoot(v *vm.VM) error {
} }
// headerGetNextConsensus returns version from the header. // headerGetNextConsensus returns version from the header.
func (ic *interopContext) headerGetNextConsensus(v *vm.VM) error { func headerGetNextConsensus(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -77,7 +77,7 @@ func (ic *interopContext) headerGetNextConsensus(v *vm.VM) error {
} }
// txGetAttributes returns current transaction attributes. // txGetAttributes returns current transaction attributes.
func (ic *interopContext) txGetAttributes(v *vm.VM) error { func txGetAttributes(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -95,7 +95,7 @@ func (ic *interopContext) txGetAttributes(v *vm.VM) error {
} }
// txGetInputs returns current transaction inputs. // txGetInputs returns current transaction inputs.
func (ic *interopContext) txGetInputs(v *vm.VM) error { func txGetInputs(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -113,7 +113,7 @@ func (ic *interopContext) txGetInputs(v *vm.VM) error {
} }
// txGetOutputs returns current transaction outputs. // txGetOutputs returns current transaction outputs.
func (ic *interopContext) txGetOutputs(v *vm.VM) error { func txGetOutputs(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -131,7 +131,7 @@ func (ic *interopContext) txGetOutputs(v *vm.VM) error {
} }
// txGetReferences returns current transaction references. // txGetReferences returns current transaction references.
func (ic *interopContext) txGetReferences(v *vm.VM) error { func txGetReferences(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -159,7 +159,7 @@ func (ic *interopContext) txGetReferences(v *vm.VM) error {
} }
// txGetType returns current transaction type. // txGetType returns current transaction type.
func (ic *interopContext) txGetType(v *vm.VM) error { func txGetType(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -170,7 +170,7 @@ func (ic *interopContext) txGetType(v *vm.VM) error {
} }
// txGetUnspentCoins returns current transaction unspent coins. // txGetUnspentCoins returns current transaction unspent coins.
func (ic *interopContext) txGetUnspentCoins(v *vm.VM) error { func txGetUnspentCoins(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -185,7 +185,7 @@ func (ic *interopContext) txGetUnspentCoins(v *vm.VM) error {
} }
// txGetWitnesses returns current transaction witnesses. // txGetWitnesses returns current transaction witnesses.
func (ic *interopContext) txGetWitnesses(v *vm.VM) error { func txGetWitnesses(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -203,7 +203,7 @@ func (ic *interopContext) txGetWitnesses(v *vm.VM) error {
} }
// invocationTx_GetScript returns invocation script from the current transaction. // invocationTx_GetScript returns invocation script from the current transaction.
func (ic *interopContext) invocationTxGetScript(v *vm.VM) error { func invocationTxGetScript(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -221,7 +221,7 @@ func (ic *interopContext) invocationTxGetScript(v *vm.VM) error {
} }
// witnessGetVerificationScript returns current witness' script. // witnessGetVerificationScript returns current witness' script.
func (ic *interopContext) witnessGetVerificationScript(v *vm.VM) error { func witnessGetVerificationScript(ic *interopContext, v *vm.VM) error {
witInterface := v.Estack().Pop().Value() witInterface := v.Estack().Pop().Value()
wit, ok := witInterface.(*transaction.Witness) wit, ok := witInterface.(*transaction.Witness)
if !ok { if !ok {
@ -235,7 +235,7 @@ func (ic *interopContext) witnessGetVerificationScript(v *vm.VM) error {
} }
// bcGetValidators returns validators. // bcGetValidators returns validators.
func (ic *interopContext) bcGetValidators(v *vm.VM) error { func bcGetValidators(ic *interopContext, v *vm.VM) error {
validators := ic.dao.GetValidators() validators := ic.dao.GetValidators()
v.Estack().PushVal(validators) v.Estack().PushVal(validators)
return nil return nil
@ -256,7 +256,7 @@ func popInputFromVM(v *vm.VM) (*transaction.Input, error) {
} }
// inputGetHash returns hash from the given input. // inputGetHash returns hash from the given input.
func (ic *interopContext) inputGetHash(v *vm.VM) error { func inputGetHash(ic *interopContext, v *vm.VM) error {
input, err := popInputFromVM(v) input, err := popInputFromVM(v)
if err != nil { if err != nil {
return err return err
@ -266,7 +266,7 @@ func (ic *interopContext) inputGetHash(v *vm.VM) error {
} }
// inputGetIndex returns index from the given input. // inputGetIndex returns index from the given input.
func (ic *interopContext) inputGetIndex(v *vm.VM) error { func inputGetIndex(ic *interopContext, v *vm.VM) error {
input, err := popInputFromVM(v) input, err := popInputFromVM(v)
if err != nil { if err != nil {
return err return err
@ -290,7 +290,7 @@ func popOutputFromVM(v *vm.VM) (*transaction.Output, error) {
} }
// outputGetAssetId returns asset ID from the given output. // outputGetAssetId returns asset ID from the given output.
func (ic *interopContext) outputGetAssetID(v *vm.VM) error { func outputGetAssetID(ic *interopContext, v *vm.VM) error {
output, err := popOutputFromVM(v) output, err := popOutputFromVM(v)
if err != nil { if err != nil {
return err return err
@ -300,7 +300,7 @@ func (ic *interopContext) outputGetAssetID(v *vm.VM) error {
} }
// outputGetScriptHash returns scripthash from the given output. // outputGetScriptHash returns scripthash from the given output.
func (ic *interopContext) outputGetScriptHash(v *vm.VM) error { func outputGetScriptHash(ic *interopContext, v *vm.VM) error {
output, err := popOutputFromVM(v) output, err := popOutputFromVM(v)
if err != nil { if err != nil {
return err return err
@ -310,7 +310,7 @@ func (ic *interopContext) outputGetScriptHash(v *vm.VM) error {
} }
// outputGetValue returns value (amount) from the given output. // outputGetValue returns value (amount) from the given output.
func (ic *interopContext) outputGetValue(v *vm.VM) error { func outputGetValue(ic *interopContext, v *vm.VM) error {
output, err := popOutputFromVM(v) output, err := popOutputFromVM(v)
if err != nil { if err != nil {
return err return err
@ -320,7 +320,7 @@ func (ic *interopContext) outputGetValue(v *vm.VM) error {
} }
// attrGetData returns tx attribute data. // attrGetData returns tx attribute data.
func (ic *interopContext) attrGetData(v *vm.VM) error { func attrGetData(ic *interopContext, v *vm.VM) error {
attrInterface := v.Estack().Pop().Value() attrInterface := v.Estack().Pop().Value()
attr, ok := attrInterface.(*transaction.Attribute) attr, ok := attrInterface.(*transaction.Attribute)
if !ok { if !ok {
@ -331,7 +331,7 @@ func (ic *interopContext) attrGetData(v *vm.VM) error {
} }
// attrGetData returns tx attribute usage field. // attrGetData returns tx attribute usage field.
func (ic *interopContext) attrGetUsage(v *vm.VM) error { func attrGetUsage(ic *interopContext, v *vm.VM) error {
attrInterface := v.Estack().Pop().Value() attrInterface := v.Estack().Pop().Value()
attr, ok := attrInterface.(*transaction.Attribute) attr, ok := attrInterface.(*transaction.Attribute)
if !ok { if !ok {
@ -342,7 +342,7 @@ func (ic *interopContext) attrGetUsage(v *vm.VM) error {
} }
// bcGetAccount returns or creates an account. // bcGetAccount returns or creates an account.
func (ic *interopContext) bcGetAccount(v *vm.VM) error { func bcGetAccount(ic *interopContext, v *vm.VM) error {
accbytes := v.Estack().Pop().Bytes() accbytes := v.Estack().Pop().Bytes()
acchash, err := util.Uint160DecodeBytesBE(accbytes) acchash, err := util.Uint160DecodeBytesBE(accbytes)
if err != nil { if err != nil {
@ -357,7 +357,7 @@ func (ic *interopContext) bcGetAccount(v *vm.VM) error {
} }
// bcGetAsset returns an asset. // bcGetAsset returns an asset.
func (ic *interopContext) bcGetAsset(v *vm.VM) error { func bcGetAsset(ic *interopContext, v *vm.VM) error {
asbytes := v.Estack().Pop().Bytes() asbytes := v.Estack().Pop().Bytes()
ashash, err := util.Uint256DecodeBytesBE(asbytes) ashash, err := util.Uint256DecodeBytesBE(asbytes)
if err != nil { if err != nil {
@ -372,7 +372,7 @@ func (ic *interopContext) bcGetAsset(v *vm.VM) error {
} }
// accountGetBalance returns balance for a given account. // accountGetBalance returns balance for a given account.
func (ic *interopContext) accountGetBalance(v *vm.VM) error { func accountGetBalance(ic *interopContext, v *vm.VM) error {
accInterface := v.Estack().Pop().Value() accInterface := v.Estack().Pop().Value()
acc, ok := accInterface.(*state.Account) acc, ok := accInterface.(*state.Account)
if !ok { if !ok {
@ -392,7 +392,7 @@ func (ic *interopContext) accountGetBalance(v *vm.VM) error {
} }
// accountGetScriptHash returns script hash of a given account. // accountGetScriptHash returns script hash of a given account.
func (ic *interopContext) accountGetScriptHash(v *vm.VM) error { func accountGetScriptHash(ic *interopContext, v *vm.VM) error {
accInterface := v.Estack().Pop().Value() accInterface := v.Estack().Pop().Value()
acc, ok := accInterface.(*state.Account) acc, ok := accInterface.(*state.Account)
if !ok { if !ok {
@ -403,7 +403,7 @@ func (ic *interopContext) accountGetScriptHash(v *vm.VM) error {
} }
// accountGetVotes returns votes of a given account. // accountGetVotes returns votes of a given account.
func (ic *interopContext) accountGetVotes(v *vm.VM) error { func accountGetVotes(ic *interopContext, v *vm.VM) error {
accInterface := v.Estack().Pop().Value() accInterface := v.Estack().Pop().Value()
acc, ok := accInterface.(*state.Account) acc, ok := accInterface.(*state.Account)
if !ok { if !ok {
@ -421,7 +421,7 @@ func (ic *interopContext) accountGetVotes(v *vm.VM) error {
} }
// accountIsStandard checks whether given account is standard. // accountIsStandard checks whether given account is standard.
func (ic *interopContext) accountIsStandard(v *vm.VM) error { func accountIsStandard(ic *interopContext, v *vm.VM) error {
accbytes := v.Estack().Pop().Bytes() accbytes := v.Estack().Pop().Bytes()
acchash, err := util.Uint160DecodeBytesBE(accbytes) acchash, err := util.Uint160DecodeBytesBE(accbytes)
if err != nil { if err != nil {
@ -434,13 +434,13 @@ func (ic *interopContext) accountIsStandard(v *vm.VM) error {
} }
// storageFind finds stored key-value pair. // storageFind finds stored key-value pair.
func (ic *interopContext) storageFind(v *vm.VM) error { func storageFind(ic *interopContext, v *vm.VM) error {
stcInterface := v.Estack().Pop().Value() stcInterface := v.Estack().Pop().Value()
stc, ok := stcInterface.(*StorageContext) stc, ok := stcInterface.(*StorageContext)
if !ok { if !ok {
return fmt.Errorf("%T is not a StorageContext", stcInterface) return fmt.Errorf("%T is not a StorageContext", stcInterface)
} }
err := ic.checkStorageContext(stc) err := checkStorageContext(ic, stc)
if err != nil { if err != nil {
return err return err
} }
@ -467,7 +467,7 @@ func (ic *interopContext) storageFind(v *vm.VM) error {
// createContractStateFromVM pops all contract state elements from the VM // createContractStateFromVM pops all contract state elements from the VM
// evaluation stack, does a lot of checks and returns Contract if it // evaluation stack, does a lot of checks and returns Contract if it
// succeeds. // succeeds.
func (ic *interopContext) createContractStateFromVM(v *vm.VM) (*state.Contract, error) { func createContractStateFromVM(ic *interopContext, v *vm.VM) (*state.Contract, error) {
if ic.trigger != trigger.Application { if ic.trigger != trigger.Application {
return nil, errors.New("can't create contract when not triggered by an application") return nil, errors.New("can't create contract when not triggered by an application")
} }
@ -520,8 +520,8 @@ func (ic *interopContext) createContractStateFromVM(v *vm.VM) (*state.Contract,
} }
// contractCreate creates a contract. // contractCreate creates a contract.
func (ic *interopContext) contractCreate(v *vm.VM) error { func contractCreate(ic *interopContext, v *vm.VM) error {
newcontract, err := ic.createContractStateFromVM(v) newcontract, err := createContractStateFromVM(ic, v)
if err != nil { if err != nil {
return err return err
} }
@ -538,7 +538,7 @@ func (ic *interopContext) contractCreate(v *vm.VM) error {
} }
// contractGetScript returns a script associated with a contract. // contractGetScript returns a script associated with a contract.
func (ic *interopContext) contractGetScript(v *vm.VM) error { func contractGetScript(ic *interopContext, v *vm.VM) error {
csInterface := v.Estack().Pop().Value() csInterface := v.Estack().Pop().Value()
cs, ok := csInterface.(*state.Contract) cs, ok := csInterface.(*state.Contract)
if !ok { if !ok {
@ -549,7 +549,7 @@ func (ic *interopContext) contractGetScript(v *vm.VM) error {
} }
// contractIsPayable returns whether contract is payable. // contractIsPayable returns whether contract is payable.
func (ic *interopContext) contractIsPayable(v *vm.VM) error { func contractIsPayable(ic *interopContext, v *vm.VM) error {
csInterface := v.Estack().Pop().Value() csInterface := v.Estack().Pop().Value()
cs, ok := csInterface.(*state.Contract) cs, ok := csInterface.(*state.Contract)
if !ok { if !ok {
@ -560,8 +560,8 @@ func (ic *interopContext) contractIsPayable(v *vm.VM) error {
} }
// contractMigrate migrates a contract. // contractMigrate migrates a contract.
func (ic *interopContext) contractMigrate(v *vm.VM) error { func contractMigrate(ic *interopContext, v *vm.VM) error {
newcontract, err := ic.createContractStateFromVM(v) newcontract, err := createContractStateFromVM(ic, v)
if err != nil { if err != nil {
return err return err
} }
@ -588,11 +588,11 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error {
} }
} }
v.Estack().PushVal(vm.NewInteropItem(contract)) v.Estack().PushVal(vm.NewInteropItem(contract))
return ic.contractDestroy(v) return contractDestroy(ic, v)
} }
// assetCreate creates an asset. // assetCreate creates an asset.
func (ic *interopContext) assetCreate(v *vm.VM) error { func assetCreate(ic *interopContext, v *vm.VM) error {
if ic.trigger != trigger.Application { if ic.trigger != trigger.Application {
return errors.New("can't create asset when not triggered by an application") return errors.New("can't create asset when not triggered by an application")
} }
@ -635,7 +635,7 @@ func (ic *interopContext) assetCreate(v *vm.VM) error {
if owner.IsInfinity() { if owner.IsInfinity() {
return errors.New("can't have infinity as an owner key") return errors.New("can't have infinity as an owner key")
} }
witnessOk, err := ic.checkKeyedWitness(owner) witnessOk, err := checkKeyedWitness(ic, owner)
if err != nil { if err != nil {
return err return err
} }
@ -670,7 +670,7 @@ func (ic *interopContext) assetCreate(v *vm.VM) error {
} }
// assetGetAdmin returns asset admin. // assetGetAdmin returns asset admin.
func (ic *interopContext) assetGetAdmin(v *vm.VM) error { func assetGetAdmin(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -681,7 +681,7 @@ func (ic *interopContext) assetGetAdmin(v *vm.VM) error {
} }
// assetGetAmount returns the overall amount of asset available. // assetGetAmount returns the overall amount of asset available.
func (ic *interopContext) assetGetAmount(v *vm.VM) error { func assetGetAmount(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -692,7 +692,7 @@ func (ic *interopContext) assetGetAmount(v *vm.VM) error {
} }
// assetGetAssetId returns the id of an asset. // assetGetAssetId returns the id of an asset.
func (ic *interopContext) assetGetAssetID(v *vm.VM) error { func assetGetAssetID(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -703,7 +703,7 @@ func (ic *interopContext) assetGetAssetID(v *vm.VM) error {
} }
// assetGetAssetType returns type of an asset. // assetGetAssetType returns type of an asset.
func (ic *interopContext) assetGetAssetType(v *vm.VM) error { func assetGetAssetType(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -714,7 +714,7 @@ func (ic *interopContext) assetGetAssetType(v *vm.VM) error {
} }
// assetGetAvailable returns available (not yet issued) amount of asset. // assetGetAvailable returns available (not yet issued) amount of asset.
func (ic *interopContext) assetGetAvailable(v *vm.VM) error { func assetGetAvailable(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -725,7 +725,7 @@ func (ic *interopContext) assetGetAvailable(v *vm.VM) error {
} }
// assetGetIssuer returns issuer of an asset. // assetGetIssuer returns issuer of an asset.
func (ic *interopContext) assetGetIssuer(v *vm.VM) error { func assetGetIssuer(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -736,7 +736,7 @@ func (ic *interopContext) assetGetIssuer(v *vm.VM) error {
} }
// assetGetOwner returns owner of an asset. // assetGetOwner returns owner of an asset.
func (ic *interopContext) assetGetOwner(v *vm.VM) error { func assetGetOwner(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -747,7 +747,7 @@ func (ic *interopContext) assetGetOwner(v *vm.VM) error {
} }
// assetGetPrecision returns precision used to measure this asset. // assetGetPrecision returns precision used to measure this asset.
func (ic *interopContext) assetGetPrecision(v *vm.VM) error { func assetGetPrecision(ic *interopContext, v *vm.VM) error {
asInterface := v.Estack().Pop().Value() asInterface := v.Estack().Pop().Value()
as, ok := asInterface.(*state.Asset) as, ok := asInterface.(*state.Asset)
if !ok { if !ok {
@ -758,7 +758,7 @@ func (ic *interopContext) assetGetPrecision(v *vm.VM) error {
} }
// assetRenew updates asset expiration date. // assetRenew updates asset expiration date.
func (ic *interopContext) assetRenew(v *vm.VM) error { func assetRenew(ic *interopContext, v *vm.VM) error {
if ic.trigger != trigger.Application { if ic.trigger != trigger.Application {
return errors.New("can't create asset when not triggered by an application") return errors.New("can't create asset when not triggered by an application")
} }
@ -790,57 +790,57 @@ func (ic *interopContext) assetRenew(v *vm.VM) error {
} }
// runtimeSerialize serializes top stack item into a ByteArray. // runtimeSerialize serializes top stack item into a ByteArray.
func (ic *interopContext) runtimeSerialize(v *vm.VM) error { func runtimeSerialize(_ *interopContext, v *vm.VM) error {
return vm.RuntimeSerialize(v) return vm.RuntimeSerialize(v)
} }
// runtimeDeserialize deserializes ByteArray from a stack into an item. // runtimeDeserialize deserializes ByteArray from a stack into an item.
func (ic *interopContext) runtimeDeserialize(v *vm.VM) error { func runtimeDeserialize(_ *interopContext, v *vm.VM) error {
return vm.RuntimeDeserialize(v) return vm.RuntimeDeserialize(v)
} }
// enumeratorConcat concatenates 2 enumerators into a single one. // enumeratorConcat concatenates 2 enumerators into a single one.
func (ic *interopContext) enumeratorConcat(v *vm.VM) error { func enumeratorConcat(_ *interopContext, v *vm.VM) error {
return vm.EnumeratorConcat(v) return vm.EnumeratorConcat(v)
} }
// enumeratorCreate creates an enumerator from an array-like stack item. // enumeratorCreate creates an enumerator from an array-like stack item.
func (ic *interopContext) enumeratorCreate(v *vm.VM) error { func enumeratorCreate(_ *interopContext, v *vm.VM) error {
return vm.EnumeratorCreate(v) return vm.EnumeratorCreate(v)
} }
// enumeratorNext advances the enumerator, pushes true if is it was successful // enumeratorNext advances the enumerator, pushes true if is it was successful
// and false otherwise. // and false otherwise.
func (ic *interopContext) enumeratorNext(v *vm.VM) error { func enumeratorNext(_ *interopContext, v *vm.VM) error {
return vm.EnumeratorNext(v) return vm.EnumeratorNext(v)
} }
// enumeratorValue returns the current value of the enumerator. // enumeratorValue returns the current value of the enumerator.
func (ic *interopContext) enumeratorValue(v *vm.VM) error { func enumeratorValue(_ *interopContext, v *vm.VM) error {
return vm.EnumeratorValue(v) return vm.EnumeratorValue(v)
} }
// iteratorConcat concatenates 2 iterators into a single one. // iteratorConcat concatenates 2 iterators into a single one.
func (ic *interopContext) iteratorConcat(v *vm.VM) error { func iteratorConcat(_ *interopContext, v *vm.VM) error {
return vm.IteratorConcat(v) return vm.IteratorConcat(v)
} }
// iteratorCreate creates an iterator from array-like or map stack item. // iteratorCreate creates an iterator from array-like or map stack item.
func (ic *interopContext) iteratorCreate(v *vm.VM) error { func iteratorCreate(_ *interopContext, v *vm.VM) error {
return vm.IteratorCreate(v) return vm.IteratorCreate(v)
} }
// iteratorKey returns current iterator key. // iteratorKey returns current iterator key.
func (ic *interopContext) iteratorKey(v *vm.VM) error { func iteratorKey(_ *interopContext, v *vm.VM) error {
return vm.IteratorKey(v) return vm.IteratorKey(v)
} }
// iteratorKeys returns keys of the iterator. // iteratorKeys returns keys of the iterator.
func (ic *interopContext) iteratorKeys(v *vm.VM) error { func iteratorKeys(_ *interopContext, v *vm.VM) error {
return vm.IteratorKeys(v) return vm.IteratorKeys(v)
} }
// iteratorValues returns values of the iterator. // iteratorValues returns values of the iterator.
func (ic *interopContext) iteratorValues(v *vm.VM) error { func iteratorValues(_ *interopContext, v *vm.VM) error {
return vm.IteratorValues(v) return vm.IteratorValues(v)
} }

View file

@ -39,7 +39,7 @@ import (
func TestGetTrigger(t *testing.T) { func TestGetTrigger(t *testing.T) {
v, _, context, chain := createVMAndPushBlock(t) v, _, context, chain := createVMAndPushBlock(t)
defer chain.Close() defer chain.Close()
require.NoError(t, context.runtimeGetTrigger(v)) require.NoError(t, runtimeGetTrigger(context, v))
} }
func TestStorageFind(t *testing.T) { func TestStorageFind(t *testing.T) {
@ -69,25 +69,25 @@ func TestStorageFind(t *testing.T) {
v.Estack().PushVal([]byte{0x01}) v.Estack().PushVal([]byte{0x01})
v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: scriptHash})) v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: scriptHash}))
err := context.storageFind(v) err := storageFind(context, v)
require.NoError(t, err) require.NoError(t, err)
var iter *vm.InteropItem var iter *vm.InteropItem
require.NotPanics(t, func() { iter = v.Estack().Top().Interop() }) require.NotPanics(t, func() { iter = v.Estack().Top().Interop() })
require.NoError(t, context.enumeratorNext(v)) require.NoError(t, enumeratorNext(context, v))
require.True(t, v.Estack().Pop().Bool()) require.True(t, v.Estack().Pop().Bool())
v.Estack().PushVal(iter) v.Estack().PushVal(iter)
require.NoError(t, context.iteratorKey(v)) require.NoError(t, iteratorKey(context, v))
require.Equal(t, []byte{0x01, 0x02}, v.Estack().Pop().Bytes()) require.Equal(t, []byte{0x01, 0x02}, v.Estack().Pop().Bytes())
v.Estack().PushVal(iter) v.Estack().PushVal(iter)
require.NoError(t, context.enumeratorValue(v)) require.NoError(t, enumeratorValue(context, v))
require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, v.Estack().Pop().Bytes()) require.Equal(t, []byte{0x01, 0x02, 0x03, 0x04}, v.Estack().Pop().Bytes())
v.Estack().PushVal(iter) v.Estack().PushVal(iter)
require.NoError(t, context.enumeratorNext(v)) require.NoError(t, enumeratorNext(context, v))
require.False(t, v.Estack().Pop().Bool()) require.False(t, v.Estack().Pop().Bool())
}) })
@ -95,7 +95,7 @@ func TestStorageFind(t *testing.T) {
v.Estack().PushVal([]byte{0x01}) v.Estack().PushVal([]byte{0x01})
v.Estack().PushVal(vm.NewInteropItem(nil)) v.Estack().PushVal(vm.NewInteropItem(nil))
require.Error(t, context.storageFind(v)) require.Error(t, storageFind(context, v))
}) })
t.Run("invalid script hash", func(t *testing.T) { t.Run("invalid script hash", func(t *testing.T) {
@ -105,7 +105,7 @@ func TestStorageFind(t *testing.T) {
v.Estack().PushVal([]byte{0x01}) v.Estack().PushVal([]byte{0x01})
v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: invalidHash})) v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: invalidHash}))
require.Error(t, context.storageFind(v)) require.Error(t, storageFind(context, v))
}) })
} }
@ -113,7 +113,7 @@ func TestHeaderGetVersion(t *testing.T) {
v, block, context, chain := createVMAndPushBlock(t) v, block, context, chain := createVMAndPushBlock(t)
defer chain.Close() defer chain.Close()
err := context.headerGetVersion(v) err := headerGetVersion(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().(*big.Int) value := v.Estack().Pop().Value().(*big.Int)
require.Equal(t, uint64(block.Version), value.Uint64()) require.Equal(t, uint64(block.Version), value.Uint64())
@ -127,7 +127,7 @@ func TestHeaderGetVersion_Negative(t *testing.T) {
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), block, nil) context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), block, nil)
v.Estack().PushVal(vm.NewBoolItem(false)) v.Estack().PushVal(vm.NewBoolItem(false))
err := context.headerGetVersion(v) err := headerGetVersion(context, v)
require.Errorf(t, err, "value is not a header or block") require.Errorf(t, err, "value is not a header or block")
} }
@ -135,7 +135,7 @@ func TestHeaderGetConsensusData(t *testing.T) {
v, block, context, chain := createVMAndPushBlock(t) v, block, context, chain := createVMAndPushBlock(t)
defer chain.Close() defer chain.Close()
err := context.headerGetConsensusData(v) err := headerGetConsensusData(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().(*big.Int) value := v.Estack().Pop().Value().(*big.Int)
require.Equal(t, block.ConsensusData, value.Uint64()) require.Equal(t, block.ConsensusData, value.Uint64())
@ -145,7 +145,7 @@ func TestHeaderGetMerkleRoot(t *testing.T) {
v, block, context, chain := createVMAndPushBlock(t) v, block, context, chain := createVMAndPushBlock(t)
defer chain.Close() defer chain.Close()
err := context.headerGetMerkleRoot(v) err := headerGetMerkleRoot(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value() value := v.Estack().Pop().Value()
require.Equal(t, block.MerkleRoot.BytesBE(), value) require.Equal(t, block.MerkleRoot.BytesBE(), value)
@ -155,7 +155,7 @@ func TestHeaderGetNextConsensus(t *testing.T) {
v, block, context, chain := createVMAndPushBlock(t) v, block, context, chain := createVMAndPushBlock(t)
defer chain.Close() defer chain.Close()
err := context.headerGetNextConsensus(v) err := headerGetNextConsensus(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value() value := v.Estack().Pop().Value()
require.Equal(t, block.NextConsensus.BytesBE(), value) require.Equal(t, block.NextConsensus.BytesBE(), value)
@ -165,7 +165,7 @@ func TestTxGetAttributes(t *testing.T) {
v, tx, context, chain := createVMAndPushTX(t) v, tx, context, chain := createVMAndPushTX(t)
defer chain.Close() defer chain.Close()
err := context.txGetAttributes(v) err := txGetAttributes(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().([]vm.StackItem) value := v.Estack().Pop().Value().([]vm.StackItem)
require.Equal(t, tx.Attributes[0].Usage, value[0].Value().(*transaction.Attribute).Usage) require.Equal(t, tx.Attributes[0].Usage, value[0].Value().(*transaction.Attribute).Usage)
@ -175,7 +175,7 @@ func TestTxGetInputs(t *testing.T) {
v, tx, context, chain := createVMAndPushTX(t) v, tx, context, chain := createVMAndPushTX(t)
defer chain.Close() defer chain.Close()
err := context.txGetInputs(v) err := txGetInputs(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().([]vm.StackItem) value := v.Estack().Pop().Value().([]vm.StackItem)
require.Equal(t, tx.Inputs[0], *value[0].Value().(*transaction.Input)) require.Equal(t, tx.Inputs[0], *value[0].Value().(*transaction.Input))
@ -185,7 +185,7 @@ func TestTxGetOutputs(t *testing.T) {
v, tx, context, chain := createVMAndPushTX(t) v, tx, context, chain := createVMAndPushTX(t)
defer chain.Close() defer chain.Close()
err := context.txGetOutputs(v) err := txGetOutputs(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().([]vm.StackItem) value := v.Estack().Pop().Value().([]vm.StackItem)
require.Equal(t, tx.Outputs[0], *value[0].Value().(*transaction.Output)) require.Equal(t, tx.Outputs[0], *value[0].Value().(*transaction.Output))
@ -195,7 +195,7 @@ func TestTxGetType(t *testing.T) {
v, tx, context, chain := createVMAndPushTX(t) v, tx, context, chain := createVMAndPushTX(t)
defer chain.Close() defer chain.Close()
err := context.txGetType(v) err := txGetType(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().(*big.Int) value := v.Estack().Pop().Value().(*big.Int)
require.Equal(t, big.NewInt(int64(tx.Type)), value) require.Equal(t, big.NewInt(int64(tx.Type)), value)
@ -205,7 +205,7 @@ func TestInvocationTxGetScript(t *testing.T) {
v, tx, context, chain := createVMAndPushTX(t) v, tx, context, chain := createVMAndPushTX(t)
defer chain.Close() defer chain.Close()
err := context.invocationTxGetScript(v) err := invocationTxGetScript(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().([]byte) value := v.Estack().Pop().Value().([]byte)
inv := tx.Data.(*transaction.InvocationTX) inv := tx.Data.(*transaction.InvocationTX)
@ -222,7 +222,7 @@ func TestWitnessGetVerificationScript(t *testing.T) {
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil) context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
v.Estack().PushVal(vm.NewInteropItem(&witness)) v.Estack().PushVal(vm.NewInteropItem(&witness))
err := context.witnessGetVerificationScript(v) err := witnessGetVerificationScript(context, v)
require.NoError(t, err) require.NoError(t, err)
value := v.Estack().Pop().Value().([]byte) value := v.Estack().Pop().Value().([]byte)
require.Equal(t, witness.VerificationScript, value) require.Equal(t, witness.VerificationScript, value)
@ -243,7 +243,7 @@ func TestInputGetHash(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0]))
err := context.inputGetHash(v) err := inputGetHash(context, v)
require.NoError(t, err) require.NoError(t, err)
hash := v.Estack().Pop().Value() hash := v.Estack().Pop().Value()
require.Equal(t, tx.Inputs[0].PrevHash.BytesBE(), hash) require.Equal(t, tx.Inputs[0].PrevHash.BytesBE(), hash)
@ -254,7 +254,7 @@ func TestInputGetIndex(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Inputs[0]))
err := context.inputGetIndex(v) err := inputGetIndex(context, v)
require.NoError(t, err) require.NoError(t, err)
index := v.Estack().Pop().Value() index := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(tx.Inputs[0].PrevIndex)), index) require.Equal(t, big.NewInt(int64(tx.Inputs[0].PrevIndex)), index)
@ -275,7 +275,7 @@ func TestOutputGetAssetID(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0]))
err := context.outputGetAssetID(v) err := outputGetAssetID(context, v)
require.NoError(t, err) require.NoError(t, err)
assetID := v.Estack().Pop().Value() assetID := v.Estack().Pop().Value()
require.Equal(t, tx.Outputs[0].AssetID.BytesBE(), assetID) require.Equal(t, tx.Outputs[0].AssetID.BytesBE(), assetID)
@ -286,7 +286,7 @@ func TestOutputGetScriptHash(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0]))
err := context.outputGetScriptHash(v) err := outputGetScriptHash(context, v)
require.NoError(t, err) require.NoError(t, err)
scriptHash := v.Estack().Pop().Value() scriptHash := v.Estack().Pop().Value()
require.Equal(t, tx.Outputs[0].ScriptHash.BytesBE(), scriptHash) require.Equal(t, tx.Outputs[0].ScriptHash.BytesBE(), scriptHash)
@ -297,7 +297,7 @@ func TestOutputGetValue(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Outputs[0]))
err := context.outputGetValue(v) err := outputGetValue(context, v)
require.NoError(t, err) require.NoError(t, err)
amount := v.Estack().Pop().Value() amount := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(tx.Outputs[0].Amount)), amount) require.Equal(t, big.NewInt(int64(tx.Outputs[0].Amount)), amount)
@ -308,7 +308,7 @@ func TestAttrGetData(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Attributes[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Attributes[0]))
err := context.attrGetData(v) err := attrGetData(context, v)
require.NoError(t, err) require.NoError(t, err)
data := v.Estack().Pop().Value() data := v.Estack().Pop().Value()
require.Equal(t, tx.Attributes[0].Data, data) require.Equal(t, tx.Attributes[0].Data, data)
@ -319,7 +319,7 @@ func TestAttrGetUsage(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(&tx.Attributes[0])) v.Estack().PushVal(vm.NewInteropItem(&tx.Attributes[0]))
err := context.attrGetUsage(v) err := attrGetUsage(context, v)
require.NoError(t, err) require.NoError(t, err)
usage := v.Estack().Pop().Value() usage := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(tx.Attributes[0].Usage)), usage) require.Equal(t, big.NewInt(int64(tx.Attributes[0].Usage)), usage)
@ -330,7 +330,7 @@ func TestAccountGetScriptHash(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(accState)) v.Estack().PushVal(vm.NewInteropItem(accState))
err := context.accountGetScriptHash(v) err := accountGetScriptHash(context, v)
require.NoError(t, err) require.NoError(t, err)
hash := v.Estack().Pop().Value() hash := v.Estack().Pop().Value()
require.Equal(t, accState.ScriptHash.BytesBE(), hash) require.Equal(t, accState.ScriptHash.BytesBE(), hash)
@ -341,7 +341,7 @@ func TestAccountGetVotes(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(accState)) v.Estack().PushVal(vm.NewInteropItem(accState))
err := context.accountGetVotes(v) err := accountGetVotes(context, v)
require.NoError(t, err) require.NoError(t, err)
votes := v.Estack().Pop().Value().([]vm.StackItem) votes := v.Estack().Pop().Value().([]vm.StackItem)
require.Equal(t, vm.NewByteArrayItem(accState.Votes[0].Bytes()), votes[0]) require.Equal(t, vm.NewByteArrayItem(accState.Votes[0].Bytes()), votes[0])
@ -352,7 +352,7 @@ func TestContractGetScript(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(contractState)) v.Estack().PushVal(vm.NewInteropItem(contractState))
err := context.contractGetScript(v) err := contractGetScript(context, v)
require.NoError(t, err) require.NoError(t, err)
script := v.Estack().Pop().Value() script := v.Estack().Pop().Value()
require.Equal(t, contractState.Script, script) require.Equal(t, contractState.Script, script)
@ -363,7 +363,7 @@ func TestContractIsPayable(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(contractState)) v.Estack().PushVal(vm.NewInteropItem(contractState))
err := context.contractIsPayable(v) err := contractIsPayable(context, v)
require.NoError(t, err) require.NoError(t, err)
isPayable := v.Estack().Pop().Value() isPayable := v.Estack().Pop().Value()
require.Equal(t, contractState.IsPayable(), isPayable) require.Equal(t, contractState.IsPayable(), isPayable)
@ -374,7 +374,7 @@ func TestAssetGetAdmin(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetAdmin(v) err := assetGetAdmin(context, v)
require.NoError(t, err) require.NoError(t, err)
admin := v.Estack().Pop().Value() admin := v.Estack().Pop().Value()
require.Equal(t, assetState.Admin.BytesBE(), admin) require.Equal(t, assetState.Admin.BytesBE(), admin)
@ -385,7 +385,7 @@ func TestAssetGetAmount(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetAmount(v) err := assetGetAmount(context, v)
require.NoError(t, err) require.NoError(t, err)
amount := v.Estack().Pop().Value() amount := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.Amount)), amount) require.Equal(t, big.NewInt(int64(assetState.Amount)), amount)
@ -396,7 +396,7 @@ func TestAssetGetAssetID(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetAssetID(v) err := assetGetAssetID(context, v)
require.NoError(t, err) require.NoError(t, err)
assetID := v.Estack().Pop().Value() assetID := v.Estack().Pop().Value()
require.Equal(t, assetState.ID.BytesBE(), assetID) require.Equal(t, assetState.ID.BytesBE(), assetID)
@ -407,7 +407,7 @@ func TestAssetGetAssetType(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetAssetType(v) err := assetGetAssetType(context, v)
require.NoError(t, err) require.NoError(t, err)
assetType := v.Estack().Pop().Value() assetType := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.AssetType)), assetType) require.Equal(t, big.NewInt(int64(assetState.AssetType)), assetType)
@ -418,7 +418,7 @@ func TestAssetGetAvailable(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetAvailable(v) err := assetGetAvailable(context, v)
require.NoError(t, err) require.NoError(t, err)
available := v.Estack().Pop().Value() available := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.Available)), available) require.Equal(t, big.NewInt(int64(assetState.Available)), available)
@ -429,7 +429,7 @@ func TestAssetGetIssuer(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetIssuer(v) err := assetGetIssuer(context, v)
require.NoError(t, err) require.NoError(t, err)
issuer := v.Estack().Pop().Value() issuer := v.Estack().Pop().Value()
require.Equal(t, assetState.Issuer.BytesBE(), issuer) require.Equal(t, assetState.Issuer.BytesBE(), issuer)
@ -440,7 +440,7 @@ func TestAssetGetOwner(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetOwner(v) err := assetGetOwner(context, v)
require.NoError(t, err) require.NoError(t, err)
owner := v.Estack().Pop().Value() owner := v.Estack().Pop().Value()
require.Equal(t, assetState.Owner.Bytes(), owner) require.Equal(t, assetState.Owner.Bytes(), owner)
@ -451,7 +451,7 @@ func TestAssetGetPrecision(t *testing.T) {
defer chain.Close() defer chain.Close()
v.Estack().PushVal(vm.NewInteropItem(assetState)) v.Estack().PushVal(vm.NewInteropItem(assetState))
err := context.assetGetPrecision(v) err := assetGetPrecision(context, v)
require.NoError(t, err) require.NoError(t, err)
precision := v.Estack().Pop().Value() precision := v.Estack().Pop().Value()
require.Equal(t, big.NewInt(int64(assetState.Precision)), precision) require.Equal(t, big.NewInt(int64(assetState.Precision)), precision)

View file

@ -48,7 +48,7 @@ func getBlockHashFromElement(bc Blockchainer, element *vm.Element) (util.Uint256
} }
// bcGetBlock returns current block. // bcGetBlock returns current block.
func (ic *interopContext) bcGetBlock(v *vm.VM) error { func bcGetBlock(ic *interopContext, v *vm.VM) error {
hash, err := getBlockHashFromElement(ic.bc, v.Estack().Pop()) hash, err := getBlockHashFromElement(ic.bc, v.Estack().Pop())
if err != nil { if err != nil {
return err return err
@ -63,7 +63,7 @@ func (ic *interopContext) bcGetBlock(v *vm.VM) error {
} }
// bcGetContract returns contract. // bcGetContract returns contract.
func (ic *interopContext) bcGetContract(v *vm.VM) error { func bcGetContract(ic *interopContext, v *vm.VM) error {
hashbytes := v.Estack().Pop().Bytes() hashbytes := v.Estack().Pop().Bytes()
hash, err := util.Uint160DecodeBytesBE(hashbytes) hash, err := util.Uint160DecodeBytesBE(hashbytes)
if err != nil { if err != nil {
@ -79,7 +79,7 @@ func (ic *interopContext) bcGetContract(v *vm.VM) error {
} }
// bcGetHeader returns block header. // bcGetHeader returns block header.
func (ic *interopContext) bcGetHeader(v *vm.VM) error { func bcGetHeader(ic *interopContext, v *vm.VM) error {
hash, err := getBlockHashFromElement(ic.bc, v.Estack().Pop()) hash, err := getBlockHashFromElement(ic.bc, v.Estack().Pop())
if err != nil { if err != nil {
return err return err
@ -94,7 +94,7 @@ func (ic *interopContext) bcGetHeader(v *vm.VM) error {
} }
// bcGetHeight returns blockchain height. // bcGetHeight returns blockchain height.
func (ic *interopContext) bcGetHeight(v *vm.VM) error { func bcGetHeight(ic *interopContext, v *vm.VM) error {
v.Estack().PushVal(ic.bc.BlockHeight()) v.Estack().PushVal(ic.bc.BlockHeight())
return nil return nil
} }
@ -111,7 +111,7 @@ func getTransactionAndHeight(cd *dao.Cached, v *vm.VM) (*transaction.Transaction
} }
// bcGetTransaction returns transaction. // bcGetTransaction returns transaction.
func (ic *interopContext) bcGetTransaction(v *vm.VM) error { func bcGetTransaction(ic *interopContext, v *vm.VM) error {
tx, _, err := getTransactionAndHeight(ic.dao, v) tx, _, err := getTransactionAndHeight(ic.dao, v)
if err != nil { if err != nil {
return err return err
@ -121,7 +121,7 @@ func (ic *interopContext) bcGetTransaction(v *vm.VM) error {
} }
// bcGetTransactionHeight returns transaction height. // bcGetTransactionHeight returns transaction height.
func (ic *interopContext) bcGetTransactionHeight(v *vm.VM) error { func bcGetTransactionHeight(ic *interopContext, v *vm.VM) error {
_, h, err := getTransactionAndHeight(ic.dao, v) _, h, err := getTransactionAndHeight(ic.dao, v)
if err != nil { if err != nil {
return err return err
@ -147,7 +147,7 @@ func popHeaderFromVM(v *vm.VM) (*block.Header, error) {
} }
// headerGetIndex returns block index from the header. // headerGetIndex returns block index from the header.
func (ic *interopContext) headerGetIndex(v *vm.VM) error { func headerGetIndex(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -157,7 +157,7 @@ func (ic *interopContext) headerGetIndex(v *vm.VM) error {
} }
// headerGetHash returns header hash of the passed header. // headerGetHash returns header hash of the passed header.
func (ic *interopContext) headerGetHash(v *vm.VM) error { func headerGetHash(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -167,7 +167,7 @@ func (ic *interopContext) headerGetHash(v *vm.VM) error {
} }
// headerGetPrevHash returns previous header hash of the passed header. // headerGetPrevHash returns previous header hash of the passed header.
func (ic *interopContext) headerGetPrevHash(v *vm.VM) error { func headerGetPrevHash(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -177,7 +177,7 @@ func (ic *interopContext) headerGetPrevHash(v *vm.VM) error {
} }
// headerGetTimestamp returns timestamp of the passed header. // headerGetTimestamp returns timestamp of the passed header.
func (ic *interopContext) headerGetTimestamp(v *vm.VM) error { func headerGetTimestamp(ic *interopContext, v *vm.VM) error {
header, err := popHeaderFromVM(v) header, err := popHeaderFromVM(v)
if err != nil { if err != nil {
return err return err
@ -187,7 +187,7 @@ func (ic *interopContext) headerGetTimestamp(v *vm.VM) error {
} }
// blockGetTransactionCount returns transactions count in the given block. // blockGetTransactionCount returns transactions count in the given block.
func (ic *interopContext) blockGetTransactionCount(v *vm.VM) error { func blockGetTransactionCount(ic *interopContext, v *vm.VM) error {
blockInterface := v.Estack().Pop().Value() blockInterface := v.Estack().Pop().Value()
block, ok := blockInterface.(*block.Block) block, ok := blockInterface.(*block.Block)
if !ok { if !ok {
@ -198,7 +198,7 @@ func (ic *interopContext) blockGetTransactionCount(v *vm.VM) error {
} }
// blockGetTransactions returns transactions from the given block. // blockGetTransactions returns transactions from the given block.
func (ic *interopContext) blockGetTransactions(v *vm.VM) error { func blockGetTransactions(ic *interopContext, v *vm.VM) error {
blockInterface := v.Estack().Pop().Value() blockInterface := v.Estack().Pop().Value()
block, ok := blockInterface.(*block.Block) block, ok := blockInterface.(*block.Block)
if !ok { if !ok {
@ -217,7 +217,7 @@ func (ic *interopContext) blockGetTransactions(v *vm.VM) error {
// blockGetTransaction returns transaction with the given number from the given // blockGetTransaction returns transaction with the given number from the given
// block. // block.
func (ic *interopContext) blockGetTransaction(v *vm.VM) error { func blockGetTransaction(ic *interopContext, v *vm.VM) error {
blockInterface := v.Estack().Pop().Value() blockInterface := v.Estack().Pop().Value()
block, ok := blockInterface.(*block.Block) block, ok := blockInterface.(*block.Block)
if !ok { if !ok {
@ -233,7 +233,7 @@ func (ic *interopContext) blockGetTransaction(v *vm.VM) error {
} }
// txGetHash returns transaction's hash. // txGetHash returns transaction's hash.
func (ic *interopContext) txGetHash(v *vm.VM) error { func txGetHash(ic *interopContext, v *vm.VM) error {
txInterface := v.Estack().Pop().Value() txInterface := v.Estack().Pop().Value()
tx, ok := txInterface.(*transaction.Transaction) tx, ok := txInterface.(*transaction.Transaction)
if !ok { if !ok {
@ -245,7 +245,7 @@ func (ic *interopContext) txGetHash(v *vm.VM) error {
// engineGetScriptContainer returns transaction that contains the script being // engineGetScriptContainer returns transaction that contains the script being
// run. // run.
func (ic *interopContext) engineGetScriptContainer(v *vm.VM) error { func engineGetScriptContainer(ic *interopContext, v *vm.VM) error {
v.Estack().PushVal(vm.NewInteropItem(ic.tx)) v.Estack().PushVal(vm.NewInteropItem(ic.tx))
return nil return nil
} }
@ -267,35 +267,35 @@ func pushContextScriptHash(v *vm.VM, n int) error {
} }
// engineGetExecutingScriptHash returns executing script hash. // engineGetExecutingScriptHash returns executing script hash.
func (ic *interopContext) engineGetExecutingScriptHash(v *vm.VM) error { func engineGetExecutingScriptHash(ic *interopContext, v *vm.VM) error {
return pushContextScriptHash(v, 0) return pushContextScriptHash(v, 0)
} }
// engineGetCallingScriptHash returns calling script hash. // engineGetCallingScriptHash returns calling script hash.
func (ic *interopContext) engineGetCallingScriptHash(v *vm.VM) error { func engineGetCallingScriptHash(ic *interopContext, v *vm.VM) error {
return pushContextScriptHash(v, 1) return pushContextScriptHash(v, 1)
} }
// engineGetEntryScriptHash returns entry script hash. // engineGetEntryScriptHash returns entry script hash.
func (ic *interopContext) engineGetEntryScriptHash(v *vm.VM) error { func engineGetEntryScriptHash(ic *interopContext, v *vm.VM) error {
return pushContextScriptHash(v, v.Istack().Len()-1) return pushContextScriptHash(v, v.Istack().Len()-1)
} }
// runtimePlatform returns the name of the platform. // runtimePlatform returns the name of the platform.
func (ic *interopContext) runtimePlatform(v *vm.VM) error { func runtimePlatform(ic *interopContext, v *vm.VM) error {
v.Estack().PushVal([]byte("NEO")) v.Estack().PushVal([]byte("NEO"))
return nil return nil
} }
// runtimeGetTrigger returns the script trigger. // runtimeGetTrigger returns the script trigger.
func (ic *interopContext) runtimeGetTrigger(v *vm.VM) error { func runtimeGetTrigger(ic *interopContext, v *vm.VM) error {
v.Estack().PushVal(byte(ic.trigger)) v.Estack().PushVal(byte(ic.trigger))
return nil return nil
} }
// checkHashedWitness checks given hash against current list of script hashes // checkHashedWitness checks given hash against current list of script hashes
// for verifying in the interop context. // for verifying in the interop context.
func (ic *interopContext) checkHashedWitness(hash util.Uint160) (bool, error) { func checkHashedWitness(ic *interopContext, hash util.Uint160) (bool, error) {
hashes, err := ic.bc.GetScriptHashesForVerifying(ic.tx) hashes, err := ic.bc.GetScriptHashesForVerifying(ic.tx)
if err != nil { if err != nil {
return false, gherr.Wrap(err, "failed to get script hashes") return false, gherr.Wrap(err, "failed to get script hashes")
@ -310,12 +310,12 @@ func (ic *interopContext) checkHashedWitness(hash util.Uint160) (bool, error) {
// checkKeyedWitness checks hash of signature check contract with a given public // checkKeyedWitness checks hash of signature check contract with a given public
// key against current list of script hashes for verifying in the interop context. // key against current list of script hashes for verifying in the interop context.
func (ic *interopContext) checkKeyedWitness(key *keys.PublicKey) (bool, error) { func checkKeyedWitness(ic *interopContext, key *keys.PublicKey) (bool, error) {
return ic.checkHashedWitness(key.GetScriptHash()) return checkHashedWitness(ic, key.GetScriptHash())
} }
// runtimeCheckWitness checks witnesses. // runtimeCheckWitness checks witnesses.
func (ic *interopContext) runtimeCheckWitness(v *vm.VM) error { func runtimeCheckWitness(ic *interopContext, v *vm.VM) error {
var res bool var res bool
var err error var err error
@ -327,9 +327,9 @@ func (ic *interopContext) runtimeCheckWitness(v *vm.VM) error {
if err != nil { if err != nil {
return errors.New("parameter given is neither a key nor a hash") return errors.New("parameter given is neither a key nor a hash")
} }
res, err = ic.checkKeyedWitness(key) res, err = checkKeyedWitness(ic, key)
} else { } else {
res, err = ic.checkHashedWitness(hash) res, err = checkHashedWitness(ic, hash)
} }
if err != nil { if err != nil {
return gherr.Wrap(err, "failed to check") return gherr.Wrap(err, "failed to check")
@ -340,7 +340,7 @@ func (ic *interopContext) runtimeCheckWitness(v *vm.VM) error {
// runtimeNotify should pass stack item to the notify plugin to handle it, but // runtimeNotify should pass stack item to the notify plugin to handle it, but
// in neo-go the only meaningful thing to do here is to log. // in neo-go the only meaningful thing to do here is to log.
func (ic *interopContext) runtimeNotify(v *vm.VM) error { func runtimeNotify(ic *interopContext, v *vm.VM) error {
// It can be just about anything. // It can be just about anything.
e := v.Estack().Pop() e := v.Estack().Pop()
item := e.Item() item := e.Item()
@ -359,7 +359,7 @@ func (ic *interopContext) runtimeNotify(v *vm.VM) error {
} }
// runtimeLog logs the message passed. // runtimeLog logs the message passed.
func (ic *interopContext) runtimeLog(v *vm.VM) error { func runtimeLog(ic *interopContext, v *vm.VM) error {
msg := fmt.Sprintf("%q", v.Estack().Pop().Bytes()) msg := fmt.Sprintf("%q", v.Estack().Pop().Bytes())
ic.log.Info("runtime log", ic.log.Info("runtime log",
zap.Stringer("script", getContextScriptHash(v, 0)), zap.Stringer("script", getContextScriptHash(v, 0)),
@ -369,7 +369,7 @@ func (ic *interopContext) runtimeLog(v *vm.VM) error {
// runtimeGetTime returns timestamp of the block being verified, or the latest // runtimeGetTime returns timestamp of the block being verified, or the latest
// one in the blockchain if no block is given to interopContext. // one in the blockchain if no block is given to interopContext.
func (ic *interopContext) runtimeGetTime(v *vm.VM) error { func runtimeGetTime(ic *interopContext, v *vm.VM) error {
var header *block.Header var header *block.Header
if ic.block == nil { if ic.block == nil {
var err error var err error
@ -386,16 +386,16 @@ func (ic *interopContext) runtimeGetTime(v *vm.VM) error {
/* /*
// runtimeSerialize serializes given stack item. // runtimeSerialize serializes given stack item.
func (ic *interopContext) runtimeSerialize(v *vm.VM) error { func runtimeSerialize(ic *interopContext, v *vm.VM) error {
panic("TODO") panic("TODO")
} }
// runtimeDeserialize deserializes given stack item. // runtimeDeserialize deserializes given stack item.
func (ic *interopContext) runtimeDeserialize(v *vm.VM) error { func runtimeDeserialize(ic *interopContext, v *vm.VM) error {
panic("TODO") panic("TODO")
} }
*/ */
func (ic *interopContext) checkStorageContext(stc *StorageContext) error { func checkStorageContext(ic *interopContext, stc *StorageContext) error {
contract, err := ic.dao.GetContractState(stc.ScriptHash) contract, err := ic.dao.GetContractState(stc.ScriptHash)
if err != nil { if err != nil {
return errors.New("no contract found") return errors.New("no contract found")
@ -407,7 +407,7 @@ func (ic *interopContext) checkStorageContext(stc *StorageContext) error {
} }
// storageDelete deletes stored key-value pair. // storageDelete deletes stored key-value pair.
func (ic *interopContext) storageDelete(v *vm.VM) error { func storageDelete(ic *interopContext, v *vm.VM) error {
if ic.trigger != trigger.Application && ic.trigger != trigger.ApplicationR { if ic.trigger != trigger.Application && ic.trigger != trigger.ApplicationR {
return errors.New("can't delete when the trigger is not application") return errors.New("can't delete when the trigger is not application")
} }
@ -419,7 +419,7 @@ func (ic *interopContext) storageDelete(v *vm.VM) error {
if stc.ReadOnly { if stc.ReadOnly {
return errors.New("StorageContext is read only") return errors.New("StorageContext is read only")
} }
err := ic.checkStorageContext(stc) err := checkStorageContext(ic, stc)
if err != nil { if err != nil {
return err return err
} }
@ -432,13 +432,13 @@ func (ic *interopContext) storageDelete(v *vm.VM) error {
} }
// storageGet returns stored key-value pair. // storageGet returns stored key-value pair.
func (ic *interopContext) storageGet(v *vm.VM) error { func storageGet(ic *interopContext, v *vm.VM) error {
stcInterface := v.Estack().Pop().Value() stcInterface := v.Estack().Pop().Value()
stc, ok := stcInterface.(*StorageContext) stc, ok := stcInterface.(*StorageContext)
if !ok { if !ok {
return fmt.Errorf("%T is not a StorageContext", stcInterface) return fmt.Errorf("%T is not a StorageContext", stcInterface)
} }
err := ic.checkStorageContext(stc) err := checkStorageContext(ic, stc)
if err != nil { if err != nil {
return err return err
} }
@ -453,7 +453,7 @@ func (ic *interopContext) storageGet(v *vm.VM) error {
} }
// storageGetContext returns storage context (scripthash). // storageGetContext returns storage context (scripthash).
func (ic *interopContext) storageGetContext(v *vm.VM) error { func storageGetContext(ic *interopContext, v *vm.VM) error {
sc := &StorageContext{ sc := &StorageContext{
ScriptHash: getContextScriptHash(v, 0), ScriptHash: getContextScriptHash(v, 0),
ReadOnly: false, ReadOnly: false,
@ -463,7 +463,7 @@ func (ic *interopContext) storageGetContext(v *vm.VM) error {
} }
// storageGetReadOnlyContext returns read-only context (scripthash). // storageGetReadOnlyContext returns read-only context (scripthash).
func (ic *interopContext) storageGetReadOnlyContext(v *vm.VM) error { func storageGetReadOnlyContext(ic *interopContext, v *vm.VM) error {
sc := &StorageContext{ sc := &StorageContext{
ScriptHash: getContextScriptHash(v, 0), ScriptHash: getContextScriptHash(v, 0),
ReadOnly: true, ReadOnly: true,
@ -472,7 +472,7 @@ func (ic *interopContext) storageGetReadOnlyContext(v *vm.VM) error {
return nil return nil
} }
func (ic *interopContext) putWithContextAndFlags(stc *StorageContext, key []byte, value []byte, isConst bool) error { func putWithContextAndFlags(ic *interopContext, stc *StorageContext, key []byte, value []byte, isConst bool) error {
if ic.trigger != trigger.Application && ic.trigger != trigger.ApplicationR { if ic.trigger != trigger.Application && ic.trigger != trigger.ApplicationR {
return errors.New("can't delete when the trigger is not application") return errors.New("can't delete when the trigger is not application")
} }
@ -482,7 +482,7 @@ func (ic *interopContext) putWithContextAndFlags(stc *StorageContext, key []byte
if stc.ReadOnly { if stc.ReadOnly {
return errors.New("StorageContext is read only") return errors.New("StorageContext is read only")
} }
err := ic.checkStorageContext(stc) err := checkStorageContext(ic, stc)
if err != nil { if err != nil {
return err return err
} }
@ -499,7 +499,7 @@ func (ic *interopContext) putWithContextAndFlags(stc *StorageContext, key []byte
} }
// storagePutInternal is a unified implementation of storagePut and storagePutEx. // storagePutInternal is a unified implementation of storagePut and storagePutEx.
func (ic *interopContext) storagePutInternal(v *vm.VM, getFlag bool) error { func storagePutInternal(ic *interopContext, v *vm.VM, getFlag bool) error {
stcInterface := v.Estack().Pop().Value() stcInterface := v.Estack().Pop().Value()
stc, ok := stcInterface.(*StorageContext) stc, ok := stcInterface.(*StorageContext)
if !ok { if !ok {
@ -511,21 +511,21 @@ func (ic *interopContext) storagePutInternal(v *vm.VM, getFlag bool) error {
if getFlag { if getFlag {
flag = int(v.Estack().Pop().BigInt().Int64()) flag = int(v.Estack().Pop().BigInt().Int64())
} }
return ic.putWithContextAndFlags(stc, key, value, flag == 1) return putWithContextAndFlags(ic, stc, key, value, flag == 1)
} }
// storagePut puts key-value pair into the storage. // storagePut puts key-value pair into the storage.
func (ic *interopContext) storagePut(v *vm.VM) error { func storagePut(ic *interopContext, v *vm.VM) error {
return ic.storagePutInternal(v, false) return storagePutInternal(ic, v, false)
} }
// storagePutEx puts key-value pair with given flags into the storage. // storagePutEx puts key-value pair with given flags into the storage.
func (ic *interopContext) storagePutEx(v *vm.VM) error { func storagePutEx(ic *interopContext, v *vm.VM) error {
return ic.storagePutInternal(v, true) return storagePutInternal(ic, v, true)
} }
// storageContextAsReadOnly sets given context to read-only mode. // storageContextAsReadOnly sets given context to read-only mode.
func (ic *interopContext) storageContextAsReadOnly(v *vm.VM) error { func storageContextAsReadOnly(ic *interopContext, v *vm.VM) error {
stcInterface := v.Estack().Pop().Value() stcInterface := v.Estack().Pop().Value()
stc, ok := stcInterface.(*StorageContext) stc, ok := stcInterface.(*StorageContext)
if !ok { if !ok {
@ -543,7 +543,7 @@ func (ic *interopContext) storageContextAsReadOnly(v *vm.VM) error {
} }
// contractDestroy destroys a contract. // contractDestroy destroys a contract.
func (ic *interopContext) contractDestroy(v *vm.VM) error { func contractDestroy(ic *interopContext, v *vm.VM) error {
if ic.trigger != trigger.Application { if ic.trigger != trigger.Application {
return errors.New("can't destroy contract when not triggered by application") return errors.New("can't destroy contract when not triggered by application")
} }
@ -569,7 +569,7 @@ func (ic *interopContext) contractDestroy(v *vm.VM) error {
} }
// contractGetStorageContext retrieves StorageContext of a contract. // contractGetStorageContext retrieves StorageContext of a contract.
func (ic *interopContext) contractGetStorageContext(v *vm.VM) error { func contractGetStorageContext(ic *interopContext, v *vm.VM) error {
csInterface := v.Estack().Pop().Value() csInterface := v.Estack().Pop().Value()
cs, ok := csInterface.(*state.Contract) cs, ok := csInterface.(*state.Contract)
if !ok { if !ok {

View file

@ -39,7 +39,7 @@ func newInteropContext(trigger trigger.Type, bc Blockchainer, d dao.DAO, block *
// SpawnVM returns a VM with script getter and interop functions set // SpawnVM returns a VM with script getter and interop functions set
// up for current blockchain. // up for current blockchain.
func (ic *interopContext) SpawnVM() *vm.VM { func SpawnVM(ic *interopContext) *vm.VM {
vm := vm.New() vm := vm.New()
vm.SetScriptGetter(func(hash util.Uint160) ([]byte, bool) { vm.SetScriptGetter(func(hash util.Uint160) ([]byte, bool) {
cs, err := ic.dao.GetContractState(hash) cs, err := ic.dao.GetContractState(hash)
@ -49,8 +49,8 @@ func (ic *interopContext) SpawnVM() *vm.VM {
hasDynamicInvoke := (cs.Properties & smartcontract.HasDynamicInvoke) != 0 hasDynamicInvoke := (cs.Properties & smartcontract.HasDynamicInvoke) != 0
return cs.Script, hasDynamicInvoke return cs.Script, hasDynamicInvoke
}) })
vm.RegisterInteropGetter(ic.getSystemInterop) vm.RegisterInteropGetter(getSystemInterop(ic))
vm.RegisterInteropGetter(ic.getNeoInterop) vm.RegisterInteropGetter(getNeoInterop(ic))
return vm return vm
} }
@ -66,213 +66,214 @@ type interopedFunction struct {
// getSystemInterop returns matching interop function from the System namespace // getSystemInterop returns matching interop function from the System namespace
// for a given id in the current context. // for a given id in the current context.
func (ic *interopContext) getSystemInterop(id uint32) *vm.InteropFuncPrice { func getSystemInterop(ic *interopContext) vm.InteropGetterFunc {
return ic.getInteropFromSlice(id, systemInterops) return getInteropFromSlice(ic, systemInterops)
} }
// getNeoInterop returns matching interop function from the Neo and AntShares // getNeoInterop returns matching interop function from the Neo and AntShares
// namespaces for a given id in the current context. // namespaces for a given id in the current context.
func (ic *interopContext) getNeoInterop(id uint32) *vm.InteropFuncPrice { func getNeoInterop(ic *interopContext) vm.InteropGetterFunc {
return ic.getInteropFromSlice(id, neoInterops) return getInteropFromSlice(ic, neoInterops)
} }
// getInteropFromSlice returns matching interop function from the given slice of // getInteropFromSlice returns matching interop function from the given slice of
// interop functions in the current context. // interop functions in the current context.
func (ic *interopContext) getInteropFromSlice(id uint32, slice []interopedFunction) *vm.InteropFuncPrice { func getInteropFromSlice(ic *interopContext, slice []interopedFunction) func(uint32) *vm.InteropFuncPrice {
return func(id uint32) *vm.InteropFuncPrice {
n := sort.Search(len(slice), func(i int) bool { n := sort.Search(len(slice), func(i int) bool {
return slice[i].ID >= id return slice[i].ID >= id
}) })
if n < len(slice) && slice[n].ID == id { if n < len(slice) && slice[n].ID == id {
// Currying, yay!
return &vm.InteropFuncPrice{Func: func(v *vm.VM) error { return &vm.InteropFuncPrice{Func: func(v *vm.VM) error {
return slice[n].Func(ic, v) return slice[n].Func(ic, v)
}, Price: slice[n].Price} }, Price: slice[n].Price}
} }
return nil return nil
} }
}
// All lists are sorted, keep 'em this way, please. // All lists are sorted, keep 'em this way, please.
var systemInterops = []interopedFunction{ var systemInterops = []interopedFunction{
{Name: "System.Block.GetTransaction", Func: (*interopContext).blockGetTransaction, Price: 1}, {Name: "System.Block.GetTransaction", Func: blockGetTransaction, Price: 1},
{Name: "System.Block.GetTransactionCount", Func: (*interopContext).blockGetTransactionCount, Price: 1}, {Name: "System.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1},
{Name: "System.Block.GetTransactions", Func: (*interopContext).blockGetTransactions, Price: 1}, {Name: "System.Block.GetTransactions", Func: blockGetTransactions, Price: 1},
{Name: "System.Blockchain.GetBlock", Func: (*interopContext).bcGetBlock, Price: 200}, {Name: "System.Blockchain.GetBlock", Func: bcGetBlock, Price: 200},
{Name: "System.Blockchain.GetContract", Func: (*interopContext).bcGetContract, Price: 100}, {Name: "System.Blockchain.GetContract", Func: bcGetContract, Price: 100},
{Name: "System.Blockchain.GetHeader", Func: (*interopContext).bcGetHeader, Price: 100}, {Name: "System.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
{Name: "System.Blockchain.GetHeight", Func: (*interopContext).bcGetHeight, Price: 1}, {Name: "System.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
{Name: "System.Blockchain.GetTransaction", Func: (*interopContext).bcGetTransaction, Price: 200}, {Name: "System.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 200},
{Name: "System.Blockchain.GetTransactionHeight", Func: (*interopContext).bcGetTransactionHeight, Price: 100}, {Name: "System.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
{Name: "System.Contract.Destroy", Func: (*interopContext).contractDestroy, Price: 1}, {Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1},
{Name: "System.Contract.GetStorageContext", Func: (*interopContext).contractGetStorageContext, Price: 1}, {Name: "System.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
{Name: "System.ExecutionEngine.GetCallingScriptHash", Func: (*interopContext).engineGetCallingScriptHash, Price: 1}, {Name: "System.ExecutionEngine.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 1},
{Name: "System.ExecutionEngine.GetEntryScriptHash", Func: (*interopContext).engineGetEntryScriptHash, Price: 1}, {Name: "System.ExecutionEngine.GetEntryScriptHash", Func: engineGetEntryScriptHash, Price: 1},
{Name: "System.ExecutionEngine.GetExecutingScriptHash", Func: (*interopContext).engineGetExecutingScriptHash, Price: 1}, {Name: "System.ExecutionEngine.GetExecutingScriptHash", Func: engineGetExecutingScriptHash, Price: 1},
{Name: "System.ExecutionEngine.GetScriptContainer", Func: (*interopContext).engineGetScriptContainer, Price: 1}, {Name: "System.ExecutionEngine.GetScriptContainer", Func: engineGetScriptContainer, Price: 1},
{Name: "System.Header.GetHash", Func: (*interopContext).headerGetHash, Price: 1}, {Name: "System.Header.GetHash", Func: headerGetHash, Price: 1},
{Name: "System.Header.GetIndex", Func: (*interopContext).headerGetIndex, Price: 1}, {Name: "System.Header.GetIndex", Func: headerGetIndex, Price: 1},
{Name: "System.Header.GetPrevHash", Func: (*interopContext).headerGetPrevHash, Price: 1}, {Name: "System.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1},
{Name: "System.Header.GetTimestamp", Func: (*interopContext).headerGetTimestamp, Price: 1}, {Name: "System.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1},
{Name: "System.Runtime.CheckWitness", Func: (*interopContext).runtimeCheckWitness, Price: 200}, {Name: "System.Runtime.CheckWitness", Func: runtimeCheckWitness, Price: 200},
{Name: "System.Runtime.Deserialize", Func: (*interopContext).runtimeDeserialize, Price: 1}, {Name: "System.Runtime.Deserialize", Func: runtimeDeserialize, Price: 1},
{Name: "System.Runtime.GetTime", Func: (*interopContext).runtimeGetTime, Price: 1}, {Name: "System.Runtime.GetTime", Func: runtimeGetTime, Price: 1},
{Name: "System.Runtime.GetTrigger", Func: (*interopContext).runtimeGetTrigger, Price: 1}, {Name: "System.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 1},
{Name: "System.Runtime.Log", Func: (*interopContext).runtimeLog, Price: 1}, {Name: "System.Runtime.Log", Func: runtimeLog, Price: 1},
{Name: "System.Runtime.Notify", Func: (*interopContext).runtimeNotify, Price: 1}, {Name: "System.Runtime.Notify", Func: runtimeNotify, Price: 1},
{Name: "System.Runtime.Platform", Func: (*interopContext).runtimePlatform, Price: 1}, {Name: "System.Runtime.Platform", Func: runtimePlatform, Price: 1},
{Name: "System.Runtime.Serialize", Func: (*interopContext).runtimeSerialize, Price: 1}, {Name: "System.Runtime.Serialize", Func: runtimeSerialize, Price: 1},
{Name: "System.Storage.Delete", Func: (*interopContext).storageDelete, Price: 100}, {Name: "System.Storage.Delete", Func: storageDelete, Price: 100},
{Name: "System.Storage.Get", Func: (*interopContext).storageGet, Price: 100}, {Name: "System.Storage.Get", Func: storageGet, Price: 100},
{Name: "System.Storage.GetContext", Func: (*interopContext).storageGetContext, Price: 1}, {Name: "System.Storage.GetContext", Func: storageGetContext, Price: 1},
{Name: "System.Storage.GetReadOnlyContext", Func: (*interopContext).storageGetReadOnlyContext, Price: 1}, {Name: "System.Storage.GetReadOnlyContext", Func: storageGetReadOnlyContext, Price: 1},
{Name: "System.Storage.Put", Func: (*interopContext).storagePut, Price: 0}, // These don't have static price in C# code. {Name: "System.Storage.Put", Func: storagePut, Price: 0}, // These don't have static price in C# code.
{Name: "System.Storage.PutEx", Func: (*interopContext).storagePutEx, Price: 0}, {Name: "System.Storage.PutEx", Func: storagePutEx, Price: 0},
{Name: "System.StorageContext.AsReadOnly", Func: (*interopContext).storageContextAsReadOnly, Price: 1}, {Name: "System.StorageContext.AsReadOnly", Func: storageContextAsReadOnly, Price: 1},
{Name: "System.Transaction.GetHash", Func: (*interopContext).txGetHash, Price: 1}, {Name: "System.Transaction.GetHash", Func: txGetHash, Price: 1},
} }
var neoInterops = []interopedFunction{ var neoInterops = []interopedFunction{
{Name: "Neo.Account.GetBalance", Func: (*interopContext).accountGetBalance, Price: 1}, {Name: "Neo.Account.GetBalance", Func: accountGetBalance, Price: 1},
{Name: "Neo.Account.GetScriptHash", Func: (*interopContext).accountGetScriptHash, Price: 1}, {Name: "Neo.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
{Name: "Neo.Account.GetVotes", Func: (*interopContext).accountGetVotes, Price: 1}, {Name: "Neo.Account.GetVotes", Func: accountGetVotes, Price: 1},
{Name: "Neo.Account.IsStandard", Func: (*interopContext).accountIsStandard, Price: 100}, {Name: "Neo.Account.IsStandard", Func: accountIsStandard, Price: 100},
{Name: "Neo.Asset.Create", Func: (*interopContext).assetCreate, Price: 0}, {Name: "Neo.Asset.Create", Func: assetCreate, Price: 0},
{Name: "Neo.Asset.GetAdmin", Func: (*interopContext).assetGetAdmin, Price: 1}, {Name: "Neo.Asset.GetAdmin", Func: assetGetAdmin, Price: 1},
{Name: "Neo.Asset.GetAmount", Func: (*interopContext).assetGetAmount, Price: 1}, {Name: "Neo.Asset.GetAmount", Func: assetGetAmount, Price: 1},
{Name: "Neo.Asset.GetAssetId", Func: (*interopContext).assetGetAssetID, Price: 1}, {Name: "Neo.Asset.GetAssetId", Func: assetGetAssetID, Price: 1},
{Name: "Neo.Asset.GetAssetType", Func: (*interopContext).assetGetAssetType, Price: 1}, {Name: "Neo.Asset.GetAssetType", Func: assetGetAssetType, Price: 1},
{Name: "Neo.Asset.GetAvailable", Func: (*interopContext).assetGetAvailable, Price: 1}, {Name: "Neo.Asset.GetAvailable", Func: assetGetAvailable, Price: 1},
{Name: "Neo.Asset.GetIssuer", Func: (*interopContext).assetGetIssuer, Price: 1}, {Name: "Neo.Asset.GetIssuer", Func: assetGetIssuer, Price: 1},
{Name: "Neo.Asset.GetOwner", Func: (*interopContext).assetGetOwner, Price: 1}, {Name: "Neo.Asset.GetOwner", Func: assetGetOwner, Price: 1},
{Name: "Neo.Asset.GetPrecision", Func: (*interopContext).assetGetPrecision, Price: 1}, {Name: "Neo.Asset.GetPrecision", Func: assetGetPrecision, Price: 1},
{Name: "Neo.Asset.Renew", Func: (*interopContext).assetRenew, Price: 0}, {Name: "Neo.Asset.Renew", Func: assetRenew, Price: 0},
{Name: "Neo.Attribute.GetData", Func: (*interopContext).attrGetData, Price: 1}, {Name: "Neo.Attribute.GetData", Func: attrGetData, Price: 1},
{Name: "Neo.Attribute.GetUsage", Func: (*interopContext).attrGetUsage, Price: 1}, {Name: "Neo.Attribute.GetUsage", Func: attrGetUsage, Price: 1},
{Name: "Neo.Block.GetTransaction", Func: (*interopContext).blockGetTransaction, Price: 1}, {Name: "Neo.Block.GetTransaction", Func: blockGetTransaction, Price: 1},
{Name: "Neo.Block.GetTransactionCount", Func: (*interopContext).blockGetTransactionCount, Price: 1}, {Name: "Neo.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1},
{Name: "Neo.Block.GetTransactions", Func: (*interopContext).blockGetTransactions, Price: 1}, {Name: "Neo.Block.GetTransactions", Func: blockGetTransactions, Price: 1},
{Name: "Neo.Blockchain.GetAccount", Func: (*interopContext).bcGetAccount, Price: 100}, {Name: "Neo.Blockchain.GetAccount", Func: bcGetAccount, Price: 100},
{Name: "Neo.Blockchain.GetAsset", Func: (*interopContext).bcGetAsset, Price: 100}, {Name: "Neo.Blockchain.GetAsset", Func: bcGetAsset, Price: 100},
{Name: "Neo.Blockchain.GetBlock", Func: (*interopContext).bcGetBlock, Price: 200}, {Name: "Neo.Blockchain.GetBlock", Func: bcGetBlock, Price: 200},
{Name: "Neo.Blockchain.GetContract", Func: (*interopContext).bcGetContract, Price: 100}, {Name: "Neo.Blockchain.GetContract", Func: bcGetContract, Price: 100},
{Name: "Neo.Blockchain.GetHeader", Func: (*interopContext).bcGetHeader, Price: 100}, {Name: "Neo.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
{Name: "Neo.Blockchain.GetHeight", Func: (*interopContext).bcGetHeight, Price: 1}, {Name: "Neo.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
{Name: "Neo.Blockchain.GetTransaction", Func: (*interopContext).bcGetTransaction, Price: 100}, {Name: "Neo.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 100},
{Name: "Neo.Blockchain.GetTransactionHeight", Func: (*interopContext).bcGetTransactionHeight, Price: 100}, {Name: "Neo.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
{Name: "Neo.Blockchain.GetValidators", Func: (*interopContext).bcGetValidators, Price: 200}, {Name: "Neo.Blockchain.GetValidators", Func: bcGetValidators, Price: 200},
{Name: "Neo.Contract.Create", Func: (*interopContext).contractCreate, Price: 0}, {Name: "Neo.Contract.Create", Func: contractCreate, Price: 0},
{Name: "Neo.Contract.Destroy", Func: (*interopContext).contractDestroy, Price: 1}, {Name: "Neo.Contract.Destroy", Func: contractDestroy, Price: 1},
{Name: "Neo.Contract.GetScript", Func: (*interopContext).contractGetScript, Price: 1}, {Name: "Neo.Contract.GetScript", Func: contractGetScript, Price: 1},
{Name: "Neo.Contract.GetStorageContext", Func: (*interopContext).contractGetStorageContext, Price: 1}, {Name: "Neo.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
{Name: "Neo.Contract.IsPayable", Func: (*interopContext).contractIsPayable, Price: 1}, {Name: "Neo.Contract.IsPayable", Func: contractIsPayable, Price: 1},
{Name: "Neo.Contract.Migrate", Func: (*interopContext).contractMigrate, Price: 0}, {Name: "Neo.Contract.Migrate", Func: contractMigrate, Price: 0},
{Name: "Neo.Enumerator.Concat", Func: (*interopContext).enumeratorConcat, Price: 1}, {Name: "Neo.Enumerator.Concat", Func: enumeratorConcat, Price: 1},
{Name: "Neo.Enumerator.Create", Func: (*interopContext).enumeratorCreate, Price: 1}, {Name: "Neo.Enumerator.Create", Func: enumeratorCreate, Price: 1},
{Name: "Neo.Enumerator.Next", Func: (*interopContext).enumeratorNext, Price: 1}, {Name: "Neo.Enumerator.Next", Func: enumeratorNext, Price: 1},
{Name: "Neo.Enumerator.Value", Func: (*interopContext).enumeratorValue, Price: 1}, {Name: "Neo.Enumerator.Value", Func: enumeratorValue, Price: 1},
{Name: "Neo.Header.GetConsensusData", Func: (*interopContext).headerGetConsensusData, Price: 1}, {Name: "Neo.Header.GetConsensusData", Func: headerGetConsensusData, Price: 1},
{Name: "Neo.Header.GetHash", Func: (*interopContext).headerGetHash, Price: 1}, {Name: "Neo.Header.GetHash", Func: headerGetHash, Price: 1},
{Name: "Neo.Header.GetIndex", Func: (*interopContext).headerGetIndex, Price: 1}, {Name: "Neo.Header.GetIndex", Func: headerGetIndex, Price: 1},
{Name: "Neo.Header.GetMerkleRoot", Func: (*interopContext).headerGetMerkleRoot, Price: 1}, {Name: "Neo.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
{Name: "Neo.Header.GetNextConsensus", Func: (*interopContext).headerGetNextConsensus, Price: 1}, {Name: "Neo.Header.GetNextConsensus", Func: headerGetNextConsensus, Price: 1},
{Name: "Neo.Header.GetPrevHash", Func: (*interopContext).headerGetPrevHash, Price: 1}, {Name: "Neo.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1},
{Name: "Neo.Header.GetTimestamp", Func: (*interopContext).headerGetTimestamp, Price: 1}, {Name: "Neo.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1},
{Name: "Neo.Header.GetVersion", Func: (*interopContext).headerGetVersion, Price: 1}, {Name: "Neo.Header.GetVersion", Func: headerGetVersion, Price: 1},
{Name: "Neo.Input.GetHash", Func: (*interopContext).inputGetHash, Price: 1}, {Name: "Neo.Input.GetHash", Func: inputGetHash, Price: 1},
{Name: "Neo.Input.GetIndex", Func: (*interopContext).inputGetIndex, Price: 1}, {Name: "Neo.Input.GetIndex", Func: inputGetIndex, Price: 1},
{Name: "Neo.InvocationTransaction.GetScript", Func: (*interopContext).invocationTxGetScript, Price: 1}, {Name: "Neo.InvocationTransaction.GetScript", Func: invocationTxGetScript, Price: 1},
{Name: "Neo.Iterator.Concat", Func: (*interopContext).iteratorConcat, Price: 1}, {Name: "Neo.Iterator.Concat", Func: iteratorConcat, Price: 1},
{Name: "Neo.Iterator.Create", Func: (*interopContext).iteratorCreate, Price: 1}, {Name: "Neo.Iterator.Create", Func: iteratorCreate, Price: 1},
{Name: "Neo.Iterator.Key", Func: (*interopContext).iteratorKey, Price: 1}, {Name: "Neo.Iterator.Key", Func: iteratorKey, Price: 1},
{Name: "Neo.Iterator.Keys", Func: (*interopContext).iteratorKeys, Price: 1}, {Name: "Neo.Iterator.Keys", Func: iteratorKeys, Price: 1},
{Name: "Neo.Iterator.Values", Func: (*interopContext).iteratorValues, Price: 1}, {Name: "Neo.Iterator.Values", Func: iteratorValues, Price: 1},
{Name: "Neo.Output.GetAssetId", Func: (*interopContext).outputGetAssetID, Price: 1}, {Name: "Neo.Output.GetAssetId", Func: outputGetAssetID, Price: 1},
{Name: "Neo.Output.GetScriptHash", Func: (*interopContext).outputGetScriptHash, Price: 1}, {Name: "Neo.Output.GetScriptHash", Func: outputGetScriptHash, Price: 1},
{Name: "Neo.Output.GetValue", Func: (*interopContext).outputGetValue, Price: 1}, {Name: "Neo.Output.GetValue", Func: outputGetValue, Price: 1},
{Name: "Neo.Runtime.CheckWitness", Func: (*interopContext).runtimeCheckWitness, Price: 200}, {Name: "Neo.Runtime.CheckWitness", Func: runtimeCheckWitness, Price: 200},
{Name: "Neo.Runtime.Deserialize", Func: (*interopContext).runtimeDeserialize, Price: 1}, {Name: "Neo.Runtime.Deserialize", Func: runtimeDeserialize, Price: 1},
{Name: "Neo.Runtime.GetTime", Func: (*interopContext).runtimeGetTime, Price: 1}, {Name: "Neo.Runtime.GetTime", Func: runtimeGetTime, Price: 1},
{Name: "Neo.Runtime.GetTrigger", Func: (*interopContext).runtimeGetTrigger, Price: 1}, {Name: "Neo.Runtime.GetTrigger", Func: runtimeGetTrigger, Price: 1},
{Name: "Neo.Runtime.Log", Func: (*interopContext).runtimeLog, Price: 1}, {Name: "Neo.Runtime.Log", Func: runtimeLog, Price: 1},
{Name: "Neo.Runtime.Notify", Func: (*interopContext).runtimeNotify, Price: 1}, {Name: "Neo.Runtime.Notify", Func: runtimeNotify, Price: 1},
{Name: "Neo.Runtime.Serialize", Func: (*interopContext).runtimeSerialize, Price: 1}, {Name: "Neo.Runtime.Serialize", Func: runtimeSerialize, Price: 1},
{Name: "Neo.Storage.Delete", Func: (*interopContext).storageDelete, Price: 100}, {Name: "Neo.Storage.Delete", Func: storageDelete, Price: 100},
{Name: "Neo.Storage.Find", Func: (*interopContext).storageFind, Price: 1}, {Name: "Neo.Storage.Find", Func: storageFind, Price: 1},
{Name: "Neo.Storage.Get", Func: (*interopContext).storageGet, Price: 100}, {Name: "Neo.Storage.Get", Func: storageGet, Price: 100},
{Name: "Neo.Storage.GetContext", Func: (*interopContext).storageGetContext, Price: 1}, {Name: "Neo.Storage.GetContext", Func: storageGetContext, Price: 1},
{Name: "Neo.Storage.GetReadOnlyContext", Func: (*interopContext).storageGetReadOnlyContext, Price: 1}, {Name: "Neo.Storage.GetReadOnlyContext", Func: storageGetReadOnlyContext, Price: 1},
{Name: "Neo.Storage.Put", Func: (*interopContext).storagePut, Price: 0}, {Name: "Neo.Storage.Put", Func: storagePut, Price: 0},
{Name: "Neo.StorageContext.AsReadOnly", Func: (*interopContext).storageContextAsReadOnly, Price: 1}, {Name: "Neo.StorageContext.AsReadOnly", Func: storageContextAsReadOnly, Price: 1},
{Name: "Neo.Transaction.GetAttributes", Func: (*interopContext).txGetAttributes, Price: 1}, {Name: "Neo.Transaction.GetAttributes", Func: txGetAttributes, Price: 1},
{Name: "Neo.Transaction.GetHash", Func: (*interopContext).txGetHash, Price: 1}, {Name: "Neo.Transaction.GetHash", Func: txGetHash, Price: 1},
{Name: "Neo.Transaction.GetInputs", Func: (*interopContext).txGetInputs, Price: 1}, {Name: "Neo.Transaction.GetInputs", Func: txGetInputs, Price: 1},
{Name: "Neo.Transaction.GetOutputs", Func: (*interopContext).txGetOutputs, Price: 1}, {Name: "Neo.Transaction.GetOutputs", Func: txGetOutputs, Price: 1},
{Name: "Neo.Transaction.GetReferences", Func: (*interopContext).txGetReferences, Price: 200}, {Name: "Neo.Transaction.GetReferences", Func: txGetReferences, Price: 200},
{Name: "Neo.Transaction.GetType", Func: (*interopContext).txGetType, Price: 1}, {Name: "Neo.Transaction.GetType", Func: txGetType, Price: 1},
{Name: "Neo.Transaction.GetUnspentCoins", Func: (*interopContext).txGetUnspentCoins, Price: 200}, {Name: "Neo.Transaction.GetUnspentCoins", Func: txGetUnspentCoins, Price: 200},
{Name: "Neo.Transaction.GetWitnesses", Func: (*interopContext).txGetWitnesses, Price: 200}, {Name: "Neo.Transaction.GetWitnesses", Func: txGetWitnesses, Price: 200},
{Name: "Neo.Witness.GetVerificationScript", Func: (*interopContext).witnessGetVerificationScript, Price: 100}, {Name: "Neo.Witness.GetVerificationScript", Func: witnessGetVerificationScript, Price: 100},
// Aliases. // Aliases.
{Name: "Neo.Iterator.Next", Func: (*interopContext).enumeratorNext, Price: 1}, {Name: "Neo.Iterator.Next", Func: enumeratorNext, Price: 1},
{Name: "Neo.Iterator.Value", Func: (*interopContext).enumeratorValue, Price: 1}, {Name: "Neo.Iterator.Value", Func: enumeratorValue, Price: 1},
// Old compatibility APIs. // Old compatibility APIs.
{Name: "AntShares.Account.GetBalance", Func: (*interopContext).accountGetBalance, Price: 1}, {Name: "AntShares.Account.GetBalance", Func: accountGetBalance, Price: 1},
{Name: "AntShares.Account.GetScriptHash", Func: (*interopContext).accountGetScriptHash, Price: 1}, {Name: "AntShares.Account.GetScriptHash", Func: accountGetScriptHash, Price: 1},
{Name: "AntShares.Account.GetVotes", Func: (*interopContext).accountGetVotes, Price: 1}, {Name: "AntShares.Account.GetVotes", Func: accountGetVotes, Price: 1},
{Name: "AntShares.Asset.Create", Func: (*interopContext).assetCreate, Price: 0}, {Name: "AntShares.Asset.Create", Func: assetCreate, Price: 0},
{Name: "AntShares.Asset.GetAdmin", Func: (*interopContext).assetGetAdmin, Price: 1}, {Name: "AntShares.Asset.GetAdmin", Func: assetGetAdmin, Price: 1},
{Name: "AntShares.Asset.GetAmount", Func: (*interopContext).assetGetAmount, Price: 1}, {Name: "AntShares.Asset.GetAmount", Func: assetGetAmount, Price: 1},
{Name: "AntShares.Asset.GetAssetId", Func: (*interopContext).assetGetAssetID, Price: 1}, {Name: "AntShares.Asset.GetAssetId", Func: assetGetAssetID, Price: 1},
{Name: "AntShares.Asset.GetAssetType", Func: (*interopContext).assetGetAssetType, Price: 1}, {Name: "AntShares.Asset.GetAssetType", Func: assetGetAssetType, Price: 1},
{Name: "AntShares.Asset.GetAvailable", Func: (*interopContext).assetGetAvailable, Price: 1}, {Name: "AntShares.Asset.GetAvailable", Func: assetGetAvailable, Price: 1},
{Name: "AntShares.Asset.GetIssuer", Func: (*interopContext).assetGetIssuer, Price: 1}, {Name: "AntShares.Asset.GetIssuer", Func: assetGetIssuer, Price: 1},
{Name: "AntShares.Asset.GetOwner", Func: (*interopContext).assetGetOwner, Price: 1}, {Name: "AntShares.Asset.GetOwner", Func: assetGetOwner, Price: 1},
{Name: "AntShares.Asset.GetPrecision", Func: (*interopContext).assetGetPrecision, Price: 1}, {Name: "AntShares.Asset.GetPrecision", Func: assetGetPrecision, Price: 1},
{Name: "AntShares.Asset.Renew", Func: (*interopContext).assetRenew, Price: 0}, {Name: "AntShares.Asset.Renew", Func: assetRenew, Price: 0},
{Name: "AntShares.Attribute.GetData", Func: (*interopContext).attrGetData, Price: 1}, {Name: "AntShares.Attribute.GetData", Func: attrGetData, Price: 1},
{Name: "AntShares.Attribute.GetUsage", Func: (*interopContext).attrGetUsage, Price: 1}, {Name: "AntShares.Attribute.GetUsage", Func: attrGetUsage, Price: 1},
{Name: "AntShares.Block.GetTransaction", Func: (*interopContext).blockGetTransaction, Price: 1}, {Name: "AntShares.Block.GetTransaction", Func: blockGetTransaction, Price: 1},
{Name: "AntShares.Block.GetTransactionCount", Func: (*interopContext).blockGetTransactionCount, Price: 1}, {Name: "AntShares.Block.GetTransactionCount", Func: blockGetTransactionCount, Price: 1},
{Name: "AntShares.Block.GetTransactions", Func: (*interopContext).blockGetTransactions, Price: 1}, {Name: "AntShares.Block.GetTransactions", Func: blockGetTransactions, Price: 1},
{Name: "AntShares.Blockchain.GetAccount", Func: (*interopContext).bcGetAccount, Price: 100}, {Name: "AntShares.Blockchain.GetAccount", Func: bcGetAccount, Price: 100},
{Name: "AntShares.Blockchain.GetAsset", Func: (*interopContext).bcGetAsset, Price: 100}, {Name: "AntShares.Blockchain.GetAsset", Func: bcGetAsset, Price: 100},
{Name: "AntShares.Blockchain.GetBlock", Func: (*interopContext).bcGetBlock, Price: 200}, {Name: "AntShares.Blockchain.GetBlock", Func: bcGetBlock, Price: 200},
{Name: "AntShares.Blockchain.GetContract", Func: (*interopContext).bcGetContract, Price: 100}, {Name: "AntShares.Blockchain.GetContract", Func: bcGetContract, Price: 100},
{Name: "AntShares.Blockchain.GetHeader", Func: (*interopContext).bcGetHeader, Price: 100}, {Name: "AntShares.Blockchain.GetHeader", Func: bcGetHeader, Price: 100},
{Name: "AntShares.Blockchain.GetHeight", Func: (*interopContext).bcGetHeight, Price: 1}, {Name: "AntShares.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
{Name: "AntShares.Blockchain.GetTransaction", Func: (*interopContext).bcGetTransaction, Price: 100}, {Name: "AntShares.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 100},
{Name: "AntShares.Blockchain.GetValidators", Func: (*interopContext).bcGetValidators, Price: 200}, {Name: "AntShares.Blockchain.GetValidators", Func: bcGetValidators, Price: 200},
{Name: "AntShares.Contract.Create", Func: (*interopContext).contractCreate, Price: 0}, {Name: "AntShares.Contract.Create", Func: contractCreate, Price: 0},
{Name: "AntShares.Contract.Destroy", Func: (*interopContext).contractDestroy, Price: 1}, {Name: "AntShares.Contract.Destroy", Func: contractDestroy, Price: 1},
{Name: "AntShares.Contract.GetScript", Func: (*interopContext).contractGetScript, Price: 1}, {Name: "AntShares.Contract.GetScript", Func: contractGetScript, Price: 1},
{Name: "AntShares.Contract.GetStorageContext", Func: (*interopContext).contractGetStorageContext, Price: 1}, {Name: "AntShares.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
{Name: "AntShares.Contract.Migrate", Func: (*interopContext).contractMigrate, Price: 0}, {Name: "AntShares.Contract.Migrate", Func: contractMigrate, Price: 0},
{Name: "AntShares.Header.GetConsensusData", Func: (*interopContext).headerGetConsensusData, Price: 1}, {Name: "AntShares.Header.GetConsensusData", Func: headerGetConsensusData, Price: 1},
{Name: "AntShares.Header.GetHash", Func: (*interopContext).headerGetHash, Price: 1}, {Name: "AntShares.Header.GetHash", Func: headerGetHash, Price: 1},
{Name: "AntShares.Header.GetMerkleRoot", Func: (*interopContext).headerGetMerkleRoot, Price: 1}, {Name: "AntShares.Header.GetMerkleRoot", Func: headerGetMerkleRoot, Price: 1},
{Name: "AntShares.Header.GetNextConsensus", Func: (*interopContext).headerGetNextConsensus, Price: 1}, {Name: "AntShares.Header.GetNextConsensus", Func: headerGetNextConsensus, Price: 1},
{Name: "AntShares.Header.GetPrevHash", Func: (*interopContext).headerGetPrevHash, Price: 1}, {Name: "AntShares.Header.GetPrevHash", Func: headerGetPrevHash, Price: 1},
{Name: "AntShares.Header.GetTimestamp", Func: (*interopContext).headerGetTimestamp, Price: 1}, {Name: "AntShares.Header.GetTimestamp", Func: headerGetTimestamp, Price: 1},
{Name: "AntShares.Header.GetVersion", Func: (*interopContext).headerGetVersion, Price: 1}, {Name: "AntShares.Header.GetVersion", Func: headerGetVersion, Price: 1},
{Name: "AntShares.Input.GetHash", Func: (*interopContext).inputGetHash, Price: 1}, {Name: "AntShares.Input.GetHash", Func: inputGetHash, Price: 1},
{Name: "AntShares.Input.GetIndex", Func: (*interopContext).inputGetIndex, Price: 1}, {Name: "AntShares.Input.GetIndex", Func: inputGetIndex, Price: 1},
{Name: "AntShares.Output.GetAssetId", Func: (*interopContext).outputGetAssetID, Price: 1}, {Name: "AntShares.Output.GetAssetId", Func: outputGetAssetID, Price: 1},
{Name: "AntShares.Output.GetScriptHash", Func: (*interopContext).outputGetScriptHash, Price: 1}, {Name: "AntShares.Output.GetScriptHash", Func: outputGetScriptHash, Price: 1},
{Name: "AntShares.Output.GetValue", Func: (*interopContext).outputGetValue, Price: 1}, {Name: "AntShares.Output.GetValue", Func: outputGetValue, Price: 1},
{Name: "AntShares.Runtime.CheckWitness", Func: (*interopContext).runtimeCheckWitness, Price: 200}, {Name: "AntShares.Runtime.CheckWitness", Func: runtimeCheckWitness, Price: 200},
{Name: "AntShares.Runtime.Log", Func: (*interopContext).runtimeLog, Price: 1}, {Name: "AntShares.Runtime.Log", Func: runtimeLog, Price: 1},
{Name: "AntShares.Runtime.Notify", Func: (*interopContext).runtimeNotify, Price: 1}, {Name: "AntShares.Runtime.Notify", Func: runtimeNotify, Price: 1},
{Name: "AntShares.Storage.Delete", Func: (*interopContext).storageDelete, Price: 100}, {Name: "AntShares.Storage.Delete", Func: storageDelete, Price: 100},
{Name: "AntShares.Storage.Get", Func: (*interopContext).storageGet, Price: 100}, {Name: "AntShares.Storage.Get", Func: storageGet, Price: 100},
{Name: "AntShares.Storage.GetContext", Func: (*interopContext).storageGetContext, Price: 1}, {Name: "AntShares.Storage.GetContext", Func: storageGetContext, Price: 1},
{Name: "AntShares.Storage.Put", Func: (*interopContext).storagePut, Price: 0}, {Name: "AntShares.Storage.Put", Func: storagePut, Price: 0},
{Name: "AntShares.Transaction.GetAttributes", Func: (*interopContext).txGetAttributes, Price: 1}, {Name: "AntShares.Transaction.GetAttributes", Func: txGetAttributes, Price: 1},
{Name: "AntShares.Transaction.GetHash", Func: (*interopContext).txGetHash, Price: 1}, {Name: "AntShares.Transaction.GetHash", Func: txGetHash, Price: 1},
{Name: "AntShares.Transaction.GetInputs", Func: (*interopContext).txGetInputs, Price: 1}, {Name: "AntShares.Transaction.GetInputs", Func: txGetInputs, Price: 1},
{Name: "AntShares.Transaction.GetOutputs", Func: (*interopContext).txGetOutputs, Price: 1}, {Name: "AntShares.Transaction.GetOutputs", Func: txGetOutputs, Price: 1},
{Name: "AntShares.Transaction.GetReferences", Func: (*interopContext).txGetReferences, Price: 200}, {Name: "AntShares.Transaction.GetReferences", Func: txGetReferences, Price: 200},
{Name: "AntShares.Transaction.GetType", Func: (*interopContext).txGetType, Price: 1}, {Name: "AntShares.Transaction.GetType", Func: txGetType, Price: 1},
} }
// initIDinInteropsSlice initializes IDs from names in one given // initIDinInteropsSlice initializes IDs from names in one given

View file

@ -31,55 +31,55 @@ func TestUnexpectedNonInterops(t *testing.T) {
// All of these functions expect an interop item on the stack. // All of these functions expect an interop item on the stack.
funcs := []func(*interopContext, *vm.VM) error{ funcs := []func(*interopContext, *vm.VM) error{
(*interopContext).accountGetBalance, accountGetBalance,
(*interopContext).accountGetScriptHash, accountGetScriptHash,
(*interopContext).accountGetVotes, accountGetVotes,
(*interopContext).assetGetAdmin, assetGetAdmin,
(*interopContext).assetGetAmount, assetGetAmount,
(*interopContext).assetGetAssetID, assetGetAssetID,
(*interopContext).assetGetAssetType, assetGetAssetType,
(*interopContext).assetGetAvailable, assetGetAvailable,
(*interopContext).assetGetIssuer, assetGetIssuer,
(*interopContext).assetGetOwner, assetGetOwner,
(*interopContext).assetGetPrecision, assetGetPrecision,
(*interopContext).assetRenew, assetRenew,
(*interopContext).attrGetData, attrGetData,
(*interopContext).attrGetUsage, attrGetUsage,
(*interopContext).blockGetTransaction, blockGetTransaction,
(*interopContext).blockGetTransactionCount, blockGetTransactionCount,
(*interopContext).blockGetTransactions, blockGetTransactions,
(*interopContext).contractGetScript, contractGetScript,
(*interopContext).contractGetStorageContext, contractGetStorageContext,
(*interopContext).contractIsPayable, contractIsPayable,
(*interopContext).headerGetConsensusData, headerGetConsensusData,
(*interopContext).headerGetHash, headerGetHash,
(*interopContext).headerGetIndex, headerGetIndex,
(*interopContext).headerGetMerkleRoot, headerGetMerkleRoot,
(*interopContext).headerGetNextConsensus, headerGetNextConsensus,
(*interopContext).headerGetPrevHash, headerGetPrevHash,
(*interopContext).headerGetTimestamp, headerGetTimestamp,
(*interopContext).headerGetVersion, headerGetVersion,
(*interopContext).inputGetHash, inputGetHash,
(*interopContext).inputGetIndex, inputGetIndex,
(*interopContext).invocationTxGetScript, invocationTxGetScript,
(*interopContext).outputGetAssetID, outputGetAssetID,
(*interopContext).outputGetScriptHash, outputGetScriptHash,
(*interopContext).outputGetValue, outputGetValue,
(*interopContext).storageContextAsReadOnly, storageContextAsReadOnly,
(*interopContext).storageDelete, storageDelete,
(*interopContext).storageFind, storageFind,
(*interopContext).storageGet, storageGet,
(*interopContext).storagePut, storagePut,
(*interopContext).storagePutEx, storagePutEx,
(*interopContext).txGetAttributes, txGetAttributes,
(*interopContext).txGetHash, txGetHash,
(*interopContext).txGetInputs, txGetInputs,
(*interopContext).txGetOutputs, txGetOutputs,
(*interopContext).txGetReferences, txGetReferences,
(*interopContext).txGetType, txGetType,
(*interopContext).txGetUnspentCoins, txGetUnspentCoins,
(*interopContext).txGetWitnesses, txGetWitnesses,
(*interopContext).witnessGetVerificationScript, witnessGetVerificationScript,
} }
for _, f := range funcs { for _, f := range funcs {
for k, v := range vals { for k, v := range vals {