Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eth, les: add new config "syncFromCheckpoint" #22123

Merged
merged 3 commits into from
Jan 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions eth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,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
LightIngress int `toml:",omitempty"` // Incoming bandwidth limit for light servers
LightEgress int `toml:",omitempty"` // Outgoing bandwidth limit for light servers
LightPeers int `toml:",omitempty"` // Maximum number of LES client peers
LightNoPrune bool `toml:",omitempty"` // Whether to disable light chain pruning
LightServ int `toml:",omitempty"` // Maximum percentage of time allowed for serving LES requests
LightIngress int `toml:",omitempty"` // Incoming bandwidth limit for light servers
LightEgress int `toml:",omitempty"` // Outgoing bandwidth limit for light servers
LightPeers int `toml:",omitempty"` // Maximum number of LES client peers
LightNoPrune bool `toml:",omitempty"` // Whether to disable light chain pruning
SyncFromCheckpoint bool `toml:",omitempty"` // Whether to sync the header chain from the configured checkpoint

// Ultra Light client options
UltraLightServers []string `toml:",omitempty"` // List of trusted ultra light servers
Expand Down
12 changes: 12 additions & 0 deletions eth/gen_config.go

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

9 changes: 6 additions & 3 deletions les/client_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,12 @@ type clientHandler struct {
downloader *downloader.Downloader
backend *LightEthereum

closeCh chan struct{}
wg sync.WaitGroup // WaitGroup used to track all connected peers.
syncDone func() // Test hooks when syncing is done.
closeCh chan struct{}
wg sync.WaitGroup // WaitGroup used to track all connected peers.

// Hooks used in the testing
syncStart func(header *types.Header) // Hook called when the syncing is started
syncEnd func(header *types.Header) // Hook called when the syncing is done
}

func newClientHandler(ulcServers []string, ulcFraction int, checkpoint *params.TrustedCheckpoint, backend *LightEthereum) *clientHandler {
Expand Down
6 changes: 3 additions & 3 deletions les/commons.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@ func (c *lesCommons) setupOracle(node *node.Node, genesis common.Hash, ethconfig
config = params.CheckpointOracles[genesis]
}
if config == nil {
log.Info("Checkpoint registrar is not enabled")
log.Info("Checkpoint oracle is not enabled")
return nil
}
if config.Address == (common.Address{}) || uint64(len(config.Signers)) < config.Threshold {
log.Warn("Invalid checkpoint registrar config")
log.Warn("Invalid checkpoint oracle config")
return nil
}
oracle := checkpointoracle.New(config, c.localCheckpoint)
rpcClient, _ := node.Attach()
client := ethclient.NewClient(rpcClient)
oracle.Start(client)
log.Info("Configured checkpoint registrar", "address", config.Address, "signers", len(config.Signers), "threshold", config.Threshold)
log.Info("Configured checkpoint oracle", "address", config.Address, "signers", len(config.Signers), "threshold", config.Threshold)
return oracle
}
52 changes: 35 additions & 17 deletions les/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/light"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)

var errInvalidCheckpoint = errors.New("invalid advertised checkpoint")
Expand Down Expand Up @@ -98,30 +99,41 @@ func (h *clientHandler) synchronise(peer *serverPeer) {
if currentTd != nil && peer.Td().Cmp(currentTd) < 0 {
return
}
// Recap the checkpoint.
//
// The light client may be connected to several different versions of the server.
// (1) Old version server which can not provide stable checkpoint in the handshake packet.
// => Use hardcoded checkpoint or empty checkpoint
// (2) New version server but simple checkpoint syncing is not enabled(e.g. mainnet, new testnet or private network)
// => Use hardcoded checkpoint or empty checkpoint
// (3) New version server but the provided stable checkpoint is even lower than the hardcoded one.
// => Use hardcoded checkpoint
// Recap the checkpoint. The light client may be connected to several different
// versions of the server.
// (1) Old version server which can not provide stable checkpoint in the
// handshake packet.
// => Use local checkpoint or empty checkpoint
// (2) New version server but simple checkpoint syncing is not enabled
// (e.g. mainnet, new testnet or private network)
// => Use local checkpoint or empty checkpoint
// (3) New version server but the provided stable checkpoint is even lower
// than the local one.
// => Use local checkpoint
// (4) New version server with valid and higher stable checkpoint
// => Use provided checkpoint
var checkpoint = &peer.checkpoint
var hardcoded bool
var (
local bool
checkpoint = &peer.checkpoint
)
if h.checkpoint != nil && h.checkpoint.SectionIndex >= peer.checkpoint.SectionIndex {
checkpoint = h.checkpoint // Use the hardcoded one.
hardcoded = true
local, checkpoint = true, h.checkpoint
}
// Replace the checkpoint with locally configured one If it's required by
// users. Nil checkpoint means synchronization from the scratch.
if h.backend.config.SyncFromCheckpoint {
local, checkpoint = true, h.backend.config.Checkpoint
if h.backend.config.Checkpoint == nil {
checkpoint = &params.TrustedCheckpoint{}
}
}
// Determine whether we should run checkpoint syncing or normal light syncing.
//
// Here has four situations that we will disable the checkpoint syncing:
//
// 1. The checkpoint is empty
// 2. The latest head block of the local chain is above the checkpoint.
// 3. The checkpoint is hardcoded(recap with local hardcoded checkpoint)
// 3. The checkpoint is local(replaced with local checkpoint)
// 4. For some networks the checkpoint syncing is not activated.
mode := checkpointSync
switch {
Expand All @@ -131,7 +143,7 @@ func (h *clientHandler) synchronise(peer *serverPeer) {
case latest.Number.Uint64() >= (checkpoint.SectionIndex+1)*h.backend.iConfig.ChtSize-1:
mode = lightSync
log.Debug("Disable checkpoint syncing", "reason", "local chain beyond the checkpoint")
case hardcoded:
case local:
mode = legacyCheckpointSync
log.Debug("Disable checkpoint syncing", "reason", "checkpoint is hardcoded")
case h.backend.oracle == nil || !h.backend.oracle.IsRunning():
Expand All @@ -143,12 +155,14 @@ func (h *clientHandler) synchronise(peer *serverPeer) {
}
log.Debug("Disable checkpoint syncing", "reason", "checkpoint syncing is not activated")
}

// Notify testing framework if syncing has completed(for testing purpose).
defer func() {
if h.syncDone != nil {
h.syncDone()
if h.syncEnd != nil {
h.syncEnd(h.backend.blockchain.CurrentHeader())
}
}()

start := time.Now()
if mode == checkpointSync || mode == legacyCheckpointSync {
// Validate the advertised checkpoint
Expand Down Expand Up @@ -177,6 +191,10 @@ func (h *clientHandler) synchronise(peer *serverPeer) {
return
}
}

if h.syncStart != nil {
h.syncStart(h.backend.blockchain.CurrentHeader())
}
// Fetch the remaining block headers based on the current chain header.
if err := h.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), downloader.LightSync); err != nil {
log.Debug("Synchronise failed", "reason", err)
Expand Down
Loading