From 93bb4057fb0dc2eb0c302249c67fcf07e206e578 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Mon, 14 Apr 2025 14:29:14 +0200 Subject: [PATCH] core: restore test --- core/blockchain_test.go | 244 ++++++++++++++++++++++------------------ 1 file changed, 133 insertions(+), 111 deletions(-) diff --git a/core/blockchain_test.go b/core/blockchain_test.go index c97026c791..289eff0a8f 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -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()) + } + } + } +}