2024-05-16 22:29:11 +02:00
|
|
|
import ../group_manager_base, ../../rln, std/sequtils, ../../constants
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
export group_manager_base
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
type StaticGroupManager* = ref object of GroupManager
|
|
|
|
|
groupKeys*: seq[IdentityCredential]
|
|
|
|
|
groupSize*: uint
|
2023-01-16 18:26:18 +05:30
|
|
|
|
|
|
|
|
template initializedGuard*(g: StaticGroupManager): untyped =
|
|
|
|
|
if not g.initialized:
|
2024-03-16 00:08:47 +01:00
|
|
|
raise newException(ValueError, "StaticGroupManager is not initialized")
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-04-26 11:53:58 +02:00
|
|
|
proc resultifiedInitGuard(g: StaticGroupManager): GroupManagerResult[void] =
|
|
|
|
|
try:
|
|
|
|
|
initializedGuard(g)
|
|
|
|
|
return ok()
|
|
|
|
|
except CatchableError:
|
|
|
|
|
return err("StaticGroupManager is not initialized")
|
|
|
|
|
|
|
|
|
|
method init*(g: StaticGroupManager): Future[GroupManagerResult[void]] {.async.} =
|
2023-01-16 18:26:18 +05:30
|
|
|
let
|
2023-02-28 19:08:30 +05:30
|
|
|
groupSize = g.groupSize
|
|
|
|
|
groupKeys = g.groupKeys
|
2024-03-16 00:08:47 +01:00
|
|
|
membershipIndex =
|
|
|
|
|
if g.membershipIndex.isSome():
|
|
|
|
|
g.membershipIndex.get()
|
|
|
|
|
else:
|
2024-04-26 11:53:58 +02:00
|
|
|
return err("membershipIndex is not set")
|
2024-03-16 00:08:47 +01:00
|
|
|
|
|
|
|
|
if membershipIndex < MembershipIndex(0) or
|
|
|
|
|
membershipIndex >= MembershipIndex(groupSize):
|
2024-04-26 11:53:58 +02:00
|
|
|
return err(
|
2024-03-16 00:08:47 +01:00
|
|
|
"Invalid membership index. Must be within 0 and " & $(groupSize - 1) & "but was " &
|
2024-04-26 11:53:58 +02:00
|
|
|
$membershipIndex
|
2024-03-16 00:08:47 +01:00
|
|
|
)
|
2024-06-20 15:05:21 +05:30
|
|
|
g.userMessageLimit = some(DefaultUserMessageLimit)
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-03-04 17:41:33 +05:30
|
|
|
g.idCredentials = some(groupKeys[membershipIndex])
|
2023-01-16 18:26:18 +05:30
|
|
|
# Seed the received commitments into the merkle tree
|
2024-06-20 15:05:21 +05:30
|
|
|
let rateCommitments = groupKeys.mapIt(
|
|
|
|
|
RateCommitment(
|
|
|
|
|
idCommitment: it.idCommitment, userMessageLimit: g.userMessageLimit.get()
|
2024-03-16 00:08:47 +01:00
|
|
|
)
|
2024-06-20 15:05:21 +05:30
|
|
|
)
|
|
|
|
|
let leaves = rateCommitments.toLeaves().valueOr:
|
|
|
|
|
return err("Failed to convert rate commitments to leaves: " & $error)
|
|
|
|
|
let membersInserted = g.rlnInstance.insertMembers(g.latestIndex, leaves)
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2023-03-31 19:15:04 +05:30
|
|
|
discard g.slideRootQueue()
|
2023-02-28 19:08:30 +05:30
|
|
|
|
2024-03-04 17:41:33 +05:30
|
|
|
g.latestIndex += MembershipIndex(groupKeys.len - 1)
|
2023-01-16 18:26:18 +05:30
|
|
|
|
|
|
|
|
g.initialized = true
|
|
|
|
|
|
2024-04-26 11:53:58 +02:00
|
|
|
return ok()
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
method startGroupSync*(
|
|
|
|
|
g: StaticGroupManager
|
2024-04-26 11:53:58 +02:00
|
|
|
): Future[GroupManagerResult[void]] {.async.} =
|
|
|
|
|
?g.resultifiedInitGuard()
|
2023-01-16 18:26:18 +05:30
|
|
|
# No-op
|
2024-04-26 11:53:58 +02:00
|
|
|
return ok()
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
method register*(
|
|
|
|
|
g: StaticGroupManager, rateCommitment: RateCommitment
|
|
|
|
|
): Future[void] {.async: (raises: [Exception]).} =
|
|
|
|
|
initializedGuard(g)
|
2024-02-09 16:31:45 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
let leaf = rateCommitment.toLeaf().get()
|
2024-02-09 16:31:45 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
await g.registerBatch(@[leaf])
|
2024-02-09 16:31:45 +05:30
|
|
|
|
2024-03-04 17:41:33 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
method registerBatch*(
|
|
|
|
|
g: StaticGroupManager, rateCommitments: seq[RawRateCommitment]
|
|
|
|
|
): Future[void] {.async: (raises: [Exception]).} =
|
|
|
|
|
initializedGuard(g)
|
2024-03-04 17:41:33 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
let membersInserted = g.rlnInstance.insertMembers(g.latestIndex + 1, rateCommitments)
|
|
|
|
|
if not membersInserted:
|
|
|
|
|
raise newException(ValueError, "Failed to insert members into the merkle tree")
|
|
|
|
|
|
|
|
|
|
if g.registerCb.isSome():
|
|
|
|
|
var memberSeq = newSeq[Membership]()
|
|
|
|
|
for i in 0 ..< rateCommitments.len:
|
|
|
|
|
memberSeq.add(
|
|
|
|
|
Membership(
|
|
|
|
|
rateCommitment: rateCommitments[i],
|
|
|
|
|
index: g.latestIndex + MembershipIndex(i) + 1,
|
2024-03-16 00:08:47 +01:00
|
|
|
)
|
2024-06-20 15:05:21 +05:30
|
|
|
)
|
|
|
|
|
await g.registerCb.get()(memberSeq)
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
discard g.slideRootQueue()
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
g.latestIndex += MembershipIndex(rateCommitments.len)
|
|
|
|
|
return
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
method withdraw*(
|
|
|
|
|
g: StaticGroupManager, idSecretHash: IdentitySecretHash
|
|
|
|
|
): Future[void] {.async: (raises: [Exception]).} =
|
|
|
|
|
initializedGuard(g)
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-06-20 15:05:21 +05:30
|
|
|
let groupKeys = g.groupKeys
|
|
|
|
|
|
|
|
|
|
for i in 0 ..< groupKeys.len:
|
|
|
|
|
if groupKeys[i].idSecretHash == idSecretHash:
|
|
|
|
|
let idCommitment = groupKeys[i].idCommitment
|
|
|
|
|
let index = MembershipIndex(i)
|
|
|
|
|
let rateCommitment = RateCommitment(
|
|
|
|
|
idCommitment: idCommitment, userMessageLimit: g.userMessageLimit.get()
|
|
|
|
|
).toLeaf().valueOr:
|
|
|
|
|
raise newException(ValueError, "Failed to parse rateCommitment")
|
|
|
|
|
let memberRemoved = g.rlnInstance.removeMember(index)
|
|
|
|
|
if not memberRemoved:
|
|
|
|
|
raise newException(ValueError, "Failed to remove member from the merkle tree")
|
|
|
|
|
|
|
|
|
|
if g.withdrawCb.isSome():
|
|
|
|
|
let withdrawCb = g.withdrawCb.get()
|
|
|
|
|
await withdrawCb(@[Membership(rateCommitment: rateCommitment, index: index)])
|
|
|
|
|
|
|
|
|
|
return
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2024-03-16 00:08:47 +01:00
|
|
|
method withdrawBatch*(
|
|
|
|
|
g: StaticGroupManager, idSecretHashes: seq[IdentitySecretHash]
|
|
|
|
|
): Future[void] {.async: (raises: [Exception]).} =
|
2023-01-16 18:26:18 +05:30
|
|
|
initializedGuard(g)
|
|
|
|
|
|
|
|
|
|
# call withdraw on each idSecretHash
|
|
|
|
|
for idSecretHash in idSecretHashes:
|
2024-03-16 00:08:47 +01:00
|
|
|
await g.withdraw(idSecretHash)
|
2023-01-16 18:26:18 +05:30
|
|
|
|
2023-02-28 19:08:30 +05:30
|
|
|
method onRegister*(g: StaticGroupManager, cb: OnRegisterCallback) {.gcsafe.} =
|
2023-01-16 18:26:18 +05:30
|
|
|
g.registerCb = some(cb)
|
|
|
|
|
|
2023-02-28 19:08:30 +05:30
|
|
|
method onWithdraw*(g: StaticGroupManager, cb: OnWithdrawCallback) {.gcsafe.} =
|
2023-01-16 18:26:18 +05:30
|
|
|
g.withdrawCb = some(cb)
|
2023-07-27 17:21:21 +05:30
|
|
|
|
2023-12-14 07:16:39 +01:00
|
|
|
method stop*(g: StaticGroupManager): Future[void] {.async.} =
|
2023-07-27 17:21:21 +05:30
|
|
|
initializedGuard(g)
|
|
|
|
|
# No-op
|
2023-09-06 14:16:19 +05:30
|
|
|
|
2023-12-14 07:16:39 +01:00
|
|
|
method isReady*(g: StaticGroupManager): Future[bool] {.async.} =
|
2023-09-06 14:16:19 +05:30
|
|
|
initializedGuard(g)
|
2023-12-14 07:16:39 +01:00
|
|
|
return true
|