remove remaining `int` holdouts in rlp (#737)

these were never well defined
This commit is contained in:
Jacek Sieka 2024-09-30 18:32:36 +02:00 committed by GitHub
parent b49df0a71a
commit 119c910a4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 112 additions and 107 deletions

View File

@ -35,7 +35,7 @@ type
msgResponse msgResponse
Message* = ref object Message* = ref object
id*: Opt[uint] id*: Opt[uint64]
ident*: NimNode ident*: NimNode
kind*: MessageKind kind*: MessageKind
procDef*: NimNode procDef*: NimNode
@ -83,7 +83,7 @@ type
P2PProtocol* = ref object P2PProtocol* = ref object
# Settings # Settings
name*: string name*: string
version*: int version*: uint64
timeouts*: int64 timeouts*: int64
useRequestIds*: bool useRequestIds*: bool
useSingleRecordInlining*: bool useSingleRecordInlining*: bool
@ -148,8 +148,7 @@ const
let let
# Variable names affecting the public interface of the library: # Variable names affecting the public interface of the library:
reqIdVar* {.compileTime.} = ident "reqId" reqIdVar* {.compileTime.} = ident "reqId"
# XXX: Binding the int type causes instantiation failure for some reason ReqIdType* {.compileTime.} = ident "uint64"
ReqIdType* {.compileTime.} = ident "uint"
peerVar* {.compileTime.} = ident "peer" peerVar* {.compileTime.} = ident "peer"
responseVar* {.compileTime.} = ident "response" responseVar* {.compileTime.} = ident "response"
streamVar* {.compileTime.} = ident "stream" streamVar* {.compileTime.} = ident "stream"
@ -313,7 +312,7 @@ proc verifyStateType(t: NimNode): NimNode =
proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode)
proc init*(T: type P2PProtocol, backendFactory: BackendFactory, proc init*(T: type P2PProtocol, backendFactory: BackendFactory,
name: string, version: int, body: NimNode, name: string, version: uint64, body: NimNode,
timeouts: int64, useRequestIds: bool, rlpxName: string, timeouts: int64, useRequestIds: bool, rlpxName: string,
outgoingRequestDecorator: NimNode, outgoingRequestDecorator: NimNode,
incomingRequestDecorator: NimNode, incomingRequestDecorator: NimNode,
@ -345,14 +344,14 @@ proc init*(T: type P2PProtocol, backendFactory: BackendFactory,
assert(not result.backend.implementProtocolInit.isNil) assert(not result.backend.implementProtocolInit.isNil)
if result.backend.ReqIdType.isNil: if result.backend.ReqIdType.isNil:
result.backend.ReqIdType = ident "uint" result.backend.ReqIdType = ident "uint64"
result.processProtocolBody body result.processProtocolBody body
if not result.backend.afterProtocolInit.isNil: if not result.backend.afterProtocolInit.isNil:
result.backend.afterProtocolInit(result) result.backend.afterProtocolInit(result)
proc augmentUserHandler(p: P2PProtocol, userHandlerProc: NimNode, msgId = Opt.none(uint)) = proc augmentUserHandler(p: P2PProtocol, userHandlerProc: NimNode, msgId = Opt.none(uint64)) =
## This procs adds a set of common helpers available in all messages handlers ## This procs adds a set of common helpers available in all messages handlers
## (e.g. `perProtocolMsgId`, `peer.state`, etc). ## (e.g. `perProtocolMsgId`, `peer.state`, etc).
@ -446,7 +445,7 @@ proc ResponderType(msg: Message): NimNode =
proc needsSingleParamInlining(msg: Message): bool = proc needsSingleParamInlining(msg: Message): bool =
msg.recBody.kind == nnkDistinctTy msg.recBody.kind == nnkDistinctTy
proc newMsg(protocol: P2PProtocol, kind: MessageKind, msgId: uint, proc newMsg(protocol: P2PProtocol, kind: MessageKind, msgId: uint64,
procDef: NimNode, response: Message = nil): Message = procDef: NimNode, response: Message = nil): Message =
if procDef[0].kind == nnkPostfix: if procDef[0].kind == nnkPostfix:
@ -528,7 +527,7 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, msgId: uint,
proc isVoid(t: NimNode): bool = proc isVoid(t: NimNode): bool =
t.kind == nnkEmpty or eqIdent(t, "void") t.kind == nnkEmpty or eqIdent(t, "void")
proc addMsg(p: P2PProtocol, msgId: uint, procDef: NimNode) = proc addMsg(p: P2PProtocol, msgId: uint64, procDef: NimNode) =
var var
returnType = procDef.params[0] returnType = procDef.params[0]
hasReturnValue = not isVoid(returnType) hasReturnValue = not isVoid(returnType)
@ -544,7 +543,7 @@ proc addMsg(p: P2PProtocol, msgId: uint, procDef: NimNode) =
let let
responseIdent = ident($procDef.name & "Response") responseIdent = ident($procDef.name & "Response")
response = Message(protocol: p, response = Message(protocol: p,
id: Opt.none(uint), id: Opt.none(uint64),
ident: responseIdent, ident: responseIdent,
kind: msgResponse, kind: msgResponse,
recName: returnType, recName: returnType,
@ -871,7 +870,7 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) =
## ##
## All messages will have properly computed numeric IDs ## All messages will have properly computed numeric IDs
## ##
var nextId = 0u var nextId = 0u64
for n in protocolBody: for n in protocolBody:
case n.kind case n.kind
@ -880,7 +879,7 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) =
# By default message IDs are assigned in increasing order # By default message IDs are assigned in increasing order
# `nextID` can be used to skip some of the numeric slots # `nextID` can be used to skip some of the numeric slots
if n.len == 2 and n[1].kind == nnkIntLit: if n.len == 2 and n[1].kind == nnkIntLit:
nextId = n[1].intVal.uint nextId = n[1].intVal.uint64
else: else:
error("nextID expects a single int value", n) error("nextID expects a single int value", n)
@ -895,10 +894,10 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) =
error "requestResponse expects a block with at least two proc definitions" error "requestResponse expects a block with at least two proc definitions"
var queries = newSeq[Message]() var queries = newSeq[Message]()
let responseMsg = p.newMsg(msgResponse, nextId + procs.len.uint - 1, procs[^1]) let responseMsg = p.newMsg(msgResponse, nextId + procs.len.uint64 - 1, procs[^1])
for i in 0 .. procs.len - 2: for i in 0 .. procs.len - 2:
queries.add p.newMsg(msgRequest, nextId + i.uint, procs[i], response = responseMsg) queries.add p.newMsg(msgRequest, nextId + i.uint64, procs[i], response = responseMsg)
p.requests.add Request(queries: queries, response: responseMsg) p.requests.add Request(queries: queries, response: responseMsg)
@ -991,7 +990,7 @@ proc genTypeSection*(p: P2PProtocol): NimNode =
if p.isRlpx: if p.isRlpx:
result.add quote do: result.add quote do:
template msgId*(`MSG`: type `msgStrongRecName`): uint = `msgId` template msgId*(`MSG`: type `msgStrongRecName`): uint64 = `msgId`
proc genCode*(p: P2PProtocol): NimNode = proc genCode*(p: P2PProtocol): NimNode =
for msg in p.messages: for msg in p.messages:
@ -1027,7 +1026,7 @@ proc genCode*(p: P2PProtocol): NimNode =
macro emitForSingleBackend( macro emitForSingleBackend(
name: static[string], name: static[string],
version: static[int], version: static[uint64],
backend: static[BackendFactory], backend: static[BackendFactory],
body: untyped, body: untyped,
# TODO Nim can't handle a proper duration parameter here # TODO Nim can't handle a proper duration parameter here

View File

@ -40,7 +40,7 @@ type
protocolStates*: seq[RootRef] protocolStates*: seq[RootRef]
discovery*: DiscoveryProtocol discovery*: DiscoveryProtocol
when useSnappy: when useSnappy:
protocolVersion*: uint protocolVersion*: uint64
rng*: ref HmacDrbgContext rng*: ref HmacDrbgContext
Peer* = ref object Peer* = ref object
@ -50,7 +50,7 @@ type
# Private fields: # Private fields:
transport*: StreamTransport transport*: StreamTransport
dispatcher*: Dispatcher dispatcher*: Dispatcher
lastReqId*: Opt[uint] lastReqId*: Opt[uint64]
secretsState*: SecretState secretsState*: SecretState
connectionState*: ConnectionState connectionState*: ConnectionState
protocolStates*: seq[RootRef] protocolStates*: seq[RootRef]
@ -86,7 +86,7 @@ type
Capability* = object Capability* = object
name*: string name*: string
version*: int version*: uint64
EthP2PError* = object of CatchableError EthP2PError* = object of CatchableError
@ -112,7 +112,7 @@ type
ProtocolInfo* = ref object ProtocolInfo* = ref object
name*: string name*: string
version*: int version*: uint64
messages*: seq[MessageInfo] messages*: seq[MessageInfo]
index*: int # the position of the protocol in the index*: int # the position of the protocol in the
# ordered list of supported protocols # ordered list of supported protocols
@ -124,7 +124,7 @@ type
disconnectHandler*: DisconnectionHandler disconnectHandler*: DisconnectionHandler
MessageInfo* = ref object MessageInfo* = ref object
id*: uint # this is a `msgId` (as opposed to a `reqId`) id*: uint64 # this is a `msgId` (as opposed to a `reqId`)
name*: string name*: string
# Private fields: # Private fields:
@ -142,11 +142,11 @@ type
# protocol. If the other peer also supports the protocol, the stored # protocol. If the other peer also supports the protocol, the stored
# offset indicates the numeric value of the first message of the protocol # offset indicates the numeric value of the first message of the protocol
# (for this particular connection). If the other peer doesn't support the # (for this particular connection). If the other peer doesn't support the
# particular protocol, the stored offset is `Opt.none(uint)`. # particular protocol, the stored offset is `Opt.none(uint64)`.
# #
# `messages` holds a mapping from valid message IDs to their handler procs. # `messages` holds a mapping from valid message IDs to their handler procs.
# #
protocolOffsets*: seq[Opt[uint]] protocolOffsets*: seq[Opt[uint64]]
messages*: seq[MessageInfo] # per `msgId` table (se above) messages*: seq[MessageInfo] # per `msgId` table (se above)
activeProtocols*: seq[ProtocolInfo] activeProtocols*: seq[ProtocolInfo]
@ -155,14 +155,14 @@ type
## ##
OutstandingRequest* = object OutstandingRequest* = object
id*: uint # a `reqId` that may be used for response id*: uint64 # a `reqId` that may be used for response
future*: FutureBase future*: FutureBase
timeoutAt*: Moment timeoutAt*: Moment
# Private types: # Private types:
MessageHandlerDecorator* = proc(msgId: uint, n: NimNode): NimNode MessageHandlerDecorator* = proc(msgId: uint64, n: NimNode): NimNode
ThunkProc* = proc(x: Peer, msgId: uint, data: Rlp): Future[void] ThunkProc* = proc(x: Peer, msgId: uint64, data: Rlp): Future[void]
{.gcsafe, async: (raises: [RlpError, EthP2PError]).} {.gcsafe, async: (raises: [RlpError, EthP2PError]).}
MessageContentPrinter* = proc(msg: pointer): string MessageContentPrinter* = proc(msg: pointer): string

View File

@ -64,7 +64,7 @@ logScope:
type type
ResponderWithId*[MsgType] = object ResponderWithId*[MsgType] = object
peer*: Peer peer*: Peer
reqId*: uint reqId*: uint64
ResponderWithoutId*[MsgType] = distinct Peer ResponderWithoutId*[MsgType] = distinct Peer
@ -126,14 +126,14 @@ when tracingEnabled:
init, writeValue, getOutput init, writeValue, getOutput
proc init*[MsgName](T: type ResponderWithId[MsgName], proc init*[MsgName](T: type ResponderWithId[MsgName],
peer: Peer, reqId: uint): T = peer: Peer, reqId: uint64): T =
T(peer: peer, reqId: reqId) T(peer: peer, reqId: reqId)
proc init*[MsgName](T: type ResponderWithoutId[MsgName], peer: Peer): T = proc init*[MsgName](T: type ResponderWithoutId[MsgName], peer: Peer): T =
T(peer) T(peer)
chronicles.formatIt(Peer): $(it.remote) chronicles.formatIt(Peer): $(it.remote)
chronicles.formatIt(Opt[uint]): (if it.isSome(): $it.value else: "-1") chronicles.formatIt(Opt[uint64]): (if it.isSome(): $it.value else: "-1")
include p2p_backends_helpers include p2p_backends_helpers
@ -247,9 +247,9 @@ proc getDispatcher(node: EthereumNode,
new result new result
newSeq(result.protocolOffsets, protocolCount()) newSeq(result.protocolOffsets, protocolCount())
result.protocolOffsets.fill Opt.none(uint) result.protocolOffsets.fill Opt.none(uint64)
var nextUserMsgId = 0x10u var nextUserMsgId = 0x10u64
for localProtocol in node.protocols: for localProtocol in node.protocols:
let idx = localProtocol.index let idx = localProtocol.index
@ -258,7 +258,7 @@ proc getDispatcher(node: EthereumNode,
if localProtocol.name == remoteCapability.name and if localProtocol.name == remoteCapability.name and
localProtocol.version == remoteCapability.version: localProtocol.version == remoteCapability.version:
result.protocolOffsets[idx] = Opt.some(nextUserMsgId) result.protocolOffsets[idx] = Opt.some(nextUserMsgId)
nextUserMsgId += localProtocol.messages.len.uint nextUserMsgId += localProtocol.messages.len.uint64
break findMatchingProtocol break findMatchingProtocol
template copyTo(src, dest; index: int) = template copyTo(src, dest; index: int) =
@ -275,9 +275,9 @@ proc getDispatcher(node: EthereumNode,
localProtocol.messages.copyTo(result.messages, localProtocol.messages.copyTo(result.messages,
result.protocolOffsets[idx].value.int) result.protocolOffsets[idx].value.int)
proc getMsgName*(peer: Peer, msgId: uint): string = proc getMsgName*(peer: Peer, msgId: uint64): string =
if not peer.dispatcher.isNil and if not peer.dispatcher.isNil and
msgId < peer.dispatcher.messages.len.uint and msgId < peer.dispatcher.messages.len.uint64 and
not peer.dispatcher.messages[msgId].isNil: not peer.dispatcher.messages[msgId].isNil:
return peer.dispatcher.messages[msgId].name return peer.dispatcher.messages[msgId].name
else: else:
@ -288,14 +288,14 @@ proc getMsgName*(peer: Peer, msgId: uint): string =
of 3: "pong" of 3: "pong"
else: $msgId else: $msgId
proc getMsgMetadata*(peer: Peer, msgId: uint): (ProtocolInfo, MessageInfo) = proc getMsgMetadata*(peer: Peer, msgId: uint64): (ProtocolInfo, MessageInfo) =
doAssert msgId >= 0 doAssert msgId >= 0
let dpInfo = devp2pInfo() let dpInfo = devp2pInfo()
if msgId <= dpInfo.messages[^1].id: if msgId <= dpInfo.messages[^1].id:
return (dpInfo, dpInfo.messages[msgId]) return (dpInfo, dpInfo.messages[msgId])
if msgId < peer.dispatcher.messages.len.uint: if msgId < peer.dispatcher.messages.len.uint64:
let numProtocol = protocolCount() let numProtocol = protocolCount()
for i in 0 ..< numProtocol: for i in 0 ..< numProtocol:
let protocol = getProtocol(i) let protocol = getProtocol(i)
@ -307,7 +307,7 @@ proc getMsgMetadata*(peer: Peer, msgId: uint): (ProtocolInfo, MessageInfo) =
# Protocol info objects # Protocol info objects
# #
proc initProtocol(name: string, version: int, proc initProtocol(name: string, version: uint64,
peerInit: PeerStateInitializer, peerInit: PeerStateInitializer,
networkInit: NetworkStateInitializer): ProtocolInfo = networkInit: NetworkStateInitializer): ProtocolInfo =
ProtocolInfo( ProtocolInfo(
@ -338,13 +338,13 @@ proc nextMsgResolver[MsgType](msgData: Rlp, future: FutureBase)
MsgType.rlpFieldsCount > 1) MsgType.rlpFieldsCount > 1)
proc registerMsg(protocol: ProtocolInfo, proc registerMsg(protocol: ProtocolInfo,
msgId: uint, msgId: uint64,
name: string, name: string,
thunk: ThunkProc, thunk: ThunkProc,
printer: MessageContentPrinter, printer: MessageContentPrinter,
requestResolver: RequestResolver, requestResolver: RequestResolver,
nextMsgResolver: NextMsgResolver) = nextMsgResolver: NextMsgResolver) =
if protocol.messages.len.uint <= msgId: if protocol.messages.len.uint64 <= msgId:
protocol.messages.setLen(msgId + 1) protocol.messages.setLen(msgId + 1)
protocol.messages[msgId] = MessageInfo( protocol.messages[msgId] = MessageInfo(
id: msgId, id: msgId,
@ -357,7 +357,7 @@ proc registerMsg(protocol: ProtocolInfo,
# Message composition and encryption # Message composition and encryption
# #
proc perPeerMsgIdImpl(peer: Peer, proto: ProtocolInfo, msgId: uint): uint = proc perPeerMsgIdImpl(peer: Peer, proto: ProtocolInfo, msgId: uint64): uint64 =
result = msgId result = msgId
if not peer.dispatcher.isNil: if not peer.dispatcher.isNil:
result += peer.dispatcher.protocolOffsets[proto.index].value result += peer.dispatcher.protocolOffsets[proto.index].value
@ -373,10 +373,10 @@ proc supports*(peer: Peer, Protocol: type): bool =
## Checks whether a Peer supports a particular protocol ## Checks whether a Peer supports a particular protocol
peer.supports(Protocol.protocolInfo) peer.supports(Protocol.protocolInfo)
template perPeerMsgId(peer: Peer, MsgType: type): uint = template perPeerMsgId(peer: Peer, MsgType: type): uint64 =
perPeerMsgIdImpl(peer, MsgType.msgProtocol.protocolInfo, MsgType.msgId) perPeerMsgIdImpl(peer, MsgType.msgProtocol.protocolInfo, MsgType.msgId)
proc invokeThunk*(peer: Peer, msgId: uint, msgData: Rlp): Future[void] proc invokeThunk*(peer: Peer, msgId: uint64, msgData: Rlp): Future[void]
{.async: (raises: [rlp.RlpError, EthP2PError]).} = {.async: (raises: [rlp.RlpError, EthP2PError]).} =
template invalidIdError: untyped = template invalidIdError: untyped =
raise newException(UnsupportedMessageError, raise newException(UnsupportedMessageError,
@ -384,7 +384,7 @@ proc invokeThunk*(peer: Peer, msgId: uint, msgData: Rlp): Future[void]
" on a connection supporting " & peer.dispatcher.describeProtocols) " on a connection supporting " & peer.dispatcher.describeProtocols)
# msgId can be negative as it has int as type and gets decoded from rlp # msgId can be negative as it has int as type and gets decoded from rlp
if msgId >= peer.dispatcher.messages.len.uint: invalidIdError() if msgId >= peer.dispatcher.messages.len.uint64: invalidIdError()
if peer.dispatcher.messages[msgId].isNil: invalidIdError() if peer.dispatcher.messages[msgId].isNil: invalidIdError()
let thunk = peer.dispatcher.messages[msgId].thunk let thunk = peer.dispatcher.messages[msgId].thunk
@ -423,8 +423,8 @@ proc send*[Msg](peer: Peer, msg: Msg): Future[void] =
proc registerRequest(peer: Peer, proc registerRequest(peer: Peer,
timeout: Duration, timeout: Duration,
responseFuture: FutureBase, responseFuture: FutureBase,
responseMsgId: uint): uint = responseMsgId: uint64): uint64 =
result = if peer.lastReqId.isNone: 0u else: peer.lastReqId.value + 1u result = if peer.lastReqId.isNone: 0u64 else: peer.lastReqId.value + 1u64
peer.lastReqId = Opt.some(result) peer.lastReqId = Opt.some(result)
let timeoutAt = Moment.fromNow(timeout) let timeoutAt = Moment.fromNow(timeout)
@ -440,7 +440,7 @@ proc registerRequest(peer: Peer,
discard setTimer(timeoutAt, timeoutExpired, nil) discard setTimer(timeoutAt, timeoutExpired, nil)
proc resolveResponseFuture(peer: Peer, msgId: uint, msg: pointer) = proc resolveResponseFuture(peer: Peer, msgId: uint64, msg: pointer) =
## This function is a split off from the previously combined version with ## This function is a split off from the previously combined version with
## the same name using optional request ID arguments. This here is the ## the same name using optional request ID arguments. This here is the
## version without a request ID (there is the other part below.). ## version without a request ID (there is the other part below.).
@ -485,7 +485,7 @@ proc resolveResponseFuture(peer: Peer, msgId: uint, msg: pointer) =
else: else:
trace "late or dup RPLx reply ignored", msgId trace "late or dup RPLx reply ignored", msgId
proc resolveResponseFuture(peer: Peer, msgId: uint, msg: pointer, reqId: uint) = proc resolveResponseFuture(peer: Peer, msgId: uint64, msg: pointer, reqId: uint64) =
## Variant of `resolveResponseFuture()` for request ID argument. ## Variant of `resolveResponseFuture()` for request ID argument.
logScope: logScope:
msg = peer.dispatcher.messages[msgId].name msg = peer.dispatcher.messages[msgId].name
@ -544,7 +544,7 @@ proc resolveResponseFuture(peer: Peer, msgId: uint, msg: pointer, reqId: uint) =
trace "late or dup RPLx reply ignored" trace "late or dup RPLx reply ignored"
proc recvMsg*(peer: Peer): Future[tuple[msgId: uint, msgData: Rlp]] {.async.} = proc recvMsg*(peer: Peer): Future[tuple[msgId: uint64, msgData: Rlp]] {.async.} =
## This procs awaits the next complete RLPx message in the TCP stream ## This procs awaits the next complete RLPx message in the TCP stream
var headerBytes: array[32, byte] var headerBytes: array[32, byte]
@ -610,7 +610,7 @@ proc recvMsg*(peer: Peer): Future[tuple[msgId: uint, msgData: Rlp]] {.async.} =
try: try:
# uint32 as this seems more than big enough for the amount of msgIds # uint32 as this seems more than big enough for the amount of msgIds
msgId = rlp.read(uint32) msgId = rlp.read(uint32)
result = (msgId.uint, rlp) result = (msgId.uint64, rlp)
except RlpError: except RlpError:
await peer.disconnectAndRaise(BreachOfProtocol, await peer.disconnectAndRaise(BreachOfProtocol,
"Cannot read RLPx message id") "Cannot read RLPx message id")
@ -680,7 +680,7 @@ proc nextMsg*(peer: Peer, MsgType: type): Future[MsgType] =
# message handler code as the TODO mentions already. # message handler code as the TODO mentions already.
proc dispatchMessages*(peer: Peer) {.async.} = proc dispatchMessages*(peer: Peer) {.async.} =
while peer.connectionState notin {Disconnecting, Disconnected}: while peer.connectionState notin {Disconnecting, Disconnected}:
var msgId: uint var msgId: uint64
var msgData: Rlp var msgData: Rlp
try: try:
(msgId, msgData) = await peer.recvMsg() (msgId, msgData) = await peer.recvMsg()
@ -721,7 +721,7 @@ proc dispatchMessages*(peer: Peer) {.async.} =
# The documentation will need to be updated, explaining the fact that # The documentation will need to be updated, explaining the fact that
# nextMsg will be resolved only if the message handler has executed # nextMsg will be resolved only if the message handler has executed
# successfully. # successfully.
if msgId < peer.awaitedMessages.len.uint and if msgId < peer.awaitedMessages.len.uint64 and
peer.awaitedMessages[msgId] != nil: peer.awaitedMessages[msgId] != nil:
let msgInfo = peer.dispatcher.messages[msgId] let msgInfo = peer.dispatcher.messages[msgId]
try: try:
@ -791,7 +791,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
msgIdent = msg.ident msgIdent = msg.ident
msgName = $msgIdent msgName = $msgIdent
msgRecName = msg.recName msgRecName = msg.recName
responseMsgId = if msg.response.isNil: Opt.none(uint) else: msg.response.id responseMsgId = if msg.response.isNil: Opt.none(uint64) else: msg.response.id
hasReqId = msg.hasReqId hasReqId = msg.hasReqId
protocol = msg.protocol protocol = msg.protocol
@ -812,7 +812,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
if hasReqId: if hasReqId:
# Messages using request Ids # Messages using request Ids
readParams.add quote do: readParams.add quote do:
let `reqIdVar` = `read`(`receivedRlp`, uint) let `reqIdVar` = `read`(`receivedRlp`, uint64)
case msg.kind case msg.kind
of msgRequest: of msgRequest:
@ -887,7 +887,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
thunkName = ident(msgName & "Thunk") thunkName = ident(msgName & "Thunk")
msg.defineThunk quote do: msg.defineThunk quote do:
proc `thunkName`(`peerVar`: `Peer`, _: uint, data: Rlp) proc `thunkName`(`peerVar`: `Peer`, _: uint64, data: Rlp)
# Fun error if you just use `RlpError` instead of `rlp.RlpError`: # Fun error if you just use `RlpError` instead of `rlp.RlpError`:
# "Error: type expected, but got symbol 'RlpError' of kind 'EnumField'" # "Error: type expected, but got symbol 'RlpError' of kind 'EnumField'"
{.async: (raises: [rlp.RlpError, EthP2PError]).} = {.async: (raises: [rlp.RlpError, EthP2PError]).} =
@ -973,7 +973,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend =
p2pProtocol DevP2P(version = 5, rlpxName = "p2p"): p2pProtocol DevP2P(version = 5, rlpxName = "p2p"):
proc hello(peer: Peer, proc hello(peer: Peer,
version: uint, version: uint64,
clientId: string, clientId: string,
capabilities: seq[Capability], capabilities: seq[Capability],
listenPort: uint, listenPort: uint,
@ -1082,7 +1082,7 @@ proc initPeerState*(peer: Peer, capabilities: openArray[Capability])
# Similarly, we need a bit of book-keeping data to keep track # Similarly, we need a bit of book-keeping data to keep track
# of the potentially concurrent calls to `nextMsg`. # of the potentially concurrent calls to `nextMsg`.
peer.awaitedMessages.newSeq(peer.dispatcher.messages.len) peer.awaitedMessages.newSeq(peer.dispatcher.messages.len)
peer.lastReqId = Opt.some(0u) peer.lastReqId = Opt.some(0u64)
peer.initProtocolStates peer.dispatcher.activeProtocols peer.initProtocolStates peer.dispatcher.activeProtocols
proc postHelloSteps(peer: Peer, h: DevP2P.hello) {.async.} = proc postHelloSteps(peer: Peer, h: DevP2P.hello) {.async.} =
@ -1145,10 +1145,10 @@ proc initSecretState(p: Peer, hs: Handshake, authMsg, ackMsg: openArray[byte]) =
template setSnappySupport(peer: Peer, node: EthereumNode, handshake: Handshake) = template setSnappySupport(peer: Peer, node: EthereumNode, handshake: Handshake) =
when useSnappy: when useSnappy:
peer.snappyEnabled = node.protocolVersion >= devp2pSnappyVersion.uint and peer.snappyEnabled = node.protocolVersion >= devp2pSnappyVersion.uint64 and
handshake.version >= devp2pSnappyVersion.uint handshake.version >= devp2pSnappyVersion.uint64
template getVersion(handshake: Handshake): uint = template getVersion(handshake: Handshake): uint64 =
when useSnappy: when useSnappy:
handshake.version handshake.version
else: else:
@ -1160,7 +1160,7 @@ template baseProtocolVersion(node: EthereumNode): untyped =
else: else:
devp2pVersion devp2pVersion
template baseProtocolVersion(peer: Peer): uint = template baseProtocolVersion(peer: Peer): uint64 =
when useSnappy: when useSnappy:
if peer.snappyEnabled: devp2pSnappyVersion if peer.snappyEnabled: devp2pSnappyVersion
else: devp2pVersion else: devp2pVersion
@ -1473,10 +1473,10 @@ when isMainModule:
# are considered GcSafe. The short answer is that they aren't, because # are considered GcSafe. The short answer is that they aren't, because
# they dispatch into user code that might use the GC. # they dispatch into user code that might use the GC.
type type
GcSafeDispatchMsg = proc (peer: Peer, msgId: uint, msgData: var Rlp) GcSafeDispatchMsg = proc (peer: Peer, msgId: uint64, msgData: var Rlp)
GcSafeRecvMsg = proc (peer: Peer): GcSafeRecvMsg = proc (peer: Peer):
Future[tuple[msgId: uint, msgData: Rlp]] {.gcsafe.} Future[tuple[msgId: uint64, msgData: Rlp]] {.gcsafe.}
GcSafeAccept = proc (transport: StreamTransport, myKeys: KeyPair): GcSafeAccept = proc (transport: StreamTransport, myKeys: KeyPair):
Future[Peer] {.gcsafe.} Future[Peer] {.gcsafe.}

View File

@ -502,10 +502,7 @@ func validate*(self: Rlp) =
# score in order to facilitate easier overloading with user types: # score in order to facilitate easier overloading with user types:
template read*(rlp: var Rlp, T: type): auto = template read*(rlp: var Rlp, T: type): auto =
when T is SomeSignedInt: when T is SomeSignedInt:
let value = readImpl(rlp, uint64) {.error "Signed integer encoding is not defined for rlp".}
if value > uint64(T.high()):
raiseIntOutOfBounds()
T value
else: else:
readImpl(rlp, T) readImpl(rlp, T)

View File

@ -301,15 +301,15 @@ proc appendImpl(self: var RlpWriter, data: tuple) {.inline.} =
# We define a single `append` template with a pretty low specificity # We define a single `append` template with a pretty low specificity
# score in order to facilitate easier overloading with user types: # score in order to facilitate easier overloading with user types:
template append*[T](w: var RlpWriter; data: T) = template append*[T](w: var RlpWriter; data: T) =
when data is (SomeSignedInt|enum|bool): when data is (enum|bool):
when data is SomeSignedInt: # TODO detect negative enum values at compile time?
# TODO potentially remove signed integer support - we should never make it
# this far!
{.warning: "Signed integers cannot reliably be encoded using RLP".}
appendImpl(w, uint64(data)) appendImpl(w, uint64(data))
else: else:
appendImpl(w, data) appendImpl(w, data)
template append*(w: var RlpWriter; data: SomeSignedInt) =
{.error: "Signed integer encoding is not defined for rlp".}
proc initRlpList*(listSize: int): RlpWriter = proc initRlpList*(listSize: int): RlpWriter =
result = initRlpWriter() result = initRlpWriter()
startList(result, listSize) startList(result, listSize)

View File

@ -20,7 +20,7 @@ proc generate() =
# valid data for a Ping packet # valid data for a Ping packet
block: block:
let payload = rlp.encode((4, fromAddr, toAddr, expiration())) let payload = rlp.encode((uint64 4, fromAddr, toAddr, expiration()))
let encodedData = @[1.byte] & payload let encodedData = @[1.byte] & payload
debug "Ping", data=byteutils.toHex(encodedData) debug "Ping", data=byteutils.toHex(encodedData)

View File

@ -23,9 +23,8 @@ test:
testDecode(payload, uint16) testDecode(payload, uint16)
testDecode(payload, uint32) testDecode(payload, uint32)
testDecode(payload, uint64) testDecode(payload, uint64)
testDecode(payload, int)
testDecode(payload, bool) testDecode(payload, bool)
testDecode(payload, seq[byte]) testDecode(payload, seq[byte])
testDecode(payload, (string, int32)) testDecode(payload, (string, uint32))
testDecode(payload, TestEnum) testDecode(payload, TestEnum)
testDecode(payload, TestObject) testDecode(payload, TestObject)

View File

@ -64,16 +64,24 @@ suite "test api usage":
MyObj = object MyObj = object
a: array[3, char] a: array[3, char]
b: int b: uint64
c: MyEnum c: MyEnum
IntObj = object
v: int
var input: MyObj var input: MyObj
input.a = ['e', 't', 'h'] input.a = ['e', 't', 'h']
input.b = 63 input.b = 63
input.c = bar input.c = bar
var writer = initRlpWriter() var writer = initRlpWriter()
writer.append(input) writer.append(input)
check:
not compiles(writer.append(default(IntObj)))
let bytes = writer.finish() let bytes = writer.finish()
var rlp = rlpFromBytes(bytes) var rlp = rlpFromBytes(bytes)
@ -85,7 +93,7 @@ suite "test api usage":
var writer = initRlpList(3) var writer = initRlpList(3)
writer.append "foo" writer.append "foo"
writer.append ["bar", "baz"] writer.append ["bar", "baz"]
writer.append [30, 40, 50] writer.append [uint64 30, 40, 50]
var var
bytes = writer.finish bytes = writer.finish
@ -108,14 +116,14 @@ suite "test api usage":
} }
""" """
bytes = encodeList(6000, bytes = encodeList(uint64 6000,
"Lorem ipsum dolor sit amet", "Lorem ipsum dolor sit amet",
"Donec ligula tortor, egestas eu est vitae") "Donec ligula tortor, egestas eu est vitae")
rlp = rlpFromBytes bytes rlp = rlpFromBytes bytes
check: check:
rlp.listLen == 3 rlp.listLen == 3
rlp.listElem(0).toInt(int) == 6000 rlp.listElem(0).toInt(uint64) == 6000
rlp.listElem(1).toString == "Lorem ipsum dolor sit amet" rlp.listElem(1).toString == "Lorem ipsum dolor sit amet"
rlp.listElem(2).toString == "Donec ligula tortor, egestas eu est vitae" rlp.listElem(2).toString == "Donec ligula tortor, egestas eu est vitae"
@ -127,8 +135,8 @@ suite "test api usage":
check list.toString == "Lorem ipsum dolor sit amet" check list.toString == "Lorem ipsum dolor sit amet"
list.skipElem list.skipElem
check list.toInt(int32) == 6000.int32 check list.toInt(uint32) == 6000.uint32
var intVar: int var intVar: uint32
list >> intVar list >> intVar
check intVar == 6000 check intVar == 6000
@ -146,19 +154,19 @@ suite "test api usage":
tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4" tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4"
test "nested lists": test "nested lists":
let listBytes = encode([[1, 2, 3], [5, 6, 7]]) let listBytes = encode([[uint64 1, 2, 3], [uint64 5, 6, 7]])
let listRlp = rlpFromBytes listBytes let listRlp = rlpFromBytes listBytes
let sublistRlp0 = listRlp.listElem(0) let sublistRlp0 = listRlp.listElem(0)
let sublistRlp1 = listRlp.listElem(1) let sublistRlp1 = listRlp.listElem(1)
check sublistRlp0.listElem(0).toInt(int) == 1 check sublistRlp0.listElem(0).toInt(uint64) == 1
check sublistRlp0.listElem(1).toInt(int) == 2 check sublistRlp0.listElem(1).toInt(uint64) == 2
check sublistRlp0.listElem(2).toInt(int) == 3 check sublistRlp0.listElem(2).toInt(uint64) == 3
check sublistRlp1.listElem(0).toInt(int) == 5 check sublistRlp1.listElem(0).toInt(uint64) == 5
check sublistRlp1.listElem(1).toInt(int) == 6 check sublistRlp1.listElem(1).toInt(uint64) == 6
check sublistRlp1.listElem(2).toInt(int) == 7 check sublistRlp1.listElem(2).toInt(uint64) == 7
test "encoding length": test "encoding length":
let listBytes = encode([1,2,3,4,5]) let listBytes = encode([uint64 1,2,3,4,5])
let listRlp = rlpFromBytes listBytes let listRlp = rlpFromBytes listBytes
check listRlp.listLen == 5 check listRlp.listLen == 5
@ -208,8 +216,8 @@ suite "test api usage":
bar = 0x01 bar = 0x01
var writer = initRlpWriter() var writer = initRlpWriter()
writer.append(1) # valid writer.append(byte 1) # valid
writer.append(2) # invalid writer.append(byte 2) # invalid
writer.append(cast[uint64](-1)) # invalid writer.append(cast[uint64](-1)) # invalid
let bytes = writer.finish() let bytes = writer.finish()
var rlp = rlpFromBytes(bytes) var rlp = rlpFromBytes(bytes)
@ -231,10 +239,10 @@ suite "test api usage":
baz = 0x0100 baz = 0x0100
var writer = initRlpWriter() var writer = initRlpWriter()
writer.append(1) # valid writer.append(1'u64) # valid
writer.append(2) # invalid - enum hole value writer.append(2'u64) # invalid - enum hole value
writer.append(256) # valid writer.append(256'u64) # valid
writer.append(257) # invalid - too large writer.append(257'u64) # invalid - too large
let bytes = writer.finish() let bytes = writer.finish()
var rlp = rlpFromBytes(bytes) var rlp = rlpFromBytes(bytes)

View File

@ -9,7 +9,7 @@ type
HelloObj = object HelloObj = object
version*: uint version*: uint
clientId*: string clientId*: string
capabilities*: seq[(string,int)] capabilities*: seq[(string,uint)]
listenPort*: uint listenPort*: uint
nodeId*: array[64, byte] nodeId*: array[64, byte]

View File

@ -8,15 +8,15 @@ import
type type
Transaction = object Transaction = object
amount: int amount: uint64
time: Time time: uint64
sender: string sender: string
receiver: string receiver: string
Foo = object Foo = object
x: uint64 x: uint64
y: string y: string
z: seq[int] z: seq[uint64]
Bar = object Bar = object
b: string b: string
@ -24,7 +24,7 @@ type
CustomSerialized = object CustomSerialized = object
customFoo {.rlpCustomSerialization.}: Foo customFoo {.rlpCustomSerialization.}: Foo
ignored {.rlpIgnore.}: int ignored {.rlpIgnore.}: uint64
rlpFields Foo, rlpFields Foo,
x, y, z x, y, z
@ -34,19 +34,19 @@ rlpFields Transaction,
proc append*(rlpWriter: var RlpWriter, holder: CustomSerialized, f: Foo) = proc append*(rlpWriter: var RlpWriter, holder: CustomSerialized, f: Foo) =
rlpWriter.append(f.x) rlpWriter.append(f.x)
rlpWriter.append(f.y.len) rlpWriter.append(uint64 f.y.len)
rlpWriter.append(holder.ignored) rlpWriter.append(holder.ignored)
proc read*(rlp: var Rlp, holder: var CustomSerialized, T: type Foo): Foo = proc read*(rlp: var Rlp, holder: var CustomSerialized, T: type Foo): Foo =
result.x = rlp.read(uint64) result.x = rlp.read(uint64)
result.y = newString(rlp.read(int)) result.y = newString(rlp.read(uint64))
holder.ignored = rlp.read(int) * 2 holder.ignored = rlp.read(uint64) * 2
proc suite() = proc suite() =
suite "object serialization": suite "object serialization":
test "encoding and decoding an object": test "encoding and decoding an object":
var originalBar = Bar(b: "abracadabra", var originalBar = Bar(b: "abracadabra",
f: Foo(x: 5'u64, y: "hocus pocus", z: @[100, 200, 300])) f: Foo(x: 5'u64, y: "hocus pocus", z: @[uint64 100, 200, 300]))
var bytes = encode(originalBar) var bytes = encode(originalBar)
var r = rlpFromBytes(bytes) var r = rlpFromBytes(bytes)
@ -55,13 +55,13 @@ proc suite() =
check: check:
originalBar == restoredBar originalBar == restoredBar
var t1 = Transaction(time: getTime(), amount: 1000, sender: "Alice", receiver: "Bob") var t1 = Transaction(time: 100, amount: 1000, sender: "Alice", receiver: "Bob")
bytes = encode(t1) bytes = encode(t1)
var t2 = bytes.decode(Transaction) var t2 = bytes.decode(Transaction)
check: check:
bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first
t2.time == default(Time) t2.time == 0
t2.sender == "Alice" t2.sender == "Alice"
t2.receiver == "Bob" t2.receiver == "Bob"
t2.amount == 1000 t2.amount == 1000

View File

@ -9,9 +9,11 @@ proc append(output: var RlpWriter, js: JsonNode) =
of JNull, JFloat, JObject: of JNull, JFloat, JObject:
raise newException(ValueError, "Unsupported JSON value type " & $js.kind) raise newException(ValueError, "Unsupported JSON value type " & $js.kind)
of JBool: of JBool:
output.append js.bval.int output.append js.bval
of JInt: of JInt:
output.append int(js.num) if js.num < 0:
raise newException(ValueError, "Integer out of range: " & $js.num)
output.append uint64(js.num)
of JString: of JString:
output.append js.str output.append js.str
of JArray: of JArray: