From 119c910a4eb858db5e7d51d7124514704c938967 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Mon, 30 Sep 2024 18:32:36 +0200 Subject: [PATCH] remove remaining `int` holdouts in rlp (#737) these were never well defined --- eth/p2p/p2p_protocol_dsl.nim | 31 ++++++----- eth/p2p/private/p2p_types.nim | 20 +++---- eth/p2p/rlpx.nim | 72 ++++++++++++------------- eth/rlp.nim | 5 +- eth/rlp/writer.nim | 10 ++-- tests/fuzzing/discovery/generate.nim | 2 +- tests/fuzzing/rlp/rlp_decode.nim | 3 +- tests/rlp/test_api_usage.nim | 48 ++++++++++------- tests/rlp/test_empty_string.nim | 2 +- tests/rlp/test_object_serialization.nim | 20 +++---- tests/rlp/util/json_testing.nim | 6 ++- 11 files changed, 112 insertions(+), 107 deletions(-) diff --git a/eth/p2p/p2p_protocol_dsl.nim b/eth/p2p/p2p_protocol_dsl.nim index aae1347..ef3644f 100644 --- a/eth/p2p/p2p_protocol_dsl.nim +++ b/eth/p2p/p2p_protocol_dsl.nim @@ -35,7 +35,7 @@ type msgResponse Message* = ref object - id*: Opt[uint] + id*: Opt[uint64] ident*: NimNode kind*: MessageKind procDef*: NimNode @@ -83,7 +83,7 @@ type P2PProtocol* = ref object # Settings name*: string - version*: int + version*: uint64 timeouts*: int64 useRequestIds*: bool useSingleRecordInlining*: bool @@ -148,8 +148,7 @@ const let # Variable names affecting the public interface of the library: reqIdVar* {.compileTime.} = ident "reqId" - # XXX: Binding the int type causes instantiation failure for some reason - ReqIdType* {.compileTime.} = ident "uint" + ReqIdType* {.compileTime.} = ident "uint64" peerVar* {.compileTime.} = ident "peer" responseVar* {.compileTime.} = ident "response" streamVar* {.compileTime.} = ident "stream" @@ -313,7 +312,7 @@ proc verifyStateType(t: NimNode): NimNode = proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) 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, outgoingRequestDecorator: NimNode, incomingRequestDecorator: NimNode, @@ -345,14 +344,14 @@ proc init*(T: type P2PProtocol, backendFactory: BackendFactory, assert(not result.backend.implementProtocolInit.isNil) if result.backend.ReqIdType.isNil: - result.backend.ReqIdType = ident "uint" + result.backend.ReqIdType = ident "uint64" result.processProtocolBody body if not result.backend.afterProtocolInit.isNil: 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 ## (e.g. `perProtocolMsgId`, `peer.state`, etc). @@ -446,7 +445,7 @@ proc ResponderType(msg: Message): NimNode = proc needsSingleParamInlining(msg: Message): bool = 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 = if procDef[0].kind == nnkPostfix: @@ -528,7 +527,7 @@ proc newMsg(protocol: P2PProtocol, kind: MessageKind, msgId: uint, proc isVoid(t: NimNode): bool = t.kind == nnkEmpty or eqIdent(t, "void") -proc addMsg(p: P2PProtocol, msgId: uint, procDef: NimNode) = +proc addMsg(p: P2PProtocol, msgId: uint64, procDef: NimNode) = var returnType = procDef.params[0] hasReturnValue = not isVoid(returnType) @@ -544,7 +543,7 @@ proc addMsg(p: P2PProtocol, msgId: uint, procDef: NimNode) = let responseIdent = ident($procDef.name & "Response") response = Message(protocol: p, - id: Opt.none(uint), + id: Opt.none(uint64), ident: responseIdent, kind: msgResponse, recName: returnType, @@ -871,7 +870,7 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) = ## ## All messages will have properly computed numeric IDs ## - var nextId = 0u + var nextId = 0u64 for n in protocolBody: case n.kind @@ -880,7 +879,7 @@ proc processProtocolBody*(p: P2PProtocol, protocolBody: NimNode) = # By default message IDs are assigned in increasing order # `nextID` can be used to skip some of the numeric slots if n.len == 2 and n[1].kind == nnkIntLit: - nextId = n[1].intVal.uint + nextId = n[1].intVal.uint64 else: 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" 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: - 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) @@ -991,7 +990,7 @@ proc genTypeSection*(p: P2PProtocol): NimNode = if p.isRlpx: result.add quote do: - template msgId*(`MSG`: type `msgStrongRecName`): uint = `msgId` + template msgId*(`MSG`: type `msgStrongRecName`): uint64 = `msgId` proc genCode*(p: P2PProtocol): NimNode = for msg in p.messages: @@ -1027,7 +1026,7 @@ proc genCode*(p: P2PProtocol): NimNode = macro emitForSingleBackend( name: static[string], - version: static[int], + version: static[uint64], backend: static[BackendFactory], body: untyped, # TODO Nim can't handle a proper duration parameter here diff --git a/eth/p2p/private/p2p_types.nim b/eth/p2p/private/p2p_types.nim index 17f9c33..abf7f58 100644 --- a/eth/p2p/private/p2p_types.nim +++ b/eth/p2p/private/p2p_types.nim @@ -40,7 +40,7 @@ type protocolStates*: seq[RootRef] discovery*: DiscoveryProtocol when useSnappy: - protocolVersion*: uint + protocolVersion*: uint64 rng*: ref HmacDrbgContext Peer* = ref object @@ -50,7 +50,7 @@ type # Private fields: transport*: StreamTransport dispatcher*: Dispatcher - lastReqId*: Opt[uint] + lastReqId*: Opt[uint64] secretsState*: SecretState connectionState*: ConnectionState protocolStates*: seq[RootRef] @@ -86,7 +86,7 @@ type Capability* = object name*: string - version*: int + version*: uint64 EthP2PError* = object of CatchableError @@ -112,7 +112,7 @@ type ProtocolInfo* = ref object name*: string - version*: int + version*: uint64 messages*: seq[MessageInfo] index*: int # the position of the protocol in the # ordered list of supported protocols @@ -124,7 +124,7 @@ type disconnectHandler*: DisconnectionHandler 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 # Private fields: @@ -142,11 +142,11 @@ type # protocol. If the other peer also supports the protocol, the stored # offset indicates the numeric value of the first message of the protocol # (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. # - protocolOffsets*: seq[Opt[uint]] + protocolOffsets*: seq[Opt[uint64]] messages*: seq[MessageInfo] # per `msgId` table (se above) activeProtocols*: seq[ProtocolInfo] @@ -155,14 +155,14 @@ type ## OutstandingRequest* = object - id*: uint # a `reqId` that may be used for response + id*: uint64 # a `reqId` that may be used for response future*: FutureBase timeoutAt*: Moment # 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]).} MessageContentPrinter* = proc(msg: pointer): string diff --git a/eth/p2p/rlpx.nim b/eth/p2p/rlpx.nim index 62390b1..c078169 100644 --- a/eth/p2p/rlpx.nim +++ b/eth/p2p/rlpx.nim @@ -64,7 +64,7 @@ logScope: type ResponderWithId*[MsgType] = object peer*: Peer - reqId*: uint + reqId*: uint64 ResponderWithoutId*[MsgType] = distinct Peer @@ -126,14 +126,14 @@ when tracingEnabled: init, writeValue, getOutput proc init*[MsgName](T: type ResponderWithId[MsgName], - peer: Peer, reqId: uint): T = + peer: Peer, reqId: uint64): T = T(peer: peer, reqId: reqId) proc init*[MsgName](T: type ResponderWithoutId[MsgName], peer: Peer): T = T(peer) 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 @@ -247,9 +247,9 @@ proc getDispatcher(node: EthereumNode, new result 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: let idx = localProtocol.index @@ -258,7 +258,7 @@ proc getDispatcher(node: EthereumNode, if localProtocol.name == remoteCapability.name and localProtocol.version == remoteCapability.version: result.protocolOffsets[idx] = Opt.some(nextUserMsgId) - nextUserMsgId += localProtocol.messages.len.uint + nextUserMsgId += localProtocol.messages.len.uint64 break findMatchingProtocol template copyTo(src, dest; index: int) = @@ -275,9 +275,9 @@ proc getDispatcher(node: EthereumNode, localProtocol.messages.copyTo(result.messages, 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 - msgId < peer.dispatcher.messages.len.uint and + msgId < peer.dispatcher.messages.len.uint64 and not peer.dispatcher.messages[msgId].isNil: return peer.dispatcher.messages[msgId].name else: @@ -288,14 +288,14 @@ proc getMsgName*(peer: Peer, msgId: uint): string = of 3: "pong" else: $msgId -proc getMsgMetadata*(peer: Peer, msgId: uint): (ProtocolInfo, MessageInfo) = +proc getMsgMetadata*(peer: Peer, msgId: uint64): (ProtocolInfo, MessageInfo) = doAssert msgId >= 0 let dpInfo = devp2pInfo() if msgId <= dpInfo.messages[^1].id: return (dpInfo, dpInfo.messages[msgId]) - if msgId < peer.dispatcher.messages.len.uint: + if msgId < peer.dispatcher.messages.len.uint64: let numProtocol = protocolCount() for i in 0 ..< numProtocol: let protocol = getProtocol(i) @@ -307,7 +307,7 @@ proc getMsgMetadata*(peer: Peer, msgId: uint): (ProtocolInfo, MessageInfo) = # Protocol info objects # -proc initProtocol(name: string, version: int, +proc initProtocol(name: string, version: uint64, peerInit: PeerStateInitializer, networkInit: NetworkStateInitializer): ProtocolInfo = ProtocolInfo( @@ -338,13 +338,13 @@ proc nextMsgResolver[MsgType](msgData: Rlp, future: FutureBase) MsgType.rlpFieldsCount > 1) proc registerMsg(protocol: ProtocolInfo, - msgId: uint, + msgId: uint64, name: string, thunk: ThunkProc, printer: MessageContentPrinter, requestResolver: RequestResolver, nextMsgResolver: NextMsgResolver) = - if protocol.messages.len.uint <= msgId: + if protocol.messages.len.uint64 <= msgId: protocol.messages.setLen(msgId + 1) protocol.messages[msgId] = MessageInfo( id: msgId, @@ -357,7 +357,7 @@ proc registerMsg(protocol: ProtocolInfo, # Message composition and encryption # -proc perPeerMsgIdImpl(peer: Peer, proto: ProtocolInfo, msgId: uint): uint = +proc perPeerMsgIdImpl(peer: Peer, proto: ProtocolInfo, msgId: uint64): uint64 = result = msgId if not peer.dispatcher.isNil: 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 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) -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]).} = template invalidIdError: untyped = raise newException(UnsupportedMessageError, @@ -384,7 +384,7 @@ proc invokeThunk*(peer: Peer, msgId: uint, msgData: Rlp): Future[void] " on a connection supporting " & peer.dispatcher.describeProtocols) # 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() let thunk = peer.dispatcher.messages[msgId].thunk @@ -423,8 +423,8 @@ proc send*[Msg](peer: Peer, msg: Msg): Future[void] = proc registerRequest(peer: Peer, timeout: Duration, responseFuture: FutureBase, - responseMsgId: uint): uint = - result = if peer.lastReqId.isNone: 0u else: peer.lastReqId.value + 1u + responseMsgId: uint64): uint64 = + result = if peer.lastReqId.isNone: 0u64 else: peer.lastReqId.value + 1u64 peer.lastReqId = Opt.some(result) let timeoutAt = Moment.fromNow(timeout) @@ -440,7 +440,7 @@ proc registerRequest(peer: Peer, 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 ## the same name using optional request ID arguments. This here is the ## version without a request ID (there is the other part below.). @@ -485,7 +485,7 @@ proc resolveResponseFuture(peer: Peer, msgId: uint, msg: pointer) = else: 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. logScope: 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" -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 var headerBytes: array[32, byte] @@ -610,7 +610,7 @@ proc recvMsg*(peer: Peer): Future[tuple[msgId: uint, msgData: Rlp]] {.async.} = try: # uint32 as this seems more than big enough for the amount of msgIds msgId = rlp.read(uint32) - result = (msgId.uint, rlp) + result = (msgId.uint64, rlp) except RlpError: await peer.disconnectAndRaise(BreachOfProtocol, "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. proc dispatchMessages*(peer: Peer) {.async.} = while peer.connectionState notin {Disconnecting, Disconnected}: - var msgId: uint + var msgId: uint64 var msgData: Rlp try: (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 # nextMsg will be resolved only if the message handler has executed # successfully. - if msgId < peer.awaitedMessages.len.uint and + if msgId < peer.awaitedMessages.len.uint64 and peer.awaitedMessages[msgId] != nil: let msgInfo = peer.dispatcher.messages[msgId] try: @@ -791,7 +791,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend = msgIdent = msg.ident msgName = $msgIdent 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 protocol = msg.protocol @@ -812,7 +812,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend = if hasReqId: # Messages using request Ids readParams.add quote do: - let `reqIdVar` = `read`(`receivedRlp`, uint) + let `reqIdVar` = `read`(`receivedRlp`, uint64) case msg.kind of msgRequest: @@ -887,7 +887,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend = thunkName = ident(msgName & "Thunk") 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`: # "Error: type expected, but got symbol 'RlpError' of kind 'EnumField'" {.async: (raises: [rlp.RlpError, EthP2PError]).} = @@ -973,7 +973,7 @@ proc p2pProtocolBackendImpl*(protocol: P2PProtocol): Backend = p2pProtocol DevP2P(version = 5, rlpxName = "p2p"): proc hello(peer: Peer, - version: uint, + version: uint64, clientId: string, capabilities: seq[Capability], 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 # of the potentially concurrent calls to `nextMsg`. peer.awaitedMessages.newSeq(peer.dispatcher.messages.len) - peer.lastReqId = Opt.some(0u) + peer.lastReqId = Opt.some(0u64) peer.initProtocolStates peer.dispatcher.activeProtocols 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) = when useSnappy: - peer.snappyEnabled = node.protocolVersion >= devp2pSnappyVersion.uint and - handshake.version >= devp2pSnappyVersion.uint + peer.snappyEnabled = node.protocolVersion >= devp2pSnappyVersion.uint64 and + handshake.version >= devp2pSnappyVersion.uint64 -template getVersion(handshake: Handshake): uint = +template getVersion(handshake: Handshake): uint64 = when useSnappy: handshake.version else: @@ -1160,7 +1160,7 @@ template baseProtocolVersion(node: EthereumNode): untyped = else: devp2pVersion -template baseProtocolVersion(peer: Peer): uint = +template baseProtocolVersion(peer: Peer): uint64 = when useSnappy: if peer.snappyEnabled: devp2pSnappyVersion else: devp2pVersion @@ -1473,10 +1473,10 @@ when isMainModule: # are considered GcSafe. The short answer is that they aren't, because # they dispatch into user code that might use the GC. type - GcSafeDispatchMsg = proc (peer: Peer, msgId: uint, msgData: var Rlp) + GcSafeDispatchMsg = proc (peer: Peer, msgId: uint64, msgData: var Rlp) GcSafeRecvMsg = proc (peer: Peer): - Future[tuple[msgId: uint, msgData: Rlp]] {.gcsafe.} + Future[tuple[msgId: uint64, msgData: Rlp]] {.gcsafe.} GcSafeAccept = proc (transport: StreamTransport, myKeys: KeyPair): Future[Peer] {.gcsafe.} diff --git a/eth/rlp.nim b/eth/rlp.nim index a923d5e..f01214f 100644 --- a/eth/rlp.nim +++ b/eth/rlp.nim @@ -502,10 +502,7 @@ func validate*(self: Rlp) = # score in order to facilitate easier overloading with user types: template read*(rlp: var Rlp, T: type): auto = when T is SomeSignedInt: - let value = readImpl(rlp, uint64) - if value > uint64(T.high()): - raiseIntOutOfBounds() - T value + {.error "Signed integer encoding is not defined for rlp".} else: readImpl(rlp, T) diff --git a/eth/rlp/writer.nim b/eth/rlp/writer.nim index 8b4607f..8c4d432 100644 --- a/eth/rlp/writer.nim +++ b/eth/rlp/writer.nim @@ -301,15 +301,15 @@ proc appendImpl(self: var RlpWriter, data: tuple) {.inline.} = # We define a single `append` template with a pretty low specificity # score in order to facilitate easier overloading with user types: template append*[T](w: var RlpWriter; data: T) = - when data is (SomeSignedInt|enum|bool): - when data is SomeSignedInt: - # TODO potentially remove signed integer support - we should never make it - # this far! - {.warning: "Signed integers cannot reliably be encoded using RLP".} + when data is (enum|bool): + # TODO detect negative enum values at compile time? appendImpl(w, uint64(data)) else: appendImpl(w, data) +template append*(w: var RlpWriter; data: SomeSignedInt) = + {.error: "Signed integer encoding is not defined for rlp".} + proc initRlpList*(listSize: int): RlpWriter = result = initRlpWriter() startList(result, listSize) diff --git a/tests/fuzzing/discovery/generate.nim b/tests/fuzzing/discovery/generate.nim index c51bc72..a77d6f5 100644 --- a/tests/fuzzing/discovery/generate.nim +++ b/tests/fuzzing/discovery/generate.nim @@ -20,7 +20,7 @@ proc generate() = # valid data for a Ping packet block: - let payload = rlp.encode((4, fromAddr, toAddr, expiration())) + let payload = rlp.encode((uint64 4, fromAddr, toAddr, expiration())) let encodedData = @[1.byte] & payload debug "Ping", data=byteutils.toHex(encodedData) diff --git a/tests/fuzzing/rlp/rlp_decode.nim b/tests/fuzzing/rlp/rlp_decode.nim index 57937f2..a2624ca 100644 --- a/tests/fuzzing/rlp/rlp_decode.nim +++ b/tests/fuzzing/rlp/rlp_decode.nim @@ -23,9 +23,8 @@ test: testDecode(payload, uint16) testDecode(payload, uint32) testDecode(payload, uint64) - testDecode(payload, int) testDecode(payload, bool) testDecode(payload, seq[byte]) - testDecode(payload, (string, int32)) + testDecode(payload, (string, uint32)) testDecode(payload, TestEnum) testDecode(payload, TestObject) diff --git a/tests/rlp/test_api_usage.nim b/tests/rlp/test_api_usage.nim index 2662835..41ec9c2 100644 --- a/tests/rlp/test_api_usage.nim +++ b/tests/rlp/test_api_usage.nim @@ -64,16 +64,24 @@ suite "test api usage": MyObj = object a: array[3, char] - b: int + b: uint64 c: MyEnum + IntObj = object + v: int + var input: MyObj input.a = ['e', 't', 'h'] input.b = 63 input.c = bar + var writer = initRlpWriter() writer.append(input) + + check: + not compiles(writer.append(default(IntObj))) + let bytes = writer.finish() var rlp = rlpFromBytes(bytes) @@ -85,7 +93,7 @@ suite "test api usage": var writer = initRlpList(3) writer.append "foo" writer.append ["bar", "baz"] - writer.append [30, 40, 50] + writer.append [uint64 30, 40, 50] var bytes = writer.finish @@ -108,14 +116,14 @@ suite "test api usage": } """ - bytes = encodeList(6000, + bytes = encodeList(uint64 6000, "Lorem ipsum dolor sit amet", "Donec ligula tortor, egestas eu est vitae") rlp = rlpFromBytes bytes check: 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(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" list.skipElem - check list.toInt(int32) == 6000.int32 - var intVar: int + check list.toInt(uint32) == 6000.uint32 + var intVar: uint32 list >> intVar check intVar == 6000 @@ -146,19 +154,19 @@ suite "test api usage": tok.toHex == "40ef02798f211da2e8173d37f255be908871ae65060dbb2f77fb29c0421447f4" 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 sublistRlp0 = listRlp.listElem(0) let sublistRlp1 = listRlp.listElem(1) - check sublistRlp0.listElem(0).toInt(int) == 1 - check sublistRlp0.listElem(1).toInt(int) == 2 - check sublistRlp0.listElem(2).toInt(int) == 3 - check sublistRlp1.listElem(0).toInt(int) == 5 - check sublistRlp1.listElem(1).toInt(int) == 6 - check sublistRlp1.listElem(2).toInt(int) == 7 + check sublistRlp0.listElem(0).toInt(uint64) == 1 + check sublistRlp0.listElem(1).toInt(uint64) == 2 + check sublistRlp0.listElem(2).toInt(uint64) == 3 + check sublistRlp1.listElem(0).toInt(uint64) == 5 + check sublistRlp1.listElem(1).toInt(uint64) == 6 + check sublistRlp1.listElem(2).toInt(uint64) == 7 test "encoding length": - let listBytes = encode([1,2,3,4,5]) + let listBytes = encode([uint64 1,2,3,4,5]) let listRlp = rlpFromBytes listBytes check listRlp.listLen == 5 @@ -208,8 +216,8 @@ suite "test api usage": bar = 0x01 var writer = initRlpWriter() - writer.append(1) # valid - writer.append(2) # invalid + writer.append(byte 1) # valid + writer.append(byte 2) # invalid writer.append(cast[uint64](-1)) # invalid let bytes = writer.finish() var rlp = rlpFromBytes(bytes) @@ -231,10 +239,10 @@ suite "test api usage": baz = 0x0100 var writer = initRlpWriter() - writer.append(1) # valid - writer.append(2) # invalid - enum hole value - writer.append(256) # valid - writer.append(257) # invalid - too large + writer.append(1'u64) # valid + writer.append(2'u64) # invalid - enum hole value + writer.append(256'u64) # valid + writer.append(257'u64) # invalid - too large let bytes = writer.finish() var rlp = rlpFromBytes(bytes) diff --git a/tests/rlp/test_empty_string.nim b/tests/rlp/test_empty_string.nim index 1371271..284171d 100644 --- a/tests/rlp/test_empty_string.nim +++ b/tests/rlp/test_empty_string.nim @@ -9,7 +9,7 @@ type HelloObj = object version*: uint clientId*: string - capabilities*: seq[(string,int)] + capabilities*: seq[(string,uint)] listenPort*: uint nodeId*: array[64, byte] diff --git a/tests/rlp/test_object_serialization.nim b/tests/rlp/test_object_serialization.nim index 8fa1f80..31ee914 100644 --- a/tests/rlp/test_object_serialization.nim +++ b/tests/rlp/test_object_serialization.nim @@ -8,15 +8,15 @@ import type Transaction = object - amount: int - time: Time + amount: uint64 + time: uint64 sender: string receiver: string Foo = object x: uint64 y: string - z: seq[int] + z: seq[uint64] Bar = object b: string @@ -24,7 +24,7 @@ type CustomSerialized = object customFoo {.rlpCustomSerialization.}: Foo - ignored {.rlpIgnore.}: int + ignored {.rlpIgnore.}: uint64 rlpFields Foo, x, y, z @@ -34,19 +34,19 @@ rlpFields Transaction, proc append*(rlpWriter: var RlpWriter, holder: CustomSerialized, f: Foo) = rlpWriter.append(f.x) - rlpWriter.append(f.y.len) + rlpWriter.append(uint64 f.y.len) rlpWriter.append(holder.ignored) proc read*(rlp: var Rlp, holder: var CustomSerialized, T: type Foo): Foo = result.x = rlp.read(uint64) - result.y = newString(rlp.read(int)) - holder.ignored = rlp.read(int) * 2 + result.y = newString(rlp.read(uint64)) + holder.ignored = rlp.read(uint64) * 2 proc suite() = suite "object serialization": test "encoding and decoding an object": 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 r = rlpFromBytes(bytes) @@ -55,13 +55,13 @@ proc suite() = check: 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) var t2 = bytes.decode(Transaction) check: bytes.toHex == "cd85416c69636583426f628203e8" # verifies that Alice comes first - t2.time == default(Time) + t2.time == 0 t2.sender == "Alice" t2.receiver == "Bob" t2.amount == 1000 diff --git a/tests/rlp/util/json_testing.nim b/tests/rlp/util/json_testing.nim index 4c6eb98..ad4592d 100644 --- a/tests/rlp/util/json_testing.nim +++ b/tests/rlp/util/json_testing.nim @@ -9,9 +9,11 @@ proc append(output: var RlpWriter, js: JsonNode) = of JNull, JFloat, JObject: raise newException(ValueError, "Unsupported JSON value type " & $js.kind) of JBool: - output.append js.bval.int + output.append js.bval 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: output.append js.str of JArray: