Merge f133a17bd16f01e78b00cfc5291267c8abdbfac5 into 77cb8a6c7a199b7823e5149bb72f8ce384883b8f

This commit is contained in:
Tanya S 2026-07-14 09:28:24 +00:00 committed by GitHub
commit ff7c6d0e5b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 153 additions and 134 deletions

View File

@ -48,6 +48,9 @@ type
proofPathRefreshInFlightFut*: Future[seq[byte]]
lastRootsRefreshMoment*: Moment
rootsRefreshInFlightFut*: Future[void]
# Pacing for retried on-chain transaction calls; a zero value is replaced
# with the RetryStrategy defaults during init.
retryStrategy*: RetryStrategy
# The below code is not working with the latest web3 version due to chainId being null (specifically on linea-sepolia)
# TODO: find better solution than this custom sendEthCallWithoutParams call
@ -358,7 +361,7 @@ method register*(
let gasPrice = (
await retryWrapper(
RetryStrategy.new(),
g.retryStrategy,
"Failed to get gas price",
proc(): Future[int] {.async.} =
let fetchedGasPrice = uint64(await ethRpc.provider.eth_gasPrice())
@ -383,7 +386,7 @@ method register*(
idCommitmentsToErase = idCommitmentsToErase
let txHash = (
await retryWrapper(
RetryStrategy.new(),
g.retryStrategy,
"Failed to register the member",
proc(): Future[TxHash] {.async.} =
return await wakuRlnContract
@ -396,7 +399,7 @@ method register*(
# wait for the transaction to be mined and get the receipt
let tsReceipt = (
await retryWrapper(
RetryStrategy.new(),
g.retryStrategy,
"Failed to get the transaction receipt",
proc(): Future[ReceiptObject] {.async.} =
let r = await ethRpc.provider.eth_getTransactionReceipt(txHash)
@ -610,6 +613,9 @@ proc establishConnection(
return ok(ethRpc)
method init*(g: OnchainGroupManager): Future[GroupManagerResult[void]] {.async.} =
if g.retryStrategy.retryCount == 0:
g.retryStrategy = RetryStrategy.new()
# check if the Ethereum client is reachable
let ethRpc: Web3 = (await establishConnection(g)).valueOr:
return err("failed to connect to Ethereum clients: " & $error)

View File

@ -136,7 +136,7 @@ suite "RLN Proofs as a Lightpush Service":
check (await server.mountLegacyLightPush()).isOk()
client.mountLegacyLightPushClient()
let manager1 = cast[OnchainGroupManager](server.rln.groupManager)
let manager1 = cast[OnchainGroupManager](server.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:

View File

@ -132,7 +132,7 @@ suite "RLN Proofs as a Lightpush Service":
check (await server.mountLightPush()).isOk()
client.mountLightPushClient()
let manager1 = cast[OnchainGroupManager](server.rln.groupManager)
let manager1 = cast[OnchainGroupManager](server.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:

View File

@ -29,17 +29,16 @@ import
../testlib/wakucore,
./utils_onchain
# Anvil is started once for the whole suite. The first test runs the full
# `setupOnchainGroupManager` flow (fund a fresh account + mint tokens + approve
# allowance) and then takes a baseline snapshot capturing that post-setup chain
# state. Subsequent tests revert to the baseline (restoring the funded account)
# and build a bare manager pointing at the same key. evm_revert consumes the snapshot
# ID, so we re-snapshot after every revert. Cleanup is registered via
# Anvil is started once for the whole suite from the cached state file, which
# already contains the deployed RLN contracts and the funded, token-approved
# FUNDED_TEST_PRIVATE_KEY account — no per-run on-chain setup is needed. A
# baseline snapshot is taken right after startup; every test reverts to it and
# builds a bare manager pointing at the baked-in key. evm_revert consumes the
# snapshot ID, so we re-snapshot after every revert. Cleanup is registered via
# addExitProc so anvil is terminated when the test binary exits.
var sharedAnvilProc: Process
var anvilStarted: bool = false
var baselineSnapshotId: string
var fundedPrivateKey: string
suite "Onchain group manager":
var manager {.threadVar.}: OnchainGroupManager
@ -53,13 +52,10 @@ suite "Onchain group manager":
if not sharedAnvilProc.isNil:
stopAnvil(sharedAnvilProc)
)
manager = waitFor setupOnchainGroupManager(deployContracts = false)
fundedPrivateKey = manager.ethPrivateKey.get()
baselineSnapshotId = waitFor takeEvmSnapshot()
else:
discard waitFor revertEvmSnapshot(baselineSnapshotId)
baselineSnapshotId = waitFor takeEvmSnapshot()
manager = buildOnchainGroupManager(fundedPrivateKey)
baselineSnapshotId = waitFor takeEvmSnapshot()
manager = buildOnchainGroupManager(FUNDED_TEST_PRIVATE_KEY)
test "should initialize successfully":
(waitFor manager.init()).isOkOr:

View File

@ -230,7 +230,7 @@ suite "Waku rln relay":
rln = (await Rln.new(wakuRlnConfig)).valueOr:
raiseAssert $error
let manager = cast[OnchainGroupManager](rln.groupManager)
let manager = cast[OnchainGroupManager](rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -286,7 +286,7 @@ suite "Waku rln relay":
rln = (await Rln.new(wakuRlnConfig)).valueOr:
raiseAssert $error
let manager = cast[OnchainGroupManager](rln.groupManager)
let manager = cast[OnchainGroupManager](rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -335,7 +335,8 @@ suite "Waku rln relay":
wakuRlnRelay1 = (await Rln.new(rlnConf1)).valueOr:
raiseAssert "failed to create waku rln relay: " & $error
let manager1 = cast[OnchainGroupManager](wakuRlnRelay1.groupManager)
let manager1 =
cast[OnchainGroupManager](wakuRlnRelay1.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -348,7 +349,8 @@ suite "Waku rln relay":
wakuRlnRelay2 = (await Rln.new(rlnConf2)).valueOr:
raiseAssert "failed to create waku rln relay: " & $error
let manager2 = cast[OnchainGroupManager](wakuRlnRelay2.groupManager)
let manager2 =
cast[OnchainGroupManager](wakuRlnRelay2.groupManager).withFastRetries()
let idCredentials2 = generateCredentials()
(waitFor manager2.register(idCredentials2, UserMessageLimit(20))).isOkOr:

View File

@ -57,7 +57,7 @@ procSuite "WakuNode - RLN relay":
await node1.start()
# Registration is mandatory before sending messages with rln-relay
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -80,7 +80,7 @@ procSuite "WakuNode - RLN relay":
await node2.setRlnValidator(wakuRlnConfig2)
await node2.start()
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager).withFastRetries()
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
@ -98,7 +98,7 @@ procSuite "WakuNode - RLN relay":
await node3.setRlnValidator(wakuRlnConfig3)
await node3.start()
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager).withFastRetries()
let rootUpdated3 = waitFor manager3.updateRoots()
info "Updated root for node3", rootUpdated3
@ -168,7 +168,7 @@ procSuite "WakuNode - RLN relay":
getWakuRlnConfig(manager = manager, index = MembershipIndex(1))
await node1.setRlnValidator(wakuRlnConfig1)
await node1.start()
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -185,7 +185,7 @@ procSuite "WakuNode - RLN relay":
getWakuRlnConfig(manager = manager, index = MembershipIndex(2))
await node2.setRlnValidator(wakuRlnConfig2)
await node2.start()
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager).withFastRetries()
let idCredentials2 = generateCredentials()
(waitFor manager2.register(idCredentials2, UserMessageLimit(20))).isOkOr:
@ -202,7 +202,7 @@ procSuite "WakuNode - RLN relay":
getWakuRlnConfig(manager = manager, index = MembershipIndex(3))
await node3.setRlnValidator(wakuRlnConfig3)
await node3.start()
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager).withFastRetries()
let idCredentials3 = generateCredentials()
(waitFor manager3.register(idCredentials3, UserMessageLimit(20))).isOkOr:
@ -319,7 +319,7 @@ procSuite "WakuNode - RLN relay":
await node1.setRlnValidator(wakuRlnConfig1)
await node1.start()
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -340,7 +340,7 @@ procSuite "WakuNode - RLN relay":
await node2.setRlnValidator(wakuRlnConfig2)
await node2.start()
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager).withFastRetries()
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
lockNewGlobalBrokerContext:
@ -356,7 +356,7 @@ procSuite "WakuNode - RLN relay":
await node3.setRlnValidator(wakuRlnConfig3)
await node3.start()
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager).withFastRetries()
let rootUpdated3 = waitFor manager3.updateRoots()
info "Updated root for node3", rootUpdated3
@ -431,7 +431,7 @@ procSuite "WakuNode - RLN relay":
await node1.start()
# Registration is mandatory before sending messages with rln-relay
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -454,7 +454,7 @@ procSuite "WakuNode - RLN relay":
await node2.start()
# Registration is mandatory before sending messages with rln-relay
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager).withFastRetries()
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2
lockNewGlobalBrokerContext:
@ -472,7 +472,7 @@ procSuite "WakuNode - RLN relay":
await node3.start()
# Registration is mandatory before sending messages with rln-relay
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager)
let manager3 = cast[OnchainGroupManager](node3.rln.groupManager).withFastRetries()
let rootUpdated3 = waitFor manager3.updateRoots()
info "Updated root for node3", rootUpdated3
@ -600,7 +600,7 @@ procSuite "WakuNode - RLN relay":
await node1.start()
# Registration is mandatory before sending messages with rln-relay
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager)
let manager1 = cast[OnchainGroupManager](node1.rln.groupManager).withFastRetries()
let idCredentials1 = generateCredentials()
(waitFor manager1.register(idCredentials1, UserMessageLimit(20))).isOkOr:
@ -619,7 +619,7 @@ procSuite "WakuNode - RLN relay":
await node2.start()
# Registration is mandatory before sending messages with rln-relay
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager)
let manager2 = cast[OnchainGroupManager](node2.rln.groupManager).withFastRetries()
let rootUpdated2 = waitFor manager2.updateRoots()
info "Updated root for node2", rootUpdated2

View File

@ -20,7 +20,13 @@ import
results
import
logos_delivery/waku/[rln, rln/protocol_types, rln/constants, rln/bindings],
logos_delivery/waku/[
rln,
rln/protocol_types,
rln/constants,
rln/bindings,
rln/group_manager/on_chain/retry_wrapper,
],
../testlib/common
const CHAIN_ID* = 1234'u256
@ -31,6 +37,26 @@ const DEFAULT_ANVIL_STATE_PATH* =
const TOKEN_ADDRESS* = "0x5FbDB2315678afecb367f032d93F642f64180aa3"
const WAKU_RLNV2_PROXY_ADDRESS* = "0x5fc8d32690cc91d4c39d9d3abcbd16989f875707"
# Private key of the account baked into DEFAULT_ANVIL_STATE_PATH. The state
# regeneration flow (test_rln_contract_deployment.nim) funds this exact account
# with ETH, mints test tokens to it and approves the RLN contract allowance, so
# tests that load the cached state can use it directly without any per-run
# on-chain setup. Using a fixed key also makes the deployed contract addresses
# deterministic across state regenerations.
const FUNDED_TEST_PRIVATE_KEY* =
"1111111111111111111111111111111111111111111111111111111111111111"
# Anvil mines instantly, so the multi-second production retry delay only adds
# dead time when polling for transaction receipts.
const FastRetryStrategy = RetryStrategy(retryDelay: 100.millis, retryCount: 15)
proc withFastRetries*(m: OnchainGroupManager): OnchainGroupManager =
## Applies test retry pacing to a manager built outside these helpers, such as
## the node-internal manager created during RLN mount. register() reads the
## strategy at call time, so setting it after init() is effective.
m.retryStrategy = FastRetryStrategy
return m
proc generateCredentials*(): IdentityCredential =
let credRes = membershipKeyGen()
return credRes.get()
@ -624,10 +650,17 @@ proc stopAnvil*(runAnvil: Process) {.used.} =
try:
when not defined(windows):
discard execCmdEx(fmt"kill -TERM {anvilPID}")
# Give Anvil time to dump state on graceful shutdown before escalating to KILL.
sleep(200)
let checkResult = execCmdEx(fmt"kill -0 {anvilPID} 2>/dev/null")
if checkResult.exitCode == 0:
# Give Anvil time to dump state on graceful shutdown before escalating to
# KILL; killing too early truncates the dump and corrupts the state file.
# Poll via osproc `running` (which reaps the child) rather than `kill -0`,
# since the latter also succeeds for an exited-but-unreaped zombie.
const gracefulExitTimeoutMs = 10_000
const pollIntervalMs = 100
var elapsed = 0
while runAnvil.running and elapsed < gracefulExitTimeoutMs:
sleep(pollIntervalMs)
elapsed += pollIntervalMs
if runAnvil.running:
warn "Anvil process still running after TERM signal, sending KILL",
anvilPID = anvilPID
discard execCmdEx(fmt"kill -9 {anvilPID}")
@ -639,26 +672,55 @@ proc stopAnvil*(runAnvil: Process) {.used.} =
except Exception as e:
error "Error stopping Anvil daemon", anvilPID = anvilPID, error = e.msg
proc buildOnchainGroupManager*(
privateKey: string = FUNDED_TEST_PRIVATE_KEY, ethClientUrl: string = EthClient
): OnchainGroupManager =
## Constructs an OnchainGroupManager pointing at the cached RLN proxy contract
## using the supplied private key. No on-chain work happens here — the caller
## is expected to run Anvil from a state where this key already owns a funded,
## token-approved account (the cached DEFAULT_ANVIL_STATE_PATH state provides
## this for FUNDED_TEST_PRIVATE_KEY). Each call returns a fresh RLN instance.
let rlnInstanceRes = createRlnInstance()
check:
rlnInstanceRes.isOk()
return OnchainGroupManager(
ethClientUrls: @[ethClientUrl],
ethContractAddress: WAKU_RLNV2_PROXY_ADDRESS,
chainId: CHAIN_ID,
ethPrivateKey: some(privateKey),
rlnInstance: rlnInstanceRes.get(),
retryStrategy: FastRetryStrategy,
onFatalErrorAction: proc(errStr: string) =
raiseAssert errStr
,
)
proc setupOnchainGroupManager*(
ethClientUrl: string = EthClient,
amountEth: UInt256 = 10.u256,
deployContracts: bool = true,
): Future[OnchainGroupManager] {.async.} =
## Setup an onchain group manager for testing
## If deployContracts is false, it will assume that the Anvil testnet already has the required contracts deployed, this significantly speeds up test runs.
## To run Anvil with a cached state file containing pre-deployed contracts, see runAnvil documentation.
##
## If deployContracts is false, it assumes the Anvil testnet was started from
## the cached state file (DEFAULT_ANVIL_STATE_PATH), which already contains the
## deployed contracts and the funded, token-approved FUNDED_TEST_PRIVATE_KEY
## account — no on-chain setup happens at all.
##
## To generate/update the cached state file:
## 1. Call runAnvil with stateFile and dumpStateOnExit=true
## 2. Run setupOnchainGroupManager with deployContracts=true to deploy contracts
## (this funds/mints/approves FUNDED_TEST_PRIVATE_KEY, baking it into state)
## 3. The state will be saved to the specified file when anvil exits
## 4. Commit this file to git
##
##
## To use cached state:
## 1. Call runAnvil with stateFile and dumpStateOnExit=false
## 2. Anvil loads state in read-only mode (won't overwrite the cached file)
## 3. Call setupOnchainGroupManager with deployContracts=false
## 4. Tests run fast using pre-deployed contracts
if not deployContracts:
return buildOnchainGroupManager(FUNDED_TEST_PRIVATE_KEY, ethClientUrl)
let rlnInstanceRes = createRlnInstance()
check:
rlnInstanceRes.isOk()
@ -669,76 +731,50 @@ proc setupOnchainGroupManager*(
let accounts = await web3.provider.eth_accounts()
web3.defaultAccount = accounts[1]
var privateKey: keys.PrivateKey
var acc: Address
var testTokenAddress: Address
var contractAddress: Address
debug "Performing Token and RLN contracts deployment"
let privateKey = keys.PrivateKey.fromHex(FUNDED_TEST_PRIVATE_KEY).valueOr:
assert false, "invalid FUNDED_TEST_PRIVATE_KEY: " & $error
return
let acc = Address(toCanonicalAddress(privateKey.toPublicKey()))
if not deployContracts:
debug "Using contract addresses from constants"
discard await sendEthTransfer(
web3, web3.defaultAccount, acc, ethToWei(1000.u256), some(0.u256)
)
testTokenAddress = Address(hexToByteArray[20](TOKEN_ADDRESS))
contractAddress = Address(hexToByteArray[20](WAKU_RLNV2_PROXY_ADDRESS))
let testTokenAddress = (await deployTestToken(privateKey, acc, web3)).valueOr:
assert false, "Failed to deploy test token contract: " & $error
return
(privateKey, acc) = createEthAccount(web3)
await sendMintCall(
web3, web3.defaultAccount, testTokenAddress, acc, ethToWei(1000.u256), some(0.u256)
)
discard await sendEthTransfer(web3, web3.defaultAccount, acc, ethToWei(1000.u256))
let contractAddress = (await executeForgeContractDeployScripts(privateKey, acc, web3)).valueOr:
assert false, "Failed to deploy RLN contract: " & $error
return
await sendMintCall(
web3, web3.defaultAccount, testTokenAddress, acc, ethToWei(1000.u256)
)
# `executeForgeContractDeployScripts` shells out to `forge` via blocking
# `execCmdEx` calls (many seconds). While those run the chronos event loop
# is frozen and the existing web3 HTTP connection to Anvil rots; the next
# eth_call fails with "Not connected". Reconnect before continuing.
try:
await web3.close()
except CatchableError:
discard
web3 = await newWeb3(ethClientUrl)
web3.defaultAccount = accounts[1]
let tokenApprovalResult = await approveTokenAllowanceAndVerify(
web3, acc, privateKey, testTokenAddress, contractAddress, ethToWei(2000.u256)
)
assert tokenApprovalResult.isOk(), tokenApprovalResult.error
else:
debug "Performing Token and RLN contracts deployment"
(privateKey, acc) = createEthAccount(web3)
let tokenApprovalResult = await approveTokenAllowanceAndVerify(
web3,
acc,
privateKey,
testTokenAddress,
contractAddress,
ethToWei(2000.u256),
some(0.u256),
)
discard await sendEthTransfer(
web3, web3.defaultAccount, acc, ethToWei(1000.u256), some(0.u256)
)
testTokenAddress = (await deployTestToken(privateKey, acc, web3)).valueOr:
assert false, "Failed to deploy test token contract: " & $error
return
await sendMintCall(
web3,
web3.defaultAccount,
testTokenAddress,
acc,
ethToWei(1000.u256),
some(0.u256),
)
contractAddress = (await executeForgeContractDeployScripts(privateKey, acc, web3)).valueOr:
assert false, "Failed to deploy RLN contract: " & $error
return
# `executeForgeContractDeployScripts` shells out to `forge` via blocking
# `execCmdEx` calls (many seconds). While those run the chronos event loop
# is frozen and the existing web3 HTTP connection to Anvil rots; the next
# eth_call fails with "Not connected". Reconnect before continuing.
try:
await web3.close()
except CatchableError:
discard
web3 = await newWeb3(ethClientUrl)
web3.defaultAccount = accounts[1]
let tokenApprovalResult = await approveTokenAllowanceAndVerify(
web3,
acc,
privateKey,
testTokenAddress,
contractAddress,
ethToWei(2000.u256),
some(0.u256),
)
assert tokenApprovalResult.isOk(), tokenApprovalResult.error
assert tokenApprovalResult.isOk(), tokenApprovalResult.error
let manager = OnchainGroupManager(
ethClientUrls: @[ethClientUrl],
@ -746,6 +782,7 @@ proc setupOnchainGroupManager*(
chainId: CHAIN_ID,
ethPrivateKey: some($privateKey),
rlnInstance: rlnInstance,
retryStrategy: FastRetryStrategy,
onFatalErrorAction: proc(errStr: string) =
raiseAssert errStr
,
@ -753,26 +790,4 @@ proc setupOnchainGroupManager*(
return manager
proc buildOnchainGroupManager*(
privateKey: string, ethClientUrl: string = EthClient
): OnchainGroupManager =
## Constructs an OnchainGroupManager pointing at the cached RLN proxy contract
## using the supplied private key. No on-chain work happens here — the caller
## is expected to have an Anvil snapshot where this key already owns a funded,
## token-approved account (e.g. via a prior `setupOnchainGroupManager` followed
## by `takeEvmSnapshot`). Each call returns a fresh RLN instance.
let rlnInstanceRes = createRlnInstance()
check:
rlnInstanceRes.isOk()
return OnchainGroupManager(
ethClientUrls: @[ethClientUrl],
ethContractAddress: WAKU_RLNV2_PROXY_ADDRESS,
chainId: CHAIN_ID,
ethPrivateKey: some(privateKey),
rlnInstance: rlnInstanceRes.get(),
onFatalErrorAction: proc(errStr: string) =
raiseAssert errStr
,
)
{.pop.}

View File

@ -264,7 +264,7 @@ suite "Waku v2 Rest API - Relay":
await node.setRlnValidator(wakuRlnConfig)
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -535,7 +535,7 @@ suite "Waku v2 Rest API - Relay":
await node.connectToNodes(@[meshNode.peerInfo.toRemotePeerInfo()])
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -604,7 +604,7 @@ suite "Waku v2 Rest API - Relay":
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -663,7 +663,7 @@ suite "Waku v2 Rest API - Relay":
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr:
@ -735,7 +735,7 @@ suite "Waku v2 Rest API - Relay":
await node.start()
# Registration is mandatory before sending messages with rln-relay
let manager = cast[OnchainGroupManager](node.rln.groupManager)
let manager = cast[OnchainGroupManager](node.rln.groupManager).withFastRetries()
let idCredentials = generateCredentials()
(waitFor manager.register(idCredentials, UserMessageLimit(20))).isOkOr: