mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core, core/rawdb, eth/sync: no tx indexing during snap sync
This commit is contained in:
parent
e5d5e09faa
commit
8b1664dac8
7 changed files with 74 additions and 143 deletions
|
|
@ -1155,14 +1155,13 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
// Ensure genesis is in ancients.
|
// Ensure genesis is in ancients.
|
||||||
if first.NumberU64() == 1 {
|
if first.NumberU64() == 1 {
|
||||||
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
if frozen, _ := bc.db.Ancients(); frozen == 0 {
|
||||||
b := bc.genesisBlock
|
|
||||||
td := bc.genesisBlock.Difficulty()
|
td := bc.genesisBlock.Difficulty()
|
||||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{b}, []types.Receipts{nil}, td)
|
writeSize, err := rawdb.WriteAncientBlocks(bc.db, []*types.Block{bc.genesisBlock}, []types.Receipts{nil}, td)
|
||||||
size += writeSize
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error writing genesis to ancients", "err", err)
|
log.Error("Error writing genesis to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
size += writeSize
|
||||||
log.Info("Wrote genesis to ancients")
|
log.Info("Wrote genesis to ancients")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1176,44 +1175,11 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
// Write all chain data to ancients.
|
// Write all chain data to ancients.
|
||||||
td := bc.GetTd(first.Hash(), first.NumberU64())
|
td := bc.GetTd(first.Hash(), first.NumberU64())
|
||||||
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, td)
|
writeSize, err := rawdb.WriteAncientBlocks(bc.db, blockChain, receiptChain, td)
|
||||||
size += writeSize
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error importing chain data to ancients", "err", err)
|
log.Error("Error importing chain data to ancients", "err", err)
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
size += writeSize
|
||||||
// Write tx indices if any condition is satisfied:
|
|
||||||
// * If user requires to reserve all tx indices(txlookuplimit=0)
|
|
||||||
// * If all ancient tx indices are required to be reserved(txlookuplimit is even higher than ancientlimit)
|
|
||||||
// * If block number is large enough to be regarded as a recent block
|
|
||||||
// It means blocks below the ancientLimit-txlookupLimit won't be indexed.
|
|
||||||
//
|
|
||||||
// But if the `TxIndexTail` is not nil, e.g. Geth is initialized with
|
|
||||||
// an external ancient database, during the setup, blockchain will start
|
|
||||||
// a background routine to re-indexed all indices in [ancients - txlookupLimit, ancients)
|
|
||||||
// range. In this case, all tx indices of newly imported blocks should be
|
|
||||||
// generated.
|
|
||||||
batch := bc.db.NewBatch()
|
|
||||||
for i, block := range blockChain {
|
|
||||||
if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit || block.NumberU64() >= ancientLimit-bc.txLookupLimit {
|
|
||||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
|
||||||
} else if rawdb.ReadTxIndexTail(bc.db) != nil {
|
|
||||||
rawdb.WriteTxLookupEntriesByBlock(batch, block)
|
|
||||||
}
|
|
||||||
stats.processed++
|
|
||||||
|
|
||||||
if batch.ValueSize() > ethdb.IdealBatchSize || i == len(blockChain)-1 {
|
|
||||||
size += int64(batch.ValueSize())
|
|
||||||
if err = batch.Write(); err != nil {
|
|
||||||
snapBlock := bc.CurrentSnapBlock().Number.Uint64()
|
|
||||||
if _, err := bc.db.TruncateHead(snapBlock + 1); err != nil {
|
|
||||||
log.Error("Can't truncate ancient store after failed insert", "err", err)
|
|
||||||
}
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
batch.Reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
// Sync the ancient store explicitly to ensure all data has been flushed to disk.
|
||||||
if err := bc.db.Sync(); err != nil {
|
if err := bc.db.Sync(); err != nil {
|
||||||
|
|
@ -1231,8 +1197,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete block data from the main database.
|
// Delete block data from the main database.
|
||||||
batch.Reset()
|
var (
|
||||||
canonHashes := make(map[common.Hash]struct{})
|
batch = bc.db.NewBatch()
|
||||||
|
canonHashes = make(map[common.Hash]struct{})
|
||||||
|
)
|
||||||
for _, block := range blockChain {
|
for _, block := range blockChain {
|
||||||
canonHashes[block.Hash()] = struct{}{}
|
canonHashes[block.Hash()] = struct{}{}
|
||||||
if block.NumberU64() == 0 {
|
if block.NumberU64() == 0 {
|
||||||
|
|
@ -1255,8 +1223,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
|
|
||||||
// writeLive writes blockchain and corresponding receipt chain into active store.
|
// writeLive writes blockchain and corresponding receipt chain into active store.
|
||||||
writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
|
writeLive := func(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) {
|
||||||
skipPresenceCheck := false
|
var (
|
||||||
batch := bc.db.NewBatch()
|
skipPresenceCheck = false
|
||||||
|
batch = bc.db.NewBatch()
|
||||||
|
)
|
||||||
for i, block := range blockChain {
|
for i, block := range blockChain {
|
||||||
// Short circuit insertion if shutting down or processing failed
|
// Short circuit insertion if shutting down or processing failed
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
|
|
@ -1281,11 +1251,10 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
// Write all the data out into the database
|
// Write all the data out into the database
|
||||||
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
|
rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body())
|
||||||
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
|
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receiptChain[i])
|
||||||
rawdb.WriteTxLookupEntriesByBlock(batch, block) // Always write tx indices for live blocks, we assume they are needed
|
|
||||||
|
|
||||||
// Write everything belongs to the blocks into the database. So that
|
// Write everything belongs to the blocks into the database. So that
|
||||||
// we can ensure all components of body is completed(body, receipts,
|
// we can ensure all components of body is completed(body, receipts)
|
||||||
// tx indexes)
|
// except transaction indexes(will be created once sync is finished).
|
||||||
if batch.ValueSize() >= ethdb.IdealBatchSize {
|
if batch.ValueSize() >= ethdb.IdealBatchSize {
|
||||||
if err := batch.Write(); err != nil {
|
if err := batch.Write(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
@ -1317,19 +1286,6 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Write the tx index tail (block number from where we index) before write any live blocks
|
|
||||||
if len(liveBlocks) > 0 && liveBlocks[0].NumberU64() == ancientLimit+1 {
|
|
||||||
// The tx index tail can only be one of the following two options:
|
|
||||||
// * 0: all ancient blocks have been indexed
|
|
||||||
// * ancient-limit: the indices of blocks before ancient-limit are ignored
|
|
||||||
if tail := rawdb.ReadTxIndexTail(bc.db); tail == nil {
|
|
||||||
if bc.txLookupLimit == 0 || ancientLimit <= bc.txLookupLimit {
|
|
||||||
rawdb.WriteTxIndexTail(bc.db, 0)
|
|
||||||
} else {
|
|
||||||
rawdb.WriteTxIndexTail(bc.db, ancientLimit-bc.txLookupLimit)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(liveBlocks) > 0 {
|
if len(liveBlocks) > 0 {
|
||||||
if n, err := writeLive(liveBlocks, liveReceipts); err != nil {
|
if n, err := writeLive(liveBlocks, liveReceipts); err != nil {
|
||||||
if err == errInsertionInterrupted {
|
if err == errInsertionInterrupted {
|
||||||
|
|
@ -1338,13 +1294,14 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
head := blockChain[len(blockChain)-1]
|
head = blockChain[len(blockChain)-1]
|
||||||
context := []interface{}{
|
context = []interface{}{
|
||||||
"count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
|
"count", stats.processed, "elapsed", common.PrettyDuration(time.Since(start)),
|
||||||
"number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)),
|
"number", head.Number(), "hash", head.Hash(), "age", common.PrettyAge(time.Unix(int64(head.Time()), 0)),
|
||||||
"size", common.StorageSize(size),
|
"size", common.StorageSize(size),
|
||||||
}
|
}
|
||||||
|
)
|
||||||
if stats.ignored > 0 {
|
if stats.ignored > 0 {
|
||||||
context = append(context, []interface{}{"ignored", stats.ignored}...)
|
context = append(context, []interface{}{"ignored", stats.ignored}...)
|
||||||
}
|
}
|
||||||
|
|
@ -1360,7 +1317,6 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e
|
||||||
if bc.insertStopped() {
|
if bc.insertStopped() {
|
||||||
return errInsertionInterrupted
|
return errInsertionInterrupted
|
||||||
}
|
}
|
||||||
|
|
||||||
batch := bc.db.NewBatch()
|
batch := bc.db.NewBatch()
|
||||||
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
|
rawdb.WriteTd(batch, block.Hash(), block.NumberU64(), td)
|
||||||
rawdb.WriteBlock(batch, block)
|
rawdb.WriteBlock(batch, block)
|
||||||
|
|
@ -2427,23 +2383,24 @@ func (bc *BlockChain) skipBlock(err error, it *insertIterator) bool {
|
||||||
func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
|
func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{}) {
|
||||||
defer func() { close(done) }()
|
defer func() { close(done) }()
|
||||||
|
|
||||||
// If head is 0, it means the chain is just initialized and no blocks are inserted,
|
// If head is 0, it means the chain is just initialized and no blocks are
|
||||||
// so don't need to indexing anything.
|
// inserted, so don't need to index anything.
|
||||||
if head == 0 {
|
if head == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// The tail flag is not existent, it means the node is just initialized
|
// The tail flag is not existent, it means the node is just initialized
|
||||||
// and all blocks(may from ancient store) are not indexed yet.
|
// and all blocks in the chain (part of them may from ancient store) are
|
||||||
|
// not indexed yet, index the chain according to the configuration then.
|
||||||
if tail == nil {
|
if tail == nil {
|
||||||
from := uint64(0)
|
from := uint64(0)
|
||||||
if bc.txLookupLimit != 0 && head >= bc.txLookupLimit {
|
if bc.txLookupLimit != 0 && head >= bc.txLookupLimit {
|
||||||
from = head - bc.txLookupLimit + 1
|
from = head - bc.txLookupLimit + 1
|
||||||
}
|
}
|
||||||
rawdb.IndexTransactions(bc.db, from, head+1, bc.quit)
|
rawdb.IndexTransactions(bc.db, from, head+1, bc.quit, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// The tail flag is existent, but the whole chain is required to be indexed.
|
// The tail flag is existent (which means indexes in [tail, head] should be
|
||||||
|
// present), while the whole chain are requested for indexing.
|
||||||
if bc.txLookupLimit == 0 || head < bc.txLookupLimit {
|
if bc.txLookupLimit == 0 || head < bc.txLookupLimit {
|
||||||
if *tail > 0 {
|
if *tail > 0 {
|
||||||
// It can happen when chain is rewound to a historical point which
|
// It can happen when chain is rewound to a historical point which
|
||||||
|
|
@ -2453,17 +2410,18 @@ func (bc *BlockChain) indexBlocks(tail *uint64, head uint64, done chan struct{})
|
||||||
if end > head+1 {
|
if end > head+1 {
|
||||||
end = head + 1
|
end = head + 1
|
||||||
}
|
}
|
||||||
rawdb.IndexTransactions(bc.db, 0, end, bc.quit)
|
rawdb.IndexTransactions(bc.db, 0, end, bc.quit, true)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Update the transaction index to the new chain state
|
// The tail flag is existent, adjust the index range according to configuration
|
||||||
|
// and latest head.
|
||||||
if head-bc.txLookupLimit+1 < *tail {
|
if head-bc.txLookupLimit+1 < *tail {
|
||||||
// Reindex a part of missing indices and rewind index tail to HEAD-limit
|
// Reindex a part of missing indices and rewind index tail to HEAD-limit
|
||||||
rawdb.IndexTransactions(bc.db, head-bc.txLookupLimit+1, *tail, bc.quit)
|
rawdb.IndexTransactions(bc.db, head-bc.txLookupLimit+1, *tail, bc.quit, true)
|
||||||
} else {
|
} else {
|
||||||
// Unindex a part of stale indices and forward index tail to HEAD-limit
|
// Unindex a part of stale indices and forward index tail to HEAD-limit
|
||||||
rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit)
|
rawdb.UnindexTransactions(bc.db, *tail, head-bc.txLookupLimit+1, bc.quit, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2492,14 +2450,13 @@ func (bc *BlockChain) maintainTxIndex() {
|
||||||
defer sub.Unsubscribe()
|
defer sub.Unsubscribe()
|
||||||
log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit())
|
log.Info("Initialized transaction indexer", "limit", bc.TxLookupLimit())
|
||||||
|
|
||||||
// Launch the initial processing if chain is not empty. This step is
|
// Launch the initial processing if chain is not empty (head != genesis).
|
||||||
// useful in these scenarios that chain has no progress and indexer
|
// This step is useful in these scenarios that chain has no progress and
|
||||||
// is never triggered.
|
// indexer is never triggered.
|
||||||
if head := rawdb.ReadHeadBlock(bc.db); head != nil {
|
if head := rawdb.ReadHeadBlock(bc.db); head != nil && head.Number().Uint64() != 0 {
|
||||||
done = make(chan struct{})
|
done = make(chan struct{})
|
||||||
go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.NumberU64(), done)
|
go bc.indexBlocks(rawdb.ReadTxIndexTail(bc.db), head.NumberU64(), done)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case head := <-headCh:
|
case head := <-headCh:
|
||||||
|
|
|
||||||
|
|
@ -278,23 +278,6 @@ func WriteTxIndexTail(db ethdb.KeyValueWriter, number uint64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadFastTxLookupLimit retrieves the tx lookup limit used in fast sync.
|
|
||||||
func ReadFastTxLookupLimit(db ethdb.KeyValueReader) *uint64 {
|
|
||||||
data, _ := db.Get(fastTxLookupLimitKey)
|
|
||||||
if len(data) != 8 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
number := binary.BigEndian.Uint64(data)
|
|
||||||
return &number
|
|
||||||
}
|
|
||||||
|
|
||||||
// WriteFastTxLookupLimit stores the txlookup limit used in fast sync into database.
|
|
||||||
func WriteFastTxLookupLimit(db ethdb.KeyValueWriter, number uint64) {
|
|
||||||
if err := db.Put(fastTxLookupLimitKey, encodeBlockNumber(number)); err != nil {
|
|
||||||
log.Crit("Failed to store transaction lookup limit for fast sync", "err", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReadHeaderRange returns the rlp-encoded headers, starting at 'number', and going
|
// ReadHeaderRange returns the rlp-encoded headers, starting at 'number', and going
|
||||||
// backwards towards genesis. This method assumes that the caller already has
|
// backwards towards genesis. This method assumes that the caller already has
|
||||||
// placed a cap on count, to prevent DoS issues.
|
// placed a cap on count, to prevent DoS issues.
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,7 @@ func iterateTransactions(db ethdb.Database, from uint64, to uint64, reverse bool
|
||||||
//
|
//
|
||||||
// There is a passed channel, the whole procedure will be interrupted if any
|
// There is a passed channel, the whole procedure will be interrupted if any
|
||||||
// signal received.
|
// signal received.
|
||||||
func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
||||||
// short circuit for invalid range
|
// short circuit for invalid range
|
||||||
if from >= to {
|
if from >= to {
|
||||||
return
|
return
|
||||||
|
|
@ -188,13 +188,13 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
|
||||||
batch = db.NewBatch()
|
batch = db.NewBatch()
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
logged = start.Add(-7 * time.Second)
|
logged = start.Add(-7 * time.Second)
|
||||||
|
|
||||||
// Since we iterate in reverse, we expect the first number to come
|
// Since we iterate in reverse, we expect the first number to come
|
||||||
// in to be [to-1]. Therefore, setting lastNum to means that the
|
// in to be [to-1]. Therefore, setting lastNum to means that the
|
||||||
// prqueue gap-evaluation will work correctly
|
// queue gap-evaluation will work correctly
|
||||||
lastNum = to
|
lastNum = to
|
||||||
queue = prque.New[int64, *blockTxHashes](nil)
|
queue = prque.New[int64, *blockTxHashes](nil)
|
||||||
// for stats reporting
|
blocks, txs = 0, 0 // for stats reporting
|
||||||
blocks, txs = 0, 0
|
|
||||||
)
|
)
|
||||||
for chanDelivery := range hashesCh {
|
for chanDelivery := range hashesCh {
|
||||||
// Push the delivery into the queue and process contiguous ranges.
|
// Push the delivery into the queue and process contiguous ranges.
|
||||||
|
|
@ -240,11 +240,15 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
|
||||||
log.Crit("Failed writing batch to db", "error", err)
|
log.Crit("Failed writing batch to db", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logger := log.Debug
|
||||||
|
if report {
|
||||||
|
logger = log.Info
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-interrupt:
|
case <-interrupt:
|
||||||
log.Debug("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
|
logger("Transaction indexing interrupted", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
default:
|
default:
|
||||||
log.Debug("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
|
logger("Indexed transactions", "blocks", blocks, "txs", txs, "tail", lastNum, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,20 +261,20 @@ func indexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan
|
||||||
//
|
//
|
||||||
// There is a passed channel, the whole procedure will be interrupted if any
|
// There is a passed channel, the whole procedure will be interrupted if any
|
||||||
// signal received.
|
// signal received.
|
||||||
func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
|
func IndexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) {
|
||||||
indexTransactions(db, from, to, interrupt, nil)
|
indexTransactions(db, from, to, interrupt, nil, report)
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexTransactionsForTesting is the internal debug version with an additional hook.
|
// indexTransactionsForTesting is the internal debug version with an additional hook.
|
||||||
func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
func indexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
||||||
indexTransactions(db, from, to, interrupt, hook)
|
indexTransactions(db, from, to, interrupt, hook, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unindexTransactions removes txlookup indices of the specified block range.
|
// unindexTransactions removes txlookup indices of the specified block range.
|
||||||
//
|
//
|
||||||
// There is a passed channel, the whole procedure will be interrupted if any
|
// There is a passed channel, the whole procedure will be interrupted if any
|
||||||
// signal received.
|
// signal received.
|
||||||
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool, report bool) {
|
||||||
// short circuit for invalid range
|
// short circuit for invalid range
|
||||||
if from >= to {
|
if from >= to {
|
||||||
return
|
return
|
||||||
|
|
@ -280,12 +284,12 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
|
||||||
batch = db.NewBatch()
|
batch = db.NewBatch()
|
||||||
start = time.Now()
|
start = time.Now()
|
||||||
logged = start.Add(-7 * time.Second)
|
logged = start.Add(-7 * time.Second)
|
||||||
|
|
||||||
// we expect the first number to come in to be [from]. Therefore, setting
|
// we expect the first number to come in to be [from]. Therefore, setting
|
||||||
// nextNum to from means that the prqueue gap-evaluation will work correctly
|
// nextNum to from means that the queue gap-evaluation will work correctly
|
||||||
nextNum = from
|
nextNum = from
|
||||||
queue = prque.New[int64, *blockTxHashes](nil)
|
queue = prque.New[int64, *blockTxHashes](nil)
|
||||||
// for stats reporting
|
blocks, txs = 0, 0 // for stats reporting
|
||||||
blocks, txs = 0, 0
|
|
||||||
)
|
)
|
||||||
// Otherwise spin up the concurrent iterator and unindexer
|
// Otherwise spin up the concurrent iterator and unindexer
|
||||||
for delivery := range hashesCh {
|
for delivery := range hashesCh {
|
||||||
|
|
@ -332,11 +336,15 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
|
||||||
log.Crit("Failed writing batch to db", "error", err)
|
log.Crit("Failed writing batch to db", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
logger := log.Debug
|
||||||
|
if report {
|
||||||
|
logger = log.Info
|
||||||
|
}
|
||||||
select {
|
select {
|
||||||
case <-interrupt:
|
case <-interrupt:
|
||||||
log.Debug("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
|
logger("Transaction unindexing interrupted", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
default:
|
default:
|
||||||
log.Debug("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
|
logger("Unindexed transactions", "blocks", blocks, "txs", txs, "tail", to, "elapsed", common.PrettyDuration(time.Since(start)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -345,11 +353,11 @@ func unindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt ch
|
||||||
//
|
//
|
||||||
// There is a passed channel, the whole procedure will be interrupted if any
|
// There is a passed channel, the whole procedure will be interrupted if any
|
||||||
// signal received.
|
// signal received.
|
||||||
func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}) {
|
func UnindexTransactions(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, report bool) {
|
||||||
unindexTransactions(db, from, to, interrupt, nil)
|
unindexTransactions(db, from, to, interrupt, nil, report)
|
||||||
}
|
}
|
||||||
|
|
||||||
// unindexTransactionsForTesting is the internal debug version with an additional hook.
|
// unindexTransactionsForTesting is the internal debug version with an additional hook.
|
||||||
func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
func unindexTransactionsForTesting(db ethdb.Database, from uint64, to uint64, interrupt chan struct{}, hook func(uint64) bool) {
|
||||||
unindexTransactions(db, from, to, interrupt, hook)
|
unindexTransactions(db, from, to, interrupt, hook, false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -162,18 +162,18 @@ func TestIndexTransactions(t *testing.T) {
|
||||||
t.Fatalf("Transaction tail mismatch")
|
t.Fatalf("Transaction tail mismatch")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IndexTransactions(chainDb, 5, 11, nil)
|
IndexTransactions(chainDb, 5, 11, nil, false)
|
||||||
verify(5, 11, true, 5)
|
verify(5, 11, true, 5)
|
||||||
verify(0, 5, false, 5)
|
verify(0, 5, false, 5)
|
||||||
|
|
||||||
IndexTransactions(chainDb, 0, 5, nil)
|
IndexTransactions(chainDb, 0, 5, nil, false)
|
||||||
verify(0, 11, true, 0)
|
verify(0, 11, true, 0)
|
||||||
|
|
||||||
UnindexTransactions(chainDb, 0, 5, nil)
|
UnindexTransactions(chainDb, 0, 5, nil, false)
|
||||||
verify(5, 11, true, 5)
|
verify(5, 11, true, 5)
|
||||||
verify(0, 5, false, 5)
|
verify(0, 5, false, 5)
|
||||||
|
|
||||||
UnindexTransactions(chainDb, 5, 11, nil)
|
UnindexTransactions(chainDb, 5, 11, nil, false)
|
||||||
verify(0, 11, false, 11)
|
verify(0, 11, false, 11)
|
||||||
|
|
||||||
// Testing corner cases
|
// Testing corner cases
|
||||||
|
|
@ -190,7 +190,7 @@ func TestIndexTransactions(t *testing.T) {
|
||||||
})
|
})
|
||||||
verify(9, 11, true, 9)
|
verify(9, 11, true, 9)
|
||||||
verify(0, 9, false, 9)
|
verify(0, 9, false, 9)
|
||||||
IndexTransactions(chainDb, 0, 9, nil)
|
IndexTransactions(chainDb, 0, 9, nil, false)
|
||||||
|
|
||||||
signal = make(chan struct{})
|
signal = make(chan struct{})
|
||||||
var once2 sync.Once
|
var once2 sync.Once
|
||||||
|
|
|
||||||
|
|
@ -657,7 +657,6 @@ func ReadChainMetadata(db ethdb.KeyValueStore) [][]string {
|
||||||
{"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))},
|
{"snapshotRecoveryNumber", pp(ReadSnapshotRecoveryNumber(db))},
|
||||||
{"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))},
|
{"snapshotRoot", fmt.Sprintf("%v", ReadSnapshotRoot(db))},
|
||||||
{"txIndexTail", pp(ReadTxIndexTail(db))},
|
{"txIndexTail", pp(ReadTxIndexTail(db))},
|
||||||
{"fastTxLookupLimit", pp(ReadFastTxLookupLimit(db))},
|
|
||||||
}
|
}
|
||||||
if b := ReadSkeletonSyncStatus(db); b != nil {
|
if b := ReadSkeletonSyncStatus(db); b != nil {
|
||||||
data = append(data, []string{"SkeletonSyncStatus", string(b)})
|
data = append(data, []string{"SkeletonSyncStatus", string(b)})
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ var (
|
||||||
txIndexTailKey = []byte("TransactionIndexTail")
|
txIndexTailKey = []byte("TransactionIndexTail")
|
||||||
|
|
||||||
// fastTxLookupLimitKey tracks the transaction lookup limit during fast sync.
|
// fastTxLookupLimitKey tracks the transaction lookup limit during fast sync.
|
||||||
|
// This flag is deprecated, it's kept to avoid reporting errors when inspect
|
||||||
|
// database.
|
||||||
fastTxLookupLimitKey = []byte("FastTransactionLookupLimit")
|
fastTxLookupLimitKey = []byte("FastTransactionLookupLimit")
|
||||||
|
|
||||||
// badBlockKey tracks the list of bad blocks seen by local
|
// badBlockKey tracks the list of bad blocks seen by local
|
||||||
|
|
|
||||||
18
eth/sync.go
18
eth/sync.go
|
|
@ -228,24 +228,6 @@ func (cs *chainSyncer) startSync(op *chainSyncOp) {
|
||||||
|
|
||||||
// doSync synchronizes the local blockchain with a remote peer.
|
// doSync synchronizes the local blockchain with a remote peer.
|
||||||
func (h *handler) doSync(op *chainSyncOp) error {
|
func (h *handler) doSync(op *chainSyncOp) error {
|
||||||
if op.mode == downloader.SnapSync {
|
|
||||||
// Before launch the snap sync, we have to ensure user uses the same
|
|
||||||
// txlookup limit.
|
|
||||||
// The main concern here is: during the snap sync Geth won't index the
|
|
||||||
// block(generate tx indices) before the HEAD-limit. But if user changes
|
|
||||||
// the limit in the next snap sync(e.g. user kill Geth manually and
|
|
||||||
// restart) then it will be hard for Geth to figure out the oldest block
|
|
||||||
// has been indexed. So here for the user-experience wise, it's non-optimal
|
|
||||||
// that user can't change limit during the snap sync. If changed, Geth
|
|
||||||
// will just blindly use the original one.
|
|
||||||
limit := h.chain.TxLookupLimit()
|
|
||||||
if stored := rawdb.ReadFastTxLookupLimit(h.database); stored == nil {
|
|
||||||
rawdb.WriteFastTxLookupLimit(h.database, limit)
|
|
||||||
} else if *stored != limit {
|
|
||||||
h.chain.SetTxLookupLimit(*stored)
|
|
||||||
log.Warn("Update txLookup limit", "provided", limit, "updated", *stored)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Run the sync cycle, and disable snap sync if we're past the pivot block
|
// Run the sync cycle, and disable snap sync if we're past the pivot block
|
||||||
err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
|
err := h.downloader.LegacySync(op.peer.ID(), op.head, op.td, h.chain.Config().TerminalTotalDifficulty, op.mode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue