diff options
Diffstat (limited to 'miner/worker.go')
-rw-r--r-- | miner/worker.go | 80 |
1 files changed, 58 insertions, 22 deletions
diff --git a/miner/worker.go b/miner/worker.go index 4a52a40fe..e21765f9d 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -13,7 +13,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/pow" - "github.com/ethereum/go-ethereum/state" + "github.com/ethereum/go-ethereum/core/state" "gopkg.in/fatih/set.v0" ) @@ -24,7 +24,7 @@ type environment struct { state *state.StateDB coinbase *state.StateObject block *types.Block - ancestors *set.Set + family *set.Set uncles *set.Set } @@ -34,13 +34,10 @@ func env(block *types.Block, eth core.Backend) *environment { totalUsedGas: new(big.Int), state: state, block: block, - ancestors: set.New(), + family: set.New(), uncles: set.New(), coinbase: state.GetOrNewStateObject(block.Coinbase()), } - for _, ancestor := range eth.ChainManager().GetAncestors(block, 7) { - env.ancestors.Add(ancestor.Hash()) - } return env } @@ -75,17 +72,21 @@ type worker struct { current *environment + uncleMu sync.Mutex + possibleUncles map[common.Hash]*types.Block + mining bool } func newWorker(coinbase common.Address, eth core.Backend) *worker { return &worker{ - eth: eth, - mux: eth.EventMux(), - recv: make(chan Work), - chain: eth.ChainManager(), - proc: eth.BlockProcessor(), - coinbase: coinbase, + eth: eth, + mux: eth.EventMux(), + recv: make(chan Work), + chain: eth.ChainManager(), + proc: eth.BlockProcessor(), + possibleUncles: make(map[common.Hash]*types.Block), + coinbase: coinbase, } } @@ -115,7 +116,7 @@ func (self *worker) register(agent Agent) { } func (self *worker) update() { - events := self.mux.Subscribe(core.ChainHeadEvent{}, core.NewMinedBlockEvent{}) + events := self.mux.Subscribe(core.ChainHeadEvent{}, core.NewMinedBlockEvent{}, core.ChainSideEvent{}) timer := time.NewTicker(2 * time.Second) @@ -130,6 +131,10 @@ out: } case core.NewMinedBlockEvent: self.commitNewWork() + case core.ChainSideEvent: + self.uncleMu.Lock() + self.possibleUncles[ev.Block.Hash()] = ev.Block + self.uncleMu.Unlock() } case <-self.quit: // stop all agents @@ -145,6 +150,9 @@ out: events.Unsubscribe() } +func (self *worker) addUncle(uncle *types.Block) { +} + func (self *worker) wait() { for { for work := range self.recv { @@ -162,6 +170,10 @@ func (self *worker) wait() { }) if err := self.chain.InsertChain(types.Blocks{self.current.block}); err == nil { + for _, uncle := range self.current.block.Uncles() { + delete(self.possibleUncles, uncle.Hash()) + } + self.mux.Post(core.NewMinedBlockEvent{self.current.block}) } else { self.commitNewWork() @@ -191,15 +203,21 @@ func (self *worker) commitNewWork() { block := self.chain.NewBlock(self.coinbase) self.current = env(block, self.eth) + for _, ancestor := range self.chain.GetAncestors(block, 7) { + self.current.family.Add(ancestor.Hash()) + } + parent := self.chain.GetBlock(self.current.block.ParentHash()) self.current.coinbase.SetGasPool(core.CalcGasLimit(parent, self.current.block)) transactions := self.eth.TxPool().GetTransactions() sort.Sort(types.TxByNonce{transactions}) - minerlogger.Infof("committing new work with %d txs\n", len(transactions)) // Keep track of transactions which return errors so they can be removed - var remove types.Transactions + var ( + remove types.Transactions + tcount = 0 + ) gasLimit: for i, tx := range transactions { err := self.commitTransaction(tx) @@ -217,10 +235,30 @@ gasLimit: minerlogger.Infof("Gas limit reached for block. %d TXs included in this block\n", i) // Break on gas limit break gasLimit + default: + tcount++ } } self.eth.TxPool().RemoveSet(remove) + var uncles []*types.Header + for hash, uncle := range self.possibleUncles { + if len(uncles) == 2 { + break + } + + if err := self.commitUncle(uncle.Header()); err != nil { + minerlogger.Infof("Bad uncle found and will be removed (%x)\n", hash[:4]) + minerlogger.Debugln(uncle) + } else { + minerlogger.Infof("commiting %x as uncle\n", hash[:4]) + uncles = append(uncles, uncle.Header()) + } + } + minerlogger.Infof("commit new work with %d txs & %d uncles\n", tcount, len(uncles)) + + self.current.block.SetUncles(uncles) + self.current.state.AddBalance(self.coinbase, core.BlockReward) self.current.state.Update(common.Big0) @@ -240,18 +278,16 @@ func (self *worker) commitUncle(uncle *types.Header) error { } self.current.uncles.Add(uncle.Hash()) - if !self.current.ancestors.Has(uncle.ParentHash) { + if !self.current.family.Has(uncle.ParentHash) { return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } - if !self.pow.Verify(types.NewBlockWithHeader(uncle)) { - return core.ValidationError("Uncle's nonce is invalid (= %x)", uncle.Nonce) + if self.current.family.Has(uncle.Hash()) { + return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash())) } - uncleAccount := self.current.state.GetAccount(uncle.Coinbase) - uncleAccount.AddBalance(uncleReward) - - self.current.coinbase.AddBalance(uncleReward) + self.current.state.AddBalance(uncle.Coinbase, uncleReward) + self.current.state.AddBalance(self.coinbase, inclusionReward) return nil } |