<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://dankradfeist.de/feed.xml" rel="self" type="application/atom+xml" /><link href="https://dankradfeist.de/" rel="alternate" type="text/html" /><updated>2026-02-21T16:59:42+00:00</updated><id>https://dankradfeist.de/feed.xml</id><title type="html">Dankrad Feist</title><subtitle>Researcher at Tempo</subtitle><entry><title type="html">Minimmit: Simple and fast consensus</title><link href="https://dankradfeist.de/tempo/2025/12/31/minimmit-simple-fast-consensus.html" rel="alternate" type="text/html" title="Minimmit: Simple and fast consensus" /><published>2025-12-31T00:00:00+00:00</published><updated>2025-12-31T00:00:00+00:00</updated><id>https://dankradfeist.de/tempo/2025/12/31/minimmit-simple-fast-consensus</id><content type="html" xml:base="https://dankradfeist.de/tempo/2025/12/31/minimmit-simple-fast-consensus.html"><![CDATA[<p>Minimmit <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup> is a recently proposed blockchain consensus algorithm by Commonware. It falls into the new class of consensus protocols that require more than 80% of participants to be honest (rather than 2/3rds as in traditional asynchronous BFT protocols); in return, you get a lower latency protocol that achieves consensus after only one round of voting (this is called 2 rounds because the block proposal by the leader counts as the first round).</p>

<p>What I like about it is that it feels like a consensus algorithm properly designed for blockchain protocols: Leader rotation with chained proposals is integrated into the protocol rather than bolted on as an afterthought. This achieves a beautiful simplicity that has a cleaner feel than many traditional BFT algorithms. The separation of justification and finalization is one of the most difficult things to understand when first approaching BFT literature; and full leader rotation in the case of leader failure is often horribly complicated and incompletely described in papers and buggy in implementations. In Minimmit, it feels much more natural (assuming that you are coming from a blockchain context).</p>

<h2 id="quick-notes-on-this-article">Quick notes on this article</h2>

<p>My goal here is mostly to give an intuition for how Minimmit works and why it needs an 80% majority. Whenever I write 2/3rds majority, or 80% majority, it should be read as saying as requiring one extra vote, so 2 out of 3 is not enough to satisfy a 2/3rd majority but 3 out of 4 is and 7 out of 10 is.</p>

<h2 id="the-intuition-of-why-an-80-majority-is-needed">The intuition of why an 80% majority is needed</h2>

<p>If you want to finalize with a single round of voting, you need 80% of nodes to be honest: formally Minimmit uses \(n \geq 5f+1\), where \(n\) is the total number of nodes and \(f\) the number of byzantine failures tolerated, i.e. the number of nodes that can behave completely adversarially. This means strictly more than 80% of nodes need to be honest. The general tight lower bound for fast Byzantine consensus is actually \(n \geq 5f-1\) <sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>, which applies when proposers are a subset of acceptors. However, FaB Paxos <sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup> established that \(n \geq 5f+1\) is necessary for a specific class of protocols where proposers and acceptors are distinct sets. For a recent treatment in the blockchain context see Minimmit <sup id="fnref:1:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>.</p>

<p>A good way to understand why this is necessary is to understand that the leader, i.e. the block proposer, can be byzantine, and one of the things they can do is to propose several blocks at the same time, so honest nodes disagree on what to vote for. What we want to avoid is the leader being able to put the protocol into any bad state; the worst case would be finalizing two incompatible blocks (blocks that aren’t in the same chain), but we also can’t allow them to put the protocol into an unrecoverable state (i.e. a state where the protocol can’t automatically recover without manual intervention).</p>

<p>Here is an intuition why 2/3rds majority can’t do one round finalization. Assume we finalize a block if it gets 2/3rds of the votes. Let’s start with the easy part: An honest proposer proposes exactly one block. All honest nodes will vote for this. In a partially synchronous network all votes will eventually arrive at all the honest parties, so they will all see that 2/3rds have voted for the block. So far, so good.</p>

<p>However now we have to think about a malicious proposer. One thing they can do is not propose a block. The protocol needs to be able to detect this, so parties have to be able to vote for an empty slot (in Minimmit this is called nullify, so I will call it nullifying from here onward). If 2/3rds of the nodes vote to nullify the block, we can move on.</p>

<p>But unfortunately, the leader can do worse than just not proposing a block: They can also propose two different blocks at the same time. Now we will have a situation where about half the honest nodes vote for each proposal. In addition we have to remember that malicious nodes can vote twice, or not at all, or even withhold their votes until a later time to decide their action after seeing what the honest nodes are doing. Here they could temporarily lend some votes to the proposal with fewer votes to have it appear to have the majority of votes, like this:
<img src="/assets/minimmit-67.png" alt="Split vote with 33 honest votes voting for proposal A, 34 for proposal B, and the malicious nodes lending 2 votes to A to make it appear like the winning proposal" />
If the protocol uses the option with more votes to continue the chain it means that the next round is started on an unsound building block, because the malicious nodes would have the power to finalize the other option. The protocol designer faces an impossible choice:</p>
<ul>
  <li>Never continue until a proposal reaches 2/3rds of votes. In this case, the malicious proposer can stop the chain</li>
  <li>Continue with whichever proposal reaches the most votes. In this case, the malicious nodes may be able to finalize a different proposal with their remaining votes or by equivocating</li>
</ul>

<p>This is the conundrum that traditional BFT algorithms solve with justification. The first round of voting is to justify a block (which cements that it was properly proposed by a non-equivocating proposer). When a block has been justified (i.e., when f+1 correct nodes have seen a quorum of first-round votes in a timely fashion), honest nodes cannot vote for incompatible blocks in later views in protocols like PBFT <sup id="fnref:4"><a href="#fn:4" class="footnote" rel="footnote" role="doc-noteref">4</a></sup>. But this adds an extra round, which is what we want to avoid here.</p>

<p>This is the intuitive explanation why we can’t finalize with a 2/3rds majority in a single round.</p>

<h3 id="why-it-works-with-an-80-majority">Why it works with an 80% majority:</h3>

<p>Let’s change this, and require a greater than 80% (4/5ths) majority to finalize. As before, we don’t need to worry about the case where there’s an honest proposer.</p>

<p>Instead let’s look at the case where the proposer splits honest nodes. Let’s say we have the honest nodes about equally split between the two different proposals:
<img src="/assets/minimmit-81.png" alt="Split vote with 40 honest votes voting for proposal A, 41 for proposal B, and the malicious nodes lending 2 votes to A to make it appear like the winning proposal" /></p>

<p>Note an important difference now: The malicious nodes no longer hold the power to finalize either of the two. Adding their votes only gets them to 60% and not to 80%. This is good: It means we can move on with one of these options <em>without risking that the other will be finalized</em>, which would be bad. This lets us formulate more clearly what we want:</p>

<ul>
  <li>We need the next proposer to be able to infer a <em>safe</em> block to build on – or an empty (nullified) one. What we want is that if they are honest, their block will be finalized (and this can’t be contradicted by a conflicting block from the previous round being finalized)</li>
</ul>

<p>Minimmit does this using an M-notarization (M for mini), which is a set of more than 40% votes (or nullify votes). The important thing is that an M-notarization is not a finalization (called L-notarization in Minimmit, though I will just call it finalization). That’s because there can be several M-notarizations in the same slot. The best way to think is that it’s a signal by the protocol to the next proposer: “It’s safe to build on this block”:</p>
<ul>
  <li>It means in the slot of the M-notarization, no other proposal can be finalized</li>
  <li>If an honest proposer builds on an M-notarized proposal (or nullification), then their block will be finalized; in other words, if the next proposer (a) proposes on time and (b) does not equivocate then their proposal will be finalized</li>
</ul>

<p>The tricky part is now making sure that there always <em>is</em> an M-notarization for each slot; when there are only two options like in my constructed example, this is ok; but what if the proposer sends many different blocks, so there are now more options and none of them gets more than 40% of votes? This is solved by instructing honest nodes to also send a nullify message if they have already voted, but <em>only</em> if they have seen more than 40% votes that are either nullify votes or votes for a block that they didn’t vote for. This is safe because that condition means that the block they voted for can’t be finalized anymore; so they can safely vote to nullify this slot.</p>

<p>This idea is very cool, because it makes the protocol super simple: No special view change algorithms other than the one that is already built into the blockchain. And it’s also doubly fast: It can progress with only 40% of votes, and it can finalize after only one round of voting (with 80%) of votes coming in.</p>

<p>Now, let’s get back to the part why we need specifically more than 80% honest nodes, and not some smaller fraction like 75% (we have already seen that 2/3 is not enough). The key property we have used is that if an M-notarized proposal exists, then no other proposal can get finalized in the given round. Now, 20% of that could be the malicious nodes, so we really only know that more than 20% honest nodes have voted for this proposal. This means another just under 60% of the honest nodes could have voted for a different proposal. This is key: with the malicious nodes double voting for the second proposal, it can still only get to just under 80%, not enough to bring it over the edge and finalize it.</p>

<p>This being very close to the finalization threshold of 80% prevents us from lowering the honesty requirement. If we allowed 21% malicious nodes, the math wouldn’t work out: We now require 79% of votes to finalize (need to be able to finalize without the help of malicious nodes), and we would have to require \(100\% - 79\% + 21\% = 42\%\) to M-notarize. We also need to increase the threshold to send a nullify vote after already voting (the key to moving on with malicious proposers who do multiple proposals) to 42%. Now let’s say the malicious proposer sends two blocks, and the malicious votes don’t vote; there is a possibility they each get 39% of the honest votes. The protocol is now stuck: Neither side of the split votes would be able to nullify their votes, because they can’t see 42% votes for something else (only 39% are on the other side). This shows intuitively why we can only tolerate less than 20% nodes malicious with this protocol.</p>

<h2 id="description-of-the-protocol">Description of the protocol</h2>

<p>We are ready to give a description of the protocol. We assume a schedule of leaders pre-determined in another way (this is typically given in blockchain protocols, for example they can use a VRF (verifiable random function) to determine a random leader or simply rotate through all nodes).</p>

<p>Definitions:</p>
<ul>
  <li>A proposal is a block signed by the proposer of the current round. A block also refers to its ancestor, thus creating a chain of blocks.</li>
  <li>A vote is a message signed by a node that includes a hash of the proposal being voted for. It is signed by the voting node</li>
  <li>A nullify message is an alternative vote that says there was no valid proposal, or there are several valid proposals in this round. It only includes the round number and the node signature</li>
  <li>An M-notarization is a collection of more than 40% of the votes for a valid proposal; more than 40% of valid nullify messages for the current round are called a nullification</li>
  <li>A finalization is a collection of more than 80% of votes for a valid proposal</li>
  <li>A proposal is valid if it is a descendant of the last finalized block, all ancestors since the last finalized blocks are M-notarized or valid nullifications, and it bears the signature of the round leader (the blockchain protocol can add additional validity conditions)</li>
</ul>

<p>In each round:</p>
<ol>
  <li>The leader waits until they see an M-notarization for a valid proposal in the previous round (or a nullification)</li>
  <li>They propose a block based on this</li>
  <li>All nodes vote for the valid proposal that they see first, or to nullify if they don’t see a proposal within a time specified by the protocol</li>
  <li>If a node sees 40% of votes that are not for the proposal it voted for, it also votes to nullify the round.</li>
  <li>Nodes advance to the next round as soon as they see an M-notarization for the current round.</li>
</ol>

<p>The key is that for each round:</p>
<ul>
  <li>There is always an M-notarization or a nullification (so the protocol can always progress)</li>
  <li>If there are several options (several M-notarized proposals or an M-notarized proposal and a nullification), then none of these options can be finalized (this means it’s always safe to build on an M-notarization of a nullification)</li>
</ul>

<h2 id="is-m-notarization-similar-to-dynamic-availability">Is M-notarization similar to dynamic availability?</h2>

<p>In Ethereum, the idea of “dynamic availability” is that we can continue building a chain even if less than the consensus majority (in Ethereum’s case, 2/3rds) are online – this dynamically available chain is not safe against reorgs like a finalized chain, although it does provide some guarantees against minority attackers.</p>

<p>Assuming all online nodes are honest and under reasonable synchrony assumptions, Minimmit can build a chain with only 40% of nodes being online, similar to a dynamically available consensus. While it requires 40% of nodes being online (compared to being able to continue even with single-digit percentages in Ethereum), it’s still much better than most BFT protocols which fail as soon as fewer than 2/3rds of all nodes are online. It looks similar to ebb and flow constructions or Ethereum’s FFG+GHOST construction.</p>

<p>Let’s consider what happens when two different chains of M-notarizations are available, which can occur after a network partition. Suppose we have a partition where two sets of nodes (each with sufficient nodes to form M-notarizations) operate independently, with synchrony maintained within each partition but no communication between them. Since Minimmit doesn’t use fixed slot times but instead advances rounds when M-notarizations are seen, the two chains will likely advance at different rates, resulting in different round numbers.</p>

<p>When the partition is resolved and synchrony is restored, the next honest leader (assuming leaders are randomly selected and unknown to the adversary in advance) will see both chains. They can choose which chain to build on, and all honest nodes will vote for their proposal. However, if one chain has reached a higher round number (i.e., has more M-notarized rounds, not counting nullifications), then nodes following the shorter chain will have already advanced to match the longer chain’s round number as they see the missing M-notarizations. In this case, the leader has no choice but to build on the chain with the higher round number, so the partition resolves in favor of the chain that advanced faster.</p>

<p>This is not unlike Ethereum, where proposer boost <sup id="fnref:5"><a href="#fn:5" class="footnote" rel="footnote" role="doc-noteref">5</a></sup> had to be added in order to ensure that chain splits can always be resolved in the presence of an attacker who tries to balance the chains (adds their vote to always keep the votes split). In Minimmit, when chains have similar round numbers, the proposer acts as the arbiter; but when one chain is clearly longer (in terms of round numbers with M-notarizations), the protocol naturally favors it.</p>

<h2 id="references">References</h2>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>Chou, B. K., Lewis-Pye, A., &amp; O’Grady, P. (2025). <a href="https://arxiv.org/abs/2508.10862">Minimmit: Fast Finality with Even Faster Blocks</a>. Accepted to FC’26 (<a href="https://fc26.ifca.ai/">Financial Cryptography 2026</a>). <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a> <a href="#fnref:1:1" class="reversefootnote" role="doc-backlink">&#8617;<sup>2</sup></a></p>
    </li>
    <li id="fn:2">
      <p>Kuznetsov, P., Tonkikh, A., &amp; Zhang, Y. X. (2021). <a href="https://arxiv.org/abs/2102.12825">Revisiting Optimal Resilience of Fast Byzantine Consensus</a>. The authors show that \(5f-1\) is the tight lower bound for fast Byzantine consensus when proposers are a subset of acceptors, correcting earlier misconceptions. <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>Martin, J. P., &amp; Alvisi, L. (2006). <a href="https://www.cs.cornell.edu/lorenzo/papers/fab.pdf">Fast Byzantine Consensus</a>. <em>IEEE Transactions on Dependable and Secure Computing</em>, 3(3), 202-215. FaB Paxos established that at least 5f+1 replicas are necessary for two-step consensus protocols where proposers and acceptors are distinct sets. <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:4">
      <p>Castro, M., &amp; Liskov, B. (1999). <a href="https://www.usenix.org/legacy/events/osdi99/full_papers/castro/castro.pdf">Practical Byzantine Fault Tolerance</a>. In <em>OSDI</em> (Vol. 99, pp. 173-186). In PBFT, once a request is prepared (justified) in the prepare phase, honest replicas will not prepare conflicting requests in the same view. <a href="#fnref:4" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:5">
      <p>Proposer boost was introduced to prevent balancing attacks in Ethereum’s fork choice. The mechanism is specified in the <a href="https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/fork-choice.md#proposer-boost">Ethereum consensus specifications</a> and was discussed in the context of LMD GHOST fork choice. For the original discussion of balancing attacks and the need for proposer boost, see <a href="https://ethresear.ch/t/a-balancing-attack-on-gasper-the-current-candidate-for-eth2s-beacon-chain/8079/6">ethresear.ch discussions</a>. <a href="#fnref:5" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="tempo" /><category term="consensus" /><category term="english" /><summary type="html"><![CDATA[Minimmit 1 is a recently proposed blockchain consensus algorithm by Commonware. It falls into the new class of consensus protocols that require more than 80% of participants to be honest (rather than 2/3rds as in traditional asynchronous BFT protocols); in return, you get a lower latency protocol that achieves consensus after only one round of voting (this is called 2 rounds because the block proposal by the leader counts as the first round). Chou, B. K., Lewis-Pye, A., &amp; O’Grady, P. (2025). Minimmit: Fast Finality with Even Faster Blocks. Accepted to FC’26 (Financial Cryptography 2026). &#8617;]]></summary></entry><entry><title type="html">L1 Tokens</title><link href="https://dankradfeist.de/ethereum/2025/12/07/l1-tokens.html" rel="alternate" type="text/html" title="L1 Tokens" /><published>2025-12-07T00:00:00+00:00</published><updated>2025-12-07T00:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2025/12/07/l1-tokens</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2025/12/07/l1-tokens.html"><![CDATA[<h1 id="l1-tokens">L1 Tokens</h1>

<p>I’m not a trader. This post is just a summary of my views, not investment advice.</p>

<p>Something interesting has been happening to L1 token valuations: while on-chain activity continues to grow, many tokens have struggled to maintain their previous price levels. This disconnect suggests that the fundamental value proposition of these tokens may have shifted. Here’s my take on what’s going on.</p>

<h2 id="eth-was-money">ETH was money</h2>

<p>There has been a lot of debate about whether ETH is money, but if we look at the facts, the reality is that ETH was money.</p>

<p>In 2017, the first major product market fit of the Ethereum chain was ICOs. It was a crazy year with a lot of exuberance, but most importantly, ICOs collected their investments in ETH. Since ETH seemed to be up only, people as well as organizations kept large parts of their investments in ETH and even used it as a primary way to value their stashes.</p>

<p>2020/2021 brought another wave of adoption, centered around DeFi and NFTs. Again, ETH was front and center – remember when Christie’s and Sotheby’s started showing prices in ETH?</p>

<p>Retrospectively, this was the highest point of ETH adoption as money. In some aspects, it had achieved the trifecta:</p>
<ul>
  <li>Unit of Account (mostly for NFTs)</li>
  <li>Store of Value</li>
  <li>Medium of Exchange</li>
</ul>

<p>The velocity of money equation (MV = PQ, where M is money supply, V is velocity, P is price level, and Q is quantity of goods/services) tells us that when ETH is used as money, its market capitalization (proportional to M) should be proportional to the on-chain GDP (PQ), assuming velocity remains relatively constant. In other words, as the economic activity on Ethereum grows, so should ETH’s valuation if it continues to serve as the primary medium of exchange.</p>

<h2 id="eth-was-displaced-by-stablecoins">ETH was displaced by stablecoins</h2>

<p>Since 2021, time has been less kind to ETH: NFTs lost a lot of their value, and adoption as a medium of exchange has mostly been replaced by stablecoins:</p>

<p><img src="/assets/stablecoins_and_eth_transfers.png" alt="Stablecoins and ETH transfers" /></p>

<p>Ethereum is now rarely used as a medium of exchange or unit of account, when compared to the 2017-2021 period. This could be an explanation why appreciation of ETH seems to have stalled, while adoption is still growing.</p>

<h2 id="the-path-forward">The path forward</h2>

<p>ETH could escape this by:</p>
<ul>
  <li>Becoming a memetic store of value modeled after gold (and now maybe Bitcoin). However, this largely decouples it from the success of the Ethereum chain itself, and it is unclear if it will be perceived as much better than Bitcoin; the value for memetic stores of value is largely driven by brand and not technical properties</li>
  <li>Driving a massive campaign to re-establish ETH as money in the functions that it has lost</li>
  <li>Focusing on earning revenue and burning fees, aiming to have at least 10s of billions USD in revenue. This will require turning the EF into an effective R&amp;D and BD org, as well as finding ways to continuously fund those efforts</li>
</ul>

<p>Many L1s will face the same question. While their tokens don’t have a history of being used as money, they mostly attained their valuations by being seen as a potential replacement to Ethereum, with the implied assumption that their tokens would similarly be used as a medium of exchange. Solana did have some short success in this during the memecoin craze in early 2025, but it was even more short lived than the past drivers of Ethereum’s success.</p>

<h2 id="conclusion">Conclusion</h2>

<p>The challenge facing L1 tokens is that their historical valuations were largely predicated on their use as money – specifically as a medium of exchange. The velocity of money equation suggests that when a token serves this function, its valuation will track on-chain economic activity. However, the shift to stablecoins has broken this link for most L1 tokens.</p>

<p>This creates a valuation problem: if tokens are no longer used as money, what drives their value? The options are: either recapture the monetary functions, pivot to a store-of-value narrative (competing with Bitcoin), or fundamentally change the value proposition by generating substantial revenue through fees and burns. The latter path requires a different kind of organization: one focused on business development and sustainable revenue generation rather than just protocol development.</p>]]></content><author><name></name></author><category term="ethereum" /><category term="economics" /><category term="english" /><summary type="html"><![CDATA[L1 Tokens]]></summary></entry><entry><title type="html">What’s the core functionality of blockchains</title><link href="https://dankradfeist.de/ethereum/2025/08/07/core-of-blockchains.html" rel="alternate" type="text/html" title="What’s the core functionality of blockchains" /><published>2025-08-07T00:00:00+00:00</published><updated>2025-08-07T00:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2025/08/07/core-of-blockchains</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2025/08/07/core-of-blockchains.html"><![CDATA[<h1 id="the-core-functionality-of-blockchains">The core functionality of blockchains</h1>

