mirror of
https://github.com/logos-storage/logos-storage-nim-dht.git
synced 2026-01-02 13:33:08 +00:00
chore: remove nim-eth/keys in favour of over to libp2p/crypto
Closes: #2. Libp2p supports multiple cryptographic curves, however we have currently only implented support for secp256k1. This needs to be run with the compiler flag `libp2p_pki_schemes` set to `secp256k1`. If running the tests, this can be run like so: `nimble test —libp2p_pki_schemes=secp256k1` to put secp as the first supported crypto scheme.
This commit is contained in:
parent
74b73bfda0
commit
4c65f4bd94
1
config.nims
Normal file
1
config.nims
Normal file
@ -0,0 +1 @@
|
||||
switch("define", "libp2p_pki_schemes=secp256k1")
|
||||
@ -1,4 +1,4 @@
|
||||
import
|
||||
./discv5/[spr, encoding, messages, messages_encoding, node, nodes_verification, protocol, routing_table, sessions, transport]
|
||||
./discv5/[crypto, spr, encoding, messages, messages_encoding, node, nodes_verification, protocol, routing_table, sessions, transport]
|
||||
|
||||
export spr, encoding, messages, messages_encoding, node, nodes_verification, protocol, routing_table, sessions, transport
|
||||
export crypto, spr, encoding, messages, messages_encoding, node, nodes_verification, protocol, routing_table, sessions, transport
|
||||
|
||||
4
libp2pdht/discv5/crypto.nim
Normal file
4
libp2pdht/discv5/crypto.nim
Normal file
@ -0,0 +1,4 @@
|
||||
import
|
||||
../private/eth/p2p/discoveryv5/crypto
|
||||
|
||||
export crypto
|
||||
30
libp2pdht/private/eth/p2p/discoveryv5/crypto.nim
Normal file
30
libp2pdht/private/eth/p2p/discoveryv5/crypto.nim
Normal file
@ -0,0 +1,30 @@
|
||||
import
|
||||
std/sugar,
|
||||
libp2p/crypto/[crypto, secp]
|
||||
|
||||
from secp256k1 import ecdhRaw, SkEcdhRawSecret, toRaw
|
||||
|
||||
proc fromHex*(T: type PrivateKey, data: string): Result[PrivateKey, cstring] =
|
||||
let skKey = ? SkPrivateKey.init(data).mapErr(e =>
|
||||
("Failed to init private key from hex string: " & $e).cstring)
|
||||
ok PrivateKey.init(skKey)
|
||||
|
||||
proc fromHex*(T: type PublicKey, data: string): Result[PublicKey, cstring] =
|
||||
let skKey = ? SkPublicKey.init(data).mapErr(e =>
|
||||
("Failed to init public key from hex string: " & $e).cstring)
|
||||
ok PublicKey.init(skKey)
|
||||
|
||||
func ecdhRaw*(seckey: SkPrivateKey, pubkey: SkPublicKey): SkEcdhRawSecret {.borrow.}
|
||||
|
||||
proc ecdhRaw*(
|
||||
priv: PrivateKey,
|
||||
pub: PublicKey): Result[SkEcdhRawSecret, cstring] =
|
||||
|
||||
# TODO: Do we need to support non-secp256k1 schemes?
|
||||
if priv.scheme != Secp256k1 or pub.scheme != Secp256k1:
|
||||
return err "Must use secp256k1 scheme".cstring
|
||||
|
||||
ok ecdhRaw(priv.skkey, pub.skkey)
|
||||
|
||||
proc toRaw*(pubkey: PublicKey): seq[byte] =
|
||||
secp256k1.SkPublicKey(pubkey.skkey).toRaw()[1..^1]
|
||||
@ -14,15 +14,24 @@
|
||||
{.push raises: [Defect].}
|
||||
|
||||
import
|
||||
std/[tables, options, hashes, net],
|
||||
nimcrypto, stint, chronicles, bearssl, stew/[results, byteutils], metrics,
|
||||
eth/[rlp, keys],
|
||||
std/[hashes, net, options, sugar, tables],
|
||||
eth/rlp,
|
||||
bearssl,
|
||||
chronicles,
|
||||
stew/[results, byteutils],
|
||||
stint,
|
||||
libp2p/crypto/crypto as libp2p_crypto,
|
||||
libp2p/crypto/secp,
|
||||
libp2p/signed_envelope,
|
||||
"."/[messages, messages_encoding, node, spr, hkdf, sessions]
|
||||
metrics,
|
||||
nimcrypto,
|
||||
"."/[messages, messages_encoding, node, spr, hkdf, sessions],
|
||||
"."/crypto
|
||||
|
||||
from nimcrypto/utils import toHex
|
||||
from stew/objects import checkedEnumAssign
|
||||
|
||||
export keys
|
||||
export crypto
|
||||
|
||||
declareCounter discovery_session_lru_cache_hits, "Session LRU cache hits"
|
||||
declareCounter discovery_session_lru_cache_misses, "Session LRU cache misses"
|
||||
@ -57,7 +66,7 @@ type
|
||||
|
||||
Challenge* = object
|
||||
whoareyouData*: WhoareyouData
|
||||
pubkey*: Option[keys.PublicKey]
|
||||
pubkey*: Option[PublicKey]
|
||||
|
||||
StaticHeader* = object
|
||||
flag: Flag
|
||||
@ -93,12 +102,16 @@ type
|
||||
|
||||
Codec* = object
|
||||
localNode*: Node
|
||||
privKey*: keys.PrivateKey
|
||||
privKey*: PrivateKey
|
||||
handshakes*: Table[HandshakeKey, Challenge]
|
||||
sessions*: Sessions
|
||||
|
||||
EncodeResult*[T] = Result[T, cstring]
|
||||
|
||||
DecodeResult*[T] = Result[T, cstring]
|
||||
|
||||
CryptoResult*[T] = Result[T, CryptoError]
|
||||
|
||||
func `==`*(a, b: HandshakeKey): bool =
|
||||
(a.nodeId == b.nodeId) and (a.address == b.address)
|
||||
|
||||
@ -117,18 +130,23 @@ proc idHash(challengeData, ephkey: openArray[byte], nodeId: NodeId):
|
||||
result = ctx.finish()
|
||||
ctx.clear()
|
||||
|
||||
proc createIdSignature*(privKey: keys.PrivateKey, challengeData,
|
||||
ephKey: openArray[byte], nodeId: NodeId): SignatureNR =
|
||||
signNR(privKey, SkMessage(idHash(challengeData, ephKey, nodeId).data))
|
||||
proc createIdSignature*(privKey: PrivateKey, challengeData,
|
||||
ephKey: openArray[byte], nodeId: NodeId): EncodeResult[Signature] =
|
||||
|
||||
proc verifyIdSignature*(sig: SignatureNR, challengeData, ephKey: openArray[byte],
|
||||
nodeId: NodeId, pubkey: keys.PublicKey): bool =
|
||||
let h = idHash(challengeData, ephKey, nodeId)
|
||||
verify(sig, SkMessage(h.data), pubkey)
|
||||
sign(privKey, h.data).mapErr(e =>
|
||||
("Failed to sign challegene data: " & $e).cstring)
|
||||
|
||||
proc deriveKeys*(n1, n2: NodeId, priv: keys.PrivateKey, pub: keys.PublicKey,
|
||||
challengeData: openArray[byte]): HandshakeSecrets =
|
||||
let eph = ecdhRawFull(priv, pub)
|
||||
proc verifyIdSignature*(sig: Signature, challengeData, ephKey: openArray[byte],
|
||||
nodeId: NodeId, pubkey: PublicKey): bool =
|
||||
|
||||
let h = idHash(challengeData, ephKey, nodeId)
|
||||
verify(sig, h.data, pubkey)
|
||||
|
||||
proc deriveKeys*(n1, n2: NodeId, priv: PrivateKey, pub: PublicKey,
|
||||
challengeData: openArray[byte]): EncodeResult[HandshakeSecrets] =
|
||||
|
||||
let eph = ? ecdhRaw(priv, pub)
|
||||
|
||||
var info = newSeqOfCap[byte](keyAgreementPrefix.len + 32 * 2)
|
||||
for i, c in keyAgreementPrefix: info.add(byte(c))
|
||||
@ -141,7 +159,7 @@ proc deriveKeys*(n1, n2: NodeId, priv: keys.PrivateKey, pub: keys.PublicKey,
|
||||
|
||||
hkdf(sha256, eph.data, challengeData, info,
|
||||
toOpenArray(res, 0, sizeof(secrets) - 1))
|
||||
secrets
|
||||
ok secrets
|
||||
|
||||
proc encryptGCM*(key: AesKey, nonce, pt, authData: openArray[byte]): seq[byte] =
|
||||
var ectx: GCM[aes128]
|
||||
@ -236,7 +254,7 @@ proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec,
|
||||
|
||||
proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec,
|
||||
toId: NodeId, toAddr: Address, requestNonce: AESGCMNonce, recordSeq: uint64,
|
||||
pubkey: Option[keys.PublicKey]): seq[byte] =
|
||||
pubkey: Option[PublicKey]): seq[byte] =
|
||||
var idNonce: IdNonce
|
||||
brHmacDrbgGenerate(rng, idNonce)
|
||||
|
||||
@ -278,7 +296,7 @@ proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec,
|
||||
|
||||
proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec,
|
||||
toId: NodeId, toAddr: Address, message: openArray[byte],
|
||||
whoareyouData: WhoareyouData, pubkey: keys.PublicKey): seq[byte] =
|
||||
whoareyouData: WhoareyouData, pubkey: PublicKey): EncodeResult[seq[byte]] =
|
||||
var header: seq[byte]
|
||||
var nonce: AESGCMNonce
|
||||
brHmacDrbgGenerate(rng, nonce)
|
||||
@ -289,37 +307,52 @@ proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec,
|
||||
var authdataHead: seq[byte]
|
||||
|
||||
authdataHead.add(c.localNode.id.toByteArrayBE())
|
||||
authdataHead.add(64'u8) # sig-size: 64
|
||||
authdataHead.add(33'u8) # eph-key-size: 33
|
||||
|
||||
let ephKeys = ? KeyPair.random(rng)
|
||||
.mapErr((e: CryptoError) =>
|
||||
("Failed to create random key pair: " & $e).cstring)
|
||||
|
||||
# TODO: Do we need to support non-secp256k1 schemes?
|
||||
if ephKeys.pubkey.scheme != Secp256k1:
|
||||
return err "Crypto scheme must be secp256k1".cstring
|
||||
|
||||
let
|
||||
pubKeyRaw = ? ephKeys.pubkey.getBytes().mapErr((e: CryptoError) =>
|
||||
("Failed to serialize public key: " & $e).cstring)
|
||||
signature = ? createIdSignature(
|
||||
c.privKey,
|
||||
whoareyouData.challengeData,
|
||||
pubKeyRaw,
|
||||
toId)
|
||||
|
||||
let sigBytes = signature.getBytes()
|
||||
authdataHead.add(sigBytes.len.uint8) # DER variable, less than 72 bytes
|
||||
authdataHead.add(pubKeyRaw.len.uint8) # eph-key-size: 33
|
||||
authdata.add(authdataHead)
|
||||
authdata.add(sigBytes)
|
||||
|
||||
let ephKeys = keys.KeyPair.random(rng)
|
||||
let signature = createIdSignature(c.privKey, whoareyouData.challengeData,
|
||||
ephKeys.pubkey.toRawCompressed(), toId)
|
||||
|
||||
authdata.add(signature.toRaw())
|
||||
# compressed pub key format (33 bytes)
|
||||
authdata.add(ephKeys.pubkey.toRawCompressed())
|
||||
authdata.add(pubKeyRaw)
|
||||
|
||||
# Add SPR of sequence number is newer
|
||||
if whoareyouData.recordSeq < c.localNode.record.seqNum:
|
||||
let encoded = c.localNode.record.encode
|
||||
if encoded.isOk:
|
||||
trace "Encoded local node's SignedPeerRecord", bytes = encoded.get
|
||||
authdata.add(encoded.get)
|
||||
else:
|
||||
error "Failed to encode local node's SignedPeerRecord", error = encoded.error
|
||||
authdata.add(@[])
|
||||
let encoded = ? c.localNode.record.encode.mapErr((e: CryptoError) =>
|
||||
("Failed to encode local node's SignedPeerRecord: " &
|
||||
$e).cstring)
|
||||
authdata.add(encoded)
|
||||
|
||||
let secrets = deriveKeys(c.localNode.id, toId, ephKeys.seckey, pubkey,
|
||||
whoareyouData.challengeData)
|
||||
let secrets = ? deriveKeys(
|
||||
c.localNode.id,
|
||||
toId,
|
||||
ephKeys.seckey,
|
||||
pubkey,
|
||||
whoareyouData.challengeData)
|
||||
|
||||
# Header
|
||||
let staticHeader = encodeStaticHeader(Flag.HandshakeMessage, nonce,
|
||||
authdata.len())
|
||||
|
||||
header.add(staticHeader)
|
||||
trace "Handshake packet's authdata", authdata
|
||||
header.add(authdata)
|
||||
|
||||
c.sessions.store(toId, toAddr, secrets.recipientKey, secrets.initiatorKey)
|
||||
@ -333,7 +366,7 @@ proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec,
|
||||
packet.add(maskedHeader)
|
||||
packet.add(messageEncrypted)
|
||||
|
||||
return packet
|
||||
return ok packet
|
||||
|
||||
proc decodeHeader*(id: NodeId, iv, maskedHeader: openArray[byte]):
|
||||
DecodeResult[(StaticHeader, seq[byte])] =
|
||||
@ -437,6 +470,7 @@ proc decodeWhoareyouPacket(c: var Codec, nonce: AESGCMNonce,
|
||||
|
||||
proc decodeHandshakePacket(c: var Codec, fromAddr: Address, nonce: AESGCMNonce,
|
||||
iv, header, ct: openArray[byte]): DecodeResult[Packet] =
|
||||
|
||||
# Checking if there is enough data to decode authdata-head
|
||||
if header.len <= staticHeaderSize + authdataHeadSize:
|
||||
return err("Invalid header for handshake message packet: no authdata-head")
|
||||
@ -469,24 +503,26 @@ proc decodeHandshakePacket(c: var Codec, fromAddr: Address, nonce: AESGCMNonce,
|
||||
let
|
||||
ephKeyPos = authdataHeadSize + int(sigSize)
|
||||
ephKeyRaw = authdata[ephKeyPos..<ephKeyPos + int(ephKeySize)]
|
||||
ephKey = ? keys.PublicKey.fromRaw(ephKeyRaw)
|
||||
ephKey = ? PublicKey.init(ephKeyRaw).mapErr(e =>
|
||||
("Failed to deserialize PublicKey: " & $e).cstring)
|
||||
|
||||
var record: Option[SignedPeerRecord]
|
||||
let recordPos = ephKeyPos + int(ephKeySize)
|
||||
if authdata.len() > recordPos:
|
||||
# There is possibly an SPR still
|
||||
try:
|
||||
trace "Decoding handshake packet's authdata", authdata, recordPos, decodeBytes = authdata.toOpenArray(recordPos, authdata.high)
|
||||
# Signature check of record happens in decode.
|
||||
let
|
||||
prBytes = @(authdata.toOpenArray(recordPos, authdata.high))
|
||||
decoded = SignedPeerRecord.decode(prBytes)
|
||||
.expect("Should be valid bytes for SignedPeerRecord")
|
||||
decoded = ? SignedPeerRecord.decode(prBytes).mapErr(
|
||||
(e: EnvelopeError) =>
|
||||
("Invalid bytes for SignedPeerRecord: " & $e).cstring
|
||||
)
|
||||
record = some(decoded)
|
||||
except RlpError, ValueError:
|
||||
return err("Invalid encoded SPR")
|
||||
|
||||
var pubkey: keys.PublicKey
|
||||
var pubkey: PublicKey
|
||||
var newNode: Option[Node]
|
||||
# TODO: Shall we return Node or SignedPeerRecord? SignedPeerRecord makes
|
||||
# more sense, but we do need the pubkey and the nodeid
|
||||
@ -509,16 +545,27 @@ proc decodeHandshakePacket(c: var Codec, fromAddr: Address, nonce: AESGCMNonce,
|
||||
return err("Missing SPR in handshake packet")
|
||||
|
||||
# Verify the id-signature
|
||||
let sig = ? SignatureNR.fromRaw(
|
||||
authdata.toOpenArray(authdataHeadSize, authdataHeadSize + int(sigSize) - 1))
|
||||
let
|
||||
sigBytes = @(authdata.toOpenArray(
|
||||
authdataHeadSize,
|
||||
authdataHeadSize + int(sigSize) - 1
|
||||
))
|
||||
|
||||
sig = ? Signature.init(sigBytes).mapErr((e: CryptoError) =>
|
||||
("Failed to deserialize signature from bytes: " & $e).cstring)
|
||||
|
||||
if not verifyIdSignature(sig, challenge.whoareyouData.challengeData,
|
||||
ephKeyRaw, c.localNode.id, pubkey):
|
||||
return err("Invalid id-signature")
|
||||
|
||||
# Do the key derivation step only after id-signature is verified as this is
|
||||
# costly.
|
||||
var secrets = deriveKeys(srcId, c.localNode.id, c.privKey,
|
||||
ephKey, challenge.whoareyouData.challengeData)
|
||||
var secrets = ? deriveKeys(
|
||||
srcId,
|
||||
c.localNode.id,
|
||||
c.privKey,
|
||||
ephKey,
|
||||
challenge.whoareyouData.challengeData)
|
||||
|
||||
swap(secrets.recipientKey, secrets.initiatorKey)
|
||||
|
||||
|
||||
@ -9,8 +9,14 @@
|
||||
|
||||
import
|
||||
std/hashes,
|
||||
nimcrypto, stint, chronos, stew/shims/net, chronicles,
|
||||
eth/keys, eth/net/utils,
|
||||
bearssl,
|
||||
chronicles,
|
||||
chronos,
|
||||
nimcrypto,
|
||||
stew/shims/net,
|
||||
stint,
|
||||
eth/net/utils,
|
||||
./crypto,
|
||||
./spr
|
||||
|
||||
export stint
|
||||
@ -24,24 +30,28 @@ type
|
||||
|
||||
Node* = ref object
|
||||
id*: NodeId
|
||||
pubkey*: keys.PublicKey
|
||||
pubkey*: PublicKey
|
||||
address*: Option[Address]
|
||||
record*: SignedPeerRecord
|
||||
seen*: bool ## Indicates if there was at least one successful
|
||||
## request-response with this node, or if the nde was verified
|
||||
## through the underlying transport mechanisms.
|
||||
|
||||
func toNodeId*(pk: keys.PublicKey): NodeId =
|
||||
func toNodeId*(pid: PeerId): NodeId =
|
||||
## Convert public key to a node identifier.
|
||||
# Keccak256 hash is used as defined in SPR spec for scheme v4:
|
||||
# https://github.com/ethereum/devp2p/blob/master/enr.md#v4-identity-scheme
|
||||
readUintBE[256](keccak256.digest(pk.toRaw()).data)
|
||||
readUintBE[256](keccak256.digest(pid.data).data)
|
||||
|
||||
proc toNodeId*(pk: PublicKey): Result[NodeId, cstring] =
|
||||
let pid = ? PeerId.init(pk)
|
||||
ok pid.toNodeId
|
||||
|
||||
func newNode*(r: SignedPeerRecord): Result[Node, cstring] =
|
||||
## Create a new `Node` from a `SignedPeerRecord`.
|
||||
# TODO: Handle IPv6
|
||||
|
||||
let pk = r.get(keys.PublicKey)
|
||||
let pk = r.get(PublicKey)
|
||||
# This check is redundant for a properly created record as the deserialization
|
||||
# of a record will fail at `verifySignature` if there is no public key.
|
||||
if pk.isNone():
|
||||
@ -49,17 +59,20 @@ func newNode*(r: SignedPeerRecord): Result[Node, cstring] =
|
||||
|
||||
# Also this can not fail for a properly created record as id is checked upon
|
||||
# deserialization.
|
||||
let tr = ? r.toTypedRecord()
|
||||
let
|
||||
tr = ? r.toTypedRecord()
|
||||
nodeId = ? pk.get().toNodeId()
|
||||
|
||||
if tr.ip.isSome() and tr.udp.isSome():
|
||||
let a = Address(ip: ipv4(tr.ip.get()), port: Port(tr.udp.get()))
|
||||
|
||||
ok(Node(id: pk.get().toNodeId(), pubkey: pk.get() , record: r,
|
||||
ok(Node(id: nodeId, pubkey: pk.get() , record: r,
|
||||
address: some(a)))
|
||||
else:
|
||||
ok(Node(id: pk.get().toNodeId(), pubkey: pk.get(), record: r,
|
||||
ok(Node(id: nodeId, pubkey: pk.get(), record: r,
|
||||
address: none(Address)))
|
||||
|
||||
proc update*(n: Node, pk: keys.PrivateKey, ip: Option[ValidIpAddress],
|
||||
proc update*(n: Node, pk: PrivateKey, ip: Option[ValidIpAddress],
|
||||
tcpPort, udpPort: Option[Port] = none[Port]()): Result[void, cstring] =
|
||||
? n.record.update(pk, ip, tcpPort, udpPort)
|
||||
|
||||
@ -77,7 +90,8 @@ proc update*(n: Node, pk: keys.PrivateKey, ip: Option[ValidIpAddress],
|
||||
|
||||
ok()
|
||||
|
||||
func hash*(n: Node): hashes.Hash = hash(n.pubkey.toRaw)
|
||||
func hash*(n: Node): hashes.Hash =
|
||||
hash(n.pubkey.getRawBytes.expect("Public key has correct structure"))
|
||||
|
||||
func `==`*(a, b: Node): bool =
|
||||
(a.isNil and b.isNil) or
|
||||
|
||||
@ -77,7 +77,8 @@ 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, keys, async_utils], libp2p/routing_record,
|
||||
metrics, eth/[rlp, async_utils],
|
||||
libp2p/[crypto/crypto, routing_record],
|
||||
"."/[transport, messages, messages_encoding, node, routing_table, spr, random2, ip_vote, nodes_verification]
|
||||
|
||||
import nimcrypto except toHex
|
||||
@ -120,7 +121,7 @@ type
|
||||
|
||||
Protocol* = ref object
|
||||
localNode*: Node
|
||||
privateKey: keys.PrivateKey
|
||||
privateKey: PrivateKey
|
||||
transport*: Transport[Protocol] # exported for tests
|
||||
routingTable*: RoutingTable
|
||||
awaitedMessages: Table[(NodeId, RequestId), Future[Option[Message]]]
|
||||
@ -214,7 +215,7 @@ proc neighboursAtDistances*(d: Protocol, distances: seq[uint16],
|
||||
|
||||
proc nodesDiscovered*(d: Protocol): int = d.routingTable.len
|
||||
|
||||
func privKey*(d: Protocol): lent keys.PrivateKey =
|
||||
func privKey*(d: Protocol): lent PrivateKey =
|
||||
d.privateKey
|
||||
|
||||
func getRecord*(d: Protocol): SignedPeerRecord =
|
||||
@ -948,7 +949,7 @@ func init*(
|
||||
)
|
||||
|
||||
proc newProtocol*(
|
||||
privKey: keys.PrivateKey,
|
||||
privKey: PrivateKey,
|
||||
enrIp: Option[ValidIpAddress],
|
||||
enrTcpPort, enrUdpPort: Option[Port],
|
||||
localEnrFields: openArray[(string, seq[byte])] = [],
|
||||
@ -958,7 +959,7 @@ proc newProtocol*(
|
||||
bindIp = IPv4_any(),
|
||||
enrAutoUpdate = false,
|
||||
config = defaultDiscoveryConfig,
|
||||
rng = keys.newRng()):
|
||||
rng = newRng()):
|
||||
Protocol =
|
||||
# TODO: Tried adding bindPort = udpPort as parameter but that gave
|
||||
# "Error: internal error: environment misses: udpPort" in nim-beacon-chain.
|
||||
|
||||
@ -12,7 +12,6 @@ import
|
||||
stew/shims/net,
|
||||
stew/base64,
|
||||
eth/rlp,
|
||||
eth/keys,
|
||||
libp2p/crypto/crypto,
|
||||
libp2p/crypto/secp,
|
||||
libp2p/routing_record,
|
||||
@ -36,13 +35,11 @@ proc seqNum*(r: SignedPeerRecord): uint64 =
|
||||
proc append*(rlpWriter: var RlpWriter, value: SignedPeerRecord) =
|
||||
# echo "encoding to:" & $value.signedPeerRecord.encode.get
|
||||
var encoded = value.encode
|
||||
trace "Encoding SignedPeerRecord for RLP", bytes = encoded.get(@[])
|
||||
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 =
|
||||
trace "Decoding SignedPeerRecord for RLP", bytes = s
|
||||
|
||||
let decoded = SignedPeerRecord.decode(@s)
|
||||
if decoded.isErr:
|
||||
@ -56,46 +53,24 @@ proc read*(rlp: var Rlp, T: typedesc[SignedPeerRecord]):
|
||||
T {.raises: [RlpError, ValueError, Defect].} =
|
||||
# echo "read:" & $rlp.rawData
|
||||
## code directly borrowed from spr.nim
|
||||
trace "Reading RLP SignedPeerRecord", rawData = rlp.rawData, toBytes = rlp.toBytes
|
||||
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 crypto.PublicKey): Option[T] =
|
||||
## Get the `PublicKey` from provided `Record`. Return `none` when there is
|
||||
## no `PublicKey` in the record.
|
||||
some(r.envelope.publicKey)
|
||||
|
||||
func pkToPk(pk: crypto.PublicKey) : Option[keys.PublicKey] =
|
||||
some((keys.PublicKey)(pk.skkey))
|
||||
|
||||
func pkToPk(pk: keys.PublicKey) : Option[crypto.PublicKey] =
|
||||
some(crypto.PublicKey.init((secp.SkPublicKey)(pk)))
|
||||
|
||||
func pkToPk(pk: crypto.PrivateKey) : Option[keys.PrivateKey] =
|
||||
some((keys.PrivateKey)(pk.skkey))
|
||||
|
||||
func pkToPk(pk: keys.PrivateKey) : Option[crypto.PrivateKey] =
|
||||
some(crypto.PrivateKey.init((secp.SkPrivateKey)(pk)))
|
||||
|
||||
proc get*(r: SignedPeerRecord, T: type keys.PublicKey): Option[T] =
|
||||
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.
|
||||
## PublicKey* = distinct SkPublicKey
|
||||
let
|
||||
pk = r.envelope.publicKey
|
||||
pkToPk(pk)
|
||||
r.envelope.publicKey.some
|
||||
|
||||
proc incSeqNo*(
|
||||
r: var SignedPeerRecord,
|
||||
pk: keys.PrivateKey): RecordResult[void] =
|
||||
|
||||
let cryptoPk = pk.pkToPk.get() # TODO: remove when eth/keys removed
|
||||
pk: PrivateKey): RecordResult[void] =
|
||||
|
||||
r.data.seqNo.inc()
|
||||
r = ? SignedPeerRecord.init(cryptoPk, r.data).mapErr(
|
||||
r = ? SignedPeerRecord.init(pk, r.data).mapErr(
|
||||
(e: CryptoError) =>
|
||||
("Error initialising SignedPeerRecord with incremented seqNo: " &
|
||||
$e).cstring
|
||||
@ -123,10 +98,11 @@ proc update*(r: var SignedPeerRecord, pk: crypto.PrivateKey,
|
||||
# ip/tcpPort/udpPort/extraFields
|
||||
|
||||
let
|
||||
pubkey = r.get(crypto.PublicKey)
|
||||
keysPubKey = pubkey.get.pkToPk.get # remove when move away from eth/keys
|
||||
keysPrivKey = pk.pkToPk.get
|
||||
if pubkey.isNone() or keysPubKey != keysPrivKey.toPublicKey:
|
||||
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")
|
||||
|
||||
var
|
||||
@ -208,13 +184,6 @@ proc update*(r: var SignedPeerRecord, pk: crypto.PrivateKey,
|
||||
|
||||
return ok()
|
||||
|
||||
proc update*(r: var SignedPeerRecord, pk: keys.PrivateKey,
|
||||
ip: Option[ValidIpAddress],
|
||||
tcpPort, udpPort: Option[Port] = none[Port]()):
|
||||
RecordResult[void] =
|
||||
let cPk = pkToPk(pk).get
|
||||
r.update(cPk, ip, tcpPort, udpPort)
|
||||
|
||||
proc toTypedRecord*(r: SignedPeerRecord) : RecordResult[SignedPeerRecord] = ok(r)
|
||||
|
||||
proc ip*(r: SignedPeerRecord): Option[array[4, byte]] =
|
||||
@ -275,7 +244,7 @@ proc toBase64*(r: SignedPeerRecord): string =
|
||||
proc toURI*(r: SignedPeerRecord): string = "spr:" & r.toBase64
|
||||
|
||||
proc init*(T: type SignedPeerRecord, seqNum: uint64,
|
||||
pk: crypto.PrivateKey,
|
||||
pk: PrivateKey,
|
||||
ip: Option[ValidIpAddress],
|
||||
tcpPort, udpPort: Option[Port]):
|
||||
RecordResult[T] =
|
||||
@ -317,35 +286,10 @@ proc init*(T: type SignedPeerRecord, seqNum: uint64,
|
||||
|
||||
|
||||
let ma = MultiAddress.init(ipAddr, proto, protoPort)
|
||||
# if ip.isSome:
|
||||
# let
|
||||
# ipAddr = ip.get
|
||||
# proto = ipAddr.family
|
||||
# address = if proto == IPv4: ipAddr.address_v4
|
||||
# else: ipAddr.address_v6
|
||||
# u and udpPort.isSome
|
||||
# # let ta = initTAddress(ip.get, udpPort.get)
|
||||
# # echo ta
|
||||
# # ma = MultiAddress.init(ta).get
|
||||
# #let ma1 = MultiAddress.init("/ip4/127.0.0.1").get() #TODO
|
||||
# #let ma2 = MultiAddress.init(multiCodec("udp"), udpPort.get.int).get
|
||||
# #ma = ma1 & ma2
|
||||
# ma = MultiAddress.init("/ip4/127.0.0.1/udp/" & $udpPort.get.int).get #TODO
|
||||
# else:
|
||||
# ma = MultiAddress.init()
|
||||
# # echo "not implemented"
|
||||
|
||||
let pr = PeerRecord.init(peerId, @[ma], seqNum)
|
||||
SignedPeerRecord.init(pk, pr).mapErr((e: CryptoError) => ("Failed to init SignedPeerRecord: " & $e).cstring)
|
||||
|
||||
proc init*(T: type SignedPeerRecord, seqNum: uint64,
|
||||
pk: keys.PrivateKey,
|
||||
ip: Option[ValidIpAddress],
|
||||
tcpPort, udpPort: Option[Port]):
|
||||
RecordResult[T] =
|
||||
let kPk = pkToPk(pk).get
|
||||
SignedPeerRecord.init(seqNum, kPk, ip, tcpPort, udpPort)
|
||||
|
||||
proc contains*(r: SignedPeerRecord, fp: (string, seq[byte])): bool =
|
||||
# TODO: use FieldPair for this, but that is a bit cumbersome. Perhaps the
|
||||
# `get` call can be improved to make this easier.
|
||||
|
||||
@ -7,8 +7,10 @@
|
||||
# Everything below the handling of ordinary messages
|
||||
import
|
||||
std/[tables, options],
|
||||
bearssl,
|
||||
chronos,
|
||||
chronicles,
|
||||
libp2p/crypto/crypto,
|
||||
stew/shims/net,
|
||||
"."/[node, encoding, sessions]
|
||||
|
||||
@ -124,8 +126,15 @@ proc receive*(t: Transport, a: Address, packet: openArray[byte]) =
|
||||
# This is a node we previously contacted and thus must have an address.
|
||||
doAssert(toNode.address.isSome())
|
||||
let address = toNode.address.get()
|
||||
let data = encodeHandshakePacket(t.rng[], t.codec, toNode.id,
|
||||
address, pr.message, packet.whoareyou, toNode.pubkey)
|
||||
let data = encodeHandshakePacket(
|
||||
t.rng[],
|
||||
t.codec,
|
||||
toNode.id,
|
||||
address,
|
||||
pr.message,
|
||||
packet.whoareyou,
|
||||
toNode.pubkey
|
||||
).expect("Valid handshake packet to encode")
|
||||
|
||||
trace "Send handshake message packet", dstId = toNode.id, address
|
||||
t.send(toNode, data)
|
||||
|
||||
@ -1,19 +1,30 @@
|
||||
import
|
||||
stew/shims/net, bearssl, chronos,
|
||||
eth/keys,
|
||||
libp2pdht/discv5/[spr, node, routing_table],
|
||||
bearssl,
|
||||
chronos,
|
||||
libp2p/crypto/[crypto, secp],
|
||||
libp2p/multiaddress,
|
||||
libp2pdht/discv5/[node, routing_table, spr],
|
||||
libp2pdht/discv5/crypto as dhtcrypto,
|
||||
libp2pdht/discv5/protocol as discv5_protocol,
|
||||
libp2p/crypto/crypto,
|
||||
libp2p/multiaddress
|
||||
stew/shims/net
|
||||
|
||||
export net
|
||||
|
||||
proc localAddress*(port: int): Address =
|
||||
Address(ip: ValidIpAddress.init("127.0.0.1"), port: Port(port))
|
||||
|
||||
proc example*(T: type PrivateKey, rng: ref HmacDrbgContext): PrivateKey =
|
||||
PrivateKey.random(rng[]).expect("Valid rng for private key")
|
||||
|
||||
proc example*(T: type NodeId, rng: ref HmacDrbgContext): NodeId =
|
||||
let
|
||||
privKey = PrivateKey.example(rng)
|
||||
pubKey = privKey.getPublicKey.expect("Valid private key for public key")
|
||||
pubKey.toNodeId().expect("Public key valid for node id")
|
||||
|
||||
proc initDiscoveryNode*(
|
||||
rng: ref BrHmacDrbgContext,
|
||||
privKey: keys.PrivateKey,
|
||||
privKey: PrivateKey,
|
||||
address: Address,
|
||||
bootstrapRecords: openArray[SignedPeerRecord] = [],
|
||||
localEnrFields: openArray[(string, seq[byte])] = [],
|
||||
@ -41,7 +52,7 @@ proc nodeIdInNodes*(id: NodeId, nodes: openArray[Node]): bool =
|
||||
for n in nodes:
|
||||
if id == n.id: return true
|
||||
|
||||
proc generateNode*(privKey: keys.PrivateKey, port: int = 20302,
|
||||
proc generateNode*(privKey: PrivateKey, port: int = 20302,
|
||||
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node =
|
||||
let
|
||||
port = Port(port)
|
||||
@ -52,17 +63,20 @@ proc generateNode*(privKey: keys.PrivateKey, port: int = 20302,
|
||||
proc generateNRandomNodes*(rng: ref BrHmacDrbgContext, n: int): seq[Node] =
|
||||
var res = newSeq[Node]()
|
||||
for i in 1..n:
|
||||
let node = generateNode(keys.PrivateKey.random(rng[]))
|
||||
let
|
||||
privKey = PrivateKey.example(rng)
|
||||
node = privKey.generateNode()
|
||||
res.add(node)
|
||||
res
|
||||
|
||||
proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
|
||||
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, keys.PrivateKey) =
|
||||
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, PrivateKey) =
|
||||
while true:
|
||||
let pk = keys.PrivateKey.random(rng)
|
||||
let node = generateNode(pk, ip = ip)
|
||||
let
|
||||
privKey = PrivateKey.random(rng).expect("Valid rng for private key")
|
||||
node = privKey.generateNode(ip = ip)
|
||||
if logDistance(n.id, node.id) == d:
|
||||
return (node, pk)
|
||||
return (node, privKey)
|
||||
|
||||
proc nodeAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
|
||||
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node =
|
||||
@ -98,7 +112,7 @@ func udpExamples*(_: type MultiAddress, count: int): seq[MultiAddress] =
|
||||
res.add Multiaddress.init("/ip4/0.0.0.0/udp/" & $i).get
|
||||
return res
|
||||
|
||||
proc toSignedPeerRecord*(privKey: crypto.PrivateKey) : SignedPeerRecord =
|
||||
proc toSignedPeerRecord*(privKey: PrivateKey) : SignedPeerRecord =
|
||||
## handle conversion between the two worlds
|
||||
|
||||
let pr = PeerRecord.init(
|
||||
@ -109,7 +123,7 @@ proc toSignedPeerRecord*(privKey: crypto.PrivateKey) : SignedPeerRecord =
|
||||
|
||||
proc example*(T: type SignedPeerRecord): T =
|
||||
let
|
||||
rng = crypto.newRng()
|
||||
privKey = crypto.PrivateKey.random(rng[]).expect("Valid rng")
|
||||
rng = newRng()
|
||||
privKey = PrivateKey.example(rng)
|
||||
|
||||
privKey.toSignedPeerRecord
|
||||
|
||||
@ -10,32 +10,30 @@
|
||||
{.used.}
|
||||
|
||||
import
|
||||
std/options,
|
||||
std/sequtils,
|
||||
chronos, stew/byteutils, nimcrypto, asynctest,
|
||||
eth/keys,
|
||||
libp2pdht/dht,
|
||||
std/[options, sequtils],
|
||||
asynctest,
|
||||
bearssl,
|
||||
chronicles,
|
||||
chronos,
|
||||
nimcrypto,
|
||||
libp2p/crypto/[crypto, secp],
|
||||
libp2p/[multiaddress, multicodec, multihash, routing_record, signed_envelope],
|
||||
libp2pdht/dht,
|
||||
libp2pdht/discv5/crypto as dhtcrypto,
|
||||
libp2pdht/discv5/protocol as discv5_protocol,
|
||||
test_helper,
|
||||
libp2p/crypto/crypto,
|
||||
libp2p/crypto/secp,
|
||||
libp2p/routing_record,
|
||||
libp2p/multiaddress,
|
||||
libp2p/multihash,
|
||||
libp2p/multicodec,
|
||||
libp2p/signed_envelope
|
||||
stew/byteutils,
|
||||
test_helper
|
||||
|
||||
proc bootstrapNodes(
|
||||
nodecount: int,
|
||||
bootnodes: seq[SignedPeerRecord],
|
||||
rng = keys.newRng(),
|
||||
rng = newRng(),
|
||||
delay: int = 0
|
||||
) : Future[seq[(discv5_protocol.Protocol, keys.PrivateKey)]] {.async.} =
|
||||
) : Future[seq[(discv5_protocol.Protocol, PrivateKey)]] {.async.} =
|
||||
|
||||
debug "---- STARTING BOOSTRAPS ---"
|
||||
for i in 0..<nodecount:
|
||||
let privKey = keys.PrivateKey.random(rng[])
|
||||
let privKey = PrivateKey.example(rng)
|
||||
let node = initDiscoveryNode(rng, privKey, localAddress(20302 + i), bootnodes)
|
||||
node.start()
|
||||
result.add((node, privKey))
|
||||
@ -47,13 +45,14 @@ proc bootstrapNodes(
|
||||
|
||||
proc bootstrapNetwork(
|
||||
nodecount: int,
|
||||
rng = keys.newRng(),
|
||||
rng = newRng(),
|
||||
delay: int = 0
|
||||
) : Future[seq[(discv5_protocol.Protocol, keys.PrivateKey)]] {.async.} =
|
||||
) : Future[seq[(discv5_protocol.Protocol, PrivateKey)]] {.async.} =
|
||||
|
||||
let
|
||||
bootNodeKey = keys.PrivateKey.fromHex(
|
||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
|
||||
bootNodeKey = PrivateKey.fromHex(
|
||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")
|
||||
.expect("Valid private key hex")
|
||||
bootNodeAddr = localAddress(20301)
|
||||
bootNode = initDiscoveryNode(rng, bootNodeKey, bootNodeAddr, @[]) # just a shortcut for new and open
|
||||
|
||||
@ -66,30 +65,23 @@ proc bootstrapNetwork(
|
||||
res.insert((bootNode, bootNodeKey), 0)
|
||||
return res
|
||||
|
||||
# TODO: Remove this once we have removed all traces of nim-eth/keys
|
||||
func pkToPk(pk: keys.PrivateKey) : Option[crypto.PrivateKey] =
|
||||
let res = some(crypto.PrivateKey.init((secp.SkPrivateKey)(pk)))
|
||||
return res
|
||||
|
||||
|
||||
# suite "Providers Tests":
|
||||
suite "Providers Tests: node alone":
|
||||
var
|
||||
rng: ref HmacDrbgContext
|
||||
nodes: seq[(discv5_protocol.Protocol, keys.PrivateKey)]
|
||||
nodes: seq[(discv5_protocol.Protocol, PrivateKey)]
|
||||
targetId: NodeId
|
||||
node0: discv5_protocol.Protocol
|
||||
privKey_keys0: keys.PrivateKey
|
||||
privKey0: crypto.PrivateKey
|
||||
privKey0: PrivateKey
|
||||
signedPeerRec0: SignedPeerRecord
|
||||
peerRec0: PeerRecord
|
||||
|
||||
setupAll:
|
||||
rng = keys.newRng()
|
||||
rng = newRng()
|
||||
nodes = await bootstrapNetwork(nodecount=1)
|
||||
targetId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
||||
(node0, privKey_keys0) = nodes[0]
|
||||
privKey0 = privKey_keys0.pkToPk.get
|
||||
targetId = NodeId.example(rng)
|
||||
(node0, privKey0) = nodes[0]
|
||||
signedPeerRec0 = privKey0.toSignedPeerRecord
|
||||
peerRec0 = signedPeerRec0.data
|
||||
|
||||
@ -122,7 +114,7 @@ suite "Providers Tests: node alone":
|
||||
|
||||
test "Should not retrieve bogus":
|
||||
|
||||
let bogusId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
||||
let bogusId = NodeId.example(rng)
|
||||
|
||||
debug "---- STARTING PROVIDERS LOOKUP ---"
|
||||
let providersRes = await node0.getProviders(bogusId)
|
||||
@ -138,20 +130,18 @@ suite "Providers Tests: two nodes":
|
||||
|
||||
var
|
||||
rng: ref HmacDrbgContext
|
||||
nodes: seq[(discv5_protocol.Protocol, keys.PrivateKey)]
|
||||
nodes: seq[(discv5_protocol.Protocol, PrivateKey)]
|
||||
targetId: NodeId
|
||||
node0: discv5_protocol.Protocol
|
||||
privKey_keys0: keys.PrivateKey
|
||||
privKey0: crypto.PrivateKey
|
||||
privKey0: PrivateKey
|
||||
signedPeerRec0: SignedPeerRecord
|
||||
peerRec0: PeerRecord
|
||||
|
||||
setupAll:
|
||||
rng = keys.newRng()
|
||||
rng = newRng()
|
||||
nodes = await bootstrapNetwork(nodecount=3)
|
||||
targetId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
||||
(node0, privKey_keys0) = nodes[0]
|
||||
privKey0 = privKey_keys0.pkToPk.get
|
||||
targetId = NodeId.example(rng)
|
||||
(node0, privKey0) = nodes[0]
|
||||
signedPeerRec0 = privKey0.toSignedPeerRecord
|
||||
peerRec0 = signedPeerRec0.data
|
||||
|
||||
@ -185,26 +175,22 @@ suite "Providers Tests: two nodes":
|
||||
debug "Providers:", providers
|
||||
check (providers.len == 1 and providers[0].data.peerId == peerRec0.peerId)
|
||||
|
||||
|
||||
|
||||
suite "Providers Tests: 20 nodes":
|
||||
|
||||
var
|
||||
rng: ref HmacDrbgContext
|
||||
nodes: seq[(discv5_protocol.Protocol, keys.PrivateKey)]
|
||||
nodes: seq[(discv5_protocol.Protocol, PrivateKey)]
|
||||
targetId: NodeId
|
||||
node0: discv5_protocol.Protocol
|
||||
privKey_keys0: keys.PrivateKey
|
||||
privKey0: crypto.PrivateKey
|
||||
privKey0: PrivateKey
|
||||
signedPeerRec0: SignedPeerRecord
|
||||
peerRec0: PeerRecord
|
||||
|
||||
setupAll:
|
||||
rng = keys.newRng()
|
||||
rng = newRng()
|
||||
nodes = await bootstrapNetwork(nodecount=20)
|
||||
targetId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
||||
(node0, privKey_keys0) = nodes[0]
|
||||
privKey0 = privKey_keys0.pkToPk.get
|
||||
targetId = NodeId.example(rng)
|
||||
(node0, privKey0) = nodes[0]
|
||||
signedPeerRec0 = privKey0.toSignedPeerRecord
|
||||
peerRec0 = signedPeerRec0.data
|
||||
|
||||
|
||||
@ -4,8 +4,9 @@ import
|
||||
std/tables,
|
||||
chronos, chronicles, stint, asynctest, stew/shims/net,
|
||||
stew/byteutils, bearssl,
|
||||
eth/keys,
|
||||
libp2p/crypto/crypto,
|
||||
libp2pdht/discv5/[transport, spr, node, routing_table, encoding, sessions, messages, nodes_verification],
|
||||
libp2pdht/discv5/crypto as dhtcrypto,
|
||||
libp2pdht/discv5/protocol as discv5_protocol,
|
||||
../dht/test_helper
|
||||
|
||||
@ -13,18 +14,21 @@ suite "Discovery v5 Tests":
|
||||
var rng: ref HmacDrbgContext
|
||||
|
||||
setup:
|
||||
rng = keys.newRng()
|
||||
rng = newRng()
|
||||
|
||||
test "GetNode":
|
||||
# TODO: This could be tested in just a routing table only context
|
||||
let
|
||||
node = initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
targetNode = generateNode(keys.PrivateKey.random(rng[]))
|
||||
pk = PrivateKey.example(rng)
|
||||
targetPk = PrivateKey.example(rng)
|
||||
node = initDiscoveryNode(rng, pk, localAddress(20302))
|
||||
targetNode = targetPk.generateNode()
|
||||
|
||||
check node.addNode(targetNode)
|
||||
|
||||
for i in 0..<1000:
|
||||
discard node.addNode(generateNode(keys.PrivateKey.random(rng[])))
|
||||
let pk = PrivateKey.example(rng)
|
||||
discard node.addNode(pk.generateNode())
|
||||
|
||||
let n = node.getNode(targetNode.id)
|
||||
check n.isSome()
|
||||
@ -34,13 +38,14 @@ suite "Discovery v5 Tests":
|
||||
|
||||
test "Node deletion":
|
||||
let
|
||||
pkBootnode = PrivateKey.example(rng)
|
||||
bootnode = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
rng, PrivateKey.example(rng), localAddress(20301))
|
||||
node1 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302),
|
||||
rng, PrivateKey.example(rng), localAddress(20302),
|
||||
@[bootnode.localNode.record])
|
||||
node2 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20303),
|
||||
rng, PrivateKey.example(rng), localAddress(20303),
|
||||
@[bootnode.localNode.record])
|
||||
pong1 = await discv5_protocol.ping(node1, bootnode.localNode)
|
||||
pong2 = await discv5_protocol.ping(node1, node2.localNode)
|
||||
@ -88,58 +93,64 @@ suite "Discovery v5 Tests":
|
||||
# Values for this test are taken from
|
||||
# https://github.com/ethereum/go-ethereum/blob/d8ff53dfb8a516f47db37dbc7fd7ad18a1e8a125/p2p/discover/v4_lookup_test.go#L176
|
||||
const
|
||||
targetKey = "5d485bdcbe9bc89314a10ae9231e429d33853e3a8fa2af39f5f827370a2e4185e344ace5d16237491dad41f278f1d3785210d29ace76cd627b9147ee340b1125"
|
||||
targetKey = "045d485bdcbe9bc89314a10ae9231e429d33853e3a8fa2af39f5f827370a2e4185e344ace5d16237491dad41f278f1d3785210d29ace76cd627b9147ee340b1125"
|
||||
testValues = [
|
||||
("29738ba0c1a4397d6a65f292eee07f02df8e58d41594ba2be3cf84ce0fc58169", 251'u16),
|
||||
("511b1686e4e58a917f7f848e9bf5539d206a68f5ad6b54b552c2399fe7d174ae", 251'u16),
|
||||
("d09e5eaeec0fd596236faed210e55ef45112409a5aa7f3276d26646080dcfaeb", 251'u16),
|
||||
("c1e20dbbf0d530e50573bd0a260b32ec15eb9190032b4633d44834afc8afe578", 251'u16),
|
||||
("ed5f38f5702d92d306143e5d9154fb21819777da39af325ea359f453d179e80b", 251'u16),
|
||||
("14a98db9b46a831d67eff29f3b85b1b485bb12ae9796aea98d91be3dc78d8a91", 248'u16),
|
||||
|
||||
("1c9b1cafbec00848d2c174b858219914b42a7d5c9359b1ca03fd650e8239ae94", 252'u16),
|
||||
("e0e1e8db4a6f13c1ffdd3e96b72fa7012293ced187c9dcdcb9ba2af37a46fa10", 252'u16),
|
||||
("3d53823e0a0295cb09f3e11d16c1b44d07dd37cec6f739b8df3a590189fe9fb9", 252'u16),
|
||||
("29738ba0c1a4397d6a65f292eee07f02df8e58d41594ba2be3cf84ce0fc58169", 252'u16),
|
||||
("dec742079ec00ff4ec1284d7905bc3de2366f67a0769431fd16f80fd68c58a7c", 252'u16),
|
||||
|
||||
("2d0511ae9bf590166597eeab86b6f27b1ab761761eaea8965487b162f8703847", 253'u16),
|
||||
("6cfbd7b8503073fc3dbdb746a7c672571648d3bd15197ccf7f7fef3d904f53a2", 253'u16),
|
||||
("a30599b12827b69120633f15b98a7f6bc9fc2e9a0fd6ae2ebb767c0e64d743ab", 253'u16),
|
||||
("14a98db9b46a831d67eff29f3b85b1b485bb12ae9796aea98d91be3dc78d8a91", 253'u16),
|
||||
("2369ff1fc1ff8ca7d20b17e2673adc3365c3674377f21c5d9dafaff21fe12e24", 253'u16),
|
||||
("9ae91101d6b5048607f41ec0f690ef5d09507928aded2410aabd9237aa2727d7", 253'u16),
|
||||
("05e3c59090a3fd1ae697c09c574a36fcf9bedd0afa8fe3946f21117319ca4973", 253'u16),
|
||||
("06f31c5ea632658f718a91a1b1b9ae4b7549d7b3bc61cbc2be5f4a439039f3ad", 253'u16),
|
||||
("ce1435a956a98ffec484cd11489c4f165cf1606819ab6b521cee440f0c677e9e", 253'u16),
|
||||
("120260dce739b6f71f171da6f65bc361b5fad51db74cf02d3e973347819a6518", 253'u16),
|
||||
|
||||
("dec742079ec00ff4ec1284d7905bc3de2366f67a0769431fd16f80fd68c58a7c", 254'u16),
|
||||
("ff02c8861fa12fbd129d2a95ea663492ef9c1e51de19dcfbbfe1c59894a28d2b", 254'u16),
|
||||
("4dded9e4eefcbce4262be4fd9e8a773670ab0b5f448f286ec97dfc8cf681444a", 254'u16),
|
||||
("750d931e2a8baa2c9268cb46b7cd851f4198018bed22f4dceb09dd334a2395f6", 254'u16),
|
||||
("ce1435a956a98ffec484cd11489c4f165cf1606819ab6b521cee440f0c677e9e", 254'u16),
|
||||
("a30599b12827b69120633f15b98a7f6bc9fc2e9a0fd6ae2ebb767c0e64d743ab", 254'u16),
|
||||
("8c5b422155d33ea8e9d46f71d1ad3e7b24cb40051413ffa1a81cff613d243ba9", 254'u16),
|
||||
("996e7f8d1638be92d7328b4770f47e5420fc4bafecb4324fd33b1f5d9f403a75", 254'u16),
|
||||
("46bd1eddcf6431bea66fc19ebc45df191c1c7d6ed552dcdc7392885009c322f0", 254'u16),
|
||||
|
||||
("da8645f90826e57228d9ea72aff84500060ad111a5d62e4af831ed8e4b5acfb8", 255'u16),
|
||||
("3c944c5d9af51d4c1d43f5d0f3a1a7ef65d5e82744d669b58b5fed242941a566", 255'u16),
|
||||
("5ebcde76f1d579eebf6e43b0ffe9157e65ffaa391175d5b9aa988f47df3e33da", 255'u16),
|
||||
("d09e5eaeec0fd596236faed210e55ef45112409a5aa7f3276d26646080dcfaeb", 255'u16),
|
||||
("6cfbd7b8503073fc3dbdb746a7c672571648d3bd15197ccf7f7fef3d904f53a2", 255'u16),
|
||||
("9ae91101d6b5048607f41ec0f690ef5d09507928aded2410aabd9237aa2727d7", 255'u16),
|
||||
("06f31c5ea632658f718a91a1b1b9ae4b7549d7b3bc61cbc2be5f4a439039f3ad", 255'u16),
|
||||
("97f78253a7d1d796e4eaabce721febcc4550dd68fb11cc818378ba807a2cb7de", 255'u16),
|
||||
("a38cd7dc9b4079d1c0406afd0fdb1165c285f2c44f946eca96fc67772c988c7d", 255'u16),
|
||||
("d64cbb3ffdf712c372b7a22a176308ef8f91861398d5dbaf326fd89c6eaeef1c", 255'u16),
|
||||
("d269609743ef29d6446e3355ec647e38d919c82a4eb5837e442efd7f4218944f", 255'u16),
|
||||
("d8f7bcc4a530efde1d143717007179e0d9ace405ddaaf151c4d863753b7fd64c", 255'u16),
|
||||
("1fa56cf25d4b46c2bf94e82355aa631717b63190785ac6bae545a88aadc304a9", 255'u16),
|
||||
("3c38c503c0376f9b4adcbe935d5f4b890391741c764f61b03cd4d0d42deae002", 255'u16),
|
||||
("3a54af3e9fa162bc8623cdf3e5d9b70bf30ade1d54cc3abea8659aba6cff471f", 255'u16),
|
||||
|
||||
("8c5b422155d33ea8e9d46f71d1ad3e7b24cb40051413ffa1a81cff613d243ba9", 256'u16),
|
||||
("511b1686e4e58a917f7f848e9bf5539d206a68f5ad6b54b552c2399fe7d174ae", 256'u16),
|
||||
("c1e20dbbf0d530e50573bd0a260b32ec15eb9190032b4633d44834afc8afe578", 256'u16),
|
||||
("ed5f38f5702d92d306143e5d9154fb21819777da39af325ea359f453d179e80b", 256'u16),
|
||||
("1c9b1cafbec00848d2c174b858219914b42a7d5c9359b1ca03fd650e8239ae94", 256'u16),
|
||||
("e0e1e8db4a6f13c1ffdd3e96b72fa7012293ced187c9dcdcb9ba2af37a46fa10", 256'u16),
|
||||
("3d53823e0a0295cb09f3e11d16c1b44d07dd37cec6f739b8df3a590189fe9fb9", 256'u16),
|
||||
("2d0511ae9bf590166597eeab86b6f27b1ab761761eaea8965487b162f8703847", 256'u16),
|
||||
("2369ff1fc1ff8ca7d20b17e2673adc3365c3674377f21c5d9dafaff21fe12e24", 256'u16),
|
||||
("05e3c59090a3fd1ae697c09c574a36fcf9bedd0afa8fe3946f21117319ca4973", 256'u16),
|
||||
("ff02c8861fa12fbd129d2a95ea663492ef9c1e51de19dcfbbfe1c59894a28d2b", 256'u16),
|
||||
("4dded9e4eefcbce4262be4fd9e8a773670ab0b5f448f286ec97dfc8cf681444a", 256'u16),
|
||||
("750d931e2a8baa2c9268cb46b7cd851f4198018bed22f4dceb09dd334a2395f6", 256'u16),
|
||||
("46bd1eddcf6431bea66fc19ebc45df191c1c7d6ed552dcdc7392885009c322f0", 256'u16),
|
||||
("da8645f90826e57228d9ea72aff84500060ad111a5d62e4af831ed8e4b5acfb8", 256'u16),
|
||||
("3c944c5d9af51d4c1d43f5d0f3a1a7ef65d5e82744d669b58b5fed242941a566", 256'u16),
|
||||
("5ebcde76f1d579eebf6e43b0ffe9157e65ffaa391175d5b9aa988f47df3e33da", 256'u16),
|
||||
("a38cd7dc9b4079d1c0406afd0fdb1165c285f2c44f946eca96fc67772c988c7d", 256'u16),
|
||||
("d64cbb3ffdf712c372b7a22a176308ef8f91861398d5dbaf326fd89c6eaeef1c", 255'u16),
|
||||
("d269609743ef29d6446e3355ec647e38d919c82a4eb5837e442efd7f4218944f", 256'u16),
|
||||
("937b1af801def4e8f5a3a8bd225a8bcff1db764e41d3e177f2e9376e8dd87233", 256'u16),
|
||||
("120260dce739b6f71f171da6f65bc361b5fad51db74cf02d3e973347819a6518", 256'u16),
|
||||
("1fa56cf25d4b46c2bf94e82355aa631717b63190785ac6bae545a88aadc304a9", 256'u16),
|
||||
("3c38c503c0376f9b4adcbe935d5f4b890391741c764f61b03cd4d0d42deae002", 256'u16),
|
||||
("3a54af3e9fa162bc8623cdf3e5d9b70bf30ade1d54cc3abea8659aba6cff471f", 256'u16),
|
||||
("6799a02ea1999aefdcbcc4d3ff9544478be7365a328d0d0f37c26bd95ade0cda", 256'u16),
|
||||
("e24a7bc9051058f918646b0f6e3d16884b2a55a15553b89bab910d55ebc36116", 256'u16)
|
||||
]
|
||||
|
||||
let targetId = toNodeId(keys.PublicKey.fromHex(targetKey)[])
|
||||
let
|
||||
targetPubKey = PublicKey.fromHex(targetKey).expect("Valid public key hex")
|
||||
targetId = targetPubKey.toNodeId().expect("Public key valid for node id")
|
||||
|
||||
for (key, d) in testValues:
|
||||
let id = toNodeId(keys.PrivateKey.fromHex(key)[].toPublicKey())
|
||||
let
|
||||
privKey = PrivateKey.fromHex(key).expect("Valid private key hex")
|
||||
pubKey = privKey.getPublicKey.expect("Valid private key for public key")
|
||||
id = pubKey.toNodeId.expect("Public key valid for node id")
|
||||
debugEcho ">>> key: ", key
|
||||
check logDistance(targetId, id) == d
|
||||
|
||||
test "Distance to id check":
|
||||
@ -160,17 +171,19 @@ suite "Discovery v5 Tests":
|
||||
|
||||
test "Distance to id check with keys":
|
||||
const
|
||||
targetKey = "5d485bdcbe9bc89314a10ae9231e429d33853e3a8fa2af39f5f827370a2e4185e344ace5d16237491dad41f278f1d3785210d29ace76cd627b9147ee340b1125"
|
||||
targetKey = "045d485bdcbe9bc89314a10ae9231e429d33853e3a8fa2af39f5f827370a2e4185e344ace5d16237491dad41f278f1d3785210d29ace76cd627b9147ee340b1125"
|
||||
testValues = [ # possible id in that distance range
|
||||
("9e5b34809116e3790b2258a45e7ef03b11af786503fb1a6d4b4a8ca021ad653c", 251'u16),
|
||||
("925b34809116e3790b2258a45e7ef03b11af786503fb1a6d4b4a8ca021ad653c", 252'u16),
|
||||
("8a5b34809116e3790b2258a45e7ef03b11af786503fb1a6d4b4a8ca021ad653c", 253'u16),
|
||||
("ba5b34809116e3790b2258a45e7ef03b11af786503fb1a6d4b4a8ca021ad653c", 254'u16),
|
||||
("da5b34809116e3790b2258a45e7ef03b11af786503fb1a6d4b4a8ca021ad653c", 255'u16),
|
||||
("1a5b34809116e3790b2258a45e7ef03b11af786503fb1a6d4b4a8ca021ad653c", 256'u16)
|
||||
("cd2c707bdcbdf5109c66de68e8f26adec1527d075e0f93df0ad21c72e98b7a4d", 251'u16),
|
||||
("c12c707bdcbdf5109c66de68e8f26adec1527d075e0f93df0ad21c72e98b7a4d", 252'u16),
|
||||
("d92c707bdcbdf5109c66de68e8f26adec1527d075e0f93df0ad21c72e98b7a4d", 253'u16),
|
||||
("e92c707bdcbdf5109c66de68e8f26adec1527d075e0f93df0ad21c72e98b7a4d", 254'u16),
|
||||
("892c707bdcbdf5109c66de68e8f26adec1527d075e0f93df0ad21c72e98b7a4d", 255'u16),
|
||||
("492c707bdcbdf5109c66de68e8f26adec1527d075e0f93df0ad21c72e98b7a4d", 256'u16)
|
||||
]
|
||||
|
||||
let targetId = toNodeId(keys.PublicKey.fromHex(targetKey)[])
|
||||
let
|
||||
targetPubKey = PublicKey.fromHex(targetKey).expect("Valid public key hex")
|
||||
targetId = targetPubKey.toNodeId().expect("Public key valid for node id")
|
||||
|
||||
for (id, d) in testValues:
|
||||
check idAtDistance(targetId, d) == parse(id, UInt256, 16)
|
||||
@ -178,10 +191,12 @@ suite "Discovery v5 Tests":
|
||||
test "FindNode Test":
|
||||
const dist = 253'u16
|
||||
let
|
||||
mainNodeKey = keys.PrivateKey.fromHex(
|
||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
|
||||
testNodeKey = keys.PrivateKey.fromHex(
|
||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")[]
|
||||
mainNodeKey = PrivateKey.fromHex(
|
||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")
|
||||
.expect("Valid private key hex")
|
||||
testNodeKey = PrivateKey.fromHex(
|
||||
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618")
|
||||
.expect("Valid private key hex")
|
||||
mainNode = initDiscoveryNode(rng, mainNodeKey, localAddress(20301))
|
||||
testNode = initDiscoveryNode(rng, testNodeKey, localAddress(20302))
|
||||
# logarithmic distance between mainNode and testNode is 256
|
||||
@ -246,11 +261,11 @@ suite "Discovery v5 Tests":
|
||||
test "FindNode with test table":
|
||||
|
||||
let mainNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301))
|
||||
|
||||
# Generate 1000 random nodes and add to our main node's routing table
|
||||
for i in 0..<1000:
|
||||
discard mainNode.addSeenNode(generateNode(keys.PrivateKey.random(rng[]))) # for testing only!
|
||||
discard mainNode.addSeenNode(generateNode(PrivateKey.example(rng))) # for testing only!
|
||||
|
||||
let
|
||||
neighbours = mainNode.neighbours(mainNode.localNode.id)
|
||||
@ -261,7 +276,7 @@ suite "Discovery v5 Tests":
|
||||
|
||||
let
|
||||
testNode = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302),
|
||||
rng, PrivateKey.example(rng), localAddress(20302),
|
||||
@[mainNode.localNode.record])
|
||||
discovered = await findNode(testNode, mainNode.localNode,
|
||||
@[closestDistance])
|
||||
@ -277,13 +292,13 @@ suite "Discovery v5 Tests":
|
||||
nodeCount = 17
|
||||
|
||||
let bootNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301))
|
||||
bootNode.start()
|
||||
|
||||
var nodes = newSeqOfCap[discv5_protocol.Protocol](nodeCount)
|
||||
nodes.add(bootNode)
|
||||
for i in 1 ..< nodeCount:
|
||||
nodes.add(initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301 + i),
|
||||
nodes.add(initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301 + i),
|
||||
@[bootNode.localNode.record]))
|
||||
|
||||
# Make sure all nodes have "seen" each other by forcing pings
|
||||
@ -317,10 +332,10 @@ suite "Discovery v5 Tests":
|
||||
test "Resolve target":
|
||||
let
|
||||
mainNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301))
|
||||
lookupNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
targetKey = keys.PrivateKey.random(rng[])
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20302))
|
||||
targetKey = PrivateKey.example(rng)
|
||||
targetAddress = localAddress(20303)
|
||||
targetNode = initDiscoveryNode(rng, targetKey, targetAddress)
|
||||
targetId = targetNode.localNode.id
|
||||
@ -400,10 +415,10 @@ suite "Discovery v5 Tests":
|
||||
# We no longer support field filtering
|
||||
# test "Random nodes with spr field filter":
|
||||
# let
|
||||
# lookupNode = initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
# targetNode = generateNode(keys.PrivateKey.random(rng[]))
|
||||
# otherNode = generateNode(keys.PrivateKey.random(rng[]))
|
||||
# anotherNode = generateNode(keys.PrivateKey.random(rng[]))
|
||||
# lookupNode = initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301))
|
||||
# targetNode = generateNode(PrivateKey.example(rng))
|
||||
# otherNode = generateNode(PrivateKey.example(rng))
|
||||
# anotherNode = generateNode(PrivateKey.example(rng))
|
||||
|
||||
# check:
|
||||
# lookupNode.addNode(targetNode)
|
||||
@ -420,7 +435,7 @@ suite "Discovery v5 Tests":
|
||||
|
||||
test "New protocol with spr":
|
||||
let
|
||||
privKey = keys.PrivateKey.random(rng[])
|
||||
privKey = PrivateKey.example(rng)
|
||||
ip = some(ValidIpAddress.init("127.0.0.1"))
|
||||
port = Port(20301)
|
||||
node = newProtocol(privKey, ip, some(port), some(port), bindPort = port,
|
||||
@ -441,16 +456,16 @@ suite "Discovery v5 Tests":
|
||||
|
||||
# Defect (for now?) on incorrect key use
|
||||
expect ResultDefect:
|
||||
let incorrectKeyUpdates = newProtocol(keys.PrivateKey.random(rng[]),
|
||||
let incorrectKeyUpdates = newProtocol(PrivateKey.example(rng),
|
||||
ip, some(port), some(port), bindPort = port, rng = rng,
|
||||
previousRecord = some(updatesNode.getRecord()))
|
||||
|
||||
test "Update node record with revalidate":
|
||||
let
|
||||
mainNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301))
|
||||
testNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20302))
|
||||
testNodeId = testNode.localNode.id
|
||||
|
||||
check:
|
||||
@ -482,9 +497,9 @@ suite "Discovery v5 Tests":
|
||||
test "Update node record with handshake":
|
||||
let
|
||||
mainNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20301))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20301))
|
||||
testNode =
|
||||
initDiscoveryNode(rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
initDiscoveryNode(rng, PrivateKey.example(rng), localAddress(20302))
|
||||
testNodeId = testNode.localNode.id
|
||||
|
||||
# Add the node (from the record, so new node!) so no handshake is done yet.
|
||||
@ -515,18 +530,20 @@ suite "Discovery v5 Tests":
|
||||
test "Verify records of nodes message":
|
||||
let
|
||||
port = Port(9000)
|
||||
fromNoderecord = SignedPeerRecord.init(1, keys.PrivateKey.random(rng[]),
|
||||
fromNoderecord = SignedPeerRecord.init(1, PrivateKey.example(rng),
|
||||
some(ValidIpAddress.init("11.12.13.14")),
|
||||
some(port), some(port))[]
|
||||
fromNode = newNode(fromNoderecord)[]
|
||||
pk = keys.PrivateKey.random(rng[])
|
||||
targetDistance = @[logDistance(fromNode.id, pk.toPublicKey().toNodeId())]
|
||||
privKey = PrivateKey.example(rng)
|
||||
pubKey = privKey.getPublicKey.expect("Valid private key for public key")
|
||||
nodeId = pubKey.toNodeId().expect("Public key valid for node id")
|
||||
targetDistance = @[logDistance(fromNode.id, nodeId)]
|
||||
limit = 16
|
||||
|
||||
block: # Duplicates
|
||||
let
|
||||
record = SignedPeerRecord.init(
|
||||
1, pk, some(ValidIpAddress.init("12.13.14.15")),
|
||||
1, privKey, some(ValidIpAddress.init("12.13.14.15")),
|
||||
some(port), some(port))[]
|
||||
|
||||
# Exact duplicates
|
||||
@ -536,7 +553,7 @@ suite "Discovery v5 Tests":
|
||||
|
||||
# Node id duplicates
|
||||
let recordSameId = SignedPeerRecord.init(
|
||||
1, pk, some(ValidIpAddress.init("212.13.14.15")),
|
||||
1, privKey, some(ValidIpAddress.init("212.13.14.15")),
|
||||
some(port), some(port))[]
|
||||
records.add(recordSameId)
|
||||
nodes = verifyNodesRecords(records, fromNode, limit, targetDistance)
|
||||
@ -545,7 +562,7 @@ suite "Discovery v5 Tests":
|
||||
block: # No address
|
||||
let
|
||||
recordNoAddress = SignedPeerRecord.init(
|
||||
1, pk, none(ValidIpAddress), some(port), some(port))[]
|
||||
1, privKey, none(ValidIpAddress), some(port), some(port))[]
|
||||
records = [recordNoAddress]
|
||||
test = verifyNodesRecords(records, fromNode, limit, targetDistance)
|
||||
check test.len == 0
|
||||
@ -553,7 +570,7 @@ suite "Discovery v5 Tests":
|
||||
block: # Invalid address - site local
|
||||
let
|
||||
recordInvalidAddress = SignedPeerRecord.init(
|
||||
1, pk, some(ValidIpAddress.init("10.1.2.3")),
|
||||
1, privKey, some(ValidIpAddress.init("10.1.2.3")),
|
||||
some(port), some(port))[]
|
||||
records = [recordInvalidAddress]
|
||||
test = verifyNodesRecords(records, fromNode, limit, targetDistance)
|
||||
@ -562,7 +579,7 @@ suite "Discovery v5 Tests":
|
||||
block: # Invalid address - loopback
|
||||
let
|
||||
recordInvalidAddress = SignedPeerRecord.init(
|
||||
1, pk, some(ValidIpAddress.init("127.0.0.1")),
|
||||
1, privKey, some(ValidIpAddress.init("127.0.0.1")),
|
||||
some(port), some(port))[]
|
||||
records = [recordInvalidAddress]
|
||||
test = verifyNodesRecords(records, fromNode, limit, targetDistance)
|
||||
@ -571,7 +588,7 @@ suite "Discovery v5 Tests":
|
||||
block: # Invalid distance
|
||||
let
|
||||
recordInvalidDistance = SignedPeerRecord.init(
|
||||
1, pk, some(ValidIpAddress.init("12.13.14.15")),
|
||||
1, privKey, some(ValidIpAddress.init("12.13.14.15")),
|
||||
some(port), some(port))[]
|
||||
records = [recordInvalidDistance]
|
||||
test = verifyNodesRecords(records, fromNode, limit, @[0'u16])
|
||||
@ -580,7 +597,7 @@ suite "Discovery v5 Tests":
|
||||
block: # Invalid distance but distance validation is disabled
|
||||
let
|
||||
recordInvalidDistance = SignedPeerRecord.init(
|
||||
1, pk, some(ValidIpAddress.init("12.13.14.15")),
|
||||
1, privKey, some(ValidIpAddress.init("12.13.14.15")),
|
||||
some(port), some(port))[]
|
||||
records = [recordInvalidDistance]
|
||||
test = verifyNodesRecords(records, fromNode, limit)
|
||||
@ -598,14 +615,14 @@ suite "Discovery v5 Tests":
|
||||
test "Handshake cleanup: different ids":
|
||||
# Node to test the handshakes on.
|
||||
let receiveNode = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
rng, PrivateKey.example(rng), localAddress(20302))
|
||||
|
||||
# Create random packets with same ip but different node ids
|
||||
# and "receive" them on receiveNode
|
||||
let a = localAddress(20303)
|
||||
for i in 0 ..< 5:
|
||||
let
|
||||
privKey = keys.PrivateKey.random(rng[])
|
||||
privKey = PrivateKey.example(rng)
|
||||
enrRec = SignedPeerRecord.init(1, privKey,
|
||||
some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)),
|
||||
some(Port(9000))).expect("Properly intialized private key")
|
||||
@ -629,12 +646,12 @@ suite "Discovery v5 Tests":
|
||||
test "Handshake cleanup: different ips":
|
||||
# Node to test the handshakes on.
|
||||
let receiveNode = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
rng, PrivateKey.example(rng), localAddress(20302))
|
||||
|
||||
# Create random packets with same node ids but different ips
|
||||
# and "receive" them on receiveNode
|
||||
let
|
||||
privKey = keys.PrivateKey.random(rng[])
|
||||
privKey = PrivateKey.example(rng)
|
||||
enrRec = SignedPeerRecord.init(1, privKey,
|
||||
some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)),
|
||||
some(Port(9000))).expect("Properly intialized private key")
|
||||
@ -659,13 +676,13 @@ suite "Discovery v5 Tests":
|
||||
test "Handshake duplicates":
|
||||
# Node to test the handshakes on.
|
||||
let receiveNode = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
rng, PrivateKey.example(rng), localAddress(20302))
|
||||
|
||||
# Create random packets with same node ids and same ips
|
||||
# and "receive" them on receiveNode
|
||||
let
|
||||
a = localAddress(20303)
|
||||
privKey = keys.PrivateKey.random(rng[])
|
||||
privKey = PrivateKey.example(rng)
|
||||
enrRec = SignedPeerRecord.init(1, privKey,
|
||||
some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)),
|
||||
some(Port(9000))).expect("Properly intialized private key")
|
||||
@ -692,9 +709,9 @@ suite "Discovery v5 Tests":
|
||||
test "Talkreq no protocol":
|
||||
let
|
||||
node1 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
rng, PrivateKey.example(rng), localAddress(20302))
|
||||
node2 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20303))
|
||||
rng, PrivateKey.example(rng), localAddress(20303))
|
||||
talkresp = await discv5_protocol.talkReq(node1, node2.localNode,
|
||||
@[byte 0x01], @[])
|
||||
|
||||
@ -708,9 +725,9 @@ suite "Discovery v5 Tests":
|
||||
test "Talkreq echo protocol":
|
||||
let
|
||||
node1 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
rng, PrivateKey.example(rng), localAddress(20302))
|
||||
node2 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20303))
|
||||
rng, PrivateKey.example(rng), localAddress(20303))
|
||||
talkProtocol = "echo".toBytes()
|
||||
|
||||
proc handler(protocol: TalkProtocol, request: seq[byte], fromId: NodeId, fromUdpAddress: Address): seq[byte]
|
||||
@ -733,9 +750,9 @@ suite "Discovery v5 Tests":
|
||||
test "Talkreq register protocols":
|
||||
let
|
||||
node1 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20302))
|
||||
rng, PrivateKey.example(rng), localAddress(20302))
|
||||
node2 = initDiscoveryNode(
|
||||
rng, keys.PrivateKey.random(rng[]), localAddress(20303))
|
||||
rng, PrivateKey.example(rng), localAddress(20303))
|
||||
talkProtocol = "echo".toBytes()
|
||||
|
||||
proc handler(protocol: TalkProtocol, request: seq[byte], fromId: NodeId, fromUdpAddress: Address): seq[byte]
|
||||
|
||||
@ -2,13 +2,20 @@
|
||||
|
||||
import
|
||||
std/[options, sequtils, tables],
|
||||
chronos,
|
||||
asynctest/unittest2,
|
||||
stint, stew/byteutils, stew/shims/net,
|
||||
eth/[keys,rlp],
|
||||
bearssl,
|
||||
chronos,
|
||||
eth/rlp,
|
||||
libp2p/crypto/secp,
|
||||
libp2pdht/discv5/[messages, messages_encoding, encoding, spr, node, sessions],
|
||||
libp2pdht/discv5/crypto,
|
||||
stew/byteutils,
|
||||
stew/shims/net,
|
||||
stint,
|
||||
../dht/test_helper
|
||||
|
||||
from secp256k1 import toRaw
|
||||
|
||||
suite "Discovery v5.1 Protocol Message Encodings":
|
||||
test "Ping Request":
|
||||
let
|
||||
@ -89,15 +96,15 @@ suite "Discovery v5.1 Protocol Message Encodings":
|
||||
|
||||
test "Nodes Response (multiple)":
|
||||
var s1, s2: SignedPeerRecord
|
||||
check s1.fromURI("spr:CiQIARIgWu2YZ5TQVW1gWEfvQijVHqSBtjCbwDt9VppJvYpHX9wSAgMBGlUKJgAkCAESIFrtmGeU0FVtYFhH70Io1R6kgbYwm8A7fVaaSb2KR1_cEKz1xZEGGgsKCQQAAAAAkQIAARoLCgkEAAAAAJECAAIaCwoJBAAAAACRAgADKkAjkK9DeWc82uzd1AEjRr-ksQyRiQ7vYGV4Af3FAEi0JgHvMC8RCQdqn2wBYxvBcyO8o1XMEEKCG01AUZrJlCkD")
|
||||
check s2.fromURI("spr:CiQIARIguW3cNKnlvRsJVmV0ddgFMmvfAQLi0zf4tlt_6WGA03YSAgMBGlUKJgAkCAESILlt3DSp5b0bCVZldHXYBTJr3wEC4tM3-LZbf-lhgNN2EKz1xZEGGgsKCQQAAAAAkQIAARoLCgkEAAAAAJECAAIaCwoJBAAAAACRAgADKkC4Y9NkDHf-71LOvZon0NjmyzQnkm4IlAJGMDPS0cbSgIF3-2cECC5mRiXHjcHWlI5hPpxUURxFyIgSp7XX1jIL")
|
||||
check s1.fromURI("spr:CiUIAhIhAjOdSH7SNzktg3kZUNyJHwY23mmMH6BR6gGuP6WL14WAEgIDARpWCicAJQgCEiECM51IftI3OS2DeRlQ3IkfBjbeaYwfoFHqAa4_pYvXhYAQnP2JkgYaCwoJBAAAAACRAgABGgsKCQQAAAAAkQIAAhoLCgkEAAAAAJECAAMqRzBFAiEAjMd_0mXjPJVRdLn0ligEiy1ypjlayzDwup2QU2-hpdUCIH-o5bq46N3umISo4kSwmQIo41RrWptoSGMqvZJHluV2")
|
||||
check s2.fromURI("spr:CiUIAhIhAmvtpc_d8c2JEw57W7YJK6wj20oES_hHMoqgMQ3RI6RFEgIDARpWCicAJQgCEiECa-2lz93xzYkTDntbtgkrrCPbSgRL-EcyiqAxDdEjpEUQnP2JkgYaCwoJBAAAAACRAgABGgsKCQQAAAAAkQIAAhoLCgkEAAAAAJECAAMqRjBEAiA9QbGnjF5tmMm08_yyE9wWrk3lChyHFaspxRav5kiLTgIgWEHQnpKz0vGtcse8Bm5WHatXMgiG8_u_Jy0s8XMsolk")
|
||||
let
|
||||
total = 0x1'u32
|
||||
n = NodesMessage(total: total, sprs: @[s1, s2])
|
||||
reqId = RequestId(id: @[1.byte])
|
||||
|
||||
let encoded = encodeMessage(n, reqId)
|
||||
check byteutils.toHex(encoded) == "04f9018f0101f9018ab8c30a24080112205aed986794d0556d605847ef4228d51ea481b6309bc03b7d569a49bd8a475fdc120203011a550a260024080112205aed986794d0556d605847ef4228d51ea481b6309bc03b7d569a49bd8a475fdc10acf5c591061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a402390af4379673cdaecddd4012346bfa4b10c91890eef60657801fdc50048b42601ef302f1109076a9f6c01631bc17323bca355cc1042821b4d40519ac9942903b8c30a2408011220b96ddc34a9e5bd1b0956657475d805326bdf0102e2d337f8b65b7fe96180d376120203011a550a26002408011220b96ddc34a9e5bd1b0956657475d805326bdf0102e2d337f8b65b7fe96180d37610acf5c591061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a40b863d3640c77feef52cebd9a27d0d8e6cb3427926e089402463033d2d1c6d2808177fb6704082e664625c78dc1d6948e613e9c54511c45c88812a7b5d7d6320b"
|
||||
check byteutils.toHex(encoded) == "04f901a00101f9019bb8cc0a250802122102339d487ed237392d83791950dc891f0636de698c1fa051ea01ae3fa58bd78580120203011a560a2700250802122102339d487ed237392d83791950dc891f0636de698c1fa051ea01ae3fa58bd78580109cfd8992061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a4730450221008cc77fd265e33c955174b9f49628048b2d72a6395acb30f0ba9d90536fa1a5d502207fa8e5bab8e8ddee9884a8e244b0990228e3546b5a9b6848632abd924796e576b8cb0a2508021221026beda5cfddf1cd89130e7b5bb6092bac23db4a044bf847328aa0310dd123a445120203011a560a27002508021221026beda5cfddf1cd89130e7b5bb6092bac23db4a044bf847328aa0310dd123a445109cfd8992061a0b0a090400000000910200011a0b0a090400000000910200021a0b0a090400000000910200032a46304402203d41b1a78c5e6d98c9b4f3fcb213dc16ae4de50a1c8715ab29c516afe6488b4e02205841d09e92b3d2f1ad72c7bc066e561dab57320886f3fbbf272d2cf1732ca259"
|
||||
|
||||
let decoded = decodeMessage(encoded)
|
||||
check decoded.isOk()
|
||||
@ -177,9 +184,9 @@ suite "Discovery v5.1 Cryptographic Primitives Test Vectors":
|
||||
sharedSecret = "0x033b11a2a1f214567e1537ce5e509ffd9b21373247f2a3ff6841f4976f53165e7e"
|
||||
|
||||
let
|
||||
pub = keys.PublicKey.fromHex(publicKey)[]
|
||||
priv = keys.PrivateKey.fromHex(secretKey)[]
|
||||
eph = ecdhRawFull(priv, pub)
|
||||
pub = PublicKey.fromHex(publicKey).expect("Valid public key hex")
|
||||
priv = PrivateKey.fromHex(secretKey).expect("Valid private key hex")
|
||||
eph = ecdhRaw(priv, pub).expect("Valid public and private keys")
|
||||
check:
|
||||
eph.data == hexToSeqByte(sharedSecret)
|
||||
|
||||
@ -198,9 +205,10 @@ suite "Discovery v5.1 Cryptographic Primitives Test Vectors":
|
||||
let secrets = deriveKeys(
|
||||
NodeId.fromHex(nodeIdA),
|
||||
NodeId.fromHex(nodeIdB),
|
||||
keys.PrivateKey.fromHex(ephemeralKey)[],
|
||||
keys.PublicKey.fromHex(destPubkey)[],
|
||||
hexToSeqByte(challengeData))
|
||||
PrivateKey.fromHex(ephemeralKey).expect("Valid private key hex"),
|
||||
PublicKey.fromHex(destPubkey).expect("Valid public key hex"),
|
||||
hexToSeqByte(challengeData)
|
||||
).expect("Valid key structure")
|
||||
|
||||
check:
|
||||
secrets.initiatorKey == hexToByteArray[aesKeySize](initiatorKey)
|
||||
@ -214,20 +222,23 @@ suite "Discovery v5.1 Cryptographic Primitives Test Vectors":
|
||||
ephemeralPubkey = "0x039961e4c2356d61bedb83052c115d311acb3a96f5777296dcf297351130266231"
|
||||
nodeIdB = "0xbbbb9d047f0488c0b5a93c1c3f2d8bafc7c8ff337024a55434a0d0555de64db9"
|
||||
# expected output
|
||||
idSignature = "0x94852a1e2318c4e5e9d422c98eaf19d1d90d876b29cd06ca7cb7546d0fff7b484fe86c09a064fe72bdbef73ba8e9c34df0cd2b53e9d65528c2c7f336d5dfc6e6"
|
||||
idSignature = "0xdb0ae930a460fd767cb26a519221e6be5edc3501865406d8af6d215f87ebf35b07563d891082d97147d9499f49bb86ee399f57367af1b866674f9e54760e3a21"
|
||||
|
||||
let
|
||||
privKey = keys.PrivateKey.fromHex(staticKey)[]
|
||||
privKey = PrivateKey.fromHex(staticKey).expect("Valid private key hex")
|
||||
signature = createIdSignature(
|
||||
privKey,
|
||||
hexToSeqByte(challengeData),
|
||||
hexToSeqByte(ephemeralPubkey),
|
||||
NodeId.fromHex(nodeIdB))
|
||||
NodeId.fromHex(nodeIdB)
|
||||
).expect("Valid signature data")
|
||||
libp2pSig = SkSignature.init(signature.data).expect("Valid sig data")
|
||||
skSig = secp256k1.SkSignature(libp2pSig)
|
||||
check:
|
||||
signature.toRaw() == hexToByteArray[64](idSignature)
|
||||
skSig.toRaw() == hexToByteArray[64](idSignature)
|
||||
verifyIdSignature(signature, hexToSeqByte(challengeData),
|
||||
hexToSeqByte(ephemeralPubkey), NodeId.fromHex(nodeIdB),
|
||||
privKey.toPublicKey())
|
||||
privKey.getPublicKey.expect("Valid private key for public key"))
|
||||
|
||||
test "Encryption/Decryption":
|
||||
const
|
||||
@ -249,17 +260,19 @@ suite "Discovery v5.1 Cryptographic Primitives Test Vectors":
|
||||
# https://github.com/ethereum/devp2p/blob/master/discv5/discv5-wire-test-vectors.md#packet-encodings
|
||||
suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
const
|
||||
nodeAKey = "0xeef77acb6c6a6eebc5b363a475ac583ec7eccdb42b6481424c60f59aa326547f"
|
||||
nodeBKey = "0x66fb62bfbd66b9177a138c1e5cddbe4f7c30c343e94e68df8769459cb1cde628"
|
||||
nodeAKey = "0xfe5f08c842aa946659b266ce68faa5d2fd982634594dccdf7f916e3fcf0541a3"
|
||||
nodeBKey = "0x00064765abe9a4e63b068b5af99c26c61c8ade9bfdae6494873b137ec8152578"
|
||||
|
||||
var
|
||||
codecA, codecB: Codec
|
||||
nodeA, nodeB: Node
|
||||
privKeyA, privKeyB: keys.PrivateKey
|
||||
privKeyA, privKeyB: PrivateKey
|
||||
|
||||
setup:
|
||||
privKeyA = keys.PrivateKey.fromHex(nodeAKey)[] # sender -> encode
|
||||
privKeyB = keys.PrivateKey.fromHex(nodeBKey)[] # receive -> decode
|
||||
# sender -> encode
|
||||
privKeyA = PrivateKey.fromHex(nodeAKey).expect("Valid private key hex")
|
||||
# receive -> decode
|
||||
privKeyB = PrivateKey.fromHex(nodeBKey).expect("Valid private key hex")
|
||||
|
||||
let
|
||||
enrRecA = SignedPeerRecord.init(1, privKeyA,
|
||||
@ -284,9 +297,9 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
pingSprSeq = 2'u64
|
||||
|
||||
encodedPacket =
|
||||
"00000000000000000000000000000000088b3d4342774649325f313964a39e55" &
|
||||
"ea96c005ad52be8c7560413a7008f16c9e6d2f43bbea8814a546b7409ce783d3" &
|
||||
"4c4f53245d08dab84102ed931f66d1492acb308fa1c6715b9d139b81acbdcc"
|
||||
"000000000000000000000000000000003788c1e1079e89374c4beac74d76364d" &
|
||||
"bd9e8cd1847adc2f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
|
||||
"7afd279a5fe4ffdded6d1a6d388217da82d38761b60b0c6e9dd94a8713bc5d"
|
||||
|
||||
let dummyKey = "0x00000000000000000000000000000001" # of no importance
|
||||
codecA.sessions.store(nodeB.id, nodeB.address.get(),
|
||||
@ -311,8 +324,8 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
whoareyouSprSeq = 0
|
||||
|
||||
encodedPacket =
|
||||
"00000000000000000000000000000000088b3d434277464933a1ccc59f5967ad" &
|
||||
"1d6035f15e528627dde75cd68292f9e6c27d6b66c8100a873fcbaed4e16b8d"
|
||||
"000000000000000000000000000000003788c1e1079e89374d4beac74d76364d" &
|
||||
"bd9e8cd1847ae48d2f96e595c7a904454033dd25eaefc076a4537f17e8a43a"
|
||||
|
||||
let decoded = codecB.decodePacket(nodeA.address.get(),
|
||||
hexToSeqByte(encodedPacket))
|
||||
@ -341,13 +354,13 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
whoareyouSprSeq = 1'u64
|
||||
|
||||
encodedPacket =
|
||||
"00000000000000000000000000000000088b3d4342774649305f313964a39e55" &
|
||||
"ea96c005ad521d8c7560413a7008f16c9e6d2f43bbea8814a546b7409ce783d3" &
|
||||
"4c4f53245d08da4bb252012b2cba3f4f374a90a75cff91f142fa9be3e0a5f3ef" &
|
||||
"268ccb9065aeecfd67a999e7fdc137e062b2ec4a0eb92947f0d9a74bfbf44dfb" &
|
||||
"a776b21301f8b65efd5796706adff216ab862a9186875f9494150c4ae06fa4d1" &
|
||||
"f0396c93f215fa4ef524f1eadf5f0f4126b79336671cbcf7a885b1f8bd2a5d83" &
|
||||
"9cf8"
|
||||
"000000000000000000000000000000003788c1e1079e89374e4beac74d76364d" &
|
||||
"bd9e8cd1847a712f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
|
||||
"7afd279a5fe4ff441af3b17ec968350f37edbda9e0ba8ac0fd2617ef67a1e362" &
|
||||
"5ea8eb284a3ca85f7ef976ccf2e87932ffeada775849d7aca378033b7a75dbe8" &
|
||||
"7cc1767123bb7d7e5d96b5d6ad7c26cb55f6160b250d042ef1b9e6000191ce4e" &
|
||||
"a93234ca3de051518684902e70e6a47eb8f0c2efeca8e42d2ea7f5bd1f27c12d" &
|
||||
"ae3c579ddcef630659089c99"
|
||||
|
||||
let
|
||||
whoareyouData = WhoareyouData(
|
||||
@ -355,7 +368,9 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
idNonce: hexToByteArray[idNonceSize](whoareyouIdNonce),
|
||||
recordSeq: whoareyouSprSeq,
|
||||
challengeData: hexToSeqByte(whoareyouChallengeData))
|
||||
pubkey = some(privKeyA.toPublicKey())
|
||||
pubkey = privKeyA.getPublicKey
|
||||
.expect("Valid private key for public key")
|
||||
.some
|
||||
challenge = Challenge(whoareyouData: whoareyouData, pubkey: pubkey)
|
||||
key = HandshakeKey(nodeId: nodeA.id, address: nodeA.address.get())
|
||||
|
||||
@ -387,18 +402,18 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
whoareyouSprSeq = 0'u64
|
||||
|
||||
encodedPacket =
|
||||
"2746cce362989b5d7e2496490b25f952e9198c524b06c7e9e069c5f7c8d2c84b" &
|
||||
"943322ac741826023cb35086eee94baaf98f81217c3dbcb022afb1464555b144" &
|
||||
"69b49cb19fe1f3459b4bbb03a52fc588bcc69d7ff50842ee6c3fc3ffd58d425f" &
|
||||
"e8c7bec9777fcb15d9c9e37c4aa3b226274f6631526d6d2127f39e1daff277fd" &
|
||||
"e867a8222ae509922d9e94456f7cbde14c1788894708713789b28b307ac983c8" &
|
||||
"31ebc00113ded4011af2bfa06078c8f0a3401e8c034b3ae5506fb002a0355bf1" &
|
||||
"48b19022bae8b088a0c0bdc22dc3d5ce4a6c5ad700a3f8a82be214c2bef98afe" &
|
||||
"2dbf4ffaaf816602d470dcfe8184b1db8d873d8813984f86b6350ff5d00d466c" &
|
||||
"06de59f1797ad01a68bb9c07b9cb56e6989ab0e94d32c60e435a48aa7c89d602" &
|
||||
"3863bd1605a33f895903657fe72f79ded24b366486a1c02a893702ec7d299ea8" &
|
||||
"7afe0bb771fad244b8d4d0bd7bf4dc833a17c4db2f926eb7614788308a6f98af" &
|
||||
"9a0e20bd75af75175645058702122b15"
|
||||
"000000000000000000000000000000003788c1e1079e89374e4beac74d76364d" &
|
||||
"bd9e8cd1847bc02f49fbacc6862425583586c023b19b6fdd1d836777ee39fee8" &
|
||||
"7afd279a5fe4ff451af3b07ec8407cedec19c57a8460e08d3d8a908f78261170" &
|
||||
"68196e7df56279e7493fbb2076025b395dde6ffeecc45daa59def06c9be97b1f" &
|
||||
"95636fb8f16887cf13b4a8cca0bcaf805fe62529ad86c59204e73917cf183d19" &
|
||||
"847617448722cc8c0eea80b68653e858eff5d250abbd55315db21fac1485db8f" &
|
||||
"deaadba582d43c88f0b25512a5fd8395bd2f9519362d29cceb29028de04e0076" &
|
||||
"4f6aece318e26e2d123888e484cb1c0ce37ecfee42ced9a811966bae40f40e9d" &
|
||||
"4b46e27c388330304409a405b6455547661361d2129aa7bed4ff26f68d53532d" &
|
||||
"cb6bae00506a7c5161b0652afcbf2416e97116bdcf9a7a548d6d8b5b0ab2ed0e" &
|
||||
"b7a737afc0dbf65f32fd22c27cb17ebfe3c0d43e9bf45cfd24170c9fea348b10" &
|
||||
"1207010ad51e28040b46770c1e96e22e7c552a6f1a62b4e29f8c99"
|
||||
|
||||
let
|
||||
whoareyouData = WhoareyouData(
|
||||
@ -406,7 +421,7 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
idNonce: hexToByteArray[idNonceSize](whoareyouIdNonce),
|
||||
recordSeq: whoareyouSprSeq,
|
||||
challengeData: hexToSeqByte(whoareyouChallengeData))
|
||||
pubkey = none(keys.PublicKey)
|
||||
pubkey = none(PublicKey)
|
||||
challenge = Challenge(whoareyouData: whoareyouData, pubkey: pubkey)
|
||||
key = HandshakeKey(nodeId: nodeA.id, address: nodeA.address.get())
|
||||
|
||||
@ -426,7 +441,7 @@ suite "Discovery v5.1 Packet Encodings Test Vectors":
|
||||
hexToSeqByte(encodedPacket & "00")).isErr()
|
||||
|
||||
suite "Discovery v5.1 Additional Encode/Decode":
|
||||
var rng = keys.newRng()
|
||||
var rng = newRng()
|
||||
|
||||
test "Encryption/Decryption":
|
||||
let
|
||||
@ -467,8 +482,7 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
var nonce: AESGCMNonce
|
||||
brHmacDrbgGenerate(rng[], nonce)
|
||||
let
|
||||
privKey = keys.PrivateKey.random(rng[])
|
||||
nodeId = privKey.toPublicKey().toNodeId()
|
||||
nodeId = NodeId.example(rng)
|
||||
authdata = newSeq[byte](32)
|
||||
staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce,
|
||||
authdata.len())
|
||||
@ -486,11 +500,11 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
var
|
||||
codecA, codecB: Codec
|
||||
nodeA, nodeB: Node
|
||||
privKeyA, privKeyB: keys.PrivateKey
|
||||
privKeyA, privKeyB: PrivateKey
|
||||
|
||||
setup:
|
||||
privKeyA = keys.PrivateKey.random(rng[]) # sender -> encode
|
||||
privKeyB = keys.PrivateKey.random(rng[]) # receiver -> decode
|
||||
privKeyA = PrivateKey.example(rng) # sender -> encode
|
||||
privKeyB = PrivateKey.example(rng) # receiver -> decode
|
||||
|
||||
let
|
||||
enrRecA = SignedPeerRecord.init(1, privKeyA,
|
||||
@ -528,7 +542,7 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
let recordSeq = 0'u64
|
||||
|
||||
let data = encodeWhoareyouPacket(rng[], codecA, nodeB.id,
|
||||
nodeB.address.get(), requestNonce, recordSeq, none(keys.PublicKey))
|
||||
nodeB.address.get(), requestNonce, recordSeq, none(PublicKey))
|
||||
|
||||
let decoded = codecB.decodePacket(nodeA.address.get(), data)
|
||||
|
||||
@ -551,7 +565,9 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
m = PingMessage(sprSeq: 0)
|
||||
reqId = RequestId.init(rng[])
|
||||
message = encodeMessage(m, reqId)
|
||||
pubkey = some(privKeyA.toPublicKey())
|
||||
pubkey = privKeyA.getPublicKey
|
||||
.expect("Valid private key for public key")
|
||||
.some
|
||||
|
||||
# Encode/decode whoareyou packet to get the handshake stored and the
|
||||
# whoareyou data returned. It's either that or construct the header for the
|
||||
@ -561,9 +577,12 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
nodeA.address.get(), requestNonce, recordSeq, pubkey)
|
||||
decodedDummy = codecA.decodePacket(nodeB.address.get(), encodedDummy)
|
||||
|
||||
let data = encodeHandshakePacket(rng[], codecA, nodeB.id,
|
||||
nodeB.address.get(), message, decodedDummy[].whoareyou,
|
||||
privKeyB.toPublicKey())
|
||||
let
|
||||
pubKeyB = privKeyB.getPublicKey.expect("Valid private key for public key")
|
||||
data = encodeHandshakePacket(rng[], codecA, nodeB.id,
|
||||
nodeB.address.get(), message, decodedDummy[].whoareyou,
|
||||
pubKeyB
|
||||
).expect("Valid handshake packet data")
|
||||
|
||||
let decoded = codecB.decodePacket(nodeA.address.get(), data)
|
||||
|
||||
@ -582,7 +601,7 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
m = PingMessage(sprSeq: 0)
|
||||
reqId = RequestId.init(rng[])
|
||||
message = encodeMessage(m, reqId)
|
||||
pubkey = none(keys.PublicKey)
|
||||
pubkey = none(PublicKey)
|
||||
|
||||
# Encode/decode whoareyou packet to get the handshake stored and the
|
||||
# whoareyou data returned. It's either that or construct the header for the
|
||||
@ -592,9 +611,12 @@ suite "Discovery v5.1 Additional Encode/Decode":
|
||||
nodeA.address.get(), requestNonce, recordSeq, pubkey)
|
||||
decodedDummy = codecA.decodePacket(nodeB.address.get(), encodedDummy)
|
||||
|
||||
let encoded = encodeHandshakePacket(rng[], codecA, nodeB.id,
|
||||
nodeB.address.get(), message, decodedDummy[].whoareyou,
|
||||
privKeyB.toPublicKey())
|
||||
let
|
||||
pubKeyB = privKeyB.getPublicKey.expect("Valid private key for public key")
|
||||
encoded = encodeHandshakePacket(rng[], codecA, nodeB.id,
|
||||
nodeB.address.get(), message, decodedDummy[].whoareyou,
|
||||
pubKeyB
|
||||
).expect("Valid handshake packet data")
|
||||
|
||||
let decoded = codecB.decodePacket(nodeA.address.get(), encoded)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user