Add snap protocol service stub (#1438)

* Cosmetics, update logger `topics`

* Clean up sync/start methods in nimbus

why:
* The `protocols` list selects served (as opposed to sync) protocols only.
* The `SyncMode.Default` object is allocated with the other possible sync
  mode objects.

* Add snap service stub to `nimbus`

* Provide full set of snap response handler stubs

* Bicarb for the latest CI hiccup

why:
  Might be a change in the CI engine for MacOS.
This commit is contained in:
Jordan Hrycaj 2023-01-20 15:01:29 +00:00 committed by GitHub
parent 9efb40336b
commit 6fb48517ba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 406 additions and 131 deletions

View File

@ -129,6 +129,13 @@ jobs:
chmod 755 external/bin/gcc external/bin/g++
echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH
- name: Install build dependencies (Macos)
# Some home brew modules were reported missing
if: runner.os == 'Macos'
run: |
HOMEBREW_NO_INSTALL_CLEANUP=1 brew install gnu-getopt
brew link --force gnu-getopt
- name: Restore rocksdb from cache (Macos/Linux)
if: runner.os != 'Windows'
id: rocksdb-cache

View File

@ -120,6 +120,7 @@ type
ProtocolFlag* {.pure.} = enum
## Protocol flags
Eth ## enable eth subprotocol
Snap ## enable snap sub-protocol
Les ## enable les subprotocol
RpcFlag* {.pure.} = enum
@ -169,7 +170,7 @@ type
"- default -- legacy sync mode\n" &
"- full -- full blockchain archive\n" &
"- snap -- experimental snap mode (development only)\n" &
"- snapCtx -- snap considering possible recovery context\n"
"- snapCtx -- snap considering possible recovery context"
defaultValue: SyncMode.Default
defaultValueDesc: $SyncMode.Default
abbr: "y"
@ -347,7 +348,8 @@ type
name: "agent-string" .}: string
protocols {.
desc: "Enable specific set of protocols (available: Eth, Les)"
desc: "Enable specific set of server protocols (available: Eth, " &
" Snap, Les, None.) This will not affect the sync mode"
defaultValue: @[]
defaultValueDesc: $ProtocolFlag.Eth
name: "protocols" .}: seq[string]
@ -622,13 +624,19 @@ proc getProtocolFlags*(conf: NimbusConf): set[ProtocolFlag] =
if conf.protocols.len == 0:
return {ProtocolFlag.Eth}
var noneOk = false
for item in repeatingList(conf.protocols):
case item.toLowerAscii()
of "eth": result.incl ProtocolFlag.Eth
of "les": result.incl ProtocolFlag.Les
of "snap": result.incl ProtocolFlag.Snap
of "none": noneOk = true
else:
error "Unknown protocol", name=item
quit QuitFailure
if noneOk and 0 < result.len:
error "Setting none contradicts wire protocols", names=result
quit QuitFailure
proc getRpcFlags(api: openArray[string]): set[RpcFlag] =
if api.len == 0:

View File

