cmd, eth, les: fix up ultra light config integration

This commit is contained in:
Péter Szilágyi 2019-07-09 20:30:24 +03:00
parent 8c249cb82f
commit 213690cdfd
No known key found for this signature in database
GPG Key ID: E9AE538CEDF8293D
21 changed files with 187 additions and 272 deletions

View File

@ -123,7 +123,6 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
} }
// Apply flags. // Apply flags.
utils.SetULC(ctx, &cfg.Eth)
utils.SetNodeConfig(ctx, &cfg.Node) utils.SetNodeConfig(ctx, &cfg.Node)
stack, err := node.New(&cfg.Node) stack, err := node.New(&cfg.Node)
if err != nil { if err != nil {
@ -133,7 +132,6 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) { if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name) cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
} }
utils.SetShhConfig(ctx, stack, &cfg.Shh) utils.SetShhConfig(ctx, stack, &cfg.Shh)
utils.SetDashboardConfig(ctx, &cfg.Dashboard) utils.SetDashboardConfig(ctx, &cfg.Dashboard)

View File

@ -90,10 +90,6 @@ var (
utils.TxPoolAccountQueueFlag, utils.TxPoolAccountQueueFlag,
utils.TxPoolGlobalQueueFlag, utils.TxPoolGlobalQueueFlag,
utils.TxPoolLifetimeFlag, utils.TxPoolLifetimeFlag,
utils.ULCModeConfigFlag,
utils.OnlyAnnounceModeFlag,
utils.ULCTrustedNodesFlag,
utils.ULCMinTrustedFractionFlag,
utils.SyncModeFlag, utils.SyncModeFlag,
utils.ExitWhenSyncedFlag, utils.ExitWhenSyncedFlag,
utils.GCModeFlag, utils.GCModeFlag,
@ -102,6 +98,9 @@ var (
utils.LightBandwidthOutFlag, utils.LightBandwidthOutFlag,
utils.LightPeersFlag, utils.LightPeersFlag,
utils.LightKDFFlag, utils.LightKDFFlag,
utils.UltraLightServersFlag,
utils.UltraLightFractionFlag,
utils.UltraLightOnlyAnnounceFlag,
utils.WhitelistFlag, utils.WhitelistFlag,
utils.CacheFlag, utils.CacheFlag,
utils.CacheDatabaseFlag, utils.CacheDatabaseFlag,

View File

@ -86,6 +86,9 @@ var AppHelpFlagGroups = []flagGroup{
utils.LightBandwidthInFlag, utils.LightBandwidthInFlag,
utils.LightBandwidthOutFlag, utils.LightBandwidthOutFlag,
utils.LightPeersFlag, utils.LightPeersFlag,
utils.UltraLightServersFlag,
utils.UltraLightFractionFlag,
utils.UltraLightOnlyAnnounceFlag,
utils.LightKDFFlag, utils.LightKDFFlag,
utils.WhitelistFlag, utils.WhitelistFlag,
}, },

View File

@ -19,7 +19,6 @@ package utils
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -100,7 +99,6 @@ func NewApp(gitCommit, gitDate, usage string) *cli.App {
app := cli.NewApp() app := cli.NewApp()
app.Name = filepath.Base(os.Args[0]) app.Name = filepath.Base(os.Args[0])
app.Author = "" app.Author = ""
//app.Authors = nil
app.Email = "" app.Email = ""
app.Version = params.VersionWithCommit(gitCommit, gitDate) app.Version = params.VersionWithCommit(gitCommit, gitDate)
app.Usage = usage app.Usage = usage
@ -176,21 +174,19 @@ var (
Name: "exitwhensynced", Name: "exitwhensynced",
Usage: "Exits after block synchronisation completes", Usage: "Exits after block synchronisation completes",
} }
ULCModeConfigFlag = cli.StringFlag{ UltraLightServersFlag = cli.StringFlag{
Name: "ulc.config", Name: "ulc.servers",
Usage: "Config file to use for ultra light client mode", Usage: "List of trusted ultra-light servers",
Value: strings.Join(eth.DefaultConfig.UltraLightServers, ","),
} }
OnlyAnnounceModeFlag = cli.BoolFlag{ UltraLightFractionFlag = cli.IntFlag{
Name: "ulc.onlyannounce",
Usage: "ULC server sends announcements only",
}
ULCMinTrustedFractionFlag = cli.IntFlag{
Name: "ulc.fraction", Name: "ulc.fraction",
Usage: "Minimum % of trusted ULC servers required to announce a new head", Usage: "Minimum % of trusted ultra-light servers required to announce a new head",
Value: eth.DefaultConfig.UltraLightFraction,
} }
ULCTrustedNodesFlag = cli.StringFlag{ UltraLightOnlyAnnounceFlag = cli.BoolFlag{
Name: "ulc.trusted", Name: "ulc.onlyannounce",
Usage: "List of trusted ULC servers", Usage: "Ultra light server sends announcements only",
} }
IterativeOutputFlag = cli.BoolFlag{ IterativeOutputFlag = cli.BoolFlag{
Name: "iterative", Name: "iterative",
@ -953,37 +949,20 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
} }
} }
// SetULC setup ULC config from file if given. // setUltraLight configures the ultra light client settings from the command line flags.
func SetULC(ctx *cli.Context, cfg *eth.Config) { func setUltraLight(ctx *cli.Context, cfg *eth.Config) {
// ULC config isn't loaded from global config and ULC config and ULC trusted nodes are not defined. if ctx.GlobalIsSet(UltraLightServersFlag.Name) {
if cfg.ULC == nil && !(ctx.GlobalIsSet(ULCModeConfigFlag.Name) || ctx.GlobalIsSet(ULCTrustedNodesFlag.Name)) { cfg.UltraLightServers = strings.Split(ctx.GlobalString(UltraLightServersFlag.Name), ",")
return
} }
cfg.ULC = &eth.ULCConfig{} if ctx.GlobalIsSet(UltraLightFractionFlag.Name) {
cfg.UltraLightFraction = ctx.GlobalInt(UltraLightFractionFlag.Name)
path := ctx.GlobalString(ULCModeConfigFlag.Name)
if path != "" {
cfgData, err := ioutil.ReadFile(path)
if err != nil {
Fatalf("Failed to unmarshal ULC configuration: %v", err)
}
err = json.Unmarshal(cfgData, &cfg.ULC)
if err != nil {
Fatalf("Failed to unmarshal ULC configuration: %s", err.Error())
}
} }
if cfg.UltraLightFraction <= 0 && cfg.UltraLightFraction > 100 {
if trustedNodes := ctx.GlobalString(ULCTrustedNodesFlag.Name); trustedNodes != "" { log.Error("Ultra light fraction is invalid", "had", cfg.UltraLightFraction, "updated", eth.DefaultConfig.UltraLightFraction)
cfg.ULC.TrustedServers = strings.Split(trustedNodes, ",") cfg.UltraLightFraction = eth.DefaultConfig.UltraLightFraction
} }
if ctx.GlobalIsSet(UltraLightOnlyAnnounceFlag.Name) {
if trustedFraction := ctx.GlobalInt(ULCMinTrustedFractionFlag.Name); trustedFraction > 0 { cfg.UltraLightOnlyAnnounce = ctx.GlobalBool(UltraLightOnlyAnnounceFlag.Name)
cfg.ULC.MinTrustedFraction = trustedFraction
}
if cfg.ULC.MinTrustedFraction <= 0 && cfg.ULC.MinTrustedFraction > 100 {
log.Error("MinTrustedFraction is invalid", "MinTrustedFraction", cfg.ULC.MinTrustedFraction, "Changed to default", eth.DefaultULCMinTrustedFraction)
cfg.ULC.MinTrustedFraction = eth.DefaultULCMinTrustedFraction
} }
} }
@ -1400,6 +1379,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
setEthash(ctx, cfg) setEthash(ctx, cfg)
setMiner(ctx, &cfg.Miner) setMiner(ctx, &cfg.Miner)
setWhitelist(ctx, cfg) setWhitelist(ctx, cfg)
setUltraLight(ctx, cfg)
if ctx.GlobalIsSet(SyncModeFlag.Name) { if ctx.GlobalIsSet(SyncModeFlag.Name) {
cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode) cfg.SyncMode = *GlobalTextMarshaler(ctx, SyncModeFlag.Name).(*downloader.SyncMode)
@ -1412,9 +1392,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
if ctx.GlobalIsSet(LightPeersFlag.Name) { if ctx.GlobalIsSet(LightPeersFlag.Name) {
cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name) cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
} }
if ctx.GlobalIsSet(OnlyAnnounceModeFlag.Name) {
cfg.OnlyAnnounce = ctx.GlobalBool(OnlyAnnounceModeFlag.Name)
}
if ctx.GlobalIsSet(NetworkIdFlag.Name) { if ctx.GlobalIsSet(NetworkIdFlag.Name) {
cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name) cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
} }

