-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(rln-relay): gracefully handle chain forks #1623
Changes from 4 commits
134e249
ed9a55b
e132c55
e63afd0
2229fa3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ else: | |
{.push raises: [].} | ||
|
||
import | ||
std/[options, osproc, streams, strutils], | ||
std/[options, osproc, streams, strutils, tables], | ||
stew/[results, byteutils], | ||
stew/shims/net as stewNet, | ||
testutils/unittests, | ||
|
@@ -246,17 +246,20 @@ suite "Onchain group manager": | |
|
||
asyncTest "startGroupSync: should fetch history correctly": | ||
let manager = await setup() | ||
let credentials = generateCredentials(manager.rlnInstance, 5) | ||
const credentialCount = 6 | ||
let credentials = generateCredentials(manager.rlnInstance, credentialCount) | ||
await manager.init() | ||
|
||
let merkleRootBeforeRes = manager.rlnInstance.getMerkleRoot() | ||
require: | ||
merkleRootBeforeRes.isOk() | ||
let merkleRootBefore = merkleRootBeforeRes.get() | ||
|
||
var futures = [newFuture[void](), newFuture[void](), newFuture[void](), newFuture[void](), newFuture[void]()] | ||
|
||
proc generateCallback(futs: array[0..4, Future[system.void]], credentials: seq[IdentityCredential]): OnRegisterCallback = | ||
type VoidFuturesArray = array[0..credentialCount - 1, Future[void]] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rather avoid defining There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This type would be dependant on the |
||
var futures: array[0..credentialCount - 1, Future[void]] | ||
for i in 0 ..< futures.len(): | ||
futures[i] = newFuture[void]() | ||
proc generateCallback(futs: VoidFuturesArray, credentials: seq[IdentityCredential]): OnRegisterCallback = | ||
var futureIndex = 0 | ||
proc callback(registrations: seq[Membership]): Future[void] {.async.} = | ||
if registrations.len == 1 and | ||
|
@@ -281,6 +284,7 @@ suite "Onchain group manager": | |
|
||
check: | ||
merkleRootBefore != merkleRootAfter | ||
manager.validRootBuffer.len() == credentialCount - AcceptableRootWindowSize | ||
|
||
asyncTest "register: should guard against uninitialized state": | ||
let manager = await setup() | ||
|
@@ -477,6 +481,54 @@ suite "Onchain group manager": | |
check: | ||
verifiedRes.get() == false | ||
|
||
asyncTest "backfillRootQueue: should backfill roots in event of chain reorg": | ||
let manager = await setup() | ||
const credentialCount = 6 | ||
let credentials = generateCredentials(manager.rlnInstance, credentialCount) | ||
await manager.init() | ||
|
||
type VoidFuturesArray = array[0..credentialCount - 1, Future[void]] | ||
var futures: array[0..credentialCount - 1, Future[void]] | ||
for i in 0 ..< futures.len(): | ||
futures[i] = newFuture[void]() | ||
|
||
proc generateCallback(futs: VoidFuturesArray, credentials: seq[IdentityCredential]): OnRegisterCallback = | ||
var futureIndex = 0 | ||
proc callback(registrations: seq[Membership]): Future[void] {.async.} = | ||
if registrations.len == 1 and | ||
registrations[0].idCommitment == credentials[futureIndex].idCommitment and | ||
registrations[0].index == MembershipIndex(futureIndex + 1): | ||
futs[futureIndex].complete() | ||
futureIndex += 1 | ||
return callback | ||
|
||
manager.onRegister(generateCallback(futures, credentials)) | ||
await manager.startGroupSync() | ||
|
||
for i in 0 ..< credentials.len(): | ||
await manager.register(credentials[i]) | ||
|
||
await allFutures(futures) | ||
|
||
# At this point, we should have a full root queue, 5 roots, and partial buffer of 1 root | ||
require: | ||
manager.validRoots.len() == credentialCount - 1 | ||
manager.validRootBuffer.len() == 1 | ||
|
||
# We can now simulate a chain reorg by calling backfillRootQueue | ||
var blockTable = default(BlockTable) | ||
blockTable[1.uint] = @[Membership(idCommitment: credentials[4].idCommitment, index: 4.uint)] | ||
|
||
let expectedLastRoot = manager.validRootBuffer[0] | ||
await manager.backfillRootQueue(blockTable) | ||
|
||
# We should now have 5 roots in the queue, and no partial buffer | ||
check: | ||
manager.validRoots.len() == credentialCount - 1 | ||
manager.validRootBuffer.len() == 0 | ||
manager.validRoots[credentialCount - 2] == expectedLastRoot | ||
|
||
|
||
################################ | ||
## Terminating/removing Ganache | ||
################################ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -253,6 +253,13 @@ proc removeMember*(rlnInstance: ptr RLN, index: MembershipIndex): bool = | |
let deletion_success = delete_member(rlnInstance, index) | ||
return deletion_success | ||
|
||
proc removeMembers*(rlnInstance: ptr RLN, indices: seq[MembershipIndex]): bool = | ||
for index in indices: | ||
let deletion_success = delete_member(rlnInstance, index) | ||
if not deletion_success: | ||
return false | ||
return true | ||
Comment on lines
+256
to
+261
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will be an atomic operation in zerokit soon |
||
|
||
proc getMerkleRoot*(rlnInstance: ptr RLN): MerkleNodeResult = | ||
# read the Merkle Tree root after insertion | ||
var | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The
const
keyword should be only used at "package level". Here, alet
is sufficient.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used const since it can be evaluated at compile time, is that okay?