Skip to content

Commit

Permalink
feat(credential): sort groups, test credential retrieval/group merging
Browse files Browse the repository at this point in the history
  • Loading branch information
s1fr0 committed Jan 24, 2023
1 parent 48fc72c commit 58724d7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 30 deletions.
99 changes: 73 additions & 26 deletions tests/v2/test_utils_credentials.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{.used.}

import
std/[options, os, strutils, sequtils],
std/[algorithm, options, os, strutils, sequtils, sets],
testutils/unittests, chronos, chronicles, stint, json,
stew/byteutils,
../../waku/v2/utils/credentials,
Expand Down Expand Up @@ -99,17 +99,21 @@ procSuite "Credentials test suite":
let filepath = "./testAppKeystore.txt"
defer: removeFile(filepath)

# We generate a random identity credential (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
# We generate two random identity credentials (inter-value constrains are not enforced, otherwise we need to load e.g. zerokit RLN keygen)
var
idTrapdoor = randomSeqByte(rng[], 32)
idNullifier = randomSeqByte(rng[], 32)
idSecretHash = randomSeqByte(rng[], 32)
idCommitment = randomSeqByte(rng[], 32)

var idCredential = IdentityCredential(idTrapdoor: idTrapdoor, idNullifier: idNullifier, idSecretHash: idSecretHash, idCommitment: idCommitment)

debug "the generated identity credential: ", idCredential

idTrapdoor1 = randomSeqByte(rng[], 32)
idNullifier1 = randomSeqByte(rng[], 32)
idSecretHash1 = randomSeqByte(rng[], 32)
idCommitment1 = randomSeqByte(rng[], 32)
idCredential1 = IdentityCredential(idTrapdoor: idTrapdoor1, idNullifier: idNullifier1, idSecretHash: idSecretHash1, idCommitment: idCommitment1)

var
idTrapdoor2 = randomSeqByte(rng[], 32)
idNullifier2 = randomSeqByte(rng[], 32)
idSecretHash2 = randomSeqByte(rng[], 32)
idCommitment2 = randomSeqByte(rng[], 32)
idCredential2 = IdentityCredential(idTrapdoor: idTrapdoor2, idNullifier: idNullifier2, idSecretHash: idSecretHash2, idCommitment: idCommitment2)

# We generate two distinct membership groups
var contract1 = MembershipContract(chainId: "5", address: "0x0123456789012345678901234567890123456789")
var index1 = MembershipIndex(1)
Expand All @@ -119,22 +123,25 @@ procSuite "Credentials test suite":
var index2 = MembershipIndex(2)
var membershipGroup2 = MembershipGroup(membershipContract: contract2, treeIndex: index2)

# We generate three membership credentials with same identity credential
let membershipCredentials1 = MembershipCredentials(identityCredential: idCredential,
# We generate three membership credentials
let membershipCredentials1 = MembershipCredentials(identityCredential: idCredential1,
membershipGroups: @[membershipGroup1])

let membershipCredentials2 = MembershipCredentials(identityCredential: idCredential,
let membershipCredentials2 = MembershipCredentials(identityCredential: idCredential2,
membershipGroups: @[membershipGroup2])

# This is the same as rlnMembershipCredentials2, should not change the keystore entry of idCredential
let membershipCredentials3 = MembershipCredentials(identityCredential: idCredential,
let membershipCredentials3 = MembershipCredentials(identityCredential: idCredential1,
membershipGroups: @[membershipGroup2])

# This is the same as rlnMembershipCredentials3, should not change the keystore entry of idCredential
let membershipCredentials4 = MembershipCredentials(identityCredential: idCredential1,
membershipGroups: @[membershipGroup2])

let password = "%m0um0ucoW%"

# We should get only two distinct credentials, since membershipCredentials2 is equal to membershipCredentials3
# We add credentials to the keystore. Note that only 3 credentials should be effectively added, since rlnMembershipCredentials3 is equal to membershipCredentials2
let keystore = addMembershipCredentials(path = filepath,
credentials = @[membershipCredentials1, membershipCredentials2, membershipCredentials3],
credentials = @[membershipCredentials1, membershipCredentials2, membershipCredentials3, membershipCredentials4],
password = password,
application = "test",
appIdentifier = "1234",
Expand All @@ -143,13 +150,53 @@ procSuite "Credentials test suite":
check:
keystore.isOk()

# We test retrieval of credentials.
var expectedMembershipGroups1 = @[membershipGroup1, membershipGroup2]
expectedMembershipGroups1.sort(sortMembershipGroup, Ascending)
let expectedCredential1 = MembershipCredentials(identityCredential: idCredential1,
membershipGroups: expectedMembershipGroups1)


var expectedMembershipGroups2 = @[membershipGroup2]
expectedMembershipGroups2.sort(sortMembershipGroup, Ascending)
let expectedCredential2 = MembershipCredentials(identityCredential: idCredential2,
membershipGroups: expectedMembershipGroups2)


# We retrieve all credentials stored under password (no filter)
var recoveredCredentials = getMembershipCredentials(path = filepath,
password = password,
application = "test",
appIdentifier = "1234",
version = "0.1")


check:
recoveredCredentials.isOk()
recoveredCredentials.get() == @[expectedCredential1, expectedCredential2]


# We retrieve credentials by filtering on an IdentityCredential
recoveredCredentials = getMembershipCredentials(path = filepath,
password = password,
filterIdentityCredentials = @[idCredential1],
application = "test",
appIdentifier = "1234",
version = "0.1")

check:
recoveredCredentials.isOk()
recoveredCredentials.get() == @[expectedCredential1]

# We retrieve credentials by filtering on multiple IdentityCredentials
recoveredCredentials = getMembershipCredentials(path = filepath,
password = password,
filterIdentityCredentials = @[idCredential1, idCredential2],
application = "test",
appIdentifier = "1234",
version = "0.1")

check:
recoveredCredentials.isOk()
recoveredCredentials.get() == @[expectedCredential1, expectedCredential2]

let creds = getMembershipCredentials(path = filepath,
password = password,
filterIdentityCredentials = @[idCredential],
filterMembershipContracts = @[contract1],
application = "test",
appIdentifier = "1234",
version = "0.1")
echo creds
14 changes: 10 additions & 4 deletions waku/v2/utils/credentials.nim
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ else:
import
chronicles, options, json, strutils,
stew/byteutils,
std/[os, sequtils, sets],
std/[algorithm, os, sequtils, sets],
./keyfile

type
Expand Down Expand Up @@ -64,14 +64,14 @@ type
type KeystoreResult[T] = Result[T, AppKeystoreError]


proc encode(credential: MembershipCredentials): seq[byte] =
proc encode*(credential: MembershipCredentials): seq[byte] =
# TODO: use custom encoding, avoid wordy json
var stringCredential: string
# NOTE: toUgly appends to the string, doesn't replace its contents
stringCredential.toUgly(%credential)
return toBytes(stringCredential)

proc decode(encodedCredential: seq[byte]): KeystoreResult[MembershipCredentials] =
proc decode*(encodedCredential: seq[byte]): KeystoreResult[MembershipCredentials] =
# TODO: use custom decoding, avoid wordy json
try:
# we parse the json decrypted keystoreCredential
Expand All @@ -83,6 +83,9 @@ proc decode(encodedCredential: seq[byte]): KeystoreResult[MembershipCredentials]
return err(OsError)


proc sortMembershipGroup*(a,b: MembershipGroup): int =
return cmp(a.membershipContract.address, b.membershipContract.address)

proc createAppKeystore*(path: string,
application: string,
appIdentifier: string,
Expand Down Expand Up @@ -219,7 +222,10 @@ proc addMembershipCredentials*(path: string,
# We check if the decrypted credential has its identityCredential field equal to the input credential
if keyfileMembershipCredential.identityCredential == membershipCredential.identityCredential:
# idCredential is present in keystore. We add the input credential membership group to the one contained in the decrypted keystore credential (we deduplicate groups using sets)
let allMemberships = toSeq(toHashSet(keyfileMembershipCredential.membershipGroups) + toHashSet(membershipCredential.membershipGroups))
var allMemberships = toSeq(toHashSet(keyfileMembershipCredential.membershipGroups) + toHashSet(membershipCredential.membershipGroups))

# We sort membership groups, otherwise we will not have deterministic results in tests
allMemberships.sort(sortMembershipGroup, Ascending)

# we define the updated credential with the updated membership sets
let updatedCredential = MembershipCredentials(identityCredential: keyfileMembershipCredential.identityCredential, membershipGroups: allMemberships)
Expand Down

0 comments on commit 58724d7

Please sign in to comment.