mirror of
https://github.com/waku-org/nwaku.git
synced 2025-02-28 23:10:54 +00:00
feat(discv5): topic subscriptions update discv5 filter predicate (#1918)
This commit is contained in:
parent
c369b3294e
commit
4539dfc761
@ -547,7 +547,7 @@ proc startApp*(app: App): Future[AppResult[void]] {.async.} =
|
|||||||
if res.isErr():
|
if res.isErr():
|
||||||
return err("failed to start waku discovery v5: " & $res.error)
|
return err("failed to start waku discovery v5: " & $res.error)
|
||||||
|
|
||||||
asyncSpawn wakuDiscv5.searchLoop(app.node.peerManager, some(app.record))
|
asyncSpawn wakuDiscv5.searchLoop(app.node.peerManager)
|
||||||
asyncSpawn wakuDiscv5.subscriptionsListener(app.node.topicSubscriptionQueue)
|
asyncSpawn wakuDiscv5.subscriptionsListener(app.node.topicSubscriptionQueue)
|
||||||
|
|
||||||
return await startNode(
|
return await startNode(
|
||||||
|
@ -74,7 +74,7 @@ proc setupAndPublish(rng: ref HmacDrbgContext) {.async.} =
|
|||||||
error "failed to start discv5", error= discv5Res.error
|
error "failed to start discv5", error= discv5Res.error
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
||||||
asyncSpawn wakuDiscv5.searchLoop(node.peerManager, some(node.enr))
|
asyncSpawn wakuDiscv5.searchLoop(node.peerManager)
|
||||||
|
|
||||||
# wait for a minimum of peers to be connected, otherwise messages wont be gossiped
|
# wait for a minimum of peers to be connected, otherwise messages wont be gossiped
|
||||||
while true:
|
while true:
|
||||||
|
@ -69,7 +69,7 @@ proc setupAndSubscribe(rng: ref HmacDrbgContext) {.async.} =
|
|||||||
error "failed to start discv5", error = discv5Res.error
|
error "failed to start discv5", error = discv5Res.error
|
||||||
quit(1)
|
quit(1)
|
||||||
|
|
||||||
asyncSpawn wakuDiscv5.searchLoop(node.peerManager, some(node.enr))
|
asyncSpawn wakuDiscv5.searchLoop(node.peerManager)
|
||||||
|
|
||||||
# wait for a minimum of peers to be connected, otherwise messages wont be gossiped
|
# wait for a minimum of peers to be connected, otherwise messages wont be gossiped
|
||||||
while true:
|
while true:
|
||||||
|
@ -155,8 +155,8 @@ procSuite "Waku Peer Exchange":
|
|||||||
assert resultDisc1StartRes.isOk(), resultDisc1StartRes.error
|
assert resultDisc1StartRes.isOk(), resultDisc1StartRes.error
|
||||||
let resultDisc2StartRes = disc2.start()
|
let resultDisc2StartRes = disc2.start()
|
||||||
assert resultDisc2StartRes.isOk(), resultDisc2StartRes.error
|
assert resultDisc2StartRes.isOk(), resultDisc2StartRes.error
|
||||||
asyncSpawn disc1.searchLoop(node1.peerManager, none(enr.Record))
|
asyncSpawn disc1.searchLoop(node1.peerManager)
|
||||||
asyncSpawn disc2.searchLoop(node2.peerManager, none(enr.Record))
|
asyncSpawn disc2.searchLoop(node2.peerManager)
|
||||||
|
|
||||||
## When
|
## When
|
||||||
var attempts = 10
|
var attempts = 10
|
||||||
|
@ -48,6 +48,31 @@ type WakuDiscoveryV5* = ref object
|
|||||||
conf: WakuDiscoveryV5Config
|
conf: WakuDiscoveryV5Config
|
||||||
protocol*: protocol.Protocol
|
protocol*: protocol.Protocol
|
||||||
listening*: bool
|
listening*: bool
|
||||||
|
predicate: Option[WakuDiscv5Predicate]
|
||||||
|
|
||||||
|
proc shardingPredicate*(record: Record): Option[WakuDiscv5Predicate] =
|
||||||
|
## Filter peers based on relay sharding information
|
||||||
|
|
||||||
|
let typeRecordRes = record.toTyped()
|
||||||
|
let typedRecord =
|
||||||
|
if typeRecordRes.isErr():
|
||||||
|
debug "peer filtering failed", reason= $typeRecordRes.error
|
||||||
|
return none(WakuDiscv5Predicate)
|
||||||
|
else: typeRecordRes.get()
|
||||||
|
|
||||||
|
let nodeShardOp = typedRecord.relaySharding()
|
||||||
|
let nodeShard =
|
||||||
|
if nodeShardOp.isNone():
|
||||||
|
debug "no relay sharding information, peer filtering disabled"
|
||||||
|
return none(WakuDiscv5Predicate)
|
||||||
|
else: nodeShardOp.get()
|
||||||
|
|
||||||
|
debug "peer filtering updated"
|
||||||
|
|
||||||
|
let predicate = proc(record: waku_enr.Record): bool =
|
||||||
|
nodeShard.indices.anyIt(record.containsShard(nodeShard.cluster, it))
|
||||||
|
|
||||||
|
return some(predicate)
|
||||||
|
|
||||||
proc new*(T: type WakuDiscoveryV5, rng: ref HmacDrbgContext, conf: WakuDiscoveryV5Config, record: Option[waku_enr.Record]): T =
|
proc new*(T: type WakuDiscoveryV5, rng: ref HmacDrbgContext, conf: WakuDiscoveryV5Config, record: Option[waku_enr.Record]): T =
|
||||||
let protocol = newProtocol(
|
let protocol = newProtocol(
|
||||||
@ -64,7 +89,13 @@ proc new*(T: type WakuDiscoveryV5, rng: ref HmacDrbgContext, conf: WakuDiscovery
|
|||||||
enrUdpPort = none(Port),
|
enrUdpPort = none(Port),
|
||||||
)
|
)
|
||||||
|
|
||||||
WakuDiscoveryV5(conf: conf, protocol: protocol, listening: false)
|
let shardPredOp =
|
||||||
|
if record.isSome():
|
||||||
|
shardingPredicate(record.get())
|
||||||
|
else:
|
||||||
|
none(WakuDiscv5Predicate)
|
||||||
|
|
||||||
|
WakuDiscoveryV5(conf: conf, protocol: protocol, listening: false, predicate: shardPredOp)
|
||||||
|
|
||||||
proc new*(T: type WakuDiscoveryV5,
|
proc new*(T: type WakuDiscoveryV5,
|
||||||
extIp: Option[ValidIpAddress],
|
extIp: Option[ValidIpAddress],
|
||||||
@ -195,57 +226,29 @@ proc updateENRShards(wd: WakuDiscoveryV5,
|
|||||||
|
|
||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
proc shardingPredicate*(record: Record): Option[WakuDiscv5Predicate] =
|
proc findRandomPeers*(wd: WakuDiscoveryV5, overridePred = none(WakuDiscv5Predicate)): Future[seq[waku_enr.Record]] {.async.} =
|
||||||
## Filter peers based on relay sharding information
|
|
||||||
|
|
||||||
let typeRecordRes = record.toTyped()
|
|
||||||
let typedRecord =
|
|
||||||
if typeRecordRes.isErr():
|
|
||||||
debug "peer filtering failed", reason= $typeRecordRes.error
|
|
||||||
return none(WakuDiscv5Predicate)
|
|
||||||
else: typeRecordRes.get()
|
|
||||||
|
|
||||||
let nodeShardOp = typedRecord.relaySharding()
|
|
||||||
let nodeShard =
|
|
||||||
if nodeShardOp.isNone():
|
|
||||||
debug "no relay sharding information, peer filtering disabled"
|
|
||||||
return none(WakuDiscv5Predicate)
|
|
||||||
else: nodeShardOp.get()
|
|
||||||
|
|
||||||
debug "peer filtering enabled"
|
|
||||||
|
|
||||||
let predicate = proc(record: waku_enr.Record): bool =
|
|
||||||
nodeShard.indices.anyIt(record.containsShard(nodeShard.cluster, it))
|
|
||||||
|
|
||||||
return some(predicate)
|
|
||||||
|
|
||||||
proc findRandomPeers*(wd: WakuDiscoveryV5, pred = none(WakuDiscv5Predicate)): Future[seq[waku_enr.Record]] {.async.} =
|
|
||||||
## Find random peers to connect to using Discovery v5
|
## Find random peers to connect to using Discovery v5
|
||||||
let discoveredNodes = await wd.protocol.queryRandom()
|
let discoveredNodes = await wd.protocol.queryRandom()
|
||||||
|
|
||||||
var discoveredRecords = discoveredNodes.mapIt(it.record)
|
var discoveredRecords = discoveredNodes.mapIt(it.record)
|
||||||
|
|
||||||
# Filter out nodes that do not match the predicate
|
# Filter out nodes that do not match the predicate
|
||||||
if pred.isSome():
|
if overridePred.isSome():
|
||||||
discoveredRecords = discoveredRecords.filter(pred.get())
|
discoveredRecords = discoveredRecords.filter(overridePred.get())
|
||||||
|
elif wd.predicate.isSome():
|
||||||
|
discoveredRecords = discoveredRecords.filter(wd.predicate.get())
|
||||||
|
|
||||||
return discoveredRecords
|
return discoveredRecords
|
||||||
|
|
||||||
#TODO abstract away PeerManager
|
#TODO abstract away PeerManager
|
||||||
proc searchLoop*(wd: WakuDiscoveryV5, peerManager: PeerManager, record: Option[enr.Record]) {.async.} =
|
proc searchLoop*(wd: WakuDiscoveryV5, peerManager: PeerManager) {.async.} =
|
||||||
## Continuously add newly discovered nodes
|
## Continuously add newly discovered nodes
|
||||||
|
|
||||||
info "Starting discovery v5 search"
|
info "Starting discovery v5 search"
|
||||||
|
|
||||||
let shardPredOp =
|
|
||||||
if record.isSome():
|
|
||||||
shardingPredicate(record.get())
|
|
||||||
else:
|
|
||||||
none(WakuDiscv5Predicate)
|
|
||||||
|
|
||||||
while wd.listening:
|
while wd.listening:
|
||||||
trace "running discv5 discovery loop"
|
trace "running discv5 discovery loop"
|
||||||
let discoveredRecords = await wd.findRandomPeers(shardPredOp)
|
let discoveredRecords = await wd.findRandomPeers()
|
||||||
let discoveredPeers = discoveredRecords.mapIt(it.toRemotePeerInfo()).filterIt(it.isOk()).mapIt(it.value)
|
let discoveredPeers = discoveredRecords.mapIt(it.toRemotePeerInfo()).filterIt(it.isOk()).mapIt(it.value)
|
||||||
|
|
||||||
for peer in discoveredPeers:
|
for peer in discoveredPeers:
|
||||||
@ -305,6 +308,9 @@ proc subscriptionsListener*(wd: WakuDiscoveryV5, topicSubscriptionQueue: AsyncEv
|
|||||||
let subs = events.filterIt(it.kind == SubscriptionKind.PubsubSub).mapIt(it.pubsubSub)
|
let subs = events.filterIt(it.kind == SubscriptionKind.PubsubSub).mapIt(it.pubsubSub)
|
||||||
let unsubs = events.filterIt(it.kind == SubscriptionKind.PubsubUnsub).mapIt(it.pubsubUnsub)
|
let unsubs = events.filterIt(it.kind == SubscriptionKind.PubsubUnsub).mapIt(it.pubsubUnsub)
|
||||||
|
|
||||||
|
if subs.len == 0 and unsubs.len == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
let unsubRes = wd.updateENRShards(unsubs, false)
|
let unsubRes = wd.updateENRShards(unsubs, false)
|
||||||
let subRes = wd.updateENRShards(subs, true)
|
let subRes = wd.updateENRShards(subs, true)
|
||||||
|
|
||||||
@ -314,9 +320,13 @@ proc subscriptionsListener*(wd: WakuDiscoveryV5, topicSubscriptionQueue: AsyncEv
|
|||||||
if unsubRes.isErr():
|
if unsubRes.isErr():
|
||||||
debug "ENR shard removal failed", reason= $unsubRes.error
|
debug "ENR shard removal failed", reason= $unsubRes.error
|
||||||
|
|
||||||
if subRes.isOk() and unsubRes.isOk():
|
if subRes.isErr() and unsubRes.isErr():
|
||||||
|
continue
|
||||||
|
|
||||||
debug "ENR updated successfully"
|
debug "ENR updated successfully"
|
||||||
|
|
||||||
|
wd.predicate = shardingPredicate(wd.protocol.localNode.record)
|
||||||
|
|
||||||
topicSubscriptionQueue.unregister(key)
|
topicSubscriptionQueue.unregister(key)
|
||||||
|
|
||||||
## Helper functions
|
## Helper functions
|
||||||
|
Loading…
x
Reference in New Issue
Block a user