mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-12 09:51:36 +00:00
core/rawdb: remove BAL from chain freezer
This commit is contained in:
parent
50e5b7b60a
commit
34a09b1aaf
6 changed files with 14 additions and 142 deletions
|
|
@ -1476,7 +1476,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||
// Ensure genesis is in the ancient store
|
||||
if blockChain[0].NumberU64() == 1 {
|
||||
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList}, nil)
|
||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList})
|
||||
if err != nil {
|
||||
log.Error("Error writing genesis to ancients", "err", err)
|
||||
return 0, err
|
||||
|
|
@ -1486,7 +1486,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
|||
}
|
||||
}
|
||||
// Write all chain data to ancients.
|
||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, nil)
|
||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain)
|
||||
if err != nil {
|
||||
log.Error("Error importing chain data to ancients", "err", err)
|
||||
return 0, err
|
||||
|
|
@ -2907,7 +2907,7 @@ func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, e
|
|||
first = headers[0].Number.Uint64()
|
||||
)
|
||||
if first == 1 && frozen == 0 {
|
||||
_, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList}, nil)
|
||||
_, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []rlp.RawValue{rlp.EmptyList})
|
||||
if err != nil {
|
||||
log.Error("Error writing genesis to ancients", "err", err)
|
||||
return 0, err
|
||||
|
|
|
|||
|
|
@ -611,41 +611,9 @@ func HasAccessList(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
|||
return len(ReadAccessListRLP(db, hash, number)) > 0
|
||||
}
|
||||
|
||||
// ReadAccessListRLP retrieves the RLP-encoded block access list for a block.
|
||||
// ReadAccessListRLP retrieves the RLP-encoded block access list for a block from KV.
|
||||
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
err := db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
||||
return nil
|
||||
}
|
||||
data, _ = db.Get(balKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
log.Crit("error reading from ancient store", "err", err)
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
// ReadCanonicalAccessListRLP retrieves the BAL RLP for the canonical block at number.
|
||||
// Optionally takes the block hash to avoid looking it up.
|
||||
func ReadCanonicalAccessListRLP(db ethdb.Reader, number uint64, hash *common.Hash) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
||||
if len(data) > 0 {
|
||||
return nil
|
||||
}
|
||||
// BAL is not in ancients, read from db by hash and number.
|
||||
if hash != nil {
|
||||
data, _ = db.Get(balKey(number, *hash))
|
||||
} else {
|
||||
hashBytes, _ := db.Get(headerHashKey(number))
|
||||
data, _ = db.Get(balKey(number, common.BytesToHash(hashBytes)))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
data, _ := db.Get(balKey(number, hash))
|
||||
return data
|
||||
}
|
||||
|
||||
|
|
@ -760,15 +728,11 @@ func WriteBlock(db ethdb.KeyValueWriter, block *types.Block) {
|
|||
}
|
||||
|
||||
// WriteAncientBlocks writes entire block data into ancient store and returns the total written size.
|
||||
func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []rlp.RawValue, bals []rlp.RawValue) (int64, error) {
|
||||
func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts []rlp.RawValue) (int64, error) {
|
||||
return db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||
for i, block := range blocks {
|
||||
header := block.Header()
|
||||
var bal rlp.RawValue
|
||||
if bals != nil {
|
||||
bal = bals[i]
|
||||
}
|
||||
if err := writeAncientBlock(op, block, header, receipts[i], bal); err != nil {
|
||||
if err := writeAncientBlock(op, block, header, receipts[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -776,7 +740,7 @@ func WriteAncientBlocks(db ethdb.AncientWriter, blocks []*types.Block, receipts
|
|||
})
|
||||
}
|
||||
|
||||
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts rlp.RawValue, bal rlp.RawValue) error {
|
||||
func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *types.Header, receipts rlp.RawValue) error {
|
||||
num := block.NumberU64()
|
||||
if err := op.AppendRaw(ChainFreezerHashTable, num, block.Hash().Bytes()); err != nil {
|
||||
return fmt.Errorf("can't add block %d hash: %v", num, err)
|
||||
|
|
@ -790,9 +754,6 @@ func writeAncientBlock(op ethdb.AncientWriteOp, block *types.Block, header *type
|
|||
if err := op.Append(ChainFreezerReceiptTable, num, receipts); err != nil {
|
||||
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
||||
}
|
||||
if err := op.AppendRaw(ChainFreezerBALTable, num, bal); err != nil {
|
||||
return fmt.Errorf("can't append block %d BAL: %v", num, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -815,9 +776,6 @@ func WriteAncientHeaderChain(db ethdb.AncientWriter, headers []*types.Header) (i
|
|||
if err := op.AppendRaw(ChainFreezerReceiptTable, num, nil); err != nil {
|
||||
return fmt.Errorf("can't append block %d receipts: %v", num, err)
|
||||
}
|
||||
if err := op.AppendRaw(ChainFreezerBALTable, num, nil); err != nil {
|
||||
return fmt.Errorf("can't append block %d BAL: %v", num, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
|
@ -826,7 +784,6 @@ func WriteAncientHeaderChain(db ethdb.AncientWriter, headers []*types.Header) (i
|
|||
// DeleteBlock removes all block data associated with a hash.
|
||||
func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||
DeleteReceipts(db, hash, number)
|
||||
DeleteAccessList(db, hash, number)
|
||||
DeleteHeader(db, hash, number)
|
||||
DeleteBody(db, hash, number)
|
||||
}
|
||||
|
|
@ -835,7 +792,6 @@ func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
|||
// the hash to number mapping.
|
||||
func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
|
||||
DeleteReceipts(db, hash, number)
|
||||
DeleteAccessList(db, hash, number)
|
||||
deleteHeaderWithoutNumber(db, hash, number)
|
||||
DeleteBody(db, hash, number)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ func TestAncientStorage(t *testing.T) {
|
|||
}
|
||||
|
||||
// Write and verify the header in the database
|
||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), nil)
|
||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}))
|
||||
|
||||
if blob := ReadHeaderRLP(db, hash, number); len(blob) == 0 {
|
||||
t.Fatalf("no header returned")
|
||||
|
|
@ -563,7 +563,7 @@ func BenchmarkWriteAncientBlocks(b *testing.B) {
|
|||
|
||||
blocks := allBlocks[i : i+length]
|
||||
receipts := batchReceipts[:length]
|
||||
writeSize, err := WriteAncientBlocks(db, blocks, types.EncodeBlockReceiptLists(receipts), nil)
|
||||
writeSize, err := WriteAncientBlocks(db, blocks, types.EncodeBlockReceiptLists(receipts))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
|
@ -868,7 +868,7 @@ func TestHeadersRLPStorage(t *testing.T) {
|
|||
}
|
||||
receipts := make([]types.Receipts, 100)
|
||||
// Write first half to ancients
|
||||
WriteAncientBlocks(db, chain[:50], types.EncodeBlockReceiptLists(receipts[:50]), nil)
|
||||
WriteAncientBlocks(db, chain[:50], types.EncodeBlockReceiptLists(receipts[:50]))
|
||||
// Write second half to db
|
||||
for i := 50; i < 100; i++ {
|
||||
WriteCanonicalHash(db, chain[i].Hash(), chain[i].NumberU64())
|
||||
|
|
@ -977,80 +977,4 @@ func TestBALStorage(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestBALFreezer tests that BALs are frozen alongside other block data
|
||||
// and can be read from the freezer.
|
||||
func TestBALFreezer(t *testing.T) {
|
||||
frdir := t.TempDir()
|
||||
db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database with ancient backend: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Create a test block.
|
||||
block := types.NewBlockWithHeader(&types.Header{
|
||||
Number: big.NewInt(0),
|
||||
Extra: []byte("test block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
hash, number := block.Hash(), block.NumberU64()
|
||||
|
||||
// Verify no BAL exists before writing.
|
||||
if blob := ReadAccessListRLP(db, hash, number); len(blob) > 0 {
|
||||
t.Fatalf("non existent BAL returned")
|
||||
}
|
||||
|
||||
// Write a BAL to KV first, then freeze.
|
||||
balRLP, testBAL := makeTestBAL(t)
|
||||
|
||||
// Freeze via WriteAncientBlocks.
|
||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), []rlp.RawValue{balRLP})
|
||||
|
||||
// Verify the BAL can be read from the freezer.
|
||||
if blob := ReadAccessListRLP(db, hash, number); len(blob) == 0 {
|
||||
t.Fatal("no BAL returned from freezer")
|
||||
}
|
||||
if b := ReadAccessList(db, hash, number); b == nil {
|
||||
t.Fatal("ReadAccessList returned nil from freezer")
|
||||
} else if b.Hash() != testBAL.Hash() {
|
||||
t.Fatalf("frozen BAL hash mismatch: got %x, want %x", b.Hash(), testBAL.Hash())
|
||||
}
|
||||
|
||||
// Verify ReadCanonicalAccessListRLP works.
|
||||
if blob := ReadCanonicalAccessListRLP(db, number, &hash); len(blob) == 0 {
|
||||
t.Fatal("ReadCanonicalAccessListRLP returned empty for frozen block")
|
||||
}
|
||||
}
|
||||
|
||||
// TestBALEmptyFreezer tests that pre-EIP-8189 blocks without BALs have empty
|
||||
// freezer entries.
|
||||
func TestBALEmptyFreezer(t *testing.T) {
|
||||
frdir := t.TempDir()
|
||||
db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: frdir})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database with ancient backend: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
// Create and freeze a block with no BAL.
|
||||
block := types.NewBlockWithHeader(&types.Header{
|
||||
Number: big.NewInt(0),
|
||||
Extra: []byte("no bal block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
})
|
||||
hash, number := block.Hash(), block.NumberU64()
|
||||
|
||||
WriteAncientBlocks(db, []*types.Block{block}, types.EncodeBlockReceiptLists([]types.Receipts{nil}), nil)
|
||||
|
||||
// HasAccessList should return false for a block with an empty freezer entry.
|
||||
if HasAccessList(db, hash, number) {
|
||||
t.Fatal("HasAccessList returned true for block with no BAL")
|
||||
}
|
||||
if b := ReadAccessList(db, hash, number); b != nil {
|
||||
t.Fatalf("ReadAccessList returned non-nil for block with no BAL: %v", b)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,6 @@ const (
|
|||
|
||||
// ChainFreezerReceiptTable indicates the name of the freezer receipts table.
|
||||
ChainFreezerReceiptTable = "receipts"
|
||||
|
||||
// ChainFreezerBALTable indicates the name of the freezer block access list table.
|
||||
ChainFreezerBALTable = "bals"
|
||||
)
|
||||
|
||||
// chainFreezerTableConfigs configures the settings for tables in the chain freezer.
|
||||
|
|
@ -49,7 +46,6 @@ var chainFreezerTableConfigs = map[string]freezerTableConfig{
|
|||
ChainFreezerHashTable: {noSnappy: true, prunable: false},
|
||||
ChainFreezerBodiesTable: {noSnappy: false, prunable: true},
|
||||
ChainFreezerReceiptTable: {noSnappy: false, prunable: true},
|
||||
ChainFreezerBALTable: {noSnappy: false, prunable: true},
|
||||
}
|
||||
|
||||
// freezerTableConfig contains the settings for a freezer table.
|
||||
|
|
|
|||
|
|
@ -327,7 +327,6 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
|
|||
if len(receipts) == 0 {
|
||||
return fmt.Errorf("block receipts missing, can't freeze block %d", number)
|
||||
}
|
||||
bal := ReadAccessListRLP(nfdb, hash, number)
|
||||
// Write to the batch.
|
||||
if err := op.AppendRaw(ChainFreezerHashTable, number, hash[:]); err != nil {
|
||||
return fmt.Errorf("can't write hash to Freezer: %v", err)
|
||||
|
|
@ -341,9 +340,6 @@ func (f *chainFreezer) freezeRange(nfdb *nofreezedb, number, limit uint64) (hash
|
|||
if err := op.AppendRaw(ChainFreezerReceiptTable, number, receipts); err != nil {
|
||||
return fmt.Errorf("can't write receipts to Freezer: %v", err)
|
||||
}
|
||||
if err := op.AppendRaw(ChainFreezerBALTable, number, bal); err != nil {
|
||||
return fmt.Errorf("can't write BAL to Freezer: %v", err)
|
||||
}
|
||||
hashes = append(hashes, hash)
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ func TestTxIndexer(t *testing.T) {
|
|||
}
|
||||
for _, c := range cases {
|
||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...)), nil)
|
||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...)))
|
||||
|
||||
// Index the initial blocks from ancient store
|
||||
indexer := &txIndexer{
|
||||
|
|
@ -237,7 +237,7 @@ func TestTxIndexerRepair(t *testing.T) {
|
|||
for _, c := range cases {
|
||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||
encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))
|
||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts, nil)
|
||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts)
|
||||
|
||||
// Index the initial blocks from ancient store
|
||||
indexer := &txIndexer{
|
||||
|
|
@ -428,7 +428,7 @@ func TestTxIndexerReport(t *testing.T) {
|
|||
for _, c := range cases {
|
||||
db, _ := rawdb.Open(rawdb.NewMemoryDatabase(), rawdb.OpenOptions{})
|
||||
encReceipts := types.EncodeBlockReceiptLists(append([]types.Receipts{{}}, receipts...))
|
||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts, nil)
|
||||
rawdb.WriteAncientBlocks(db, append([]*types.Block{gspec.ToBlock()}, blocks...), encReceipts)
|
||||
|
||||
// Index the initial blocks from ancient store
|
||||
indexer := &txIndexer{
|
||||
|
|
|
|||
Loading…
Reference in a new issue