mirror of https://github.com/waku-org/nwaku.git
feat: RLN proofs as a lightpush service (#2768)
This commit is contained in:
parent
b52286524b
commit
0561e5bd45
|
@ -1,7 +1,7 @@
|
||||||
{.used.}
|
{.used.}
|
||||||
|
|
||||||
import
|
import
|
||||||
std/[options, tables, sequtils],
|
std/[options, tables, sequtils, tempfiles],
|
||||||
stew/shims/net as stewNet,
|
stew/shims/net as stewNet,
|
||||||
testutils/unittests,
|
testutils/unittests,
|
||||||
chronos,
|
chronos,
|
||||||
|
@ -23,6 +23,7 @@ import
|
||||||
waku_lightpush/client,
|
waku_lightpush/client,
|
||||||
waku_lightpush/protocol_metrics,
|
waku_lightpush/protocol_metrics,
|
||||||
waku_lightpush/rpc,
|
waku_lightpush/rpc,
|
||||||
|
waku_rln_relay
|
||||||
],
|
],
|
||||||
../testlib/[assertions, common, wakucore, wakunode, testasync, futures, testutils],
|
../testlib/[assertions, common, wakucore, wakunode, testasync, futures, testutils],
|
||||||
../resources/payloads
|
../resources/payloads
|
||||||
|
@ -59,7 +60,7 @@ suite "Waku Lightpush - End To End":
|
||||||
await server.start()
|
await server.start()
|
||||||
|
|
||||||
await server.mountRelay()
|
await server.mountRelay()
|
||||||
await server.mountLightpush()
|
await server.mountLightpush() # without rln-relay
|
||||||
client.mountLightpushClient()
|
client.mountLightpushClient()
|
||||||
|
|
||||||
serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo()
|
serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo()
|
||||||
|
@ -104,3 +105,82 @@ suite "Waku Lightpush - End To End":
|
||||||
check:
|
check:
|
||||||
publishResponse.isErr()
|
publishResponse.isErr()
|
||||||
publishResponse.error == fmt"Message size exceeded maximum of {DefaultMaxWakuMessageSize} bytes"
|
publishResponse.error == fmt"Message size exceeded maximum of {DefaultMaxWakuMessageSize} bytes"
|
||||||
|
|
||||||
|
suite "RLN Proofs as a Lightpush Service":
|
||||||
|
var
|
||||||
|
handlerFuture {.threadvar.}: Future[(PubsubTopic, WakuMessage)]
|
||||||
|
handler {.threadvar.}: PushMessageHandler
|
||||||
|
|
||||||
|
server {.threadvar.}: WakuNode
|
||||||
|
client {.threadvar.}: WakuNode
|
||||||
|
|
||||||
|
serverRemotePeerInfo {.threadvar.}: RemotePeerInfo
|
||||||
|
pubsubTopic {.threadvar.}: PubsubTopic
|
||||||
|
contentTopic {.threadvar.}: ContentTopic
|
||||||
|
message {.threadvar.}: WakuMessage
|
||||||
|
|
||||||
|
asyncSetup:
|
||||||
|
handlerFuture = newPushHandlerFuture()
|
||||||
|
handler = proc(
|
||||||
|
peer: PeerId, pubsubTopic: PubsubTopic, message: WakuMessage
|
||||||
|
): Future[WakuLightPushResult[void]] {.async.} =
|
||||||
|
handlerFuture.complete((pubsubTopic, message))
|
||||||
|
return ok()
|
||||||
|
|
||||||
|
let
|
||||||
|
serverKey = generateSecp256k1Key()
|
||||||
|
clientKey = generateSecp256k1Key()
|
||||||
|
|
||||||
|
server = newTestWakuNode(serverKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
||||||
|
client = newTestWakuNode(clientKey, ValidIpAddress.init("0.0.0.0"), Port(0))
|
||||||
|
|
||||||
|
# mount rln-relay
|
||||||
|
when defined(rln_v2):
|
||||||
|
let wakuRlnConfig = WakuRlnConfig(
|
||||||
|
rlnRelayDynamic: false,
|
||||||
|
rlnRelayCredIndex: some(1.uint),
|
||||||
|
rlnRelayUserMessageLimit: 1,
|
||||||
|
rlnEpochSizeSec: 1,
|
||||||
|
rlnRelayTreePath: genTempPath("rln_tree", "wakunode"),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
let wakuRlnConfig = WakuRlnConfig(
|
||||||
|
rlnRelayDynamic: false,
|
||||||
|
rlnRelayCredIndex: some(1.uint),
|
||||||
|
rlnEpochSizeSec: 1,
|
||||||
|
rlnRelayTreePath: genTempPath("rln_tree", "wakunode"),
|
||||||
|
)
|
||||||
|
|
||||||
|
await allFutures(server.start(), client.start())
|
||||||
|
await server.start()
|
||||||
|
|
||||||
|
await server.mountRelay()
|
||||||
|
await server.mountRlnRelay(wakuRlnConfig)
|
||||||
|
await server.mountLightpush()
|
||||||
|
client.mountLightpushClient()
|
||||||
|
|
||||||
|
serverRemotePeerInfo = server.peerInfo.toRemotePeerInfo()
|
||||||
|
pubsubTopic = DefaultPubsubTopic
|
||||||
|
contentTopic = DefaultContentTopic
|
||||||
|
message = fakeWakuMessage()
|
||||||
|
|
||||||
|
asyncTeardown:
|
||||||
|
await server.stop()
|
||||||
|
|
||||||
|
suite "Lightpush attaching RLN proofs":
|
||||||
|
asyncTest "Message is published when RLN enabled":
|
||||||
|
# Given a light lightpush client
|
||||||
|
let lightpushClient =
|
||||||
|
newTestWakuNode(generateSecp256k1Key(), ValidIpAddress.init("0.0.0.0"), Port(0))
|
||||||
|
lightpushClient.mountLightpushClient()
|
||||||
|
|
||||||
|
# When the client publishes a message
|
||||||
|
let publishResponse = await lightpushClient.lightpushPublish(
|
||||||
|
some(pubsubTopic), message, serverRemotePeerInfo
|
||||||
|
)
|
||||||
|
|
||||||
|
if not publishResponse.isOk():
|
||||||
|
echo "Publish failed: ", publishResponse.error()
|
||||||
|
|
||||||
|
# Then the message is relayed to the server
|
||||||
|
assertResultOk publishResponse
|
|
@ -44,6 +44,7 @@ import
|
||||||
../waku_lightpush/common,
|
../waku_lightpush/common,
|
||||||
../waku_lightpush/protocol,
|
../waku_lightpush/protocol,
|
||||||
../waku_lightpush/self_req_handler,
|
../waku_lightpush/self_req_handler,
|
||||||
|
../waku_lightpush/callbacks,
|
||||||
../waku_enr,
|
../waku_enr,
|
||||||
../waku_peer_exchange,
|
../waku_peer_exchange,
|
||||||
../waku_rln_relay,
|
../waku_rln_relay,
|
||||||
|
@ -977,33 +978,21 @@ proc mountLightPush*(
|
||||||
) {.async.} =
|
) {.async.} =
|
||||||
info "mounting light push"
|
info "mounting light push"
|
||||||
|
|
||||||
var pushHandler: PushMessageHandler
|
var pushHandler =
|
||||||
if node.wakuRelay.isNil():
|
if node.wakuRelay.isNil:
|
||||||
debug "mounting lightpush without relay (nil)"
|
debug "mounting lightpush without relay (nil)"
|
||||||
pushHandler = proc(
|
getNilPushHandler()
|
||||||
peer: PeerId, pubsubTopic: string, message: WakuMessage
|
else:
|
||||||
): Future[WakuLightPushResult[void]] {.async.} =
|
debug "mounting lightpush with relay"
|
||||||
return err("no waku relay found")
|
let rlnPeer =
|
||||||
else:
|
if isNil(node.wakuRlnRelay):
|
||||||
pushHandler = proc(
|
debug "mounting lightpush without rln-relay"
|
||||||
peer: PeerId, pubsubTopic: string, message: WakuMessage
|
none(WakuRLNRelay)
|
||||||
): Future[WakuLightPushResult[void]] {.async.} =
|
else:
|
||||||
let validationRes = await node.wakuRelay.validateMessage(pubSubTopic, message)
|
debug "mounting lightpush with rln-relay"
|
||||||
if validationRes.isErr():
|
some(node.wakuRlnRelay)
|
||||||
return err(validationRes.error)
|
getRelayPushHandler(node.wakuRelay, rlnPeer)
|
||||||
|
|
||||||
let publishedCount =
|
|
||||||
await node.wakuRelay.publish(pubsubTopic, message.encode().buffer)
|
|
||||||
|
|
||||||
if publishedCount == 0:
|
|
||||||
## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93
|
|
||||||
let msgHash = computeMessageHash(pubsubTopic, message).to0xHex()
|
|
||||||
notice "Lightpush request has not been published to any peers",
|
|
||||||
msg_hash = msgHash
|
|
||||||
|
|
||||||
return ok()
|
|
||||||
|
|
||||||
debug "mounting lightpush with relay"
|
|
||||||
node.wakuLightPush =
|
node.wakuLightPush =
|
||||||
WakuLightPush.new(node.peerManager, node.rng, pushHandler, some(rateLimit))
|
WakuLightPush.new(node.peerManager, node.rng, pushHandler, some(rateLimit))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
when (NimMajor, NimMinor) < (1, 4):
|
||||||
|
{.push raises: [Defect].}
|
||||||
|
else:
|
||||||
|
{.push raises: [].}
|
||||||
|
|
||||||
|
import
|
||||||
|
../waku_core,
|
||||||
|
../waku_relay,
|
||||||
|
./common,
|
||||||
|
./protocol,
|
||||||
|
../waku_rln_relay,
|
||||||
|
../waku_rln_relay/protocol_types,
|
||||||
|
../common/ratelimit
|
||||||
|
import
|
||||||
|
std/times,
|
||||||
|
libp2p/peerid,
|
||||||
|
stew/byteutils
|
||||||
|
|
||||||
|
proc checkAndGenerateRLNProof*(rlnPeer: Option[WakuRLNRelay], message: WakuMessage): Result[WakuMessage, string] =
|
||||||
|
# check if the message already has RLN proof
|
||||||
|
if message.proof.len > 0:
|
||||||
|
return ok(message)
|
||||||
|
|
||||||
|
if rlnPeer.isNone():
|
||||||
|
notice "Publishing message without RLN proof"
|
||||||
|
return ok(message)
|
||||||
|
# generate and append RLN proof
|
||||||
|
let
|
||||||
|
time = getTime().toUnix()
|
||||||
|
senderEpochTime = float64(time)
|
||||||
|
var msgWithProof = message
|
||||||
|
rlnPeer.get().appendRLNProof(msgWithProof, senderEpochTime).isOkOr:
|
||||||
|
return err(error)
|
||||||
|
return ok(msgWithProof)
|
||||||
|
|
||||||
|
proc getNilPushHandler*(): PushMessageHandler =
|
||||||
|
return proc(
|
||||||
|
peer: PeerId, pubsubTopic: string, message: WakuMessage
|
||||||
|
): Future[WakuLightPushResult[void]] {.async.} =
|
||||||
|
return err("no waku relay found")
|
||||||
|
|
||||||
|
proc getRelayPushHandler*(
|
||||||
|
wakuRelay: WakuRelay,
|
||||||
|
rlnPeer: Option[WakuRLNRelay] = none[WakuRLNRelay]()
|
||||||
|
): PushMessageHandler =
|
||||||
|
return proc(
|
||||||
|
peer: PeerId, pubsubTopic: string, message: WakuMessage
|
||||||
|
): Future[WakuLightPushResult[void]] {.async.} =
|
||||||
|
# append RLN proof
|
||||||
|
let msgWithProof = checkAndGenerateRLNProof(rlnPeer, message)
|
||||||
|
if msgWithProof.isErr():
|
||||||
|
return err(msgWithProof.error)
|
||||||
|
|
||||||
|
(await wakuRelay.validateMessage(pubSubTopic, msgWithProof.value)).isOkOr:
|
||||||
|
return err(error)
|
||||||
|
|
||||||
|
let publishedCount = await wakuRelay.publish(pubsubTopic, msgWithProof.value)
|
||||||
|
if publishedCount == 0:
|
||||||
|
## Agreed change expected to the lightpush protocol to better handle such case. https://github.com/waku-org/pm/issues/93
|
||||||
|
let msgHash = computeMessageHash(pubsubTopic, message).to0xHex()
|
||||||
|
notice "Lightpush request has not been published to any peers", msg_hash = msgHash
|
||||||
|
|
||||||
|
return ok()
|
Loading…
Reference in New Issue