mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 06:06:44 +00:00
sync 3
This commit is contained in:
parent
4d6c54dbf6
commit
6e3dc9806d
4 changed files with 51 additions and 21 deletions
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
35
les/peer.go
35
les/peer.go
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
23
les/sync.go
23
les/sync.go
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue