forked from cerc-io/plugeth
cmd, eth, les: fix up ultra light config integration
This commit is contained in:
parent
8c249cb82f
commit
213690cdfd
@ -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)
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
|
@ -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 = ð.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)
|
||||||
}
|
}
|
||||||
|
@ -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:"-"`
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
|
||||||
}
|
|
@ -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
|
||||||
|
@ -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})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
32
les/peer.go
32
les/peer.go
@ -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)
|
||||||
|
@ -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")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
40
les/ulc.go
40
les/ulc.go
@ -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
|
|
||||||
}
|
}
|
||||||
|
@ -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 := ð.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 := ð.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 := ð.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 := ð.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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user