View File

@ -43,12 +43,13 @@ var DefaultConfig = Config{
DatasetsInMem: 1, DatasetsInMem: 1,
DatasetsOnDisk: 2, DatasetsOnDisk: 2,
}, },
NetworkId: 1, NetworkId: 1,
LightPeers: 100, LightPeers: 100,
DatabaseCache: 512, UltraLightFraction: 75,
TrieCleanCache: 256, DatabaseCache: 512,
TrieDirtyCache: 256, TrieCleanCache: 256,
TrieTimeout: 60 * time.Minute, TrieDirtyCache: 256,
TrieTimeout: 60 * time.Minute,
Miner: miner.Config{ Miner: miner.Config{
GasFloor: 8000000, GasFloor: 8000000,
GasCeil: 8000000, GasCeil: 8000000,
@ -101,14 +102,15 @@ type Config struct {
Whitelist map[uint64]common.Hash `toml:"-"` Whitelist map[uint64]common.Hash `toml:"-"`
// Light client options // Light client options
LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests
LightBandwidthIn int `toml:",omitempty"` // Incoming bandwidth limit for light servers LightBandwidthIn int `toml:",omitempty"` // Incoming bandwidth limit for light servers
LightBandwidthOut int `toml:",omitempty"` // Outgoing bandwidth limit for light servers LightBandwidthOut int `toml:",omitempty"` // Outgoing bandwidth limit for light servers
LightPeers int `toml:",omitempty"` // Maximum number of LES client peers LightPeers int `toml:",omitempty"` // Maximum number of LES client peers
OnlyAnnounce bool // Maximum number of LES client peers
// Ultra Light client options // Ultra Light client options
ULC *ULCConfig `toml:",omitempty"` UltraLightServers []string `toml:",omitempty"` // List of trusted ultra light servers
UltraLightFraction int `toml:",omitempty"` // Percentage of trusted servers to accept an announcement
UltraLightOnlyAnnounce bool `toml:",omitempty"` // Whether to only announce headers, or also serve them
// Database options // Database options
SkipBcVersionCheck bool `toml:"-"` SkipBcVersionCheck bool `toml:"-"`

View File

@ -28,10 +28,11 @@ func (c Config) MarshalTOML() (interface{}, error) {
LightBandwidthIn int `toml:",omitempty"` LightBandwidthIn int `toml:",omitempty"`
LightBandwidthOut int `toml:",omitempty"` LightBandwidthOut int `toml:",omitempty"`
LightPeers int `toml:",omitempty"` LightPeers int `toml:",omitempty"`
OnlyAnnounce bool UltraLightServers []string `toml:",omitempty"`
ULC *ULCConfig `toml:",omitempty"` UltraLightFraction int `toml:",omitempty"`
SkipBcVersionCheck bool `toml:"-"` UltraLightOnlyAnnounce bool `toml:",omitempty"`
DatabaseHandles int `toml:"-"` SkipBcVersionCheck bool `toml:"-"`
DatabaseHandles int `toml:"-"`
DatabaseCache int DatabaseCache int
DatabaseFreezer string DatabaseFreezer string
TrieCleanCache int TrieCleanCache int
@ -45,7 +46,6 @@ func (c Config) MarshalTOML() (interface{}, error) {
DocRoot string `toml:"-"` DocRoot string `toml:"-"`
EWASMInterpreter string EWASMInterpreter string
EVMInterpreter string EVMInterpreter string
ConstantinopleOverride *big.Int
RPCGasCap *big.Int `toml:",omitempty"` RPCGasCap *big.Int `toml:",omitempty"`
Checkpoint *params.TrustedCheckpoint Checkpoint *params.TrustedCheckpoint
CheckpointOracle *params.CheckpointOracleConfig CheckpointOracle *params.CheckpointOracleConfig
@ -61,8 +61,9 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.LightBandwidthIn = c.LightBandwidthIn enc.LightBandwidthIn = c.LightBandwidthIn
enc.LightBandwidthOut = c.LightBandwidthOut enc.LightBandwidthOut = c.LightBandwidthOut
enc.LightPeers = c.LightPeers enc.LightPeers = c.LightPeers
enc.OnlyAnnounce = c.OnlyAnnounce enc.UltraLightServers = c.UltraLightServers
enc.ULC = c.ULC enc.UltraLightFraction = c.UltraLightFraction
enc.UltraLightOnlyAnnounce = c.UltraLightOnlyAnnounce
enc.SkipBcVersionCheck = c.SkipBcVersionCheck enc.SkipBcVersionCheck = c.SkipBcVersionCheck
enc.DatabaseHandles = c.DatabaseHandles enc.DatabaseHandles = c.DatabaseHandles
enc.DatabaseCache = c.DatabaseCache enc.DatabaseCache = c.DatabaseCache
@ -97,10 +98,11 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
LightBandwidthIn *int `toml:",omitempty"` LightBandwidthIn *int `toml:",omitempty"`
LightBandwidthOut *int `toml:",omitempty"` LightBandwidthOut *int `toml:",omitempty"`
LightPeers *int `toml:",omitempty"` LightPeers *int `toml:",omitempty"`
OnlyAnnounce *bool UltraLightServers []string `toml:",omitempty"`
ULC *ULCConfig `toml:",omitempty"` UltraLightFraction *int `toml:",omitempty"`
SkipBcVersionCheck *bool `toml:"-"` UltraLightOnlyAnnounce *bool `toml:",omitempty"`
DatabaseHandles *int `toml:"-"` SkipBcVersionCheck *bool `toml:"-"`
DatabaseHandles *int `toml:"-"`
DatabaseCache *int DatabaseCache *int
DatabaseFreezer *string DatabaseFreezer *string
TrieCleanCache *int TrieCleanCache *int
@ -152,11 +154,14 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.LightPeers != nil { if dec.LightPeers != nil {
c.LightPeers = *dec.LightPeers c.LightPeers = *dec.LightPeers
} }
if dec.OnlyAnnounce != nil { if dec.UltraLightServers != nil {
c.OnlyAnnounce = *dec.OnlyAnnounce c.UltraLightServers = dec.UltraLightServers
} }
if dec.ULC != nil { if dec.UltraLightFraction != nil {
c.ULC = dec.ULC c.UltraLightFraction = *dec.UltraLightFraction
}
if dec.UltraLightOnlyAnnounce != nil {
c.UltraLightOnlyAnnounce = *dec.UltraLightOnlyAnnounce
} }
if dec.SkipBcVersionCheck != nil { if dec.SkipBcVersionCheck != nil {
c.SkipBcVersionCheck = *dec.SkipBcVersionCheck c.SkipBcVersionCheck = *dec.SkipBcVersionCheck

View File

@ -1,9 +0,0 @@
package eth
const DefaultULCMinTrustedFraction = 75
// ULCConfig is a Ultra Light client options.
type ULCConfig struct {
TrustedServers []string `toml:",omitempty"` // A list of trusted servers
MinTrustedFraction int `toml:",omitempty"` // Minimum percentage of connected trusted servers to validate trusted (1-100)
}

View File

@ -110,12 +110,7 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
bloomRequests: make(chan chan *bloombits.Retrieval), bloomRequests: make(chan chan *bloombits.Retrieval),
bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations), bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations),
} }
leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg, leth.config.UltraLightServers)
var trustedNodes []string
if leth.config.ULC != nil {
trustedNodes = leth.config.ULC.TrustedServers
}
leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg, trustedNodes)
leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool) leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool)
leth.relay = newLesTxRelay(peers, leth.retriever) leth.relay = newLesTxRelay(peers, leth.retriever)
@ -159,11 +154,11 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
oracle = params.CheckpointOracles[genesisHash] oracle = params.CheckpointOracles[genesisHash]
} }
registrar := newCheckpointOracle(oracle, leth.getLocalCheckpoint) registrar := newCheckpointOracle(oracle, leth.getLocalCheckpoint)
if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, checkpoint, light.DefaultClientIndexerConfig, config.ULC, true, config.NetworkId, leth.eventMux, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.serverPool, registrar, quitSync, &leth.wg, nil); err != nil { if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, checkpoint, light.DefaultClientIndexerConfig, config.UltraLightServers, config.UltraLightFraction, true, config.NetworkId, leth.eventMux, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.serverPool, registrar, quitSync, &leth.wg, nil); err != nil {
return nil, err return nil, err
} }
if leth.protocolManager.isULCEnabled() { if leth.protocolManager.ulc != nil {
log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction) log.Warn("Ultra light client is enabled", "servers", len(config.UltraLightServers), "fraction", config.UltraLightFraction)
leth.blockchain.DisableCheckFreq() leth.blockchain.DisableCheckFreq()
} }
return leth, nil return leth, nil

