diff --git a/waku/waku_rln_relay/conversion_utils.nim b/waku/waku_rln_relay/conversion_utils.nim index 29503e28e..b8ee486f5 100644 --- a/waku/waku_rln_relay/conversion_utils.nim +++ b/waku/waku_rln_relay/conversion_utils.nim @@ -119,15 +119,19 @@ proc serialize*(memIndices: seq[MembershipIndex]): seq[byte] = proc serialize*(witness: Witness): seq[byte] = ## Serializes the witness into a byte array according to the RLN protocol format var buffer: seq[byte] - buffer.add(witness.identity_secret) - buffer.add(witness.user_message_limit.toBytesBE()) - buffer.add(witness.message_id.toBytesBE()) + # Convert Fr types to bytes and add them to buffer + buffer.add(@(witness.identity_secret)) + buffer.add(@(witness.user_message_limit)) + buffer.add(@(witness.message_id)) + # Add path elements length as uint64 in little-endian buffer.add(toBytes(uint64(witness.path_elements.len), Endianness.littleEndian)) + # Add each path element for element in witness.path_elements: - buffer.add(element) + buffer.add(@element) + # Add remaining fields buffer.add(witness.identity_path_index) - buffer.add(witness.x) - buffer.add(witness.external_nullifier) + buffer.add(@(witness.x)) + buffer.add(@(witness.external_nullifier)) return buffer proc toEpoch*(t: uint64): Epoch = diff --git a/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim b/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim index 54998dcb9..4e6312e84 100644 --- a/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim +++ b/waku/waku_rln_relay/group_manager/on_chain/group_manager.nim @@ -248,22 +248,16 @@ method withdrawBatch*( ): Future[void] {.async: (raises: [Exception]).} = initializedGuard(g) -proc convertUint256SeqToByteSeq(input: seq[UInt256]): seq[seq[byte]] = - result = newSeq[seq[byte]](input.len) - for i, uint256val in input: - # Convert UInt256 to a byte sequence (big endian) - let bytes = uint256val.toBytesBE() - result[i] = @bytes +proc toArray32*(s: seq[byte]): array[32, byte] = + var output: array[32, byte] + discard output.copyFrom(s) + return output -proc uinttoSeqByte*(value: uint64): seq[byte] = - ## Converts a uint64 to a sequence of bytes (big-endian) - result = newSeq[byte](8) - for i in 0 ..< 8: - result[7 - i] = byte((value shr (i * 8)) and 0xFF) - -proc toSeqByte*(value: array[32, byte]): seq[byte] = - ## Converts an array[32, byte] to a sequence of bytes - result = @value +proc toArray32Seq*(values: seq[UInt256]): seq[array[32, byte]] = + ## Converts a sequence of UInt256 to a sequence of 32-byte arrays + result = newSeqOfCap[array[32, byte]](values.len) + for value in values: + result.add(value.toBytesLE()) method generateProof*( g: OnchainGroupManager, @@ -281,17 +275,16 @@ method generateProof*( if g.userMessageLimit.isNone(): return err("user message limit is not set") - let pathElements = convertUint256SeqToByteSeq(g.merkleProofCache) let externalNullifierRes = poseidon(@[@(epoch), @(rlnIdentifier)]) let witness = Witness( - identity_secret: g.idCredentials.get().idSecretHash, - user_message_limit: g.userMessageLimit.get(), - message_id: messageId, - path_elements: pathElements, - identity_path_index: uinttoSeqByte(g.membershipIndex.get()), - x: data, - external_nullifier: toSeqByte(externalNullifierRes.get()), + identity_secret: g.idCredentials.get().idSecretHash.toArray32(), + user_message_limit: serialize(g.userMessageLimit.get()), + message_id: serialize(messageId), + path_elements: toArray32Seq(g.merkleProofCache), + identity_path_index: @(toBytes(g.membershipIndex.get(), littleEndian)), + x: toArray32(data), + external_nullifier: externalNullifierRes.get(), ) let serializedWitness = serialize(witness) diff --git a/waku/waku_rln_relay/protocol_types.nim b/waku/waku_rln_relay/protocol_types.nim index 9e43e7800..e0019990b 100644 --- a/waku/waku_rln_relay/protocol_types.nim +++ b/waku/waku_rln_relay/protocol_types.nim @@ -52,14 +52,17 @@ type RateLimitProof* = object ## the external nullifier used for the generation of the `proof` (derived from poseidon([epoch, rln_identifier])) externalNullifier*: ExternalNullifier -type Witness* = object ## Represents the custom witness for generating an RLN proof - identity_secret*: seq[byte] # Identity secret (private key) - user_message_limit*: UserMessageLimit # Maximum number of messages a user can send - message_id*: MessageId # Message ID (used for rate limiting) - path_elements*: seq[seq[byte]] # Merkle proof path elements - identity_path_index*: seq[byte] # Merkle proof path indices - x*: seq[byte] # Hash of the signal data - external_nullifier*: seq[byte] # Hash of epoch and RLN identifier +type + Fr = array[32, byte] # Field element representation (256 bits) + + Witness* = object + identity_secret*: Fr + user_message_limit*: Fr + message_id*: Fr + path_elements*: seq[Fr] + identity_path_index*: seq[byte] + x*: Fr + external_nullifier*: Fr type ProofMetadata* = object nullifier*: Nullifier