core: get data from dao in interops

It's more logically correct as Blockchain can be several transactions behind
in terms of its state.
This commit is contained in:
Roman Khimov 2019-12-13 17:10:51 +03:00
parent 0abd55c2c2
commit 212cf44e26
3 changed files with 33 additions and 36 deletions

View file

@ -1336,8 +1336,8 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM { func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM {
vm := vm.New() vm := vm.New()
vm.SetScriptGetter(func(hash util.Uint160) []byte { vm.SetScriptGetter(func(hash util.Uint160) []byte {
cs := bc.GetContractState(hash) cs, err := interopCtx.dao.GetContractState(hash)
if cs == nil { if err != nil {
return nil return nil
} }
return cs.Script return cs.Script

View file

@ -172,8 +172,8 @@ func (ic *interopContext) txGetUnspentCoins(v *vm.VM) error {
if !ok { if !ok {
return errors.New("value is not a transaction") return errors.New("value is not a transaction")
} }
ucs := ic.bc.GetUnspentCoinState(tx.Hash()) ucs, err := ic.dao.GetUnspentCoinState(tx.Hash())
if ucs == nil { if err != nil {
return errors.New("no unspent coin state found") return errors.New("no unspent coin state found")
} }
v.Estack().PushVal(vm.NewInteropItem(ucs)) v.Estack().PushVal(vm.NewInteropItem(ucs))
@ -200,10 +200,7 @@ func (ic *interopContext) txGetWitnesses(v *vm.VM) error {
// bcGetValidators returns validators. // bcGetValidators returns validators.
func (ic *interopContext) bcGetValidators(v *vm.VM) error { func (ic *interopContext) bcGetValidators(v *vm.VM) error {
validators, err := ic.bc.GetValidators() validators := ic.dao.GetValidators()
if err != nil {
return err
}
v.Estack().PushVal(validators) v.Estack().PushVal(validators)
return nil return nil
} }
@ -315,9 +312,9 @@ func (ic *interopContext) bcGetAccount(v *vm.VM) error {
if err != nil { if err != nil {
return err return err
} }
acc := ic.bc.GetAccountState(acchash) acc, err := ic.dao.GetAccountStateOrNew(acchash)
if acc == nil { if err != nil {
acc = state.NewAccount(acchash) return err
} }
v.Estack().PushVal(vm.NewInteropItem(acc)) v.Estack().PushVal(vm.NewInteropItem(acc))
return nil return nil
@ -330,8 +327,8 @@ func (ic *interopContext) bcGetAsset(v *vm.VM) error {
if err != nil { if err != nil {
return err return err
} }
as := ic.bc.GetAssetState(ashash) as, err := ic.dao.GetAssetState(ashash)
if as == nil { if err != nil {
return errors.New("asset not found") return errors.New("asset not found")
} }
v.Estack().PushVal(vm.NewInteropItem(as)) v.Estack().PushVal(vm.NewInteropItem(as))
@ -394,8 +391,8 @@ func (ic *interopContext) accountIsStandard(v *vm.VM) error {
if err != nil { if err != nil {
return err return err
} }
contract := ic.bc.GetContractState(acchash) contract, err := ic.dao.GetContractState(acchash)
res := contract == nil || vm.IsStandardContract(contract.Script) res := err != nil || vm.IsStandardContract(contract.Script)
v.Estack().PushVal(res) v.Estack().PushVal(res)
return nil return nil
} }
@ -413,7 +410,7 @@ func (ic *interopContext) storageFind(v *vm.VM) error {
return err return err
} }
prefix := string(v.Estack().Pop().Bytes()) prefix := string(v.Estack().Pop().Bytes())
siMap, err := ic.bc.GetStorageItems(stc.ScriptHash) siMap, err := ic.dao.GetStorageItems(stc.ScriptHash)
if err != nil { if err != nil {
return err return err
} }
@ -488,8 +485,8 @@ func (ic *interopContext) contractCreate(v *vm.VM) error {
if err != nil { if err != nil {
return nil return nil
} }
contract := ic.bc.GetContractState(newcontract.ScriptHash()) contract, err := ic.dao.GetContractState(newcontract.ScriptHash())
if contract == nil { if err != nil {
contract = newcontract contract = newcontract
err := ic.dao.PutContractState(contract) err := ic.dao.PutContractState(contract)
if err != nil { if err != nil {
@ -528,8 +525,8 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error {
if err != nil { if err != nil {
return nil return nil
} }
contract := ic.bc.GetContractState(newcontract.ScriptHash()) contract, err := ic.dao.GetContractState(newcontract.ScriptHash())
if contract == nil { if err != nil {
contract = newcontract contract = newcontract
err := ic.dao.PutContractState(contract) err := ic.dao.PutContractState(contract)
if err != nil { if err != nil {
@ -537,7 +534,7 @@ func (ic *interopContext) contractMigrate(v *vm.VM) error {
} }
if contract.HasStorage() { if contract.HasStorage() {
hash := getContextScriptHash(v, 0) hash := getContextScriptHash(v, 0)
siMap, err := ic.bc.GetStorageItems(hash) siMap, err := ic.dao.GetStorageItems(hash)
if err != nil { if err != nil {
return err return err
} }
@ -729,8 +726,8 @@ func (ic *interopContext) assetRenew(v *vm.VM) error {
} }
years := byte(v.Estack().Pop().BigInt().Int64()) years := byte(v.Estack().Pop().BigInt().Int64())
// Not sure why C# code regets an asset from the Store, but we also do it. // Not sure why C# code regets an asset from the Store, but we also do it.
asset := ic.bc.GetAssetState(as.ID) asset, err := ic.dao.GetAssetState(as.ID)
if asset == nil { if err != nil {
return errors.New("can't renew non-existent asset") return errors.New("can't renew non-existent asset")
} }
if asset.Expiration < ic.bc.BlockHeight()+1 { if asset.Expiration < ic.bc.BlockHeight()+1 {
@ -741,7 +738,7 @@ func (ic *interopContext) assetRenew(v *vm.VM) error {
expiration = math.MaxUint32 expiration = math.MaxUint32
} }
asset.Expiration = uint32(expiration) asset.Expiration = uint32(expiration)
err := ic.dao.PutAssetState(asset) err = ic.dao.PutAssetState(asset)
if err != nil { if err != nil {
return gherr.Wrap(err, "failed to store asset") return gherr.Wrap(err, "failed to store asset")
} }

View file

@ -68,8 +68,8 @@ func (ic *interopContext) bcGetContract(v *vm.VM) error {
if err != nil { if err != nil {
return err return err
} }
cs := ic.bc.GetContractState(hash) cs, err := ic.dao.GetContractState(hash)
if cs == nil { if err != nil {
v.Estack().PushVal([]byte{}) v.Estack().PushVal([]byte{})
} else { } else {
v.Estack().PushVal(vm.NewInteropItem(cs)) 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 // getTransactionAndHeight gets parameter from the vm evaluation stack and
// returns transaction and its height if it's present in the blockchain. // 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() hashbytes := v.Estack().Pop().Bytes()
hash, err := util.Uint256DecodeBytesLE(hashbytes) hash, err := util.Uint256DecodeBytesLE(hashbytes)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }
return bc.GetTransaction(hash) return cd.GetTransaction(hash)
} }
// bcGetTransaction returns transaction. // bcGetTransaction returns transaction.
func (ic *interopContext) bcGetTransaction(v *vm.VM) error { func (ic *interopContext) bcGetTransaction(v *vm.VM) error {
tx, _, err := getTransactionAndHeight(ic.bc, 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 (ic *interopContext) bcGetTransactionHeight(v *vm.VM) error {
_, h, err := getTransactionAndHeight(ic.bc, v) _, h, err := getTransactionAndHeight(ic.dao, v)
if err != nil { if err != nil {
return err return err
} }
@ -383,8 +383,8 @@ func (ic *interopContext) runtimeDeserialize(v *vm.VM) error {
} }
*/ */
func (ic *interopContext) checkStorageContext(stc *StorageContext) error { func (ic *interopContext) checkStorageContext(stc *StorageContext) error {
contract := ic.bc.GetContractState(stc.ScriptHash) contract, err := ic.dao.GetContractState(stc.ScriptHash)
if contract == nil { if err != nil {
return errors.New("no contract found") return errors.New("no contract found")
} }
if !contract.HasStorage() { 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") return errors.New("can't destroy contract when not triggered by application")
} }
hash := getContextScriptHash(v, 0) hash := getContextScriptHash(v, 0)
cs := ic.bc.GetContractState(hash) cs, err := ic.dao.GetContractState(hash)
if cs == nil { if err != nil {
return nil return nil
} }
err := ic.dao.DeleteContractState(hash) err = ic.dao.DeleteContractState(hash)
if err != nil { if err != nil {
return err return err
} }
if cs.HasStorage() { if cs.HasStorage() {
siMap, err := ic.bc.GetStorageItems(hash) siMap, err := ic.dao.GetStorageItems(hash)
if err != nil { if err != nil {
return err return err
} }