Skip to content

Commit 1f4ac6b

Browse files
committed
Merge pull request ethereum#1587 from obscuren/miner-race
miner: fixed worker race condition
2 parents 56219a5 + d8590d9 commit 1f4ac6b

File tree

1 file changed

+44
-43
lines changed

1 file changed

+44
-43
lines changed

miner/worker.go

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,9 @@ func (self *worker) wait() {
263263
continue
264264
}
265265
block := result.Block
266+
work := result.Work
266267

267-
self.current.state.Sync()
268+
work.state.Sync()
268269
if self.fullValidation {
269270
if _, err := self.chain.InsertChain(types.Blocks{block}); err != nil {
270271
glog.V(logger.Error).Infoln("mining err", err)
@@ -292,7 +293,7 @@ func (self *worker) wait() {
292293
// This puts transactions in a extra db for rpc
293294
core.PutTransactions(self.extraDb, block, block.Transactions())
294295
// store the receipts
295-
core.PutReceipts(self.extraDb, self.current.receipts)
296+
core.PutReceipts(self.extraDb, work.receipts)
296297
}
297298

298299
// broadcast before waiting for validation
@@ -303,7 +304,7 @@ func (self *worker) wait() {
303304
self.mux.Post(core.ChainHeadEvent{block})
304305
self.mux.Post(logs)
305306
}
306-
}(block, self.current.state.Logs())
307+
}(block, work.state.Logs())
307308
}
308309

309310
// check staleness and display confirmation
@@ -313,7 +314,7 @@ func (self *worker) wait() {
313314
stale = "stale "
314315
} else {
315316
confirm = "Wait 5 blocks for confirmation"
316-
self.current.localMinedBlocks = newLocalMinedBlock(block.Number().Uint64(), self.current.localMinedBlocks)
317+
work.localMinedBlocks = newLocalMinedBlock(block.Number().Uint64(), work.localMinedBlocks)
317318
}
318319
glog.V(logger.Info).Infof("🔨 Mined %sblock (#%v / %x). %s", stale, block.Number(), block.Hash().Bytes()[:4], confirm)
319320

@@ -322,9 +323,9 @@ func (self *worker) wait() {
322323
}
323324
}
324325

325-
func (self *worker) push() {
326+
func (self *worker) push(work *Work) {
326327
if atomic.LoadInt32(&self.mining) == 1 {
327-
if core.Canary(self.current.state) {
328+
if core.Canary(work.state) {
328329
glog.Infoln("Toxicity levels rising to deadly levels. Your canary has died. You can go back or continue down the mineshaft --more--")
329330
glog.Infoln("You turn back and abort mining")
330331
return
@@ -335,7 +336,7 @@ func (self *worker) push() {
335336
atomic.AddInt32(&self.atWork, 1)
336337

337338
if agent.Work() != nil {
338-
agent.Work() <- self.current
339+
agent.Work() <- work
339340
}
340341
}
341342
}
@@ -344,7 +345,7 @@ func (self *worker) push() {
344345
// makeCurrent creates a new environment for the current cycle.
345346
func (self *worker) makeCurrent(parent *types.Block, header *types.Header) {
346347
state := state.New(parent.Root(), self.eth.StateDb())
347-
current := &Work{
348+
work := &Work{
348349
state: state,
349350
ancestors: set.New(),
350351
family: set.New(),
@@ -357,23 +358,23 @@ func (self *worker) makeCurrent(parent *types.Block, header *types.Header) {
357358
// when 08 is processed ancestors contain 07 (quick block)
358359
for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) {
359360
for _, uncle := range ancestor.Uncles() {
360-
current.family.Add(uncle.Hash())
361+
work.family.Add(uncle.Hash())
361362
}
362-
current.family.Add(ancestor.Hash())
363-
current.ancestors.Add(ancestor.Hash())
363+
work.family.Add(ancestor.Hash())
364+
work.ancestors.Add(ancestor.Hash())
364365
}
365366
accounts, _ := self.eth.AccountManager().Accounts()
366367

367368
// Keep track of transactions which return errors so they can be removed
368-
current.remove = set.New()
369-
current.tcount = 0
370-
current.ignoredTransactors = set.New()
371-
current.lowGasTransactors = set.New()
372-
current.ownedAccounts = accountAddressesSet(accounts)
369+
work.remove = set.New()
370+
work.tcount = 0
371+
work.ignoredTransactors = set.New()
372+
work.lowGasTransactors = set.New()
373+
work.ownedAccounts = accountAddressesSet(accounts)
373374
if self.current != nil {
374-
current.localMinedBlocks = self.current.localMinedBlocks
375+
work.localMinedBlocks = self.current.localMinedBlocks
375376
}
376-
self.current = current
377+
self.current = work
377378
}
378379

379380
func (w *worker) setGasPrice(p *big.Int) {
@@ -387,13 +388,13 @@ func (w *worker) setGasPrice(p *big.Int) {
387388
w.mux.Post(core.GasPriceChanged{w.gasPrice})
388389
}
389390

390-
func (self *worker) isBlockLocallyMined(deepBlockNum uint64) bool {
391+
func (self *worker) isBlockLocallyMined(current *Work, deepBlockNum uint64) bool {
391392
//Did this instance mine a block at {deepBlockNum} ?
392393
var isLocal = false
393-
for idx, blockNum := range self.current.localMinedBlocks.ints {
394+
for idx, blockNum := range current.localMinedBlocks.ints {
394395
if deepBlockNum == blockNum {
395396
isLocal = true
396-
self.current.localMinedBlocks.ints[idx] = 0 //prevent showing duplicate logs
397+
current.localMinedBlocks.ints[idx] = 0 //prevent showing duplicate logs
397398
break
398399
}
399400
}
@@ -407,12 +408,12 @@ func (self *worker) isBlockLocallyMined(deepBlockNum uint64) bool {
407408
return block != nil && block.Coinbase() == self.coinbase
408409
}
409410

410-
func (self *worker) logLocalMinedBlocks(previous *Work) {
411-
if previous != nil && self.current.localMinedBlocks != nil {
412-
nextBlockNum := self.current.Block.NumberU64()
411+
func (self *worker) logLocalMinedBlocks(current, previous *Work) {
412+
if previous != nil && current.localMinedBlocks != nil {
413+
nextBlockNum := current.Block.NumberU64()
413414
for checkBlockNum := previous.Block.NumberU64(); checkBlockNum < nextBlockNum; checkBlockNum++ {
414415
inspectBlockNum := checkBlockNum - miningLogAtDepth
415-
if self.isBlockLocallyMined(inspectBlockNum) {
416+
if self.isBlockLocallyMined(current, inspectBlockNum) {
416417
glog.V(logger.Info).Infof("🔨 🔗 Mined %d blocks back: block #%v", miningLogAtDepth, inspectBlockNum)
417418
}
418419
}
@@ -454,14 +455,14 @@ func (self *worker) commitNewWork() {
454455

455456
previous := self.current
456457
self.makeCurrent(parent, header)
457-
current := self.current
458+
work := self.current
458459

459460
// commit transactions for this run.
460461
transactions := self.eth.TxPool().GetTransactions()
461462
sort.Sort(types.TxByNonce{transactions})
462-
current.coinbase.SetGasLimit(header.GasLimit)
463-
current.commitTransactions(transactions, self.gasPrice, self.proc)
464-
self.eth.TxPool().RemoveTransactions(current.lowGasTxs)
463+
work.coinbase.SetGasLimit(header.GasLimit)
464+
work.commitTransactions(transactions, self.gasPrice, self.proc)
465+
self.eth.TxPool().RemoveTransactions(work.lowGasTxs)
465466

466467
// compute uncles for the new block.
467468
var (
@@ -472,7 +473,7 @@ func (self *worker) commitNewWork() {
472473
if len(uncles) == 2 {
473474
break
474475
}
475-
if err := self.commitUncle(uncle.Header()); err != nil {
476+
if err := self.commitUncle(work, uncle.Header()); err != nil {
476477
if glog.V(logger.Ridiculousness) {
477478
glog.V(logger.Detail).Infof("Bad uncle found and will be removed (%x)\n", hash[:4])
478479
glog.V(logger.Detail).Infoln(uncle)
@@ -489,36 +490,36 @@ func (self *worker) commitNewWork() {
489490

490491
if atomic.LoadInt32(&self.mining) == 1 {
491492
// commit state root after all state transitions.
492-
core.AccumulateRewards(self.current.state, header, uncles)
493-
current.state.SyncObjects()
494-
header.Root = current.state.Root()
493+
core.AccumulateRewards(work.state, header, uncles)
494+
work.state.SyncObjects()
495+
header.Root = work.state.Root()
495496
}
496497

497498
// create the new block whose nonce will be mined.
498-
current.Block = types.NewBlock(header, current.txs, uncles, current.receipts)
499-
self.current.Block.Td = new(big.Int).Set(core.CalcTD(self.current.Block, self.chain.GetBlock(self.current.Block.ParentHash())))
499+
work.Block = types.NewBlock(header, work.txs, uncles, work.receipts)
500+
work.Block.Td = new(big.Int).Set(core.CalcTD(work.Block, self.chain.GetBlock(work.Block.ParentHash())))
500501

501502
// We only care about logging if we're actually mining.
502503
if atomic.LoadInt32(&self.mining) == 1 {
503-
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", current.Block.Number(), current.tcount, len(uncles), time.Since(tstart))
504-
self.logLocalMinedBlocks(previous)
504+
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", work.Block.Number(), work.tcount, len(uncles), time.Since(tstart))
505+
self.logLocalMinedBlocks(work, previous)
505506
}
506507

507-
self.push()
508+
self.push(work)
508509
}
509510

510-
func (self *worker) commitUncle(uncle *types.Header) error {
511+
func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
511512
hash := uncle.Hash()
512-
if self.current.uncles.Has(hash) {
513+
if work.uncles.Has(hash) {
513514
return core.UncleError("Uncle not unique")
514515
}
515-
if !self.current.ancestors.Has(uncle.ParentHash) {
516+
if !work.ancestors.Has(uncle.ParentHash) {
516517
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
517518
}
518-
if self.current.family.Has(hash) {
519+
if work.family.Has(hash) {
519520
return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", hash))
520521
}
521-
self.current.uncles.Add(uncle.Hash())
522+
work.uncles.Add(uncle.Hash())
522523
return nil
523524
}
524525

0 commit comments

Comments
 (0)