2022-11-04 09:52:27 +00:00
when ( NimMajor , NimMinor ) < ( 1 , 4 ) :
{. push raises : [ Defect ] . }
else :
{. push raises : [ ] . }
2021-07-22 08:43:41 +00:00
2022-05-10 21:09:18 +00:00
import
2022-11-04 09:52:08 +00:00
std / [ options , tables , deques ] ,
stew / arrayops ,
chronos ,
2021-06-08 18:56:32 +00:00
web3 ,
2022-11-16 19:02:14 +00:00
eth / keys
2022-11-04 09:52:08 +00:00
import
2023-02-08 15:26:23 +00:00
.. / waku_keystore ,
2022-11-16 19:02:14 +00:00
.. / .. / .. / common / protobuf
2021-06-08 18:56:32 +00:00
2022-11-04 03:00:42 +00:00
type RlnRelayResult * [ T ] = Result [ T , string ]
2022-11-09 18:45:04 +00:00
## RLN is a Nim wrapper for the data types used in zerokit RLN
type RLN * {. incompleteStruct . } = object
type RLNResult * = RlnRelayResult [ ptr RLN ]
2021-06-08 18:56:32 +00:00
2022-05-10 21:09:18 +00:00
type
MerkleNode * = array [ 32 , byte ] # Each node of the Merkle tee is a Poseidon hash which is a 32 byte value
Nullifier * = array [ 32 , byte ]
Epoch * = array [ 32 , byte ]
2022-10-04 20:20:44 +00:00
RlnIdentifier * = array [ 32 , byte ]
2022-11-09 18:45:04 +00:00
ZKSNARK * = array [ 128 , byte ]
2022-08-05 20:58:19 +00:00
2021-06-08 18:56:32 +00:00
# Custom data types defined for waku rln relay -------------------------
2022-10-04 20:20:44 +00:00
type RateLimitProof * = object
## RateLimitProof holds the public inputs to rln circuit as
## defined in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Public-Inputs
## the `proof` field carries the actual zkSNARK proof
proof * : ZKSNARK
## the root of Merkle tree used for the generation of the `proof`
merkleRoot * : MerkleNode
## the epoch used for the generation of the `proof`
epoch * : Epoch
## shareX and shareY are shares of user's identity key
## these shares are created using Shamir secret sharing scheme
## see details in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Linear-Equation-amp-SSS
shareX * : MerkleNode
shareY * : MerkleNode
## nullifier enables linking two messages published during the same epoch
## see details in https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Nullifiers
nullifier * : Nullifier
## Application specific RLN Identifier
rlnIdentifier * : RlnIdentifier
2022-08-05 20:58:19 +00:00
2021-11-23 22:48:40 +00:00
type ProofMetadata * = object
nullifier * : Nullifier
shareX * : MerkleNode
shareY * : MerkleNode
2022-11-09 18:45:04 +00:00
type WakuRLNRelay * = ref object
2022-12-14 11:28:09 +00:00
identityCredential * : IdentityCredential
2022-11-09 18:45:04 +00:00
# membershipIndex denotes the index of a leaf in the Merkle tree
# that contains the pk of the current peer
# this index is used to retrieve the peer's authentication path
membershipIndex * : MembershipIndex
membershipContractAddress * : Address
ethClientAddress * : string
ethAccountAddress * : Option [ Address ]
# this field is required for signing transactions
# TODO may need to erase this ethAccountPrivateKey when is not used
# TODO may need to make ethAccountPrivateKey mandatory
ethAccountPrivateKey * : Option [ PrivateKey ]
rlnInstance * : ptr RLN
pubsubTopic * : string # the pubsub topic for which rln relay is mounted
# contentTopic should be of type waku_message.ContentTopic, however, due to recursive module dependency, the underlying type of ContentTopic is used instead
# TODO a long-term solution is to place types with recursive dependency inside one file
contentTopic * : string
# the log of nullifiers and Shamir shares of the past messages grouped per epoch
nullifierLog * : Table [ Epoch , seq [ ProofMetadata ] ]
lastEpoch * : Epoch # the epoch of the last published rln message
validMerkleRoots * : Deque [ MerkleNode ] # An array of valid merkle roots, which are updated in a FIFO fashion
lastSeenMembershipIndex * : MembershipIndex # the last seen membership index
2022-11-10 16:58:31 +00:00
lastProcessedBlock * : BlockNumber # the last processed block number
2022-11-09 18:45:04 +00:00
type
MessageValidationResult * {. pure . } = enum
Valid ,
Invalid ,
Spam
MerkleNodeResult * = RlnRelayResult [ MerkleNode ]
RateLimitProofResult * = RlnRelayResult [ RateLimitProof ]
2021-11-23 22:48:40 +00:00
# Protobufs enc and init
2021-10-20 00:37:29 +00:00
proc init * ( T : type RateLimitProof , buffer : seq [ byte ] ) : ProtoResult [ T ] =
var nsp : RateLimitProof
let pb = initProtoBuffer ( buffer )
var proof : seq [ byte ]
discard ? pb . getField ( 1 , proof )
discard nsp . proof . copyFrom ( proof )
var merkleRoot : seq [ byte ]
discard ? pb . getField ( 2 , merkleRoot )
discard nsp . merkleRoot . copyFrom ( merkleRoot )
var epoch : seq [ byte ]
discard ? pb . getField ( 3 , epoch )
discard nsp . epoch . copyFrom ( epoch )
var shareX : seq [ byte ]
discard ? pb . getField ( 4 , shareX )
discard nsp . shareX . copyFrom ( shareX )
var shareY : seq [ byte ]
discard ? pb . getField ( 5 , shareY )
discard nsp . shareY . copyFrom ( shareY )
var nullifier : seq [ byte ]
discard ? pb . getField ( 6 , nullifier )
discard nsp . nullifier . copyFrom ( nullifier )
2022-10-04 20:20:44 +00:00
var rlnIdentifier : seq [ byte ]
discard ? pb . getField ( 7 , rlnIdentifier )
discard nsp . rlnIdentifier . copyFrom ( rlnIdentifier )
2022-08-05 20:58:19 +00:00
2022-05-10 21:09:18 +00:00
return ok ( nsp )
2021-10-20 00:37:29 +00:00
2022-05-10 21:09:18 +00:00
proc encode * ( nsp : RateLimitProof ) : ProtoBuffer =
2021-10-20 00:37:29 +00:00
var output = initProtoBuffer ( )
2022-06-16 14:04:47 +00:00
output . write3 ( 1 , nsp . proof )
output . write3 ( 2 , nsp . merkleRoot )
output . write3 ( 3 , nsp . epoch )
output . write3 ( 4 , nsp . shareX )
output . write3 ( 5 , nsp . shareY )
output . write3 ( 6 , nsp . nullifier )
2022-10-04 20:20:44 +00:00
output . write3 ( 7 , nsp . rlnIdentifier )
2022-08-05 20:58:19 +00:00
2022-06-16 14:04:47 +00:00
output . finish3 ( )
2021-10-20 00:37:29 +00:00
2022-11-10 16:58:31 +00:00
return output