This commit is contained in:
zsfelfoldi 2016-06-24 19:41:23 +02:00
parent 4d6c54dbf6
commit 6e3dc9806d
4 changed files with 51 additions and 21 deletions

View file

@ -107,6 +107,9 @@ type ProtocolManager struct {
quitSync chan struct{} quitSync chan struct{}
noMorePeers chan struct{} noMorePeers chan struct{}
syncMu sync.Mutex
syncing uint32
// wait group is used for graceful shutdowns during downloading // wait group is used for graceful shutdowns during downloading
// and processing // and processing
wg sync.WaitGroup wg sync.WaitGroup
@ -171,7 +174,7 @@ func NewProtocolManager(chainConfig *core.ChainConfig, lightSync bool, networkId
manager.downloader = downloader.New(downloader.LightSync, chainDb, manager.eventMux, blockchain.HasHeader, nil, blockchain.GetHeaderByHash, manager.downloader = downloader.New(downloader.LightSync, chainDb, manager.eventMux, blockchain.HasHeader, nil, blockchain.GetHeaderByHash,
nil, blockchain.CurrentHeader, nil, nil, nil, blockchain.GetTdByHash, nil, blockchain.CurrentHeader, nil, nil, nil, blockchain.GetTdByHash,
blockchain.InsertHeaderChain, nil, nil, blockchain.Rollback, func(id string) {}) // manager.removePeer) blockchain.InsertHeaderChain, nil, nil, blockchain.Rollback, func(id string) {}) // manager.removePeer)
manager.fetcher = newLightFetcher(odr, blockchain) manager.fetcher = newLightFetcher(manager)
} }
/*validator := func(block *types.Block, parent *types.Block) error { /*validator := func(block *types.Block, parent *types.Block) error {
@ -252,7 +255,8 @@ func (pm *ProtocolManager) handle(p *peer) error {
// Execute the LES handshake // Execute the LES handshake
td, head, genesis := pm.blockchain.Status() td, head, genesis := pm.blockchain.Status()
if err := p.Handshake(td, head, genesis, pm.server); err != nil { headNum := core.GetBlockNumber(pm.chainDb, head)
if err := p.Handshake(td, head, headNum, genesis, pm.server); err != nil {
glog.V(logger.Debug).Infof("%v: handshake failed: %v", p, err) glog.V(logger.Debug).Infof("%v: handshake failed: %v", p, err)
return err return err
} }

View file

@ -54,8 +54,8 @@ type peer struct {
id string id string
head common.Hash headInfo blockInfo
td *big.Int number uint64
lock sync.RWMutex lock sync.RWMutex
knownBlocks *set.Set // Set of block hashes known to be known by this peer knownBlocks *set.Set // Set of block hashes known to be known by this peer
@ -92,16 +92,23 @@ func (p *peer) Head() (hash common.Hash) {
p.lock.RLock() p.lock.RLock()
defer p.lock.RUnlock() defer p.lock.RUnlock()
copy(hash[:], p.head[:]) copy(hash[:], p.headInfo.Hash[:])
return hash return hash
} }
func (p *peer) headBlockInfo() blockInfo {
p.lock.RLock()
defer p.lock.RUnlock()
return p.headInfo
}
// Td retrieves the current total difficulty of a peer. // Td retrieves the current total difficulty of a peer.
func (p *peer) Td() *big.Int { func (p *peer) Td() *big.Int {
p.lock.RLock() p.lock.RLock()
defer p.lock.RUnlock() defer p.lock.RUnlock()
return new(big.Int).Set(p.td) return new(big.Int).Set(p.headInfo.Td)
} }
func sendRequest(w p2p.MsgWriter, msgcode, reqID, cost uint64, data interface{}) error { func sendRequest(w p2p.MsgWriter, msgcode, reqID, cost uint64, data interface{}) error {
@ -273,15 +280,16 @@ func (p *peer) sendReceiveHandshake(sendList keyValueList) (keyValueList, error)
// Handshake executes the les protocol handshake, negotiating version number, // Handshake executes the les protocol handshake, negotiating version number,
// network IDs, difficulties, head and genesis blocks. // network IDs, difficulties, head and genesis blocks.
func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash, server *LesServer) error { func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, server *LesServer) error {
p.lock.Lock() p.lock.Lock()
defer p.lock.Unlock() defer p.lock.Unlock()
var send keyValueList var send keyValueList
send = send.add("protocolVersion", uint64(p.version)) send = send.add("protocolVersion", uint64(p.version))
send = send.add("networkId", uint64(p.network)) send = send.add("networkId", uint64(p.network))
send = send.add("td", td) send = send.add("headTd", td)
send = send.add("bestHash", head) send = send.add("headHash", head)
send = send.add("headNum", headNum)
send = send.add("genesisHash", genesis) send = send.add("genesisHash", genesis)
if server != nil { if server != nil {
send = send.add("serveHeaders", nil) send = send.add("serveHeaders", nil)
@ -300,8 +308,8 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash, ser
} }
recv := recvList.decode() recv := recvList.decode()
var rGenesis, rBest common.Hash var rGenesis, rHash common.Hash
var rVersion, rNetwork uint64 var rVersion, rNetwork, rNum uint64
var rTd *big.Int var rTd *big.Int
if err := recv.get("protocolVersion", &rVersion); err != nil { if err := recv.get("protocolVersion", &rVersion); err != nil {
@ -310,10 +318,13 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash, ser
if err := recv.get("networkId", &rNetwork); err != nil { if err := recv.get("networkId", &rNetwork); err != nil {
return err return err
} }
if err := recv.get("td", &rTd); err != nil { if err := recv.get("headTd", &rTd); err != nil {
return err return err
} }
if err := recv.get("bestHash", &rBest); err != nil { if err := recv.get("headHash", &rHash); err != nil {
return err
}
if err := recv.get("headNum", &rNum); err != nil {
return err return err
} }
if err := recv.get("genesisHash", &rGenesis); err != nil { if err := recv.get("genesisHash", &rGenesis); err != nil {
@ -359,7 +370,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, genesis common.Hash, ser
p.fcCosts = MRC.decode() p.fcCosts = MRC.decode()
} }
// Configure the remote peer, and sanity check out handshake too // Configure the remote peer, and sanity check out handshake too
p.td, p.head = rTd, rBest p.headInfo.Td, p.headInfo.Hash, p.headInfo.Number = rTd, rHash, rNum
return nil return nil
} }

View file

@ -124,8 +124,8 @@ type statusData struct {
} }
// newBlockHashesData is the network packet for the block announcements. // newBlockHashesData is the network packet for the block announcements.
type newBlockHashesData []newBlockHashData type newBlockHashesData []blockInfo
type newBlockHashData struct { type blockInfo struct {
Hash common.Hash // Hash of one particular block being announced Hash common.Hash // Hash of one particular block being announced
Number uint64 // Number of one particular block being announced Number uint64 // Number of one particular block being announced
Td *big.Int // Total difficulty of one particular block being announced Td *big.Int // Total difficulty of one particular block being announced

View file

@ -17,8 +17,10 @@
package les package les
import ( import (
"sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
) )
@ -56,18 +58,31 @@ func (pm *ProtocolManager) syncer() {
} }
} }
func (pm *ProtocolManager) needToSync(peerHead blockInfo) bool {
head := pm.blockchain.CurrentHeader()
currentTd := core.GetTd(pm.chainDb, head.Hash(), head.Number.Uint64())
return peerHead.Td.Cmp(currentTd) > 0
}
// synchronise tries to sync up our local block chain with a remote peer. // synchronise tries to sync up our local block chain with a remote peer.
func (pm *ProtocolManager) synchronise(peer *peer) { func (pm *ProtocolManager) synchronise(peer *peer) {
// Short circuit if no peers are available // Short circuit if no peers are available
if peer == nil { if peer == nil {
return return
} }
// Make sure the peer's TD is higher than our own. // Make sure the peer's TD is higher than our own.
td := pm.blockchain.GetTdByHash(pm.blockchain.LastBlockHash()) if !pm.needToSync(peer.headBlockInfo()) {
if peer.Td().Cmp(td) <= 0 {
return return
} }
if pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync) != nil {
return pm.syncMu.Lock()
pm.syncWithoutLock(peer)
pm.syncMu.Unlock()
} }
func (pm *ProtocolManager) syncWithoutLock(peer *peer) {
atomic.StoreUint32(&pm.syncing, 1)
pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync)
atomic.StoreUint32(&pm.syncing, 0)
} }