erigon-pulse/common/dbutils/composite_keys.go
Alex Sharov ce96cf75b2
Intermediate hash phase 3 (#377)
* #remove debug prints

* remove storage-mode="i"

* minnet re-execute hack with checkpoints

* minnet re-execute hack with checkpoints

* rollback to master setup

* mainnet re-exec hack

* rollback some changes

* v0 of "push down" functionality

* move all logic to own functions

* handle case when re-created account already has some storage

* clear path for storage

* try to rely on tree structure (but maybe need to rely on DB because can be intra-block re-creations of account)

* fix some bugs with indexes, moving to tests

* tests added

* make linter happy

* make linter happy

* simplify logic

* adjust comparison of keys with and without incarnation

* test for keyIsBefore

* test for keyIsBefore

* better nibbles alignment

* better nibbles alignment

* cleanup

* continue work on tests

* simplify test

* check tombstone existence before pushing it down.

* put tombstone only when account deleted, not created

* put tombstone only when account has storage

* make linter happy

* test for storage resolver

* make fixedbytes work without incarnation

* fix panic on short keys

* use special comparison only when working with keys from cache

* add blockNr for better tracing

* fix: incorrect tombstone check

* fix: incorrect tombstone check

* trigger ci

* hack for problem block

* more test-cases

* add test case for too long keys

* speedup cached resolver by removing bucket creation transaction

* remove parent type check in pruning, remove unused copy from mutation.put

* dump resolving info on fail

* dump resolving info on fail

* set tombstone everytime for now to check if it will help

* on unload: check parent type, not type of node

* fix wrong order of checking node type

* fix wrong order of checking node type

* rebase to new master

* make linter happy

* rebase to new master

* place tombstone only if acc has storage

* rebase master

* rebase master

* rebase master

* rebase master

Co-authored-by: alex.sharov <alex.sharov@lazada.com>
2020-03-11 10:31:49 +00:00

138 lines
4.2 KiB
Go

package dbutils
import (
"bytes"
"encoding/binary"
"github.com/ledgerwatch/turbo-geth/common"
"github.com/ledgerwatch/turbo-geth/common/pool"
)
// EncodeBlockNumber encodes a block number as big endian uint64
func EncodeBlockNumber(number uint64) []byte {
enc := make([]byte, 8)
binary.BigEndian.PutUint64(enc, number)
return enc
}
// headerKey = headerPrefix + num (uint64 big endian) + hash
func HeaderKey(number uint64, hash common.Hash) []byte {
return append(EncodeBlockNumber(number), hash.Bytes()...)
}
func IsHeaderKey(k []byte) bool {
l := common.BlockNumberLength + common.HashLength
if len(k) != l {
return false
}
return !IsHeaderHashKey(k) && !IsHeaderTDKey(k)
}
// headerTDKey = headerPrefix + num (uint64 big endian) + hash + headerTDSuffix
func HeaderTDKey(number uint64, hash common.Hash) []byte {
return append(HeaderKey(number, hash), HeaderTDSuffix...)
}
func IsHeaderTDKey(k []byte) bool {
l := common.BlockNumberLength + common.HashLength + 1
return len(k) == l && bytes.Equal(k[l-1:], HeaderTDSuffix)
}
// headerHashKey = headerPrefix + num (uint64 big endian) + headerHashSuffix
func HeaderHashKey(number uint64) []byte {
return append(EncodeBlockNumber(number), HeaderHashSuffix...)
}
func IsHeaderHashKey(k []byte) bool {
l := common.BlockNumberLength + 1
return len(k) == l && bytes.Equal(k[l-1:], HeaderHashSuffix)
}
// headerNumberKey = headerNumberPrefix + hash
func HeaderNumberKey(hash common.Hash) []byte {
return append(HeaderNumberPrefix, hash.Bytes()...)
}
// blockBodyKey = blockBodyPrefix + num (uint64 big endian) + hash
func BlockBodyKey(number uint64, hash common.Hash) []byte {
return append(EncodeBlockNumber(number), hash.Bytes()...)
}
// blockReceiptsKey = blockReceiptsPrefix + num (uint64 big endian) + hash
func BlockReceiptsKey(number uint64, hash common.Hash) []byte {
return append(EncodeBlockNumber(number), hash.Bytes()...)
}
// txLookupKey = txLookupPrefix + hash
func TxLookupKey(hash common.Hash) []byte {
return append(TxLookupPrefix, hash.Bytes()...)
}
// bloomBitsKey = bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash
func BloomBitsKey(bit uint, section uint64, hash common.Hash) []byte {
key := append(make([]byte, 10), hash.Bytes()...)
binary.BigEndian.PutUint16(key[0:], uint16(bit))
binary.BigEndian.PutUint64(key[2:], section)
return key
}
// preimageKey = preimagePrefix + hash
func PreimageKey(hash common.Hash) []byte {
return append(PreimagePrefix, hash.Bytes()...)
}
// configKey = configPrefix + hash
func ConfigKey(hash common.Hash) []byte {
return append(ConfigPrefix, hash.Bytes()...)
}
// AddrHash + KeyHash
// Only for trie
func GenerateCompositeTrieKey(addressHash common.Hash, seckey common.Hash) []byte {
compositeKey := make([]byte, 0, common.HashLength+common.HashLength)
compositeKey = append(compositeKey, addressHash[:]...)
compositeKey = append(compositeKey, seckey[:]...)
return compositeKey
}
// AddrHash + incarnation + KeyHash
// For contract storage
func GenerateCompositeStorageKey(addressHash common.Hash, incarnation uint64, seckey common.Hash) []byte {
compositeKey := make([]byte, 0, common.HashLength+8+common.HashLength)
compositeKey = append(compositeKey, GenerateStoragePrefix(addressHash, incarnation)...)
compositeKey = append(compositeKey, seckey[:]...)
return compositeKey
}
// address hash + incarnation prefix
func GenerateStoragePrefix(addressHash common.Hash, incarnation uint64) []byte {
prefix := make([]byte, 0, common.HashLength+8)
prefix = append(prefix, addressHash[:]...)
buf := pool.GetBuffer(8)
defer pool.PutBuffer(buf)
binary.BigEndian.PutUint64(buf.B, incarnation^^uint64(0))
prefix = append(prefix, buf.B...)
return prefix
}
// Key + blockNum
func CompositeKeySuffix(key []byte, timestamp uint64) (composite, encodedTS []byte) {
encodedTS = EncodeTimestamp(timestamp)
composite = make([]byte, len(key)+len(encodedTS))
copy(composite, key)
copy(composite[len(key):], encodedTS)
return composite, encodedTS
}
// blockNum + history bucket
func CompositeChangeSetKey(encodedTS, hBucket []byte) []byte {
changeSetKey := make([]byte, len(encodedTS)+len(hBucket))
copy(changeSetKey, encodedTS)
copy(changeSetKey[len(encodedTS):], hBucket)
return changeSetKey
}