eth, les: reject light client connection is server is not synced (#19616)

* eth, les: reject light client connection is server is not synced

* eth, les: rename function and variables

* les: format
This commit is contained in:
gary rong 2019-05-27 00:15:05 +08:00 committed by Péter Szilágyi
parent 922e757f19
commit 4e0c1a1a6b
8 changed files with 71 additions and 31 deletions

View File

@ -480,6 +480,7 @@ func (s *Ethereum) IsListening() bool { return true } // Always
func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) } func (s *Ethereum) EthVersion() int { return int(s.protocolManager.SubProtocols[0].Version) }
func (s *Ethereum) NetVersion() uint64 { return s.networkID } func (s *Ethereum) NetVersion() uint64 { return s.networkID }
func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader } func (s *Ethereum) Downloader() *downloader.Downloader { return s.protocolManager.downloader }
func (s *Ethereum) Synced() bool { return atomic.LoadUint32(&s.protocolManager.acceptTxs) == 1 }
// Protocols implements node.Service, returning all the currently configured // Protocols implements node.Service, returning all the currently configured
// network protocols to start. // network protocols to start.

View File

@ -158,7 +158,8 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
leth.serverPool, leth.serverPool,
quitSync, quitSync,
&leth.wg, &leth.wg,
config.ULC); err != nil { config.ULC,
nil); err != nil {
return nil, err return nil, err
} }

View File

