automated merge
This commit is contained in:
@@ -625,7 +625,7 @@ func ReadRawReceipts(db ethdb.Reader, hash common.Hash, number uint64) types.Rec
|
||||
// The current implementation populates these metadata fields by reading the receipts'
|
||||
// corresponding block body, so if the block body is not found it will return nil even
|
||||
// if the receipt itself is stored.
|
||||
func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts {
|
||||
func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, time uint64, config *params.ChainConfig) types.Receipts {
|
||||
// We're deriving many fields from the block body, retrieve beside the receipt
|
||||
receipts := ReadRawReceipts(db, hash, number)
|
||||
if receipts == nil {
|
||||
@@ -643,7 +643,7 @@ func ReadReceipts(db ethdb.Reader, hash common.Hash, number uint64, config *para
|
||||
} else {
|
||||
baseFee = header.BaseFee
|
||||
}
|
||||
if err := receipts.DeriveFields(config, hash, number, baseFee, body.Transactions); err != nil {
|
||||
if err := receipts.DeriveFields(config, hash, number, time, baseFee, body.Transactions); err != nil {
|
||||
log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
|
||||
// Check that no receipt entries are in a pristine database
|
||||
hash := common.BytesToHash([]byte{0x03, 0x14})
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
t.Fatalf("non existent receipts returned: %v", rs)
|
||||
}
|
||||
// Insert the body that corresponds to the receipts
|
||||
@@ -387,7 +387,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
|
||||
// Insert the receipt slice into the database and check presence
|
||||
WriteReceipts(db, hash, 0, receipts)
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) == 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) == 0 {
|
||||
t.Fatalf("no receipts returned")
|
||||
} else {
|
||||
if err := checkReceiptsRLP(rs, receipts); err != nil {
|
||||
@@ -396,7 +396,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
}
|
||||
// Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed)
|
||||
DeleteBody(db, hash, 0)
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); rs != nil {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); rs != nil {
|
||||
t.Fatalf("receipts returned when body was deleted: %v", rs)
|
||||
}
|
||||
// Ensure that receipts without metadata can be returned without the block body too
|
||||
@@ -407,7 +407,7 @@ func TestBlockReceiptStorage(t *testing.T) {
|
||||
WriteBody(db, hash, 0, body)
|
||||
|
||||
DeleteReceipts(db, hash, 0)
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
t.Fatalf("deleted receipts returned: %v", rs)
|
||||
}
|
||||
}
|
||||
@@ -727,7 +727,7 @@ func TestReadLogs(t *testing.T) {
|
||||
|
||||
hash := common.BytesToHash([]byte{0x03, 0x14})
|
||||
// Check that no receipt entries are in a pristine database
|
||||
if rs := ReadReceipts(db, hash, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
if rs := ReadReceipts(db, hash, 0, 0, params.TestChainConfig); len(rs) != 0 {
|
||||
t.Fatalf("non existent receipts returned: %v", rs)
|
||||
}
|
||||
// Insert the body that corresponds to the receipts
|
||||
|
||||
@@ -130,8 +130,12 @@ func ReadReceipt(db ethdb.Reader, hash common.Hash, config *params.ChainConfig)
|
||||
if blockHash == (common.Hash{}) {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
blockHeader := ReadHeader(db, blockHash, *blockNumber)
|
||||
if blockHeader == nil {
|
||||
return nil, common.Hash{}, 0, 0
|
||||
}
|
||||
// Read all the receipts from the block and return the one with the matching hash
|
||||
receipts := ReadReceipts(db, blockHash, *blockNumber, config)
|
||||
receipts := ReadReceipts(db, blockHash, *blockNumber, blockHeader.Time, config)
|
||||
for receiptIndex, receipt := range receipts {
|
||||
if receipt.TxHash == hash {
|
||||
return receipt, blockHash, *blockNumber, uint64(receiptIndex)
|
||||
|
||||
+20
-7
@@ -358,9 +358,15 @@ type OpenOptions struct {
|
||||
//
|
||||
// type == null type != null
|
||||
// +----------------------------------------
|
||||
// db is non-existent | leveldb default | specified type
|
||||
// db is existent | from db | specified type (if compatible)
|
||||
// db is non-existent | pebble default | specified type
|
||||
// db is existent | from db | specified type (if compatible)
|
||||
func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||
// Reject any unsupported database type
|
||||
if len(o.Type) != 0 && o.Type != dbLeveldb && o.Type != dbPebble {
|
||||
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
|
||||
}
|
||||
// Retrieve any pre-existing database's type and use that or the requested one
|
||||
// as long as there's no conflict between the two types
|
||||
existingDb := hasPreexistingDb(o.Directory)
|
||||
if len(existingDb) != 0 && len(o.Type) != 0 && o.Type != existingDb {
|
||||
return nil, fmt.Errorf("db.engine choice was %v but found pre-existing %v database in specified data directory", o.Type, existingDb)
|
||||
@@ -373,12 +379,19 @@ func openKeyValueDatabase(o OpenOptions) (ethdb.Database, error) {
|
||||
return nil, errors.New("db.engine 'pebble' not supported on this platform")
|
||||
}
|
||||
}
|
||||
if len(o.Type) != 0 && o.Type != dbLeveldb {
|
||||
return nil, fmt.Errorf("unknown db.engine %v", o.Type)
|
||||
if o.Type == dbLeveldb || existingDb == dbLeveldb {
|
||||
log.Info("Using leveldb as the backing database")
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
// No pre-existing database, no user-requested one either. Default to Pebble
|
||||
// on supported platforms and LevelDB on anything else.
|
||||
if PebbleEnabled {
|
||||
log.Info("Defaulting to pebble as the backing database")
|
||||
return NewPebbleDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
} else {
|
||||
log.Info("Defaulting to leveldb as the backing database")
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
log.Info("Using leveldb as the backing database")
|
||||
// Use leveldb, either as default (no explicit choice), or pre-existing, or chosen explicitly
|
||||
return NewLevelDBDatabase(o.Directory, o.Cache, o.Handles, o.Namespace, o.ReadOnly)
|
||||
}
|
||||
|
||||
// Open opens both a disk-based key-value database such as leveldb or pebble, but also
|
||||
|
||||
+47
-1
@@ -22,6 +22,7 @@ import (
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
)
|
||||
|
||||
@@ -100,7 +101,7 @@ var (
|
||||
CodePrefix = []byte("c") // CodePrefix + code hash -> account code
|
||||
skeletonHeaderPrefix = []byte("S") // skeletonHeaderPrefix + num (uint64 big endian) -> header
|
||||
|
||||
// Path-based trie node scheme.
|
||||
// Path-based storage scheme of merkle patricia trie.
|
||||
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
|
||||
trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node
|
||||
|
||||
@@ -248,3 +249,48 @@ func accountTrieNodeKey(path []byte) []byte {
|
||||
func storageTrieNodeKey(accountHash common.Hash, path []byte) []byte {
|
||||
return append(append(trieNodeStoragePrefix, accountHash.Bytes()...), path...)
|
||||
}
|
||||
|
||||
// IsLegacyTrieNode reports whether a provided database entry is a legacy trie
|
||||
// node. The characteristics of legacy trie node are:
|
||||
// - the key length is 32 bytes
|
||||
// - the key is the hash of val
|
||||
func IsLegacyTrieNode(key []byte, val []byte) bool {
|
||||
if len(key) != common.HashLength {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(key, crypto.Keccak256(val))
|
||||
}
|
||||
|
||||
// IsAccountTrieNode reports whether a provided database entry is an account
|
||||
// trie node in path-based state scheme.
|
||||
func IsAccountTrieNode(key []byte) (bool, []byte) {
|
||||
if !bytes.HasPrefix(key, trieNodeAccountPrefix) {
|
||||
return false, nil
|
||||
}
|
||||
// The remaining key should only consist a hex node path
|
||||
// whose length is in the range 0 to 64 (64 is excluded
|
||||
// since leaves are always wrapped with shortNode).
|
||||
if len(key) >= len(trieNodeAccountPrefix)+common.HashLength*2 {
|
||||
return false, nil
|
||||
}
|
||||
return true, key[len(trieNodeAccountPrefix):]
|
||||
}
|
||||
|
||||
// IsStorageTrieNode reports whether a provided database entry is a storage
|
||||
// trie node in path-based state scheme.
|
||||
func IsStorageTrieNode(key []byte) (bool, common.Hash, []byte) {
|
||||
if !bytes.HasPrefix(key, trieNodeStoragePrefix) {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
// The remaining key consists of 2 parts:
|
||||
// - 32 bytes account hash
|
||||
// - hex node path whose length is in the range 0 to 64
|
||||
if len(key) < len(trieNodeStoragePrefix)+common.HashLength {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
if len(key) >= len(trieNodeStoragePrefix)+common.HashLength+common.HashLength*2 {
|
||||
return false, common.Hash{}, nil
|
||||
}
|
||||
accountHash := common.BytesToHash(key[len(trieNodeStoragePrefix) : len(trieNodeStoragePrefix)+common.HashLength])
|
||||
return true, accountHash, key[len(trieNodeStoragePrefix)+common.HashLength:]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user