Skip to content

Commit

Permalink
les: implement ultralight client (#16904)
Browse files Browse the repository at this point in the history
For more information about this light client mode, read
https://hackmd.io/s/HJy7jjZpm
  • Loading branch information
b00ris authored and fjl committed Jan 24, 2019
1 parent b8f9b37 commit 7696570
Show file tree
Hide file tree
Showing 23 changed files with 1,285 additions and 176 deletions.
1 change: 1 addition & 0 deletions cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
}

// Apply flags.
utils.SetULC(ctx, &cfg.Eth)
utils.SetNodeConfig(ctx, &cfg.Node)
stack, err := node.New(&cfg.Node)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ var (
utils.TxPoolAccountQueueFlag,
utils.TxPoolGlobalQueueFlag,
utils.TxPoolLifetimeFlag,
utils.ULCModeConfigFlag,
utils.OnlyAnnounceModeFlag,
utils.ULCTrustedNodesFlag,
utils.ULCMinTrustedFractionFlag,
utils.SyncModeFlag,
utils.GCModeFlag,
utils.LightServFlag,
Expand Down
55 changes: 55 additions & 0 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package utils

import (
"crypto/ecdsa"
"encoding/json"
"fmt"
"io/ioutil"
"math/big"
Expand Down Expand Up @@ -161,6 +162,23 @@ var (
Usage: "Document Root for HTTPClient file scheme",
Value: DirectoryString{homeDir()},
}
ULCModeConfigFlag = cli.StringFlag{
Name: "ulc.config",
Usage: "Config file to use for ultra light client mode",
}
OnlyAnnounceModeFlag = cli.BoolFlag{
Name: "ulc.onlyannounce",
Usage: "ULC server sends announcements only",
}
ULCMinTrustedFractionFlag = cli.IntFlag{
Name: "ulc.fraction",
Usage: "Minimum % of trusted ULC servers required to announce a new head",
}
ULCTrustedNodesFlag = cli.StringFlag{
Name: "ulc.trusted",
Usage: "List of trusted ULC servers",
}

defaultSyncMode = eth.DefaultConfig.SyncMode
SyncModeFlag = TextMarshalerFlag{
Name: "syncmode",
Expand Down Expand Up @@ -871,6 +889,40 @@ func setIPC(ctx *cli.Context, cfg *node.Config) {
}
}

// SetULC setup ULC config from file if given.
func SetULC(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 cfg.ULC == nil && !(ctx.GlobalIsSet(ULCModeConfigFlag.Name) || ctx.GlobalIsSet(ULCTrustedNodesFlag.Name)) {
return
}
cfg.ULC = &eth.ULCConfig{}

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 trustedNodes := ctx.GlobalString(ULCTrustedNodesFlag.Name); trustedNodes != "" {
cfg.ULC.TrustedServers = strings.Split(trustedNodes, ",")
}

if trustedFraction := ctx.GlobalInt(ULCMinTrustedFractionFlag.Name); trustedFraction > 0 {
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
}
}

// makeDatabaseHandles raises out the number of allowed file handles per process
// for Geth and returns half of the allowance to assign to the database.
func makeDatabaseHandles() int {
Expand Down Expand Up @@ -1222,6 +1274,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
if ctx.GlobalIsSet(LightPeersFlag.Name) {
cfg.LightPeers = ctx.GlobalInt(LightPeersFlag.Name)
}
if ctx.GlobalIsSet(OnlyAnnounceModeFlag.Name) {
cfg.OnlyAnnounce = ctx.GlobalBool(OnlyAnnounceModeFlag.Name)
}
if ctx.GlobalIsSet(NetworkIdFlag.Name) {
cfg.NetworkId = ctx.GlobalUint64(NetworkIdFlag.Name)
}
Expand Down
16 changes: 10 additions & 6 deletions core/headerchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,18 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)

// Generate the list of seal verification requests, and start the parallel verifier
seals := make([]bool, len(chain))
for i := 0; i < len(seals)/checkFreq; i++ {
index := i*checkFreq + hc.rand.Intn(checkFreq)
if index >= len(seals) {
index = len(seals) - 1
if checkFreq != 0 {
// In case of checkFreq == 0 all seals are left false.
for i := 0; i < len(seals)/checkFreq; i++ {
index := i*checkFreq + hc.rand.Intn(checkFreq)
if index >= len(seals) {
index = len(seals) - 1
}
seals[index] = true
}
seals[index] = true
// Last should always be verified to avoid junk.
seals[len(seals)-1] = true
}
seals[len(seals)-1] = true // Last should always be verified to avoid junk

abort, results := hc.engine.VerifyHeaders(hc, chain, seals)
defer close(abort)
Expand Down
8 changes: 6 additions & 2 deletions eth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,12 @@ type Config struct {
Whitelist map[uint64]common.Hash `toml:"-"`

// Light client options
LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests
LightPeers int `toml:",omitempty"` // Maximum number of LES client peers
LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests
LightPeers int `toml:",omitempty"` // Maximum number of LES client peers
OnlyAnnounce bool // Maximum number of LES client peers

// Ultra Light client options
ULC *ULCConfig `toml:",omitempty"`

// Database options
SkipBcVersionCheck bool `toml:"-"`
Expand Down
29 changes: 21 additions & 8 deletions eth/gen_config.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions eth/ulc_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
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)
}
31 changes: 29 additions & 2 deletions les/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,12 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
bloomIndexer: eth.NewBloomIndexer(chainDb, params.BloomBitsBlocksClient, params.HelperTrieConfirmations),
}

var trustedNodes []string
if leth.config.ULC != nil {
trustedNodes = leth.config.ULC.TrustedServers
}
leth.relay = NewLesTxRelay(peers, leth.reqDist)
leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg)
leth.serverPool = newServerPool(chainDb, quitSync, &leth.wg, trustedNodes)
leth.retriever = newRetrieveManager(peers, leth.reqDist, leth.serverPool)

leth.odr = NewLesOdr(chainDb, light.DefaultClientIndexerConfig, leth.retriever)
Expand All @@ -136,10 +140,33 @@ func New(ctx *node.ServiceContext, config *eth.Config) (*LightEthereum, error) {
}

leth.txPool = light.NewTxPool(leth.chainConfig, leth.blockchain, leth.relay)
if leth.protocolManager, err = NewProtocolManager(leth.chainConfig, light.DefaultClientIndexerConfig, true, config.NetworkId, leth.eventMux, leth.engine, leth.peers, leth.blockchain, nil, chainDb, leth.odr, leth.relay, leth.serverPool, quitSync, &leth.wg); err != nil {

if leth.protocolManager, err = NewProtocolManager(
leth.chainConfig,
light.DefaultClientIndexerConfig,
true,
config.NetworkId,
leth.eventMux,
leth.engine,
leth.peers,
leth.blockchain,
nil,
chainDb,
leth.odr,
leth.relay,
leth.serverPool,
quitSync,
&leth.wg,
config.ULC); err != nil {
return nil, err
}

if leth.protocolManager.isULCEnabled() {
log.Warn("Ultra light client is enabled", "trustedNodes", len(leth.protocolManager.ulc.trustedKeys), "minTrustedFraction", leth.protocolManager.ulc.minTrustedFraction)
leth.blockchain.DisableCheckFreq()
}
leth.ApiBackend = &LesApiBackend{leth, nil}

gpoParams := config.GPO
if gpoParams.Default == nil {
gpoParams.Default = config.MinerGasPrice
Expand Down
Loading

0 comments on commit 7696570

Please sign in to comment.