mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
les: address comments
This commit is contained in:
parent
16d2323590
commit
15d3b0a05c
10 changed files with 228 additions and 201 deletions
|
|
@ -49,6 +49,7 @@ import (
|
||||||
type LightEthereum struct {
|
type LightEthereum struct {
|
||||||
lesCommons
|
lesCommons
|
||||||
|
|
||||||
|
peers *serverPeerSet
|
||||||
reqDist *requestDistributor
|
reqDist *requestDistributor
|
||||||
retriever *retrieveManager
|
retriever *retrieveManager
|
||||||
odr *LesOdr
|
odr *LesOdr
|
||||||
|
|
@ -80,7 +81,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
}
|
}
|
||||||
log.Info("Initialised chain configuration", "config", chainConfig)
|
log.Info("Initialised chain configuration", "config", chainConfig)
|
||||||
|
|
||||||
peers := newPeerSet(true)
|
peers := newServerPeerSet()
|
||||||
leth := &LightEthereum{
|
leth := &LightEthereum{
|
||||||
lesCommons: lesCommons{
|
lesCommons: lesCommons{
|
||||||
genesis: genesisHash,
|
genesis: genesisHash,
|
||||||
|
|
@ -88,9 +89,9 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
|
||||||
chainConfig: chainConfig,
|
chainConfig: chainConfig,
|
||||||
iConfig: light.DefaultClientIndexerConfig,
|
iConfig: light.DefaultClientIndexerConfig,
|
||||||
chainDb: chainDb,
|
chainDb: chainDb,
|
||||||
peers: peers,
|
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
},
|
},
|
||||||
|
peers: peers,
|
||||||
eventMux: ctx.EventMux,
|
eventMux: ctx.EventMux,
|
||||||
reqDist: newRequestDistributor(peers, &mclock.System{}),
|
reqDist: newRequestDistributor(peers, &mclock.System{}),
|
||||||
accountManager: ctx.AccountManager,
|
accountManager: ctx.AccountManager,
|
||||||
|
|
@ -225,7 +226,7 @@ func (s *LightEthereum) EventMux() *event.TypeMux { return s.eventMux
|
||||||
// network protocols to start.
|
// network protocols to start.
|
||||||
func (s *LightEthereum) Protocols() []p2p.Protocol {
|
func (s *LightEthereum) Protocols() []p2p.Protocol {
|
||||||
return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
return s.makeProtocols(ClientProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
||||||
if p := s.peers.serverPeer(peerIdToString(id)); p != nil {
|
if p := s.peers.peer(peerIdToString(id)); p != nil {
|
||||||
return p.Info()
|
return p.Info()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,6 @@ type lesCommons struct {
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
iConfig *light.IndexerConfig
|
iConfig *light.IndexerConfig
|
||||||
chainDb ethdb.Database
|
chainDb ethdb.Database
|
||||||
peers *peerSet
|
|
||||||
chainReader chainReader
|
chainReader chainReader
|
||||||
chtIndexer, bloomTrieIndexer *core.ChainIndexer
|
chtIndexer, bloomTrieIndexer *core.ChainIndexer
|
||||||
oracle *checkpointoracle.CheckpointOracle
|
oracle *checkpointoracle.CheckpointOracle
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,7 @@ type distReq struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// newRequestDistributor creates a new request distributor
|
// newRequestDistributor creates a new request distributor
|
||||||
func newRequestDistributor(peers *peerSet, clock mclock.Clock) *requestDistributor {
|
func newRequestDistributor(peers *serverPeerSet, clock mclock.Clock) *requestDistributor {
|
||||||
d := &requestDistributor{
|
d := &requestDistributor{
|
||||||
clock: clock,
|
clock: clock,
|
||||||
reqQueue: list.New(),
|
reqQueue: list.New(),
|
||||||
|
|
|
||||||
349
les/peer.go
349
les/peer.go
|
|
@ -163,11 +163,11 @@ func (p *peerCommons) queueSend(f func()) bool {
|
||||||
|
|
||||||
// mustQueueSend starts a for loop and retry the caching if failed.
|
// mustQueueSend starts a for loop and retry the caching if failed.
|
||||||
// If the stopCh is closed, then it returns.
|
// If the stopCh is closed, then it returns.
|
||||||
func (p *peerCommons) mustQueueSend(f func(), stopCh chan struct{}) {
|
func (p *peerCommons) mustQueueSend(f func()) {
|
||||||
for {
|
for {
|
||||||
// Check whether the stopCh is closed.
|
// Check whether the stopCh is closed.
|
||||||
select {
|
select {
|
||||||
case <-stopCh:
|
case <-p.closeCh:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
@ -198,8 +198,7 @@ func (p *peerCommons) Head() (hash common.Hash) {
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
defer p.lock.RUnlock()
|
defer p.lock.RUnlock()
|
||||||
|
|
||||||
copy(hash[:], p.headInfo.Hash[:])
|
return p.headInfo.Hash
|
||||||
return hash
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Td retrieves the current total difficulty of a peer.
|
// Td retrieves the current total difficulty of a peer.
|
||||||
|
|
@ -215,8 +214,7 @@ func (p *peerCommons) HeadAndTd() (hash common.Hash, td *big.Int) {
|
||||||
p.lock.RLock()
|
p.lock.RLock()
|
||||||
defer p.lock.RUnlock()
|
defer p.lock.RUnlock()
|
||||||
|
|
||||||
copy(hash[:], p.headInfo.Hash[:])
|
return p.headInfo.Hash, new(big.Int).Set(p.headInfo.Td)
|
||||||
return hash, new(big.Int).Set(p.headInfo.Td)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sendReceiveHandshake exchanges handshake packet with remote peer and returns any error
|
// sendReceiveHandshake exchanges handshake packet with remote peer and returns any error
|
||||||
|
|
@ -805,9 +803,7 @@ func (p *clientPeer) updateCapacity(cap uint64) {
|
||||||
var kvList keyValueList
|
var kvList keyValueList
|
||||||
kvList = kvList.add("flowControl/MRR", cap)
|
kvList = kvList.add("flowControl/MRR", cap)
|
||||||
kvList = kvList.add("flowControl/BL", cap*bufLimitRatio)
|
kvList = kvList.add("flowControl/BL", cap*bufLimitRatio)
|
||||||
|
p.mustQueueSend(func() { p.sendAnnounce(announceData{Update: kvList}) })
|
||||||
// todo(rjl493456442) please ensure the capacity upgrade function can be queued
|
|
||||||
p.mustQueueSend(func() { p.sendAnnounce(announceData{Update: kvList}) }, p.closeCh)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// freezeClient temporarily puts the client in a frozen state which means all
|
// freezeClient temporarily puts the client in a frozen state which means all
|
||||||
|
|
@ -900,223 +896,272 @@ func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, ge
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverPeerSubscriber is a callback interface to notify services about added or
|
// serverPeerSubscriber is an interface to notify services about added or
|
||||||
// removed server peers
|
// removed server peers
|
||||||
type serverPeerSubscriber interface {
|
type serverPeerSubscriber interface {
|
||||||
registerPeer(*serverPeer)
|
registerPeer(*serverPeer)
|
||||||
unregisterPeer(*serverPeer)
|
unregisterPeer(*serverPeer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// clientPeerSubscriber is a callback interface to notify services about added or
|
// clientPeerSubscriber is an interface to notify services about added or
|
||||||
// removed client peers
|
// removed client peers
|
||||||
type clientPeerSubscriber interface {
|
type clientPeerSubscriber interface {
|
||||||
registerPeer(*clientPeer)
|
registerPeer(*clientPeer)
|
||||||
unregisterPeer(*clientPeer)
|
unregisterPeer(*clientPeer)
|
||||||
}
|
}
|
||||||
|
|
||||||
// peerSet represents the collection of active peers currently participating in
|
// clientPeerSet represents the set of active client peers currently
|
||||||
// the Light Ethereum sub-protocol.
|
// participating in the Light Ethereum sub-protocol.
|
||||||
type peerSet struct {
|
type clientPeerSet struct {
|
||||||
serverPeers map[string]*serverPeer
|
peers map[string]*clientPeer
|
||||||
clientPeers map[string]*clientPeer
|
// subscribers is a batch of subscribers and peerset will notify
|
||||||
|
// these subscribers when the peerset changes(new client peer is
|
||||||
// sSubs is a batch of subscribers and peerset will notify these
|
// added or removed)
|
||||||
// subscribers when the peerset changes(new server peer is added
|
subscribers []clientPeerSubscriber
|
||||||
// or removed)
|
|
||||||
sSubs []serverPeerSubscriber
|
|
||||||
|
|
||||||
// cSubs is a batch of subscribers and peerset will notify these
|
|
||||||
// subscribers when the peerset changes(new client peer is added
|
|
||||||
// or removed)
|
|
||||||
cSubs []clientPeerSubscriber
|
|
||||||
|
|
||||||
closed bool
|
closed bool
|
||||||
client bool
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// newPeerSet creates a new peer set to track the active participants.
|
// newClientPeerSet creates a new peer set to track the client peers.
|
||||||
func newPeerSet(client bool) *peerSet {
|
func newClientPeerSet() *clientPeerSet {
|
||||||
set := &peerSet{client: client}
|
return &clientPeerSet{peers: make(map[string]*clientPeer)}
|
||||||
if client {
|
|
||||||
set.serverPeers = make(map[string]*serverPeer)
|
|
||||||
} else {
|
|
||||||
set.clientPeers = make(map[string]*clientPeer)
|
|
||||||
}
|
|
||||||
return set
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// subscribe adds a service to be notified about added or removed
|
// subscribe adds a service to be notified about added or removed
|
||||||
// peers and also register all active peers into the given service.
|
// peers and also register all active peers into the given service.
|
||||||
func (ps *peerSet) subscribe(s interface{}) {
|
func (ps *clientPeerSet) subscribe(sub clientPeerSubscriber) {
|
||||||
ps.lock.Lock()
|
ps.lock.Lock()
|
||||||
defer ps.lock.Unlock()
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
if ps.client {
|
ps.subscribers = append(ps.subscribers, sub)
|
||||||
sub := s.(serverPeerSubscriber)
|
for _, p := range ps.peers {
|
||||||
ps.sSubs = append(ps.sSubs, sub)
|
|
||||||
for _, p := range ps.serverPeers {
|
|
||||||
sub.registerPeer(p)
|
sub.registerPeer(p)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
sub := s.(clientPeerSubscriber)
|
|
||||||
ps.cSubs = append(ps.cSubs, sub)
|
|
||||||
for _, p := range ps.clientPeers {
|
|
||||||
sub.registerPeer(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unSubscribe removes the specified service from the subscriber pool.
|
// unSubscribe removes the specified service from the subscriber pool.
|
||||||
func (ps *peerSet) unSubscribe(s interface{}) {
|
func (ps *clientPeerSet) unSubscribe(sub clientPeerSubscriber) {
|
||||||
ps.lock.Lock()
|
ps.lock.Lock()
|
||||||
defer ps.lock.Unlock()
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
if ps.client {
|
for i, s := range ps.subscribers {
|
||||||
sub := s.(serverPeerSubscriber)
|
if s == sub {
|
||||||
for i, ss := range ps.sSubs {
|
ps.subscribers = append(ps.subscribers[:i], ps.subscribers[i+1:]...)
|
||||||
if ss == sub {
|
return
|
||||||
ps.sSubs = append(ps.sSubs[:i], ps.sSubs[i+1:]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sub := s.(clientPeerSubscriber)
|
|
||||||
for i, cs := range ps.cSubs {
|
|
||||||
if cs == sub {
|
|
||||||
ps.cSubs = append(ps.cSubs[:i], ps.cSubs[i+1:]...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register injects a new peer into the working set, or returns an error if the
|
// register adds a new peer into the peer set, or returns an error if the
|
||||||
// peer is already known.
|
// peer is already known.
|
||||||
func (ps *peerSet) register(p interface{}) error {
|
func (ps *clientPeerSet) register(peer *clientPeer) error {
|
||||||
ps.lock.Lock()
|
ps.lock.Lock()
|
||||||
defer ps.lock.Unlock()
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
if ps.closed {
|
if ps.closed {
|
||||||
return errClosed
|
return errClosed
|
||||||
}
|
}
|
||||||
if ps.client {
|
if _, exist := ps.peers[peer.id]; exist {
|
||||||
peer := p.(*serverPeer)
|
|
||||||
if _, exist := ps.serverPeers[peer.id]; exist {
|
|
||||||
return errAlreadyRegistered
|
return errAlreadyRegistered
|
||||||
}
|
}
|
||||||
ps.serverPeers[peer.id] = peer
|
ps.peers[peer.id] = peer
|
||||||
for _, sub := range ps.sSubs {
|
for _, sub := range ps.subscribers {
|
||||||
sub.registerPeer(peer)
|
sub.registerPeer(peer)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
peer := p.(*clientPeer)
|
|
||||||
if _, exist := ps.clientPeers[peer.id]; exist {
|
|
||||||
return errAlreadyRegistered
|
|
||||||
}
|
|
||||||
ps.clientPeers[peer.id] = peer
|
|
||||||
for _, sub := range ps.cSubs {
|
|
||||||
sub.registerPeer(peer)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unregister removes a remote peer from the active set, disabling any further
|
// unregister removes a remote peer from the peer set, disabling any further
|
||||||
// actions to/from that particular entity. It also initiates disconnection at the networking layer.
|
// actions to/from that particular entity. It also initiates disconnection
|
||||||
func (ps *peerSet) unregister(id string) error {
|
// at the networking layer.
|
||||||
|
func (ps *clientPeerSet) unregister(id string) error {
|
||||||
ps.lock.Lock()
|
ps.lock.Lock()
|
||||||
defer ps.lock.Unlock()
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
if ps.client {
|
p, ok := ps.peers[id]
|
||||||
p, ok := ps.serverPeers[id]
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return errNotRegistered
|
return errNotRegistered
|
||||||
}
|
}
|
||||||
delete(ps.serverPeers, id)
|
delete(ps.peers, id)
|
||||||
for _, sub := range ps.sSubs {
|
for _, sub := range ps.subscribers {
|
||||||
sub.unregisterPeer(p)
|
sub.unregisterPeer(p)
|
||||||
}
|
}
|
||||||
p.Peer.Disconnect(p2p.DiscUselessPeer)
|
p.Peer.Disconnect(p2p.DiscRequested)
|
||||||
} else {
|
|
||||||
p, ok := ps.clientPeers[id]
|
|
||||||
if !ok {
|
|
||||||
return errNotRegistered
|
|
||||||
}
|
|
||||||
delete(ps.clientPeers, id)
|
|
||||||
for _, sub := range ps.cSubs {
|
|
||||||
sub.unregisterPeer(p)
|
|
||||||
}
|
|
||||||
p.Peer.Disconnect(p2p.DiscUselessPeer)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AllPeerIDs returns a list of all registered peer IDs
|
// ids returns a list of all registered peer IDs
|
||||||
func (ps *peerSet) allPeerIds() []string {
|
func (ps *clientPeerSet) ids() []string {
|
||||||
ps.lock.RLock()
|
ps.lock.RLock()
|
||||||
defer ps.lock.RUnlock()
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
var ids []string
|
var ids []string
|
||||||
if ps.client {
|
for id := range ps.peers {
|
||||||
for id := range ps.serverPeers {
|
|
||||||
ids = append(ids, id)
|
ids = append(ids, id)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for id := range ps.clientPeers {
|
|
||||||
ids = append(ids, id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
// Peer retrieves the registered peer with the given id.
|
// peer retrieves the registered peer with the given id.
|
||||||
func (ps *peerSet) serverPeer(id string) *serverPeer {
|
func (ps *clientPeerSet) peer(id string) *clientPeer {
|
||||||
ps.lock.RLock()
|
ps.lock.RLock()
|
||||||
defer ps.lock.RUnlock()
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
if !ps.client {
|
return ps.peers[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
// len returns if the current number of peers in the set.
|
||||||
|
func (ps *clientPeerSet) len() int {
|
||||||
|
ps.lock.RLock()
|
||||||
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
|
return len(ps.peers)
|
||||||
|
}
|
||||||
|
|
||||||
|
// allClientPeers returns all client peers in a list.
|
||||||
|
func (ps *clientPeerSet) allPeers() []*clientPeer {
|
||||||
|
ps.lock.RLock()
|
||||||
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
|
list := make([]*clientPeer, 0, len(ps.peers))
|
||||||
|
for _, p := range ps.peers {
|
||||||
|
list = append(list, p)
|
||||||
|
}
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// close disconnects all peers. No new peers can be registered
|
||||||
|
// after close has returned.
|
||||||
|
func (ps *clientPeerSet) close() {
|
||||||
|
ps.lock.Lock()
|
||||||
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
|
for _, p := range ps.peers {
|
||||||
|
p.Disconnect(p2p.DiscQuitting)
|
||||||
|
}
|
||||||
|
ps.closed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// serverPeerSet represents the set of active server peers currently
|
||||||
|
// participating in the Light Ethereum sub-protocol.
|
||||||
|
type serverPeerSet struct {
|
||||||
|
peers map[string]*serverPeer
|
||||||
|
// subscribers is a batch of subscribers and peerset will notify
|
||||||
|
// these subscribers when the peerset changes(new server peer is
|
||||||
|
// added or removed)
|
||||||
|
subscribers []serverPeerSubscriber
|
||||||
|
closed bool
|
||||||
|
lock sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// newServerPeerSet creates a new peer set to track the active server peers.
|
||||||
|
func newServerPeerSet() *serverPeerSet {
|
||||||
|
return &serverPeerSet{peers: make(map[string]*serverPeer)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// subscribe adds a service to be notified about added or removed
|
||||||
|
// peers and also register all active peers into the given service.
|
||||||
|
func (ps *serverPeerSet) subscribe(sub serverPeerSubscriber) {
|
||||||
|
ps.lock.Lock()
|
||||||
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
|
ps.subscribers = append(ps.subscribers, sub)
|
||||||
|
for _, p := range ps.peers {
|
||||||
|
sub.registerPeer(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// unSubscribe removes the specified service from the subscriber pool.
|
||||||
|
func (ps *serverPeerSet) unSubscribe(sub serverPeerSubscriber) {
|
||||||
|
ps.lock.Lock()
|
||||||
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
|
for i, s := range ps.subscribers {
|
||||||
|
if s == sub {
|
||||||
|
ps.subscribers = append(ps.subscribers[:i], ps.subscribers[i+1:]...)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// register adds a new server peer into the set, or returns an error if the
|
||||||
|
// peer is already known.
|
||||||
|
func (ps *serverPeerSet) register(peer *serverPeer) error {
|
||||||
|
ps.lock.Lock()
|
||||||
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
|
if ps.closed {
|
||||||
|
return errClosed
|
||||||
|
}
|
||||||
|
if _, exist := ps.peers[peer.id]; exist {
|
||||||
|
return errAlreadyRegistered
|
||||||
|
}
|
||||||
|
ps.peers[peer.id] = peer
|
||||||
|
for _, sub := range ps.subscribers {
|
||||||
|
sub.registerPeer(peer)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ps.serverPeers[id]
|
|
||||||
|
// unregister removes a remote peer from the active set, disabling any further
|
||||||
|
// actions to/from that particular entity. It also initiates disconnection at
|
||||||
|
// the networking layer.
|
||||||
|
func (ps *serverPeerSet) unregister(id string) error {
|
||||||
|
ps.lock.Lock()
|
||||||
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
|
p, ok := ps.peers[id]
|
||||||
|
if !ok {
|
||||||
|
return errNotRegistered
|
||||||
}
|
}
|
||||||
|
delete(ps.peers, id)
|
||||||
// Peer retrieves the registered peer with the given id.
|
for _, sub := range ps.subscribers {
|
||||||
func (ps *peerSet) clientPeer(id string) *clientPeer {
|
sub.unregisterPeer(p)
|
||||||
ps.lock.RLock()
|
}
|
||||||
defer ps.lock.RUnlock()
|
p.Peer.Disconnect(p2p.DiscRequested)
|
||||||
|
|
||||||
if ps.client {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return ps.clientPeers[id]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns if the current number of peers in the set.
|
// ids returns a list of all registered peer IDs
|
||||||
func (ps *peerSet) len() int {
|
func (ps *serverPeerSet) ids() []string {
|
||||||
ps.lock.RLock()
|
ps.lock.RLock()
|
||||||
defer ps.lock.RUnlock()
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
if ps.client {
|
var ids []string
|
||||||
return len(ps.serverPeers)
|
for id := range ps.peers {
|
||||||
} else {
|
ids = append(ids, id)
|
||||||
return len(ps.clientPeers)
|
|
||||||
}
|
}
|
||||||
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
// BestPeer retrieves the known peer with the currently highest total difficulty.
|
// peer retrieves the registered peer with the given id.
|
||||||
|
func (ps *serverPeerSet) peer(id string) *serverPeer {
|
||||||
|
ps.lock.RLock()
|
||||||
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
|
return ps.peers[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
// len returns if the current number of peers in the set.
|
||||||
|
func (ps *serverPeerSet) len() int {
|
||||||
|
ps.lock.RLock()
|
||||||
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
|
return len(ps.peers)
|
||||||
|
}
|
||||||
|
|
||||||
|
// bestPeer retrieves the known peer with the currently highest total difficulty.
|
||||||
// If the peerset is "client peer set", then nothing meaningful will return. The
|
// If the peerset is "client peer set", then nothing meaningful will return. The
|
||||||
// reason is client peer never send back their latest status to server.
|
// reason is client peer never send back their latest status to server.
|
||||||
func (ps *peerSet) bestPeer() *serverPeer {
|
func (ps *serverPeerSet) bestPeer() *serverPeer {
|
||||||
ps.lock.RLock()
|
ps.lock.RLock()
|
||||||
defer ps.lock.RUnlock()
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
if !ps.client {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var (
|
var (
|
||||||
bestPeer *serverPeer
|
bestPeer *serverPeer
|
||||||
bestTd *big.Int
|
bestTd *big.Int
|
||||||
)
|
)
|
||||||
for _, p := range ps.serverPeers {
|
for _, p := range ps.peers {
|
||||||
if td := p.Td(); bestTd == nil || td.Cmp(bestTd) > 0 {
|
if td := p.Td(); bestTd == nil || td.Cmp(bestTd) > 0 {
|
||||||
bestPeer, bestTd = p, td
|
bestPeer, bestTd = p, td
|
||||||
}
|
}
|
||||||
|
|
@ -1125,49 +1170,25 @@ func (ps *peerSet) bestPeer() *serverPeer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// allServerPeers returns all server peers in a list.
|
// allServerPeers returns all server peers in a list.
|
||||||
func (ps *peerSet) allServerPeers() []*serverPeer {
|
func (ps *serverPeerSet) allPeers() []*serverPeer {
|
||||||
ps.lock.RLock()
|
ps.lock.RLock()
|
||||||
defer ps.lock.RUnlock()
|
defer ps.lock.RUnlock()
|
||||||
|
|
||||||
if !ps.client {
|
list := make([]*serverPeer, 0, len(ps.peers))
|
||||||
return nil
|
for _, p := range ps.peers {
|
||||||
}
|
|
||||||
list := make([]*serverPeer, 0, len(ps.serverPeers))
|
|
||||||
for _, p := range ps.serverPeers {
|
|
||||||
list = append(list, p)
|
list = append(list, p)
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
// allClientPeers returns all client peers in a list.
|
// close disconnects all peers. No new peers can be registered
|
||||||
func (ps *peerSet) allClientPeers() []*clientPeer {
|
// after close has returned.
|
||||||
ps.lock.RLock()
|
func (ps *serverPeerSet) close() {
|
||||||
defer ps.lock.RUnlock()
|
|
||||||
|
|
||||||
if ps.client {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
list := make([]*clientPeer, 0, len(ps.clientPeers))
|
|
||||||
for _, p := range ps.clientPeers {
|
|
||||||
list = append(list, p)
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close disconnects all peers.
|
|
||||||
// No new peers can be registered after Close has returned.
|
|
||||||
func (ps *peerSet) close() {
|
|
||||||
ps.lock.Lock()
|
ps.lock.Lock()
|
||||||
defer ps.lock.Unlock()
|
defer ps.lock.Unlock()
|
||||||
|
|
||||||
if ps.client {
|
for _, p := range ps.peers {
|
||||||
for _, p := range ps.serverPeers {
|
|
||||||
p.Disconnect(p2p.DiscQuitting)
|
p.Disconnect(p2p.DiscQuitting)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for _, p := range ps.clientPeers {
|
|
||||||
p.Disconnect(p2p.DiscQuitting)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ps.closed = true
|
ps.closed = true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,11 +45,11 @@ func (t *testServerPeerSub) registerPeer(p *serverPeer) { t.regCh <- p }
|
||||||
func (t *testServerPeerSub) unregisterPeer(p *serverPeer) { t.unregCh <- p }
|
func (t *testServerPeerSub) unregisterPeer(p *serverPeer) { t.unregCh <- p }
|
||||||
|
|
||||||
func TestPeerSubscription(t *testing.T) {
|
func TestPeerSubscription(t *testing.T) {
|
||||||
peers := newPeerSet(true)
|
peers := newServerPeerSet()
|
||||||
defer peers.close()
|
defer peers.close()
|
||||||
|
|
||||||
checkIds := func(expect []string) {
|
checkIds := func(expect []string) {
|
||||||
given := peers.allPeerIds()
|
given := peers.ids()
|
||||||
if len(given) == 0 && len(expect) == 0 {
|
if len(given) == 0 && len(expect) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ var (
|
||||||
// matching replies by request ID and handles timeouts and resends if necessary.
|
// matching replies by request ID and handles timeouts and resends if necessary.
|
||||||
type retrieveManager struct {
|
type retrieveManager struct {
|
||||||
dist *requestDistributor
|
dist *requestDistributor
|
||||||
peers *peerSet
|
peers *serverPeerSet
|
||||||
serverPool peerSelector
|
serverPool peerSelector
|
||||||
|
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
|
|
@ -99,7 +99,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// newRetrieveManager creates the retrieve manager
|
// newRetrieveManager creates the retrieve manager
|
||||||
func newRetrieveManager(peers *peerSet, dist *requestDistributor, serverPool peerSelector) *retrieveManager {
|
func newRetrieveManager(peers *serverPeerSet, dist *requestDistributor, serverPool peerSelector) *retrieveManager {
|
||||||
return &retrieveManager{
|
return &retrieveManager{
|
||||||
peers: peers,
|
peers: peers,
|
||||||
dist: dist,
|
dist: dist,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ type LesServer struct {
|
||||||
lesCommons
|
lesCommons
|
||||||
|
|
||||||
archiveMode bool // Flag whether the ethereum node runs in archive mode.
|
archiveMode bool // Flag whether the ethereum node runs in archive mode.
|
||||||
|
peers *clientPeerSet
|
||||||
handler *serverHandler
|
handler *serverHandler
|
||||||
lesTopics []discv5.Topic
|
lesTopics []discv5.Topic
|
||||||
privateKey *ecdsa.PrivateKey
|
privateKey *ecdsa.PrivateKey
|
||||||
|
|
@ -75,13 +76,13 @@ func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) {
|
||||||
chainConfig: e.BlockChain().Config(),
|
chainConfig: e.BlockChain().Config(),
|
||||||
iConfig: light.DefaultServerIndexerConfig,
|
iConfig: light.DefaultServerIndexerConfig,
|
||||||
chainDb: e.ChainDb(),
|
chainDb: e.ChainDb(),
|
||||||
peers: newPeerSet(false),
|
|
||||||
chainReader: e.BlockChain(),
|
chainReader: e.BlockChain(),
|
||||||
chtIndexer: light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations),
|
chtIndexer: light.NewChtIndexer(e.ChainDb(), nil, params.CHTFrequency, params.HelperTrieProcessConfirmations),
|
||||||
bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency),
|
bloomTrieIndexer: light.NewBloomTrieIndexer(e.ChainDb(), nil, params.BloomBitsBlocks, params.BloomTrieFrequency),
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
},
|
},
|
||||||
archiveMode: e.ArchiveMode(),
|
archiveMode: e.ArchiveMode(),
|
||||||
|
peers: newClientPeerSet(),
|
||||||
lesTopics: lesTopics,
|
lesTopics: lesTopics,
|
||||||
fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}),
|
fcManager: flowcontrol.NewClientManager(nil, &mclock.System{}),
|
||||||
servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100),
|
servingQueue: newServingQueue(int64(time.Millisecond*10), float64(config.LightServ)/100),
|
||||||
|
|
@ -152,7 +153,7 @@ func (s *LesServer) APIs() []rpc.API {
|
||||||
|
|
||||||
func (s *LesServer) Protocols() []p2p.Protocol {
|
func (s *LesServer) Protocols() []p2p.Protocol {
|
||||||
ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
ps := s.makeProtocols(ServerProtocolVersions, s.handler.runPeer, func(id enode.ID) interface{} {
|
||||||
if p := s.peers.clientPeer(peerIdToString(id)); p != nil {
|
if p := s.peers.peer(peerIdToString(id)); p != nil {
|
||||||
return p.Info()
|
return p.Info()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,7 @@ func (h *serverHandler) handleMsg(p *clientPeer, wg *sync.WaitGroup) error {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, p.closeCh)
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch msg.Code {
|
switch msg.Code {
|
||||||
|
|
@ -914,7 +914,7 @@ func (h *serverHandler) broadcastHeaders() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case ev := <-headCh:
|
case ev := <-headCh:
|
||||||
peers := h.server.peers.allClientPeers()
|
peers := h.server.peers.allPeers()
|
||||||
if len(peers) == 0 {
|
if len(peers) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -940,14 +940,18 @@ func (h *serverHandler) broadcastHeaders() {
|
||||||
p := p
|
p := p
|
||||||
switch p.announceType {
|
switch p.announceType {
|
||||||
case announceTypeSimple:
|
case announceTypeSimple:
|
||||||
p.mustQueueSend(func() { p.sendAnnounce(announce) }, p.closeCh)
|
if !p.queueSend(func() { p.sendAnnounce(announce) }) {
|
||||||
|
log.Debug("Drop announcement because queue is full", "number", number, "hash", hash)
|
||||||
|
}
|
||||||
case announceTypeSigned:
|
case announceTypeSigned:
|
||||||
if !signed {
|
if !signed {
|
||||||
signedAnnounce = announce
|
signedAnnounce = announce
|
||||||
signedAnnounce.sign(h.server.privateKey)
|
signedAnnounce.sign(h.server.privateKey)
|
||||||
signed = true
|
signed = true
|
||||||
}
|
}
|
||||||
p.mustQueueSend(func() { p.sendAnnounce(signedAnnounce) }, p.closeCh)
|
if !p.queueSend(func() { p.sendAnnounce(signedAnnounce) }) {
|
||||||
|
log.Debug("Drop announcement because queue is full", "number", number, "hash", hash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case <-h.closeCh:
|
case <-h.closeCh:
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ func testIndexers(db ethdb.Database, odr light.OdrBackend, config *light.Indexer
|
||||||
return indexers[:]
|
return indexers[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, ulcServers []string, ulcFraction int) *clientHandler {
|
func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, indexers []*core.ChainIndexer, db ethdb.Database, peers *serverPeerSet, ulcServers []string, ulcFraction int) *clientHandler {
|
||||||
var (
|
var (
|
||||||
evmux = new(event.TypeMux)
|
evmux = new(event.TypeMux)
|
||||||
engine = ethash.NewFaker()
|
engine = ethash.NewFaker()
|
||||||
|
|
@ -206,9 +206,9 @@ func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, index
|
||||||
chainDb: db,
|
chainDb: db,
|
||||||
oracle: oracle,
|
oracle: oracle,
|
||||||
chainReader: chain,
|
chainReader: chain,
|
||||||
peers: peers,
|
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
},
|
},
|
||||||
|
peers: peers,
|
||||||
reqDist: odr.retriever.dist,
|
reqDist: odr.retriever.dist,
|
||||||
retriever: odr.retriever,
|
retriever: odr.retriever,
|
||||||
odr: odr,
|
odr: odr,
|
||||||
|
|
@ -224,7 +224,7 @@ func newTestClientHandler(backend *backends.SimulatedBackend, odr *LesOdr, index
|
||||||
return client.handler
|
return client.handler
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, peers *peerSet, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) {
|
func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Database, peers *clientPeerSet, clock mclock.Clock) (*serverHandler, *backends.SimulatedBackend) {
|
||||||
var (
|
var (
|
||||||
gspec = core.Genesis{
|
gspec = core.Genesis{
|
||||||
Config: params.AllEthashProtocolChanges,
|
Config: params.AllEthashProtocolChanges,
|
||||||
|
|
@ -269,9 +269,9 @@ func newTestServerHandler(blocks int, indexers []*core.ChainIndexer, db ethdb.Da
|
||||||
chainDb: db,
|
chainDb: db,
|
||||||
chainReader: simulation.Blockchain(),
|
chainReader: simulation.Blockchain(),
|
||||||
oracle: oracle,
|
oracle: oracle,
|
||||||
peers: peers,
|
|
||||||
closeCh: make(chan struct{}),
|
closeCh: make(chan struct{}),
|
||||||
},
|
},
|
||||||
|
peers: peers,
|
||||||
servingQueue: newServingQueue(int64(time.Millisecond*10), 1),
|
servingQueue: newServingQueue(int64(time.Millisecond*10), 1),
|
||||||
defParams: flowcontrol.ServerParams{
|
defParams: flowcontrol.ServerParams{
|
||||||
BufLimit: testBufLimit,
|
BufLimit: testBufLimit,
|
||||||
|
|
@ -446,7 +446,7 @@ func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallba
|
||||||
if simClock {
|
if simClock {
|
||||||
clock = &mclock.Simulated{}
|
clock = &mclock.Simulated{}
|
||||||
}
|
}
|
||||||
handler, b := newTestServerHandler(blocks, indexers, db, newPeerSet(false), clock)
|
handler, b := newTestServerHandler(blocks, indexers, db, newClientPeerSet(), clock)
|
||||||
|
|
||||||
var peer *testPeer
|
var peer *testPeer
|
||||||
if newPeer {
|
if newPeer {
|
||||||
|
|
@ -485,14 +485,14 @@ func newServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallba
|
||||||
|
|
||||||
func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool) (*testServer, *testClient, func()) {
|
func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexerCallback, ulcServers []string, ulcFraction int, simClock bool, connect bool) (*testServer, *testClient, func()) {
|
||||||
sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase()
|
sdb, cdb := rawdb.NewMemoryDatabase(), rawdb.NewMemoryDatabase()
|
||||||
speers, cPeers := newPeerSet(false), newPeerSet(true)
|
speers, cpeers := newServerPeerSet(), newClientPeerSet()
|
||||||
|
|
||||||
var clock mclock.Clock = &mclock.System{}
|
var clock mclock.Clock = &mclock.System{}
|
||||||
if simClock {
|
if simClock {
|
||||||
clock = &mclock.Simulated{}
|
clock = &mclock.Simulated{}
|
||||||
}
|
}
|
||||||
dist := newRequestDistributor(cPeers, clock)
|
dist := newRequestDistributor(speers, clock)
|
||||||
rm := newRetrieveManager(cPeers, dist, nil)
|
rm := newRetrieveManager(speers, dist, nil)
|
||||||
odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm)
|
odr := NewLesOdr(cdb, light.TestClientIndexerConfig, rm)
|
||||||
|
|
||||||
sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig)
|
sindexers := testIndexers(sdb, nil, light.TestServerIndexerConfig)
|
||||||
|
|
@ -502,8 +502,8 @@ func newClientServerEnv(t *testing.T, blocks int, protocol int, callback indexer
|
||||||
ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2]
|
ccIndexer, cbIndexer, cbtIndexer := cIndexers[0], cIndexers[1], cIndexers[2]
|
||||||
odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer)
|
odr.SetIndexers(ccIndexer, cbIndexer, cbtIndexer)
|
||||||
|
|
||||||
server, b := newTestServerHandler(blocks, sindexers, sdb, speers, clock)
|
server, b := newTestServerHandler(blocks, sindexers, sdb, cpeers, clock)
|
||||||
client := newTestClientHandler(b, odr, cIndexers, cdb, cPeers, ulcServers, ulcFraction)
|
client := newTestClientHandler(b, odr, cIndexers, cdb, speers, ulcServers, ulcFraction)
|
||||||
|
|
||||||
scIndexer.Start(server.blockchain)
|
scIndexer.Start(server.blockchain)
|
||||||
sbIndexer.Start(server.blockchain)
|
sbIndexer.Start(server.blockchain)
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ type lesTxRelay struct {
|
||||||
retriever *retrieveManager
|
retriever *retrieveManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func newLesTxRelay(ps *peerSet, retriever *retrieveManager) *lesTxRelay {
|
func newLesTxRelay(ps *serverPeerSet, retriever *retrieveManager) *lesTxRelay {
|
||||||
r := &lesTxRelay{
|
r := &lesTxRelay{
|
||||||
txSent: make(map[common.Hash]*ltrInfo),
|
txSent: make(map[common.Hash]*ltrInfo),
|
||||||
txPending: make(map[common.Hash]struct{}),
|
txPending: make(map[common.Hash]struct{}),
|
||||||
|
|
@ -75,6 +75,7 @@ func (ltrx *lesTxRelay) unregisterPeer(p *serverPeer) {
|
||||||
if peer == p {
|
if peer == p {
|
||||||
// Remove from the peer list
|
// Remove from the peer list
|
||||||
ltrx.peerList = append(ltrx.peerList[:i], ltrx.peerList[i+1:]...)
|
ltrx.peerList = append(ltrx.peerList[:i], ltrx.peerList[i+1:]...)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue