mirror of https://github.com/waku-org/nwaku.git
refactor(rln): use zerokit extended_key_gen in place of key_gen (#1459)
* chore(rln-relay): refactor mounting procedure * fix(rln-relay): tests * fix(rln-relay|chat2): update mounting proc in chat2, fix args to mountRlnRelay * refactor(rln): use zerokit extended_key_gen in place of key_gen refactor(rln): rename membershipKeyPair to identityCredential update zerokit submodule refactor(rln): use extended_key_gen; rebrand keypairs to idCredentials refactor(rln): rename mountRlnRelay memKeyPair argument * fix(rln): fix wrong field * fix(rln): add () to toHex Co-authored-by: Aaryamann Challani <43716372+rymnc@users.noreply.github.com> Co-authored-by: rymnc <43716372+rymnc@users.noreply.github.com>
This commit is contained in:
parent
33e9d8b9b2
commit
226b44c86d
|
@ -570,8 +570,10 @@ proc processInput(rfd: AsyncFD) {.async.} =
|
|||
registrationHandler=some(registrationHandler))
|
||||
|
||||
echo "your membership index is: ", node.wakuRlnRelay.membershipIndex
|
||||
echo "your rln identity key is: ", node.wakuRlnRelay.membershipKeyPair.idKey.inHex()
|
||||
echo "your rln identity commitment key is: ", node.wakuRlnRelay.membershipKeyPair.idCommitment.inHex()
|
||||
echo "your rln identity trapdoor is: ", node.wakuRlnRelay.identityCredential.idTrapdoor.inHex()
|
||||
echo "your rln identity nullifier is: ", node.wakuRlnRelay.identityCredential.idNullifier.inHex()
|
||||
echo "your rln identity secret hash is: ", node.wakuRlnRelay.identityCredential.idSecretHash.inHex()
|
||||
echo "your rln identity commitment key is: ", node.wakuRlnRelay.identityCredential.idCommitment.inHex()
|
||||
|
||||
if conf.metricsLogging:
|
||||
startMetricsLog()
|
||||
|
|
|
@ -33,31 +33,31 @@ procSuite "Waku rln relay":
|
|||
require:
|
||||
memListRes.isOk()
|
||||
|
||||
let (groupKeys, root) = memListRes.get()
|
||||
let (groupCredentials, root) = memListRes.get()
|
||||
require:
|
||||
groupKeys.len == 100
|
||||
groupCredentials.len == 100
|
||||
let
|
||||
# convert the keys to MembershipKeyPair structs
|
||||
groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
|
||||
# convert the keys to IdentityCredential structs
|
||||
groupIdCredentialsRes = groupCredentials.toIdentityCredentials()
|
||||
require:
|
||||
groupKeyPairsRes.isOk()
|
||||
groupIdCredentialsRes.isOk()
|
||||
|
||||
let
|
||||
groupKeyPairs = groupKeyPairsRes.get()
|
||||
groupIdCredentials = groupIdCredentialsRes.get()
|
||||
# extract the id commitments
|
||||
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
|
||||
debug "groupKeyPairs", groupKeyPairs
|
||||
groupIDCommitments = groupIdCredentials.mapIt(it.idCommitment)
|
||||
debug "groupIdCredentials", groupIdCredentials
|
||||
debug "groupIDCommitments", groupIDCommitments
|
||||
|
||||
# index indicates the position of a membership key pair in the static list of group keys i.e., groupKeyPairs
|
||||
# the corresponding key pair will be used to mount rlnRelay on the current node
|
||||
# index indicates the position of a membership credential in the static list of group keys i.e., groupIdCredentials
|
||||
# the corresponding credential will be used to mount rlnRelay on the current node
|
||||
# index also represents the index of the leaf in the Merkle tree that contains node's commitment key
|
||||
let index = MembershipIndex(5)
|
||||
|
||||
# -------- mount rln-relay in the off-chain mode
|
||||
await node.mountRelay(@[RlnRelayPubsubTopic])
|
||||
let mountRes = node.wakuRelay.mountRlnRelayStatic(group = groupIDCommitments,
|
||||
memKeyPair = groupKeyPairs[index],
|
||||
memIdCredential = groupIdCredentials[index],
|
||||
memIndex = index,
|
||||
pubsubTopic = RlnRelayPubsubTopic,
|
||||
contentTopic = RlnRelayContentTopic)
|
||||
|
@ -91,7 +91,7 @@ suite "Waku rln relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
# keysBufferPtr will hold the generated key pairs i.e., secret and public keys
|
||||
# keysBufferPtr will hold the generated identity credential i.e., id trapdoor, nullifier, secret hash and commitment
|
||||
var
|
||||
keysBuffer: Buffer
|
||||
let
|
||||
|
@ -101,10 +101,10 @@ suite "Waku rln relay":
|
|||
# check whether the keys are generated successfully
|
||||
done
|
||||
|
||||
let generatedKeys = cast[ptr array[64, byte]](keysBufferPtr.`ptr`)[]
|
||||
let generatedKeys = cast[ptr array[4*32, byte]](keysBufferPtr.`ptr`)[]
|
||||
check:
|
||||
# the public and secret keys together are 64 bytes
|
||||
generatedKeys.len == 64
|
||||
# the id trapdoor, nullifier, secert hash and commitment together are 4*32 bytes
|
||||
generatedKeys.len == 4*32
|
||||
debug "generated keys: ", generatedKeys
|
||||
|
||||
test "membership Key Generation":
|
||||
|
@ -113,19 +113,23 @@ suite "Waku rln relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
let keyPairRes = membershipKeyGen(rlnInstance.get())
|
||||
let idCredentialsRes = membershipKeyGen(rlnInstance.get())
|
||||
require:
|
||||
keyPairRes.isOk()
|
||||
idCredentialsRes.isOk()
|
||||
|
||||
let keyPair = keyPairRes.get()
|
||||
let idCredential = idCredentialsRes.get()
|
||||
let empty = default(array[32, byte])
|
||||
check:
|
||||
keyPair.idKey.len == 32
|
||||
keyPair.idCommitment.len == 32
|
||||
keyPair.idKey != empty
|
||||
keyPair.idCommitment != empty
|
||||
idCredential.idTrapdoor.len == 32
|
||||
idCredential.idNullifier.len == 32
|
||||
idCredential.idSecretHash.len == 32
|
||||
idCredential.idCommitment.len == 32
|
||||
idCredential.idTrapdoor != empty
|
||||
idCredential.idNullifier != empty
|
||||
idCredential.idSecretHash != empty
|
||||
idCredential.idCommitment != empty
|
||||
|
||||
debug "the generated membership key pair: ", keyPair
|
||||
debug "the generated identity credential: ", idCredential
|
||||
|
||||
test "getRoot Nim binding":
|
||||
# create an RLN instance which also includes an empty Merkle tree
|
||||
|
@ -189,13 +193,13 @@ suite "Waku rln relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
# generate a key pair
|
||||
let keyPairRes = membershipKeyGen(rln)
|
||||
# generate an identity credential
|
||||
let idCredentialRes = membershipKeyGen(rln)
|
||||
require:
|
||||
keypairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let keyPair = keyPairRes.get()
|
||||
let pkBuffer = toBuffer(keyPair.idCommitment)
|
||||
let idCredential = idCredentialRes.get()
|
||||
let pkBuffer = toBuffer(idCredential.idCommitment)
|
||||
let pkBufferPtr = unsafeAddr(pkBuffer)
|
||||
|
||||
# add the member to the tree
|
||||
|
@ -221,12 +225,12 @@ suite "Waku rln relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
# generate a key pair
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
# generate an identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
keypairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
check:
|
||||
rln.insertMembers(0, @[keyPairRes.get().idCommitment])
|
||||
rln.insertMembers(0, @[idCredentialRes.get().idCommitment])
|
||||
|
||||
test "insertMember rln utils":
|
||||
# create an RLN instance which also includes an empty Merkle tree
|
||||
|
@ -234,12 +238,12 @@ suite "Waku rln relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
# generate a key pair
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
# generate an identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
keypairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
check:
|
||||
rln.insertMember(keyPairRes.get().idCommitment)
|
||||
rln.insertMember(idCredentialRes.get().idCommitment)
|
||||
|
||||
test "removeMember rln utils":
|
||||
# create an RLN instance which also includes an empty Merkle tree
|
||||
|
@ -267,13 +271,13 @@ suite "Waku rln relay":
|
|||
getRootSuccessful1
|
||||
root1.len == 32
|
||||
|
||||
# generate a key pair
|
||||
let keyPairRes = membershipKeyGen(rln)
|
||||
# generate an identity credential
|
||||
let idCredentialRes = membershipKeyGen(rln)
|
||||
require:
|
||||
keypairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let keyPair = keyPairRes.get()
|
||||
let pkBuffer = toBuffer(keyPair.idCommitment)
|
||||
let idCredential = idCredentialRes.get()
|
||||
let pkBuffer = toBuffer(idCredential.idCommitment)
|
||||
let pkBufferPtr = unsafeAddr(pkBuffer)
|
||||
|
||||
# add the member to the tree
|
||||
|
@ -340,11 +344,11 @@ suite "Waku rln relay":
|
|||
root1.isOk()
|
||||
let rootHex1 = root1.value().inHex()
|
||||
|
||||
# generate a key pair
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
# generate an identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
keyPairRes.isOk()
|
||||
let memberInserted = rln.insertMembers(0, @[keypairRes.get().idCommitment])
|
||||
idCredentialRes.isOk()
|
||||
let memberInserted = rln.insertMembers(0, @[idCredentialRes.get().idCommitment])
|
||||
require:
|
||||
memberInserted
|
||||
|
||||
|
@ -445,17 +449,17 @@ suite "Waku rln relay":
|
|||
list.len == groupSize # check the number of keys
|
||||
root.len == HashHexSize # check the size of the calculated tree root
|
||||
|
||||
test "check correctness of toMembershipKeyPairs and calcMerkleRoot":
|
||||
test "check correctness of toIdentityCredentials and calcMerkleRoot":
|
||||
let groupKeys = StaticGroupKeys
|
||||
|
||||
# create a set of MembershipKeyPair objects from groupKeys
|
||||
let groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
|
||||
# create a set of IdentityCredentials objects from groupKeys
|
||||
let groupIdCredentialsRes = groupKeys.toIdentityCredentials()
|
||||
require:
|
||||
groupKeyPairsRes.isOk()
|
||||
groupIdCredentialsRes.isOk()
|
||||
|
||||
let groupKeyPairs = groupKeyPairsRes.get()
|
||||
let groupIdCredentials = groupIdCredentialsRes.get()
|
||||
# extract the id commitments
|
||||
let groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
|
||||
let groupIDCommitments = groupIdCredentials.mapIt(it.idCommitment)
|
||||
# calculate the Merkle tree root out of the extracted id commitments
|
||||
let rootRes = calcMerkleRoot(groupIDCommitments)
|
||||
|
||||
|
@ -464,13 +468,13 @@ suite "Waku rln relay":
|
|||
|
||||
let root = rootRes.get()
|
||||
|
||||
debug "groupKeyPairs", groupKeyPairs
|
||||
debug "groupIdCredentials", groupIdCredentials
|
||||
debug "groupIDCommitments", groupIDCommitments
|
||||
debug "root", root
|
||||
|
||||
check:
|
||||
# check that the correct number of key pairs is created
|
||||
groupKeyPairs.len == StaticGroupSize
|
||||
# check that the correct number of identity credentials is created
|
||||
groupIdCredentials.len == StaticGroupSize
|
||||
# compare the calculated root against the correct root
|
||||
root == StaticGroupMerkleRoot
|
||||
|
||||
|
@ -518,26 +522,26 @@ suite "Waku rln relay":
|
|||
let
|
||||
# peer's index in the Merkle Tree
|
||||
index = 5'u
|
||||
# create a membership key pair
|
||||
memKeysRes = membershipKeyGen(rln)
|
||||
# create an identity credential
|
||||
idCredentialRes = membershipKeyGen(rln)
|
||||
|
||||
require:
|
||||
memKeysRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let memKeys = memKeysRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
|
||||
var members = newSeq[IDCommitment]()
|
||||
# Create a Merkle tree with random members
|
||||
for i in 0'u..10'u:
|
||||
if (i == index):
|
||||
# insert the current peer's pk
|
||||
members.add(memKeys.idCommitment)
|
||||
members.add(idCredential.idCommitment)
|
||||
else:
|
||||
# create a new key pair
|
||||
let memberKeysRes = rln.membershipKeyGen()
|
||||
# create a new identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
memberKeysRes.isOk()
|
||||
members.add(memberKeysRes.get().idCommitment)
|
||||
idCredentialRes.isOk()
|
||||
members.add(idCredentialRes.get().idCommitment)
|
||||
|
||||
# Batch the insert
|
||||
let batchInsertRes = rln.insertMembers(0, members)
|
||||
|
@ -553,7 +557,7 @@ suite "Waku rln relay":
|
|||
|
||||
# generate proof
|
||||
let proofRes = rln.proofGen(data = messageBytes,
|
||||
memKeys = memKeys,
|
||||
memKeys = idCredential,
|
||||
memIndex = MembershipIndex(index),
|
||||
epoch = epoch)
|
||||
require:
|
||||
|
@ -582,26 +586,26 @@ suite "Waku rln relay":
|
|||
let
|
||||
# peer's index in the Merkle Tree
|
||||
index = 5'u
|
||||
# create a membership key pair
|
||||
memKeysRes = membershipKeyGen(rln)
|
||||
# create an identity credential
|
||||
idCredentialRes = membershipKeyGen(rln)
|
||||
|
||||
require:
|
||||
memKeysRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let memKeys = memKeysRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
|
||||
# Create a Merkle tree with random members
|
||||
for i in 0'u..10'u:
|
||||
var memberAdded: bool = false
|
||||
if (i == index):
|
||||
# insert the current peer's pk
|
||||
memberAdded = rln.insertMembers(i, @[memKeys.idCommitment])
|
||||
memberAdded = rln.insertMembers(i, @[idCredential.idCommitment])
|
||||
else:
|
||||
# create a new key pair
|
||||
let memberKeysRes = rln.membershipKeyGen()
|
||||
# create a new identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
memberKeysRes.isOk()
|
||||
memberAdded = rln.insertMembers(i, @[memberKeysRes.get().idCommitment])
|
||||
idCredentialRes.isOk()
|
||||
memberAdded = rln.insertMembers(i, @[idCredentialRes.get().idCommitment])
|
||||
# check the member is added
|
||||
require:
|
||||
memberAdded
|
||||
|
@ -617,7 +621,7 @@ suite "Waku rln relay":
|
|||
let badIndex = 4
|
||||
# generate proof
|
||||
let proofRes = rln.proofGen(data = messageBytes,
|
||||
memKeys = memKeys,
|
||||
memKeys = idCredential,
|
||||
memIndex = MembershipIndex(badIndex),
|
||||
epoch = epoch)
|
||||
require:
|
||||
|
@ -649,29 +653,29 @@ suite "Waku rln relay":
|
|||
let
|
||||
# peer's index in the Merkle Tree.
|
||||
index = 5'u
|
||||
# create a membership key pair
|
||||
memKeysRes = membershipKeyGen(rlnRelay.rlnInstance)
|
||||
# create an identity credential
|
||||
idCredentialRes = membershipKeyGen(rlnRelay.rlnInstance)
|
||||
|
||||
require:
|
||||
memKeysRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let memKeys = memKeysRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
|
||||
let membershipCount: uint = AcceptableRootWindowSize + 5'u
|
||||
|
||||
var members = newSeq[MembershipKeyPair]()
|
||||
var members = newSeq[IdentityCredential]()
|
||||
|
||||
# Generate membership keys
|
||||
for i in 0'u..membershipCount:
|
||||
if (i == index):
|
||||
# insert the current peer's pk
|
||||
members.add(memKeys)
|
||||
members.add(idCredential)
|
||||
else:
|
||||
# create a new key pair
|
||||
let memberKeysRes = rlnRelay.rlnInstance.membershipKeyGen()
|
||||
# create a new identity credential
|
||||
let idCredentialRes = rlnRelay.rlnInstance.membershipKeyGen()
|
||||
require:
|
||||
memberKeysRes.isOk()
|
||||
members.add(memberKeysRes.get())
|
||||
idCredentialRes.isOk()
|
||||
members.add(idCredentialRes.get())
|
||||
|
||||
# Batch inserts into the tree
|
||||
let insertedRes = rlnRelay.insertMembers(0, members.mapIt(it.idCommitment))
|
||||
|
@ -689,7 +693,7 @@ suite "Waku rln relay":
|
|||
|
||||
# generate proof
|
||||
let validProofRes = rlnRelay.rlnInstance.proofGen(data = messageBytes,
|
||||
memKeys = memKeys,
|
||||
memKeys = idCredential,
|
||||
memIndex = MembershipIndex(index),
|
||||
epoch = epoch)
|
||||
require:
|
||||
|
@ -745,13 +749,13 @@ suite "Waku rln relay":
|
|||
let
|
||||
# peer's index in the Merkle Tree.
|
||||
index = 6'u
|
||||
# create a membership key pair
|
||||
memKeysRes = membershipKeyGen(rlnRelay.rlnInstance)
|
||||
# create an identity credential
|
||||
idCredentialRes = membershipKeyGen(rlnRelay.rlnInstance)
|
||||
|
||||
require:
|
||||
memKeysRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let memKeys = memKeysRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
|
||||
let membershipCount: uint = AcceptableRootWindowSize + 5'u
|
||||
|
||||
|
@ -760,13 +764,13 @@ suite "Waku rln relay":
|
|||
var memberIsAdded: RlnRelayResult[void]
|
||||
if (i == index):
|
||||
# insert the current peer's pk
|
||||
memberIsAdded = rlnRelay.insertMembers(i, @[memKeys.idCommitment])
|
||||
memberIsAdded = rlnRelay.insertMembers(i, @[idCredential.idCommitment])
|
||||
else:
|
||||
# create a new key pair
|
||||
let memberKeysRes = rlnRelay.rlnInstance.membershipKeyGen()
|
||||
# create a new identity credential
|
||||
let idCredentialRes = rlnRelay.rlnInstance.membershipKeyGen()
|
||||
require:
|
||||
memberKeysRes.isOk()
|
||||
memberIsAdded = rlnRelay.insertMembers(i, @[memberKeysRes.get().idCommitment])
|
||||
idCredentialRes.isOk()
|
||||
memberIsAdded = rlnRelay.insertMembers(i, @[idCredentialRes.get().idCommitment])
|
||||
# require that the member is added
|
||||
require:
|
||||
memberIsAdded.isOk()
|
||||
|
@ -782,7 +786,7 @@ suite "Waku rln relay":
|
|||
|
||||
# generate proof
|
||||
let validProofRes = rlnRelay.rlnInstance.proofGen(data = messageBytes,
|
||||
memKeys = memKeys,
|
||||
memKeys = idCredential,
|
||||
memIndex = MembershipIndex(index),
|
||||
epoch = epoch)
|
||||
require:
|
||||
|
@ -916,20 +920,20 @@ suite "Waku rln relay":
|
|||
memListRes.isOk()
|
||||
let
|
||||
(groupKeys, _) = memListRes.get()
|
||||
# convert the keys to MembershipKeyPair structs
|
||||
groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
|
||||
# convert the keys to IdentityCredential structs
|
||||
groupIdCredentialsRes = groupKeys.toIdentityCredentials()
|
||||
|
||||
require:
|
||||
groupKeyPairsRes.isOk()
|
||||
groupIdCredentialsRes.isOk()
|
||||
|
||||
let groupKeyPairs = groupKeyPairsRes.get()
|
||||
let groupIdCredentials = groupIdCredentialsRes.get()
|
||||
# extract the id commitments
|
||||
let groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
|
||||
debug "groupKeyPairs", groupKeyPairs
|
||||
let groupIDCommitments = groupIdCredentials.mapIt(it.idCommitment)
|
||||
debug "groupIdCredentials", groupIdCredentials
|
||||
debug "groupIDCommitments", groupIDCommitments
|
||||
|
||||
# index indicates the position of a membership key pair in the static list of group keys i.e., groupKeyPairs
|
||||
# the corresponding key pair will be used to mount rlnRelay on the current node
|
||||
# index indicates the position of an identity credential in the static list of group keys i.e., groupIdCredentials
|
||||
# the corresponding identity credential will be used to mount rlnRelay on the current node
|
||||
# index also represents the index of the leaf in the Merkle tree that contains node's commitment key
|
||||
let index = MembershipIndex(5)
|
||||
|
||||
|
@ -941,7 +945,7 @@ suite "Waku rln relay":
|
|||
|
||||
let
|
||||
wakuRlnRelay = WakuRLNRelay(membershipIndex: index,
|
||||
membershipKeyPair: groupKeyPairs[index], rlnInstance: rln)
|
||||
identityCredential: groupIdCredentials[index], rlnInstance: rln)
|
||||
|
||||
# add members
|
||||
let commitmentAddRes = wakuRlnRelay.addAll(groupIDCommitments)
|
||||
|
@ -997,21 +1001,21 @@ suite "Waku rln relay":
|
|||
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
# create a key pair
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
# create an idendity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
keyPairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let keyPair = keyPairRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
|
||||
# convert the idCommitment to UInt256
|
||||
let idCUInt = keypair.idCommitment.toUInt256()
|
||||
let idCUInt = idCredential.idCommitment.toUInt256()
|
||||
# convert the UInt256 back to ICommitment
|
||||
let idCommitment = toIDCommitment(idCUInt)
|
||||
|
||||
# check that the conversion has not distorted the original value
|
||||
check:
|
||||
keypair.idCommitment == idCommitment
|
||||
idCredential.idCommitment == idCommitment
|
||||
|
||||
test "Read/Write RLN credentials":
|
||||
# create an RLN instance
|
||||
|
@ -1019,23 +1023,27 @@ suite "Waku rln relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
let keyPairRes = membershipKeyGen(rlnInstance.get())
|
||||
let idCredentialRes = membershipKeyGen(rlnInstance.get())
|
||||
require:
|
||||
keyPairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let keyPair = keyPairRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
let empty = default(array[32, byte])
|
||||
require:
|
||||
keyPair.idKey.len == 32
|
||||
keyPair.idCommitment.len == 32
|
||||
keyPair.idKey != empty
|
||||
keyPair.idCommitment != empty
|
||||
idCredential.idTrapdoor.len == 32
|
||||
idCredential.idNullifier.len == 32
|
||||
idCredential.idSecretHash.len == 32
|
||||
idCredential.idCommitment.len == 32
|
||||
idCredential.idTrapdoor != empty
|
||||
idCredential.idNullifier != empty
|
||||
idCredential.idSecretHash != empty
|
||||
idCredential.idCommitment != empty
|
||||
|
||||
debug "the generated membership key pair: ", keyPair
|
||||
debug "the generated identity credential: ", idCredential
|
||||
|
||||
let index = MembershipIndex(1)
|
||||
|
||||
let rlnMembershipCredentials = RlnMembershipCredentials(membershipKeyPair: keyPair,
|
||||
let rlnMembershipCredentials = RlnMembershipCredentials(identityCredential: idCredential,
|
||||
rlnIndex: index)
|
||||
|
||||
let password = "%m0um0ucoW%"
|
||||
|
@ -1056,7 +1064,7 @@ suite "Waku rln relay":
|
|||
require:
|
||||
credentials.isSome()
|
||||
check:
|
||||
credentials.get().membershipKeyPair == keyPair
|
||||
credentials.get().identityCredential == idCredential
|
||||
credentials.get().rlnIndex == index
|
||||
|
||||
test "histogram static bucket generation":
|
||||
|
|
|
@ -195,11 +195,11 @@ procSuite "Waku-rln-relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
# generate the membership keys
|
||||
let membershipKeyPairRes = membershipKeyGen(rlnInstance.get())
|
||||
let identityCredentialRes = membershipKeyGen(rlnInstance.get())
|
||||
require:
|
||||
membershipKeyPairRes.isOk()
|
||||
let membershipKeyPair = membershipKeyPairRes.get()
|
||||
let pk = membershipKeyPair.idCommitment.toUInt256()
|
||||
identityCredentialRes.isOk()
|
||||
let identityCredential = identityCredentialRes.get()
|
||||
let pk = identityCredential.idCommitment.toUInt256()
|
||||
debug "membership commitment key", pk = pk
|
||||
|
||||
# test ------------------------------
|
||||
|
@ -252,27 +252,27 @@ procSuite "Waku-rln-relay":
|
|||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
keyPairRes.isOk()
|
||||
let keypair = keyPairRes.get()
|
||||
let pk = keyPair.idCommitment.toUInt256()
|
||||
idCredentialRes.isOk()
|
||||
let idCredential = idCredentialRes.get()
|
||||
let pk = idCredential.idCommitment.toUInt256()
|
||||
debug "membership commitment key", pk = pk
|
||||
|
||||
# initialize the WakuRLNRelay
|
||||
let rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair,
|
||||
let rlnPeer = WakuRLNRelay(identityCredential: idCredential,
|
||||
membershipIndex: MembershipIndex(0),
|
||||
ethClientAddress: EthClient,
|
||||
ethAccountAddress: some(accounts[0]),
|
||||
membershipContractAddress: contractAddress,
|
||||
rlnInstance: rln)
|
||||
|
||||
# generate another membership key pair
|
||||
let keyPair2Res = rln.membershipKeyGen()
|
||||
# generate another identity credential
|
||||
let idCredential2Res = rln.membershipKeyGen()
|
||||
require:
|
||||
keyPair2Res.isOk()
|
||||
let keyPair2 = keyPair2Res.get()
|
||||
let pk2 = keyPair2.idCommitment.toUInt256()
|
||||
idCredential2Res.isOk()
|
||||
let idCredential2 = idCredential2Res.get()
|
||||
let pk2 = idCredential2.idCommitment.toUInt256()
|
||||
debug "membership commitment key", pk2 = pk2
|
||||
|
||||
let events = [newFuture[void](), newFuture[void]()]
|
||||
|
@ -358,17 +358,17 @@ procSuite "Waku-rln-relay":
|
|||
rlnInstance.isOk()
|
||||
|
||||
# generate the membership keys
|
||||
let membershipKeyPairRes = membershipKeyGen(rlnInstance.get())
|
||||
let identityCredentialRes = membershipKeyGen(rlnInstance.get())
|
||||
require:
|
||||
membershipKeyPairRes.isOk()
|
||||
let membershipKeyPair = membershipKeyPairRes.get()
|
||||
identityCredentialRes.isOk()
|
||||
let identityCredential = identityCredentialRes.get()
|
||||
|
||||
# create an Ethereum private key and the corresponding account
|
||||
let (ethPrivKey, ethacc) = await createEthAccount()
|
||||
|
||||
# test ------------------------------
|
||||
# initialize the WakuRLNRelay
|
||||
let rlnPeer = WakuRLNRelay(membershipKeyPair: membershipKeyPair,
|
||||
let rlnPeer = WakuRLNRelay(identityCredential: identityCredential,
|
||||
membershipIndex: MembershipIndex(0),
|
||||
ethClientAddress: EthClient,
|
||||
ethAccountPrivateKey: some(ethPrivKey),
|
||||
|
@ -393,12 +393,12 @@ procSuite "Waku-rln-relay":
|
|||
require:
|
||||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
# generate a key pair
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
# generate an identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
keyPairRes.isOk()
|
||||
idCredentialRes.isOk()
|
||||
|
||||
let keyPair = keyPairRes.get()
|
||||
let idCredential = idCredentialRes.get()
|
||||
# current peer index in the Merkle tree
|
||||
let index = uint(5)
|
||||
|
||||
|
@ -408,20 +408,20 @@ procSuite "Waku-rln-relay":
|
|||
var memberAdded: bool = false
|
||||
if (i == index):
|
||||
# insert the current peer's pk
|
||||
group.add(keyPair.idCommitment)
|
||||
memberAdded = rln.insertMembers(i, @[keyPair.idCommitment])
|
||||
group.add(idCredential.idCommitment)
|
||||
memberAdded = rln.insertMembers(i, @[idCredential.idCommitment])
|
||||
doAssert(memberAdded)
|
||||
debug "member key", key = keyPair.idCommitment.inHex
|
||||
debug "member key", key = idCredential.idCommitment.inHex
|
||||
else:
|
||||
let memberKeyPairRes = rln.membershipKeyGen()
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
require:
|
||||
memberKeyPairRes.isOk()
|
||||
let memberKeyPair = memberKeyPairRes.get()
|
||||
group.add(memberKeyPair.idCommitment)
|
||||
let memberAdded = rln.insertMembers(i, @[memberKeyPair.idCommitment])
|
||||
idCredentialRes.isOk()
|
||||
let idCredential = idCredentialRes.get()
|
||||
group.add(idCredential.idCommitment)
|
||||
let memberAdded = rln.insertMembers(i, @[idCredential.idCommitment])
|
||||
require:
|
||||
memberAdded
|
||||
debug "member key", key = memberKeyPair.idCommitment.inHex
|
||||
debug "member key", key = idCredential.idCommitment.inHex
|
||||
|
||||
let expectedRoot = rln.getMerkleRoot().value().inHex
|
||||
debug "expected root ", expectedRoot
|
||||
|
@ -431,7 +431,7 @@ procSuite "Waku-rln-relay":
|
|||
await node.mountRelay(@[RlnRelayPubsubTopic])
|
||||
let mountRes = mountRlnRelayStatic(wakuRelay = node.wakuRelay,
|
||||
group = group,
|
||||
memKeyPair = keyPair,
|
||||
memIdCredential = idCredential,
|
||||
memIndex = index,
|
||||
pubsubTopic = RlnRelayPubsubTopic,
|
||||
contentTopic = RlnRelayContentTopic)
|
||||
|
@ -475,26 +475,26 @@ procSuite "Waku-rln-relay":
|
|||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
# create two rln key pairs
|
||||
# create two identity credentials
|
||||
let
|
||||
keyPair1Res = rln.membershipKeyGen()
|
||||
keyPair2Res = rln.membershipKeyGen()
|
||||
idCredential1Res = rln.membershipKeyGen()
|
||||
idCredential2Res = rln.membershipKeyGen()
|
||||
require:
|
||||
keyPair1Res.isOk()
|
||||
keyPair2Res.isOk()
|
||||
idCredential1Res.isOk()
|
||||
idCredential2Res.isOk()
|
||||
|
||||
let
|
||||
keyPair1 = keyPair1Res.get()
|
||||
keyPair2 = keyPair2Res.get()
|
||||
pk1 = keyPair1.idCommitment.toUInt256()
|
||||
pk2 = keyPair2.idCommitment.toUInt256()
|
||||
debug "member key1", key = keyPair1.idCommitment.inHex
|
||||
debug "member key2", key = keyPair2.idCommitment.inHex
|
||||
idCredential1 = idCredential1Res.get()
|
||||
idCredential2 = idCredential2Res.get()
|
||||
pk1 = idCredential1.idCommitment.toUInt256()
|
||||
pk2 = idCredential2.idCommitment.toUInt256()
|
||||
debug "member key1", key = idCredential1.idCommitment.inHex
|
||||
debug "member key2", key = idCredential2.idCommitment.inHex
|
||||
|
||||
# add the rln keys to the Merkle tree
|
||||
let
|
||||
memberIsAdded1 = rln.insertMembers(0, @[keyPair1.idCommitment])
|
||||
memberIsAdded2 = rln.insertMembers(1, @[keyPair2.idCommitment])
|
||||
memberIsAdded1 = rln.insertMembers(0, @[idCredential1.idCommitment])
|
||||
memberIsAdded2 = rln.insertMembers(1, @[idCredential2.idCommitment])
|
||||
|
||||
require:
|
||||
memberIsAdded1
|
||||
|
@ -527,7 +527,7 @@ procSuite "Waku-rln-relay":
|
|||
ethAccountAddress = some(ethacc),
|
||||
ethAccountPrivKeyOpt = some(ethPrivKey),
|
||||
memContractAddr = contractAddress,
|
||||
memKeyPair = some(keyPair1),
|
||||
memIdCredential = some(idCredential1),
|
||||
memIndex = some(MembershipIndex(0)),
|
||||
pubsubTopic = RlnRelayPubsubTopic,
|
||||
contentTopic = RlnRelayContentTopic)
|
||||
|
@ -586,7 +586,7 @@ procSuite "Waku-rln-relay":
|
|||
ethAccountAddress = some(ethacc),
|
||||
ethAccountPrivKeyOpt = some(ethPrivKey),
|
||||
memContractAddr = contractAddress,
|
||||
memKeyPair = none(MembershipKeyPair),
|
||||
memIdCredential = none(IdentityCredential),
|
||||
memIndex = none(MembershipIndex),
|
||||
pubsubTopic = RlnRelayPubsubTopic,
|
||||
contentTopic = RlnRelayContentTopic)
|
||||
|
@ -603,7 +603,7 @@ procSuite "Waku-rln-relay":
|
|||
ethAccountAddress = some(ethacc),
|
||||
ethAccountPrivKeyOpt = some(ethPrivKey),
|
||||
memContractAddr = contractAddress,
|
||||
memKeyPair = none(MembershipKeyPair),
|
||||
memIdCredential = none(IdentityCredential),
|
||||
memIndex = none(MembershipIndex),
|
||||
pubsubTopic = RlnRelayPubsubTopic,
|
||||
contentTopic = RlnRelayContentTopic)
|
||||
|
|
|
@ -197,7 +197,7 @@ procSuite "WakuNode - RLN relay":
|
|||
input = concat(payload, contentTopicBytes)
|
||||
extraBytes: seq[byte] = @[byte(1),2,3]
|
||||
rateLimitProofRes = node1.wakuRlnRelay.rlnInstance.proofGen(data = concat(input, extraBytes), # we add extra bytes to invalidate proof verification against original payload
|
||||
memKeys = node1.wakuRlnRelay.membershipKeyPair,
|
||||
memKeys = node1.wakuRlnRelay.identityCredential,
|
||||
memIndex = MembershipIndex(1),
|
||||
epoch = epoch)
|
||||
require:
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 490206aa440fb524f0cdf47019ea9604466aae75
|
||||
Subproject commit 32f3202e9dacde84c0f1552582732dbac5da9964
|
|
@ -19,8 +19,10 @@ type RLN* {.incompleteStruct.} = object
|
|||
type RLNResult* = RlnRelayResult[ptr RLN]
|
||||
|
||||
type
|
||||
IdentityTrapdoor* = array[32, byte]
|
||||
IdentityNullifier* = array[32, byte]
|
||||
# identity key as defined in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership
|
||||
IDKey* = array[32, byte]
|
||||
IdentitySecretHash* = array[32, byte]
|
||||
# hash of identity key as defined ed in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership
|
||||
IDCommitment* = array[32, byte]
|
||||
MerkleNode* = array[32, byte] # Each node of the Merkle tee is a Poseidon hash which is a 32 byte value
|
||||
|
@ -30,10 +32,12 @@ type
|
|||
ZKSNARK* = array[128, byte]
|
||||
|
||||
# Custom data types defined for waku rln relay -------------------------
|
||||
type MembershipKeyPair* = object
|
||||
type IdentityCredential* = object
|
||||
idTrapdoor*: IdentityTrapdoor
|
||||
idNullifier*: IdentityNullifier
|
||||
## user's identity key (a secret key) which is selected randomly
|
||||
## see details in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership
|
||||
idKey*: IDKey
|
||||
idSecretHash*: IdentitySecretHash
|
||||
# hash of user's identity key generated by
|
||||
# Poseidon hash function implemented in rln lib
|
||||
# more details in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Membership
|
||||
|
@ -62,7 +66,7 @@ type RateLimitProof* = object
|
|||
type MembershipIndex* = uint
|
||||
|
||||
type RlnMembershipCredentials* = object
|
||||
membershipKeyPair*: MembershipKeyPair
|
||||
identityCredential*: IdentityCredential
|
||||
rlnIndex*: MembershipIndex
|
||||
|
||||
type ProofMetadata* = object
|
||||
|
@ -71,7 +75,7 @@ type ProofMetadata* = object
|
|||
shareY*: MerkleNode
|
||||
|
||||
type WakuRLNRelay* = ref object
|
||||
membershipKeyPair*: MembershipKeyPair
|
||||
identityCredential*: IdentityCredential
|
||||
# membershipIndex denotes the index of a leaf in the Merkle tree
|
||||
# that contains the pk of the current peer
|
||||
# this index is used to retrieve the peer's authentication path
|
||||
|
|
|
@ -66,16 +66,18 @@ proc reset_tree*(ctx: ptr RLN, tree_height: uint): bool {.importc: "set_tree".}
|
|||
#----------------------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------- zkSNARKs operations -----------------------------------------
|
||||
proc key_gen*(ctx: ptr RLN, output_buffer: ptr Buffer): bool {.importc: "key_gen".}
|
||||
## generates id key and id commitment key serialized inside output_buffer as | id_key <32 bytes>| id_commitment_key <32 bytes> |
|
||||
## id commitment is the poseidon hash of the id key
|
||||
proc key_gen*(ctx: ptr RLN, output_buffer: ptr Buffer): bool {.importc: "extended_key_gen".}
|
||||
## generates identity trapdoor, identity nullifier, identity secret hash and id commitment tuple serialized inside output_buffer as | identity_trapdoor<32> | identity_nullifier<32> | identity_secret_hash<32> | id_commitment<32> |
|
||||
## identity secret hash is the poseidon hash of [identity_trapdoor, identity_nullifier]
|
||||
## id commitment is the poseidon hash of the identity secret hash
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
proc seeded_key_gen*(ctx: ptr RLN, input_buffer: ptr Buffer, output_buffer: ptr Buffer): bool {.importc: "seeded_key_gen".}
|
||||
## generates id key and id commitment key serialized inside output_buffer as | id_key <32 bytes>| id_commitment_key <32 bytes> | using ChaCha20
|
||||
proc seeded_key_gen*(ctx: ptr RLN, input_buffer: ptr Buffer, output_buffer: ptr Buffer): bool {.importc: "seeded_extended_key_gen".}
|
||||
## generates identity trapdoor, identity nullifier, identity secret hash and id commitment tuple serialized inside output_buffer as | identity_trapdoor<32> | identity_nullifier<32> | identity_secret_hash<32> | id_commitment<32> | using ChaCha20
|
||||
## seeded with an arbitrary long seed serialized in input_buffer
|
||||
## The input seed provided by the user is hashed using Keccak256 before being passed to ChaCha20 as seed.
|
||||
## id commitment is the poseidon hash of the id key
|
||||
## identity secret hash is the poseidon hash of [identity_trapdoor, identity_nullifier]
|
||||
## id commitment is the poseidon hash of the identity secret hash
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
proc generate_proof*(ctx: ptr RLN,
|
||||
|
|
|
@ -83,11 +83,11 @@ proc createRLNInstanceLocal(d: int = MerkleTreeDepth): RLNResult =
|
|||
return err("error in parameters generation")
|
||||
return ok(rlnInstance)
|
||||
|
||||
proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[MembershipKeyPair] =
|
||||
## generates a MembershipKeyPair that can be used for the registration into the rln membership contract
|
||||
proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[IdentityCredential] =
|
||||
## generates a IdentityCredential that can be used for the registration into the rln membership contract
|
||||
## Returns an error if the key generation fails
|
||||
|
||||
# keysBufferPtr will hold the generated key pairs i.e., secret and public keys
|
||||
# keysBufferPtr will hold the generated identity tuple i.e., trapdoor, nullifier, secret hash and commitment
|
||||
var
|
||||
keysBuffer: Buffer
|
||||
keysBufferPtr = addr(keysBuffer)
|
||||
|
@ -97,22 +97,26 @@ proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[MembershipKeyPair] =
|
|||
if(done == false):
|
||||
return err("error in key generation")
|
||||
|
||||
var generatedKeys = cast[ptr array[64, byte]](keysBufferPtr.`ptr`)[]
|
||||
var generatedKeys = cast[ptr array[4*32, byte]](keysBufferPtr.`ptr`)[]
|
||||
# the public and secret keys together are 64 bytes
|
||||
if (generatedKeys.len != 64):
|
||||
if (generatedKeys.len != 4*32):
|
||||
return err("generated keys are of invalid length")
|
||||
|
||||
# TODO define a separate proc to decode the generated keys to the secret and public components
|
||||
var
|
||||
secret: array[32, byte]
|
||||
public: array[32, byte]
|
||||
for (i, x) in secret.mpairs: x = generatedKeys[i]
|
||||
for (i, x) in public.mpairs: x = generatedKeys[i+32]
|
||||
idTrapdoor: array[32, byte]
|
||||
idNullifier: array[32, byte]
|
||||
idSecretHash: array[32, byte]
|
||||
idCommitment: array[32, byte]
|
||||
for (i, x) in idTrapdoor.mpairs: x = generatedKeys[i+0*32]
|
||||
for (i, x) in idNullifier.mpairs: x = generatedKeys[i+1*32]
|
||||
for (i, x) in idSecretHash.mpairs: x = generatedKeys[i+2*32]
|
||||
for (i, x) in idCommitment.mpairs: x = generatedKeys[i+3*32]
|
||||
|
||||
var
|
||||
keypair = MembershipKeyPair(idKey: secret, idCommitment: public)
|
||||
identityCredential = IdentityCredential(idTrapdoor: idTrapdoor, idNullifier: idNullifier, idSecretHash: idSecretHash, idCommitment: idCommitment)
|
||||
|
||||
return ok(keypair)
|
||||
return ok(identityCredential)
|
||||
|
||||
proc createRLNInstance*(d: int = MerkleTreeDepth): RLNResult =
|
||||
## Wraps the rln instance creation for metrics
|
||||
|
@ -130,8 +134,8 @@ proc toIDCommitment*(idCommitmentUint: UInt256): IDCommitment =
|
|||
let pk = IDCommitment(idCommitmentUint.toBytesLE())
|
||||
return pk
|
||||
|
||||
proc inHex*(value: IDKey or IDCommitment or MerkleNode or Nullifier or Epoch or RlnIdentifier): string =
|
||||
var valueHex = (UInt256.fromBytesLE(value)).toHex
|
||||
proc inHex*(value: IdentityTrapdoor or IdentityNullifier or IdentitySecretHash or IDCommitment or MerkleNode or Nullifier or Epoch or RlnIdentifier): string =
|
||||
var valueHex = (UInt256.fromBytesLE(value)).toHex()
|
||||
# We pad leading zeroes
|
||||
while valueHex.len < value.len * 2:
|
||||
valueHex = "0" & valueHex
|
||||
|
@ -204,9 +208,9 @@ proc register*(idComm: IDCommitment, ethAccountAddress: Option[Address], ethAcco
|
|||
return ok(toMembershipIndex(eventIndex))
|
||||
|
||||
proc register*(rlnPeer: WakuRLNRelay, registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)): Future[RlnRelayResult[bool]] {.async.} =
|
||||
## registers the public key of the rlnPeer which is rlnPeer.membershipKeyPair.publicKey
|
||||
## registers the public key of the rlnPeer which is rlnPeer.identityCredential.publicKey
|
||||
## into the membership contract whose address is in rlnPeer.membershipContractAddress
|
||||
let pk = rlnPeer.membershipKeyPair.idCommitment
|
||||
let pk = rlnPeer.identityCredential.idCommitment
|
||||
let regResult = await register(idComm = pk, ethAccountAddress = rlnPeer.ethAccountAddress, ethAccountPrivKey = rlnPeer.ethAccountPrivateKey.get(), ethClientAddress = rlnPeer.ethClientAddress, membershipContractAddress = rlnPeer.membershipContractAddress, registrationHandler = registrationHandler)
|
||||
if regResult.isErr:
|
||||
return err(regResult.error())
|
||||
|
@ -239,7 +243,7 @@ proc hash*(rlnInstance: ptr RLN, data: openArray[byte]): MerkleNode =
|
|||
|
||||
return output
|
||||
|
||||
proc serialize(idKey: IDKey, memIndex: MembershipIndex, epoch: Epoch,
|
||||
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
|
||||
|
@ -247,15 +251,15 @@ proc serialize(idKey: IDKey, memIndex: MembershipIndex, epoch: Epoch,
|
|||
## [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
|
||||
let memIndexBytes = toBytes(uint64(memIndex), Endianness.littleEndian)
|
||||
let lenPrefMsg = appendLength(msg)
|
||||
let output = concat(@idKey, @memIndexBytes, @epoch, lenPrefMsg)
|
||||
let output = concat(@idSecretHash, @memIndexBytes, @epoch, lenPrefMsg)
|
||||
return output
|
||||
|
||||
proc proofGen*(rlnInstance: ptr RLN, data: openArray[byte],
|
||||
memKeys: MembershipKeyPair, memIndex: MembershipIndex,
|
||||
memKeys: IdentityCredential, memIndex: MembershipIndex,
|
||||
epoch: Epoch): RateLimitProofResult =
|
||||
|
||||
# serialize inputs
|
||||
let serializedInputs = serialize(idKey = memKeys.idKey,
|
||||
let serializedInputs = serialize(idSecretHash = memKeys.idSecretHash,
|
||||
memIndex = memIndex,
|
||||
epoch = epoch,
|
||||
msg = data)
|
||||
|
@ -464,25 +468,49 @@ proc validateRoot*(wakuRlnRelay: WakuRLNRelay, root: MerkleNode): bool =
|
|||
## Validate against the window of roots stored in wakuRlnRelay.validMerkleRoots
|
||||
return root in wakuRlnRelay.validMerkleRoots
|
||||
|
||||
proc toMembershipKeyPairs*(groupKeys: seq[(string, string)]): RlnRelayResult[seq[
|
||||
MembershipKeyPair]] =
|
||||
# Converts a sequence of tuples containing 4 string (i.e. identity trapdoor, nullifier, secret hash and commitment) to an IndentityCredential
|
||||
proc toIdentityCredentials*(groupKeys: seq[(string, string, string, string)]): RlnRelayResult[seq[
|
||||
IdentityCredential]] =
|
||||
## groupKeys is sequence of membership key tuples in the form of (identity key, identity commitment) all in the hexadecimal format
|
||||
## the toMembershipKeyPairs proc populates a sequence of MembershipKeyPairs using the supplied groupKeys
|
||||
## the toIdentityCredentials proc populates a sequence of IdentityCredentials using the supplied groupKeys
|
||||
## Returns an error if the conversion fails
|
||||
|
||||
var groupKeyPairs = newSeq[MembershipKeyPair]()
|
||||
var groupIdCredentials = newSeq[IdentityCredential]()
|
||||
|
||||
for i in 0..groupKeys.len-1:
|
||||
try:
|
||||
let
|
||||
idKey = hexToUint[IDKey.len*8](groupKeys[i][0]).toBytesLE()
|
||||
idCommitment = hexToUint[IDCommitment.len*8](groupKeys[i][1]).toBytesLE()
|
||||
groupKeyPairs.add(MembershipKeyPair(idKey: idKey,
|
||||
idTrapdoor = hexToUint[IdentityTrapdoor.len*8](groupKeys[i][0]).toBytesLE()
|
||||
idNullifier = hexToUint[IdentityNullifier.len*8](groupKeys[i][1]).toBytesLE()
|
||||
idSecretHash = hexToUint[IdentitySecretHash.len*8](groupKeys[i][2]).toBytesLE()
|
||||
idCommitment = hexToUint[IDCommitment.len*8](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(groupKeyPairs)
|
||||
return ok(groupIdCredentials)
|
||||
|
||||
# Converts a sequence of tuples containing 2 string (i.e. identity secret hash and commitment) to an IndentityCredential
|
||||
proc toIdentityCredentials*(groupKeys: seq[(string, string)]): 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
|
||||
idSecretHash = hexToUint[IdentitySecretHash.len*8](groupKeys[i][0]).toBytesLE()
|
||||
idCommitment = hexToUint[IDCommitment.len*8](groupKeys[i][1]).toBytesLE()
|
||||
groupIdCredentials.add(IdentityCredential(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 calcMerkleRoot*(list: seq[IDCommitment]): RlnRelayResult[string] =
|
||||
## returns the root of the Merkle tree that is computed from the supplied list
|
||||
|
@ -502,9 +530,9 @@ proc calcMerkleRoot*(list: seq[IDCommitment]): RlnRelayResult[string] =
|
|||
return ok(root)
|
||||
|
||||
proc createMembershipList*(n: int): RlnRelayResult[(
|
||||
seq[(string, string)], string
|
||||
seq[(string, string, string, string)], string
|
||||
)] =
|
||||
## createMembershipList produces a sequence of membership key pairs in the form of (identity key, id commitment keys) in the hexadecimal format
|
||||
## createMembershipList produces a sequence of identity credentials in the form of (identity trapdoor, identity nullifier, identity secret hash, id commitment) in the hexadecimal format
|
||||
## this proc also returns the root of a Merkle tree constructed out of the identity commitment keys of the generated list
|
||||
## the output of this proc is used to initialize a static group keys (to test waku-rln-relay in the off-chain mode)
|
||||
## Returns an error if it cannot create the membership list
|
||||
|
@ -515,19 +543,18 @@ proc createMembershipList*(n: int): RlnRelayResult[(
|
|||
return err("could not create rln instance: " & rlnInstance.error())
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
var output = newSeq[(string, string)]()
|
||||
var output = newSeq[(string, string, string, string)]()
|
||||
var idCommitments = newSeq[IDCommitment]()
|
||||
|
||||
for i in 0..n-1:
|
||||
|
||||
# generate a key pair
|
||||
let keypairRes = rln.membershipKeyGen()
|
||||
if keypairRes.isErr():
|
||||
return err("could not generate a key pair: " & keypairRes.error())
|
||||
let keypair = keypairRes.get()
|
||||
let keyTuple = (keypair.idKey.inHex(), keypair.idCommitment.inHex())
|
||||
output.add(keyTuple)
|
||||
|
||||
idCommitments.add(keypair.idCommitment)
|
||||
# generate an identity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
if idCredentialRes.isErr():
|
||||
return err("could not generate an identity credential: " & idCredentialRes.error())
|
||||
let idCredential = idCredentialRes.get()
|
||||
let idTuple = (idCredential.idTrapdoor.inHex(), idCredential.idNullifier.inHex(), idCredential.idSecretHash.inHex(), idCredential.idCommitment.inHex())
|
||||
output.add(idTuple)
|
||||
idCommitments.add(idCredential.idCommitment)
|
||||
|
||||
# Insert members into tree
|
||||
let membersAdded = rln.insertMembers(0, idCommitments)
|
||||
|
@ -538,11 +565,11 @@ proc createMembershipList*(n: int): RlnRelayResult[(
|
|||
return ok((output, root))
|
||||
|
||||
proc rlnRelayStaticSetUp*(rlnRelayMembershipIndex: MembershipIndex): RlnRelayResult[(Option[seq[
|
||||
IDCommitment]], Option[MembershipKeyPair], Option[
|
||||
IDCommitment]], Option[IdentityCredential], Option[
|
||||
MembershipIndex])] =
|
||||
## rlnRelayStaticSetUp is a proc that is used to initialize the static group keys and the static membership index
|
||||
## this proc is used to test waku-rln-relay in the off-chain mode
|
||||
## it returns the static group keys, the static membership key pair, and the static membership index
|
||||
## it returns the static group id commitments, the static identity credentials, and the static membership indexes
|
||||
## Returns an error if it cannot initialize the static group keys and the static membership index
|
||||
let
|
||||
# static group
|
||||
|
@ -555,27 +582,27 @@ proc rlnRelayStaticSetUp*(rlnRelayMembershipIndex: MembershipIndex): RlnRelayRes
|
|||
if rlnRelayMembershipIndex < MembershipIndex(0) or rlnRelayMembershipIndex >=
|
||||
MembershipIndex(groupSize):
|
||||
error "wrong membership index"
|
||||
return ok((none(seq[IDCommitment]), none(MembershipKeyPair), none(MembershipIndex)))
|
||||
return ok((none(seq[IDCommitment]), none(IdentityCredential), none(MembershipIndex)))
|
||||
|
||||
# prepare the outputs from the static group keys
|
||||
let
|
||||
# create a sequence of MembershipKeyPairs from the group keys (group keys are in string format)
|
||||
groupKeyPairsRes = groupKeys.toMembershipKeyPairs()
|
||||
# create a sequence of IdentityCredentials from the group keys (group keys are in string format)
|
||||
groupIdCredentialsRes = groupKeys.toIdentityCredentials()
|
||||
|
||||
if groupKeyPairsRes.isErr():
|
||||
return err("could not convert the group keys to MembershipKeyPairs: " &
|
||||
groupKeyPairsRes.error())
|
||||
if groupIdCredentialsRes.isErr():
|
||||
return err("could not convert the group keys to IdentityCredentials: " &
|
||||
groupIdCredentialsRes.error())
|
||||
|
||||
let
|
||||
groupKeyPairs = groupKeyPairsRes.get()
|
||||
groupIdCredentials = groupIdCredentialsRes.get()
|
||||
# extract id commitment keys
|
||||
groupIDCommitments = groupKeyPairs.mapIt(it.idCommitment)
|
||||
groupOpt = some(groupIDCommitments)
|
||||
# user selected membership key pair
|
||||
memKeyPairOpt = some(groupKeyPairs[rlnRelayMembershipIndex])
|
||||
groupIDCommitments = groupIdCredentials.mapIt(it.idCommitment)
|
||||
groupIDCommitmentsOpt = some(groupIDCommitments)
|
||||
# user selected rln membership credential
|
||||
groupIdCredentialsOpt = some(groupIdCredentials[rlnRelayMembershipIndex])
|
||||
memIndexOpt = some(rlnRelayMembershipIndex)
|
||||
|
||||
return ok((groupOpt, memKeyPairOpt, memIndexOpt))
|
||||
return ok((groupIDCommitmentsOpt, groupIdCredentialsOpt, memIndexOpt))
|
||||
|
||||
proc hasDuplicate*(rlnPeer: WakuRLNRelay, msg: WakuMessage): RlnRelayResult[bool] =
|
||||
## returns true if there is another message in the `nullifierLog` of the `rlnPeer` with the same
|
||||
|
@ -794,7 +821,7 @@ proc appendRLNProof*(rlnPeer: WakuRLNRelay, msg: var WakuMessage,
|
|||
let input = msg.toRLNSignal()
|
||||
|
||||
var proof: RateLimitProofResult = proofGen(rlnInstance = rlnPeer.rlnInstance, data = input,
|
||||
memKeys = rlnPeer.membershipKeyPair,
|
||||
memKeys = rlnPeer.identityCredential,
|
||||
memIndex = rlnPeer.membershipIndex,
|
||||
epoch = calcEpoch(senderEpochTime))
|
||||
|
||||
|
@ -1031,7 +1058,7 @@ proc addRLNRelayValidator*(wakuRlnRelay: WakuRLNRelay,
|
|||
|
||||
proc mountRlnRelayStatic*(wakuRelay: WakuRelay,
|
||||
group: seq[IDCommitment],
|
||||
memKeyPair: MembershipKeyPair,
|
||||
memIdCredential: IdentityCredential,
|
||||
memIndex: MembershipIndex,
|
||||
pubsubTopic: PubsubTopic,
|
||||
contentTopic: ContentTopic,
|
||||
|
@ -1040,7 +1067,7 @@ proc mountRlnRelayStatic*(wakuRelay: WakuRelay,
|
|||
|
||||
debug "mounting rln-relay in off-chain/static mode"
|
||||
# check the peer's index and the inclusion of user's identity commitment in the group
|
||||
if not memKeyPair.idCommitment == group[int(memIndex)]:
|
||||
if not memIdCredential.idCommitment == group[int(memIndex)]:
|
||||
return err("The peer's index is not consistent with the group")
|
||||
|
||||
# create an RLN instance
|
||||
|
@ -1050,7 +1077,7 @@ proc mountRlnRelayStatic*(wakuRelay: WakuRelay,
|
|||
let rln = rlnInstance.get()
|
||||
|
||||
# create the WakuRLNRelay
|
||||
let rlnPeer = WakuRLNRelay(membershipKeyPair: memKeyPair,
|
||||
let rlnPeer = WakuRLNRelay(identityCredential: memIdCredential,
|
||||
membershipIndex: memIndex,
|
||||
rlnInstance: rln,
|
||||
pubsubTopic: pubsubTopic,
|
||||
|
@ -1074,7 +1101,7 @@ proc mountRlnRelayDynamic*(wakuRelay: WakuRelay,
|
|||
ethAccountAddress: Option[web3.Address] = none(web3.Address),
|
||||
ethAccountPrivKeyOpt: Option[keys.PrivateKey],
|
||||
memContractAddr: web3.Address,
|
||||
memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair),
|
||||
memIdCredential: Option[IdentityCredential] = none(IdentityCredential),
|
||||
memIndex: Option[MembershipIndex] = none(MembershipIndex),
|
||||
pubsubTopic: PubsubTopic,
|
||||
contentTopic: ContentTopic,
|
||||
|
@ -1088,21 +1115,21 @@ proc mountRlnRelayDynamic*(wakuRelay: WakuRelay,
|
|||
return err("RLN instance creation failed.")
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
# prepare rln membership key pair
|
||||
# prepare rln membership credential
|
||||
var
|
||||
keyPair: MembershipKeyPair
|
||||
idCredential: IdentityCredential
|
||||
rlnIndex: MembershipIndex
|
||||
if memKeyPair.isNone: # no rln credentials provided
|
||||
if memIdCredential.isNone: # no rln credentials provided
|
||||
if ethAccountPrivKeyOpt.isSome: # if an ethereum private key is supplied, then create rln credentials and register to the membership contract
|
||||
trace "no rln-relay key is provided, generating one"
|
||||
let keyPairRes = rln.membershipKeyGen()
|
||||
if keyPairRes.isErr():
|
||||
error "failed to generate rln-relay key pair"
|
||||
return err("failed to generate rln-relay key pair: " & keyPairRes.error())
|
||||
keyPair = keyPairRes.value()
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
if idCredentialRes.isErr():
|
||||
error "failed to generate rln-relay identity credential"
|
||||
return err("failed to generate rln-relay identity credential: " & idCredentialRes.error())
|
||||
idCredential = idCredentialRes.value()
|
||||
# register the rln-relay peer to the membership contract
|
||||
waku_rln_registration_duration_seconds.nanosecondTime:
|
||||
let regIndexRes = await register(idComm = keyPair.idCommitment,
|
||||
let regIndexRes = await register(idComm = idCredential.idCommitment,
|
||||
ethAccountAddress = ethAccountAddress,
|
||||
ethAccountPrivKey = ethAccountPrivKeyOpt.get(),
|
||||
ethClientAddress = ethClientAddr,
|
||||
|
@ -1118,11 +1145,11 @@ proc mountRlnRelayDynamic*(wakuRelay: WakuRelay,
|
|||
debug "running waku-rln-relay in relay-only mode"
|
||||
else:
|
||||
debug "Peer is already registered to the membership contract"
|
||||
keyPair = memKeyPair.get()
|
||||
idCredential = memIdCredential.get()
|
||||
rlnIndex = memIndex.get()
|
||||
|
||||
# create the WakuRLNRelay
|
||||
var rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair,
|
||||
var rlnPeer = WakuRLNRelay(identityCredential: idCredential,
|
||||
membershipIndex: rlnIndex,
|
||||
membershipContractAddress: memContractAddr,
|
||||
ethClientAddress: ethClientAddr,
|
||||
|
@ -1199,7 +1226,7 @@ proc mount(wakuRelay: WakuRelay,
|
|||
let staticSetupRes = rlnRelayStaticSetUp(MembershipIndex(conf.rlnRelayMembershipIndex))
|
||||
if staticSetupRes.isErr():
|
||||
return err("rln relay static setup failed: " & staticSetupRes.error())
|
||||
let (groupOpt, memKeyPairOpt, memIndexOpt) = staticSetupRes.get()
|
||||
let (groupOpt, idCredentialOpt, memIndexOpt) = staticSetupRes.get()
|
||||
if memIndexOpt.isNone():
|
||||
error "failed to mount WakuRLNRelay"
|
||||
return err("failed to mount WakuRLNRelay")
|
||||
|
@ -1207,7 +1234,7 @@ proc mount(wakuRelay: WakuRelay,
|
|||
# mount rlnrelay in off-chain mode with a static group of users
|
||||
let mountRes = mountRlnRelayStatic(wakuRelay,
|
||||
group = groupOpt.get(),
|
||||
memKeyPair = memKeyPairOpt.get(),
|
||||
memIdCredential = idCredentialOpt.get(),
|
||||
memIndex = memIndexOpt.get(),
|
||||
pubsubTopic = conf.rlnRelayPubsubTopic,
|
||||
contentTopic = conf.rlnRelayContentTopic,
|
||||
|
@ -1218,8 +1245,8 @@ proc mount(wakuRelay: WakuRelay,
|
|||
|
||||
let rlnRelay = mountRes.get()
|
||||
|
||||
info "membership id key", idkey=memKeyPairOpt.get().idKey.inHex()
|
||||
info "membership id commitment key", idCommitmentkey=memKeyPairOpt.get().idCommitment.inHex()
|
||||
info "membership id key", idkey=idCredentialOpt.get().idSecretHash.inHex()
|
||||
info "membership id commitment key", idCommitmentkey=idCredentialOpt.get().idCommitment.inHex()
|
||||
|
||||
# check the correct construction of the tree by comparing the calculated root against the expected root
|
||||
# no error should happen as it is already captured in the unit tests
|
||||
|
@ -1306,7 +1333,7 @@ proc mount(wakuRelay: WakuRelay,
|
|||
contentTopic = conf.rlnRelayContentTopic,
|
||||
spamHandler = spamHandler,
|
||||
registrationHandler = registrationHandler,
|
||||
memKeyPair = some(credentials.get().membershipKeyPair),
|
||||
memIdCredential = some(credentials.get().identityCredential),
|
||||
memIndex = some(credentials.get().rlnIndex))
|
||||
else:
|
||||
# mount rln-relay in on-chain mode, with the provided private key
|
||||
|
@ -1342,7 +1369,7 @@ proc mount(wakuRelay: WakuRelay,
|
|||
if persistCredentials:
|
||||
# persist rln credential
|
||||
credentials = some(RlnMembershipCredentials(rlnIndex: wakuRlnRelay.membershipIndex,
|
||||
membershipKeyPair: wakuRlnRelay.membershipKeyPair))
|
||||
identityCredential: wakuRlnRelay.identityCredential))
|
||||
if writeRlnCredentials(rlnRelayCredPath, credentials.get(), conf.rlnRelayCredentialsPassword).isErr():
|
||||
return err("error in storing rln credentials")
|
||||
return ok(wakuRlnRelay)
|
||||
|
|
Loading…
Reference in New Issue