From 212cf44e26a7c1a7f53378643ce1fddf0bc5e0df Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 13 Dec 2019 17:10:51 +0300 Subject: [PATCH] core: get data from dao in interops It's more logically correct as Blockchain can be several transactions behind in terms of its state. --- pkg/core/blockchain.go | 4 ++-- pkg/core/interop_neo.go | 41 ++++++++++++++++++-------------------- pkg/core/interop_system.go | 24 +++++++++++----------- 3 files changed, 33 insertions(+), 36 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index e92016dc6..07e39322b 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1336,8 +1336,8 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([ func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM { vm := vm.New() vm.SetScriptGetter(func(hash util.Uint160) []byte { - cs := bc.GetContractState(hash) - if cs == nil { + cs, err := interopCtx.dao.GetContractState(hash) + if err != nil { return nil } return cs.Script diff --git a/pkg/core/interop_neo.go b/pkg/core/interop_neo.go index 31576d95a..44c55b225 100644 --- a/pkg/core/interop_neo.go +++ b/pkg/core/interop_neo.go @@ -172,8 +172,8 @@ func (ic *interopContext) txGetUnspentCoins(v *vm.VM) error { if !ok { return errors.New("value is not a transaction") } - ucs := ic.bc.GetUnspentCoinState(tx.Hash()) - if ucs == nil { + ucs, err := ic.dao.GetUnspentCoinState(tx.Hash()) + if err != nil { return errors.New("no unspent coin state found") } v.Estack().PushVal(vm.NewInteropItem(ucs)) @@ -200,10 +200,7 @@ func (ic *interopContext) txGetWitnesses(v *vm.VM) error { // bcGetValidators returns validators. func (ic *interopContext) bcGetValidators(v *vm.VM) error { - validators, err := ic.bc.GetValidators() - if err != nil { - return err - } + validators := ic.dao.GetValidators() v.Estack().PushVal(validators) return nil } @@ -315,9 +312,9 @@ func (ic *interopContext) bcGetAccount(v *vm.VM) error { if err != nil { return err } - acc := ic.bc.GetAccountState(acchash) - if acc == nil { - acc = state.NewAccount(acchash) + acc, err := ic.dao.GetAccountStateOrNew(acchash) + if err != nil { + return err } v.Estack().PushVal(vm.NewInteropItem(acc)) return nil @@ -330,8 +327,8 @@ func (ic *interopContext) bcGetAsset(v *vm.VM) error { if err != nil { return err } - as := ic.bc.GetAssetState(ashash) - if as == nil { + as, err := ic.dao.GetAssetState(ashash) + if err != nil { return errors.New("asset not found") } v.Estack().PushVal(vm.NewInteropItem(as)) @@ -394,8 +391,8 @@ func (ic *interopContext) accountIsStandard(v *vm.VM) error { if err != nil { return err } - contract := ic.bc.GetContractState(acchash) - res := contract == nil || vm.IsStandardContract(contract.Script) + contract, err := ic.dao.GetContractState(acchash) + res := err != nil || vm.IsStandardContract(contract.Script) v.Estack().PushVal(res) return nil } @@ -413,7 +410,7 @@ func (ic *interopContext) storageFind(v *vm.VM) error { return err } prefix := string(v.Estack().Pop().Bytes()) - siMap, err := ic.bc.GetStorageItems(stc.ScriptHash) + siMap, err := ic.dao.GetStorageItems(stc.ScriptHash) if err != nil { return err } @@ -488,8 +485,8 @@ func (ic *interopContext) contractCreate(v *vm.VM) error { if err != nil { return nil } - contract := ic.bc.GetContractState(newcontract.ScriptHash()) - if contract == nil { + contract, err := ic.dao.GetContractState(newcontract.ScriptHash()) + if err != nil { contract = newcontract err := ic.dao.PutContractState(contract) if err != nil { @@ -528,8 +525,8 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error { if err != nil { return nil } - contract := ic.bc.GetContractState(newcontract.ScriptHash()) - if contract == nil { + contract, err := ic.dao.GetContractState(newcontract.ScriptHash()) + if err != nil { contract = newcontract err := ic.dao.PutContractState(contract) if err != nil { @@ -537,7 +534,7 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error { } if contract.HasStorage() { hash := getContextScriptHash(v, 0) - siMap, err := ic.bc.GetStorageItems(hash) + siMap, err := ic.dao.GetStorageItems(hash) if err != nil { return err } @@ -729,8 +726,8 @@ func (ic *interopContext) assetRenew(v *vm.VM) error { } years := byte(v.Estack().Pop().BigInt().Int64()) // Not sure why C# code regets an asset from the Store, but we also do it. - asset := ic.bc.GetAssetState(as.ID) - if asset == nil { + asset, err := ic.dao.GetAssetState(as.ID) + if err != nil { return errors.New("can't renew non-existent asset") } if asset.Expiration < ic.bc.BlockHeight()+1 { @@ -741,7 +738,7 @@ func (ic *interopContext) assetRenew(v *vm.VM) error { expiration = math.MaxUint32 } asset.Expiration = uint32(expiration) - err := ic.dao.PutAssetState(asset) + err = ic.dao.PutAssetState(asset) if err != nil { return gherr.Wrap(err, "failed to store asset") } diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 319c8bb14..91f919d32 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -68,8 +68,8 @@ func (ic *interopContext) bcGetContract(v *vm.VM) error { if err != nil { return err } - cs := ic.bc.GetContractState(hash) - if cs == nil { + cs, err := ic.dao.GetContractState(hash) + if err != nil { v.Estack().PushVal([]byte{}) } else { v.Estack().PushVal(vm.NewInteropItem(cs)) @@ -100,18 +100,18 @@ func (ic *interopContext) bcGetHeight(v *vm.VM) error { // getTransactionAndHeight gets parameter from the vm evaluation stack and // returns transaction and its height if it's present in the blockchain. -func getTransactionAndHeight(bc Blockchainer, v *vm.VM) (*transaction.Transaction, uint32, error) { +func getTransactionAndHeight(cd *cachedDao, v *vm.VM) (*transaction.Transaction, uint32, error) { hashbytes := v.Estack().Pop().Bytes() hash, err := util.Uint256DecodeBytesLE(hashbytes) if err != nil { return nil, 0, err } - return bc.GetTransaction(hash) + return cd.GetTransaction(hash) } // bcGetTransaction returns transaction. func (ic *interopContext) bcGetTransaction(v *vm.VM) error { - tx, _, err := getTransactionAndHeight(ic.bc, v) + tx, _, err := getTransactionAndHeight(ic.dao, v) if err != nil { return err } @@ -121,7 +121,7 @@ func (ic *interopContext) bcGetTransaction(v *vm.VM) error { // bcGetTransactionHeight returns transaction height. func (ic *interopContext) bcGetTransactionHeight(v *vm.VM) error { - _, h, err := getTransactionAndHeight(ic.bc, v) + _, h, err := getTransactionAndHeight(ic.dao, v) if err != nil { return err } @@ -383,8 +383,8 @@ func (ic *interopContext) runtimeDeserialize(v *vm.VM) error { } */ func (ic *interopContext) checkStorageContext(stc *StorageContext) error { - contract := ic.bc.GetContractState(stc.ScriptHash) - if contract == nil { + contract, err := ic.dao.GetContractState(stc.ScriptHash) + if err != nil { return errors.New("no contract found") } if !contract.HasStorage() { @@ -535,16 +535,16 @@ func (ic *interopContext) contractDestroy(v *vm.VM) error { return errors.New("can't destroy contract when not triggered by application") } hash := getContextScriptHash(v, 0) - cs := ic.bc.GetContractState(hash) - if cs == nil { + cs, err := ic.dao.GetContractState(hash) + if err != nil { return nil } - err := ic.dao.DeleteContractState(hash) + err = ic.dao.DeleteContractState(hash) if err != nil { return err } if cs.HasStorage() { - siMap, err := ic.bc.GetStorageItems(hash) + siMap, err := ic.dao.GetStorageItems(hash) if err != nil { return err }