# Sequence diagram for RLN Relay protocol (publishing,routing, and slashing) msc { hscale="1", wordwraparcs=true; a [label=" "], b [label=" "], c [label=" "], d [label=" "], e [label=" "]; a rbox a [label="Relay Node: Publisher"], b rbox b [label="Relay Node: Router"], c rbox c [label="Relay Node"], d rbox d [label="Relay Node"], e note e [label="Membership Contract"]; |||; b box b [label=" \n nullifierMap= [(nullifier, shareX, shareY)...] \n \n Initialize an empty map of the received nullifiers \n "], c box c [label=" \n nullifierMap= [(nullifier, shareX, shareY)...] \n \n Initialize an empty map of the received nullifiers \n "], d box d [label=" \n nullifierMap= [(nullifier, shareX, shareY)...] \n \n Initialize an empty map of the received nullifiers \n "]; |||; ..., a -> a [label="Keep track of epoch"], b -> b [label="Keep track of epoch"], c -> c [label="Keep track of epoch"], d -> d [label="Keep track of epoch"]; a box a [label=" \n Message: the intended message \n \n epoch: the current epoch \n "]; a box a [label=" \n A(x) = sk + H(sk, epoch)x \n \n shareX = H(message), shareY = A(shareX) \n \n nullifier = H(H(sk,epoch)) \n "]; a box a [label=" \n zkProof: generate the proof using zkSNARK \n "]; |||; a => b [label="Message, epoch, proofBundle:(shareX, shareY, nullifier, zkProof) \n "]; b box b [label="1. If the received epoch is far from the current epoch"]; b -x c [label="Do not relay"]; b box b [label=" \n 2. If verification of zkProof failed \n "]; b -x c [label="Do not relay"]; b box b [label=" \n 3. If identical nullifier exists in the nullifierMap, \n \n extract the publisher sk \n "]; b -x c [label="Do not relay"]; b => e [label="Slash the publisher: Unlbock the deposit associated with sk"]; e => b [label="x ETH"]; b box b [label=" \n 4. If none of 1-3 happens, update the nullifierMap \n "]; b => c [label="Relay"]; b => d [label="Relay"]; }