<p>Blockchains are a lot of things to different people, but I think most fundamentally they can be seen as:</p>
<ol>
  <li>A place where you can post stuff so that anyone can see it and it has a canonical order and</li>
  <li>An interpretation of the posted stuff</li>
</ol>

<p>To illustrate this further, when Alice sends Bob some coins, she has to put a transaction on chain (1) and this transaction is then interpreted as being a transfer of her coins to Bob (2). We can also say (1) is data availability and (2) is execution.</p>

<h2 id="what-do-we-care-about">What do we care about</h2>

<p>A lot of us talk about security and hardness. So let’s get deeper into the properties that we would want from such a system:</p>

<ol>
  <li>How do you post a transaction to be processed (this is censorship resistance and ordering)</li>
  <li>How predictable is the interpretation of this data (this is security)</li>
  <li>How will the interpretation of the data change in the future (this is hardness)</li>
</ol>

<p>The difference between security and hardness is that security refers to the code as it is now, and hardness to future changes. Let’s say that there is a bug in the EVM that allows anyone to create any number of ERC20 tokens; this is clearly against the expectation we have on these smart contracts, and so it would constitute a major security bug.</p>

<p>If instead, say, all Ethereum core devs decided it is a good idea to change the code so that anyone can create any number of ERC20 tokens, and announced this to everyone, and the node operators simply decided to install this update instead of protesting this violation of core principles, this would not violate the predictability of the current code; but it would violate past expectations that the behaviour would not change, and would therefore violate hardness.</p>

<p>Censorship resistance, ordering and hardness are all important properties of blockchains. However, with new learning over the last few years, I think we have to reassess how we prioritize different properties, because the tradeoffs are not free.</p>

<h2 id="bitcoin-established-hardness">Bitcoin established hardness</h2>

<ul>
  <li>21 million cap central tenet</li>
</ul>

<h2 id="smart-contract-blockchains-are-becoming-money-apis">Smart contract blockchains are becoming money APIs</h2>

<ul>
  <li>RWAs don’t require as much hardness</li>
  <li>issuer always provides security of last resort</li>
  <li>stability still good but no more central value proposition</li>
</ul>

<h2 id="ordering-and-censorship-resistance-should-become-new-focus">Ordering and censorship resistance should become new focus</h2>

<ul>
  <li>Ethereum so far has taken a very long term view</li>
  <li>Censorship resistance is seen as a long term property (see, inclusion into blocks with )</li>
</ul>

<h2 id="security-and-hardness-still-matter">Security and hardness still matter</h2>

<ul>
  <li>security is important for everything that happens on chain</li>
  <li>hardness should be seen like the stability of the money API</li>
  <li>predictable, long term changes are ok</li>
  <li>it’s not about making commitments for decades</li>
</ul>

<h2 id="summary--refocus-on">Summary – refocus on</h2>]]></content><author><name></name></author><category term="ethereum" /><category term="strategy" /><category term="english" /><summary type="html"><![CDATA[The core functionality of blockchains]]></summary></entry><entry><title type="html">SUMCHECK Quickie</title><link href="https://dankradfeist.de/ethereum/2023/08/08/sumcheck-quickie.html" rel="alternate" type="text/html" title="SUMCHECK Quickie" /><published>2023-08-08T00:00:00+00:00</published><updated>2023-08-08T00:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2023/08/08/sumcheck-quickie</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2023/08/08/sumcheck-quickie.html"><![CDATA[<h1 id="the-sumcheck-protocol">The SUMCHECK protocol</h1>

<p>I won’t delve deeply into its introduction here, but the SUMCHECK protocol (Carsten Lund, Lance Fortnow, Howard J. Karloff, and Noam Nisan. “Algebraic Methods for Interactive Proof Systems”, 1992) serves as a foundation for many “verifiable computation” primitives. If you’re reading this, you likely already know its significance.</p>

<p>Let \(\mathbb{F}\) be a finite field and \(f(X_1, X_2, \ldots, X_n)\) be a multivariate polynomial of degree \(d\) over \(\mathbb{F}\). Consider the sum \(S\) defined as:</p>

\[S = \sum_{x_1\in\{0, 1\}} \sum_{x_2\in\{0, 1\}} \cdots \sum_{x_n\in\{0, 1\}} f(x_1, x_2, \ldots, x_n) = \sum_{(x_1, x_2, \ldots, x_n) \in \{0,1\}^n} f(x_1, x_2, \ldots, x_n)\]

<p>The SUMCHECK protocol provides an \(n\) round interactive protocol to verify the correctness of \(S\), using only a single evaluation of \(f\) (i.e. the verifier only has to evaluate \(f(X)\) once, rather than \(2^n\) times).</p>

<p>The protocol advances through \(n\) rounds. In each round, the prover sends a univariate polynomial to the verifier. In response, the verifier conducts a check and responds by sending a single field element challenge.</p>

<p><strong>Round 1</strong></p>

<p>The prover computes and shares the univariate polynomial:</p>

\[f_1(X) = \sum_{(x_2, \ldots, x_n) \in \{0,1\}^{n-1}} f(X, x_2, x_3, \ldots, x_n)\]

<p>The verifier ensures that the degree of \(f_1\) is less than \(d\), checks if \(f_1(0) + f_1(1) = S\), and issues the challenge \(r_1 \in \mathbb{F}\).</p>

<p><strong>Round 2</strong></p>

<p>The prover computes and shares the univariate polynomial:</p>

\[f_2(X) = \sum_{(x_3, \ldots, x_n) \in \{0,1\}^{n-2}} f(r_1, X, x_3, x_4, \ldots, x_n)\]

<p>The verifier ensures that the degree of \(f_2\) is less than \(d\), checks if \(f_2(0) + f_2(1) = f_1(r_1)\), and issues the challenge \(r_2 \in \mathbb{F}\).</p>

<p><strong>Round \(i\)</strong></p>

<p>The prover computes and shares the univariate polynomial:</p>

\[f_i(X) = \sum_{(x_{i+1}, \ldots, x_n) \in \{0,1\}^{n-i}} f(r_1, \ldots, r_{i-1}, X, x_{i+1}, x_{i+2}, \ldots, x_n)\]

<p>The verifier ensures that the degree of \(f_i\) is less than \(d\), checks if \(f_i(0) + f_i(1) = f_{i-1}(r_{i-1})\), and issues the challenge \(r_i \in \mathbb{F}\).</p>

<p><strong>Round \(n\)</strong></p>

<p>The prover computes and shares the univariate polynomial:</p>

\[f_n(X) = f(r_1, \ldots, r_{n-1}, X)\]

<p>The verifier ensures that the degree of \(f_n\) is less than \(d\), checks if \(f_n(0) + f_n(1) = f_{n-1}(r_{n-1})\), and issues the challenge \(r_n \in \mathbb{F}\).</p>

<p><strong>Final check</strong></p>

<p>The verifier evaluates \(f(r_1, \ldots, r_n)\) and confirms that it equals \(f_n(r_n)\).</p>

<h1 id="why-does-it-work">Why does it work</h1>

<p>Below, I present an intuitive proof for the efficacy of the SUMCHECK protocol, assuming a large field \(\mathbb{F}\). For this explanation, the Schwartz-Zippel lemma is essential.</p>

<h2 id="the-schwartz-zippel-lemma">The Schwartz-Zippel Lemma</h2>

<p>The Schwartz-Zippel lemma states: For a non-zero multivariate polynomial \(P(X_1, \ldots, X_n)\) with a total degree of at most \(d\) over the field \(\mathbb{F}\), when evaluating \(P\) at random points \(r_1, \ldots, r_n\) from \(\mathbb{F}\), the likelihood of \(P(r_1, \ldots, r_n)\) being zero is less than \(\frac{d}{\lvert\mathbb{F}\rvert}\).</p>

<p>In large fields (like the scalar fields of elliptic curves often, which are cryptographically secure with field sizes around \(2^{256}\)), this probability is minuscule. This is because a polynomial can only have a limited number of zeros. For a univariate polynomial, this is immediately evident from the “factor theorem”: Every zero of the polynomial corresponds to a linear factor, so a degree \(d\) polynomial can have up to \(d\) zeros.</p>

<p>A common application of the Schwartz-Zippel lemma is comparing two univariate polynomials, \(f(X)\) and \(g(X)\), to determine their identity. By generating a random number \(r \in \mathbb{F}\) and checking if \(f(r) = g(r)\), we can determine if they are the same. This method is <em>correct</em>, but is it also <em>sound</em>? What’s the likelihood of erroneously claiming \(f(X)\) and \(g(X)\) are identical when they aren’t?</p>

<p>Claim: If \(f(X) \not= g(X)\), then the probability of the check being successful is at most \(\frac{d}{\lvert\mathbb{F}\rvert}\).</p>

<p>Proof: Let’s set \(P(X) = f(X) - g(X)\). Given that \(f(X) \not= g(X)\), \(P(X)\) isn’t the zero polynomial. As per Schwartz-Zippel, the chance of \(P(r) = f(r) - g(r) = 0\) is at most \(\frac{d}{\lvert\mathbb{F}\rvert}\).</p>

<p>A succinct takeaway from Schwartz-Zippel is: Over large fields, two “low-degree” polynomials are either identical or different almost everywhere.</p>

<h2 id="sumcheck-protocol-proof">SUMCHECK protocol proof</h2>

<p>The SUMCHECK protocol harnesses this property to convert a sum with a potentially large number of terms into a singular evaluation. Let’s see why it works, by trying to create a prover that attempts to cheat the protocol, attempting to prove a sum \(\tilde S \not= S\).</p>

<p><strong>Round 1</strong></p>

<p>The prover needs to send a polynomial \(\tilde f_1(X)\) with the property \(\tilde f_1(0) + \tilde f_1(1) = \tilde S\). Any other choice would make the first check fail immediately, so there would be no point.</p>

<p>Since \(\tilde S \not= S\), the prover cannot send the honest polynomial \(f_1(X)\). Recall that this means that the polynomial they will be sending is different almost everywhere from \(f_1(X)\); more precisely, it is the same as \(f_1\) on at most \(d\) points.</p>

<p>The verifier then sends the challenge \(r_1\).</p>

<p><strong>Round 2</strong></p>

<p>In round 2, the prover needs to send a polynomial \(\tilde f_2(X)\) with the property that \(\tilde f_2(0) + \tilde f_2(1) = \tilde f_1(r_1)\).</p>

<p>Now there are two possibilities:</p>
<ul>
  <li>\(\tilde f_1(r_1)= f_1(r_1)\). In this case the prover has hit the jackpot: He can simply send \(f_2(X)\) (the “honest” answer) and continue the protocol honestly to the end. He will succeed at cheating. However, the probability for this happening is only \(\frac{d}{\lvert\mathbb{F}\rvert}\).</li>
  <li>\(\tilde f_1(r_1) \not= f_1(r_1)\) (which is overwhelmingly likely). In this case, the prover is in the same situation as before: He cannot send the honest \(f_2(X)\), but only a malicious \(\tilde f_2(X)\) with \(\tilde f_2(0) + \tilde f_2(1) = \tilde f_1(r_1)\), which can coincide with the honest answer on at most \(d\) points.</li>
</ul>

<p>This repeats every round:</p>

<p><strong>Round \(i\)</strong></p>

<p>In round \(i\), the prover needs to send a polynomial \(\tilde f_i(X)\) with the property that \(\tilde f_i(0) + \tilde f_i(1) = \tilde f_{i-1}(r_{i-1})\).</p>

<p>Again, two possibilities:</p>
<ul>
  <li>\(\tilde f_{i-1}(r_{i-1}) = f_{i-1}(r_{i-1})\). Prover wins (probability of this happening \(\frac{d}{\lvert\mathbb{F}\rvert}\)).</li>
  <li>\(\tilde f_{i-1}(r_{i-1}) \not= f_{i-1}(r_{i-1})\). Prover needs to send  \(\tilde f_i(X)\) with \(\tilde f_i(0) + \tilde f_i(1) = \tilde f_{i-1}(r_{i-1})\)</li>
</ul>

<p><strong>Final check</strong></p>

<p>Finally, in the last round, the verifier checks if \(f(r_1, \ldots, r_n)=f_n(r_n)\). Assuming the prover didn’t “win” in one of the rounds before, he sends a malicious \(\tilde f_n(X)\) which coincides with the honest \(f_n(r_n)\) on at most \(d\) points, so the probability that the final check will pass is \(\frac{d}{\lvert\mathbb{F}\rvert}\).</p>

<p>As you can see from the above analysis, the prover has a small probability of “winning” and cheating the verifier in each round: If his polynomial happens to have the same evaluation on the challenge field element as the honest version, the prover can continue the protocol like an honest prover and the verification will succeed.</p>

<p>However, assuming that the field \(\mathbb{F}\) is large, the probability for this is small. Since there are \(n\) rounds, at best, the prover can succeed with probability \(\frac{nd}{\lvert\mathbb{F}\rvert}\).</p>]]></content><author><name></name></author><category term="ethereum" /><category term="cryptography" /><category term="english" /><summary type="html"><![CDATA[The SUMCHECK protocol]]></summary></entry><entry><title type="html">RAI – one of the coolest experiments in crypto</title><link href="https://dankradfeist.de/ethereum/2023/01/31/rai-crypto-experiment.html" rel="alternate" type="text/html" title="RAI – one of the coolest experiments in crypto" /><published>2023-01-31T10:30:00+00:00</published><updated>2023-01-31T10:30:00+00:00</updated><id>https://dankradfeist.de/ethereum/2023/01/31/rai-crypto-experiment</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2023/01/31/rai-crypto-experiment.html"><![CDATA[<p><em>Special thanks to Vitalik Buterin and Ameen Soleimani for feedback and review.</em></p>

<p><em>Note (2025): Reflexer Labs, the team behind RAI, has wound down active development. The RAI smart contracts remain immutable and operational on-chain, but the project is no longer actively maintained. MakerDAO has also undergone major changes, rebranding to “Sky” and introducing USDS alongside DAI.</em></p>

<h1 id="rai--one-of-the-coolest-experiments-in-crypto">RAI – one of the coolest experiments in crypto</h1>

<p>I think <a href="https://reflexer.finance">RAI</a> is one of the coolest experiments in crypto right now. So I thought I’d write my version of an explainer for it, from the perspective that I have introduced in my previous article on <a href="/ethereum/2021/09/27/stablecoins-supply-demand.html">Supply and demand for stablecoins</a>. Back when I wrote it, my understanding of RAI was poor. The version of DAI it describes (single-collateral DAI, before the introduction of custodial stablecoins as collateral) is actually very close to RAI, however there is an interesting difference: Instead of applying an interest rate to balances, like DAI does, RAI directly manipulates the redemption price (which is always 1 USD for DAI). I think it’s nice to directly describe this mechanism. If you want to understand more on how Collateralized Debt Positions (CDPs) work to maintain stability, then I still recommend reading my previous article!</p>

<h1 id="why-is-rai-floating-and-not-tracking-one-currency">Why is RAI floating, and not tracking one currency?</h1>

<p>In the past, the goal of creating stablecoins was seen as creating an asset that is always worth 1 USD (or some other currency). But as Vitalik remarked in <a href="https://vitalik.ca/general/2022/05/25/stable.html">his thought experiments on automated stablecoins</a>, if you can create a coin that is always worth 1 USD, why can’t you use the same mechanism to create one that is worth 1 USD plus 20% interest per year (i.e. 1.00 USD in year 1, 1.20 USD in year 2, 1.44 USD in year 3, and so on)? After all, the only way the blockchain knows about prices is through oracles, and it’s an easy change to the oracle to make it return the value of the coin priced in this new unit (USD appreciating by 20% per year) instead of USD.</p>

