aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/main.go2
-rw-r--r--core/block_processor.go2
-rw-r--r--eth/downloader/downloader.go69
-rw-r--r--miner/worker.go10
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]))
}