Skip to content
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

Use Zerokit RLN module in nwaku #1030

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
564e5ed
Update zerokit submodule to master
s1fr0 Jun 30, 2022
e5be52a
Update .gitmodules
s1fr0 Jun 30, 2022
9547f6c
Update zerokit submodule
s1fr0 Jun 30, 2022
1b91a2a
refactor(rln): replace kilic's RLN module with zerokit RLN
s1fr0 Jun 30, 2022
e0daa25
fix(rln): update hardcoded values for zerokit RLN Bn254
s1fr0 Jun 30, 2022
9054ab9
fix(rln): fix serialization order
s1fr0 Jun 30, 2022
05ca701
fix(rln): allow more time for proof generation
s1fr0 Jun 30, 2022
765e8c5
Merge branch 'master' into zerokit-rln-integration
s1fr0 Jun 30, 2022
80dddff
fix(rln): update comment for rln API
s1fr0 Jul 6, 2022
e5c4a65
refactor(rln): add release compilation flag, change zerokit branch
s1fr0 Jul 26, 2022
b05d485
Removed submodule zerokit
s1fr0 Jul 26, 2022
bb01e2b
chore(rln): switch to zerokit rln improved circuit loading branch
s1fr0 Jul 26, 2022
ccc2724
fix(rln): restore timeouts to previous values
s1fr0 Jul 26, 2022
175d961
fix(rln): remove unnecessary comments
s1fr0 Jul 26, 2022
08a68be
Merge branch 'master' into zerokit-rln-integration
s1fr0 Jul 26, 2022
d28030b
refactor(rln): add RLNZEROKIT compiler flag to switch RLN module
s1fr0 Jul 26, 2022
794c93f
chore(rln): select only rln tests
s1fr0 Jul 26, 2022
80b3c79
fix(rln): add zerokit submodule
s1fr0 Jul 26, 2022
0d2b847
fix(rln): solve resolve conflicts with when define
s1fr0 Jul 26, 2022
537cdee
fix(rln): restore correct endianess in contract registration
s1fr0 Jul 26, 2022
56b30a5
fix(rln): disable RLNZEROKIT in CI make; restore all tests
s1fr0 Jul 26, 2022
5047e6c
Merge branch 'zerokit-compiler-flag' into zerokit-rln-integration
s1fr0 Jul 26, 2022
1d6904f
fix(rln): fix previously wrong rebase
s1fr0 Jul 27, 2022
2c4b2b3
fix(rln): add correct when defined to avoid conflicts with rlnzerokit
s1fr0 Jul 27, 2022
ae4711a
Merge branch 'master' into zerokit-rln-integration
s1fr0 Jul 28, 2022
831d3cf
fix(rln): update zerokit module branch
s1fr0 Jul 29, 2022
32bea0d
Merge branch 'master' into zerokit-rln-integration
s1fr0 Jul 29, 2022
311fc25
Merge branch 'master' into zerokit-rln-integration
s1fr0 Aug 1, 2022
4cf80df
Merge branch 'master' into zerokit-rln-integration
s1fr0 Aug 3, 2022
67282a2
Merge branch 'master' into zerokit-rln-integration
s1fr0 Aug 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,7 @@
url = https://github.com/status-im/nim-presto.git
ignore = untracked
branch = master
[submodule "vendor/zerokit"]
path = vendor/zerokit
url = https://github.com/vacp2p/zerokit.git
branch = master
8 changes: 4 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ endif

rlnlib:
ifeq ($(RLN), true)
cargo build --manifest-path vendor/rln/Cargo.toml
cargo build --manifest-path vendor/zerokit/rln/Cargo.toml
else ifeq ($(CI), true)
cargo build --manifest-path vendor/rln/Cargo.toml
cargo build --manifest-path vendor/zerokit/rln/Cargo.toml
endif

test2: | build deps installganache
Expand Down Expand Up @@ -227,11 +227,11 @@ clean: | clean-common
ifneq ($(USE_LIBBACKTRACE), 0)
+ $(MAKE) -C vendor/nim-libbacktrace clean $(HANDLE_OUTPUT)
endif
cargo clean --manifest-path vendor/rln/Cargo.toml
cargo clean --manifest-path vendor/zerokit/rln/Cargo.toml

