aboutsummaryrefslogtreecommitdiffstats
path: root/core/blockchain.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/blockchain.go')
-rw-r--r--core/blockchain.go116
1 files changed, 97 insertions, 19 deletions
diff --git a/core/blockchain.go b/core/blockchain.go
index b4a2882dd..73e820c32 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -160,6 +160,7 @@ type BlockChain struct {
pendingBlocks map[uint64]struct {
block *types.Block
receipts types.Receipts
+ proctime time.Duration
}
}
@@ -199,6 +200,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
pendingBlocks: make(map[uint64]struct {
block *types.Block
receipts types.Receipts
+ proctime time.Duration
}),
confirmedBlocks: make(map[uint32]map[coreCommon.Hash]*blockInfo),
addressNonce: make(map[uint32]map[common.Address]uint64),
@@ -1073,6 +1075,13 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
bytes += batch.ValueSize()
batch.Reset()
}
+
+ if i == len(blockChain)-1 {
+ err := bc.updateLastRoundNumber(block.Round())
+ if err != nil {
+ return 0, err
+ }
+ }
}
if batch.ValueSize() > 0 {
bytes += batch.ValueSize()
@@ -1350,7 +1359,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
case err == consensus.ErrPrunedAncestor:
return bc.insertSidechain(block, it)
- // First block is future, shove it (and all children) to the future queue (unknown ancestor)
+ // First block is future, shove it (and all children) to the future queue (unknown ancestor)
case err == consensus.ErrFutureBlock || (err == consensus.ErrUnknownAncestor && bc.futureBlocks.Contains(it.first().ParentHash())):
for block != nil && (it.index == 0 || err == consensus.ErrUnknownAncestor) {
if err := bc.addFutureBlock(block); err != nil {
@@ -1364,10 +1373,10 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
// If there are any still remaining, mark as ignored
return it.index, events, coalescedLogs, err
- // First block (and state) is known
- // 1. We did a roll-back, and should now do a re-import
- // 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot
- // from the canonical chain, which has not been verified.
+ // First block (and state) is known
+ // 1. We did a roll-back, and should now do a re-import
+ // 2. The block is stored as a sidechain, and is lying about it's stateroot, and passes a stateroot
+ // from the canonical chain, which has not been verified.
case err == ErrKnownBlock:
// Skip all known blocks that behind us
current := bc.CurrentBlock().NumberU64()
@@ -1378,7 +1387,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, []
}
// Falls through to the block import
- // Some other error occurred, abort
+ // Some other error occurred, abort
case err != nil:
stats.ignored += len(it.chain)
bc.reportBlock(block, nil, err)
@@ -1786,6 +1795,13 @@ func (bc *BlockChain) insertDexonChain(chain types.Blocks) (int, []interface{},
cache, _ := bc.stateCache.TrieDB().Size()
stats.report(chain, i, cache)
+
+ if i == len(chain)-1 {
+ err = bc.updateLastRoundNumber(block.Round())
+ if err != nil {
+ return 0, nil, nil, err
+ }
+ }
}
// Append a single chain head event if we've progressed the chain
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
@@ -1823,15 +1839,7 @@ func (bc *BlockChain) processPendingBlock(
coalescedLogs []*types.Log
)
- // Start a parallel signature recovery (signer will fluke on fork transition, minimal perf loss)
- senderCacher.recoverFromBlocks(types.MakeSigner(bc.chainConfig, block.Number()), []*types.Block{block})
-
- if atomic.LoadInt32(&bc.procInterrupt) == 1 {
- log.Debug("Premature abort during blocks processing")
- return nil, nil, nil, fmt.Errorf("interrupt")
- }
bstart := time.Now()
-
var witnessData types.WitnessData
if err := rlp.Decode(bytes.NewReader(witness.Data), &witnessData); err != nil {
log.Error("Witness rlp decode failed", "error", err)
@@ -1898,13 +1906,18 @@ func (bc *BlockChain) processPendingBlock(
}
// Add into pending blocks.
- bc.addPendingBlock(newPendingBlock, receipts)
+ bc.addPendingBlock(newPendingBlock, receipts, proctime)
events = append(events, BlockConfirmedEvent{newPendingBlock})
log.Debug("Inserted pending block", "height", newPendingBlock.Number(), "hash", newPendingBlock.Hash())
// Start insert available pending blocks into db
for pendingHeight := bc.CurrentBlock().NumberU64() + 1; pendingHeight <= witness.Height; pendingHeight++ {
+ if atomic.LoadInt32(&bc.procInterrupt) == 1 {
+ log.Debug("Premature abort during blocks processing")
+ return nil, nil, nil, fmt.Errorf("interrupt")
+ }
+
pendingIns, exist := bc.pendingBlocks[pendingHeight]
if !exist {
log.Error("Block has already inserted", "height", pendingHeight)
@@ -1917,6 +1930,7 @@ func (bc *BlockChain) processPendingBlock(
}
// Write the block to the chain and get the status.
+ insertTime := time.Now()
status, err := bc.WriteBlockWithState(pendingIns.block, pendingIns.receipts, s)
if err != nil {
return nil, events, coalescedLogs, fmt.Errorf("WriteBlockWithState error: %v", err)
@@ -1933,12 +1947,12 @@ func (bc *BlockChain) processPendingBlock(
allLogs = append(allLogs, r.Logs...)
}
coalescedLogs = append(coalescedLogs, allLogs...)
- blockInsertTimer.UpdateSince(bstart)
+ blockInsertTimer.UpdateSince(insertTime)
events = append(events, ChainEvent{pendingIns.block, pendingIns.block.Hash(), allLogs})
lastCanon = pendingIns.block
// Only count canonical blocks for GC processing time
- bc.gcproc += proctime
+ bc.gcproc += pendingIns.proctime
case SideStatTy:
return nil, nil, nil, fmt.Errorf("insert pending block and fork found")
@@ -1950,6 +1964,13 @@ func (bc *BlockChain) processPendingBlock(
cache, _ := bc.stateCache.TrieDB().Size()
stats.report([]*types.Block{pendingIns.block}, 0, cache)
+
+ if pendingHeight == witness.Height {
+ err = bc.updateLastRoundNumber(pendingIns.block.Round())
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ }
}
// Append a single chain head event if we've progressed the chain
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
@@ -1960,6 +1981,46 @@ func (bc *BlockChain) processPendingBlock(
return &root, events, coalescedLogs, nil
}
+func (bc *BlockChain) ProcessEmptyBlock(block *types.Block) error {
+ bstart := time.Now()
+ var header = block.Header()
+ var parentBlock *types.Block
+ var pendingState *state.StateDB
+ var err error
+ parent, exist := bc.pendingBlocks[block.NumberU64()-1]
+ if !exist {
+ parentBlock = bc.GetBlockByNumber(block.NumberU64() - 1)
+ if parentBlock == nil {
+ return fmt.Errorf("parent block %d not exist", block.NumberU64()-1)
+ }
+ } else {
+ parentBlock = parent.block
+ }
+
+ pendingState, err = state.New(parentBlock.Root(), bc.stateCache)
+ if err != nil {
+ return err
+ }
+
+ header.ParentHash = parentBlock.Hash()
+ header.GasUsed = 0
+ header.Root = pendingState.IntermediateRoot(true)
+ if header.Root != parentBlock.Root() {
+ return fmt.Errorf("empty block state root must same as parent")
+ }
+
+ newPendingBlock := types.NewBlock(header, nil, nil, nil)
+ if _, ok := bc.GetRoundHeight(newPendingBlock.Round()); !ok {
+ bc.storeRoundHeight(newPendingBlock.Round(), newPendingBlock.NumberU64())
+ }
+
+ proctime := time.Since(bstart)
+ bc.addPendingBlock(newPendingBlock, nil, proctime)
+ bc.PostChainEvents([]interface{}{BlockConfirmedEvent{newPendingBlock}}, nil)
+
+ return nil
+}
+
func (bc *BlockChain) removePendingBlock(height uint64) {
bc.pendingBlockMu.Lock()
defer bc.pendingBlockMu.Unlock()
@@ -1967,14 +2028,15 @@ func (bc *BlockChain) removePendingBlock(height uint64) {
delete(bc.pendingBlocks, height)
}
-func (bc *BlockChain) addPendingBlock(block *types.Block, receipts types.Receipts) {
+func (bc *BlockChain) addPendingBlock(block *types.Block, receipts types.Receipts, proctime time.Duration) {
bc.pendingBlockMu.Lock()
defer bc.pendingBlockMu.Unlock()
bc.pendingBlocks[block.NumberU64()] = struct {
block *types.Block
receipts types.Receipts
- }{block: block, receipts: receipts}
+ proctime time.Duration
+ }{block: block, receipts: receipts, proctime: proctime}
bc.lastPendingHeight = block.NumberU64()
}
@@ -2418,3 +2480,19 @@ func (bc *BlockChain) GetRoundHeight(round uint64) (uint64, bool) {
func (bc *BlockChain) storeRoundHeight(round uint64, height uint64) {
bc.roundHeightMap.Store(round, height)
}
+
+func (bc *BlockChain) updateLastRoundNumber(round uint64) error {
+ currentLastRound, err := rawdb.ReadLastRoundNumber(bc.db)
+ if err != nil {
+ return err
+ }
+
+ if round > currentLastRound {
+ err = rawdb.WriteLastRoundNumber(bc.db, round)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}