<p>Clearly there is something missing in the picture. As we will see below, in order to balance supply and demand, a fully decentralized stablecoin needs to be able to give incentives to those going long (using the stablecoin) and going short (supplying the stablecoin) in some form. This is true whether it tracks USD, USD+20% interest or USD-5% interest.</p>

<p>One way of doing this is to add a mechanism rate that charges interest on debt (the suppliers of the stablecoin) and credits it to the holders (the users of the stablecoin). The interest rate can however be negative when there is more demand for holding than there is for stablecoin debt.</p>

<p>In March 2020, DAI first depegged upward (the market price increased to more than 1 USD) and only repegged after USDC (a custodial, centralized stablecoin pegged to 1 USD) was added as one of the forms of collateral to mint DAI, otherwise it would have required a negative interest rate. Since its inception, RAI has mostly had negative interest rates. For now, it seems like decentralized stablecoin require negative interest rates most of the time.</p>

<p>When interest rates are negative, instead of having your balance change from 1 to 0.99 to 0.98, RAI keeps the balance the same and changes the actual price target of the stablecoin instead. This means that RAI looks like a floating currency, but with the property that it is much less volatile than cryptos like Ether and Bitcoin.</p>

<h2 id="the-stablecoin-problem">The stablecoin problem</h2>

<p>Cryptocurrencies are volatile. Apart from scaling, this is probably still the largest barrier to adoption. This is why there have been many attempts to create a coin that is less volatile.</p>

<p>Like any commodity, the price of a stablecoin is determined by supply and demand. At any instant, some people want to buy and sell the coin, and these inflows and outflows must be matched, so the price will adjust until they do (the price where they match is the market price). Market makers will try to cover short term spikes in supply or demand, but will adjust their quote prices if they see consistent pressure in one direction.
<img src="/assets/supply_demand.png" alt="Supply and demand" /></p>

<p>So if you want to keep a coin stable, you have to be able to somehow manipulate supply and demand such that they cross at a desired price. If the current price is too high, it’s easy to create more supply and push the price down. The trouble comes when the coin falls below the desired price (more outflows than inflows): We need to either decrease supply or increase demand, but how do we do that if the supply comes from independent holders wanting to sell?</p>

<p>There is only one decentralized and sustainable option that I know of. It requires saving during the good times in order to be able to create demand in the bad times: In order for new stablecoins to be created, enough collateral for has to be added to the protocol, so that when demand decreases, this collateral can be used to generate new demand.</p>

<h3 id="collateralized-debt-positions">Collateralized debt positions</h3>

<p>Creating stablecoins by means of Collateralized Debt Positions (CDPs) is a way in which this can be implemented. A CDP is a position where a holder of a volatile currency, such as Ether, takes out a loan in the stablecoin. The CDP represents this position. It can also be seen as a leverage position in the collateral. For example, this graph represents a CDP that has 200 RAI borrowed against 1 ETH, where the value of 1 ETH is currently 1400 USD and 1 RAI is 3 USD; the holder of the CDP gets the “equity” value of this position (currently 1400-600=800 USD, but it can fluctuate with the price), and the RAI holder the debt (which is independent of the current price of Ether).</p>

<p><img src="/assets/debt-equity-rai.png" alt="RAI CDP" /></p>

<p>How can CDPs create demand? Some protocols do this directly by allowing stablecoin holders to redeem against the collateral, this is for example how <a href="https://www.liquity.org/">Liquity</a> works. However, RAI follows MakerDAO’s original DAI in not integrating such a mechanism. But CDPs can still generate demand:</p>
<ol>
  <li>While the CDP is well collateralized, charging an interest rate to the debt holder can incentivize them to take action in relation to their CDP. For example, if the interest rate on debt increases, a CDP holder may decide that holding on to the position is no longer worth it, and that it’s better to repay the debt. When they do this, they have to buy the stablecoin on the market, which creates demand.</li>
  <li>Once the CDP gets close to the liquidation ratio, the holder is incentivized to close the position to avoid the liquidation penalty, unless they can add more collateral. If the position gets liquidated, the liquidator will also have to buy stablecoins in order to bid for the collateral.</li>
</ol>

<p>By only ever issuing new stablecoins in the form of debt when a CDP is created, the protocol has all the collateral in the CDPs to prop up the coin when other demand for stablecoin collapses.</p>

<p>This construction comes with a counterintuitive downside: New coins can only be created when someone is willing to take out a CDP. This requires someone who wants to take a leveraged position in the collateral.</p>

<p>This demand is currently the limiting factor for stablecoins based on this construction. In order to stop the stablecoin from increasing in value due to limited supply of willing CDP holders (in other words, demand for leverage), we will have to do one of two things:</p>
<ol>
  <li>Make the leveraged position more attractive to the CDP holders</li>
  <li>Make holding the stablecoin less attractive</li>
</ol>

<p>What we can do is that we charge the stablecoin holders a negative interest rate, which is paid out to the CDP holders. This actually does both: It increases the attractiveness of leveraged positions, and makes holding the stablecoin less attractive.</p>

<p>Margin exchanges have done this for a while: They too have to find this balance, as every long position has to be matched to a short position, so that the net exposure is equal to the deposited assets. They use the same mechanism to balance the books: The funding rate is paid by the type of position for which there is more demand to the side that for which there is less.</p>

<h2 id="how-rai-balances-supply-and-demand">How RAI balances supply and demand</h2>

<p>We have just learned that one mechanism to achieve the balance between CDPs (stablecoin shorts) and holders (stablecoin longs) is an interest rate transfer between the two. DAI implements this mechanism using the DAI savings rate: you can put your DAI into the savings contract and you get paid an interest.</p>

<p>Things become more awkward when the interest rate is negative, i.e. DAI holders are paying to CDP holders. In this regime, DAI balances would have to be slowly decreasing. Implementing it in this way has the advantage that your balance always represents the value in USD, and 1 DAI remains worth 1 USD. It’s less good for smart contract developers who now have to deal with the fact that balances in an account can decrease.</p>

<p>Instead, RAI goes a different way: Adjust the “redemption price” to represent the interest rate. What’s the redemption price? It’s the target value of 1 RAI. In particular it is used</p>
<ol>
  <li>To borrow RAI in CDPs and to repay debt, as well as determine whether a position is underwater and should be liquidated</li>
  <li>As the value at which all debts and deposits are settled when global settlement is triggered.</li>
</ol>

<p>Since the interest rate is applied to the redemption price, it is called redemption rate. As an example, if the redemption rate is -3% and the redemption price is currently 1.00 USD, then in 1 year the redemption price will be 0.97 USD (RAI actually started with a redemption price of 3.14 USD).</p>

<p>Now when such a negative redemption rate is applied, two things will happen:</p>
<ol>
  <li>RAI holders will expect to have 3% less value when compared to holding USD after one year</li>
  <li>RAI borrowers (who buy RAI back on the market) will expect their debt to decrease in value by 3% after one year</li>
</ol>

<h3 id="how-does-rai-determine-the-redemption-rate">How does RAI determine the redemption rate</h3>

<p>Another cool component of RAI is that the redemption rate is actually automatically computed by the protocol. The protocol detects the supply and demand imbalance by tracking the deviation of the market price from the redemption price. If the market price is higher than the redemption price, it means there is more demand for RAI than there is for CDPs – and so a negative redemption rate has to be applied. Conversely, if the market price is lower than the redemption price, the redemption rate needs to be be positive.</p>

<p>So a very simple design could look like this: Find the current difference between the redemption price and the market price, multiply it by some number – for simplicitly say 1, and make that the redemption rate. Say the current redemption price is 4% under market, then the redemption rate will be -4%. If it is 10% above, the redemption rate will be +10%.</p>

<p>If we did this, it would constitute a P controller (P for proportional), which is actually what RAI did initially. RAI’s adjustment mechanism was later updated to use a <a href="https://en.wikipedia.org/wiki/PID_controller">PI controller</a> that takes the difference between market and redemption prices (the error) as an input. A PI controller, in addition to the current value, also uses the integral (I), so takes into consideration how much the value has deviated in the past. This makes the system more stable and means interest rates fluctuate a bit less with short term price changes.</p>

<p>The <a href="https://reflexer.finance">RAI website</a> shows the history of RAI redemption price and market price, as well as the interest rates, which can be a nice demonstration of how this mechanism works</p>

<p><img src="/assets/rai-rate-screenshot.png" alt="RAI rates" /></p>

<p>On top, you can see the market (red) and redemption prices (grey). The market price is typically above the redemption price, representing excess demand for RAI over CDPs, which the protocol compensates by applying a negative redemption rate – this is why the redemption price is slowly decreasing.</p>

<p>The lower graph shows how the redemption rate is computed. the blue curve (<code class="language-plaintext highlighter-rouge">p_rate</code>) is the P part of the PI controller. It is proportional to the error and indeed, the graph looks like the inverted difference between the red and grey curves in the upper graph. The orange curve (<code class="language-plaintext highlighter-rouge">i_rate</code>) is much smoother and represents the I part (integral) of the controller, which reacts to past deviations. The sum of the <code class="language-plaintext highlighter-rouge">p_rate</code> and the <code class="language-plaintext highlighter-rouge">i_rate</code> is the redemption rate and is how fast the redemption price is going down at any given time.</p>

<p>The higher the market price is above the redemption price, the faster the redemption price thus decreases – rebalancing supply and demand as the expected value of holding RAI decreases (and RAI debt becomes more attractive).</p>

<h2 id="but-what-pulls-rai-back-to-the-redemption-price">But what pulls RAI back to the redemption price</h2>

<p>There’s one thing we skipped over. The redemption price represents the target value of RAI in the protocol, and we’ve just been taking it for granted that lowering the price will make long RAI positions less attractive and short positions more attractive. But this assumes that market participants have some expectation of being able to use RAI at or near the redemption price – which requires some force that pulls the market at least in the direction of the redemption price, so that lowering the redemption price has a meaning.</p>

<p>Of course, we can expect “global settlement” will solve this: There is a mechanism in the protocol, which can be triggered by governance, that settles all deposits and debts according to the current redemption price. It is expected that this mechanism will be triggered when the deviations become too extreme. So maybe that’s the reason why the redemption price matters?</p>

<p>Actually, the global settlement is a cool emergency feature, but it is not necessary to explain why the market price will track the redemption price, assuming (some) rational market participants (with enough capital).</p>

<p>Let’s assume that market participants just ignore the redemption price entirely. What would happen?</p>
<ol>
  <li>The current minimal collateralization for CDPs is 135%. What that means is that if the market price is more than 35% above the redemption price, anyone can just mint RAI for Ether and “forget” about their CDP – just sell the RAI, buy more Ether with it and take the arbitrage profit. RAI can’t trade significantly more than 35% above redemption price for this reason.</li>
  <li>There is no strict bound like this from below – but we can do a thought experiment: Let’s say that RAI trades consistently 10% below redemption price. Note that this would lead to an enormous redemption rate of something like 240% per year (in the long term, when the integral term has had enough time to accumulate). CDP holders have to take this redemption rate into account – eventually they will get liquidated, when their collateralization ratio (which is computed using redemption price) reaches 135%. They thus have a strong incentive to buy RAI before this happens.</li>
  <li>Similarly, we can find that if RAI trades 10% above the redemption price, the negative interest rate will reach something crazy like -70% (again in the long term, when the integral term has had enough time to accumulate this), which means there is a very strong incentive for RAI holders to get out before this happens. If they don’t, lots of newly minted RAI from new CDPs will eventually be available at the much lower redemption price.</li>
</ol>

<p>Combined, these forces mean that while the market price can deviate, it cannot deviate too far and too long from the redemption price.</p>

<h2 id="how-does-tracking-another-currency-change-rai">How does tracking another currency change RAI?</h2>

<p>An interesting question is: How would RAI be different if instead of tracking USD, it had been set up to track the Euro, the Chinese Yuan, or maybe the 6 months moving average of the Ether price?</p>

<p>To start with, we will do a thought experiment (one proposed by <a href="https://vitalik.ca/general/2022/05/25/stable.html">Vitalik</a>): What if RAI was set up to track USD + 20% (a version of the USD that comes with a 20% interest rate)? Let’s call this asset RAI-PONZI.</p>

<p>Obviously holding this asset seems really attractive and having debt in that asset much less so. The price of RAI-PONZI will keep rising as buyers want the high interest rates and there are few people available wanting to take out CDPs in RAI-PONZI.</p>

<p>As RAI-PONZI rises above the redemption price, the redemption rate will get more and more negative. It will reach -20%, which makes RAI-PONZI equivalent to USD. From there, it will likely go even further: Currently RAI’s redemption rate is about -10%, so I would expect RAI-PONZI to settle at -30% in current market conditions. At that point, it becomes equivalent to current RAI, so it makes sense that market participants would behave in this way, assuming the same risk tolerance of market participants.</p>

<p>This is actually nothing else than creating an “offset” in the redemption rate of +20%, and an equivalent price offset.</p>

<p>What can we learn from this? The long-term expected gains or losses of a currency do not impact how RAI behaves. If RAI were pegged to Turkish Lira, which seems to lose about 25% of its value compared to the USD every year, it would probably not behave too differently on long timescales. Let’s call this asset RAI-TRY.</p>

<p>Where RAI-TRY is different is on short timescales and unexpected shocks. If the Lira suddenly drops 20%, due to a black swan, then RAI-TRY will do so, too. The same goes for a sudden increase.</p>

<p>What exact currency is used as an input to the RAI oracles therefore probably does not matter that much. It is likely that most major currencies like EUR or GBP will result in a very similar asset, except that it will react slightly differently under market shocks. This is because any expectation in different performance will just be corrected by market participants (so if they expect that GBP will lose 1% per year vs USD, they will just correct for it by picking a different redemption rate).</p>

<h2 id="why-do-i-think-rai-is-such-a-cool-experiment">Why do I think RAI is such a cool experiment?</h2>

<p>There have been many attempts to solve the decentralized stablecoin problem. MakerDAO with DAI was probably the first that solved a major part of the puzzle – how to stop it from crashing to zero in a confidence crisis. However, it turned out that they had still missed one part, which is how to stop it from going up.</p>

<p>Finally, RAI came and added this missing piece in a slightly unexpected way – whilst many had been expecting a DAI with negative interest rate, doing it via the redemption rate adjustment is much more elegant. And at the same time, it allows us to learn a lot:</p>

<p>First and foremost, the point of a stablecoin is not to be pegged to USD. It is to provide an asset with low volatility. RAI does indeed solve this task, and has much lower volatility than the underlying collateral, Ether.</p>

<p>RAI therefore is something like a new currency, which is underlined by the fact that it doesn’t really matter that much which fiat currency is used for the oracles, as long as it is reasonably stable. In fact you can change the reference asset while the system is working without much of a problem.</p>

<p>Secondly, the current market structure dictates that if users want a decentralized stablecoin, they have to pay a “price for stability”, in the form of a slowly decaying price of RAI (vs the USD). This is because there is a lot of demand for stablecoins, and limited demand for leverage on decentralized assets like Ether. While it currently feels like this might be an eternal truth, it does not have to be. It could be that this balance tips in the favour of stablecoins again in a bull market, as demand for leverage increases. However, before that happens, it is likely that we would have to see MakerDAO shrug off all of its custodial stablecoin exposure (in order to get their funding rates off zero), which currently seems a long way off.</p>

<p>What I love about RAI is that it is a completely fair way to determine the “price of stability”, and also much cleaner than others. I have posited in my <a href="/ethereum/2021/09/27/stablecoins-supply-demand.html">past article on stablecoins</a> that the price of stability isn’t currently fairly determined – and that if it were, it may well be a negative interest rate. Many see inflation as a scourge, but the reality is that having a “guaranteed stable asset” as we implicitly expect currencies to be has to be paid for by someone. If that price were determined using a market like it is in RAI, what would it be?</p>

<p>At least in the decentralized world, we now have an answer, that the price is typically higher than the 2% inflation allowed for by many central banks. Obviously, the number of assets that can be used as collateral in decentralized stablecoins is small, and the result in the real world may well be different. After all, there are 100s of trillions of collateral available, compared to currently less than one trillion in crypto assets.</p>

<p>RAI is, in many ways, central banking in a pure form. We will probably learn many things from this experiment, and that already makes it a worthwhile project.</p>]]></content><author><name></name></author><category term="ethereum" /><category term="economics" /><category term="english" /><summary type="html"><![CDATA[Special thanks to Vitalik Buterin and Ameen Soleimani for feedback and review.]]></summary></entry><entry><title type="html">Ethereum Merge: Run the majority client at your own peril!</title><link href="https://dankradfeist.de/ethereum/2022/03/24/run-the-majority-client-at-your-own-peril.html" rel="alternate" type="text/html" title="Ethereum Merge: Run the majority client at your own peril!" /><published>2022-03-24T11:00:00+00:00</published><updated>2022-03-24T11:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2022/03/24/run-the-majority-client-at-your-own-peril</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2022/03/24/run-the-majority-client-at-your-own-peril.html"><![CDATA[<p><em>Special thanks to Vitalik Buterin, Hsiao-Wei Wang and Caspar Schwarz-Schilling for feedback and review.</em></p>

<p><em>Note (2025): This post was written before The Merge (September 2022). The Merge has since happened successfully. The Ethereum community has made significant progress on client diversity: Prysm no longer holds a 2/3 supermajority on the consensus side, and the execution client landscape has diversified beyond Go-ethereum. The analysis and incentive arguments in this post remain valid, and client diversity continues to be important.</em></p>

<p><strong>TL;DR</strong>: For reasons of both safety and liveness, Ethereum has chosen a multi-client architecture. In order to encourage stakers to diversify their setups, penalties are higher for correlated failures. A staker running a minority client will thus typically only lose moderate amounts should their client have a bug, but running a majority client can incur a total loss. Responsible stakers should therefore look at the client landscape and choose a less popular client.</p>

<h2 id="why-do-we-need-multiple-clients">Why do we need multiple clients?</h2>

<p>There are arguments why a single client architecture would be preferable. Developing multiple clients incurs a substantial overhead, which is the reason why we haven’t seen any other blockchain network seriously pursue the multi-client option.</p>

<p>So why does Ethereum aim to be multi-client? Clients are very complex pieces of code and likely contain bugs. The worst of these are so called “consensus bugs”, bugs in the core state transition logic of the blockchain. One often quoted example of this is the so-called “infinite money supply” bug, in which a buggy client accepts a transaction printing arbitrary amounts of Ether. If someone finds such a bug and isn’t stopped before they get to the exit doors (i.e. making use of the funds by sending them through a mixer or to an exchange), it would massively crash the value of Ether.</p>

