|
|
@ -72,7 +72,6 @@ import ( |
|
|
|
var ( |
|
|
|
var ( |
|
|
|
headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil) |
|
|
|
headBlockGauge = metrics.NewRegisteredGauge("chain/head/block", nil) |
|
|
|
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) |
|
|
|
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil) |
|
|
|
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) |
|
|
|
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil) |
|
|
|
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) |
|
|
|
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil) |
|
|
@ -189,7 +188,6 @@ type BlockChainImpl struct { |
|
|
|
pendingSlashingCandidatesMU sync.RWMutex // pending slashing candidates
|
|
|
|
pendingSlashingCandidatesMU sync.RWMutex // pending slashing candidates
|
|
|
|
|
|
|
|
|
|
|
|
currentBlock atomic.Value // Current head of the block chain
|
|
|
|
currentBlock atomic.Value // Current head of the block chain
|
|
|
|
currentFastBlock atomic.Value // Current head of the fast-sync chain (may be above the block chain!)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stateCache state.Database // State database to reuse between imports (contains state cache)
|
|
|
|
stateCache state.Database // State database to reuse between imports (contains state cache)
|
|
|
|
bodyCache *lru.Cache // Cache for the most recent block bodies
|
|
|
|
bodyCache *lru.Cache // Cache for the most recent block bodies
|
|
|
@ -323,7 +321,6 @@ func newBlockChainWithOptions( |
|
|
|
} |
|
|
|
} |
|
|
|
var nilBlock *types.Block |
|
|
|
var nilBlock *types.Block |
|
|
|
bc.currentBlock.Store(nilBlock) |
|
|
|
bc.currentBlock.Store(nilBlock) |
|
|
|
bc.currentFastBlock.Store(nilBlock) |
|
|
|
|
|
|
|
if err := bc.loadLastState(); err != nil { |
|
|
|
if err := bc.loadLastState(); err != nil { |
|
|
|
return nil, err |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
@ -617,22 +614,8 @@ func (bc *BlockChainImpl) loadLastState() error { |
|
|
|
return errors.Wrap(err, "headerChain SetCurrentHeader") |
|
|
|
return errors.Wrap(err, "headerChain SetCurrentHeader") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Restore the last known head fast block
|
|
|
|
|
|
|
|
bc.currentFastBlock.Store(currentBlock) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(currentBlock.NumberU64())) |
|
|
|
|
|
|
|
if head := rawdb.ReadHeadFastBlockHash(bc.db); head != (common.Hash{}) { |
|
|
|
|
|
|
|
if block := bc.GetBlockByHash(head); block != nil { |
|
|
|
|
|
|
|
bc.currentFastBlock.Store(block) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(block.NumberU64())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Issue a status log for the user
|
|
|
|
|
|
|
|
currentFastBlock := bc.CurrentFastBlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number().Uint64()) |
|
|
|
headerTd := bc.GetTd(currentHeader.Hash(), currentHeader.Number().Uint64()) |
|
|
|
blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) |
|
|
|
blockTd := bc.GetTd(currentBlock.Hash(), currentBlock.NumberU64()) |
|
|
|
fastTd := bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils.Logger().Info(). |
|
|
|
utils.Logger().Info(). |
|
|
|
Str("number", currentHeader.Number().String()). |
|
|
|
Str("number", currentHeader.Number().String()). |
|
|
@ -646,12 +629,6 @@ func (bc *BlockChainImpl) loadLastState() error { |
|
|
|
Str("td", blockTd.String()). |
|
|
|
Str("td", blockTd.String()). |
|
|
|
Str("age", common.PrettyAge(time.Unix(currentBlock.Time().Int64(), 0)).String()). |
|
|
|
Str("age", common.PrettyAge(time.Unix(currentBlock.Time().Int64(), 0)).String()). |
|
|
|
Msg("Loaded most recent local full block") |
|
|
|
Msg("Loaded most recent local full block") |
|
|
|
utils.Logger().Info(). |
|
|
|
|
|
|
|
Str("number", currentFastBlock.Number().String()). |
|
|
|
|
|
|
|
Str("hash", currentFastBlock.Hash().Hex()). |
|
|
|
|
|
|
|
Str("td", fastTd.String()). |
|
|
|
|
|
|
|
Str("age", common.PrettyAge(time.Unix(currentFastBlock.Time().Int64(), 0)).String()). |
|
|
|
|
|
|
|
Msg("Loaded most recent local fast block") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
@ -691,30 +668,16 @@ func (bc *BlockChainImpl) SetHead(head uint64) error { |
|
|
|
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Rewind the fast block in a simpleton way to the target head
|
|
|
|
|
|
|
|
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && currentHeader.Number().Uint64() < currentFastBlock.NumberU64() { |
|
|
|
|
|
|
|
newHeadFastBlock := bc.GetBlock(currentHeader.Hash(), currentHeader.Number().Uint64()) |
|
|
|
|
|
|
|
bc.currentFastBlock.Store(newHeadFastBlock) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(newHeadFastBlock.NumberU64())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// If either blocks reached nil, reset to the genesis state
|
|
|
|
// If either blocks reached nil, reset to the genesis state
|
|
|
|
if currentBlock := bc.CurrentBlock(); currentBlock == nil { |
|
|
|
if currentBlock := bc.CurrentBlock(); currentBlock == nil { |
|
|
|
bc.currentBlock.Store(bc.genesisBlock) |
|
|
|
bc.currentBlock.Store(bc.genesisBlock) |
|
|
|
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
} |
|
|
|
} |
|
|
|
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock == nil { |
|
|
|
|
|
|
|
bc.currentFastBlock.Store(bc.genesisBlock) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
currentBlock := bc.CurrentBlock() |
|
|
|
currentBlock := bc.CurrentBlock() |
|
|
|
currentFastBlock := bc.CurrentFastBlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if err := rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash()); err != nil { |
|
|
|
if err := rawdb.WriteHeadBlockHash(bc.db, currentBlock.Hash()); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
if err := rawdb.WriteHeadFastBlockHash(bc.db, currentFastBlock.Hash()); err != nil { |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return bc.loadLastState() |
|
|
|
return bc.loadLastState() |
|
|
|
} |
|
|
|
} |
|
|
@ -727,12 +690,6 @@ func (bc *BlockChainImpl) CurrentBlock() *types.Block { |
|
|
|
return bc.currentBlock.Load().(*types.Block) |
|
|
|
return bc.currentBlock.Load().(*types.Block) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
|
|
|
|
|
|
|
|
// chain. The block is retrieved from the blockchain's internal cache.
|
|
|
|
|
|
|
|
func (bc *BlockChainImpl) CurrentFastBlock() *types.Block { |
|
|
|
|
|
|
|
return bc.currentFastBlock.Load().(*types.Block) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (bc *BlockChainImpl) Processor() Processor { |
|
|
|
func (bc *BlockChainImpl) Processor() Processor { |
|
|
|
bc.procmu.RLock() |
|
|
|
bc.procmu.RLock() |
|
|
|
defer bc.procmu.RUnlock() |
|
|
|
defer bc.procmu.RUnlock() |
|
|
@ -779,8 +736,6 @@ func (bc *BlockChainImpl) ResetWithGenesisBlock(genesis *types.Block) error { |
|
|
|
} |
|
|
|
} |
|
|
|
bc.currentBlock.Store(bc.genesisBlock) |
|
|
|
bc.currentBlock.Store(bc.genesisBlock) |
|
|
|
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
bc.currentFastBlock.Store(bc.genesisBlock) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(bc.genesisBlock.NumberU64())) |
|
|
|
|
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -914,9 +869,6 @@ func (bc *BlockChainImpl) writeHeadBlock(block *types.Block) error { |
|
|
|
if err := rawdb.WriteHeadFastBlockHash(bc.db, block.Hash()); err != nil { |
|
|
|
if err := rawdb.WriteHeadFastBlockHash(bc.db, block.Hash()); err != nil { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bc.currentFastBlock.Store(block) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(block.NumberU64())) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
@ -930,9 +882,6 @@ func (bc *BlockChainImpl) tikvFastForward(block *types.Block, logs []*types.Log) |
|
|
|
return errors.Wrap(err, "HeaderChain SetCurrentHeader") |
|
|
|
return errors.Wrap(err, "HeaderChain SetCurrentHeader") |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bc.currentFastBlock.Store(block) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(block.NumberU64())) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var events []interface{} |
|
|
|
var events []interface{} |
|
|
|
events = append(events, ChainEvent{block, block.Hash(), logs}) |
|
|
|
events = append(events, ChainEvent{block, block.Hash(), logs}) |
|
|
|
events = append(events, ChainHeadEvent{block}) |
|
|
|
events = append(events, ChainHeadEvent{block}) |
|
|
@ -1234,14 +1183,6 @@ func (bc *BlockChainImpl) Rollback(chain []common.Hash) error { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && currentFastBlock.Hash() == hash { |
|
|
|
|
|
|
|
newFastBlock := bc.GetBlock(currentFastBlock.ParentHash(), currentFastBlock.NumberU64()-1) |
|
|
|
|
|
|
|
if newFastBlock != nil { |
|
|
|
|
|
|
|
bc.currentFastBlock.Store(newFastBlock) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(newFastBlock.NumberU64())) |
|
|
|
|
|
|
|
rawdb.WriteHeadFastBlockHash(bc.db, newFastBlock.Hash()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if currentBlock := bc.CurrentBlock(); currentBlock != nil && currentBlock.Hash() == hash { |
|
|
|
if currentBlock := bc.CurrentBlock(); currentBlock != nil && currentBlock.Hash() == hash { |
|
|
|
newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1) |
|
|
|
newBlock := bc.GetBlock(currentBlock.ParentHash(), currentBlock.NumberU64()-1) |
|
|
|
if newBlock != nil { |
|
|
|
if newBlock != nil { |
|
|
@ -1326,111 +1267,6 @@ func SetReceiptsData(config *params.ChainConfig, block *types.Block, receipts ty |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// InsertReceiptChain attempts to complete an already existing header chain with
|
|
|
|
|
|
|
|
// transaction and receipt data.
|
|
|
|
|
|
|
|
// Deprecated: no usages of this function found.
|
|
|
|
|
|
|
|
// TODO: should be removed
|
|
|
|
|
|
|
|
func (bc *BlockChainImpl) InsertReceiptChain(blockChain types.Blocks, receiptChain []types.Receipts) (int, error) { |
|
|
|
|
|
|
|
// Do a sanity check that the provided chain is actually ordered and linked
|
|
|
|
|
|
|
|
for i := 1; i < len(blockChain); i++ { |
|
|
|
|
|
|
|
if blockChain[i].NumberU64() != blockChain[i-1].NumberU64()+1 || blockChain[i].ParentHash() != blockChain[i-1].Hash() { |
|
|
|
|
|
|
|
utils.Logger().Error(). |
|
|
|
|
|
|
|
Str("number", blockChain[i].Number().String()). |
|
|
|
|
|
|
|
Str("hash", blockChain[i].Hash().Hex()). |
|
|
|
|
|
|
|
Str("parent", blockChain[i].ParentHash().Hex()). |
|
|
|
|
|
|
|
Str("prevnumber", blockChain[i-1].Number().String()). |
|
|
|
|
|
|
|
Str("prevhash", blockChain[i-1].Hash().Hex()). |
|
|
|
|
|
|
|
Msg("Non contiguous receipt insert") |
|
|
|
|
|
|
|
return 0, fmt.Errorf("non contiguous insert: item %d is #%d [%x…], item %d is #%d [%x…] (parent [%x…])", i-1, blockChain[i-1].NumberU64(), |
|
|
|
|
|
|
|
blockChain[i-1].Hash().Bytes()[:4], i, blockChain[i].NumberU64(), blockChain[i].Hash().Bytes()[:4], blockChain[i].ParentHash().Bytes()[:4]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bc.chainmu.Lock() |
|
|
|
|
|
|
|
defer bc.chainmu.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
|
|
|
stats = struct{ processed, ignored int32 }{} |
|
|
|
|
|
|
|
start = time.Now() |
|
|
|
|
|
|
|
bytes = 0 |
|
|
|
|
|
|
|
batch = bc.db.NewBatch() |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
for i, block := range blockChain { |
|
|
|
|
|
|
|
receipts := receiptChain[i] |
|
|
|
|
|
|
|
// Short circuit insertion if shutting down or processing failed
|
|
|
|
|
|
|
|
if atomic.LoadInt32(&bc.procInterrupt) == 1 { |
|
|
|
|
|
|
|
return 0, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Short circuit if the owner header is unknown
|
|
|
|
|
|
|
|
if !bc.HasHeader(block.Hash(), block.NumberU64()) { |
|
|
|
|
|
|
|
return 0, fmt.Errorf("containing header #%d [%x…] unknown", block.Number(), block.Hash().Bytes()[:4]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Skip if the entire data is already known
|
|
|
|
|
|
|
|
if bc.HasBlock(block.Hash(), block.NumberU64()) { |
|
|
|
|
|
|
|
stats.ignored++ |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Compute all the non-consensus fields of the receipts
|
|
|
|
|
|
|
|
if err := SetReceiptsData(bc.chainConfig, block, receipts); err != nil { |
|
|
|
|
|
|
|
return 0, fmt.Errorf("failed to set receipts data: %v", err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Write all the data out into the database
|
|
|
|
|
|
|
|
if err := rawdb.WriteBody(batch, block.Hash(), block.NumberU64(), block.Body()); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if err := rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if err := rawdb.WriteBlockTxLookUpEntries(batch, block); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if err := rawdb.WriteBlockStxLookUpEntries(batch, block); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stats.processed++ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if batch.ValueSize() >= ethdb.IdealBatchSize { |
|
|
|
|
|
|
|
if err := batch.Write(); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
bytes += batch.ValueSize() |
|
|
|
|
|
|
|
batch.Reset() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if batch.ValueSize() > 0 { |
|
|
|
|
|
|
|
bytes += batch.ValueSize() |
|
|
|
|
|
|
|
if err := batch.Write(); err != nil { |
|
|
|
|
|
|
|
return 0, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Update the head fast sync block if better
|
|
|
|
|
|
|
|
bc.mu.Lock() |
|
|
|
|
|
|
|
head := blockChain[len(blockChain)-1] |
|
|
|
|
|
|
|
if td := bc.GetTd(head.Hash(), head.NumberU64()); td != nil { // Rewind may have occurred, skip in that case
|
|
|
|
|
|
|
|
currentFastBlock := bc.CurrentFastBlock() |
|
|
|
|
|
|
|
if bc.GetTd(currentFastBlock.Hash(), currentFastBlock.NumberU64()).Cmp(td) < 0 { |
|
|
|
|
|
|
|
rawdb.WriteHeadFastBlockHash(bc.db, head.Hash()) |
|
|
|
|
|
|
|
bc.currentFastBlock.Store(head) |
|
|
|
|
|
|
|
headFastBlockGauge.Update(int64(head.NumberU64())) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
bc.mu.Unlock() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils.Logger().Info(). |
|
|
|
|
|
|
|
Int32("count", stats.processed). |
|
|
|
|
|
|
|
Str("elapsed", common.PrettyDuration(time.Since(start)).String()). |
|
|
|
|
|
|
|
Str("age", common.PrettyAge(time.Unix(head.Time().Int64(), 0)).String()). |
|
|
|
|
|
|
|
Str("head", head.Number().String()). |
|
|
|
|
|
|
|
Str("hash", head.Hash().Hex()). |
|
|
|
|
|
|
|
Str("size", common.StorageSize(bytes).String()). |
|
|
|
|
|
|
|
Int32("ignored", stats.ignored). |
|
|
|
|
|
|
|
Msg("Imported new block receipts") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var lastWrite uint64 |
|
|
|
var lastWrite uint64 |
|
|
|
|
|
|
|
|
|
|
|
func (bc *BlockChainImpl) WriteBlockWithoutState(block *types.Block, td *big.Int) (err error) { |
|
|
|
func (bc *BlockChainImpl) WriteBlockWithoutState(block *types.Block, td *big.Int) (err error) { |
|
|
|