From 7d6f08733710f4919d3440e77e14285e937361ed Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Fri, 18 Feb 2022 15:19:57 +0300 Subject: [PATCH] storage: drop (KeyPrefix).Bytes() API It allocates and most of the time we can avoid that. --- pkg/core/blockchain.go | 4 ++-- pkg/core/blockchain_test.go | 19 +++++++++------- pkg/core/dao/dao.go | 36 ++++++++++++++++++------------- pkg/core/dao/dao_test.go | 4 ++-- pkg/core/statesync/module_test.go | 4 ++-- pkg/core/statesync_test.go | 4 ++-- pkg/core/storage/store.go | 5 ----- 7 files changed, 40 insertions(+), 36 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 624b9932c..1d51823f8 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -406,7 +406,7 @@ func (bc *Blockchain) init() error { } // Check whether StateJump stage is in the storage and continue interrupted state jump if so. - jumpStage, err := bc.dao.Store.Get(storage.SYSStateJumpStage.Bytes()) + jumpStage, err := bc.dao.Store.Get([]byte{byte(storage.SYSStateJumpStage)}) if err == nil { if !(bc.GetConfig().P2PStateExchangeExtensions && bc.GetConfig().RemoveUntraceableBlocks) { return errors.New("state jump was not completed, but P2PStateExchangeExtensions are disabled or archival node capability is on. " + @@ -500,7 +500,7 @@ func (bc *Blockchain) jumpToStateInternal(p uint32, stage stateJumpStage) error bc.log.Info("jumping to state sync point", zap.Uint32("state sync point", p)) - jumpStageKey := storage.SYSStateJumpStage.Bytes() + jumpStageKey := []byte{byte(storage.SYSStateJumpStage)} switch stage { case none: bc.dao.Store.Put(jumpStageKey, []byte{byte(stateJumpStarted)}) diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index 079b4efd3..39710482f 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -1853,7 +1853,9 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { if bcSpout.dao.Version.StoragePrefix == tempPrefix { tempPrefix = storage.STStorage } - bcSpout.dao.Store.Seek(storage.SeekRange{Prefix: bcSpout.dao.Version.StoragePrefix.Bytes()}, func(k, v []byte) bool { + bPrefix := make([]byte, 1) + bPrefix[0] = byte(bcSpout.dao.Version.StoragePrefix) + bcSpout.dao.Store.Seek(storage.SeekRange{Prefix: bPrefix}, func(k, v []byte) bool { key := slice.Copy(k) key[0] = byte(tempPrefix) value := slice.Copy(v) @@ -1880,34 +1882,35 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { c.ProtocolConfiguration.KeepOnlyLatestState = true } // manually store statejump stage to check statejump recover process + bPrefix[0] = byte(storage.SYSStateJumpStage) t.Run("invalid RemoveUntraceableBlocks setting", func(t *testing.T) { - bcSpout.dao.Store.Put(storage.SYSStateJumpStage.Bytes(), []byte{byte(stateJumpStarted)}) + bcSpout.dao.Store.Put(bPrefix, []byte{byte(stateJumpStarted)}) checkNewBlockchainErr(t, func(c *config.Config) { boltCfg(c) c.ProtocolConfiguration.RemoveUntraceableBlocks = false }, bcSpout.dao.Store, true) }) t.Run("invalid state jump stage format", func(t *testing.T) { - bcSpout.dao.Store.Put(storage.SYSStateJumpStage.Bytes(), []byte{0x01, 0x02}) + bcSpout.dao.Store.Put(bPrefix, []byte{0x01, 0x02}) checkNewBlockchainErr(t, boltCfg, bcSpout.dao.Store, true) }) t.Run("missing state sync point", func(t *testing.T) { - bcSpout.dao.Store.Put(storage.SYSStateJumpStage.Bytes(), []byte{byte(stateJumpStarted)}) + bcSpout.dao.Store.Put(bPrefix, []byte{byte(stateJumpStarted)}) checkNewBlockchainErr(t, boltCfg, bcSpout.dao.Store, true) }) t.Run("invalid state sync point", func(t *testing.T) { - bcSpout.dao.Store.Put(storage.SYSStateJumpStage.Bytes(), []byte{byte(stateJumpStarted)}) + bcSpout.dao.Store.Put(bPrefix, []byte{byte(stateJumpStarted)}) point := make([]byte, 4) binary.LittleEndian.PutUint32(point, uint32(len(bcSpout.headerHashes))) - bcSpout.dao.Store.Put(storage.SYSStateSyncPoint.Bytes(), point) + bcSpout.dao.Store.Put([]byte{byte(storage.SYSStateSyncPoint)}, point) checkNewBlockchainErr(t, boltCfg, bcSpout.dao.Store, true) }) for _, stage := range []stateJumpStage{stateJumpStarted, newStorageItemsAdded, genesisStateRemoved, 0x03} { t.Run(fmt.Sprintf("state jump stage %d", stage), func(t *testing.T) { - bcSpout.dao.Store.Put(storage.SYSStateJumpStage.Bytes(), []byte{byte(stage)}) + bcSpout.dao.Store.Put(bPrefix, []byte{byte(stage)}) point := make([]byte, 4) binary.LittleEndian.PutUint32(point, uint32(stateSyncPoint)) - bcSpout.dao.Store.Put(storage.SYSStateSyncPoint.Bytes(), point) + bcSpout.dao.Store.Put([]byte{byte(storage.SYSStateSyncPoint)}, point) shouldFail := stage == 0x03 // unknown stage checkNewBlockchainErr(t, spountCfg, bcSpout.dao.Store, shouldFail) }) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 4b7520d45..cae2622d6 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -448,12 +448,18 @@ func (v *Version) Bytes() []byte { return append([]byte(v.Value), '\x00', byte(v.StoragePrefix), mask) } +func (dao *Simple) mkKeyPrefix(k storage.KeyPrefix) []byte { + b := dao.getKeyBuf(1) + b[0] = byte(k) + return b +} + // GetVersion attempts to get the current version stored in the // underlying store. func (dao *Simple) GetVersion() (Version, error) { var version Version - data, err := dao.Store.Get(storage.SYSVersion.Bytes()) + data, err := dao.Store.Get(dao.mkKeyPrefix(storage.SYSVersion)) if err == nil { err = version.FromBytes(data) } @@ -463,7 +469,7 @@ func (dao *Simple) GetVersion() (Version, error) { // GetCurrentBlockHeight returns the current block height found in the // underlying store. func (dao *Simple) GetCurrentBlockHeight() (uint32, error) { - b, err := dao.Store.Get(storage.SYSCurrentBlock.Bytes()) + b, err := dao.Store.Get(dao.mkKeyPrefix(storage.SYSCurrentBlock)) if err != nil { return 0, err } @@ -474,7 +480,7 @@ func (dao *Simple) GetCurrentBlockHeight() (uint32, error) { // the underlying store. func (dao *Simple) GetCurrentHeaderHeight() (i uint32, h util.Uint256, err error) { var b []byte - b, err = dao.Store.Get(storage.SYSCurrentHeader.Bytes()) + b, err = dao.Store.Get(dao.mkKeyPrefix(storage.SYSCurrentHeader)) if err != nil { return } @@ -485,7 +491,7 @@ func (dao *Simple) GetCurrentHeaderHeight() (i uint32, h util.Uint256, err error // GetStateSyncPoint returns current state synchronisation point P. func (dao *Simple) GetStateSyncPoint() (uint32, error) { - b, err := dao.Store.Get(storage.SYSStateSyncPoint.Bytes()) + b, err := dao.Store.Get(dao.mkKeyPrefix(storage.SYSStateSyncPoint)) if err != nil { return 0, err } @@ -495,7 +501,7 @@ func (dao *Simple) GetStateSyncPoint() (uint32, error) { // GetStateSyncCurrentBlockHeight returns current block height stored during state // synchronisation process. func (dao *Simple) GetStateSyncCurrentBlockHeight() (uint32, error) { - b, err := dao.Store.Get(storage.SYSStateSyncCurrentBlockHeight.Bytes()) + b, err := dao.Store.Get(dao.mkKeyPrefix(storage.SYSStateSyncCurrentBlockHeight)) if err != nil { return 0, err } @@ -508,7 +514,7 @@ func (dao *Simple) GetHeaderHashes() ([]util.Uint256, error) { var hashes = make([]util.Uint256, 0) dao.Store.Seek(storage.SeekRange{ - Prefix: storage.IXHeaderHashList.Bytes(), + Prefix: dao.mkKeyPrefix(storage.IXHeaderHashList), }, func(k, v []byte) bool { newHashes, err := read2000Uint256Hashes(v) if err != nil { @@ -555,7 +561,7 @@ func (dao *Simple) GetTransaction(hash util.Uint256) (*transaction.Transaction, // PutVersion stores the given version in the underlying store. func (dao *Simple) PutVersion(v Version) { dao.Version = v - dao.Store.Put(storage.SYSVersion.Bytes(), v.Bytes()) + dao.Store.Put(dao.mkKeyPrefix(storage.SYSVersion), v.Bytes()) } // PutCurrentHeader stores current header. @@ -563,21 +569,21 @@ func (dao *Simple) PutCurrentHeader(h util.Uint256, index uint32) { buf := dao.getDataBuf() buf.WriteBytes(h.BytesLE()) buf.WriteU32LE(index) - dao.Store.Put(storage.SYSCurrentHeader.Bytes(), buf.Bytes()) + dao.Store.Put(dao.mkKeyPrefix(storage.SYSCurrentHeader), buf.Bytes()) } // PutStateSyncPoint stores current state synchronisation point P. func (dao *Simple) PutStateSyncPoint(p uint32) { - buf := dao.getKeyBuf(4) // It's very small, no point in using BufBinWriter. - binary.LittleEndian.PutUint32(buf, p) - dao.Store.Put(storage.SYSStateSyncPoint.Bytes(), buf) + buf := dao.getDataBuf() + buf.WriteU32LE(p) + dao.Store.Put(dao.mkKeyPrefix(storage.SYSStateSyncPoint), buf.Bytes()) } // PutStateSyncCurrentBlockHeight stores current block height during state synchronisation process. func (dao *Simple) PutStateSyncCurrentBlockHeight(h uint32) { - buf := dao.getKeyBuf(4) // It's very small, no point in using BufBinWriter. - binary.LittleEndian.PutUint32(buf, h) - dao.Store.Put(storage.SYSStateSyncCurrentBlockHeight.Bytes(), buf) + buf := dao.getDataBuf() + buf.WriteU32LE(h) + dao.Store.Put(dao.mkKeyPrefix(storage.SYSStateSyncCurrentBlockHeight), buf.Bytes()) } // read2000Uint256Hashes attempts to read 2000 Uint256 hashes from @@ -712,7 +718,7 @@ func (dao *Simple) StoreAsCurrentBlock(block *block.Block) { h := block.Hash() h.EncodeBinary(buf.BinWriter) buf.WriteU32LE(block.Index) - dao.Store.Put(storage.SYSCurrentBlock.Bytes(), buf.Bytes()) + dao.Store.Put(dao.mkKeyPrefix(storage.SYSCurrentBlock), buf.Bytes()) } // StoreAsTransaction stores given TX as DataTransaction. It also stores transactions diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index feb2e2055..6583319e7 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -132,14 +132,14 @@ func TestGetVersion(t *testing.T) { t.Run("invalid", func(t *testing.T) { dao := NewSimple(storage.NewMemoryStore(), false, false) - dao.Store.Put(storage.SYSVersion.Bytes(), []byte("0.1.2\x00x")) + dao.Store.Put([]byte{byte(storage.SYSVersion)}, []byte("0.1.2\x00x")) _, err := dao.GetVersion() require.Error(t, err) }) t.Run("old format", func(t *testing.T) { dao := NewSimple(storage.NewMemoryStore(), false, false) - dao.Store.Put(storage.SYSVersion.Bytes(), []byte("0.1.2")) + dao.Store.Put([]byte{byte(storage.SYSVersion)}, []byte("0.1.2")) version, err := dao.GetVersion() require.NoError(t, err) diff --git a/pkg/core/statesync/module_test.go b/pkg/core/statesync/module_test.go index 79e24a8ba..6894f0593 100644 --- a/pkg/core/statesync/module_test.go +++ b/pkg/core/statesync/module_test.go @@ -32,7 +32,7 @@ func TestModule_PR2019_discussion_r689629704(t *testing.T) { nodes = make(map[util.Uint256][]byte) expectedItems []storage.KeyValue ) - expectedStorage.Seek(storage.SeekRange{Prefix: storage.DataMPT.Bytes()}, func(k, v []byte) bool { + expectedStorage.Seek(storage.SeekRange{Prefix: []byte{byte(storage.DataMPT)}}, func(k, v []byte) bool { key := slice.Copy(k) value := slice.Copy(v) expectedItems = append(expectedItems, storage.KeyValue{ @@ -96,7 +96,7 @@ func TestModule_PR2019_discussion_r689629704(t *testing.T) { // Compare resulting storage items and refcounts. var actualItems []storage.KeyValue - expectedStorage.Seek(storage.SeekRange{Prefix: storage.DataMPT.Bytes()}, func(k, v []byte) bool { + expectedStorage.Seek(storage.SeekRange{Prefix: []byte{byte(storage.DataMPT)}}, func(k, v []byte) bool { key := slice.Copy(k) value := slice.Copy(v) actualItems = append(actualItems, storage.KeyValue{ diff --git a/pkg/core/statesync_test.go b/pkg/core/statesync_test.go index 9da8e5f2b..2be3b01a9 100644 --- a/pkg/core/statesync_test.go +++ b/pkg/core/statesync_test.go @@ -423,7 +423,7 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) { // compare storage states fetchStorage := func(bc *Blockchain) []storage.KeyValue { var kv []storage.KeyValue - bc.dao.Store.Seek(storage.SeekRange{Prefix: bc.dao.Version.StoragePrefix.Bytes()}, func(k, v []byte) bool { + bc.dao.Store.Seek(storage.SeekRange{Prefix: []byte{byte(bc.dao.Version.StoragePrefix)}}, func(k, v []byte) bool { key := slice.Copy(k) value := slice.Copy(v) if key[0] == byte(storage.STTempStorage) { @@ -444,7 +444,7 @@ func TestStateSyncModule_RestoreBasicChain(t *testing.T) { // no temp items should be left require.Eventually(t, func() bool { var haveItems bool - bcBolt.dao.Store.Seek(storage.SeekRange{Prefix: storage.STStorage.Bytes()}, func(_, _ []byte) bool { + bcBolt.dao.Store.Seek(storage.SeekRange{Prefix: []byte{byte(storage.STStorage)}}, func(_, _ []byte) bool { haveItems = true return false }) diff --git a/pkg/core/storage/store.go b/pkg/core/storage/store.go index 0812a5f08..4d2b1a550 100644 --- a/pkg/core/storage/store.go +++ b/pkg/core/storage/store.go @@ -106,11 +106,6 @@ type ( KeyPrefix uint8 ) -// Bytes returns the bytes representation of KeyPrefix. -func (k KeyPrefix) Bytes() []byte { - return []byte{byte(k)} -} - func seekRangeToPrefixes(sr SeekRange) *util.Range { var ( rang *util.Range