Allow LibP2P to break the ties with RLPx by allowing more natural RPC syntax

Integrate the Stew macro printer and use to store the generated code for Whisper
This commit is contained in:
Zahary Karadjov 2020-05-24 01:01:22 +03:00
parent 9375ccc3a9
commit 218192aa09
No known key found for this signature in database
GPG Key ID: C8936F8A3073D609
4 changed files with 1042 additions and 109 deletions

View File

@ -22,6 +22,7 @@ type
response*: Message
userHandler*: NimNode
initResponderCall*: NimNode
outputParamDef*: NimNode
Request* = ref object
queries*: seq[Message]
@ -127,7 +128,9 @@ let
peerVar* {.compileTime.} = ident "peer"
responseVar* {.compileTime.} = ident "response"
streamVar* {.compileTime.} = ident "stream"
protocolVar* {.compileTime.} = ident "protocol"
deadlineVar* {.compileTime.} = ident "deadline"
timeoutVar* {.compileTime.} = ident "timeout"
perProtocolMsgIdVar* {.compileTime.} = ident "perProtocolMsgId"
currentProtocolSym* {.compileTime.} = ident "CurrentProtocol"
resultIdent* {.compileTime.} = ident "result"
@ -138,12 +141,18 @@ let
Void {.compileTime.} = ident "void"
writeField {.compileTime.} = ident "writeField"
PROTO {.compileTime.} = ident "PROTO"
MSG {.compileTime.} = ident "MSG"
template Opt(T): auto = newTree(nnkBracketExpr, Option, T)
template Fut(T): auto = newTree(nnkBracketExpr, Future, T)
proc initFuture*[T](loc: var Future[T]) =
loc = newFuture[T]()
proc isRlpx*(p: P2PProtocol): bool =
p.rlpxName.len > 0
template applyDecorator(p: NimNode, decorator: NimNode) =
if decorator.kind != nnkNilLit:
p.pragma.insert(0, decorator)
@ -152,7 +161,7 @@ when tracingEnabled:
proc logSentMsgFields(peer: NimNode,
protocolInfo: NimNode,
msgName: string,
fields: openarray[NimNode]): NimNode =
fields: openArray[NimNode]): NimNode =
## This generates the tracing code inserted in the message sending procs
## `fields` contains all the params that were serialized in the message
let
@ -206,6 +215,49 @@ proc nameOrNil*(procDef: NimNode): NimNode =
else:
newNilLit()
proc isOutputParamName(paramName: NimNode): bool =
eqIdent(paramName, "output") or eqIdent(paramName, "response")
proc isOutputParam(param: NimNode): bool =
param.len > 0 and param[0].skipPragma.isOutputParamName
proc getOutputParam(procDef: NimNode): NimNode =
let params = procDef.params
for i in countdown(params.len - 1, 1):
let param = params[i]
if isOutputParam(param):
return param
proc outputParam*(msg: Message): NimNode =
case msg.kind
of msgRequest:
outputParam(msg.response)
of msgResponse:
msg.outputParamDef
else:
raiseAssert "Only requests (and the attached responses) can have output parameters"
proc outputParamIdent*(msg: Message): NimNode =
let outputParam = msg.outputParam
if outputParam != nil:
return outputParam[0].skipPragma
proc outputParamType*(msg: Message): NimNode =
let outputParam = msg.outputParam
if outputParam != nil:
return outputParam[1]
iterator typedInputParams(procDef: NimNode, skip = 0): (NimNode, NimNode) =
for paramName, paramType in typedParams(procDef, skip):
if not isOutputParamName(paramName):
yield (paramName, paramType)
proc copyInputParams(params: NimNode): NimNode =
result = newTree(params.kind)
for param in params:
if not isOutputParam(param):
result.add param
proc chooseFieldType(n: NimNode): NimNode =
## Examines the parameter types used in the message signature
## and selects the corresponding field type for use in the
@ -213,7 +265,7 @@ proc chooseFieldType(n: NimNode): NimNode =
##
## For now, only openarray types are remapped to sequences.
result = n
if n.kind == nnkBracketExpr and eqIdent(n[0], "openarray"):
if n.kind == nnkBracketExpr and eqIdent(n[0], "openArray"):
result = n.copyNimTree
result[0] = ident("seq")
@ -257,7 +309,6 @@ proc init*(T: type P2PProtocol, backendFactory: BackendFactory,
result.backend = backendFactory(result)
assert(not result.backend.implementProtocolInit.isNil)
assert(not result.backend.ResponderType.isNil)
if result.backend.ReqIdType.isNil:
result.backend.ReqIdType = ident "int"
@ -267,11 +318,17 @@ proc init*(T: type P2PProtocol, backendFactory: BackendFactory,
if not result.backend.afterProtocolInit.isNil:
result.backend.afterProtocolInit(result)
proc isFuture(t: NimNode): bool =
t.kind == nnkBracketExpr and eqIdent(t[0], "Future")
proc augmentUserHandler(p: P2PProtocol, userHandlerProc: NimNode, msgId = -1) =
## This procs adds a set of common helpers available in all messages handlers
## (e.g. `perProtocolMsgId`, `peer.state`, etc).
userHandlerProc.addPragma ident"gcsafe"
if p.isRlpx:
userHandlerProc.addPragma ident"async"
var
@ -295,7 +352,7 @@ proc augmentUserHandler(p: P2PProtocol, userHandlerProc: NimNode, msgId = -1) =
prelude.add quote do:
type `currentProtocolSym` = `protocolNameIdent`
if msgId >= 0:
if msgId >= 0 and p.isRlpx:
prelude.add quote do:
const `perProtocolMsgIdVar` = `msgId`
@ -303,13 +360,13 @@ proc augmentUserHandler(p: P2PProtocol, userHandlerProc: NimNode, msgId = -1) =
# inside each user message handler proc (e.g. peer.state.foo = bar)
if PeerStateType != nil:
prelude.add quote do:
template state(p: `PeerType`): `PeerStateType` =
cast[`PeerStateType`](`getState`(p, `protocolInfoVar`))
template state(`peerVar`: `PeerType`): `PeerStateType` =
cast[`PeerStateType`](`getState`(`peerVar`, `protocolInfoVar`))
if NetworkStateType != nil:
prelude.add quote do:
template networkState(p: `PeerType`): `NetworkStateType` =
cast[`NetworkStateType`](`getNetworkState`(p.network, `protocolInfoVar`))
template networkState(`peerVar`: `PeerType`): `NetworkStateType` =
cast[`NetworkStateType`](`getNetworkState`(`peerVar`.network, `protocolInfoVar`))
proc addPreludeDefs*(userHandlerProc: NimNode, definitions: NimNode) =
userHandlerProc.body[0].add definitions
@ -322,32 +379,16 @@ proc eventHandlerToProc(p: P2PProtocol, doBlock: NimNode, handlerName: string):
result.name = ident(p.name & handlerName) # genSym(nskProc, p.name & handlerName)
p.augmentUserHandler result
proc ensureTimeoutParam(procDef: NimNode, timeouts: int64): NimNode =
## Make sure the messages has a timeout parameter and it has the correct type.
## The parameter will be removed from the signature and returned for caching
## in the Message's timeoutParam field. It is needed only for the send procs.
proc addTimeoutParam(procDef: NimNode, defaultValue: int64) =
var
Duration = bindSym"Duration"
milliseconds = bindSym"milliseconds"
lastParam = procDef.params[^1]
if eqIdent(lastParam[0], "timeout"):
if lastParam[2].kind == nnkEmpty:
error "You must specify a default value for the `timeout` parameter", lastParam
lastParam[2] = newCall(milliseconds, newLit(100))# newCall(Duration, lastParam[2])
if lastParam[1].kind == nnkEmpty:
lastParam[1] = Duration
elif not eqIdent(lastParam[1], "Duration"):
error "The timeout parameter should be of type 'chronos.Duration'", lastParam[1]
result = lastParam
procDef.params.del(procDef.params.len - 1)
else:
result = newTree(nnkIdentDefs,
ident"timeout",
procDef.params.add newTree(nnkIdentDefs,
timeoutVar,
Duration,
newCall(milliseconds, newLit(timeouts)))
newCall(milliseconds, newLit(defaultValue)))
proc hasReqId*(msg: Message): bool =
msg.protocol.useRequestIds and msg.kind in {msgRequest, msgResponse}
@ -357,9 +398,11 @@ proc ResponderType(msg: Message): NimNode =
newTree(nnkBracketExpr,
msg.protocol.backend.ResponderType, resp.strongRecName)
proc needsSingleParamInlining(msg: Message): bool =
msg.recBody.kind == nnkDistinctTy
proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
procDef: NimNode, timeoutParam: NimNode = nil,
response: Message = nil): Message =
procDef: NimNode, response: Message = nil): Message =
if procDef[0].kind == nnkPostfix:
error("p2pProcotol procs are public by default. " &
@ -373,7 +416,7 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
strongRecName = ident(msgName & "Obj")
recName = strongRecName
for param, paramType in procDef.typedParams(skip = 1):
for param, paramType in procDef.typedInputParams(skip = 1):
recFields.add newTree(nnkIdentDefs,
newTree(nnkPostfix, ident("*"), param), # The fields are public
chooseFieldType(paramType), # some types such as openarray
@ -397,14 +440,13 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
recName: recName,
strongRecName: strongRecName,
recBody: recBody,
timeoutParam: timeoutParam,
response: response)
if procDef.body.kind != nnkEmpty:
var userHandler = copy procDef
protocol.augmentUserHandler userHandler, id
userHandler.name = genSym(nskProc, msgName)
userHandler.name = ident(msgName & "UserHandler")
# Request and Response handlers get an extra `reqId` parameter if the
# protocol uses them:
@ -412,7 +454,7 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
userHandler.params.insert(2, newIdentDefs(reqIdVar, protocol.backend.ReqIdType))
# All request handlers get an automatically inserter `response` variable:
if kind == msgRequest:
if kind == msgRequest and protocol.isRlpx:
assert response != nil
let
peerParam = userHandler.params[1][0]
@ -436,6 +478,39 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, id: int,
protocol.messages.add result
proc isVoid(t: NimNode): bool =
t.kind == nnkEmpty or eqIdent(t, "void")
proc addMsg(p: P2PProtocol, id: int, procDef: NimNode) =
var
returnType = procDef.params[0]
hasReturnValue = not isVoid(returnType)
outputParam = procDef.getOutputParam()
if outputParam != nil:
if hasReturnValue:
error "A request proc should either use a return value or an output parameter"
returnType = outputParam[1]
hasReturnValue = true
if hasReturnValue:
let
responseIdent = ident($procDef.name & "Response")
response = Message(protocol: p,
id: -1, # TODO: Implement the message IDs in RLPx-specific way
ident: responseIdent,
kind: msgResponse,
recName: returnType,
strongRecName: returnType,
recBody: returnType,
outputParamDef: outputParam)
p.messages.add response
let msg = p.newMsg(msgRequest, id, procDef, response = response)
p.requests.add Request(queries: @[msg], response: response)
else:
p.notifications.add p.newMsg(msgNotification, id, procDef)
proc identWithExportMarker*(msg: Message): NimNode =
newTree(nnkPostfix, ident("*"), msg.ident)
@ -475,19 +550,20 @@ proc createSendProc*(msg: Message,
name,
newEmptyNode(),
newEmptyNode(),
copy msg.procDef.params,
copyInputParams msg.procDef.params,
pragmas,
newEmptyNode(),
newStmtList()) ## body
if proctype == nnkProcDef:
for p in msg.procDef.pragma:
if not eqIdent(p, "async"):
def.addPragma p
result.msg = msg
result.def = def
for param, paramType in def.typedParams():
for param, paramType in def.typedInputParams():
if result.peerParam.isNil:
result.peerParam = param
else:
@ -496,11 +572,10 @@ proc createSendProc*(msg: Message,
case msg.kind
of msgHandshake, msgRequest:
# Add a timeout parameter for all request procs
let timeout = copy msg.timeoutParam
def[3].add timeout
result.timeoutParam = timeout[0]
def.addTimeoutParam(msg.protocol.timeouts)
of msgResponse:
if msg.ResponderType != nil:
# A response proc must be called with a response object that originates
# from a certain request. Here we change the Peer parameter at position
# 1 to the correct strongly-typed ResponderType. The incoming procs still
@ -546,7 +621,7 @@ proc setBody*(sendProc: SendProc, body: NimNode) =
if sendProc.extraDefs != nil:
msg.protocol.outSendProcs.add sendProc.extraDefs
proc writeParamsAsRecord*(params: openarray[NimNode],
proc writeParamsAsRecord*(params: openArray[NimNode],
outputStream, Format, RecordType: NimNode): NimNode =
if params.len == 0:
return newStmtList()
@ -584,10 +659,19 @@ proc useStandardBody*(sendProc: SendProc,
sendCallGenerator: proc (peer, bytes: NimNode): NimNode) =
let
msg = sendProc.msg
outputStream = ident "outputStream"
msgBytes = ident "msgBytes"
recipient = sendProc.peerParam
sendCall = sendCallGenerator(recipient, msgBytes)
if sendProc.msgParams.len == 0:
sendProc.setBody quote do:
var `msgBytes`: seq[byte]
`sendCall`
return
let
outputStream = ident "outputStream"
msgRecName = msg.recName
Format = msg.protocol.backend.SerializationFormat
@ -602,8 +686,6 @@ proc useStandardBody*(sendProc: SendProc,
appendParams = newStmtList()
sendCall = sendCallGenerator(recipient, msgBytes)
tracing = when not tracingEnabled:
newStmtList()
else:
@ -655,27 +737,32 @@ proc defineThunk*(msg: Message, thunk: NimNode) =
protocol.outRecvProcs.add thunk
proc genUserHandlerCall*(msg: Message, receivedMsg: NimNode,
leadingParams: varargs[NimNode]): NimNode =
leadingParams: openArray[NimNode],
outputParam: NimNode = nil): NimNode =
if msg.userHandler == nil:
return newStmtList()
result = newCall(msg.userHandler.name, leadingParams)
var params = toSeq(msg.procDef.typedParams(skip = 1))
if params.len == 1 and msg.protocol.useSingleRecordInlining:
if msg.needsSingleParamInlining:
result.add receivedMsg
else:
var params = toSeq(msg.procDef.typedInputParams(skip = 1))
for p in params:
result.add newDotExpr(receivedMsg, p[0])
if outputParam != nil:
result.add outputParam
proc genAwaitUserHandler*(msg: Message, receivedMsg: NimNode,
leadingParams: varargs[NimNode]): NimNode =
result = msg.genUserHandlerCall(receivedMsg, leadingParams)
leadingParams: openArray[NimNode],
outputParam: NimNode = nil): NimNode =
result = msg.genUserHandlerCall(receivedMsg, leadingParams, outputParam)
if result.len > 0: result = newCall("await", result)
proc appendAllParams*(node: NimNode, procDef: NimNode, skipFirst = 0): NimNode =
proc appendAllInputParams*(node: NimNode, procDef: NimNode): NimNode =
result = node
for p, _ in procDef.typedParams(skip = skipFirst):
for p, _ in procDef.typedInputParams():
result.add p
proc paramNames*(procDef: NimNode, skipFirst = 0): seq[NimNode] =
@ -696,22 +783,20 @@ proc createHandshakeTemplate*(msg: Message,
nextMsg: NimNode): SendProc =
let
handshakeExchanger = msg.createSendProc(procType = nnkTemplateDef)
forwardCall = newCall(rawSendProc).appendAllParams(handshakeExchanger.def)
forwardCall = newCall(rawSendProc).appendAllInputParams(handshakeExchanger.def)
peerValue = forwardCall[1]
timeoutValue = msg.timeoutParam[0]
peerVarSym = genSym(nskLet, "peer")
msgRecName = msg.recName
forwardCall[1] = peerVarSym
forwardCall[1] = peerVar
forwardCall.del(forwardCall.len - 1)
handshakeExchanger.setBody quote do:
let `peerVarSym` = `peerValue`
let `peerVar` = `peerValue`
let sendingFuture = `forwardCall`
`handshakeImpl`(`peerVarSym`,
`handshakeImpl`(`peerVar`,
sendingFuture,
`nextMsg`(`peerVarSym`, `msgRecName`),
`timeoutValue`)
`nextMsg`(`peerVar`, `msgRecName`),
`timeoutVar`)
return handshakeExchanger
@ -762,9 +847,7 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) =
let responseMsg = p.newMsg(msgResponse, nextId + procs.len - 1, procs[^1])
for i in 0 .. procs.len - 2:
var timeout = ensureTimeoutParam(procs[i], p.timeouts)
queries.add p.newMsg(msgRequest, nextId + i, procs[i], timeout,
response = responseMsg)
queries.add p.newMsg(msgRequest, nextId + i, procs[i], response = responseMsg)
p.requests.add Request(queries: queries, response: responseMsg)
@ -778,8 +861,7 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) =
if p.handshake != nil:
error "The handshake for the protocol is already defined", n
var timeout = ensureTimeoutParam(procs[0], p.timeouts)
p.handshake = p.newMsg(msgHandshake, nextId, procs[0], timeout)
p.handshake = p.newMsg(msgHandshake, nextId, procs[0])
inc nextId
elif eqIdent(n[0], "onPeerConnected"):
@ -791,8 +873,8 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) =
else:
error(repr(n) & " is not a recognized call in P2P protocol definitions", n)
of nnkProcDef:
p.notifications.add p.newMsg(msgNotification, nextId, n)
of nnkProcDef, nnkIteratorDef:
p.addMsg(nextId, n)
inc nextId
of nnkCommentStmt:
@ -815,13 +897,16 @@ proc genTypeSection*(p: P2PProtocol): NimNode =
if peerState != nil:
result.add quote do:
template State*(P: type `protocolName`): type = `peerState`
template State*(`PROTO`: type `protocolName`): type = `peerState`
if networkState != nil:
result.add quote do:
template NetworkState*(P: type `protocolName`): type = `networkState`
template NetworkState*(`PROTO`: type `protocolName`): type = `networkState`
for msg in p.messages:
if msg.procDef == nil:
continue
let
msgId = msg.id
msgName = msg.ident
@ -835,42 +920,34 @@ proc genTypeSection*(p: P2PProtocol): NimNode =
# Add a helper template for accessing the message type:
# e.g. p2p.hello:
template `msgName`*(T: type `protocolName`): type = `msgRecName`
template `msgName`*(`PROTO`: type `protocolName`): type = `msgRecName`
# Add a helper template for obtaining the message Id for
# a particular message type:
template msgId*(T: type `msgStrongRecName`): int = `msgId`
template msgProtocol*(T: type `msgStrongRecName`): type = `protocolName`
template RecType*(T: type `msgStrongRecName`): untyped = `msgRecName`
template msgProtocol*(`MSG`: type `msgStrongRecName`): type = `protocolName`
template RecType*(`MSG`: type `msgStrongRecName`): untyped = `msgRecName`
if p.isRlpx:
result.add quote do:
template msgId*(`MSG`: type `msgStrongRecName`): int = `msgId`
proc genCode*(p: P2PProtocol): NimNode =
# TODO: try switching to a simpler for msg in p.messages: loop
when true:
for msg in p.messages:
p.backend.implementMsg msg
else:
if p.handshake != nil:
p.backend.implementMsg p.handshake
for msg in p.notifications:
p.backend.implementMsg msg
for req in p.requests:
p.backend.implementMsg req.response
for query in req.queries: p.backend.implementMsg(query)
result = newStmtList()
result.add p.genTypeSection()
let
protocolInfoVar = p.protocolInfoVar
protocolInfoVarObj = ident($protocolInfoVar & "Obj")
protocolName = p.nameIdent
protocolInit = p.backend.implementProtocolInit(p)
result.add quote do:
# One global variable per protocol holds the protocol run-time data
var p = `protocolInit`
var `protocolInfoVar` = addr p
var `protocolInfoVarObj` = `protocolInit`
var `protocolInfoVar` = addr `protocolInfoVarObj`
# The protocol run-time data is available as a pseudo-field
# (e.g. `p2p.protocolInfo`)
@ -919,9 +996,7 @@ macro emitForSingleBackend(
peerState.getType, networkState.getType)
result = p.genCode()
when defined(debugP2pProtocol) or defined(debugMacros):
echo repr(result)
result.storeMacroResult true
macro emitForAllBackends(backendSyms: typed, options: untyped, body: untyped): untyped =
let name = $(options[0])

View File

@ -643,7 +643,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
# assumes there is one outstanding request at a time (if there are
# multiple requests we'll resolve them in FIFO order).
let registerRequestCall = newCall(registerRequest, peerVar,
msg.timeoutParam[0],
timeoutVar,
resultIdent,
responseMsgId)
if hasReqId:
@ -695,7 +695,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
let
awaitUserHandler = msg.genAwaitUserHandler(receivedMsg, userHandlerParams)
thunkName = ident(msgName & "_thunk")
thunkName = ident(msgName & "Thunk")
msg.defineThunk quote do:
proc `thunkName`(`peerVar`: `Peer`, _: int, data: Rlp) {.async, gcsafe.} =

View File

@ -0,0 +1,196 @@
## Generated at line 781
type
DevP2P* = object
type
helloObj* = object
version*: uint
clientId*: string
capabilities*: seq[Capability]
listenPort*: uint
nodeId*: array[RawPublicKeySize, byte]
template hello*(PROTO: type DevP2P): type =
helloObj
template msgProtocol*(MSG: type helloObj): type =
DevP2P
template RecType*(MSG: type helloObj): untyped =
helloObj
template msgId*(MSG: type helloObj): int =
0
type
sendDisconnectMsgObj* = object
reason*: DisconnectionReasonList
template sendDisconnectMsg*(PROTO: type DevP2P): type =
sendDisconnectMsgObj
template msgProtocol*(MSG: type sendDisconnectMsgObj): type =
DevP2P
template RecType*(MSG: type sendDisconnectMsgObj): untyped =
sendDisconnectMsgObj
template msgId*(MSG: type sendDisconnectMsgObj): int =
1
type
pingObj* = object
emptyList*: EmptyList
template ping*(PROTO: type DevP2P): type =
pingObj
template msgProtocol*(MSG: type pingObj): type =
DevP2P
template RecType*(MSG: type pingObj): untyped =
pingObj
template msgId*(MSG: type pingObj): int =
2
type
pongObj* = object
emptyList*: EmptyList
template pong*(PROTO: type DevP2P): type =
pongObj
template msgProtocol*(MSG: type pongObj): type =
DevP2P
template RecType*(MSG: type pongObj): untyped =
pongObj
template msgId*(MSG: type pongObj): int =
3
var DevP2PProtocolObj = initProtocol("p2p", 5, nil, nil)
var DevP2PProtocol = addr DevP2PProtocolObj
template protocolInfo*(P`gensym75730262: type DevP2P): auto =
DevP2PProtocol
proc hello*(peerOrResponder: Peer; version: uint; clientId: string;
capabilities: seq[Capability]; listenPort: uint;
nodeId: array[RawPublicKeySize, byte]): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 0
let perPeerMsgId = 0
append(writer, perPeerMsgId)
startList(writer, 5)
append(writer, version)
append(writer, clientId)
append(writer, capabilities)
append(writer, listenPort)
append(writer, nodeId)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc sendDisconnectMsg*(peerOrResponder: Peer; reason: DisconnectionReasonList): Future[
void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 1
let perPeerMsgId = 1
append(writer, perPeerMsgId)
append(writer, reason)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc ping*(peerOrResponder: Peer; emptyList: EmptyList): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 2
let perPeerMsgId = 2
append(writer, perPeerMsgId)
append(writer, emptyList)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc pong*(peerOrResponder: Peer; emptyList: EmptyList): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 3
let perPeerMsgId = 3
append(writer, perPeerMsgId)
append(writer, emptyList)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc sendDisconnectMsgUserHandler(peer: Peer; reason: DisconnectionReasonList) {.
gcsafe, async.} =
type
CurrentProtocol = DevP2P
const
perProtocolMsgId = 1
trace "disconnect message received", reason = reason.value, peer
await peer.disconnect(reason.value, false)
proc pingUserHandler(peer: Peer; emptyList: EmptyList) {.gcsafe, async.} =
type
CurrentProtocol = DevP2P
const
perProtocolMsgId = 2
discard peer.pong(EmptyList())
proc pongUserHandler(peer: Peer; emptyList: EmptyList) {.gcsafe, async.} =
type
CurrentProtocol = DevP2P
const
perProtocolMsgId = 3
discard
proc helloThunk(peer: Peer; _`gensym75730215: int; data`gensym75730216: Rlp) {.async,
gcsafe.} =
var rlp = data`gensym75730216
var msg {.noinit.}: helloObj
tryEnterList(rlp)
msg.version = checkedRlpRead(peer, rlp, uint)
msg.clientId = checkedRlpRead(peer, rlp, string)
msg.capabilities = checkedRlpRead(peer, rlp, seq[Capability])
msg.listenPort = checkedRlpRead(peer, rlp, uint)
msg.nodeId = checkedRlpRead(peer, rlp, array[RawPublicKeySize, byte])
proc sendDisconnectMsgThunk(peer: Peer; _`gensym75730250: int;
data`gensym75730251: Rlp) {.async, gcsafe.} =
var rlp = data`gensym75730251
var msg {.noinit.}: sendDisconnectMsgObj
msg.reason = checkedRlpRead(peer, rlp, DisconnectionReasonList)
await(sendDisconnectMsgUserHandler(peer, msg.reason))
proc pingThunk(peer: Peer; _`gensym75730252: int; data`gensym75730253: Rlp) {.async,
gcsafe.} =
var rlp = data`gensym75730253
var msg {.noinit.}: pingObj
msg.emptyList = checkedRlpRead(peer, rlp, EmptyList)
await(pingUserHandler(peer, msg.emptyList))
proc pongThunk(peer: Peer; _`gensym75730254: int; data`gensym75730255: Rlp) {.async,
gcsafe.} =
var rlp = data`gensym75730255
var msg {.noinit.}: pongObj
msg.emptyList = checkedRlpRead(peer, rlp, EmptyList)
await(pongUserHandler(peer, msg.emptyList))
registerMsg(DevP2PProtocol, 0, "hello", helloThunk, messagePrinter[helloObj],
requestResolver[helloObj], nextMsgResolver[helloObj])
registerMsg(DevP2PProtocol, 1, "sendDisconnectMsg", sendDisconnectMsgThunk,
messagePrinter[sendDisconnectMsgObj],
requestResolver[sendDisconnectMsgObj],
nextMsgResolver[sendDisconnectMsgObj])
registerMsg(DevP2PProtocol, 2, "ping", pingThunk, messagePrinter[pingObj],
requestResolver[pingObj], nextMsgResolver[pingObj])
registerMsg(DevP2PProtocol, 3, "pong", pongThunk, messagePrinter[pongObj],
requestResolver[pongObj], nextMsgResolver[pongObj])
setEventHandlers(DevP2PProtocol, nil, nil)
registerProtocol(DevP2PProtocol)

View File

@ -0,0 +1,662 @@
## Generated at line 119
type
Whisper* = object
template State*(PROTO: type Whisper): type =
ref[WhisperPeer:ObjectType]
template NetworkState*(PROTO: type Whisper): type =
ref[WhisperNetwork:ObjectType]
type
statusObj* = object
protocolVersion*: uint
powConverted*: uint64
bloom*: seq[byte]
isLightNode*: bool
template status*(PROTO: type Whisper): type =
statusObj
template msgProtocol*(MSG: type statusObj): type =
Whisper
template RecType*(MSG: type statusObj): untyped =
statusObj
template msgId*(MSG: type statusObj): int =
0
type
messagesObj* = object
envelopes*: seq[Envelope]
template messages*(PROTO: type Whisper): type =
messagesObj
template msgProtocol*(MSG: type messagesObj): type =
Whisper
template RecType*(MSG: type messagesObj): untyped =
messagesObj
template msgId*(MSG: type messagesObj): int =
1
type
powRequirementObj* = object
value*: uint64
template powRequirement*(PROTO: type Whisper): type =
powRequirementObj
template msgProtocol*(MSG: type powRequirementObj): type =
Whisper
template RecType*(MSG: type powRequirementObj): untyped =
powRequirementObj
template msgId*(MSG: type powRequirementObj): int =
2
type
bloomFilterExchangeObj* = object
bloom*: seq[byte]
template bloomFilterExchange*(PROTO: type Whisper): type =
bloomFilterExchangeObj
template msgProtocol*(MSG: type bloomFilterExchangeObj): type =
Whisper
template RecType*(MSG: type bloomFilterExchangeObj): untyped =
bloomFilterExchangeObj
template msgId*(MSG: type bloomFilterExchangeObj): int =
3
type
p2pRequestObj* = object
envelope*: Envelope
template p2pRequest*(PROTO: type Whisper): type =
p2pRequestObj
template msgProtocol*(MSG: type p2pRequestObj): type =
Whisper
template RecType*(MSG: type p2pRequestObj): untyped =
p2pRequestObj
template msgId*(MSG: type p2pRequestObj): int =
126
type
p2pMessageObj* = object
envelope*: Envelope
template p2pMessage*(PROTO: type Whisper): type =
p2pMessageObj
template msgProtocol*(MSG: type p2pMessageObj): type =
Whisper
template RecType*(MSG: type p2pMessageObj): untyped =
p2pMessageObj
template msgId*(MSG: type p2pMessageObj): int =
127
type
batchAcknowledgedObj* = object
template batchAcknowledged*(PROTO: type Whisper): type =
batchAcknowledgedObj
template msgProtocol*(MSG: type batchAcknowledgedObj): type =
Whisper
template RecType*(MSG: type batchAcknowledgedObj): untyped =
batchAcknowledgedObj
template msgId*(MSG: type batchAcknowledgedObj): int =
11
type
messageResponseObj* = object
template messageResponse*(PROTO: type Whisper): type =
messageResponseObj
template msgProtocol*(MSG: type messageResponseObj): type =
Whisper
template RecType*(MSG: type messageResponseObj): untyped =
messageResponseObj
template msgId*(MSG: type messageResponseObj): int =
12
type
p2pSyncResponseObj* = object
template p2pSyncResponse*(PROTO: type Whisper): type =
p2pSyncResponseObj
template msgProtocol*(MSG: type p2pSyncResponseObj): type =
Whisper
template RecType*(MSG: type p2pSyncResponseObj): untyped =
p2pSyncResponseObj
template msgId*(MSG: type p2pSyncResponseObj): int =
124
type
p2pSyncRequestObj* = object
template p2pSyncRequest*(PROTO: type Whisper): type =
p2pSyncRequestObj
template msgProtocol*(MSG: type p2pSyncRequestObj): type =
Whisper
template RecType*(MSG: type p2pSyncRequestObj): untyped =
p2pSyncRequestObj
template msgId*(MSG: type p2pSyncRequestObj): int =
123
type
p2pRequestCompleteObj* = object
template p2pRequestComplete*(PROTO: type Whisper): type =
p2pRequestCompleteObj
template msgProtocol*(MSG: type p2pRequestCompleteObj): type =
Whisper
template RecType*(MSG: type p2pRequestCompleteObj): untyped =
p2pRequestCompleteObj
template msgId*(MSG: type p2pRequestCompleteObj): int =
125
var WhisperProtocolObj = initProtocol("shh", 6, createPeerState[Peer,
ref[WhisperPeer:ObjectType]], createNetworkState[EthereumNode,
ref[WhisperNetwork:ObjectType]])
var WhisperProtocol = addr WhisperProtocolObj
template protocolInfo*(P`gensym85175079: type Whisper): auto =
WhisperProtocol
proc statusRawSender(peerOrResponder: Peer; protocolVersion: uint;
powConverted: uint64; bloom: seq[byte]; isLightNode: bool;
timeout: Duration = milliseconds(10000'i64)): Future[void] {.
gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 0
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 0)
append(writer, perPeerMsgId)
startList(writer, 4)
append(writer, protocolVersion)
append(writer, powConverted)
append(writer, bloom)
append(writer, isLightNode)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
template status*(peerOrResponder: Peer; protocolVersion: uint; powConverted: uint64;
bloom: seq[byte]; isLightNode: bool;
timeout: Duration = milliseconds(10000'i64)): Future[statusObj] =
let peer = peerOrResponder
let sendingFuture`gensym85175056 = statusRawSender(peer, protocolVersion,
powConverted, bloom, isLightNode)
handshakeImpl(peer, sendingFuture`gensym85175056, nextMsg(peer, statusObj),
timeout)
proc messages*(peerOrResponder: Peer; envelopes: openarray[Envelope]): Future[void] {.
gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 1
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 1)
append(writer, perPeerMsgId)
append(writer, envelopes)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc powRequirement*(peerOrResponder: Peer; value: uint64): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 2
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 2)
append(writer, perPeerMsgId)
append(writer, value)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc bloomFilterExchange*(peerOrResponder: Peer; bloom: openArray[byte]): Future[void] {.
gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 3
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 3)
append(writer, perPeerMsgId)
append(writer, bloom)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc p2pRequest*(peerOrResponder: Peer; envelope: Envelope): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 126
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 126)
append(writer, perPeerMsgId)
append(writer, envelope)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc p2pMessage*(peerOrResponder: Peer; envelope: Envelope): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 127
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 127)
append(writer, perPeerMsgId)
append(writer, envelope)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc batchAcknowledged*(peerOrResponder: Peer): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 11
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 11)
append(writer, perPeerMsgId)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc messageResponse*(peerOrResponder: Peer): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 12
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 12)
append(writer, perPeerMsgId)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc p2pSyncResponse*(peerOrResponder: ResponderWithId[p2pSyncResponseObj]): Future[
void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 124
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 124)
append(writer, perPeerMsgId)
append(writer, peerOrResponder.reqId)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
template send*(r`gensym85175073: ResponderWithId[p2pSyncResponseObj];
args`gensym85175074: varargs[untyped]): auto =
p2pSyncResponse(r`gensym85175073, args`gensym85175074)
proc p2pSyncRequest*(peerOrResponder: Peer;
timeout: Duration = milliseconds(10000'i64)): Future[
Option[p2pSyncResponseObj]] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 123
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 123)
append(writer, perPeerMsgId)
initFuture result
let reqId = registerRequest(peer, timeout, result, perPeerMsgId + 1)
append(writer, reqId)
let msgBytes = finish(writer)
linkSendFailureToReqFuture(sendMsg(peer, msgBytes), result)
proc p2pRequestComplete*(peerOrResponder: Peer): Future[void] {.gcsafe.} =
let peer = getPeer(peerOrResponder)
var writer = initRlpWriter()
const
perProtocolMsgId = 125
let perPeerMsgId = perPeerMsgIdImpl(peer, WhisperProtocol, 125)
append(writer, perPeerMsgId)
let msgBytes = finish(writer)
return sendMsg(peer, msgBytes)
proc messagesUserHandler(peer: Peer; envelopes: seq[Envelope]) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 1
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
if not peer.state.initialized:
warn "Handshake not completed yet, discarding messages"
return
for envelope in envelopes:
if not envelope.valid():
warn "Expired or future timed envelope", peer
continue
let msg = initMessage(envelope)
if not msg.allowed(peer.networkState.config):
continue
if peer.state.received.containsOrIncl(msg.hash):
dropped_duplicate_envelopes.inc()
trace "Peer sending duplicate messages", peer, hash = $msg.hash
continue
if peer.networkState.queue[].add(msg):
peer.networkState.filters.notify(msg)
proc powRequirementUserHandler(peer: Peer; value: uint64) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 2
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
if not peer.state.initialized:
warn "Handshake not completed yet, discarding powRequirement"
return
peer.state.powRequirement = cast[float64](value)
proc bloomFilterExchangeUserHandler(peer: Peer; bloom: seq[byte]) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 3
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
if not peer.state.initialized:
warn "Handshake not completed yet, discarding bloomFilterExchange"
return
if bloom.len == bloomSize:
peer.state.bloom.bytesCopy(bloom)
proc p2pRequestUserHandler(peer: Peer; envelope: Envelope) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 126
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
discard
proc p2pMessageUserHandler(peer: Peer; envelope: Envelope) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 127
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
if peer.state.trusted:
let msg = Message(env: envelope, isP2P: true)
peer.networkState.filters.notify(msg)
proc batchAcknowledgedUserHandler(peer: Peer) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 11
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
discard
proc messageResponseUserHandler(peer: Peer) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 12
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
discard
proc p2pSyncResponseUserHandler(peer: Peer; reqId: int) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 124
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
discard
proc p2pSyncRequestUserHandler(peer: Peer; reqId: int) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 123
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
var response = init(ResponderWithId[p2pSyncResponseObj], peer, reqId)
discard
proc p2pRequestCompleteUserHandler(peer: Peer) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
const
perProtocolMsgId = 125
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
discard
proc statusThunk(peer: Peer; _`gensym85175033: int; data`gensym85175034: Rlp) {.async,
gcsafe.} =
var rlp = data`gensym85175034
var msg {.noinit.}: statusObj
tryEnterList(rlp)
msg.protocolVersion = checkedRlpRead(peer, rlp, uint)
msg.powConverted = checkedRlpRead(peer, rlp, uint64)
msg.bloom = checkedRlpRead(peer, rlp, seq[byte])
msg.isLightNode = checkedRlpRead(peer, rlp, bool)
proc messagesThunk(peer: Peer; _`gensym85175057: int; data`gensym85175058: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175058
var msg {.noinit.}: messagesObj
msg.envelopes = checkedRlpRead(peer, rlp, openarray[Envelope])
await(messagesUserHandler(peer, msg.envelopes))
proc powRequirementThunk(peer: Peer; _`gensym85175059: int; data`gensym85175060: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175060
var msg {.noinit.}: powRequirementObj
msg.value = checkedRlpRead(peer, rlp, uint64)
await(powRequirementUserHandler(peer, msg.value))
proc bloomFilterExchangeThunk(peer: Peer; _`gensym85175061: int;
data`gensym85175062: Rlp) {.async, gcsafe.} =
var rlp = data`gensym85175062
var msg {.noinit.}: bloomFilterExchangeObj
msg.bloom = checkedRlpRead(peer, rlp, openArray[byte])
await(bloomFilterExchangeUserHandler(peer, msg.bloom))
proc p2pRequestThunk(peer: Peer; _`gensym85175063: int; data`gensym85175064: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175064
var msg {.noinit.}: p2pRequestObj
msg.envelope = checkedRlpRead(peer, rlp, Envelope)
await(p2pRequestUserHandler(peer, msg.envelope))
proc p2pMessageThunk(peer: Peer; _`gensym85175065: int; data`gensym85175066: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175066
var msg {.noinit.}: p2pMessageObj
msg.envelope = checkedRlpRead(peer, rlp, Envelope)
await(p2pMessageUserHandler(peer, msg.envelope))
proc batchAcknowledgedThunk(peer: Peer; _`gensym85175067: int;
data`gensym85175068: Rlp) {.async, gcsafe.} =
var rlp = data`gensym85175068
var msg {.noinit.}: batchAcknowledgedObj
await(batchAcknowledgedUserHandler(peer))
proc messageResponseThunk(peer: Peer; _`gensym85175069: int; data`gensym85175070: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175070
var msg {.noinit.}: messageResponseObj
await(messageResponseUserHandler(peer))
proc p2pSyncResponseThunk(peer: Peer; _`gensym85175071: int; data`gensym85175072: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175072
var msg {.noinit.}: p2pSyncResponseObj
let reqId = read(rlp, int)
await(p2pSyncResponseUserHandler(peer, reqId))
resolveResponseFuture(peer, perPeerMsgId(peer, p2pSyncResponseObj), addr(msg),
reqId)
proc p2pSyncRequestThunk(peer: Peer; _`gensym85175075: int; data`gensym85175076: Rlp) {.
async, gcsafe.} =
var rlp = data`gensym85175076
var msg {.noinit.}: p2pSyncRequestObj
let reqId = read(rlp, int)
await(p2pSyncRequestUserHandler(peer, reqId))
proc p2pRequestCompleteThunk(peer: Peer; _`gensym85175077: int;
data`gensym85175078: Rlp) {.async, gcsafe.} =
var rlp = data`gensym85175078
var msg {.noinit.}: p2pRequestCompleteObj
await(p2pRequestCompleteUserHandler(peer))
registerMsg(WhisperProtocol, 0, "status", statusThunk, messagePrinter[statusObj],
requestResolver[statusObj], nextMsgResolver[statusObj])
registerMsg(WhisperProtocol, 1, "messages", messagesThunk,
messagePrinter[messagesObj], requestResolver[messagesObj],
nextMsgResolver[messagesObj])
registerMsg(WhisperProtocol, 2, "powRequirement", powRequirementThunk,
messagePrinter[powRequirementObj],
requestResolver[powRequirementObj],
nextMsgResolver[powRequirementObj])
registerMsg(WhisperProtocol, 3, "bloomFilterExchange", bloomFilterExchangeThunk,
messagePrinter[bloomFilterExchangeObj],
requestResolver[bloomFilterExchangeObj],
nextMsgResolver[bloomFilterExchangeObj])
registerMsg(WhisperProtocol, 126, "p2pRequest", p2pRequestThunk,
messagePrinter[p2pRequestObj], requestResolver[p2pRequestObj],
nextMsgResolver[p2pRequestObj])
registerMsg(WhisperProtocol, 127, "p2pMessage", p2pMessageThunk,
messagePrinter[p2pMessageObj], requestResolver[p2pMessageObj],
nextMsgResolver[p2pMessageObj])
registerMsg(WhisperProtocol, 11, "batchAcknowledged", batchAcknowledgedThunk,
messagePrinter[batchAcknowledgedObj],
requestResolver[batchAcknowledgedObj],
nextMsgResolver[batchAcknowledgedObj])
registerMsg(WhisperProtocol, 12, "messageResponse", messageResponseThunk,
messagePrinter[messageResponseObj],
requestResolver[messageResponseObj],
nextMsgResolver[messageResponseObj])
registerMsg(WhisperProtocol, 124, "p2pSyncResponse", p2pSyncResponseThunk,
messagePrinter[p2pSyncResponseObj],
requestResolver[p2pSyncResponseObj],
nextMsgResolver[p2pSyncResponseObj])
registerMsg(WhisperProtocol, 123, "p2pSyncRequest", p2pSyncRequestThunk,
messagePrinter[p2pSyncRequestObj],
requestResolver[p2pSyncRequestObj],
nextMsgResolver[p2pSyncRequestObj])
registerMsg(WhisperProtocol, 125, "p2pRequestComplete", p2pRequestCompleteThunk,
messagePrinter[p2pRequestCompleteObj],
requestResolver[p2pRequestCompleteObj],
nextMsgResolver[p2pRequestCompleteObj])
proc WhisperPeerConnected(peer: Peer) {.gcsafe, async.} =
type
CurrentProtocol = Whisper
template state(peer: Peer): ref[WhisperPeer:ObjectType] =
cast[ref[WhisperPeer:ObjectType]](getState(peer, WhisperProtocol))
template networkState(peer: Peer): ref[WhisperNetwork:ObjectType] =
cast[ref[WhisperNetwork:ObjectType]](getNetworkState(peer.network,
WhisperProtocol))
trace "onPeerConnected Whisper"
let
whisperNet = peer.networkState
whisperPeer = peer.state
let m = await peer.status(whisperVersion,
cast[uint64](whisperNet.config.powRequirement),
@(whisperNet.config.bloom),
whisperNet.config.isLightNode,
timeout = chronos.milliseconds(5000))
if m.protocolVersion == whisperVersion:
debug "Whisper peer", peer, whisperVersion
else:
raise newException(UselessPeerError, "Incompatible Whisper version")
whisperPeer.powRequirement = cast[float64](m.powConverted)
if m.bloom.len > 0:
if m.bloom.len != bloomSize:
raise newException(UselessPeerError, "Bloomfilter size mismatch")
else:
whisperPeer.bloom.bytesCopy(m.bloom)
else:
whisperPeer.bloom = fullBloom()
whisperPeer.isLightNode = m.isLightNode
if whisperPeer.isLightNode and whisperNet.config.isLightNode:
raise newException(UselessPeerError, "Two light nodes connected")
whisperPeer.received.init()
whisperPeer.trusted = false
whisperPeer.initialized = true
if not whisperNet.config.isLightNode:
traceAsyncErrors peer.run()
debug "Whisper peer initialized", peer
setEventHandlers(WhisperProtocol, WhisperPeerConnected, nil)
registerProtocol(WhisperProtocol)