From 92546bd997f08dd65c5f3aef2465dbbbc678ee10 Mon Sep 17 00:00:00 2001 From: Aaryamann Challani <43716372+rymnc@users.noreply.github.com> Date: Wed, 1 Mar 2023 17:29:13 +0530 Subject: [PATCH] chore(rln-relay): address laundry list of improvements (#1585) --- tests/v2/test_waku_rln_relay.nim | 2 +- .../protocol/waku_keystore/protocol_types.nim | 59 ++++++++++++++++- waku/v2/protocol/waku_rln_relay/constants.nim | 2 - .../waku_rln_relay/conversion_utils.nim | 63 +++---------------- .../protocol/waku_rln_relay/rln/wrappers.nim | 4 +- 5 files changed, 68 insertions(+), 62 deletions(-) diff --git a/tests/v2/test_waku_rln_relay.nim b/tests/v2/test_waku_rln_relay.nim index 4f6b181fc..a735773a6 100644 --- a/tests/v2/test_waku_rln_relay.nim +++ b/tests/v2/test_waku_rln_relay.nim @@ -332,7 +332,7 @@ suite "Waku rln relay": # prepare the input let msg = "Hello".toBytes() - hashInput = appendLength(msg) + hashInput = encodeLengthPrefix(msg) hashInputBuffer = toBuffer(hashInput) # prepare other inputs to the hash function diff --git a/waku/v2/protocol/waku_keystore/protocol_types.nim b/waku/v2/protocol/waku_keystore/protocol_types.nim index a2bfc25a0..95b3254a8 100644 --- a/waku/v2/protocol/waku_keystore/protocol_types.nim +++ b/waku/v2/protocol/waku_keystore/protocol_types.nim @@ -4,7 +4,12 @@ else: {.push raises: [].} import - stew/results + std/sequtils, + stew/[results, endians2], + stint + +# NOTE: 256-bytes long credentials are due to the use of BN254 in RLN. Other implementations/curves might have a different byte size +const CredentialByteSize* = 256 type IdentityTrapdoor* = seq[byte] #array[32, byte] @@ -25,8 +30,60 @@ type IdentityCredential* = object # more details in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership idCommitment*: IDCommitment +proc toUInt256*(idCommitment: IDCommitment): UInt256 = + let pk = UInt256.fromBytesLE(idCommitment) + return pk + +proc toIDCommitment*(idCommitmentUint: UInt256): IDCommitment = + let pk = IDCommitment(@(idCommitmentUint.toBytesLE())) + return pk + type MembershipIndex* = uint +proc toMembershipIndex*(v: UInt256): MembershipIndex = + let membershipIndex: MembershipIndex = cast[MembershipIndex](v) + return membershipIndex + +# Converts a sequence of tuples containing 4 string (i.e. identity trapdoor, nullifier, secret hash and commitment) to an IndentityCredential +type RawMembershipCredentials* = (string, string, string, string) +proc toIdentityCredentials*(groupKeys: seq[RawMembershipCredentials]): Result[seq[ + IdentityCredential], string] = + ## groupKeys is sequence of membership key tuples in the form of (identity key, identity commitment) all in the hexadecimal format + ## the toIdentityCredentials proc populates a sequence of IdentityCredentials using the supplied groupKeys + ## Returns an error if the conversion fails + + var groupIdCredentials = newSeq[IdentityCredential]() + + for i in 0..groupKeys.len-1: + try: + let + idTrapdoor = IdentityTrapdoor(@(hexToUint[CredentialByteSize](groupKeys[i][0]).toBytesLE())) + idNullifier = IdentityNullifier(@(hexToUint[CredentialByteSize](groupKeys[i][1]).toBytesLE())) + idSecretHash = IdentitySecretHash(@(hexToUint[CredentialByteSize](groupKeys[i][2]).toBytesLE())) + idCommitment = IDCommitment(@(hexToUint[CredentialByteSize](groupKeys[i][3]).toBytesLE())) + groupIdCredentials.add(IdentityCredential(idTrapdoor: idTrapdoor, + idNullifier: idNullifier, + idSecretHash: idSecretHash, + idCommitment: idCommitment)) + except ValueError as err: + return err("could not convert the group key to bytes: " & err.msg) + return ok(groupIdCredentials) + +proc serialize*(idComms: seq[IDCommitment]): seq[byte] = + ## serializes a seq of IDCommitments to a byte seq + ## the serialization is based on https://github.com/status-im/nwaku/blob/37bd29fbc37ce5cf636734e7dd410b1ed27b88c8/waku/v2/protocol/waku_rln_relay/rln.nim#L142 + ## the order of serialization is |id_commitment_len<8>|id_commitment| + var idCommsBytes = newSeq[byte]() + + # serialize the idComms, with its length prefixed + let len = toBytes(uint64(idComms.len), Endianness.littleEndian) + idCommsBytes.add(len) + + for idComm in idComms: + idCommsBytes = concat(idCommsBytes, @idComm) + + return idCommsBytes + type MembershipContract* = object chainId*: string address*: string diff --git a/waku/v2/protocol/waku_rln_relay/constants.nim b/waku/v2/protocol/waku_rln_relay/constants.nim index be065ea16..5b628221c 100644 --- a/waku/v2/protocol/waku_rln_relay/constants.nim +++ b/waku/v2/protocol/waku_rln_relay/constants.nim @@ -55,5 +55,3 @@ const MaxEpochGap* = uint64(MaxClockGapSeconds/EpochUnitSeconds) # RLN Keystore defaults const RLNAppInfo* = AppInfo(application: "nwaku-rln-relay", appIdentifier: "01234567890abcdef", version: "0.1") - # NOTE: 256-bytes long credentials are due to the use of BN254 in RLN. Other implementations/curves might have a different byte size - CredentialByteSize* = 256 \ No newline at end of file diff --git a/waku/v2/protocol/waku_rln_relay/conversion_utils.nim b/waku/v2/protocol/waku_rln_relay/conversion_utils.nim index fa7aeac7a..11b8c403a 100644 --- a/waku/v2/protocol/waku_rln_relay/conversion_utils.nim +++ b/waku/v2/protocol/waku_rln_relay/conversion_utils.nim @@ -24,18 +24,6 @@ export logScope: topics = "waku rln_relay conversion_utils" -proc toUInt256*(idCommitment: IDCommitment): UInt256 = - let pk = UInt256.fromBytesLE(idCommitment) - return pk - -proc toIDCommitment*(idCommitmentUint: UInt256): IDCommitment = - let pk = IDCommitment(@(idCommitmentUint.toBytesLE())) - return pk - -proc toMembershipIndex*(v: UInt256): MembershipIndex = - let membershipIndex: MembershipIndex = cast[MembershipIndex](v) - return membershipIndex - proc inHex*(value: IdentityTrapdoor or IdentityNullifier or IdentitySecretHash or @@ -52,7 +40,7 @@ proc inHex*(value: IdentityTrapdoor or valueHex = "0" & valueHex return toLowerAscii(valueHex) -proc appendLength*(input: openArray[byte]): seq[byte] = +proc encodeLengthPrefix*(input: openArray[byte]): seq[byte] = ## returns length prefixed version of the input ## with the following format [len<8>|input] ## len: 8-byte value that represents the number of bytes in the `input` @@ -64,14 +52,16 @@ proc appendLength*(input: openArray[byte]): seq[byte] = output = concat(@len, @input) return output -proc serialize*(idSecretHash: IdentitySecretHash, memIndex: MembershipIndex, epoch: Epoch, - msg: openArray[byte]): seq[byte] = +proc serialize*(idSecretHash: IdentitySecretHash, + memIndex: MembershipIndex, + epoch: Epoch, + msg: openArray[byte]): seq[byte] = ## a private proc to convert RateLimitProof and the data to a byte seq ## this conversion is used in the proofGen proc ## the serialization is done as instructed in https://github.com/kilic/rln/blob/7ac74183f8b69b399e3bc96c1ae8ab61c026dc43/src/public.rs#L146 ## [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal ] let memIndexBytes = toBytes(uint64(memIndex), Endianness.littleEndian) - let lenPrefMsg = appendLength(msg) + let lenPrefMsg = encodeLengthPrefix(msg) let output = concat(@idSecretHash, @memIndexBytes, @epoch, lenPrefMsg) return output @@ -80,7 +70,7 @@ proc serialize*(proof: RateLimitProof, data: openArray[byte]): seq[byte] = ## a private proc to convert RateLimitProof and data to a byte seq ## this conversion is used in the proof verification proc ## [ proof<128> | root<32> | epoch<32> | share_x<32> | share_y<32> | nullifier<32> | rln_identifier<32> | signal_len<8> | signal ] - let lenPrefMsg = appendLength(@data) + let lenPrefMsg = encodeLengthPrefix(@data) var proofBytes = concat(@(proof.proof), @(proof.merkleRoot), @(proof.epoch), @@ -99,45 +89,6 @@ proc serialize*(roots: seq[MerkleNode]): seq[byte] = rootsBytes = concat(rootsBytes, @root) return rootsBytes -proc serializeIdCommitments*(idComms: seq[IDCommitment]): seq[byte] = - ## serializes a seq of IDCommitments to a byte seq - ## the serialization is based on https://github.com/status-im/nwaku/blob/37bd29fbc37ce5cf636734e7dd410b1ed27b88c8/waku/v2/protocol/waku_rln_relay/rln.nim#L142 - ## the order of serialization is |id_commitment_len<8>|id_commitment| - var idCommsBytes = newSeq[byte]() - - # serialize the idComms, with its length prefixed - let len = toBytes(uint64(idComms.len), Endianness.littleEndian) - idCommsBytes.add(len) - - for idComm in idComms: - idCommsBytes = concat(idCommsBytes, @idComm) - - return idCommsBytes - -# Converts a sequence of tuples containing 4 string (i.e. identity trapdoor, nullifier, secret hash and commitment) to an IndentityCredential -type RawMembershipCredentials* = (string, string, string, string) -proc toIdentityCredentials*(groupKeys: seq[RawMembershipCredentials]): RlnRelayResult[seq[ - IdentityCredential]] = - ## groupKeys is sequence of membership key tuples in the form of (identity key, identity commitment) all in the hexadecimal format - ## the toIdentityCredentials proc populates a sequence of IdentityCredentials using the supplied groupKeys - ## Returns an error if the conversion fails - - var groupIdCredentials = newSeq[IdentityCredential]() - - for i in 0..groupKeys.len-1: - try: - let - idTrapdoor = IdentityTrapdoor(@(hexToUint[CredentialByteSize](groupKeys[i][0]).toBytesLE())) - idNullifier = IdentityNullifier(@(hexToUint[CredentialByteSize](groupKeys[i][1]).toBytesLE())) - idSecretHash = IdentitySecretHash(@(hexToUint[CredentialByteSize](groupKeys[i][2]).toBytesLE())) - idCommitment = IDCommitment(@(hexToUint[CredentialByteSize](groupKeys[i][3]).toBytesLE())) - groupIdCredentials.add(IdentityCredential(idTrapdoor: idTrapdoor, idNullifier: idNullifier, idSecretHash: idSecretHash, - idCommitment: idCommitment)) - except ValueError as err: - warn "could not convert the group key to bytes", err = err.msg - return err("could not convert the group key to bytes: " & err.msg) - return ok(groupIdCredentials) - proc toEpoch*(t: uint64): Epoch = ## converts `t` to `Epoch` in little-endian order let bytes = toBytes(t, Endianness.littleEndian) diff --git a/waku/v2/protocol/waku_rln_relay/rln/wrappers.nim b/waku/v2/protocol/waku_rln_relay/rln/wrappers.nim index 85840629e..7d2a5e093 100644 --- a/waku/v2/protocol/waku_rln_relay/rln/wrappers.nim +++ b/waku/v2/protocol/waku_rln_relay/rln/wrappers.nim @@ -81,7 +81,7 @@ proc createRLNInstance*(d: int = MerkleTreeDepth): RLNResult = proc sha256*(data: openArray[byte]): MerkleNode = ## a thin layer on top of the Nim wrapper of the sha256 hasher debug "sha256 hash input", hashhex = data.toHex() - var lenPrefData = appendLength(data) + var lenPrefData = encodeLengthPrefix(data) var hashInputBuffer = lenPrefData.toBuffer() outputBuffer: Buffer # will holds the hash output @@ -209,7 +209,7 @@ proc insertMembers*(rlnInstance: ptr RLN, ## Note: This proc is atomic, i.e., if any of the insertions fails, all the previous insertions are rolled back # serialize the idComms - let idCommsBytes = serializeIdCommitments(idComms) + let idCommsBytes = serialize(idComms) var idCommsBuffer = idCommsBytes.toBuffer() let idCommsBufferPtr = addr idCommsBuffer