mirror of https://github.com/waku-org/nwaku.git
Basic proof gen and vrfy (#421)
* adds the proof field to the WakuMessage * adds a basic zkProof api * adds proof gen to the publish proc * relocates the proofGen and proofVrfy to rln_relay_utils * wip: test of proof gen * adds a procedure to pass rln-relay message validator, adds the proof gen * tests the proof gen and verify * relocates zkp API * adds documentation and todos * adds todos and documentations * removes an unnecessary comment * adds todos
This commit is contained in:
parent
b3208b343f
commit
d64aadc8ad
|
@ -394,4 +394,58 @@ procSuite "WakuNode":
|
|||
await node1.stop()
|
||||
await node2.stop()
|
||||
await node3.stop()
|
||||
asyncTest "testing rln-relay with mocked zkp":
|
||||
|
||||
let
|
||||
# publisher node
|
||||
nodeKey1 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node1 = WakuNode.init(nodeKey1, ValidIpAddress.init("0.0.0.0"), Port(60000))
|
||||
# Relay node
|
||||
nodeKey2 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node2 = WakuNode.init(nodeKey2, ValidIpAddress.init("0.0.0.0"), Port(60002))
|
||||
# Subscriber
|
||||
nodeKey3 = crypto.PrivateKey.random(Secp256k1, rng[])[]
|
||||
node3 = WakuNode.init(nodeKey3, ValidIpAddress.init("0.0.0.0"), Port(60003))
|
||||
|
||||
pubSubTopic = "defaultTopic"
|
||||
contentTopic1 = ContentTopic(1)
|
||||
payload = "hello world".toBytes()
|
||||
message1 = WakuMessage(payload: payload, contentTopic: contentTopic1)
|
||||
|
||||
# start all the nodes
|
||||
await node1.start()
|
||||
node1.mountRelay(@[pubSubTopic])
|
||||
|
||||
await node2.start()
|
||||
node2.mountRelay(@[pubSubTopic])
|
||||
node2.addRLNRelayValidator(pubSubTopic)
|
||||
|
||||
await node3.start()
|
||||
node3.mountRelay(@[pubSubTopic])
|
||||
|
||||
await node1.connectToNodes(@[node2.peerInfo])
|
||||
await node3.connectToNodes(@[node2.peerInfo])
|
||||
|
||||
var completionFut = newFuture[bool]()
|
||||
proc relayHandler(topic: string, data: seq[byte]) {.async, gcsafe.} =
|
||||
let msg = WakuMessage.init(data)
|
||||
if msg.isOk():
|
||||
let val = msg.value()
|
||||
debug "The received topic:", topic
|
||||
if topic == pubSubTopic:
|
||||
completionFut.complete(true)
|
||||
|
||||
|
||||
node3.subscribe(pubSubTopic, relayHandler)
|
||||
await sleepAsync(2000.millis)
|
||||
|
||||
await node1.publish(pubSubTopic, message1, rlnRelayEnabled = true)
|
||||
await sleepAsync(2000.millis)
|
||||
|
||||
|
||||
check:
|
||||
(await completionFut.withTimeout(10.seconds)) == true
|
||||
|
||||
await node1.stop()
|
||||
await node2.stop()
|
||||
await node3.stop()
|
||||
|
|
|
@ -8,9 +8,10 @@ import
|
|||
libp2p/crypto/crypto,
|
||||
libp2p/protocols/protocol,
|
||||
# NOTE For TopicHandler, solve with exports?
|
||||
libp2p/protocols/pubsub/rpc/messages,
|
||||
libp2p/protocols/pubsub/pubsub,
|
||||
libp2p/standard_setup,
|
||||
../protocol/[waku_relay, message_notifier],
|
||||
../protocol/[waku_relay, waku_message, message_notifier],
|
||||
../protocol/waku_store/waku_store,
|
||||
../protocol/waku_swap/waku_swap,
|
||||
../protocol/waku_filter/waku_filter,
|
||||
|
@ -239,17 +240,26 @@ proc unsubscribe*(node: WakuNode, request: FilterRequest) {.async, gcsafe.} =
|
|||
waku_node_filters.set(node.filters.len.int64)
|
||||
|
||||
|
||||
proc publish*(node: WakuNode, topic: Topic, message: WakuMessage) {.async, gcsafe.} =
|
||||
proc publish*(node: WakuNode, topic: Topic, message: WakuMessage, rlnRelayEnabled: bool = false) {.async, gcsafe.} =
|
||||
## Publish a `WakuMessage` to a PubSub topic. `WakuMessage` should contain a
|
||||
## `contentTopic` field for light node functionality. This field may be also
|
||||
## be omitted.
|
||||
##
|
||||
## Status: Implemented.
|
||||
##
|
||||
## When rlnRelayEnabled is true, a zkp will be generated and attached to the message (it is an experimental feature)
|
||||
|
||||
let wakuRelay = node.wakuRelay
|
||||
|
||||
debug "publish", topic=topic, contentTopic=message.contentTopic
|
||||
var publishingMessage = message
|
||||
|
||||
if rlnRelayEnabled:
|
||||
# if rln relay is enabled then a proof must be generated and added to the waku message
|
||||
let
|
||||
proof = proofGen(message.payload)
|
||||
## TODO here since the message is immutable we have to make a copy of it and then attach the proof to its duplicate
|
||||
## TODO however, it might be better to change message type to mutable (i.e., var) so that we can add the proof field to the original message
|
||||
publishingMessage = WakuMessage(payload: message.payload, contentTopic: message.contentTopic, version: message.version, proof: proof)
|
||||
|
||||
let data = message.encode().buffer
|
||||
|
||||
discard await wakuRelay.publish(topic, data)
|
||||
|
@ -343,6 +353,20 @@ proc mountRlnRelay*(node: WakuNode, ethClientAddress: Option[string] = none(stri
|
|||
node.wakuRlnRelay = rlnPeer
|
||||
|
||||
|
||||
proc addRLNRelayValidator*(node: WakuNode, pubsubTopic: string) =
|
||||
## this procedure is a thin wrapper for the pubsub addValidator method
|
||||
## it sets message validator on the given pubsubTopic, the validator will check that
|
||||
## all the messages published in the pubsubTopic have a valid zero-knowledge proof
|
||||
proc validator(topic: string, message: messages.Message): Future[ValidationResult] {.async.} =
|
||||
let msg = WakuMessage.init(message.data)
|
||||
if msg.isOk():
|
||||
# check the proof
|
||||
if proofVrfy(msg.value().payload, msg.value().proof):
|
||||
result = ValidationResult.Accept
|
||||
# set a validator for the pubsubTopic
|
||||
let pb = PubSub(node.wakuRelay)
|
||||
pb.addValidator(pubsubTopic, validator)
|
||||
|
||||
proc mountRelay*(node: WakuNode, topics: seq[string] = newSeq[string](), rlnRelayEnabled = false) {.gcsafe.} =
|
||||
let wakuRelay = WakuRelay.init(
|
||||
switch = node.switch,
|
||||
|
@ -376,8 +400,11 @@ proc mountRelay*(node: WakuNode, topics: seq[string] = newSeq[string](), rlnRela
|
|||
# TODO pass rln relay inputs to this proc, right now it uses default values that are set in the mountRlnRelay proc
|
||||
info "WakuRLNRelay is enabled"
|
||||
waitFor mountRlnRelay(node)
|
||||
# TODO currently the message validator is set for the defaultTopic, this can be configurable to accept other pubsub topics as well
|
||||
addRLNRelayValidator(node, defaultTopic)
|
||||
info "WakuRLNRelay is mounted successfully"
|
||||
|
||||
|
||||
## Helpers
|
||||
proc dialPeer*(n: WakuNode, address: string) {.async.} =
|
||||
info "dialPeer", address = address
|
||||
|
|
|
@ -16,6 +16,9 @@ type
|
|||
payload*: seq[byte]
|
||||
contentTopic*: ContentTopic
|
||||
version*: uint32
|
||||
# the proof field indicates that the message is not a spam
|
||||
# this field will be used in the rln-relay protocol
|
||||
proof*: seq[byte]
|
||||
|
||||
# Encoding and decoding -------------------------------------------------------
|
||||
proc init*(T: type WakuMessage, buffer: seq[byte]): ProtoResult[T] =
|
||||
|
@ -25,6 +28,7 @@ proc init*(T: type WakuMessage, buffer: seq[byte]): ProtoResult[T] =
|
|||
discard ? pb.getField(1, msg.payload)
|
||||
discard ? pb.getField(2, msg.contentTopic)
|
||||
discard ? pb.getField(3, msg.version)
|
||||
discard ? pb.getField(4, msg.proof)
|
||||
|
||||
ok(msg)
|
||||
|
||||
|
@ -34,3 +38,4 @@ proc encode*(message: WakuMessage): ProtoBuffer =
|
|||
result.write(1, message.payload)
|
||||
result.write(2, message.contentTopic)
|
||||
result.write(3, message.version)
|
||||
result.write(4, message.proof)
|
||||
|
|
|
@ -67,3 +67,5 @@ proc hash*(ctx: ptr RLNBn256, inputs_buffer:ptr Buffer, input_len: ptr csize_t,
|
|||
# ) -> bool
|
||||
|
||||
{.pop.}
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import
|
||||
chronicles, options, chronos, stint,
|
||||
chronicles, options, chronos, stint, sequtils,
|
||||
web3,
|
||||
stew/byteutils,
|
||||
eth/keys,
|
||||
|
@ -99,3 +99,11 @@ proc register*(rlnPeer: WakuRLNRelay): Future[bool] {.async.} =
|
|||
# TODO check the receipt and then return true/false
|
||||
await web3.close()
|
||||
return true
|
||||
|
||||
proc proofGen*(data: seq[byte]): seq[byte] =
|
||||
# TODO to implement the actual proof generation logic
|
||||
return "proof".toBytes()
|
||||
|
||||
proc proofVrfy*(data, proof: seq[byte]): bool =
|
||||
# TODO to implement the actual proof verification logic
|
||||
return true
|
Loading…
Reference in New Issue