@ -57,6 +57,7 @@ type
networkLoop: Future[void]
dbBackend: ChainDB
peerManager: PeerManagerRef
legaSyncRef: LegacySyncRef
snapSyncRef: SnapSyncRef
fullSyncRef: FullSyncRef
merger: MergerRef
@ -145,38 +146,45 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
rng = nimbus.ctx.rng)
# Add protocol capabilities based on protocol flags
if ProtocolFlag.Eth in protocols:
nimbus.ethNode.addEthHandlerCapability(
nimbus.chainRef,
nimbus.txPool,
nimbus.ethNode.peerPool
)
case conf.syncMode:
of SyncMode.Snap, SyncMode.SnapCtx:
nimbus.ethNode.addCapability protocol.snap
of SyncMode.Full, SyncMode.Default:
discard
if ProtocolFlag.Les in protocols:
nimbus.ethNode.addCapability les
for w in protocols:
case w: # handle all possibilities
of ProtocolFlag.Eth:
nimbus.ethNode.addEthHandlerCapability(
nimbus.ethNode.peerPool,
nimbus.chainRef,
nimbus.txPool)
of ProtocolFlag.Les:
nimbus.ethNode.addCapability les
of ProtocolFlag.Snap:
nimbus.ethNode.addSnapHandlerCapability(
nimbus.ethNode.peerPool,
nimbus.chainRef)
# Early-initialise "--snap-sync" before starting any network connections.
if ProtocolFlag.Eth in protocols:
block:
let tickerOK =
conf.logLevel in {LogLevel.INFO, LogLevel.DEBUG, LogLevel.TRACE}
# Minimal capability needed for sync only
if ProtocolFlag.Eth notin protocols:
nimbus.ethNode.addEthHandlerCapability(
nimbus.ethNode.peerPool,
nimbus.chainRef)
case conf.syncMode:
of SyncMode.Full:
nimbus.fullSyncRef = FullSyncRef.init(
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
tickerOK)
nimbus.fullSyncRef.start
of SyncMode.Snap, SyncMode.SnapCtx:
# Minimal capability needed for sync only
if ProtocolFlag.Snap notin protocols:
nimbus.ethNode.addSnapHandlerCapability(
nimbus.ethNode.peerPool)
nimbus.snapSyncRef = SnapSyncRef.init(
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
nimbus.dbBackend, tickerOK, noRecovery = (conf.syncMode==SyncMode.Snap))
nimbus.snapSyncRef.start
of SyncMode.Default:
discard
nimbus.legaSyncRef = LegacySyncRef.new(
nimbus.ethNode, nimbus.chainRef)
# Connect directly to the static nodes
let staticPeers = conf.getStaticPeers()
@ -406,20 +414,18 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
setupP2P(nimbus, conf, protocols)
localServices(nimbus, conf, com, protocols)
if ProtocolFlag.Eth in protocols and conf.maxPeers > 0:
if conf.maxPeers > 0:
case conf.syncMode:
of SyncMode.Default:
let syncer = LegacySyncRef.new(nimbus.ethNode, nimbus.chainRef)
syncer.start
nimbus.legaSyncRef.start
nimbus.ethNode.setEthHandlerNewBlocksAndHashes(
legacy.newBlockHandler,
legacy.newBlockHashesHandler,
cast[pointer](syncer)
)
of SyncMode.Full, SyncMode.Snap, SyncMode.SnapCtx:
discard
cast[pointer](nimbus.legaSyncRef))
of SyncMode.Full:
nimbus.fullSyncRef.start
of SyncMode.Snap, SyncMode.SnapCtx:
nimbus.snapSyncRef.start
if nimbus.state == Starting:
# it might have been set to "Stopping" with Ctrl+C

View File

