diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index 5b7fb5e90..92f59b34c 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -17,7 +17,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/cmd/sentry/sentry" - "github.com/ledgerwatch/erigon/common/dbutils" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core" @@ -483,7 +482,7 @@ func stageHeaders(db kv.RwDB, ctx context.Context) error { return fmt.Errorf("re-read Bodies progress: %w", err) } { // hard-unwind stage_body also - if err := rawdb.DeleteNewBlocks(tx, progress+1); err != nil { + if err := rawdb.TruncateBlocks(tx, progress+1); err != nil { return err } progressBodies, err := stages.GetStageProgress(tx, stages.Bodies) @@ -497,14 +496,10 @@ func stageHeaders(db kv.RwDB, ctx context.Context) error { } } // remove all canonical markers from this point - if err := tx.ForEach(kv.HeaderCanonical, dbutils.EncodeBlockNumber(progress+1), func(k, v []byte) error { - return tx.Delete(kv.HeaderCanonical, k, nil) - }); err != nil { + if err = rawdb.TruncateCanonicalHash(tx, progress+1); err != nil { return err } - if err := tx.ForEach(kv.HeaderTD, dbutils.EncodeBlockNumber(progress+1), func(k, v []byte) error { - return tx.Delete(kv.HeaderTD, k, nil) - }); err != nil { + if err = rawdb.TruncateTd(tx, progress+1); err != nil { return err } hash, err := rawdb.ReadCanonicalHash(tx, progress-1) diff --git a/core/genesis_test.go b/core/genesis_test.go index 575cfea0f..799a6f216 100644 --- a/core/genesis_test.go +++ b/core/genesis_test.go @@ -1,16 +1,48 @@ package core import ( + "context" + "testing" + + "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/params/networkname" "github.com/stretchr/testify/require" - "testing" ) func TestDefaultBSCGenesisBlock(t *testing.T) { - genesis := DefaultBSCGenesisBlock() - db := memdb.New() - _, block, err := CommitGenesisBlock(db, genesis) - require.NoError(t, err) - require.Equal(t, block.Hash(), params.BSCGenesisHash) + db := memdb.NewTestDB(t) + check := func(network string) { + genesis := DefaultGenesisBlockByChainName(network) + tx, err := db.BeginRw(context.Background()) + if err != nil { + t.Fatal(err) + } + defer tx.Rollback() + _, block, err := WriteGenesisBlock(tx, genesis) + require.NoError(t, err) + expect := params.GenesisHashByChainName(network) + require.NotNil(t, expect, network) + require.Equal(t, block.Hash().Bytes(), expect.Bytes(), network) + } + for _, network := range networkname.All { + check(network) + } +} + +func TestCommitGenesisIdempotency(t *testing.T) { + _, tx := memdb.NewTestTx(t) + genesis := DefaultGenesisBlockByChainName(networkname.MainnetChainName) + _, _, err := WriteGenesisBlock(tx, genesis) + require.NoError(t, err) + seq, err := tx.ReadSequence(kv.EthTx) + require.NoError(t, err) + require.Equal(t, uint64(2), seq) + + _, _, err = WriteGenesisBlock(tx, genesis) + require.NoError(t, err) + seq, err = tx.ReadSequence(kv.EthTx) + require.NoError(t, err) + require.Equal(t, uint64(2), seq) } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index 021c1a45d..a4995f497 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -26,8 +26,6 @@ import ( "time" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/cmd/rpcdaemon/interfaces" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/dbutils" @@ -35,6 +33,7 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/ethdb/cbor" "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/log/v3" ) // ReadCanonicalHash retrieves the hash assigned to a canonical block number. @@ -57,10 +56,12 @@ func WriteCanonicalHash(db kv.Putter, hash common.Hash, number uint64) error { return nil } -// DeleteCanonicalHash removes the number to hash canonical mapping. -func DeleteCanonicalHash(db kv.Deleter, number uint64) error { - if err := db.Delete(kv.HeaderCanonical, dbutils.EncodeBlockNumber(number), nil); err != nil { - return fmt.Errorf("failed to delete number to hash mapping: %w", err) +// TruncateCanonicalHash removes all the number to hash canonical mapping from block number N +func TruncateCanonicalHash(tx kv.RwTx, blockFrom uint64) error { + if err := tx.ForEach(kv.HeaderCanonical, dbutils.EncodeBlockNumber(blockFrom), func(k, _ []byte) error { + return tx.Delete(kv.HeaderCanonical, k, nil) + }); err != nil { + return fmt.Errorf("TruncateCanonicalHash: %w", err) } return nil } @@ -254,8 +255,8 @@ func WriteHeader(db kv.Putter, header *types.Header) { } } -// DeleteHeader removes all block header data associated with a hash. -func DeleteHeader(db kv.Deleter, hash common.Hash, number uint64) { +// deleteHeader - dangerous, use DeleteAncientBlocks/TruncateBlocks methods +func deleteHeader(db kv.Deleter, hash common.Hash, number uint64) { if err := db.Delete(kv.Headers, dbutils.HeaderKey(number, hash), nil); err != nil { log.Crit("Failed to delete header", "err", err) } @@ -617,8 +618,8 @@ func WriteSenders(db kv.Putter, hash common.Hash, number uint64, senders []commo return nil } -// DeleteBody removes all block body data associated with a hash. -func DeleteBody(db kv.Deleter, hash common.Hash, number uint64) { +// deleteBody removes all block body data associated with a hash. +func deleteBody(db kv.Deleter, hash common.Hash, number uint64) { if err := db.Delete(kv.BlockBody, dbutils.BlockBodyKey(number, hash), nil); err != nil { log.Crit("Failed to delete block body", "err", err) } @@ -797,10 +798,12 @@ func WriteTd(db kv.Putter, hash common.Hash, number uint64, td *big.Int) error { return nil } -// DeleteTd removes all block total difficulty data associated with a hash. -func DeleteTd(db kv.Deleter, hash common.Hash, number uint64) error { - if err := db.Delete(kv.HeaderTD, dbutils.HeaderKey(number, hash), nil); err != nil { - return fmt.Errorf("failed to delete block total difficulty: %w", err) +// TruncateTd removes all block total difficulty from block number N +func TruncateTd(tx kv.RwTx, blockFrom uint64) error { + if err := tx.ForEach(kv.HeaderTD, dbutils.EncodeBlockNumber(blockFrom), func(k, _ []byte) error { + return tx.Delete(kv.HeaderTD, k, nil) + }); err != nil { + return fmt.Errorf("TruncateTd: %w", err) } return nil } @@ -960,25 +963,9 @@ func AppendReceipts(tx kv.StatelessWriteTx, blockNumber uint64, receipts types.R return nil } -// DeleteReceipts removes all receipt data associated with a block hash. -func DeleteReceipts(db kv.RwTx, number uint64) error { - if err := db.Delete(kv.Receipts, dbutils.EncodeBlockNumber(number), nil); err != nil { - return fmt.Errorf("receipts delete failed: %d, %w", number, err) - } - - prefix := make([]byte, 8) - binary.BigEndian.PutUint64(prefix, number) - if err := db.ForPrefix(kv.Log, prefix, func(k, v []byte) error { - return db.Delete(kv.Log, k, nil) - }); err != nil { - return err - } - return nil -} - -// DeleteNewerReceipts removes all receipt for given block number or newer -func DeleteNewerReceipts(db kv.RwTx, number uint64) error { - if err := db.ForEach(kv.Receipts, dbutils.EncodeBlockNumber(number), func(k, v []byte) error { +// TruncateReceipts removes all receipt for given block number or newer +func TruncateReceipts(db kv.RwTx, number uint64) error { + if err := db.ForEach(kv.Receipts, dbutils.EncodeBlockNumber(number), func(k, _ []byte) error { return db.Delete(kv.Receipts, k, nil) }); err != nil { return err @@ -986,7 +973,7 @@ func DeleteNewerReceipts(db kv.RwTx, number uint64) error { from := make([]byte, 8) binary.BigEndian.PutUint64(from, number) - if err := db.ForEach(kv.Log, from, func(k, v []byte) error { + if err := db.ForEach(kv.Log, from, func(k, _ []byte) error { return db.Delete(kv.Log, k, nil) }); err != nil { return err @@ -1099,22 +1086,17 @@ func DeleteAncientBlocks(db kv.RwTx, blockTo uint64, blocksDeleteLimit int) erro } defer c.Close() - var stopAtBlock, firstNonGenesisInDB uint64 - { - k, _, err := c.First() - if err != nil { - return err - } - firstNonGenesisInDB = binary.BigEndian.Uint64(k) - if firstNonGenesisInDB == 0 { // keep genesis in DB - k, _, err := c.Next() - if err != nil { - return err - } - firstNonGenesisInDB = binary.BigEndian.Uint64(k) - } - stopAtBlock = min(blockTo, firstNonGenesisInDB+uint64(blocksDeleteLimit)) + // find first non-genesis block + k, _, err := c.Seek(dbutils.EncodeBlockNumber(1)) + if err != nil { + return err } + if k == nil { //nothing to delete + return nil + } + blockFrom := binary.BigEndian.Uint64(k) + stopAtBlock := min(blockTo, blockFrom+uint64(blocksDeleteLimit)) + for k, _, err := c.Current(); k != nil; k, _, err = c.Next() { if err != nil { return err @@ -1124,38 +1106,7 @@ func DeleteAncientBlocks(db kv.RwTx, blockTo uint64, blocksDeleteLimit int) erro if n >= stopAtBlock { // [from, to) break } - - canonicalHash, err := ReadCanonicalHash(db, n) - if err != nil { - return err - } - isCanonical := bytes.Equal(k[8:], canonicalHash[:]) - - b, err := ReadBodyForStorageByKey(db, k) - if err != nil { - return err - } - if b == nil { - return fmt.Errorf("DeleteAncientBlocks: block body not found for block %d", n) - } - txIDBytes := make([]byte, 8) - for txID := b.BaseTxId; txID < b.BaseTxId+uint64(b.TxAmount); txID++ { - binary.BigEndian.PutUint64(txIDBytes, txID) - bucket := kv.EthTx - if !isCanonical { - bucket = kv.NonCanonicalTxs - } - if err := db.Delete(bucket, txIDBytes, nil); err != nil { - return err - } - } - if err := db.Delete(kv.Headers, k, nil); err != nil { - return err - } - if err := db.Delete(kv.BlockBody, k, nil); err != nil { - return err - } - if err := db.Delete(kv.Senders, k, nil); err != nil { + if err := delBlock(db, k, true); err != nil { return err } } @@ -1163,65 +1114,125 @@ func DeleteAncientBlocks(db kv.RwTx, blockTo uint64, blocksDeleteLimit int) erro return nil } -func DeleteNewBlocks(db kv.RwTx, blockFrom uint64) error { - c, err := db.Cursor(kv.Headers) +func lastKey(tx kv.Tx, table string) ([]byte, error) { + c, err := tx.Cursor(table) + if err != nil { + return nil, err + } + defer c.Close() + k, _, err := c.Last() + if err != nil { + return nil, err + } + return k, nil +} + +// delBlock - low-level method to delete 1 block by key +// keeps genesis in db: [1, to) +// doesn't delete Reciepts +// doesn't delete Canonical markers +// doesn't delete TotalDifficulty +// keepSequence - can track decrement sequnces of Canonical and Non-Canonical txs +func delBlock(tx kv.RwTx, k []byte, keepSequence bool) error { + n := binary.BigEndian.Uint64(k) + canonicalHash, err := ReadCanonicalHash(tx, n) + if err != nil { + return err + } + isCanonical := bytes.Equal(k[8:], canonicalHash[:]) + b, err := ReadBodyForStorageByKey(tx, k) + if err != nil { + return err + } + if b == nil { + return fmt.Errorf("DeleteAncientBlocks: block body not found for block %d", n) + } + txIDBytes := make([]byte, 8) + for txID := b.BaseTxId; txID < b.BaseTxId+uint64(b.TxAmount); txID++ { + binary.BigEndian.PutUint64(txIDBytes, txID) + bucket := kv.EthTx + if !isCanonical { + bucket = kv.NonCanonicalTxs + } + + if !keepSequence { + lastK, err := lastKey(tx, bucket) + if err != nil { + return err + } + seq, err := tx.ReadSequence(bucket) + if err != nil { + return err + } + if lastK != nil && binary.BigEndian.Uint64(lastK) > seq { + return fmt.Errorf("please delete blocks from newest to older. txnId: %d > %d", binary.BigEndian.Uint64(lastK), seq) + } + if seq > b.BaseTxId+uint64(b.TxAmount) { + return fmt.Errorf("please delete blocks from newest to older. seq: %d > %d+%d", seq, b.BaseTxId, uint64(b.TxAmount)) + } + if err := ResetSequence(tx, bucket, b.BaseTxId); err != nil { + return err + } + } + + if err := tx.Delete(bucket, txIDBytes, nil); err != nil { + return err + } + } + if err := tx.Delete(kv.Headers, k, nil); err != nil { + return err + } + if err := tx.Delete(kv.BlockBody, k, nil); err != nil { + return err + } + if err := tx.Delete(kv.Senders, k, nil); err != nil { + return err + } + + if !keepSequence { + bucket := kv.EthTx + if !isCanonical { + bucket = kv.NonCanonicalTxs + } + lastK, err := lastKey(tx, bucket) + if err != nil { + return err + } + seq, err := tx.ReadSequence(bucket) + if err != nil { + return err + } + if lastK != nil && binary.BigEndian.Uint64(lastK) > seq { + return fmt.Errorf("end: please delete blocks from newest to older. txnId: %d > %d", binary.BigEndian.Uint64(lastK), seq) + } + if seq > b.BaseTxId+uint64(b.TxAmount) { + return fmt.Errorf("end: please delete blocks from newest to older. seq: %d > %d+%d", seq, b.BaseTxId, uint64(b.TxAmount)) + } + } + return nil +} + +// TruncateBlocks - delete block >= blockFrom +func TruncateBlocks(tx kv.RwTx, blockFrom uint64) error { + c, err := tx.Cursor(kv.Headers) if err != nil { return err } defer c.Close() - - for k, _, err := c.Seek(dbutils.EncodeBlockNumber(blockFrom)); k != nil; k, _, err = c.Next() { + if blockFrom < 1 { //protect genesis + blockFrom = 1 + } + for k, _, err := c.Last(); k != nil; k, _, err = c.Prev() { if err != nil { return err } n := binary.BigEndian.Uint64(k) - - canonicalHash, err := ReadCanonicalHash(db, n) - if err != nil { + if n < blockFrom { // [from, to) + break + } + if err := delBlock(tx, k, false); err != nil { return err } - isCanonical := bytes.Equal(k[8:], canonicalHash[:]) - - b, err := ReadBodyForStorageByKey(db, k) - if err != nil { - return err - } - if b != nil { // b == nil means body were marked as non-canonical already - txIDBytes := make([]byte, 8) - for txID := b.BaseTxId; txID < b.BaseTxId+uint64(b.TxAmount); txID++ { - binary.BigEndian.PutUint64(txIDBytes, txID) - bucket := kv.EthTx - if !isCanonical { - bucket = kv.NonCanonicalTxs - } - if err := db.Delete(bucket, txIDBytes, nil); err != nil { - return err - } - } - } - if err := db.Delete(kv.Headers, k, nil); err != nil { - return err - } - if err := db.Delete(kv.BlockBody, k, nil); err != nil { - return err - } - if err := db.Delete(kv.Senders, k, nil); err != nil { - return err - } - } - - return nil -} - -// DeleteBlock removes all block data associated with a hash. -func DeleteBlock(db kv.RwTx, hash common.Hash, number uint64) error { - if err := DeleteReceipts(db, number); err != nil { - return err - } - DeleteHeader(db, hash, number) - DeleteBody(db, hash, number) - if err := DeleteTd(db, hash, number); err != nil { - return err } return nil } diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index 7f49659c0..f1d96e81d 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -61,7 +61,7 @@ func TestHeaderStorage(t *testing.T) { } } // Delete the header and verify the execution - DeleteHeader(tx, header.Hash(), header.Number.Uint64()) + deleteHeader(tx, header.Hash(), header.Number.Uint64()) if entry := ReadHeader(tx, header.Hash(), header.Number.Uint64()); entry != nil { t.Fatalf("Deleted header returned: %v", entry) } @@ -116,7 +116,7 @@ func TestBodyStorage(t *testing.T) { } } // Delete the body and verify the execution - DeleteBody(tx, hash, 0) + deleteBody(tx, hash, 0) if entry := ReadCanonicalBodyWithTransactions(tx, hash, 0); entry != nil { t.Fatalf("Deleted body returned: %v", entry) } @@ -128,6 +128,7 @@ func TestBlockStorage(t *testing.T) { // Create a test block to move around the database and make sure it's really new block := types.NewBlockWithHeader(&types.Header{ + Number: big.NewInt(1), Extra: []byte("test block"), UncleHash: types.EmptyUncleHash, TxHash: types.EmptyRootHash, @@ -157,15 +158,21 @@ func TestBlockStorage(t *testing.T) { } else if entry.Hash() != block.Hash() { t.Fatalf("Retrieved header mismatch: have %v, want %v", entry, block.Header()) } + if err := TruncateBlocks(tx, 2); err != nil { + t.Fatal(err) + } if entry := ReadCanonicalBodyWithTransactions(tx, block.Hash(), block.NumberU64()); entry == nil { t.Fatalf("Stored body not found") } else if types.DeriveSha(types.Transactions(entry.Transactions)) != types.DeriveSha(block.Transactions()) || types.CalcUncleHash(entry.Uncles) != types.CalcUncleHash(block.Uncles()) { t.Fatalf("Retrieved body mismatch: have %v, want %v", entry, block.Body()) } // Delete the block and verify the execution - if err := DeleteBlock(tx, block.Hash(), block.NumberU64()); err != nil { - t.Fatalf("Could not delete block: %v", err) + if err := TruncateBlocks(tx, block.NumberU64()); err != nil { + t.Fatal(err) } + //if err := DeleteBlock(tx, block.Hash(), block.NumberU64()); err != nil { + // t.Fatalf("Could not delete block: %v", err) + //} if entry := ReadBlock(tx, block.Hash(), block.NumberU64()); entry != nil { t.Fatalf("Deleted block returned: %v", entry) } @@ -175,6 +182,14 @@ func TestBlockStorage(t *testing.T) { if entry := ReadCanonicalBodyWithTransactions(tx, block.Hash(), block.NumberU64()); entry != nil { t.Fatalf("Deleted body returned: %v", entry) } + + // write again and delete it as old one + if err := WriteBlock(tx, block); err != nil { + t.Fatalf("Could not write block: %v", err) + } + if err := DeleteAncientBlocks(tx, 0, 1); err != nil { + t.Fatal(err) + } } // Tests that partial block contents don't get reassembled into full blocks. @@ -193,7 +208,7 @@ func TestPartialBlockStorage(t *testing.T) { if entry := ReadBlock(tx, block.Hash(), block.NumberU64()); entry != nil { t.Fatalf("Non existent block returned: %v", entry) } - DeleteHeader(tx, block.Hash(), block.NumberU64()) + deleteHeader(tx, block.Hash(), block.NumberU64()) // Store a body and check that it's not recognized as a block if err := WriteBody(tx, block.Hash(), block.NumberU64(), block.Body()); err != nil { @@ -202,7 +217,7 @@ func TestPartialBlockStorage(t *testing.T) { if entry := ReadBlock(tx, block.Hash(), block.NumberU64()); entry != nil { t.Fatalf("Non existent block returned: %v", entry) } - DeleteBody(tx, block.Hash(), block.NumberU64()) + deleteBody(tx, block.Hash(), block.NumberU64()) // Store a header and a body separately and check reassembly WriteHeader(tx, header) @@ -245,7 +260,7 @@ func TestTdStorage(t *testing.T) { t.Fatalf("Retrieved TD mismatch: have %v, want %v", entry, td) } // Delete the TD and verify the execution - err = DeleteTd(tx, hash, 0) + err = TruncateTd(tx, 0) if err != nil { t.Fatalf("DeleteTd failed: %v", err) } @@ -286,7 +301,7 @@ func TestCanonicalMappingStorage(t *testing.T) { t.Fatalf("Retrieved canonical mapping mismatch: have %v, want %v", entry, hash) } // Delete the TD and verify the execution - err = DeleteCanonicalHash(tx, number) + err = TruncateCanonicalHash(tx, number) if err != nil { t.Fatalf("DeleteCanonicalHash failed: %v", err) } @@ -394,8 +409,8 @@ func TestBlockReceiptStorage(t *testing.T) { } } // Delete the body and ensure that the receipts are no longer returned (metadata can't be recomputed) - DeleteHeader(tx, hash, 0) - DeleteBody(tx, hash, 0) + deleteHeader(tx, hash, 0) + deleteBody(tx, hash, 0) b, senders, err = ReadBlockWithSenders(tx, hash, 0) require.NoError(err) require.Nil(b) @@ -409,7 +424,7 @@ func TestBlockReceiptStorage(t *testing.T) { WriteHeader(tx, header) // Sanity check that body alone without the receipt is a full purge require.NoError(WriteBody(tx, hash, 0, body)) - require.NoError(DeleteReceipts(tx, 0)) + require.NoError(TruncateReceipts(tx, 0)) b, senders, err = ReadBlockWithSenders(tx, hash, 0) require.NoError(err) require.NotNil(b) diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go index 9202ab507..002f066ff 100644 --- a/eth/stagedsync/stage_execute.go +++ b/eth/stagedsync/stage_execute.go @@ -519,7 +519,7 @@ func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, quit <-chan return err } - if err := rawdb.DeleteNewerReceipts(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.TruncateReceipts(tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("walking receipts: %w", err) } if err := rawdb.DeleteNewerEpochs(tx, u.UnwindPoint+1); err != nil { diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index 4aff122c5..b29a0db40 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -23,7 +23,6 @@ import ( "github.com/ledgerwatch/erigon/common/dbutils" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/ethdb/privateapi" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" @@ -871,11 +870,6 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx kv.RwTx, cfg HeadersCfg, te defer tx.Rollback() } // Delete canonical hashes that are being unwound - var headerProgress uint64 - headerProgress, err = stages.GetStageProgress(tx, stages.Headers) - if err != nil { - return err - } badBlock := u.BadBlock != (common.Hash{}) if badBlock { cfg.hd.ReportBadHeader(u.BadBlock) @@ -899,10 +893,8 @@ func HeadersUnwind(u *UnwindState, s *StageState, tx kv.RwTx, cfg HeadersCfg, te return fmt.Errorf("iterate over headers to mark bad headers: %w", err) } } - for blockHeight := headerProgress; blockHeight > u.UnwindPoint; blockHeight-- { - if err = rawdb.DeleteCanonicalHash(tx, blockHeight); err != nil { - return err - } + if err := rawdb.TruncateCanonicalHash(tx, u.UnwindPoint+1); err != nil { + return err } if badBlock { var maxTd big.Int diff --git a/migrations/txs_begin_end_test.go b/migrations/txs_begin_end_test.go index f15cc892a..148c4bcc4 100644 --- a/migrations/txs_begin_end_test.go +++ b/migrations/txs_begin_end_test.go @@ -41,8 +41,8 @@ func TestTxsBeginEnd(t *testing.T) { return err } + err = rawdb.TruncateCanonicalHash(tx, 7) for i := uint64(7); i < 10; i++ { - err = rawdb.DeleteCanonicalHash(tx, i) require.NoError(err) hash := common.Hash{0xa, byte(i)} err = writeRawBodyDeprecated(tx, hash, i, b) diff --git a/params/networkname/network_name.go b/params/networkname/network_name.go index 589321993..f6bb6887a 100644 --- a/params/networkname/network_name.go +++ b/params/networkname/network_name.go @@ -17,3 +17,21 @@ const ( MumbaiChainName = "mumbai" BorMainnetChainName = "bor-mainnet" ) + +var All = []string{ + MainnetChainName, + SepoliaChainName, + RopstenChainName, + RinkebyChainName, + GoerliChainName, + KilnDevnetChainName, + //DevChainName, + ErigonMineName, + SokolChainName, + FermionChainName, + BSCChainName, + ChapelChainName, + //RialtoChainName, + MumbaiChainName, + BorMainnetChainName, +}