mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-18 21:01:38 +00:00
core/rawdb: add some basic tests
This commit is contained in:
parent
8f4668cebb
commit
b49a15c5b2
1 changed files with 155 additions and 0 deletions
|
|
@ -27,10 +27,12 @@ import (
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"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/crypto"
|
||||||
"github.com/ethereum/go-ethereum/crypto/keccak"
|
"github.com/ethereum/go-ethereum/crypto/keccak"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tests block header storage and retrieval operations.
|
// Tests block header storage and retrieval operations.
|
||||||
|
|
@ -899,3 +901,156 @@ func TestHeadersRLPStorage(t *testing.T) {
|
||||||
checkSequence(1, 1) // Only block 1
|
checkSequence(1, 1) // Only block 1
|
||||||
checkSequence(1, 2) // Genesis + block 1
|
checkSequence(1, 2) // Genesis + block 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeTestBAL(t *testing.T) (rlp.RawValue, *bal.BlockAccessList) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
cb := bal.NewConstructionBlockAccessList()
|
||||||
|
addr := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
||||||
|
cb.AccountRead(addr)
|
||||||
|
cb.StorageRead(addr, common.BytesToHash([]byte{0x01}))
|
||||||
|
cb.StorageWrite(0, addr, common.BytesToHash([]byte{0x02}), common.BytesToHash([]byte{0xaa}))
|
||||||
|
cb.BalanceChange(0, addr, uint256.NewInt(100))
|
||||||
|
cb.NonceChange(addr, 0, 1)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err := cb.EncodeRLP(&buf); err != nil {
|
||||||
|
t.Fatalf("failed to encode BAL: %v", err)
|
||||||
|
}
|
||||||
|
encoded := buf.Bytes()
|
||||||
|
|
||||||
|
var decoded bal.BlockAccessList
|
||||||
|
if err := rlp.DecodeBytes(encoded, &decoded); err != nil {
|
||||||
|
t.Fatalf("failed to decode BAL: %v", err)
|
||||||
|
}
|
||||||
|
return encoded, &decoded
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestBALStorage tests write/read/delete of BALs in the KV store.
|
||||||
|
func TestBALStorage(t *testing.T) {
|
||||||
|
db := NewMemoryDatabase()
|
||||||
|
|
||||||
|
hash := common.BytesToHash([]byte{0x03, 0x14})
|
||||||
|
number := uint64(42)
|
||||||
|
|
||||||
|
// Check that no BAL exists in a new database.
|
||||||
|
if HasBAL(db, hash, number) {
|
||||||
|
t.Fatal("BAL found in new database")
|
||||||
|
}
|
||||||
|
if b := ReadBAL(db, hash, number); b != nil {
|
||||||
|
t.Fatalf("non existent BAL returned: %v", b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a BAL and verify it can be read back.
|
||||||
|
encoded, testBAL := makeTestBAL(t)
|
||||||
|
WriteBAL(db, hash, number, testBAL)
|
||||||
|
|
||||||
|
if !HasBAL(db, hash, number) {
|
||||||
|
t.Fatal("HasBAL returned false after write")
|
||||||
|
}
|
||||||
|
if blob := ReadBALRLP(db, hash, number); len(blob) == 0 {
|
||||||
|
t.Fatal("ReadBALRLP returned empty after write")
|
||||||
|
}
|
||||||
|
if b := ReadBAL(db, hash, number); b == nil {
|
||||||
|
t.Fatal("ReadBAL returned nil after write")
|
||||||
|
} else if b.Hash() != testBAL.Hash() {
|
||||||
|
t.Fatalf("BAL hash mismatch: got %x, want %x", b.Hash(), testBAL.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also test WriteBALRLP with pre-encoded data.
|
||||||
|
hash2 := common.BytesToHash([]byte{0x03, 0x15})
|
||||||
|
WriteBALRLP(db, hash2, number, encoded)
|
||||||
|
if b := ReadBAL(db, hash2, number); b == nil {
|
||||||
|
t.Fatal("ReadBAL returned nil after WriteBALRLP")
|
||||||
|
} else if b.Hash() != testBAL.Hash() {
|
||||||
|
t.Fatalf("BAL hash mismatch after WriteBALRLP: got %x, want %x", b.Hash(), testBAL.Hash())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the BAL and verify it's gone.
|
||||||
|
DeleteBAL(db, hash, number)
|
||||||
|
|
||||||
|
if HasBAL(db, hash, number) {
|
||||||
|
t.Fatal("HasBAL returned true after delete")
|
||||||
|
}
|
||||||
|
if b := ReadBAL(db, hash, number); b != nil {
|
||||||
|
t.Fatalf("deleted BAL returned: %v", b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 := ReadBALRLP(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 := ReadBALRLP(db, hash, number); len(blob) == 0 {
|
||||||
|
t.Fatal("no BAL returned from freezer")
|
||||||
|
}
|
||||||
|
if b := ReadBAL(db, hash, number); b == nil {
|
||||||
|
t.Fatal("ReadBAL 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 ReadCanonicalBALRLP works.
|
||||||
|
if blob := ReadCanonicalBALRLP(db, number, &hash); len(blob) == 0 {
|
||||||
|
t.Fatal("ReadCanonicalBALRLP 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)
|
||||||
|
|
||||||
|
// HasBAL should return false for a block with an empty freezer entry.
|
||||||
|
if HasBAL(db, hash, number) {
|
||||||
|
t.Fatal("HasBAL returned true for block with no BAL")
|
||||||
|
}
|
||||||
|
if b := ReadBAL(db, hash, number); b != nil {
|
||||||
|
t.Fatalf("ReadBAL returned non-nil for block with no BAL: %v", b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue