Skip to content

Commit b7f304f

Browse files
Revert "core, eth/downloader: implement pruning mode sync (ethereum#31414)"
This reverts commit 90d44e7.
1 parent 8838ccf commit b7f304f

File tree

14 files changed

+278
-459
lines changed

14 files changed

+278
-459
lines changed

cmd/geth/chaincmd.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ func importHistory(ctx *cli.Context) error {
482482
network = networks[0]
483483
}
484484

485-
if err := utils.ImportHistory(chain, dir, network); err != nil {
485+
if err := utils.ImportHistory(chain, db, dir, network); err != nil {
486486
return err
487487
}
488488
fmt.Printf("Import done in %v\n", time.Since(start))

cmd/utils/cmd.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -268,9 +268,8 @@ func readList(filename string) ([]string, error) {
268268
}
269269

270270
// ImportHistory imports Era1 files containing historical block information,
271-
// starting from genesis. The assumption is held that the provided chain
272-
// segment in Era1 file should all be canonical and verified.
273-
func ImportHistory(chain *core.BlockChain, dir string, network string) error {
271+
// starting from genesis.
272+
func ImportHistory(chain *core.BlockChain, db ethdb.Database, dir string, network string) error {
274273
if chain.CurrentSnapBlock().Number.BitLen() != 0 {
275274
return errors.New("history import only supported when starting from genesis")
276275
}
@@ -332,6 +331,11 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error {
332331
if err != nil {
333332
return fmt.Errorf("error reading receipts %d: %w", it.Number(), err)
334333
}
334+
if status, err := chain.HeaderChain().InsertHeaderChain([]*types.Header{block.Header()}, start); err != nil {
335+
return fmt.Errorf("error inserting header %d: %w", it.Number(), err)
336+
} else if status != core.CanonStatTy {
337+
return fmt.Errorf("error inserting header %d, not canon: %v", it.Number(), status)
338+
}
335339
if _, err := chain.InsertReceiptChain([]*types.Block{block}, []types.Receipts{receipts}, 2^64-1); err != nil {
336340
return fmt.Errorf("error inserting body %d: %w", it.Number(), err)
337341
}

cmd/utils/history_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ func TestHistoryImportAndExport(t *testing.T) {
171171
if err != nil {
172172
t.Fatalf("unable to initialize chain: %v", err)
173173
}
174-
if err := ImportHistory(imported, dir, "mainnet"); err != nil {
174+
if err := ImportHistory(imported, db2, dir, "mainnet"); err != nil {
175175
t.Fatalf("failed to import chain: %v", err)
176176
}
177177
if have, want := imported.CurrentHeader(), chain.CurrentHeader(); have.Hash() != want.Hash() {

core/blockchain.go

Lines changed: 50 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,10 @@ type CacheConfig struct {
180180
SnapshotNoBuild bool // Whether the background generation is allowed
181181
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
182182

183+
ChainHistoryMode history.HistoryMode
183184
// This defines the cutoff block for history expiry.
184185
// Blocks before this number may be unavailable in the chain database.
185-
ChainHistoryMode history.HistoryMode
186+
HistoryPruningCutoff uint64
186187
}
187188

188189
// triedbConfig derives the configures for trie database.
@@ -391,10 +392,10 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
391392
bc.processor = NewStateProcessor(chainConfig, bc.hc, bc)
392393

393394
genesisHeader := bc.GetHeaderByNumber(0)
394-
if genesisHeader == nil {
395+
bc.genesisBlock = types.NewBlockWithHeader(genesisHeader)
396+
if bc.genesisBlock == nil {
395397
return nil, ErrNoGenesis
396398
}
397-
bc.genesisBlock = types.NewBlockWithHeader(genesisHeader)
398399

399400
bc.currentBlock.Store(nil)
400401
bc.currentSnapBlock.Store(nil)
@@ -1446,6 +1447,7 @@ func (bc *BlockChain) stopWithoutSaving() {
14461447
// the mutex should become available quickly. It cannot be taken again after Close has
14471448
// returned.
14481449
bc.chainmu.Close()
1450+
bc.wg.Wait()
14491451
}
14501452

14511453
// Stop stops the blockchain service. If any imports are currently in progress
@@ -1534,36 +1536,45 @@ const (
15341536
SideStatTy
15351537
)
15361538

1537-
// InsertReceiptChain inserts a batch of blocks along with their receipts into
1538-
// the database. Unlike InsertChain, this function does not verify the state root
1539-
// in the blocks. It is used exclusively for snap sync. All the inserted blocks
1540-
// will be regarded as canonical, chain reorg is not supported.
1541-
//
1542-
// The optional ancientLimit can also be specified and chain segment before that
1543-
// will be directly stored in the ancient, getting rid of the chain migration.
1539+
// InsertReceiptChain attempts to complete an already existing header chain with
1540+
// transaction and receipt data.
15441541
func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts, ancientLimit uint64) (int, error) {
1545-
// Verify the supplied headers before insertion without lock
1546-
var headers []*types.Header
1547-
for _, block := range blockChain {
1548-
headers = append(headers, block.Header())
1542+
// We don't require the chainMu here since we want to maximize the
1543+
// concurrency of header insertion and receipt insertion.
1544+
bc.wg.Add(1)
1545+
defer bc.wg.Done()
15491546

1550-
// Here we also validate that blob transactions in the block do not
1551-
// contain a sidecar. While the sidecar does not affect the block hash
1552-
// or tx hash, sending blobs within a block is not allowed.
1547+
var (
1548+
ancientBlocks, liveBlocks types.Blocks
1549+
ancientReceipts, liveReceipts []types.Receipts
1550+
)
1551+
// Do a sanity check that the provided chain is actually ordered and linked
1552+
for i, block := range blockChain {
1553+
if i != 0 {
1554+
prev := blockChain[i-1]
1555+
if block.NumberU64() != prev.NumberU64()+1 || block.ParentHash() != prev.Hash() {
1556+
log.Error("Non contiguous receipt insert",
1557+
"number", block.Number(), "hash", block.Hash(), "parent", block.ParentHash(),
1558+
"prevnumber", prev.Number(), "prevhash", prev.Hash())
1559+
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x..], item %d is #%d [%x..] (parent [%x..])",
1560+
i-1, prev.NumberU64(), prev.Hash().Bytes()[:4],
1561+
i, block.NumberU64(), block.Hash().Bytes()[:4], block.ParentHash().Bytes()[:4])
1562+
}
1563+
}
1564+
if block.NumberU64() <= ancientLimit {
1565+
ancientBlocks, ancientReceipts = append(ancientBlocks, block), append(ancientReceipts, receiptChain[i])
1566+
} else {
1567+
liveBlocks, liveReceipts = append(liveBlocks, block), append(liveReceipts, receiptChain[i])
1568+
}
1569+
1570+
// Here we also validate that blob transactions in the block do not contain a sidecar.
1571+
// While the sidecar does not affect the block hash / tx hash, sending blobs within a block is not allowed.
15531572
for txIndex, tx := range block.Transactions() {
15541573
if tx.Type() == types.BlobTxType && tx.BlobTxSidecar() != nil {
15551574
return 0, fmt.Errorf("block #%d contains unexpected blob sidecar in tx at index %d", block.NumberU64(), txIndex)
15561575
}
15571576
}
15581577
}
1559-
if n, err := bc.hc.ValidateHeaderChain(headers); err != nil {
1560-
return n, err
1561-
}
1562-
// Hold the mutation lock
1563-
if !bc.chainmu.TryLock() {
1564-
return 0, errChainStopped
1565-
}
1566-
defer bc.chainmu.Unlock()
15671578

15681579
var (
15691580
stats = struct{ processed, ignored int32 }{}
@@ -1611,8 +1622,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
16111622
// this function only accepts canonical chain data. All side chain will be reverted
16121623
// eventually.
16131624
writeAncient := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
1614-
// Ensure genesis is in the ancient store
1615-
if blockChain[0].NumberU64() == 1 {
1625+
first := blockChain[0]
1626+
last := blockChain[len(blockChain)-1]
1627+
1628+
// Ensure genesis is in ancients.
1629+
if first.NumberU64() == 1 {
16161630
if frozen, _ := bc.db.Ancients(); frozen == 0 {
16171631
td := bc.genesisBlock.Difficulty()
16181632
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, []types.Receipts{nil}, td)
@@ -1728,12 +1742,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
17281742
return 0, nil
17291743
}
17301744

1731-
// writeLive writes the blockchain and corresponding receipt chain to the active store.
1732-
//
1733-
// Notably, in different snap sync cycles, the supplied chain may partially reorganize
1734-
// existing local chain segments (reorg around the chain tip). The reorganized part
1735-
// will be included in the provided chain segment, and stale canonical markers will be
1736-
// silently rewritten. Therefore, no explicit reorg logic is needed.
1745+
// writeLive writes blockchain and corresponding receipt chain into active store.
17371746
writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
17381747
headers := make([]*types.Header, 0, len(blockChain))
17391748
var (
@@ -1766,8 +1775,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
17661775
}
17671776
}
17681777
// Write all the data out into the database
1769-
rawdb.WriteCanonicalHash(batch, block.Hash(), block.NumberU64())
1770-
rawdb.WriteBlock(batch, block)
1778+
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
17711779
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
17721780

17731781
// Write everything belongs to the blocks into the database. So that
@@ -1800,22 +1808,18 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
18001808
return 0, nil
18011809
}
18021810

1803-
// Split the supplied blocks into two groups, according to the
1804-
// given ancient limit.
1805-
index := sort.Search(len(blockChain), func(i int) bool {
1806-
return blockChain[i].NumberU64() >= ancientLimit
1807-
})
1808-
if index > 0 {
1809-
if n, err := writeAncient(blockChain[:index], receiptChain[:index]); err != nil {
1811+
// Write downloaded chain data and corresponding receipt chain data
1812+
if len(ancientBlocks) > 0 {
1813+
if n, err := writeAncient(ancientBlocks, ancientReceipts); err != nil {
18101814
if err == errInsertionInterrupted {
18111815
return 0, nil
18121816
}
18131817

18141818
return n, err
18151819
}
18161820
}
1817-
if index != len(blockChain) {
1818-
if n, err := writeLive(blockChain[index:], receiptChain[index:]); err != nil {
1821+
if len(liveBlocks) > 0 {
1822+
if n, err := writeLive(liveBlocks, liveReceipts); err != nil {
18191823
if err == errInsertionInterrupted {
18201824
return 0, nil
18211825
}
@@ -1837,6 +1841,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
18371841
}
18381842

18391843
log.Debug("Imported new block receipts", context...)
1844+
18401845
return 0, nil
18411846
}
18421847

@@ -3347,6 +3352,7 @@ func (bc *BlockChain) InsertHeaderChain(chain []*types.Header) (int, error) {
33473352
if i, err := bc.hc.ValidateHeaderChain(chain); err != nil {
33483353
return i, err
33493354
}
3355+
33503356
if !bc.chainmu.TryLock() {
33513357
return 0, errChainStopped
33523358
}
@@ -3359,74 +3365,6 @@ func (bc *BlockChain) GetChainConfig() *params.ChainConfig {
33593365
return bc.chainConfig
33603366
}
33613367

3362-
// InsertHeadersBeforeCutoff inserts the given headers into the ancient store
3363-
// as they are claimed older than the configured chain cutoff point. All the
3364-
// inserted headers are regarded as canonical and chain reorg is not supported.
3365-
func (bc *BlockChain) InsertHeadersBeforeCutoff(headers []*types.Header) (int, error) {
3366-
if len(headers) == 0 {
3367-
return 0, nil
3368-
}
3369-
// TODO(rjl493456442): Headers before the configured cutoff have already
3370-
// been verified by the hash of cutoff header. Theoretically, header validation
3371-
// could be skipped here.
3372-
if n, err := bc.hc.ValidateHeaderChain(headers); err != nil {
3373-
return n, err
3374-
}
3375-
if !bc.chainmu.TryLock() {
3376-
return 0, errChainStopped
3377-
}
3378-
defer bc.chainmu.Unlock()
3379-
3380-
// Initialize the ancient store with genesis block if it's empty.
3381-
var (
3382-
frozen, _ = bc.db.Ancients()
3383-
first = headers[0].Number.Uint64()
3384-
)
3385-
if first == 1 && frozen == 0 {
3386-
_, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil})
3387-
if err != nil {
3388-
log.Error("Error writing genesis to ancients", "err", err)
3389-
return 0, err
3390-
}
3391-
log.Info("Wrote genesis to ancient store")
3392-
} else if frozen != first {
3393-
return 0, fmt.Errorf("headers are gapped with the ancient store, first: %d, ancient: %d", first, frozen)
3394-
}
3395-
3396-
// Write headers to the ancient store, with block bodies and receipts set to nil
3397-
// to ensure consistency across tables in the freezer.
3398-
_, err := rawdb.WriteAncientHeaderChain(bc.db, headers)
3399-
if err != nil {
3400-
return 0, err
3401-
}
3402-
if err := bc.db.Sync(); err != nil {
3403-
return 0, err
3404-
}
3405-
// Write hash to number mappings
3406-
batch := bc.db.NewBatch()
3407-
for _, header := range headers {
3408-
rawdb.WriteHeaderNumber(batch, header.Hash(), header.Number.Uint64())
3409-
}
3410-
// Write head header and head snap block flags
3411-
last := headers[len(headers)-1]
3412-
rawdb.WriteHeadHeaderHash(batch, last.Hash())
3413-
rawdb.WriteHeadFastBlockHash(batch, last.Hash())
3414-
if err := batch.Write(); err != nil {
3415-
return 0, err
3416-
}
3417-
// Truncate the useless chain segment (zero bodies and receipts) in the
3418-
// ancient store.
3419-
if _, err := bc.db.TruncateTail(last.Number.Uint64() + 1); err != nil {
3420-
return 0, err
3421-
}
3422-
// Last step update all in-memory markers
3423-
bc.hc.currentHeader.Store(last)
3424-
bc.currentSnapBlock.Store(last)
3425-
headHeaderGauge.Update(last.Number.Int64())
3426-
headFastBlockGauge.Update(last.Number.Int64())
3427-
return 0, nil
3428-
}
3429-
34303368
// SetBlockValidatorAndProcessorForTesting sets the current validator and processor.
34313369
// This method can be used to force an invalid blockchain to be verified for tests.
34323370
// This method is unsafe and should only be used before block import starts.

0 commit comments

Comments
 (0)