mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-11 14:33:52 +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 {
|
func ReadAccessListRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue {
|
||||||
var data []byte
|
var data []byte
|
||||||
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
db.ReadAncients(func(reader ethdb.AncientReaderOp) error {
|
||||||
data, _ = reader.Ancient(ChainFreezerBALTable, number)
|
// Ancients maintain only canonical data. For a non-canonical hash at an
|
||||||
if len(data) > 0 {
|
// ancient height, fall back to the key-value store.
|
||||||
return nil
|
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))
|
data, _ = db.Get(accessListKey(number, hash))
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types/bal"
|
"github.com/ethereum/go-ethereum/core/types/bal"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/keccak"
|
"github.com/ethereum/go-ethereum/crypto/keccak"
|
||||||
|
"github.com/ethereum/go-ethereum/ethdb"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/holiman/uint256"
|
"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.
|
// TestBALStorage tests write/read/delete of BALs in the KV store.
|
||||||
func TestBALStorage(t *testing.T) {
|
func TestBALStorage(t *testing.T) {
|
||||||
db := NewMemoryDatabase()
|
db := NewMemoryDatabase()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue