|
|
|
@ -483,13 +483,6 @@ func (bc *BlockChain) Stop() { |
|
|
|
|
glog.V(logger.Info).Infoln("Chain manager stopped") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
type queueEvent struct { |
|
|
|
|
queue []interface{} |
|
|
|
|
canonicalCount int |
|
|
|
|
sideCount int |
|
|
|
|
splitCount int |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *BlockChain) procFutureBlocks() { |
|
|
|
|
blocks := make([]*types.Block, self.futureBlocks.Len()) |
|
|
|
|
for i, hash := range self.futureBlocks.Keys() { |
|
|
|
@ -573,10 +566,9 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
|
|
|
|
// faster than direct delivery and requires much less mutex
|
|
|
|
|
// acquiring.
|
|
|
|
|
var ( |
|
|
|
|
queue = make([]interface{}, len(chain)) |
|
|
|
|
queueEvent = queueEvent{queue: queue} |
|
|
|
|
stats struct{ queued, processed, ignored int } |
|
|
|
|
tstart = time.Now() |
|
|
|
|
stats struct{ queued, processed, ignored int } |
|
|
|
|
events = make([]interface{}, 0, len(chain)) |
|
|
|
|
tstart = time.Now() |
|
|
|
|
|
|
|
|
|
nonceChecked = make([]bool, len(chain)) |
|
|
|
|
) |
|
|
|
@ -659,22 +651,21 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
|
|
|
|
if glog.V(logger.Debug) { |
|
|
|
|
glog.Infof("[%v] inserted block #%d (%d TXs %v G %d UNCs) (%x...). Took %v\n", time.Now().UnixNano(), block.Number(), len(block.Transactions()), block.GasUsed(), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) |
|
|
|
|
} |
|
|
|
|
queue[i] = ChainEvent{block, block.Hash(), logs} |
|
|
|
|
queueEvent.canonicalCount++ |
|
|
|
|
events = append(events, ChainEvent{block, block.Hash(), logs}) |
|
|
|
|
|
|
|
|
|
// This puts transactions in a extra db for rpc
|
|
|
|
|
PutTransactions(self.chainDb, block, block.Transactions()) |
|
|
|
|
// store the receipts
|
|
|
|
|
PutReceipts(self.chainDb, receipts) |
|
|
|
|
|
|
|
|
|
case SideStatTy: |
|
|
|
|
if glog.V(logger.Detail) { |
|
|
|
|
glog.Infof("inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...). Took %v\n", block.Number(), block.Difficulty(), len(block.Transactions()), len(block.Uncles()), block.Hash().Bytes()[0:4], time.Since(bstart)) |
|
|
|
|
} |
|
|
|
|
queue[i] = ChainSideEvent{block, logs} |
|
|
|
|
queueEvent.sideCount++ |
|
|
|
|
events = append(events, ChainSideEvent{block, logs}) |
|
|
|
|
|
|
|
|
|
case SplitStatTy: |
|
|
|
|
queue[i] = ChainSplitEvent{block, logs} |
|
|
|
|
queueEvent.splitCount++ |
|
|
|
|
events = append(events, ChainSplitEvent{block, logs}) |
|
|
|
|
} |
|
|
|
|
stats.processed++ |
|
|
|
|
} |
|
|
|
@ -684,8 +675,7 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) { |
|
|
|
|
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.eventMux.Post(queueEvent) |
|
|
|
|
go self.postChainEvents(events) |
|
|
|
|
|
|
|
|
|
return 0, nil |
|
|
|
|
} |
|
|
|
@ -774,32 +764,31 @@ func (self *BlockChain) reorg(oldBlock, newBlock *types.Block) error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// postChainEvents iterates over the events generated by a chain insertion and
|
|
|
|
|
// posts them into the event mux.
|
|
|
|
|
func (self *BlockChain) postChainEvents(events []interface{}) { |
|
|
|
|
for _, event := range events { |
|
|
|
|
if event, ok := event.(ChainEvent); ok { |
|
|
|
|
// We need some control over the mining operation. Acquiring locks and waiting for the miner to create new block takes too long
|
|
|
|
|
// and in most cases isn't even necessary.
|
|
|
|
|
if self.currentBlock.Hash() == event.Hash { |
|
|
|
|
self.currentGasLimit = CalcGasLimit(event.Block) |
|
|
|
|
self.eventMux.Post(ChainHeadEvent{event.Block}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Fire the insertion events individually too
|
|
|
|
|
self.eventMux.Post(event) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (self *BlockChain) update() { |
|
|
|
|
events := self.eventMux.Subscribe(queueEvent{}) |
|
|
|
|
futureTimer := time.Tick(5 * time.Second) |
|
|
|
|
out: |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case ev := <-events.Chan(): |
|
|
|
|
switch ev := ev.(type) { |
|
|
|
|
case queueEvent: |
|
|
|
|
for _, event := range ev.queue { |
|
|
|
|
switch event := event.(type) { |
|
|
|
|
case ChainEvent: |
|
|
|
|
// We need some control over the mining operation. Acquiring locks and waiting for the miner to create new block takes too long
|
|
|
|
|
// and in most cases isn't even necessary.
|
|
|
|
|
if self.currentBlock.Hash() == event.Hash { |
|
|
|
|
self.currentGasLimit = CalcGasLimit(event.Block) |
|
|
|
|
self.eventMux.Post(ChainHeadEvent{event.Block}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
self.eventMux.Post(event) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
case <-futureTimer: |
|
|
|
|
self.procFutureBlocks() |
|
|
|
|
case <-self.quit: |
|
|
|
|
break out |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|