eth: fix data race accessing peer.recentHash
This commit is contained in:
parent
05cae69d72
commit
44147d057d
@ -157,7 +157,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
|
|||||||
}
|
}
|
||||||
defer pm.removePeer(p.id)
|
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
|
return err
|
||||||
}
|
}
|
||||||
// propagate existing transactions. new transactions appearing
|
// 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
|
// Mark the hashes as present at the remote node
|
||||||
for _, hash := range hashes {
|
for _, hash := range hashes {
|
||||||
p.blockHashes.Add(hash)
|
p.blockHashes.Add(hash)
|
||||||
p.recentHash = hash
|
p.SetHead(hash)
|
||||||
}
|
}
|
||||||
// Schedule all the unknown hashes for retrieval
|
// Schedule all the unknown hashes for retrieval
|
||||||
unknown := make([]common.Hash, 0, len(hashes))
|
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)
|
// Mark the block as present at the remote node (don't duplicate already held data)
|
||||||
p.blockHashes.Add(hash)
|
p.blockHashes.Add(hash)
|
||||||
p.recentHash = hash
|
p.SetHead(hash)
|
||||||
if td != nil {
|
if td != nil {
|
||||||
p.td = td
|
p.td = td
|
||||||
}
|
}
|
||||||
|
27
eth/peer.go
27
eth/peer.go
@ -40,10 +40,12 @@ type peer struct {
|
|||||||
|
|
||||||
protv, netid int
|
protv, netid int
|
||||||
|
|
||||||
recentHash common.Hash
|
|
||||||
id string
|
id string
|
||||||
td *big.Int
|
td *big.Int
|
||||||
|
|
||||||
|
head common.Hash
|
||||||
|
headLock sync.RWMutex
|
||||||
|
|
||||||
genesis, ourHash common.Hash
|
genesis, ourHash common.Hash
|
||||||
ourTd *big.Int
|
ourTd *big.Int
|
||||||
|
|
||||||
@ -51,14 +53,14 @@ type peer struct {
|
|||||||
blockHashes *set.Set
|
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()
|
id := p.ID()
|
||||||
|
|
||||||
return &peer{
|
return &peer{
|
||||||
Peer: p,
|
Peer: p,
|
||||||
rw: rw,
|
rw: rw,
|
||||||
genesis: genesis,
|
genesis: genesis,
|
||||||
ourHash: recentHash,
|
ourHash: head,
|
||||||
ourTd: td,
|
ourTd: td,
|
||||||
protv: protv,
|
protv: protv,
|
||||||
netid: netid,
|
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
|
// 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
|
// 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
|
// 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
|
// Set the total difficulty of the peer
|
||||||
p.td = status.TD
|
p.td = status.TD
|
||||||
// set the best hash of the peer
|
// set the best hash of the peer
|
||||||
p.recentHash = status.CurrentBlock
|
p.head = status.CurrentBlock
|
||||||
|
|
||||||
return <-errc
|
return <-errc
|
||||||
}
|
}
|
||||||
|
@ -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
|
// 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.
|
// much higher than ours, something is wrong with us or the peer.
|
||||||
// Check if the hash is on our own chain
|
// 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")
|
glog.V(logger.Debug).Infoln("Synchronisation canceled: head already known")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Get the hashes from the peer (synchronously)
|
// 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 {
|
switch err {
|
||||||
case nil:
|
case nil:
|
||||||
glog.V(logger.Detail).Infof("Synchronisation completed")
|
glog.V(logger.Detail).Infof("Synchronisation completed")
|
||||||
|
Loading…
Reference in New Issue
Block a user