# clean the rln build (forces recompile of old crates on next build)
cleanrln:
cargo clean --manifest-path vendor/rln/Cargo.toml
cargo clean --manifest-path vendor/zerokit/rln/Cargo.toml

endif # "variables.mk" was not included

Expand Down
36 changes: 13 additions & 23 deletions tests/v2/test_waku_rln_relay.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import
const RLNRELAY_PUBSUB_TOPIC = "waku/2/rlnrelay/proto"
const RLNRELAY_CONTENT_TOPIC = "waku/2/rlnrelay/proto"


procSuite "Waku rln relay":

asyncTest "mount waku-rln-relay in the off-chain mode":
let
nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[]
Expand Down Expand Up @@ -65,33 +67,17 @@ procSuite "Waku rln relay":
suite "Waku rln relay":
test "key_gen Nim Wrappers":
var
merkleDepth: csize_t = 32
# parameters.key contains the parameters related to the Poseidon hasher
# to generate this file, clone this repo https://github.com/kilic/rln
# and run the following command in the root directory of the cloned project
# cargo run --example export_test_keys
# the file is generated separately and copied here
parameters = readFile("waku/v2/protocol/waku_rln_relay/parameters.key")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this isn't needed anymore?

pbytes = parameters.toBytes()
len: csize_t = uint(pbytes.len)
parametersBuffer = Buffer(`ptr`: addr(pbytes[0]), len: len)
check:
# check the parameters.key is not empty
pbytes.len != 0
merkleDepth: csize_t = 20

var
rlnInstance: RLN[Bn256]
let res = new_circuit_from_params(merkleDepth, addr parametersBuffer,
addr rlnInstance)
var rlnInstance = createRLNInstance()
check:
# check whether the circuit parameters are generated successfully
res == true
rlnInstance.isOk == true

# keysBufferPtr will hold the generated key pairs i.e., secret and public keys
var
keysBuffer: Buffer
keysBufferPtr = addr(keysBuffer)
done = key_gen(rlnInstance, keysBufferPtr)
done = key_gen(rlnInstance.value(), keysBufferPtr)
check:
# check whether the keys are generated successfully
done == true
Expand Down Expand Up @@ -371,7 +357,7 @@ suite "Waku rln relay":
hashSuccess
let outputArr = cast[ptr array[32, byte]](outputBuffer.`ptr`)[]
check:
"efb8ac39dc22eaf377fe85b405b99ba78dbc2f3f32494add4501741df946bd1d" ==
"4c6ea217404bd5f10e243bac29dc4f1ec36bf4a41caba7b4c8075c54abb3321e" ==
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea why these are different? (Not saying they shouldn't be, just wondering if we understand reason)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the main reason is that Kilic's library is internally using Bn256, while in zerokit RLN I use circom's Bn254.

outputArr.toHex()

var
Expand All @@ -392,7 +378,7 @@ suite "Waku rln relay":

let hash = rln.hash(msg)
check:
"efb8ac39dc22eaf377fe85b405b99ba78dbc2f3f32494add4501741df946bd1d" ==
"4c6ea217404bd5f10e243bac29dc4f1ec36bf4a41caba7b4c8075c54abb3321e" ==
hash.toHex()

test "create a list of membership keys and construct a Merkle tree based on the list":
Expand Down Expand Up @@ -435,21 +421,25 @@ suite "Waku rln relay":
shareX: MerkleNode
shareY: MerkleNode
nullifier: Nullifier
rlnIdentifier: RlnIdentifier

# populate fields with dummy values
for x in proof.mitems: x = 1
for x in merkleRoot.mitems: x = 2
for x in epoch.mitems: x = 3
for x in shareX.mitems: x = 4
for x in shareY.mitems: x = 5
for x in nullifier.mitems: x = 6
for x in rlnIdentifier.mitems: x = 7

let
rateLimitProof = RateLimitProof(proof: proof,
merkleRoot: merkleRoot,
epoch: epoch,
shareX: shareX,
shareY: shareY,
nullifier: nullifier)
nullifier: nullifier,
rlnIdentifier: rlnIdentifier)
protobuf = rateLimitProof.encode()
decodednsp = RateLimitProof.init(protobuf.buffer)

