fix(rln-relay): RLN DB should be aware of chain and contract address (#1932)

This commit is contained in:
Aaryamann Challani 2023-08-23 18:23:30 +05:30 committed by GitHub
parent c9b48ea1a0
commit 1ae5b5a951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 93 additions and 22 deletions

View File

@ -197,6 +197,29 @@ suite "Onchain group manager":
manager.membershipFee.isSome()
manager.initialized
asyncTest "should error on initialization when loaded metadata does not match":
let manager = await setup()
await manager.init()
let metadataSetRes = manager.setMetadata()
assert metadataSetRes.isOk(), metadataSetRes.error
let metadataRes = manager.rlnInstance.getMetadata()
assert metadataRes.isOk(), metadataRes.error
let metadata = metadataRes.get()
require:
metadata.chainId == 1337
metadata.contractAddress == manager.ethContractAddress
await manager.stop()
# simulating a change in the contractAddress
let manager2 = OnchainGroupManager(ethClientUrl: EthClient,
ethContractAddress: "0x0000000000000000000000000000000000000000",
ethPrivateKey: manager.ethPrivateKey,
rlnInstance: manager.rlnInstance,
saveKeystore: false)
expect(ValueError): await manager2.init()
asyncTest "startGroupSync: should start group sync":
let manager = await setup()

View File

@ -245,7 +245,9 @@ suite "Waku rln relay":
rlnInstance.isOk()
let rln = rlnInstance.get()
check:
rln.setMetadata(RlnMetadata(lastProcessedBlock: 128)).isOk()
rln.setMetadata(RlnMetadata(lastProcessedBlock: 128,
chainId: 1155511,
contractAddress: "0x9c09146844c1326c2dbc41c451766c7138f88155")).isOk()
test "getMetadata rln utils":
# create an RLN instance which also includes an empty Merkle tree
@ -255,7 +257,9 @@ suite "Waku rln relay":
let rln = rlnInstance.get()
require:
rln.setMetadata(RlnMetadata(lastProcessedBlock: 128)).isOk()
rln.setMetadata(RlnMetadata(lastProcessedBlock: 128,
chainId: 1155511,
contractAddress: "0x9c09146844c1326c2dbc41c451766c7138f88155")).isOk()
let metadataRes = rln.getMetadata()
@ -266,7 +270,8 @@ suite "Waku rln relay":
check:
metadata.lastProcessedBlock == 128
metadata.chainId == 1155511
metadata.contractAddress == "0x9c09146844c1326c2dbc41c451766c7138f88155"
test "Merkle tree consistency check between deletion and insertion":
# create an RLN instance

View File

@ -12,7 +12,8 @@ import
json,
std/tables,
stew/[byteutils, arrayops],
sequtils
sequtils,
strutils
import
../../../waku_keystore,
../../rln,
@ -281,6 +282,20 @@ 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.} =
@ -293,8 +308,7 @@ proc getAndHandleEvents(g: OnchainGroupManager,
let latestProcessedBlock = if toBlock.isSome(): toBlock.get()
else: fromBlock
g.latestProcessedBlock = some(latestProcessedBlock)
let metadataSetRes = g.rlnInstance.setMetadata(RlnMetadata(
lastProcessedBlock: latestProcessedBlock))
let metadataSetRes = g.setMetadata()
if metadataSetRes.isErr():
# this is not a fatal error, hence we don't raise an exception
warn "failed to persist rln metadata", error=metadataSetRes.error()
@ -465,17 +479,8 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} =
let contractAddress = web3.fromHex(web3.Address, g.ethContractAddress)
contract = ethRpc.contractSender(RlnContract, contractAddress)
# check if the contract exists by calling a static function
var membershipFee: Uint256
try:
membershipFee = await contract.MEMBERSHIP_DEPOSIT().call()
except CatchableError:
raise newException(ValueError, "could not get the membership deposit: {}")
g.ethRpc = some(ethRpc)
g.rlnContract = some(contract)
g.membershipFee = some(membershipFee)
if g.keystorePath.isSome() and g.keystorePassword.isSome():
waku_rln_membership_credentials_import_duration_seconds.nanosecondTime:
@ -498,8 +503,22 @@ method init*(g: OnchainGroupManager): Future[void] {.async.} =
g.latestProcessedBlock = some(BlockNumber(0))
else:
let metadata = metadataGetRes.get()
if metadata.chainId != uint64(g.chainId.get()):
raise newException(ValueError, "persisted data: chain id mismatch")
if metadata.contractAddress != g.ethContractAddress.toLower():
raise newException(ValueError, "persisted data: contract address mismatch")
g.latestProcessedBlock = some(metadata.lastProcessedBlock)
# check if the contract exists by calling a static function
var membershipFee: Uint256
try:
membershipFee = await contract.MEMBERSHIP_DEPOSIT().call()
except CatchableError:
raise newException(ValueError,
"could not get the membership deposit: " & getCurrentExceptionMsg())
g.membershipFee = some(membershipFee)
ethRpc.ondisconnect = proc() =
error "Ethereum client disconnected"
let fromBlock = g.latestProcessedBlock.get()

