protobuf encoding for all message types

This commit is contained in:
Michael Bradley, Jr 2022-04-07 14:02:12 -05:00 committed by Michael Bradley
parent 4c65f4bd94
commit faf5cad9d4
10 changed files with 432 additions and 172 deletions

View File

@ -1,6 +1,10 @@
# A DHT implementation for Dagger
![GitHub CI](https://github.com/status-im/nim-libp2p-dht/actions/workflows/ci.yml/badge.svg) ![codecov](https://codecov.io/gh/status-im/nim-libp2p-dht/branch/main/graph/badge.svg?token=tlmMJgU4l7)](https://codecov.io/gh/status-im/nim-libp2p-dht)
[![License: Apache](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Stability: experimental](https://img.shields.io/badge/stability-experimental-orange.svg)](#stability)
[![CI (GitHub Actions)](https://github.com/status-im/nim-libp2p-dht/workflows/CI/badge.svg?branch=main)](https://github.com/status-im/nim-libp2p-dht/actions?query=workflow%3ACI+branch%3Amain)
[![codecov](https://codecov.io/gh/status-im/nim-libp2p-dht/branch/main/graph/badge.svg?token=tlmMJgU4l7)](https://codecov.io/gh/status-im/nim-libp2p-dht)
This DHT implementation is aiming to provide a DHT for Dagger with the following properties
* flexible transport usage with
@ -12,5 +16,6 @@ This DHT implementation is aiming to provide a DHT for Dagger with the following
* roughly follow the libp2p-dht specifications from https://github.com/libp2p/specs/tree/master/kad-dht
* provide compatibility mode with the above specs
Current implementation is based on nim-eth's Discovery v5 implementation. Base files were copied
from nim-eth@779d767b024175a51cf74c79ec7513301ebe2f46
Current implementation is based on nim-eth's Discovery v5 implementation.
Base files were copied from [`status-im/nim-eth@779d767b024175a51cf74c79ec7513301ebe2f46`](https://github.com/status-im/nim-eth/commit/779d767b024175a51cf74c79ec7513301ebe2f46)

View File

@ -121,4 +121,3 @@ proc encode*(msg: ProvidersMessage): seq[byte] =
pb.finish()
pb.buffer

View File

@ -15,7 +15,6 @@
import
std/[hashes, net, options, sugar, tables],
eth/rlp,
bearssl,
chronicles,
stew/[results, byteutils],
@ -519,7 +518,7 @@ proc decodeHandshakePacket(c: var Codec, fromAddr: Address, nonce: AESGCMNonce,
("Invalid bytes for SignedPeerRecord: " & $e).cstring
)
record = some(decoded)
except RlpError, ValueError:
except ValueError:
return err("Invalid encoded SPR")
var pubkey: PublicKey

View File

@ -7,14 +7,14 @@
#
## Discovery v5 Protocol Messages as specified at
## https://github.com/ethereum/devp2p/blob/master/discv5/discv5-wire.md#protocol-messages
## These messages get RLP encoded.
## These messages get protobuf encoded, while in the spec they get RLP encoded.
##
{.push raises: [Defect].}
import
std/[hashes, net],
eth/[keys],
bearssl,
./spr,
./node,
../../../../dht/providers_messages

View File

@ -10,8 +10,6 @@
import
std/net,
stew/arrayops,
eth/[rlp],
chronicles,
libp2p/routing_record,
libp2p/signed_envelope,
@ -23,83 +21,312 @@ from stew/objects import checkedEnumAssign
type
DecodeResult*[T] = Result[T, cstring]
proc read*(rlp: var Rlp, T: type RequestId): T
{.raises: [ValueError, RlpError, Defect].} =
mixin read
var reqId: RequestId
reqId.id = rlp.toBytes()
if reqId.id.len > 8:
raise newException(ValueError, "RequestId is > 8 bytes")
rlp.skipElem()
Distances = seq[uint16]
reqId
EncodedMessage = seq[byte]
proc append*(writer: var RlpWriter, value: RequestId) =
writer.append(value.id)
IPv4 = array[0..3, uint8]
proc read*(rlp: var Rlp, T: type IpAddress): T
{.raises: [RlpError, Defect].} =
let ipBytes = rlp.toBytes()
rlp.skipElem()
IPv6 = array[0..15, uint8]
if ipBytes.len == 4:
var ip: array[4, byte]
discard copyFrom(ip, ipBytes)
IpAddress(family: IPv4, address_v4: ip)
elif ipBytes.len == 16:
var ip: array[16, byte]
discard copyFrom(ip, ipBytes)
IpAddress(family: IPv6, address_v6: ip)
Port = uint16
proc getField*(pb: ProtoBuffer, field: int,
reqId: var RequestId): ProtoResult[bool] {.inline.} =
## Read ``RequestId`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
elif buffer.len > 8:
ok(false) # RequestId must not be more than 8 bytes
else:
raise newException(RlpTypeMismatch,
"Amount of bytes for IP address is different from 4 or 16")
reqId = RequestId(id: buffer)
ok(true)
proc write*(pb: var ProtoBuffer, field: int, reqId: RequestId) =
## Write RequestId value ``reqId`` to object ``pb`` using ProtoBuf's encoding.
let encoded = reqId.id
write(pb, field, encoded)
proc decode*(
T: typedesc[PingMessage],
buffer: openArray[byte]): Result[PingMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = PingMessage()
? pb.getRequiredField(1, msg.sprSeq)
ok(msg)
proc encode*(msg: PingMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.sprSeq)
pb.finish()
pb.buffer
proc getField*(pb: ProtoBuffer, field: int,
ipv4: var IPv4): ProtoResult[bool] {.inline.} =
## Read ``IPv4`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
for i in 0..<ipv4.len: ipv4[i] = buffer[i]
ok(true)
proc getField*(pb: ProtoBuffer, field: int,
ipv6: var IPv6): ProtoResult[bool] {.inline.} =
## Read ``IPv6`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
for i in 0..<ipv6.len: ipv6[i] = buffer[i]
ok(true)
proc getField*(pb: ProtoBuffer, field: int,
family: var IpAddressFamily): ProtoResult[bool] {.inline.} =
## Read ``IpAddressFamily`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
family = uint8.fromBytesBE(buffer).IpAddressFamily
ok(true)
proc write*(pb: var ProtoBuffer, field: int, family: IpAddressFamily) =
## Write IpAddressFamily value ``family`` to object ``pb`` using ProtoBuf's encoding.
let encoded = family.uint8.toBytesBe()
write(pb, field, encoded)
proc decode*(
T: typedesc[IpAddress],
buffer: openArray[byte]): Result[IpAddress, ProtoError] =
let pb = initProtoBuffer(buffer)
var family: IpAddressFamily
? pb.getRequiredField(1, family)
var ip = IpAddress(family: family)
proc append*(writer: var RlpWriter, ip: IpAddress) =
case ip.family:
of IpAddressFamily.IPv6:
? pb.getRequiredField(2, ip.address_v6)
of IpAddressFamily.IPv4:
writer.append(ip.address_v4)
of IpAddressFamily.IPv6: writer.append(ip.address_v6)
? pb.getRequiredField(2, ip.address_v4)
proc read*(rlp: var Rlp, T: type NodeId): T
{.raises: [ValueError, RlpError, Defect].} =
mixin read
let nodeId = NodeId.fromBytesBE(rlp.toBytes())
rlp.skipElem()
nodeId
ok(ip)
proc append*(writer: var RlpWriter, value: NodeId) =
writer.append(value.toBytesBE)
proc encode*(ip: IpAddress): seq[byte] =
var pb = initProtoBuffer()
proc numFields(T: typedesc): int =
for k, v in fieldPairs(default(T)): inc result
pb.write(1, ip.family)
case ip.family:
of IpAddressFamily.IPv6:
pb.write(2, ip.address_v6)
of IpAddressFamily.IPv4:
pb.write(2, ip.address_v4)
pb.finish()
pb.buffer
proc getField*(pb: ProtoBuffer, field: int,
ip: var IpAddress): ProtoResult[bool] {.inline.} =
## Read ``IpAddress`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
let res2 = IpAddress.decode(buffer)
if res2.isOk():
ip = res2.get()
ok(true)
else:
err(ProtoError.IncorrectBlob)
proc write*(pb: var ProtoBuffer, field: int, ip: IpAddress) =
## Write IpAddress value ``ip`` to object ``pb`` using ProtoBuf's encoding.
let encoded = ip.encode()
write(pb, field, encoded)
proc getField*(pb: ProtoBuffer, field: int,
port: var Port): ProtoResult[bool] {.inline.} =
## Read ``Port`` from ProtoBuf's message and validate it
var buffer: seq[byte]
let res = ? pb.getField(field, buffer)
if not(res):
ok(false)
else:
port = uint16.fromBytesBE(buffer)
ok(true)
proc write*(pb: var ProtoBuffer, field: int, port: Port) =
## Write Port value ``port`` to object ``pb`` using ProtoBuf's encoding.
write(pb, field, port.toBytesBE())
proc decode*(
T: typedesc[PongMessage],
buffer: openArray[byte]): Result[PongMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = PongMessage()
? pb.getRequiredField(1, msg.sprSeq)
? pb.getRequiredField(2, msg.ip)
? pb.getRequiredField(3, msg.port)
ok(msg)
proc encode*(msg: PongMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.sprSeq)
pb.write(2, msg.ip)
pb.write(3, msg.port)
pb.finish()
pb.buffer
proc getRepeatedField*(pb: ProtoBuffer, field: int,
distances: var Distances): ProtoResult[bool] {.inline.} =
## Read ``Distances`` from ProtoBuf's message and validate it
var buffers: seq[seq[byte]]
distances.setLen(0)
let res = ? pb.getRepeatedField(field, buffers)
if not(res):
ok(false)
else:
for b in buffers:
distances.add(uint16.fromBytesBE(b))
ok(true)
proc decode*(
T: typedesc[FindNodeMessage],
buffer: openArray[byte]): Result[FindNodeMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = FindNodeMessage()
? pb.getRequiredRepeatedField(1, msg.distances)
ok(msg)
proc encode*(msg: FindNodeMessage): seq[byte] =
var pb = initProtoBuffer()
for d in msg.distances:
pb.write(1, d.toBytesBE())
pb.finish()
pb.buffer
proc decode*(
T: typedesc[FindNodeFastMessage],
buffer: openArray[byte]): Result[FindNodeFastMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = FindNodeFastMessage()
? pb.getRequiredField(1, msg.target)
ok(msg)
proc encode*(msg: FindNodeFastMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.target)
pb.finish()
pb.buffer
proc decode*(
T: typedesc[NodesMessage],
buffer: openArray[byte]): Result[NodesMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = NodesMessage()
? pb.getRequiredField(1, msg.total)
discard ? pb.getRepeatedField(2, msg.sprs)
ok(msg)
proc encode*(msg: NodesMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.total)
for r in msg.sprs:
pb.write(2, r)
pb.finish()
pb.buffer
proc decode*(
T: typedesc[TalkReqMessage],
buffer: openArray[byte]): Result[TalkReqMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = TalkReqMessage()
? pb.getRequiredField(1, msg.protocol)
? pb.getRequiredField(2, msg.request)
ok(msg)
proc encode*(msg: TalkReqMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(1, msg.protocol)
pb.write(2, msg.request)
pb.finish()
pb.buffer
proc decode*(
T: typedesc[TalkRespMessage],
buffer: openArray[byte]): Result[TalkRespMessage, ProtoError] =
let pb = initProtoBuffer(buffer)
var msg = TalkRespMessage()
? pb.getRequiredField(2, msg.response)
ok(msg)
proc encode*(msg: TalkRespMessage): seq[byte] =
var pb = initProtoBuffer()
pb.write(2, msg.response)
pb.finish()
pb.buffer
proc encodeMessage*[T: SomeMessage](p: T, reqId: RequestId): seq[byte] =
# TODO: Remove all RLP encoding in favour of Protobufs
result = newSeqOfCap[byte](64)
result.add(messageKind(T).ord)
const
usePbs = T is AddProviderMessage | GetProvidersMessage | ProvidersMessage
sz = if usePbs: 1 else: numFields(T)
var writer = initRlpList(sz + 1)
writer.append(reqId)
when usePbs:
let encoded =
try: p.encode()
except ResultError[CryptoError] as e:
error "Failed to encode protobuf message", typ = $T, msg = e.msg
@[]
writer.append(encoded)
trace "Encoded protobuf message", typ = $T, encoded
else:
for k, v in fieldPairs(p):
writer.append(v)
result.add(writer.finish())
let encoded =
try: p.encode()
except ResultError[CryptoError] as e:
error "Failed to encode protobuf message", typ = $T, msg = e.msg
@[]
var pb = initProtoBuffer()
pb.write(1, reqId)
pb.write(2, encoded)
pb.finish()
result.add(pb.buffer)
trace "Encoded protobuf message", typ = $T, encoded
proc decodeMessage*(body: openArray[byte]): DecodeResult[Message] =
# TODO: Remove all RLP decoding in favour of Protobufs
## Decodes to the specific `Message` type.
if body.len < 1:
return err("No message data")
@ -109,56 +336,107 @@ proc decodeMessage*(body: openArray[byte]): DecodeResult[Message] =
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))
let pb = initProtoBuffer(body[1..body.high])
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 findNodeFast: rlp.decode(message.findNodeFast)
of nodes: rlp.decode(message.nodes)
of talkReq: rlp.decode(message.talkReq)
of talkResp: rlp.decode(message.talkResp)
of addProvider:
let res = AddProviderMessage.decode(rlp.toBytes)
if res.isOk:
message.addProvider = res.get
else:
return err "Unable to decode AddProviderMessage"
of getProviders:
let res = GetProvidersMessage.decode(rlp.toBytes)
if res.isOk:
message.getProviders = res.get
else:
return err "Unable to decode GetProvidersMessage"
of providers:
let res = ProvidersMessage.decode(rlp.toBytes)
if res.isOk:
message.provs = res.get
else:
return err "Unable to decode ProvidersMessage"
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")
var
reqId: RequestId
encoded: EncodedMessage
ok(message)
else:
err("Invalid message encoding: no rlp list")
if pb.getRequiredField(1, reqId).isErr:
return err("Invalid request-id")
message.reqId = reqId
if pb.getRequiredField(2, encoded).isErr:
return err("Invalid message encoding")
case kind
of unused: return err("Invalid message type")
of ping:
let res = PingMessage.decode(encoded)
if res.isOk:
message.ping = res.get
return ok(message)
else:
return err("Unable to decode PingMessage")
of pong:
let res = PongMessage.decode(encoded)
if res.isOk:
message.pong = res.get
return ok(message)
else:
return err("Unable to decode PongMessage")
of findNode:
let res = FindNodeMessage.decode(encoded)
if res.isOk:
message.findNode = res.get
return ok(message)
else:
return err("Unable to decode FindNodeMessage")
of nodes:
let res = NodesMessage.decode(encoded)
if res.isOk:
message.nodes = res.get
return ok(message)
else:
return err("Unable to decode NodesMessage")
of talkReq:
let res = TalkReqMessage.decode(encoded)
if res.isOk:
message.talkReq = res.get
return ok(message)
else:
return err("Unable to decode TalkReqMessage")
of talkResp:
let res = TalkRespMessage.decode(encoded)
if res.isOk:
message.talkResp = res.get
return ok(message)
else:
return err("Unable to decode TalkRespMessage")
of findNodeFast:
let res = FindNodeFastMessage.decode(encoded)
if res.isOk:
message.findNodeFast = res.get
return ok(message)
else:
return err("Unable to decode FindNodeFastMessage")
of addProvider:
let res = AddProviderMessage.decode(encoded)
if res.isOk:
message.addProvider = res.get
return ok(message)
else:
return err "Unable to decode AddProviderMessage"
of getProviders:
let res = GetProvidersMessage.decode(encoded)
if res.isOk:
message.getProviders = res.get
return ok(message)
else:
return err("Unable to decode GetProvidersMessage")
of providers:
let res = ProvidersMessage.decode(encoded)
if res.isOk:
message.provs = res.get
return ok(message)
else:
return err("Unable to decode ProvidersMessage")
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

View File

@ -77,7 +77,7 @@ import
std/[tables, sets, options, math, sequtils, algorithm],
stew/shims/net as stewNet, json_serialization/std/net,
stew/[base64, endians2, results], chronicles, chronos, chronos/timer, stint, bearssl,
metrics, eth/[rlp, async_utils],
metrics, eth/async_utils,
libp2p/[crypto/crypto, routing_record],
"."/[transport, messages, messages_encoding, node, routing_table, spr, random2, ip_vote, nodes_verification]
@ -296,7 +296,7 @@ proc handleFindNodeFast(d: Protocol, fromId: NodeId, fromAddr: Address,
fnf: FindNodeFastMessage, reqId: RequestId) =
d.sendNodes(fromId, fromAddr, reqId,
d.routingTable.neighbours(fnf.target, seenOnly = true))
# TODO: if known, maybe we should add exact target even if not yet "seen"
# TODO: if known, maybe we should add exact target even if not yet "seen"
proc handleTalkReq(d: Protocol, fromId: NodeId, fromAddr: Address,
talkreq: TalkReqMessage, reqId: RequestId) =
@ -593,7 +593,7 @@ proc lookup*(d: Protocol, target: NodeId, fast: bool = false): Future[seq[Node]]
while i < closestNodes.len and pendingQueries.len < alpha:
let n = closestNodes[i]
if not asked.containsOrIncl(n.id):
if fast:
if fast:
pendingQueries.add(d.lookupWorkerFast(n, target))
else:
pendingQueries.add(d.lookupWorker(n, target))

View File

@ -6,12 +6,11 @@
#
import
chronicles,
std/[options, sequtils, strutils, sugar],
std/[options, strutils, sugar],
pkg/stew/[results, byteutils, arrayops],
stew/endians2,
stew/shims/net,
stew/base64,
eth/rlp,
libp2p/crypto/crypto,
libp2p/crypto/secp,
libp2p/routing_record,
@ -31,14 +30,6 @@ type
proc seqNum*(r: SignedPeerRecord): uint64 =
r.data.seqNo
#proc encode
proc append*(rlpWriter: var RlpWriter, value: SignedPeerRecord) =
# echo "encoding to:" & $value.signedPeerRecord.encode.get
var encoded = value.encode
if encoded.isErr:
error "Error encoding SignedPeerRecord for RLP", error = encoded.error
rlpWriter.append encoded.get(@[])
proc fromBytes(r: var SignedPeerRecord, s: openArray[byte]): bool =
let decoded = SignedPeerRecord.decode(@s)
@ -49,16 +40,6 @@ proc fromBytes(r: var SignedPeerRecord, s: openArray[byte]): bool =
r = decoded.get
return true
proc read*(rlp: var Rlp, T: typedesc[SignedPeerRecord]):
T {.raises: [RlpError, ValueError, Defect].} =
# echo "read:" & $rlp.rawData
## code directly borrowed from spr.nim
if not rlp.hasData() or not result.fromBytes(rlp.toBytes):
# TODO: This could also just be an invalid signature, would be cleaner to
# split of RLP deserialisation errors from this.
raise newException(ValueError, "Could not deserialize")
rlp.skipElem()
proc get*(r: SignedPeerRecord, T: type PublicKey): Option[T] =
## Get the `PublicKey` from provided `Record`. Return `none` when there is
## no `PublicKey` in the record.
@ -100,8 +81,6 @@ proc update*(r: var SignedPeerRecord, pk: crypto.PrivateKey,
let
sprPubKey = r.get(PublicKey)
pubKey = pk.getPublicKey
# keysPubKey = pubkey.get.pkToPk.get # remove when move away from eth/keys
# keysPrivKey = pk.pkToPk.get
if sprPubKey.isNone or pubKey.isErr or sprPubKey.get != pubKey.get:
return err("Public key does not correspond with given private key")
@ -220,7 +199,7 @@ proc udp*(r: SignedPeerRecord): Option[int] =
return some(p.int)
proc fromBase64*(r: var SignedPeerRecord, s: string): bool =
## Loads SPR from base64-encoded rlp-encoded bytes, and validates the
## Loads SPR from base64-encoded protobuf-encoded bytes, and validates the
## signature.
let bytes = Base64Url.decode(s)
r.fromBytes(bytes)

View File

@ -110,7 +110,7 @@ proc receive*(t: Transport, a: Address, packet: openArray[byte]) =
if packet.messageOpt.isSome():
let message = packet.messageOpt.get()
trace "Received message packet", srcId = packet.srcId, address = a,
kind = message.kind
kind = message.kind, packet
t.client.handleMessage(packet.srcId, a, message)
else:
trace "Not decryptable message packet received",

View File

@ -5,7 +5,6 @@ import
asynctest/unittest2,
bearssl,
chronos,
eth/rlp,
libp2p/crypto/secp,
libp2pdht/discv5/[messages, messages_encoding, encoding, spr, node, sessions],
libp2pdht/discv5/crypto,
@ -24,7 +23,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(p, reqId)
check byteutils.toHex(encoded) == "01c20101"
check byteutils.toHex(encoded) == "010a010112020801"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -44,7 +43,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(p, reqId)
check byteutils.toHex(encoded) == "02ca0101847f000001821388"
check byteutils.toHex(encoded) == "020a01011211080112090a010112047f0000011a021388"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -64,7 +63,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(fn, reqId)
check byteutils.toHex(encoded) == "03c501c3820100"
check byteutils.toHex(encoded) == "030a010112040a020100"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -82,7 +81,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(n, reqId)
check byteutils.toHex(encoded) == "04c30101c0"
check byteutils.toHex(encoded) == "040a010112020801"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -104,7 +103,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(n, reqId)
check byteutils.toHex(encoded) == "04f901a00101f9019bb8cc0a250802122102339d487ed237392d83791950dc891f0636de698c1fa051ea01ae3fa58bd78580120203011a560a2700250802122102339d487ed237392d83791950dc891f0636de698c1fa051ea01ae3fa58bd78580109cfd8992061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a4730450221008cc77fd265e33c955174b9f49628048b2d72a6395acb30f0ba9d90536fa1a5d502207fa8e5bab8e8ddee9884a8e244b0990228e3546b5a9b6848632abd924796e576b8cb0a2508021221026beda5cfddf1cd89130e7b5bb6092bac23db4a044bf847328aa0310dd123a445120203011a560a27002508021221026beda5cfddf1cd89130e7b5bb6092bac23db4a044bf847328aa0310dd123a445109cfd8992061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a46304402203d41b1a78c5e6d98c9b4f3fcb213dc16ae4de50a1c8715ab29c516afe6488b4e02205841d09e92b3d2f1ad72c7bc066e561dab57320886f3fbbf272d2cf1732ca259"
check byteutils.toHex(encoded) == "040a0101129f03080112cc010a250802122102339d487ed237392d83791950dc891f0636de698c1fa051ea01ae3fa58bd78580120203011a560a2700250802122102339d487ed237392d83791950dc891f0636de698c1fa051ea01ae3fa58bd78580109cfd8992061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a4730450221008cc77fd265e33c955174b9f49628048b2d72a6395acb30f0ba9d90536fa1a5d502207fa8e5bab8e8ddee9884a8e244b0990228e3546b5a9b6848632abd924796e57612cb010a2508021221026beda5cfddf1cd89130e7b5bb6092bac23db4a044bf847328aa0310dd123a445120203011a560a27002508021221026beda5cfddf1cd89130e7b5bb6092bac23db4a044bf847328aa0310dd123a445109cfd8992061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a46304402203d41b1a78c5e6d98c9b4f3fcb213dc16ae4de50a1c8715ab29c516afe6488b4e02205841d09e92b3d2f1ad72c7bc066e561dab57320886f3fbbf272d2cf1732ca259"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -124,7 +123,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(tr, reqId)
check byteutils.toHex(encoded) == "05c901846563686f826869"
check byteutils.toHex(encoded) == "050a0101120a0a046563686f12026869"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -142,7 +141,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
reqId = RequestId(id: @[1.byte])
let encoded = encodeMessage(tr, reqId)
check byteutils.toHex(encoded) == "06c401826869"
check byteutils.toHex(encoded) == "060a0101120412026869"
let decoded = decodeMessage(encoded)
check decoded.isOk()
@ -160,7 +159,7 @@ suite "Discovery v5.1 Protocol Message Encodings":
# 1 byte too large
reqId = RequestId(id: @[0.byte, 1, 2, 3, 4, 5, 6, 7, 8])
let encoded = encodeMessage(p, reqId)
check byteutils.toHex(encoded) == "01cb8900010203040506070801"
check byteutils.toHex(encoded) == "010a0900010203040506070812020801"
let decoded = decodeMessage(encoded)
check decoded.isErr()
@ -299,7 +298,8 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
encodedPacket =
"000000000000000000000000000000003788c1e1079e89374c4beac74d76364d" &
"bd9e8cd1847adc2f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
"7afd279a5fe4ffdded6d1a6d388217da82d38761b60b0c6e9dd94a8713bc5d"
"7afd279a5fe4ffdd21ed1a6d388207f00b48115b8ee4e8eaf675b0865821e126" &
"36bc"
let dummyKey = "0x00000000000000000000000000000001" # of no importance
codecA.sessions.store(nodeB.id, nodeB.address.get(),
@ -356,11 +356,11 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
encodedPacket =
"000000000000000000000000000000003788c1e1079e89374e4beac74d76364d" &
"bd9e8cd1847a712f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
"7afd279a5fe4ff441af3b17ec968350f37edbda9e0ba8ac0fd2617ef67a1e362" &
"5ea8eb284a3ca85f7ef976ccf2e87932ffeada775849d7aca378033b7a75dbe8" &
"7cc1767123bb7d7e5d96b5d6ad7c26cb55f6160b250d042ef1b9e6000191ce4e" &
"a93234ca3de051518684902e70e6a47eb8f0c2efeca8e42d2ea7f5bd1f27c12d" &
"ae3c579ddcef630659089c99"
"7afd279a5fe4ff441af3b17ec840104be4fae12da6828a752f1f7df615c4c757" &
"9558b0b537760549eb0e5ada50545b066734abb4b7bddbd503fad873e981b485" &
"dc9f8eee725661ebf766ce027edc9dcb55f6160b06d9c764481fb520b7581678" &
"e5fce2ab0d5fa2edaa92f252db6d6ea30d52a78e4114fb9dcf26fb1690e65ca0" &
"079386331f311bfc0aef4a771155ed"
let
whoareyouData = WhoareyouData(
@ -403,17 +403,17 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
encodedPacket =
"000000000000000000000000000000003788c1e1079e89374e4beac74d76364d" &
"bd9e8cd1847bc02f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
"7afd279a5fe4ff451af3b07ec8407cedec19c57a8460e08d3d8a908f78261170" &
"68196e7df56279e7493fbb2076025b395dde6ffeecc45daa59def06c9be97b1f" &
"95636fb8f16887cf13b4a8cca0bcaf805fe62529ad86c59204e73917cf183d19" &
"847617448722cc8c0eea80b68653e858eff5d250abbd55315db21fac1485db8f" &
"deaadba582d43c88f0b25512a5fd8395bd2f9519362d29cceb29028de04e0076" &
"4f6aece318e26e2d123888e484cb1c0ce37ecfee42ced9a811966bae40f40e9d" &
"4b46e27c388330304409a405b6455547661361d2129aa7bed4ff26f68d53532d" &
"cb6bae00506a7c5161b0652afcbf2416e97116bdcf9a7a548d6d8b5b0ab2ed0e" &
"b7a737afc0dbf65f32fd22c27cb17ebfe3c0d43e9bf45cfd24170c9fea348b10" &
"1207010ad51e28040b46770c1e96e22e7c552a6f1a62b4e29f8c99"
"bd9e8cd1847bc72f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
"7afd279a5fe4ff441af3b17ec96b7e0586467988bd0c4784575e02a32d0e7594" &
"b65e939a8490bd71813894c9f4e8796f8c3d3fce29171fc3c568ace28d89ea80" &
"a9707693d2ee9388e74f89a5a62bc3cb55f6160bae865f0779b75c989805232d" &
"55b73645bbd797a7d550db7233300b3d1de011fbde92783b4d813ddabff9c96a" &
"a0361139ec10df16cf2c136caf44d064194cc6777202952dc24c6fccf04f026d" &
"6d58c1c43dcf643d211afe4ff8d9f9727fb45380862d47978fd015a4f9a7ff39" &
"28158c38173fd1192164e714ad5454446b681ed2130a349fdffd4b81f814700c" &
"5b04551e621b65432d3e1beca05dc8e801a4c21da44d4cb29b1eddb92417aedd" &
"de855ba1016e93eb25d55879a0d27d170dc7904c6dfa06ce813b0455b3258c66" &
"1de55dcd349397bc5b8eb8e8ef5b4ed2115e968197effe44a0f5fb2b7d"
let
whoareyouData = WhoareyouData(

View File

@ -1,3 +1,3 @@
import
./dht/test_providers,
./discv5/[test_discoveryv5, test_discoveryv5_encoding]
./discv5/[test_discoveryv5, test_discoveryv5_encoding]