les: les/4 minimalistic version (#21909)

* les: allow tx unindexing in les/4 light server mode

* les: minor fixes

* les: more small fixes

* les: add meaningful constants for recentTxIndex handshake field
This commit is contained in:
Felföldi Zsolt 2020-12-15 20:12:14 +01:00 committed by GitHub
parent 8cde2966af
commit c7f2536735
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 6 deletions

View File

@ -1491,10 +1491,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
CheckExclusive(ctx, LegacyLightServFlag, LightServeFlag, SyncModeFlag, "light") CheckExclusive(ctx, LegacyLightServFlag, LightServeFlag, SyncModeFlag, "light")
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
CheckExclusive(ctx, GCModeFlag, "archive", TxLookupLimitFlag) CheckExclusive(ctx, GCModeFlag, "archive", TxLookupLimitFlag)
// todo(rjl493456442) make it available for les server if (ctx.GlobalIsSet(LegacyLightServFlag.Name) || ctx.GlobalIsSet(LightServeFlag.Name)) && ctx.GlobalIsSet(TxLookupLimitFlag.Name) {
// Ancient tx indices pruning is not available for les server now log.Warn("LES server cannot serve old transaction status and cannot connect below les/4 protocol version if transaction lookup index is limited")
// since light client relies on the server for transaction status query. }
CheckExclusive(ctx, LegacyLightServFlag, LightServeFlag, TxLookupLimitFlag)
var ks *keystore.KeyStore var ks *keystore.KeyStore
if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 { if keystores := stack.AccountManager().Backends(keystore.KeyStoreType); len(keystores) > 0 {
ks = keystores[0].(*keystore.KeyStore) ks = keystores[0].(*keystore.KeyStore)

View File

@ -488,7 +488,7 @@ func (r *TxStatusRequest) GetCost(peer *serverPeer) uint64 {
// CanSend tells if a certain peer is suitable for serving the given request // CanSend tells if a certain peer is suitable for serving the given request
func (r *TxStatusRequest) CanSend(peer *serverPeer) bool { func (r *TxStatusRequest) CanSend(peer *serverPeer) bool {
return peer.version >= lpv2 return peer.serveTxLookup
} }
// Request sends an ODR request to the LES network (implementation of LesOdrRequest) // Request sends an ODR request to the LES network (implementation of LesOdrRequest)

View File

@ -341,6 +341,7 @@ type serverPeer struct {
onlyAnnounce bool // The flag whether the server sends announcement only. onlyAnnounce bool // The flag whether the server sends announcement only.
chainSince, chainRecent uint64 // The range of chain server peer can serve. chainSince, chainRecent uint64 // The range of chain server peer can serve.
stateSince, stateRecent uint64 // The range of state server peer can serve. stateSince, stateRecent uint64 // The range of state server peer can serve.
serveTxLookup bool // The server peer can serve tx lookups.
// Advertised checkpoint fields // Advertised checkpoint fields
checkpointNumber uint64 // The block height which the checkpoint is registered. checkpointNumber uint64 // The block height which the checkpoint is registered.
@ -628,6 +629,18 @@ func (p *serverPeer) Handshake(genesis common.Hash, forkid forkid.ID, forkFilter
if recv.get("txRelay", nil) != nil { if recv.get("txRelay", nil) != nil {
p.onlyAnnounce = true p.onlyAnnounce = true
} }
if p.version >= lpv4 {
var recentTx uint
if err := recv.get("recentTxLookup", &recentTx); err != nil {
return err
}
// Note: in the current version we only consider the tx index service useful
// if it is unlimited. This can be made configurable in the future.
p.serveTxLookup = recentTx == txIndexUnlimited
} else {
p.serveTxLookup = true
}
if p.onlyAnnounce && !p.trusted { if p.onlyAnnounce && !p.trusted {
return errResp(ErrUselessPeer, "peer cannot serve requests") return errResp(ErrUselessPeer, "peer cannot serve requests")
} }
@ -969,6 +982,20 @@ func (p *clientPeer) freezeClient() {
// Handshake executes the les protocol handshake, negotiating version number, // Handshake executes the les protocol handshake, negotiating version number,
// network IDs, difficulties, head and genesis blocks. // network IDs, difficulties, head and genesis blocks.
func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter, server *LesServer) error { func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, genesis common.Hash, forkID forkid.ID, forkFilter forkid.Filter, server *LesServer) error {
recentTx := server.handler.blockchain.TxLookupLimit()
if recentTx != txIndexUnlimited {
if recentTx < blockSafetyMargin {
recentTx = txIndexDisabled
} else {
recentTx -= blockSafetyMargin - txIndexRecentOffset
}
}
if server.config.UltraLightOnlyAnnounce {
recentTx = txIndexDisabled
}
if recentTx != txIndexUnlimited && p.version < lpv4 {
return errors.New("Cannot serve old clients without a complete tx index")
}
// Note: clientPeer.headInfo should contain the last head announced to the client by us. // Note: clientPeer.headInfo should contain the last head announced to the client by us.
// The values announced in the handshake are dummy values for compatibility reasons and should be ignored. // The values announced in the handshake are dummy values for compatibility reasons and should be ignored.
p.headInfo = blockInfo{Hash: head, Number: headNum, Td: td} p.headInfo = blockInfo{Hash: head, Number: headNum, Td: td}
@ -981,13 +1008,16 @@ func (p *clientPeer) Handshake(td *big.Int, head common.Hash, headNum uint64, ge
// If local ethereum node is running in archive mode, advertise ourselves we have // If local ethereum node is running in archive mode, advertise ourselves we have
// all version state data. Otherwise only recent state is available. // all version state data. Otherwise only recent state is available.
stateRecent := uint64(core.TriesInMemory - 4) stateRecent := uint64(core.TriesInMemory - blockSafetyMargin)
if server.archiveMode { if server.archiveMode {
stateRecent = 0 stateRecent = 0
} }
*lists = (*lists).add("serveRecentState", stateRecent) *lists = (*lists).add("serveRecentState", stateRecent)
*lists = (*lists).add("txRelay", nil) *lists = (*lists).add("txRelay", nil)
} }
if p.version >= lpv4 {
*lists = (*lists).add("recentTxLookup", recentTx)
}
*lists = (*lists).add("flowControl/BL", server.defParams.BufLimit) *lists = (*lists).add("flowControl/BL", server.defParams.BufLimit)
*lists = (*lists).add("flowControl/MRR", server.defParams.MinRecharge) *lists = (*lists).add("flowControl/MRR", server.defParams.MinRecharge)

View File

@ -50,6 +50,11 @@ var ProtocolLengths = map[uint]uint64{lpv2: 22, lpv3: 24, lpv4: 24}
const ( const (
NetworkId = 1 NetworkId = 1
ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message ProtocolMaxMsgSize = 10 * 1024 * 1024 // Maximum cap on the size of a protocol message
blockSafetyMargin = 4 // safety margin applied to block ranges specified relative to head block
txIndexUnlimited = 0 // this value in the "recentTxLookup" handshake field means the entire tx index history is served
txIndexDisabled = 1 // this value means tx index is not served at all
txIndexRecentOffset = 1 // txIndexRecentOffset + N in the handshake field means then tx index of the last N blocks is supported
) )
// les protocol message codes // les protocol message codes