mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-10 05:53:46 +00:00
core/rawdb: verify canonical hash before reading ancient BAL (#35471)
This commit is contained in:
parent
7e520c4310
commit
cae76d5a3c
2 changed files with 53 additions and 4 deletions
|
|
@ -618,11 +618,14 @@ func HasAccessList(db ethdb.Reader, hash common.Hash, number uint64) bool {
|
|||
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||
var data []byte
|
||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
||||
if len(data) > 0 {
|
||||
return nil
|
||||
// Ancients maintain only canonical data. For a non-canonical hash at an
|
||||
// ancient height, fall back to the key-value store.
|
||||
if isCanon(reader, number, hash) {
|
||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
||||
if len(data) > 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// Block is not in ancients, read from key-value store by hash and number.
|
||||
data, _ = db.Get(accessListKey(number, hash))
|
||||
return nil
|
||||
})
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/keccak"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/holiman/uint256"
|
||||
|
|
@ -967,6 +968,51 @@ func TestWriteAncientBlocksNilBAL(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReadAccessListRLPAncientNonCanonical(t *testing.T) {
|
||||
db, err := Open(NewMemoryDatabase(), OpenOptions{Ancient: t.TempDir()})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create database with ancient backend: %v", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
encoded, accessList := makeTestBAL(t)
|
||||
accessListHash := accessList.Hash()
|
||||
block := types.NewBlockWithHeader(&types.Header{
|
||||
Number: big.NewInt(0),
|
||||
Extra: []byte("canonical-bal block"),
|
||||
UncleHash: types.EmptyUncleHash,
|
||||
TxHash: types.EmptyTxsHash,
|
||||
ReceiptHash: types.EmptyReceiptsHash,
|
||||
BlockAccessListHash: &accessListHash,
|
||||
}).WithAccessList(accessList)
|
||||
if _, err := db.ModifyAncients(func(op ethdb.AncientWriteOp) error {
|
||||
if err := op.AppendRaw(ChainFreezerHashTable, 0, block.Hash().Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := op.Append(ChainFreezerHeaderTable, 0, block.Header()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := op.Append(ChainFreezerBodiesTable, 0, block.Body()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := op.AppendRaw(ChainFreezerReceiptTable, 0, types.EncodeBlockReceiptLists([]types.Receipts{nil})[0]); err != nil {
|
||||
return err
|
||||
}
|
||||
return op.AppendRaw(ChainFreezerBALTable, 0, encoded)
|
||||
}); err != nil {
|
||||
t.Fatalf("failed to write ancient block: %v", err)
|
||||
}
|
||||
if blob := ReadAccessListRLP(db, block.Hash(), block.NumberU64()); len(blob) == 0 {
|
||||
t.Fatal("canonical block access list not found in ancients")
|
||||
}
|
||||
// Ancients contain data only for the canonical hash. Looking up another
|
||||
// hash at the same height must not return the canonical block's access list.
|
||||
nonCanonical := common.HexToHash("0xdeadbeef")
|
||||
if blob := ReadAccessListRLP(db, nonCanonical, block.NumberU64()); len(blob) != 0 {
|
||||
t.Fatalf("ReadAccessListRLP returned canonical data for non-canonical hash: %x", blob)
|
||||
}
|
||||
}
|
||||
|
||||
// TestBALStorage tests write/read/delete of BALs in the KV store.
|
||||
func TestBALStorage(t *testing.T) {
|
||||
db := NewMemoryDatabase()
|
||||
|
|
|
|||
Loading…
Reference in a new issue