6868 # # Group manager that propagates membership via logos-messaging content topics.
6969 # # Membership additions and deletions are broadcast to all nodes.
7070 publishCallback: Option [PublishCallback ]
71- membershipByIdCommitment: Table [IDCommitment , MembershipIndex ] # # idCommitment -> index (for spam recovery)
71+ membershipByIdCommitment: Table [IDCommitment , MembershipIndex ]
72+ # # idCommitment -> index (for spam recovery)
7273 membershipByIndex: Table [MembershipIndex , IDCommitment ] # # index -> idCommitment
7374 # We track per-user rate limits because the Merkle tree stores rateCommitment = Poseidon(idCommitment, userMessageLimit),
7475 # not the raw userMessageLimit. When serializing tree snapshots, we need the original userMessageLimit to correctly
7576 # recompute rateCommitment on load. Without this, we'd have to assume all members use the same limit.
76- rateLimitByIdCommitment: Table [IDCommitment , uint64 ] # # idCommitment -> userMessageLimit
77+ rateLimitByIdCommitment: Table [IDCommitment , uint64 ]
78+ # # idCommitment -> userMessageLimit
7779 nextIndex: MembershipIndex
7880 membershipContentTopic* : string # # Content topic for membership updates
7981
@@ -161,9 +163,7 @@ proc refreshProofCache*(gm: OffchainGroupManager): RlnResult[void] =
161163 return ok ()
162164
163165 let cache = gm.rlnInstance.generatePartialProofCache (
164- gm.credentials.get (),
165- gm.membershipIndex.get (),
166- gm.userMessageLimit,
166+ gm.credentials.get (), gm.membershipIndex.get (), gm.userMessageLimit
167167 ).valueOr:
168168 gm.partialProofCache = none (PartialProofCache )
169169 return err (" Failed to refresh partial proof cache: " & error)
@@ -234,8 +234,7 @@ method generateProof*(
234234 let index = gm.membershipIndex.get ()
235235
236236 trace " Generating proof with credentials" ,
237- membershipIndex = index,
238- commitment = creds.idCommitment.toHex ()
237+ membershipIndex = index, commitment = creds.idCommitment.toHex ()
239238
240239 # Flush tree to ensure internal state is synced
241240 if not flush (gm.rlnInstance.ctx):
@@ -252,8 +251,7 @@ method generateProof*(
252251 return err (" Failed to compute expected rate commitment: " & error)
253252
254253 trace " Tree state verification before proof generation" ,
255- membershipIndex = index,
256- commitmentsMatch = treeCommitment == expectedRateCommitment
254+ membershipIndex = index, commitmentsMatch = treeCommitment == expectedRateCommitment
257255
258256 if treeCommitment != expectedRateCommitment:
259257 error " CRITICAL: Tree commitment at index does not match our credentials!" ,
@@ -270,9 +268,7 @@ method generateProof*(
270268 return err (" Failed to get current Merkle root: " & error)
271269
272270 trace " Generating RLN proof" ,
273- signalLen = signal.len,
274- messageId = messageId,
275- membershipIndex = index
271+ signalLen = signal.len, messageId = messageId, membershipIndex = index
276272
277273 # Happy path: cached partial-proof should be available and valid most of the time.
278274 # On cache miss/staleness, rebuild once and retry. Fall back to full proof generation.
@@ -309,7 +305,8 @@ method generateProof*(
309305 )
310306 usedPartialCache = proofResult.isOk
311307 if proofResult.isErr:
312- warn " Refreshed partial proof cache could not be used" , error = proofResult.error
308+ warn " Refreshed partial proof cache could not be used" ,
309+ error = proofResult.error
313310
314311 if not usedPartialCache:
315312 proofResult = gm.rlnInstance.generateRlnProofWithWitness (
@@ -429,11 +426,7 @@ proc restoreMemberFromKeystore*(
429426 if not gm.isInitialized:
430427 return err (" Group manager not initialized" )
431428
432- let memberLimit =
433- if userMessageLimit > 0 :
434- userMessageLimit
435- else :
436- gm.userMessageLimit
429+ let memberLimit = if userMessageLimit > 0 : userMessageLimit else : gm.userMessageLimit
437430
438431 # Compute rate commitment = Poseidon(idCommitment, userMessageLimit)
439432 # This is the actual leaf value stored in the RLN Merkle tree
@@ -512,7 +505,8 @@ method register*(
512505 index: index,
513506 )
514507 let data = update.toBytes ()
515- await gm.publishCallback.get ()(gm.membershipContentTopic, data)
508+ (await gm.publishCallback.get ()(gm.membershipContentTopic, data)).isOkOr:
509+ warn " Failed to broadcast membership update" , error = error
516510
517511 # Call callback
518512 if gm.onRegister.isSome:
@@ -538,7 +532,8 @@ proc registerWithLimit*(
538532 return err (" Failed to compute rate commitment: " & error)
539533
540534 let index = gm.nextIndex
541- trace " Registering member with custom limit" , index = index, userMessageLimit = userMessageLimit
535+ trace " Registering member with custom limit" ,
536+ index = index, userMessageLimit = userMessageLimit
542537 gm.nextIndex += 1
543538
544539 # Insert rateCommitment into RLN tree
@@ -564,13 +559,15 @@ proc registerWithLimit*(
564559 index: index,
565560 )
566561 let data = update.toBytes ()
567- await gm.publishCallback.get ()(gm.membershipContentTopic, data)
562+ (await gm.publishCallback.get ()(gm.membershipContentTopic, data)).isOkOr:
563+ warn " Failed to broadcast membership update" , error = error
568564
569565 # Call callback
570566 if gm.onRegister.isSome:
571567 await gm.onRegister.get ()(commitment, index)
572568
573- debug " Member registered with custom limit" , index = index, userMessageLimit = userMessageLimit
569+ debug " Member registered with custom limit" ,
570+ index = index, userMessageLimit = userMessageLimit
574571 ok (index)
575572
576573method register * (
@@ -613,9 +610,8 @@ method withdraw*(
613610 return err (" Failed to delete member: " & deleteResult.error)
614611
615612 # Get the member's rate limit before deleting (for broadcast)
616- let memberRateLimit = gm.rateLimitByIdCommitment.getOrDefault (
617- idCommitment, gm.userMessageLimit
618- )
613+ let memberRateLimit =
614+ gm.rateLimitByIdCommitment.getOrDefault (idCommitment, gm.userMessageLimit)
619615
620616 # Update local tracking
621617 gm.membershipByIdCommitment.del (idCommitment)
@@ -635,7 +631,8 @@ method withdraw*(
635631 index: index,
636632 )
637633 let data = update.toBytes ()
638- await gm.publishCallback.get ()(gm.membershipContentTopic, data)
634+ (await gm.publishCallback.get ()(gm.membershipContentTopic, data)).isOkOr:
635+ warn " Failed to broadcast membership update" , error = error
639636
640637 # Call callback
641638 if gm.onWithdraw.isSome:
@@ -789,8 +786,8 @@ proc getMemberRateLimit*(
789786# └─────────────────────────────────────────────────────────────┘
790787
791788const
792- SnapshotHeaderSize = 16 # member_count (8) + next_index (8)
793- SnapshotMemberSize = 48 # commitment (32) + index (8) + userMessageLimit (8)
789+ SnapshotHeaderSize = 16 # member_count (8) + next_index (8)
790+ SnapshotMemberSize = 48 # commitment (32) + index (8) + userMessageLimit (8)
794791
795792# Note: writeUint64LE and readUint64LE are imported from bytes_utils via types
796793
@@ -821,9 +818,8 @@ proc serializeTreeSnapshot*(gm: OffchainGroupManager): seq[byte] =
821818 offset += Uint64ByteSize
822819
823820 # Write userMessageLimit
824- let rateLimit = gm.rateLimitByIdCommitment.getOrDefault (
825- commitment, gm.userMessageLimit
826- )
821+ let rateLimit =
822+ gm.rateLimitByIdCommitment.getOrDefault (commitment, gm.userMessageLimit)
827823 result .writeUint64LE (offset, rateLimit)
828824 offset += Uint64ByteSize
829825
@@ -849,7 +845,10 @@ proc loadTreeSnapshot*(gm: OffchainGroupManager, data: seq[byte]): RlnResult[voi
849845 if data.len != expectedSize:
850846 error " Snapshot size mismatch" ,
851847 actual = data.len, expected = expectedSize, memberCount = memberCount
852- return err (" Invalid snapshot: size mismatch (expected " & $ expectedSize & " , got " & $ data.len & " )" )
848+ return err (
849+ " Invalid snapshot: size mismatch (expected " & $ expectedSize & " , got " & $ data.len &
850+ " )"
851+ )
853852
854853 trace " Loading tree snapshot" , memberCount = memberCount, nextIndex = nextIndex
855854
@@ -883,7 +882,8 @@ proc loadTreeSnapshot*(gm: OffchainGroupManager, data: seq[byte]): RlnResult[voi
883882 # Insert into RLN Merkle tree
884883 let insertResult = gm.rlnInstance.insertMemberAt (index, rateCommitment)
885884 if insertResult.isErr:
886- error " Failed to insert member from snapshot" , index = index, error = insertResult.error
885+ error " Failed to insert member from snapshot" ,
886+ index = index, error = insertResult.error
887887 return err (" Failed to insert member: " & insertResult.error)
888888
889889 # Update tracking tables - track by idCommitment for spam recovery
@@ -897,7 +897,8 @@ proc loadTreeSnapshot*(gm: OffchainGroupManager, data: seq[byte]): RlnResult[voi
897897 gm.resetRootTrackerOrLog ()
898898 gm.refreshProofCacheOrLog ()
899899
900- debug " Tree snapshot loaded successfully" , memberCount = memberCount, nextIndex = nextIndex
900+ debug " Tree snapshot loaded successfully" ,
901+ memberCount = memberCount, nextIndex = nextIndex
901902 ok ()
902903
903904proc saveTreeToFile * (gm: OffchainGroupManager , path: string ): RlnResult [void ] =
@@ -929,9 +930,7 @@ proc loadTreeFromFile*(gm: OffchainGroupManager, path: string): RlnResult[void]
929930 if not flush (gm.rlnInstance.ctx):
930931 return err (" Failed to flush tree after loading" )
931932
932- debug " Tree loaded and flushed" ,
933- path = path,
934- memberCount = gm.membershipByIndex.len
933+ debug " Tree loaded and flushed" , path = path, memberCount = gm.membershipByIndex.len
935934
936935 return ok ()
937936 except IOError as e:
0 commit comments