core: deduplicate state commit methods, use interim MemCachedStore

commit methods duplicated putSmthIntoStore functions, but have MemCachedStore
now that can easily substitute for a Batch, especially given that interop
needs something like that for its storage purposes anyway.
This commit is contained in:
Roman Khimov 2019-10-16 17:29:21 +03:00
parent fc0031e5aa
commit 2245fedbb1
9 changed files with 71 additions and 67 deletions

View file

@ -48,17 +48,23 @@ func getAccountStateFromStore(s storage.Store, hash util.Uint160) (*AccountState
return account, err
}
// commit writes all account states to the given Batch.
func (a Accounts) commit(b storage.Batch) error {
// putAccountStateIntoStore puts given AccountState into the given store.
func putAccountStateIntoStore(store storage.Store, as *AccountState) error {
buf := io.NewBufBinWriter()
for hash, state := range a {
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
as.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STAccount, as.ScriptHash.Bytes())
return store.Put(key, buf.Bytes())
}
// commit writes all account states to the given Batch.
func (a Accounts) commit(store storage.Store) error {
for _, state := range a {
if err := putAccountStateIntoStore(store, state); err != nil {
return err
}
key := storage.AppendPrefix(storage.STAccount, hash.Bytes())
b.Put(key, buf.Bytes())
buf.Reset()
}
return nil
}

View file

@ -13,16 +13,11 @@ const feeMode = 0x0
// Assets is mapping between AssetID and the AssetState.
type Assets map[util.Uint256]*AssetState
func (a Assets) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, state := range a {
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
func (a Assets) commit(store storage.Store) error {
for _, state := range a {
if err := putAssetStateIntoStore(store, state); err != nil {
return err
}
key := storage.AppendPrefix(storage.STAsset, hash.Bytes())
b.Put(key, buf.Bytes())
buf.Reset()
}
return nil
}

View file

@ -306,7 +306,7 @@ func (bc *Blockchain) processHeader(h *Header, batch storage.Batch, headerList *
// and all tests are in place, we can make a more optimized and cleaner implementation.
func (bc *Blockchain) storeBlock(block *Block) error {
var (
batch = bc.store.Batch()
tmpStore = storage.NewMemCachedStore(bc.store)
unspentCoins = make(UnspentCoins)
spentCoins = make(SpentCoins)
accounts = make(Accounts)
@ -314,14 +314,16 @@ func (bc *Blockchain) storeBlock(block *Block) error {
contracts = make(Contracts)
)
if err := storeAsBlock(batch, block, 0); err != nil {
if err := storeAsBlock(tmpStore, block, 0); err != nil {
return err
}
storeAsCurrentBlock(batch, block)
if err := storeAsCurrentBlock(tmpStore, block); err != nil {
return err
}
for _, tx := range block.Transactions {
if err := storeAsTransaction(batch, tx, block.Index); err != nil {
if err := storeAsTransaction(tmpStore, tx, block.Index); err != nil {
return err
}
@ -415,7 +417,7 @@ func (bc *Blockchain) storeBlock(block *Block) error {
return cs.Script
})
systemInterop := newInteropContext(0x10, bc, bc.store, block, tx)
systemInterop := newInteropContext(0x10, bc, tmpStore, block, tx)
vm.RegisterInteropFuncs(systemInterop.getSystemInteropMap())
vm.RegisterInteropFuncs(systemInterop.getNeoInteropMap())
vm.LoadScript(t.Script)
@ -435,22 +437,22 @@ func (bc *Blockchain) storeBlock(block *Block) error {
}
// Persist all to storage.
if err := accounts.commit(batch); err != nil {
if err := accounts.commit(tmpStore); err != nil {
return err
}
if err := unspentCoins.commit(batch); err != nil {
if err := unspentCoins.commit(tmpStore); err != nil {
return err
}
if err := spentCoins.commit(batch); err != nil {
if err := spentCoins.commit(tmpStore); err != nil {
return err
}
if err := assets.commit(batch); err != nil {
if err := assets.commit(tmpStore); err != nil {
return err
}
if err := contracts.commit(batch); err != nil {
if err := contracts.commit(tmpStore); err != nil {
return err
}
if err := bc.store.PutBatch(batch); err != nil {
if _, err := tmpStore.Persist(); err != nil {
return err
}

View file

@ -27,16 +27,11 @@ type ContractState struct {
}
// commit flushes all contracts to the given storage.Batch.
func (a Contracts) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
for hash, contract := range a {
contract.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
func (a Contracts) commit(store storage.Store) error {
for _, contract := range a {
if err := putContractStateIntoStore(store, contract); err != nil {
return err
}
key := storage.AppendPrefix(storage.STContract, hash.Bytes())
b.Put(key, buf.Bytes())
buf.Reset()
}
return nil
}

View file

@ -35,16 +35,22 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
return spent, nil
}
func (s SpentCoins) commit(b storage.Batch) error {
// putSpentCoinStateIntoStore puts given SpentCoinState into the given store.
func putSpentCoinStateIntoStore(store storage.Store, hash util.Uint256, scs *SpentCoinState) error {
buf := io.NewBufBinWriter()
scs.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
return store.Put(key, buf.Bytes())
}
func (s SpentCoins) commit(store storage.Store) error {
for hash, state := range s {
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
if err := putSpentCoinStateIntoStore(store, hash, state); err != nil {
return err
}
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
b.Put(key, buf.Bytes())
buf.Reset()
}
return nil
}

View file

@ -33,7 +33,6 @@ func TestEncodeDecodeSpentCoinState(t *testing.T) {
func TestCommitSpentCoins(t *testing.T) {
var (
store = storage.NewMemoryStore()
batch = store.Batch()
spentCoins = make(SpentCoins)
)
@ -49,6 +48,5 @@ func TestCommitSpentCoins(t *testing.T) {
txHeight: 1,
}
}
assert.Nil(t, spentCoins.commit(batch))
assert.Nil(t, store.PutBatch(batch))
assert.Nil(t, spentCoins.commit(store))
}

View file

@ -51,6 +51,17 @@ func getUnspentCoinStateFromStore(s storage.Store, hash util.Uint256) (*UnspentC
return unspent, nil
}
// putUnspentCoinStateIntoStore puts given UnspentCoinState into the given store.
func putUnspentCoinStateIntoStore(store storage.Store, hash util.Uint256, ucs *UnspentCoinState) error {
buf := io.NewBufBinWriter()
ucs.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
}
key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse())
return store.Put(key, buf.Bytes())
}
// UnspentCoinState hold the state of a unspent coin.
type UnspentCoinState struct {
states []CoinState
@ -68,16 +79,11 @@ func NewUnspentCoinState(n int) *UnspentCoinState {
}
// commit writes all unspent coin states to the given Batch.
func (u UnspentCoins) commit(b storage.Batch) error {
buf := io.NewBufBinWriter()
func (u UnspentCoins) commit(store storage.Store) error {
for hash, state := range u {
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil {
return buf.Err
if err := putUnspentCoinStateIntoStore(store, hash, state); err != nil {
return err
}
key := storage.AppendPrefix(storage.STCoin, hash.BytesReverse())
b.Put(key, buf.Bytes())
buf.Reset()
}
return nil
}

View file

@ -31,7 +31,6 @@ func TestDecodeEncodeUnspentCoinState(t *testing.T) {
func TestCommitUnspentCoins(t *testing.T) {
var (
store = storage.NewMemoryStore()
batch = store.Batch()
unspentCoins = make(UnspentCoins)
)
@ -56,6 +55,5 @@ func TestCommitUnspentCoins(t *testing.T) {
},
}
assert.Nil(t, unspentCoins.commit(batch))
assert.Nil(t, store.PutBatch(batch))
assert.Nil(t, unspentCoins.commit(store))
}

View file

@ -179,15 +179,15 @@ func headerSliceReverse(dest []*Header) {
// storeAsCurrentBlock stores the given block witch prefix
// SYSCurrentBlock.
func storeAsCurrentBlock(batch storage.Batch, block *Block) {
func storeAsCurrentBlock(store storage.Store, block *Block) error {
buf := io.NewBufBinWriter()
buf.WriteLE(block.Hash().BytesReverse())
buf.WriteLE(block.Index)
batch.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes())
return store.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes())
}
// storeAsBlock stores the given block as DataBlock.
func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
func storeAsBlock(store storage.Store, block *Block, sysFee uint32) error {
var (
key = storage.AppendPrefix(storage.DataBlock, block.Hash().BytesReverse())
buf = io.NewBufBinWriter()
@ -202,12 +202,11 @@ func storeAsBlock(batch storage.Batch, block *Block, sysFee uint32) error {
if buf.Err != nil {
return buf.Err
}
batch.Put(key, buf.Bytes())
return nil
return store.Put(key, buf.Bytes())
}
// storeAsTransaction stores the given TX as DataTransaction.
func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index uint32) error {
func storeAsTransaction(store storage.Store, tx *transaction.Transaction, index uint32) error {
key := storage.AppendPrefix(storage.DataTransaction, tx.Hash().BytesReverse())
buf := io.NewBufBinWriter()
buf.WriteLE(index)
@ -215,6 +214,5 @@ func storeAsTransaction(batch storage.Batch, tx *transaction.Transaction, index
if buf.Err != nil {
return buf.Err
}
batch.Put(key, buf.Bytes())
return nil
return store.Put(key, buf.Bytes())
}