mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-01-12 05:14:14 +00:00
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:
parent
9efb40336b
commit
6fb48517ba
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
120
nimbus/sync/handlers/snap.nim
Normal file
120
nimbus/sync/handlers/snap.nim
Normal 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
|
||||
# ------------------------------------------------------------------------------
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -75,7 +75,7 @@ const
|
||||
|
||||
p2pProtocol eth66(version = ethVersion,
|
||||
rlpxName = "eth",
|
||||
peerState = PeerState,
|
||||
peerState = EthPeerState,
|
||||
networkState = EthWireBase,
|
||||
useRequestIds = true):
|
||||
|
||||
|
@ -75,7 +75,7 @@ const
|
||||
|
||||
p2pProtocol eth67(version = ethVersion,
|
||||
rlpxName = "eth",
|
||||
peerState = PeerState,
|
||||
peerState = EthPeerState,
|
||||
networkState = EthWireBase,
|
||||
useRequestIds = true):
|
||||
|
||||
|
74
nimbus/sync/protocol/snap/snap_types.nim
Normal file
74
nimbus/sync/protocol/snap/snap_types.nim
Normal 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
|
@ -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
|
||||
|
@ -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) =
|
||||
|
Loading…
x
Reference in New Issue
Block a user