Expand Down
7 changes: 4 additions & 3 deletions tests/v2/test_wakunode.nim
Original file line number Diff line number Diff line change
Expand Up @@ -789,9 +789,9 @@ procSuite "WakuNode":
await node1.publish(rlnRelayPubSubTopic, message)
await sleepAsync(2000.millis)


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this line is removed unintentionally.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous extra line doesn't seem to be consistent with the remaining tests.

## Current circom takes more time to load the circuit..
check:
(await completionFut.withTimeout(10.seconds)) == true
(await completionFut.withTimeout(200.seconds)) == true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double checking that 200 is indeed necessary. :) Any idea what the usual successful loading time is, more or less? I know the circom loading takes a long time, but waiting > 3 mins for the test to fail could be frustrating during regular CI.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary anymore with zerokit rln perfomance fixes.


await node1.stop()
await node2.stop()
Expand Down Expand Up @@ -892,9 +892,10 @@ procSuite "WakuNode":
await node1.publish(rlnRelayPubSubTopic, message)
await sleepAsync(2000.millis)

## Current circom takes more time to load the circuit...
check:
# the relayHandler of node3 never gets called
(await completionFut.withTimeout(10.seconds)) == false
(await completionFut.withTimeout(200.seconds)) == false

await node1.stop()
await node2.stop()
Expand Down
1 change: 1 addition & 0 deletions vendor/zerokit
Submodule zerokit added at 9cc333
96 changes: 62 additions & 34 deletions waku/v2/protocol/waku_rln_relay/rln.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import
os,
waku_rln_relay_types

const libPath = "vendor/rln/target/debug/"
const libPath = "vendor/zerokit/target/debug/"
when defined(Windows):
const libName* = libPath / "rln.dll"
elif defined(Linux):
Expand All @@ -17,72 +17,100 @@ elif defined(MacOsX):
# all the following procedures are Nim wrappers for the functions defined in libName
{.push dynlib: libName, raises: [Defect].}


## Buffer struct is taken from
# https://github.com/celo-org/celo-threshold-bls-rs/blob/master/crates/threshold-bls-ffi/src/ffi.rs
type Buffer* = object
`ptr`*: ptr uint8
len*: uint

#------------------------------ Merkle Tree operations -----------------------------------------
proc update_next_member*(ctx: RLN[Bn256],
input_buffer: ptr Buffer): bool {.importc: "update_next_member".}
proc update_next_member*(ctx: ptr RLN, input_buffer: ptr Buffer): bool {.importc: "set_next_leaf".}
## adds an element in the merkle tree to the next available position
## input_buffer points to the id commitment byte seq
## the return bool value indicates the success or failure of the operation

proc delete_member*(ctx: RLN[Bn256], index: uint): bool {.importc: "delete_member".}
proc delete_member*(ctx: ptr RLN, index: uint): bool {.importc: "delete_leaf".}
## index is the position of the id commitment key to be deleted from the tree
## the deleted id commitment key is replaced with a zero leaf
## the return bool value indicates the success or failure of the operation

