aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2015-06-09 19:27:44 +0800
committerPéter Szilágyi <peterke@gmail.com>2015-06-09 19:27:44 +0800
commit44147d057dd91d8b35dd6f4ed025bdb4baf225eb (patch)
tree0747516ad8924a1e61ceb97936419d9c3f41ffd1
parent05cae69d7295a924a4d2aeb49d23869047451e08 (diff)
downloadgo-tangerine-44147d057dd91d8b35dd6f4ed025bdb4baf225eb.tar.gz
go-tangerine-44147d057dd91d8b35dd6f4ed025bdb4baf225eb.tar.zst
go-tangerine-44147d057dd91d8b35dd6f4ed025bdb4baf225eb.zip
eth: fix data race accessing peer.recentHash
-rw-r--r--eth/handler.go6
-rw-r--r--eth/peer.go31
-rw-r--r--eth/sync.go7
3 files changed, 32 insertions, 12 deletions
diff --git a/eth/handler.go b/eth/handler.go
index 64f89b273..847e7a0e8 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -157,7 +157,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
}
defer pm.removePeer(p.id)
- if err := pm.downloader.RegisterPeer(p.id, p.recentHash, p.requestHashes, p.requestBlocks); err != nil {
+ if err := pm.downloader.RegisterPeer(p.id, p.Head(), p.requestHashes, p.requestBlocks); err != nil {
return err
}
// propagate existing transactions. new transactions appearing
@@ -303,7 +303,7 @@ func (self *ProtocolManager) handleMsg(p *peer) error {
// Mark the hashes as present at the remote node
for _, hash := range hashes {
p.blockHashes.Add(hash)
- p.recentHash = hash
+ p.SetHead(hash)
}
// Schedule all the unknown hashes for retrieval
unknown := make([]common.Hash, 0, len(hashes))
@@ -354,7 +354,7 @@ func (pm *ProtocolManager) importBlock(p *peer, block *types.Block, td *big.Int)
// Mark the block as present at the remote node (don't duplicate already held data)
p.blockHashes.Add(hash)
- p.recentHash = hash
+ p.SetHead(hash)
if td != nil {
p.td = td
}
diff --git a/eth/peer.go b/eth/peer.go
index cf2c58ec9..5f5007891 100644
--- a/eth/peer.go
+++ b/eth/peer.go
@@ -40,9 +40,11 @@ type peer struct {
protv, netid int
- recentHash common.Hash
- id string
- td *big.Int
+ id string
+ td *big.Int
+
+ head common.Hash
+ headLock sync.RWMutex
genesis, ourHash common.Hash
ourTd *big.Int
@@ -51,14 +53,14 @@ type peer struct {
blockHashes *set.Set
}
-func newPeer(protv, netid int, genesis, recentHash common.Hash, td *big.Int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
+func newPeer(protv, netid int, genesis, head common.Hash, td *big.Int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
id := p.ID()
return &peer{
Peer: p,
rw: rw,
genesis: genesis,
- ourHash: recentHash,
+ ourHash: head,
ourTd: td,
protv: protv,
netid: netid,
@@ -68,6 +70,23 @@ func newPeer(protv, netid int, genesis, recentHash common.Hash, td *big.Int, p *
}
}
+// Head retrieves a copy of the current head (most recent) hash of the peer.
+func (p *peer) Head() (hash common.Hash) {
+ p.headLock.RLock()
+ defer p.headLock.RUnlock()
+
+ copy(hash[:], p.head[:])
+ return hash
+}
+
+// SetHead updates the head (most recent) hash of the peer.
+func (p *peer) SetHead(hash common.Hash) {
+ p.headLock.Lock()
+ defer p.headLock.Unlock()
+
+ copy(p.head[:], hash[:])
+}
+
// sendTransactions sends transactions to the peer and includes the hashes
// in it's tx hash set for future reference. The tx hash will allow the
// manager to check whether the peer has already received this particular
@@ -160,7 +179,7 @@ func (p *peer) handleStatus() error {
// Set the total difficulty of the peer
p.td = status.TD
// set the best hash of the peer
- p.recentHash = status.CurrentBlock
+ p.head = status.CurrentBlock
return <-errc
}
diff --git a/eth/sync.go b/eth/sync.go
index dd7414da8..b3184364f 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -214,14 +214,15 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
// FIXME if we have the hash in our chain and the TD of the peer is
// much higher than ours, something is wrong with us or the peer.
// Check if the hash is on our own chain
- if pm.chainman.HasBlock(peer.recentHash) {
+ head := peer.Head()
+ if pm.chainman.HasBlock(head) {
glog.V(logger.Debug).Infoln("Synchronisation canceled: head already known")
return
}
// Get the hashes from the peer (synchronously)
- glog.V(logger.Detail).Infof("Attempting synchronisation: %v, 0x%x", peer.id, peer.recentHash)
+ glog.V(logger.Detail).Infof("Attempting synchronisation: %v, 0x%x", peer.id, head)
- err := pm.downloader.Synchronise(peer.id, peer.recentHash)
+ err := pm.downloader.Synchronise(peer.id, head)
switch err {
case nil:
glog.V(logger.Detail).Infof("Synchronisation completed")