vac.dev-experimental-old/rln-relay.html
2021-09-02 21:14:19 +00:00

829 lines
55 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html class="h-full" lang="en-US">
<head>
<title>Vac - Privacy-preserving p2p economic spam protection in Waku v2</title>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Vac</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="shortcut icon"
href="/assets/img/favicon.png"
type="image/png"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link
href="https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,400;0,600;0,700;1,400;1,600&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="/assets/css/style.css" />
</head>
<body class="h-full flex flex-col">
<div
class="flex-grow container max-w-screen-xl mx-auto px-5 md:px-12 lg:pt-6"
>
<header>
<div class="container max-w-screen-xl sm:border-b">
<div
class="
nav-section
flex
justify-between
items-center
py-3
md:py-5
lg:py-10
"
>
<div class="logo md:pr-8 l:p-0">
<a href="/"
><img src="/assets/img/logo.png"
/></a>
</div>
<div class="flex justify-between items-center w-9/12">
<div class="burger block sm:hidden z-50">
<button
class="
burger__button burger__button--open
fixed
top-2
right-5
w-12
h-12
"
type="button"
aria-label="Mobile menu button"
>
<img
class="burger__icon"
src="/assets/img/burger.svg"
alt="Open menu button"
/>
</button>
<button
class="
burger__button burger__button--close
hidden
fixed
top-2
right-5
w-12
h-12
"
type="button"
aria-label="Close mobile menu button"
>
<img
class="burger__icon burger__icon--close"
src="/assets/img/close.svg"
alt="Close menu button"
/>
</button>
</div>
<nav class="nav max-w-screen-xm md:max-w-screen-sl container">
<ul
class="
nav__list
hidden
sm:flex
justify-between
container
text-xs
font-semibold
md:pr-8
l:p-0
"
>
<li class="hover:opacity-50">
<a class="nav__link" href="/#work">Work</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/#about">About</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/#join">Join VAC</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/research-log">Research log</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/media">Media</a>
</li>
<li class="hover:opacity-50">
<a href="https://specs.vac.dev" target="_blank" rel="noopener noreferrer"
>Specs</a
>
</li>
<li class="hover:opacity-50">
<a href="https://forum.vac.dev/" target="_blank" rel="noopener noreferrer"
>Forum</a
>
</li>
</ul>
</nav>
<ul class="social items-center hidden md:flex">
<li class="pr-5">
<a href="https://twitter.com/vacp2p" target="_blank" rel="noopener noreferrer"
><svg
width="25"
height="21"
viewBox="0 0 25 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="hover:opacity-50"
>
<path
d="M24.8872 3.04499C23.9872 3.43499 23.0572 3.70498 22.0672 3.82499C23.0872 3.22498 23.8672 2.26499 24.2272 1.09499C23.2672 1.66499 22.2172 2.05499 21.1072 2.29499C20.2072 1.33499 18.9172 0.734985 17.5072 0.734985C14.7772 0.734985 12.5872 2.95499 12.5872 5.65499C12.5872 6.04499 12.6172 6.40498 12.7072 6.76498C8.62721 6.58498 5.02721 4.60498 2.59721 1.63499C0.857207 4.75498 2.80721 7.33499 4.09721 8.20499C3.31721 8.20499 2.53721 7.96499 1.87721 7.60499C1.87721 10.035 3.58721 12.045 5.80721 12.495C5.32721 12.645 4.24721 12.735 3.58721 12.585C4.21721 14.535 6.04721 15.975 8.17721 16.005C6.49721 17.325 4.03721 18.375 0.887207 18.045C3.07721 19.455 5.65721 20.265 8.44721 20.265C17.5072 20.265 22.4272 12.765 22.4272 6.28499C22.4272 6.07499 22.4272 5.86499 22.3972 5.65499C23.4172 4.90499 24.2572 4.03499 24.8872 3.04499Z"
fill="#151512"
/>
</svg>
</a>
</li>
<li class="pr-5">
<a href="https://github.com/vacp2p" target="_blank" rel="noopener noreferrer"
><svg
width="26"
height="25"
viewBox="0 0 26 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="hover:opacity-50"
>
<path
d="M12.8857 0.856567C6.26021 0.856567 0.915339 6.20154 0.950043 12.7951C0.9778 18.0687 4.43935 22.5427 9.21766 24.1227C9.81824 24.2327 10.0353 23.864 10.0336 23.5474C10.0321 23.2635 10.0177 22.5129 10.0065 21.5171C6.67274 22.238 5.95552 19.9163 5.95552 19.9163C5.40376 18.5369 4.61433 18.1698 4.61433 18.1698C3.51994 17.4296 4.69151 17.4444 4.69151 17.4444C5.89646 17.5291 6.53549 18.6751 6.53549 18.6751C7.61609 20.4989 9.35182 19.9727 10.0342 19.6665C10.1382 18.8951 10.4459 18.3689 10.7878 18.0702C8.12222 17.7684 5.31483 16.7443 5.29076 12.1708C5.2839 10.8672 5.74629 9.80152 6.50989 8.96619C6.3838 8.66445 5.96641 7.45009 6.61027 5.80766C6.61027 5.80766 7.61658 5.4866 9.9167 7.03094C10.8723 6.76636 11.8976 6.63408 12.9191 6.62962C13.9376 6.63556 14.9658 6.76636 15.9257 7.03242C18.2081 5.48809 19.2163 5.80914 19.2163 5.80914C19.8789 7.45306 19.4743 8.66594 19.3529 8.96767C20.1268 9.80301 20.5959 10.8687 20.6028 12.1723C20.6269 16.7577 17.8272 17.767 15.1558 18.0628C15.5882 18.4314 15.976 19.1597 15.9819 20.273C15.9903 21.8693 15.9821 23.1565 15.9841 23.5474C15.9858 23.867 16.2038 24.2386 16.8122 24.1212C21.5663 22.5397 24.9778 18.0672 24.95 12.7951C24.9153 6.20154 19.5142 0.856567 12.8857 0.856567Z"
fill="#151512"
/>
</svg>
</a>
</li>
<li>
<a
href="https://discord.gg/PQFdubGt6d"
target="_blank"
rel="noopener noreferrer"
><svg
width="25"
height="21"
viewBox="0 0 25 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="hover:opacity-50"
>
<path
d="M22.7861 9.04256C21.8482 5.74455 20.7799 4.04048 20.7627 4.00991C20.7017 3.93459 19.189 2.104 15.5271 0.75L15.0353 2.0764C16.7774 2.72057 18.0116 3.50643 18.6899 4.01419C16.6599 3.40408 14.2431 3.03041 12.1008 3.03041C9.95851 3.03041 7.53775 3.40408 5.50128 4.01419C6.18496 3.50648 7.42744 2.72057 9.17631 2.0764L8.69846 0.75C5.02238 2.104 3.49044 3.93459 3.42863 4.00991C3.41108 4.04048 2.32479 5.74455 1.35221 9.04256C0.414855 12.2208 0.0415214 16.7045 0.027872 16.8843C0.109225 17.0131 1.97891 20.25 7.12077 20.25L8.43406 18.3536C6.97595 17.964 5.58693 17.3357 4.31689 16.4832L5.10228 15.3069C7.15122 16.6822 9.54509 17.4092 12.0251 17.4092C14.5051 17.4092 16.9067 16.6822 18.9701 15.3069L19.7431 16.4832C18.4641 17.3357 17.0684 17.964 15.6062 18.3536L16.8995 20.25C22.0414 20.25 23.9452 17.0131 24.0279 16.8843C24.0161 16.7045 23.69 12.2208 22.7861 9.04256ZM8.79853 12.7392H7.39228L7.40468 10.3841H8.81093L8.79853 12.7392ZM16.7071 12.7392H15.3008L15.3132 10.3841H16.7195L16.7071 12.7392Z"
fill="#151512"
/>
</svg>
</a>
</li>
</ul>
</div>
<div
class="
overlay
container
max-w-screen-sm
w-full
hidden
sm:hidden
fixed
top-0
right-0
h-screen
bg-black bg-opacity-40
z-30
"
>
<nav
class="
nav-mobile
hidden
fixed
top-0
right-0
flex flex-col
justify-between
items-center
pt-14
px-12
pb-5
bg-white
w-9/12
h-3/4
z-40
"
>
<ul
class="
nav__list
flex flex-col flex-1
justify-between
items-center
container
box-content
w-32
h-auto
max-h-nav
text-xs
font-normal
"
>
<li class="hover:opacity-50">
<a class="nav__link" href="/#work">Work</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/#about">About</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/#join">Join VAC</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/research-log">Research log</a>
</li>
<li class="hover:opacity-50">
<a class="nav__link" href="/media">Media</a>
</li>
<li class="hover:opacity-50">
<a href="https://specs.vac.dev" target="_blank" rel="noopener noreferrer"
>Specs</a
>
</li>
<li class="hover:opacity-50">
<a href="https://forum.vac.dev/" target="_blank" rel="noopener noreferrer"
>Forum</a
>
</li>
</ul>
<ul class="social items-center flex mt-8">
<li class="pr-5">
<a href="https://twitter.com/vacp2p" target="_blank" rel="noopener noreferrer"
><svg
width="25"
height="21"
viewBox="0 0 25 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="hover:opacity-50"
>
<path
d="M24.8872 3.04499C23.9872 3.43499 23.0572 3.70498 22.0672 3.82499C23.0872 3.22498 23.8672 2.26499 24.2272 1.09499C23.2672 1.66499 22.2172 2.05499 21.1072 2.29499C20.2072 1.33499 18.9172 0.734985 17.5072 0.734985C14.7772 0.734985 12.5872 2.95499 12.5872 5.65499C12.5872 6.04499 12.6172 6.40498 12.7072 6.76498C8.62721 6.58498 5.02721 4.60498 2.59721 1.63499C0.857207 4.75498 2.80721 7.33499 4.09721 8.20499C3.31721 8.20499 2.53721 7.96499 1.87721 7.60499C1.87721 10.035 3.58721 12.045 5.80721 12.495C5.32721 12.645 4.24721 12.735 3.58721 12.585C4.21721 14.535 6.04721 15.975 8.17721 16.005C6.49721 17.325 4.03721 18.375 0.887207 18.045C3.07721 19.455 5.65721 20.265 8.44721 20.265C17.5072 20.265 22.4272 12.765 22.4272 6.28499C22.4272 6.07499 22.4272 5.86499 22.3972 5.65499C23.4172 4.90499 24.2572 4.03499 24.8872 3.04499Z"
fill="#151512"
/>
</svg>
</a>
</li>
<li class="pr-5">
<a href="https://github.com/vacp2p" target="_blank" rel="noopener noreferrer"
><svg
width="26"
height="25"
viewBox="0 0 26 25"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="hover:opacity-50"
>
<path
d="M12.8857 0.856567C6.26021 0.856567 0.915339 6.20154 0.950043 12.7951C0.9778 18.0687 4.43935 22.5427 9.21766 24.1227C9.81824 24.2327 10.0353 23.864 10.0336 23.5474C10.0321 23.2635 10.0177 22.5129 10.0065 21.5171C6.67274 22.238 5.95552 19.9163 5.95552 19.9163C5.40376 18.5369 4.61433 18.1698 4.61433 18.1698C3.51994 17.4296 4.69151 17.4444 4.69151 17.4444C5.89646 17.5291 6.53549 18.6751 6.53549 18.6751C7.61609 20.4989 9.35182 19.9727 10.0342 19.6665C10.1382 18.8951 10.4459 18.3689 10.7878 18.0702C8.12222 17.7684 5.31483 16.7443 5.29076 12.1708C5.2839 10.8672 5.74629 9.80152 6.50989 8.96619C6.3838 8.66445 5.96641 7.45009 6.61027 5.80766C6.61027 5.80766 7.61658 5.4866 9.9167 7.03094C10.8723 6.76636 11.8976 6.63408 12.9191 6.62962C13.9376 6.63556 14.9658 6.76636 15.9257 7.03242C18.2081 5.48809 19.2163 5.80914 19.2163 5.80914C19.8789 7.45306 19.4743 8.66594 19.3529 8.96767C20.1268 9.80301 20.5959 10.8687 20.6028 12.1723C20.6269 16.7577 17.8272 17.767 15.1558 18.0628C15.5882 18.4314 15.976 19.1597 15.9819 20.273C15.9903 21.8693 15.9821 23.1565 15.9841 23.5474C15.9858 23.867 16.2038 24.2386 16.8122 24.1212C21.5663 22.5397 24.9778 18.0672 24.95 12.7951C24.9153 6.20154 19.5142 0.856567 12.8857 0.856567Z"
fill="#151512"
/>
</svg>
</a>
</li>
<li>
<a
href="https://discord.gg/PQFdubGt6d"
target="_blank"
rel="noopener noreferrer"
><svg
width="25"
height="21"
viewBox="0 0 25 21"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="hover:opacity-50"
>
<path
d="M22.7861 9.04256C21.8482 5.74455 20.7799 4.04048 20.7627 4.00991C20.7017 3.93459 19.189 2.104 15.5271 0.75L15.0353 2.0764C16.7774 2.72057 18.0116 3.50643 18.6899 4.01419C16.6599 3.40408 14.2431 3.03041 12.1008 3.03041C9.95851 3.03041 7.53775 3.40408 5.50128 4.01419C6.18496 3.50648 7.42744 2.72057 9.17631 2.0764L8.69846 0.75C5.02238 2.104 3.49044 3.93459 3.42863 4.00991C3.41108 4.04048 2.32479 5.74455 1.35221 9.04256C0.414855 12.2208 0.0415214 16.7045 0.027872 16.8843C0.109225 17.0131 1.97891 20.25 7.12077 20.25L8.43406 18.3536C6.97595 17.964 5.58693 17.3357 4.31689 16.4832L5.10228 15.3069C7.15122 16.6822 9.54509 17.4092 12.0251 17.4092C14.5051 17.4092 16.9067 16.6822 18.9701 15.3069L19.7431 16.4832C18.4641 17.3357 17.0684 17.964 15.6062 18.3536L16.8995 20.25C22.0414 20.25 23.9452 17.0131 24.0279 16.8843C24.0161 16.7045 23.69 12.2208 22.7861 9.04256ZM8.79853 12.7392H7.39228L7.40468 10.3841H8.81093L8.79853 12.7392ZM16.7071 12.7392H15.3008L15.3132 10.3841H16.7195L16.7071 12.7392Z"
fill="#151512"
/>
</svg>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
</header>
<main class="bg-white text-black flex flex-col"><section
class="
container
max-w-screen-xl
flex flex-col
sm:flex-row
pt-10
pb-0
md:pb-10
lg:pb-0
"
>
<div
class="
heading-block
w-full
sm:w-2/12
lg:w-3/12
flex
lg:justify-center
items-start
pb-3
sm:pb-0
"
>
<a class="link link--back" href="/research-log/">Back</a>
</div>
<div
class="info-block w-full sm:w-10/12 lg:w-9/12 pb-5 sm:pb-10 overflow-hidden"
>
<div class="post mb-10">
<h1 class="text-xl md:text-xxl mb-5 sm:max-w-md lg:max-w-2xl">
Privacy-preserving p2p economic spam protection in Waku v2
</h1>
<div>
<span class="text-s lg:text-base">
05 Mar 2021 • by
</span>
<a
href="/authors/sanaztaheri"
class="text-s lg:text-base font-bold hover:underline"
>sanaztaheri</a
>
</div>
</div>
<div class="post__content"><h1 id="introduction">Introduction</h1>
<p>This post is going to give you an overview of how spam protection can be achieved in Waku Relay protocol<sup id="fnref:2" role="doc-noteref"><a href="#fn:2" class="footnote" rel="footnote">1</a></sup> through Rate-Limiting Nullifiers<sup id="fnref:3" role="doc-noteref"><a href="#fn:3" class="footnote" rel="footnote">2</a></sup> <sup id="fnref:4" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">3</a></sup> or RLN for short.</p>
<p>Let me give a little background about Waku(v2)<sup id="fnref:1" role="doc-noteref"><a href="#fn:1" class="footnote" rel="footnote">4</a></sup>. Waku is a privacy-preserving peer-to-peer (p2p) messaging protocol for resource-restricted devices. Being p2p means that Waku relies on <strong>No</strong> central server. Instead, peers collaboratively deliver messages in the network. Waku uses GossipSub<sup id="fnref:16" role="doc-noteref"><a href="#fn:16" class="footnote" rel="footnote">5</a></sup> as the underlying routing protocol (as of the writeup of this post). At a high level, GossipSub is based on publisher-subscriber architecture. That is, <em>peers, congregate around topics they are interested in and can send messages to topics. Each message gets delivered to all peers subscribed to the topic</em>. In GossipSub, a peer has a constant number of direct connections/neighbors. In order to publish a message, the author forwards its message to a subset of neighbors. The neighbors proceed similarly till the message gets propagated in the network of the subscribed peers. The message publishing and routing procedures are part of the Waku Relay<sup id="fnref:17" role="doc-noteref"><a href="#fn:17" class="footnote" rel="footnote">6</a></sup> protocol.</p>
<p align="center">
<img src="../assets/img/rln-relay-overview.png" width="200%" />
<br />
Figure 1: An overview of privacy-preserving p2p economic spam protection in Waku v2 RLN-Relay protocol.
</p>
<h2 id="what-do-we-mean-by-spamming">What do we mean by spamming?</h2>
<p>In centralized messaging systems, a spammer usually indicates an entity that uses the messaging system to send an unsolicited message (spam) to large numbers of recipients. However, in Waku with a p2p architecture, spam messages not only affect the recipients but also all the other peers involved in the routing process as they have to spend their computational power/bandwidth/storage capacity on processing spam messages. As such, we define a spammer as an entity that uses the messaging system to publish a large number of messages in a short amount of time. The messages issued in this way are called spam. In this definition, we disregard the intention of the spammer as well as the content of the message and the number of recipients.</p>
<h2 id="possible-solutions">Possible Solutions</h2>
<p>Has the spamming issue been addressed before? Of course yes! Here is an overview of the spam protection techniques with their trade-offs and use-cases. In this overview, we distinguish between protection techniques that are targeted for centralized messaging systems and those for p2p architectures.</p>
<h3 id="centralized-messaging-systems">Centralized Messaging Systems</h3>
<p>In traditional centralized messaging systems, spam usually signifies unsolicited messages sent in bulk or messages with malicious content like malware. Protection mechanisms include</p>
<ul>
<li>authentication through some piece of personally identifiable information e.g., phone number</li>
<li>checksum-based filtering to protect against messages sent in bulk</li>
<li>challenge-response systems</li>
<li>content filtering on the server or via a proxy application</li>
</ul>
<p>These methods exploit the fact that the messaging system is centralized and a global view of the users activities is available based on which spamming patterns can be extracted and defeated accordingly. Moreover, users are associated with an identifier e.g., a username which enables the server to profile each user e.g., to detect suspicious behavior like spamming. Such profiling possibility is against the users anonymity and privacy.</p>
<p>Among the techniques enumerated above, authentication through phone numbers is a some-what economic-incentive measure as providing multiple valid phone numbers will be expensive for the attacker. Notice that while using an expensive authentication method can reduce the number of accounts owned by a single spammer, cannot address the spam issue entirely. This is because the spammer can still send bulk messages through one single account. For this approach to be effective, a centralized mediator is essential. That is why such a solution would not fit the p2p environments where no centralized control exists.</p>
<h3 id="p2p-systems">P2P Systems</h3>
<p>What about spam prevention in p2p messaging platforms? There are two techniques, namely <em>Proof of Work</em><sup id="fnref:8" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">7</a></sup> deployed by Whisper<sup id="fnref:9" role="doc-noteref"><a href="#fn:9" class="footnote" rel="footnote">8</a></sup> and <em>Peer scoring</em><sup id="fnref:6" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">9</a></sup> method (namely reputation-based approach) adopted by LibP2P. However, each of these solutions has its own shortcomings for real-life use-cases as explained below.</p>
<h4 id="proof-of-work">Proof of work</h4>
<p>The idea behind the Proof Of Work i.e., POW<sup id="fnref:8:1" role="doc-noteref"><a href="#fn:8" class="footnote" rel="footnote">7</a></sup> is to make messaging a computationally costly operation hence lowering the messaging rate of <strong>all</strong> the peers including the spammers. In specific, the message publisher has to solve a puzzle and the puzzle is to find a nonce such that the hash of the message concatenated with the nonce has at least z leading zeros. z is known as the difficulty of the puzzle. Since the hash function is one-way, peers have to brute-force to find a nonce. Hashing is a computationally-heavy operation so is the brute-force. While solving the puzzle is computationally expensive, it is comparatively cheap to verify the solution.</p>
<p>POW is also used as the underlying mining algorithm in Ethereum and Bitcoin blockchain. There, the goal is to contain the mining speed and allow the decentralized network to come to a consensus, or agree on things like account balances and the order of transactions.</p>
<p>While the use of POW makes perfect sense in Ethereum / Bitcoin blockchain, it shows practical issues in heterogeneous p2p messaging systems with resource-restricted peers. Some peers wont be able to carry the designated computation and will be effectively excluded. Such exclusion showed to be practically an issue in applications like Status, which used to rely on POW for spam-protection, to the extent that the difficulty level had to be set close to zero.</p>
<h4 id="peer-scoring">Peer Scoring</h4>
<p>The peer scoring method<sup id="fnref:6:1" role="doc-noteref"><a href="#fn:6" class="footnote" rel="footnote">9</a></sup> that is utilized by libp2p is to limit the number of messages issued by a peer in connection to another peer. That is each peer monitors all the peers to which it is directly connected and adjusts their messaging quota i.e., to route or not route their messages depending on their past activities. For example, if a peer detects its neighbor is sending more than x messages per month, can drop its quota to z.x where z is less than one. The shortcoming of this solution is that scoring is based on peers local observations and the concept of the score is defined in relation to one single peer. This leaves room for an attack where a spammer can make connections to k peers in the system and publishes k.(x-1) messages by exploiting all of its k connections. Another attack scenario is through botnets consisting of a large number of e.g., a million bots. The attacker rents a botnet and inserts each of them as a legitimate peer to the network and each can publish x-1 messages per month<sup id="fnref:7" role="doc-noteref"><a href="#fn:7" class="footnote" rel="footnote">10</a></sup>.</p>
<h4 id="economic-incentive-spam-protection">Economic-Incentive Spam protection</h4>
<p>Is this the end of our spam-protection journey? Shall we simply give up and leave spammers be? Certainly not!
Waku RLN-Relay gives us a p2p spam-protection method which:</p>
<ul>
<li>suits <strong>p2p</strong> systems and does not rely on any central entity.</li>
<li>is <strong>efficient</strong> i.e., with no unreasonable computational, storage, memory, and bandwidth requirement! as such, it fits the network of <strong>heterogeneous</strong> peers.</li>
<li>respects users <strong>privacy</strong> unlike reputation-based and centralized methods.</li>
<li>deploys <strong>economic-incentives</strong> to contain spammers activity. Namely, there is a financial sacrifice for those who want to spam the system. How? follow along …</li>
</ul>
<p>We devise a general rule to save everyones life and that is</p>
<p><strong>No one can publish more than M messages per epoch without being financially charged!</strong></p>
<p>We set M to 1 for now, but this can be any arbitrary value. You may be thinking “This is too restrictive! Only one per epoch?”. Dont worry, we set the epoch to a reasonable value so that it does not slow down the communication of innocent users but will make the life of spammers harder! Epoch here can be every second, as defined by UTC date-time +-20s.</p>
<p>The remainder of this post is all about the story of how to enforce this limit on each users messaging rate as well as how to impose the financial cost when the limit gets violated. This brings us to the Rate Limiting Nullifiers and how we integrate this technique into Waku v2 (in specific the Waku Relay protocol) to protect our valuable users against spammers.</p>
<h1 id="technical-terms">Technical Terms</h1>
<p><strong>Zero-knowledge proof</strong>: Zero-knowledge proof (ZKP)<sup id="fnref:14" role="doc-noteref"><a href="#fn:14" class="footnote" rel="footnote">11</a></sup> allows a <em>prover</em> to show a <em>verifier</em> that they know something, without revealing what that something is. This means you can do the trust-minimized computation that is also privacy-preserving. As a basic example, instead of showing your ID when going to a bar you simply give them proof that you are over 18, without showing the doorman your id. In this write-up, by ZKP we essentially mean zkSNARK<sup id="fnref:15" role="doc-noteref"><a href="#fn:15" class="footnote" rel="footnote">12</a></sup> which is one of the many types of ZKPs.</p>
<p><strong>Threshold Secret Sharing Scheme</strong>: (m,n) Threshold secret-sharing is a method by which you can split a secret value s into n pieces in a way that the secret s can be reconstructed by having m pieces (m &lt;= n). The economic-incentive spam protection utilizes a (2,n) secret sharing realized by Shamir Secret Sharing Scheme<sup id="fnref:13" role="doc-noteref"><a href="#fn:13" class="footnote" rel="footnote">13</a></sup>.</p>
<h1 id="overview-economic-incentive-spam-protection-through-rate-limiting-nullifiers">Overview: Economic-Incentive Spam protection through Rate Limiting Nullifiers</h1>
<p><strong>Context</strong>: We started the idea of economic-incentive spam protection more than a year ago and conducted a feasibility study to identify blockers and unknowns. The results are published in our prior <a href="https://vac.dev/feasibility-semaphore-rate-limiting-zksnarks">post</a>. Since then major progress has been made and the prior identified blockers that are listed below are now addressed. Kudos to <a href="https://github.com/barryWhiteHat">Barry WhiteHat</a>, <a href="https://github.com/kilic">Onur Kilic</a>, <a href="https://github.com/weijiekoh/perpetualpowersoftau">Koh Wei Jie</a> for all of their hard work, research, and development which made this progress possible.</p>
<ul>
<li>the proof time<sup id="fnref:22" role="doc-noteref"><a href="#fn:22" class="footnote" rel="footnote">14</a></sup> which was initially in the order of minutes ~10 mins and now is almost 0.5 seconds</li>
<li>the prover key size<sup id="fnref:21" role="doc-noteref"><a href="#fn:21" class="footnote" rel="footnote">15</a></sup> which was initially ~110MB and now is ~3.9MB</li>
<li>the lack of Shamir logic<sup id="fnref:19" role="doc-noteref"><a href="#fn:19" class="footnote" rel="footnote">16</a></sup> which is now implemented and part of the RLN repository<sup id="fnref:4:1" role="doc-noteref"><a href="#fn:4" class="footnote" rel="footnote">3</a></sup></li>
<li>the concern regarding the potential multi-party computation for the trusted setup of zkSNARKs which got resolved<sup id="fnref:20" role="doc-noteref"><a href="#fn:20" class="footnote" rel="footnote">17</a></sup></li>
<li>the lack of end-to-end integration that now we made it possible, have it implemented, and are going to present it in this post. New blockers are also sorted out during the e2e integration which we will discuss in the <a href="#feasibility-and-open-issues">Feasibility and Open Issues</a> section.</li>
</ul>
<p>Now that you have more context, lets see how the final solution works. The fundamental point is to make it economically costly to send more than your share of messages and to do so in a privacy-preserving and e2e fashion. To do that we have the following components:</p>
<ul>
<li>1- <strong>Group</strong>: We manage all the peers inside a large group (later we can split peers into smaller groups, but for now consider only one). The group management is done via a smart contract which is devised for this purpose and is deployed on the Ethereum blockchain.</li>
<li>2- <strong>Membership</strong>: To be able to send messages and in specific for the published messages to get routed by all the peers, publishing peers have to register to the group. Membership involves setting up public and private key pairs (think of it as the username and password). The private key remains at the user side but the public key becomes a part of the group information on the contract (publicly available) and everyone has access to it. Public keys are not human-generated (like usernames) and instead they are random numbers, as such, they do not reveal any information about the owner (think of public keys as pseudonyms). Registration is mandatory for the users who want to publish a message, however, users who only want to listen to the messages are more than welcome and do not have to register in the group.</li>
<li><strong>Membership fee</strong>: Membership is not for free! each peer has to lock a certain amount of funds during the registration (this means peers have to have an Ethereum account with sufficient balance for this sake). This fund is safely stored on the contract and remains intact unless the peer attempts to break the rules and publish more than one message per epoch.</li>
<li><strong>Zero-knowledge Proof of membership</strong>: Do you want your message to get routed to its destination, fine, but you have to prove that you are a member of the group (sorry, no one can escape the registration phase!). Now, you may be thinking that should I attach my public key to my message to prove my membership? Absolutely Not! we said that our solution respects privacy! membership proofs are done in a zero-knowledge manner that is each message will carry cryptographic proof asserting that “the message is generated by one of the current members of the group”, so your identity remains private and your anonymity is preserved!</li>
<li><strong>Slashing through secret sharing</strong>: Till now it does not seem like we can catch spammers, right? yes, you are right! now comes the exciting part, detecting spammers and slashing them. The core idea behind the slashing is that each publishing peer (not routing peers!) has to integrate a secret share of its private key inside the message. The secret share is deterministically computed over the private key and the current epoch. The content of this share is harmless for the peers privacy (it looks random) unless the peer attempts to publish more than one message in the same epoch hence disclosing more than one secret share of its private key. Indeed two distinct shares of the private key under the same epoch are enough to reconstruct the entire private key. Then what should you do with the recovered private key? hurry up! go to the contract and withdraw the private key and claim its fund and get rich!! Are you thinking what if spammers attach junk values instead of valid secret shares? Of course, that wouldnt be cool! so, there is a zero-knowledge proof for this sake as well where the publishing peer has to prove that the secret shares are generated correctly.</li>
</ul>
<p>A high-level overview of the economic spam protection is shown in Figure 1.</p>
<h1 id="flow">Flow</h1>
<p>In this section, we describe the flow of the economic-incentive spam detection mechanism from the viewpoint of a single peer. An overview of this flow is provided in Figure 3.</p>
<h2 id="setup-and-registration">Setup and Registration</h2>
<p>A peer willing to publish a message is required to register. Registration is moderated through a smart contract deployed on the Ethereum blockchain. The state of the contract contains the list of registered members public keys. An overview of registration is illustrated in Figure 2.</p>
<p>For the registration, a peer creates a transaction that sends x amount of Ether to the contract. The peer who has the “private key” <code class="language-plaintext highlighter-rouge">sk</code> associated with that deposit would be able to withdraw x Ether by providing valid proof. Note that <code class="language-plaintext highlighter-rouge">sk</code> is initially only known by the owning peer however it may get exposed to other peers in case the owner attempts spamming the system i.e., sending more than one message per epoch.
The following relation holds between the <code class="language-plaintext highlighter-rouge">sk</code> and <code class="language-plaintext highlighter-rouge">pk</code> i.e., <code class="language-plaintext highlighter-rouge">pk = H(sk)</code> where <code class="language-plaintext highlighter-rouge">H</code> denotes a hash function.</p>
<p align="center">
<img src="../assets/img/rln-relay.png" />
<br />
Figure 2: Registration.
</p>
<h2 id="maintaining-the-membership-merkle-tree">Maintaining the membership Merkle Tree</h2>
<p>The ZKP of membership that we mentioned before relies on the representation of the entire group as a <a href="">Merkle Tree</a>. The tree construction and maintenance is delegated to the peers (the initial idea was to keep the tree on the chain as part of the contract, however, the cost associated with member deletion and insertion was high and unreasonable, please see <a href="#Feasibility-and-Open-Issues">Feasibility and Open Issues</a> for more details). As such, each peer needs to build the tree locally and sync itself with the contract updates (peer insertion and deletion) to mirror them on its tree.
Two pieces of information of the tree are important as they enable peers to generate zero-knowledge proofs. One is the root of the tree and the other is the membership proof (or the authentication path). The tree root is public information whereas the membership proof is private data (or more precisely the index of the peer in the tree).</p>
<h2 id="publishing">Publishing</h2>
<p>In order to publish at a given epoch, each message must carry a proof i.e., a zero-knowledge proof signifying that the publishing peer is a registered member, and has not exceeded the messaging rate at the given epoch.</p>
<p>Recall that the enforcement of the messaging rate was through associating a secret shared version of the peers <code class="language-plaintext highlighter-rouge">sk</code> into the message together with a ZKP that the secret shares are constructed correctly. As for the secret sharing part, the peer generates the following data:</p>
<ol>
<li><code class="language-plaintext highlighter-rouge">shareX</code></li>
<li><code class="language-plaintext highlighter-rouge">shareY</code></li>
<li><code class="language-plaintext highlighter-rouge">nullifier</code></li>
</ol>
<p>The pair (<code class="language-plaintext highlighter-rouge">shareX</code>, <code class="language-plaintext highlighter-rouge">shareY</code>) is the secret shared version of <code class="language-plaintext highlighter-rouge">sk</code> that are generated using Shamir secret sharing scheme. Having two such pairs for an identical <code class="language-plaintext highlighter-rouge">nullifier</code> results in full disclosure of peers <code class="language-plaintext highlighter-rouge">sk</code> and hence burning the associated deposit. Note that the <code class="language-plaintext highlighter-rouge">nullifier</code> is a deterministic value derived from <code class="language-plaintext highlighter-rouge">sk</code> and <code class="language-plaintext highlighter-rouge">epoch</code> therefore any two messages issued by the same peer (i.e., using the same <code class="language-plaintext highlighter-rouge">sk</code>) for the same <code class="language-plaintext highlighter-rouge">epoch</code> are guaranteed to have identical <code class="language-plaintext highlighter-rouge">nullifier</code>s.</p>
<p>Finally, the peer generates a zero-knowledge proof <code class="language-plaintext highlighter-rouge">zkProof</code> asserting the membership of the peer in the group and the correctness of the attached secret share (<code class="language-plaintext highlighter-rouge">shareX</code>, <code class="language-plaintext highlighter-rouge">shareY</code>) and the <code class="language-plaintext highlighter-rouge">nullifier</code>. In order to generate a valid proof, the peer needs to have two private inputs i.e., its <code class="language-plaintext highlighter-rouge">sk</code> and its authentication path. Other inputs are the tree root, epoch, and the content of the message.</p>
<p><strong>Privacy Hint:</strong> Note that the authentication path of each peer depends on the recent list of members (hence changes when new peers register or leave). As such, it is recommended (and necessary for privacy/anonymity) that the publisher updates her authentication path based on the latest status of the group and attempts the proof using the updated version.</p>
<p>An overview of the publishing procedure is provided in Figure 3.</p>
<h2 id="routing">Routing</h2>
<p>Upon the receipt of a message, the routing peer needs to decide whether to route it or not. This decision relies on the following factors:</p>
<ol>
<li>If the epoch value attached to the message has a non-reasonable gap with the routing peers current epoch then the message must be dropped (this is to prevent a newly registered peer spamming the system by messaging for all the past epochs).</li>
<li>The message MUST contain valid proof that gets verified by the routing peer.
If the preceding checks are passed successfully, then the message is relayed. In case of an invalid proof, the message is dropped. If spamming is detected, the publishing peer gets slashed (see <a href="#Spam-Detection-and-Slashing">Spam Detection and Slashing</a>).</li>
</ol>
<p>An overview of the routing procedure is provided in Figure 3.</p>
<h3 id="spam-detection-and-slashing">Spam Detection and Slashing</h3>
<p>In order to enable local spam detection and slashing, routing peers MUST record the <code class="language-plaintext highlighter-rouge">nullifier</code>, <code class="language-plaintext highlighter-rouge">shareX</code>, and <code class="language-plaintext highlighter-rouge">shareY</code> of any incoming message conditioned that it is not spam and has valid proof. To do so, the peer should follow the following steps.</p>
<ol>
<li>The routing peer first verifies the <code class="language-plaintext highlighter-rouge">zkProof</code> and drops the message if not verified.</li>
<li>Otherwise, it checks whether a message with an identical <code class="language-plaintext highlighter-rouge">nullifier</code> has already been relayed.
<ul>
<li>a) If such message exists and its <code class="language-plaintext highlighter-rouge">shareX</code> and <code class="language-plaintext highlighter-rouge">shareY</code> components are different from the incoming message, then slashing takes place (if the <code class="language-plaintext highlighter-rouge">shareX</code> and <code class="language-plaintext highlighter-rouge">shareY</code> fields of the previously relayed message is identical to the incoming message, then the message is a duplicate and shall be dropped).</li>
<li>b) If none found, then the message gets relayed.</li>
</ul>
</li>
</ol>
<p>An overview of the slashing procedure is provided in Figure 3.</p>
<p align="center">
<img src="../assets/img/rln-message-verification.png" />
<br />
Figure 3: Publishing, Routing and Slashing workflow.
</p>
<h1 id="feasibility-and-open-issues">Feasibility and Open Issues</h1>
<p>Weve come a long way since a year ago, blockers resolved, now we have implemented it end-to-end. We learned lot and could identify further issues and unknowns some of which are blocking getting to production. The summary of the identified issues are presented below.</p>
<h2 id="storage-overhead-per-peer">Storage overhead per peer</h2>
<p>Currently, peers are supposed to maintain the entire tree locally and it imposes storage overhead which is linear in the size of the group (see this <a href="https://github.com/vacp2p/research/issues/57">issue</a><sup id="fnref:11" role="doc-noteref"><a href="#fn:11" class="footnote" rel="footnote">18</a></sup> for more details). One way to cope with this is to use the light-node and full-node paradigm in which only a subset of peers who are more resourceful retain the tree whereas the light nodes obtain the necessary information by interacting with the full nodes. Another way to approach this problem is through a more storage efficient method (as described in this research issue<sup id="fnref:12" role="doc-noteref"><a href="#fn:12" class="footnote" rel="footnote">19</a></sup>) where peers store a partial view of the tree instead of the entire tree. Keeping the partial view lowers the storage complexity to O(log(N)) where N is the size of the group. There are still unknown unknowns to this solution, as such, it must be studied further to become fully functional.</p>
<h2 id="cost-effective-way-of-member-insertion-and-deletion">Cost-effective way of member insertion and deletion</h2>
<p>Currently, the cost associated with RLN-Relay membership is around 30 USD<sup id="fnref:10" role="doc-noteref"><a href="#fn:10" class="footnote" rel="footnote">20</a></sup>. We aim at finding a more cost-effective approach. Please feel free to share with us your solution ideas in this regard in this <a href="https://github.com/vacp2p/research/issues/56">issue</a>.</p>
<h2 id="exceeding-the-messaging-rate-via-multiple-registrations">Exceeding the messaging rate via multiple registrations</h2>
<p>While the economic-incentive solution has an economic incentive to discourage spamming, we should note that there is still <strong>expensive attack(s)</strong><sup id="fnref:23" role="doc-noteref"><a href="#fn:23" class="footnote" rel="footnote">21</a></sup> that a spammer can launch to break the messaging rate limit. That is, the attacker can pay for multiple legit registrations e.g., k, hence being able to publish k messages per epoch. We believe that the higher the membership fee is, the less probable would be such an attack, hence a stronger level of spam-protection can be achieved. Following this argument, the high fee associated with the membership (which we listed above as an open problem) can indeed be contributing to a better protection level.</p>
<h1 id="conclusion-and-future-steps">Conclusion and Future Steps</h1>
<p>As discussed in this post, Waku RLN Relay can achieve a privacy-preserving economic spam protection through rate-limiting nullifiers. The idea is to financially discourage peers from publishing more than one message per epoch. In specific, exceeding the messaging rate results in a financial charge. Those who violate this rule are called spammers and their messages are spam. The identification of spammers does not rely on any central entity. Also, the financial punishment of spammers is cryptographically guaranteed.
In this solution, privacy is guaranteed since: 1) Peers do not have to disclose any piece of personally identifiable information in any phase i.e., neither in the registration nor in the messaging phase 2) Peers can prove that they have not exceeded the messaging rate in a zero-knowledge manner and without leaving any trace to their membership accounts.
Furthermore, all the computations are light hence this solution fits the heterogenous p2p messaging system. Note that the zero-knowledge proof parts are handled through zkSNARKs and the benchmarking result can be found in the RLN benchmark report<sup id="fnref:5" role="doc-noteref"><a href="#fn:5" class="footnote" rel="footnote">22</a></sup>.</p>
<p><strong>Future steps</strong>: We are still at the PoC level, and the development is in progress. As our future steps,</p>
<ul>
<li>we would like to evaluate the running time associated with the Merkle tree operations. Indeed, the need to locally store Merkle tree on each peer was one of the unknowns discovered during this PoC and yet the concrete benchmarking result in this regard is not available.</li>
<li>We would also like to pursue our storage-efficient Merkle Tree maintenance solution in order to lower the storage overhead of peers.</li>
<li>In line with the storage optimization, the full-node light-node structure is another path to follow.</li>
<li>Another possible improvement is to replace the membership contract with a distributed group management scheme e.g., through distributed hash tables. This is to address possible performance issues that the interaction with the Ethereum blockchain may cause. For example, the registration transactions are subject to delay as they have to be mined before being visible in the state of the membership contract. This means peers have to wait for some time before being able to publish any message.</li>
</ul>
<h1 id="acknowledgement">Acknowledgement</h1>
<p>Thanks to Onur Kılıç for his explanation and pointers and for assisting with development and runtime issues. Also thanks to Barry Whitehat for his time and insightful comments. Special thanks to Oskar Thoren for his constructive comments and his guides during the development of this PoC and the writeup of this post.</p>
<h1 id="references">References</h1>
<div class="footnotes" role="doc-endnotes">
<ol>
<li id="fn:2" role="doc-endnote">
<p>RLN-Relay specifications: <a href="https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-rln-relay.md">https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-rln-relay.md</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:3" role="doc-endnote">
<p>RLN documentation: <a href="https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?both">https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?both</a> <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:4" role="doc-endnote">
<p>RLN repositories: <a href="https://github.com/kilic/RLN">https://github.com/kilic/RLN</a> and <a href="https://github.com/kilic/rlnapp">https://github.com/kilic/rlnapp</a> <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:4:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
</li>
<li id="fn:1" role="doc-endnote">
<p>Waku v2: <a href="https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-v2.md">https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-v2.md</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:16" role="doc-endnote">
<p>GossipSub: <a href="https://docs.libp2p.io/concepts/publish-subscribe/">https://docs.libp2p.io/concepts/publish-subscribe/</a> <a href="#fnref:16" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:17" role="doc-endnote">
<p>Waku Relay: <a href="https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-relay.md">https://github.com/vacp2p/specs/blob/master/specs/waku/v2/waku-relay.md</a> <a href="#fnref:17" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:8" role="doc-endnote">
<p>Proof of work: <a href="http://www.infosecon.net/workshop/downloads/2004/pdf/clayton.pdf">http://www.infosecon.net/workshop/downloads/2004/pdf/clayton.pdf</a> and <a href="https://link.springer.com/content/pdf/10.1007/3-540-48071-4_10.pdf">https://link.springer.com/content/pdf/10.1007/3-540-48071-4_10.pdf</a> <a href="#fnref:8" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:8:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
</li>
<li id="fn:9" role="doc-endnote">
<p>Whisper: <a href="Whisper: https://eips.ethereum.org/EIPS/eip-627">https://eips.ethereum.org/EIPS/eip-627</a> <a href="#fnref:9" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:6" role="doc-endnote">
<p>Peer Scoring: <a href="https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#peer-scoring">https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md#peer-scoring</a> <a href="#fnref:6" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:6:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
</li>
<li id="fn:7" role="doc-endnote">
<p>Peer scoring security issues: <a href="https://github.com/vacp2p/research/issues/44">https://github.com/vacp2p/research/issues/44</a> <a href="#fnref:7" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:14" role="doc-endnote">
<p>Zero Knowledge Proof: <a href="https://dl.acm.org/doi/abs/10.1145/3335741.3335750">https://dl.acm.org/doi/abs/10.1145/3335741.3335750</a> and <a href="https://en.wikipedia.org/wiki/Zero-knowledge_proof">https://en.wikipedia.org/wiki/Zero-knowledge_proof</a> <a href="#fnref:14" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:15" role="doc-endnote">
<p>zkSNARKs: <a href="https://link.springer.com/chapter/10.1007/978-3-662-49896-5_11">https://link.springer.com/chapter/10.1007/978-3-662-49896-5_11</a> and <a href="https://coinpare.io/whitepaper/zcash.pdf">https://coinpare.io/whitepaper/zcash.pdf</a> <a href="#fnref:15" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:13" role="doc-endnote">
<p>Shamir Secret Sharing Scheme: <a href="https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing">https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing</a> <a href="#fnref:13" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:22" role="doc-endnote">
<p>zkSNARKs proof time: <a href="https://github.com/vacp2p/research/issues/7">https://github.com/vacp2p/research/issues/7</a> <a href="#fnref:22" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:21" role="doc-endnote">
<p>Prover key size: <a href="https://github.com/vacp2p/research/issues/8">https://github.com/vacp2p/research/issues/8</a> <a href="#fnref:21" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:19" role="doc-endnote">
<p>The lack of Shamir secret sharing in zkSNARKs: <a href="https://github.com/vacp2p/research/issues/10">https://github.com/vacp2p/research/issues/10</a> <a href="#fnref:19" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:20" role="doc-endnote">
<p>The MPC required for zkSNARKs trusted setup: <a href="https://github.com/vacp2p/research/issues/9">https://github.com/vacp2p/research/issues/9</a> <a href="#fnref:20" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:11" role="doc-endnote">
<p>Storage overhead per peer: <a href="https://github.com/vacp2p/research/issues/57">https://github.com/vacp2p/research/issues/57</a> <a href="#fnref:11" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:12" role="doc-endnote">
<p>Storage-efficient Merkle Tree maintenance: <a href="https://github.com/vacp2p/research/pull/54">https://github.com/vacp2p/research/pull/54</a> <a href="#fnref:12" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:10" role="doc-endnote">
<p>Cost-effective way of member insertion and deletion: <a href="https://github.com/vacp2p/research/issues/56">https://github.com/vacp2p/research/issues/56</a> <a href="#fnref:10" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:23" role="doc-endnote">
<p>Attack on the messaging rate: <a href="https://github.com/vacp2p/specs/issues/251">https://github.com/vacp2p/specs/issues/251</a> <a href="#fnref:23" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
<li id="fn:5" role="doc-endnote">
<p>RLN Benchmark: <a href="https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Benchmarks">https://hackmd.io/tMTLMYmTR5eynw2lwK9n1w?view#Benchmarks</a> <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
</li>
</ol>
</div>
</div>
</div>
</section>
</main>
</div>
<footer class="footer bg-black flex flex-shrink-0 justify-center">
<div
class="
container
max-w-screen-xl
flex
sl:justify-between
lm:justify-start
p-5
pb-10
md:px-12 md:pt-5
lg:pt-10
"
>
<div class="logo mr-10 sm:mr-0 sm:w-2/12 lg:w-3/12">
<a href="/"
><img
src="/assets/img/logo.png"
alt="Vac logo"
class="w-9 h-11"
/></a>
</div>
<div
class="flex flex-col xm:flex-row xm:justify-between sm:w-10/12 lg:w-9/12"
>
<p
class="
hidden
ml:inline-block ml:mr-10
w-52
text-base text-white
opacity-75
lm:mr-32
"
>
VAC researches peer-to-peer, private, censorship resistant communication
</p>
<nav class="flex max-w-xs mr-0 xm:mr-5 l:mr-32 mb-5 sm:mb-0">
<div class="flex">
<div class="flex flex-col mr-5 sm:mr-10 sl:mr-14">
<p class="text-base text-white mb-5 lg:mb-4">Research</p>
<ul>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://status.im/" target="_blank" rel="noopener noreferrer"
>Log</a
>
</li>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://forum.vac.dev/" target="_blank" rel="noopener noreferrer"
>Forum</a
>
</li>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://status.im/" target="_blank" rel="noopener noreferrer"
>Media</a
>
</li>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://jobs.status.im/?search=Vac" target="_blank" rel="noopener noreferrer"
>Careers</a
>
</li>
</ul>
</div>
<div class="flex flex-col sl:mr-14">
<p class="text-base text-white mb-5 lg:mb-4 mr-5">Socials</p>
<ul>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://twitter.com/vacp2p" target="_blank" rel="noopener noreferrer"
>Twitter</a
>
</li>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://discord.gg/PQFdubGt6d" target="_blank" rel="noopener noreferrer"
>Discord</a
>
</li>
<li class="text-xxs lg:text-base text-white opacity-75 hover:opacity-50 mb-5">
<a href="https://t.me/vacp2p" target="_blank" rel="noopener noreferrer"
>Telegram</a
>
</li>
</ul>
</div>
</div></nav>
<div class="flex flex-col w-52">
<h3 class="text-base text-white mb-5">Signup for updates</h3>
<form action="" class="footer__form">
<div class="flex items-center w-full">
<input
class="
text-xs text-white
w-full
bg-black
border-b border-white
rounded-none
mr-2
focus:outline-none
placeholder-white placeholder-opacity-50
"
type="email"
placeholder="your email"
required
/>
<button
class="
h-10
w-10
bg-arrowWhite bg-auto bg-no-repeat bg-left
focus:outline-none
hover:opacity-50
"
type="submit"
></button>
</div>
</form>
<p
class="footer__confirm text-base italic text-white opacity-75 hidden"
>
You signed up! Check your e-mail
</p>
</div>
</div>
</div>
</footer>
<script src="/assets/js/main.js"></script>
<script src="/assets/js/smooth-scroll.js"></script>
</body>
</html>