diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index f20d675ff83..17316c9d67c 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -88,7 +88,7 @@ type NumberHash struct { // This method considers both limits to be _inclusive_. func ReadAllHashesInRange(db ethdb.Iteratee, first, last uint64) []*NumberHash { var ( - start = encodeBlockNumber(first) + start = encodeUint64(first) keyLength = len(headerPrefix) + 8 + 32 hashes = make([]*NumberHash, 0, 1+last-first) it = db.NewIterator(headerPrefix, start) @@ -155,7 +155,7 @@ func ReadHeaderNumber(db ethdb.KeyValueReader, hash common.Hash) (uint64, bool) // WriteHeaderNumber stores the hash->number mapping. func WriteHeaderNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { key := headerNumberKey(hash) - enc := encodeBlockNumber(number) + enc := encodeUint64(number) if err := db.Put(key, enc); err != nil { log.Crit("Failed to store hash to number mapping", "err", err) } @@ -272,7 +272,7 @@ func ReadTxIndexTail(db ethdb.KeyValueReader) *uint64 { // WriteTxIndexTail stores the number of oldest indexed block // into database. func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) { - if err := db.Put(txIndexTailKey, encodeBlockNumber(number)); err != nil { + if err := db.Put(txIndexTailKey, encodeUint64(number)); err != nil { log.Crit("Failed to store the transaction index tail", "err", err) } } diff --git a/core/rawdb/accessors_state.go b/core/rawdb/accessors_state.go index 714c1f77d6e..d972cdf2ecf 100644 --- a/core/rawdb/accessors_state.go +++ b/core/rawdb/accessors_state.go @@ -130,7 +130,7 @@ func ReadPersistentStateID(db ethdb.KeyValueReader) uint64 { // WritePersistentStateID stores the id of the persistent state into database. func WritePersistentStateID(db ethdb.KeyValueWriter, number uint64) { - if err := db.Put(persistentStateIDKey, encodeBlockNumber(number)); err != nil { + if err := db.Put(persistentStateIDKey, encodeUint64(number)); err != nil { log.Crit("Failed to store the persistent state ID", "err", err) } } diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index d9140c5fd65..2f3e8b4b1c5 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -177,80 +177,115 @@ type LegacyTxLookupEntry struct { Index uint64 } -// encodeBlockNumber encodes a block number as big endian uint64 -func encodeBlockNumber(number uint64) []byte { +// encodeUint64 encodes a block number as big endian uint64 +func encodeUint64(number uint64) []byte { enc := make([]byte, 8) binary.BigEndian.PutUint64(enc, number) return enc } +func encodeUint32(number uint32) []byte { + enc := make([]byte, 4) + binary.BigEndian.PutUint32(enc, number) + return enc +} + +func encodeKey(input []byte, values ...[]byte) []byte { + off := 0 + for _, h := range values { + off += copy(input[off:], h) + } + return input +} + // headerKeyPrefix = headerPrefix + num (uint64 big endian) func headerKeyPrefix(number uint64) []byte { - return append(headerPrefix, encodeBlockNumber(number)...) + // len(headerPrefix) + len(uint64) + buf := make([]byte, 1+8) + return encodeKey(buf, headerPrefix, encodeUint64(number)) } // headerKey = headerPrefix + num (uint64 big endian) + hash func headerKey(number uint64, hash common.Hash) []byte { - return append(append(headerPrefix, encodeBlockNumber(number)...), hash.Bytes()...) + // len(headerPrefix) + len(uint64) + len(hash) + buf := make([]byte, 1+8+common.HashLength) + return encodeKey(buf, headerPrefix, encodeUint64(number), hash.Bytes()) } // headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix func headerHashKey(number uint64) []byte { - return append(append(headerPrefix, encodeBlockNumber(number)...), headerHashSuffix...) + // len(headerPrefix) + len(uint64) + len(headerHashSuffix) + buf := make([]byte, 1+8+1) + return encodeKey(buf, headerPrefix, encodeUint64(number), headerHashSuffix) } // headerNumberKey = headerNumberPrefix + hash func headerNumberKey(hash common.Hash) []byte { - return append(headerNumberPrefix, hash.Bytes()...) + buf := make([]byte, 1+common.HashLength) + return encodeKey(buf, headerNumberPrefix, hash.Bytes()) } // blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash func blockBodyKey(number uint64, hash common.Hash) []byte { - return append(append(blockBodyPrefix, encodeBlockNumber(number)...), hash.Bytes()...) + // len(blockBodyPrefix) + len(uint64) + len(hash) + buf := make([]byte, 1+8+common.HashLength) + return encodeKey(buf, blockBodyPrefix, encodeUint64(number), hash.Bytes()) } // blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash func blockReceiptsKey(number uint64, hash common.Hash) []byte { - return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) + // len(blockReceiptsPrefix) + len(uint64) + len(hash) + buf := make([]byte, 1+8+common.HashLength) + return encodeKey(buf, blockReceiptsPrefix, encodeUint64(number), hash.Bytes()) } // txLookupKey = txLookupPrefix + hash func txLookupKey(hash common.Hash) []byte { - return append(txLookupPrefix, hash.Bytes()...) + // len(txLookupPrefix) + len(hash) + buf := make([]byte, 1+common.HashLength) + return encodeKey(buf, txLookupPrefix, hash.Bytes()) } // accountSnapshotKey = SnapshotAccountPrefix + hash func accountSnapshotKey(hash common.Hash) []byte { - return append(SnapshotAccountPrefix, hash.Bytes()...) + // len(SnapshotAccountPrefix) + len(hash) + buf := make([]byte, 1+common.HashLength) + return encodeKey(buf, SnapshotAccountPrefix, hash.Bytes()) } // storageSnapshotKey = SnapshotStoragePrefix + account hash + storage hash func storageSnapshotKey(accountHash, storageHash common.Hash) []byte { - buf := make([]byte, len(SnapshotStoragePrefix)+common.HashLength+common.HashLength) - n := copy(buf, SnapshotStoragePrefix) - n += copy(buf[n:], accountHash.Bytes()) - copy(buf[n:], storageHash.Bytes()) - return buf + //len(SnapshotStoragePrefix) + len(accountHash) + len(storageHash) + buf := make([]byte, 1+common.HashLength+common.HashLength) + return encodeKey(buf, SnapshotStoragePrefix, accountHash.Bytes(), storageHash.Bytes()) } -// storageSnapshotsKey = SnapshotStoragePrefix + account hash + storage hash +// storageSnapshotsKey = SnapshotStoragePrefix + account hash func storageSnapshotsKey(accountHash common.Hash) []byte { - return append(SnapshotStoragePrefix, accountHash.Bytes()...) + // len(SnapshotStoragePrefix) + len(accountHash) + buf := make([]byte, 1+common.HashLength) + return encodeKey(buf, SnapshotStoragePrefix, accountHash.Bytes()) } // skeletonHeaderKey = skeletonHeaderPrefix + num (uint64 big endian) func skeletonHeaderKey(number uint64) []byte { - return append(skeletonHeaderPrefix, encodeBlockNumber(number)...) + // len(skeletonHeaderPrefix) + len(uint64) + buf := make([]byte, 1+8) + return encodeKey(buf, skeletonHeaderPrefix, encodeUint64(number)) } // preimageKey = PreimagePrefix + hash func preimageKey(hash common.Hash) []byte { - return append(PreimagePrefix, hash.Bytes()...) + // len(PreimagePrefix) + len(hash) + buf := make([]byte, 11+common.HashLength) + return encodeKey(buf, PreimagePrefix, hash.Bytes()) } // codeKey = CodePrefix + hash func codeKey(hash common.Hash) []byte { - return append(CodePrefix, hash.Bytes()...) + // len(CodePrefix) + len(hash) + buf := make([]byte, 1+common.HashLength) + return encodeKey(buf, CodePrefix, hash.Bytes()) } // IsCodeKey reports whether the given byte slice is the key of contract code, @@ -264,17 +299,23 @@ func IsCodeKey(key []byte) (bool, []byte) { // configKey = configPrefix + hash func configKey(hash common.Hash) []byte { - return append(configPrefix, hash.Bytes()...) + // len(configPrefix) + len(hash) + buf := make([]byte, 16+common.HashLength) + return encodeKey(buf, configPrefix, hash.Bytes()) } // genesisStateSpecKey = genesisPrefix + hash func genesisStateSpecKey(hash common.Hash) []byte { - return append(genesisPrefix, hash.Bytes()...) + // len(genesisPrefix) + len(hash) + buf := make([]byte, 17+common.HashLength) + return encodeKey(buf, genesisPrefix, hash.Bytes()) } // stateIDKey = stateIDPrefix + root (32 bytes) func stateIDKey(root common.Hash) []byte { - return append(stateIDPrefix, root.Bytes()...) + // len(stateIDPrefix) + len(root) + buf := make([]byte, 1+common.HashLength) + return encodeKey(buf, stateIDPrefix, root.Bytes()) } // accountTrieNodeKey = TrieNodeAccountPrefix + nodePath. @@ -352,53 +393,42 @@ func IsStorageTrieNode(key []byte) bool { return ok } -// filterMapRowKey = filterMapRowPrefix + mapRowIndex (uint64 big endian) func filterMapRowKey(mapRowIndex uint64, base bool) []byte { - extLen := 8 - if base { - extLen = 9 + // len(filterMapRowPrefix) + extLen + key := make([]byte, 4+9) + key = encodeKey(key, filterMapRowPrefix, encodeUint64(mapRowIndex)) + if !base { + return key[0 : 4+8] } - l := len(filterMapRowPrefix) - key := make([]byte, l+extLen) - copy(key[:l], filterMapRowPrefix) - binary.BigEndian.PutUint64(key[l:l+8], mapRowIndex) return key } // filterMapLastBlockKey = filterMapLastBlockPrefix + mapIndex (uint32 big endian) func filterMapLastBlockKey(mapIndex uint32) []byte { - l := len(filterMapLastBlockPrefix) - key := make([]byte, l+4) - copy(key[:l], filterMapLastBlockPrefix) - binary.BigEndian.PutUint32(key[l:], mapIndex) - return key + // len(filterMapLastBlockPrefix) + len(uint32) + key := make([]byte, 4+4) + return encodeKey(key, filterMapLastBlockPrefix, encodeUint32(mapIndex)) } // filterMapBlockLVKey = filterMapBlockLVPrefix + num (uint64 big endian) func filterMapBlockLVKey(number uint64) []byte { - l := len(filterMapBlockLVPrefix) - key := make([]byte, l+8) - copy(key[:l], filterMapBlockLVPrefix) - binary.BigEndian.PutUint64(key[l:], number) - return key + //len(filterMapBlockLVPrefix) + len(uint64) + key := make([]byte, 4+8) + return encodeKey(key, filterMapBlockLVPrefix, encodeUint64(number)) } // accountHistoryIndexKey = StateHistoryAccountMetadataPrefix + addressHash func accountHistoryIndexKey(addressHash common.Hash) []byte { - return append(StateHistoryAccountMetadataPrefix, addressHash.Bytes()...) + // len(StateHistoryAccountMetadataPrefix) + len(addressHash) + buf := make([]byte, 2+common.HashLength) + return encodeKey(buf, StateHistoryAccountMetadataPrefix, addressHash.Bytes()) } // storageHistoryIndexKey = StateHistoryStorageMetadataPrefix + addressHash + storageHash func storageHistoryIndexKey(addressHash common.Hash, storageHash common.Hash) []byte { - totalLen := len(StateHistoryStorageMetadataPrefix) + 2*common.HashLength - out := make([]byte, totalLen) - - off := 0 - off += copy(out[off:], StateHistoryStorageMetadataPrefix) - off += copy(out[off:], addressHash.Bytes()) - copy(out[off:], storageHash.Bytes()) - - return out + // len(StateHistoryStorageMetadataPrefix) + len(addressHash) + len(storageHash) + out := make([]byte, 2+2*common.HashLength) + return encodeKey(out, StateHistoryStorageMetadataPrefix, addressHash.Bytes(), storageHash.Bytes()) } // trienodeHistoryIndexKey = TrienodeHistoryMetadataPrefix + addressHash + trienode path @@ -416,29 +446,16 @@ func trienodeHistoryIndexKey(addressHash common.Hash, path []byte) []byte { // accountHistoryIndexBlockKey = StateHistoryAccountBlockPrefix + addressHash + blockID func accountHistoryIndexBlockKey(addressHash common.Hash, blockID uint32) []byte { - totalLen := len(StateHistoryAccountBlockPrefix) + common.HashLength + 4 - out := make([]byte, totalLen) - - off := 0 - off += copy(out[off:], StateHistoryAccountBlockPrefix) - off += copy(out[off:], addressHash.Bytes()) - binary.BigEndian.PutUint32(out[off:], blockID) - - return out + // len(StateHistoryAccountBlockPrefix) + len(common.Hash) + len(uint32) + out := make([]byte, 3+common.HashLength+4) + return encodeKey(out, StateHistoryAccountBlockPrefix, addressHash.Bytes(), encodeUint32(blockID)) } // storageHistoryIndexBlockKey = StateHistoryStorageBlockPrefix + addressHash + storageHash + blockID func storageHistoryIndexBlockKey(addressHash common.Hash, storageHash common.Hash, blockID uint32) []byte { - totalLen := len(StateHistoryStorageBlockPrefix) + 2*common.HashLength + 4 - out := make([]byte, totalLen) - - off := 0 - off += copy(out[off:], StateHistoryStorageBlockPrefix) - off += copy(out[off:], addressHash.Bytes()) - off += copy(out[off:], storageHash.Bytes()) - binary.BigEndian.PutUint32(out[off:], blockID) - - return out + // len(StateHistoryStorageBlockPrefix) + 2*common.HashLength + len(uint32) + out := make([]byte, 3+2*common.HashLength+4) + return encodeKey(out, StateHistoryStorageBlockPrefix, addressHash.Bytes(), storageHash.Bytes(), encodeUint32(blockID)) } // trienodeHistoryIndexBlockKey = TrienodeHistoryBlockPrefix + addressHash + trienode path + blockID @@ -457,5 +474,7 @@ func trienodeHistoryIndexBlockKey(addressHash common.Hash, path []byte, blockID // transitionStateKey = transitionStatusKey + hash func transitionStateKey(hash common.Hash) []byte { - return append(VerkleTransitionStatePrefix, hash.Bytes()...) + // len(VerkleTransitionStatePrefix) + len(hash) + buf := make([]byte, 24+common.HashLength) + return encodeKey(buf, VerkleTransitionStatePrefix, hash.Bytes()) }