2024-06-28 10:34:57 +00:00
|
|
|
{.push raises: [].}
|
2023-01-16 12:56:18 +00:00
|
|
|
|
|
|
|
import
|
2023-02-28 13:38:30 +00:00
|
|
|
std/[sequtils, strutils, algorithm],
|
2023-01-16 12:56:18 +00:00
|
|
|
web3,
|
|
|
|
chronicles,
|
2024-04-26 09:53:58 +00:00
|
|
|
stew/[arrayops, endians2],
|
2023-01-16 12:56:18 +00:00
|
|
|
stint
|
2024-03-15 23:08:47 +00:00
|
|
|
import ./constants, ./protocol_types
|
|
|
|
import ../waku_keystore
|
2023-01-16 12:56:18 +00:00
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
export web3, chronicles, stint, constants, endians2
|
2023-01-16 12:56:18 +00:00
|
|
|
|
|
|
|
logScope:
|
2024-03-15 23:08:47 +00:00
|
|
|
topics = "waku rln_relay conversion_utils"
|
2023-01-16 12:56:18 +00:00
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
proc inHex*(
|
|
|
|
value:
|
|
|
|
IdentityTrapdoor or IdentityNullifier or IdentitySecretHash or IDCommitment or
|
|
|
|
MerkleNode or Nullifier or Epoch or RlnIdentifier
|
|
|
|
): string =
|
2023-02-28 13:38:30 +00:00
|
|
|
var valueHex = "" #UInt256.fromBytesLE(value)
|
|
|
|
for b in value.reversed():
|
|
|
|
valueHex = valueHex & b.toHex()
|
|
|
|
# We pad leading zeroes
|
|
|
|
while valueHex.len < value.len * 2:
|
|
|
|
valueHex = "0" & valueHex
|
|
|
|
return toLowerAscii(valueHex)
|
|
|
|
|
2024-06-20 09:35:21 +00:00
|
|
|
proc toUserMessageLimit*(v: UInt256): UserMessageLimit =
|
|
|
|
return cast[UserMessageLimit](v)
|
2024-02-09 11:01:45 +00:00
|
|
|
|
2023-03-01 11:59:13 +00:00
|
|
|
proc encodeLengthPrefix*(input: openArray[byte]): seq[byte] =
|
2023-01-16 12:56:18 +00:00
|
|
|
## returns length prefixed version of the input
|
|
|
|
## with the following format [len<8>|input<var>]
|
|
|
|
## len: 8-byte value that represents the number of bytes in the `input`
|
|
|
|
## len is serialized in little-endian
|
|
|
|
## input: the supplied `input`
|
|
|
|
let
|
|
|
|
# the length should be serialized in little-endian
|
|
|
|
len = toBytes(uint64(input.len), Endianness.littleEndian)
|
|
|
|
output = concat(@len, @input)
|
|
|
|
return output
|
|
|
|
|
2024-02-14 07:54:05 +00:00
|
|
|
proc serialize*(v: uint64): array[32, byte] =
|
|
|
|
## a private proc to convert uint64 to a byte seq
|
|
|
|
## this conversion is used in the proofGen proc
|
2024-03-15 23:08:47 +00:00
|
|
|
|
2024-02-14 07:54:05 +00:00
|
|
|
## converts `v` to a byte seq in little-endian order
|
|
|
|
let bytes = toBytes(v, Endianness.littleEndian)
|
|
|
|
var output: array[32, byte]
|
|
|
|
discard output.copyFrom(bytes)
|
|
|
|
return output
|
|
|
|
|
2024-06-20 09:35:21 +00:00
|
|
|
proc serialize*(
|
|
|
|
idSecretHash: IdentitySecretHash,
|
|
|
|
memIndex: MembershipIndex,
|
|
|
|
userMessageLimit: UserMessageLimit,
|
|
|
|
messageId: MessageId,
|
|
|
|
externalNullifier: ExternalNullifier,
|
|
|
|
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<var> ]
|
|
|
|
let memIndexBytes = toBytes(uint64(memIndex), Endianness.littleEndian)
|
|
|
|
let userMessageLimitBytes = userMessageLimit.serialize()
|
|
|
|
let messageIdBytes = messageId.serialize()
|
|
|
|
let lenPrefMsg = encodeLengthPrefix(msg)
|
|
|
|
let output = concat(
|
|
|
|
@idSecretHash,
|
|
|
|
@memIndexBytes,
|
|
|
|
@userMessageLimitBytes,
|
|
|
|
@messageIdBytes,
|
|
|
|
@externalNullifier,
|
|
|
|
lenPrefMsg,
|
|
|
|
)
|
|
|
|
return output
|
2024-03-15 23:08:47 +00:00
|
|
|
|
2023-01-16 12:56:18 +00:00
|
|
|
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<var> ]
|
2023-03-01 11:59:13 +00:00
|
|
|
let lenPrefMsg = encodeLengthPrefix(@data)
|
2024-06-20 09:35:21 +00:00
|
|
|
var proofBytes = concat(
|
|
|
|
@(proof.proof),
|
|
|
|
@(proof.merkleRoot),
|
|
|
|
@(proof.externalNullifier),
|
|
|
|
@(proof.shareX),
|
|
|
|
@(proof.shareY),
|
|
|
|
@(proof.nullifier),
|
|
|
|
lenPrefMsg,
|
|
|
|
)
|
2023-01-16 12:56:18 +00:00
|
|
|
|
|
|
|
return proofBytes
|
|
|
|
|
|
|
|
# Serializes a sequence of MerkleNodes
|
|
|
|
proc serialize*(roots: seq[MerkleNode]): seq[byte] =
|
|
|
|
var rootsBytes: seq[byte] = @[]
|
|
|
|
for root in roots:
|
|
|
|
rootsBytes = concat(rootsBytes, @root)
|
|
|
|
return rootsBytes
|
|
|
|
|
2023-05-18 05:12:08 +00:00
|
|
|
# Serializes a sequence of MembershipIndex's
|
|
|
|
proc serialize*(memIndices: seq[MembershipIndex]): seq[byte] =
|
|
|
|
var memIndicesBytes = newSeq[byte]()
|
|
|
|
|
|
|
|
# serialize the memIndices, with its length prefixed
|
|
|
|
let len = toBytes(uint64(memIndices.len), Endianness.littleEndian)
|
|
|
|
memIndicesBytes.add(len)
|
|
|
|
|
|
|
|
for memIndex in memIndices:
|
|
|
|
let memIndexBytes = toBytes(uint64(memIndex), Endianness.littleEndian)
|
|
|
|
memIndicesBytes = concat(memIndicesBytes, @memIndexBytes)
|
|
|
|
|
|
|
|
return memIndicesBytes
|
|
|
|
|
2023-01-16 12:56:18 +00:00
|
|
|
proc toEpoch*(t: uint64): Epoch =
|
|
|
|
## converts `t` to `Epoch` in little-endian order
|
|
|
|
let bytes = toBytes(t, Endianness.littleEndian)
|
2024-03-12 10:50:30 +00:00
|
|
|
trace "epoch bytes", bytes = bytes
|
2023-01-16 12:56:18 +00:00
|
|
|
var epoch: Epoch
|
|
|
|
discard epoch.copyFrom(bytes)
|
|
|
|
return epoch
|
|
|
|
|
|
|
|
proc fromEpoch*(epoch: Epoch): uint64 =
|
|
|
|
## decodes bytes of `epoch` (in little-endian) to uint64
|
|
|
|
let t = fromBytesLE(uint64, array[32, byte](epoch))
|
|
|
|
return t
|