core/rawdb: add BAL storage layer

This commit is contained in:
jonny rhea 2026-03-20 13:17:40 -05:00
parent 77779d1098
commit 1b9666962f
3 changed files with 96 additions and 0 deletions

View file

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/types/bal"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
@ -605,6 +606,91 @@ func DeleteReceipts(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
}
}
// HasBAL verifies the existence of a block access list for a block.
func HasBAL(db ethdb.Reader, hash common.Hash, number uint64) bool {
if isCanon(db, number, hash) {
return true
}
if has, err := db.Has(balKey(number, hash)); !has || err != nil {
return false
}
return true
}
// ReadBALRLP retrieves the RLP-encoded block access list for a block.
func ReadBALRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
var data []byte
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
})
return data
}
// ReadCanonicalBALRLP retrieves the BAL RLP for the canonical block at number.
// Optionally takes the block hash to avoid looking it up.
func ReadCanonicalBALRLP(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
})
return data
}
// ReadBAL retrieves and decodes the block access list for a block.
func ReadBAL(db ethdb.Reader, hash common.Hash, number uint64) *bal.BlockAccessList {
data := ReadBALRLP(db, hash, number)
if len(data) == 0 {
return nil
}
b := new(bal.BlockAccessList)
if err := rlp.DecodeBytes(data, b); err != nil {
log.Error("Invalid BAL RLP", "hash", hash, "err", err)
return nil
}
return b
}
// WriteBAL RLP-encodes and stores a block access list in the active KV store.
func WriteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64, b *bal.BlockAccessList) {
bytes, err := rlp.EncodeToBytes(b)
if err != nil {
log.Crit("Failed to encode BAL", "err", err)
}
if err := db.Put(balKey(number, hash), bytes); err != nil {
log.Crit("Failed to store BAL", "err", err)
}
}
// WriteBALRLP stores a pre-encoded block access list in the active KV store.
func WriteBALRLP(db ethdb.KeyValueWriter, hash common.Hash, number uint64, encoded rlp.RawValue) {
if err := db.Put(balKey(number, hash), encoded); err != nil {
log.Crit("Failed to store BAL", "err", err)
}
}
// DeleteBAL removes a block access list from the active KV store.
func DeleteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64) {
if err := db.Delete(balKey(number, hash)); err != nil {
log.Crit("Failed to delete BAL", "err", err)
}
}
// ReceiptLogs is a barebone version of ReceiptForStorage which only keeps
// the list of logs. When decoding a stored receipt into this object we
// avoid creating the bloom filter.

View file

@ -35,6 +35,9 @@ 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.
@ -46,6 +49,7 @@ 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.

View file

@ -112,6 +112,7 @@ var (
blockBodyPrefix = []byte("b") // blockBodyPrefix + num (uint64 big endian) + hash -> block body
blockReceiptsPrefix = []byte("r") // blockReceiptsPrefix + num (uint64 big endian) + hash -> block receipts
balPrefix = []byte("j") // balPrefix + num (uint64 big endian) + hash -> block access list
txLookupPrefix = []byte("l") // txLookupPrefix + hash -> transaction/receipt lookup metadata
bloomBitsPrefix = []byte("B") // bloomBitsPrefix + bit (uint16 big endian) + section (uint64 big endian) + hash -> bloom bits
@ -214,6 +215,11 @@ func blockReceiptsKey(number uint64, hash common.Hash) []byte {
return append(append(blockReceiptsPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
}
// balKey = balPrefix + num (uint64 big endian) + hash
func balKey(number uint64, hash common.Hash) []byte {
return append(append(balPrefix, encodeBlockNumber(number)...), hash.Bytes()...)
}
// txLookupKey = txLookupPrefix + hash
func txLookupKey(hash common.Hash) []byte {
return append(txLookupPrefix, hash.Bytes()...)