Skip to content

Commit

Permalink
Merge pull request #141 from daira/cosmetics-and-clarifications
Browse files Browse the repository at this point in the history
Crosslink: Cosmetics and clarifications
  • Loading branch information
daira authored Jan 19, 2024
2 parents 2a7118b + 215b51e commit aabf489
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 252 deletions.
262 changes: 136 additions & 126 deletions src/design/crosslink/construction.md

Large diffs are not rendered by default.

47 changes: 23 additions & 24 deletions src/design/crosslink/notes-on-snap-and-chat.md

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions src/design/crosslink/potential-changes.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ The answer given for this question at [The Crosslink Construction](./constructio
This may have been too hasty. It is not clear that merging bc‑block‑producers and bft‑proposers actually does "concentrate security into fewer participants" in a way that can have any harmful effect.

Remember, the job of a bft‑proposer in Crosslink is primarily to snapshot the bc‑best‑chain (even more so if the [Increasing Tip Score rule](./potential-changes.md#Changing-the-Increasing-Score-rule-to-require-the-score-of-the-tip-rather-than-the-score-of-the-snapshot-to-increase) is adopted). An honest miner *by definition* is claiming to build on the best chain, and miners have a strong economic incentive to do so. Therefore, it is entirely reasonable for every newly produced block to be treated as a bft‑proposal. This arguably decentralizes the task of proposing bft‑blocks more effectively than using a leader election protocol would --- especially given that in a hybrid protocol we *necessarily* still rely on there being sufficient honest miners.
Remember, the job of a bft‑proposer in Crosslink is primarily to snapshot the bc‑best‑chain (even more so if the [Increasing Tip Score rule](#changing-the-increasing-score-rule-to-require-the-score-of-the-tip-rather-than-the-score-of-the-snapshot-to-increase) is adopted). An honest miner *by definition* is claiming to build on the best chain, and miners have a strong economic incentive to do so. Therefore, it is entirely reasonable for every newly produced block to be treated as a bft‑proposal. This arguably decentralizes the task of proposing bft‑blocks more effectively than using a leader election protocol would — especially given that in a hybrid protocol we *necessarily* still rely on there being sufficient honest miners.

[[DKT2021]](https://arxiv.org/pdf/2010.08154.pdf), for example, argues for the importance of "the complete unpredictability of who will get to propose a block next, even by the winner itself." The main basis of this argument is that it makes subversion of the proposer significantly more difficult. A PoW protocol has that property, and most PoS protocols do not. (It is not that PoS protocols are unable to provide this property; indeed, [[DKT2021]](https://arxiv.org/pdf/2010.08154.pdf) constructs a PoS protocol, "PoSAT", that provides it.)

Expand All @@ -245,19 +245,19 @@ Considered as a bft‑proposal, a bc‑block needs to refer to a parent bft‑bl
```admonish info collapsible=true title="What are the caveats?"
If we are in an execution where **Final Agreement** holds <span style="white-space: nowrap">for $\Pi_{\mathrm{bft}}$,</span> then it is possible to show that merging the two fields has no negative effect, *provided* that $\Pi_{\mathrm{origbft}}$ has no additional rules that could disallow it in some cases.
This is because, by **Final Agreement**, $\textsf{bft-last-final}(H'\mathsf{.context_bft}) \preceq\hspace{-0.5em}\succeq_{\mathrm{*bft}} \textsf{bft-last-final}(C)\,$ for any potential <span style="white-space: nowrap">bft‑block $C$</span> that the bc‑block‑producer of a new block $H$ could choose <span style="white-space: nowrap">as $H\mathsf{.context\_bft}$.</span> Suppose that the bc‑block‑producer freely chooses $H\mathsf{.parent\_bft}$ according to the desired honest behaviour for a bft‑proposer <span style="white-space: nowrap">in $\Pi_{\mathrm{bft}}$,</span> and then chooses $C$ to be the same block (which is always reasonable as long as it is allowed).
This is because, by **Final Agreement**, $\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \preceq\hspace{-0.5em}\succeq_{\mathrm{*bft}} \textsf{bft-last-final}(C)\,$ for any potential <span style="white-space: nowrap">bft‑block $C$</span> that the bc‑block‑producer of a new block $H$ could choose <span style="white-space: nowrap">as $H\mathsf{.context\_bft}$.</span> Suppose that the bc‑block‑producer freely chooses $H\mathsf{.parent\_bft}$ according to the desired honest behaviour for a bft‑proposer <span style="white-space: nowrap">in $\Pi_{\mathrm{bft}}$,</span> and then chooses $C$ to be the same block (which is always reasonable as long as it is allowed).
In the case <span style="white-space: nowrap">$\textsf{bft-last-final}(H'\mathsf{.context_bft}) \preceq_{\mathrm{*bft}} \textsf{bft-last-final}(C)$,</span> we are done, because this choice of $H\mathsf{.context\_bft}$ is allowed by the **Extension rule**.
In the case <span style="white-space: nowrap">$\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \preceq_{\mathrm{*bft}} \textsf{bft-last-final}(C)$,</span> we are done, because this choice of $H\mathsf{.context\_bft}$ is allowed by the **Extension rule**.
In the case <span style="white-space: nowrap">$\textsf{bft-last-final}(H'\mathsf{.context_bft}) ⪲_{\mathrm{*bft}} \textsf{bft-last-final}(C)$,</span> we can argue that $H'\mathsf{.context\_bft}$ would be a better choice than $C$ for $H\mathsf{.parent\_bft}$ as well as for <span style="white-space: nowrap">$H\mathsf{.context\_bft}$,</span> because it has a later final ancestor. This is where the argument might fall down if $\Pi_{\mathrm{origbft}}$ <span style="white-space: nowrap">(and therefore $\Pi_{\mathrm{bft}}$)</span> has any additional rules that could disallow this choice. For now let's suppose that situtation does not arise, but it is one of the caveats.
In the case <span style="white-space: nowrap">$\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \;⪲_{\mathrm{*bft}}\; \textsf{bft-last-final}(C)$,</span> we can argue that $H'\mathsf{.context\_bft}$ would be a better choice than $C$ for $H\mathsf{.parent\_bft}$ as well as for <span style="white-space: nowrap">$H\mathsf{.context\_bft}$,</span> because it has a later final ancestor. This is where the argument might fall down if $\Pi_{\mathrm{origbft}}$ <span style="white-space: nowrap">(and therefore $\Pi_{\mathrm{bft}}$)</span> has any additional rules that could disallow this choice. For now let's suppose that situtation does not arise, but it is one of the caveats.
Another potential problem is that in an execution where **Final Agreement** does *not* hold for <span style="white-space: nowrap">$\Pi_{\mathrm{bft}}$,</span> we can no longer infer that either $\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \preceq_{\mathrm{*bft}} \textsf{bft-last-final}(C)$ or $\textsf{bft-last-final}(H'\mathsf{.context\_bft}) ⪲_{\mathrm{*bft}} \textsf{bft-last-final}(C)$. In particular it could be the case that the producer of $H'$ was adversarial, and chose $H'\mathsf{.context\_bft}$ in such a way as to favour its own bft‑block that is final in that context.
Another potential problem is that in an execution where **Final Agreement** does *not* hold for <span style="white-space: nowrap">$\Pi_{\mathrm{bft}}$,</span> we can no longer infer that either $\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \preceq_{\mathrm{*bft}} \textsf{bft-last-final}(C)$ or $\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \;⪲_{\mathrm{*bft}}\; \textsf{bft-last-final}(C)$. In particular it could be the case that the producer of $H'$ was adversarial, and chose $H'\mathsf{.context\_bft}$ in such a way as to favour its own bft‑block that is final in that context.
However, in that situation it must be possible for the bc‑block‑producer to see (and prove) that the bft‑chain has a final fork. That is, it can produce a <span style="white-space: nowrap">witness $C$</span> to the violation of **Final Agreement**, showing that $\textsf{bft-last-final}(H'\mathsf{.context_bft}) \preceq\hspace{-0.5em}\succeq_{\mathrm{*bft}} \textsf{bft-last-final}(C)\,$ does not hold, as discussed in the section [Recording more info about the bft‑chain in bc‑blocks](./potential-changes.md#Low-risk-Recording-more-info-about-the-bft-chain-in-bc-blocks) above.
However, in that situation it must be possible for the bc‑block‑producer to see (and prove) that the bft‑chain has a final fork. That is, it can produce a <span style="white-space: nowrap">witness $C$</span> to the violation of **Final Agreement**, showing that $\textsf{bft-last-final}(H'\mathsf{.context\_bft}) \preceq\hspace{-0.5em}\succeq_{\mathrm{*bft}} \textsf{bft-last-final}(C)\,$ does not hold, as discussed in the section [Recording more info about the bft‑chain in bc‑blocks](#recommended-recording-more-info-about-the-bftchain-in-bcblocks) above.
The second caveat is that in that situation, we still need to set $H\mathsf{.parent\_bft}$ and $H\mathsf{.context\_bft}$ in order to be able to recover, and they typically should not be the same in order to do so.
```
${}$

The **Increasing Tip Score rule** is still needed, but it can be simplified. A newly produced <span style="white-space: nowrap">bc-block $H$</span> is also a bft‑proposal <span style="white-space: nowrap">such that $\mathsf{snapshot}(H) = H$.</span> This would yield the following bft‑proposal / bc‑block validity rule:

> [Candidate rule for discussion] Either $\mathsf{score}(\mathsf{tip}(H\mathsf{.parent\_bft})) < \mathsf{score}(H)$ <span style="white-space: nowrap">or $\mathsf{tip}(H\mathsf{.parent\_bft}) = H$.</span>
Expand All @@ -266,7 +266,7 @@ except that $\mathsf{tip}(H\mathsf{.parent\_bft})$ *cannot* <span style="white-s

> **Increasing Tip Score (producer = proposer) rule:** $\mathsf{score}(\mathsf{tip}(H\mathsf{.parent\_bft})) < \mathsf{score}(H)$.
This works because, if $H$ does not have a higher score than the <span style="white-space: nowrap">bc‑block $\mathsf{tip}(H\mathsf{.parent\_bft})$,</span> the bc‑block‑producer should instead have built on top of that bc‑block --- which was necessarily known to the producer in order for it to set $H\mathsf{.parent\_bft}$ in the header of the new block.
This works because, if $H$ does not have a higher score than the <span style="white-space: nowrap">bc‑block $\mathsf{tip}(H\mathsf{.parent\_bft})$,</span> the bc‑block‑producer should instead have built on top of that bc‑block &mdash; which was necessarily known to the producer in order for it to set $H\mathsf{.parent\_bft}$ in the header of the new block.

The voting would be the same, performed by the same parties. Therefore, there is no concentration of voting into fewer parties. There is no change in the producer/proposer's incentive to make the bft‑notarization‑proof or its soundness properties. Everything else is roughly the same, including the use of the <span style="white-space: nowrap">$\mathsf{context\_bft}$ field</span> of a bc‑block and the validity rules related to it. As far as I can see, all of the security analysis goes through essentially unchanged.

Expand All @@ -279,7 +279,7 @@ Strictly speaking, whether there is a stake requirement to make a proposal is in
In a system that uses PoS, validators by definition need to have stake in order to control the ability to vote. This also allows validators to be slashed.
On the other hand, there is no *technical* reason why the ability to make a bft‑proposal has to be gatekept by a stake requirement --- given the situation of Zcash in which we already have a mining infrastructure, and that in a Snap‑and‑Chat or Crosslink‑style hybrid protocol we necessarily still rely on miners not to censor transactions. The potential to make proposals that are expensive to validate as a denial of service is made sufficiently difficult by proof‑of‑work. This option has probably been underexplored by previous PoS protocols because they cannot assume an existing mining infrastructure.
On the other hand, there is no *technical* reason why the ability to make a bft‑proposal has to be gatekept by a stake requirement &mdash; given the situation of Zcash in which we already have a mining infrastructure, and that in a Snap‑and‑Chat or Crosslink‑style hybrid protocol we necessarily still rely on miners not to censor transactions. The potential to make proposals that are expensive to validate as a denial of service is made sufficiently difficult by proof‑of‑work. This option has probably been underexplored by previous PoS protocols because they cannot assume an existing mining infrastructure.
```

It could be argued that this approach goes less far toward a pure PoS‑based blockchain protocol, leaving more to be done in the second stage. However, there is a clear route to that second stage, by replacing PoW with a protocol like PoSAT that has full unpredictabilty and dynamic availability. PoSAT does this using a VDF, and as it happens, Halo 2 is a strong candidate to be used to construct such a VDF.
Expand All @@ -292,13 +292,13 @@ Building on the previous idea, we can try to eliminate the explicit bft‑chain

This left the concept of a bft‑block intact. Recall that in baseline Crosslink, a <span style="white-space: nowrap">bft‑block $B$</span> consists of $(P, \mathsf{proof}_P)$ signed by the proposer. So in "Crosslink with proposer = producer", a bft‑block consists of $(H, \mathsf{proof}_H)$ signed by the producer.

What if a <span style="white-space: nowrap">bc‑block $H$</span> were to "inline" its parent and context bft‑blocks rather than referring to them? <span style="white-space: nowrap">I.e. a bc‑block $H$</span> with $H\mathsf{.parent\_bft}$ *referring to* <span style="white-space: nowrap">$(H', \mathsf{proof}_{H'})$ signed for $H'\mathsf{.pubkey}$,</span> would instead <span style="white-space: nowrap">*literally include*</span> (either in the header or the coinbase transaction) $(H', \mathsf{proof}_{H'})$ signed <span style="white-space: nowrap">for $H'\mathsf{.pubkey}$ ---</span> and similarly <span style="white-space: nowrap">for $H\mathsf{.context\_bft}$.</span>
What if a <span style="white-space: nowrap">bc‑block $H$</span> were to "inline" its parent and context bft‑blocks rather than referring to them? <span style="white-space: nowrap">I.e. a bc‑block $H$</span> with $H\mathsf{.parent\_bft}$ *referring to* <span style="white-space: nowrap">$(H', \mathsf{proof}_{H'})$ signed for $H'\mathsf{.pubkey}$,</span> would instead <span style="white-space: nowrap">*literally include*</span> (either in the header or the coinbase transaction) $(H', \mathsf{proof}_{H'})$ signed <span style="white-space: nowrap">for $H'\mathsf{.pubkey}$ &mdash;</span> and similarly <span style="white-space: nowrap">for $H\mathsf{.context\_bft}$.</span>

It would still be necessary to have the message type that the proposer/producer previously used to submit a notarized bft‑block. (It cannot be merged with a bc‑block announcement: the producer of a new block is not in general the producer of its parent, and their incentives may differ; also we cannot wait until a new block is found before publishing the previous notarization.) It would also still be necessary for Crosslink nodes to keep track of notarizations that have not made it into any bc‑block. Nevertheless, this is a potential simplification.

Note that unless notarization proofs are particularly short and constant-length, it would not be appropriate to include them in the bc‑block headers, and so they would have to go into the coinbase transaction or another similar variable-length data structure. In that case we would still have an indirection to obtain the bft‑block information; it would just be merged with the indirection to obtain a coinbase transaction (or similar) --- which is already needed in order to check validity of the bc‑block.
Note that unless notarization proofs are particularly short and constant-length, it would not be appropriate to include them in the bc‑block headers, and so they would have to go into the coinbase transaction or another similar variable-length data structure. In that case we would still have an indirection to obtain the bft‑block information; it would just be merged with the indirection to obtain a coinbase transaction (or similar) &mdash; which is already needed in order to check validity of the bc‑block.

As discussed under "[Recording more info about the bft‑chain in bc‑blocks](#Low-risk-Recording-more-info-about-the-bft-chain-in-bc-blocks)" above, we might in any case want to record information about other proposed and notarized bft‑blocks, and the data structure needed for this would necessarily be variable-length. The complexity burden of doing so would be shared between these two changes.
As discussed under "[Recording more info about the bft‑chain in bc‑blocks](#recommended-recording-more-info-about-the-bftchain-in-bcblocks)" above, we might in any case want to record information about other proposed and notarized bft‑blocks, and the data structure needed for this would necessarily be variable-length. The complexity burden of doing so would be shared between these two changes.

It would be possible to save some space in headers (while keeping them fixed-length), by inlining only one of $H\mathsf{.parent\_bft}$ and $H\mathsf{.context\_bft}$ in the header and keeping the other as a hash. As discussed under "What are the caveats?" above, the only reason for the two bft‑blocks referred to by these fields to be different, is that the bc‑block producer has observed a violation of **Final Agreement** <span style="white-space: nowrap">in $\Pi_{\mathrm{bft}}$.</span> In that case, we can include an inlining of the other <span style="white-space: nowrap">$H\mathsf{.*\_bft}$ block,</span> and any other information needed to prove that a violation of **Final Agreement** has occurred, in a variable-length overflow structure.

Expand Down
Loading

0 comments on commit aabf489

Please sign in to comment.