@ -87,12 +87,16 @@ type txPool interface {
} }
type ProtocolManager struct { type ProtocolManager struct {
lightSync bool // Configs
chainConfig *params.ChainConfig
iConfig *light.IndexerConfig
client bool // The indicator whether the node is light client
maxPeers int // The maximum number peers allowed to connect.
networkId uint64 // The identity of network.
txpool txPool txpool txPool
txrelay *LesTxRelay txrelay *LesTxRelay
networkId uint64
chainConfig *params.ChainConfig
iConfig *light.IndexerConfig
blockchain BlockChain blockchain BlockChain
chainDb ethdb.Database chainDb ethdb.Database
odr *LesOdr odr *LesOdr
@ -102,23 +106,21 @@ type ProtocolManager struct {
reqDist *requestDistributor reqDist *requestDistributor
retriever *retrieveManager retriever *retrieveManager
servingQueue *servingQueue servingQueue *servingQueue
downloader *downloader.Downloader
downloader *downloader.Downloader fetcher *lightFetcher
fetcher *lightFetcher ulc *ulc
peers *peerSet peers *peerSet
maxPeers int
eventMux *event.TypeMux
// channels for fetcher, syncer, txsyncLoop // channels for fetcher, syncer, txsyncLoop
newPeerCh chan *peer newPeerCh chan *peer
quitSync chan struct{} quitSync chan struct{}
noMorePeers chan struct{} noMorePeers chan struct{}
// wait group is used for graceful shutdowns during downloading wg *sync.WaitGroup
// and processing eventMux *event.TypeMux
wg *sync.WaitGroup
ulc *ulc // Callbacks
synced func() bool
} }
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable // NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
@ -126,7 +128,7 @@ type ProtocolManager struct {
func NewProtocolManager( func NewProtocolManager(
chainConfig *params.ChainConfig, chainConfig *params.ChainConfig,
indexerConfig *light.IndexerConfig, indexerConfig *light.IndexerConfig,
lightSync bool, client bool,
networkId uint64, networkId uint64,
mux *event.TypeMux, mux *event.TypeMux,
engine consensus.Engine, engine consensus.Engine,
@ -139,10 +141,10 @@ func NewProtocolManager(
serverPool *serverPool, serverPool *serverPool,
quitSync chan struct{}, quitSync chan struct{},
wg *sync.WaitGroup, wg *sync.WaitGroup,
ulcConfig *eth.ULCConfig) (*ProtocolManager, error) { ulcConfig *eth.ULCConfig, synced func() bool) (*ProtocolManager, error) {
// Create the protocol manager with the base fields // Create the protocol manager with the base fields
manager := &ProtocolManager{ manager := &ProtocolManager{
lightSync: lightSync, client: client,
eventMux: mux, eventMux: mux,
blockchain: blockchain, blockchain: blockchain,
chainConfig: chainConfig, chainConfig: chainConfig,
@ -158,6 +160,7 @@ func NewProtocolManager(
quitSync: quitSync, quitSync: quitSync,
wg: wg, wg: wg,
noMorePeers: make(chan struct{}), noMorePeers: make(chan struct{}),
synced: synced,
} }
if odr != nil { if odr != nil {
manager.retriever = odr.retriever manager.retriever = odr.retriever
@ -174,7 +177,7 @@ func NewProtocolManager(
if disableClientRemovePeer { if disableClientRemovePeer {
removePeer = func(id string) {} removePeer = func(id string) {}
} }
if lightSync { if client {
var checkpoint uint64 var checkpoint uint64
if cht, ok := params.TrustedCheckpoints[blockchain.Genesis().Hash()]; ok { if cht, ok := params.TrustedCheckpoints[blockchain.Genesis().Hash()]; ok {
checkpoint = (cht.SectionIndex+1)*params.CHTFrequency - 1 checkpoint = (cht.SectionIndex+1)*params.CHTFrequency - 1
@ -193,7 +196,7 @@ func (pm *ProtocolManager) removePeer(id string) {
func (pm *ProtocolManager) Start(maxPeers int) { func (pm *ProtocolManager) Start(maxPeers int) {
pm.maxPeers = maxPeers pm.maxPeers = maxPeers
if pm.lightSync { if pm.client {
go pm.syncer() go pm.syncer()
} else { } else {
go func() { go func() {
@ -268,10 +271,13 @@ func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgRea
func (pm *ProtocolManager) handle(p *peer) error { func (pm *ProtocolManager) handle(p *peer) error {
// Ignore maxPeers if this is a trusted peer // Ignore maxPeers if this is a trusted peer
// In server mode we try to check into the client pool after handshake // In server mode we try to check into the client pool after handshake
if pm.lightSync && pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted { if pm.client && pm.peers.Len() >= pm.maxPeers && !p.Peer.Info().Network.Trusted {
return p2p.DiscTooManyPeers return p2p.DiscTooManyPeers
} }
// Reject light clients if server is not synced.
if !pm.client && !pm.synced() {
return p2p.DiscRequested
}
p.Log().Debug("Light Ethereum peer connected", "name", p.Name()) p.Log().Debug("Light Ethereum peer connected", "name", p.Name())
// Execute the LES handshake // Execute the LES handshake
@ -304,7 +310,7 @@ func (pm *ProtocolManager) handle(p *peer) error {
}() }()
// Register the peer in the downloader. If the downloader considers it banned, we disconnect // Register the peer in the downloader. If the downloader considers it banned, we disconnect
if pm.lightSync { if pm.client {
p.lock.Lock() p.lock.Lock()
head := p.headInfo head := p.headInfo
p.lock.Unlock() p.lock.Unlock()

View File

@ -170,7 +170,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
if lightSync { if lightSync {
indexConfig = light.TestClientIndexerConfig indexConfig = light.TestClientIndexerConfig
} }
pm, err := NewProtocolManager(gspec.Config, indexConfig, lightSync, NetworkId, evmux, engine, peers, chain, pool, db, odr, nil, nil, make(chan struct{}), new(sync.WaitGroup), ulcConfig) pm, err := NewProtocolManager(gspec.Config, indexConfig, lightSync, NetworkId, evmux, engine, peers, chain, pool, db, odr, nil, nil, make(chan struct{}), new(sync.WaitGroup), ulcConfig, func() bool { return true })
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -74,7 +74,7 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
nil, nil,
quitSync, quitSync,
new(sync.WaitGroup), new(sync.WaitGroup),
config.ULC) config.ULC, eth.Synced)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -243,6 +243,7 @@ func (s *LesServer) Stop() {
s.protocolManager.Stop() s.protocolManager.Stop()
} }
// todo(rjl493456442) separate client and server implementation.
func (pm *ProtocolManager) blockLoop() { func (pm *ProtocolManager) blockLoop() {
pm.wg.Add(1) pm.wg.Add(1)
headCh := make(chan core.ChainHeadEvent, 10) headCh := make(chan core.ChainHeadEvent, 10)

0
les/transactions.rlp Executable file
View File

View File

@ -1,9 +1,24 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package les package les
import ( import (
"fmt"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
) )
@ -12,24 +27,24 @@ type ulc struct {
minTrustedFraction int minTrustedFraction int
} }
// newULC creates and returns a ultra light client instance.
func newULC(ulcConfig *eth.ULCConfig) *ulc { func newULC(ulcConfig *eth.ULCConfig) *ulc {
if ulcConfig == nil { if ulcConfig == nil {
return nil return nil
} }
m := make(map[string]struct{}, len(ulcConfig.TrustedServers)) m := make(map[string]struct{}, len(ulcConfig.TrustedServers))
for _, id := range ulcConfig.TrustedServers { for _, id := range ulcConfig.TrustedServers {
node, err := enode.ParseV4(id) node, err := enode.ParseV4(id)
if err != nil { if err != nil {
fmt.Println("node:", id, " err:", err) log.Debug("Failed to parse trusted server", "id", id, "err", err)
continue continue
} }
m[node.ID().String()] = struct{}{} m[node.ID().String()] = struct{}{}
} }
return &ulc{m, ulcConfig.MinTrustedFraction} return &ulc{m, ulcConfig.MinTrustedFraction}
} }
// isTrusted return an indicator that whether the specified peer is trusted.
func (u *ulc) isTrusted(p enode.ID) bool { func (u *ulc) isTrusted(p enode.ID) bool {
if u.trustedKeys == nil { if u.trustedKeys == nil {
return false return false

View File

@ -1,3 +1,19 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package les package les
import ( import (