mirror of
https://github.com/status-im/nimbus-eth1.git
synced 2025-02-04 16:25:10 +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++
|
chmod 755 external/bin/gcc external/bin/g++
|
||||||
echo '${{ github.workspace }}/external/bin' >> $GITHUB_PATH
|
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)
|
- name: Restore rocksdb from cache (Macos/Linux)
|
||||||
if: runner.os != 'Windows'
|
if: runner.os != 'Windows'
|
||||||
id: rocksdb-cache
|
id: rocksdb-cache
|
||||||
|
@ -120,6 +120,7 @@ type
|
|||||||
ProtocolFlag* {.pure.} = enum
|
ProtocolFlag* {.pure.} = enum
|
||||||
## Protocol flags
|
## Protocol flags
|
||||||
Eth ## enable eth subprotocol
|
Eth ## enable eth subprotocol
|
||||||
|
Snap ## enable snap sub-protocol
|
||||||
Les ## enable les subprotocol
|
Les ## enable les subprotocol
|
||||||
|
|
||||||
RpcFlag* {.pure.} = enum
|
RpcFlag* {.pure.} = enum
|
||||||
@ -169,7 +170,7 @@ type
|
|||||||
"- default -- legacy sync mode\n" &
|
"- default -- legacy sync mode\n" &
|
||||||
"- full -- full blockchain archive\n" &
|
"- full -- full blockchain archive\n" &
|
||||||
"- snap -- experimental snap mode (development only)\n" &
|
"- snap -- experimental snap mode (development only)\n" &
|
||||||
"- snapCtx -- snap considering possible recovery context\n"
|
"- snapCtx -- snap considering possible recovery context"
|
||||||
defaultValue: SyncMode.Default
|
defaultValue: SyncMode.Default
|
||||||
defaultValueDesc: $SyncMode.Default
|
defaultValueDesc: $SyncMode.Default
|
||||||
abbr: "y"
|
abbr: "y"
|
||||||
@ -347,7 +348,8 @@ type
|
|||||||
name: "agent-string" .}: string
|
name: "agent-string" .}: string
|
||||||
|
|
||||||
protocols {.
|
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: @[]
|
defaultValue: @[]
|
||||||
defaultValueDesc: $ProtocolFlag.Eth
|
defaultValueDesc: $ProtocolFlag.Eth
|
||||||
name: "protocols" .}: seq[string]
|
name: "protocols" .}: seq[string]
|
||||||
@ -622,13 +624,19 @@ proc getProtocolFlags*(conf: NimbusConf): set[ProtocolFlag] =
|
|||||||
if conf.protocols.len == 0:
|
if conf.protocols.len == 0:
|
||||||
return {ProtocolFlag.Eth}
|
return {ProtocolFlag.Eth}
|
||||||
|
|
||||||
|
var noneOk = false
|
||||||
for item in repeatingList(conf.protocols):
|
for item in repeatingList(conf.protocols):
|
||||||
case item.toLowerAscii()
|
case item.toLowerAscii()
|
||||||
of "eth": result.incl ProtocolFlag.Eth
|
of "eth": result.incl ProtocolFlag.Eth
|
||||||
of "les": result.incl ProtocolFlag.Les
|
of "les": result.incl ProtocolFlag.Les
|
||||||
|
of "snap": result.incl ProtocolFlag.Snap
|
||||||
|
of "none": noneOk = true
|
||||||
else:
|
else:
|
||||||
error "Unknown protocol", name=item
|
error "Unknown protocol", name=item
|
||||||
quit QuitFailure
|
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] =
|
proc getRpcFlags(api: openArray[string]): set[RpcFlag] =
|
||||||
if api.len == 0:
|
if api.len == 0:
|
||||||
|
@ -57,6 +57,7 @@ type
|
|||||||
networkLoop: Future[void]
|
networkLoop: Future[void]
|
||||||
dbBackend: ChainDB
|
dbBackend: ChainDB
|
||||||
peerManager: PeerManagerRef
|
peerManager: PeerManagerRef
|
||||||
|
legaSyncRef: LegacySyncRef
|
||||||
snapSyncRef: SnapSyncRef
|
snapSyncRef: SnapSyncRef
|
||||||
fullSyncRef: FullSyncRef
|
fullSyncRef: FullSyncRef
|
||||||
merger: MergerRef
|
merger: MergerRef
|
||||||
@ -145,38 +146,45 @@ proc setupP2P(nimbus: NimbusNode, conf: NimbusConf,
|
|||||||
rng = nimbus.ctx.rng)
|
rng = nimbus.ctx.rng)
|
||||||
|
|
||||||
# Add protocol capabilities based on protocol flags
|
# Add protocol capabilities based on protocol flags
|
||||||
if ProtocolFlag.Eth in protocols:
|
for w in protocols:
|
||||||
|
case w: # handle all possibilities
|
||||||
|
of ProtocolFlag.Eth:
|
||||||
nimbus.ethNode.addEthHandlerCapability(
|
nimbus.ethNode.addEthHandlerCapability(
|
||||||
|
nimbus.ethNode.peerPool,
|
||||||
nimbus.chainRef,
|
nimbus.chainRef,
|
||||||
nimbus.txPool,
|
nimbus.txPool)
|
||||||
nimbus.ethNode.peerPool
|
of ProtocolFlag.Les:
|
||||||
)
|
|
||||||
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
|
nimbus.ethNode.addCapability les
|
||||||
|
of ProtocolFlag.Snap:
|
||||||
|
nimbus.ethNode.addSnapHandlerCapability(
|
||||||
|
nimbus.ethNode.peerPool,
|
||||||
|
nimbus.chainRef)
|
||||||
|
|
||||||
# Early-initialise "--snap-sync" before starting any network connections.
|
# Early-initialise "--snap-sync" before starting any network connections.
|
||||||
if ProtocolFlag.Eth in protocols:
|
block:
|
||||||
let tickerOK =
|
let tickerOK =
|
||||||
conf.logLevel in {LogLevel.INFO, LogLevel.DEBUG, LogLevel.TRACE}
|
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:
|
case conf.syncMode:
|
||||||
of SyncMode.Full:
|
of SyncMode.Full:
|
||||||
nimbus.fullSyncRef = FullSyncRef.init(
|
nimbus.fullSyncRef = FullSyncRef.init(
|
||||||
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
||||||
tickerOK)
|
tickerOK)
|
||||||
nimbus.fullSyncRef.start
|
|
||||||
of SyncMode.Snap, SyncMode.SnapCtx:
|
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.snapSyncRef = SnapSyncRef.init(
|
||||||
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
nimbus.ethNode, nimbus.chainRef, nimbus.ctx.rng, conf.maxPeers,
|
||||||
nimbus.dbBackend, tickerOK, noRecovery = (conf.syncMode==SyncMode.Snap))
|
nimbus.dbBackend, tickerOK, noRecovery = (conf.syncMode==SyncMode.Snap))
|
||||||
nimbus.snapSyncRef.start
|
|
||||||
of SyncMode.Default:
|
of SyncMode.Default:
|
||||||
discard
|
nimbus.legaSyncRef = LegacySyncRef.new(
|
||||||
|
nimbus.ethNode, nimbus.chainRef)
|
||||||
|
|
||||||
# Connect directly to the static nodes
|
# Connect directly to the static nodes
|
||||||
let staticPeers = conf.getStaticPeers()
|
let staticPeers = conf.getStaticPeers()
|
||||||
@ -406,20 +414,18 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
|
|||||||
setupP2P(nimbus, conf, protocols)
|
setupP2P(nimbus, conf, protocols)
|
||||||
localServices(nimbus, conf, com, protocols)
|
localServices(nimbus, conf, com, protocols)
|
||||||
|
|
||||||
if ProtocolFlag.Eth in protocols and conf.maxPeers > 0:
|
if conf.maxPeers > 0:
|
||||||
case conf.syncMode:
|
case conf.syncMode:
|
||||||
of SyncMode.Default:
|
of SyncMode.Default:
|
||||||
let syncer = LegacySyncRef.new(nimbus.ethNode, nimbus.chainRef)
|
nimbus.legaSyncRef.start
|
||||||
syncer.start
|
|
||||||
|
|
||||||
nimbus.ethNode.setEthHandlerNewBlocksAndHashes(
|
nimbus.ethNode.setEthHandlerNewBlocksAndHashes(
|
||||||
legacy.newBlockHandler,
|
legacy.newBlockHandler,
|
||||||
legacy.newBlockHashesHandler,
|
legacy.newBlockHashesHandler,
|
||||||
cast[pointer](syncer)
|
cast[pointer](nimbus.legaSyncRef))
|
||||||
)
|
of SyncMode.Full:
|
||||||
|
nimbus.fullSyncRef.start
|
||||||
of SyncMode.Full, SyncMode.Snap, SyncMode.SnapCtx:
|
of SyncMode.Snap, SyncMode.SnapCtx:
|
||||||
discard
|
nimbus.snapSyncRef.start
|
||||||
|
|
||||||
if nimbus.state == Starting:
|
if nimbus.state == Starting:
|
||||||
# it might have been set to "Stopping" with Ctrl+C
|
# it might have been set to "Stopping" with Ctrl+C
|
||||||
|
@ -44,12 +44,17 @@ type
|
|||||||
arg: pointer
|
arg: pointer
|
||||||
handler: NewBlockHashesHandler
|
handler: NewBlockHashesHandler
|
||||||
|
|
||||||
|
EthWireRunState = enum
|
||||||
|
Enabled
|
||||||
|
Suspended
|
||||||
|
NotAvailable
|
||||||
|
|
||||||
EthWireRef* = ref object of EthWireBase
|
EthWireRef* = ref object of EthWireBase
|
||||||
db: ChainDBRef
|
db: ChainDBRef
|
||||||
chain: ChainRef
|
chain: ChainRef
|
||||||
txPool: TxPoolRef
|
txPool: TxPoolRef
|
||||||
peerPool: PeerPool
|
peerPool: PeerPool
|
||||||
disableTxPool: bool
|
enableTxPool: EthWireRunState
|
||||||
knownByPeer: Table[Peer, HashToTime]
|
knownByPeer: Table[Peer, HashToTime]
|
||||||
pending: HashSet[Hash256]
|
pending: HashSet[Hash256]
|
||||||
lastCleanup: Time
|
lastCleanup: Time
|
||||||
@ -296,7 +301,9 @@ proc fetchTransactions(ctx: EthWireRef, reqHashes: seq[Hash256], peer: Peer): Fu
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc onPeerConnected(ctx: EthWireRef, peer: Peer) =
|
proc onPeerConnected(ctx: EthWireRef, peer: Peer) =
|
||||||
if ctx.disableTxPool:
|
if ctx.enableTxPool != Enabled:
|
||||||
|
when trMissingOrDisabledGossipOk:
|
||||||
|
notEnabled("onPeerConnected")
|
||||||
return
|
return
|
||||||
|
|
||||||
var txHashes = newSeqOfCap[Hash256](ctx.txPool.numTxs)
|
var txHashes = newSeqOfCap[Hash256](ctx.txPool.numTxs)
|
||||||
@ -341,8 +348,11 @@ proc new*(_: type EthWireRef,
|
|||||||
chain: chain,
|
chain: chain,
|
||||||
txPool: txPool,
|
txPool: txPool,
|
||||||
peerPool: peerPool,
|
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.setupPeerObserver()
|
||||||
ctx
|
ctx
|
||||||
@ -368,7 +378,8 @@ proc setNewBlockHashesHandler*(ctx: EthWireRef, handler: NewBlockHashesHandler,
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
proc txPoolEnabled*(ctx: EthWireRef; ena: bool) =
|
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
|
method getStatus*(ctx: EthWireRef): EthState
|
||||||
{.gcsafe, raises: [Defect,RlpError,EVMError].} =
|
{.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])
|
method handleAnnouncedTxs*(ctx: EthWireRef, peer: Peer, txs: openArray[Transaction])
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
if ctx.disableTxPool:
|
if ctx.enableTxPool != Enabled:
|
||||||
when trMissingOrDisabledGossipOk:
|
when trMissingOrDisabledGossipOk:
|
||||||
notEnabled("handleAnnouncedTxs")
|
notEnabled("handleAnnouncedTxs")
|
||||||
return
|
return
|
||||||
@ -482,7 +493,7 @@ method handleAnnouncedTxs*(ctx: EthWireRef, peer: Peer, txs: openArray[Transacti
|
|||||||
|
|
||||||
method handleAnnouncedTxsHashes*(ctx: EthWireRef, peer: Peer, txHashes: openArray[Hash256])
|
method handleAnnouncedTxsHashes*(ctx: EthWireRef, peer: Peer, txHashes: openArray[Hash256])
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
{.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
if ctx.disableTxPool:
|
if ctx.enableTxPool != Enabled:
|
||||||
when trMissingOrDisabledGossipOk:
|
when trMissingOrDisabledGossipOk:
|
||||||
notEnabled("handleAnnouncedTxsHashes")
|
notEnabled("handleAnnouncedTxsHashes")
|
||||||
return
|
return
|
||||||
|
@ -12,7 +12,8 @@ import
|
|||||||
eth/p2p,
|
eth/p2p,
|
||||||
../../core/[chain, tx_pool],
|
../../core/[chain, tx_pool],
|
||||||
../protocol,
|
../protocol,
|
||||||
./eth as handlers_eth
|
./eth as handlers_eth,
|
||||||
|
./snap as handlers_snap
|
||||||
|
|
||||||
{.used, push raises: [Defect].}
|
{.used, push raises: [Defect].}
|
||||||
|
|
||||||
@ -24,18 +25,20 @@ proc setEthHandlerNewBlocksAndHashes*(
|
|||||||
node: var EthereumNode;
|
node: var EthereumNode;
|
||||||
blockHandler: NewBlockHandler;
|
blockHandler: NewBlockHandler;
|
||||||
hashesHandler: NewBlockHashesHandler;
|
hashesHandler: NewBlockHashesHandler;
|
||||||
arg: pointer)
|
arg: pointer;
|
||||||
{.gcsafe, raises: [Defect,CatchableError].} =
|
) {.gcsafe, raises: [Defect,CatchableError].} =
|
||||||
let w = EthWireRef(node.protocolState protocol.eth)
|
let w = EthWireRef(node.protocolState protocol.eth)
|
||||||
w.setNewBlockHandler(blockHandler, arg)
|
w.setNewBlockHandler(blockHandler, arg)
|
||||||
w.setNewBlockHashesHandler(hashesHandler, arg)
|
w.setNewBlockHashesHandler(hashesHandler, arg)
|
||||||
|
|
||||||
proc addEthHandlerCapability*(
|
proc addEthHandlerCapability*(
|
||||||
node: var EthereumNode;
|
node: var EthereumNode;
|
||||||
|
peerPool: PeerPool;
|
||||||
chain: ChainRef;
|
chain: ChainRef;
|
||||||
txPool: TxPoolRef;
|
txPool = TxPoolRef(nil);
|
||||||
peerPool: PeerPool) =
|
) =
|
||||||
## Install handler
|
## Install `eth` handlers. Passing `txPool` as `nil` installs the handler
|
||||||
|
## in minimal/outbound mode.
|
||||||
node.addCapability(
|
node.addCapability(
|
||||||
protocol.eth,
|
protocol.eth,
|
||||||
EthWireRef.new(chain, txPool, peerPool))
|
EthWireRef.new(chain, txPool, peerPool))
|
||||||
@ -44,7 +47,17 @@ proc addEthHandlerCapability*(
|
|||||||
# Public functions: convenience mappings for `snap`
|
# 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
|
# 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].}
|
{.push raises:[Defect].}
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "fast-sync"
|
topics = "legacy-sync"
|
||||||
|
|
||||||
const
|
const
|
||||||
minPeersToStartSync* = 2 # Wait for consensus of at least this
|
minPeersToStartSync* = 2 # Wait for consensus of at least this
|
||||||
|
@ -20,7 +20,7 @@ type
|
|||||||
bestBlockHash*: Hash256
|
bestBlockHash*: Hash256
|
||||||
forkId*: ChainForkId
|
forkId*: ChainForkId
|
||||||
|
|
||||||
PeerState* = ref object of RootRef
|
EthPeerState* = ref object of RootRef
|
||||||
initialized*: bool
|
initialized*: bool
|
||||||
bestBlockHash*: Hash256
|
bestBlockHash*: Hash256
|
||||||
bestDifficulty*: DifficultyInt
|
bestDifficulty*: DifficultyInt
|
||||||
|
@ -75,7 +75,7 @@ const
|
|||||||
|
|
||||||
p2pProtocol eth66(version = ethVersion,
|
p2pProtocol eth66(version = ethVersion,
|
||||||
rlpxName = "eth",
|
rlpxName = "eth",
|
||||||
peerState = PeerState,
|
peerState = EthPeerState,
|
||||||
networkState = EthWireBase,
|
networkState = EthWireBase,
|
||||||
useRequestIds = true):
|
useRequestIds = true):
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ const
|
|||||||
|
|
||||||
p2pProtocol eth67(version = ethVersion,
|
p2pProtocol eth67(version = ethVersion,
|
||||||
rlpxName = "eth",
|
rlpxName = "eth",
|
||||||
peerState = PeerState,
|
peerState = EthPeerState,
|
||||||
networkState = EthWireBase,
|
networkState = EthWireBase,
|
||||||
useRequestIds = true):
|
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,
|
chronos,
|
||||||
eth/[common, p2p, p2p/private/p2p_types],
|
eth/[common, p2p, p2p/private/p2p_types],
|
||||||
nimcrypto/hash,
|
nimcrypto/hash,
|
||||||
stew/byteutils,
|
./snap/snap_types,
|
||||||
../../constants,
|
../../constants
|
||||||
./trace_config
|
|
||||||
|
export
|
||||||
|
snap_types
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "datax"
|
topics = "snap1"
|
||||||
|
|
||||||
type
|
|
||||||
SnapAccount* = object
|
|
||||||
accHash*: Hash256
|
|
||||||
accBody* {.rlpCustomSerialization.}: Account
|
|
||||||
|
|
||||||
SnapAccountProof* = seq[Blob]
|
|
||||||
|
|
||||||
SnapStorage* = object
|
|
||||||
slotHash*: Hash256
|
|
||||||
slotData*: Blob
|
|
||||||
|
|
||||||
SnapStorageProof* = seq[Blob]
|
|
||||||
|
|
||||||
const
|
const
|
||||||
snapVersion* = 1
|
snapVersion* = 1
|
||||||
@ -245,98 +234,145 @@ proc append(rlpWriter: var RlpWriter, t: SnapAccount, account: Account) =
|
|||||||
|
|
||||||
p2pProtocol snap1(version = snapVersion,
|
p2pProtocol snap1(version = snapVersion,
|
||||||
rlpxName = "snap",
|
rlpxName = "snap",
|
||||||
|
peerState = SnapPeerState,
|
||||||
|
networkState = SnapWireBase,
|
||||||
useRequestIds = true):
|
useRequestIds = true):
|
||||||
|
|
||||||
requestResponse:
|
requestResponse:
|
||||||
# User message 0x00: GetAccountRange.
|
# User message 0x00: GetAccountRange.
|
||||||
# Note: `origin` and `limit` differs from the specification to match Geth.
|
# Note: `origin` and `limit` differs from the specification to match Geth.
|
||||||
proc getAccountRange(peer: Peer, rootHash: Hash256, origin: Hash256,
|
proc getAccountRange(
|
||||||
limit: Hash256, responseBytes: uint64) =
|
peer: Peer;
|
||||||
trace trSnapRecvReceived & "GetAccountRange (0x00)", peer,
|
root: Hash256;
|
||||||
accountRange=[origin,limit], stateRoot=($rootHash), responseBytes
|
origin: Hash256;
|
||||||
|
limit: Hash256;
|
||||||
|
replySizeMax: uint64;
|
||||||
|
) =
|
||||||
|
trace trSnapRecvReceived & "GetAccountRange (0x00)", peer, root,
|
||||||
|
origin, limit, replySizeMax
|
||||||
|
|
||||||
trace trSnapSendReplying & "EMPTY AccountRange (0x01)", peer, sent=0
|
let
|
||||||
await response.send(@[], @[])
|
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.
|
# User message 0x01: AccountRange.
|
||||||
proc accountRange(peer: Peer, accounts: seq[SnapAccount],
|
proc accountRange(
|
||||||
|
peer: Peer;
|
||||||
|
accounts: seq[SnapAccount];
|
||||||
proof: SnapAccountProof)
|
proof: SnapAccountProof)
|
||||||
|
|
||||||
|
|
||||||
requestResponse:
|
requestResponse:
|
||||||
# User message 0x02: GetStorageRanges.
|
# User message 0x02: GetStorageRanges.
|
||||||
# Note: `origin` and `limit` differs from the specification to match Geth.
|
# Note: `origin` and `limit` differs from the specification to match Geth.
|
||||||
proc getStorageRanges(peer: Peer, rootHash: Hash256,
|
proc getStorageRanges(
|
||||||
accounts: openArray[Hash256], origin: openArray[byte],
|
peer: Peer;
|
||||||
limit: openArray[byte], responseBytes: uint64) =
|
root: Hash256;
|
||||||
when trSnapTracePacketsOk:
|
accounts: openArray[Hash256];
|
||||||
var definiteFullRange = ((origin.len == 32 or origin.len == 0) and
|
origin: openArray[byte];
|
||||||
(limit.len == 32 or limit.len == 0))
|
limit: openArray[byte];
|
||||||
if definiteFullRange:
|
replySizeMax: uint64;
|
||||||
for i in 0 ..< origin.len:
|
) =
|
||||||
if origin[i] != 0x00:
|
trace trSnapRecvReceived & "GetStorageRanges (0x02)", peer, root,
|
||||||
definiteFullRange = false
|
nAccounts=accounts.len, nOrigin=origin.len, nLimit=limit.len,
|
||||||
break
|
replySizeMax
|
||||||
if definiteFullRange:
|
|
||||||
for i in 0 ..< limit.len:
|
|
||||||
if limit[i] != 0xff:
|
|
||||||
definiteFullRange = false
|
|
||||||
break
|
|
||||||
|
|
||||||
template describe(value: openArray[byte]): string =
|
let
|
||||||
if value.len == 0: "(empty)"
|
ctx = peer.networkState()
|
||||||
elif value.len == 32: value.toHex
|
(slots, proof) = ctx.getStorageRanges(
|
||||||
else: "(non-standard-len=" & $value.len & ')' & value.toHex
|
root, accounts, origin, limit, replySizeMax)
|
||||||
|
|
||||||
if definiteFullRange:
|
# For logging only
|
||||||
# Fetching storage for multiple accounts.
|
nSlots = slots.len
|
||||||
trace trSnapRecvReceived & "GetStorageRanges/A (0x02)", peer,
|
nProof = proof.len
|
||||||
accountPaths=accounts.len,
|
|
||||||
stateRoot=($rootHash), responseBytes
|
if nSlots == 0 and nProof == 0:
|
||||||
elif accounts.len == 1:
|
trace trSnapSendReplying & "EMPTY StorageRanges (0x03)", peer
|
||||||
# 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:
|
else:
|
||||||
# This branch is separated because these shouldn't occur. It's not
|
trace trSnapSendReplying & "StorageRanges (0x03)", peer,
|
||||||
# really specified what happens when there are multiple accounts and
|
nSlots, nProof
|
||||||
# non-default path range.
|
|
||||||
trace trSnapRecvReceived & "GetStorageRanges/AS?? (0x02)", peer,
|
|
||||||
accountPaths=accounts.len,
|
|
||||||
storageRange=(describe(origin) & '-' & describe(limit)),
|
|
||||||
stateRoot=($rootHash), responseBytes
|
|
||||||
|
|
||||||
trace trSnapSendReplying & "EMPTY StorageRanges (0x03)", peer, sent=0
|
await response.send(slots, proof)
|
||||||
await response.send(@[], @[])
|
|
||||||
|
|
||||||
# User message 0x03: StorageRanges.
|
# User message 0x03: StorageRanges.
|
||||||
# Note: See comments in this file for a list of Geth quirks to expect.
|
# Note: See comments in this file for a list of Geth quirks to expect.
|
||||||
proc storageRanges(peer: Peer, slotLists: openArray[seq[SnapStorage]],
|
proc storageRanges(
|
||||||
|
peer: Peer;
|
||||||
|
slotLists: openArray[seq[SnapStorage]];
|
||||||
proof: SnapStorageProof)
|
proof: SnapStorageProof)
|
||||||
|
|
||||||
# User message 0x04: GetByteCodes.
|
|
||||||
requestResponse:
|
|
||||||
proc getByteCodes(peer: Peer, nodeHashes: openArray[Hash256],
|
|
||||||
responseBytes: uint64) =
|
|
||||||
trace trSnapRecvReceived & "GetByteCodes (0x04)", peer,
|
|
||||||
hashes=nodeHashes.len, responseBytes
|
|
||||||
|
|
||||||
trace trSnapSendReplying & "EMPTY ByteCodes (0x05)", peer, sent=0
|
requestResponse:
|
||||||
|
# User message 0x04: GetByteCodes.
|
||||||
|
proc getByteCodes(
|
||||||
|
peer: Peer;
|
||||||
|
nodes: openArray[Hash256];
|
||||||
|
replySizeMax: uint64;
|
||||||
|
) =
|
||||||
|
trace trSnapRecvReceived & "GetByteCodes (0x04)", peer,
|
||||||
|
nNodes=nodes.len, replySizeMax
|
||||||
|
|
||||||
|
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(@[])
|
await response.send(@[])
|
||||||
|
|
||||||
# User message 0x05: ByteCodes.
|
# User message 0x05: ByteCodes.
|
||||||
proc byteCodes(peer: Peer, codes: openArray[Blob])
|
proc byteCodes(
|
||||||
|
peer: Peer;
|
||||||
|
codes: openArray[Blob])
|
||||||
|
|
||||||
|
|
||||||
# User message 0x06: GetTrieNodes.
|
|
||||||
requestResponse:
|
requestResponse:
|
||||||
proc getTrieNodes(peer: Peer, rootHash: Hash256,
|
# User message 0x06: GetTrieNodes.
|
||||||
paths: openArray[seq[Blob]], responseBytes: uint64) =
|
proc getTrieNodes(
|
||||||
trace trSnapRecvReceived & "GetTrieNodes (0x06)", peer,
|
peer: Peer;
|
||||||
nodePaths=paths.len, stateRoot=($rootHash), responseBytes
|
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
|
let
|
||||||
await response.send(@[])
|
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.
|
# 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.rng = rng
|
||||||
result.ctx.data.dbBackend = dbBackend
|
result.ctx.data.dbBackend = dbBackend
|
||||||
result.ctx.data.noRecovery = noRecovery
|
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
|
doAssert not result.ctx.ethWireCtx.isNil
|
||||||
|
|
||||||
proc start*(ctx: SnapSyncRef) =
|
proc start*(ctx: SnapSyncRef) =
|
||||||
|
Loading…
x
Reference in New Issue
Block a user