View File

@ -3,7 +3,9 @@ import
import
chronicles,
options,
stew/[arrayops, results],
eth/keys,
stew/[arrayops, byteutils, results, endians2],
std/[sequtils, strformat, strutils, tables],
nimcrypto/utils
import
@ -120,7 +122,6 @@ proc createRLNInstance*(d = MerkleTreeDepth,
proc sha256*(data: openArray[byte]): RlnRelayResult[MerkleNode] =
## a thin layer on top of the Nim wrapper of the sha256 hasher
trace "sha256 hash input", hashhex = data.toHex()
var lenPrefData = encodeLengthPrefix(data)
var
hashInputBuffer = lenPrefData.toBuffer()
@ -247,7 +248,7 @@ proc proofVerify*(rlnInstance: ptr RLN,
rootsBytes = serialize(validRoots)
rootsBuffer = rootsBytes.toBuffer()
trace "serialized proof", proof = proofBytes.toHex()
trace "serialized proof", proof = byteutils.toHex(proofBytes)
let verifyIsSuccessful = verify_with_roots(rlnInstance, addr proofBuffer, addr rootsBuffer, addr validProof)
if not verifyIsSuccessful:
@ -350,11 +351,15 @@ proc getMerkleRoot*(rlnInstance: ptr RLN): MerkleNodeResult =
type
RlnMetadata* = object
lastProcessedBlock*: uint64
chainId*: uint64
contractAddress*: string
proc serialize(metadata: RlnMetadata): seq[byte] =
## serializes the metadata
## returns the serialized metadata
return @(metadata.lastProcessedBlock.toBytes())
return concat(@(metadata.lastProcessedBlock.toBytes()),
@(metadata.chainId.toBytes()),
@(hexToSeqByte(toLower(metadata.contractAddress))))
proc setMetadata*(rlnInstance: ptr RLN, metadata: RlnMetadata): RlnRelayResult[void] =
## sets the metadata of the RLN instance
@ -368,6 +373,7 @@ proc setMetadata*(rlnInstance: ptr RLN, metadata: RlnMetadata): RlnRelayResult[v
# set the metadata
let metadataSet = set_metadata(rlnInstance, metadataBufferPtr)
if not metadataSet:
return err("could not set the metadata")
return ok()
@ -384,8 +390,26 @@ 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 == 8:
if not metadata.len == 36:
return err("wrong output size")
var metadataValue = cast[ptr uint64] (metadata.`ptr`)[]
return ok(RlnMetadata(lastProcessedBlock: metadataValue))
let
lastProcessedBlockOffset = 0
chainIdOffset = lastProcessedBlockOffset + 8
contractAddressOffset = chainIdOffset + 8
var
lastProcessedBlock: uint64
chainId: uint64
contractAddress: string
var metadataValue = cast[ptr array[36, byte]] (metadata.`ptr`)
let metadataBytes: array[36, byte] = metadataValue[]
lastProcessedBlock = uint64.fromBytes(metadataBytes[lastProcessedBlockOffset..chainIdOffset-1])
chainId = uint64.fromBytes(metadataBytes[chainIdOffset..contractAddressOffset-1])
contractAddress = byteutils.toHex(metadataBytes[contractAddressOffset..metadataBytes.high])
return ok(RlnMetadata(lastProcessedBlock: lastProcessedBlock,
chainId: chainId,
contractAddress: "0x" & contractAddress))