proc get_root*(ctx: RLN[Bn256], output_buffer: ptr Buffer): bool {.importc: "get_root".}
proc get_root*(ctx: ptr RLN, output_buffer: ptr Buffer): bool {.importc: "get_root".}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come this is difference?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current RLN object instantiation is not parametrized by the curve equation (it's hardcoded to Bn254), but this will likely change in the future. Passing the pointer rather than the object is much more efficient and makes more sense IMO since its instantiation and processing should be managed by the RLN library and the object should not be copied around by nim implementation (also the pointer is what is returned by the new_circuit call).

## get_root populates the passed pointer output_buffer with the current tree root
## the output_buffer holds the Merkle tree root of size 32 bytes
## the return bool value indicates the success or failure of the operation
##

proc get_merkle_proof*(ctx: ptr RLN, index: uint, output_buffer: ptr Buffer): bool {.importc: "get_proof".}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably keep this as qualified merkle proof, as "get proof" could be a ZK proof

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So is fine like this, or you mean changing the zerokit RLN api name to get_merkle_proof too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_merkle_proof

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This nim wrapper is already named get_merkle_proof and with this name the API is used internally in nwaku. If you mean to change zerokit RLN public API name, this has to be addressed with an issue in vacp2p/zerokit.

## populates the passed pointer output_buffer with the merkle proof for the leaf at position index in the tree stored by ctx
## the output_buffer holds a serialized Merkle proof (vector of 32 bytes nodes)
## the return bool value indicates the success or failure of the operation

proc set_leaf*(ctx: ptr RLN, index: uint, input_buffer: ptr Buffer): bool {.importc: "set_leaf".}
## sets the leaf at position index in the tree stored by ctx to the value passed by input_buffer
## the input_buffer holds a serialized leaf of 32 bytes
## the return bool value indicates the success or failure of the operation

proc set_leaves*(ctx: ptr RLN, input_buffer: ptr Buffer): bool {.importc: "set_leaves".}
## sets multiple leaves in the tree stored by ctx to the value passed by input_buffer
## the input_buffer holds a serialized vector of leaves (32 bytes each)
## leaves are set one after each other starting from index 0
## the return bool value indicates the success or failure of the operation

proc reset_tree*(ctx: ptr RLN, tree_height: uint): bool {.importc: "set_tree".}
## resets the tree stored by ctx to the the empty tree (all leaves set to 0) of height tree_height
## the return bool value indicates the success or failure of the operation

#----------------------------------------------------------------------------------------------

#-------------------------------- zkSNARKs operations -----------------------------------------
proc key_gen*(ctx: RLN[Bn256], keypair_buffer: ptr Buffer): bool {.importc: "key_gen".}
proc key_gen*(ctx: ptr RLN, output_buffer: ptr Buffer): bool {.importc: "key_gen".}
## generates id key and id commitment key serialized inside keypair_buffer as | id_key <32 bytes>| id_commitment_key <32 bytes> |
## id commitment is the poseidon hash of the id key
## the return bool value indicates the success or failure of the operation

proc generate_proof*(ctx: RLN[Bn256],
input_buffer: ptr Buffer,
output_buffer: ptr Buffer): bool {.importc: "generate_proof".}
## input_buffer serialized as [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
## output_buffer holds the proof data and should be parsed as |proof<256>|root<32>|epoch<32>|share_x<32>|share_y<32>|nullifier<32>|
proc generate_proof*(ctx: ptr RLN,
input_buffer: ptr Buffer,
output_buffer: ptr Buffer): bool {.importc: "generate_rln_proof".}
## input_buffer has to be serialized as [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
## output_buffer holds the proof data and should be parsed as [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come proof size is different?I find the order of share_/share_y/nullifier a bit odd, any particular reason for changing this order?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proof is 128 bytes since it's compressed: 254 bits for each X coordinate of the 3 proof points + 1 bit for the sign of the y coordinate = 32 bytes per coordinate x 4 coordinates (2x1 over G1, 1x2 over G2) = 128 bytes. Compressed proofs are the default returned by ark-circom create_random_proof_with_reduction and verify_proof, so to make the API the same I should have gone through a decompression and re-compression adding useless overhead. There is probably a way to directly process proofs in uncompressed form (to avoid square roots operation to recover the right y coordinate), but here we discussed how we can benchmark if this makes actually sense.

The comment is wrong with respect to the implementation: the current version is
[ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<32> | rln_identifier<32> ]

The reason for such order of variables was in order to follow the order of the circuit's variables, cf. https://github.com/privacy-scaling-explorations/rln/blob/616ee9b0b085bdf14e7f39df884496b8e77ddc2f/circuits/rln.circom#L5 and https://github.com/privacy-scaling-explorations/rln/blob/616ee9b0b085bdf14e7f39df884496b8e77ddc2f/circuits/rln-base.circom#L60-L62. For serialization/deserialization purposes, this order makes more sense to me since this is the order parameters should be passed to the verify_proof function. However, ultimately, I didn't want to change too much nwaku code, so I ultimately decided the keep the previously implemented order and add rln_identifier at the end.
Can be easily changed though, since the zerokit witness structure abstracts the fields order: it is just a matter of redefining the serialization/deserialization order.

Comment updated in 80dddff

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay for compressed proofs!

## integers wrapped in <> indicate value sizes in bytes
## the return bool value indicates the success or failure of the operation
##
proc verify*(ctx: RLN[Bn256],
proof_buffer: ptr Buffer,
result_ptr: ptr uint32): bool {.importc: "verify".}
## proof_buffer [ proof<256>| root<32>| epoch<32>| share_x<32>| share_y<32>| nullifier<32> | signal_len<8> | signal<var> ]

proc verify*(ctx: ptr RLN,
proof_buffer: ptr Buffer,
proof_is_valid_ptr: ptr bool): bool {.importc: "verify_rln_proof".}
## proof_buffer has to be serialized as [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> | signal_len<8> | signal<var> ]
## the return bool value indicates the success or failure of the call to the verify function
## the result of the verification of the zk proof is stored in the value pointed by result_ptr, where 0 indicates success and 1 is failure
## the verification of the zk proof is available in result_ptr, where 0 indicates success and 1 is failure

proc zk_prove*(ctx: ptr RLN,
input_buffer: ptr Buffer,
output_buffer: ptr Buffer): bool {.importc: "prove".}
## input_buffer serialized as input_data is [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
## output_buffer holds the proof data and should be parsed as [ proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32> ]
## integers wrapped in <> indicate value sizes in bytes
## the return bool value indicates the success or failure of the operation



proc zk_verify*(ctx: ptr RLN,
proof_buffer: ptr Buffer,
proof_is_valid_ptr: ptr bool): bool {.importc: "verify".}

#----------------------------------------------------------------------------------------------
#-------------------------------- Common procedures -------------------------------------------

proc new_circuit_from_params*(merkle_depth: uint,
parameters_buffer: ptr Buffer,
ctx: ptr RLN[Bn256]): bool {.importc: "new_circuit_from_params".}
## creates an instance of rln object as defined by the rln lib https://github.com/kilic/rln/blob/7ac74183f8b69b399e3bc96c1ae8ab61c026dc43/src/public.rs#L48
#-------------------------------- Common procedures -------------------------------------------
proc new_circuit*(tree_height: uint, input_buffer: ptr Buffer, ctx: ptr (ptr RLN)): bool {.importc: "new".}
## creates an instance of rln object as defined by the zerokit RLN lib
## merkle_depth represent the depth of the Merkle tree
## parameters_buffer holds prover and verifier keys
## input_buffer contains a serialization of the path where the circuit resources can be found (.r1cs, .wasm, .zkey and optionally the verification_key.json)
## ctx holds the final created rln object
## the return bool value indicates the success or failure of the operation


proc hash*(ctx: RLN[Bn256],
inputs_buffer: ptr Buffer,
output_buffer: ptr Buffer): bool {.importc: "signal_to_field".}
## as explained in https://github.com/kilic/rln/blob/7ac74183f8b69b399e3bc96c1ae8ab61c026dc43/src/public.rs#L135, it hashes (sha256) the plain text supplied in inputs_buffer and then maps it to a field element
proc hash*(ctx: ptr RLN,
input_buffer: ptr Buffer,
output_buffer: ptr Buffer): bool {.importc: "hash".}
## it hashes (sha256) the plain text supplied in inputs_buffer and then maps it to a field element
## this proc is used to map arbitrary signals to field element for the sake of proof generation
## inputs_buffer holds the hash input as a byte seq
## the hash output is generated and populated inside output_buffer
## the output_buffer contains 32 bytes hash output

{.pop.}
## the output_buffer contains 32 bytes hash output
25 changes: 16 additions & 9 deletions waku/v2/protocol/waku_rln_relay/waku_rln_relay_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,20 @@ import
stew/arrayops,
../../utils/protobuf

## Bn256 and RLN are Nim wrappers for the data types used in
## the rln library https://github.com/kilic/rln/blob/3bbec368a4adc68cd5f9bfae80b17e1bbb4ef373/src/ffi.rs
type Bn256* = pointer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we don't have Bn256 anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In zerokit RLN I used as default Bn254, the same curve used by circom for generating zkSNARK proofs. Hopefully in the next future, RLN object implementation and API can be extended so that can be instantiatied with any curve from ark-ec.

type RLN*[E] = pointer

## RLN is a Nim wrapper for the data types used in zerokit RLN
type RLN* {.incompleteStruct.} = object

type
# identity key as defined in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership
IDKey* = array[32, byte]
# hash of identity key as defined ed in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership
IDCommitment* = array[32, byte]


type
MerkleNode* = array[32, byte] # Each node of the Merkle tee is a Poseidon hash which is a 32 byte value
RlnIdentifier* = array[32, byte]
Nullifier* = array[32, byte]
ZKSNARK* = array[256, byte]
ZKSNARK* = array[128, byte]
Epoch* = array[32, byte]

# Custom data types defined for waku rln relay -------------------------
Expand Down Expand Up @@ -55,6 +52,8 @@ type RateLimitProof* = object
## nullifier enables linking two messages published during the same epoch
## see details in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Nullifiers
nullifier*: Nullifier
## Application specific RLN Identifier
rlnIdentifier*: RlnIdentifier
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, we should probably add this to RLN relay spec @staheri14


type MembershipIndex* = uint

Expand All @@ -76,7 +75,7 @@ type WakuRLNRelay* = ref object
# TODO may need to erase this ethAccountPrivateKey when is not used
# TODO may need to make ethAccountPrivateKey mandatory
ethAccountPrivateKey*: PrivateKey
rlnInstance*: RLN[Bn256]
rlnInstance*: ptr RLN
pubsubTopic*: string # the pubsub topic for which rln relay is mounted
# contentTopic should be of type waku_message.ContentTopic, however, due to recursive module dependency, the underlying type of ContentTopic is used instead
# TODO a long-term solution is to place types with recursive dependency inside one file
Expand All @@ -98,6 +97,9 @@ const
ETH_CLIENT* = "ws://localhost:8540/"

const
# The relative folder where the circuit, proving and verification key for RLN can be found
# Note that resources has to be compiled with respect to the above MERKLE_TREE_DEPTH
RLN_RESOURCE_FOLDER* = "vendor/zerokit/rln/resources/tree_height_" & $MERKLE_TREE_DEPTH & "/"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come we need this now?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to not have duplicates of the circuit in nwaku, I thought that it is better to point to zerokit resource folder directly. Since nwaku is calling zerokit API from a different path than the latter, the resource folders should be passed to correctly locate the circuit (i.e., this string cannot be hardcoded in zerokit)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I don't know how exactly but I suspect this might fail when we do distribution. In general vendoring and static resources should be kept separate. Perhaps OK for initial integration where we compile stuff ourselves.

cc @jm-clius

# the size of poseidon hash output in bits
HASH_BIT_SIZE* = 256
# the size of poseidon hash output as the number hex digits
Expand Down Expand Up @@ -314,7 +316,7 @@ const
# STATIC_GROUP_MERKLE_ROOT is the root of the Merkle tree constructed from the STATIC_GROUP_KEYS above
# only identity commitments are used for the Merkle tree construction
# the root is created locally, using createMembershipList proc from waku_rln_relay_utils module, and the result is hardcoded in here
STATIC_GROUP_MERKLE_ROOT* = "a1877a553eff12e1b21632a0545a916a5c5b8060ad7cc6c69956741134397b2d"
STATIC_GROUP_MERKLE_ROOT* = "2af1e8ca39f5b1c3b097d37c2281da47b5a9b5cdde0525fe51dd929c27cb5400"

const EPOCH_UNIT_SECONDS* = float64(10) # the rln-relay epoch length in seconds
const MAX_CLOCK_GAP_SECONDS* = 20.0 # the maximum clock difference between peers in seconds
Expand Down Expand Up @@ -351,6 +353,10 @@ proc init*(T: type RateLimitProof, buffer: seq[byte]): ProtoResult[T] =
discard ? pb.getField(6, nullifier)
discard nsp.nullifier.copyFrom(nullifier)

var rlnIdentifier: seq[byte]
discard ? pb.getField(7, rlnIdentifier)
discard nsp.rlnIdentifier.copyFrom(rlnIdentifier)

return ok(nsp)

proc encode*(nsp: RateLimitProof): ProtoBuffer =
Expand All @@ -362,6 +368,7 @@ proc encode*(nsp: RateLimitProof): ProtoBuffer =
output.write3(4, nsp.shareX)
output.write3(5, nsp.shareY)
output.write3(6, nsp.nullifier)
output.write3(7, nsp.rlnIdentifier)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires spec change I believe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tracking issue: vacp2p/rfc#523


output.finish3()

Expand Down
Loading