Restore not waiting for fastBlockchainSync() to succeed on start up (#1077)
why: Accidentally wrapped into waitFor() directive with reviving jl/sync branch. also: Decorate eth/66 and snap/1 protocol trace messages with protocol type and version
This commit is contained in:
parent
d3f231e3da
commit
569d426ea8
|
@ -325,14 +325,11 @@ proc start(nimbus: NimbusNode, conf: NimbusConf) =
|
||||||
localServices(nimbus, conf, chainDB, protocols)
|
localServices(nimbus, conf, chainDB, protocols)
|
||||||
|
|
||||||
if ProtocolFlag.Eth in protocols and conf.maxPeers > 0:
|
if ProtocolFlag.Eth in protocols and conf.maxPeers > 0:
|
||||||
# previously: nimbus.syncLoop = nimbus.ethNode.fastBlockchainSync()
|
|
||||||
# TODO: temp code until the CLI/RPC interface is fleshed out
|
# TODO: temp code until the CLI/RPC interface is fleshed out
|
||||||
if not conf.newSync:
|
if conf.newSync:
|
||||||
let status = waitFor nimbus.ethNode.fastBlockchainSync()
|
|
||||||
if status != syncSuccess:
|
|
||||||
debug "Block sync failed: ", status
|
|
||||||
else:
|
|
||||||
newSync()
|
newSync()
|
||||||
|
else:
|
||||||
|
nimbus.syncLoop = nimbus.ethNode.fastBlockchainSync()
|
||||||
|
|
||||||
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
|
||||||
|
|
|
@ -17,7 +17,7 @@ import
|
||||||
eth/[common/eth_types, p2p, rlp],
|
eth/[common/eth_types, p2p, rlp],
|
||||||
eth/p2p/[rlpx, peer_pool, private/p2p_types],
|
eth/p2p/[rlpx, peer_pool, private/p2p_types],
|
||||||
stint,
|
stint,
|
||||||
"."/[sync_types, protocol_ethxx, chain_head_tracker, get_nodedata]
|
"."/[chain_head_tracker, protocol_ethxx, protocol/get_nodedata, sync_types]
|
||||||
|
|
||||||
proc syncPeerLoop(sp: SyncPeer) {.async.} =
|
proc syncPeerLoop(sp: SyncPeer) {.async.} =
|
||||||
# This basic loop just runs the head-hunter for each peer.
|
# This basic loop just runs the head-hunter for each peer.
|
||||||
|
|
|
@ -29,7 +29,7 @@ import
|
||||||
chronos,
|
chronos,
|
||||||
eth/[common/eth_types, rlp, p2p],
|
eth/[common/eth_types, rlp, p2p],
|
||||||
stint,
|
stint,
|
||||||
".."/[sync_types, get_nodedata, validate_trienode],
|
".."/[protocol/get_nodedata, sync_types, validate_trienode],
|
||||||
./common
|
./common
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
|
@ -51,6 +51,7 @@ const
|
||||||
maxReceiptsFetch* = 256
|
maxReceiptsFetch* = 256
|
||||||
maxHeadersFetch* = 192
|
maxHeadersFetch* = 192
|
||||||
ethVersion* = 66
|
ethVersion* = 66
|
||||||
|
prettyEthProtoName* = "[eth/" & $ethVersion & "]"
|
||||||
|
|
||||||
func toHex*(hash: Hash256): string = hash.data.toHex
|
func toHex*(hash: Hash256): string = hash.data.toHex
|
||||||
|
|
||||||
|
@ -60,6 +61,22 @@ func traceStep*(request: BlocksRequest): string =
|
||||||
return str & $(request.skip + 1)
|
return str & $(request.skip + 1)
|
||||||
return static($(high(typeof(request.skip)).u256 + 1))
|
return static($(high(typeof(request.skip)).u256 + 1))
|
||||||
|
|
||||||
|
|
||||||
|
# Shortcuts, print the protocol type as well (might be removed in future)
|
||||||
|
const protoInfo = prettyEthProtoName
|
||||||
|
|
||||||
|
template traceReceived(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket "<< " & protoInfo & " Received " & msg, `args`
|
||||||
|
template traceDiscarding(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket "<< " & protoInfo & " Discarding " & msg, `args`
|
||||||
|
template traceGossipDiscarding(msg: static[string], args: varargs[untyped]) =
|
||||||
|
traceGossip "<< " & protoInfo & " Discarding " & msg, `args`
|
||||||
|
template traceSending(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket ">> " & protoInfo & " Sending " & msg, `args`
|
||||||
|
template traceReplying(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket ">> " & protoInfo & " Replying " & msg, `args`
|
||||||
|
|
||||||
|
|
||||||
p2pProtocol eth(version = ethVersion,
|
p2pProtocol eth(version = ethVersion,
|
||||||
peerState = PeerState,
|
peerState = PeerState,
|
||||||
useRequestIds = true):
|
useRequestIds = true):
|
||||||
|
@ -74,7 +91,7 @@ p2pProtocol eth(version = ethVersion,
|
||||||
forkHash: chainForkId.crc.toBytesBE,
|
forkHash: chainForkId.crc.toBytesBE,
|
||||||
forkNext: chainForkId.nextFork.toBlockNumber)
|
forkNext: chainForkId.nextFork.toBlockNumber)
|
||||||
|
|
||||||
tracePacket ">> Sending eth.Status (0x00) [eth/" & $ethVersion & "]",
|
traceSending "eth.Status (0x00) " & prettyEthProtoName,
|
||||||
peer, td=bestBlock.difficulty,
|
peer, td=bestBlock.difficulty,
|
||||||
bestHash=bestBlock.blockHash.toHex,
|
bestHash=bestBlock.blockHash.toHex,
|
||||||
networkId=network.networkId,
|
networkId=network.networkId,
|
||||||
|
@ -122,7 +139,7 @@ p2pProtocol eth(version = ethVersion,
|
||||||
bestHash: BlockHash,
|
bestHash: BlockHash,
|
||||||
genesisHash: BlockHash,
|
genesisHash: BlockHash,
|
||||||
forkId: ForkId) =
|
forkId: ForkId) =
|
||||||
tracePacket "<< Received eth.Status (0x00) [eth/" & $ethVersion & "]",
|
traceReceived "eth.Status (0x00) [eth/" & $ethVersion & "]",
|
||||||
peer, td=totalDifficulty,
|
peer, td=totalDifficulty,
|
||||||
bestHash=bestHash.toHex,
|
bestHash=bestHash.toHex,
|
||||||
networkId,
|
networkId,
|
||||||
|
@ -131,13 +148,13 @@ p2pProtocol eth(version = ethVersion,
|
||||||
|
|
||||||
# User message 0x01: NewBlockHashes.
|
# User message 0x01: NewBlockHashes.
|
||||||
proc newBlockHashes(peer: Peer, hashes: openArray[NewBlockHashesAnnounce]) =
|
proc newBlockHashes(peer: Peer, hashes: openArray[NewBlockHashesAnnounce]) =
|
||||||
traceGossip "<< Discarding eth.NewBlockHashes (0x01)",
|
traceGossipDiscarding "eth.NewBlockHashes (0x01)",
|
||||||
peer, hashes=hashes.len
|
peer, hashes=hashes.len
|
||||||
discard
|
discard
|
||||||
|
|
||||||
# User message 0x02: Transactions.
|
# User message 0x02: Transactions.
|
||||||
proc transactions(peer: Peer, transactions: openArray[Transaction]) =
|
proc transactions(peer: Peer, transactions: openArray[Transaction]) =
|
||||||
traceGossip "<< Discarding eth.Transactions (0x02)",
|
traceGossipDiscarding "eth.Transactions (0x02)",
|
||||||
peer, transactions=transactions.len
|
peer, transactions=transactions.len
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
@ -146,18 +163,18 @@ p2pProtocol eth(version = ethVersion,
|
||||||
proc getBlockHeaders(peer: Peer, request: BlocksRequest) =
|
proc getBlockHeaders(peer: Peer, request: BlocksRequest) =
|
||||||
if tracePackets:
|
if tracePackets:
|
||||||
if request.maxResults == 1 and request.startBlock.isHash:
|
if request.maxResults == 1 and request.startBlock.isHash:
|
||||||
tracePacket "<< Received eth.GetBlockHeaders/Hash (0x03)",
|
traceReceived "eth.GetBlockHeaders/Hash (0x03)",
|
||||||
peer, blockHash=($request.startBlock.hash), count=1
|
peer, blockHash=($request.startBlock.hash), count=1
|
||||||
elif request.maxResults == 1:
|
elif request.maxResults == 1:
|
||||||
tracePacket "<< Received eth.GetBlockHeaders (0x03)",
|
traceReceived "eth.GetBlockHeaders (0x03)",
|
||||||
peer, `block`=request.startBlock.number, count=1
|
peer, `block`=request.startBlock.number, count=1
|
||||||
elif request.startBlock.isHash:
|
elif request.startBlock.isHash:
|
||||||
tracePacket "<< Received eth.GetBlockHeaders/Hash (0x03)",
|
traceReceived "eth.GetBlockHeaders/Hash (0x03)",
|
||||||
peer, firstBlockHash=($request.startBlock.hash),
|
peer, firstBlockHash=($request.startBlock.hash),
|
||||||
count=request.maxResults,
|
count=request.maxResults,
|
||||||
step=traceStep(request)
|
step=traceStep(request)
|
||||||
else:
|
else:
|
||||||
tracePacket "<< Received eth.GetBlockHeaders (0x03)",
|
traceReceived "eth.GetBlockHeaders (0x03)",
|
||||||
peer, firstBlock=request.startBlock.number,
|
peer, firstBlock=request.startBlock.number,
|
||||||
count=request.maxResults,
|
count=request.maxResults,
|
||||||
step=traceStep(request)
|
step=traceStep(request)
|
||||||
|
@ -170,10 +187,10 @@ p2pProtocol eth(version = ethVersion,
|
||||||
|
|
||||||
let headers = peer.network.chain.getBlockHeaders(request)
|
let headers = peer.network.chain.getBlockHeaders(request)
|
||||||
if headers.len > 0:
|
if headers.len > 0:
|
||||||
tracePacket ">> Replying with eth.BlockHeaders (0x04)",
|
traceReplying "with eth.BlockHeaders (0x04)",
|
||||||
peer, sent=headers.len, requested=request.maxResults
|
peer, sent=headers.len, requested=request.maxResults
|
||||||
else:
|
else:
|
||||||
tracePacket ">> Replying EMPTY eth.BlockHeaders (0x04)",
|
traceReplying "EMPTY eth.BlockHeaders (0x04)",
|
||||||
peer, sent=0, requested=request.maxResults
|
peer, sent=0, requested=request.maxResults
|
||||||
|
|
||||||
await response.send(headers)
|
await response.send(headers)
|
||||||
|
@ -184,7 +201,7 @@ p2pProtocol eth(version = ethVersion,
|
||||||
requestResponse:
|
requestResponse:
|
||||||
# User message 0x05: GetBlockBodies.
|
# User message 0x05: GetBlockBodies.
|
||||||
proc getBlockBodies(peer: Peer, hashes: openArray[BlockHash]) =
|
proc getBlockBodies(peer: Peer, hashes: openArray[BlockHash]) =
|
||||||
tracePacket "<< Received eth.GetBlockBodies (0x05)",
|
traceReceived "eth.GetBlockBodies (0x05)",
|
||||||
peer, hashes=hashes.len
|
peer, hashes=hashes.len
|
||||||
if hashes.len > maxBodiesFetch:
|
if hashes.len > maxBodiesFetch:
|
||||||
debug "eth.GetBlockBodies (0x05) requested too many bodies",
|
debug "eth.GetBlockBodies (0x05) requested too many bodies",
|
||||||
|
@ -194,10 +211,10 @@ p2pProtocol eth(version = ethVersion,
|
||||||
|
|
||||||
let bodies = peer.network.chain.getBlockBodies(hashes)
|
let bodies = peer.network.chain.getBlockBodies(hashes)
|
||||||
if bodies.len > 0:
|
if bodies.len > 0:
|
||||||
tracePacket ">> Replying with eth.BlockBodies (0x06)",
|
traceReplying "with eth.BlockBodies (0x06)",
|
||||||
peer, sent=bodies.len, requested=hashes.len
|
peer, sent=bodies.len, requested=hashes.len
|
||||||
else:
|
else:
|
||||||
tracePacket ">> Replying EMPTY eth.BlockBodies (0x06)",
|
traceReplying "EMPTY eth.BlockBodies (0x06)",
|
||||||
peer, sent=0, requested=hashes.len
|
peer, sent=0, requested=hashes.len
|
||||||
|
|
||||||
await response.send(bodies)
|
await response.send(bodies)
|
||||||
|
@ -209,7 +226,7 @@ p2pProtocol eth(version = ethVersion,
|
||||||
proc newBlock(peer: Peer, bh: EthBlock, totalDifficulty: DifficultyInt) =
|
proc newBlock(peer: Peer, bh: EthBlock, totalDifficulty: DifficultyInt) =
|
||||||
# (Note, needs to use `EthBlock` instead of its alias `NewBlockAnnounce`
|
# (Note, needs to use `EthBlock` instead of its alias `NewBlockAnnounce`
|
||||||
# because either `p2pProtocol` or RLPx doesn't work with an alias.)
|
# because either `p2pProtocol` or RLPx doesn't work with an alias.)
|
||||||
traceGossip "<< Discarding eth.NewBlock (0x07)",
|
traceGossipDiscarding "eth.NewBlock (0x07)",
|
||||||
peer, totalDifficulty,
|
peer, totalDifficulty,
|
||||||
blockNumber = bh.header.blockNumber,
|
blockNumber = bh.header.blockNumber,
|
||||||
blockDifficulty = bh.header.difficulty
|
blockDifficulty = bh.header.difficulty
|
||||||
|
@ -217,17 +234,17 @@ p2pProtocol eth(version = ethVersion,
|
||||||
|
|
||||||
# User message 0x08: NewPooledTransactionHashes.
|
# User message 0x08: NewPooledTransactionHashes.
|
||||||
proc newPooledTransactionHashes(peer: Peer, hashes: openArray[TxHash]) =
|
proc newPooledTransactionHashes(peer: Peer, hashes: openArray[TxHash]) =
|
||||||
traceGossip "<< Discarding eth.NewPooledTransactionHashes (0x08)",
|
traceGossipDiscarding "eth.NewPooledTransactionHashes (0x08)",
|
||||||
peer, hashes=hashes.len
|
peer, hashes=hashes.len
|
||||||
discard
|
discard
|
||||||
|
|
||||||
requestResponse:
|
requestResponse:
|
||||||
# User message 0x09: GetPooledTransactions.
|
# User message 0x09: GetPooledTransactions.
|
||||||
proc getPooledTransactions(peer: Peer, hashes: openArray[TxHash]) =
|
proc getPooledTransactions(peer: Peer, hashes: openArray[TxHash]) =
|
||||||
tracePacket "<< Received eth.GetPooledTransactions (0x09)",
|
traceReceived "eth.GetPooledTransactions (0x09)",
|
||||||
peer, hashes=hashes.len
|
peer, hashes=hashes.len
|
||||||
|
|
||||||
tracePacket ">> Replying EMPTY eth.PooledTransactions (0x10)",
|
traceReplying "EMPTY eth.PooledTransactions (0x10)",
|
||||||
peer, sent=0, requested=hashes.len
|
peer, sent=0, requested=hashes.len
|
||||||
await response.send([])
|
await response.send([])
|
||||||
|
|
||||||
|
@ -238,7 +255,7 @@ p2pProtocol eth(version = ethVersion,
|
||||||
|
|
||||||
# User message 0x0d: GetNodeData.
|
# User message 0x0d: GetNodeData.
|
||||||
proc getNodeData(peer: Peer, hashes: openArray[NodeHash]) =
|
proc getNodeData(peer: Peer, hashes: openArray[NodeHash]) =
|
||||||
tracePacket "<< Received eth.GetNodeData (0x0d)", peer,
|
traceReceived "eth.GetNodeData (0x0d)", peer,
|
||||||
hashes=hashes.len
|
hashes=hashes.len
|
||||||
|
|
||||||
var data: seq[Blob]
|
var data: seq[Blob]
|
||||||
|
@ -248,10 +265,10 @@ p2pProtocol eth(version = ethVersion,
|
||||||
data = peer.network.chain.getStorageNodes(hashes)
|
data = peer.network.chain.getStorageNodes(hashes)
|
||||||
|
|
||||||
if data.len > 0:
|
if data.len > 0:
|
||||||
tracePacket ">> Replying with eth.NodeData (0x0e)", peer,
|
traceReplying "with eth.NodeData (0x0e)", peer,
|
||||||
sent=data.len, requested=hashes.len
|
sent=data.len, requested=hashes.len
|
||||||
else:
|
else:
|
||||||
tracePacket ">> Replying EMPTY eth.NodeData (0x0e)", peer,
|
traceReplying "EMPTY eth.NodeData (0x0e)", peer,
|
||||||
sent=0, requested=hashes.len
|
sent=0, requested=hashes.len
|
||||||
|
|
||||||
await peer.nodeData(data)
|
await peer.nodeData(data)
|
||||||
|
@ -263,16 +280,16 @@ p2pProtocol eth(version = ethVersion,
|
||||||
# know if this is a valid reply ("Got reply") or something else.
|
# know if this is a valid reply ("Got reply") or something else.
|
||||||
peer.state.onNodeData(peer, data)
|
peer.state.onNodeData(peer, data)
|
||||||
else:
|
else:
|
||||||
tracePacket "<< Discarding eth.NodeData (0x0e)", peer,
|
traceDiscarding "eth.NodeData (0x0e)", peer,
|
||||||
bytes=data.len
|
bytes=data.len
|
||||||
|
|
||||||
requestResponse:
|
requestResponse:
|
||||||
# User message 0x0f: GetReceipts.
|
# User message 0x0f: GetReceipts.
|
||||||
proc getReceipts(peer: Peer, hashes: openArray[BlockHash]) =
|
proc getReceipts(peer: Peer, hashes: openArray[BlockHash]) =
|
||||||
tracePacket "<< Received eth.GetReceipts (0x0f)",
|
traceReceived "eth.GetReceipts (0x0f)",
|
||||||
peer, hashes=hashes.len
|
peer, hashes=hashes.len
|
||||||
|
|
||||||
tracePacket ">> Replying EMPTY eth.Receipts (0x10)",
|
traceReplying "EMPTY eth.Receipts (0x10)",
|
||||||
peer, sent=0, requested=hashes.len
|
peer, sent=0, requested=hashes.len
|
||||||
await response.send([])
|
await response.send([])
|
||||||
# TODO: implement `getReceipts` and reactivate this code
|
# TODO: implement `getReceipts` and reactivate this code
|
||||||
|
|
|
@ -61,9 +61,11 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[sequtils, sets, tables, hashes],
|
std/[sequtils, sets, tables, hashes],
|
||||||
chronos, stint, nimcrypto/keccak,
|
chronos,
|
||||||
eth/[common/eth_types, rlp, p2p],
|
eth/[common/eth_types, rlp, p2p],
|
||||||
"."/[sync_types, protocol_ethxx]
|
nimcrypto/keccak,
|
||||||
|
stint,
|
||||||
|
".."/[sync_types, protocol_ethxx]
|
||||||
|
|
||||||
type
|
type
|
||||||
NodeDataRequestQueue* = ref object of typeof SyncPeer().nodeDataRequestsBase
|
NodeDataRequestQueue* = ref object of typeof SyncPeer().nodeDataRequestsBase
|
||||||
|
@ -91,6 +93,27 @@ type
|
||||||
reverseMap: seq[int] # Access with `reversMap(i)` instead.
|
reverseMap: seq[int] # Access with `reversMap(i)` instead.
|
||||||
hashVerifiedData*: seq[Blob]
|
hashVerifiedData*: seq[Blob]
|
||||||
|
|
||||||
|
# Shortcuts, print the protocol type as well (might be removed in future)
|
||||||
|
const protoInfo = prettyEthProtoName
|
||||||
|
|
||||||
|
template traceReceived(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket "<< " & protoInfo & " Received " & msg, `args`
|
||||||
|
template traceWaitTimeout(msg: static[string], args: varargs[untyped]) =
|
||||||
|
traceTimeout "<< " & protoInfo & " Timeout waiting " & msg, `args`
|
||||||
|
template traceWaitError(msg: static[string], args: varargs[untyped]) =
|
||||||
|
traceNetworkError "<< " & protoInfo & " Error waiting " & msg, `args`
|
||||||
|
template traceProtoError(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacketError "<< " & protoInfo & " Protocol violation, " & msg, `args`
|
||||||
|
template traceDisconError(msg: static[string], args: varargs[untyped]) =
|
||||||
|
traceNetworkError "<< " & protoInfo & " Peer disconnected, " & msg, `args`
|
||||||
|
template traceSending(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket ">> " & protoInfo & " Sending " & msg, `args`
|
||||||
|
template traceSendError(msg: static[string], args: varargs[untyped]) =
|
||||||
|
traceNetworkError ">> " & protoInfo & " Error sending " & msg, `args`
|
||||||
|
template traceDelaying(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket ">> " & protoInfo & " Dlaying " & msg, `args`
|
||||||
|
|
||||||
|
|
||||||
template reverseMap*(reply: NodeDataReply, index: int): int =
|
template reverseMap*(reply: NodeDataReply, index: int): int =
|
||||||
## Given an index into the request hash list, return index into the reply
|
## Given an index into the request hash list, return index into the reply
|
||||||
## `hashVerifiedData`, or -1 if there is no data for that request hash.
|
## `hashVerifiedData`, or -1 if there is no data for that request hash.
|
||||||
|
@ -110,47 +133,45 @@ template `$`*(paths: (InteriorPath, InteriorPath)): string =
|
||||||
pathRange(paths[0], paths[1])
|
pathRange(paths[0], paths[1])
|
||||||
|
|
||||||
proc traceGetNodeDataSending(request: NodeDataRequest) =
|
proc traceGetNodeDataSending(request: NodeDataRequest) =
|
||||||
tracePacket ">> Sending eth.GetNodeData (0x0d)", peer=request.sp,
|
traceSending "eth.GetNodeData (0x0d)", peer=request.sp,
|
||||||
hashes=request.hashes.len, pathRange=request.pathRange
|
hashes=request.hashes.len, pathRange=request.pathRange
|
||||||
|
|
||||||
proc traceGetNodeDataDelaying(request: NodeDataRequest) =
|
proc traceGetNodeDataDelaying(request: NodeDataRequest) =
|
||||||
tracePacket ">> Delaying eth.GetNodeData (0x0d)", peer=request.sp,
|
traceDelaying "eth.GetNodeData (0x0d)", peer=request.sp,
|
||||||
hashes=request.hashes.len, pathRange=request.pathRange
|
hashes=request.hashes.len, pathRange=request.pathRange
|
||||||
|
|
||||||
proc traceGetNodeDataSendError(request: NodeDataRequest,
|
proc traceGetNodeDataSendError(request: NodeDataRequest,
|
||||||
e: ref CatchableError) =
|
e: ref CatchableError) =
|
||||||
traceNetworkError ">> Error sending eth.GetNodeData (0x0d)",
|
traceSendError "eth.GetNodeData (0x0d)",
|
||||||
peer=request.sp, error=e.msg,
|
peer=request.sp, error=e.msg,
|
||||||
hashes=request.hashes.len, pathRange=request.pathRange
|
hashes=request.hashes.len, pathRange=request.pathRange
|
||||||
|
|
||||||
proc traceNodeDataReplyError(request: NodeDataRequest,
|
proc traceNodeDataReplyError(request: NodeDataRequest,
|
||||||
e: ref CatchableError) =
|
e: ref CatchableError) =
|
||||||
traceNetworkError "<< Error waiting for reply to eth.GetNodeData (0x0d)",
|
traceWaitError "for reply to eth.GetNodeData (0x0d)",
|
||||||
peer=request.sp, error=e.msg,
|
peer=request.sp, error=e.msg,
|
||||||
hashes=request.hashes.len, pathRange=request.pathRange
|
hashes=request.hashes.len, pathRange=request.pathRange
|
||||||
|
|
||||||
proc traceNodeDataReplyTimeout(request: NodeDataRequest) =
|
proc traceNodeDataReplyTimeout(request: NodeDataRequest) =
|
||||||
traceTimeout "<< Timeout waiting for reply to eth.GetNodeData (0x0d)",
|
traceWaitTimeout "for reply to eth.GetNodeData (0x0d)",
|
||||||
hashes=request.hashes.len, pathRange=request.pathRange, peer=request.sp
|
hashes=request.hashes.len, pathRange=request.pathRange, peer=request.sp
|
||||||
|
|
||||||
proc traceGetNodeDataDisconnected(request: NodeDataRequest) =
|
proc traceGetNodeDataDisconnected(request: NodeDataRequest) =
|
||||||
traceNetworkError "<< Peer disconnected, not sending eth.GetNodeData (0x0d)",
|
traceDisconError "not sending eth.GetNodeData (0x0d)",
|
||||||
peer=request.sp, hashes=request.hashes.len, pathRange=request.pathRange
|
peer=request.sp, hashes=request.hashes.len, pathRange=request.pathRange
|
||||||
|
|
||||||
proc traceNodeDataReplyEmpty(sp: SyncPeer, request: NodeDataRequest) =
|
proc traceNodeDataReplyEmpty(sp: SyncPeer, request: NodeDataRequest) =
|
||||||
# `request` can be `nil` because we don't always know which request
|
# `request` can be `nil` because we don't always know which request
|
||||||
# the empty reply goes with. Therefore `sp` must be included.
|
# the empty reply goes with. Therefore `sp` must be included.
|
||||||
if request.isNil:
|
if request.isNil:
|
||||||
tracePacket "<< Got EMPTY eth.NodeData (0x0e)", peer=sp,
|
traceReceived "EMPTY eth.NodeData (0x0e)", peer=sp, got=0
|
||||||
got=0
|
|
||||||
else:
|
else:
|
||||||
tracePacket "<< Got eth.NodeData (0x0e)", peer=sp,
|
traceReceived "eth.NodeData (0x0e)", peer=sp, got=0,
|
||||||
got=0, requested=request.hashes.len, pathRange=request.pathRange
|
requested=request.hashes.len, pathRange=request.pathRange
|
||||||
|
|
||||||
proc traceNodeDataReplyUnmatched(sp: SyncPeer, got: int) =
|
proc traceNodeDataReplyUnmatched(sp: SyncPeer, got: int) =
|
||||||
# There is no request for this reply. Therefore `sp` must be included.
|
# There is no request for this reply. Therefore `sp` must be included.
|
||||||
tracePacketError "<< Protocol violation, non-reply eth.NodeData (0x0e)",
|
traceProtoError "non-reply eth.NodeData (0x0e)", peer=sp, got
|
||||||
peer=sp, got
|
|
||||||
debug "Sync: Warning: Unexpected non-reply eth.NodeData from peer"
|
debug "Sync: Warning: Unexpected non-reply eth.NodeData from peer"
|
||||||
|
|
||||||
proc traceNodeDataReply(request: NodeDataRequest,
|
proc traceNodeDataReply(request: NodeDataRequest,
|
||||||
|
@ -161,11 +182,11 @@ proc traceNodeDataReply(request: NodeDataRequest,
|
||||||
logScope: pathRange=request.pathRange
|
logScope: pathRange=request.pathRange
|
||||||
logScope: peer=request.sp
|
logScope: peer=request.sp
|
||||||
if got > request.hashes.len and (unmatched + other) == 0:
|
if got > request.hashes.len and (unmatched + other) == 0:
|
||||||
tracePacket "<< Got EXCESS reply eth.NodeData (0x0e)"
|
traceReceived "EXCESS reply eth.NodeData (0x0e)"
|
||||||
elif got == request.hashes.len or use != got:
|
elif got == request.hashes.len or use != got:
|
||||||
tracePacket "<< Got reply eth.NodeData (0x0e)"
|
traceReceived "reply eth.NodeData (0x0e)"
|
||||||
elif got < request.hashes.len:
|
elif got < request.hashes.len:
|
||||||
tracePacket "<< Got TRUNCATED reply eth.NodeData (0x0e)"
|
traceReceived "TRUNCATED reply eth.NodeData (0x0e)"
|
||||||
|
|
||||||
if use != got:
|
if use != got:
|
||||||
logScope:
|
logScope:
|
||||||
|
@ -176,17 +197,17 @@ proc traceNodeDataReply(request: NodeDataRequest,
|
||||||
pathRange=request.pathRange
|
pathRange=request.pathRange
|
||||||
peer=request.sp
|
peer=request.sp
|
||||||
if unmatched > 0:
|
if unmatched > 0:
|
||||||
tracePacketError "<< Protocol violation, incorrect hashes in eth.NodeData (0x0e)"
|
traceProtoError "incorrect hashes in eth.NodeData (0x0e)"
|
||||||
debug "Sync: Warning: eth.NodeData has nodes with incorrect hashes"
|
debug "Sync: Warning: eth.NodeData has nodes with incorrect hashes"
|
||||||
elif other > 0:
|
elif other > 0:
|
||||||
tracePacketError "<< Protocol violation, mixed request nodes in eth.NodeData (0x0e)"
|
traceProtoError "mixed request nodes in eth.NodeData (0x0e)"
|
||||||
debug "Sync: Warning: eth.NodeData has nodes from mixed requests"
|
debug "Sync: Warning: eth.NodeData has nodes from mixed requests"
|
||||||
elif got > request.hashes.len:
|
elif got > request.hashes.len:
|
||||||
# Excess without unmatched/other is only possible with duplicates > 0.
|
# Excess without unmatched/other is only possible with duplicates > 0.
|
||||||
tracePacketError "<< Protocol violation, excess nodes in eth.NodeData (0x0e)"
|
traceProtoError "excess nodes in eth.NodeData (0x0e)"
|
||||||
debug "Sync: Warning: eth.NodeData has more nodes than requested"
|
debug "Sync: Warning: eth.NodeData has more nodes than requested"
|
||||||
else:
|
else:
|
||||||
tracePacketError "<< Protocol violation, duplicate nodes in eth.NodeData (0x0e)"
|
traceProtoError "duplicate nodes in eth.NodeData (0x0e)"
|
||||||
debug "Sync: Warning: eth.NodeData has duplicate nodes"
|
debug "Sync: Warning: eth.NodeData has duplicate nodes"
|
||||||
|
|
||||||
proc hash(hash: ptr Hash256): Hash = cast[ptr Hash](addr hash.data)[]
|
proc hash(hash: ptr Hash256): Hash = cast[ptr Hash](addr hash.data)[]
|
|
@ -171,7 +171,8 @@ import
|
||||||
nimcrypto/hash,
|
nimcrypto/hash,
|
||||||
stew/byteutils,
|
stew/byteutils,
|
||||||
stint,
|
stint,
|
||||||
../sync_types
|
../sync_types,
|
||||||
|
../../constants
|
||||||
|
|
||||||
type
|
type
|
||||||
SnapAccount* = object
|
SnapAccount* = object
|
||||||
|
@ -186,6 +187,10 @@ type
|
||||||
|
|
||||||
SnapStorageProof* = seq[Blob]
|
SnapStorageProof* = seq[Blob]
|
||||||
|
|
||||||
|
const
|
||||||
|
snapVersion* = 1
|
||||||
|
prettySnapProtoName* = "[snap/" & $snapVersion & "]"
|
||||||
|
|
||||||
# The `snap` protocol represents `Account` differently from the regular RLP
|
# The `snap` protocol represents `Account` differently from the regular RLP
|
||||||
# serialisation used in `eth` protocol as well as the canonical Merkle hash
|
# serialisation used in `eth` protocol as well as the canonical Merkle hash
|
||||||
# over all accounts. In `snap`, empty storage hash and empty code hash are
|
# over all accounts. In `snap`, empty storage hash and empty code hash are
|
||||||
|
@ -193,11 +198,6 @@ type
|
||||||
# avoids transmitting these hashes in about 90% of accounts. We need to
|
# avoids transmitting these hashes in about 90% of accounts. We need to
|
||||||
# recognise or set these hashes in `Account` when serialising RLP for `snap`.
|
# recognise or set these hashes in `Account` when serialising RLP for `snap`.
|
||||||
|
|
||||||
const EMPTY_STORAGE_HASH* =
|
|
||||||
"56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421".toDigest
|
|
||||||
const EMPTY_CODE_HASH* =
|
|
||||||
"c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470".toDigest
|
|
||||||
|
|
||||||
proc read*(rlp: var Rlp, t: var SnapAccount, _: type Account): Account =
|
proc read*(rlp: var Rlp, t: var SnapAccount, _: type Account): Account =
|
||||||
## RLP decoding for `SnapAccount`, which contains a path and account.
|
## RLP decoding for `SnapAccount`, which contains a path and account.
|
||||||
## The snap representation of the account differs from `Account` RLP.
|
## The snap representation of the account differs from `Account` RLP.
|
||||||
|
@ -209,23 +209,22 @@ proc read*(rlp: var Rlp, t: var SnapAccount, _: type Account): Account =
|
||||||
|
|
||||||
if rlp.blobLen != 0 or not rlp.isBlob:
|
if rlp.blobLen != 0 or not rlp.isBlob:
|
||||||
result.storageRoot = rlp.read(typeof(result.storageRoot))
|
result.storageRoot = rlp.read(typeof(result.storageRoot))
|
||||||
if result.storageRoot == EMPTY_STORAGE_HASH:
|
if result.storageRoot == BLANK_ROOT_HASH:
|
||||||
raise newException(RlpTypeMismatch,
|
raise newException(RlpTypeMismatch,
|
||||||
"EMPTY_STORAGE_HASH not encoded as empty string in Snap protocol"
|
"BLANK_ROOT_HASH not encoded as empty string in Snap protocol"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
rlp.skipElem()
|
rlp.skipElem()
|
||||||
result.storageRoot = EMPTY_STORAGE_HASH
|
result.storageRoot = BLANK_ROOT_HASH
|
||||||
|
|
||||||
if rlp.blobLen != 0 or not rlp.isBlob:
|
if rlp.blobLen != 0 or not rlp.isBlob:
|
||||||
result.codeHash = rlp.read(typeof(result.codeHash))
|
result.codeHash = rlp.read(typeof(result.codeHash))
|
||||||
if result.codeHash == EMPTY_CODE_HASH:
|
if result.codeHash == EMPTY_SHA3:
|
||||||
raise newException(RlpTypeMismatch,
|
raise newException(RlpTypeMismatch,
|
||||||
"EMPTY_CODE_HASH not encoded as empty string in Snap protocol"
|
"EMPTY_SHA3 not encoded as empty string in Snap protocol")
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
rlp.skipElem()
|
rlp.skipElem()
|
||||||
result.codeHash = EMPTY_CODE_HASH
|
result.codeHash = EMPTY_SHA3
|
||||||
|
|
||||||
proc append*(rlpWriter: var RlpWriter, t: SnapAccount, account: Account) =
|
proc append*(rlpWriter: var RlpWriter, t: SnapAccount, account: Account) =
|
||||||
## RLP encoding for `SnapAccount`, which contains a path and account.
|
## RLP encoding for `SnapAccount`, which contains a path and account.
|
||||||
|
@ -235,12 +234,12 @@ proc append*(rlpWriter: var RlpWriter, t: SnapAccount, account: Account) =
|
||||||
rlpWriter.append(account.nonce)
|
rlpWriter.append(account.nonce)
|
||||||
rlpWriter.append(account.balance)
|
rlpWriter.append(account.balance)
|
||||||
|
|
||||||
if account.storageRoot == EMPTY_STORAGE_HASH:
|
if account.storageRoot == BLANK_ROOT_HASH:
|
||||||
rlpWriter.append("")
|
rlpWriter.append("")
|
||||||
else:
|
else:
|
||||||
rlpWriter.append(account.storageRoot)
|
rlpWriter.append(account.storageRoot)
|
||||||
|
|
||||||
if account.codeHash == EMPTY_CODE_HASH:
|
if account.codeHash == EMPTY_SHA3:
|
||||||
rlpWriter.append("")
|
rlpWriter.append("")
|
||||||
else:
|
else:
|
||||||
rlpWriter.append(account.codeHash)
|
rlpWriter.append(account.codeHash)
|
||||||
|
@ -253,23 +252,33 @@ template read*(rlp: var Rlp, _: type LeafPath): LeafPath =
|
||||||
template append*(rlpWriter: var RlpWriter, leafPath: LeafPath) =
|
template append*(rlpWriter: var RlpWriter, leafPath: LeafPath) =
|
||||||
rlpWriter.append(leafPath.toBytes)
|
rlpWriter.append(leafPath.toBytes)
|
||||||
|
|
||||||
# TODO: Don't know why, but the `p2pProtocol` can't handle this type. It tries
|
# Maybe cruft following?
|
||||||
# to serialise the `Option` as an object, looking at the internal fields. But
|
# # TODO: Don't know why, but the `p2pProtocol` can't handle this type. It
|
||||||
# then fails because they are private fields.
|
# # tries to serialise the `Option` as an object, looking at the internal
|
||||||
|
# # fields. But then fails because they are private fields.
|
||||||
|
# #
|
||||||
|
# ## RLP serialisation for `Option[SnapPath]`.
|
||||||
|
# #
|
||||||
|
# #proc read*(rlp: var Rlp, _: type Option[SnapPath]): Option[SnapPath] =
|
||||||
|
# # if rlp.blobLen == 0 and rlp.isBlob:
|
||||||
|
# # result = none(SnapPath)
|
||||||
|
# # else:
|
||||||
|
# # result = some(read(rlp, SnapPath))
|
||||||
#
|
#
|
||||||
## RLP serialisation for `Option[SnapPath]`.
|
# #proc write*(rlpWriter: var RlpWriter, value: Option[SnapPath]) =
|
||||||
#
|
# # if value.isNone:
|
||||||
#proc read*(rlp: var Rlp, _: type Option[SnapPath]): Option[SnapPath] =
|
# # rlpWriter.append("")
|
||||||
# if rlp.blobLen == 0 and rlp.isBlob:
|
# # else:
|
||||||
# result = none(SnapPath)
|
# # rlpWriter.append(value.unsafeGet)
|
||||||
# else:
|
|
||||||
# result = some(read(rlp, SnapPath))
|
# Shortcuts, print the protocol type as well (might be removed in future)
|
||||||
|
const protoInfo = prettySnapProtoName
|
||||||
|
|
||||||
|
template traceReceived(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket "<< " & protoInfo & " Received " & msg, `args`
|
||||||
|
template traceReplying(msg: static[string], args: varargs[untyped]) =
|
||||||
|
tracePacket ">> " & protoInfo & " Replying " & msg, `args`
|
||||||
|
|
||||||
#proc write*(rlpWriter: var RlpWriter, value: Option[SnapPath]) =
|
|
||||||
# if value.isNone:
|
|
||||||
# rlpWriter.append("")
|
|
||||||
# else:
|
|
||||||
# rlpWriter.append(value.unsafeGet)
|
|
||||||
|
|
||||||
p2pProtocol snap1(version = 1,
|
p2pProtocol snap1(version = 1,
|
||||||
rlpxName = "snap",
|
rlpxName = "snap",
|
||||||
|
@ -282,11 +291,11 @@ p2pProtocol snap1(version = 1,
|
||||||
# Next line differs from spec to match Geth.
|
# Next line differs from spec to match Geth.
|
||||||
origin: LeafPath, limit: LeafPath,
|
origin: LeafPath, limit: LeafPath,
|
||||||
responseBytes: uint64) =
|
responseBytes: uint64) =
|
||||||
tracePacket "<< Received snap.GetAccountRange (0x00)", peer,
|
traceReceived "snap.GetAccountRange (0x00)", peer,
|
||||||
accountRange=pathRange(origin, limit),
|
accountRange=pathRange(origin, limit),
|
||||||
stateRoot=($rootHash), responseBytes
|
stateRoot=($rootHash), responseBytes
|
||||||
|
|
||||||
tracePacket ">> Replying EMPTY snap.AccountRange (0x01)", peer, sent=0
|
traceReplying "EMPTY snap.AccountRange (0x01)", peer, sent=0
|
||||||
await response.send(@[], @[])
|
await response.send(@[], @[])
|
||||||
|
|
||||||
# User message 0x01: AccountRange.
|
# User message 0x01: AccountRange.
|
||||||
|
@ -322,12 +331,12 @@ p2pProtocol snap1(version = 1,
|
||||||
|
|
||||||
if definiteFullRange:
|
if definiteFullRange:
|
||||||
# Fetching storage for multiple accounts.
|
# Fetching storage for multiple accounts.
|
||||||
tracePacket "<< Received snap.GetStorageRanges/A (0x02)", peer,
|
traceReceived "snap.GetStorageRanges/A (0x02)", peer,
|
||||||
accountPaths=accounts.len,
|
accountPaths=accounts.len,
|
||||||
stateRoot=($rootHash), responseBytes
|
stateRoot=($rootHash), responseBytes
|
||||||
elif accounts.len == 1:
|
elif accounts.len == 1:
|
||||||
# Fetching partial storage for one account, aka. "large contract".
|
# Fetching partial storage for one account, aka. "large contract".
|
||||||
tracePacket "<< Received snap.GetStorageRanges/S (0x02)", peer,
|
traceReceived "snap.GetStorageRanges/S (0x02)", peer,
|
||||||
accountPaths=1,
|
accountPaths=1,
|
||||||
storageRange=(describe(origin) & '-' & describe(limit)),
|
storageRange=(describe(origin) & '-' & describe(limit)),
|
||||||
stateRoot=($rootHash), responseBytes
|
stateRoot=($rootHash), responseBytes
|
||||||
|
@ -335,12 +344,12 @@ p2pProtocol snap1(version = 1,
|
||||||
# This branch is separated because these shouldn't occur. It's not
|
# This branch is separated because these shouldn't occur. It's not
|
||||||
# really specified what happens when there are multiple accounts and
|
# really specified what happens when there are multiple accounts and
|
||||||
# non-default path range.
|
# non-default path range.
|
||||||
tracePacket "<< Received snap.GetStorageRanges/AS?? (0x02)", peer,
|
traceReceived "snap.GetStorageRanges/AS?? (0x02)", peer,
|
||||||
accountPaths=accounts.len,
|
accountPaths=accounts.len,
|
||||||
storageRange=(describe(origin) & '-' & describe(limit)),
|
storageRange=(describe(origin) & '-' & describe(limit)),
|
||||||
stateRoot=($rootHash), responseBytes
|
stateRoot=($rootHash), responseBytes
|
||||||
|
|
||||||
tracePacket ">> Replying EMPTY snap.StorageRanges (0x03)", peer, sent=0
|
traceReplying "EMPTY snap.StorageRanges (0x03)", peer, sent=0
|
||||||
await response.send(@[], @[])
|
await response.send(@[], @[])
|
||||||
|
|
||||||
# User message 0x03: StorageRanges.
|
# User message 0x03: StorageRanges.
|
||||||
|
@ -352,10 +361,10 @@ p2pProtocol snap1(version = 1,
|
||||||
requestResponse:
|
requestResponse:
|
||||||
proc getByteCodes(peer: Peer, hashes: openArray[NodeHash],
|
proc getByteCodes(peer: Peer, hashes: openArray[NodeHash],
|
||||||
responseBytes: uint64) =
|
responseBytes: uint64) =
|
||||||
tracePacket "<< Received snap.GetByteCodes (0x04)", peer,
|
traceReceived "snap.GetByteCodes (0x04)", peer,
|
||||||
hashes=hashes.len, responseBytes
|
hashes=hashes.len, responseBytes
|
||||||
|
|
||||||
tracePacket ">> Replying EMPTY snap.ByteCodes (0x05)", peer, sent=0
|
traceReplying "EMPTY snap.ByteCodes (0x05)", peer, sent=0
|
||||||
await response.send(@[])
|
await response.send(@[])
|
||||||
|
|
||||||
# User message 0x05: ByteCodes.
|
# User message 0x05: ByteCodes.
|
||||||
|
@ -365,10 +374,10 @@ p2pProtocol snap1(version = 1,
|
||||||
requestResponse:
|
requestResponse:
|
||||||
proc getTrieNodes(peer: Peer, rootHash: TrieHash,
|
proc getTrieNodes(peer: Peer, rootHash: TrieHash,
|
||||||
paths: openArray[InteriorPath], responseBytes: uint64) =
|
paths: openArray[InteriorPath], responseBytes: uint64) =
|
||||||
tracePacket "<< Received snap.GetTrieNodes (0x06)", peer,
|
traceReceived "snap.GetTrieNodes (0x06)", peer,
|
||||||
nodePaths=paths.len, stateRoot=($rootHash), responseBytes
|
nodePaths=paths.len, stateRoot=($rootHash), responseBytes
|
||||||
|
|
||||||
tracePacket ">> Replying EMPTY snap.TrieNodes (0x07)", peer, sent=0
|
traceReplying "EMPTY snap.TrieNodes (0x07)", peer, sent=0
|
||||||
await response.send(@[])
|
await response.send(@[])
|
||||||
|
|
||||||
# User message 0x07: TrieNodes.
|
# User message 0x07: TrieNodes.
|
||||||
|
|
|
@ -135,13 +135,13 @@ type
|
||||||
## numerical properties: ordering, intervals and meaningful difference.
|
## numerical properties: ordering, intervals and meaningful difference.
|
||||||
number: UInt256
|
number: UInt256
|
||||||
|
|
||||||
# Use `import get_nodedata` to access the real type's methods.
|
# Use `import protocol/get_nodedata` to access the real type's methods.
|
||||||
NodeDataRequestQueue {.inheritable, pure.} = ref object
|
NodeDataRequestQueue {.inheritable, pure.} = ref object
|
||||||
|
|
||||||
# Use `import trie_fetch` to access the real type's methods.
|
# Use `import pie/trie_fetch` to access the real type's methods.
|
||||||
SharedFetchState {.inheritable, pure.} = ref object
|
SharedFetchState {.inheritable, pure.} = ref object
|
||||||
|
|
||||||
# Use `import trie_fetch` to access the real type's methods.
|
# Use `import pie/trie_fetch` to access the real type's methods.
|
||||||
FetchState {.inheritable, pure.} = ref object
|
FetchState {.inheritable, pure.} = ref object
|
||||||
|
|
||||||
proc inc(stat: var Stat) {.borrow.}
|
proc inc(stat: var Stat) {.borrow.}
|
||||||
|
|
Loading…
Reference in New Issue