<p>If everyone runs the same client, stopping this requires manual intervention, because the chain, all smart contracts and exchanges will keep running as usual. Even a few minutes could be enough to execute a successful attack and sufficiently disperse the funds to make it impossible to roll back <em>only</em> the attacker’s transactions. Depending on the amount of ETH printed, the community would likely coordinate on rolling back the chain to before the exploit (after having identified and fixed the bug).</p>

<p>Now let’s have a look at what happens when we have multiple clients. There are two possible cases:</p>

<ol>
  <li>
    <p><strong>The client with the bug represents less than 50% of the stake.</strong> The client will produce a block with the transaction exploiting the bug, printing ETH. Let’s call this chain <strong>A</strong>.</p>

    <p>However, the majority of stake running a non-faulty client will ignore this block, because it is <strong>invalid</strong> (to them the printing ETH operation is simply invalid). They will build an alternative chain <strong>B</strong> that does not contain the invalid block.</p>

    <p>Since the correct clients are in the majority, chain <strong>B</strong> will accumulate more attestations. Hence, even the buggy client will vote for chain <strong>B</strong>; as a result chain <strong>B</strong> will accumulate 100% of the votes and chain <strong>A</strong> will die. The chain will continue as if the bug never happened.</p>
  </li>
  <li>
    <p><strong>The majority of stake uses the buggy client.</strong> In this case, chain <strong>A</strong> will accumulate the majority of votes. But since <strong>B</strong> has less than 50% of all attestations, the offending client will never see a reason to switch from chain <strong>A</strong> to chain <strong>B</strong>. We will thus see a chain split.</p>
  </li>
</ol>

<p><img src="/assets/chainsplit.png" alt="" /></p>

<p>Case 1 is the ideal case. It would most likely lead to a single orphaned block which most users wouldn’t even notice. Devs can debug the client, fix the bug, and everything is great. Case 2 is clearly less than ideal, but still a better outcome than if there’s only a single client – most people would very quickly detect that there is a chain split (you can do this automatically by running several clients), exchanges would quickly suspend deposits, Defi users could tread carefully while the split is resolved. Basically, compared to the single client architecture, this still gives us a big flashing red warning light that allows to protect against the worst outcomes.</p>

<p>Case 2 will be much worse if the buggy client is run by more than 2/3 of the stake, in which case it would be finalizing the invalid chain. More on that later.</p>

<p>Some people think a chain split is so catastrophic that in itself it is an argument for a single-client architecture. But note that the chain split only happened because of a bug in the client. With a single client, if you wanted to fix this and return the chain back to status quo ante, you would have to roll back to the block before the bug happened – that’s just as bad as the chain split! So as bad as a chain split sounds, in the case where there is a critical bug in a client, it’s actually a feature, not a bug. At least you can see that something is seriously wrong.</p>

<h2 id="incentivising-client-diversity-anti-correlation-penalties">Incentivising client diversity: anti-correlation penalties</h2>

<p>It is clearly good for the network if the stake is split across multiple clients, with the best case being each client owning less than 1/3 of the total stake. This will make it resilient against a bug in any individual client. But why would stakers care? If there aren’t any incentives by the network, it’s unlikely that they will take on the cost of switching to a minority client.</p>

<p>Unfortunately we can’t make rewards directly dependent on what client a validator runs. There is no objective way to measure this that can’t be spoofed.</p>

<p>However, you can’t hide when your client has a bug. And this is where anti-correlation penalties come in: The idea is that if your validator does something bad, then the penalty is higher if more validators make a mistake <strong>around the same time</strong>. In other words, you get punished for correlated failures.</p>

<p>In Ethereum, you can currently get slashed for two behaviours:</p>
<ol>
  <li>Signing two blocks at the same height</li>
  <li>Creating a pair of slashable attestations (<a href="https://blog.ethereum.org/2020/01/13/validated-staking-on-eth2-1-incentives/">surround or double votes</a>)</li>
</ol>

<p>When you get slashed, you don’t usually lose all your funds. At the time of this writing (Altair fork), the default penalty is actually quite small: You would only lose 0.5 ETH, or about 1.5% of your staked Ether (ultimately this will be increased to 1 ETH or 3%).</p>

<p>However, there is a catch: There is an additional penalty that is dependent on all other slashings that occur during the 4096 epochs (18 days) before and after your validator was slashed. You are further penalized by an amount that is proportional to the total amount slashed during this period.</p>

<p>This can be a much larger penalty than the initial penalty. Currently (Altair fork) it is set so that if more than half of the full staking balance got slashed during this period, then you will lose all your funds. Ultimately this will be set so that you will lose all of your stake if 1/3 of other validators got slashed. 1/3 was chosen because this is the minimum amount of the stake that has to equivocate in order to create a consensus failure.</p>

<p><img src="/assets/proportional-penalties.png" alt="" /></p>

<h3 id="the-other-anti-correlation-penalty-the-quadratic-inactivity-leak">The other anti-correlation penalty: The quadratic inactivity leak</h3>

<p>Another way a validator can fail is by being offline. Again there is a penalty for it, but its mechanism is very different. We do not call it slashing, and it’s usually small: Under normal operation, a validator that is offline is penalized by the same amount that they would be gaining if they were validating perfectly. At the time of this writing, this is 4.8% per year. It is probably not worth breaking a sweat if your validator is offline for a few hours or days, for example due to a temporary internet outage.</p>

<p>It becomes very different when more than 1/3 of all validators are offline. Then the beacon chain cannot finalize, which threatens a fundamental property of the consensus protocol, namely liveness.</p>

<p>To restore liveness in a scenario like this the so-called “quadratic inactivity leak” kicks in. The total penalty amount raises quadratically with time if a validator continues being offline while the chain is not finalizing. Initially it is very low; after ~4.5 days, the offline validators will lose 1% of their stake. However, it increases to 5% after ~10 days and to 20% after ~21 days (these are Altair values, they will be doubled in the future).</p>

<p><img src="/assets/quadratic-leak.png" alt="" /></p>

<p>This mechanism is designed so that in the case of a catastrophic event that annihilates a large number of validator operations, the chain will eventually be able to finalize again. As the offline validators lose larger and larger parts of their stake, they will make up a smaller and smaller share of the total, and as their stake drops below 1/3, the remaining online validators gain the required 2/3-majority, allowing them to finalize the chain.</p>

<p>However, there is another case where this becomes relevant: In certain cases, validators cannot vote for the valid chain anymore because they accidentally locked themselves into an invalid chain. More on this below.</p>

<h1 id="how-bad-is-it-to-run-the-majority-client">How bad is it to run the majority client?</h1>

<p>In order to understand what the dangers are, let’s take a look at three failure types:</p>

<ol>
  <li>Mass slashing event: Due to a bug, majority-client validators sign slashable attestations</li>
  <li>Mass offline event: Due to a bug, all majority-client validators go offline</li>
  <li>Invalid block event: Due to a bug, majority-client validators all attest to an invalid block</li>
</ol>

<p>There are other kinds of mass failures and slashings that can happen, but I’m restricting myself to those related to client bugs (the ones you should consider when choosing which client to run).</p>

<h2 id="scenario-1-double-signing">Scenario 1: Double signing</h2>

<p>This is probably the most feared scenario by most validator operators: A bug leading the validator client to sign slashable attestations. One example would be two attestations voting for the same target epoch, but with different payloads. Because it is a client bug, it’s not just one staker that is concerned, but all stakers that run this particular client. When the equivocations are detected, the slashings will be a bloodbath: All concerned stakers will lose 100% of their staked funds. This is because we are considering a majority client: If the stake of the concerned client were only 10%, then “only” about 20% of their stake would be slashed (in Altair; 30% with the final penalty parameters in place).</p>

<p>The damage in this case is clearly extreme, but I also think it is <em>extremely unlikely</em>. The conditions for slashable attestations are simple, and that’s why validator clients (VCs) were built to enforce them. The validator client is a small, well audited piece of software. A bug of this magnitude is unlikely.</p>

<p>We have seen some slashings so far, but as far as I know all of them where due to operator failures – almost all of them resulting from an operator running the same validator in several locations. Since these aren’t correlated, the slashing amounts are small.</p>

<h2 id="scenario-2-mass-offline-event">Scenario 2: Mass offline event</h2>

<p>For this scenario, we assume that the majority client has a bug, which when triggered, leads to a crash of the client. An offending block has been integrated into the chain, and whenever the client encounters that block, it goes offline, leaving it unable to participate any further in consensus. The majority client is now offline, so the inactivity leak kicks in.</p>

<p>Client developers will scramble to get things back together. Realistically within hours, at most in a few days, they will release a bug fix that will remove the crash.</p>

<p>In the meantime, stakers also have the option to simply switch to another client. As long as enough do this to get more than 2/3 of all validators online, the quadratic inactivity leak will stop. It is not unlikely that this will happen before there is a fix for the buggy client.</p>

<p>This scenario is not unlikely (bugs that lead to crashes are one of the most common types), but the total penalty would probably be less than 1% of the stake affected.</p>

<h2 id="scenario-3-invalid-block">Scenario 3: Invalid block</h2>

<p>For this scenario, we consider the case where the majority client has a bug that produces an invalid block, and also accepts it as valid – i.e. when other validators using the same client see the invalid block, they will consider it as valid, and hence attest to it.</p>

<p>Let’s call the chain that includes the invalid block chain <strong>A</strong>. As soon as the invalid block is produced, two things will happen:</p>
<ol>
  <li>All correctly functioning clients will ignore the invalid block and instead build on the latest valid head producing a separate chain <strong>B</strong>. All correctly working clients will vote and build on chain <strong>B</strong>.</li>
  <li>The faulty client considers both chain <strong>A</strong> and <strong>B</strong> valid. It will thus vote for whichever of the two it currently sees as the heaviest chain.</li>
</ol>

<p><img src="/assets/chainsplit.png" alt="" /></p>

<p>We need to distinguish three cases:</p>

<ol>
  <li>
    <p><strong>The buggy client has less than 1/2 of total stake.</strong> In this case, all correct clients vote and build on chain <strong>B</strong> eventually making it the heaviest chain. At this point even the buggy client will switch to chain <strong>B</strong>. Other than one or a few orphaned blocks, nothing bad will happen. This is the happy case, and why it is great to only have sub-majority clients.</p>
  </li>
  <li>
    <p><strong>The buggy client has more than 1/2 and less than 2/3 of the stake.</strong> In this case, we will see two chains being built – <strong>A</strong> by the buggy client, and <strong>B</strong> by all other clients. Neither chain has a 2/3-majority and therefore they cannot finalize.
As this happens, developers will scramble to understand why there are two chains. As they figure out that there is an invalid block in chain <strong>A</strong>, they can proceed to fix the buggy client. Once it is fixed, it will recognize chain <strong>A</strong> as invalid. It will thus start building on chain <strong>B</strong>, which will allow it to finalize.
This is very disruptive for users. While hopefully the confusion between which chain is valid will be short and less than an hour, the chain probably won’t finalize for many hours, potentially even a day.
But for stakers, even the ones running the buggy client, the penalties would still be relatively light. They will receive the “inactivity leak” penalty for not participating in chain <strong>B</strong> while they were building the invalid chain <strong>A</strong>. However, since this is likely less than a day, we are talking of a penalty that’s less than 1% of the stake.</p>
  </li>
  <li>
    <p><strong>The buggy client has more than 2/3 of the stake.</strong> In this case, the buggy client will not just build chain <strong>A</strong> – it will actually have enough stake to “finalize” it. Note that it will be the only client that will think that chain <strong>A</strong> is finalized. One of the conditions of finalization is that the chain is valid, and to all other correctly operating clients, chain <strong>A</strong> will be invalid.
However, due to how the Casper FFG protocol works, when a validator has finalized chain <strong>A</strong>, they can never take part in another chain that is in conflict with <strong>A</strong> without getting slashed, <em>unless that chain is finalized</em> (for anyone interested in the details, see <a href="#A2-Why-can%E2%80%99t-the-buggy-client-switch-to-chain-B-once-it-has-finalized-chain-A">Appendix 2</a>). So once chain <strong>A</strong> has been finalized, the validators running the buggy client are in a terrible bind: They have committed to chain <strong>A</strong>, but chain <strong>A</strong> is invalid. They cannot contribute to <strong>B</strong> because it hasn’t finalized yet. Even the bugfix to their validator software won’t help them – they have already sent the offending votes.
What will happen now is very painful: Chain <strong>B</strong>, which is not finalizing, will go into the quadratic inactivity leak. Over several weeks, the offending validators will leak their stake until enough has been lost so that <strong>B</strong> will finalize again. Let’s say they started off with 70% of the stake – then they would lose 79% of their stake, because this is how much they would need to lose in order to represent less than 1/3 of the total stake.
At this point, chain <strong>B</strong> will finalize again and all stakers can switch to it. The chain will be healthy again, but the disruption will have lasted weeks, and millions of ETH were destroyed in the process.</p>
  </li>
</ol>

<p>Clearly, case 3 is nothing short of a catastrophe. This is why we are extremely keen not to have any client with more than 2/3 of the stake. Then no invalid block can ever be finalized, and this can never happen.</p>

<h2 id="risk-analysis">Risk analysis</h2>

<p>So how do we evaluate these scenarios? A typical risk analysis strategy is to evaluate the likelihood of an event happening (1 – extremely unlikely, 5 – quite likely) as well as the impact (1 – very low, 5 – catastrophic). The most important risks to focus on are those that score high on both metrics, represented by the product of impact and likelihood.</p>

<table>
  <thead>
    <tr>
      <th>Scenario</th>
      <th>Likelihood</th>
      <th>Impact</th>
      <th>Product (Impact * Likelihood)</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Scenario 1</td>
      <td>1</td>
      <td>5</td>
      <td>5</td>
    </tr>
    <tr>
      <td>Scenario 2</td>
      <td>4</td>
      <td>2</td>
      <td>8</td>
    </tr>
    <tr>
      <td>Scenario 3</td>
      <td>3</td>
      <td>5</td>
      <td>15</td>
    </tr>
  </tbody>
</table>

<p>Looking at this, by far the highest priority is scenario 3. The impact when one client is in a 2/3 supermajority is quite catastrophic, and it is also a relatively likely scenario. To highlight how easily such a bug can happen, a bug of this sort happened recently on the Kiln testnet (see <a href="https://hackmd.io/@prysmaticlabs/HyZqgTA-c">Kiln testnet block proposal failure</a>). In this case, Prysm did detect that the block was faulty after proposing it, and did not attest to it. Had Prysm considered that block as valid, and this had happened on mainnet, then we would be in the catastrophic case described in case 3 of scenario 3 – because Prysm <a href="https://pools.invis.cloud/">currently has a 2/3 majority in mainnet</a>. So if you are currently running Prysm, there is a very real risk that you could lose all your funds and you should consider switching clients.</p>

<p>Scenario 1, which people are probably most worried about, received a relatively low rating. The reason for this is that I consider the likelihood of it happening to be quite low, because I think that the Validator Client software is very well implemented in all clients and it is unlikely to produce slashable attestations or blocks.</p>

<h1 id="what-are-my-options-if-i-currently-run-the-majority-client-and-im-worried-about-switching">What are my options, if I currently run the majority client and I’m worried about switching?</h1>

<p>Switching clients can be a major undertaking. It also comes with some risks. What if the slashing database is not properly migrated to the new setup? There might be a risk of getting slashed, which completely defeats the purpose.</p>

<p>There is another option that I would suggest to anyone who is worried about this. It is also possible to leave your validator setup exactly as it is (no need to take those keys out etc.) and only switch the beacon node. This is extremely low risk because as long as the validator client is working as intended, it will never double sign and thus cannot be slashed. Especially if you have large operations, where changing the validator client (or remote signer) infrastructure would be very expensive and might require audits, this may be a good option. Should the setup perform less well than expected, it can also be easily switched back to the original client or another minority client can be tried.</p>

<p>The nice thing is that you have very little to worry about when switching your beacon node: The worst thing it can do to you is to be temporarily offline. That’s because the beacon node itself can never produce a slashable message on its own. And you can’t end up in scenario 3 if you’re running a minority client, because even if you would vote for an invalid block, that block would not get enough votes to be finalized.</p>

<h1 id="how-about-the-execution-clients">How about the execution clients?</h1>

<p>What I have written above applies to the Consensus clients – Prysm, Lighthouse, Nimbus, Lodestar and Teku, of which at the time of writing, Prysm likely has a 2/3 majority on the network.</p>

<p>All of this applies in the same way to the execution client. Should Go-ethereum, likely to be the majority execution client after the merge, produce an invalid block, it could get finalized and thus cause the catastrophic failure described in scenario 3.</p>

<p>Luckily, we now have three other execution clients ready for production – Nethermind, Besu and Erigon. If you are a staker, I highly recommend running one of these. If you are running a minority client, the risks are very low! But if you run the majority client, you are at serious risk of losing all your funds.</p>

<h1 id="appendix">Appendix</h1>

<h2 id="a1-why-is-there-no-slashing-for-invalid-blocks">A1: Why is there no slashing for invalid blocks?</h2>

<p>In Scenario 3, we have to rely on the quadratic inactivity leak to punish validators for proposing and voting for an invalid block. That’s strange – why don’t we just punish them directly? It would be faster and less painful to watch.</p>

<p>There are actually two reasons why we don’t do this – one is that we currently can’t, but even if we could, we may well not do it:</p>

<ol>
  <li>
    <p>Currently, it is practically impossible to introduce a penalty (“slashing”) for invalid blocks. The reason for this is that neither the beacon chain nor the execution chain are currently “<a href="/ethereum/2021/02/14/why-stateless.html">stateless</a>” – i.e. in order to check whether a block is valid, you need a context (the “state”) that is 100s of MB (beacon chain) or GB (execution chain) large. This means there is no “concise proof” that a block is invalid. We need such a proof to slash a validator: The block that “slashes” a validator needs to include a proof that the validator has made an offence.
  There are ways around this without having a stateless consensus, however it would involve much more complex constructions such as multi-round fraud proofs, such as Arbitrum is currently using for their rollup.</p>
  </li>
  <li>
    <p>The second reason why we might not be that eager to introduce this type of slashing even if we could, is because producing invalid blocks is a much harder thing to protect against than the current slashing conditions. The current conditions are extremely simple and can be validated easily in a few lines of code by validator clients. This is why I consider scenario 1 above so unlikely – slashable messages have so far only been produced by operator failures, and I think that’s likely to remain the case.
Adding slashing for producing invalid blocks (or attesting to them) raises the risks for stakers. Now even those running minority clients could risk serious penalties.</p>
  </li>
</ol>

<p>In summary, we are unlikely to see direct penalties for invalid blocks and/or attestations to them for the next few years.</p>

<h2 id="a2-why-cant-the-buggy-client-switch-to-chain-b-once-it-has-finalized-chain-a">A2: Why can’t the buggy client switch to chain B once it has finalized chain A?</h2>

<p>This section is for anyone who wants to understand in more detail why the buggy client can’t just switch back and has to suffer the horrendous inactivity leak. For this we have to look how Casper FFG finalization works.</p>

<p>Each attestation contains a source and a target checkpoint. A checkpoint is the first block of an epoch. If there is a link from one epoch to another which has a total of &gt;2/3 of all stake voting for it (i.e., there are this many attestations with the first checkpoint as the “source” and the second checkpoint as the “target”), then we call this a “supermajority link”.</p>

<p>An epoch can be “justified” and “finalized”. These are defined as follows:</p>

<ol>
  <li>Epoch 0 is justified</li>
  <li>An epoch is justified if there is a supermajority link from a justified epoch.</li>
  <li>An epoch X is finalized if (1) the epoch X is justified and (2) the next epoch is also justified, with the source of the supermajority link being epoch X</li>
</ol>

<p>Rule 3 is slightly simplified (there are more conditions under which an epoch can be finalized, but they aren’t important for this discussion). Now let’s come to the slashing conditions. There are two rules for slashing attestations. Both compare a pair of attestations V and W:</p>

<ol>
  <li>They are slashable if the target of V and W is the same epoch (i.e. the same height), but they don’t vote for the same checkpoint (double vote)</li>
  <li>They are slashable if V “jumps over” W. What this means as that (1) the source of V is earlier than the source of W and (2) the target of V is later than the target of W (surround vote)</li>
</ol>

<p>The first condition is obvious: It prevents simply voting for two different chains at the same height. But what does the second condition do?</p>

<p>Its function is to slash all validators that take part in finalizing two conflicting chains (which should never happen). To see why, let’s look at our scenario 3 again, in the worst case where the buggy client is in a supermajority (&gt;2/3 of the stake). As it continues voting for the faulty chain, it will finalize the epoch with the invalid block, like this:</p>

<p><img src="/assets/invalid-finalization.png" alt="" /></p>

<p>The rounded boxes in this picture represent epochs, not blocks. The green arrow is the last supermajority link created by all validators. The red arrows are supermajority links that were only supported by the buggy client. Correctly working clients ignore the epoch with the invalid block (red). The first red arrow will justify the invalid epoch, and the second one finalizes it.</p>

<p>Now let’s assume that the bug has been fixed and the validators that finalized the invalid epoch would like to rejoin the correct chain <strong>B</strong>. In order to be able to finalize the chain, a first step is to justify epoch X:</p>

<p><img src="/assets/invalid-finalization-2.png" alt="" /></p>

<p>However, in order to participate in the justification of epoch X (which needs a supermajority link as indicated by the dashed green arrow), they would have to “jump over” the second red arrow – the one that finalized the invalid epoch. Voting for both of these links is a slashable offense.</p>

<p>This continues to be true for any later epoch. The only way it will get fixed is through the quadratic inactivity leak: As chain <strong>B</strong> grows, the locked out validators will leak their funds until chain <strong>B</strong> can be justified and finalized by the correctly working clients.</p>]]></content><author><name></name></author><category term="ethereum" /><category term="economics" /><category term="english" /><summary type="html"><![CDATA[Special thanks to Vitalik Buterin, Hsiao-Wei Wang and Caspar Schwarz-Schilling for feedback and review.]]></summary></entry><entry><title type="html">Exponential EIP-1559</title><link href="https://dankradfeist.de/ethereum/2022/03/16/exponential-eip1559.html" rel="alternate" type="text/html" title="Exponential EIP-1559" /><published>2022-03-16T11:00:00+00:00</published><updated>2022-03-16T11:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2022/03/16/exponential-eip1559</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2022/03/16/exponential-eip1559.html"><![CDATA[<h1 id="exponential-eip-1559-explainer">Exponential EIP-1559 explainer</h1>

<p>In this blog post I will try to help understand how the exponential version of EIP-1559 works – the one that was suggested for the <a href="https://notes.ethereum.org/@vbuterin/blob_transactions">Shard Blob EIP</a>.</p>

<p>I’m not going to try to explain how the EIP-1559 mechanism works – good explainers already exist, for example <a href="https://barnabe.substack.com/p/congestion-control-and-EIP-1559">by Barnabé Monnot</a>.</p>

<h2 id="linear-eip-1559-mechanics-original-version">Linear EIP-1559 mechanics (“original version”)</h2>

<p>I will call the current implementation of <a href="https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md">EIP-1559</a> the “linear version” of EIP-1559.</p>

<p>In the linear version, we define the constants</p>

\[T = 15{,}000{,}000 \text{    (Gas target)}\\
A = 8 \text{ (Max base fee change denominator)}\]

<p>Each block \(B_i\) has a base fee of \(b_i\) and total gas consumed in the block of \(g_i\). There is an update rule for the Basefee:</p>

\[b_{i+1} = b_i \cdot \left(1+ \frac{1}{A}\frac{g_i - T}{T}\right)\]

<p>There is also a constraint that the maximum amount of gas per block can’t be more than \(2 T\). However, this limit is not important in the scope of this post so I will ignore it.</p>

<h2 id="exponential-eip-1559">Exponential EIP-1559</h2>

<p>One way to understand this “linear EIP-1559” better is to compute what happens after many updates. In particular, how does \(b_n\) depend on \(b_0\)? By substituting the equation into itself many times, we get</p>

\[b_{n} = b_0 \prod_{i=0}^{n-1} \left(1+ \frac{1}{A}\frac{g_i - T}{T}\right)\]

<p>Now let’s say that \(A\) is a large number, so that all the terms of the form \(\frac{1}{A}\frac{g_i - T}{T}\) are small? Let’s call \(x_i = \frac{g_i - T}{T}\).</p>

<p>If we assume this, we can use an approximation: The exponential function \(e^x \approx 1+x\)  for small \(x\). We use this approximation in the inverse to replace \(1+\frac{x_i}{A} = e^{\frac{x_i}{A}}\) to get</p>

\[b_{n} = b_0 \prod_{i=0}^{n-1} \left(1+ \frac{x_i}{A}\right) \approx b_0 \prod_{i=0}^{n-1} e^\frac{x_i}{A} = b_0 \exp\left(\frac{1}{A}\sum_{i=0}^{n-1}x_i\right)\]

<p>For the last step, we have used the property that \(e^x \cdot e^y = e^{x+y}\). Note that</p>

\[\frac{1}{A}\sum_{i=0}^{n-1}x_i = \frac{1}{TA}\sum_{i=0}^{n-1}(g_i - T) = \frac{1}{TA}\left(\sum_{i=0}^{n-1}g_i - nT\right)\]

<p>so we get this new formula for \(b_n\)</p>

\[b_{n} = b_0 \exp\left(\frac{1}{TA}\left(\sum_{i=0}^{n-1}g_i - nT\right)\right)= b_0 \exp\left(\frac{1}{TA}\left(G_n - T_n\right)\right)\]

<p>where we used \(G_n = \sum_{i=0}^{n-1}g_i\) for the total gas used since block 0 and \(T_n = nT\) the cumulative gas target.</p>

<p>This is the exponential form of EIP-1559. The only thing we need to keep track of to compute the basefee current \(b_n\) is (1) the total gas used, which is \(G_n = \sum_{i=0}^{n-1}g_i\), and the total gas target, which is represented by \(T_n = nT\) (so it’s enough to just count the number of blocks).</p>

<h2 id="analyzing-the-exponential-form">Analyzing the exponential form</h2>

<p>Here is a question I have heard many times about  exponential EIP-1559: Isn’t the goal of EIP-1559 that in the long term, the total gas used \(G_n\) equals to the gas target \(T_n\)?</p>

<p>And if so, if you evaluate the equation for \(G_n = T_n\), the exponential becomes one and thus \(b_n = b_0\). So if the target is achieved, then the basefee would always be \(b_0\) (which is typically very low)?</p>

<p>Here I will explain why this is not the case. Let’s see how this happens in linear EIP-1559 first. Here is a very simple economic model: Let’s assume a there is a “fair price” for gas at price \(p\). For simplicity assume that below \(p\), demand is infinite: All blocks will be filled. Above \(p\), blocks will be empty. And when the base fee is equal to \(p\), then there will be exactly enough demand to fill the blocks to half.</p>

<p>So what will happen in this model in linear EIP-1559?</p>
<ul>
  <li>We assume that the base fee starts of low with \(b_0 &lt; p\).</li>
  <li>Then there will be a number of \(n_0\) blocks where the basefee is lower than \(p\), which will be completely full by our assumption.</li>
  <li>When the basefee reaches \(p\) at \(n_0\), all futher blocks will be filled to target.</li>
</ul>

<p>To keep things simple, say the max block size is exactly \(2T\). Then how much gas has been used at any block \(n&gt;n_0\)? It would be \(G_n = 2 n_0 T + (n - n_0) T = n_0 T + n T = T_n + n_0 T\). So it is actually not exactly the target, despite the EIP-1559 mechanism now being in equilibrium.</p>

<p>What happened? Note that it is still correct to say that EIP-1559 will ensure \(G_n \approx T_n\); for example, if you take the fraction \(\frac{G_n}{T_n}\), it will tend to \(1\) so in asymptotic notation we would write \(G_n \sim T_n\).</p>

<p>But there is a constant difference between \(G_n\) and \(T_n\), which is the amount of gas that was needed to shift the basefee from \(b_0\) to \(p\).</p>

<p>More generally, the current difference between \(G_n\) and \(T_n\) is a constant determined by the current basefee. In the linear version, this is approximately true; in the exponential version, it is exactly true (it follows directly from the definition \(b_{n} = b_0 \exp\left(\frac{1}{TA}\left(G_n - T_n\right)\right)\))</p>

<h2 id="graphical-illustration">Graphical illustration</h2>

<p>First let’s look at our simplified example. The following graph illustrates what is happening: Above you see the relation between total gas used and the basefee (an exponential function). Once in equilibrium, the basefee is at \(p\) which means that \(G_n-T_n = n_0 T\). Below we see how this adds up. The green shaded area of gas used is the blocks filled up to the target, and the orange area is the gas used above the target that sums up to \(n_0 T\).
<img src="/assets/eip1559-1.png" alt="" /></p>

<p>Next we look at a generic example, where some blocks are filled with more than target gas and some blocks are below. In this case, we need to sum up all the gas consumed by each block above the target (marked in green) and substract the gas that was below the target in underfull blocks (marked with red and white diagonal stripes). We can then read the sum on the \(x\) axis of the basefee relation to determine the basefee \(b_n\).
<img src="/assets/eip1559-2.png" alt="" /></p>

<h2 id="appendix-using-differential-equations-to-derive-the-exponential-form">Appendix: Using differential equations to derive the exponential form</h2>

<p>Here is another way of deriving the exponential form, using differential equations:</p>

<p>Let’s start from the update rule of linear EIP-1559</p>

\[b_{i+1} = b_i \cdot \left(1+ \frac{1}{A}\frac{g_i - T}{T}\right)\]

<p>We can rewrite this as</p>

\[b_{i+1} - b_i = b_i  \frac{1}{A}\frac{g_i - T}{T}\]

<p>This is mathematically a <a href="https://en.wikipedia.org/wiki/Linear_recurrence_with_constant_coefficients">difference equation</a>. This is similar to a differential equation, but for finite differences. However, we can “approximate” it as a differential equation, by changing \(i\) into a continuous variable and writing</p>

\[b'(i) = b(i)  \frac{1}{A}\frac{g(i) - T}{T}\]

<p>where we use that \(b(i)-b(i+1) \approx b'(i)\). You could say that this form comes about naturally if you assume that we are making the blocks smaller and smaller, scaling the target as well. As the size of the blocks goes towards zero, we get the differential equation.</p>

<p>This is a linear ordinary differential equation of first order that can be solved by moving the terms depending on \(b\) to one side:</p>

\[\frac{b'(i)}{b(i)} = \frac{1}{A}\frac{g(i) - T}{T}\]

<p>Integrating on both sides yields:</p>

\[\int\frac{b'(i)}{b(i)}  = \ln b(i) = \int_{i=0}^n \frac{1}{A}\frac{g(i) - T}{T} + C\]

<p>This is because</p>

\[\frac{\mathrm{d}}{\mathrm{d}i} \ln b(i) = \frac{b'(i)}{b(i)}\]

<p>So we can exponentiate and get</p>

\[b(i) = \exp\left(\int_{i=0}^n \frac{1}{A}\frac{g(i) - T}{T} + C\right)\]

<p>Since we want \(b(0)=b_0\) we get \(C=\ln b_0\) and so</p>

\[b(i) = b_0\exp\left(\int_{i=0}^n \frac{1}{A}\frac{g(i) - T}{T}\right)\]

<p>This looks almost the same that we derived above – except we now have an integral instead of a sum, because we are working with the continuous form.</p>

<p>The exponential version thus arises naturally when you consider very small blocks and update the basefee each time. From this perspective, it is the most natural way of implementing EIP-1559.</p>]]></content><author><name></name></author><category term="ethereum" /><category term="economics" /><category term="english" /><summary type="html"><![CDATA[Exponential EIP-1559 explainer]]></summary></entry><entry><title type="html">内积证明</title><link href="https://dankradfeist.de/ethereum/2021/11/18/inner-product-arguments-mandarin.html" rel="alternate" type="text/html" title="内积证明" /><published>2021-11-18T17:00:00+00:00</published><updated>2021-11-18T17:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2021/11/18/inner-product-arguments-mandarin</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2021/11/18/inner-product-arguments-mandarin.html"><![CDATA[<p>原文链接： <a href="/ethereum/2021/07/27/inner-product-arguments.html">Inner Product Arguments</a></p>

<p>翻译：Star.LI @ Trapdoor Tech</p>

<h2 id="介绍">介绍</h2>

<p>你也许听说过“BulletProofs”：它是一种零知识证明算法，不要求可信设置。比如，门罗币（Monero）就用了这个算法。这种证明系统的核心是内积证明<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>，一个能让证明者向验证者证明“内积“正确性的小技巧。内积，即是计算两个向量中每个分量的乘积和：</p>

\[\begin{align*} \vec a \cdot \vec b = a_0 b_0 + a_1 b_1 + a_2 b_2 + \cdots + a_{n-1} b_{n-1} 
\end{align*}\]

<p>其中 \(\vec a = (a_0, a_1, \ldots, a_{n-1})\), \(\vec b = (b_0, b_1, \ldots, b_{n-1})\)。</p>

<p>一个比较有趣的例子就是当我们设置向量 \(\vec b\) 为某个 \(z\) 的幂，即 \(\vec b = (1, z, z^2, \ldots, z^{n-1})\)，那么它的内积就变成了多项式</p>

\[\begin{align*} f(X) = \sum_{i=0}^{n-1} a_i X^i
\end{align*}\]

<p>在 \(z\) 点的取值。</p>

<p>内积证明采用<em>Pedersen承诺</em>。我之前写过一篇文章介绍<a href="/ethereum/2021/10/13/kate-polynomial-commitments-mandarin.html">KZG承诺</a>，Pedersen承诺与其类似，承诺值也是在椭圆曲线上的，不同的是它不需要可信设置。下面比较这两个多项式承诺方案(PCS)，KZG承诺方案 和 Pedersen承诺与内积证明相结合的方案:</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Pedersen+IPA</th>
      <th>KZG</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>安全假设</td>
      <td>离散对数</td>
      <td>双线性群</td>
    </tr>
    <tr>
      <td>可信设置</td>
      <td>否</td>
      <td>是</td>
    </tr>
    <tr>
      <td>承诺大小</td>
      <td>1个群元素</td>
      <td>1个群元素</td>
    </tr>
    <tr>
      <td>证明大小</td>
      <td>2 log n个 群元素</td>
      <td>1个群元素</td>
    </tr>
    <tr>
      <td>验证</td>
      <td>O(n) 群运算</td>
      <td>1个配对</td>
    </tr>
  </tbody>
</table>

<p>说到底，和KZG承诺相比，我们这个承诺方案的效率要低一些。证明大小更大（\(O(\log n)\)），不过对数本身还是挺小的，所以不至于太糟。但可惜的是验证者需要做的计算是线性的, 这失去了简洁性。这些局限使得 Pedersen 承诺对于某些应用来说不太现实，但在一些情况下这些缺点可以被规避。</p>

<ul>
  <li>其中一个例子我在之前的文章<a href="/ethereum/2021/06/18/pcs-multiproofs.html">多重打开</a>中曾经提到过。这里的诀窍是你可以将多个打开聚合成一个。</li>
  <li>Halo2 <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>, 其中多个打开的线性成本可以被聚合。</li>
</ul>

<p>在以上这两个例子中，特点就是多个打开的成本被分摊了。如果你只想打开一个多项式，那就比较困难了，你需要承担整个打开的运算成本。</p>

<p>但是，Pedersen 承诺与内积证明结合的方案，很大的好处是较少的安全假设。也就是，不需要配对，并且不需要可信设置。</p>

<h2 id="pedersen-承诺">Pedersen 承诺</h2>

<p>在我们讨论内积证明之前，我们要先看一下依赖的结构：Pedersen承诺。为了使用Pedersen承诺，我们需要一个椭圆曲线 \(G\)。让我们首先回顾一下我们使用椭圆曲线可以做到哪些事情（在这里我会使用加法符号表示，看起来更自然一些）：</p>

<ol>
  <li>你可以将两个椭圆曲线点 \(g_0 \in G\) 和 \(g_1 \in G\) 相加: \(h = g_0 + g_1\)</li>
  <li>你可以将元素\(g \in G\)与一个标量\(a \in \mathbb F_p\)相乘，其中\(p\)是\(G\)椭圆曲线的阶 (即元素数量): \(h=ag\)</li>
</ol>

<p>无法计算两个曲线元素的“乘积”：“\(h * h\)”运算是未定义的，所以你没办法计算“\(h * h = a g * a g = a^2 g\)”；与此相反，与标量相乘是很容易计算的，比如 \(2 h = 2 a g\)。</p>

<p>另一个重要的性质就是不存在有效的计算“离散对数”的算法，这意味着对于满足\(h = a g\)的给定的\(h\)和\(g\)，如果你不知道\(a\)，\(a\)是不可计算的，我们称\(a\)为\(h\)对于\(g\)的离散对数。</p>

<p>Pedersen承诺则利用该不可计算性来构造承诺方案。假设有两个点\(g_0\)和\(g_1\)，它们的离散对数(比如存在\(x \in \mathbb F_p\)使得\(g_1 = x g_0\))并不可知，那么我们可以向两个数\(a_0, a_1 \in \mathbb F_p\)提交承诺:</p>

\[\begin{align*}
C = a_0 g_0 + a_1 g_1
\end{align*}\]

<p>\(C\)为椭圆曲线\(G\)的一个元素。</p>

<p>为打开一个承诺，证明者给验证者\(a_0\)和\(a_1\)，然后验证者计算\(C\)，如果相等的话就被接受。</p>

<p>承诺方案的中心性质在于它是不是绑定（binding）。给定\(C=a_0 g_0 + a_1 g_1\)，一个试图作弊的证明者是否能够生成\(b_0, b_1 \in \mathbb F_p\)并使验证者接受它们，即同时满足\(C = b_0 g_0 + b_1 g_1\) 且\(b_0, b_1 \not= a_0, a_1\)。</p>

<p>如果有人能做到上述行为的话，那么它们也可以找出离散对数。为什么呢？我们知道\(a_0 g_0 + a_1 g_1 = b_0 g_0 + b_1 g_1\)，整理后可得</p>

\[\begin{align*} (a_0 - b_0) g_0 = (b_1 - a_1) g_1
\end{align*}\]

<p>所以\(a_0 − b_0\)和\(b_1 − a_1\)不可同时为0。假说\(a_0 − b_0\)不为零，我们得到：</p>

\[\begin{align*} g_0 = \frac{b_1 - a_1}{a_0 - b_0} g_1 = x g_1
\end{align*}\]

<p>对于\(x = \frac{b_1 - a_1}{a_0 - b_0}\)。这样我们就找到了\(x\)的值。我们知道该问题是难题，所以在现实中没有攻击者能够做到。</p>

<p>这意味着对于攻击者来说找到另外的\(b_0 , b_1\)来打开承诺\(C\)在计算性上是不可能的。（它们的确存在，只是无法通过计算获得 – 就像哈希碰撞）。</p>

<p>我们可以扩展一个向量的承诺，比如说一个标量列表\(a_0, a_1, \ldots, a_{n-1} \in \mathbb F_p\)。我们只是需要一个“基”，即一个相等数量的互相未知离散对数的群元素，然后我们就可以计算承诺了：</p>

\[\begin{align*} C = a_0 g_0 + a_1 g_1 + a_2 g_2 + \ldots + a_{n-1} g_{n-1}
\end{align*}\]

<p>这给了我们一个向量承诺，尽管这个承诺相对复杂：为了打开任意元素，必须打开所有的元素。但这里有一个重要的性质：这个承诺方案是加同态的，这意味着如果我们有另外一个承诺\(D = b_0 g_0 + b_1 g_1 + b_2 g_2 + \ldots + b_{n-1} g_{n-1}\)，那么我们可能可以通过添加两个承诺得到两个向量\(\vec a\) 和 \(\vec b\)的和:</p>

\[\begin{align*} C + D = (a_0 + b_0) g_0 + (a_1 + b_1) g_1 + (a_2 + b_2) g_2 + \ldots + (a_{n-1} + b_{n-1}) g_{n-1}
\end{align*}\]

<p>因为有了加同态的性质，这个向量承诺就变得有用了。</p>

<h2 id="内积证明">内积证明</h2>

<p>内积证明的基本策略是“分治法”：将一个问题规约成多个同类型的子问题，而不是试图一步完全解决它。当子问题规约到一定程度的时候，就可以简单解决。</p>

<p>在这当中每一步，问题的大小都会减半。这保证了\(\log n\)步后，问题大小会减少到1，可以通过简单证明解决。</p>

<p>假设我们需要证明的承诺 \(C\) 具有以下形式：</p>

\[\begin{align*} C = \vec a \cdot \vec g + \vec b \cdot \vec h + (\vec a \cdot \vec b) q
\end{align*}\]

<p>其中 \(\vec g = (g_0, g_1, \ldots, g_{n-1}), \vec h = (h_0, h_1, \ldots, h_{n-1})\) ，且 \(q\) 是我们的“基”，即：它们是群 \(G\) 中的元素，并且它们之间对于任意一方的离散对数都未知。同时介绍一种新的表示方法：\(\vec a \cdot \vec g\)，一个由标量组成的向量（\(\vec a\)）和另一个由群元素组成的向量（\(\vec g\)）的乘积，我们将其定义为</p>

\[\begin{align*}  \vec a \cdot \vec g = a_0 g_0 + a_1 g_1 + \cdots + a_{n-1} g_{n-1} 
\end{align*}\]

<p>也就是说，我们要证明 \(C\) 是以下元素的承诺</p>

<ul>
  <li>基为 \(\vec g\) 的向量 \(\vec a\)</li>
  <li>基为 \(\vec h\) 的向量 \(\vec b\)</li>
  <li>基为 \(q\) 的内积 \(\vec a \cdot \vec b\) 。</li>
</ul>

<p>单看本身似乎并不是很有用 – 在大多数应用中我们想让验证者知道 \(\vec a \cdot \vec b\)，而不是仅仅将这个结果藏在一个承诺里。这可以通过我后面要讲到的一个小技巧来解决。</p>

<h2 id="证明">证明</h2>

<p>我们想让证明者向验证者证明 \(C\) 的确具有形式 \(C = \vec a \cdot \vec g + \vec b \cdot \vec h + (\vec a \cdot \vec b) q\)。就像之前提到的，不是直接证明，而是要把这个问题规约成，如果这一性质对于另一个承诺 \(C′\) 成立，则 \(C\) 也满足该性质。</p>

<p>接下来证明者就要和验证者玩一个小游戏了。证明者提交一些信息，然后验证者发起一个挑战，从而引出下一个承诺 \(C′\)。将它称作一个游戏不代表这个证明必须是交互的：Fiat-Shamir算法允许我们通过将挑战换成一个承诺的抗碰撞哈希值，从而将交互式的证明转化成非交互式的。</p>

<h3 id="证明描述">证明描述</h3>

<p>承诺 \(C\) 符合 \(C = \vec a \cdot \vec g + \vec b \cdot \vec h + (\vec a \cdot \vec b) q\) 的形式，并且以\(\vec g, \vec h, q\)为基。我们将符合这样形式的 \(C\) 称为拥有“内积性质”。</p>

<h3 id="规约步骤">规约步骤</h3>

<p>假设 \(m = \frac{n}{2}\), 证明者计算</p>

\[\begin{align*}  z_L = a_m b_0 + a_{m+1} b_1 + \cdots + a_{n-1} b_{m-1} = \vec a_R \cdot \vec b_L \\ z_R = a_0 b_m + a_{1} b_{m+1} + \cdots + a_{m-1} b_{n-1} = \vec a_L \cdot \vec b_R 
\end{align*}\]

<p>这里我们定义 \(\vec a_L\) 为向量 \(\vec a\) 的“左半部”，\(\vec a_R\) 为“右半部”，向量 \(\vec b\) 类似。</p>

<p>然后证明者计算如下的承诺：</p>

\[\begin{align*}  C_L = \vec a_R \cdot \vec g_L + \vec b_L \cdot \vec h_R + z_L q \\ C_R = \vec a_L \cdot \vec g_R + \vec b_R \cdot \vec h_L + z_R q 
\end{align*}\]

<p>并发送给验证者。然后验证者发送挑战 \(x \in \mathbb F_p\) (通过使用Fiat-Shamir将它变成非交互式的，这意味着 \(x\) 是 \(C_L\) 和  \(C_R\) 的哈希)。证明者以此来计算更新的向量：</p>

\[\begin{align*}  \vec a' = \vec a_L + x \vec a_R \\ \vec b' = \vec b_L + x^{-1} \vec b_R 
\end{align*}\]

<p>长度为原向量的一半。</p>

<p>现在，验证者计算新的承诺：</p>

\[\begin{align*}   C' = x C_L + C + x^{-1} C_R 
\end{align*}\]

<p>还有更新的基：</p>

\[\begin{align*}   \vec g' = \vec g_L + x^{-1} \vec g_R \\ \vec h' = \vec h_L + x \vec h_R 
\end{align*}\]

<p>现在，如果新的承诺 \(C′\) 符合了 \(C' = \vec a' \cdot \vec g' +\vec b' \cdot \vec h' + \vec a' \cdot \vec b' q\)的形式 - 那么承诺\(C\)就遵从最初的假设，拥有“内积性质”。</p>

<p>所有的向量大小都减半 – 这让我们离成功又近一步。在这里我们替换 \(C:=C'\), \(\vec g := \vec g'\)，\(\vec h := \vec h'\) 并重复以上步骤。</p>

<p>接下来我解释这个方法可行的数学原理，同时推荐你们去看看 Vitalik 所做的一个漂亮的<a href="https://twitter.com/VitalikButerin/status/1371844878968176647">可视化展示</a> 以得到一些直观的感受。</p>

<h3 id="最终步骤">最终步骤</h3>

<p>当我们一直重复以上步骤，n每次降低一半。最终我们会到达\(n=1\)，然后就可以停下了。这时证明者发送\(\vec a\)和\(\vec b\)两个向量，事实上就是两个标量，然后验证者就可以非常直观地计算：</p>

\[\begin{align*}  D = a g + b h + a b q 
\end{align*}\]

<p>如果等于 \(C\) 就接受，反之则拒绝。</p>

<h3 id="正确性correctness-及合理性soundness">正确性(correctness) 及合理性(soundness)</h3>

<p>在之前我假设 \(C′\) 为我们所需要的形式，然后以此证明 \(C\)也成立。现在我要证明为什么该逻辑成立。我们需要验证以下两点：</p>

<ul>
  <li><em>正确性</em> – 即当证明者遵从相应操作的时候，它们可以达到说服验证者该结论为正确的目的；</li>
  <li><em>合理性</em> – 即试图作弊的证明者不能使用错误的证明通过验证者验证，或者成功率低至可忽略不计。</li>
</ul>

<p>让我们从正确性证起，假设证明者依照操作进行每一个步骤。既然如此，我们知道给定 \(\vec g, \vec h, q\) 为基，\(C = \vec a \cdot \vec g + \vec b \cdot \vec h + (\vec a \cdot \vec b) q\)，同时 \(C'= \vec a' \cdot \vec g' +\vec b' \cdot \vec h' + \vec a' \cdot \vec b' q\)。</p>

<p>验证者计算\(C' = x C_L + C + x^{-1} C_R\)。</p>

\[\begin{eqnarray} C' &amp; = &amp; x C_L + C + x^{-1} C_R \\ &amp; = &amp; x ( \vec a_R \cdot \vec g_L + \vec b_L \cdot \vec h_R + z_L q) \\  &amp;  &amp; +  \vec a_L \cdot \vec g_L +  \vec a_R \cdot \vec g_R + \vec b_L \cdot \vec h_L + \vec b_R \cdot \vec h_R + \vec a \cdot \vec b q \\ &amp;  &amp; + x^{-1} (\vec a_L \cdot \vec g_R + \vec b_R \cdot \vec h_L + z_R q) \\ &amp; = &amp; (x \vec a_R + \vec a_L)\cdot(\vec g_L + x^{-1} \vec g_R) \\ &amp; &amp; + (\vec b_L + x^{-1} \vec b_R)\cdot(\vec h_L + x \vec h_R) \\ &amp; &amp;  + (x z_L + \vec a \cdot \vec b + x^{-1} z_R) q \\ &amp;=&amp; (x \vec a_R + \vec a_L)\cdot \vec g' + (\vec b_L + x^{-1} \vec b_R)\cdot \vec h' + (x z_L + \vec a \cdot \vec b + x^{-1} z_R) q
\end{eqnarray}\]

<p>为了使承诺具有内积属性，我们需要验证 \((x \vec a_R + \vec a_L) \cdot (\vec b_L + x^{-1} \vec b_R) = x z_L + \vec a \cdot \vec b + x^{-1} z_R\)。这个等式成立，因为</p>

\[\begin{eqnarray} (x \vec a_R + \vec a_L) \cdot (\vec b_L + x^{-1} \vec b_R) &amp; = &amp; x \vec a_R \cdot \vec b_L + \vec a_L \cdot \vec b_L + \vec a_R \cdot \vec b_R + x^{-1} \vec a_L \cdot \vec b_R \\ &amp; = &amp; x z_L + \vec a \cdot \vec b + x^{-1} z_R \end{eqnarray}\]

<p>这样正确性就证明了。为证明合理性，我们需要证明，证明者的初始承诺 \(C\) 不具有内积属性，那么通过规约步骤，是无法产生一个具有内积属性的承诺 \(C'\)。</p>

<p>假设证明者提交了 \(C=\vec a \cdot \vec g + \vec b \cdot \vec h + r q\)，其中 \(r \neq \vec a \cdot \vec b\)。如果我们走一遍如上的规约步骤，我们会得到</p>

\[\begin{align*}   C' = (x \vec a_R + \vec a_L)\cdot \vec g' + (\vec b_L + x^{-1} \vec b_R)\cdot \vec h' + (x z_L + r + x^{-1} z_R) q 
\end{align*}\]

<p>所以现在我们假设证明者成功作弊，那么 \(C′\) 就满足了内积属性，则有：</p>

\[\begin{align*}  (x \vec a_R + \vec a_L) \cdot (\vec b_L + x^{-1} \vec b_R) = x z_L + r + x^{-1} z_R 
\end{align*}\]

<p>展开左侧可得</p>

\[\begin{align*}  x \vec a_R \cdot \vec b_L + \vec a \cdot \vec b + x^{-1} \vec a_L \cdot \vec b_R = x z_L + r + x^{-1} z_R
\end{align*}\]

<p>注意证明者可以自由选择 \(z_L\) 和 \(z_R\)，所以我们不能直接假设它们会遵从以上定义。</p>

<p>同时乘以 \(x\) 并移到同一边，我们得到 \(x\) 的二次方程式：</p>

\[\begin{align*}  x^2 ( \vec a_R \cdot \vec b_L - z_L) + x (\vec a \cdot \vec b - r) + (\vec a_L \cdot \vec b_R - z_R ) 
\end{align*}\]

<p>除非所有项都为零，该等式至多会有两个解 \(x \in \mathbb F_p\)，但是验证者是在证明者已经承诺了他们的 \(r\), \(z_L\) 和 \(z_R\)值后选择 \(x\)值，证明者能够成功作弊的概率非常小；我们通常选择域 \(\mathbb F_p\) 大小约为 \(2^{256}\)。因此，当证明者不按照协议选择正确值时，验证者选择到一个让等式能够成立的 \(x\) 值的概率微乎其微。</p>

<p>这就完成了我们的合理性证明。</p>

<h3 id="仅在最后计算基变化">仅在最后计算基变化</h3>

<p>验证者在每一轮都需要做两件事：计算挑战 \(x\)，并计算更新的基 \(\vec g'\) 和 \(\vec h'\)。但是在每一轮都更新 \(g\) 效率很低，验证者可以简单地保存他们在 \(k\) 轮中遇到的挑战值 \(x_1 ,  x_2 \dots x_k\)。</p>

<p>假设\(k\)轮后，这些基为 \(\vec g_k, \vec h_k\)。元素\(g_\ell\)和\(h_\ell\)是标量（或者长度为1的向量），因为长度到达1的时候我们会终止协议。通过\(\vec g_0\)计算\(\vec g_\ell\)，是一个长度为n的椭圆曲线上的多标量点乘（MSM）。\(\vec g_0\)的标量因子是下面多项式的系数</p>

\[\begin{align*}  f_g(X) = \prod_{j=0}^{k-1} \left(1+x^{-1}_{k-j} X^{2^{j}}\right)
\end{align*}\]

<p>且\(\vec h_0\)的标量因子由以下多项式给定</p>

\[\begin{align*}  f_h(X) = \prod_{j=0}^{k-1} \left(1+x_{k-j} X^{2^{j}}\right)
\end{align*}\]

<h2 id="使用内积证明来验证多项式值">使用内积证明来验证多项式值</h2>

<p>针对我们的主要应用 – 验证 \(f(x) = \sum_{i=0}^{n-1} a_i x^i\)在\(z\)处的取值 – 我们需要对协议做一些小的扩充。</p>

<ul>
  <li>最重要的一点是，我们想要验证 \(f(z) = \vec a \cdot \vec b\) 的结果，而不仅是承诺 \(C\) 拥有“内积属性”。</li>
  <li>\(\vec b = (1, z, z^2, ..., z^{n-1})\) 对于验证者来说是已知的。因此我们可以把这部分从承诺中移除来简化协议。</li>
</ul>

<h3 id="如何构造承诺">如何构造承诺</h3>

<p>如果我们想要验证多项式\(f(x) = \sum_{i=0}^{n-1} a_i x^i\)，我们通常需要从承诺\(F = \vec a \cdot \vec g\)开始进行构造。证明者可以将\(y=f(z)\)的计算发送给验证者。</p>

<p>那么貌似验证者可以计算最初的承诺\(C=\vec a \cdot \vec g + \vec b \cdot \vec h + \vec a \cdot \vec b q = F + \vec b \cdot \vec h + f(z) q\)，因为他们已知\(\vec b = (1, z, z^2, ..., z^{n-1})\)，然后开始证明流程。</p>

<p>但稍等一下。大多数情况下，\(F\)是证明者生成的承诺，一个恶意的证明者可以在这里作弊，比如说提交一个\(F = \vec a \cdot \vec g + tq\)。在这种情况下，因为证明者生成的承诺有一个偏移，他们能够证明\(f(z) = y - t\)。</p>

<p>为了避免这种情况，我们需要在证明流程中进行一点改变。 收到承诺\(F\)和计算结果\(y\)后，验证者生成一个向量\(w\)并且重新选择基\(q:=wq\)，之后证明继续。因为证明者不能预判\(w\)的取值，它们就无法成功操控除了\(f(z)\)之外的结果（或者说概率极小）。</p>

<p>注意如果想要得到一个通用的内积，我们还要防止证明者操控向量\(\vec b\) – 但在多项式取值的应用中，\(\vec b\)的部分可以完全去掉不用考虑，因此这里略过细节。</p>

<h3 id="如何去掉第二个向量">如何去掉第二个向量</h3>

<p>注意，如果我们想要进行多项式计算，验证者已知向量\(\vec b = (1, z, z^2, ..., z^{n-1})\)。给定挑战\(x_0, x_1, \ldots, x_\ell\)，他们可以通过在“仅在最终计算基变化”一节中提到的技巧简单地得到\(b_\ell\)。</p>

<p>因此，我们可以从所有承诺中移除第二个向量并且只计算\(b_\ell\)。这意味着验证者必须要能够从初始向量\(\vec b_0 = (1, z, z^2, ..., z^{n-1})\)中计算最终的\(b_\ell\)。因为\(\vec b\)的规约过程与基向量\(\vec g\)相同，线性组合也由之前定义的多项式\(f_g\)的系数定义，也就是说\(b_\ell=f_g(z)\)。</p>

<h3 id="针对点值形式多项式的ipa">针对点值形式多项式的IPA</h3>

<p>目前为止，我们用一个内积证明计算了使用它的系数提交的多项式，即一个由\(f(X) = \sum_{i=0}^{n-1} f_i X^i\)定义的多项式中的\(f_i\)。然而，多数情况下我们想要一个在给定定义域\(x_0, x_1, \ldots, x_{n-1}\)计算值定义的多项式。因为任何阶低于\(n−1\)的多项式都是由\(f(x_0), f(x_1), \ldots, f(x_{n-1})\)的计算结果定义的独一无二的多项式，所以这两者是完全相等的。但是这两者之间的转换在计算上非常费时，如果定义域适用快速傅立叶转换的话需要花费\(O(n \log n)\)次计算，否则就是\(O(n^2)\)次。</p>

<p>为了避免这项开销，我们尝试避免使用多项式系数形式。这可以通过提交多项式值\(f\)的承诺的而不是系数的承诺来实现：</p>

\[\begin{align*}
C = f(x_0) g_0 + f(x_1) g_1 + \cdots + f(x_{n-1}) g_{n-1}
\end{align*}\]

<p>这表示我们IPA的向量\(\vec a\)形式为\(\vec a = (f(x_0), f(x_1), \ldots, f(x_{n-1}))\)：</p>

<p><a href="/ethereum/2021/06/18/pcs-multiproofs.html#evaluating-a-polynomial-in-evaluation-form-on-a-point-outside-the-domain">重心公式</a> 使我们现在可以计算这个新的承诺多项式的取值，记作：</p>

\[\begin{align*}
f(z) = A(z)\sum_{i=0}^{n-1} \frac{f(x_i)}{A'(x_i)} \frac{1}{z-x_i}
\end{align*}\]

<p>如果我们选择向量\(\vec b\)</p>

\[\begin{align*} b_i = \frac{A(z)}{A'(x_i)} \frac{1}{z-x_i}
\end{align*}\]

<p>我们可以得到\(\vec a \cdot \vec b = f(z)\)，因此采用这种向量的IPA可以被用作证明点值多项式的取值。除了这一点差异之外，其他的证明过程是完全相同的。</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:2">
      <p>Bowe, Grigg, Hopwood: <a href="https://eprint.iacr.org/2019/1021.pdf">Recursive Proof Composition without a Trusted setup</a> <a href="https://dankradfeist.de/ethereum/2021/07/27/inner-product-arguments.html#fnref:1">↩</a> <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:1">
      <p>Bootle, Cerulli, Chaidos, Groth, Petit: <a href="https://eprint.iacr.org/2016/263.pdf">Efficient Zero-Knowledge Arguments forArithmetic Circuits in the Discrete Log Setting</a> <a href="https://dankradfeist.de/ethereum/2021/07/27/inner-product-arguments.html#fnref:2">↩</a> <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="ethereum" /><category term="cryptography" /><category term="mandarin" /><summary type="html"><![CDATA[原文链接： Inner Product Arguments]]></summary></entry><entry><title type="html">KZG多项式承诺</title><link href="https://dankradfeist.de/ethereum/2021/10/13/kate-polynomial-commitments-mandarin.html" rel="alternate" type="text/html" title="KZG多项式承诺" /><published>2021-10-13T00:00:00+00:00</published><updated>2021-10-13T00:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2021/10/13/kate-polynomial-commitments-mandarin</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2021/10/13/kate-polynomial-commitments-mandarin.html"><![CDATA[<p>原文链接： <a href="/ethereum/2020/06/16/kate-polynomial-commitments.html">KZG Polynomial Commitments</a></p>

<p>翻译：Star.LI @ Trapdoor Tech</p>

<h2 id="简介">简介</h2>

<p>今天我想向你们介绍一下Kate，Zaverucha和Goldberg发表的多项式承诺方案 <sup id="fnref:1"><a href="#fn:1" class="footnote" rel="footnote" role="doc-noteref">1</a></sup>。这篇文章并不涉及复杂的数学及密码学理论知识，仅作为一篇简介。</p>

<p>该方案通常被称作卡特（Kate，读作<a href="https://www.cs.purdue.edu/homes/akate/howtopronounce.html">kah-tay</a>）多项式承诺方案。在一个多项式承诺方案中，证明者计算一个多项式的承诺（commitment）, 并可以在多项式的任意一个点进行打开（opening）：该承诺方案能证明多项式在特定位置的值与指定的数值一致。</p>

<p>之所以被称为<em>承诺</em>，是因为当一个承诺值（椭圆曲线上的一个点）发送给某对象（ <em>验证者</em>），证明者不可以改变当前计算的多项式。它们只能够对一个多项式提供有效的证明；当试图作弊时，它们要不无法提供证明，要不证明被验证者拒绝。</p>

<h3 id="预备知识">预备知识</h3>

<p>如果你对有限域，椭圆曲线和配对这几个话题不是很熟悉的话，非常推荐去读一读<a href="https://vitalik.ca/general/2017/01/14/exploring_ecp.html">Vitalik Buterin的博客：椭圆曲线配对</a>这篇文章。</p>

<h3 id="默克尔树对比">默克尔树对比</h3>

<p>如果你已经熟知默克尔树，我想在此之上和卡特承诺进行对比。默克尔树即是密码学家所说的<em>矢量承诺</em>：运用一个深度为\(d\)的默克尔树，你可以计算一个矢量的承诺（矢量为一个固定长度的列表\(a_0, \ldots, a_{2^d-1}\)）。运用熟知的<em>默克尔证明</em>，你可以用\(d\)个哈希来提供证明元素\(a_i\)存在于这个矢量的位置\(i\)。</p>

<p>事实上，我们可以用默克尔树来构造多项式承诺：回忆一下，一个\(n\)次的多项式\(p(X)\)，无非是一个函数 \(p(X) = \sum_{i=0}^{n} p_i X^i\)，其中\(p_i\)是该多项式的系数。</p>

<p>通过设置\(a_i=p_i\)，我们可以计算这一系列系数的默克尔树根，从而比较容易地对一个\(n=2^{d}-1\)次的多项式进行承诺。证明一个取值，意味着证明者想要向验证者展示对于某个值z，\(p(z)=y\)。为达到这个目的，证明者可以向验证者发送所有的\(p_i\)，然后验证者计算p(z)是否等于y。</p>

<p>当然，这是一个极度简单化的多项式承诺，但它能帮助我们理解真实的多项式承诺的益处。让我们一起回顾多项式承诺的性质：</p>

<ol>
  <li>承诺的大小是一个单一哈希（默克尔树根）。一个足够安全的加密散列一般需要256位，即32字节。</li>
  <li>为了证明一个取值，证明者需要发送所有的\(p_i\)，所以证明的大小和多项式次数是线性相关的。同时，验证者需要做同等的线性量级的计算（他们需要计算多项式在\(z\)点的取值，即计算\(p(z)=\sum_{i=0}^{n} p_i z^i\)）。</li>
  <li>该方案不隐藏多项式的任何部分 - 证明者一个系数接一个系数地发送完整的多项式。</li>
</ol>

<p>现在让我们一起来看看卡特方案是如何达成以上要求的：</p>

<ol>
  <li>承诺大小是一个支持配对的椭圆曲线群元素。比如说对于BLS12_381曲线，大小应是48字节。</li>
  <li>证明大小<em>独立</em>于多项式大小，永远是一个群元素。验证，同样独立于多项式大小，无论多项式次数为多少都只要两次群乘法和两次配对。</li>
  <li>大多数时候该方案隐藏多项式 - 事实上，无限多的多项式将会拥有完全一样的卡特承诺。但是这并不是完美隐藏：如果你能猜多项式（比如说该多项式过于简单，或者它存在于一个很小的多项式集合中），你就可以找到这个被承诺的多项式。</li>
</ol>

<p>还有一点，在一个承诺中合并任意数量的取值证明是可行的。这些性质使得卡特方案对于零知识证明系统来说非常具有吸引力，例如PLONK和SONIC。同时对于一些更日常的目的，或者简单的作为一个矢量承诺来使用也是非常有趣的场景，接下来的文章中我们就会看到。</p>

<h2 id="椭圆曲线以及配对">椭圆曲线以及配对</h2>

<p>正如之前所提到的预备知识所说，我强烈推荐<a href="https://vitalik.ca/general/2017/01/14/exploring_ecp.html">Vitalik Buterin的博客：椭圆曲线配对</a>。本文包含了本文所需的背景知识：特别是有限域，椭圆曲线和配对相关知识。</p>

<p>假设\(\mathbb G_1\)和\(\mathbb G_2\)是两条满足\(e: \mathbb G_1 \times \mathbb G_2 \rightarrow \mathbb G_T\)的配对，假设p是\(\mathbb G_1\)和\(\mathbb G_2\)的阶，同时G和H是\(\mathbb G_1\)和\(\mathbb G_2\)的生成元。接下来，我们定义一个非常有效的速记符号：对于任意\(x \in \mathbb F_p\)
\(\displaystyle
[x]_1 = x G \in \mathbb G_1 \text{ and  } [x]_2 = x H \in \mathbb G_2\)</p>

<h3 id="可信设置">可信设置</h3>

<p>假设我们已有一个可信设置，使得对于一个秘密s，其子元素\([s^i]_1\)和\([s^i]_2\)都对于任意\(i=0, \ldots, n-1\)的证明者和验证者有效。</p>

<p>有一种方法能够达到这种可信设置：我们用离线计算机生成一个随机数\(s\)，计算所有的群元素\([s^i]_x\)，并通过电线传输出去（不包括\(s\)）,然后烧掉这部计算机。当然这并不是一个好的解决方案，你必须相信计算机的操纵者没有通过其他渠道泄露这个秘密\(s\)。</p>

<p>在实际应用中，这种设置通常采用安全多方计算（MPC），使用一组计算机来创建这个群元素，而没有任何单一计算机知道秘密s，这样只有挟持了整组计算机才能知道s。</p>

<p>注意这里有一件事是不可能的：你不能仅仅选择一个随机群元素\([s]_1\)（其中\(s\)是未知的）然后通过它计算其他的群元素。不知道\(s\)是无法计算\([s^2]_1\)的。</p>

<p>好了，椭圆曲线密码学基础告诉我们通过可信设置的群元素是无法破解\(s\)的，它是有限域\(\mathbb F_p\)中的一个数字，但证明者无法找出它的具体数值。他们只能在给定的元素上做一些特定的计算。举个例子，他们可以用椭圆曲线乘法轻易地计算\(c [s^i]_1 = c s^i G = [cs^i]_1\)，或者说将椭圆曲线点值相加算出\(c [s^i]_1 + d [s^j]_1 = (c s^i + d s^j) G = [cs^i + d s^j]_1\)。实际上如果\(p(X) = \sum_{i=0}^{n} p_i X^i\)是一个多项式，证明者可以计算
\(\displaystyle
[p(s)]_1 = [\sum_{i=0}^{n} p_i s^i]_1 = \sum_{i=0}^{n} p_i [s^i]_1\)</p>

<p>这就显得非常有趣 – 通过使用这套可信设置，任何人都可以计算出一个多项式在一个谁也不知道的秘密点s上的值。只是他们得到的输出值不是一个自然数，而是一个椭圆曲线点\([p(s)]_1 = p(s) G\)，这已经足够有用。</p>

<h2 id="卡特承诺">卡特承诺</h2>

<p>在卡特承诺方案中，元素\(C = [p(s)]_1\)是多项式\(p(X)\)的承诺。</p>

<p>这样你可能会问了，证明者是不是在不知道\(s\)的情况下找到另一个有相同承诺的多项式\(q(X) \neq p(X)\)，使得\([p(s)]_1 = [q(s)]_1\)？我们假设这个推理成立，那么就是说\([p(s) - q(s)]_1=[0]_1\)，即\(p(s)-q(s)=0\)。</p>

<p>\(r(X) = p(X)-q(X)\)本身就是一个多项式。我们知道它不是常数，因为\(p(X) \neq q(X)\)。有一个非常著名的定理，即是任意非常数的\(n\)次多项式至多可以有\(n\)个零点，这是因为如果\(r(z)=0\)，\(r(X)\)就可以被线性因子\(X−z\)整除；因为每一个零点都意味着可以被一个线性因子整除，同时每经过一次除法会降低一阶，所以推理可知至多存在\(n\)个零点<sup id="fnref:2"><a href="#fn:2" class="footnote" rel="footnote" role="doc-noteref">2</a></sup>。</p>

<p>因为证明者不知道\(s\)，他们只能通过在尽可能多的地方让\(p(X)−q(X)=0\)来使得\(p(s)−q(s)=0\)。如上所证，他们只能在至多\(n\)个点上使\(p(s)−q(s)=0\)，那么成功的可能性就很小，因为\(n\)比起曲线的次数\(p\)要小很多，\(s\)被选中成为\(p(X)=q(X)\)成立点的概率是微乎其微的。来感受一下这个概率的大小，假设我们采用现有最大的可信设置，当\(n = 2^{28}\)，把它来和曲线顺序\(p \approx 2^{256}\)对比：攻击者设立的多项式\(q(X)\)来与\(p(X)\)尽可能多的重合，\(n=2^{28}\)个点，得到相同承诺（p(s)=q(s)）的概率是\(2^{28}/2^{256} = 2^{28-256} \approx 2 \cdot 10^{-69}\)。这是一个非常低的概率，在现实中意味着攻击者没有办法施行该攻击。</p>

<h3 id="多项式相乘">多项式相乘</h3>

<p>目前为止我们学习了在一个秘密\(s\)的多项式取值是可计算的，这就使得我们可以对一个独一无二的多项式进行承诺 - 对于同一个承诺\(C=[p(s)]_1\)存在多个多项式，但是在实践中它们其实是无法计算的（这就是密码学家所说的<em>绑定</em> （computationally binding））。</p>

<p>但是，我们仍缺少在不发送给验证者完整多项式的情况下“打开”这个承诺的能力。为了达到这个目的，我们需要用到配对。如上所述，我们可以对这个秘密进行线性操作；举个例子，我们可以计算\(p(X)\)的承诺\([p(s)]_1\)，还可以通过两个承诺\(p(X)\)和\(q(X)\)来计算\(p(X)+q(X)\)的联合承诺：\([p(s)]_1+[q(s)]_1=[p(s)+q(s)]_1\)。</p>

<p>现在我们所缺少的就是两个多项式的乘法。如果我们做到乘法，就能利用多项式的性质打开更多酷炫玩法的大门。尽管椭圆曲线本身不允许作乘法，幸运的事我们可以通过配对解决这个问题：我们有</p>

<p>\(\displaystyle
e([a]_1, [b]_2) = e(G, H)^{(ab)} = [ab]_T\)
在这里介绍一个新的标识方法：\([x]_T = e(G, H)^x\)。这样，尽管我们不能直接<em>在椭圆曲线上</em>直接将两个元素相乘得到它们的乘积，一个椭圆曲线元素（这就是所谓全同态加密/FHE的一个性质；椭圆曲线仅是<em>加同态</em>)。如果是在不同的曲线上（比如一个在\(\mathbb G1\)，另一个在\(\mathbb G2\)上）提交承诺，我们可以将两个字段元素相乘，这样所得到的输出就是一个\(\mathbb G_T\)元素。</p>

<p>这里我们就看到了卡特证明的核心。记得我们之前提到的线性因子：如果一个多项式在\(z\)处有零点，那么它就可以被\(X−z\)整除。同理反向可证 - 如果多项式可以被\(X−z\)整除，那么它必在\(z\)处有零点。可被\(X−z\)整除，意味着对于某个多项式\(q(X)\)我们可得\(p(X)=(X−z)⋅q(X)\)，并且很明显在\(X=z\)处得到零点。</p>

<p>举个例子，我们想要证明\(p(z)=y\)，使用多项式\(p(X)−y\) – 明显该多项式在\(z\)处达到零点，这样我们就可以应用线性因子的知识。取多项式\(q(X)\)，\(p(X)−y\)被线性因子\(X−z\)除，即：</p>

\[\displaystyle
q(X) = \frac{p(X)-y}{X-z}\]

<p>这就等同于\(q(X)(X-z) = p(X)-y\)。</p>

<h3 id="卡特证明">卡特证明</h3>

<p>定义\(p(z)=y\)的卡特证明为\(π=[q(s)]_1\)，记得多项式\(p(X)\)的承诺是\(C=[p(s)]_1\).</p>

<p>验证者用如下等式来确认这个证明：</p>

<p>\(\displaystyle
e(\pi,[s-z]_2) = e(C-[y]_1, H)\)
注意验证者可以计算\([s−z]_2\)，因为这仅是可信设置的元素\([s]_2\)和多项式被计算的点\(z\)的一个组合。同样的，验证者已知了\(y\)是取值\(p(z)\)，所以他们也可以计算\([y]_1\)。那么为什么上述证明能向验证者证明\(p(z)=y\)，或者更准确地说，\(C\)所提交的多项式在\(z\)点的取值是\(y\)？</p>

<p>这里我们需要考证两个性质：<em>正确性</em> 和 <em>可靠性</em>。 <em>正确性</em> 指的是如果证明者遵循我们定义的步骤，他们就可以产出一个能被验证的证明。这个通常难度不大。还有就是<em>可靠性</em>，这个性质是指证明者不会产出一个“不正确”的证明 – 比如说，他们不会欺骗验证者对于某个\(y′≠y\)，\(p(z)=y′\)。</p>

<p>接下来我们先写出配对组的对应等式：
\(\displaystyle
[q(s) \cdot (s-z)]_T = [p(s) - y]_T\)
<em>正确性</em>非常一目了然 – 这就是等式\(q(X)(X−z)=p(X)−y\)在一个没人知道的随机点\(s\)的取值。</p>

<p>那么，我们怎么才能知道它的可靠性，证明者不会创建假的证明呢？让我们从多项式的角度来看待这个问题。如果证明者想依循我们的方法来构建一个证明，他们就需要用\(X−z\)来除\(p(X)−y′\)。但是\(p(z)−y′\)并不为零，无论怎么除都会有一个余数，所以他们就无法进行这个多项式除法。这样一来，证明者就无法用这个方法进行伪造了。</p>

<p>剩下的就只能直接在椭圆群中想办法了：如果说对于某个承诺\(C\)，他们可以计算椭圆群元素</p>

<p>\(\displaystyle
\pi_\text{Fake} = \frac{1}{s-z} (C-[y']_1)\)
一旦成立，那证明者就可以为所欲为了。感觉上这是很难做到的，你必须用和s相关的什么东西来求幂，但s又是未知的。为了严格证明，你需要针对证明和配对的一个密码学假设，即所谓的\(q\)-strong SDH假设 <sup id="fnref:3"><a href="#fn:3" class="footnote" rel="footnote" role="doc-noteref">3</a></sup>。</p>

<h3 id="多重证明">多重证明</h3>

<p>为这里为止我们已经看到了如何在一个单点上证明一个多项式取值，这是已经是非常了不起的一件事：你可以仅靠发送单个的群元素（可以是48字节大小，例如BLS12_381）来证明任何次数的多项式 - 比如说\(2^{28}\)次 – 在任意点的取值。作为对比，在一个简单的把默克尔树用作多项式承诺的例子中，我们需要发送\(2^{28}\)个元素，即这个多项式所有的系数。</p>

<p>更进一步，我们来看看如何仅使用一个群元素，来计算并证明一个多项式在<em>任意多个点</em> 的取值。首先我们需要了解一个新概念：插值多项式。有一个包含k个点的列表\((z_0, y_0), (z_1, y_1), \ldots, (z_{k-1}, y_{k-1})\)，我们随时都可以找到一个次数小于\(k\)的多项式来经过这些点。其中一个方法是利用拉格朗日插值，这样我们可以得到该多项式的公式I(X)：</p>

<p>\(I(X) = \sum_{i=0}^{k-1} y_i \prod_{j=0 \atop j \neq i}^{k-1} \frac{X-z_j}{z_i-z_j}\)
现在我们假设已知\(p(X)\)经过了所有的点，那么多项式\(z_0, z_1, \ldots, z_{k-1}\)都是零点。这就意味着多项式可被所有的线性因子：\((X-z_0), (X-z_1), \ldots (X-z_{k-1})\)整除，我们将它们组合在一起，称为零多项式：</p>

<p>\(\displaystyle
Z(X) = (X-z_0) \cdot (X-z_1) \cdots (X-z_{k-1})\)
我们可以计算商值</p>

<p>\(\displaystyle
q(X) = \frac{p(X) - I(X)}{Z(X)}\)
注意，因为\(p(X)−I(X)\)能被\(Z(X)\)所有的线性因子整除，所以它能被\(Z(X)\)本身整除。</p>

<p>现在我们可以定义这个计算\((z_0, y_0), (z_1, y_1), \ldots, (z_{k-1}, y_{k-1})\)的卡特证明：\(\pi=[q(s)]_1\) – 这仍然仅是一个群元素。</p>

<p>为了验证这个证明，验证者同样需要计算插值多项式\(I(X)\)和零多项式\(Z(X)\)，使用这些结果他们可以计算\([Z(s)]_2\)和\([I(s)]_1\)，然后就可以确认配对等式：</p>

<p>\(\displaystyle
e(\pi,[Z(s)]_2) = e(C-[I(s)]_1, H)\)
将该等式写成配对，我们可以像单点上的卡特证明一样简单地确认它是否能够成立：</p>

<p>\(\displaystyle
[q(s)\cdot Z(s)]_T = [p(s)-I(s)]_T\)
这就非常酷炫了：仅仅提供一个群元素，你就能证明任何数量的计算，甚至是百万个！这相当于通过48个字节来证明海量的计算。</p>

<h2 id="将卡特作为矢量承诺来使用">将卡特作为矢量承诺来使用</h2>

<p>尽管卡特承诺被设计成多项式承诺，但它作为矢量承诺来使用也大有用处。回忆一下，一个矢量承诺是针对矢量\(a_0, \ldots, a_{n-1}\)的承诺，并且允许你证明任意位置\(i\)对应\(a_i\)。我们可以使用卡特承诺的方案来重现这一场景：使\(p(X)\)为对所有的\(i\)计算 \(p(i)=a_i\)的一个多项式，我们知道这样一个多项式存在，并且可以通过拉格朗日插值来计算它：</p>

<p>\(\displaystyle
p(X) = \sum_{i=0}^{n-1} a_i \prod_{j=0 \atop j \neq i}^{n-1} \frac{X-j}{i-j}\)
使用这个多项式，我们可以就可以利用一个单一群元素来证明这个矢量中任意数量的元素！注意到比起默克尔树（在证明大小方面）这个方案更加高效：仅证明一个元素，默克尔证明就需要花费\(\log n\)大小的哈希！</p>

<h2 id="延伸阅读">延伸阅读</h2>

<p>为了得到一个无状态版本的以太坊，我们正在积极探索卡特承诺的应用。在这里我强烈建议在ethresearch论坛中使用关键字<a href="https://ethresear.ch/search?q=kate">Kate</a>来搜索你感兴趣的话题。</p>

<p>另一篇很赞的博文是Vitalik的<a href="https://vitalik.ca/general/2019/09/22/plonk.html">introduction to PLONK</a>，其中大量运用到了多项式承诺，其中卡特方案就是多项式承诺实现的主要方案。</p>

<div class="footnotes" role="doc-endnotes">
  <ol>
    <li id="fn:1">
      <p>https://www.iacr.org/archive/asiacrypt2010/6477178/6477178.pdf <a href="#fnref:1" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:2">
      <p>这个结果经常被错误引用为代数基本定理。实际上代数基本理论是其反推的结论。该结论在代数封闭的域中才有:效。而代数基本定理是对于复数而言，所有n次的多项式都有n个线性因子。很可惜这个简单一点的版本没有简洁易记的名字，尽管它可以说比代数基本定理更基本一些。 <a href="#fnref:2" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
    <li id="fn:3">
      <p>https://www.cs.cmu.edu/~goyal/ibe.pdf <a href="#fnref:3" class="reversefootnote" role="doc-backlink">&#8617;</a></p>
    </li>
  </ol>
</div>]]></content><author><name></name></author><category term="ethereum" /><category term="cryptography" /><category term="mandarin" /><summary type="html"><![CDATA[原文链接： KZG Polynomial Commitments]]></summary></entry><entry><title type="html">Proofs of Custody</title><link href="https://dankradfeist.de/ethereum/2021/09/30/proofs-of-custody.html" rel="alternate" type="text/html" title="Proofs of Custody" /><published>2021-09-30T00:00:00+00:00</published><updated>2021-09-30T00:00:00+00:00</updated><id>https://dankradfeist.de/ethereum/2021/09/30/proofs-of-custody</id><content type="html" xml:base="https://dankradfeist.de/ethereum/2021/09/30/proofs-of-custody.html"><![CDATA[<p><em>Thanks to Vitalik Buterin, Chih-Cheng Liang and Alex Stokes for helpful comments</em></p>

<p>A proof of custody is a construction that helps against the “lazy validator” problem. A lazy validator is a validator that instead of doing the work they are supposed to do – for example, ensuring that some data is available (relevant for data sharding) or that some execution was performed correctly (for execution chains) – they pretend that they’ve done it and sign the result, for example an attestations that claims the data is available anyway.</p>

<p>The proof of custody construction is a cryptoeconomic primitive that changes the game theory so that lazy validating simply isn’t an interesting strategy anymore.</p>

<h2 id="lazy-validators--the-game-theory">Lazy validators – the game theory</h2>

<p>Let’s assume there is a well-running Ethereum 2.0 chain (insert your favourite alternative PoS blockchain if you prefer). We don’t usually expect that bad things – data being withheld, invalid blocks being produced happens. In fact, you are likely to not see them ever happen, because as long as the system is run by a majority of honest validators there is no point in even trying to attack it in one of these ways. Since the attack is pretty much guaranteed to fail, there is no point in even doing it.</p>

<p>Now assume you run a validator. This comes with different kinds of costs – obviously the staking captial, but also hardware costs, electricity and internet bandwidth, which you might pay for directly (your provider charges you per GB) or indirectly (when your validator is running, your netflix lags). The lower you can make this cost, the more net profits you make from running your validator.</p>

<p>One of the tasks you do as a validator in sharded Eth2, is to assure the availability of shard data. Each attestation committee is assigned one blob of data to check, which is around 512 kB to 1 MB. The task of each validator is to download it and store it for around 90 days.</p>

<p>But what happens if you simply sign all attestations for shard blobs, without actually downloading the data? You would still get your full rewards, but your costs have suddently decreased. We are assuming the network is in a good state, so your laziness isn’t going to do anything to the network immediately. Let’s say your profit of running a validator was $1 per attestation, and the cost of downloading all the blocks was $0.10 per year. Now your profit has increased to $1.10.</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Profit per signed attestation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Honest</td>
      <td>$1.00</td>
    </tr>
    <tr>
      <td>Lazy</td>
      <td>$1.10</td>
    </tr>
  </tbody>
</table>

<p>This problem is called the verifier’s dilemma and was introduced in <a href="https://eprint.iacr.org/2015/702.pdf">Demystifying Incentives in the Consensus Computer</a> by Luu et al.</p>

<h3 id="but-i-would-never-do-this-who-would-cheat-like-that">But I would never do this! Who would cheat like that?</h3>

<p>It often seems obvious to us that in games like this, surely you would not succumb to bribery and stay with the honest behaviour. But it’s often more subtle than that.</p>

<p>Let’s assume that after having run a validator for years, a new client comes out that claims to be 10% more cost effective. People run it and see that it works, and it seems to be safe. The way it actually does this is by not downloading the shard blocks.</p>

<p>This could even happen by accident. Someone cut some corners in the development process, everything looks normal, it’s just that it doesn’t join the right shard subnet and nobody missed this, because it does not cause any faults in normal operation.</p>

<p>Some people will probably run this client.</p>

<p>Something else that could happen is that a service could step in to do the downloading for you. For $0.01 per shard blob, they will download the data, store it for 90 days, and send you a message that the data is available and you can sign the attestation. How bad is this?</p>

<p>It’s also quite bad. Because as many people start using this service, it becomes a single point of failure. Or even worse, it could be part of an attack. If it can make more than 50% of validators vote for the availability of a shard blob, without ever publishing the blob, that would be a withholding attack.</p>

<p>As it is often the case, dishonesty can come in many disguises, so our best bet is to work on the equilibrium to make the honest strategy rational.</p>

<h2 id="a-proof-of-custody-and-an-update-to-the-game-theory">A proof of custody and an update to the game theory</h2>

<p>The proof of custody works like this: Imagine we can put a “bomb” in a shard blob: If you sign this blob, you get a large penalty (you get slashed), of $3,000. You definitely don’t want to sign this blob.</p>

<p>Does that make you want to download it? That is certainly one way to avoid signing the bomb. But if anyone can detect the bomb, then someone can simply write a service that warns you before signing an attestation if it’s a bomb. So the bomb needs to be specific to an individual validator, and noone else can compute whether a shard blob is a bomb.</p>

<p>OK, now we have the essential ingredients for the proof of custody. We need</p>
<ol>
  <li>An ephemeral secret, that is recomputed every custody epoch (ca. 90 days), individual to each validator, and then revealed when it has expired (so that other validators have a chance to check the proof of custody)</li>
  <li>A function that takes the whole shard blob data, as well as the ephemeral key, and outputs 0 (not a bomb), or, with very small probability, 1 (this blob is a bomb)</li>
</ol>

<p>It is essential that the ephemeral secret isn’t made available to anyone else, so there are three slashing conditions:</p>
<ol>
  <li>A validator can get slashed if anyone knows its current ephemeral secret</li>
  <li>The ephemeral secret has to be published after the custody period, and failing to do so also leads to slashing</li>
  <li>Signing a bomb leads to slashing</li>
</ol>

<p>How can we create this function? A simple construction works like this. Compute a Merkle tree of leaves <code class="language-plaintext highlighter-rouge">(data0, secret, data1, secret, data2, secret, ...)</code> as illustrated here:</p>
<div class="mermaid">graph TB
A[Root] --&gt;B[Hash]
    A --&gt; B1[Hash]
    B --&gt; C[Hash]
    B --&gt; C1[Hash]
    C --&gt; D[data0]
    C --&gt; E[secret]
    C1 --&gt; D1[data1]
    C1 --&gt; E1[secret]
    B1 --&gt; C2[Hash]
    B1 --&gt; C3[Hash]
    C2 --&gt; D2[data2]
    C2 --&gt; E2[secret]
    C3 --&gt; D3[data3]
    C3 --&gt; E3[secret]
</div>

<p>Then take the logical <code class="language-plaintext highlighter-rouge">AND</code> of the first 10 bits. This gives you a single bit that’s 1 in an expected 1 in 1024 times.</p>

<p>This function cannot be computed without knowing both the secret and the data.</p>

<p>(Because we do want to enable secret shared validators, a lot of work has gone into optimizing this function so that it can be efficiently computed in an MPC, which a Merkle tree cannot. For this we are suggesting a construction based on a Universal Hash Function and the Legendre symbol: https://ethresear.ch/t/using-the-legendre-symbol-as-a-prf-for-the-proof-of-custody/5169)</p>

<h3 id="new-game-theory">New game theory</h3>

<p>All right, so with the proof of custody, any shard blob has a 1/1,024 chance of being a bomb, and you don’t know which one it is without downloading it.</p>

<p>The lazy validator does just fine when the blob is not a bomb. However, when it is a bomb, we see the big difference: The honest validator simply skips this attestation, which is very minor an simply sets the profit to zero. However, the lazy validator signs it and will get slashed, making a huge loss. The payoff matrix now looks like this:</p>

<table>
  <thead>
    <tr>
      <th> </th>
      <th>Profit for non-bomb attestation</th>
      <th>Profit for bomb attestation</th>
      <th>Average for 1,024 attestations</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Honest</td>
      <td>$1.00</td>
      <td>$0.00</td>
      <td>$1,023.00</td>
    </tr>
    <tr>
      <td>Lazy</td>
      <td>$1.10</td>
      <td>$-3,000.00</td>
      <td>$-1,873.60</td>
    </tr>
  </tbody>
</table>

<p>In the third column, we see that the expected profit for the lazy validator is now negative. Since the whole reason for being lazy was increased profits from lower costs, this means that the lazy validator is not an interesting strategy anymore.</p>

<h2 id="proof-of-custody-for-execution">Proof of custody for execution</h2>

<p>Another task of validators will be verifying the correct execution of blocks. This means verifying that the new stateroot that is part of a block is the correct one that results from applying all the transactions. The proof of custody idea can also be applied to this: The validator will have to compute the proof of custody in the same way as described above, however the data is the <em>execution trace</em>. The execution trace is some output generated by the step by step execution of the block. It does not have to be complete in any sense; what we want from it is just two properties:</p>
<ol>
  <li>It should be difficult to guess the execution trace without actually executing the block.</li>
  <li>The total size of the execution trace should be large enough that simply distributing it in addition to normal blocks is unattractive.</li>
</ol>

<p>There are some easy options of doing this; for example simply outputting every single instruction byte that the EVM executes would probably result in an execution trace of a few MB per execution block. Another option would be to use the top of the stack.</p>

<h3 id="with-fraud-proofs-do-we-still-need-the-proof-of-custody-for-execution">With fraud proofs, do we still need the proof of custody for execution?</h3>

<p>When we upgrade the execution chain to statelessness, which means that blocks can be verified without having the current state, fraud proofs become easy. (Without statelessness, they are hard: Fraud proofs always have to be included on a chain <em>different</em> from the one where the fraud happened, and thus the actual pre-state would not be available when they have to be verified.)</p>

<p>This means that it will be possible to slash a validator who has produced an invalid execution block. Furthermore we can also penalize any validator that has attested to this block. Would that mean that the proof of custody is no longer necessary?</p>

<p>It does certainly shift the balance. But even with this penalty present, lazy validation can still be a rational strategy. It would probably be a bad idea for a validator to simply sign every block without verifying execution, as an attacker only needs to sacrifice a single validator of their own to get you slashed.</p>

<p>However, you can employ the following strategy: On each new block, you wait for some small percentage of other validators to sign it before you sign it yourself. Those who sign it first are unlikely to be lazy validators, as they would be employing the same strategy. This would get you quite good protection in most situations, but at a systemic level it would still leave the chain vulnerable in extreme cases.</p>

<p>The case with fraud proofs is thus improved, but a proof of custody remains superior for ensuring that lazy validation can’t be a rational strategy.</p>

<h2 id="how-is-it-different-from-data-availability-checks">How is it different from data availability checks?</h2>

<p>I wrote a primer on data availability checks <a href="https://dankradfeist.de/ethereum/2019/12/20/data-availability-checks.html">here</a>. It looks like the proof of custody for shard blobs tries to solve a very similar problem: Ensuring that data that is committed to in shard blob headers is actually available on the network.</p>

<p>So we may wonder: Do we need both a proof of custody and data availability checks?</p>

<p>There is an important difference between the two constructions, though:</p>
<ul>
  <li>Data availability checks ensure the availability of the data <em>independent of the honest majority assumption</em>. Even a powerful attacker controlling the entirety of the stake can’t trick full nodes into accepting data is available that is actually withheld</li>
  <li>In contrast, a proof of custody does not help if the majority of the stake is performing an attack. The majority can compute the proof of custody without ever releasing the data to anyone else.</li>
</ul>

<p>So in a theoretical sense, data availability checks are strictly superior to proof of custody for shard data: They hold unconditionally, whereas the latter only serve to keep rational validators honest, making an attack less likely.</p>

<p>Why do we still need a proof of custody for shard blobs? It might not necessarily be needed. There are however some practical problems with data availability checks that make it desirable to have a “first line of defence” against missing data:</p>

<p>The reason for this is that data availability checks work by excluding unavailable blocks from the fork choice rule. However, this cannot be permanent: data availability checks only ensure that <em>eventually</em>, everyone will see the same result, but not immediately.</p>

<p>The reason for this is that publishing a partially available block, might result in some nodes seeing it as available (they are seeing all their samples) and some other nodes as unavailable (missing some of the samples). Data availability checks ensure that in this situation, the data can always be reconstructed. However, this needs some node to first get enough samples to reconstruct the data, and then re-seed the samples so everyone can see them; this process can take a few slots.</p>

<p>In order to avoid a minority attacker (with less than 1/3 of the stake) to cause such a disruption, we only want to apply data availability checks when the chain is finalized and not immediately. In the meantime, the proof of custody can ensure that an honest majority will only ever build an available chain, where the shard data is already seeded in committees; since the committees are ready to re-seed all samples even if the original blob producer doesn’t, an attacker can’t easily force a partially available block.</p>

<p>In this construction, the proof of custody and data availability checks have two orthogonal functions:</p>
<ol>
  <li>The proof of custody for shard data ensures that an honest majority of validators will only ever build a chain in which all shard data is available and well seeded across committees. A minority attacker cannot easily cause disruption to this.</li>
  <li>Data availability checks will guarantee that even if the majority of stake is attacking, they will not be able to get the remaining full nodes to consider a chain with withheld data as finalized.</li>
</ol>]]></content><author><name></name></author><category term="ethereum" /><category term="english" /><summary type="html"><![CDATA[Thanks to Vitalik Buterin, Chih-Cheng Liang and Alex Stokes for helpful comments]]></summary></entry></feed>