@ -44,12 +44,17 @@ type
arg: pointer
handler: NewBlockHashesHandler
EthWireRunState = enum
Enabled
Suspended
NotAvailable
EthWireRef* = ref object of EthWireBase
db: ChainDBRef
chain: ChainRef
txPool: TxPoolRef
peerPool: PeerPool
disableTxPool: bool
enableTxPool: EthWireRunState
knownByPeer: Table[Peer, HashToTime]
pending: HashSet[Hash256]
lastCleanup: Time
@ -296,7 +301,9 @@ proc fetchTransactions(ctx: EthWireRef, reqHashes: seq[Hash256], peer: Peer): Fu
# ------------------------------------------------------------------------------
proc onPeerConnected(ctx: EthWireRef, peer: Peer) =
if ctx.disableTxPool:
if ctx.enableTxPool != Enabled:
when trMissingOrDisabledGossipOk:
notEnabled("onPeerConnected")
return
var txHashes = newSeqOfCap[Hash256](ctx.txPool.numTxs)
@ -341,8 +348,11 @@ proc new*(_: type EthWireRef,
chain: chain,
txPool: txPool,
peerPool: peerPool,
lastCleanup: getTime(),
)
lastCleanup: getTime())
if txPool.isNil:
ctx.enableTxPool = NotAvailable
when trMissingOrDisabledGossipOk:
trace "New eth handler, minimal/outbound support only"
ctx.setupPeerObserver()
ctx
@ -368,7 +378,8 @@ proc setNewBlockHashesHandler*(ctx: EthWireRef, handler: NewBlockHashesHandler,
# ------------------------------------------------------------------------------
proc txPoolEnabled*(ctx: EthWireRef; ena: bool) =
ctx.disableTxPool = not ena
if ctx.enableTxPool != NotAvailable:
ctx.enableTxPool = if ena: Enabled else: Suspended
method getStatus*(ctx: EthWireRef): EthState
{.gcsafe, raises: [Defect,RlpError,EVMError].} =
@ -440,7 +451,7 @@ method getBlockHeaders*(ctx: EthWireRef, req: BlocksRequest): seq[BlockHeader]
method handleAnnouncedTxs*(ctx: EthWireRef, peer: Peer, txs: openArray[Transaction])
{.gcsafe, raises: [Defect,CatchableError].} =
if ctx.disableTxPool:
if ctx.enableTxPool != Enabled:
when trMissingOrDisabledGossipOk:
notEnabled("handleAnnouncedTxs")
return
@ -482,7 +493,7 @@ method handleAnnouncedTxs*(ctx: EthWireRef, peer: Peer, txs: openArray[Transacti
method handleAnnouncedTxsHashes*(ctx: EthWireRef, peer: Peer, txHashes: openArray[Hash256])
{.gcsafe, raises: [Defect,CatchableError].} =
if ctx.disableTxPool:
if ctx.enableTxPool != Enabled:
when trMissingOrDisabledGossipOk:
notEnabled("handleAnnouncedTxsHashes")
return

View File

@ -12,7 +12,8 @@ import
eth/p2p,
../../core/[chain, tx_pool],
../protocol,
./eth as handlers_eth
./eth as handlers_eth,
./snap as handlers_snap
{.used, push raises: [Defect].}
@ -24,27 +25,39 @@ proc setEthHandlerNewBlocksAndHashes*(
node: var EthereumNode;
blockHandler: NewBlockHandler;
hashesHandler: NewBlockHashesHandler;
arg: pointer)
{.gcsafe, raises: [Defect,CatchableError].} =
arg: pointer;
) {.gcsafe, raises: [Defect,CatchableError].} =
let w = EthWireRef(node.protocolState protocol.eth)
w.setNewBlockHandler(blockHandler, arg)
w.setNewBlockHashesHandler(hashesHandler, arg)
proc addEthHandlerCapability*(
node: var EthereumNode;
peerPool: PeerPool;
chain: ChainRef;
txPool: TxPoolRef;
peerPool: PeerPool) =
## Install handler
txPool = TxPoolRef(nil);
) =
## Install `eth` handlers. Passing `txPool` as `nil` installs the handler
## in minimal/outbound mode.
node.addCapability(
protocol.eth,
EthWireRef.new(chain, txPool, peerPool))
# ------------------------------------------------------------------------------
# Public functions: convenience mappings for `snap`
# ------------------------------------------------------------------------------
# To do ...
proc addSnapHandlerCapability*(
node: var EthereumNode;
peerPool: PeerPool;
chain = ChainRef(nil);
) =
## Install `snap` handlers,Passing `chein` as `nil` installs the handler
## in minimal/outbound mode.
if chain.isNil:
node.addCapability protocol.snap
else:
node.addCapability(protocol.snap, SnapWireRef.init(chain, peerPool))
# ------------------------------------------------------------------------------
# End

View File

@ -0,0 +1,120 @@
# Nimbus
# Copyright (c) 2018-2021 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed
# except according to those terms.
import
chronicles,
chronos,
eth/[p2p, p2p/peer_pool],
../protocol,
../protocol/[snap/snap_types, trace_config],
../../core/chain
{.push raises: [Defect].}
logScope:
topics = "wire-protocol"
type
SnapWireRef* = ref object of SnapWireBase
chain: ChainRef
peerPool: PeerPool
# ------------------------------------------------------------------------------
# Private functions: helper functions
# ------------------------------------------------------------------------------
proc notImplemented(name: string) =
debug "snapWire: hHandler method not implemented", meth=name
# ------------------------------------------------------------------------------
# Private functions: peer observer
# ------------------------------------------------------------------------------
#proc onPeerConnected(ctx: SnapWireRef, peer: Peer) =
# debug "snapWire: add peer", peer
# discard
#
#proc onPeerDisconnected(ctx: SnapWireRef, peer: Peer) =
# debug "snapWire: remove peer", peer
# discard
#
#proc setupPeerObserver(ctx: SnapWireRef) =
# var po = PeerObserver(
# onPeerConnected:
# proc(p: Peer) {.gcsafe.} =
# ctx.onPeerConnected(p),
# onPeerDisconnected:
# proc(p: Peer) {.gcsafe.} =
# ctx.onPeerDisconnected(p))
# po.setProtocol protocol.snap
# ctx.peerPool.addObserver(ctx, po)
# ------------------------------------------------------------------------------
# Public constructor/destructor
# ------------------------------------------------------------------------------
proc init*(
T: type SnapWireRef;
chain: ChainRef;
peerPool: PeerPool;
): T =
## Constructor (uses `init()` as suggested in style guide.)
let ctx = T(
chain: chain,
peerPool: peerPool)
#ctx.setupPeerObserver()
ctx
# ------------------------------------------------------------------------------
# Public functions: snap wire protocol handlers
# ------------------------------------------------------------------------------
method getAccountRange*(
ctx: SnapWireRef;
root: Hash256;
origin: Hash256;
limit: Hash256;
replySizeMax: uint64;
): (seq[SnapAccount], SnapAccountProof)
{.gcsafe.} =
notImplemented("getAccountRange")
method getStorageRanges*(
ctx: SnapWireRef;
root: Hash256;
accounts: openArray[Hash256];
origin: openArray[byte];
limit: openArray[byte];
replySizeMax: uint64;
): (seq[seq[SnapStorage]], SnapStorageProof)
{.gcsafe.} =
notImplemented("getStorageRanges")
method getByteCodes*(
ctx: SnapWireRef;
nodes: openArray[Hash256];
replySizeMax: uint64;
): seq[Blob]
{.gcsafe.} =
notImplemented("getByteCodes")
method getTrieNodes*(
ctx: SnapWireRef;
root: Hash256;
paths: openArray[seq[Blob]];
replySizeMax: uint64;
): seq[Blob]
{.gcsafe.} =
notImplemented("getTrieNodes")
# ------------------------------------------------------------------------------
# End
# ------------------------------------------------------------------------------

View File

@ -26,7 +26,7 @@ import
{.push raises:[Defect].}
logScope:
topics = "fast-sync"
topics = "legacy-sync"
const
minPeersToStartSync* = 2 # Wait for consensus of at least this

View File

@ -20,7 +20,7 @@ type
bestBlockHash*: Hash256
forkId*: ChainForkId
PeerState* = ref object of RootRef
EthPeerState* = ref object of RootRef
initialized*: bool
bestBlockHash*: Hash256
bestDifficulty*: DifficultyInt

View File

@ -75,7 +75,7 @@ const
p2pProtocol eth66(version = ethVersion,
rlpxName = "eth",
peerState = PeerState,
peerState = EthPeerState,
networkState = EthWireBase,
useRequestIds = true):

View File

@ -75,7 +75,7 @@ const
p2pProtocol eth67(version = ethVersion,
rlpxName = "eth",
peerState = PeerState,
peerState = EthPeerState,
networkState = EthWireBase,
useRequestIds = true):

View File

@ -0,0 +1,74 @@
# Nimbus
# Copyright (c) 2018-2021 Status Research & Development GmbH
# Licensed under either of
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
# http://www.apache.org/licenses/LICENSE-2.0)
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or
# http://opensource.org/licenses/MIT)
# at your option. This file may not be copied, modified, or distributed
# except according to those terms.
import
chronicles,
eth/[common, p2p, p2p/private/p2p_types]
# ../../types
type
SnapAccount* = object
accHash*: Hash256
accBody* {.rlpCustomSerialization.}: Account
SnapAccountProof* = seq[Blob]
SnapStorage* = object
slotHash*: Hash256
slotData*: Blob
SnapStorageProof* = seq[Blob]
SnapWireBase* = ref object of RootRef
SnapPeerState* = ref object of RootRef
proc notImplemented(name: string) =
debug "Method not implemented", meth = name
method getAccountRange*(
ctx: SnapWireBase;
root: Hash256;
origin: Hash256;
limit: Hash256;
replySizeMax: uint64;
): (seq[SnapAccount], SnapAccountProof)
{.base.} =
notImplemented("getAccountRange")
method getStorageRanges*(
ctx: SnapWireBase;
root: Hash256;
accounts: openArray[Hash256];
origin: openArray[byte];
limit: openArray[byte];
replySizeMax: uint64;
): (seq[seq[SnapStorage]], SnapStorageProof)
{.base.} =
notImplemented("getStorageRanges")
method getByteCodes*(
ctx: SnapWireBase;
nodes: openArray[Hash256];
replySizeMax: uint64;
): seq[Blob]
{.base.} =
notImplemented("getByteCodes")
method getTrieNodes*(
ctx: SnapWireBase;
root: Hash256;
paths: openArray[seq[Blob]];
replySizeMax: uint64;
): seq[Blob]
{.base.} =
notImplemented("getTrieNodes")
# End

View File

@ -139,25 +139,14 @@ import
chronos,
eth/[common, p2p, p2p/private/p2p_types],
nimcrypto/hash,
stew/byteutils,
../../constants,
./trace_config
./snap/snap_types,
../../constants
export
snap_types
logScope:
topics = "datax"
type
SnapAccount* = object
accHash*: Hash256
accBody* {.rlpCustomSerialization.}: Account
SnapAccountProof* = seq[Blob]
SnapStorage* = object
slotHash*: Hash256
slotData*: Blob
SnapStorageProof* = seq[Blob]
topics = "snap1"
const
snapVersion* = 1
@ -245,98 +234,145 @@ proc append(rlpWriter: var RlpWriter, t: SnapAccount, account: Account) =
p2pProtocol snap1(version = snapVersion,
rlpxName = "snap",
peerState = SnapPeerState,
networkState = SnapWireBase,
useRequestIds = true):
requestResponse:
# User message 0x00: GetAccountRange.
# Note: `origin` and `limit` differs from the specification to match Geth.
proc getAccountRange(peer: Peer, rootHash: Hash256, origin: Hash256,
limit: Hash256, responseBytes: uint64) =
trace trSnapRecvReceived & "GetAccountRange (0x00)", peer,
accountRange=[origin,limit], stateRoot=($rootHash), responseBytes
proc getAccountRange(
peer: Peer;
root: Hash256;
origin: Hash256;
limit: Hash256;
replySizeMax: uint64;
) =
trace trSnapRecvReceived & "GetAccountRange (0x00)", peer, root,
origin, limit, replySizeMax
trace trSnapSendReplying & "EMPTY AccountRange (0x01)", peer, sent=0
await response.send(@[], @[])
let
ctx = peer.networkState()
(accounts, proof) = ctx.getAccountRange(
root, origin, limit, replySizeMax)
# For logging only
nAccounts = accounts.len
nProof = proof.len
if nAccounts == 0 and nProof == 0:
trace trSnapSendReplying & "EMPTY AccountRange (0x01)", peer
else:
trace trSnapSendReplying & "AccountRange (0x01)", peer,
nAccounts, nProof
await response.send(accounts, proof)
# User message 0x01: AccountRange.
proc accountRange(peer: Peer, accounts: seq[SnapAccount],
proof: SnapAccountProof)
proc accountRange(
peer: Peer;
accounts: seq[SnapAccount];
proof: SnapAccountProof)
requestResponse:
# User message 0x02: GetStorageRanges.
# Note: `origin` and `limit` differs from the specification to match Geth.
proc getStorageRanges(peer: Peer, rootHash: Hash256,
accounts: openArray[Hash256], origin: openArray[byte],
limit: openArray[byte], responseBytes: uint64) =
when trSnapTracePacketsOk:
var definiteFullRange = ((origin.len == 32 or origin.len == 0) and
(limit.len == 32 or limit.len == 0))
if definiteFullRange:
for i in 0 ..< origin.len:
if origin[i] != 0x00:
definiteFullRange = false
break
if definiteFullRange:
for i in 0 ..< limit.len:
if limit[i] != 0xff:
definiteFullRange = false
break
proc getStorageRanges(
peer: Peer;
root: Hash256;
accounts: openArray[Hash256];
origin: openArray[byte];
limit: openArray[byte];
replySizeMax: uint64;
) =
trace trSnapRecvReceived & "GetStorageRanges (0x02)", peer, root,
nAccounts=accounts.len, nOrigin=origin.len, nLimit=limit.len,
replySizeMax
template describe(value: openArray[byte]): string =
if value.len == 0: "(empty)"
elif value.len == 32: value.toHex
else: "(non-standard-len=" & $value.len & ')' & value.toHex
let
ctx = peer.networkState()
(slots, proof) = ctx.getStorageRanges(
root, accounts, origin, limit, replySizeMax)
if definiteFullRange:
# Fetching storage for multiple accounts.
trace trSnapRecvReceived & "GetStorageRanges/A (0x02)", peer,
accountPaths=accounts.len,
stateRoot=($rootHash), responseBytes
elif accounts.len == 1:
# Fetching partial storage for one account, aka. "large contract".
trace trSnapRecvReceived & "GetStorageRanges/S (0x02)", peer,
accountPaths=1,
storageRange=(describe(origin) & '-' & describe(limit)),
stateRoot=($rootHash), responseBytes
else:
# This branch is separated because these shouldn't occur. It's not
# really specified what happens when there are multiple accounts and
# non-default path range.
trace trSnapRecvReceived & "GetStorageRanges/AS?? (0x02)", peer,
accountPaths=accounts.len,
storageRange=(describe(origin) & '-' & describe(limit)),
stateRoot=($rootHash), responseBytes
# For logging only
nSlots = slots.len
nProof = proof.len
trace trSnapSendReplying & "EMPTY StorageRanges (0x03)", peer, sent=0
await response.send(@[], @[])
if nSlots == 0 and nProof == 0:
trace trSnapSendReplying & "EMPTY StorageRanges (0x03)", peer
else:
trace trSnapSendReplying & "StorageRanges (0x03)", peer,
nSlots, nProof
await response.send(slots, proof)
# User message 0x03: StorageRanges.
# Note: See comments in this file for a list of Geth quirks to expect.
proc storageRanges(peer: Peer, slotLists: openArray[seq[SnapStorage]],
proof: SnapStorageProof)
proc storageRanges(
peer: Peer;
slotLists: openArray[seq[SnapStorage]];
proof: SnapStorageProof)
# User message 0x04: GetByteCodes.
requestResponse:
proc getByteCodes(peer: Peer, nodeHashes: openArray[Hash256],
responseBytes: uint64) =
# User message 0x04: GetByteCodes.
proc getByteCodes(
peer: Peer;
nodes: openArray[Hash256];
replySizeMax: uint64;
) =
trace trSnapRecvReceived & "GetByteCodes (0x04)", peer,
hashes=nodeHashes.len, responseBytes
nNodes=nodes.len, replySizeMax
trace trSnapSendReplying & "EMPTY ByteCodes (0x05)", peer, sent=0
let
ctx = peer.networkState()
codes = ctx.getByteCodes(nodes, replySizeMax)
# For logging only
nCodes = codes.len
if nCodes == 0:
trace trSnapSendReplying & "EMPTY ByteCodes (0x05)", peer
else:
trace trSnapSendReplying & "ByteCodes (0x05)", peer, nCodes
await response.send(@[])
# User message 0x05: ByteCodes.
proc byteCodes(peer: Peer, codes: openArray[Blob])
proc byteCodes(
peer: Peer;
codes: openArray[Blob])
# User message 0x06: GetTrieNodes.
requestResponse:
proc getTrieNodes(peer: Peer, rootHash: Hash256,
paths: openArray[seq[Blob]], responseBytes: uint64) =
trace trSnapRecvReceived & "GetTrieNodes (0x06)", peer,
nodePaths=paths.len, stateRoot=($rootHash), responseBytes
# User message 0x06: GetTrieNodes.
proc getTrieNodes(
peer: Peer;
root: Hash256;
paths: openArray[seq[Blob]];
replySizeMax: uint64;
) =
trace trSnapRecvReceived & "GetTrieNodes (0x06)", peer, root,
nPaths=paths.len, replySizeMax
trace trSnapSendReplying & "EMPTY TrieNodes (0x07)", peer, sent=0
await response.send(@[])
let
ctx = peer.networkState()
nodes = ctx.getTrieNodes(root, paths, replySizeMax)
# For logging only
nNodes = nodes.len
if nNodes == 0:
trace trSnapSendReplying & "EMPTY TrieNodes (0x07)", peer
else:
trace trSnapSendReplying & "TrieNodes (0x07)", peer, nNodes
await response.send(nodes)
# User message 0x07: TrieNodes.
proc trieNodes(peer: Peer, nodes: openArray[Blob])
proc trieNodes(
peer: Peer;
nodes: openArray[Blob])
# End

View File

@ -122,7 +122,7 @@ proc init*(
result.ctx.data.rng = rng
result.ctx.data.dbBackend = dbBackend
result.ctx.data.noRecovery = noRecovery
# Required to have been initialised via `addCapability()`
# Required to have been initialised via `addEthHandlerCapability()`
doAssert not result.ctx.ethWireCtx.isNil
proc start*(ctx: SnapSyncRef) =