mirror of https://github.com/waku-org/nwaku.git
fix(rln-relay): window of acceptable roots synced to rln metadata (#1953)
* fix(rln-relay): window of acceptable roots synced to rln metadata * fix(rln-relay): s/var/let, use for loop
This commit is contained in:
parent
cc9f8d4254
commit
01634f57f0
|
@ -6,7 +6,7 @@ else:
|
|||
{.push raises: [].}
|
||||
|
||||
import
|
||||
std/[options, osproc, streams, strutils, tempfiles],
|
||||
std/[options, osproc, sequtils, deques, streams, strutils, tempfiles],
|
||||
stew/[results, byteutils],
|
||||
stew/shims/net as stewNet,
|
||||
testutils/unittests,
|
||||
|
@ -351,6 +351,9 @@ suite "Onchain group manager":
|
|||
|
||||
await fut
|
||||
|
||||
check:
|
||||
manager.rlnInstance.getMetadata().get().validRoots == manager.validRoots.toSeq()
|
||||
|
||||
asyncTest "withdraw: should guard against uninitialized state":
|
||||
let manager = await setup()
|
||||
let idSecretHash = generateCredentials(manager.rlnInstance).idSecretHash
|
||||
|
|
|
@ -75,6 +75,22 @@ template initializedGuard(g: OnchainGroupManager): untyped =
|
|||
if not g.initialized:
|
||||
raise newException(ValueError, "OnchainGroupManager is not initialized")
|
||||
|
||||
|
||||
proc setMetadata*(g: OnchainGroupManager): RlnRelayResult[void] =
|
||||
if g.latestProcessedBlock.isNone():
|
||||
return err("latest processed block is not set")
|
||||
try:
|
||||
let metadataSetRes = g.rlnInstance.setMetadata(RlnMetadata(
|
||||
lastProcessedBlock: g.latestProcessedBlock.get(),
|
||||
chainId: uint64(g.chainId.get()),
|
||||
contractAddress: g.ethContractAddress,
|
||||
validRoots: g.validRoots.toSeq()))
|
||||
if metadataSetRes.isErr():
|
||||
return err("failed to persist rln metadata: " & metadataSetRes.error)
|
||||
except CatchableError:
|
||||
return err("failed to persist rln metadata: " & getCurrentExceptionMsg())
|
||||
return ok()
|
||||
|
||||
method atomicBatch*(g: OnchainGroupManager,
|
||||
start: MembershipIndex,
|
||||
idCommitments = newSeq[IDCommitment](),
|
||||
|
@ -91,12 +107,15 @@ method atomicBatch*(g: OnchainGroupManager,
|
|||
var membersSeq = newSeq[Membership]()
|
||||
for i in 0 ..< idCommitments.len():
|
||||
var index = start + MembershipIndex(i)
|
||||
debug "registering member", idCommitment = idCommitments[i], index = index
|
||||
trace "registering member", idCommitment = idCommitments[i], index = index
|
||||
let member = Membership(idCommitment: idCommitments[i], index: index)
|
||||
membersSeq.add(member)
|
||||
await g.registerCb.get()(membersSeq)
|
||||
|
||||
g.validRootBuffer = g.slideRootQueue()
|
||||
let setMetadataRes = g.setMetadata()
|
||||
if setMetadataRes.isErr():
|
||||
error "failed to persist rln metadata", error=setMetadataRes.error
|
||||
|
||||
method register*(g: OnchainGroupManager, idCommitment: IDCommitment): Future[void] {.async.} =
|
||||
initializedGuard(g)
|
||||
|
@ -286,20 +305,6 @@ proc handleRemovedEvents(g: OnchainGroupManager, blockTable: BlockTable): Future
|
|||
|
||||
await g.backfillRootQueue(numRemovedBlocks)
|
||||
|
||||
proc setMetadata*(g: OnchainGroupManager): RlnRelayResult[void] =
|
||||
if g.latestProcessedBlock.isNone():
|
||||
return err("latest processed block is not set")
|
||||
try:
|
||||
let metadataSetRes = g.rlnInstance.setMetadata(RlnMetadata(
|
||||
lastProcessedBlock: g.latestProcessedBlock.get(),
|
||||
chainId: uint64(g.chainId.get()),
|
||||
contractAddress: g.ethContractAddress))
|
||||
if metadataSetRes.isErr():
|
||||
return err("failed to persist rln metadata: " & metadataSetRes.error())
|
||||
except CatchableError:
|
||||
return err("failed to persist rln metadata: " & getCurrentExceptionMsg())
|
||||
return ok()
|
||||
|
||||
proc getAndHandleEvents(g: OnchainGroupManager,
|
||||
fromBlock: BlockNumber,
|
||||
toBlock: Option[BlockNumber] = none(BlockNumber)): Future[void] {.async.} =
|
||||
|
@ -317,7 +322,7 @@ proc getAndHandleEvents(g: OnchainGroupManager,
|
|||
# this is not a fatal error, hence we don't raise an exception
|
||||
warn "failed to persist rln metadata", error=metadataSetRes.error()
|
||||
else:
|
||||
debug "rln metadata persisted", blockNumber = latestProcessedBlock
|
||||
trace "rln metadata persisted", blockNumber = latestProcessedBlock
|
||||
|
||||
proc getNewHeadCallback(g: OnchainGroupManager): BlockHeaderHandler =
|
||||
proc newHeadCallback(blockheader: BlockHeader) {.gcsafe.} =
|
||||
|
@ -461,6 +466,7 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} =
|
|||
if metadata.contractAddress != g.ethContractAddress.toLower():
|
||||
raise newException(ValueError, "persisted data: contract address mismatch")
|
||||
g.latestProcessedBlock = some(metadata.lastProcessedBlock)
|
||||
g.validRoots = metadata.validRoots.toDeque()
|
||||
|
||||
# check if the contract exists by calling a static function
|
||||
var membershipFee: Uint256
|
||||
|
|
|
@ -353,13 +353,36 @@ type
|
|||
lastProcessedBlock*: uint64
|
||||
chainId*: uint64
|
||||
contractAddress*: string
|
||||
validRoots*: seq[MerkleNode]
|
||||
|
||||
proc serialize(metadata: RlnMetadata): seq[byte] =
|
||||
## serializes the metadata
|
||||
## returns the serialized metadata
|
||||
return concat(@(metadata.lastProcessedBlock.toBytes()),
|
||||
@(metadata.chainId.toBytes()),
|
||||
@(hexToSeqByte(toLower(metadata.contractAddress))))
|
||||
@(hexToSeqByte(toLower(metadata.contractAddress))),
|
||||
@(uint64(metadata.validRoots.len()).toBytes()),
|
||||
@(serialize(metadata.validRoots)))
|
||||
|
||||
type MerkleNodeSeq = seq[MerkleNode]
|
||||
|
||||
proc deserialize*(T: type MerkleNodeSeq, merkleNodeByteSeq: seq[byte]): T =
|
||||
## deserializes a byte seq to a seq of MerkleNodes
|
||||
## the order of serialization is |merkle_node_len<8>|merkle_node[len]|
|
||||
|
||||
var roots = newSeq[MerkleNode]()
|
||||
var i = 1'u64
|
||||
let len = uint64.fromBytes(merkleNodeByteSeq[0..7], Endianness.littleEndian)
|
||||
trace "length of valid roots", len
|
||||
let offset = 8'u64
|
||||
for i in 1'u64..len:
|
||||
# convert seq[byte] to array[32, byte]
|
||||
let rawRoot = merkleNodeByteSeq[offset*i .. offset*i + 31]
|
||||
trace "raw root", rawRoot = rawRoot
|
||||
var root: MerkleNode
|
||||
discard root.copyFrom(rawRoot)
|
||||
roots.add(root)
|
||||
return roots
|
||||
|
||||
proc setMetadata*(rlnInstance: ptr RLN, metadata: RlnMetadata): RlnRelayResult[void] =
|
||||
## sets the metadata of the RLN instance
|
||||
|
@ -368,6 +391,7 @@ proc setMetadata*(rlnInstance: ptr RLN, metadata: RlnMetadata): RlnRelayResult[v
|
|||
|
||||
# serialize the metadata
|
||||
let metadataBytes = serialize(metadata)
|
||||
trace "setting metadata", metadata = metadata, metadataBytes = metadataBytes, len = metadataBytes.len
|
||||
var metadataBuffer = metadataBytes.toBuffer()
|
||||
let metadataBufferPtr = addr metadataBuffer
|
||||
|
||||
|
@ -390,26 +414,31 @@ proc getMetadata*(rlnInstance: ptr RLN): RlnRelayResult[RlnMetadata] =
|
|||
getMetadataSuccessful = get_metadata(rlnInstance, metadataPtr)
|
||||
if not getMetadataSuccessful:
|
||||
return err("could not get the metadata")
|
||||
if not metadata.len == 36:
|
||||
return err("wrong output size")
|
||||
trace "metadata length", metadataLen = metadata.len
|
||||
|
||||
let
|
||||
lastProcessedBlockOffset = 0
|
||||
chainIdOffset = lastProcessedBlockOffset + 8
|
||||
contractAddressOffset = chainIdOffset + 8
|
||||
|
||||
validRootsOffset = contractAddressOffset + 20
|
||||
|
||||
var
|
||||
lastProcessedBlock: uint64
|
||||
chainId: uint64
|
||||
contractAddress: string
|
||||
validRoots: MerkleNodeSeq
|
||||
|
||||
var metadataValue = cast[ptr array[36, byte]] (metadata.`ptr`)
|
||||
let metadataBytes: array[36, byte] = metadataValue[]
|
||||
# 8 + 8 + 20 + 8 + (5*32) = 204
|
||||
var metadataBytes = cast[ptr array[204, byte]](metadata.`ptr`)[]
|
||||
trace "received metadata bytes", metadataBytes = metadataBytes, len = metadataBytes.len
|
||||
|
||||
lastProcessedBlock = uint64.fromBytes(metadataBytes[lastProcessedBlockOffset..chainIdOffset-1])
|
||||
chainId = uint64.fromBytes(metadataBytes[chainIdOffset..contractAddressOffset-1])
|
||||
contractAddress = byteutils.toHex(metadataBytes[contractAddressOffset..metadataBytes.high])
|
||||
contractAddress = byteutils.toHex(metadataBytes[contractAddressOffset..validRootsOffset - 1])
|
||||
let validRootsBytes = metadataBytes[validRootsOffset..metadataBytes.high]
|
||||
validRoots = MerkleNodeSeq.deserialize(validRootsBytes)
|
||||
|
||||
return ok(RlnMetadata(lastProcessedBlock: lastProcessedBlock,
|
||||
chainId: chainId,
|
||||
contractAddress: "0x" & contractAddress))
|
||||
contractAddress: "0x" & contractAddress,
|
||||
validRoots: validRoots))
|
||||
|
|
Loading…
Reference in New Issue