forked from TrueCloudLab/neoneo-go
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:
parent
0abd55c2c2
commit
212cf44e26
3 changed files with 33 additions and 36 deletions
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue