mirror of
https://github.com/waku-org/nwaku.git
synced 2025-02-28 15:00:57 +00:00
feat(Rln relay): Improves rln-chat2 interface, displays links to the registration tx, warns about spam messages (#1082)
* warns about publishing spam messages, display tx hash on Goerli * passes registration handler
This commit is contained in:
parent
11158c3ea2
commit
bc29619679
@ -229,7 +229,13 @@ proc publish(c: Chat, line: string) =
|
|||||||
else:
|
else:
|
||||||
debug "rate limit proof is appended to the message", success=success
|
debug "rate limit proof is appended to the message", success=success
|
||||||
# TODO move it to log after doogfooding
|
# TODO move it to log after doogfooding
|
||||||
echo "--rln epoch: ", fromEpoch(message.proof.epoch)
|
let msgEpoch = fromEpoch(message.proof.epoch)
|
||||||
|
if fromEpoch(c.node.wakuRlnRelay.lastEpoch) == fromEpoch(message.proof.epoch):
|
||||||
|
echo "--rln epoch: ", msgEpoch, " ⚠️ message rate violation! you are spamming the network!"
|
||||||
|
else:
|
||||||
|
echo "--rln epoch: ", msgEpoch
|
||||||
|
# update the last epoch
|
||||||
|
c.node.wakuRlnRelay.lastEpoch = message.proof.epoch
|
||||||
if not c.node.wakuLightPush.isNil():
|
if not c.node.wakuLightPush.isNil():
|
||||||
# Attempt lightpush
|
# Attempt lightpush
|
||||||
asyncSpawn c.node.lightpush(DefaultTopic, message, handler)
|
asyncSpawn c.node.lightpush(DefaultTopic, message, handler)
|
||||||
@ -250,7 +256,14 @@ proc publish(c: Chat, line: string) =
|
|||||||
debug "could not append rate limit proof to the message", success=success
|
debug "could not append rate limit proof to the message", success=success
|
||||||
else:
|
else:
|
||||||
debug "rate limit proof is appended to the message", success=success
|
debug "rate limit proof is appended to the message", success=success
|
||||||
echo "--rln epoch: ", fromEpoch(message.proof.epoch)
|
# TODO move it to log after doogfooding
|
||||||
|
let msgEpoch = fromEpoch(message.proof.epoch)
|
||||||
|
if fromEpoch(c.node.wakuRlnRelay.lastEpoch) == msgEpoch:
|
||||||
|
echo "--rln epoch: ", msgEpoch, " ⚠️ message rate violation! you are spamming the network!"
|
||||||
|
else:
|
||||||
|
echo "--rln epoch: ", msgEpoch
|
||||||
|
# update the last epoch
|
||||||
|
c.node.wakuRlnRelay.lastEpoch = message.proof.epoch
|
||||||
|
|
||||||
if not c.node.wakuLightPush.isNil():
|
if not c.node.wakuLightPush.isNil():
|
||||||
# Attempt lightpush
|
# Attempt lightpush
|
||||||
@ -511,8 +524,11 @@ proc processInput(rfd: AsyncFD, rng: ref BrHmacDrbgContext) {.async.} =
|
|||||||
echo "A spam message is found and discarded"
|
echo "A spam message is found and discarded"
|
||||||
chat.prompt = false
|
chat.prompt = false
|
||||||
showChatPrompt(chat)
|
showChatPrompt(chat)
|
||||||
|
proc registrationHandler(txHash: string) {.gcsafe, closure.} =
|
||||||
|
echo "You are registered to the rln membership contract, find details of your registration transaction in https://goerli.etherscan.io/tx/0x", txHash
|
||||||
|
|
||||||
echo "rln-relay preparation is in progress ..."
|
echo "rln-relay preparation is in progress ..."
|
||||||
node.mountRlnRelay(conf, some(spamHandler))
|
node.mountRlnRelay(conf = conf, spamHandler = some(spamHandler), registrationHandler = some(registrationHandler))
|
||||||
echo "your membership index is: ", node.wakuRlnRelay.membershipIndex
|
echo "your membership index is: ", node.wakuRlnRelay.membershipIndex
|
||||||
echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.toHex()
|
echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.toHex()
|
||||||
echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.toHex()
|
echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.toHex()
|
||||||
|
@ -120,6 +120,7 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)):
|
|||||||
contentTopic*: string
|
contentTopic*: string
|
||||||
# the log of nullifiers and Shamir shares of the past messages grouped per epoch
|
# the log of nullifiers and Shamir shares of the past messages grouped per epoch
|
||||||
nullifierLog*: Table[Epoch, seq[ProofMetadata]]
|
nullifierLog*: Table[Epoch, seq[ProofMetadata]]
|
||||||
|
lastEpoch*: Epoch # the epoch of the last published rln message
|
||||||
|
|
||||||
when defined(rlnzerokit):
|
when defined(rlnzerokit):
|
||||||
type WakuRLNRelay* = ref object
|
type WakuRLNRelay* = ref object
|
||||||
|
@ -33,8 +33,8 @@ when defined(rlnzerokit):
|
|||||||
|
|
||||||
type MerkleNodeResult* = Result[MerkleNode, string]
|
type MerkleNodeResult* = Result[MerkleNode, string]
|
||||||
type RateLimitProofResult* = Result[RateLimitProof, string]
|
type RateLimitProofResult* = Result[RateLimitProof, string]
|
||||||
type SpamHandler* = proc(wakuMessage: WakuMessage): void {.gcsafe, closure,
|
type SpamHandler* = proc(wakuMessage: WakuMessage): void {.gcsafe, closure, raises: [Defect].}
|
||||||
raises: [Defect].}
|
type RegistrationHandler* = proc(txHash: string): void {.gcsafe, closure, raises: [Defect].}
|
||||||
|
|
||||||
# membership contract interface
|
# membership contract interface
|
||||||
contract(MembershipContract):
|
contract(MembershipContract):
|
||||||
@ -190,7 +190,7 @@ proc toMembershipIndex(v: UInt256): MembershipIndex =
|
|||||||
let result: MembershipIndex = cast[MembershipIndex](v)
|
let result: MembershipIndex = cast[MembershipIndex](v)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
proc register*(idComm: IDCommitment, ethAccountAddress: Address, ethAccountPrivKey: keys.PrivateKey, ethClientAddress: string, membershipContractAddress: Address): Future[Result[MembershipIndex, string]] {.async.} =
|
proc register*(idComm: IDCommitment, ethAccountAddress: Address, ethAccountPrivKey: keys.PrivateKey, ethClientAddress: string, membershipContractAddress: Address, registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)): Future[Result[MembershipIndex, string]] {.async.} =
|
||||||
# TODO may need to also get eth Account Private Key as PrivateKey
|
# TODO may need to also get eth Account Private Key as PrivateKey
|
||||||
## registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
|
## registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||||
let web3 = await newWeb3(ethClientAddress)
|
let web3 = await newWeb3(ethClientAddress)
|
||||||
@ -234,13 +234,16 @@ proc register*(idComm: IDCommitment, ethAccountAddress: Address, ethAccountPrivK
|
|||||||
|
|
||||||
|
|
||||||
await web3.close()
|
await web3.close()
|
||||||
|
if registrationHandler.isSome():
|
||||||
|
let handler = registrationHandler.get
|
||||||
|
handler(toHex(txHash))
|
||||||
return ok(toMembershipIndex(eventIndex))
|
return ok(toMembershipIndex(eventIndex))
|
||||||
|
|
||||||
proc register*(rlnPeer: WakuRLNRelay): Future[bool] {.async.} =
|
proc register*(rlnPeer: WakuRLNRelay, registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)): Future[bool] {.async.} =
|
||||||
## registers the public key of the rlnPeer which is rlnPeer.membershipKeyPair.publicKey
|
## registers the public key of the rlnPeer which is rlnPeer.membershipKeyPair.publicKey
|
||||||
## into the membership contract whose address is in rlnPeer.membershipContractAddress
|
## into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||||
let pk = rlnPeer.membershipKeyPair.idCommitment
|
let pk = rlnPeer.membershipKeyPair.idCommitment
|
||||||
discard await register(idComm = pk, ethAccountAddress = rlnPeer.ethAccountAddress, ethAccountPrivKey = rlnPeer.ethAccountPrivateKey.get(), ethClientAddress = rlnPeer.ethClientAddress, membershipContractAddress = rlnPeer.membershipContractAddress )
|
discard await register(idComm = pk, ethAccountAddress = rlnPeer.ethAccountAddress, ethAccountPrivKey = rlnPeer.ethAccountPrivateKey.get(), ethClientAddress = rlnPeer.ethClientAddress, membershipContractAddress = rlnPeer.membershipContractAddress, registrationHandler = registrationHandler)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
@ -957,7 +960,8 @@ proc mountRlnRelayDynamic*(node: WakuNode,
|
|||||||
memIndex: Option[MembershipIndex] = none(MembershipIndex),
|
memIndex: Option[MembershipIndex] = none(MembershipIndex),
|
||||||
pubsubTopic: string,
|
pubsubTopic: string,
|
||||||
contentTopic: ContentTopic,
|
contentTopic: ContentTopic,
|
||||||
spamHandler: Option[SpamHandler] = none(SpamHandler)) {.async.} =
|
spamHandler: Option[SpamHandler] = none(SpamHandler),
|
||||||
|
registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) {.async.} =
|
||||||
debug "mounting rln-relay in on-chain/dynamic mode"
|
debug "mounting rln-relay in on-chain/dynamic mode"
|
||||||
# TODO return a bool value to indicate the success of the call
|
# TODO return a bool value to indicate the success of the call
|
||||||
# relay protocol is the prerequisite of rln-relay
|
# relay protocol is the prerequisite of rln-relay
|
||||||
@ -986,7 +990,7 @@ proc mountRlnRelayDynamic*(node: WakuNode,
|
|||||||
doAssert(keyPairOpt.isSome)
|
doAssert(keyPairOpt.isSome)
|
||||||
keyPair = keyPairOpt.get()
|
keyPair = keyPairOpt.get()
|
||||||
# register the rln-relay peer to the membership contract
|
# register the rln-relay peer to the membership contract
|
||||||
let regIndexRes = await register(idComm = keyPair.idCommitment, ethAccountAddress = ethAccAddr, ethAccountPrivKey = ethAccountPrivKeyOpt.get(), ethClientAddress = ethClientAddr, membershipContractAddress = memContractAddr)
|
let regIndexRes = await register(idComm = keyPair.idCommitment, ethAccountAddress = ethAccAddr, ethAccountPrivKey = ethAccountPrivKeyOpt.get(), ethClientAddress = ethClientAddr, membershipContractAddress = memContractAddr, registrationHandler = registrationHandler)
|
||||||
# check whether registration is done
|
# check whether registration is done
|
||||||
doAssert(regIndexRes.isOk())
|
doAssert(regIndexRes.isOk())
|
||||||
rlnIndex = regIndexRes.value
|
rlnIndex = regIndexRes.value
|
||||||
@ -1042,7 +1046,7 @@ proc readPersistentRlnCredentials*(path: string) : RlnMembershipCredentials {.ra
|
|||||||
debug "Deserialized Rln credentials", rlnCredentials=deserializedRlnCredentials
|
debug "Deserialized Rln credentials", rlnCredentials=deserializedRlnCredentials
|
||||||
result = deserializedRlnCredentials
|
result = deserializedRlnCredentials
|
||||||
|
|
||||||
proc mountRlnRelay*(node: WakuNode, conf: WakuNodeConf|Chat2Conf, spamHandler: Option[SpamHandler] = none(SpamHandler)) {.raises: [Defect, ValueError, IOError, CatchableError, Exception].} =
|
proc mountRlnRelay*(node: WakuNode, conf: WakuNodeConf|Chat2Conf, spamHandler: Option[SpamHandler] = none(SpamHandler), registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)) {.raises: [Defect, ValueError, IOError, CatchableError, Exception].} =
|
||||||
if not conf.rlnRelayDynamic:
|
if not conf.rlnRelayDynamic:
|
||||||
info " setting up waku-rln-relay in off-chain mode... "
|
info " setting up waku-rln-relay in off-chain mode... "
|
||||||
# set up rln relay inputs
|
# set up rln relay inputs
|
||||||
@ -1091,14 +1095,14 @@ proc mountRlnRelay*(node: WakuNode, conf: WakuNodeConf|Chat2Conf, spamHandler: O
|
|||||||
# mount rln-relay with the provided rln-relay credential
|
# mount rln-relay with the provided rln-relay credential
|
||||||
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
|
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
|
||||||
memKeyPair = some(credentials.membershipKeyPair), memIndex = some(credentials.rlnIndex), ethAccAddr = ethAccountAddr,
|
memKeyPair = some(credentials.membershipKeyPair), memIndex = some(credentials.rlnIndex), ethAccAddr = ethAccountAddr,
|
||||||
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)
|
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler)
|
||||||
else: # there is no credential file available in the supplied path
|
else: # there is no credential file available in the supplied path
|
||||||
# mount the rln-relay protocol leaving rln-relay credentials arguments unassigned
|
# mount the rln-relay protocol leaving rln-relay credentials arguments unassigned
|
||||||
# this infroms mountRlnRelayDynamic proc that new credentials should be generated and registered to the membership contract
|
# this infroms mountRlnRelayDynamic proc that new credentials should be generated and registered to the membership contract
|
||||||
info "no rln credential is provided"
|
info "no rln credential is provided"
|
||||||
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
|
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
|
||||||
ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
|
ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
|
||||||
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)
|
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler)
|
||||||
# Persist generated credentials
|
# Persist generated credentials
|
||||||
var rlnMembershipCredentials =
|
var rlnMembershipCredentials =
|
||||||
RlnMembershipCredentials(membershipKeyPair: node.wakuRlnRelay.membershipKeyPair, rlnIndex: node.wakuRlnRelay.membershipIndex)
|
RlnMembershipCredentials(membershipKeyPair: node.wakuRlnRelay.membershipKeyPair, rlnIndex: node.wakuRlnRelay.membershipIndex)
|
||||||
@ -1112,4 +1116,4 @@ proc mountRlnRelay*(node: WakuNode, conf: WakuNodeConf|Chat2Conf, spamHandler: O
|
|||||||
info "no need to persist or use a persisted rln-relay credential"
|
info "no need to persist or use a persisted rln-relay credential"
|
||||||
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
|
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
|
||||||
ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
|
ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
|
||||||
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)
|
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler)
|
Loading…
x
Reference in New Issue
Block a user