diff --git a/eth/backend.go b/eth/backend.go
index 6b9c98bf2..fbf4dd7bb 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -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) NetVersion() uint64 { return s.networkID }
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
// network protocols to start.
diff --git a/les/backend.go b/les/backend.go
index 887f88210..ed0f45057 100644
--- a/les/backend.go
+++ b/les/backend.go
@@ -158,7 +158,8 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
leth.serverPool,
quitSync,
&leth.wg,
- config.ULC); err != nil {
+ config.ULC,
+ nil); err != nil {
return nil, err
}
diff --git a/les/handler.go b/les/handler.go
index 0d235e7a5..f53a4722f 100644
--- a/les/handler.go
+++ b/les/handler.go
@@ -87,12 +87,16 @@ type txPool interface {
}
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
txrelay *LesTxRelay
- networkId uint64
- chainConfig *params.ChainConfig
- iConfig *light.IndexerConfig
blockchain BlockChain
chainDb ethdb.Database
odr *LesOdr
@@ -102,23 +106,21 @@ type ProtocolManager struct {
reqDist *requestDistributor
retriever *retrieveManager
servingQueue *servingQueue
-
- downloader *downloader.Downloader
- fetcher *lightFetcher
- peers *peerSet
- maxPeers int
-
- eventMux *event.TypeMux
+ downloader *downloader.Downloader
+ fetcher *lightFetcher
+ ulc *ulc
+ peers *peerSet
// channels for fetcher, syncer, txsyncLoop
newPeerCh chan *peer
quitSync chan struct{}
noMorePeers chan struct{}
- // wait group is used for graceful shutdowns during downloading
- // and processing
- wg *sync.WaitGroup
- ulc *ulc
+ wg *sync.WaitGroup
+ eventMux *event.TypeMux
+
+ // Callbacks
+ synced func() bool
}
// NewProtocolManager returns a new ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
@@ -126,7 +128,7 @@ type ProtocolManager struct {
func NewProtocolManager(
chainConfig *params.ChainConfig,
indexerConfig *light.IndexerConfig,
- lightSync bool,
+ client bool,
networkId uint64,
mux *event.TypeMux,
engine consensus.Engine,
@@ -139,10 +141,10 @@ func NewProtocolManager(
serverPool *serverPool,
quitSync chan struct{},
wg *sync.WaitGroup,
- ulcConfig *eth.ULCConfig) (*ProtocolManager, error) {
+ ulcConfig *eth.ULCConfig, synced func() bool) (*ProtocolManager, error) {
// Create the protocol manager with the base fields
manager := &ProtocolManager{
- lightSync: lightSync,
+ client: client,
eventMux: mux,
blockchain: blockchain,
chainConfig: chainConfig,
@@ -158,6 +160,7 @@ func NewProtocolManager(
quitSync: quitSync,
wg: wg,
noMorePeers: make(chan struct{}),
+ synced: synced,
}
if odr != nil {
manager.retriever = odr.retriever
@@ -174,7 +177,7 @@ func NewProtocolManager(
if disableClientRemovePeer {
removePeer = func(id string) {}
}
- if lightSync {
+ if client {
var checkpoint uint64
if cht, ok := params.TrustedCheckpoints[blockchain.Genesis().Hash()]; ok {
checkpoint = (cht.SectionIndex+1)*params.CHTFrequency - 1
@@ -193,7 +196,7 @@ func (pm *ProtocolManager) removePeer(id string) {
func (pm *ProtocolManager) Start(maxPeers int) {
pm.maxPeers = maxPeers
- if pm.lightSync {
+ if pm.client {
go pm.syncer()
} else {
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 {
// Ignore maxPeers if this is a trusted peer
// 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
}
-
+ // 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())
// 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
- if pm.lightSync {
+ if pm.client {
p.lock.Lock()
head := p.headInfo
p.lock.Unlock()
diff --git a/les/helper_test.go b/les/helper_test.go
index 9a302f837..878e44404 100644
--- a/les/helper_test.go
+++ b/les/helper_test.go
@@ -170,7 +170,7 @@ func newTestProtocolManager(lightSync bool, blocks int, generator func(int, *cor
if lightSync {
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 {
return nil, err
}
diff --git a/les/server.go b/les/server.go
index 6c2b227f4..6b93b846d 100644
--- a/les/server.go
+++ b/les/server.go
@@ -74,7 +74,7 @@ func NewLesServer(eth *eth.Ethereum, config *eth.Config) (*LesServer, error) {
nil,
quitSync,
new(sync.WaitGroup),
- config.ULC)
+ config.ULC, eth.Synced)
if err != nil {
return nil, err
}
@@ -243,6 +243,7 @@ func (s *LesServer) Stop() {
s.protocolManager.Stop()
}
+// todo(rjl493456442) separate client and server implementation.
func (pm *ProtocolManager) blockLoop() {
pm.wg.Add(1)
headCh := make(chan core.ChainHeadEvent, 10)
diff --git a/les/transactions.rlp b/les/transactions.rlp
new file mode 100755
index 000000000..e69de29bb
diff --git a/les/ulc.go b/les/ulc.go
index d9f7dc76c..c6d415552 100644
--- a/les/ulc.go
+++ b/les/ulc.go
@@ -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 .
+
package les
import (
- "fmt"
-
"github.com/ethereum/go-ethereum/eth"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode"
)
@@ -12,24 +27,24 @@ type ulc struct {
minTrustedFraction int
}
+// newULC creates and returns a ultra light client instance.
func newULC(ulcConfig *eth.ULCConfig) *ulc {
if ulcConfig == nil {
return nil
}
-
m := make(map[string]struct{}, len(ulcConfig.TrustedServers))
for _, id := range ulcConfig.TrustedServers {
node, err := enode.ParseV4(id)
if err != nil {
- fmt.Println("node:", id, " err:", err)
+ log.Debug("Failed to parse trusted server", "id", id, "err", err)
continue
}
m[node.ID().String()] = struct{}{}
}
-
return &ulc{m, ulcConfig.MinTrustedFraction}
}
+// isTrusted return an indicator that whether the specified peer is trusted.
func (u *ulc) isTrusted(p enode.ID) bool {
if u.trustedKeys == nil {
return false
diff --git a/les/ulc_test.go b/les/ulc_test.go
index 81986fa1e..38adeb95f 100644
--- a/les/ulc_test.go
+++ b/les/ulc_test.go
@@ -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 .
+
package les
import (