|
|
@ -834,19 +834,16 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
|
|
|
// faster than direct delivery and requires much less mutex
|
|
|
|
// faster than direct delivery and requires much less mutex
|
|
|
|
// acquiring.
|
|
|
|
// acquiring.
|
|
|
|
var ( |
|
|
|
var ( |
|
|
|
stats struct{ queued, processed, ignored int } |
|
|
|
stats = insertStats{startTime: time.Now()} |
|
|
|
events = make([]interface{}, 0, len(chain)) |
|
|
|
events = make([]interface{}, 0, len(chain)) |
|
|
|
coalescedLogs vm.Logs |
|
|
|
coalescedLogs vm.Logs |
|
|
|
tstart = time.Now() |
|
|
|
nonceChecked = make([]bool, len(chain)) |
|
|
|
|
|
|
|
|
|
|
|
nonceChecked = make([]bool, len(chain)) |
|
|
|
|
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
// Start the parallel nonce verifier.
|
|
|
|
// Start the parallel nonce verifier.
|
|
|
|
nonceAbort, nonceResults := verifyNoncesFromBlocks(self.pow, chain) |
|
|
|
nonceAbort, nonceResults := verifyNoncesFromBlocks(self.pow, chain) |
|
|
|
defer close(nonceAbort) |
|
|
|
defer close(nonceAbort) |
|
|
|
|
|
|
|
|
|
|
|
txcount := 0 |
|
|
|
|
|
|
|
for i, block := range chain { |
|
|
|
for i, block := range chain { |
|
|
|
if atomic.LoadInt32(&self.procInterrupt) == 1 { |
|
|
|
if atomic.LoadInt32(&self.procInterrupt) == 1 { |
|
|
|
glog.V(logger.Debug).Infoln("Premature abort during block chain processing") |
|
|
|
glog.V(logger.Debug).Infoln("Premature abort during block chain processing") |
|
|
@ -941,7 +938,6 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
|
|
|
return i, err |
|
|
|
return i, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
txcount += len(block.Transactions()) |
|
|
|
|
|
|
|
// write the block to the chain and get the status
|
|
|
|
// write the block to the chain and get the status
|
|
|
|
status, err := self.WriteBlock(block) |
|
|
|
status, err := self.WriteBlock(block) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
@ -976,19 +972,54 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
|
|
|
case SplitStatTy: |
|
|
|
case SplitStatTy: |
|
|
|
events = append(events, ChainSplitEvent{block, logs}) |
|
|
|
events = append(events, ChainSplitEvent{block, logs}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
stats.processed++ |
|
|
|
stats.processed++ |
|
|
|
|
|
|
|
if glog.V(logger.Info) { |
|
|
|
|
|
|
|
stats.report(chain, i) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) { |
|
|
|
|
|
|
|
tend := time.Since(tstart) |
|
|
|
|
|
|
|
start, end := chain[0], chain[len(chain)-1] |
|
|
|
|
|
|
|
glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", stats.processed, stats.queued, stats.ignored, txcount, tend, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4]) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
go self.postChainEvents(events, coalescedLogs) |
|
|
|
go self.postChainEvents(events, coalescedLogs) |
|
|
|
|
|
|
|
|
|
|
|
return 0, nil |
|
|
|
return 0, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// insertStats tracks and reports on block insertion.
|
|
|
|
|
|
|
|
type insertStats struct { |
|
|
|
|
|
|
|
queued, processed, ignored int |
|
|
|
|
|
|
|
lastIndex int |
|
|
|
|
|
|
|
startTime time.Time |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
|
|
|
|
statsReportLimit = 1024 |
|
|
|
|
|
|
|
statsReportTimeLimit = 8 * time.Second |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// report prints statistics if some number of blocks have been processed
|
|
|
|
|
|
|
|
// or more than a few seconds have passed since the last message.
|
|
|
|
|
|
|
|
func (st *insertStats) report(chain []*types.Block, index int) { |
|
|
|
|
|
|
|
limit := statsReportLimit |
|
|
|
|
|
|
|
if index == len(chain)-1 { |
|
|
|
|
|
|
|
limit = 0 // Always print a message for the last block.
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
now := time.Now() |
|
|
|
|
|
|
|
duration := now.Sub(st.startTime) |
|
|
|
|
|
|
|
if duration > statsReportTimeLimit || st.queued > limit || st.processed > limit || st.ignored > limit { |
|
|
|
|
|
|
|
start, end := chain[st.lastIndex], chain[index] |
|
|
|
|
|
|
|
txcount := countTransactions(chain[st.lastIndex:index]) |
|
|
|
|
|
|
|
glog.Infof("imported %d block(s) (%d queued %d ignored) including %d txs in %v. #%v [%x / %x]\n", st.processed, st.queued, st.ignored, txcount, duration, end.Number(), start.Hash().Bytes()[:4], end.Hash().Bytes()[:4]) |
|
|
|
|
|
|
|
*st = insertStats{startTime: now, lastIndex: index} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func countTransactions(chain []*types.Block) (c int) { |
|
|
|
|
|
|
|
for _, b := range chain { |
|
|
|
|
|
|
|
c += len(b.Transactions()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return c |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// reorgs takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
|
|
|
|
// reorgs takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
|
|
|
|
// to be part of the new canonical chain and accumulates potential missing transactions and post an
|
|
|
|
// to be part of the new canonical chain and accumulates potential missing transactions and post an
|
|
|
|
// event about them
|
|
|
|
// event about them
|
|
|
|