-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
discv5 #19
Merged
discv5 #19
Changes from all commits
Commits
Show all changes
66 commits
Select commit
Hold shift + click to select a range
4e9956b
readme
decanus 9869801
create package
decanus 3c252ae
started experimenting
decanus 80346ed
cleanup
decanus 96b4a9b
adding a peer
decanus 1108369
more granular control
decanus 3288987
fix
decanus 0fdc556
fix
decanus c1c4338
removed
decanus f1259d9
experimenting
decanus 232e151
using debug
decanus a08a802
updated code to start N nodes
decanus 7362cec
fix
decanus 6cd619a
fix
decanus de04f7d
dean is too retarded for nim part 5
decanus fd280b1
confused
decanus 762ad00
fi
decanus 2687d9a
added todo, playing around
decanus 23efa82
updated
decanus 8cda0d7
distance func
decanus bf34d72
todo
decanus 6fe7419
fix
decanus acad5f0
fix
decanus 57b0041
made it work
decanus 22d353d
changes
decanus 4a0385c
update
decanus bca6584
multiple runs
decanus f044c55
minor improvements
decanus 220d48e
using for
decanus 6fb16fa
minor
decanus 9e95aeb
little error
decanus 6ac9040
woops
decanus e7bb186
update
decanus 9dfd761
using sequence
decanus 7342f15
changes
decanus ff9064d
updated
decanus 289e5d8
unused
decanus 5c73ae4
moved
decanus 2322ddd
fixed
decanus 73141d8
changed sleep to var
decanus c8a6ff8
changed node count
decanus b4546da
moved start
decanus 2d41810
using contains
decanus acdc9bd
using sample functions
decanus 690e5e0
added a random version
decanus 4417457
back
decanus 8508e9a
experimenting with random pairs
decanus 4fce088
starting bootstrap node only
decanus 7ae6a9f
made config flag
decanus ab8c6d8
remove echo
decanus c7c1e74
minor change
decanus 8f40b34
added some comments
decanus fda0f82
printing port instead, more informative
decanus 5d77e37
fixes
decanus 6e05c6f
fix
decanus 65e48b0
overhaul
decanus 9ad274a
more
decanus f12922f
updated random
decanus 0958f7f
added count
decanus 7139b4e
fixes
decanus f8127c1
started working on ENR lookup
decanus bc825fd
using smarter distribution
decanus fd395cd
using countit
decanus 335cb75
merged
decanus 3c96d91
fix
decanus 4294931
Merge pull request #25 from vacp2p/discv5-enr-lookup
decanus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# discv5 feasibility study | ||
|
||
This contains the study as documented by the issue [vacp2p/research#15](https://github.com/vacp2p/research/issues/15). | ||
Semi-inspired by [zilm13/discv5](https://github.com/zilm13/discv5). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Package | ||
|
||
version = "0.1.0" | ||
author = "decanus" | ||
description = "A new awesome nimble package" | ||
license = "MIT" | ||
srcDir = "src" | ||
bin = @["discv5"] | ||
|
||
|
||
|
||
# Dependencies | ||
|
||
requires "nim >= 1.0.6", | ||
"eth", | ||
"confutils" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
import | ||
random, chronos, sequtils, chronicles, tables, stint, options, std/bitops, sequtils, | ||
eth/[keys, rlp, async_utils], eth/p2p/enode, eth/trie/db, | ||
eth/p2p/discoveryv5/[discovery_db, enr, node, types, routing_table, encoding], | ||
eth/p2p/discoveryv5/protocol as discv5_protocol, | ||
./utils | ||
|
||
const | ||
# the amount of nodes | ||
N = 100 | ||
|
||
MAX_LOOKUPS = 100 | ||
RUNS = 100 | ||
|
||
# the cooldown period between runs. | ||
COOLDOWN = 0 | ||
|
||
# the sleep period before starting our runs. | ||
SLEEP = 600 | ||
VERBOSE = true | ||
|
||
# if true, nodes are randomly added to other nodes using the `addNode` function. | ||
# otherwise we use discv5s native paring functionality letting each node find peers using the boostrap. | ||
USE_MANUAL_PAIRING = false | ||
|
||
# when manual pairing is enabled this indicates the amount of nodes to pair with. | ||
PEERS_PER_NODE = 16 | ||
|
||
# True if looking for a node with field rather than a specific node | ||
LOOK_FOR_FIELD = true | ||
|
||
# The amount of nodes that will have our specific field to look for | ||
LOOKUP_FIELD_DISTRIBUTION = 5 | ||
|
||
proc write(str: string) = | ||
if VERBOSE: | ||
echo str | ||
|
||
proc runWith(node: discv5_protocol.Protocol, nodes: seq[discv5_protocol.Protocol]) {.async.} = | ||
randomize() | ||
|
||
let target = sample(nodes).localNode | ||
let tid = recordToNodeID(target.record) | ||
|
||
var peer: Node | ||
while true: | ||
randomize() | ||
peer = sample(nodes).localNode | ||
if peer.record.toUri() != target.record.toUri(): | ||
break | ||
|
||
var distance = logDist(recordToNodeID(peer.record), tid) | ||
|
||
var called = newSeq[string](0) | ||
|
||
for i in 0..<MAX_LOOKUPS: | ||
var lookup = await node.findNode(peer, distance) | ||
called.add(peer.record.toUri()) | ||
|
||
keepIf(lookup, proc (x: Node): bool = | ||
x.record.toUri() != node.localNode.record.toUri() and not called.contains(x.record.toUri()) | ||
) | ||
|
||
if lookup.len == 0: | ||
if distance != 256: | ||
distance = 256 | ||
continue | ||
|
||
write("Lookup from node " & $((get peer.record.toTypedRecord()).udp.get()) & " found no results at 256") | ||
return | ||
|
||
if lookup.countIt(it.record.toUri() == target.record.toUri()) == 1: | ||
echo "Found target in ", i + 1, " lookups" | ||
return | ||
|
||
let lastPeer = peer | ||
for n in items(lookup): | ||
let d = logDist(recordToNodeID(n.record), tid) | ||
if d <= distance: | ||
peer = n | ||
distance = d | ||
|
||
# This ensures we get a random node from the last lookup if we have already called the new peer. | ||
# We let this run lookup*2 times, otherwise we could reach deadlock. | ||
for i in 0..<(lookup.len*2): | ||
if lastPeer.record.toUri() != peer.record.toUri(): | ||
break | ||
|
||
peer = sample(lookup) | ||
|
||
echo "Not found in max iterations" | ||
|
||
proc runWithENR(node: discv5_protocol.Protocol, nodes: seq[discv5_protocol.Protocol]) {.async.} = | ||
randomize() | ||
|
||
var peer = sample(nodes).localNode | ||
|
||
let distance = uint32(256) | ||
|
||
var called = newSeq[string](0) | ||
|
||
for i in 0..<MAX_LOOKUPS: | ||
var lookup = await node.findNode(peer, distance) | ||
called.add(peer.record.toUri()) | ||
|
||
keepIf(lookup, proc (x: Node): bool = | ||
x.record.toUri() != node.localNode.record.toUri() and not called.contains(x.record.toUri()) | ||
) | ||
|
||
if lookup.countIt(it.record.tryGet("search", seq[byte]).isSome) >= 1: | ||
echo i + 1 | ||
return | ||
|
||
if lookup.len == 0: | ||
write("Lookup from node " & $((get peer.record.toTypedRecord()).udp.get()) & " found no results at 256") | ||
return | ||
|
||
peer = sample(lookup) | ||
|
||
echo "Not found in max iterations" | ||
|
||
proc runWithRandom(node: discv5_protocol.Protocol, nodes: seq[discv5_protocol.Protocol]) {.async.} = | ||
randomize() | ||
|
||
let target = sample(nodes).localNode | ||
let tid = recordToNodeID(target.record) | ||
|
||
var peer: Node | ||
while true: | ||
randomize() | ||
peer = sample(nodes).localNode | ||
if peer.record.toUri() != target.record.toUri(): | ||
break | ||
|
||
var called = newSeq[string](0) | ||
|
||
for i in 0..<MAX_LOOKUPS: | ||
var lookup = await node.findNode(peer, 256) | ||
called.add(peer.record.toUri()) | ||
|
||
keepIf(lookup, proc (x: Node): bool = | ||
x.record.toUri() != node.localNode.record.toUri() and not called.contains(x.record.toUri()) | ||
) | ||
|
||
if lookup.len == 0: | ||
write("Lookup from node " & $((get peer.record.toTypedRecord()).udp.get()) & " found no results at 256") | ||
return | ||
|
||
let findings = filter(lookup, proc (x: Node): bool = | ||
x.record.toUri() == target.record.toUri() | ||
) | ||
|
||
if findings.len == 1: | ||
echo "Found target in ", i + 1, " lookups" | ||
return | ||
|
||
while true: # This ensures we get a random node from the last lookup if we have already called the new peer. | ||
if not called.contains(peer.record.toUri()): | ||
break | ||
|
||
peer = sample(lookup) | ||
|
||
echo "Not found in max iterations" | ||
|
||
proc pair(node: discv5_protocol.Protocol, nodes: seq[discv5_protocol.Protocol]) = | ||
for _ in 0..<PEERS_PER_NODE: | ||
randomize() | ||
sample(nodes).addNode(node.localNode) | ||
|
||
proc run() {.async.} = | ||
var nodes = newSeq[discv5_protocol.Protocol](0) | ||
|
||
echo "Setting up ", N, " nodes" | ||
|
||
let divisor = int(N / LOOKUP_FIELD_DISTRIBUTION) | ||
|
||
for i in 0..<N: | ||
let node = initDiscoveryNode( | ||
PrivateKey.random().get, | ||
localAddress(20300 + i), | ||
if i > 0: @[nodes[0].localNode.record] else: @[], | ||
if i mod divisor == 0: 1 else: 0 | ||
) | ||
nodes.add(node) | ||
|
||
if (USE_MANUAL_PAIRING and i == 0) or not USE_MANUAL_PAIRING: | ||
node.start() | ||
|
||
if USE_MANUAL_PAIRING: | ||
for n in nodes: | ||
pair(n, nodes) | ||
|
||
if not USE_MANUAL_PAIRING: | ||
echo "Sleeping for ", SLEEP, " seconds" | ||
await sleepAsync(SLEEP.seconds) | ||
|
||
let node = initDiscoveryNode(PrivateKey.random().get, localAddress(20300 + N), @[nodes[0].localNode.record], 0) | ||
|
||
for i in 0..<RUNS: | ||
if LOOK_FOR_FIELD: | ||
await runWithENR(node, nodes) | ||
else: | ||
await runWith(node, nodes) | ||
|
||
await sleepAsync(COOLDOWN.seconds) | ||
|
||
when isMainModule: | ||
waitFor run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import | ||
chronos, options, std/bitops, | ||
eth/keys, eth/p2p/enode, eth/trie/db, stint, nimcrypto, | ||
eth/p2p/discoveryv5/[discovery_db, enr, node, types], | ||
eth/p2p/discoveryv5/protocol as discv5_protocol | ||
|
||
type ToNodeIDError* = object of CatchableError | ||
|
||
proc localAddress*(port: int): Address = | ||
let port = Port(port) | ||
result = Address( | ||
udpPort: port, | ||
tcpPort: port, | ||
ip: parseIpAddress("127.0.0.1") | ||
) | ||
|
||
proc initDiscoveryNode*(privKey: PrivateKey, address: Address, bootstrapRecords: seq[Record], field: uint): discv5_protocol.Protocol = | ||
var db = DiscoveryDB.init(newMemoryDB()) | ||
result = newProtocol(privKey, db, some(parseIpAddress("127.0.0.1")), address.tcpPort, address.udpPort, bootstrapRecords) | ||
let old = result.localNode.record | ||
|
||
if field == 1: | ||
let enr = initRecord( | ||
old.seqNum, | ||
privKey, | ||
{ | ||
"udp": uint32(address.udpPort), | ||
"tcp": uint32(address.tcpPort), | ||
"ip": [byte 127, 0, 0, 1], | ||
"search": field | ||
} | ||
) | ||
|
||
result.localNode.record = enr | ||
|
||
result.open() | ||
|
||
proc recordToNodeID*(r: Record): NodeId = | ||
var pk = r.get(PublicKey) | ||
result = readUintBE[256](keccak256.digest(pk.get.toRaw()).data) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please elaborate on the purpose of this method?