core: restore test

This commit is contained in:
Felix Lange 2025-04-14 14:29:14 +02:00
parent 9aa4df467c
commit 93bb4057fb

View file

@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/beacon"
"github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/core/history"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@ -4256,115 +4257,136 @@ func testChainReorgSnapSync(t *testing.T, ancientLimit uint64) {
// chain cutoff point. In this case the chain segment before the cutoff should
// be persisted without the receipts and bodies; chain after should be persisted
// normally.
// func TestInsertChainWithCutoff(t *testing.T) {
// testInsertChainWithCutoff(t, 32, 32) // cutoff = 32, ancientLimit = 32
// testInsertChainWithCutoff(t, 32, 64) // cutoff = 32, ancientLimit = 64 (entire chain in ancient)
// testInsertChainWithCutoff(t, 32, 65) // cutoff = 32, ancientLimit = 65 (64 blocks in ancient, 1 block in live)
// }
func TestInsertChainWithCutoff(t *testing.T) {
const chainLength = 64
// func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64) {
// // log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
//
// // Configure and generate a sample block chain
// var (
// key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
// address = crypto.PubkeyToAddress(key.PublicKey)
// funds = big.NewInt(1000000000000000)
// gspec = &Genesis{
// Config: params.TestChainConfig,
// Alloc: types.GenesisAlloc{address: {Balance: funds}},
// BaseFee: big.NewInt(params.InitialBaseFee),
// }
// signer = types.LatestSigner(gspec.Config)
// engine = beacon.New(ethash.NewFaker())
// )
// _, blocks, receipts := GenerateChainWithGenesis(gspec, engine, int(2*cutoff), func(i int, block *BlockGen) {
// block.SetCoinbase(common.Address{0x00})
//
// tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
// if err != nil {
// panic(err)
// }
// block.AddTx(tx)
// })
// db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
// defer db.Close()
//
// cutoffBlock := blocks[cutoff-1]
// config := DefaultCacheConfigWithScheme(rawdb.PathScheme)
// config.HistoryPruningCutoffNumber = cutoffBlock.NumberU64()
// config.HistoryPruningCutoffHash = cutoffBlock.Hash()
//
// chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), gspec, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
// defer chain.Stop()
//
// var (
// headersBefore []*types.Header
// blocksAfter []*types.Block
// receiptsAfter []types.Receipts
// )
// for i, b := range blocks {
// if b.NumberU64() < cutoffBlock.NumberU64() {
// headersBefore = append(headersBefore, b.Header())
// } else {
// blocksAfter = append(blocksAfter, b)
// receiptsAfter = append(receiptsAfter, receipts[i])
// }
// }
// if n, err := chain.InsertHeadersBeforeCutoff(headersBefore); err != nil {
// t.Fatalf("failed to insert headers before cutoff %d: %v", n, err)
// }
// if n, err := chain.InsertReceiptChain(blocksAfter, receiptsAfter, ancientLimit); err != nil {
// t.Fatalf("failed to insert receipt %d: %v", n, err)
// }
// headSnap := chain.CurrentSnapBlock()
// if headSnap.Hash() != blocks[len(blocks)-1].Hash() {
// t.Errorf("head snap block #%d: header mismatch: want: %v, got: %v", headSnap.Number, blocks[len(blocks)-1].Hash(), headSnap.Hash())
// }
// headHeader := chain.CurrentHeader()
// if headHeader.Hash() != blocks[len(blocks)-1].Hash() {
// t.Errorf("head header #%d: header mismatch: want: %v, got: %v", headHeader.Number, blocks[len(blocks)-1].Hash(), headHeader.Hash())
// }
// headBlock := chain.CurrentBlock()
// if headBlock.Hash() != gspec.ToBlock().Hash() {
// t.Errorf("head block #%d: header mismatch: want: %v, got: %v", headBlock.Number, gspec.ToBlock().Hash(), headBlock.Hash())
// }
//
// // Iterate over all chain data components, and cross reference
// for i := 0; i < len(blocks); i++ {
// num, hash := blocks[i].NumberU64(), blocks[i].Hash()
//
// // Canonical headers should be visible regardless of cutoff
// header := chain.GetHeaderByNumber(num)
// if header.Hash() != hash {
// t.Errorf("block #%d: header mismatch: want: %v, got: %v", num, hash, header.Hash())
// }
// tail, err := db.Tail()
// if err != nil {
// t.Fatalf("Failed to get chain tail, %v", err)
// }
// if tail != cutoffBlock.NumberU64() {
// t.Fatalf("Unexpected chain tail, want: %d, got: %d", cutoffBlock.NumberU64(), tail)
// }
// // Block bodies and receipts before the cutoff should be non-existent
// if num < cutoffBlock.NumberU64() {
// body := chain.GetBody(hash)
// if body != nil {
// t.Fatalf("Unexpected block body: %d, cutoff: %d", num, cutoffBlock.NumberU64())
// }
// receipts := chain.GetReceiptsByHash(hash)
// if receipts != nil {
// t.Fatalf("Unexpected block receipts: %d, cutoff: %d", num, cutoffBlock.NumberU64())
// }
// } else {
// body := chain.GetBody(hash)
// if body == nil || len(body.Transactions) != 1 {
// t.Fatalf("Missed block body: %d, cutoff: %d", num, cutoffBlock.NumberU64())
// }
// receipts := chain.GetReceiptsByHash(hash)
// if receipts == nil || len(receipts) != 1 {
// t.Fatalf("Missed block receipts: %d, cutoff: %d", num, cutoffBlock.NumberU64())
// }
// }
// }
// }
// Configure and generate a sample block chain
var (
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000000000)
gspec = &Genesis{
Config: params.TestChainConfig,
Alloc: types.GenesisAlloc{address: {Balance: funds}},
BaseFee: big.NewInt(params.InitialBaseFee),
}
signer = types.LatestSigner(gspec.Config)
engine = beacon.New(ethash.NewFaker())
)
_, blocks, receipts := GenerateChainWithGenesis(gspec, engine, chainLength, func(i int, block *BlockGen) {
block.SetCoinbase(common.Address{0x00})
tx, err := types.SignTx(types.NewTransaction(block.TxNonce(address), common.Address{0x00}, big.NewInt(1000), params.TxGas, block.header.BaseFee, nil), signer, key)
if err != nil {
panic(err)
}
block.AddTx(tx)
})
// Run the actual tests.
t.Run("cutoff-32/ancientLimit-32", func(t *testing.T) {
// cutoff = 32, ancientLimit = 32
testInsertChainWithCutoff(t, 32, 32, gspec, blocks, receipts)
})
t.Run("cutoff-32/ancientLimit-64", func(t *testing.T) {
// cutoff = 32, ancientLimit = 64 (entire chain in ancient)
testInsertChainWithCutoff(t, 32, 64, gspec, blocks, receipts)
})
t.Run("cutoff-32/ancientLimit-64", func(t *testing.T) {
// cutoff = 32, ancientLimit = 65 (64 blocks in ancient, 1 block in live)
testInsertChainWithCutoff(t, 32, 65, gspec, blocks, receipts)
})
}
func testInsertChainWithCutoff(t *testing.T, cutoff uint64, ancientLimit uint64, genesis *Genesis, blocks []*types.Block, receipts []types.Receipts) {
// log.SetDefault(log.NewLogger(log.NewTerminalHandlerWithLevel(os.Stderr, log.LevelDebug, true)))
// Add a known pruning point for the duration of the test.
ghash := genesis.ToBlock().Hash()
cutoffBlock := blocks[cutoff-1]
history.PrunePoints[ghash] = &history.PrunePoint{
BlockNumber: cutoffBlock.NumberU64(),
BlockHash: cutoffBlock.Hash(),
}
defer func() {
delete(history.PrunePoints, ghash)
}()
// Enable pruning in cache config.
config := DefaultCacheConfigWithScheme(rawdb.PathScheme)
config.ChainHistoryMode = history.KeepPostMerge
db, _ := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), "", "", false)
defer db.Close()
chain, _ := NewBlockChain(db, DefaultCacheConfigWithScheme(rawdb.PathScheme), genesis, nil, beacon.New(ethash.NewFaker()), vm.Config{}, nil)
defer chain.Stop()
var (
headersBefore []*types.Header
blocksAfter []*types.Block
receiptsAfter []types.Receipts
)
for i, b := range blocks {
if b.NumberU64() < cutoffBlock.NumberU64() {
headersBefore = append(headersBefore, b.Header())
} else {
blocksAfter = append(blocksAfter, b)
receiptsAfter = append(receiptsAfter, receipts[i])
}
}
if n, err := chain.InsertHeadersBeforeCutoff(headersBefore); err != nil {
t.Fatalf("failed to insert headers before cutoff %d: %v", n, err)
}
if n, err := chain.InsertReceiptChain(blocksAfter, receiptsAfter, ancientLimit); err != nil {
t.Fatalf("failed to insert receipt %d: %v", n, err)
}
headSnap := chain.CurrentSnapBlock()
if headSnap.Hash() != blocks[len(blocks)-1].Hash() {
t.Errorf("head snap block #%d: header mismatch: want: %v, got: %v", headSnap.Number, blocks[len(blocks)-1].Hash(), headSnap.Hash())
}
headHeader := chain.CurrentHeader()
if headHeader.Hash() != blocks[len(blocks)-1].Hash() {
t.Errorf("head header #%d: header mismatch: want: %v, got: %v", headHeader.Number, blocks[len(blocks)-1].Hash(), headHeader.Hash())
}
headBlock := chain.CurrentBlock()
if headBlock.Hash() != ghash {
t.Errorf("head block #%d: header mismatch: want: %v, got: %v", headBlock.Number, ghash, headBlock.Hash())
}
// Iterate over all chain data components, and cross reference
for i := 0; i < len(blocks); i++ {
num, hash := blocks[i].NumberU64(), blocks[i].Hash()
// Canonical headers should be visible regardless of cutoff
header := chain.GetHeaderByNumber(num)
if header.Hash() != hash {
t.Errorf("block #%d: header mismatch: want: %v, got: %v", num, hash, header.Hash())
}
tail, err := db.Tail()
if err != nil {
t.Fatalf("Failed to get chain tail, %v", err)
}
if tail != cutoffBlock.NumberU64() {
t.Fatalf("Unexpected chain tail, want: %d, got: %d", cutoffBlock.NumberU64(), tail)
}
// Block bodies and receipts before the cutoff should be non-existent
if num < cutoffBlock.NumberU64() {
body := chain.GetBody(hash)
if body != nil {
t.Fatalf("Unexpected block body: %d, cutoff: %d", num, cutoffBlock.NumberU64())
}
receipts := chain.GetReceiptsByHash(hash)
if receipts != nil {
t.Fatalf("Unexpected block receipts: %d, cutoff: %d", num, cutoffBlock.NumberU64())
}
} else {
body := chain.GetBody(hash)
if body == nil || len(body.Transactions) != 1 {
t.Fatalf("Missed block body: %d, cutoff: %d", num, cutoffBlock.NumberU64())
}
receipts := chain.GetReceiptsByHash(hash)
if receipts == nil || len(receipts) != 1 {
t.Fatalf("Missed block receipts: %d, cutoff: %d", num, cutoffBlock.NumberU64())
}
}
}
}