Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 1 addition & 64 deletions eth/p2p/discoveryv5/encoding.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import
std/[tables, options, hashes, net],
nimcrypto, stint, chronicles, bearssl, stew/[results, byteutils], metrics,
".."/../[rlp, keys],
"."/[messages, node, enr, hkdf, sessions]
"."/[messages, messages_encoding, node, enr, hkdf, sessions]

from stew/objects import checkedEnumAssign

Expand Down Expand Up @@ -367,50 +367,6 @@ proc decodeHeader*(id: NodeId, iv, maskedHeader: openArray[byte]):
ok((StaticHeader(authdataSize: authdataSize, flag: flag, nonce: nonce),
staticHeader & authdata))

proc decodeMessage*(body: openArray[byte]): DecodeResult[Message] =
## Decodes to the specific `Message` type.
if body.len < 1:
return err("No message data")

var kind: MessageKind
if not checkedEnumAssign(kind, body[0]):
return err("Invalid message type")

var message = Message(kind: kind)
var rlp = rlpFromBytes(body.toOpenArray(1, body.high))
if rlp.enterList:
try:
message.reqId = rlp.read(RequestId)
except RlpError, ValueError:
return err("Invalid request-id")

proc decode[T](rlp: var Rlp, v: var T)
{.nimcall, raises:[RlpError, ValueError, Defect].} =
for k, v in v.fieldPairs:
v = rlp.read(typeof(v))

try:
case kind
of unused: return err("Invalid message type")
of ping: rlp.decode(message.ping)
of pong: rlp.decode(message.pong)
of findNode: rlp.decode(message.findNode)
of nodes: rlp.decode(message.nodes)
of talkReq: rlp.decode(message.talkReq)
of talkResp: rlp.decode(message.talkResp)
of regTopic, ticket, regConfirmation, topicQuery:
# We just pass the empty type of this message without attempting to
# decode, so that the protocol knows what was received.
# But we ignore the message as per specification as "the content and
# semantics of this message are not final".
discard
except RlpError, ValueError:
return err("Invalid message encoding")

ok(message)
else:
err("Invalid message encoding: no rlp list")

proc decodeMessagePacket(c: var Codec, fromAddr: Address, nonce: AESGCMNonce,
iv, header, ct: openArray[byte]): DecodeResult[Packet] =
# We now know the exact size that the header should be
Expand Down Expand Up @@ -602,22 +558,3 @@ proc decodePacket*(c: var Codec, fromAddr: Address, input: openArray[byte]):
return decodeHandshakePacket(c, fromAddr, staticHeader.nonce,
input.toOpenArray(0, ivSize - 1), header,
input.toOpenArray(ivSize + header.len, input.high))

proc init*(T: type RequestId, rng: var BrHmacDrbgContext): T =
var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes
brHmacDrbgGenerate(rng, reqId.id)
reqId

proc numFields(T: typedesc): int =
for k, v in fieldPairs(default(T)): inc result

proc encodeMessage*[T: SomeMessage](p: T, reqId: RequestId): seq[byte] =
result = newSeqOfCap[byte](64)
result.add(messageKind(T).ord)

const sz = numFields(T)
var writer = initRlpList(sz + 1)
writer.append(reqId)
for k, v in fieldPairs(p):
writer.append(v)
result.add(writer.finish())
2 changes: 1 addition & 1 deletion eth/p2p/discoveryv5/enr.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import
stew/shims/net, stew/[base64, results], nimcrypto,
".."/../[rlp, keys]

export options, results, keys
export options, results

const
maxEnrSize = 300 ## Maximum size of an encoded node record, in bytes.
Expand Down
8 changes: 7 additions & 1 deletion eth/p2p/discoveryv5/messages.nim
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
import
std/[hashes, net],
stew/arrayops,
../../rlp, ./enr
".."/../[rlp, keys],
./enr

type
MessageKind* = enum
Expand Down Expand Up @@ -142,3 +143,8 @@ proc append*(writer: var RlpWriter, ip: IpAddress) =

proc hash*(reqId: RequestId): Hash =
hash(reqId.id)

proc init*(T: type RequestId, rng: var BrHmacDrbgContext): T =
var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes
brHmacDrbgGenerate(rng, reqId.id)
reqId
67 changes: 67 additions & 0 deletions eth/p2p/discoveryv5/messages_encoding.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import
".."/../[rlp],
"."/[messages, enr]

from stew/objects import checkedEnumAssign

type
DecodeResult*[T] = Result[T, cstring]

proc numFields(T: typedesc): int =
for k, v in fieldPairs(default(T)): inc result

proc encodeMessage*[T: SomeMessage](p: T, reqId: RequestId): seq[byte] =
result = newSeqOfCap[byte](64)
result.add(messageKind(T).ord)

const sz = numFields(T)
var writer = initRlpList(sz + 1)
writer.append(reqId)
for k, v in fieldPairs(p):
writer.append(v)
result.add(writer.finish())

proc decodeMessage*(body: openArray[byte]): DecodeResult[Message] =
## Decodes to the specific `Message` type.
if body.len < 1:
return err("No message data")

var kind: MessageKind
if not checkedEnumAssign(kind, body[0]):
return err("Invalid message type")

var message = Message(kind: kind)
var rlp = rlpFromBytes(body.toOpenArray(1, body.high))
if rlp.enterList:
try:
message.reqId = rlp.read(RequestId)
except RlpError, ValueError:
return err("Invalid request-id")

proc decode[T](rlp: var Rlp, v: var T)
{.nimcall, raises:[RlpError, ValueError, Defect].} =
for k, v in v.fieldPairs:
v = rlp.read(typeof(v))

try:
case kind
of unused: return err("Invalid message type")
of ping: rlp.decode(message.ping)
of pong: rlp.decode(message.pong)
of findNode: rlp.decode(message.findNode)
of nodes: rlp.decode(message.nodes)
of talkReq: rlp.decode(message.talkReq)
of talkResp: rlp.decode(message.talkResp)
of regTopic, ticket, regConfirmation, topicQuery:
# We just pass the empty type of this message without attempting to
# decode, so that the protocol knows what was received.
# But we ignore the message as per specification as "the content and
# semantics of this message are not final".
discard
except RlpError, ValueError:
return err("Invalid message encoding")

ok(message)
else:
err("Invalid message encoding: no rlp list")

Loading