diff options
-rw-r--r-- | cmd/geth/main.go | 2 | ||||
-rw-r--r-- | core/block_processor.go | 2 | ||||
-rw-r--r-- | eth/downloader/downloader.go | 69 | ||||
-rw-r--r-- | miner/worker.go | 10 |
4 files changed, 47 insertions, 36 deletions
diff --git a/cmd/geth/main.go b/cmd/geth/main.go index b4d7feed1..725f04efe 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -563,7 +563,7 @@ func upgradeDb(ctx *cli.Context) { bcVersion = core.BlockChainVersion } - filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("2006-01-02_15:04:05")) + filename := fmt.Sprintf("blockchain_%d_%s.chain", bcVersion, time.Now().Format("20060102_150405")) exportFile := filepath.Join(ctx.GlobalString(utils.DataDirFlag.Name), filename) err = utils.ExportChain(ethereum.ChainManager(), exportFile) diff --git a/core/block_processor.go b/core/block_processor.go index af47069ad..059c442cc 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -197,7 +197,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st // There can be at most two uncles if len(block.Uncles()) > 2 { - return nil, ValidationError("Block can only contain one uncle (contained %v)", len(block.Uncles())) + return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(block.Uncles())) } receipts, err := sm.TransitionState(state, parent, block, false) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 55455262a..85de78ebf 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -65,12 +65,15 @@ type Downloader struct { // Status synchronising int32 + notified int32 // Channels newPeerCh chan *peer hashCh chan hashPack blockCh chan blockPack - cancelCh chan struct{} + + cancelCh chan struct{} // Channel to cancel mid-flight syncs + cancelLock sync.RWMutex // Lock to protect the cancel channel in delivers } func New(hasBlock hashCheckFn, getBlock getBlockFn) *Downloader { @@ -83,7 +86,6 @@ func New(hasBlock hashCheckFn, getBlock getBlockFn) *Downloader { hashCh: make(chan hashPack, 1), blockCh: make(chan blockPack, 1), } - return downloader } @@ -123,8 +125,14 @@ func (d *Downloader) Synchronise(id string, hash common.Hash) error { } defer atomic.StoreInt32(&d.synchronising, 0) - // Create cancel channel for aborting midflight + // Post a user notification of the sync (only once per session) + if atomic.CompareAndSwapInt32(&d.notified, 0, 1) { + glog.V(logger.Info).Infoln("Block synchronisation started") + } + // Create cancel channel for aborting mid-flight + d.cancelLock.Lock() d.cancelCh = make(chan struct{}) + d.cancelLock.Unlock() // Abort if the queue still contains some leftover data if _, cached := d.queue.Size(); cached > 0 && d.queue.GetHeadBlock() != nil { @@ -183,32 +191,15 @@ func (d *Downloader) syncWithPeer(p *peer, hash common.Hash) (err error) { // Cancel cancels all of the operations and resets the queue. It returns true // if the cancel operation was completed. func (d *Downloader) Cancel() bool { - hs, bs := d.queue.Size() // If we're not syncing just return. + hs, bs := d.queue.Size() if atomic.LoadInt32(&d.synchronising) == 0 && hs == 0 && bs == 0 { return false } - + // Close the current cancel channel + d.cancelLock.RLock() close(d.cancelCh) - - // clean up -hashDone: - for { - select { - case <-d.hashCh: - default: - break hashDone - } - } - -blockDone: - for { - select { - case <-d.blockCh: - default: - break blockDone - } - } + d.cancelLock.RUnlock() // reset the queue d.queue.Reset() @@ -421,9 +412,18 @@ func (d *Downloader) DeliverBlocks(id string, blocks []*types.Block) error { if atomic.LoadInt32(&d.synchronising) == 0 { return errNoSyncActive } - d.blockCh <- blockPack{id, blocks} + // Deliver or abort if the sync is canceled while queuing + d.cancelLock.RLock() + cancel := d.cancelCh + d.cancelLock.RUnlock() - return nil + select { + case d.blockCh <- blockPack{id, blocks}: + return nil + + case <-cancel: + return errNoSyncActive + } } // DeliverHashes injects a new batch of hashes received from a remote node into @@ -434,11 +434,16 @@ func (d *Downloader) DeliverHashes(id string, hashes []common.Hash) error { if atomic.LoadInt32(&d.synchronising) == 0 { return errNoSyncActive } - if glog.V(logger.Debug) && len(hashes) != 0 { - from, to := hashes[0], hashes[len(hashes)-1] - glog.V(logger.Debug).Infof("adding %d (T=%d) hashes [ %x / %x ] from: %s\n", len(hashes), d.queue.Pending(), from[:4], to[:4], id) - } - d.hashCh <- hashPack{id, hashes} + // Deliver or abort if the sync is canceled while queuing + d.cancelLock.RLock() + cancel := d.cancelCh + d.cancelLock.RUnlock() - return nil + select { + case d.hashCh <- hashPack{id, hashes}: + return nil + + case <-cancel: + return errNoSyncActive + } } diff --git a/miner/worker.go b/miner/worker.go index 4316038d2..d5f9dd8c5 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -45,7 +45,8 @@ type environment struct { state *state.StateDB // apply state changes here coinbase *state.StateObject // the miner's account block *types.Block // the new block - family *set.Set // family set (used for checking uncles) + ancestors *set.Set // ancestor set (used for checking uncle parent validity) + family *set.Set // family set (used for checking uncle invalidity) uncles *set.Set // uncle set remove *set.Set // tx which will be removed tcount int // tx count in cycle @@ -62,6 +63,7 @@ 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()), @@ -264,7 +266,11 @@ func (self *worker) makeCurrent() { current := env(block, self.eth) for _, ancestor := range self.chain.GetAncestors(block, 7) { + for _, uncle := range ancestor.Uncles() { + current.family.Add(uncle.Hash()) + } current.family.Add(ancestor.Hash()) + current.ancestors.Add(ancestor.Hash()) } accounts, _ := self.eth.AccountManager().Accounts() // Keep track of transactions which return errors so they can be removed @@ -362,7 +368,7 @@ func (self *worker) commitUncle(uncle *types.Header) error { } self.current.uncles.Add(uncle.Hash()) - if !self.current.family.Has(uncle.ParentHash) { + if !self.current.ancestors.Has(uncle.ParentHash) { return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4])) } |