View File

@ -469,23 +469,18 @@ func (f *lightFetcher) findBestRequest() (bestHash common.Hash, bestAmount uint6
// isTrustedHash checks if the block can be trusted by the minimum trusted fraction. // isTrustedHash checks if the block can be trusted by the minimum trusted fraction.
func (f *lightFetcher) isTrustedHash(hash common.Hash) bool { func (f *lightFetcher) isTrustedHash(hash common.Hash) bool {
if !f.pm.isULCEnabled() { // If ultra light cliet mode is disabled, trust all hashes
if f.pm.ulc == nil {
return true return true
} }
// Ultra light enabled, only trust after enough confirmations
var numAgreed int var agreed int
for p, fp := range f.peers { for peer, info := range f.peers {
if !p.isTrusted { if peer.trusted && info.nodeByHash[hash] != nil {
continue agreed++
} }
if _, ok := fp.nodeByHash[hash]; !ok {
continue
}
numAgreed++
} }
return 100*agreed/len(f.pm.ulc.keys) >= f.pm.ulc.fraction
return 100*numAgreed/len(f.pm.ulc.trustedKeys) >= f.pm.ulc.minTrustedFraction
} }
func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq { func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq {
@ -498,16 +493,15 @@ func (f *lightFetcher) newFetcherDistReqForSync(bestHash common.Hash) *distReq {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
if p.isOnlyAnnounce { if p.onlyAnnounce {
return false return false
} }
fp := f.peers[p] fp := f.peers[p]
return fp != nil && fp.nodeByHash[bestHash] != nil return fp != nil && fp.nodeByHash[bestHash] != nil
}, },
request: func(dp distPeer) func() { request: func(dp distPeer) func() {
if f.pm.isULCEnabled() { if f.pm.ulc != nil {
//keep last trusted header before sync // Keep last trusted header before sync
f.setLastTrustedHeader(f.chain.CurrentHeader()) f.setLastTrustedHeader(f.chain.CurrentHeader())
} }
go func() { go func() {
@ -533,10 +527,9 @@ func (f *lightFetcher) newFetcherDistReq(bestHash common.Hash, reqID uint64, bes
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
if p.isOnlyAnnounce { if p.onlyAnnounce {
return false return false
} }
fp := f.peers[p] fp := f.peers[p]
if fp == nil { if fp == nil {
return false return false
@ -708,36 +701,30 @@ func (f *lightFetcher) checkSyncedHeaders(p *peer) {
p.Log().Debug("Unknown peer to check sync headers") p.Log().Debug("Unknown peer to check sync headers")
return return
} }
var (
n := fp.lastAnnounced node = fp.lastAnnounced
var td *big.Int td *big.Int
)
var h *types.Header if f.pm.ulc != nil {
if f.pm.isULCEnabled() { // Roll back untrusted blocks
var unapprovedHashes []common.Hash h, unapproved := f.lastTrustedTreeNode(p)
// Overwrite last announced for ULC mode f.chain.Rollback(unapproved)
h, unapprovedHashes = f.lastTrustedTreeNode(p) node = fp.nodeByHash[h.Hash()]
//rollback untrusted blocks
f.chain.Rollback(unapprovedHashes)
//overwrite to last trusted
n = fp.nodeByHash[h.Hash()]
} }
// Find last valid block
//find last valid block for node != nil {
for n != nil { if td = f.chain.GetTd(node.hash, node.number); td != nil {
if td = f.chain.GetTd(n.hash, n.number); td != nil {
break break
} }
n = n.parent node = node.parent
} }
// Now node is the latest downloaded/approved header after syncing
// Now n is the latest downloaded/approved header after syncing if node == nil {
if n == nil {
p.Log().Debug("Synchronisation failed") p.Log().Debug("Synchronisation failed")
go f.pm.removePeer(p.id) go f.pm.removePeer(p.id)
return return
} }
header := f.chain.GetHeader(n.hash, n.number) header := f.chain.GetHeader(node.hash, node.number)
f.newHeaders([]*types.Header{header}, []*big.Int{td}) f.newHeaders([]*types.Header{header}, []*big.Int{td})
} }

View File

@ -36,22 +36,22 @@ func TestFetcherULCPeerSelector(t *testing.T) {
lf := lightFetcher{ lf := lightFetcher{
pm: &ProtocolManager{ pm: &ProtocolManager{
ulc: &ulc{ ulc: &ulc{
trustedKeys: map[string]struct{}{ keys: map[string]bool{
id1.String(): {}, id1.String(): true,
id2.String(): {}, id2.String(): true,
id3.String(): {}, id3.String(): true,
id4.String(): {}, id4.String(): true,
}, },
minTrustedFraction: 70, fraction: 70,
}, },
}, },
maxConfirmedTd: ftn1.td, maxConfirmedTd: ftn1.td,
peers: map[*peer]*fetcherPeerInfo{ peers: map[*peer]*fetcherPeerInfo{
{ {
id: "peer1", id: "peer1",
Peer: p2p.NewPeer(id1, "peer1", []p2p.Cap{}), Peer: p2p.NewPeer(id1, "peer1", []p2p.Cap{}),
isTrusted: true, trusted: true,
}: { }: {
nodeByHash: map[common.Hash]*fetcherTreeNode{ nodeByHash: map[common.Hash]*fetcherTreeNode{
ftn1.hash: ftn1, ftn1.hash: ftn1,
@ -59,9 +59,9 @@ func TestFetcherULCPeerSelector(t *testing.T) {
}, },
}, },
{ {
Peer: p2p.NewPeer(id2, "peer2", []p2p.Cap{}), Peer: p2p.NewPeer(id2, "peer2", []p2p.Cap{}),
id: "peer2", id: "peer2",
isTrusted: true, trusted: true,
}: { }: {
nodeByHash: map[common.Hash]*fetcherTreeNode{ nodeByHash: map[common.Hash]*fetcherTreeNode{
ftn1.hash: ftn1, ftn1.hash: ftn1,
@ -69,9 +69,9 @@ func TestFetcherULCPeerSelector(t *testing.T) {
}, },
}, },
{ {
id: "peer3", id: "peer3",
Peer: p2p.NewPeer(id3, "peer3", []p2p.Cap{}), Peer: p2p.NewPeer(id3, "peer3", []p2p.Cap{}),
isTrusted: true, trusted: true,
}: { }: {
nodeByHash: map[common.Hash]*fetcherTreeNode{ nodeByHash: map[common.Hash]*fetcherTreeNode{
ftn1.hash: ftn1, ftn1.hash: ftn1,
@ -80,9 +80,9 @@ func TestFetcherULCPeerSelector(t *testing.T) {
}, },
}, },
{ {
id: "peer4", id: "peer4",
Peer: p2p.NewPeer(id4, "peer4", []p2p.Cap{}), Peer: p2p.NewPeer(id4, "peer4", []p2p.Cap{}),
isTrusted: true, trusted: true,
}: { }: {
nodeByHash: map[common.Hash]*fetcherTreeNode{ nodeByHash: map[common.Hash]*fetcherTreeNode{
ftn1.hash: ftn1, ftn1.hash: ftn1,

View File

@ -31,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -130,7 +129,7 @@ type ProtocolManager struct {
// 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
// with the ethereum network. // with the ethereum network.
func NewProtocolManager(chainConfig *params.ChainConfig, checkpoint *params.TrustedCheckpoint, indexerConfig *light.IndexerConfig, ulcConfig *eth.ULCConfig, client bool, networkId uint64, mux *event.TypeMux, peers *peerSet, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, serverPool *serverPool, registrar *checkpointOracle, quitSync chan struct{}, wg *sync.WaitGroup, synced func() bool) (*ProtocolManager, error) { func NewProtocolManager(chainConfig *params.ChainConfig, checkpoint *params.TrustedCheckpoint, indexerConfig *light.IndexerConfig, ulcServers []string, ulcFraction int, client bool, networkId uint64, mux *event.TypeMux, peers *peerSet, blockchain BlockChain, txpool txPool, chainDb ethdb.Database, odr *LesOdr, serverPool *serverPool, registrar *checkpointOracle, quitSync chan struct{}, wg *sync.WaitGroup, 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{
client: client, client: client,
@ -157,10 +156,14 @@ func NewProtocolManager(chainConfig *params.ChainConfig, checkpoint *params.Trus
manager.reqDist = odr.retriever.dist manager.reqDist = odr.retriever.dist
} }
if ulcConfig != nil { if ulcServers != nil {
manager.ulc = newULC(ulcConfig) ulc, err := newULC(ulcServers, ulcFraction)
if err != nil {
log.Warn("Failed to initialize ultra light client", "err", err)
} else {
manager.ulc = ulc
}
} }
removePeer := manager.removePeer removePeer := manager.removePeer
if disableClientRemovePeer { if disableClientRemovePeer {
removePeer = func(id string) {} removePeer = func(id string) {}
@ -247,11 +250,11 @@ func (pm *ProtocolManager) runPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWrit
} }
func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { func (pm *ProtocolManager) newPeer(pv int, nv uint64, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
var isTrusted bool var trusted bool
if pm.isULCEnabled() { if pm.ulc != nil {
isTrusted = pm.ulc.isTrusted(p.ID()) trusted = pm.ulc.trusted(p.ID())
} }
return newPeer(pv, nv, isTrusted, p, newMeteredMsgWriter(rw)) return newPeer(pv, nv, trusted, p, newMeteredMsgWriter(rw))
} }
// handle is the callback invoked to manage the life cycle of a les peer. When // handle is the callback invoked to manage the life cycle of a les peer. When
@ -1197,14 +1200,6 @@ func (pm *ProtocolManager) txStatus(hash common.Hash) light.TxStatus {
return stat return stat
} }
// isULCEnabled returns true if we can use ULC
func (pm *ProtocolManager) isULCEnabled() bool {
if pm.ulc == nil || len(pm.ulc.trustedKeys) == 0 {
return false
}
return true
}
// downloaderPeerNotify implements peerSetNotify // downloaderPeerNotify implements peerSetNotify
type downloaderPeerNotify ProtocolManager type downloaderPeerNotify ProtocolManager

View File

@ -588,7 +588,7 @@ func TestStopResumeLes3(t *testing.T) {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
clock := &mclock.Simulated{} clock := &mclock.Simulated{}
testCost := testBufLimit / 10 testCost := testBufLimit / 10
pm, _, err := newTestProtocolManager(false, 0, nil, nil, nil, db, nil, testCost, clock) pm, _, err := newTestProtocolManager(false, 0, nil, nil, nil, db, nil, 0, testCost, clock)
if err != nil { if err != nil {
t.Fatalf("Failed to create protocol manager: %v", err) t.Fatalf("Failed to create protocol manager: %v", err)
} }

View File

@ -167,7 +167,7 @@ func testIndexers(db ethdb.Database, odr light.OdrBackend, config *light.Indexer
// newTestProtocolManager creates a new protocol manager for testing purposes, // newTestProtocolManager creates a new protocol manager for testing purposes,
// with the given number of blocks already known, potential notification // with the given number of blocks already known, potential notification
// channels for different events and relative chain indexers array. // channels for different events and relative chain indexers array.
func newTestProtocolManager(lightSync bool, blocks int, odr *LesOdr, indexers []*core.ChainIndexer, peers *peerSet, db ethdb.Database, ulcConfig *eth.ULCConfig, testCost uint64, clock mclock.Clock) (*ProtocolManager, *backends.SimulatedBackend, error) { func newTestProtocolManager(lightSync bool, blocks int, odr *LesOdr, indexers []*core.ChainIndexer, peers *peerSet, db ethdb.Database, ulcServers []string, ulcFraction int, testCost uint64, clock mclock.Clock) (*ProtocolManager, *backends.SimulatedBackend, error) {
var ( var (
evmux = new(event.TypeMux) evmux = new(event.TypeMux)
engine = ethash.NewFaker() engine = ethash.NewFaker()
@ -219,7 +219,7 @@ func newTestProtocolManager(lightSync bool, blocks int, odr *LesOdr, indexers []
} }
reg = newCheckpointOracle(config, getLocal) reg = newCheckpointOracle(config, getLocal)
} }
pm, err := NewProtocolManager(gspec.Config, nil, indexConfig, ulcConfig, lightSync, NetworkId, evmux, peers, chain, pool, db, odr, nil, reg, exitCh, new(sync.WaitGroup), func() bool { return true }) pm, err := NewProtocolManager(gspec.Config, nil, indexConfig, ulcServers, ulcFraction, lightSync, NetworkId, evmux, peers, chain, pool, db, odr, nil, reg, exitCh, new(sync.WaitGroup), func() bool { return true })
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -249,8 +249,8 @@ func newTestProtocolManager(lightSync bool, blocks int, odr *LesOdr, indexers []
// with the given number of blocks already known, potential notification channels // with the given number of blocks already known, potential notification channels
// for different events and relative chain indexers array. In case of an error, the // for different events and relative chain indexers array. In case of an error, the
// constructor force-fails the test. // constructor force-fails the test.
func newTestProtocolManagerMust(t *testing.T, lightSync bool, blocks int, odr *LesOdr, indexers []*core.ChainIndexer, peers *peerSet, db ethdb.Database, ulcConfig *eth.ULCConfig) (*ProtocolManager, *backends.SimulatedBackend) { func newTestProtocolManagerMust(t *testing.T, lightSync bool, blocks int, odr *LesOdr, indexers []*core.ChainIndexer, peers *peerSet, db ethdb.Database, ulcServers []string, ulcFraction int) (*ProtocolManager, *backends.SimulatedBackend) {
pm, backend, err := newTestProtocolManager(lightSync, blocks, odr, indexers, peers, db, ulcConfig, 0, &mclock.System{}) pm, backend, err := newTestProtocolManager(lightSync, blocks, odr, indexers, peers, db, ulcServers, ulcFraction, 0, &mclock.System{})
if err != nil { if err != nil {
t.Fatalf("Failed to create protocol manager: %v", err) t.Fatalf("Failed to create protocol manager: %v", err)
} }
@ -395,7 +395,7 @@ func newServerEnv(t *testing.T, blocks int, protocol int, waitIndexers func(*cor
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
indexers := testIndexers(db, nil, light.TestServerIndexerConfig) indexers := testIndexers(db, nil, light.TestServerIndexerConfig)
pm, b := newTestProtocolManagerMust(t, false, blocks, nil, indexers, nil, db, nil) pm, b := newTestProtocolManagerMust(t, false, blocks, nil, indexers, nil, db, nil, 0)
peer, _ := newTestPeer(t, "peer", protocol, pm, true, 0) peer, _ := newTestPeer(t, "peer", protocol, pm, true, 0)
cIndexer, bIndexer, btIndexer := indexers[0], indexers[1], indexers[2] cIndexer, bIndexer, btIndexer := indexers[0], indexers[1], indexers[2]
@ -441,8 +441,8 @@ func newClientServerEnv(t *testing.T, blocks int, protocol int, waitIndexers fun
odr.SetIndexers(lcIndexer, lbtIndexer, lbIndexer) odr.SetIndexers(lcIndexer, lbtIndexer, lbIndexer)
pm, b := newTestProtocolManagerMust(t, false, blocks, nil, indexers, peers, db, nil) pm, b := newTestProtocolManagerMust(t, false, blocks, nil, indexers, peers, db, nil, 0)
lpm, lb := newTestProtocolManagerMust(t, true, 0, odr, lIndexers, lPeers, ldb, nil) lpm, lb := newTestProtocolManagerMust(t, true, 0, odr, lIndexers, lPeers, ldb, nil, 0)
startIndexers := func(clientMode bool, pm *ProtocolManager) { startIndexers := func(clientMode bool, pm *ProtocolManager) {
if clientMode { if clientMode {

View File

@ -108,7 +108,7 @@ func (odr *LesOdr) Retrieve(ctx context.Context, req light.OdrRequest) (err erro
}, },
canSend: func(dp distPeer) bool { canSend: func(dp distPeer) bool {
p := dp.(*peer) p := dp.(*peer)
if !p.isOnlyAnnounce { if !p.onlyAnnounce {
return lreq.CanSend(p) return lreq.CanSend(p)
} }
return false return false

View File

@ -110,21 +110,21 @@ type peer struct {
fcParams flowcontrol.ServerParams fcParams flowcontrol.ServerParams
fcCosts requestCostTable fcCosts requestCostTable
isTrusted bool trusted bool
isOnlyAnnounce bool onlyAnnounce bool
chainSince, chainRecent uint64 chainSince, chainRecent uint64
stateSince, stateRecent uint64 stateSince, stateRecent uint64
} }
func newPeer(version int, network uint64, isTrusted bool, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { func newPeer(version int, network uint64, trusted bool, p *p2p.Peer, rw p2p.MsgReadWriter) *peer {
return &peer{ return &peer{
Peer: p, Peer: p,
rw: rw, rw: rw,
version: version, version: version,
network: network, network: network,
id: fmt.Sprintf("%x", p.ID().Bytes()), id: fmt.Sprintf("%x", p.ID().Bytes()),
isTrusted: isTrusted, trusted: trusted,
errCh: make(chan error, 1), errCh: make(chan error, 1),
} }
} }
@ -591,7 +591,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
} else { } else {
//on client node //on client node
p.announceType = announceTypeSimple p.announceType = announceTypeSimple
if p.isTrusted { if p.trusted {
p.announceType = announceTypeSigned p.announceType = announceTypeSigned
} }
send = send.add("announceType", p.announceType) send = send.add("announceType", p.announceType)
@ -652,22 +652,22 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
} else { } else {
//mark OnlyAnnounce server if "serveHeaders", "serveChainSince", "serveStateSince" or "txRelay" fields don't exist //mark OnlyAnnounce server if "serveHeaders", "serveChainSince", "serveStateSince" or "txRelay" fields don't exist
if recv.get("serveChainSince", &p.chainSince) != nil { if recv.get("serveChainSince", &p.chainSince) != nil {
p.isOnlyAnnounce = true p.onlyAnnounce = true
} }
if recv.get("serveRecentChain", &p.chainRecent) != nil { if recv.get("serveRecentChain", &p.chainRecent) != nil {
p.chainRecent = 0 p.chainRecent = 0
} }
if recv.get("serveStateSince", &p.stateSince) != nil { if recv.get("serveStateSince", &p.stateSince) != nil {
p.isOnlyAnnounce = true p.onlyAnnounce = true
} }
if recv.get("serveRecentState", &p.stateRecent) != nil { if recv.get("serveRecentState", &p.stateRecent) != nil {
p.stateRecent = 0 p.stateRecent = 0
} }
if recv.get("txRelay", nil) != nil { if recv.get("txRelay", nil) != nil {
p.isOnlyAnnounce = true p.onlyAnnounce = true
} }
if p.isOnlyAnnounce && !p.isTrusted { if p.onlyAnnounce && !p.trusted {
return errResp(ErrUselessPeer, "peer cannot serve requests") return errResp(ErrUselessPeer, "peer cannot serve requests")
} }
@ -689,7 +689,7 @@ func (p *peer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis
recv.get("checkpoint/value", &p.checkpoint) recv.get("checkpoint/value", &p.checkpoint)
recv.get("checkpoint/registerHeight", &p.checkpointNumber) recv.get("checkpoint/registerHeight", &p.checkpointNumber)
if !p.isOnlyAnnounce { if !p.onlyAnnounce {
for msgCode := range reqAvgTimeCost { for msgCode := range reqAvgTimeCost {
if p.fcCosts[msgCode] == nil { if p.fcCosts[msgCode] == nil {
return errResp(ErrUselessPeer, "peer does not support message %d", msgCode) return errResp(ErrUselessPeer, "peer does not support message %d", msgCode)

View File

@ -29,9 +29,9 @@ func TestPeerHandshakeSetAnnounceTypeToAnnounceTypeSignedForTrustedPeer(t *testi
//peer to connect(on ulc side) //peer to connect(on ulc side)
p := peer{ p := peer{
Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}), Peer: p2p.NewPeer(id, "test peer", []p2p.Cap{}),
version: protocol_version, version: protocol_version,
isTrusted: true, trusted: true,
rw: &rwStub{ rw: &rwStub{
WriteHook: func(recvList keyValueList) { WriteHook: func(recvList keyValueList) {
//checking that ulc sends to peer allowedRequests=onlyAnnounceRequests and announceType = announceTypeSigned //checking that ulc sends to peer allowedRequests=onlyAnnounceRequests and announceType = announceTypeSigned
@ -140,7 +140,7 @@ func TestPeerHandshakeDefaultAllRequests(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if p.isOnlyAnnounce { if p.onlyAnnounce {
t.Fatal("Incorrect announceType") t.Fatal("Incorrect announceType")
} }
} }
@ -196,8 +196,8 @@ func TestPeerHandshakeClientReceiveOnlyAnnounceRequestsHeaders(t *testing.T) {
return l return l
}, },
}, },
network: test_networkid, network: test_networkid,
isTrusted: true, trusted: true,
} }
err := p.Handshake(td, hash, headNum, genesis, nil) err := p.Handshake(td, hash, headNum, genesis, nil)
@ -205,8 +205,8 @@ func TestPeerHandshakeClientReceiveOnlyAnnounceRequestsHeaders(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if !p.isOnlyAnnounce { if !p.onlyAnnounce {
t.Fatal("isOnlyAnnounce must be true") t.Fatal("onlyAnnounce must be true")
} }
} }

View File

@ -77,7 +77,7 @@ func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) {
archiveMode: e.ArchiveMode(), archiveMode: e.ArchiveMode(),
quitSync: quitSync, quitSync: quitSync,
lesTopics: lesTopics, lesTopics: lesTopics,
onlyAnnounce: config.OnlyAnnounce, onlyAnnounce: config.UltraLightOnlyAnnounce,
} }
srv.costTracker, srv.minCapacity = newCostTracker(e.ChainDb(), config) srv.costTracker, srv.minCapacity = newCostTracker(e.ChainDb(), config)
@ -103,7 +103,7 @@ func NewLesServer(e *eth.Ethereum, config *eth.Config) (*LesServer, error) {
} }
registrar := newCheckpointOracle(oracle, srv.getLocalCheckpoint) registrar := newCheckpointOracle(oracle, srv.getLocalCheckpoint)
// TODO(rjl493456442) Checkpoint is useless for les server, separate handler for client and server. // TODO(rjl493456442) Checkpoint is useless for les server, separate handler for client and server.
pm, err := NewProtocolManager(e.BlockChain().Config(), nil, light.DefaultServerIndexerConfig, config.ULC, false, config.NetworkId, e.EventMux(), newPeerSet(), e.BlockChain(), e.TxPool(), e.ChainDb(), nil, nil, registrar, quitSync, new(sync.WaitGroup), e.Synced) pm, err := NewProtocolManager(e.BlockChain().Config(), nil, light.DefaultServerIndexerConfig, config.UltraLightServers, config.UltraLightFraction, false, config.NetworkId, e.EventMux(), newPeerSet(), e.BlockChain(), e.TxPool(), e.ChainDb(), nil, nil, registrar, quitSync, new(sync.WaitGroup), e.Synced)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -130,7 +130,7 @@ func (self *lesTxRelay) send(txs types.Transactions, count int) {
return peer.GetTxRelayCost(len(ll), len(enc)) return peer.GetTxRelayCost(len(ll), len(enc))
}, },
canSend: func(dp distPeer) bool { canSend: func(dp distPeer) bool {
return !dp.(*peer).isOnlyAnnounce && dp.(*peer) == pp return !dp.(*peer).onlyAnnounce && dp.(*peer) == pp
}, },
request: func(dp distPeer) func() { request: func(dp distPeer) func() {
peer := dp.(*peer) peer := dp.(*peer)

View File

@ -17,38 +17,38 @@
package les package les
import ( import (
"github.com/ethereum/go-ethereum/eth" "errors"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
) )
type ulc struct { type ulc struct {
trustedKeys map[string]struct{} keys map[string]bool
minTrustedFraction int fraction int
} }
// newULC creates and returns a ultra light client instance. // newULC creates and returns an ultra light client instance.
func newULC(ulcConfig *eth.ULCConfig) *ulc { func newULC(servers []string, fraction int) (*ulc, error) {
if ulcConfig == nil { keys := make(map[string]bool)
return nil for _, id := range servers {
}
m := make(map[string]struct{}, len(ulcConfig.TrustedServers))
for _, id := range ulcConfig.TrustedServers {
node, err := enode.Parse(enode.ValidSchemes, id) node, err := enode.Parse(enode.ValidSchemes, id)
if err != nil { if err != nil {
log.Debug("Failed to parse trusted server", "id", id, "err", err) log.Warn("Failed to parse trusted server", "id", id, "err", err)
continue continue
} }
m[node.ID().String()] = struct{}{} keys[node.ID().String()] = true
} }
return &ulc{m, ulcConfig.MinTrustedFraction} if len(keys) == 0 {
return nil, errors.New("no trusted servers")
}
return &ulc{
keys: keys,
fraction: fraction,
}, nil
} }
// isTrusted return an indicator that whether the specified peer is trusted. // trusted return an indicator that whether the specified peer is trusted.
func (u *ulc) isTrusted(p enode.ID) bool { func (u *ulc) trusted(p enode.ID) bool {
if u.trustedKeys == nil { return u.keys[p.String()]
return false
}
_, ok := u.trustedKeys[p.String()]
return ok
} }

View File

@ -28,7 +28,6 @@ import (
"github.com/ethereum/go-ethereum/common/mclock" "github.com/ethereum/go-ethereum/common/mclock"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/light" "github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enode"
@ -36,22 +35,15 @@ import (
func TestULCSyncWithOnePeer(t *testing.T) { func TestULCSyncWithOnePeer(t *testing.T) {
f := newFullPeerPair(t, 1, 4) f := newFullPeerPair(t, 1, 4)
ulcConfig := &eth.ULCConfig{ l := newLightPeer(t, []string{f.Node.String()}, 100)
MinTrustedFraction: 100,
TrustedServers: []string{f.Node.String()},
}
l := newLightPeer(t, ulcConfig)
if reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) { if reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
t.Fatal("blocks are equal") t.Fatal("blocks are equal")
} }
_, _, err := connectPeers(f, l, 2) _, _, err := connectPeers(f, l, 2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
l.PM.fetcher.lock.Lock() l.PM.fetcher.lock.Lock()
l.PM.fetcher.nextRequest() l.PM.fetcher.nextRequest()
l.PM.fetcher.lock.Unlock() l.PM.fetcher.lock.Unlock()
@ -63,24 +55,17 @@ func TestULCSyncWithOnePeer(t *testing.T) {
func TestULCReceiveAnnounce(t *testing.T) { func TestULCReceiveAnnounce(t *testing.T) {
f := newFullPeerPair(t, 1, 4) f := newFullPeerPair(t, 1, 4)
ulcConfig := &eth.ULCConfig{ l := newLightPeer(t, []string{f.Node.String()}, 100)
MinTrustedFraction: 100,
TrustedServers: []string{f.Node.String()},
}
l := newLightPeer(t, ulcConfig)
fPeer, lPeer, err := connectPeers(f, l, 2) fPeer, lPeer, err := connectPeers(f, l, 2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
l.PM.synchronise(fPeer) l.PM.synchronise(fPeer)
//check that the sync is finished correctly //check that the sync is finished correctly
if !reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) { if !reflect.DeepEqual(f.PM.blockchain.CurrentHeader().Hash(), l.PM.blockchain.CurrentHeader().Hash()) {
t.Fatal("sync doesn't work") t.Fatal("sync doesn't work")
} }
l.PM.peers.lock.Lock() l.PM.peers.lock.Lock()
if len(l.PM.peers.peers) == 0 { if len(l.PM.peers.peers) == 0 {
t.Fatal("peer list should not be empty") t.Fatal("peer list should not be empty")
@ -101,16 +86,7 @@ func TestULCReceiveAnnounce(t *testing.T) {
func TestULCShouldNotSyncWithTwoPeersOneHaveEmptyChain(t *testing.T) { func TestULCShouldNotSyncWithTwoPeersOneHaveEmptyChain(t *testing.T) {
f1 := newFullPeerPair(t, 1, 4) f1 := newFullPeerPair(t, 1, 4)
f2 := newFullPeerPair(t, 2, 0) f2 := newFullPeerPair(t, 2, 0)
ulcConf := &ulc{minTrustedFraction: 100, trustedKeys: make(map[string]struct{})} l := newLightPeer(t, []string{f1.Node.String(), f2.Node.String()}, 100)
ulcConf.trustedKeys[f1.Node.ID().String()] = struct{}{}
ulcConf.trustedKeys[f2.Node.ID().String()] = struct{}{}
ulcConfig := &eth.ULCConfig{
MinTrustedFraction: 100,
TrustedServers: []string{f1.Node.String(), f2.Node.String()},
}
l := newLightPeer(t, ulcConfig)
l.PM.ulc.minTrustedFraction = 100
_, _, err := connectPeers(f1, l, 2) _, _, err := connectPeers(f1, l, 2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -119,7 +95,6 @@ func TestULCShouldNotSyncWithTwoPeersOneHaveEmptyChain(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
l.PM.fetcher.lock.Lock() l.PM.fetcher.lock.Lock()
l.PM.fetcher.nextRequest() l.PM.fetcher.nextRequest()
l.PM.fetcher.lock.Unlock() l.PM.fetcher.lock.Unlock()
@ -134,27 +109,19 @@ func TestULCShouldNotSyncWithThreePeersOneHaveEmptyChain(t *testing.T) {
f2 := newFullPeerPair(t, 2, 4) f2 := newFullPeerPair(t, 2, 4)
f3 := newFullPeerPair(t, 3, 0) f3 := newFullPeerPair(t, 3, 0)
ulcConfig := &eth.ULCConfig{ l := newLightPeer(t, []string{f1.Node.String(), f2.Node.String(), f3.Node.String()}, 60)
MinTrustedFraction: 60,
TrustedServers: []string{f1.Node.String(), f2.Node.String(), f3.Node.String()},
}
l := newLightPeer(t, ulcConfig)
_, _, err := connectPeers(f1, l, 2) _, _, err := connectPeers(f1, l, 2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, _, err = connectPeers(f2, l, 2) _, _, err = connectPeers(f2, l, 2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
_, _, err = connectPeers(f3, l, 2) _, _, err = connectPeers(f3, l, 2)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
l.PM.fetcher.lock.Lock() l.PM.fetcher.lock.Lock()
l.PM.fetcher.nextRequest() l.PM.fetcher.nextRequest()
l.PM.fetcher.lock.Unlock() l.PM.fetcher.lock.Unlock()
@ -213,7 +180,7 @@ func connectPeers(full, light pairPeer, version int) (*peer, *peer, error) {
func newFullPeerPair(t *testing.T, index int, numberOfblocks int) pairPeer { func newFullPeerPair(t *testing.T, index int, numberOfblocks int) pairPeer {
db := rawdb.NewMemoryDatabase() db := rawdb.NewMemoryDatabase()
pmFull, _ := newTestProtocolManagerMust(t, false, numberOfblocks, nil, nil, nil, db, nil) pmFull, _ := newTestProtocolManagerMust(t, false, numberOfblocks, nil, nil, nil, db, nil, 0)
peerPairFull := pairPeer{ peerPairFull := pairPeer{
Name: "full node", Name: "full node",
@ -229,7 +196,7 @@ func newFullPeerPair(t *testing.T, index int, numberOfblocks int) pairPeer {
} }
// newLightPeer creates node with light sync mode // newLightPeer creates node with light sync mode
func newLightPeer(t *testing.T, ulcConfig *eth.ULCConfig) pairPeer { func newLightPeer(t *testing.T, ulcServers []string, ulcFraction int) pairPeer {
peers := newPeerSet() peers := newPeerSet()
dist := newRequestDistributor(peers, make(chan struct{}), &mclock.System{}) dist := newRequestDistributor(peers, make(chan struct{}), &mclock.System{})
rm := newRetrieveManager(peers, dist, nil) rm := newRetrieveManager(peers, dist, nil)
@ -237,12 +204,11 @@ func newLightPeer(t *testing.T, ulcConfig *eth.ULCConfig) pairPeer {
odr := NewLesOdr(ldb, light.DefaultClientIndexerConfig, rm) odr := NewLesOdr(ldb, light.DefaultClientIndexerConfig, rm)
pmLight, _ := newTestProtocolManagerMust(t, true, 0, odr, nil, peers, ldb, ulcConfig) pmLight, _ := newTestProtocolManagerMust(t, true, 0, odr, nil, peers, ldb, ulcServers, ulcFraction)
peerPairLight := pairPeer{ peerPairLight := pairPeer{
Name: "ulc node", Name: "ulc node",
PM: pmLight, PM: pmLight,
} }
key, err := crypto.GenerateKey() key, err := crypto.GenerateKey()
if err != nil { if err != nil {
t.Fatal("generate key err:", err) t.Fatal("generate key err:", err)

View File

@ -76,9 +76,6 @@ type NodeConfig struct {
// Listening address of pprof server. // Listening address of pprof server.
PprofAddress string PprofAddress string
// Ultra Light client options
ULC *eth.ULCConfig
} }
// defaultNodeConfig contains the default node configuration values to use if all // defaultNodeConfig contains the default node configuration values to use if all