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 {
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

View file

@ -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")
}

View file

@ -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
}