From 5f09381cf4d4798846e4a9ae51e666b8e25cc65a Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 3 Apr 2020 09:49:01 +0300 Subject: [PATCH] core: wrap cached dao properly, don't miss cached data Fixes #817 where invoked contract missed updated account information because it got it one layer below cachedDao used to process the block. --- pkg/core/blockchain.go | 27 +++--- pkg/core/blockchainer.go | 3 +- pkg/core/cacheddao.go | 35 +++++++- pkg/core/cacheddao_test.go | 56 +++++++++++- pkg/core/dao.go | 170 ++++++++++++++++++++++++----------- pkg/core/dao_test.go | 44 ++++----- pkg/core/gas_price_test.go | 3 +- pkg/core/interop_neo_test.go | 14 +-- pkg/core/interops.go | 5 +- pkg/core/interops_test.go | 2 +- pkg/network/helper_test.go | 3 +- pkg/rpc/server/server.go | 2 +- 12 files changed, 251 insertions(+), 113 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index ea84cf0eb..1aae66f44 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -80,7 +80,7 @@ type Blockchain struct { lock sync.RWMutex // Data access object for CRUD operations around storage. - dao *dao + dao *simpleDao // Current index/height of the highest block. // Read access should always be called by BlockHeight(). @@ -154,7 +154,7 @@ func NewBlockchain(s storage.Store, cfg config.ProtocolConfiguration, log *zap.L } bc := &Blockchain{ config: cfg, - dao: newDao(s), + dao: newSimpleDao(s), headersOp: make(chan headersOpFunc), headersOpDone: make(chan struct{}), stopCh: make(chan struct{}), @@ -457,7 +457,7 @@ func (bc *Blockchain) getSystemFeeAmount(h util.Uint256) uint32 { // is happening here, quite allot as you can see :). If things are wired together // and all tests are in place, we can make a more optimized and cleaner implementation. func (bc *Blockchain) storeBlock(block *block.Block) error { - cache := newCachedDao(bc.dao.store) + cache := newCachedDao(bc.dao) fee := bc.getSystemFeeAmount(block.PrevHash) for _, tx := range block.Transactions { fee += uint32(bc.SystemFee(tx).IntegralValue()) @@ -655,7 +655,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { return err } case *transaction.InvocationTX: - systemInterop := bc.newInteropContext(trigger.Application, cache.store, block, tx) + systemInterop := bc.newInteropContext(trigger.Application, cache, block, tx) v := bc.spawnVMWithInterops(systemInterop) v.SetCheckedHash(tx.VerificationHash().BytesBE()) v.LoadScript(t.Script) @@ -721,7 +721,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error { defer bc.lock.Unlock() if bc.config.SaveStorageBatch { - bc.lastBatch = cache.dao.store.GetBatch() + bc.lastBatch = cache.dao.GetBatch() } _, err := cache.Persist() @@ -1725,7 +1725,7 @@ func (bc *Blockchain) GetStandByValidators() (keys.PublicKeys, error) { // GetValidators returns validators. // Golang implementation of GetValidators method in C# (https://github.com/neo-project/neo/blob/c64748ecbac3baeb8045b16af0d518398a6ced24/neo/Persistence/Snapshot.cs#L182) func (bc *Blockchain) GetValidators(txes ...*transaction.Transaction) ([]*keys.PublicKey, error) { - cache := newCachedDao(bc.dao.store) + cache := newCachedDao(bc.dao) if len(txes) > 0 { for _, tx := range txes { // iterate through outputs @@ -2016,12 +2016,11 @@ func (bc *Blockchain) spawnVMWithInterops(interopCtx *interopContext) *vm.VM { } // GetTestVM returns a VM and a Store setup for a test run of some sort of code. -func (bc *Blockchain) GetTestVM() (*vm.VM, storage.Store) { - tmpStore := storage.NewMemCachedStore(bc.dao.store) - systemInterop := bc.newInteropContext(trigger.Application, tmpStore, nil, nil) +func (bc *Blockchain) GetTestVM() *vm.VM { + systemInterop := bc.newInteropContext(trigger.Application, bc.dao, nil, nil) vm := bc.spawnVMWithInterops(systemInterop) vm.SetPriceGetter(getPrice) - return vm, tmpStore + return vm } // ScriptFromWitness returns verification script for provided witness. @@ -2106,7 +2105,7 @@ func (bc *Blockchain) verifyTxWitnesses(t *transaction.Transaction, block *block } sort.Slice(hashes, func(i, j int) bool { return hashes[i].Less(hashes[j]) }) sort.Slice(witnesses, func(i, j int) bool { return witnesses[i].ScriptHash().Less(witnesses[j].ScriptHash()) }) - interopCtx := bc.newInteropContext(trigger.Verification, bc.dao.store, block, t) + interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, block, t) for i := 0; i < len(hashes); i++ { err := bc.verifyHashAgainstScript(hashes[i], &witnesses[i], t.VerificationHash(), interopCtx, false) if err != nil { @@ -2126,7 +2125,7 @@ func (bc *Blockchain) verifyHeaderWitnesses(currHeader, prevHeader *block.Header } else { hash = prevHeader.NextConsensus } - interopCtx := bc.newInteropContext(trigger.Verification, bc.dao.store, nil, nil) + interopCtx := bc.newInteropContext(trigger.Verification, bc.dao, nil, nil) return bc.verifyHashAgainstScript(hash, &currHeader.Script, currHeader.VerificationHash(), interopCtx, true) } @@ -2141,6 +2140,6 @@ func (bc *Blockchain) secondsPerBlock() int { return bc.config.SecondsPerBlock } -func (bc *Blockchain) newInteropContext(trigger trigger.Type, s storage.Store, block *block.Block, tx *transaction.Transaction) *interopContext { - return newInteropContext(trigger, bc, s, block, tx, bc.log) +func (bc *Blockchain) newInteropContext(trigger trigger.Type, d dao, block *block.Block, tx *transaction.Transaction) *interopContext { + return newInteropContext(trigger, bc, d, block, tx, bc.log) } diff --git a/pkg/core/blockchainer.go b/pkg/core/blockchainer.go index d6f6040ce..a633bb523 100644 --- a/pkg/core/blockchainer.go +++ b/pkg/core/blockchainer.go @@ -5,7 +5,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/mempool" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/util" @@ -41,7 +40,7 @@ type Blockchainer interface { GetScriptHashesForVerifying(*transaction.Transaction) ([]util.Uint160, error) GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) - GetTestVM() (*vm.VM, storage.Store) + GetTestVM() *vm.VM GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) GetUnspentCoinState(util.Uint256) *state.UnspentCoin References(t *transaction.Transaction) ([]transaction.InOut, error) diff --git a/pkg/core/cacheddao.go b/pkg/core/cacheddao.go index 121de9435..e3ae20db6 100644 --- a/pkg/core/cacheddao.go +++ b/pkg/core/cacheddao.go @@ -1,8 +1,9 @@ package core import ( + "errors" + "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/util" ) @@ -20,13 +21,13 @@ type cachedDao struct { } // newCachedDao returns new cachedDao wrapping around given backing store. -func newCachedDao(backend storage.Store) *cachedDao { +func newCachedDao(d dao) *cachedDao { accs := make(map[util.Uint160]*state.Account) ctrs := make(map[util.Uint160]*state.Contract) unspents := make(map[util.Uint256]*state.UnspentCoin) balances := make(map[util.Uint160]*state.NEP5Balances) transfers := make(map[util.Uint160]map[uint32]*state.NEP5TransferLog) - return &cachedDao{*newDao(backend), accs, ctrs, unspents, balances, transfers} + return &cachedDao{d.GetWrapped(), accs, ctrs, unspents, balances, transfers} } // GetAccountStateOrNew retrieves Account from cache or underlying Store @@ -139,6 +140,24 @@ func (cd *cachedDao) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *stat // Persist flushes all the changes made into the (supposedly) persistent // underlying store. func (cd *cachedDao) Persist() (int, error) { + lowerCache, ok := cd.dao.(*cachedDao) + // If the lower dao is cachedDao, we only need to flush the MemCached DB. + // This actually breaks dao interface incapsulation, but for our current + // usage scenario it should be good enough if cd doesn't modify object + // caches (accounts/contracts/etc) in any way. + if ok { + var simpleCache *simpleDao + for simpleCache == nil { + simpleCache, ok = lowerCache.dao.(*simpleDao) + if !ok { + lowerCache, ok = cd.dao.(*cachedDao) + if !ok { + return 0, errors.New("unsupported lower dao") + } + } + } + return simpleCache.Persist() + } buf := io.NewBufBinWriter() for sc := range cd.accounts { @@ -172,3 +191,13 @@ func (cd *cachedDao) Persist() (int, error) { } return cd.dao.Persist() } + +func (cd *cachedDao) GetWrapped() dao { + return &cachedDao{cd.dao.GetWrapped(), + cd.accounts, + cd.contracts, + cd.unspents, + cd.balances, + cd.transfers, + } +} diff --git a/pkg/core/cacheddao_test.go b/pkg/core/cacheddao_test.go index eab33348c..5c4678523 100644 --- a/pkg/core/cacheddao_test.go +++ b/pkg/core/cacheddao_test.go @@ -8,15 +8,16 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/internal/random" "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestCachedDaoAccounts(t *testing.T) { store := storage.NewMemoryStore() // Persistent DAO to check for backing storage. - pdao := newDao(store) + pdao := newSimpleDao(store) // Cached DAO. - cdao := newCachedDao(store) + cdao := newCachedDao(pdao) hash := random.Uint160() _, err := cdao.GetAccountState(hash) @@ -50,7 +51,8 @@ func TestCachedDaoAccounts(t *testing.T) { func TestCachedDaoContracts(t *testing.T) { store := storage.NewMemoryStore() - dao := newCachedDao(store) + pdao := newSimpleDao(store) + dao := newCachedDao(pdao) script := []byte{0xde, 0xad, 0xbe, 0xef} sh := hash.Hash160(script) @@ -69,7 +71,7 @@ func TestCachedDaoContracts(t *testing.T) { _, err = dao.Persist() require.Nil(t, err) - dao2 := newCachedDao(store) + dao2 := newCachedDao(pdao) cs2, err = dao2.GetContractState(sh) require.Nil(t, err) require.Equal(t, cs, cs2) @@ -81,3 +83,49 @@ func TestCachedDaoContracts(t *testing.T) { _, err = dao.GetContractState(sh) require.NotNil(t, err) } + +func TestCachedCachedDao(t *testing.T) { + store := storage.NewMemoryStore() + // Persistent DAO to check for backing storage. + pdao := newSimpleDao(store) + assert.NotEqual(t, store, pdao.store) + // Cached DAO. + cdao := newCachedDao(pdao) + cdaoDao := cdao.dao.(*simpleDao) + assert.NotEqual(t, store, cdaoDao.store) + assert.NotEqual(t, pdao.store, cdaoDao.store) + + // Cached cached DAO. + ccdao := newCachedDao(cdao) + ccdaoDao := ccdao.dao.(*cachedDao) + intDao := ccdaoDao.dao.(*simpleDao) + assert.NotEqual(t, store, intDao.store) + assert.NotEqual(t, pdao.store, intDao.store) + assert.NotEqual(t, cdaoDao.store, intDao.store) + + hash := random.Uint160() + key := []byte("qwerty") + si := &state.StorageItem{Value: []byte("poiuyt")} + require.NoError(t, ccdao.PutStorageItem(hash, key, si)) + resi := ccdao.GetStorageItem(hash, key) + assert.Equal(t, si, resi) + + resi = cdao.GetStorageItem(hash, key) + assert.Equal(t, (*state.StorageItem)(nil), resi) + resi = pdao.GetStorageItem(hash, key) + assert.Equal(t, (*state.StorageItem)(nil), resi) + + cnt, err := ccdao.Persist() + assert.NoError(t, err) + assert.Equal(t, 1, cnt) + resi = cdao.GetStorageItem(hash, key) + assert.Equal(t, si, resi) + resi = pdao.GetStorageItem(hash, key) + assert.Equal(t, (*state.StorageItem)(nil), resi) + + cnt, err = cdao.Persist() + assert.NoError(t, err) + assert.Equal(t, 1, cnt) + resi = pdao.GetStorageItem(hash, key) + assert.Equal(t, si, resi) +} diff --git a/pkg/core/dao.go b/pkg/core/dao.go index d574c049f..9eb686381 100644 --- a/pkg/core/dao.go +++ b/pkg/core/dao.go @@ -16,16 +16,80 @@ import ( ) // dao is a data access object. -type dao struct { +type dao interface { + AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.NEP5Transfer) (bool, error) + DeleteContractState(hash util.Uint160) error + DeleteStorageItem(scripthash util.Uint160, key []byte) error + DeleteValidatorState(vs *state.Validator) error + GetAccountState(hash util.Uint160) (*state.Account, error) + GetAccountStateOrNew(hash util.Uint160) (*state.Account, error) + GetAndDecode(entity io.Serializable, key []byte) error + GetAppExecResult(hash util.Uint256) (*state.AppExecResult, error) + GetAssetState(assetID util.Uint256) (*state.Asset, error) + GetBatch() *storage.MemBatch + GetBlock(hash util.Uint256) (*block.Block, uint32, error) + GetContractState(hash util.Uint160) (*state.Contract, error) + GetCurrentBlockHeight() (uint32, error) + GetCurrentHeaderHeight() (i uint32, h util.Uint256, err error) + GetHeaderHashes() ([]util.Uint256, error) + GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) + GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error) + GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem + GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) + GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error) + GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) + GetValidatorState(publicKey *keys.PublicKey) (*state.Validator, error) + GetValidatorStateOrNew(publicKey *keys.PublicKey) (*state.Validator, error) + GetValidators() []*state.Validator + GetValidatorsCount() (*state.ValidatorsCount, error) + GetVersion() (string, error) + GetWrapped() dao + HasTransaction(hash util.Uint256) bool + IsDoubleClaim(claim *transaction.ClaimTX) bool + IsDoubleSpend(tx *transaction.Transaction) bool + Persist() (int, error) + PutAccountState(as *state.Account) error + PutAppExecResult(aer *state.AppExecResult) error + PutAssetState(as *state.Asset) error + PutContractState(cs *state.Contract) error + PutCurrentHeader(hashAndIndex []byte) error + PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error + PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error + PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error + PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error + PutValidatorState(vs *state.Validator) error + PutValidatorsCount(vc *state.ValidatorsCount) error + PutVersion(v string) error + StoreAsBlock(block *block.Block, sysFee uint32) error + StoreAsCurrentBlock(block *block.Block) error + StoreAsTransaction(tx *transaction.Transaction, index uint32) error + putAccountState(as *state.Account, buf *io.BufBinWriter) error + putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf *io.BufBinWriter) error + putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin, buf *io.BufBinWriter) error +} + +// simpleDao is memCached wrapper around DB, simple dao implementation. +type simpleDao struct { store *storage.MemCachedStore } -func newDao(backend storage.Store) *dao { - return &dao{store: storage.NewMemCachedStore(backend)} +func newSimpleDao(backend storage.Store) *simpleDao { + return &simpleDao{store: storage.NewMemCachedStore(backend)} +} + +// GetBatch returns currently accumulated DB changeset. +func (dao *simpleDao) GetBatch() *storage.MemBatch { + return dao.store.GetBatch() +} + +// GetWrapped returns new dao instance with another layer of wrapped +// MemCachedStore around the current dao store. +func (dao *simpleDao) GetWrapped() dao { + return newSimpleDao(dao.store) } // GetAndDecode performs get operation and decoding with serializable structures. -func (dao *dao) GetAndDecode(entity io.Serializable, key []byte) error { +func (dao *simpleDao) GetAndDecode(entity io.Serializable, key []byte) error { entityBytes, err := dao.store.Get(key) if err != nil { return err @@ -36,12 +100,12 @@ func (dao *dao) GetAndDecode(entity io.Serializable, key []byte) error { } // Put performs put operation with serializable structures. -func (dao *dao) Put(entity io.Serializable, key []byte) error { +func (dao *simpleDao) Put(entity io.Serializable, key []byte) error { return dao.putWithBuffer(entity, key, io.NewBufBinWriter()) } // putWithBuffer performs put operation using buf as a pre-allocated buffer for serialization. -func (dao *dao) putWithBuffer(entity io.Serializable, key []byte, buf *io.BufBinWriter) error { +func (dao *simpleDao) putWithBuffer(entity io.Serializable, key []byte, buf *io.BufBinWriter) error { entity.EncodeBinary(buf.BinWriter) if buf.Err != nil { return buf.Err @@ -53,7 +117,7 @@ func (dao *dao) putWithBuffer(entity io.Serializable, key []byte, buf *io.BufBin // GetAccountStateOrNew retrieves Account from temporary or persistent Store // or creates a new one if it doesn't exist and persists it. -func (dao *dao) GetAccountStateOrNew(hash util.Uint160) (*state.Account, error) { +func (dao *simpleDao) GetAccountStateOrNew(hash util.Uint160) (*state.Account, error) { account, err := dao.GetAccountState(hash) if err != nil { if err != storage.ErrKeyNotFound { @@ -66,7 +130,7 @@ func (dao *dao) GetAccountStateOrNew(hash util.Uint160) (*state.Account, error) // GetAccountState returns Account from the given Store if it's // present there. Returns nil otherwise. -func (dao *dao) GetAccountState(hash util.Uint160) (*state.Account, error) { +func (dao *simpleDao) GetAccountState(hash util.Uint160) (*state.Account, error) { account := &state.Account{} key := storage.AppendPrefix(storage.STAccount, hash.BytesBE()) err := dao.GetAndDecode(account, key) @@ -76,11 +140,11 @@ func (dao *dao) GetAccountState(hash util.Uint160) (*state.Account, error) { return account, err } -func (dao *dao) PutAccountState(as *state.Account) error { +func (dao *simpleDao) PutAccountState(as *state.Account) error { return dao.putAccountState(as, io.NewBufBinWriter()) } -func (dao *dao) putAccountState(as *state.Account, buf *io.BufBinWriter) error { +func (dao *simpleDao) putAccountState(as *state.Account, buf *io.BufBinWriter) error { key := storage.AppendPrefix(storage.STAccount, as.ScriptHash.BytesBE()) return dao.putWithBuffer(as, key, buf) } @@ -90,7 +154,7 @@ func (dao *dao) putAccountState(as *state.Account, buf *io.BufBinWriter) error { // -- start assets. // GetAssetState returns given asset state as recorded in the given store. -func (dao *dao) GetAssetState(assetID util.Uint256) (*state.Asset, error) { +func (dao *simpleDao) GetAssetState(assetID util.Uint256) (*state.Asset, error) { asset := &state.Asset{} key := storage.AppendPrefix(storage.STAsset, assetID.BytesBE()) err := dao.GetAndDecode(asset, key) @@ -104,7 +168,7 @@ func (dao *dao) GetAssetState(assetID util.Uint256) (*state.Asset, error) { } // PutAssetState puts given asset state into the given store. -func (dao *dao) PutAssetState(as *state.Asset) error { +func (dao *simpleDao) PutAssetState(as *state.Asset) error { key := storage.AppendPrefix(storage.STAsset, as.ID.BytesBE()) return dao.Put(as, key) } @@ -115,7 +179,7 @@ func (dao *dao) PutAssetState(as *state.Asset) error { // GetContractState returns contract state as recorded in the given // store by the given script hash. -func (dao *dao) GetContractState(hash util.Uint160) (*state.Contract, error) { +func (dao *simpleDao) GetContractState(hash util.Uint160) (*state.Contract, error) { contract := &state.Contract{} key := storage.AppendPrefix(storage.STContract, hash.BytesBE()) err := dao.GetAndDecode(contract, key) @@ -130,13 +194,13 @@ func (dao *dao) GetContractState(hash util.Uint160) (*state.Contract, error) { } // PutContractState puts given contract state into the given store. -func (dao *dao) PutContractState(cs *state.Contract) error { +func (dao *simpleDao) PutContractState(cs *state.Contract) error { key := storage.AppendPrefix(storage.STContract, cs.ScriptHash().BytesBE()) return dao.Put(cs, key) } // DeleteContractState deletes given contract state in the given store. -func (dao *dao) DeleteContractState(hash util.Uint160) error { +func (dao *simpleDao) DeleteContractState(hash util.Uint160) error { key := storage.AppendPrefix(storage.STContract, hash.BytesBE()) return dao.store.Delete(key) } @@ -146,7 +210,7 @@ func (dao *dao) DeleteContractState(hash util.Uint160) error { // -- start nep5 balances. // GetNEP5Balances retrieves nep5 balances from the cache. -func (dao *dao) GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) { +func (dao *simpleDao) GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) { key := storage.AppendPrefix(storage.STNEP5Balances, acc.BytesBE()) bs := state.NewNEP5Balances() err := dao.GetAndDecode(bs, key) @@ -157,11 +221,11 @@ func (dao *dao) GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error) { } // PutNEP5Balances saves nep5 balances from the cache. -func (dao *dao) PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error { +func (dao *simpleDao) PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error { return dao.putNEP5Balances(acc, bs, io.NewBufBinWriter()) } -func (dao *dao) putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf *io.BufBinWriter) error { +func (dao *simpleDao) putNEP5Balances(acc util.Uint160, bs *state.NEP5Balances, buf *io.BufBinWriter) error { key := storage.AppendPrefix(storage.STNEP5Balances, acc.BytesBE()) return dao.putWithBuffer(bs, key, buf) } @@ -181,7 +245,7 @@ func getNEP5TransferLogKey(acc util.Uint160, index uint32) []byte { } // GetNEP5TransferLog retrieves transfer log from the cache. -func (dao *dao) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error) { +func (dao *simpleDao) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error) { key := getNEP5TransferLogKey(acc, index) value, err := dao.store.Get(key) if err != nil { @@ -194,14 +258,14 @@ func (dao *dao) GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5T } // PutNEP5TransferLog saves given transfer log in the cache. -func (dao *dao) PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error { +func (dao *simpleDao) PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error { key := getNEP5TransferLogKey(acc, index) return dao.store.Put(key, lg.Raw) } // AppendNEP5Transfer appends a single NEP5 transfer to a log. // First return value signalizes that log size has exceeded batch size. -func (dao *dao) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.NEP5Transfer) (bool, error) { +func (dao *simpleDao) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.NEP5Transfer) (bool, error) { lg, err := dao.GetNEP5TransferLog(acc, index) if err != nil { if err != storage.ErrKeyNotFound { @@ -220,7 +284,7 @@ func (dao *dao) AppendNEP5Transfer(acc util.Uint160, index uint32, tr *state.NEP // -- start unspent coins. // GetUnspentCoinState retrieves UnspentCoinState from the given store. -func (dao *dao) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) { +func (dao *simpleDao) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, error) { unspent := &state.UnspentCoin{} key := storage.AppendPrefix(storage.STCoin, hash.BytesLE()) err := dao.GetAndDecode(unspent, key) @@ -231,11 +295,11 @@ func (dao *dao) GetUnspentCoinState(hash util.Uint256) (*state.UnspentCoin, erro } // PutUnspentCoinState puts given UnspentCoinState into the given store. -func (dao *dao) PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error { +func (dao *simpleDao) PutUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin) error { return dao.putUnspentCoinState(hash, ucs, io.NewBufBinWriter()) } -func (dao *dao) putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin, buf *io.BufBinWriter) error { +func (dao *simpleDao) putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin, buf *io.BufBinWriter) error { key := storage.AppendPrefix(storage.STCoin, hash.BytesLE()) return dao.putWithBuffer(ucs, key, buf) } @@ -245,7 +309,7 @@ func (dao *dao) putUnspentCoinState(hash util.Uint256, ucs *state.UnspentCoin, b // -- start validator. // GetValidatorStateOrNew gets validator from store or created new one in case of error. -func (dao *dao) GetValidatorStateOrNew(publicKey *keys.PublicKey) (*state.Validator, error) { +func (dao *simpleDao) GetValidatorStateOrNew(publicKey *keys.PublicKey) (*state.Validator, error) { validatorState, err := dao.GetValidatorState(publicKey) if err != nil { if err != storage.ErrKeyNotFound { @@ -258,7 +322,7 @@ func (dao *dao) GetValidatorStateOrNew(publicKey *keys.PublicKey) (*state.Valida } // GetValidators returns all validators from store. -func (dao *dao) GetValidators() []*state.Validator { +func (dao *simpleDao) GetValidators() []*state.Validator { var validators []*state.Validator dao.store.Seek(storage.STValidator.Bytes(), func(k, v []byte) { r := io.NewBinReaderFromBuf(v) @@ -273,7 +337,7 @@ func (dao *dao) GetValidators() []*state.Validator { } // GetValidatorState returns validator by publicKey. -func (dao *dao) GetValidatorState(publicKey *keys.PublicKey) (*state.Validator, error) { +func (dao *simpleDao) GetValidatorState(publicKey *keys.PublicKey) (*state.Validator, error) { validatorState := &state.Validator{} key := storage.AppendPrefix(storage.STValidator, publicKey.Bytes()) err := dao.GetAndDecode(validatorState, key) @@ -284,20 +348,20 @@ func (dao *dao) GetValidatorState(publicKey *keys.PublicKey) (*state.Validator, } // PutValidatorState puts given Validator into the given store. -func (dao *dao) PutValidatorState(vs *state.Validator) error { +func (dao *simpleDao) PutValidatorState(vs *state.Validator) error { key := storage.AppendPrefix(storage.STValidator, vs.PublicKey.Bytes()) return dao.Put(vs, key) } // DeleteValidatorState deletes given Validator into the given store. -func (dao *dao) DeleteValidatorState(vs *state.Validator) error { +func (dao *simpleDao) DeleteValidatorState(vs *state.Validator) error { key := storage.AppendPrefix(storage.STValidator, vs.PublicKey.Bytes()) return dao.store.Delete(key) } // GetValidatorsCount returns current ValidatorsCount or new one if there is none // in the DB. -func (dao *dao) GetValidatorsCount() (*state.ValidatorsCount, error) { +func (dao *simpleDao) GetValidatorsCount() (*state.ValidatorsCount, error) { vc := &state.ValidatorsCount{} key := []byte{byte(storage.IXValidatorsCount)} err := dao.GetAndDecode(vc, key) @@ -308,7 +372,7 @@ func (dao *dao) GetValidatorsCount() (*state.ValidatorsCount, error) { } // PutValidatorsCount put given ValidatorsCount in the store. -func (dao *dao) PutValidatorsCount(vc *state.ValidatorsCount) error { +func (dao *simpleDao) PutValidatorsCount(vc *state.ValidatorsCount) error { key := []byte{byte(storage.IXValidatorsCount)} return dao.Put(vc, key) } @@ -319,7 +383,7 @@ func (dao *dao) PutValidatorsCount(vc *state.ValidatorsCount) error { // GetAppExecResult gets application execution result from the // given store. -func (dao *dao) GetAppExecResult(hash util.Uint256) (*state.AppExecResult, error) { +func (dao *simpleDao) GetAppExecResult(hash util.Uint256) (*state.AppExecResult, error) { aer := &state.AppExecResult{} key := storage.AppendPrefix(storage.STNotification, hash.BytesBE()) err := dao.GetAndDecode(aer, key) @@ -331,7 +395,7 @@ func (dao *dao) GetAppExecResult(hash util.Uint256) (*state.AppExecResult, error // PutAppExecResult puts given application execution result into the // given store. -func (dao *dao) PutAppExecResult(aer *state.AppExecResult) error { +func (dao *simpleDao) PutAppExecResult(aer *state.AppExecResult) error { key := storage.AppendPrefix(storage.STNotification, aer.TxHash.BytesBE()) return dao.Put(aer, key) } @@ -341,7 +405,7 @@ func (dao *dao) PutAppExecResult(aer *state.AppExecResult) error { // -- start storage item. // GetStorageItem returns StorageItem if it exists in the given Store. -func (dao *dao) GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem { +func (dao *simpleDao) GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem { b, err := dao.store.Get(makeStorageItemKey(scripthash, key)) if err != nil { return nil @@ -359,18 +423,18 @@ func (dao *dao) GetStorageItem(scripthash util.Uint160, key []byte) *state.Stora // PutStorageItem puts given StorageItem for given script with given // key into the given Store. -func (dao *dao) PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error { +func (dao *simpleDao) PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error { return dao.Put(si, makeStorageItemKey(scripthash, key)) } // DeleteStorageItem drops storage item for the given script with the // given key from the Store. -func (dao *dao) DeleteStorageItem(scripthash util.Uint160, key []byte) error { +func (dao *simpleDao) DeleteStorageItem(scripthash util.Uint160, key []byte) error { return dao.store.Delete(makeStorageItemKey(scripthash, key)) } // GetStorageItems returns all storage items for a given scripthash. -func (dao *dao) GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) { +func (dao *simpleDao) GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) { var siMap = make(map[string]*state.StorageItem) var err error @@ -406,7 +470,7 @@ func makeStorageItemKey(scripthash util.Uint160, key []byte) []byte { // -- other. // GetBlock returns Block by the given hash if it exists in the store. -func (dao *dao) GetBlock(hash util.Uint256) (*block.Block, uint32, error) { +func (dao *simpleDao) GetBlock(hash util.Uint256) (*block.Block, uint32, error) { key := storage.AppendPrefix(storage.DataBlock, hash.BytesLE()) b, err := dao.store.Get(key) if err != nil { @@ -422,14 +486,14 @@ func (dao *dao) GetBlock(hash util.Uint256) (*block.Block, uint32, error) { // GetVersion attempts to get the current version stored in the // underlying Store. -func (dao *dao) GetVersion() (string, error) { +func (dao *simpleDao) GetVersion() (string, error) { version, err := dao.store.Get(storage.SYSVersion.Bytes()) return string(version), err } // GetCurrentBlockHeight returns the current block height found in the // underlying Store. -func (dao *dao) GetCurrentBlockHeight() (uint32, error) { +func (dao *simpleDao) GetCurrentBlockHeight() (uint32, error) { b, err := dao.store.Get(storage.SYSCurrentBlock.Bytes()) if err != nil { return 0, err @@ -439,7 +503,7 @@ func (dao *dao) GetCurrentBlockHeight() (uint32, error) { // GetCurrentHeaderHeight returns the current header height and hash from // the underlying Store. -func (dao *dao) GetCurrentHeaderHeight() (i uint32, h util.Uint256, err error) { +func (dao *simpleDao) GetCurrentHeaderHeight() (i uint32, h util.Uint256, err error) { var b []byte b, err = dao.store.Get(storage.SYSCurrentHeader.Bytes()) if err != nil { @@ -452,7 +516,7 @@ func (dao *dao) GetCurrentHeaderHeight() (i uint32, h util.Uint256, err error) { // GetHeaderHashes returns a sorted list of header hashes retrieved from // the given underlying Store. -func (dao *dao) GetHeaderHashes() ([]util.Uint256, error) { +func (dao *simpleDao) GetHeaderHashes() ([]util.Uint256, error) { hashMap := make(map[uint32][]util.Uint256) dao.store.Seek(storage.IXHeaderHashList.Bytes(), func(k, v []byte) { storedCount := binary.LittleEndian.Uint32(k[1:]) @@ -482,7 +546,7 @@ func (dao *dao) GetHeaderHashes() ([]util.Uint256, error) { // GetTransaction returns Transaction and its height by the given hash // if it exists in the store. -func (dao *dao) GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error) { +func (dao *simpleDao) GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error) { key := storage.AppendPrefix(storage.DataTransaction, hash.BytesLE()) b, err := dao.store.Get(key) if err != nil { @@ -502,12 +566,12 @@ func (dao *dao) GetTransaction(hash util.Uint256) (*transaction.Transaction, uin } // PutVersion stores the given version in the underlying Store. -func (dao *dao) PutVersion(v string) error { +func (dao *simpleDao) PutVersion(v string) error { return dao.store.Put(storage.SYSVersion.Bytes(), []byte(v)) } // PutCurrentHeader stores current header. -func (dao *dao) PutCurrentHeader(hashAndIndex []byte) error { +func (dao *simpleDao) PutCurrentHeader(hashAndIndex []byte) error { return dao.store.Put(storage.SYSCurrentHeader.Bytes(), hashAndIndex) } @@ -526,7 +590,7 @@ func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) { // HasTransaction returns true if the given store contains the given // Transaction hash. -func (dao *dao) HasTransaction(hash util.Uint256) bool { +func (dao *simpleDao) HasTransaction(hash util.Uint256) bool { key := storage.AppendPrefix(storage.DataTransaction, hash.BytesLE()) if _, err := dao.store.Get(key); err == nil { return true @@ -535,7 +599,7 @@ func (dao *dao) HasTransaction(hash util.Uint256) bool { } // StoreAsBlock stores the given block as DataBlock. -func (dao *dao) StoreAsBlock(block *block.Block, sysFee uint32) error { +func (dao *simpleDao) StoreAsBlock(block *block.Block, sysFee uint32) error { var ( key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesLE()) buf = io.NewBufBinWriter() @@ -553,7 +617,7 @@ func (dao *dao) StoreAsBlock(block *block.Block, sysFee uint32) error { } // StoreAsCurrentBlock stores the given block witch prefix SYSCurrentBlock. -func (dao *dao) StoreAsCurrentBlock(block *block.Block) error { +func (dao *simpleDao) StoreAsCurrentBlock(block *block.Block) error { buf := io.NewBufBinWriter() h := block.Hash() h.EncodeBinary(buf.BinWriter) @@ -562,7 +626,7 @@ func (dao *dao) StoreAsCurrentBlock(block *block.Block) error { } // StoreAsTransaction stores the given TX as DataTransaction. -func (dao *dao) StoreAsTransaction(tx *transaction.Transaction, index uint32) error { +func (dao *simpleDao) StoreAsTransaction(tx *transaction.Transaction, index uint32) error { key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesLE()) buf := io.NewBufBinWriter() buf.WriteU32LE(index) @@ -574,16 +638,16 @@ func (dao *dao) StoreAsTransaction(tx *transaction.Transaction, index uint32) er } // IsDoubleSpend verifies that the input transactions are not double spent. -func (dao *dao) IsDoubleSpend(tx *transaction.Transaction) bool { +func (dao *simpleDao) IsDoubleSpend(tx *transaction.Transaction) bool { return dao.checkUsedInputs(tx.Inputs, state.CoinSpent) } // IsDoubleClaim verifies that given claim inputs are not already claimed by another tx. -func (dao *dao) IsDoubleClaim(claim *transaction.ClaimTX) bool { +func (dao *simpleDao) IsDoubleClaim(claim *transaction.ClaimTX) bool { return dao.checkUsedInputs(claim.Claims, state.CoinClaimed) } -func (dao *dao) checkUsedInputs(inputs []transaction.Input, coin state.Coin) bool { +func (dao *simpleDao) checkUsedInputs(inputs []transaction.Input, coin state.Coin) bool { if len(inputs) == 0 { return false } @@ -604,6 +668,6 @@ func (dao *dao) checkUsedInputs(inputs []transaction.Input, coin state.Coin) boo // Persist flushes all the changes made into the (supposedly) persistent // underlying store. -func (dao *dao) Persist() (int, error) { +func (dao *simpleDao) Persist() (int, error) { return dao.store.Persist() } diff --git a/pkg/core/dao_test.go b/pkg/core/dao_test.go index b49296658..0162a0737 100644 --- a/pkg/core/dao_test.go +++ b/pkg/core/dao_test.go @@ -16,7 +16,7 @@ import ( ) func TestPutGetAndDecode(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) serializable := &TestSerializable{field: random.String(4)} hash := []byte{1} err := dao.Put(serializable, hash) @@ -41,7 +41,7 @@ func (t *TestSerializable) DecodeBinary(reader *io.BinReader) { } func TestGetAccountStateOrNew_New(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint160() createdAccount, err := dao.GetAccountStateOrNew(hash) require.NoError(t, err) @@ -49,7 +49,7 @@ func TestGetAccountStateOrNew_New(t *testing.T) { } func TestPutAndGetAccountStateOrNew(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint160() accountState := &state.Account{ScriptHash: hash} err := dao.PutAccountState(accountState) @@ -60,7 +60,7 @@ func TestPutAndGetAccountStateOrNew(t *testing.T) { } func TestPutAndGetAssetState(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) id := random.Uint256() assetState := &state.Asset{ID: id, Owner: keys.PublicKey{}} err := dao.PutAssetState(assetState) @@ -71,7 +71,7 @@ func TestPutAndGetAssetState(t *testing.T) { } func TestPutAndGetContractState(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) contractState := &state.Contract{Script: []byte{}, ParamList: []smartcontract.ParamType{}} hash := contractState.ScriptHash() err := dao.PutContractState(contractState) @@ -82,7 +82,7 @@ func TestPutAndGetContractState(t *testing.T) { } func TestDeleteContractState(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) contractState := &state.Contract{Script: []byte{}, ParamList: []smartcontract.ParamType{}} hash := contractState.ScriptHash() err := dao.PutContractState(contractState) @@ -95,7 +95,7 @@ func TestDeleteContractState(t *testing.T) { } func TestGetUnspentCoinState_Err(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint256() gotUnspentCoinState, err := dao.GetUnspentCoinState(hash) require.Error(t, err) @@ -103,7 +103,7 @@ func TestGetUnspentCoinState_Err(t *testing.T) { } func TestPutGetUnspentCoinState(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint256() unspentCoinState := &state.UnspentCoin{Height: 42, States: []state.OutputState{}} err := dao.PutUnspentCoinState(hash, unspentCoinState) @@ -114,7 +114,7 @@ func TestPutGetUnspentCoinState(t *testing.T) { } func TestGetValidatorStateOrNew_New(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) publicKey := &keys.PublicKey{} validatorState, err := dao.GetValidatorStateOrNew(publicKey) require.NoError(t, err) @@ -122,7 +122,7 @@ func TestGetValidatorStateOrNew_New(t *testing.T) { } func TestPutGetValidatorState(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) publicKey := &keys.PublicKey{} validatorState := &state.Validator{ PublicKey: publicKey, @@ -137,7 +137,7 @@ func TestPutGetValidatorState(t *testing.T) { } func TestDeleteValidatorState(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) publicKey := &keys.PublicKey{} validatorState := &state.Validator{ PublicKey: publicKey, @@ -154,7 +154,7 @@ func TestDeleteValidatorState(t *testing.T) { } func TestGetValidators(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) publicKey := &keys.PublicKey{} validatorState := &state.Validator{ PublicKey: publicKey, @@ -169,7 +169,7 @@ func TestGetValidators(t *testing.T) { } func TestPutGetAppExecResult(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint256() appExecResult := &state.AppExecResult{ TxHash: hash, @@ -184,7 +184,7 @@ func TestPutGetAppExecResult(t *testing.T) { } func TestPutGetStorageItem(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint160() key := []byte{0} storageItem := &state.StorageItem{Value: []uint8{}} @@ -195,7 +195,7 @@ func TestPutGetStorageItem(t *testing.T) { } func TestDeleteStorageItem(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint160() key := []byte{0} storageItem := &state.StorageItem{Value: []uint8{}} @@ -208,7 +208,7 @@ func TestDeleteStorageItem(t *testing.T) { } func TestGetBlock_NotExists(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) hash := random.Uint256() block, _, err := dao.GetBlock(hash) require.Error(t, err) @@ -216,7 +216,7 @@ func TestGetBlock_NotExists(t *testing.T) { } func TestPutGetBlock(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) b := &block.Block{ Base: block.Base{ Script: transaction.Witness{ @@ -235,14 +235,14 @@ func TestPutGetBlock(t *testing.T) { } func TestGetVersion_NoVersion(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) version, err := dao.GetVersion() require.Error(t, err) require.Equal(t, "", version) } func TestGetVersion(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) err := dao.PutVersion("testVersion") require.NoError(t, err) version, err := dao.GetVersion() @@ -251,14 +251,14 @@ func TestGetVersion(t *testing.T) { } func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) height, err := dao.GetCurrentBlockHeight() require.Error(t, err) require.Equal(t, uint32(0), height) } func TestGetCurrentHeaderHeight_Store(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) b := &block.Block{ Base: block.Base{ Script: transaction.Witness{ @@ -275,7 +275,7 @@ func TestGetCurrentHeaderHeight_Store(t *testing.T) { } func TestStoreAsTransaction(t *testing.T) { - dao := newDao(storage.NewMemoryStore()) + dao := newSimpleDao(storage.NewMemoryStore()) tx := &transaction.Transaction{Type: transaction.IssueType, Data: &transaction.IssueTX{}} hash := tx.Hash() err := dao.StoreAsTransaction(tx, 0) diff --git a/pkg/core/gas_price_test.go b/pkg/core/gas_price_test.go index f3331527e..4bd550d41 100644 --- a/pkg/core/gas_price_test.go +++ b/pkg/core/gas_price_test.go @@ -15,7 +15,8 @@ import ( func TestGetPrice(t *testing.T) { bc := newTestChain(t) defer bc.Close() - systemInterop := bc.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, nil) + sdao := newSimpleDao(storage.NewMemoryStore()) + systemInterop := bc.newInteropContext(trigger.Application, sdao, nil, nil) v := bc.spawnVMWithInterops(systemInterop) v.SetPriceGetter(getPrice) diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index e701c94d2..e14f8a6c4 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -123,7 +123,7 @@ func TestHeaderGetVersion_Negative(t *testing.T) { block := newDumbBlock() chain := newTestChain(t) defer chain.Close() - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), block, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), block, nil) v.Estack().PushVal(vm.NewBoolItem(false)) err := context.headerGetVersion(v) @@ -219,7 +219,7 @@ func TestWitnessGetVerificationScript(t *testing.T) { chain := newTestChain(t) defer chain.Close() - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), nil, nil) v.Estack().PushVal(vm.NewInteropItem(&witness)) err := context.witnessGetVerificationScript(v) require.NoError(t, err) @@ -462,7 +462,7 @@ func createVMAndPushBlock(t *testing.T) (*vm.VM, *block.Block, *interopContext, v := vm.New() block := newDumbBlock() chain := newTestChain(t) - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), block, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), block, nil) v.Estack().PushVal(vm.NewInteropItem(block)) return v, block, context, chain } @@ -492,7 +492,7 @@ func createVMAndAssetState(t *testing.T) (*vm.VM, *state.Asset, *interopContext, } chain := newTestChain(t) - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), nil, nil) return v, assetState, context, chain } @@ -511,7 +511,7 @@ func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interopCo } chain := newTestChain(t) - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), nil, nil) return v, contractState, context, chain } @@ -526,7 +526,7 @@ func createVMAndAccState(t *testing.T) (*vm.VM, *state.Account, *interopContext, require.NoError(t, err) chain := newTestChain(t) - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), nil, nil) return v, accountState, context, chain } @@ -557,6 +557,6 @@ func createVMAndTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interopCont tx.Inputs = inputs tx.Outputs = outputs chain := newTestChain(t) - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, tx) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), nil, tx) return v, tx, context, chain } diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 14b5eae95..def9ea5ad 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -12,7 +12,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/vm" @@ -29,8 +28,8 @@ type interopContext struct { log *zap.Logger } -func newInteropContext(trigger trigger.Type, bc Blockchainer, s storage.Store, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { - dao := newCachedDao(s) +func newInteropContext(trigger trigger.Type, bc Blockchainer, d dao, block *block.Block, tx *transaction.Transaction, log *zap.Logger) *interopContext { + dao := newCachedDao(d) nes := make([]state.NotificationEvent, 0) return &interopContext{bc, trigger, block, tx, dao, nes, log} } diff --git a/pkg/core/interops_test.go b/pkg/core/interops_test.go index feefe56bb..bf825327c 100644 --- a/pkg/core/interops_test.go +++ b/pkg/core/interops_test.go @@ -16,7 +16,7 @@ func testNonInterop(t *testing.T, value interface{}, f func(*interopContext, *vm v.Estack().PushVal(value) chain := newTestChain(t) defer chain.Close() - context := chain.newInteropContext(trigger.Application, storage.NewMemoryStore(), nil, nil) + context := chain.newInteropContext(trigger.Application, newSimpleDao(storage.NewMemoryStore()), nil, nil) require.Error(t, f(context, v)) } diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 3864440be..25e1fed7d 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -11,7 +11,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/block" "github.com/nspcc-dev/neo-go/pkg/core/mempool" "github.com/nspcc-dev/neo-go/pkg/core/state" - "github.com/nspcc-dev/neo-go/pkg/core/storage" "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/io" @@ -109,7 +108,7 @@ func (chain testChain) GetScriptHashesForVerifying(*transaction.Transaction) ([] func (chain testChain) GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem { panic("TODO") } -func (chain testChain) GetTestVM() (*vm.VM, storage.Store) { +func (chain testChain) GetTestVM() *vm.VM { panic("TODO") } func (chain testChain) GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error) { diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 72e1c5274..3d5da1e2b 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -881,7 +881,7 @@ func (s *Server) invokescript(reqParams request.Params) (interface{}, error) { // runScriptInVM runs given script in a new test VM and returns the invocation // result. func (s *Server) runScriptInVM(script []byte) *result.Invoke { - vm, _ := s.chain.GetTestVM() + vm := s.chain.GetTestVM() vm.SetGasLimit(s.config.MaxGasInvoke) vm.LoadScript(script) _ = vm.Run()