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 return account, err
} }
// commit writes all account states to the given Batch. // putAccountStateIntoStore puts given AccountState into the given store.
func (a Accounts) commit(b storage.Batch) error { func putAccountStateIntoStore(store storage.Store, as *AccountState) error {
buf := io.NewBufBinWriter() buf := io.NewBufBinWriter()
for hash, state := range a { as.EncodeBinary(buf.BinWriter)
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil { if buf.Err != nil {
return buf.Err return buf.Err
} }
key := storage.AppendPrefix(storage.STAccount, hash.Bytes()) key := storage.AppendPrefix(storage.STAccount, as.ScriptHash.Bytes())
b.Put(key, buf.Bytes()) return store.Put(key, buf.Bytes())
buf.Reset() }
// 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
}
} }
return nil return nil
} }

View file

@ -13,16 +13,11 @@ const feeMode = 0x0
// Assets is mapping between AssetID and the AssetState. // Assets is mapping between AssetID and the AssetState.
type Assets map[util.Uint256]*AssetState type Assets map[util.Uint256]*AssetState
func (a Assets) commit(b storage.Batch) error { func (a Assets) commit(store storage.Store) error {
buf := io.NewBufBinWriter() for _, state := range a {
for hash, state := range a { if err := putAssetStateIntoStore(store, state); err != nil {
state.EncodeBinary(buf.BinWriter) return err
if buf.Err != nil {
return buf.Err
} }
key := storage.AppendPrefix(storage.STAsset, hash.Bytes())
b.Put(key, buf.Bytes())
buf.Reset()
} }
return nil 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. // and all tests are in place, we can make a more optimized and cleaner implementation.
func (bc *Blockchain) storeBlock(block *Block) error { func (bc *Blockchain) storeBlock(block *Block) error {
var ( var (
batch = bc.store.Batch() tmpStore = storage.NewMemCachedStore(bc.store)
unspentCoins = make(UnspentCoins) unspentCoins = make(UnspentCoins)
spentCoins = make(SpentCoins) spentCoins = make(SpentCoins)
accounts = make(Accounts) accounts = make(Accounts)
@ -314,14 +314,16 @@ func (bc *Blockchain) storeBlock(block *Block) error {
contracts = make(Contracts) contracts = make(Contracts)
) )
if err := storeAsBlock(batch, block, 0); err != nil { if err := storeAsBlock(tmpStore, block, 0); err != nil {
return err return err
} }
storeAsCurrentBlock(batch, block) if err := storeAsCurrentBlock(tmpStore, block); err != nil {
return err
}
for _, tx := range block.Transactions { 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 return err
} }
@ -415,7 +417,7 @@ func (bc *Blockchain) storeBlock(block *Block) error {
return cs.Script 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.getSystemInteropMap())
vm.RegisterInteropFuncs(systemInterop.getNeoInteropMap()) vm.RegisterInteropFuncs(systemInterop.getNeoInteropMap())
vm.LoadScript(t.Script) vm.LoadScript(t.Script)
@ -435,22 +437,22 @@ func (bc *Blockchain) storeBlock(block *Block) error {
} }
// Persist all to storage. // Persist all to storage.
if err := accounts.commit(batch); err != nil { if err := accounts.commit(tmpStore); err != nil {
return err return err
} }
if err := unspentCoins.commit(batch); err != nil { if err := unspentCoins.commit(tmpStore); err != nil {
return err return err
} }
if err := spentCoins.commit(batch); err != nil { if err := spentCoins.commit(tmpStore); err != nil {
return err return err
} }
if err := assets.commit(batch); err != nil { if err := assets.commit(tmpStore); err != nil {
return err return err
} }
if err := contracts.commit(batch); err != nil { if err := contracts.commit(tmpStore); err != nil {
return err return err
} }
if err := bc.store.PutBatch(batch); err != nil { if _, err := tmpStore.Persist(); err != nil {
return err return err
} }

View file

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

View file

@ -35,16 +35,22 @@ func (s SpentCoins) getAndUpdate(store storage.Store, hash util.Uint256) (*Spent
return spent, nil 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() buf := io.NewBufBinWriter()
for hash, state := range s { scs.EncodeBinary(buf.BinWriter)
state.EncodeBinary(buf.BinWriter)
if buf.Err != nil { if buf.Err != nil {
return buf.Err return buf.Err
} }
key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse()) key := storage.AppendPrefix(storage.STSpentCoin, hash.BytesReverse())
b.Put(key, buf.Bytes()) return store.Put(key, buf.Bytes())
buf.Reset() }
func (s SpentCoins) commit(store storage.Store) error {
for hash, state := range s {
if err := putSpentCoinStateIntoStore(store, hash, state); err != nil {
return err
}
} }
return nil return nil
} }

View file

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

View file

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

View file

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

View file

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