mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-02 14:03:06 +00:00
feat: stateless RLN ( bump v0.9.0 ) (#3621)
This commit is contained in:
parent
7e5041d5e1
commit
deebee45d7
2
Makefile
2
Makefile
@ -177,7 +177,7 @@ nimbus-build-system-nimble-dir:
|
||||
.PHONY: librln
|
||||
|
||||
LIBRLN_BUILDDIR := $(CURDIR)/vendor/zerokit
|
||||
LIBRLN_VERSION := v0.8.0
|
||||
LIBRLN_VERSION := v0.9.0
|
||||
|
||||
ifeq ($(detected_OS),Windows)
|
||||
LIBRLN_FILE := rln.lib
|
||||
|
||||
@ -15,7 +15,7 @@ proc benchmark(
|
||||
manager: OnChainGroupManager, registerCount: int, messageLimit: int
|
||||
): Future[string] {.async, gcsafe.} =
|
||||
# Register a new member so that we can later generate proofs
|
||||
let idCredentials = generateCredentials(manager.rlnInstance, registerCount)
|
||||
let idCredentials = generateCredentials(registerCount)
|
||||
|
||||
var start_time = getTime()
|
||||
for i in 0 .. registerCount - 1:
|
||||
|
||||
@ -49,6 +49,6 @@ else
|
||||
exit 1
|
||||
fi
|
||||
# if submodule version = version in Makefile, build rln
|
||||
cargo build --release -p rln --manifest-path "${build_dir}/rln/Cargo.toml" --features arkzkey
|
||||
cargo build --release -p rln --manifest-path "${build_dir}/rln/Cargo.toml"
|
||||
cp "${build_dir}/target/release/librln.a" "${output_filename}"
|
||||
fi
|
||||
|
||||
@ -151,7 +151,7 @@ suite "RLN Proofs as a Lightpush Service":
|
||||
client.mountLegacyLightPushClient()
|
||||
|
||||
let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
|
||||
@ -151,7 +151,7 @@ suite "RLN Proofs as a Lightpush Service":
|
||||
client.mountLightPushClient()
|
||||
|
||||
let manager1 = cast[OnchainGroupManager](server.wakuRlnRelay.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
|
||||
@ -34,14 +34,9 @@ proc valid(x: seq[byte]): bool =
|
||||
return true
|
||||
|
||||
suite "membershipKeyGen":
|
||||
var rlnRes {.threadvar.}: RLNResult
|
||||
|
||||
setup:
|
||||
rlnRes = createRLNInstanceWrapper()
|
||||
|
||||
test "ok":
|
||||
# Given we generate valid membership keys
|
||||
let identityCredentialsRes = membershipKeyGen(rlnRes.get())
|
||||
let identityCredentialsRes = membershipKeyGen()
|
||||
|
||||
# Then it contains valid identity credentials
|
||||
let identityCredentials = identityCredentialsRes.get()
|
||||
@ -62,7 +57,7 @@ suite "membershipKeyGen":
|
||||
keyGenMock
|
||||
|
||||
# When we generate the membership keys
|
||||
let identityCredentialsRes = membershipKeyGen(rlnRes.get())
|
||||
let identityCredentialsRes = membershipKeyGen()
|
||||
|
||||
# Then it fails
|
||||
check:
|
||||
@ -85,7 +80,7 @@ suite "membershipKeyGen":
|
||||
keyGenMock
|
||||
|
||||
# When we generate the membership keys
|
||||
let identityCredentialsRes = membershipKeyGen(rlnRes.get())
|
||||
let identityCredentialsRes = membershipKeyGen()
|
||||
|
||||
# Then it fails
|
||||
check:
|
||||
|
||||
@ -60,44 +60,6 @@ suite "Onchain group manager":
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
test "should error on initialization when loaded metadata does not match":
|
||||
(waitFor manager.init()).isOkOr:
|
||||
assert false, $error
|
||||
let metadataSetRes = manager.setMetadata()
|
||||
assert metadataSetRes.isOk(), metadataSetRes.error
|
||||
let metadataOpt = manager.rlnInstance.getMetadata().valueOr:
|
||||
assert false, $error
|
||||
return
|
||||
assert metadataOpt.isSome(), "metadata is not set"
|
||||
let metadata = metadataOpt.get()
|
||||
assert metadata.chainId == 1234, "chainId is not equal to 1234"
|
||||
assert metadata.contractAddress == manager.ethContractAddress,
|
||||
"contractAddress is not equal to " & manager.ethContractAddress
|
||||
let web3 = manager.ethRpc.get()
|
||||
let accounts = waitFor web3.provider.eth_accounts()
|
||||
web3.defaultAccount = accounts[2]
|
||||
let (privateKey, acc) = createEthAccount(web3)
|
||||
let tokenAddress = (waitFor deployTestToken(privateKey, acc, web3)).valueOr:
|
||||
assert false, "Failed to deploy test token contract: " & $error
|
||||
return
|
||||
let differentContractAddress = (
|
||||
waitFor executeForgeContractDeployScripts(privateKey, acc, web3)
|
||||
).valueOr:
|
||||
assert false, "Failed to deploy RLN contract: " & $error
|
||||
return
|
||||
# simulating a change in the contractAddress
|
||||
let manager2 = OnchainGroupManager(
|
||||
ethClientUrls: @[EthClient],
|
||||
ethContractAddress: $differentContractAddress,
|
||||
rlnInstance: manager.rlnInstance,
|
||||
onFatalErrorAction: proc(errStr: string) =
|
||||
assert false, errStr
|
||||
,
|
||||
)
|
||||
let e = waitFor manager2.init()
|
||||
(e).isErrOr:
|
||||
assert false, "Expected error when contract address doesn't match"
|
||||
|
||||
test "should error if contract does not exist":
|
||||
manager.ethContractAddress = "0x0000000000000000000000000000000000000000"
|
||||
|
||||
@ -118,7 +80,7 @@ suite "Onchain group manager":
|
||||
check getCurrentExceptionMsg().len == 38
|
||||
|
||||
test "trackRootChanges: should sync to the state of the group":
|
||||
let credentials = generateCredentials(manager.rlnInstance)
|
||||
let credentials = generateCredentials()
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
@ -133,17 +95,7 @@ suite "Onchain group manager":
|
||||
|
||||
let merkleRootAfter = waitFor manager.fetchMerkleRoot()
|
||||
|
||||
let metadataSetRes = manager.setMetadata()
|
||||
assert metadataSetRes.isOk(), metadataSetRes.error
|
||||
|
||||
let metadataOpt = getMetadata(manager.rlnInstance).valueOr:
|
||||
raiseAssert $error
|
||||
|
||||
assert metadataOpt.isSome(), "metadata is not set"
|
||||
let metadata = metadataOpt.get()
|
||||
|
||||
check:
|
||||
metadata.validRoots == manager.validRoots.toSeq()
|
||||
merkleRootBefore != merkleRootAfter
|
||||
|
||||
test "trackRootChanges: should fetch history correctly":
|
||||
@ -152,7 +104,7 @@ suite "Onchain group manager":
|
||||
# so we can't use it in this test.
|
||||
|
||||
const credentialCount = 6
|
||||
let credentials = generateCredentials(manager.rlnInstance, credentialCount)
|
||||
let credentials = generateCredentials(credentialCount)
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
@ -191,7 +143,7 @@ suite "Onchain group manager":
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
let merkleRootBefore = waitFor manager.fetchMerkleRoot()
|
||||
|
||||
try:
|
||||
@ -207,7 +159,7 @@ suite "Onchain group manager":
|
||||
manager.latestIndex == 1
|
||||
|
||||
test "register: callback is called":
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
let idCommitment = idCredentials.idCommitment
|
||||
|
||||
let fut = newFuture[void]()
|
||||
@ -237,7 +189,7 @@ suite "Onchain group manager":
|
||||
waitFor fut
|
||||
|
||||
test "withdraw: should guard against uninitialized state":
|
||||
let idSecretHash = generateCredentials(manager.rlnInstance).idSecretHash
|
||||
let idSecretHash = generateCredentials().idSecretHash
|
||||
|
||||
try:
|
||||
waitFor manager.withdraw(idSecretHash)
|
||||
@ -247,7 +199,7 @@ suite "Onchain group manager":
|
||||
assert false, "exception raised: " & getCurrentExceptionMsg()
|
||||
|
||||
test "validateRoot: should validate good root":
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
let idCommitment = idCredentials.idCommitment
|
||||
|
||||
let fut = newFuture[void]()
|
||||
@ -298,7 +250,7 @@ suite "Onchain group manager":
|
||||
validated
|
||||
|
||||
test "validateRoot: should reject bad root":
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
let idCommitment = idCredentials.idCommitment
|
||||
|
||||
(waitFor manager.init()).isOkOr:
|
||||
@ -331,7 +283,7 @@ suite "Onchain group manager":
|
||||
validated == false
|
||||
|
||||
test "verifyProof: should verify valid proof":
|
||||
let credentials = generateCredentials(manager.rlnInstance)
|
||||
let credentials = generateCredentials()
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
@ -383,7 +335,7 @@ suite "Onchain group manager":
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
let idCredential = generateCredentials(manager.rlnInstance)
|
||||
let idCredential = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredential, UserMessageLimit(20))
|
||||
@ -420,7 +372,7 @@ suite "Onchain group manager":
|
||||
|
||||
test "root queue should be updated correctly":
|
||||
const credentialCount = 12
|
||||
let credentials = generateCredentials(manager.rlnInstance, credentialCount)
|
||||
let credentials = generateCredentials(credentialCount)
|
||||
(waitFor manager.init()).isOkOr:
|
||||
raiseAssert $error
|
||||
|
||||
|
||||
@ -36,15 +36,11 @@ suite "Waku rln relay":
|
||||
test "key_gen Nim Wrappers":
|
||||
let merkleDepth: csize_t = 20
|
||||
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
# keysBufferPtr will hold the generated identity credential i.e., id trapdoor, nullifier, secret hash and commitment
|
||||
var keysBuffer: Buffer
|
||||
let
|
||||
keysBufferPtr = addr(keysBuffer)
|
||||
done = key_gen(rlnInstance.get(), keysBufferPtr)
|
||||
done = key_gen(keysBufferPtr, true)
|
||||
require:
|
||||
# check whether the keys are generated successfully
|
||||
done
|
||||
@ -56,12 +52,7 @@ suite "Waku rln relay":
|
||||
info "generated keys: ", generatedKeys
|
||||
|
||||
test "membership Key Generation":
|
||||
# create an RLN instance
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
let idCredentialsRes = membershipKeyGen(rlnInstance.get())
|
||||
let idCredentialsRes = membershipKeyGen()
|
||||
require:
|
||||
idCredentialsRes.isOk()
|
||||
|
||||
@ -79,61 +70,6 @@ suite "Waku rln relay":
|
||||
|
||||
info "the generated identity credential: ", idCredential
|
||||
|
||||
test "setMetadata rln utils":
|
||||
# create an RLN instance which also includes an empty Merkle tree
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
require:
|
||||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
check:
|
||||
rln
|
||||
.setMetadata(
|
||||
RlnMetadata(
|
||||
lastProcessedBlock: 128,
|
||||
chainId: 1155511'u256,
|
||||
contractAddress: "0x9c09146844c1326c2dbc41c451766c7138f88155",
|
||||
)
|
||||
)
|
||||
.isOk()
|
||||
|
||||
test "getMetadata rln utils":
|
||||
# create an RLN instance which also includes an empty Merkle tree
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
require:
|
||||
rlnInstance.isOk()
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
require:
|
||||
rln
|
||||
.setMetadata(
|
||||
RlnMetadata(
|
||||
lastProcessedBlock: 128,
|
||||
chainId: 1155511'u256,
|
||||
contractAddress: "0x9c09146844c1326c2dbc41c451766c7138f88155",
|
||||
)
|
||||
)
|
||||
.isOk()
|
||||
|
||||
let metadataOpt = rln.getMetadata().valueOr:
|
||||
raiseAssert $error
|
||||
|
||||
assert metadataOpt.isSome(), "metadata is not set"
|
||||
let metadata = metadataOpt.get()
|
||||
check:
|
||||
metadata.lastProcessedBlock == 128
|
||||
metadata.chainId == 1155511'u256
|
||||
metadata.contractAddress == "0x9c09146844c1326c2dbc41c451766c7138f88155"
|
||||
|
||||
test "getMetadata: empty rln metadata":
|
||||
# create an RLN instance which also includes an empty Merkle tree
|
||||
let rln = createRLNInstanceWrapper().valueOr:
|
||||
raiseAssert $error
|
||||
let metadata = rln.getMetadata().valueOr:
|
||||
raiseAssert $error
|
||||
|
||||
check:
|
||||
metadata.isNone()
|
||||
|
||||
test "hash Nim Wrappers":
|
||||
# create an RLN instance
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
@ -149,7 +85,7 @@ suite "Waku rln relay":
|
||||
# prepare other inputs to the hash function
|
||||
let outputBuffer = default(Buffer)
|
||||
|
||||
let hashSuccess = sha256(unsafeAddr hashInputBuffer, unsafeAddr outputBuffer)
|
||||
let hashSuccess = sha256(unsafeAddr hashInputBuffer, unsafeAddr outputBuffer, true)
|
||||
require:
|
||||
hashSuccess
|
||||
let outputArr = cast[ptr array[32, byte]](outputBuffer.`ptr`)[]
|
||||
@ -348,7 +284,7 @@ suite "Waku rln relay":
|
||||
raiseAssert $error
|
||||
|
||||
let manager = cast[OnchainGroupManager](wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -405,7 +341,7 @@ suite "Waku rln relay":
|
||||
raiseAssert $error
|
||||
|
||||
let manager = cast[OnchainGroupManager](wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -455,7 +391,7 @@ suite "Waku rln relay":
|
||||
raiseAssert "failed to create waku rln relay: " & $error
|
||||
|
||||
let manager1 = cast[OnchainGroupManager](wakuRlnRelay1.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
@ -469,7 +405,7 @@ suite "Waku rln relay":
|
||||
raiseAssert "failed to create waku rln relay: " & $error
|
||||
|
||||
let manager2 = cast[OnchainGroupManager](wakuRlnRelay2.groupManager)
|
||||
let idCredentials2 = generateCredentials(manager2.rlnInstance)
|
||||
let idCredentials2 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager2.register(idCredentials2, UserMessageLimit(20))
|
||||
@ -502,15 +438,7 @@ suite "Waku rln relay":
|
||||
msgValidate2 == MessageValidationResult.Valid
|
||||
|
||||
test "toIDCommitment and toUInt256":
|
||||
# create an instance of rln
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
let rln = rlnInstance.get()
|
||||
|
||||
# create an idendity credential
|
||||
let idCredentialRes = rln.membershipKeyGen()
|
||||
let idCredentialRes = membershipKeyGen()
|
||||
require:
|
||||
idCredentialRes.isOk()
|
||||
|
||||
@ -526,12 +454,7 @@ suite "Waku rln relay":
|
||||
idCredential.idCommitment == idCommitment
|
||||
|
||||
test "Read/Write RLN credentials":
|
||||
# create an RLN instance
|
||||
let rlnInstance = createRLNInstanceWrapper()
|
||||
require:
|
||||
rlnInstance.isOk()
|
||||
|
||||
let idCredentialRes = membershipKeyGen(rlnInstance.get())
|
||||
let idCredentialRes = membershipKeyGen()
|
||||
require:
|
||||
idCredentialRes.isOk()
|
||||
|
||||
|
||||
@ -63,7 +63,7 @@ procSuite "WakuNode - RLN relay":
|
||||
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
@ -180,7 +180,7 @@ procSuite "WakuNode - RLN relay":
|
||||
await node.mountRlnRelay(wakuRlnConfig)
|
||||
await node.start()
|
||||
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -299,7 +299,7 @@ procSuite "WakuNode - RLN relay":
|
||||
await node1.start()
|
||||
|
||||
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
@ -416,7 +416,7 @@ procSuite "WakuNode - RLN relay":
|
||||
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
@ -583,7 +583,7 @@ procSuite "WakuNode - RLN relay":
|
||||
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager1 = cast[OnchainGroupManager](node1.wakuRlnRelay.groupManager)
|
||||
let idCredentials1 = generateCredentials(manager1.rlnInstance)
|
||||
let idCredentials1 = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager1.register(idCredentials1, UserMessageLimit(20))
|
||||
|
||||
@ -44,8 +44,8 @@ func strip0xPrefix(s: string): string =
|
||||
else:
|
||||
s
|
||||
|
||||
proc generateCredentials*(rlnInstance: ptr RLN): IdentityCredential =
|
||||
let credRes = membershipKeyGen(rlnInstance)
|
||||
proc generateCredentials*(): IdentityCredential =
|
||||
let credRes = membershipKeyGen()
|
||||
return credRes.get()
|
||||
|
||||
proc getRateCommitment*(
|
||||
@ -55,10 +55,10 @@ proc getRateCommitment*(
|
||||
idCommitment: idCredential.idCommitment, userMessageLimit: userMessageLimit
|
||||
).toLeaf()
|
||||
|
||||
proc generateCredentials*(rlnInstance: ptr RLN, n: int): seq[IdentityCredential] =
|
||||
proc generateCredentials*(n: int): seq[IdentityCredential] =
|
||||
var credentials: seq[IdentityCredential]
|
||||
for i in 0 ..< n:
|
||||
credentials.add(generateCredentials(rlnInstance))
|
||||
credentials.add(generateCredentials())
|
||||
return credentials
|
||||
|
||||
proc getContractAddressFromDeployScriptOutput(output: string): Result[string, string] =
|
||||
|
||||
@ -265,7 +265,7 @@ suite "Waku v2 Rest API - Relay":
|
||||
await node.start()
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -516,7 +516,7 @@ suite "Waku v2 Rest API - Relay":
|
||||
await node.start()
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -588,7 +588,7 @@ suite "Waku v2 Rest API - Relay":
|
||||
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -650,7 +650,7 @@ suite "Waku v2 Rest API - Relay":
|
||||
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
@ -725,7 +725,7 @@ suite "Waku v2 Rest API - Relay":
|
||||
|
||||
# Registration is mandatory before sending messages with rln-relay
|
||||
let manager = cast[OnchainGroupManager](node.wakuRlnRelay.groupManager)
|
||||
let idCredentials = generateCredentials(manager.rlnInstance)
|
||||
let idCredentials = generateCredentials()
|
||||
|
||||
try:
|
||||
waitFor manager.register(idCredentials, UserMessageLimit(20))
|
||||
|
||||
@ -30,16 +30,8 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) =
|
||||
# 1. load configuration
|
||||
trace "configuration", conf = $conf
|
||||
|
||||
# 2. initialize rlnInstance
|
||||
let rlnInstanceRes = createRLNInstance(d = 20)
|
||||
if rlnInstanceRes.isErr():
|
||||
error "failure while creating RLN instance", error = rlnInstanceRes.error
|
||||
quit(1)
|
||||
|
||||
let rlnInstance = rlnInstanceRes.get()
|
||||
|
||||
# 3. generate credentials
|
||||
let credentialRes = rlnInstance.membershipKeyGen()
|
||||
# 2. generate credentials
|
||||
let credentialRes = membershipKeyGen()
|
||||
if credentialRes.isErr():
|
||||
error "failure while generating credentials", error = credentialRes.error
|
||||
quit(1)
|
||||
@ -61,12 +53,11 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) =
|
||||
error "Unrecoverable error occurred", error = msg
|
||||
quit(QuitFailure)
|
||||
|
||||
# 4. initialize OnchainGroupManager
|
||||
# 3. initialize OnchainGroupManager
|
||||
let groupManager = OnchainGroupManager(
|
||||
ethClientUrls: conf.ethClientUrls,
|
||||
chainId: conf.chainId,
|
||||
ethContractAddress: conf.ethContractAddress,
|
||||
rlnInstance: rlnInstance,
|
||||
keystorePath: none(string),
|
||||
keystorePassword: none(string),
|
||||
ethPrivateKey: some(conf.ethPrivateKey),
|
||||
@ -82,7 +73,7 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) =
|
||||
error = getCurrentExceptionMsg()
|
||||
quit(1)
|
||||
|
||||
# 5. register on-chain
|
||||
# 4. register on-chain
|
||||
try:
|
||||
waitFor groupManager.register(credential, conf.userMessageLimit)
|
||||
except Exception, CatchableError:
|
||||
@ -98,7 +89,7 @@ proc doRlnKeystoreGenerator*(conf: RlnKeystoreGeneratorConf) =
|
||||
membershipIndex = groupManager.membershipIndex.get()
|
||||
info "Your user message limit is", userMessageLimit = conf.userMessageLimit
|
||||
|
||||
# 6. write to keystore
|
||||
# 5. write to keystore
|
||||
let keystoreCred = KeystoreMembership(
|
||||
membershipContract: MembershipContract(
|
||||
chainId: $groupManager.chainId, address: conf.ethContractAddress
|
||||
|
||||
2
vendor/zerokit
vendored
2
vendor/zerokit
vendored
@ -1 +1 @@
|
||||
Subproject commit dc0b31752c91e7b4fefc441cfa6a8210ad7dba7b
|
||||
Subproject commit a4bb3feb5054e6fd24827adf204493e6e173437b
|
||||
@ -144,25 +144,6 @@ proc fetchMaxMembershipRateLimit*(
|
||||
error "Failed to fetch max membership rate limit", error = getCurrentExceptionMsg()
|
||||
return err("Failed to fetch max membership rate limit: " & getCurrentExceptionMsg())
|
||||
|
||||
proc setMetadata*(
|
||||
g: OnchainGroupManager, lastProcessedBlock = none(BlockNumber)
|
||||
): GroupManagerResult[void] =
|
||||
let normalizedBlock = lastProcessedBlock.get(g.latestProcessedBlock)
|
||||
try:
|
||||
let metadataSetRes = g.rlnInstance.setMetadata(
|
||||
RlnMetadata(
|
||||
lastProcessedBlock: normalizedBlock.uint64,
|
||||
chainId: g.chainId,
|
||||
contractAddress: g.ethContractAddress,
|
||||
validRoots: g.validRoots.toSeq(),
|
||||
)
|
||||
)
|
||||
if metadataSetRes.isErr():
|
||||
return err("failed to persist rln metadata: " & metadataSetRes.error)
|
||||
except CatchableError:
|
||||
return err("failed to persist rln metadata: " & getCurrentExceptionMsg())
|
||||
return ok()
|
||||
|
||||
template initializedGuard(g: OnchainGroupManager): untyped =
|
||||
if not g.initialized:
|
||||
raise newException(CatchableError, "OnchainGroupManager is not initialized")
|
||||
@ -593,18 +574,6 @@ method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.}
|
||||
|
||||
g.idCredentials = some(keystoreCred.identityCredential)
|
||||
|
||||
let metadataGetOptRes = g.rlnInstance.getMetadata()
|
||||
if metadataGetOptRes.isErr():
|
||||
warn "could not initialize with persisted rln metadata"
|
||||
elif metadataGetOptRes.get().isSome():
|
||||
let metadata = metadataGetOptRes.get().get()
|
||||
if metadata.chainId != g.chainId:
|
||||
return err(
|
||||
fmt"chain id mismatch. persisted={metadata.chainId}, smart_contract_chainId={g.chainId}"
|
||||
)
|
||||
if metadata.contractAddress != g.ethContractAddress.toLower():
|
||||
return err("persisted data: contract address mismatch")
|
||||
|
||||
let maxMembershipRateLimitRes = await g.fetchMaxMembershipRateLimit()
|
||||
let maxMembershipRateLimit = maxMembershipRateLimitRes.valueOr:
|
||||
return err("failed to fetch max membership rate limit: " & error)
|
||||
@ -631,9 +600,6 @@ method stop*(g: OnchainGroupManager): Future[void] {.async, gcsafe.} =
|
||||
if g.ethRpc.isSome():
|
||||
g.ethRpc.get().ondisconnect = nil
|
||||
await g.ethRpc.get().close()
|
||||
let flushed = g.rlnInstance.flush()
|
||||
if not flushed:
|
||||
error "failed to flush to the tree db"
|
||||
|
||||
g.initialized = false
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ proc toBuffer*(x: openArray[byte]): Buffer =
|
||||
|
||||
#-------------------------------- zkSNARKs operations -----------------------------------------
|
||||
proc key_gen*(
|
||||
ctx: ptr RLN, output_buffer: ptr Buffer
|
||||
output_buffer: ptr Buffer, is_little_endian: bool
|
||||
): 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> |
|
||||
@ -32,7 +32,7 @@ proc key_gen*(
|
||||
## 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
|
||||
input_buffer: ptr Buffer, output_buffer: ptr Buffer, is_little_endian: bool
|
||||
): 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
|
||||
@ -40,6 +40,7 @@ proc seeded_key_gen*(
|
||||
## The input seed provided by the user is hashed using Keccak256 before being passed to ChaCha20 as seed.
|
||||
## identity secret hash is the poseidon hash of [identity_trapdoor, identity_nullifier]
|
||||
## id commitment is the poseidon hash of the identity secret hash
|
||||
# use_little_endian: if true, uses big or little endian for serialization (default: true)
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
proc generate_proof*(
|
||||
@ -120,39 +121,34 @@ proc zk_verify*(
|
||||
## the verification of the zk proof is available in proof_is_valid_ptr, where a value of true indicates success and false a failure
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
#----------------------------------------------------------------------------------------------
|
||||
|
||||
#-------------------------------- Common procedures -------------------------------------------
|
||||
# stateful version
|
||||
proc new_circuit*(
|
||||
tree_height: uint, input_buffer: ptr Buffer, ctx: ptr (ptr RLN)
|
||||
tree_depth: uint, input_buffer: ptr Buffer, ctx: ptr (ptr RLN)
|
||||
): bool {.importc: "new".}
|
||||
|
||||
## creates an instance of rln object as defined by the zerokit RLN lib
|
||||
## tree_height represent the depth of the Merkle tree
|
||||
## input_buffer contains a serialization of the path where the circuit resources can be found (.r1cs, .wasm, .zkey and optionally the verification_key.json)
|
||||
## ctx holds the final created rln object
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
# stateless version
|
||||
proc new_circuit*(ctx: ptr (ptr RLN)): bool {.importc: "new".}
|
||||
|
||||
proc new_circuit_from_data*(
|
||||
tree_height: uint,
|
||||
circom_buffer: ptr Buffer,
|
||||
zkey_buffer: ptr Buffer,
|
||||
vk_buffer: ptr Buffer,
|
||||
ctx: ptr (ptr RLN),
|
||||
zkey_buffer: ptr Buffer, graph_buffer: ptr Buffer, ctx: ptr (ptr RLN)
|
||||
): bool {.importc: "new_with_params".}
|
||||
|
||||
## creates an instance of rln object as defined by the zerokit RLN lib by passing the required inputs as byte arrays
|
||||
## tree_height represent the depth of the Merkle tree
|
||||
## circom_buffer contains the bytes read from the Circom .wasm circuit
|
||||
## zkey_buffer contains the bytes read from the .zkey proving key
|
||||
## vk_buffer contains the bytes read from the verification_key.json
|
||||
## graph_buffer contains the bytes read from the graph data file
|
||||
## ctx holds the final created rln object
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
#-------------------------------- Hashing utils -------------------------------------------
|
||||
|
||||
proc sha256*(
|
||||
input_buffer: ptr Buffer, output_buffer: ptr Buffer
|
||||
input_buffer: ptr Buffer, output_buffer: ptr Buffer, is_little_endian: bool
|
||||
): bool {.importc: "hash".}
|
||||
|
||||
## it hashes (sha256) the plain text supplied in inputs_buffer and then maps it to a field element
|
||||
@ -162,7 +158,7 @@ proc sha256*(
|
||||
## the output_buffer contains 32 bytes hash output
|
||||
|
||||
proc poseidon*(
|
||||
input_buffer: ptr Buffer, output_buffer: ptr Buffer
|
||||
input_buffer: ptr Buffer, output_buffer: ptr Buffer, is_little_endian: bool
|
||||
): bool {.importc: "poseidon_hash".}
|
||||
|
||||
## it hashes (poseidon) the plain text supplied in inputs_buffer
|
||||
@ -170,27 +166,3 @@ proc poseidon*(
|
||||
## inputs_buffer holds the hash input as a byte seq
|
||||
## the hash output is generated and populated inside output_buffer
|
||||
## the output_buffer contains 32 bytes hash output
|
||||
|
||||
#-------------------------------- Persistent Metadata utils -------------------------------------------
|
||||
|
||||
proc set_metadata*(
|
||||
ctx: ptr RLN, input_buffer: ptr Buffer
|
||||
): bool {.importc: "set_metadata".}
|
||||
|
||||
## sets the metadata stored by ctx to the value passed by input_buffer
|
||||
## the input_buffer holds a serialized representation of the metadata (format to be defined)
|
||||
## input_buffer holds the metadata as a byte seq
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
proc get_metadata*(
|
||||
ctx: ptr RLN, output_buffer: ptr Buffer
|
||||
): bool {.importc: "get_metadata".}
|
||||
|
||||
## gets the metadata stored by ctx and populates the passed pointer output_buffer with it
|
||||
## the output_buffer holds the metadata as a byte seq
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
|
||||
proc flush*(ctx: ptr RLN): bool {.importc: "flush".}
|
||||
## flushes the write buffer to the database
|
||||
## the return bool value indicates the success or failure of the operation
|
||||
## This allows more robust and graceful handling of the database connection
|
||||
|
||||
@ -14,7 +14,7 @@ import ../../waku_core, ../../waku_keystore
|
||||
logScope:
|
||||
topics = "waku rln_relay ffi"
|
||||
|
||||
proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[IdentityCredential] =
|
||||
proc membershipKeyGen*(): 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
|
||||
|
||||
@ -22,7 +22,7 @@ proc membershipKeyGen*(ctxPtr: ptr RLN): RlnRelayResult[IdentityCredential] =
|
||||
var
|
||||
keysBuffer: Buffer
|
||||
keysBufferPtr = addr(keysBuffer)
|
||||
done = key_gen(ctxPtr, keysBufferPtr)
|
||||
done = key_gen(keysBufferPtr, true)
|
||||
|
||||
# check whether the keys are generated successfully
|
||||
if (done == false):
|
||||
@ -80,14 +80,13 @@ proc `%`(c: RlnConfig): JsonNode =
|
||||
}
|
||||
return %[("resources_folder", %c.resources_folder), ("tree_config", %tree_config)]
|
||||
|
||||
proc createRLNInstanceLocal(d = MerkleTreeDepth): RLNResult =
|
||||
proc createRLNInstanceLocal(): RLNResult =
|
||||
## generates an instance of RLN
|
||||
## An RLN instance supports both zkSNARKs logics and Merkle tree data structure and operations
|
||||
## d indicates the depth of Merkle tree
|
||||
## Returns an error if the instance creation fails
|
||||
|
||||
let rln_config = RlnConfig(
|
||||
resources_folder: "tree_height_" & $d & "/",
|
||||
resources_folder: "tree_height_/",
|
||||
tree_config: RlnTreeConfig(
|
||||
cache_capacity: 15_000,
|
||||
mode: "high_throughput",
|
||||
@ -100,7 +99,7 @@ proc createRLNInstanceLocal(d = MerkleTreeDepth): RLNResult =
|
||||
|
||||
var
|
||||
rlnInstance: ptr RLN
|
||||
merkleDepth: csize_t = uint(d)
|
||||
merkleDepth: csize_t = uint(20)
|
||||
configBuffer =
|
||||
serialized_rln_config.toOpenArrayByte(0, serialized_rln_config.high).toBuffer()
|
||||
|
||||
@ -112,12 +111,12 @@ proc createRLNInstanceLocal(d = MerkleTreeDepth): RLNResult =
|
||||
return err("error in parameters generation")
|
||||
return ok(rlnInstance)
|
||||
|
||||
proc createRLNInstance*(d = MerkleTreeDepth): RLNResult =
|
||||
proc createRLNInstance*(): RLNResult =
|
||||
## Wraps the rln instance creation for metrics
|
||||
## Returns an error if the instance creation fails
|
||||
var res: RLNResult
|
||||
waku_rln_instance_creation_duration_seconds.nanosecondTime:
|
||||
res = createRLNInstanceLocal(d)
|
||||
res = createRLNInstanceLocal()
|
||||
return res
|
||||
|
||||
proc sha256*(data: openArray[byte]): RlnRelayResult[MerkleNode] =
|
||||
@ -128,7 +127,7 @@ proc sha256*(data: openArray[byte]): RlnRelayResult[MerkleNode] =
|
||||
outputBuffer: Buffer # will holds the hash output
|
||||
|
||||
trace "sha256 hash input buffer length", bufflen = hashInputBuffer.len
|
||||
let hashSuccess = sha256(addr hashInputBuffer, addr outputBuffer)
|
||||
let hashSuccess = sha256(addr hashInputBuffer, addr outputBuffer, true)
|
||||
|
||||
# check whether the hash call is done successfully
|
||||
if not hashSuccess:
|
||||
@ -145,7 +144,7 @@ proc poseidon*(data: seq[seq[byte]]): RlnRelayResult[array[32, byte]] =
|
||||
hashInputBuffer = inputBytes.toBuffer()
|
||||
outputBuffer: Buffer # will holds the hash output
|
||||
|
||||
let hashSuccess = poseidon(addr hashInputBuffer, addr outputBuffer)
|
||||
let hashSuccess = poseidon(addr hashInputBuffer, addr outputBuffer, true)
|
||||
|
||||
# check whether the hash call is done successfully
|
||||
if not hashSuccess:
|
||||
@ -192,114 +191,3 @@ proc extractMetadata*(proof: RateLimitProof): RlnRelayResult[ProofMetadata] =
|
||||
externalNullifier: externalNullifier,
|
||||
)
|
||||
)
|
||||
|
||||
type RlnMetadata* = object
|
||||
lastProcessedBlock*: uint64
|
||||
chainId*: UInt256
|
||||
contractAddress*: string
|
||||
validRoots*: seq[MerkleNode]
|
||||
|
||||
proc serialize(metadata: RlnMetadata): seq[byte] =
|
||||
## serializes the metadata
|
||||
## returns the serialized metadata
|
||||
return concat(
|
||||
@(metadata.lastProcessedBlock.toBytes()),
|
||||
@(metadata.chainId.toBytes(Endianness.littleEndian)[0 .. 7]),
|
||||
@(hexToSeqByte(toLower(metadata.contractAddress))),
|
||||
@(uint64(metadata.validRoots.len()).toBytes()),
|
||||
@(serialize(metadata.validRoots)),
|
||||
)
|
||||
|
||||
type MerkleNodeSeq = seq[MerkleNode]
|
||||
|
||||
proc deserialize(T: type MerkleNodeSeq, merkleNodeByteSeq: seq[byte]): T =
|
||||
## deserializes a byte seq to a seq of MerkleNodes
|
||||
## the order of serialization is |merkle_node_len<8>|merkle_node[len]|
|
||||
|
||||
var roots = newSeq[MerkleNode]()
|
||||
let len = uint64.fromBytes(merkleNodeByteSeq[0 .. 7], Endianness.littleEndian)
|
||||
trace "length of valid roots", len
|
||||
for i in 0'u64 ..< len:
|
||||
# convert seq[byte] to array[32, byte]
|
||||
let fromByte = 8 + i * 32
|
||||
let toByte = fromByte + 31
|
||||
let rawRoot = merkleNodeByteSeq[fromByte .. toByte]
|
||||
trace "raw root", rawRoot = rawRoot
|
||||
var root: MerkleNode
|
||||
discard root.copyFrom(rawRoot)
|
||||
roots.add(root)
|
||||
return roots
|
||||
|
||||
proc setMetadata*(rlnInstance: ptr RLN, metadata: RlnMetadata): RlnRelayResult[void] =
|
||||
## sets the metadata of the RLN instance
|
||||
## returns an error if the metadata could not be set
|
||||
## returns void if the metadata is set successfully
|
||||
|
||||
# serialize the metadata
|
||||
let metadataBytes = serialize(metadata)
|
||||
trace "setting metadata",
|
||||
metadata = metadata, metadataBytes = metadataBytes, len = metadataBytes.len
|
||||
var metadataBuffer = metadataBytes.toBuffer()
|
||||
let metadataBufferPtr = addr metadataBuffer
|
||||
|
||||
# set the metadata
|
||||
let metadataSet = set_metadata(rlnInstance, metadataBufferPtr)
|
||||
|
||||
if not metadataSet:
|
||||
return err("could not set the metadata")
|
||||
return ok()
|
||||
|
||||
proc getMetadata*(rlnInstance: ptr RLN): RlnRelayResult[Option[RlnMetadata]] =
|
||||
## gets the metadata of the RLN instance
|
||||
## returns an error if the metadata could not be retrieved
|
||||
## returns the metadata if the metadata is retrieved successfully
|
||||
|
||||
# read the metadata
|
||||
var
|
||||
metadata {.noinit.}: Buffer = Buffer()
|
||||
metadataPtr = addr(metadata)
|
||||
getMetadataSuccessful = get_metadata(rlnInstance, metadataPtr)
|
||||
if not getMetadataSuccessful:
|
||||
return err("could not get the metadata")
|
||||
trace "metadata length", metadataLen = metadata.len
|
||||
|
||||
if metadata.len == 0:
|
||||
return ok(none(RlnMetadata))
|
||||
|
||||
let
|
||||
lastProcessedBlockOffset = 0
|
||||
chainIdOffset = lastProcessedBlockOffset + 8
|
||||
contractAddressOffset = chainIdOffset + 8
|
||||
validRootsOffset = contractAddressOffset + 20
|
||||
|
||||
var
|
||||
lastProcessedBlock: uint64
|
||||
chainId: UInt256
|
||||
contractAddress: string
|
||||
validRoots: MerkleNodeSeq
|
||||
|
||||
# 8 + 8 + 20 + 8 + (5*32) = 204
|
||||
var metadataBytes = cast[ptr array[204, byte]](metadata.`ptr`)[]
|
||||
trace "received metadata bytes",
|
||||
metadataBytes = metadataBytes, len = metadataBytes.len
|
||||
|
||||
lastProcessedBlock =
|
||||
uint64.fromBytes(metadataBytes[lastProcessedBlockOffset .. chainIdOffset - 1])
|
||||
chainId = UInt256.fromBytes(
|
||||
metadataBytes[chainIdOffset .. contractAddressOffset - 1], Endianness.littleEndian
|
||||
)
|
||||
contractAddress =
|
||||
byteutils.toHex(metadataBytes[contractAddressOffset .. validRootsOffset - 1])
|
||||
let validRootsBytes = metadataBytes[validRootsOffset .. metadataBytes.high]
|
||||
validRoots = MerkleNodeSeq.deserialize(validRootsBytes)
|
||||
|
||||
return ok(
|
||||
some(
|
||||
RlnMetadata(
|
||||
lastProcessedBlock: lastProcessedBlock,
|
||||
chainId: chainId,
|
||||
contractAddress: "0x" & contractAddress,
|
||||
validRoots: validRoots,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user