mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-06-04 13:09:32 +00:00
improve recents roots retrieval and logs
This commit is contained in:
parent
3ba630daad
commit
02fc4d4889
@ -97,7 +97,8 @@ suite "Onchain group manager":
|
|||||||
check:
|
check:
|
||||||
merkleRootBefore != merkleRootAfter
|
merkleRootBefore != merkleRootAfter
|
||||||
|
|
||||||
test "trackRootChanges: should fetch history correctly":
|
test "trackRootChanges: should fetch history correctly: fetch single root()":
|
||||||
|
# basic check for the soon to be deprecated root contract function, is replaced by getRecentRoots()
|
||||||
# TODO: We can't use `trackRootChanges()` directly in this test because its current implementation
|
# TODO: We can't use `trackRootChanges()` directly in this test because its current implementation
|
||||||
# relies on a busy loop rather than event-based monitoring. but that busy loop fetch root every 5 seconds
|
# relies on a busy loop rather than event-based monitoring. but that busy loop fetch root every 5 seconds
|
||||||
# so we can't use it in this test.
|
# so we can't use it in this test.
|
||||||
@ -123,6 +124,32 @@ suite "Onchain group manager":
|
|||||||
merkleRootBefore != merkleRootAfter
|
merkleRootBefore != merkleRootAfter
|
||||||
manager.validRoots.len() == credentialCount
|
manager.validRoots.len() == credentialCount
|
||||||
|
|
||||||
|
test "trackRootChanges: should fetch history correctly: fetch root cache":
|
||||||
|
# TODO: We can't use `trackRootChanges()` directly in this test because its current implementation
|
||||||
|
# relies on a busy loop rather than event-based monitoring. but that busy loop fetch root every 5 seconds
|
||||||
|
# so we can't use it in this test.
|
||||||
|
|
||||||
|
const credentialCount = 6
|
||||||
|
let credentials = generateCredentials(credentialCount)
|
||||||
|
(waitFor manager.init()).isOkOr:
|
||||||
|
raiseAssert $error
|
||||||
|
|
||||||
|
let merkleRootCacheBefore = (waitFor manager.fetchMerkleRootsCache()).valueOr:
|
||||||
|
raiseAssert "Failed to fetch merkle root before: " & error
|
||||||
|
|
||||||
|
for i in 0 ..< credentials.len():
|
||||||
|
info "Registering credential", index = i, credential = credentials[i]
|
||||||
|
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
||||||
|
assert false, "Failed to register credential " & $i & ": " & error
|
||||||
|
discard waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
|
let merkleRootCacheAfter = (waitFor manager.fetchMerkleRootsCache()).valueOr:
|
||||||
|
raiseAssert "Failed to fetch merkle root after: " & error
|
||||||
|
|
||||||
|
check:
|
||||||
|
merkleRootCacheBefore != merkleRootCacheAfter
|
||||||
|
manager.validRoots.len() == credentialCount
|
||||||
|
|
||||||
test "trackRootChanges: oldest roots are evicted once the window is exceeded":
|
test "trackRootChanges: oldest roots are evicted once the window is exceeded":
|
||||||
const
|
const
|
||||||
initialCount = 5
|
initialCount = 5
|
||||||
@ -135,7 +162,7 @@ suite "Onchain group manager":
|
|||||||
for i in 0 ..< initialCount:
|
for i in 0 ..< initialCount:
|
||||||
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
||||||
assert false, "Failed to register credential " & $i & ": " & error
|
assert false, "Failed to register credential " & $i & ": " & error
|
||||||
discard waitFor manager.updateRoots()
|
discard waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
check manager.validRoots.len() >= 3
|
check manager.validRoots.len() >= 3
|
||||||
let firstThreeBefore =
|
let firstThreeBefore =
|
||||||
@ -145,7 +172,7 @@ suite "Onchain group manager":
|
|||||||
for i in initialCount ..< credentials.len():
|
for i in initialCount ..< credentials.len():
|
||||||
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
||||||
assert false, "Failed to register credential " & $i & ": " & error
|
assert false, "Failed to register credential " & $i & ": " & error
|
||||||
discard waitFor manager.updateRoots()
|
discard waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
let rootsAfter = manager.validRoots.items().toSeq()
|
let rootsAfter = manager.validRoots.items().toSeq()
|
||||||
|
|
||||||
@ -250,7 +277,7 @@ suite "Onchain group manager":
|
|||||||
|
|
||||||
waitFor fut
|
waitFor fut
|
||||||
|
|
||||||
let rootUpdated = waitFor manager.updateRoots()
|
let rootUpdated = waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
if rootUpdated:
|
if rootUpdated:
|
||||||
let proofResult = waitFor manager.fetchMerkleProofElements()
|
let proofResult = waitFor manager.fetchMerkleProofElements()
|
||||||
@ -332,7 +359,7 @@ suite "Onchain group manager":
|
|||||||
assert false, "error returned when calling register: " & error
|
assert false, "error returned when calling register: " & error
|
||||||
waitFor fut
|
waitFor fut
|
||||||
|
|
||||||
let rootUpdated = waitFor manager.updateRoots()
|
let rootUpdated = waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
if rootUpdated:
|
if rootUpdated:
|
||||||
let proofResult = waitFor manager.fetchMerkleProofElements()
|
let proofResult = waitFor manager.fetchMerkleProofElements()
|
||||||
@ -369,7 +396,7 @@ suite "Onchain group manager":
|
|||||||
|
|
||||||
let messageBytes = "Hello".toBytes()
|
let messageBytes = "Hello".toBytes()
|
||||||
|
|
||||||
let rootUpdated = waitFor manager.updateRoots()
|
let rootUpdated = waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
manager.merkleProofCache = newSeq[byte](640)
|
manager.merkleProofCache = newSeq[byte](640)
|
||||||
for i in 0 ..< 640:
|
for i in 0 ..< 640:
|
||||||
@ -398,7 +425,7 @@ suite "Onchain group manager":
|
|||||||
verified == false
|
verified == false
|
||||||
|
|
||||||
test "root queue should be updated correctly":
|
test "root queue should be updated correctly":
|
||||||
const credentialCount = 12
|
const credentialCount = 9
|
||||||
let credentials = generateCredentials(credentialCount)
|
let credentials = generateCredentials(credentialCount)
|
||||||
(waitFor manager.init()).isOkOr:
|
(waitFor manager.init()).isOkOr:
|
||||||
raiseAssert $error
|
raiseAssert $error
|
||||||
@ -427,7 +454,7 @@ suite "Onchain group manager":
|
|||||||
for i in 0 ..< credentials.len():
|
for i in 0 ..< credentials.len():
|
||||||
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
(waitFor manager.register(credentials[i], UserMessageLimit(20))).isOkOr:
|
||||||
assert false, "Failed to register credential " & $i & ": " & error
|
assert false, "Failed to register credential " & $i & ": " & error
|
||||||
discard waitFor manager.updateRoots()
|
discard waitFor manager.updateRecentRoots()
|
||||||
|
|
||||||
waitFor allFutures(futures)
|
waitFor allFutures(futures)
|
||||||
|
|
||||||
@ -472,7 +499,7 @@ suite "Onchain group manager":
|
|||||||
(waitFor manager.register(credentials, UserMessageLimit(20))).isOkOr:
|
(waitFor manager.register(credentials, UserMessageLimit(20))).isOkOr:
|
||||||
assert false, "register failed: " & error
|
assert false, "register failed: " & error
|
||||||
|
|
||||||
discard waitFor manager.updateRoots()
|
discard waitFor manager.updateRecentRoots()
|
||||||
let roots = manager.validRoots.items().toSeq()
|
let roots = manager.validRoots.items().toSeq()
|
||||||
require:
|
require:
|
||||||
roots.len > 0
|
roots.len > 0
|
||||||
|
|||||||
@ -86,7 +86,7 @@ proc fetchMerkleRoot*(
|
|||||||
error "Failed to fetch Merkle root", error = getCurrentExceptionMsg()
|
error "Failed to fetch Merkle root", error = getCurrentExceptionMsg()
|
||||||
return err("Failed to fetch merkle root: " & getCurrentExceptionMsg())
|
return err("Failed to fetch merkle root: " & getCurrentExceptionMsg())
|
||||||
|
|
||||||
proc fetchMerkleRoot*(
|
proc fetchMerkleRootsCache*(
|
||||||
g: OnchainGroupManager
|
g: OnchainGroupManager
|
||||||
): Future[Result[seq[byte], string]] {.async.} =
|
): Future[Result[seq[byte], string]] {.async.} =
|
||||||
let
|
let
|
||||||
@ -148,72 +148,49 @@ proc checkInitialized(g: OnchainGroupManager): Result[void, string] =
|
|||||||
return err("OnchainGroupManager is not initialized")
|
return err("OnchainGroupManager is not initialized")
|
||||||
return ok()
|
return ok()
|
||||||
|
|
||||||
# proc updateRoots*(g: OnchainGroupManager): Future[bool] {.async.} =
|
|
||||||
# let rootRes = await g.fetchMerkleRoot()
|
|
||||||
# if rootRes.isErr():
|
|
||||||
# return false
|
|
||||||
|
|
||||||
# let merkleRoot = UInt256ToField(rootRes.get())
|
|
||||||
|
|
||||||
# if g.validRoots.len == 0:
|
|
||||||
# g.validRoots.addLast(merkleRoot)
|
|
||||||
# return true
|
|
||||||
|
|
||||||
# if g.validRoots[g.validRoots.len - 1] != merkleRoot:
|
|
||||||
# if g.validRoots.len > AcceptableRootWindowSize:
|
|
||||||
# discard g.validRoots.popFirst()
|
|
||||||
# g.validRoots.addLast(merkleRoot)
|
|
||||||
# return true
|
|
||||||
|
|
||||||
# return false
|
|
||||||
|
|
||||||
proc updateRoots*(g: OnchainGroupManager): Future[bool] {.async.} =
|
proc updateRoots*(g: OnchainGroupManager): Future[bool] {.async.} =
|
||||||
let rootRes = await g.fetchMerkleRoot()
|
let rootRes = await g.fetchMerkleRoot()
|
||||||
# let rootRes = await g.fetchMerkleRecentRoots()
|
if rootRes.isErr():
|
||||||
|
return false
|
||||||
|
|
||||||
|
let merkleRoot = UInt256ToField(rootRes.get())
|
||||||
|
|
||||||
|
if g.validRoots.len == 0:
|
||||||
|
g.validRoots.addLast(merkleRoot)
|
||||||
|
return true
|
||||||
|
|
||||||
|
if g.validRoots[g.validRoots.len - 1] != merkleRoot:
|
||||||
|
if g.validRoots.len > AcceptableRootWindowSize:
|
||||||
|
discard g.validRoots.popFirst()
|
||||||
|
g.validRoots.addLast(merkleRoot)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
proc updateRecentRoots*(g: OnchainGroupManager): Future[bool] {.async.} =
|
||||||
|
let rootRes = await g.fetchMerkleRootsCache()
|
||||||
if rootRes.isErr():
|
if rootRes.isErr():
|
||||||
error "Failed to fetch recent roots", error = rootRes.error
|
error "Failed to fetch recent roots", error = rootRes.error
|
||||||
return false
|
return false
|
||||||
|
|
||||||
let bytes = rootRes.get()
|
let bytes = rootRes.get()
|
||||||
debug "recent roots raw bytes received", length = bytes.len
|
|
||||||
if (bytes.len mod 32) != 0:
|
if (bytes.len mod 32) != 0:
|
||||||
error "Invalid recent roots payload length", length = bytes.len
|
error "Invalid recent roots payload length", length = bytes.len
|
||||||
return false
|
return false
|
||||||
|
|
||||||
let chunkCount = bytes.len div 32
|
let chunkCount = bytes.len div 32
|
||||||
debug "recent roots parsed chunk count", chunks = chunkCount
|
|
||||||
if chunkCount != 5:
|
if chunkCount != 5:
|
||||||
warn "Unexpected number of recent roots returned; proceeding anyway",
|
warn "Unexpected number of recent roots returned; proceeding anyway",
|
||||||
count = chunkCount
|
count = chunkCount
|
||||||
|
|
||||||
# Parse 32-byte chunks into MerkleNode values (UInt256 -> Field bytes)
|
# Parse 32-byte chunks (contract returns newest-first) into MerkleNode values,
|
||||||
var newRoots: seq[MerkleNode] = @[] # newest-first order from contract
|
# reversing to oldest-first and skipping zero roots.
|
||||||
var zeroIndices: seq[int] = @[]
|
|
||||||
for i in 0 ..< chunkCount:
|
|
||||||
let startIdx = i * 32
|
|
||||||
let endIdx = (i + 1) * 32 - 1
|
|
||||||
var allZero = true
|
|
||||||
for b in bytes[startIdx .. endIdx]:
|
|
||||||
if b != 0'u8:
|
|
||||||
allZero = false
|
|
||||||
break
|
|
||||||
if allZero:
|
|
||||||
zeroIndices.add(i)
|
|
||||||
let u = UInt256.fromBytesBE(bytes[startIdx .. endIdx])
|
|
||||||
let node = UInt256ToField(u)
|
|
||||||
newRoots.add(node)
|
|
||||||
|
|
||||||
if zeroIndices.len > 0:
|
|
||||||
debug "zero or empty roots detected in recent roots",
|
|
||||||
zeroRootsCount = zeroIndices.len, indices = zeroIndices
|
|
||||||
|
|
||||||
# Convert to deque order: oldest-first (so newest ends up at tail)
|
|
||||||
# Skip zero roots so they are not added to the validRoots list
|
|
||||||
var newRootsDequeOrder: seq[MerkleNode] = @[]
|
var newRootsDequeOrder: seq[MerkleNode] = @[]
|
||||||
for i in countdown(newRoots.len - 1, 0):
|
for startIdx in countdown(bytes.len - 32, 0, 32):
|
||||||
if zeroIndices.contains(i):
|
let u = UInt256.fromBytesBE(bytes.toOpenArray(startIdx, startIdx + 31))
|
||||||
|
if u.isZero:
|
||||||
continue
|
continue
|
||||||
newRootsDequeOrder.add(newRoots[i])
|
newRootsDequeOrder.add(UInt256ToField(u))
|
||||||
|
|
||||||
if newRootsDequeOrder.len == 0:
|
if newRootsDequeOrder.len == 0:
|
||||||
debug "no non-zero recent roots to add; skipping update"
|
debug "no non-zero recent roots to add; skipping update"
|
||||||
@ -236,24 +213,22 @@ proc updateRoots*(g: OnchainGroupManager): Future[bool] {.async.} =
|
|||||||
|
|
||||||
let toAdd = newRootsDequeOrder[matchLen ..< newRootsDequeOrder.len]
|
let toAdd = newRootsDequeOrder[matchLen ..< newRootsDequeOrder.len]
|
||||||
if toAdd.len == 0:
|
if toAdd.len == 0:
|
||||||
debug "recent roots already present up-to-date; skipping update"
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
# If this is the first time, just seed the deque with all provided roots
|
# If this is the first time, just seed the deque with all provided roots
|
||||||
if g.validRoots.len == 0:
|
if g.validRoots.len == 0:
|
||||||
for r in newRootsDequeOrder:
|
for r in newRootsDequeOrder:
|
||||||
debug "adding new recent root", root = r
|
|
||||||
g.validRoots.addLast(r)
|
g.validRoots.addLast(r)
|
||||||
|
debug "seeded recent roots", count = newRootsDequeOrder.len
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# Add all new roots to the "top" (tail) and drop the bottom 5
|
# Add all new roots to the "top" (tail) and trim to AcceptableRootWindowSize
|
||||||
for r in toAdd:
|
for r in toAdd:
|
||||||
debug "adding new recent root", root = r
|
|
||||||
g.validRoots.addLast(r)
|
g.validRoots.addLast(r)
|
||||||
|
debug "appended recent roots", count = toAdd.len, roots = toAdd
|
||||||
|
|
||||||
# Only trim the deque if it exceeds the acceptable window size
|
|
||||||
while g.validRoots.len > AcceptableRootWindowSize:
|
while g.validRoots.len > AcceptableRootWindowSize:
|
||||||
debug "removing old recent root", root = g.validRoots[0]
|
trace "removing old merkle root", root = g.validRoots[0]
|
||||||
discard g.validRoots.popFirst()
|
discard g.validRoots.popFirst()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user