diff options
-rw-r--r-- | core/block_cache.go | 5 | ||||
-rw-r--r-- | core/events.go | 4 | ||||
-rw-r--r-- | miner/worker.go | 58 |
3 files changed, 52 insertions, 15 deletions
diff --git a/core/block_cache.go b/core/block_cache.go index 321021eb4..ea39e78e8 100644 --- a/core/block_cache.go +++ b/core/block_cache.go @@ -66,3 +66,8 @@ func (bc *BlockCache) Get(hash common.Hash) *types.Block { return nil } + +func (bc *BlockCache) Has(hash common.Hash) bool { + _, ok := bc.blocks[hash] + return ok +} diff --git a/core/events.go b/core/events.go index 8c5fb592a..b93f27c51 100644 --- a/core/events.go +++ b/core/events.go @@ -38,6 +38,10 @@ type PendingBlockEvent struct { Logs state.Logs } +type ChainUncleEvent struct { + Block *types.Block +} + type ChainHeadEvent struct{ Block *types.Block } // Mining operation events diff --git a/miner/worker.go b/miner/worker.go index 4a52a40fe..b4b9cb943 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -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.ChainSplitEvent: + 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 { @@ -191,6 +199,10 @@ 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)) @@ -221,6 +233,22 @@ gasLimit: } self.eth.TxPool().RemoveSet(remove) + ucount := 0 + for hash, uncle := range self.possibleUncles { + if ucount == 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]) + ucount++ + } + } + minerlogger.Infoln("Included %d uncle(s)") + self.current.state.AddBalance(self.coinbase, core.BlockReward) self.current.state.Update(common.Big0) @@ -240,12 +268,12 @@ 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) |