mirror of https://github.com/waku-org/nwaku.git
fix(rln-relay): RLN DB should be aware of chain and contract address (#1932)
This commit is contained in:
parent
c9b48ea1a0
commit
1ae5b5a951
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue