bearssl: use split api (#510)

This commit is contained in:
Jacek Sieka 2022-06-17 22:45:37 +02:00 committed by GitHub
parent 8761ea3222
commit 1b516682bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 206 additions and 246 deletions

View File

@ -16,12 +16,13 @@
import import
std/strformat, std/strformat,
secp256k1, bearssl, stew/[byteutils, objects, results], secp256k1, bearssl/hash as bhash, bearssl/rand,
stew/[byteutils, objects, results],
nimcrypto/[hash, keccak] nimcrypto/[hash, keccak]
from nimcrypto/utils import burnMem from nimcrypto/utils import burnMem
export secp256k1, results, bearssl export secp256k1, results, rand
const const
KeyLength* = SkEcdhRawSecretSize - 1 KeyLength* = SkEcdhRawSecretSize - 1
@ -51,24 +52,15 @@ type
template pubkey*(v: KeyPair): PublicKey = PublicKey(SkKeyPair(v).pubkey) template pubkey*(v: KeyPair): PublicKey = PublicKey(SkKeyPair(v).pubkey)
template seckey*(v: KeyPair): PrivateKey = PrivateKey(SkKeyPair(v).seckey) template seckey*(v: KeyPair): PrivateKey = PrivateKey(SkKeyPair(v).seckey)
proc newRng*(): ref BrHmacDrbgContext = proc newRng*(): ref HmacDrbgContext =
# You should only create one instance of the RNG per application / library # You should only create one instance of the RNG per application / library
# Ref is used so that it can be shared between components # Ref is used so that it can be shared between components
# TODO consider moving to bearssl HmacDrbgContext.new()
var seeder = brPrngSeederSystem(nil)
if seeder == nil:
return nil
var rng = (ref BrHmacDrbgContext)() proc random*(T: type PrivateKey, rng: var HmacDrbgContext): T =
brHmacDrbgInit(addr rng[], addr sha256Vtable, nil, 0)
if seeder(addr rng.vtable) == 0:
return nil
rng
proc random*(T: type PrivateKey, rng: var BrHmacDrbgContext): T =
let rngPtr = unsafeAddr rng # doesn't escape let rngPtr = unsafeAddr rng # doesn't escape
proc callRng(data: var openArray[byte]) = proc callRng(data: var openArray[byte]) =
brHmacDrbgGenerate(rngPtr[], data) generate(rngPtr[], data)
T(SkSecretKey.random(callRng)) T(SkSecretKey.random(callRng))
@ -106,7 +98,7 @@ func toRaw*(pubkey: PublicKey): array[RawPublicKeySize, byte] =
func toRawCompressed*(pubkey: PublicKey): array[33, byte] {.borrow.} func toRawCompressed*(pubkey: PublicKey): array[33, byte] {.borrow.}
proc random*(T: type KeyPair, rng: var BrHmacDrbgContext): T = proc random*(T: type KeyPair, rng: var HmacDrbgContext): T =
let seckey = SkSecretKey(PrivateKey.random(rng)) let seckey = SkSecretKey(PrivateKey.random(rng))
KeyPair(SkKeyPair( KeyPair(SkKeyPair(
seckey: seckey, seckey: seckey,

View File

@ -9,7 +9,7 @@
import import
std/[tables, algorithm, random], std/[tables, algorithm, random],
bearssl, chronos, chronos/timer, chronicles, chronos, chronos/timer, chronicles,
./keys, ./common/eth_types, ./p2p/private/p2p_types, ./keys, ./common/eth_types, ./p2p/private/p2p_types,
./p2p/[kademlia, discovery, enode, peer_pool, rlpx] ./p2p/[kademlia, discovery, enode, peer_pool, rlpx]

View File

@ -13,8 +13,8 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
nimcrypto/[rijndael, keccak, utils], bearssl, nimcrypto/[rijndael, keccak, utils],
stew/[byteutils, endians2, objects, results], stew/[arrayops, byteutils, endians2, objects, results],
".."/[keys, rlp], ".."/[keys, rlp],
./ecies ./ecies
@ -88,15 +88,11 @@ type
template toa(a, b, c: untyped): untyped = template toa(a, b, c: untyped): untyped =
toOpenArray((a), (b), (b) + (c) - 1) toOpenArray((a), (b), (b) + (c) - 1)
proc `xor`[N: static int](a, b: array[N, byte]): array[N, byte] =
for i in 0 ..< len(a):
result[i] = a[i] xor b[i]
proc mapErrTo[T, E](r: Result[T, E], v: static AuthError): AuthResult[T] = proc mapErrTo[T, E](r: Result[T, E], v: static AuthError): AuthResult[T] =
r.mapErr(proc (e: E): AuthError = v) r.mapErr(proc (e: E): AuthError = v)
proc init*( proc init*(
T: type Handshake, rng: var BrHmacDrbgContext, host: KeyPair, T: type Handshake, rng: var HmacDrbgContext, host: KeyPair,
flags: set[HandshakeFlag] = {Initiator}, flags: set[HandshakeFlag] = {Initiator},
version: uint8 = SupportedRlpxVersion): T = version: uint8 = SupportedRlpxVersion): T =
## Create new `Handshake` object. ## Create new `Handshake` object.
@ -108,10 +104,10 @@ proc init*(
if Initiator in flags: if Initiator in flags:
expectedLength = AckMessageV4Length expectedLength = AckMessageV4Length
brHmacDrbgGenerate(rng, initiatorNonce) rng.generate(initiatorNonce)
else: else:
expectedLength = AuthMessageV4Length expectedLength = AuthMessageV4Length
brHmacDrbgGenerate(rng, responderNonce) rng.generate(responderNonce)
return T( return T(
version: version, version: version,
@ -124,7 +120,7 @@ proc init*(
) )
proc authMessagePreEIP8(h: var Handshake, proc authMessagePreEIP8(h: var Handshake,
rng: var BrHmacDrbgContext, rng: var HmacDrbgContext,
pubkey: PublicKey, pubkey: PublicKey,
output: var openArray[byte], output: var openArray[byte],
outlen: var int, outlen: var int,
@ -163,7 +159,7 @@ proc authMessagePreEIP8(h: var Handshake,
ok() ok()
proc authMessageEIP8(h: var Handshake, proc authMessageEIP8(h: var Handshake,
rng: var BrHmacDrbgContext, rng: var HmacDrbgContext,
pubkey: PublicKey, pubkey: PublicKey,
output: var openArray[byte], output: var openArray[byte],
outlen: var int, outlen: var int,
@ -172,7 +168,6 @@ proc authMessageEIP8(h: var Handshake,
## Create EIP8 authentication message. ## Create EIP8 authentication message.
var var
buffer: array[PlainAuthMessageMaxEIP8, byte] buffer: array[PlainAuthMessageMaxEIP8, byte]
padsize: array[1, byte]
doAssert(EIP8 in h.flags) doAssert(EIP8 in h.flags)
outlen = 0 outlen = 0
@ -192,29 +187,33 @@ proc authMessageEIP8(h: var Handshake,
let let
pencsize = eciesEncryptedLength(len(payload)) pencsize = eciesEncryptedLength(len(payload))
while true: var padsize = int(rng.generate(byte)) # aka rand(max)
brHmacDrbgGenerate(rng, padsize) while padsize <= (AuthMessageV4Length - (pencsize + 2)):
if int(padsize[0]) > (AuthMessageV4Length - (pencsize + 2)): padsize = int(rng.generate(byte))
break
# It is possible to make packet size constant by uncommenting this line # It is possible to make packet size constant by uncommenting this line
# padsize = 24 # padsize = 24
let wosize = pencsize + int(padsize[0]) let
let fullsize = wosize + 2 wosize = pencsize + padsize
brHmacDrbgGenerate( fullsize = wosize + 2
rng, toa(buffer, PlainAuthMessageEIP8Length, int(padsize[0])))
rng.generate(toa(buffer, PlainAuthMessageEIP8Length, padsize))
if encrypt: if encrypt:
copyMem(addr buffer[0], addr payload[0], len(payload))
if len(output) < fullsize: if len(output) < fullsize:
return err(BufferOverrun) return err(BufferOverrun)
copyMem(addr buffer[0], addr payload[0], len(payload))
let wosizeBE = uint16(wosize).toBytesBE() let wosizeBE = uint16(wosize).toBytesBE()
output[0..<2] = wosizeBE output[0..<2] = wosizeBE
if eciesEncrypt(rng, toa(buffer, 0, len(payload) + int(padsize[0])), if eciesEncrypt(rng, toa(buffer, 0, len(payload) + padsize),
toa(output, 2, wosize), pubkey, toa(output, 2, wosize), pubkey,
toa(output, 0, 2)).isErr: toa(output, 0, 2)).isErr:
return err(EciesError) return err(EciesError)
outlen = fullsize outlen = fullsize
else: else:
let plainsize = len(payload) + int(padsize[0]) let plainsize = len(payload) + padsize
if len(output) < plainsize: if len(output) < plainsize:
return err(BufferOverrun) return err(BufferOverrun)
copyMem(addr output[0], addr buffer[0], plainsize) copyMem(addr output[0], addr buffer[0], plainsize)
@ -223,7 +222,7 @@ proc authMessageEIP8(h: var Handshake,
ok() ok()
proc ackMessagePreEIP8(h: var Handshake, proc ackMessagePreEIP8(h: var Handshake,
rng: var BrHmacDrbgContext, rng: var HmacDrbgContext,
output: var openArray[byte], output: var openArray[byte],
outlen: var int, outlen: var int,
flag: byte = 0, flag: byte = 0,
@ -250,7 +249,7 @@ proc ackMessagePreEIP8(h: var Handshake,
ok() ok()
proc ackMessageEIP8(h: var Handshake, proc ackMessageEIP8(h: var Handshake,
rng: var BrHmacDrbgContext, rng: var HmacDrbgContext,
output: var openArray[byte], output: var openArray[byte],
outlen: var int, outlen: var int,
flag: byte = 0, flag: byte = 0,
@ -267,7 +266,7 @@ proc ackMessageEIP8(h: var Handshake,
outlen = 0 outlen = 0
let pencsize = eciesEncryptedLength(len(payload)) let pencsize = eciesEncryptedLength(len(payload))
while true: while true:
brHmacDrbgGenerate(rng, padsize) generate(rng, padsize)
if int(padsize[0]) > (AckMessageV4Length - (pencsize + 2)): if int(padsize[0]) > (AckMessageV4Length - (pencsize + 2)):
break break
# It is possible to make packet size constant by uncommenting this line # It is possible to make packet size constant by uncommenting this line
@ -275,8 +274,7 @@ proc ackMessageEIP8(h: var Handshake,
let wosize = pencsize + int(padsize[0]) let wosize = pencsize + int(padsize[0])
let fullsize = wosize + 2 let fullsize = wosize + 2
if int(padsize[0]) > 0: if int(padsize[0]) > 0:
brHmacDrbgGenerate( rng.generate(toa(buffer, PlainAckMessageEIP8Length, int(padsize[0])))
rng, toa(buffer, PlainAckMessageEIP8Length, int(padsize[0])))
copyMem(addr buffer[0], addr payload[0], len(payload)) copyMem(addr buffer[0], addr payload[0], len(payload))
if encrypt: if encrypt:
@ -311,7 +309,7 @@ template ackSize*(h: Handshake, encrypt: bool = true): int =
else: else:
if encrypt: (AckMessageV4Length) else: (PlainAckMessageV4Length) if encrypt: (AckMessageV4Length) else: (PlainAckMessageV4Length)
proc authMessage*(h: var Handshake, rng: var BrHmacDrbgContext, proc authMessage*(h: var Handshake, rng: var HmacDrbgContext,
pubkey: PublicKey, pubkey: PublicKey,
output: var openArray[byte], output: var openArray[byte],
outlen: var int, flag: byte = 0, outlen: var int, flag: byte = 0,
@ -323,7 +321,7 @@ proc authMessage*(h: var Handshake, rng: var BrHmacDrbgContext,
else: else:
authMessagePreEIP8(h, rng, pubkey, output, outlen, flag, encrypt) authMessagePreEIP8(h, rng, pubkey, output, outlen, flag, encrypt)
proc ackMessage*(h: var Handshake, rng: var BrHmacDrbgContext, proc ackMessage*(h: var Handshake, rng: var HmacDrbgContext,
output: var openArray[byte], output: var openArray[byte],
outlen: var int, flag: byte = 0, outlen: var int, flag: byte = 0,
encrypt: bool = true): AuthResult[void] = encrypt: bool = true): AuthResult[void] =

View File

@ -9,7 +9,7 @@
import import
std/times, std/times,
chronos, stint, nimcrypto/keccak, chronicles, bearssl, chronos, stint, nimcrypto/keccak, chronicles,
stew/[objects, results], stew/[objects, results],
".."/[keys, rlp], ".."/[keys, rlp],
"."/[kademlia, enode] "."/[kademlia, enode]

View File

@ -15,7 +15,7 @@
import import
std/[tables, options, hashes, net], std/[tables, options, hashes, net],
nimcrypto, stint, chronicles, bearssl, stew/[results, byteutils], metrics, nimcrypto, stint, chronicles, stew/[results, byteutils], metrics,
".."/../[rlp, keys], ".."/../[rlp, keys],
"."/[messages, node, enr, hkdf, sessions] "."/[messages, node, enr, hkdf, sessions]
@ -193,18 +193,19 @@ proc encodeStaticHeader*(flag: Flag, nonce: AESGCMNonce, authSize: int):
# TODO: assert on authSize of > 2^16? # TODO: assert on authSize of > 2^16?
result.add((uint16(authSize)).toBytesBE()) result.add((uint16(authSize)).toBytesBE())
proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec, proc encodeMessagePacket*(rng: var HmacDrbgContext, c: var Codec,
toId: NodeId, toAddr: Address, message: openArray[byte]): toId: NodeId, toAddr: Address, message: openArray[byte]):
(seq[byte], AESGCMNonce) = (seq[byte], AESGCMNonce) =
var nonce: AESGCMNonce let
brHmacDrbgGenerate(rng, nonce) # Random AESGCM nonce nonce = rng.generate(AESGCMNonce) # Random AESGCM nonce
var iv: array[ivSize, byte] iv = rng.generate(array[ivSize, byte]) # Random IV
brHmacDrbgGenerate(rng, iv) # Random IV
# static-header # static-header
let authdata = c.localNode.id.toByteArrayBE() let
let staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce, authdata = c.localNode.id.toByteArrayBE()
authdata.len()) staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce,
authdata.len())
# header = static-header || authdata # header = static-header || authdata
var header: seq[byte] var header: seq[byte]
header.add(staticHeader) header.add(staticHeader)
@ -224,8 +225,7 @@ proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec,
# message. 16 bytes for the gcm tag and 4 bytes for ping with requestId of # message. 16 bytes for the gcm tag and 4 bytes for ping with requestId of
# 1 byte (e.g "01c20101"). Could increase to 27 for 8 bytes requestId in # 1 byte (e.g "01c20101"). Could increase to 27 for 8 bytes requestId in
# case this must not look like a random packet. # case this must not look like a random packet.
var randomData: array[gcmTagSize + 4, byte] let randomData = rng.generate(array[gcmTagSize + 4, byte])
brHmacDrbgGenerate(rng, randomData)
messageEncrypted.add(randomData) messageEncrypted.add(randomData)
discovery_session_lru_cache_misses.inc() discovery_session_lru_cache_misses.inc()
@ -238,11 +238,11 @@ proc encodeMessagePacket*(rng: var BrHmacDrbgContext, c: var Codec,
return (packet, nonce) return (packet, nonce)
proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec, proc encodeWhoareyouPacket*(rng: var HmacDrbgContext, c: var Codec,
toId: NodeId, toAddr: Address, requestNonce: AESGCMNonce, recordSeq: uint64, toId: NodeId, toAddr: Address, requestNonce: AESGCMNonce, recordSeq: uint64,
pubkey: Option[PublicKey]): seq[byte] = pubkey: Option[PublicKey]): seq[byte] =
var idNonce: IdNonce let
brHmacDrbgGenerate(rng, idNonce) idNonce = rng.generate(IdNonce)
# authdata # authdata
var authdata: seq[byte] var authdata: seq[byte]
@ -258,10 +258,9 @@ proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec,
header.add(staticHeader) header.add(staticHeader)
header.add(authdata) header.add(authdata)
var iv: array[ivSize, byte] let
brHmacDrbgGenerate(rng, iv) # Random IV iv = rng.generate(array[ivSize, byte]) # Random IV
maskedHeader = encryptHeader(toId, iv, header)
let maskedHeader = encryptHeader(toId, iv, header)
var packet: seq[byte] var packet: seq[byte]
packet.add(iv) packet.add(iv)
@ -280,14 +279,12 @@ proc encodeWhoareyouPacket*(rng: var BrHmacDrbgContext, c: var Codec,
return packet return packet
proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec, proc encodeHandshakePacket*(rng: var HmacDrbgContext, c: var Codec,
toId: NodeId, toAddr: Address, message: openArray[byte], toId: NodeId, toAddr: Address, message: openArray[byte],
whoareyouData: WhoareyouData, pubkey: PublicKey): seq[byte] = whoareyouData: WhoareyouData, pubkey: PublicKey): seq[byte] =
var header: seq[byte] let
var nonce: AESGCMNonce nonce = rng.generate(AESGCMNonce)
brHmacDrbgGenerate(rng, nonce) iv = rng.generate(array[ivSize, byte]) # Random IV
var iv: array[ivSize, byte]
brHmacDrbgGenerate(rng, iv) # Random IV
var authdata: seq[byte] var authdata: seq[byte]
var authdataHead: seq[byte] var authdataHead: seq[byte]
@ -316,6 +313,7 @@ proc encodeHandshakePacket*(rng: var BrHmacDrbgContext, c: var Codec,
let staticHeader = encodeStaticHeader(Flag.HandshakeMessage, nonce, let staticHeader = encodeStaticHeader(Flag.HandshakeMessage, nonce,
authdata.len()) authdata.len())
var header: seq[byte]
header.add(staticHeader) header.add(staticHeader)
header.add(authdata) header.add(authdata)
@ -611,9 +609,9 @@ proc decodePacket*(c: var Codec, fromAddr: Address, input: openArray[byte]):
input.toOpenArray(0, ivSize - 1), header, input.toOpenArray(0, ivSize - 1), header,
input.toOpenArray(ivSize + header.len, input.high)) input.toOpenArray(ivSize + header.len, input.high))
proc init*(T: type RequestId, rng: var BrHmacDrbgContext): T = proc init*(T: type RequestId, rng: var HmacDrbgContext): T =
var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes var reqId = RequestId(id: newSeq[byte](8)) # RequestId must be <= 8 bytes
brHmacDrbgGenerate(rng, reqId.id) rng.generate(reqId.id)
reqId reqId
proc numFields(T: typedesc): int = proc numFields(T: typedesc): int =

View File

@ -86,11 +86,8 @@ func `==`*(a, b: Node): bool =
func hash*(id: NodeId): Hash = func hash*(id: NodeId): Hash =
hash(id.toByteArrayBE) hash(id.toByteArrayBE)
proc random*(T: type NodeId, rng: var BrHmacDrbgContext): T = proc random*(T: type NodeId, rng: var HmacDrbgContext): T =
var id: NodeId rng.generate(T)
brHmacDrbgGenerate(addr rng, addr id, csize_t(sizeof(id)))
id
func `$`*(id: NodeId): string = func `$`*(id: NodeId): string =
id.toHex() id.toHex()

View File

@ -83,7 +83,7 @@
import import
std/[tables, sets, options, math, sequtils, algorithm], std/[tables, sets, options, math, sequtils, algorithm],
stew/shims/net as stewNet, json_serialization/std/net, stew/shims/net as stewNet, json_serialization/std/net,
stew/[endians2, results], chronicles, chronos, stint, bearssl, metrics, stew/[endians2, results], chronicles, chronos, stint, metrics,
".."/../[rlp, keys, async_utils], ".."/../[rlp, keys, async_utils],
"."/[messages, encoding, node, routing_table, enr, random2, sessions, ip_vote, "."/[messages, encoding, node, routing_table, enr, random2, sessions, ip_vote,
nodes_verification] nodes_verification]
@ -147,7 +147,7 @@ type
enrAutoUpdate: bool enrAutoUpdate: bool
talkProtocols*: Table[seq[byte], TalkProtocol] # TODO: Table is a bit of talkProtocols*: Table[seq[byte], TalkProtocol] # TODO: Table is a bit of
# overkill here, use sequence # overkill here, use sequence
rng*: ref BrHmacDrbgContext rng*: ref HmacDrbgContext
PendingRequest = object PendingRequest = object
node: Node node: Node

View File

@ -1,22 +1,25 @@
import bearssl import
bearssl/rand
## Random helpers: similar as in stdlib, but with BrHmacDrbgContext rng export rand
## Random helpers: similar as in stdlib, but with HmacDrbgContext rng
# TODO: Move these somewhere else? # TODO: Move these somewhere else?
const randMax = 18_446_744_073_709_551_615'u64 const randMax = 18_446_744_073_709_551_615'u64
proc rand*(rng: var BrHmacDrbgContext, max: Natural): int = proc rand*(rng: var HmacDrbgContext, max: Natural): int =
if max == 0: return 0 if max == 0: return 0
var x: uint64 var x: uint64
while true: while true:
brHmacDrbgGenerate(addr rng, addr x, csize_t(sizeof(x))) rng.generate(x)
if x < randMax - (randMax mod (uint64(max) + 1'u64)): # against modulo bias if x < randMax - (randMax mod (uint64(max) + 1'u64)): # against modulo bias
return int(x mod (uint64(max) + 1'u64)) return int(x mod (uint64(max) + 1'u64))
proc sample*[T](rng: var BrHmacDrbgContext, a: openArray[T]): T = proc sample*[T](rng: var HmacDrbgContext, a: openArray[T]): T =
result = a[rng.rand(a.high)] a[rng.rand(a.high)]
proc shuffle*[T](rng: var BrHmacDrbgContext, a: var openArray[T]) = proc shuffle*[T](rng: var HmacDrbgContext, a: var openArray[T]) =
for i in countdown(a.high, 1): for i in countdown(a.high, 1):
let j = rng.rand(i) let j = rng.rand(i)
swap(a[i], a[j]) swap(a[i], a[j])

View File

@ -9,7 +9,8 @@
import import
std/[algorithm, times, sequtils, bitops, sets, options], std/[algorithm, times, sequtils, bitops, sets, options],
stint, chronicles, metrics, bearssl, chronos, stew/shims/net as stewNet, bearssl/rand,
stint, chronicles, metrics, chronos, stew/shims/net as stewNet,
../../net/utils, ../../net/utils,
"."/[node, random2, enr] "."/[node, random2, enr]
@ -42,7 +43,7 @@ type
ipLimits: IpLimits ## IP limits for total routing table: all buckets and ipLimits: IpLimits ## IP limits for total routing table: all buckets and
## replacement caches. ## replacement caches.
distanceCalculator: DistanceCalculator distanceCalculator: DistanceCalculator
rng: ref BrHmacDrbgContext rng: ref HmacDrbgContext
KBucket = ref object KBucket = ref object
istart, iend: NodeId ## Range of NodeIds this KBucket covers. This is not a istart, iend: NodeId ## Range of NodeIds this KBucket covers. This is not a
@ -260,7 +261,7 @@ proc computeSharedPrefixBits(nodes: openArray[NodeId]): int =
doAssert(false, "Unable to calculate number of shared prefix bits") doAssert(false, "Unable to calculate number of shared prefix bits")
proc init*(T: type RoutingTable, localNode: Node, bitsPerHop = DefaultBitsPerHop, proc init*(T: type RoutingTable, localNode: Node, bitsPerHop = DefaultBitsPerHop,
ipLimits = DefaultTableIpLimits, rng: ref BrHmacDrbgContext, ipLimits = DefaultTableIpLimits, rng: ref HmacDrbgContext,
distanceCalculator = XorDistanceCalculator): T = distanceCalculator = XorDistanceCalculator): T =
## Initialize the routing table for provided `Node` and bitsPerHop value. ## Initialize the routing table for provided `Node` and bitsPerHop value.
## `bitsPerHop` is default set to 5 as recommended by original Kademlia paper. ## `bitsPerHop` is default set to 5 as recommended by original Kademlia paper.

View File

@ -13,7 +13,7 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
bearssl, stew/[results, endians2], stew/[results, endians2],
nimcrypto/[rijndael, bcmode, hash, hmac, sha2, utils], nimcrypto/[rijndael, bcmode, hash, hmac, sha2, utils],
../keys ../keys
@ -93,7 +93,7 @@ proc kdf*(data: openArray[byte]): array[KeyLength, byte] {.noinit.} =
ctx.clear() # clean ctx ctx.clear() # clean ctx
copyMem(addr result[0], addr storage[0], KeyLength) copyMem(addr result[0], addr storage[0], KeyLength)
proc eciesEncrypt*(rng: var BrHmacDrbgContext, input: openArray[byte], proc eciesEncrypt*(rng: var HmacDrbgContext, input: openArray[byte],
output: var openArray[byte], pubkey: PublicKey, output: var openArray[byte], pubkey: PublicKey,
sharedmac: openArray[byte] = emptyMac): EciesResult[void] = sharedmac: openArray[byte] = emptyMac): EciesResult[void] =
## Encrypt data with ECIES method using given public key `pubkey`. ## Encrypt data with ECIES method using given public key `pubkey`.
@ -107,13 +107,10 @@ proc eciesEncrypt*(rng: var BrHmacDrbgContext, input: openArray[byte],
encKey: array[aes128.sizeKey, byte] encKey: array[aes128.sizeKey, byte]
cipher: CTR[aes128] cipher: CTR[aes128]
ctx: HMAC[sha256] ctx: HMAC[sha256]
iv: array[aes128.sizeBlock, byte]
if len(output) < eciesEncryptedLength(len(input)): if len(output) < eciesEncryptedLength(len(input)):
return err(BufferOverrun) return err(BufferOverrun)
brHmacDrbgGenerate(rng, iv)
var var
ephemeral = KeyPair.random(rng) ephemeral = KeyPair.random(rng)
secret = ecdhRaw(ephemeral.seckey, pubkey) secret = ecdhRaw(ephemeral.seckey, pubkey)
@ -130,13 +127,13 @@ proc eciesEncrypt*(rng: var BrHmacDrbgContext, input: openArray[byte],
var header = cast[ptr EciesHeader](addr output[0]) var header = cast[ptr EciesHeader](addr output[0])
header.version = 0x04 header.version = 0x04
header.pubkey = ephemeral.pubkey.toRaw() header.pubkey = ephemeral.pubkey.toRaw()
header.iv = iv rng.generate(header[].iv)
clear(ephemeral) clear(ephemeral)
var so = eciesDataPos() var so = eciesDataPos()
var eo = so + len(input) var eo = so + len(input)
cipher.init(encKey, iv) cipher.init(encKey, header.iv)
cipher.encrypt(input, toOpenArray(output, so, eo)) cipher.encrypt(input, toOpenArray(output, so, eo))
burnMem(encKey) burnMem(encKey)
cipher.clear() cipher.clear()

View File

@ -9,7 +9,7 @@
import import
std/[tables, hashes, times, algorithm, sets, sequtils, random], std/[tables, hashes, times, algorithm, sets, sequtils, random],
chronos, bearssl, chronicles, stint, nimcrypto/keccak, chronos, chronicles, stint, nimcrypto/keccak,
../keys, ../keys,
./enode ./enode
@ -26,7 +26,7 @@ type
pongFutures: Table[seq[byte], Future[bool]] pongFutures: Table[seq[byte], Future[bool]]
pingFutures: Table[Node, Future[bool]] pingFutures: Table[Node, Future[bool]]
neighboursCallbacks: Table[Node, proc(n: seq[Node]) {.gcsafe, raises: [Defect].}] neighboursCallbacks: Table[Node, proc(n: seq[Node]) {.gcsafe, raises: [Defect].}]
rng: ref BrHmacDrbgContext rng: ref HmacDrbgContext
NodeId* = UInt256 NodeId* = UInt256
@ -452,12 +452,7 @@ proc lookup*(k: KademliaProtocol, nodeId: NodeId): Future[seq[Node]] {.async.} =
result = closest result = closest
proc lookupRandom*(k: KademliaProtocol): Future[seq[Node]] = proc lookupRandom*(k: KademliaProtocol): Future[seq[Node]] =
var id: NodeId k.lookup(k.rng[].generate(NodeId))
var buf: array[sizeof(id), byte]
brHmacDrbgGenerate(k.rng[], buf)
copyMem(addr id, addr buf[0], sizeof(id))
k.lookup(id)
proc resolve*(k: KademliaProtocol, id: NodeId): Future[Node] {.async.} = proc resolve*(k: KademliaProtocol, id: NodeId): Future[Node] {.async.} =
let closest = await k.lookup(id) let closest = await k.lookup(id)

View File

@ -8,7 +8,7 @@
import import
std/[deques, tables], std/[deques, tables],
bearssl, chronos, chronos,
stew/results, stew/results,
".."/../[rlp, keys], ".."/../common/eth_types, ".."/../[rlp, keys], ".."/../common/eth_types,
".."/[enode, kademlia, discovery, rlpxcrypt] ".."/[enode, kademlia, discovery, rlpxcrypt]
@ -38,7 +38,7 @@ type
discovery*: DiscoveryProtocol discovery*: DiscoveryProtocol
when useSnappy: when useSnappy:
protocolVersion*: uint protocolVersion*: uint
rng*: ref BrHmacDrbgContext rng*: ref HmacDrbgContext
Peer* = ref object Peer* = ref object
remote*: Node remote*: Node

View File

@ -9,7 +9,7 @@
import import
std/[algorithm, bitops, math, options, tables, times, hashes], std/[algorithm, bitops, math, options, tables, times, hashes],
chronicles, stew/[byteutils, endians2], metrics, bearssl, chronicles, stew/[byteutils, endians2], metrics,
nimcrypto/[bcmode, hash, keccak, rijndael], nimcrypto/[bcmode, hash, keccak, rijndael],
".."/../../[keys, rlp, p2p], ../../ecies ".."/../../[keys, rlp, p2p], ../../ecies
@ -160,10 +160,8 @@ proc topicBloom*(topic: Topic): Bloom =
doAssert idx <= 511 doAssert idx <= 511
result[idx div 8] = result[idx div 8] or byte(1 shl (idx and 7'u16)) result[idx div 8] = result[idx div 8] or byte(1 shl (idx and 7'u16))
proc generateRandomID*(rng: var BrHmacDrbgContext): string = proc generateRandomID*(rng: var HmacDrbgContext): string =
var bytes: array[256 div 8, byte] toHex(rng.generate(array[256 div 8, byte]))
brHmacDrbgGenerate(rng, bytes)
toHex(bytes)
proc `or`(a, b: Bloom): Bloom = proc `or`(a, b: Bloom): Bloom =
for i in 0..<a.len: for i in 0..<a.len:
@ -231,7 +229,7 @@ proc decryptAesGcm(cipher: openArray[byte], key: SymKey): Option[seq[byte]] =
# simply because that makes it closer to EIP 627 - see also: # simply because that makes it closer to EIP 627 - see also:
# https://github.com/paritytech/parity-ethereum/issues/9652 # https://github.com/paritytech/parity-ethereum/issues/9652
proc encode*(rng: var BrHmacDrbgContext, self: Payload): Option[seq[byte]] = proc encode*(rng: var HmacDrbgContext, self: Payload): Option[seq[byte]] =
## Encode a payload according so as to make it suitable to put in an Envelope ## Encode a payload according so as to make it suitable to put in an Envelope
## The format follows EIP 627 - https://eips.ethereum.org/EIPS/eip-627 ## The format follows EIP 627 - https://eips.ethereum.org/EIPS/eip-627
@ -284,7 +282,7 @@ proc encode*(rng: var BrHmacDrbgContext, self: Payload): Option[seq[byte]] =
plain.add self.padding.get() plain.add self.padding.get()
else: else:
var padding = newSeq[byte](padLen) var padding = newSeq[byte](padLen)
brHmacDrbgGenerate(rng, padding) rng.generate(padding)
plain.add padding plain.add padding
@ -302,8 +300,7 @@ proc encode*(rng: var BrHmacDrbgContext, self: Payload): Option[seq[byte]] =
return some(res) return some(res)
if self.symKey.isSome(): # Symmetric key present - encryption requested if self.symKey.isSome(): # Symmetric key present - encryption requested
var iv: array[gcmIVLen, byte] let iv = rng.generate(array[gcmIVLen, byte])
brHmacDrbgGenerate(rng, iv)
return some(encryptAesGcm(plain, self.symKey.get(), iv)) return some(encryptAesGcm(plain, self.symKey.get(), iv))
@ -579,7 +576,7 @@ proc initFilter*(src = none[PublicKey](), privateKey = none[PrivateKey](),
powReq: powReq, allowP2P: allowP2P, bloom: toBloom(topics)) powReq: powReq, allowP2P: allowP2P, bloom: toBloom(topics))
proc subscribeFilter*( proc subscribeFilter*(
rng: var BrHmacDrbgContext, filters: var Filters, filter: Filter, rng: var HmacDrbgContext, filters: var Filters, filter: Filter,
handler: FilterMsgHandler = nil): string = handler: FilterMsgHandler = nil): string =
# NOTE: Should we allow a filter without a key? Encryption is mandatory in v6? # NOTE: Should we allow a filter without a key? Encryption is mandatory in v6?
# Check if asymmetric _and_ symmetric key? Now asymmetric just has precedence. # Check if asymmetric _and_ symmetric key? Now asymmetric just has precedence.

View File

@ -10,10 +10,10 @@ import
std/[monotimes], std/[monotimes],
faststreams, faststreams,
chronos, chronos,
stew/[endians2, results, objects, arrayops], bearssl, stew/[endians2, results, objects, arrayops],
../p2p/discoveryv5/random2 ../p2p/discoveryv5/random2
export results export results, random2
const const
minimalHeaderSize = 20 minimalHeaderSize = 20
@ -80,11 +80,11 @@ proc getMonoTimestamp*(): TimeStampInfo =
TimeStampInfo(moment: currentMoment, timestamp: timestamp) TimeStampInfo(moment: currentMoment, timestamp: timestamp)
# Simple generator, not useful for cryptography # Simple generator, not useful for cryptography
proc randUint16*(rng: var BrHmacDrbgContext): uint16 = proc randUint16*(rng: var HmacDrbgContext): uint16 =
uint16(rand(rng, int(high(uint16)))) uint16(rand(rng, int(high(uint16))))
# Simple generator, not useful for cryptography # Simple generator, not useful for cryptography
proc randUint32*(rng: var BrHmacDrbgContext): uint32 = proc randUint32*(rng: var HmacDrbgContext): uint32 =
uint32(rand(rng, int(high(uint32)))) uint32(rand(rng, int(high(uint32))))
proc encodeTypeVer(h: PacketHeaderV1): uint8 = proc encodeTypeVer(h: PacketHeaderV1): uint8 =

View File

@ -8,7 +8,7 @@
import import
std/[tables, options, hashes, sugar, math], std/[tables, options, hashes, sugar, math],
chronos, chronicles, bearssl, chronos, chronicles,
./utp_router, ./utp_router,
../keys ../keys

View File

@ -8,7 +8,7 @@
import import
std/[tables, options, sugar], std/[tables, options, sugar],
chronos, bearssl, chronicles, metrics, chronos, chronicles, metrics,
../keys, ../keys,
./utp_socket, ./utp_socket,
./packets ./packets
@ -56,7 +56,7 @@ type
closed: bool closed: bool
sendCb*: SendCallback[A] sendCb*: SendCallback[A]
allowConnection*: AllowConnectionCallback[A] allowConnection*: AllowConnectionCallback[A]
rng*: ref BrHmacDrbgContext rng*: ref HmacDrbgContext
const const
# Maximal number of tries to generate unique socket while establishing # Maximal number of tries to generate unique socket while establishing

View File

@ -8,7 +8,7 @@
import import
std/[sugar, deques], std/[sugar, deques],
chronos, chronicles, bearssl, chronos, chronicles,
stew/[results, bitops2], stew/[results, bitops2],
./growable_buffer, ./growable_buffer,
./packets, ./packets,
@ -1880,7 +1880,7 @@ proc newOutgoingSocket*[A](
snd: SendCallback[A], snd: SendCallback[A],
cfg: SocketConfig, cfg: SocketConfig,
rcvConnectionId: uint16, rcvConnectionId: uint16,
rng: var BrHmacDrbgContext rng: var HmacDrbgContext
): UtpSocket[A] = ): UtpSocket[A] =
let sndConnectionId = rcvConnectionId + 1 let sndConnectionId = rcvConnectionId + 1
let initialSeqNr = randUint16(rng) let initialSeqNr = randUint16(rng)
@ -1905,7 +1905,7 @@ proc newIncomingSocket*[A](
cfg: SocketConfig, cfg: SocketConfig,
connectionId: uint16, connectionId: uint16,
ackNr: uint16, ackNr: uint16,
rng: var BrHmacDrbgContext rng: var HmacDrbgContext
): UtpSocket[A] = ): UtpSocket[A] =
let initialSeqNr = randUint16(rng) let initialSeqNr = randUint16(rng)

View File

@ -28,9 +28,9 @@ test:
# It is not the best idea to generate extra data and encrypt data but we do # It is not the best idea to generate extra data and encrypt data but we do
# it like this as the decodeHeader proc does decrypt + decode + decrypt. # it like this as the decodeHeader proc does decrypt + decode + decrypt.
# There is no separate decrypt step that can be skipped because of this. # There is no separate decrypt step that can be skipped because of this.
var iv: array[ivSize, byte] let
brHmacDrbgGenerate(rng[], iv) iv = rng[].generate(array[ivSize, byte])
let maskedHeader = encryptHeader(nodeB.id, iv, payload) maskedHeader = encryptHeader(nodeB.id, iv, payload)
let decoded = decodePacket(codecB, nodeA.address.get(), @iv & maskedHeader) let decoded = decodePacket(codecB, nodeA.address.get(), @iv & maskedHeader)
if decoded.isErr(): if decoded.isErr():

View File

@ -11,7 +11,7 @@
import import
unittest2, unittest2,
nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils, bearssl, stew/byteutils, nimcrypto/hash, nimcrypto/keccak, nimcrypto/utils, stew/byteutils,
../../eth/keys ../../eth/keys
from strutils import toLowerAscii from strutils import toLowerAscii
@ -218,8 +218,7 @@ suite "ECC/ECDSA/ECDHE tests suite":
test "ECDSA/100 signatures": test "ECDSA/100 signatures":
# signature test # signature test
for i in 1..100: for i in 1..100:
var m: array[32, byte] let m = rng[].generate(array[32, byte])
brHmacDrbgGenerate(rng[], m)
var s = PrivateKey.random(rng[]) var s = PrivateKey.random(rng[])
var key = s.toPublicKey() var key = s.toPublicKey()
let sig = sign(s, SkMessage(m)) let sig = sign(s, SkMessage(m))

View File

@ -1,5 +1,5 @@
import import
stew/shims/net, bearssl, chronos, stew/shims/net, chronos,
../../eth/keys, ../../eth/keys,
../../eth/p2p/discoveryv5/[enr, node, routing_table], ../../eth/p2p/discoveryv5/[enr, node, routing_table],
../../eth/p2p/discoveryv5/protocol as discv5_protocol ../../eth/p2p/discoveryv5/protocol as discv5_protocol
@ -10,7 +10,7 @@ proc localAddress*(port: int): Address =
Address(ip: ValidIpAddress.init("127.0.0.1"), port: Port(port)) Address(ip: ValidIpAddress.init("127.0.0.1"), port: Port(port))
proc initDiscoveryNode*( proc initDiscoveryNode*(
rng: ref BrHmacDrbgContext, rng: ref HmacDrbgContext,
privKey: PrivateKey, privKey: PrivateKey,
address: Address, address: Address,
bootstrapRecords: openArray[Record] = [], bootstrapRecords: openArray[Record] = [],
@ -47,14 +47,14 @@ proc generateNode*(privKey: PrivateKey, port: int = 20302,
some(port), some(port), localEnrFields).expect("Properly intialized private key") some(port), some(port), localEnrFields).expect("Properly intialized private key")
result = newNode(enr).expect("Properly initialized node") result = newNode(enr).expect("Properly initialized node")
proc generateNRandomNodes*(rng: ref BrHmacDrbgContext, n: int): seq[Node] = proc generateNRandomNodes*(rng: var HmacDrbgContext, n: int): seq[Node] =
var res = newSeq[Node]() var res = newSeq[Node]()
for i in 1..n: for i in 1..n:
let node = generateNode(PrivateKey.random(rng[])) let node = generateNode(PrivateKey.random(rng))
res.add(node) res.add(node)
res res
proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32, proc nodeAndPrivKeyAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, PrivateKey) = ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, PrivateKey) =
while true: while true:
let pk = PrivateKey.random(rng) let pk = PrivateKey.random(rng)
@ -62,19 +62,19 @@ proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
if logDistance(n.id, node.id) == d: if logDistance(n.id, node.id) == d:
return (node, pk) return (node, pk)
proc nodeAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32, proc nodeAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node = ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node =
let (node, _) = n.nodeAndPrivKeyAtDistance(rng, d, ip) let (node, _) = n.nodeAndPrivKeyAtDistance(rng, d, ip)
node node
proc nodesAtDistance*( proc nodesAtDistance*(
n: Node, rng: var BrHmacDrbgContext, d: uint32, amount: int, n: Node, rng: var HmacDrbgContext, d: uint32, amount: int,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] = ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] =
for i in 0..<amount: for i in 0..<amount:
result.add(nodeAtDistance(n, rng, d, ip)) result.add(nodeAtDistance(n, rng, d, ip))
proc nodesAtDistanceUniqueIp*( proc nodesAtDistanceUniqueIp*(
n: Node, rng: var BrHmacDrbgContext, d: uint32, amount: int, n: Node, rng: var HmacDrbgContext, d: uint32, amount: int,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] = ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] =
var ta = initTAddress(ip, Port(0)) var ta = initTAddress(ip, Port(0))
for i in 0..<amount: for i in 0..<amount:

View File

@ -1,6 +1,6 @@
import import
std/strutils, std/strutils,
chronos, bearssl, chronos,
../../eth/[keys, p2p], ../../eth/p2p/[discovery, enode] ../../eth/[keys, p2p], ../../eth/p2p/[discovery, enode]
var nextPort = 30303 var nextPort = 30303
@ -11,7 +11,7 @@ proc localAddress*(port: int): Address =
ip: parseIpAddress("127.0.0.1")) ip: parseIpAddress("127.0.0.1"))
proc setupTestNode*( proc setupTestNode*(
rng: ref BrHmacDrbgContext, rng: ref HmacDrbgContext,
capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode {.gcsafe.} = capabilities: varargs[ProtocolInfo, `protocolInfo`]): EthereumNode {.gcsafe.} =
# Don't create new RNG every time in production code! # Don't create new RNG every time in production code!
let keys1 = KeyPair.random(rng[]) let keys1 = KeyPair.random(rng[])

View File

@ -3,7 +3,7 @@
import import
std/[tables, sequtils], std/[tables, sequtils],
chronos, chronicles, stint, testutils/unittests, stew/shims/net, chronos, chronicles, stint, testutils/unittests, stew/shims/net,
stew/byteutils, bearssl, stew/byteutils,
../../eth/keys, ../../eth/keys,
../../eth/p2p/discoveryv5/[enr, node, routing_table, encoding, sessions, ../../eth/p2p/discoveryv5/[enr, node, routing_table, encoding, sessions,
messages, nodes_verification], messages, nodes_verification],

View File

@ -456,18 +456,15 @@ suite "Discovery v5.1 Additional Encode/Decode":
check decryptGCM(encryptionKey, nonce, invalidCipher, ad).isNone() check decryptGCM(encryptionKey, nonce, invalidCipher, ad).isNone()
test "Encrypt / Decrypt header": test "Encrypt / Decrypt header":
var nonce: AESGCMNonce
brHmacDrbgGenerate(rng[], nonce)
let let
nonce = rng[].generate(AESGCMNonce)
privKey = PrivateKey.random(rng[]) privKey = PrivateKey.random(rng[])
nodeId = privKey.toPublicKey().toNodeId() nodeId = privKey.toPublicKey().toNodeId()
authdata = newSeq[byte](32) authdata = newSeq[byte](32)
staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce, staticHeader = encodeStaticHeader(Flag.OrdinaryMessage, nonce,
authdata.len()) authdata.len())
header = staticHeader & authdata header = staticHeader & authdata
iv = rng[].generate(array[128 div 8, byte])
var iv: array[128 div 8, byte]
brHmacDrbgGenerate(rng[], iv)
let let
encrypted = encryptHeader(nodeId, iv, header) encrypted = encryptHeader(nodeId, iv, header)
@ -511,8 +508,7 @@ suite "Discovery v5.1 Additional Encode/Decode":
decoded[].requestNonce == nonce decoded[].requestNonce == nonce
test "Encode / Decode Whoareyou Packet": test "Encode / Decode Whoareyou Packet":
var requestNonce: AESGCMNonce let requestNonce = rng[].generate(AESGCMNonce)
brHmacDrbgGenerate(rng[], requestNonce)
let recordSeq = 0'u64 let recordSeq = 0'u64
let data = encodeWhoareyouPacket(rng[], codecA, nodeB.id, let data = encodeWhoareyouPacket(rng[], codecA, nodeB.id,
@ -532,9 +528,8 @@ suite "Discovery v5.1 Additional Encode/Decode":
decoded[].whoareyou.recordSeq == recordSeq decoded[].whoareyou.recordSeq == recordSeq
test "Encode / Decode Handshake Message Packet": test "Encode / Decode Handshake Message Packet":
var requestNonce: AESGCMNonce
brHmacDrbgGenerate(rng[], requestNonce)
let let
requestNonce = rng[].generate(AESGCMNonce)
recordSeq = 1'u64 recordSeq = 1'u64
m = PingMessage(enrSeq: 0) m = PingMessage(enrSeq: 0)
reqId = RequestId.init(rng[]) reqId = RequestId.init(rng[])
@ -563,9 +558,8 @@ suite "Discovery v5.1 Additional Encode/Decode":
decoded.get().node.isNone() decoded.get().node.isNone()
test "Encode / Decode Handshake Message Packet with ENR": test "Encode / Decode Handshake Message Packet with ENR":
var requestNonce: AESGCMNonce
brHmacDrbgGenerate(rng[], requestNonce)
let let
requestNonce = rng[].generate(AESGCMNonce)
recordSeq = 0'u64 recordSeq = 0'u64
m = PingMessage(enrSeq: 0) m = PingMessage(enrSeq: 0)
reqId = RequestId.init(rng[]) reqId = RequestId.init(rng[])

View File

@ -2,7 +2,6 @@
import import
unittest2, unittest2,
bearssl,
../../eth/keys, ../../eth/p2p/discoveryv5/[routing_table, node, enr], ../../eth/keys, ../../eth/p2p/discoveryv5/[routing_table, node, enr],
./discv5_test_helper ./discv5_test_helper
@ -528,7 +527,7 @@ suite "Routing Table Tests":
var table = RoutingTable.init(local, 1, ipLimits, rng = rng, var table = RoutingTable.init(local, 1, ipLimits, rng = rng,
distanceCalculator = customDistanceCalculator) distanceCalculator = customDistanceCalculator)
let nodes = generateNRandomNodes(rng, numNodes) let nodes = generateNRandomNodes(rng[], numNodes)
for n in nodes: for n in nodes:
check table.addNode(n) == Added check table.addNode(n) == Added
@ -548,7 +547,7 @@ suite "Routing Table Tests":
var table = RoutingTable.init(local, 1, ipLimits, rng = rng, var table = RoutingTable.init(local, 1, ipLimits, rng = rng,
distanceCalculator = customDistanceCalculator) distanceCalculator = customDistanceCalculator)
let nodes = generateNRandomNodes(rng, numNodes) let nodes = generateNRandomNodes(rng[], numNodes)
for n in nodes: for n in nodes:
check table.addNode(n) == Added check table.addNode(n) == Added

View File

@ -11,7 +11,7 @@
import import
std/[sequtils, options, tables], std/[sequtils, options, tables],
chronos, testutils/unittests, bearssl, chronos, testutils/unittests,
../../eth/[keys, p2p], ../../eth/p2p/peer_pool, ../../eth/[keys, p2p], ../../eth/p2p/peer_pool,
../../eth/p2p/rlpx_protocols/whisper_protocol, ../../eth/p2p/rlpx_protocols/whisper_protocol,
./p2p_test_helper ./p2p_test_helper

View File

@ -8,7 +8,7 @@
import import
std/options, std/options,
chronos, bearssl, chronos,
stew/shims/net, stew/byteutils, stew/shims/net, stew/byteutils,
testutils/unittests, testutils/unittests,
../../eth/p2p/discoveryv5/[enr, node, routing_table], ../../eth/p2p/discoveryv5/[enr, node, routing_table],
@ -17,11 +17,6 @@ import
../../eth/keys, ../../eth/keys,
../p2p/discv5_test_helper ../p2p/discv5_test_helper
proc generateByteArray(rng: var BrHmacDrbgContext, length: int): seq[byte] =
var bytes = newSeq[byte](length)
brHmacDrbgGenerate(rng, bytes)
return bytes
procSuite "Utp protocol over discovery v5 tests": procSuite "Utp protocol over discovery v5 tests":
let rng = newRng() let rng = newRng()
let utpProtId = "test-utp".toBytes() let utpProtId = "test-utp".toBytes()
@ -91,7 +86,7 @@ procSuite "Utp protocol over discovery v5 tests":
let serverSocket = await queue.get() let serverSocket = await queue.get()
let bytesToTransfer = generateByteArray(rng[], numOfBytes) let bytesToTransfer = rng[].generateBytes(numOfBytes)
let written = await clientSocket.write(bytesToTransfer) let written = await clientSocket.write(bytesToTransfer)
let received = await serverSocket.read(numOfBytes) let received = await serverSocket.read(numOfBytes)

View File

@ -8,7 +8,7 @@
import import
sequtils, sequtils,
chronos, bearssl, chronos,
testutils/unittests, testutils/unittests,
./test_utils, ./test_utils,
../../eth/utp/utp_router, ../../eth/utp/utp_router,
@ -210,7 +210,7 @@ procSuite "Utp protocol over udp tests":
# Server socket is not in connected state, until first data transfer # Server socket is not in connected state, until first data transfer
(not s.serverSocket.isConnected()) (not s.serverSocket.isConnected())
let bytesToTransfer = generateByteArray(rng[], 100) let bytesToTransfer = rng[].generateBytes(100)
let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer)
@ -237,7 +237,7 @@ procSuite "Utp protocol over udp tests":
(not s.serverSocket.isConnected()) (not s.serverSocket.isConnected())
# 5000 bytes is over maximal packet size # 5000 bytes is over maximal packet size
let bytesToTransfer = generateByteArray(rng[], 5000) let bytesToTransfer = rng[].generateBytes(5000)
let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer)
let bytesReceivedFromServer = await transferData(s.serverSocket, s.clientSocket, bytesToTransfer) let bytesReceivedFromServer = await transferData(s.serverSocket, s.clientSocket, bytesToTransfer)
@ -266,14 +266,14 @@ procSuite "Utp protocol over udp tests":
# 5000 bytes is over maximal packet size # 5000 bytes is over maximal packet size
let bytesToTransfer = generateByteArray(rng[], 5000) let bytesToTransfer = rng[].generateBytes(5000)
let written = await s.clientSocket.write(bytesToTransfer) let written = await s.clientSocket.write(bytesToTransfer)
check: check:
written.get() == len(bytesToTransfer) written.get() == len(bytesToTransfer)
let bytesToTransfer1 = generateByteArray(rng[], 5000) let bytesToTransfer1 = rng[].generateBytes(5000)
let written1 = await s.clientSocket.write(bytesToTransfer1) let written1 = await s.clientSocket.write(bytesToTransfer1)
@ -301,8 +301,8 @@ procSuite "Utp protocol over udp tests":
s.clientSocket2.numPacketsInOutGoingBuffer() == 0 s.clientSocket2.numPacketsInOutGoingBuffer() == 0
let numBytesToTransfer = 5000 let numBytesToTransfer = 5000
let client1Data = generateByteArray(rng[], numBytesToTransfer) let client1Data = rng[].generateBytes(numBytesToTransfer)
let client2Data = generateByteArray(rng[], numBytesToTransfer) let client2Data = rng[].generateBytes(numBytesToTransfer)
discard s.clientSocket1.write(client1Data) discard s.clientSocket1.write(client1Data)
discard s.clientSocket2.write(client2Data) discard s.clientSocket2.write(client2Data)
@ -327,7 +327,7 @@ procSuite "Utp protocol over udp tests":
# Server socket is not in connected state, until first data transfer # Server socket is not in connected state, until first data transfer
(not s.serverSocket.isConnected()) (not s.serverSocket.isConnected())
let bytesToTransfer = generateByteArray(rng[], 100) let bytesToTransfer = rng[].generateBytes(100)
let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer)
@ -362,9 +362,9 @@ procSuite "Utp protocol over udp tests":
# Server socket is not in connected state, until first data transfer # Server socket is not in connected state, until first data transfer
(not s.serverSocket.isConnected()) (not s.serverSocket.isConnected())
let bytesToTransfer1 = generateByteArray(rng[], 1000) let bytesToTransfer1 = rng[].generateBytes(1000)
let bytesToTransfer2 = generateByteArray(rng[], 1000) let bytesToTransfer2 = rng[].generateBytes(1000)
let bytesToTransfer3 = generateByteArray(rng[], 1000) let bytesToTransfer3 = rng[].generateBytes(1000)
let w1 = await s.clientSocket.write(bytesToTransfer1) let w1 = await s.clientSocket.write(bytesToTransfer1)
let w2 = await s.clientSocket.write(bytesToTransfer2) let w2 = await s.clientSocket.write(bytesToTransfer2)
@ -436,7 +436,7 @@ procSuite "Utp protocol over udp tests":
(not s.serverSocket.isConnected()) (not s.serverSocket.isConnected())
# big transfer of 50kb # big transfer of 50kb
let bytesToTransfer = generateByteArray(rng[], 50000) let bytesToTransfer = rng[].generateBytes(50000)
let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer)
@ -468,7 +468,7 @@ procSuite "Utp protocol over udp tests":
(not s.serverSocket.isConnected()) (not s.serverSocket.isConnected())
# big transfer of 50kb # big transfer of 50kb
let bytesToTransfer = generateByteArray(rng[], 50000) let bytesToTransfer = rng[].generateBytes(50000)
let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer) let bytesReceivedFromClient = await transferData(s.clientSocket, s.serverSocket, bytesToTransfer)

View File

@ -8,7 +8,7 @@
import import
std/[sequtils, tables, options, sugar], std/[sequtils, tables, options, sugar],
chronos, bearssl, chronos,
testutils/unittests, testutils/unittests,
./test_utils, ./test_utils,
../../eth/utp/utp_router, ../../eth/utp/utp_router,
@ -17,7 +17,7 @@ import
../../eth/p2p/discoveryv5/random2 ../../eth/p2p/discoveryv5/random2
proc connectTillSuccess(p: UtpProtocol, to: TransportAddress, maxTries: int = 20): Future[UtpSocket[TransportAddress]] {.async.} = proc connectTillSuccess(p: UtpProtocol, to: TransportAddress, maxTries: int = 20): Future[UtpSocket[TransportAddress]] {.async.} =
var i = 0 var i = 0
while true: while true:
let res = await p.connectTo(to) let res = await p.connectTo(to)
@ -31,7 +31,7 @@ proc connectTillSuccess(p: UtpProtocol, to: TransportAddress, maxTries: int = 20
proc buildAcceptConnection( proc buildAcceptConnection(
t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]] t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]
): AcceptConnectionCallback[TransportAddress] = ): AcceptConnectionCallback[TransportAddress] =
return ( return (
proc (server: UtpRouter[TransportAddress], client: UtpSocket[TransportAddress]): Future[void] = proc (server: UtpRouter[TransportAddress], client: UtpSocket[TransportAddress]): Future[void] =
let fut = newFuture[void]() let fut = newFuture[void]()
@ -42,7 +42,7 @@ proc buildAcceptConnection(
) )
proc getServerSocket( proc getServerSocket(
t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]], t: ref Table[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]],
clientAddress: TransportAddress, clientAddress: TransportAddress,
clientConnectionId: uint16): Option[UtpSocket[TransportAddress]] = clientConnectionId: uint16): Option[UtpSocket[TransportAddress]] =
let serverSocketKey = UtpSocketKey[TransportAddress](remoteAddress: clientAddress, rcvId: clientConnectionId + 1) let serverSocketKey = UtpSocketKey[TransportAddress](remoteAddress: clientAddress, rcvId: clientConnectionId + 1)
@ -68,27 +68,27 @@ procSuite "Utp protocol over udp tests with loss and delays":
) )
) )
proc testScenario(maxDelay: int, dropRate: int, cfg: SocketConfig = SocketConfig.init()): proc testScenario(maxDelay: int, dropRate: int, cfg: SocketConfig = SocketConfig.init()):
Future[( Future[(
UtpProtocol, UtpProtocol,
UtpSocket[TransportAddress], UtpSocket[TransportAddress],
UtpProtocol, UtpProtocol,
UtpSocket[TransportAddress]) UtpSocket[TransportAddress])
] {.async.} = ] {.async.} =
var connections1 = newTable[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]() var connections1 = newTable[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]()
let address1 = initTAddress("127.0.0.1", 9080) let address1 = initTAddress("127.0.0.1", 9080)
let utpProt1 = let utpProt1 =
UtpProtocol.new( UtpProtocol.new(
buildAcceptConnection(connections1), buildAcceptConnection(connections1),
address1, address1,
socketConfig = cfg, socketConfig = cfg,
sendCallbackBuilder = sendBuilder(maxDelay, dropRate), sendCallbackBuilder = sendBuilder(maxDelay, dropRate),
rng = rng) rng = rng)
var connections2 = newTable[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]() var connections2 = newTable[UtpSocketKey[TransportAddress], UtpSocket[TransportAddress]]()
let address2 = initTAddress("127.0.0.1", 9081) let address2 = initTAddress("127.0.0.1", 9081)
let utpProt2 = let utpProt2 =
UtpProtocol.new( UtpProtocol.new(
buildAcceptConnection(connections2), buildAcceptConnection(connections2),
address2, address2,
@ -112,9 +112,9 @@ procSuite "Utp protocol over udp tests with loss and delays":
cfg: SocketConfig cfg: SocketConfig
proc init( proc init(
T: type TestCase, T: type TestCase,
maxDelay: int, maxDelay: int,
dropRate: int, dropRate: int,
bytesToTransfer: int, bytesToTransfer: int,
cfg: SocketConfig = SocketConfig.init(), cfg: SocketConfig = SocketConfig.init(),
bytesPerRead: int = 0): TestCase = bytesPerRead: int = 0): TestCase =
@ -138,7 +138,7 @@ procSuite "Utp protocol over udp tests with loss and delays":
serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg) serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg)
let smallBytes = 10 let smallBytes = 10
let smallBytesToTransfer = generateByteArray(rng[], smallBytes) let smallBytesToTransfer = rng[].generateBytes(smallBytes)
# first transfer and read to make server socket connecteced # first transfer and read to make server socket connecteced
let write1 = await clientSocket.write(smallBytesToTransfer) let write1 = await clientSocket.write(smallBytesToTransfer)
let read1 = await serverSocket.read(smallBytes) let read1 = await serverSocket.read(smallBytes)
@ -148,11 +148,11 @@ procSuite "Utp protocol over udp tests with loss and delays":
read1 == smallBytesToTransfer read1 == smallBytesToTransfer
let numBytes = testCase.bytesToTransfer let numBytes = testCase.bytesToTransfer
let bytesToTransfer = generateByteArray(rng[], numBytes) let bytesToTransfer = rng[].generateBytes(numBytes)
discard clientSocket.write(bytesToTransfer) discard clientSocket.write(bytesToTransfer)
discard serverSocket.write(bytesToTransfer) discard serverSocket.write(bytesToTransfer)
let serverReadFut = serverSocket.read(numBytes) let serverReadFut = serverSocket.read(numBytes)
let clientReadFut = clientSocket.read(numBytes) let clientReadFut = clientSocket.read(numBytes)
@ -165,7 +165,7 @@ procSuite "Utp protocol over udp tests with loss and delays":
check: check:
clientRead == bytesToTransfer clientRead == bytesToTransfer
serverRead == bytesToTransfer serverRead == bytesToTransfer
await clientProtocol.shutdownWait() await clientProtocol.shutdownWait()
await serverProtocol.shutdownWait() await serverProtocol.shutdownWait()
@ -184,7 +184,7 @@ procSuite "Utp protocol over udp tests with loss and delays":
res.add(bytes) res.add(bytes)
inc i inc i
return res return res
asyncTest "Write and Read large data in different network conditions split over several reads": asyncTest "Write and Read large data in different network conditions split over several reads":
for testCase in testCases1: for testCase in testCases1:
@ -195,7 +195,7 @@ procSuite "Utp protocol over udp tests with loss and delays":
serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg) serverSocket) = await testScenario(testCase.maxDelay, testCase.dropRate, testcase.cfg)
let smallBytes = 10 let smallBytes = 10
let smallBytesToTransfer = generateByteArray(rng[], smallBytes) let smallBytesToTransfer = rng[].generateBytes(smallBytes)
# first transfer and read to make server socket connecteced # first transfer and read to make server socket connecteced
let write1 = await clientSocket.write(smallBytesToTransfer) let write1 = await clientSocket.write(smallBytesToTransfer)
let read1 = await serverSocket.read(smallBytes) let read1 = await serverSocket.read(smallBytes)
@ -204,11 +204,11 @@ procSuite "Utp protocol over udp tests with loss and delays":
read1 == smallBytesToTransfer read1 == smallBytesToTransfer
let numBytes = testCase.bytesToTransfer let numBytes = testCase.bytesToTransfer
let bytesToTransfer = generateByteArray(rng[], numBytes) let bytesToTransfer = rng[].generateBytes(numBytes)
discard clientSocket.write(bytesToTransfer) discard clientSocket.write(bytesToTransfer)
discard serverSocket.write(bytesToTransfer) discard serverSocket.write(bytesToTransfer)
let numOfReads = int(testCase.bytesToTransfer / testCase.bytesPerRead) let numOfReads = int(testCase.bytesToTransfer / testCase.bytesPerRead)
let serverReadFut = serverSocket.readWithMultipleReads(numOfReads, testCase.bytesPerRead) let serverReadFut = serverSocket.readWithMultipleReads(numOfReads, testCase.bytesPerRead)
let clientReadFut = clientSocket.readWithMultipleReads(numOfReads, testCase.bytesPerRead) let clientReadFut = clientSocket.readWithMultipleReads(numOfReads, testCase.bytesPerRead)
@ -244,7 +244,7 @@ procSuite "Utp protocol over udp tests with loss and delays":
let numBytes = testCase.bytesToTransfer let numBytes = testCase.bytesToTransfer
let bytesToTransfer = generateByteArray(rng[], numBytes) let bytesToTransfer = rng[].generateBytes(numBytes)
discard await clientSocket.write(bytesToTransfer) discard await clientSocket.write(bytesToTransfer)
clientSocket.close() clientSocket.close()

View File

@ -9,11 +9,6 @@ type AssertionCallback = proc(): bool {.gcsafe, raises: [Defect].}
let testBufferSize = 1024'u32 let testBufferSize = 1024'u32
let defaultRcvOutgoingId = 314'u16 let defaultRcvOutgoingId = 314'u16
proc generateByteArray*(rng: var BrHmacDrbgContext, length: int): seq[byte] =
var bytes = newSeq[byte](length)
brHmacDrbgGenerate(rng, bytes)
return bytes
proc waitUntil*(f: AssertionCallback): Future[void] {.async.} = proc waitUntil*(f: AssertionCallback): Future[void] {.async.} =
while true: while true:
let res = f() let res = f()
@ -65,7 +60,7 @@ template connectOutGoingSocketWithIncoming*(
let incomingSocket = newIncomingSocket[TransportAddress]( let incomingSocket = newIncomingSocket[TransportAddress](
testAddress, testAddress,
initTestSnd(incomingQueue), initTestSnd(incomingQueue),
cfg, cfg,
initialPacket.header.connectionId, initialPacket.header.connectionId,
initialPacket.header.seqNr, initialPacket.header.seqNr,
@ -77,9 +72,9 @@ template connectOutGoingSocketWithIncoming*(
let responseAck = await incomingQueue.get() let responseAck = await incomingQueue.get()
await outgoingSocket.processPacket(responseAck) await outgoingSocket.processPacket(responseAck)
await waitUntil(proc (): bool = outgoingSocket.isConnected()) await waitUntil(proc (): bool = outgoingSocket.isConnected())
check: check:
outgoingSocket.isConnected() outgoingSocket.isConnected()
@ -91,7 +86,7 @@ proc generateDataPackets*(
initialSeqNr: uint16, initialSeqNr: uint16,
connectionId: uint16, connectionId: uint16,
ackNr: uint16, ackNr: uint16,
rng: var BrHmacDrbgContext): seq[Packet] = rng: var HmacDrbgContext): seq[Packet] =
let packetSize = 100 let packetSize = 100
var packets = newSeq[Packet]() var packets = newSeq[Packet]()
var i = 0'u16 var i = 0'u16
@ -101,7 +96,7 @@ proc generateDataPackets*(
connectionId, connectionId,
ackNr, ackNr,
testBufferSize, testBufferSize,
generateByteArray(rng, packetSize), rng.generateBytes(packetSize),
0 0
) )
packets.add(packet) packets.add(packet)

View File

@ -8,7 +8,7 @@
import import
std/[hashes, options], std/[hashes, options],
chronos, bearssl, chronicles, chronos, chronicles,
testutils/unittests, testutils/unittests,
./test_utils, ./test_utils,
../../eth/utp/utp_router, ../../eth/utp/utp_router,
@ -313,7 +313,7 @@ procSuite "Utp router unit tests":
let connectResult = await connectFuture let connectResult = await connectFuture
await waitUntil(proc (): bool = router.len() == 0) await waitUntil(proc (): bool = router.len() == 0)
check: check:
connectResult.isErr() connectResult.isErr()
connectResult.error().kind == ConnectionTimedOut connectResult.error().kind == ConnectionTimedOut
@ -356,7 +356,7 @@ procSuite "Utp router unit tests":
check: check:
connectResult.isErr() connectResult.isErr()
# even though send is failing we will just finish with timeout, # even though send is failing we will just finish with timeout,
connectResult.error().kind == ConnectionTimedOut connectResult.error().kind == ConnectionTimedOut
router.len() == 0 router.len() == 0

View File

@ -8,7 +8,7 @@
import import
std/[algorithm, random, sequtils, options], std/[algorithm, random, sequtils, options],
chronos, bearssl, chronicles, chronos, chronicles,
testutils/unittests, testutils/unittests,
./test_utils, ./test_utils,
../../eth/utp/utp_router, ../../eth/utp/utp_router,
@ -186,7 +186,7 @@ procSuite "Utp socket unit test":
await outgoingSocket.processPacket(p) await outgoingSocket.processPacket(p)
var sentAcks: seq[Packet] = @[] var sentAcks: seq[Packet] = @[]
for i in 0'u16..<numOfPackets: for i in 0'u16..<numOfPackets:
let ack = await q.get() let ack = await q.get()
sentAcks.add(ack) sentAcks.add(ack)
@ -238,7 +238,7 @@ procSuite "Utp socket unit test":
await outgoingSocket.processPacket(p) await outgoingSocket.processPacket(p)
var sentAcks: seq[Packet] = @[] var sentAcks: seq[Packet] = @[]
for i in 0'u16..<numOfPackets: for i in 0'u16..<numOfPackets:
let ack = await q.get() let ack = await q.get()
sentAcks.add(ack) sentAcks.add(ack)
@ -378,7 +378,7 @@ procSuite "Utp socket unit test":
let initialRemoteSeq = 10'u16 let initialRemoteSeq = 10'u16
# lot of data which will generate at least 5 packets # lot of data which will generate at least 5 packets
let bigDataTowWrite = generateByteArray(rng[], 10000) let bigDataTowWrite = rng[].generateBytes(10000)
let (outgoingSocket, initialPacket) = connectOutGoingSocket(initialRemoteSeq, q) let (outgoingSocket, initialPacket) = connectOutGoingSocket(initialRemoteSeq, q)
let acker = outgoingSocket.ackAllPacket(q, initialRemoteSeq) let acker = outgoingSocket.ackAllPacket(q, initialRemoteSeq)
@ -389,7 +389,7 @@ procSuite "Utp socket unit test":
await waitUntil(proc (): bool = outgoingSocket.numPacketsInOutGoingBuffer() == 0) await waitUntil(proc (): bool = outgoingSocket.numPacketsInOutGoingBuffer() == 0)
let maxWindowAfterSuccesfulSends = outgoingSocket.currentMaxWindowSize() let maxWindowAfterSuccesfulSends = outgoingSocket.currentMaxWindowSize()
check: check:
# after processing a lot of data, our window size should be a lot bigger than our packet size # after processing a lot of data, our window size should be a lot bigger than our packet size
@ -397,9 +397,9 @@ procSuite "Utp socket unit test":
# cancel acking process, next writes will for sure timeout # cancel acking process, next writes will for sure timeout
await acker.cancelAndWait() await acker.cancelAndWait()
# data which fits one packet and will timeout # data which fits one packet and will timeout
let smallerData = generateByteArray(rng[], 100) let smallerData = rng[].generateBytes(100)
let bytesWritten1 = await outgoingSocket.write(smallerData) let bytesWritten1 = await outgoingSocket.write(smallerData)
@ -411,7 +411,7 @@ procSuite "Utp socket unit test":
# ignore also first re-send # ignore also first re-send
discard await q.get() discard await q.get()
let maxWindowAfterTimeout = outgoingSocket.currentMaxWindowSize() let maxWindowAfterTimeout = outgoingSocket.currentMaxWindowSize()
check: check:
@ -1059,7 +1059,7 @@ procSuite "Utp socket unit test":
let q = newAsyncQueue[Packet]() let q = newAsyncQueue[Packet]()
let initialRemoteSeq = 10'u16 let initialRemoteSeq = 10'u16
let dataToWrite = generateByteArray(rng[], 1001) let dataToWrite = rng[].generateBytes(1001)
# remote is initialized with buffer to small to handle whole payload # remote is initialized with buffer to small to handle whole payload
let (outgoingSocket, initialPacket) = connectOutGoingSocket(initialRemoteSeq, q, cfg = SocketConfig.init(optSndBuffer = 1000)) let (outgoingSocket, initialPacket) = connectOutGoingSocket(initialRemoteSeq, q, cfg = SocketConfig.init(optSndBuffer = 1000))
@ -1101,7 +1101,7 @@ procSuite "Utp socket unit test":
# remote is initialized with buffer to small to handle whole payload # remote is initialized with buffer to small to handle whole payload
let (outgoingSocket, initialPacket) = connectOutGoingSocket(initialRemoteSeq, q, cfg = SocketConfig.init(optSndBuffer = 1160)) let (outgoingSocket, initialPacket) = connectOutGoingSocket(initialRemoteSeq, q, cfg = SocketConfig.init(optSndBuffer = 1160))
let twoPacketData = generateByteArray(rng[], int(dataToWirte)) let twoPacketData = rng[].generateBytes(int(dataToWirte))
let writeResult = await outgoingSocket.write(twoPacketData) let writeResult = await outgoingSocket.write(twoPacketData)
@ -1140,7 +1140,7 @@ procSuite "Utp socket unit test":
# we are using ack from remote to setup our snd window size to one packet size on one packet # we are using ack from remote to setup our snd window size to one packet size on one packet
await outgoingSocket.processPacket(someAckFromRemote) await outgoingSocket.processPacket(someAckFromRemote)
let twoPacketData = generateByteArray(rng[], int(2 * remoteRcvWindowSize)) let twoPacketData = rng[].generateBytes(int(2 * remoteRcvWindowSize))
let writeFut = outgoingSocket.write(twoPacketData) let writeFut = outgoingSocket.write(twoPacketData)
@ -1197,7 +1197,7 @@ procSuite "Utp socket unit test":
# write result will be successfull as send buffer has space # write result will be successfull as send buffer has space
let writeResult = await outgoingSocket.write(someData) let writeResult = await outgoingSocket.write(someData)
# this will finish in seconds(3) as only after this time window will be set to min value # this will finish in seconds(3) as only after this time window will be set to min value
let p = await q.get() let p = await q.get()
@ -1356,7 +1356,7 @@ procSuite "Utp socket unit test":
let writeRes1 = await outgoingSocket.write(dataToWrite1) let writeRes1 = await outgoingSocket.write(dataToWrite1)
let writeRes2 = await outgoingSocket.write(dataToWrite2) let writeRes2 = await outgoingSocket.write(dataToWrite2)
let writeRes3 = await outgoingSocket.write(dataToWrite3) let writeRes3 = await outgoingSocket.write(dataToWrite3)
check: check:
writeRes1.isOk() writeRes1.isOk()
@ -1529,7 +1529,7 @@ procSuite "Utp socket unit test":
asyncTest "Maximum payload size should be configurable": asyncTest "Maximum payload size should be configurable":
let q = newAsyncQueue[Packet]() let q = newAsyncQueue[Packet]()
let initalRemoteSeqNr = 10'u16 let initalRemoteSeqNr = 10'u16
let d = generateByteArray(rng[], 5000) let d = rng[].generateBytes(5000)
let maxPayloadSize = 800'u32 let maxPayloadSize = 800'u32
let config = SocketConfig.init(payloadSize = maxPayloadSize) let config = SocketConfig.init(payloadSize = maxPayloadSize)

View File

@ -8,7 +8,7 @@
import import
std/[options, sequtils], std/[options, sequtils],
chronos, bearssl, chronicles, chronos, chronicles,
stew/bitops2, stew/bitops2,
testutils/unittests, testutils/unittests,
./test_utils, ./test_utils,
@ -62,7 +62,7 @@ procSuite "Utp socket selective acks unit test":
numOfSetBits = numOfSetBits + countOnes(b) numOfSetBits = numOfSetBits + countOnes(b)
return numOfSetBits return numOfSetBits
proc hasOnlyOneBitSet(arr: openArray[byte]): bool = proc hasOnlyOneBitSet(arr: openArray[byte]): bool =
return numOfSetBits(arr) == 1 return numOfSetBits(arr) == 1
asyncTest "Socket with empty buffer should generate array with only zeros": asyncTest "Socket with empty buffer should generate array with only zeros":
@ -75,7 +75,7 @@ procSuite "Utp socket selective acks unit test":
check: check:
extArray == [0'u8, 0, 0, 0] extArray == [0'u8, 0, 0, 0]
asyncTest "Socket should generate correct bit mask for each missing packet": asyncTest "Socket should generate correct bit mask for each missing packet":
# 1 means that received packet is packet just after expected packet i.e # 1 means that received packet is packet just after expected packet i.e
# packet.seqNr - receivingSocket.ackNr = 2 # packet.seqNr - receivingSocket.ackNr = 2
@ -113,7 +113,7 @@ procSuite "Utp socket selective acks unit test":
let bitMask = await connectAndProcessMissingPacketWithIndexes(missingIndexes) let bitMask = await connectAndProcessMissingPacketWithIndexes(missingIndexes)
check: check:
numOfSetBits(bitMask) == len(missingIndexes) numOfSetBits(bitMask) == len(missingIndexes)
for idx in missingIndexes: for idx in missingIndexes:
check: check:
getBit(bitMask, idx - 1) getBit(bitMask, idx - 1)
@ -128,7 +128,7 @@ procSuite "Utp socket selective acks unit test":
check: check:
numOfSetBits(bitMask) == 32 numOfSetBits(bitMask) == 32
len(bitMask) == 4 len(bitMask) == 4
type TestCase = object type TestCase = object
# number of packet to generate by writitng side # number of packet to generate by writitng side
numOfPackets: int numOfPackets: int
@ -155,7 +155,7 @@ procSuite "Utp socket selective acks unit test":
outgoingQueue: AsyncQueue[Packet], outgoingQueue: AsyncQueue[Packet],
incomingQueue: AsyncQueue[Packet], incomingQueue: AsyncQueue[Packet],
testCase: TestCase): Future[(UtpSocket[TransportAddress], UtpSocket[TransportAddress], seq[Packet])] {.async.} = testCase: TestCase): Future[(UtpSocket[TransportAddress], UtpSocket[TransportAddress], seq[Packet])] {.async.} =
let (outgoingSocket, incomingSocket) = let (outgoingSocket, incomingSocket) =
connectOutGoingSocketWithIncoming( connectOutGoingSocketWithIncoming(
initialRemoteSeq, initialRemoteSeq,
outgoingQueue, outgoingQueue,
@ -168,7 +168,7 @@ procSuite "Utp socket selective acks unit test":
discard await outgoingSocket.write(dataToWrite) discard await outgoingSocket.write(dataToWrite)
let packet = await outgoingQueue.get() let packet = await outgoingQueue.get()
packets.add(packet) packets.add(packet)
for toDeliver in testCase.packetsDelivered: for toDeliver in testCase.packetsDelivered:
await incomingSocket.processPacket(packets[toDeliver]) await incomingSocket.processPacket(packets[toDeliver])
@ -179,7 +179,7 @@ procSuite "Utp socket selective acks unit test":
asyncTest "Socket should calculate number of bytes acked by selective acks": asyncTest "Socket should calculate number of bytes acked by selective acks":
let dataSize = 10 let dataSize = 10
let initialRemoteSeq = 10'u16 let initialRemoteSeq = 10'u16
let smallData = generateByteArray(rng[], 10) let smallData = rng[].generateBytes(10)
for testCase in selectiveAckTestCases: for testCase in selectiveAckTestCases:
let outgoingQueue = newAsyncQueue[Packet]() let outgoingQueue = newAsyncQueue[Packet]()
@ -209,7 +209,7 @@ procSuite "Utp socket selective acks unit test":
let ackedBytes = outgoingSocket.calculateSelectiveAckBytes(finalAck.header.ackNr, finalAck.eack.unsafeGet()) let ackedBytes = outgoingSocket.calculateSelectiveAckBytes(finalAck.header.ackNr, finalAck.eack.unsafeGet())
check: check:
int(ackedBytes) == len(testCase.packetsDelivered) * dataSize int(ackedBytes) == len(testCase.packetsDelivered) * dataSize
await outgoingSocket.destroyWait() await outgoingSocket.destroyWait()
@ -218,12 +218,12 @@ procSuite "Utp socket selective acks unit test":
asyncTest "Socket should ack packets based on selective ack packet": asyncTest "Socket should ack packets based on selective ack packet":
let dataSize = 10 let dataSize = 10
let initialRemoteSeq = 10'u16 let initialRemoteSeq = 10'u16
let smallData = generateByteArray(rng[], 10) let smallData = rng[].generateBytes(10)
for testCase in selectiveAckTestCases: for testCase in selectiveAckTestCases:
let outgoingQueue = newAsyncQueue[Packet]() let outgoingQueue = newAsyncQueue[Packet]()
let incomingQueue = newAsyncQueue[Packet]() let incomingQueue = newAsyncQueue[Packet]()
let (outgoingSocket, incomingSocket, _) = await setupTestCase( let (outgoingSocket, incomingSocket, _) = await setupTestCase(
smallData, smallData,
initialRemoteSeq, initialRemoteSeq,
@ -252,8 +252,8 @@ procSuite "Utp socket selective acks unit test":
await outgoingSocket.processPacket(finalAck) await outgoingSocket.processPacket(finalAck)
let expectedPackets = testCase.numOfPackets - len(testCase.packetsDelivered) let expectedPackets = testCase.numOfPackets - len(testCase.packetsDelivered)
await waitUntil(proc (): bool = outgoingSocket.numPacketsInOutGoingBuffer() == expectedPackets) await waitUntil(proc (): bool = outgoingSocket.numPacketsInOutGoingBuffer() == expectedPackets)
check: check:
outgoingSocket.numPacketsInOutGoingBuffer() == expectedPackets outgoingSocket.numPacketsInOutGoingBuffer() == expectedPackets
@ -276,7 +276,7 @@ procSuite "Utp socket selective acks unit test":
asyncTest "Socket should re-send packets when there are at least 3 packets acked ahead": asyncTest "Socket should re-send packets when there are at least 3 packets acked ahead":
let dataSize = 10 let dataSize = 10
let initialRemoteSeq = 10'u16 let initialRemoteSeq = 10'u16
let smallData = generateByteArray(rng[], 10) let smallData = rng[].generateBytes(10)
for testCase in packetResendTestCases: for testCase in packetResendTestCases:
let outgoingQueue = newAsyncQueue[Packet]() let outgoingQueue = newAsyncQueue[Packet]()
@ -314,7 +314,7 @@ procSuite "Utp socket selective acks unit test":
resentPacket.header.seqNr == initialPackets[idx].header.seqNr resentPacket.header.seqNr == initialPackets[idx].header.seqNr
let endBufferSize = outgoingSocket.currentMaxWindowSize() let endBufferSize = outgoingSocket.currentMaxWindowSize()
if len(testCase.packetsResent) == 0: if len(testCase.packetsResent) == 0:
check: check:
# when there is no packet loss (no resent packets), buffer size increases # when there is no packet loss (no resent packets), buffer size increases