logos-storage-nim-dht/tests/dht/test_helper.nim
Eric Mastro 7c0fb7aef4
WIP: change seqNo to ttl
regarding the dht, in the meeting swapping seqNo for ttl was discussed. After attempting to implement this change, the tests fail due to the lack of granularity, eg NodeA is instantiated, then NodeB is instantiated with a different ip/port and with NodeA as its previous record. The seqNo of both will be the same as more than a second hasn't elapsed, meaning that the record for NodeB would never been seen as newer.

Maybe the cheapest solution here would be to retain the seqNo field and add a ttl field that can be checked separately for expiration? Or if we only want one field, make it nanosecond resolution?
2022-03-23 18:17:54 +11:00

114 lines
3.6 KiB
Nim

import
stew/shims/net, bearssl, chronos,
eth/keys,
libp2pdht/discv5/[spr, node, routing_table],
libp2pdht/discv5/protocol as discv5_protocol,
libp2p/crypto/crypto,
libp2p/multiaddress
export net
proc localAddress*(port: int): Address =
Address(ip: ValidIpAddress.init("127.0.0.1"), port: Port(port))
proc initDiscoveryNode*(
rng: ref BrHmacDrbgContext,
privKey: keys.PrivateKey,
address: Address,
bootstrapRecords: openArray[SignedPeerRecord] = [],
previousRecord = none[SignedPeerRecord]()):
discv5_protocol.Protocol =
# set bucketIpLimit to allow bucket split
let config = DiscoveryConfig.init(1000, 24, 5)
let protocol = newProtocol(
privKey,
some(address.ip),
some(address.port), some(address.port),
bindPort = address.port,
bootstrapRecords = bootstrapRecords,
previousRecord = previousRecord,
config = config,
rng = rng)
protocol.open()
protocol
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,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node =
let
port = Port(port)
spr = SignedPeerRecord.init(privKey, some(ip), some(port), some(port))
.expect("Properly intialized private key")
result = newNode(spr).expect("Properly initialized node")
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[]))
res.add(node)
res
proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, keys.PrivateKey) =
while true:
let pk = keys.PrivateKey.random(rng)
let node = generateNode(pk, ip = ip)
if logDistance(n.id, node.id) == d:
return (node, pk)
proc nodeAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node =
let (node, _) = n.nodeAndPrivKeyAtDistance(rng, d, ip)
node
proc nodesAtDistance*(
n: Node, rng: var BrHmacDrbgContext, d: uint32, amount: int,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] =
for i in 0..<amount:
result.add(nodeAtDistance(n, rng, d, ip))
proc nodesAtDistanceUniqueIp*(
n: Node, rng: var BrHmacDrbgContext, d: uint32, amount: int,
ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] =
var ta = initTAddress(ip, Port(0))
for i in 0..<amount:
ta.inc()
result.add(nodeAtDistance(n, rng, d, ValidIpAddress.init(ta.address())))
proc addSeenNode*(d: discv5_protocol.Protocol, n: Node): bool =
# Add it as a seen node, warning: for testing convenience only!
n.seen = true
d.addNode(n)
func udpExample*(_: type MultiAddress): MultiAddress =
## creates a new udp multiaddress on a random port
Multiaddress.init("/ip4/0.0.0.0/udp/0")
func udpExamples*(_: type MultiAddress, count: int): seq[MultiAddress] =
var res: seq[MultiAddress] = @[]
for i in 1..count:
res.add Multiaddress.init("/ip4/0.0.0.0/udp/" & $i).get
return res
proc toSignedPeerRecord*(privKey: crypto.PrivateKey) : SignedPeerRecord =
## handle conversion between the two worlds
let pr = PeerRecord.init(
peerId = PeerId.init(privKey.getPublicKey.get).get,
addresses = MultiAddress.udpExamples(3))
return SignedPeerRecord.init(privKey, pr)
.expect("Should init SignedPeerRecord with private key")
proc example*(T: type SignedPeerRecord): T =
let
rng = crypto.newRng()
privKey = crypto.PrivateKey.random(rng[]).expect("Valid rng")
privKey.toSignedPeerRecord