The zebra-crosslink Book
zebra-crosslink is Shielded Labs's implementation of Zcash
Crosslink, a hybrid PoW/PoS consensus protocol for Zcash. Refer to the Rationale, Scope, and Goals to understand our effort. See our roadmap for current progress status.
Prototype Workshops
Shielded Labs hosts semi-regular workshops as the prototype progresses; if you're interested in joining, get in touch!
Prototype Codebase
Status: This codebase is an early prototype, and suitable for the adventurous or curious who want to explore rough experimental releases.
This zebra-crosslink codebase is a fork of
zebra.
If you simply want a modern Zcash production-ready mainnet node, please use that upstream node.
Build and Usage
To try out the software and join the testnet, see Build and Usage.
Design and Implementation
This book is entirely focused on this implementation of Zcash Crosslink. For general Zebra usage or development documentation, please refer to the official Zebra Book. We strive to document the Design and Implementation changes in this book.
Maintainers
zebra-crosslink is maintained by Shielded Labs, makers of fine Zcash software.
Contributing
Our github issues are open for feedback. We will accept pull requests after the prototyping phase is done.
License
Zebra is distributed under the terms of both the MIT license and the Apache License (Version 2.0). Some Zebra crates are distributed under the MIT license only, because some of their code was originally from MIT-licensed projects. See each crate's directory for details.
See LICENSE-APACHE and LICENSE-MIT.
User Documentation
This section contains details on how to install, run, and instrument Zebra.
Building zebra-crosslink
These are the build and usage instructions for a generic linux system. nix users should check out
nix Support.
Building zebra-crosslink requires Rust,
libclang, and a C++ compiler.
Dependencies
-
Install
cargoandrustc. -
Install
zebra-crosslink's build dependencies:- libclang is a library that might have different names depending on your
package manager. Typical names are
libclang,libclang-dev,llvm, orllvm-dev. - clang or another C++ compiler:
g++(all platforms) orXcode(macOS). protoc
- libclang is a library that might have different names depending on your
package manager. Typical names are
TODO: We need to add prerequisites for the visualizer.
cargo build --locked zebrad
Usage
cargo run
To connect to the current prototype testnet, see crosslink-testnet.md.
nix Support
The flake* files/directories provide a nix flake for zebra-crosslink. This page assumes you
have flake support enabled (or pass the temporary cli flags for
flake support).
Standard flake commands
Standard flake commands all work:
nix buildnix flake checknix developnix flake install .nix flake install 'github:shieldedlabs/zebra-crosslink'
The built package includes the zebrad binary and this book (rendered).
Crosslink Design
The zebra-crosslink design fleshes out and adapts the abstract Crosslink 2 into a working implementation. This includes extending and adapting that construction to include a fully functional BFT protocol, and including staking mechanics, accounting, and associated security reasoning and arguments. Additionally, we explicitly alter some trade-offs, or terminology compared to the abstract construction.
This Design chapter focuses specifically on differences from pure PoW Zcash (using zebra as a reference implementation) and the Crosslink 2 construction. We assume basic familiarity with both. Also, please see our Terminology for terms specific to this project.
We will be refining a ZIP Draft which will enter the formal ZIP process as the prototype approaches maturity and we switch focus to productionization.
WARNINGS
- These extensions and changes from the Crosslink 2 construction may violate some of the assumptions in the ssecurity proofs. This still needs to be reviewed after this design is more complete.
- We are using a custom-fit in-house BFT protocol for prototyping. It's own security properties need to be more thoroughly verified.
- All trade-off decisions need to be thoroughly vetted for market fit, while ensuring we maintain a minimum high bar for safety befitting Zcash's pedigree. Part of our implementation approach is to do rapid prototyping to explore the market fit more directly while modifying trade-offs in the design.
It is especially important that we identify deviations from Zcash PoW consensus, the Crosslink 2 construction, and the upstream zebra implementation. In particular, it is important for us to clarify our rationale for deviation, which may fit one of these general categories:
- We intentionally prefer a different trade-off to the original design; in which case we should have very explicit rationale documentation about the difference (in an ADR). One example (TODO: not-yet-done) is our ADR-0001 selects a different approach to on-chain signatures than (TODO: link to TFL section).
- Something about the more abstract design makes assumptions we cannot uphold in practice with all of the other implementation constraints. In this case, we need to determine if the upstream design needs to be improved, or we need to alter our implementation constraints.
- As an expedient, we found it quicker and easier to do something different to get the prototype working, even though we believe the upstream makes better trade-offs. These are prime candidates for improvement during productionization to match the design, or else require persuasive rationale that a "short cut" is worth the trade-offs and risks.
Scope for Crosslink
What are our goals for the first deployment of Crosslink?
Rationale
Why add a Proof-of-Stake finality gadget?
- The Proof-of-Stake finality gadget adds crosslink finality, which protects users from being robbed, improves the safety and efficiency of bridges, and enables centralized exchanges, decentralized exchanges, and other services to reduce and unify deposit times.
- Proof-of-Stake provides a different and complementary kind of security that pure Proof-of-Work doesn't, by allowing the value at stake (which inventivizes defenders to protect users) to be cumulative instead of transient. This makes Zcash more secure—it provides better security for the same security budget. It also makes Zcash more sustainable—it provides long-term security even as the rate of issuance shrinks, which strengthens assurance that the 21M supply cap will be maintained.
- Proof-of-Stake replaces some of the sell pressure from miners with buy pressure from finalizers. This is good because the price of ZEC is the fuel for the mission and attracts users.
- Proof-of-Stake allows a larger number of users to participate actively in the network than mining does, and to become direct recipients of ZEC issued by the blockchain. This increases the size and diversity of the set of users and stakeholders 1.
Why Keep the Proof-of-Work blockchain?
- Proof-of-Work provides a different and complementary kind of security that pure Proof-of-Stake doesn’t, by requiring a recurring, non-reusable, and non-recoverable expenditure (by defenders and potential attackers). This prevents attackers from re-using resources in attacks (whether simultaneous or successive attacks). Crosslink security is therefore more robust and self-healing against large-scale attacks than pure Proof-of-Stake security.
- Proof-of-Work provides excellent liveness, availability, and censorship-resistance (which complements the censorship-resistance provided by using end-to-end-encryption whenever possible).
- Proof-of-Work allows people to earn ZEC by mining, even if they don’t already own any ZEC and they can’t acquire ZEC any other way.
- Keeping Proof-of-Work in addition to adding Proof-of-Stake means that in addition to adding the stakers, we also keep miners as active participants in the network and recipients of ZEC, increasing the size and diversity of the Zcash network and the ZEC economy.
UX goals
This list of UX Goals is tracked on GitHub.
- CEXes (GH #131) and decentralized services like DEXes/bridges (GH #128) are willing to rely on Zcash transaction finality. E.g. Coinbase reduces its required confirmations to no longer than Crosslink finality. All or most services rely on the same canonical (protocol-provided) finality instead of enforcing their own additional delays or conditions, so users get predictable transaction finality across services.
- GH #127: Casual users (who understand little about crypto and do not use specialized tools such as a Linux user interface) delegate ZEC and get rewards from their mobile wallet. GH #124 They have to learn a minimal set of new concepts in order to do this.
- GH #158: Users can get compounding returns by leaving their stake plus their rewards staked, without them or their wallet having to take action.
- GH #126: Skilled users (who understand more and can use specialized tools) run finalizers and get rewards.
- GH #214: Skilled users can easily collect records of finalizer behavior and performaance.
Shielded Labs’s First Deployment of Crosslink is not done until substantial numbers of real users are actually gaining the above benefits.
Deployment Goals
This list of Deployment Goals is tracked on GitHub.
- GH #125: Zcash transactions come with a kind of finality which protects the users as much as possible against all possible attacks, and is sufficient for services such as cross-chain bridges and centralized exchanges.
- GH #124: Users can delegate their ZEC and earn rewards, safely and while needing to learn only the minimal number of new concepts.
- Delegating to a finalizer does not enable the finalizer to steal your funds.
- Delegating to a finalizer does not leak information that links the user's action to other information about them, such as their IP address, their other ZEC holdings that they are choosing not to stake, or their previous or future transactions.
- GH #123: The time-to-market and the risk of Shielded Labs's First Deployment of Crosslink is minimized: the benefits listed above start accruing to users as soon as safely possible.
- GH #122: Activating Crosslink on Zcash mainnet retains as much as possible of Zcash users' safety, security, privacy, and availability guarantees.
Trade-offs
Goals which we currently believe are not safely achievable in this first deployment without losing some of the above goals:
- Improving Zcash's bandwidth (number of transactions per time) or latency (time for a transaction).
- Deploying cross-chain interoperation such as the Inter-Blockchain Communication protocol (IBC) or Cross-Chain Interoperability Protocol (CCIP).
- Supporting a large number of finalizers so that any user who wants to run their own finalizer can do so.
- Supporting casual users, with little computer expertise, running finalizers.
Non-Goals
- The consensus mechanism is needed primarily to prevent double-spending/multi-spending/rollback attacks. It is not the primary provider of censorship-resistance, since that is provided primarily by end-to-end encryption, and it is not the primary provider of counterfeiting-resistance, since that is provided by proofs and turnstiles. So censorship-resistance and counterfeiting-resistance are not primary goals for (at least) the first deployment of Crosslink.
- This is neutral with regard to Zcash governance —-- it doesn't change anything about Zcash governance.
-
In Proof-of-Work, smaller miners have a substantial economic disadvantage compared to larger mining operations, resulting in almost all hashpower being controlled by a few large miners. This economic disadvantage is reduced in Proof-of-Stake finalization—smaller finalizers have less of an economic disadvantage compared to larger finalizers. The economic disadvantage is almost eliminated in Proof-of-Stake delegation—smaller delegators compete on a level playing field with larger delegators, earning roughly the same reward with roughly the same risk. ↩
Engineering Deliverables for Shielded Lab's Crosslink Deployment
This is a draft list of SL's engineering deliverables as part of our Crosslink Deployment project. This list may be refined as the project develops, both to provide greater precision or clarity around deliverables, or to add or potentially remove deliverables (ideally only in early phases of the project lifecycle).
Code Products
The active list of Code Deliverables is evolving on GitHub, and includes these major components:
- a full node implementation of the Crosslink protocol - intended for use by all full node users
- GH #154 a basic working commandline finalizer (probably as a configured mode of the full node) - potentially used by production finalizers
- GH #106 a basic, minimal stake delegation tool - this will not be an easily usable or recommended product for end users
- GH #112 all necessary Continuous Integration / Continuous Deployment source code is an explicit code deliverable
All code products will be open source and suitable for merging or bundling with zebra source and binary distributions.
All code products will be first developed and released as testnet prototypes which are then matured into production-ready status as the target activation date approaches.
Technical Documentation
The active list of Documentation Deliverables is evolving on GitHub, and includes these important components:
- User facing documentation about Crosslink finality and safety considerations, including links to assessments, analyses, and audits by other parties.
- User facing documentation for users of all code deliverables.
- Design notes on prototype design trade-offs, delegation secure UX considerations, and a "Staking in Zcash" primer for PoS protocol-expert audiences.
- A Productionization Plan describing the process to develop the prototype into a safe mainnet production deployment and activation process.
- Process documentation for code releases, testnet deployments, and documentation releases intended for current and future maintainers, and developers.
External Validation Partnerships
While not deliverables per se, a key strategy we'll use for gauging our success is to establish working relationships with partner teams which are representative stakeholders for these categories:
- Wallet developers
- Finalizers
- Exchanges
- Bridges, DEXes, or other protocol-integration product teams
Our success criteria require user-facing in-production products in these categories (with the first three prioritized). In order to meet these criteria, we need to engage with high quality partners to serve as representative stakeholders relatively early in the process, as the prototype approaches a usable state. We track ongoing Partner Validation goals on GitHub.
Crosslink Security Properties
Crosslink is designed and can be analyzed with respect to the following security properties:
Irreversible Finality
Transactions enter a finalized state, and finalized transactions cannot be rolled back. Failure of this security property is called “rollback attack”.
Importantly, all participants who are sufficiently in sync with the consensus agree on finality status, or if there is a failure by the protocol to provide finality, all of those participants agree that this failure occurred. This contrasts with PoW which provides “probabilistic finality” and subtly this means every participant must select their own rollback threshold at which point they consider a protocol failure event to have occurred (including potential malicious “rollback attacks”). Because these thresholds vary over users, rollbacks naturally fragment users into groups with competing interests in the event of protocol failures.
Liveness/Availability
It is possible for any user to get at least some of their transactions paying sufficiently high fees to be included in one of the next few blocks. Failure of this security property is called a “denial-of-service for blockspace attack” (aka “blockspace DoS”). Two example attacks illustrate different attack approaches: in one case, an attacker has enough mining capacity to exclude all transactions (except perhaps their own); in another approach an attacker pays fees higher than any legitimate user for so many transactions that any other user cannot effectively get any of their transactions included.
Finality Progress
Blocks become final or they are removed from the chain within a finite amount of time. A failure of “finality progress” is called a “finality stall attack”. This is subtly distinct from a general liveness failure: a finality stall may occur even while new blocks containing transactions are continually produced. The longer that finality stalls while new blocks arrive with new transactions, the more likely it is that those users who require finality and those users who do not rely on finality will diverge in their expectations and behavior, which is a growing economic and governance risk, so finality stalls may be especially pernicious.
Censorship-resistance
It is possible to get new transactions processed even in the presence of an adversary who tries to prevent those specific transactions. Failure of this security property is called “censorship attack”. This kind of attack is distinct from blockspace DoS attacks because of the narrower targeting policy. In practice more general DoS attacks use different techniques than more targeted censorship.
Broadly speaking, an adversary may have a “censorship policy” based on a variety of criteria including both on-chain behavior and correlated metadata from many different domains.
Because censorship (and other privacy attacks) often rely on a wide array of data sources, practical protection also relies on a wide array of techniques and technologies out of scope for Crosslink’s design. One key area where we assume supporting defensive technologies (such as mixnets) is around network privacy for wallets (especially) and potentially other Crosslink infrastructure.
Supply-integrity
The total supply of ZEC is correct and any user can verify that it is correct. Failure of this security property is called “counterfeiting attack”.
TODO: Where does the following live?
What is the difference between liveness and censorship-resistance? The difference is whether specific transactions are targeted (a censorship attack) or (a stall attack). An important fact is that a stall attack would be immediately noticed and a wide set of users would be able to agree that the stall attack is happening. In contrast, a censorship attack would tend to go unnoticed except by the victims, and it might be difficult to achieve widespread recognition that it had happened. For this reason, part of the design of Crosslink is intended to “convert censorship attacks into stall attacks” – make it impossible for an attacker to censor targeted transactions without causing the entire service to stall.
The Five Component Model
There are five components of the system. Each component is responsible for preventing certain attacks, or for holding other components accountable.
Wallets
The job of the wallet is to protect a user’s funds and to enable sending or receiving funds safely.
When receiving funds, the wallet verifies that the incoming funds total to a specific amount, safe against rollbacks, and available to be respent in the future. Additionally, wallets that prioritize user privacy often ensure all incoming funds become shielded to protect the user against unintentional on-chain privacy leaks.
When sending funds, the wallet minimizes all information leakage except those details a user explicitly requests to disclose to certain parties, or those details which must be disclosed. Zcash relies on strong encryption for all information where possible given a transaction type. Privacy is also a protection against censorship, since a censor must either identify specific transactions to censor, or perform blanket or probabilistic censorship in a less effective manner. However, some information disclosures or leakages are inevitable:
- Some information disclosures are always necessary for certain transactions:
- The amount, timing, and memo always needs to be disclosed to the recipient.
- The recipient’s receiving address is always known to a sender.
- Some other kinds of transactions require that some of the information is disclosed to specific parties or to the public in order to achieve certain kinds of desirable transparency. Examples include coin-voting, bridges/DEXes/L2’s, CEXes, turnstile migrations, t-addresses for backward compatibility, staking, unstaking, and redelegating.
- Some information “leakage” occurs even when not theoretically necessary for a given kind of transaction, especially by correlation with off-chain activity, such as:
- The recipient will often know something about the sender’s relationship with them, may be able to learn the sender’s IP address, etc. Therefore if the recipient colludes with the attacker, encryption cannot entirely protect against censorship by itself.
- It is also the responsibility of the wallet to protect the user against censorship attacks that leverage network-level information leakage. Wallets can and should use network-level protections against information leakage such as Tor or Nym.
Miners
The job of the miners is to include transactions and advance the blockchain, which provides an additional kind of censorship-resistance, in addition to the kind of censorship-resistance provided by wallets encrypting the transaction contents when possible. This function of miners also provides liveness. However the miners cannot unilaterally violate finality, even if an attacker controls >½ of the hashpower, because the finalizers ensure finality regardless of the behavior of the miners. A majority of the miners (>½ of the hashpower) can violate censorship-resistance (except when it can be provided by the wallet with encryption).
Finalizers
The job of the finalisers is to ensure finality (i.e. to prevent rollback attacks) but finalisers cannot unilaterally compromise liveness or censorship-resistance (even if an attacker controls >⅔ of the stake-weighted votes) because miners ensure those properties. Also the finalisers cannot unilaterally execute rollback attacks even though they can prevent rollback attacks. A plurality of the finalisers (controlling >⅓ of the stake-weighted votes) could execute stall attacks (i.e. violate liveness).
Stakers
It is the job of the stakers to hold the finalisers accountable by detecting and punishing misbehavior on the part of the finalizers by redelegating stake away from ill-behaved finalizers to well-behaved finalizers.
Users
It is the duty of the users, collectively, to hold the stakers accountable for doing their job. If the stakers fail in their duty to hold the finalizers accountable, they can be disempowered and punished for this failure by the users with an emergency user-led hard fork (which is what happened in the STEEM/HIVE hard fork). We clarify how we envision this could work with more safety and preparedeness by the Zcash community in the User-Led Emergency Hardforks.
Attacker Resource Scenarios
When considering these components, it is useful to consider scenarios where an attacker has compromised some portion of each kind of component, as a coarse means of assessing the robustness of Crosslink in maintaining the security properties.
-
A collusion that controlled both >½ of the hashpower and >⅔ of the stake.
-
...could violate finality.
-
A collusion that included both a majority of the miners (controlling >½ of the hashpower) and a supermajority of the finalizers (controlling >⅔ of the stake-weighted votes)
-
...could execute rollback and unavailability attacks.
Censorship-resistance is necessary for stakers to stake, unstake, and redelegate, which means censorship-resistance is necessary for stakers to be able to perform their duty of holding the finalizers accountable. Therefore, if an attacker controls >½ of the hashpower (and is thereby able to censor), then the attacker can prevent the stakers from holding the finalizers accountable.
An important and under-investigated consideration is what security properties hold when an attacker controls a minority of the hashpower. In a pure-PoW system, an attacker that controls some hashpower but ≤½ of it can not completely censor transactions, but can force them to be delayed.
- A collusion that controls >⅔ of the stake and <½ of the hashpower.
User-Led Emergency Hardforks
In The Five Component Model we describe a key role of users is their governance capability to initiate a user-led hardfork in the event of an emergency.
In the context of Crosslink, we believe it's beneficial to gain community agreement on a norm for when such emergency hardforks are called for. Having an up-front agreement can help reduce confusion, debate, or contention during specific kinds of emergencies.
A Proposed Governance ZIP for the Use of an Emergency User-Led Hard Fork to Correct Layer-1 Security Failures
An emergency user-led hard fork is an extraordinary intervention that reflects a core value of cryptocurrencies: the ability of users to assert sovereignty over the protocol in response to a failure of its most fundamental security guarantees. This form of intervention is distinct from ordinary network upgrades, which change consensus rules prospectively and only with broad user acceptance. Because an emergency user-led hard fork carries significant social, economic, and political consequences, the Zcash community should establish a clear and limited social consensus in advance about when it is legitimate.
This Governance ZIP establishes that a user-led hard fork should be considered only to rectify and hold consensus operators accountable for failures of the layer-1 consensus system itself, specifically failures to prevent rollback or double-spend attacks, failures to ensure network liveness or availability, and failures to ensure censorship resistance or freedom of participation, including situations in which would-be miners, finalizers, or stakers are being systematically censored or prevented from participating in block production, finalization, or staking. These grounds are intended to capture violations of finality, liveness, and censorship resistance at the base layer and define the exclusive scope of legitimate emergency intervention under this framework.
This Governance ZIP explicitly rejects the use of an emergency user-led hard fork to mitigate harm arising from application-layer failures or to alter outcomes that, while undesirable, do not constitute violations of layer-1 security properties. It does not apply to wallet bugs, smart contract failures, bridge exploits, custodial failures, key management errors, user mistakes, or other application-level attacks or economic losses. A user-led hard fork must not be used to reverse or “make whole” thefts or hacks, to rewrite application-layer outcomes, or for purposes analogous to Ethereum’s DAO hard fork, the SUI blockchain hard fork, or similar interventions motivated by dissatisfaction with economic outcomes rather than base-layer security failure. Control over a large share of hashpower, finalization power, or stake does not itself constitute a violation, and a user-led hard fork must not be used to disadvantage miners, finalizers, or stakers solely for being large, nor to resolve governance disputes or enforce social policy outcomes.
This Governance ZIP also does not apply to ordinary prospective rule changes adopted through standard upgrade processes, including the introduction of new transaction types, new features, or protocol cleanups. It does not apply to monetary policy, economic parameters, or protocol design choices such as shielded pool deprecations, fee changes, new fee mechanisms, staking or unbonding parameters, or funding mechanisms. All such matters fall within the domain of future community governance and must be decided through ordinary governance and network upgrade processes, not through an emergency user-led hard fork justified under this security framework.
Even when one of the legitimate layer-1 security grounds is clearly met, any emergency user-led hard fork should be narrowly scoped to address only the specific security failure, avoid unnecessary collateral changes, minimize downstream disruption, and preserve continuity of honest user state where technically feasible. Possible interventions may include correcting a critical consensus bug, changing a security-critical consensus mechanism that failed to prevent the violation, or, where directly relevant, neutralizing counterfeit or illegitimate base-layer state created by the failure. The objective of such intervention is the restoration of neutral protocol function, not broad protocol re-engineering under crisis conditions.
This Governance ZIP is a proposed expression of social consensus. Its force derives solely from the degree to which the Zcash community chooses to adopt and uphold it. Whether any particular emergency intervention is ultimately acceptable will depend not only on technical criteria, but also on whether it aligns with the community’s explicit or assumed social values. By committing to these constraints in advance, the community strengthens credible neutrality, reduces moral hazard, and increases confidence that the protocol will not be arbitrarily rewritten.
Crosslink Design in a Nutshell
This chapter covers the major components of the design. This presents the design positively, without rationales, trade-offs, safety anlyses, or other supporting information. This will eventually be entirely redundant with, or simply link to, a canonical Zcash Improvement Proposal submission. Treat this chapter as a provisional sketch.
It assumes and leverages familiarity with Zcash PoW and only describes new differences from today's mainnet.
CAVEATS: A lot of the terminology and descriptions will be adjusted as we go to follow conventions and specifications in the Zcash Protocol Specification and the Zcash Improvement Proposals.
Roles and Capabilities
We rely on several roles described in the Five Component Model in this nutshell section along with their intended capabilities. The absence of an explicit capability description for a role implies that role should not be able to perform that capability
Changes to Transactions
Changes to the Coinbase Transaction
The coinbase transaction is an exceptional transaction Zcash inherited from Bitcoin which follows exceptional rules, including the distribution of newly issued tokens. This transaction is created by a block's miner.
The consensus rules are updated to require this transaction to make transfers of a portion of newly issued ZEC dedicated to Crosslink rewards only when this block updates finality to a greater height, and then as the sum of all pending finalization rewards since the previous finalization.
For each block produced which does not update finality, the per-block Crosslink rewards are collected into a running total, and a block which updates finality must then distributed this entire pending amount to the stakers and finalizers determined from the active set used to produce the finality update.
The pending finalizaiton rewards, , in a block which updates finality must be distributed by the coinbase transaction to finalizers and stakers proportionally to their reward slice, , where the active set (defined below) refers to the state as of the most recent final block, prior to this update.
This is calculated as follows where we let be the total stake weight for that participant:
-
For finalizers in the active set:
The constant is a fixed protocol parameter called the commission fee rate.
-
For all stakers:
The constant is called the staker reward rate.
Note that is the total weight of all staking positions of the given staker regardless of whether or not it is assigned to an finalizer in the active set.
Another nuance: the sum of all commission fees and staker rewards adds up to or less, with the difference coming from stake assigned to finalizers outside the active set.
New Transaction Format & Staking Actions
A new transaction format is introduced which contains a new optional field for staking actions, which enable operations such as staking ZEC to a finalizer, beginning or completing an unstaking action, or redelegating an existing staking position to a different delegator.
The ZEC flowing into staking actions, or flowing out of completing unstaking transactions must balance as part of the transactions chain value pool balancing. See The Zcash Protocol §4.17 Chain Value Pool Balances.
Additionally, we introduce a new restricting consensus rule on context-free transaction validity1:
Crosslink Staking Orchard Restriction:
A transaction which contains any staking actions must not contain any other fields contributing to or withdrawing from the Chain Value Pool Balances except Orchard actions, explicit transaction fees, and/or explicit ZEC burning fields.
Abstractly, the staking actions include:
- _stake - This creates a new staking position assigning a transparent ZEC amount, which must be a power of 10, to a finalizer and including a cryptographic signature verification key intended for only the signing-key holder of the position to redelegate or unstake.
- redelegate - This identifies a specific staking position, a new finalizer to reassign to, and a signature valid with the position's published verification key to authorize the transition.
- unbond - This initiates an "unbonding process" which puts the staking position into an unbonding state and includes the ZEC amount, the current block height, and the signature verification key to authorize a later claim. Once in this state, redelegations are not valid and the ZEC amount does not contribute to staking weight for finalizers or the staker.
- claim - This action removes a position in the unbonding state and contributes the bonded ZEC into the transaction's Chain Value Pool Balance, where because of the "Crosslink Staking Orchard Restriction, it may only be distributed into an Orchard destination and/or transaction fees.
Further Restrictions on Staking Actions
We furthermore introduce the following consensus rule restrictions on transactions involving staking actions which rely on a staking epoch design:
Staking Epoch Definition:
Once Crosslink activates at block height , staking epochs begin, which are continguous spans of block heights with two phases: staking day and the locked phase. The number of blocks for staking day is a protocol parameter constant roughly equivalent to 24 hours given assumptions about the Difficulty Adjustment Algorithm. The number of blocks for the locked phase is also a constant roughly equivalent to 6*24 hour periods, so that staking day is approximately one day per week.
Given the staking epoch definition, we introduce the following restrictions in the consensus rules:
Locked Staking Actions Restriction:
If a transaction includes any staking actions except for redelegate, and that transaction is in a block height in a locked phase of the staking epoch, then that block is invalid.
Also:
Unbonding Delay:
If a transaction is block height includes any claim staking actions which refer to unbonding state positions which have not existed in the unbonding state for at least one full staking epoch, that block is invalid.
Note: An implication of the Unbonding Delay is that the same staking day cannot include both an unbond and claim for the same position.
A final restriction (already mentioned above in introducing the staking action is:
Stake Action Amount Quantization:
If a transaction includes any staking actions with an amount which is not a power of 10 ZEC (or ZAT), that transaction is invalid.
Changes to Ledger State
The Ledger State is a conceptual and practical data structure which can be computed by fully verifying nodes solely from the sequence of blocks starting from the genesis block.2 To this Ledger State, Crosslink introduces the roster which is a table containing all of the information about all ZEC staked to finalizers.
The Roster
Crosslink's addition to Ledger State is embodied in the PoS roster, aka the roster for short. Which tracks staking positions created by Stakers, and attached to specific Finalizers. A Finalizer has a "voting weight" equal to the sum of all staking positions attached to it (see below in FIXME).
Each staking position is composed of at least a single specific target finalizer verification key, a staked ZEC amount, and a unstaking/redelegation verification key. The finalizer verification key designates a cryptographic signature verification key which serves as the sole on-chain reference to a specific finalizer3. People may mean a specific person, organization, entity, computer server, etc... when they say "finalizer", but for the rest of this document we will use the term finalizer as a shorthand for "whichever entity controls the verification key for a given finalizer verification key.
The unstaking/redelegation verifying key enables unstaking or redelegating that position from the participant that created that position (or more precisely anyone who controls the associated verifying key, which should be managed by a good wallet on behalf of users without their need to directly know or care about these keys for safe operation). These are unique to the position itself (and not linked on-chain to a user's other potential staking positions or other activity).
The sum of outstanding staking positions designating a specific finalizer verification key at a given block height is called the stake weight of that finalizer. At a given block height the top K (currently 100) finalizers by stake weight are called the active set of finalizers.
Ledger State Invariants
We adopt a design invariant around the Ledger State changes Crosslink makes against mainnet Zcash:
General Ledger State Design Invariant:
All changes to Ledger State can be computed entirely from (PoW) blocks, transactions, and data transitively referred to by such. This includes all existing Ledger State in mainnet Zcash today, the PoS and BFT roster state (see below), and the finality status of blocks and transactions.
All current mainnet Zcash Ledger State and almost all Crosslink Ledger State is height-immediate Ledger State: the value for height can be computed from height itself (and implicitly all prior heights and contents). Some examples of height-immediate values are the total ZEC issued, the UTXOs spendable by the same P2PKH t-addr, the block's zero-knowledge commitment anchor values, and so on. In Crosslink examples include all of the roster state (e.g. the active set, finalizer verification keys, staking positions, ...).
Height-Eventual Ledger State
Crosslink introduces a novel category of Ledger State not present in Zcash mainnet, which is height-eventual Ledger State. This is a property or value about height which is only computable at a later larger height (of which the implicit block at must be an ancestor). The sole example of this is finality status.
The finality status of a block at height (and by extension any transactions it contains and all previous block contents) is a property which guarantees[^guarantees] to the verifying node that this block (and all txns and previous content) is final and cannot be reverted or rolled back. Furthermore, the presence of this property also provides a guarantee that a majority of finalizers already agree on the finality status of this block and also that all verifying nodes which see a sufficient number of subsequent blocks will also agree on the finality status.
[^guarantees] In this book, whenever we say a protocol "guarantees" some condition, we mean that so long as the security assumptions truly hold verifying nodes can and should safely rely on that condition.
The finality status of a block at height (which we'll call a finality-candidate block here for precision) is computable from a block at a later height (which we'll call the attesting block). All verifying nodes who have observed the that attesting block will agree on the finality of the candidate block even though they may observe the attesting block rollback. In the event of such a rollback, the protocol guarantees that an alternative block will eventually attest to the finality status of the same candidate block.
Finality, Transaction Semantics, Ledger State, and the Roster
It bears pointing out a nuance: the Ledger State, including the Roster and the Active Set are all determined by valid transactions within PoW blocks. Every PoW block height thus has a specific unambiguous Ledger State. This comes into play later when we consider finality which is a property of a given block height which is only verifiable at a later block height.
The BFT Sub-Protocol
TODO: Flesh out this section
TODOS from deep dive:
- rewards distribution to stakers and finalizers requires changes to the Coinbase transaction.
- how finality status is calculated
- how BFT operates, votes, network, etc...
- active set selection
- quantization of amounts / time
- the power of 10 restriction on amount is only applied to "stake" (create position)
- how do staking actions pay fees?
-
A context-free transaction validity check may be performed on the bytes of the transaction itself without the need to access any chain state or index. ↩
-
Theoretically all of the Ledger State could be purely computed on demand from prior blocks, so literal Ledger State representations in memory can be thought of as chain indices or optimizing caches for verifying consensus rules. In some cases components of the Ledger State must be committed to within the blockchain state itself (for example, commitment anchors) which constrains how lazy a theoretical implementation can be. Real implementations trade off caching vs lazy-computation in a fine-grained way to achieve practical goals. ↩
-
Any particular entity may produce any number of finalizer verifying keys of course, although for economic or social reasons, we expect many finalizers to be motivated to hang their reputation on 1 or just a few well-known finalizer verifying keys. ↩
Terminology
Here we introduce terminology specific to this design, especially when it may deviate from other consensus systems or common terminology used in the consensus protocol field.
Crosslink Finality
Crosslink provides a kind of finality which we call crosslink finality. Crosslink finality has these properties:
- It is accountable because the chain contains explicit voting records which indicate each participating finalizer's on-chain behavior.
- It is irreversible within the protocol scope. The only way to "undo" a final block is to modify the software to do so, which requires intervention by the user. Note that because a finality safety violation is always theoretically possible, this implies the only recovery from such a violation is out-of-band to the protocol and requires human intervention.
- It is objectively verifiable because it is possible to determine finality from a local block history without any out-of-band information.
- It is globally consistent meaning that all nodes which have received a sufficient number of valid blocks agree on the finality status, and also can rely on all other nodes in this set arriving at the same conclusion.
- It provides asymmetric cost-of-attack defense (TODO: Describe this better.)
The Crosslink 2 Construction
This section is an almost direct paste from a section found in https://github.com/Electric-Coin-Company/tfl-book for the purposes of precisely committing to a (potentially incomplete, confusing, or inconsistent) precise set of book contents for a security design review. We believe this respects the license of the other repository.
The zebra-crosslink design in this book diverges from this text by not including "Stalled Mode" rules. This simplification to the protocol rules follows the rationale that we are already relying heavily on the stakers to guard safe operation of the protocol by redelegating appropriately to prevent hazards like BFT stalls.
The zebra-crosslink design does not use the "outer signature" referred to in this chapter, because this replaces a subtle security hazard which many participants could leverage maliciously to one where only the current proposer could leverage it maliciously, and we believe this trade-off is not worth it. This means a direct hash or copy of the most recent BFT finality certificate is insufficient evidence to ensure that specific bitwise copy is canonical or will become canonical in the chain.
We are now ready to give a description of a protocol that takes into account the issues described in Notes on Snap‑and‑Chat, and that implements bounded availability. We call this the “Crosslink” construction; more precisely the version described here is “Crosslink 2”.
This description will attempt to be self-contained, but [NTT2020] (arXiv version) is useful background on the general model of Ebb-and-Flow protocols.
Conventions
“” is a metavariable for the name of a protocol. We also use it as a wildcard in protocol names of a particular type, for example “bc” for the name of some best‑chain protocol.
Protocols are referred to as for a name “”. Where it is useful to avoid ambiguity, when referring to a concept defined by we prefix it with “‑”.
We do not take synchrony or partial synchrony as an implicit assumption of the communication model; that is, unless otherwise specified, messages between protocol participants can be arbitrarily delayed or dropped. A given message is received at most once, and messages are nonmalleably authenticated as originating from a given sender whenever needed by the applicable protocol. Particular subprotocols may require a stronger model.
For an overview of communication models used to analyze distributed protocols, see this blog post by Ittai Abraham.
Discussion of incorrect applications of the GST formalization of partial synchrony to continuously operating protocols.
Discussion of incorrect applications of the GST formalization of partial synchrony to continuously operating protocols.
The original context for the definition of the partially synchronous model in [DLS1988] was for “one‑shot” Byzantine Agreement — called “the consensus problem” in that paper. The following argument is used to justify assuming that all messages from the Global Stabilization Time onward are delivered within the upper time bound :
Therefore, we impose an additional constraint: For each execution there is a global stabilization time (GST), unknown to the processors, such that the message system respects the upper bound from time GST onward.
This constraint might at first seem too strong: In realistic situations, the upper bound cannot reasonably be expected to hold forever after GST, but perhaps only for a limited time. However, any good solution to the consensus problem in this model would have an upper bound on the amount of time after GST required for consensus to be reached; in this case it is not really necessary that the bound hold forever after time GST, but only up to time GST . We find it technically convenient to avoid explicit mention of the interval length in the model, but will instead present the appropriate upper bounds on time for each of our algorithms.
Several subsequent authors applying the partially synchronous model to block chains appear to have forgotten or neglected this context. In particular, the argument depends on the protocol completing soon after GST. Obviously a block‑chain protocol does not satisfy this assumption; it is not a “one‑shot” consensus problem.
This assumption could be removed, but some authors of papers about block‑chain protocols have taken it to be an essential aspect of modelling partial synchrony. I believe this is contrary to the intent of [DLS1988]:
Instead of requiring that the consensus problem be solvable in the GST model, we might think of separating the correctness conditions into safety and termination properties. The safety conditions are that no two correct processors should ever reach disagreement, and that no correct processor should ever make a decision that is contrary to the specified validity conditions. The termination property is just that each correct processor should eventually make a decision. Then we might require an algorithm to satisfy the safety conditions no matter how asynchronously the message system behaves, that is, even if does not hold eventually. On the other hand, we might only require termination in case holds eventually. It is easy to see that these safety and termination conditions are [for the consensus problem] equivalent to our GST condition: If an algorithm solves the consensus problem when holds from time GST onward, then that algorithm cannot possibly violate a safety property even if the message system is completely asynchronous. This is because safety violations must occur at some finite point in time, and there would be some continuation of the violating execution in which eventually holds.
This argument is correct as stated, i.e. for the one‑shot consensus problem. Subtly, essentially the same argument can be adapted to protocols with safety properties that need to be satisfied continuously. However, it cannot correctly be applied to liveness properties of non‑terminating protocols. The authors (Cynthia Dwork, Nancy Lynch, and Larry Stockmeyer) would certainly have known this: notice how they carefully distinguish “the GST model” from “partial synchrony”. They cannot plausibly have intended this GST formalization to be applied unmodified to analyze liveness in such protocols, which seems to be common in the block‑chain literature, including in the Ebb-and-Flow paper [NTT2020] and the Streamlet paper [CS2020].
The Ebb-and-Flow paper acknowledges the issue by saying “Although in reality, multiple such periods of (a‑)synchrony could alternate, we follow the long‑standing practice in the BFT literature and study only a single such transition.” This is not adequate: “long‑standing practice” notwithstanding, it is not valid in general to infer that properties holding for the first transition to synchrony also apply to subsequent transitions (where the protocol can be in states that would not occur initially), and it is plausible that this inference could fail for real protocols. The Streamlet paper also refers to “periods of synchrony” which indicates awareness of the issue, but then it uses the unmodified GST model in the proofs.
Informally, to solve this issue it is necessary to also prove that existing progress is maintained during periods of asynchrony, and that during such periods the protocol remains in states where it will be able to take advantage of a future period of synchrony to make further progress.
This provides further motivation to avoid taking the GST formalization of partial synchrony as a basic assumption.
Note that the recent result [CGSW2024] does not contradict anything we say here. Although the GST and Unknown Latency models are “equally demanding” in the sense of existence of protocols that satisfy a given goal, this result does not show that the models are equivalent for any specific protocol. In particular the requirements of the “clock‑slowing” technique fail in practice for any protocol involving Proof‑of‑Work.
A ‑execution is the complete set of events (message sends/receives and decisions by protocol participants) that occur in a particular run of from its initiation up to a given time. A prefix of a ‑execution is also a ‑execution. Since executions always start from protocol initiation, a strict suffix of a ‑execution is not a ‑execution.
Times are modelled as values of a totally ordered type with minimum value . For convenience, we consider all protocol executions to start at time .
Although protocols may be nondeterministic, an execution fixes the events that occur and times at which they occur, for the purpose of modeling.
For simplicity, we assume that all events occur at global times in a total ordering. This assumption is not realistic in an asynchronous communication model, but it is not essential to the design or analysis and could be removed: we could use a partial happens-before ordering on events in place of a total ordering on times.
A “‑node” is a participant in (the protocol may be implicit). A ‑node is “honest at time ” in a given execution iff it has followed the protocol up to and including time in that execution.
A time series on type is a function assigning a value of to each time in an execution. By convention, we will write the time as a superscript: .
A ‑chain is a nonempty sequence of ‑blocks, starting at the “genesis block” , in which each subsequent block refers to its preceding or “parent block” by a collision‑resistant hash. The “tip” of a ‑chain is its last element.
For convenience, we conflate ‑blocks with ‑chains; that is, we identify a chain with the block at its tip. This is justified because, assuming that the hash function used for parent links is collision‑resistant, there is exactly one ‑chain corresponding to a ‑block; and conversely there is exactly one ‑block at the tip of a ‑chain.
If is a ‑chain, means with the last blocks pruned, except that if , the result is the genesis ‑chain consisting only of .
The block at depth in a ‑chain is defined to be the tip of . Thus the block at depth in a chain is the last one that cannot be affected by a rollback of length (this also applies when because the genesis ‑chain cannot roll back).
Our usage of “depth” is different from [NTT2020], which uses “depth” to refer to what Bitcoin and Zcash call “height”. It also differs by from the convention for confirmation depths in zcashd, where the tip is considered to be at depth , rather than .
For ‑blocks and :
- The notation means that the ‑chain with tip is a prefix of the one with tip . This includes the case .
- The notation means that either or . That is, “one of and is a prefix of the other”. This also includes the case .
- The notation means that both and . That is, “neither of and is a prefix of the other”.
A function is ‑linear iff for every where we have . (This definition can be applied to time series where , or to sequences of ‑blocks where values of are indices.)
If and then .
Proof: The chain of ancestors of is -linear, and , are both on that chain.
The notation means the sequence of for each ‑block in chain order from genesis up to and including . ( is a bound variable within this construct.)
remove this if not used:
We use (without a subscript on ) to mean that the transaction ledger is a prefix of . Similarly to above, means that either or ; that is, “one of and is a prefix of the other”.
Views
In the simplest case, a block‑chain protocol provides a single “view” that, for a given ‑execution, provides each ‑node with a time series on ‑chains. More generally a protocol may define several “views” that provide each ‑node with time series on potentially different chain types.
We model a ‑view as a function . By convention, we will write the node index as a subscript and the time as a superscript: .
An execution of has Agreement on the view iff for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , we have .
Subprotocols
As in Snap‑and‑Chat, we depend on a BFT protocol , and a best‑chain protocol .
See this terminology note for why we do not call a “longest‑chain” protocol.
We modify (resp. ) to give (resp. ) by adding structural elements, changing validity rules, and changing the specified behaviour of honest nodes.
A Crosslink 2 node must participate in both and ; that is, it must maintain a view of the state of each protocol. Acting in more specific roles such as bft‑proposer, bft‑validator, or bc‑block‑producer is optional, but we assume that all such actors are Crosslink 2 nodes.
Model for BFT protocols (Π{origbft,bft})
A bft‑node’s view includes a set of bft‑block chains each rooted at a fixed genesis bft‑block . There is a bft‑block‑validity rule (specified below), which depends only on the content of the block and its ancestors. A non‑genesis block can only be bft‑block‑valid if its parent is bft‑block‑valid. A bft‑valid‑chain is a chain of bft‑block‑valid blocks.
Execution proceeds in a sequence of epochs. In each epoch, an honest proposer for that epoch may make a bft‑proposal.
A bft‑proposal refers to a parent bft‑block, and specifies the proposal’s epoch. The content of a proposal is signed by the proposer using a strongly unforgeable signature scheme. We consider the proposal to include this signature. There is a bft‑proposal‑validity rule, depending only on the content of the proposal and its parent block, and the validity of the proposer’s signature.
We extend the notation to bft‑proposals in the obvious way: if , is a bft‑proposal and its parent bft‑block, then .
We will shorten “bft‑block‑valid bft‑block” to “bft‑valid‑block”, and “bft‑proposal‑valid bft‑proposal” to “bft‑valid‑proposal”.
For each epoch, there is a fixed number of voting units distributed between the bft‑nodes, which they use to vote for a bft‑proposal. We say that a voting unit has been cast for a bft‑proposal at a given time in a bft‑execution, if and only if is bft‑proposal‑valid and a ballot for authenticated by the holder of the voting unit exists at that time.
Using knowledge of ballots cast for a bft‑proposal that collectively satisfy a notarization rule at a given time in a bft‑execution, and only with such knowledge, it is possible to obtain a valid bft‑notarization‑proof . The notarization rule must require at least a two‑thirds absolute supermajority of voting units in ’s epoch to have been cast for . It may also require other conditions.
A voting unit is cast non‑honestly for an epoch’s proposal iff:
- it is cast other than by the holder of the unit (due to key compromise or any flaw in the voting protocol, for example); or
- it is double‑cast (i.e. there are at least two ballots casting it for distinct proposals); or
- the holder of the unit following the conditions for honest voting in , according to its view, should not have cast that vote.
Note that a unit should be considered to be cast non-honestly in the case of key compromise, because it is then effectively under the control of an adversary. The key compromise may or may not be attributable to another flaw in the protocol, but such a flaw would not be a break of the consensus mechanism per se.
An execution of has the one‑third bound on non‑honest voting property iff for every epoch, strictly fewer than one third of the total voting units for that epoch are ever cast non‑honestly.
It may be the case that a ballot cast for is not in honest view when it is used to create a notarization proof for . Since we are not assuming synchrony, it may also be the case that such a ballot is in honest view but that any given node has not received it (and perhaps will never receive it).
There may be multiple distinct ballots or distinct ballot messages attempting to cast a given voting unit for the same proposal; this is undesirable for bandwidth usage, but it is not necessary to consider it to be non‑honest behaviour for the purpose of security analysis, as long as such ballots are not double‑counted toward the two‑thirds threshold.
The one‑third bound on non‑honest voting property considers all ballots cast in the entire execution. In particular, it is possible that a validator’s key is compromised and then used to cast its voting units for a proposal of an epoch long finished. If the number of voting units cast non-honestly for any epoch ever reaches one third of the total voting units for that epoch during an execution, then the one‑third bound on non‑honest voting property is violated for that execution.
Therefore, validator keys of honest nodes must remain secret indefinitely. Whenever a key is rotated, the old key must be securely deleted. For further discussion and potential improvements, see tfl-book issue #140.
A bft‑block consists of re‑signed by the same proposer using a strongly unforgeable signature scheme. It is bft‑block‑valid iff:
- is bft‑proposal‑valid; and
- is a valid proof that some subset of ballots cast for are sufficient to satisfy the notarization rule; and
- the proposer’s outer signature on is valid.
A bft‑proposal’s parent reference hashes the entire parent bft‑block, i.e. proposal, proof, and outer signature.
Neither nor the proposer’s outer signature is unique for a given . The proposer’s outer signature is however third‑party nonmalleable, by definition of a strongly unforgeable signature scheme. An “honest bft‑proposal” is a bft‑proposal made for a given epoch by a proposer who is honest in that epoch. Such a proposer will only create one proposal and only sign at most once for each epoch, and so there will be at most one “honestly submitted” bft‑block for each epoch.
It is possible for there to be multiple bft‑valid‑blocks for the same proposal, with different notarization proofs and/or outer signatures, if the proposer is not honest. However, the property that there will be at most one “honestly submitted” bft‑block for each epoch is important for liveness, even though we cannot guarantee that any particular proposer for an epoch is honest.
check that we are correctly using this in the liveness analysis.
There is an efficiently computable function . For a bft‑block‑valid input block , this function outputs the last ancestor of that is final in the context of .
The chain of ancestors is unambiguously determined because a bft‑proposal’s parent reference hashes the entire parent bft‑block; each bft‑block commits to a proposal; and the parent hashes are collision‑resistant. This holds despite the caveat mentioned above that there may be multiple bft‑valid‑blocks for the same proposal.
must satisfy all of the following:
- is not bft‑block‑valid.
- If is bft‑block‑valid, then:
- (and therefore it must also be bft‑block‑valid);
- for all bft‑valid‑blocks such that , .
- .
It is correct to talk about the “last final block” of a given chain (that is, each bft‑valid-block unambiguously determines a bft‑valid-block ), but it is not correct to refer to a given bft‑block as objectively “bft‑final”.
A particular BFT protocol might need adaptations to fit it into this model for , before we apply the Crosslink 2 modifications to obtain . Any such adaptions are necessarily protocol-specific. In particular:
- origbft‑proposal‑validity should correspond to the strongest property of an origbft‑proposal that is objectively and feasibly verifiable from the content of the proposal and its parent origbft‑block at the time the proposal is made. It must include verification of the proposer’s signature.
- origbft‑block‑validity should correspond to the strongest property of an origbft‑block that is objectively and feasibly verifiable from the content of the block and its ancestors at the time the block is added to an origbft‑chain. It should typically include all of the relevant checks from origbft‑proposal‑validity that apply to the created block (or equivalent checks). It must also include verification of the notarization proof and the proposer’s outer signature.
- If a node observes an origbft‑valid block , then it should be infeasible for an adversary to cause a rollback in that node’s view past , and the view of the chain up to should agree with that of all other honest nodes. This is formalized in the next section.
Safety of
The intuition behind the following safety property is that:
- For to be safe, it should never be the case that two honest nodes observe (at any time) bft‑blocks and respectively that they each consider final in some context, but does not hold.
- By definition, an honest node observes a bft‑block to be final in the context of another bft‑block , iff .
We say that a bft‑block is “in honest view” if a party observes it at some time at which that party is honest.
An execution of has Final Agreement iff for all bft‑valid blocks in honest view at time and in honest view at time , we have .
Note that it is possible for this property to hold for an execution of a BFT protocol in an asynchronous communication model. As previously mentioned, if the one‑third bound on non‑honest voting property is ever broken at any time in an execution, then it may not be possible to maintain Final Agreement from that point on.
Adapting the Streamlet BFT protocol.
Adapting the Streamlet BFT protocol.
Streamlet as described in [CS2020] has three possible states of a block in a player’s view:
- “valid” (but not notarized or final);
- “notarized” (but not final);
- “final”.
By “valid” the Streamlet paper means just that it satisfies the structural property of being part of a block chain with parent hashes. The role of bft‑block‑validity in our model corresponds roughly to Streamlet’s “notarized”. It turns out that with some straightforward changes relative to Streamlet, we can identify “origbft‑block‑valid” with “notarized” and consider an origbft‑valid‑chain to only consist of notarized blocks. This is not obvious, but is a useful simplification.
Here is how the paper defines “notarized”:
When a block gains votes from at least distinct players, it becomes notarized. A chain is notarized if its constituent blocks are all notarized.
This implies that blocks can be added to chains independently of notarization. However, the paper also says that an honest leader always proposes a block extending from a notarized chain. Therefore, only notarized chains really matter in the protocol.
In unmodified Streamlet, the order in which a player sees signatures might cause it to view blocks as notarized out of order. Streamlet’s security analysis is in a synchronous model, and assumes for liveness that any vote will have been received by all players (Streamlet nodes) within two epochs.
In Crosslink 2, however, we need origbft‑block‑validity to be an objectively and feasibly verifiable property. We also would prefer reliable message delivery within bounded time not to be a basic assumption of our communication model. (This does not dictate what assumptions about message delivery are made for particular security analyses.) If we did not make a modification to the protocol to take this into account, then some Crosslink 2 nodes might receive a two‑thirds absolute supermajority of voting messages and consider a BFT block to be notarized, while others might never receive enough of those messages.
Obviously a proposal cannot include signatures on itself — but the block formed from it can include proofs about the proposal and signatures. We can therefore say that when a proposal gains a two‑thirds absolute supermajority of signatures, a block is created from it that contains a proof (such as an aggregate signature) that it had such a supermajority. For example, we can have the proposer itself make this proof once it has enough votes, sign the resulting to create a block, then submit that block in a separate message. (The proposer has most incentive to do this in order to gain whatever reward attaches to a successful proposal; it can outsource the proving task if needed.) Then the origbft‑block‑validity rule can require a valid supermajority proof, which is objectively and feasibly verifiable. Players that see an origbft‑valid‑block can immediately consider it notarized.
Note that for the liveness analysis to be unaffected, we need to assume that the combined latency of messages, of collecting and aggregating signatures, and of block submission is such that all adapted‑Streamlet nodes will receive a notarized block corresponding to a given proposal (rather than just all of the votes for the proposal) within two epochs. Alternatively we could re‑do the timing analysis.
With this change, “origbft‑block‑valid” and “notarized” do not need to be distinguished.
Streamlet’s finality rule is:
If in any notarized chain, there are three adjacent blocks with consecutive epoch numbers, the prefix of the chain up to the second of the three blocks is considered final. When a block becomes final, all of its prefix must be final too.
We can straightforwardly express this as an function of a context block , as required by the model:
For an origbft‑valid‑block , is the last origbft‑valid‑block such that either or is the second block of a group of three adjacent blocks with consecutive epoch numbers.
Note that “When a block becomes final, all of its prefix must be final too.” is implicit in the model.
Model for best-chain protocols (Π{origbc,bc})
A node’s view in includes a set of bc‑block chains each rooted at a fixed genesis bc‑block . There is a bc‑block‑validity rule (often described as a collection of “consensus rules”), depending only on the content of the block and its ancestors. A non‑genesis block can only be bc‑block‑valid if its parent is bc‑block‑valid. By “bc‑valid‑chain” we mean a chain of bc‑block‑valid blocks.
The terminology commonly used in the block‑chain community does not distinguish between rules that are part of the consensus protocol proper, and rules required for validity of the economic computation supported by the block chain. Where it is necessary to distinguish, the former can be called “L0” consensus rules, and the latter “L1” consensus rules.
The definition of bc‑block‑validity is such that it is hard for a block producer to extend a bc‑valid‑chain unless they are selected by a random process that chooses a block producer in proportion to their resources with an approximately known and consistent time distribution, subject to some assumption about the total proportion of resources held by honest nodes.
There is a function , with a strict total ordering on . An honest node will choose one of the bc‑valid‑chains with highest score as the bc‑best‑chain in its view. Any rule can be specified for breaking ties.
The function is required to satisfy for any non‑genesis bc‑valid‑chain .
Unless an adversary is able to censor knowledge of other chains from a node’s view, it should be difficult to cause the node to switch to a chain with a last common ancestor more than blocks back from the tip of its previous bc‑best‑chain.
Let be a view such that is node ’s bc‑best‑chain at time . (This matches the notation used in [NTT2020].) We define to be .
A bc‑valid‑block is assumed to commit to a collection (usually, a sequence) of bc‑transactions. Unlike in Crosslink 1 or Snap-and-Chat, we do not need to explicitly model bc‑transaction validity or impose any additional constraints on it. The consensus rules applying to bc‑transactions are entirely unchanged, including any rules that depend on bc‑block height or previous bc‑blocks. This is because Crosslink 2 never reorders or selectively “sanitizes” transactions as Snap-and-Chat does. If a bc‑block is included in a Crosslink 2 block chain then its entire parent bc‑block chain is included just as it would have been in (only modified by the structural additions described later), so block heights are also preserved.
A “coinbase transaction” is a bc‑transaction that only distributes newly issued funds and has no inputs.
Define so that iff has exactly one transaction that is a coinbase transaction.
Each bc‑block is summarized by a bc‑header that commits to the block. There is a notion of bc‑header‑validity that is necessary, but not sufficient, for validity of the block. We will only make the distinction between bc‑headers and bc‑blocks when it is necessary to avoid ambiguity.
Header validity for Proof‑of‑Work protocols.
Header validity for Proof‑of‑Work protocols.
In a Proof‑of‑Work protocol, it is normally possible to check the Proof‑of‑Work of a block using only the header. There is a difficulty adjustment function that determines the target difficulty for a block based on its parent chain. So, checking that the correct difficulty target has been used relies on knowing that the header’s parent chain is valid.
Checking header validity before expending further resources on a purported block can be relevant to mitigating denial‑of‑service attacks that attempt to inflate validation cost.
Typically, Bitcoin‑derived best chain protocols do not need much adaptation to fit into this model. The model still omits some details that would be important to implementing Crosslink 2, but distracting for this level of abstraction.
Safety of
We make an assumption on executions of that we will call Prefix Consistency (introduced in [PSS2016, section 3.3] as just “consistency”):
An execution of has Prefix Consistency at confirmation depth , iff for all times and all nodes , (potentially the same) such that is honest at time and is honest at time , we have that .
Explain the confusion in the literature about what variants of this property are called.
Explain the confusion in the literature about what variants of this property are called.
The literature uses the same name, “common‑prefix property”, for two different properties of very different strength.
[PSS2016, section 3.3] introduced the stronger variant. That paper first describes the weaker variant, calling it the “common‑prefix property by Garay et al [GKL2015].” Then it explains what is essentially a bug in that variant, and describes the stronger variant which it just calls “consistency”:
The common‑prefix property by Garay et al [GKL2015], which was already considered and studied by Nakamoto [Nakamoto2008], requires that in any round , the record chains of any two honest players , agree on all, but potentially the last , records. We note that this property (even in combination with the other two desiderata [of Chain Growth and Chain Quality]) provides quite weak guarantees: even if any two honest parties perfectly agree on the chains, the chain could be completely different on, say, even rounds and odd rounds. We here consider a stronger notion of consistency which additionally stipulates players should be consistent with their “future selves”.
Let iff for all rounds , and all players , (potentially the same) such that is honest at and is honest at , we have that the prefixes of and consisting of the first records are identical.
Unfortunately, [GKL2020], which is a revised version of [GKL2015], switches to the stronger variant without changing the name.
(The eprint version history may be useful; the change was made in version 20181013:200033, page 17.)
Note that [GKL2020] uses an adaptive‑corruption model, “meaning that the adversary is allowed to take control of parties on the fly”, and so their wording in Definition 3:
... for any pair of honest players , adopting the chains , at rounds in view respectively, it holds that .
is intended to mean the same as our
... for all times and all nodes , (potentially the same) such that is honest at time and is honest at time , we have that .
The latter is closer to [PSS2016].
Incidentally, this property does not seem to be mentioned in [Nakamoto2008], contrary to the [PSS2016] authors’ assertion. Maybe implicitly, but it’s a stretch.
Discussion of [GKL2020]’s communication model and network partition.
Discussion of [GKL2020]’s communication model and network partition.
When Prefix Consistency is taken to hold of typical PoW-based block‑chain protocols like Bitcoin (as it often is), this implies that, in the relevant executions, the network of honest nodes is never partitioned — unless any partition lasts only for a short length of time relative to block times. If node is on one side of a full partition and node on the other, then after node ’s best chain has been extended by more than blocks, will contain information that has no way to get to node . And even if the partition is incomplete, we cannot guarantee that the Prefix Consistency property will hold for any given pair of nodes.
It might be possible to maintain Prefix Consistency if the honest nodes on one side of the partition knew that they should not continue building on their chain until the partition has healed, but it is unclear how that would be done in general without resorting to a BFT protocol (as opposed to in specific cases like a single node being unable to connect to the rest of the network). Certainly there is no mechanism to explicitly detect and respond to partitions in protocols derived from Bitcoin.
And yet, [GKL2020] claims to prove Prefix Consistency from other assumptions. So we know that those assumptions must also rule out a long partition between honest nodes. In fact the required assumption is implicit in the communication model:
- A synchronous network cannot be partitioned.
- A partially synchronous network —that is, providing reliable delivery with bounded but unknown delay— cannot be partitioned for longer than the delay.
We might be concerned that these implicit assumptions are stronger than we would like. In practice, the peer‑to‑peer network protocol of Bitcoin and Zcash attempts to flood blocks to all nodes. This protocol might have weaknesses, but it is not intended to (and plausibly does not) depend on all messages being received. (Incidentally, Streamlet also implicitly floods messages to all nodes.)
Also, Streamlet and many other BFT protocols do not assume for safety that the network is not partitioned. That is, BFT protocols can be safe in a fully asynchronous communication model with unreliable messaging. That is why we avoid taking synchrony or partial synchrony as an implicit assumption of the communication model, or else we could end up with a protocol with weaker safety properties than alone.
This leaves the question of whether the Prefix Consistency property is still too strong, even if we do not rely on it for the analysis of safety when has not been subverted. In particular, if a particular node is not well-connected to the rest of the network, then that will inevitably affect node ’s security, but should not affect other honest nodes’ security.
Fortunately, it is not the case that disconnecting a single node from the network causes the security assumption to be voided. The solution is to view as not honest in that case (even though it would follow the protocol if it could). This achieves the desired effect within the model, because other nodes can no longer rely on ’s honest input. Although viewing as potentially adversarial might seem conservative from the point of view of other nodes, bear in mind that an adversary could censor an arbitrary subset of incoming and outgoing messages from the node, and this may be best modelled by considering it to be effectively controlled by the adversary.
Prefix Consistency compares the -truncated chain of some node with the untruncated chain of node . For our analysis of safety of the derived ledgers, we will also need to make an assumption on executions of that at any given time , any two honest nodes and agree on their confirmed prefixes — with only the caveat that one may have observed more of the chain than the other. That is:
An execution of has Prefix Agreement at confirmation depth iff it has Agreement on the view .
Why are this property, and Prefix Consistency above, stated as unconditional properties of protocol executions, rather than as probabilistic assumptions?
Why are this property, and Prefix Consistency above, stated as unconditional properties of protocol executions, rather than as probabilistic assumptions?
Our security arguments that depend on these properties will all be of the form “in an execution where ⟨safety properties⟩ are not violated, ⟨undesirable thing⟩ cannot happen”.
It is not necessary to involve probability in arguments of this form. Any probabilistic reasoning can be done separately.
In particular, if a statement of this form holds, and ⟨safety properties⟩ are violated with probability at most under certain conditions, then it immediately follows that under those conditions ⟨undesirable thing⟩ happens with probability at most . Furthermore, ⟨undesirable thing⟩ can only happen after ⟨safety properties⟩ have been violated, because the execution up to that point has been an execution in which ⟨safety properties⟩ are not violated.
With few exceptions, involving probability in a security argument is best done only to account for nondeterministic choices in the protocol itself. This is opinionated advice, but a lot of security proofs would likely be simpler if inherently probabilistic arguments were more distinctly separated from unconditional ones.
In the case of the Prefix Agreement property, an alternative approach would be to prove that Prefix Agreement holds with some probability given Prefix Consistency and some other chain properties. This is what [NTT2020] does in its Theorem 2, which essentially says that under certain conditions Prefix Agreement holds except with probability .
The conclusions that can be obtained from this approach are necessarily probabilistic, and depending on the techniques used, the proof may not be tight; that is, the proof may obtain a bound on the probability of failure that is (either asymptotically or concretely) higher than needed. This is the case for [NTT2020, Theorem 2]; footnote 10 in that paper points out that the expression for the probability can be asymptotically improved:
Using the recursive bootstrapping argument developed in [DKT+2020, Section 4.2], it is possible to bring the error probability as close to an exponential decay as possible. In this context, for any , it is possible to find constants , such that is secure after C with confirmation time except with probability .
(Here is the probability that any given node gets to produce a block in any given time slot.)
In fact none of the proofs of security properties for Snap‑and‑Chat depend on the particular expression ; for example in the proofs of Lemma 5 and Theorem 1, this probability just “passes through” the proof from the premisses to the conclusion, because the argument is not probabilistic. The same will be true of our safety arguments.
Talking about what is possible in particular executions has further advantages:
- It sidesteps the issue of how to interpret results in the GST model of partial synchrony, when we do not know what C is. See also the critique of applying the GST model to block‑chain protocols under “Discussion of [GKL2020]’s communication model and network partition” above. (This is not an inherent problem with analyzing the protocol in the partially synchronous setting, but only with inappropriate use of the GST model of that setting.)
- We do not require to be a Nakamoto‑style Proof‑of‑Work block chain protocol. Some other kind of protocol could potentially satisfy Prefix Consistency and Prefix Agreement.
- It is not clear whether a probability of failure would be concretely adequate. That would depend on the value of and the constant hidden by the notation. The asymptotic property using tells us whether a sufficiently large could be chosen, but we are more interested in what needs to be assumed for a given concrete choice of .
- If a violation of a required safety property occurs in a given execution, then the safety argument for Crosslink that depended on the property fails for that execution, regardless of what the probability of that occurrence was. This approach therefore more precisely models the consequences of such violations.
Why, intuitively, should we believe that Prefix Agreement and Prefix Consistency for a large enough confirmation depth hold with high probability for executions of a PoW‑based best‑chain protocol?
Why, intuitively, should we believe that Prefix Agreement and Prefix Consistency for a large enough confirmation depth hold with high probability for executions of a PoW‑based best‑chain protocol?
Roughly speaking, the intuition behind both properties is as follows:
Honest nodes are collectively able to find blocks faster than an adversary, and communication between honest nodes is sufficiently reliable that they act as a combined network racing against that adversary. Then by the argument in [Nakamoto2008], modified by [GP2020] to correct an error in the concrete analysis, a private mining attack that attempts to cause a ‑block rollback will, with high probability, fail for large enough . A private mining attack is optimal by the argument in [DKT+2020].
Any further analysis of the conditions under which these properties hold should be done in the context of a particular .
Why is the quantification in Prefix Agreement over two different times t and t′?
Why is the quantification in Prefix Agreement over two different times t and t′?
This strengthens the security property, relative to quantifying over a single time. The question can then be split into several parts:
- What does the strengthened property mean, intuitively? Consider the full tree of bc‑valid-blocks that honest nodes have considered to be part of their bc‑best-chain at any times during the execution. This property holds iff, when we strip off all branches of length up to and including blocks, the resulting tree is bc‑linear.
- Why is the strengthening needed? Suppose that time were split into periods such that honest nodes agreed on one chain in odd periods, and a completely different chain in even periods. This would obviously not satisfy the intent, but it would satisfy a version of the property that did not quantify over different times and .
- Why should we expect the strengthened property to hold? If node were far ahead, i.e. , then it is obvious that should hold. Conversely, if node were far ahead then it is obvious that should hold. The case where is the same as quantifying over a single time. By considering intermediate cases where and converge from the extremes or where they diverge from being equal, you should be able to convince yourself that the property holds for any relative values of and , in executions of a reasonable best‑chain protocol.
Definition of Crosslink 2
Parameters
Crosslink 2 is parameterized by a bc‑confirmation‑depth (as in Snap‑and‑Chat), and also a finalization gap bound with significantly greater than .
Each node always uses the fixed confirmation depth to obtain its view of the finalized chain . Unlike in Snap‑and‑Chat or Crosslink 1, this is just a block chain; because we do not need sanitization, there is no need to express it as a log of transactions rather than blocks.
Each node chooses a potentially different bc‑confirmation‑depth where to obtain its view of the bounded‑available ledger at time , . (We make the restriction because there is no reason to choose a larger .)
Choosing is at the node’s own risk and may increase the risk of rollback attacks against (it does not affect ). Using small values of is not recommended. The default should be .
Stalled Mode
Consider, roughly speaking, the number of bc‑blocks that are not yet finalized at time (a more precise definition will be given in the section on changes from ). We call this the “finality gap” at time . Under an assumption about the distribution of bc‑block intervals, if this gap stays roughly constant then it corresponds to the approximate time that transactions take to be finalized after being included in a bc‑block (if they are finalized at all) just prior to time .
As explained in detail by The Arguments for Bounded Availability and Finality Overrides, if this bound exceeds a threshold , then it likely signals an exceptional or emergency condition, in which it is undesirable to keep accepting user transactions that spend funds into new bc‑blocks. In practice, should be at least .
The condition that the network enters in such cases will be called “Stalled Mode”. For a given higher‑level transaction protocol, we can define a policy for which bc‑blocks will be accepted in Stalled Mode. This will be modelled by a predicate . A bc‑block for which returns is called a “stalled block”.
A bc‑block producer is only constrained to produce stalled blocks while, roughly speaking, its view of the finalization point is not advancing. In particular an adversary that has subverted the BFT protocol in a way that does not keep the finalization point from advancing, can always avoid being constrained by Stalled Mode.
The desired properties of stalled blocks and a possible Stalled Mode policy for Zcash are discussed in the How to block hazards section of The Arguments for Bounded Availability and Finality Overrides.
In practice a node's view of the finalized chain, , is likely to lag only a few blocks behind (depending on the latency overhead imposed by ), unless the chain has entered Stalled Mode. So when , the main factor influencing the choice of a given application to use or is not the average latency, but rather the desired behaviour in the case of a finalization stall: i.e. stall immediately, or keep processing user transactions until blocks have passed.
Structural additions
- Each bc‑header has, in addition to origbc‑header fields, a field that commits to a bft‑block.
- Each bft‑proposal has, in addition to origbft‑proposal fields, a field containing a sequence of exactly bc‑headers (zero‑indexed, deepest first).
- Each non‑genesis bft‑block has, in addition to origbft‑block fields, a field containing a sequence of exactly bc‑headers (zero-indexed, deepest first). The genesis bft‑block has .
For a bft‑block or bft‑proposal , define For a bc‑block , define
When is the tip of a node’s bc‑best‑chain, will give the candidate finalization point, subject to a condition described below that prevents local rollbacks.
Use of the headers_bc field, and its relation to the ch field in Snap‑and‑Chat.
Use of the headers_bc field, and its relation to the ch field in Snap‑and‑Chat.
For a bft‑proposal or bft‑block , the role of the bc‑chain snapshot referenced by is comparable to the snapshot referenced by in the Snap‑and‑Chat construction from [NTT2020]. The motivation for the additional headers is to demonstrate, to any party that sees a bft‑proposal (resp. bft‑block), that the snapshot had been confirmed when the proposal (resp. the block’s proposal) was made.
Typically, a node that is validating an honest bft‑proposal or bft‑block will have seen at least the snapshotted bc‑block (and possibly some of the subsequent bc‑blocks in the chain) before. For this not to be the case, the validator’s bc‑best‑chain would have to be more than bc‑blocks behind the honest proposer’s bc‑best‑chain at a given time, which would violate the Prefix Consistency property of .
If the headers do not connect to any bc‑valid‑chain known to the validator, then the validator should be suspicious that the proposer might not be honest. It can assign a lower priority to validating the proposal in this case, or simply drop it. The latter option could drop a valid proposal, but this does not in practice cause a problem as long as a sufficient number of validators are properly synced (so that Prefix Consistency holds for them).
If the headers do connect to a known bc‑valid‑chain, it could still be the case that the whole header chain up to and including is not a bc‑valid‑chain. Therefore, to limit denial‑of‑service attacks the validator should first check the Proofs‑of‑Work and difficulty adjustment —which it can do locally using only the headers— before attempting to download and validate any bc‑blocks that it has not already seen. This is why we include the full headers rather than just the block hashes. Nodes may “trim” (i.e. not explicitly store) headers in a bft‑block that overlap with those referred to by its ancestor bft‑block(s).
Why is a distinguished value needed for the headers_bc field in the genesis bft‑block?
Why is a distinguished value needed for the headers_bc field in the genesis bft‑block?
It would be conceptually nice for to refer to , as well as being so that . That reflects the fact that we know “from the start” that neither genesis block can be rolled back.
This is not literally implementable using block hashes because it would involve a hash cycle, but we achieve the same effect by defining a function that allows us to “patch” to be . We do it this way around rather than “patching” the link from a bc‑block to a bft‑block, because the genesis bft‑block already needs a special case since there are not bc‑headers available.
Why is the context_bft field needed? Why not use a final_bft field to refer directly to the last final bft‑block before the context block?
Why is the context_bft field needed? Why not use a final_bft field to refer directly to the last final bft‑block before the context block?
The finality of some bft‑block is only defined in the context of another bft‑block. One possible design would be for a bc‑block to have both and fields, so that the finality of could be checked objectively in the context of .
However, specifying just the context block is sufficient information to determine its last final ancestor. There would never be any need to give a context block and a final ancestor that is not the last one. The function can be computed efficiently for typical BFT protocols. Therefore, having just the field is sufficient.
Locally finalized chain
Each node keeps track of a “locally finalized” bc‑chain at time . Each node’s locally finalized bc‑chain starts at . However, this chain state should not be exposed to clients of the node until it has synced.
Node has Local finalization linearity up to time iff the time series of bc‑blocks is bc‑linear.
When node ’s bc‑best‑chain view is updated from to , the node’s will become if and only if this is a descendant of . Otherwise will stay at . This guarantees Local finalization linearity by construction.
If when making this update, (i.e. and are on different forks), then the node should record a finalization safety hazard. This can only happen if global safety assumptions are violated. Note that Local finalization linearity on each node is not sufficient for Assured Finality, but it is necessary.
This can be expressed by the following state update algorithm, where is the time of the last update and is the time of the current update:
A safety hazard record should include and the history of updates including and since the last one that was an ancestor of .
In any execution of Crosslink 2, for any node that is honest at time , there exists a time such that .
Proof: By the definition of we have for all times . Let be the last time at which changed, or the genesis time if it has never changed. Then for we have , and for we have (because , and truncating always yields ).
Why does fini need to be maintained using local state?
Why does fini need to be maintained using local state?
When a node’s view of the bc‑best‑chain reorgs to a different fork (even if the reorg is shorter than blocks), it may be the case that rolls back. If Final Agreement of holds up to time , the new snapshot should in that case be an ancestor of the old one. If all is well then this snapshot will subsequently roll forward along the same path. However, we do not want applications using the node to see the temporary rollback.
Assured Finality is our main safety goal for Crosslink 2. It is essentially the same goal as Final Agreement but applied to nodes’ locally finalized bc‑chains; intuitively it means that honest nodes never see conflicting locally finalized chains. We intend to prove that this goal holds under reasonable assumptions about either or .
An execution of Crosslink 2 has Assured Finality iff for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , we have .
Note that if an execution of Crosslink 2 has Assured Finality, then all nodes that are honest for that execution have Local finalization linearity. That is because the restriction of Assured Finality to the case is equivalent to Local finalization linearity for node up to any time at which node is honest.
Why do we need to use candidate(H) rather than snapshot(LF(H))?
Why do we need to use candidate(H) rather than snapshot(LF(H))?
This ensures that the candidate is at least ‑confirmed.
In practice will rarely differ from , but using the former patches over a potential gap in the safety proof. The Last Final Snapshot rule specified later will guarantee that , and this ensures that . However, the depth of relative to is not guaranteed to be . For the proof we will need , so that we can use the Local fin‑depth lemma together with Prefix Agreement of at confirmation depth to prove Assured Finality.
An alternative would be to change the Last Final Snapshot rule to directly require .
Choose between these options based on what works well for the security proofs and finalization latency.
Locally bounded‑available chain
Define the locally bounded‑available chain on node for bc‑confirmation‑depth , as
Like the locally finalized bc‑chain, this chain state should not be exposed to clients of the node until it has synced.
For any node that is honest at time , and any confirmation depth , .
Proof: By construction of .
In any execution of Crosslink 2, for any confirmation depth and any node that is honest at time , there exists a time such that .
Proof: Either , in which case the result follows by the Local fin‑depth lemma since , or in which case it follows trivially with .
Our security goal for will be Agreement on as already defined.
Why is the ‘otherwise’ case in the definition of (baμ)it necessary?
Why is the ‘otherwise’ case in the definition of (baμ)it necessary?
Assume for this discussion that uses PoW.
Depending on the value of , the timestamps of bc‑blocks, and the difficulty adjustment rule, it can be the case that if switches to a different fork, the difficulty on that fork is greater than on the chain of the previous snapshot. Then, the new bc‑chain could reach a higher score than the previous chain in fewer than blocks from the fork point, and so might not be a descendant of (which is more likely if ). This can occur even when all safety assumptions are satisfied.
For Zcash’s difficulty adjustment algorithm, the difficulty of each block is adjusted based on the median timestamps and difficulty target thresholds over a range of blocks, where each median is taken over blocks. Other damping factors and clamps are applied in order to prevent instability and to reduce the influence that adversarially chosen timestamps can have on difficulty adjustment. This makes it unlikely that an adversary could gain a significant advantage by manipulating the difficulty adjustment. So it is safe to use in this case: even though it does not have confirmations relative to , it does have at least the required amount of work “on top” of it.
Defining this way also has the advantage of making the proof of the Ledger prefix property trivial.
Syncing and checkpoints
It is recommended that node implementations “bake in” a checkpointed bft‑block to each released version, and that node should only expose and to its clients once it is “synced”, that is:
- ; and
- ; and
- the timestamp of is within some threshold of the current time.
Πbft changes from Πorigbft
Πbft proposal and block validity
Genesis bft‑block rule: is bft‑block‑valid.
A bft‑proposal (resp. non‑genesis bft‑block) is bft‑proposal‑valid (resp. bft‑block‑valid) iff all of the following hold:
- Inherited origbft rules: The corresponding origbft‑proposal‑validity (resp. origbft‑block‑validity) rules hold for .
- Linearity rule: .
- Tail Confirmation rule: form the ‑block tail of a bc‑valid‑chain.
The “corresponding validity rules” are assumed to include the Parent rule that ’s parent is bft‑valid.
Note: origbft‑block‑validity rules may be different to origbft‑proposal‑validity rules. For example, in adapted Streamlet, a origbft‑block needs evidence that it was voted for by a supermajority, and an origbft‑proposal doesn’t. Such differences also apply to bft‑block‑validity vs bft‑proposal‑validity.
Why have validity rules been separated from the honest voting condition below?
Why have validity rules been separated from the honest voting condition below?
The reason to separate the validity rules from the honest voting condition, is that the validity rules are objective: they don’t depend on an observer’s view of the bc‑best‑chain. Therefore, they can be checked independently of validator signatures. Even a proposal voted for by 100% of validators will not be considered bft‑proposal‑valid by other nodes unless it satisfies the above rules. If more than two thirds of voting units are cast for an invalid proposal, something is seriously and visibly wrong; in any case, the block will not be accepted as a bft‑valid‑block. Importantly, a purportedly valid bft‑block will not be recognized as such by any honest Crosslink 2 node even if it includes a valid notarization proof, if it does not meet other bft‑block‑validity rules.
This is essential to making the finalized chain safe against a flaw in or its security assumptions (even, say, a complete break of the validator signature algorithm), as long as remains safe.
What does the Linearity rule do?
What does the Linearity rule do?
This rule is key to combining simplicity with strong security properties in Crosslink 2. It essentially says that, in a given bft‑valid‑chain, the snapshots pointed to by blocks in that chain cannot roll back.
This allows the informal safety argument for Crosslink 2 to be rather intuitive.
Informally, if has Final Agreement, then all nodes see only one consistent bft‑linear chain (restricting to bft‑blocks that are final in the context of some bft‑block in honest view). Within such a bft‑chain, the Linearity rule ensures by construction that the sequence of referenced bc‑chain snapshots is bc‑linear. This implies Assured Finality, without needing to assume any safety property of .
We will also be able to prove safety of the finalized snapshots based only on safety of (for a confirmation depth of ), without needing to assume any safety property of . Informally, that is because each node sees each candidate final snapshot at a given time as a -confirmed prefix of its bc‑best‑chain at that time (this can be proven based on the Last Final Snapshot rule and the fact that a snapshot includes subsequent headers), and Prefix Agreement implies that honest nodes agree on this prefix. We will leave a more detailed argument until after we have presented the changes from .
The Linearity rule replaces the “Increasing Score rule” used in Crosslink 1. The Increasing Score rule required that each snapshot in a bft‑valid‑chain either be the same snapshot, or a higher-scoring snapshot to that of its parent block. Since scores strictly increase within a bc‑valid‑chain, the Linearity rule implies the Increasing Score rule. It retains the same or stronger positive effects:
- It prevents potential attacks that rely on proposing a bc‑valid‑chain that forks from a much earlier block. This is necessary because the difficulty (or stake threshold) at that point could have been much lower.
- It limits the extent of disruption an adversary can feasibly cause to the bounded‑available chain , even if it has subverted . Informally, because the finalized chain is a chain, its safety is no worse than alone for a rollback of any depth.
- It ensures that either progress is made (the snapshot advances relative to that of the parent bft‑block), or there is no further validation that needs to be done for the snapshot because it was already validated.
Note that the adversary could take advantage of an “accidental” fork and start its attack from the base of that fork, so that not all of this work is done by it alone. This is also possible in the case of a standard “private mining” attack, and is not so much of a problem in practice because accidental forks are expected to be short. In any case, should be chosen to take it into account.
The Linearity rule is also critical to removing the need for one of the most complex elements of Snap‑and‑Chat and Crosslink 1, “sanitization”. In those protocols, because bc‑chain snapshots could be unrelated to each other, it was necessary to sanitize the chain formed from these snapshots to remove transactions that were contextually invalid (e.g. because they double‑spend). The negative consequences of this are described in Notes on Snap‑and‑Chat; avoiding it is much simpler.
The linearity property is intentionally always relative to the snapshot of the parent bft‑block, even if it is not final in the context of the current bft‑block. This is because the rule needs to hold if and when it becomes final in the context of some descendant bft‑block.
PoS Desideratum: we want leader selection with good security / performance properties that will be relevant to this rule. (Suggested: PoSAT.)
Why does the Linearity rule allow keeping the same snapshot as the parent?
Why does the Linearity rule allow keeping the same snapshot as the parent?
This is necessary in order to preserve liveness of relative to . Liveness of might require honest proposers to make proposals at a minimum rate. That requirement could be consistently violated if it were not always possible to make a valid proposal. But given that it is allowed to repeat the same snapshot as in the parent bft‑block, neither the Linearity rule nor the Tail Confirmation rule can prevent making a valid proposal — and all other rules of affecting the ability to make valid proposals are the same as in . (In principle, changes to voting in could also affect its liveness; we’ll discuss that in the liveness proof later.)
For example, Streamlet requires three notarized blocks in consecutive epochs in order to finalize a block [CS2020, section 1.1]. Its proof of liveness depends on the assumption that in each epoch for which the leader is honest, that leader will make a proposal, and that during a “period of synchrony” this proposal will be received by every node [CS2020, section 3.6]. This argument can also be extended to adapted‑Streamlet.
We could alternatively have allowed to always make a “null” proposal, rather than to always make a proposal with the same snapshot as the parent. We prefer the latter because the former would require specifying the rules for null proposals in .
As a clarification, no BFT protocol that uses leader election can require a proposal in each epoch, because the leader might be dishonest. The above issue concerns liveness of the protocol when assumptions about the attacker’s share of bft‑validators or stake are met, so that it can be assumed that sufficiently long periods with enough honest leaders to make progress (5 consecutive epochs in the case of Streamlet), will occur with significant probability.
Πbft block finality in context
The finality rule for bft‑blocks in a given context is unchanged from origbft‑finality. That is, is defined in the same way as (modulo referring to bft‑block‑validity and ).
Πbft honest proposal
An honest proposer of a bft‑proposal chooses as the ‑block tail of its bc‑best‑chain, provided that it is consistent with the Linearity rule. If it would not be consistent with that rule, it sets to the same field as ’s parent bft‑block. It does not make proposals until its bc‑best‑chain is at least blocks long.
Why σ + 1?
Why σ + 1?
If the length were less than blocks, it would be impossible to construct the field of the proposal.
Note that when the length of the proposer’s bc‑best‑chain is exactly blocks, the snapshot must be of But this does not violate the Linearity rule, because matches the previous snapshot by .
How is it possible that the Linearity rule would not be satisfied by choosing headers from an honest proposer’s bc‑best‑chain?
How is it possible that the Linearity rule would not be satisfied by choosing headers from an honest proposer’s bc‑best‑chain?
As in the answer to Why is the ‘otherwise’ case in the definition of necessary? above, after a reorg on the bc‑chain, the -confirmed block on the new chain might not be a descendant of the -confirmed block on the old chain, which could break the Linearity rule.
Πbft honest voting
An honest validator considering a proposal , first updates its view of both subprotocols with the bc‑headers given in , downloading bc‑blocks for these headers and checking their bc‑block‑validity.
For each downloaded bc‑block, the bft‑chain referenced by its field might need to be validated if it has not been seen before.
Wait what, how much validation is that?
Wait what, how much validation is that?
In general the entire referenced bft‑chain needs to be validated, not just the referenced block — and for each bft‑block, the bc‑chain in needs to be validated, and so on recursively. If this sounds overwhelming, note that:
- We should check the requirement that a bft‑valid‑block must have been voted for by a two‑thirds absolute supermajority of validators, and any other non‑recursive bft‑validity rules, first.
- Before validating a bc‑chain referenced by a field, we check that it connects to an already-validated bc‑chain and that the Proofs‑of‑Work are valid. This implies that the amount of bc‑block validation is constrained by how fast the network can find valid Proofs‑of‑Work.
- The Linearity rule reduces the worst‑case validation effort, by ensuring that only one bc‑chain needs to be validated for any bft‑chain. Assuming safety of and that the adversary does not have an overwhelming advantage in computing the Proof‑of‑Work, this is effectively only one bc‑chain overall with, at most, short side branches.
In summary, the order of validation is important to avoid denial‑of‑service — but it already is in Bitcoin and Zcash.
After updating its view, the validator will vote for a proposal only if:
- Valid proposal criterion: it is bft‑proposal‑valid, and
- Confirmed best‑chain criterion: is part of the validator’s bc‑best‑chain at a bc‑confirmation‑depth of at least .
Blocks in a bc‑best‑chain are by definition bc‑block‑valid. If we’re checking the Confirmed best‑chain criterion, why do we need to have separately checked that the blocks referenced by the headers are bc‑block‑valid?
Blocks in a bc‑best‑chain are by definition bc‑block‑valid. If we’re checking the Confirmed best‑chain criterion, why do we need to have separately checked that the blocks referenced by the headers are bc‑block‑valid?
The Confirmed best‑chain criterion is quite subtle. It ensures that is bc‑block‑valid and has bc‑block‑valid blocks after it in the validator’s bc‑best‑chain. However, it need not be the case that is part of the validator’s bc‑best‑chain after it updates its view. That is, the chain could fork after .
The bft‑proposal‑validity rule must be objective; it can’t depend on what the validator’s bc‑best‑chain is. The validator’s bc‑best‑chain may have been updated to (if it has the highest score), but it also may not.
However, if the validator’s bc‑best‑chain was updated, that makes it more likely that it will be able to vote for the proposal.
In any case, if the validator does not check that all of the blocks referenced by the headers are bc‑block‑valid, then its vote may be invalid.
How does this compare to Snap‑and‑Chat?
How does this compare to Snap‑and‑Chat?
Snap‑and‑Chat already had the voting condition:
An honest node only votes for a proposed BFT block if it views as confirmed.
but it did not give the headers potentially needed to update the validator’s view, and it did not require a proposal to be for an objectively confirmed snapshot as a matter of validity.
If a Crosslink‑like protocol were to require an objectively confirmed snapshot but without including the bc‑headers in the proposal, then validators would not immediately know which bc‑blocks to download to check its validity. This would increase latency, and would be likely to lead proposers to be more conservative and only propose blocks that they think will already be in at least a two‑thirds absolute supermajority of validators’ best chains.
That is, showing to all of the validators is advantageous to the proposer, because the proposer does not have to guess what blocks the validators might have already seen. It is also advantageous for the protocol goals in general, because it improves the trade‑off between finalization latency and security.
Πbc changes from Πorigbc
Πbc block validity
Genesis bc‑block rule: For the genesis bc‑block we must have , and therefore .
A bc‑block is bc‑block‑valid iff all of the following hold:
- Inherited origbc rules: satisfies the corresponding origbc‑block‑validity rules.
- Valid context rule: is bft‑block‑valid.
- Extension rule: .
- Last Final Snapshot rule: .
- Finality depth rule: Define: Then either or .
Explain the definition of finality‑depth.
Explain the definition of finality‑depth.
The finality depth must be objectively defined, since it is used in a consensus rule. Therefore it should measure the height of relative to , which is an objectively defined function of , rather than relative to . (These will only differ for when node has just reorged, and only then in corner cases.)
Note that the Last Final Snapshot rule ensures that it is meaningful to simply use the difference in heights, since .
Πbc contextual validity
The consensus rule changes above are all non-contextual. Modulo these changes, contextual validity in is the same as in .
Πbc honest block production
An honest producer of a bc‑block must follow the consensus rules under block validity above. In particular, it must produce a stalled block if required to do so by the Finality depth rule.
To choose , the producer considers a subset of the tips of bft‑valid‑chains in its view: It chooses one of the longest of these chains, , breaking ties by maximizing , and if there is still a tie then by taking with the smallest hash.
The honest block producer then sets to .
An honest bc‑block‑producer must not use information from the BFT protocol, other than the specified consensus rules, to decide which bc‑valid‑chain to follow. The specified consensus rules that depend on have been carefully constructed to preserve safety of relative to . Imposing any additional constraints could potentially allow an adversary that is able to subvert , to influence the evolution of the bc‑best‑chain in ways that are not considered in the safety argument.
Why not choose T such that H ⌈1bc . context_bft ⪯bft bft‑last‑final(T )?
Why not choose T such that H ⌈1bc . context_bft ⪯bft bft‑last‑final(T )?
The effect of this would be to tend to more often follow the last bft‑block seen by the producer of the parent bc‑block, if there is a choice. It is not always possible to do so, though: the resulting set of candidates for might be empty.
Also, it is not clear that giving the parent bc‑block‑producer the chance to “guide” what bft‑block should be chosen next is beneficial, since that producer might be adversarial and the resulting incentives are difficult to reason about.
Why choose the longest C, rather than the longest bft‑last‑final(C )?
Why choose the longest C, rather than the longest bft‑last‑final(C )?
We could have instead chosen to maximize the length of . The rule we chose follows Streamlet, which builds on the longest notarized chain, not the longest finalized chain. This may call for more analysis specific to the chosen BFT protocol.
Why this tie‑breaking rule?
Why this tie‑breaking rule?
Choosing the bft‑chain that has the last final snapshot with the highest score, tends to inhibit an adversary’s ability to finalize its own chain if it has a lesser score. (If it has a greater score, then it has already won a hash race and we cannot stop the adversary chain from being finalized.)
For discussion of potentially unifying the roles of bc‑block producer and bft‑proposer, see What about making the bc‑block‑producer the bft‑proposer? in Potential changes to Crosslink.
At this point we have completed the definition of Crosslink 2. In Security Analysis of Crosslink 2, we will prove it secure.
Penalty for Failure to Defend
TODO: This is a paste of a Github ticket Add "penalty-for-failure-to-defend" concept to book #264 in order to ensure the text is committed into the revision.
Our primary conceptual framework for quantitative comparison between Crosslink security properties versus pure PoW or Tendermint-like BFT protocols is called "penalty for failure to defend" (aka ).
Key Top-Level Details
- PFDs can be specific to compromising specific properties; example: and are different (so there's no simple top-line number for a given protocol).
- is distinct from the confusing misnomer of "cost-to-attack" (because the penalty may accrue to non-attackers, and the nature of successful attacks is that they cost less than designers or security defense analyzers fail to anticipate).
- Neither or the ill-conceived "cost-to-attack" metrics are conclusive about financial feasibility, since they don't capture attacker revenue/profit.
- Some may be a "financial value gauge" such as in Tendermint protocols where a could slash a large bond at stake. Meanwhile others may be a "rate" such as in PoW where the penalty to miners is loss of a future revenue rate over time.
- The two different types of (gauge vs rate) cannot be directly compared for two reasons:
- The obvious reason that rates and gauges are different unit types.
- The less obvious reason that the trade-offs in compromise, response, and recovery dynamics are qualitatively incommensurate. (TODO: flesh out the nuance here.)
Security Analysis of Crosslink 2
This section is an almost direct paste from a section found in https://github.com/Electric-Coin-Company/tfl-book for the purposes of precisely committing to a (potentially incomplete, confusing, or inconsistent) precise set of book contents for a security design review. We believe this respects the license of the other repository.
This document analyzes the security of Crosslink 2 in terms of liveness and safety. It assumes that you have read The Crosslink 2 Construction which defines the protocol.
Liveness argument
First note that Crosslink 2 intentionally sacrifices availability if there is a long finalization stall.
This is technically independent of the other changes; you can omit the Finality depth rule and the protocol would still have security advantages over Snap‑and‑Chat, as well as being much simpler and solving its “spending from finalized outputs” issue. In that case the incentives to “pull” the finalization point forward to include new final bft‑blocks would be weaker, but honest bc‑block‑producers would still do it.
It would still be a bug if there were any situation in which failed to be live, though, because that would allow tail‑thrashing attacks.
Crosslink 2 involves a bidirectional dependence between and . The Ebb‑and‑Flow paper [NTT2020] argues in Appendix E ("Bouncing Attack on Casper FFG") that it can be more difficult to reason about liveness given a bidirectional dependence between protocols:
To ensure consistency among the two tiers [of Casper FFG], the fork choice rule of the blockchain is modified to always respect ‘the justified checkpoint of the greatest height [*]’ [22]. There is thus a bidirectional interaction between the block proposal and the finalization layer: blocks proposed by the blockchain are input to finalization, while justified checkpoints constrain future block proposals. This bidirectional interaction is intricate to reason about and a gateway for liveness attacks.
[*] The quotation changes this to “[depth]”, but our terminology is consistent with Ethereum here and not with [NTT2020]’s idiosyncratic use of “depth” to mean “block height”.
The argument is correct as far as it goes. The main reason why this does not present any great difficulty to proving liveness of Crosslink, is due to a fundamental difference from Casper FFG: in Crosslink 2 the fork‑choice rule of is not modified.
Let be the subset of bc‑blocks . Assume that is such that a bc‑block‑producer can always produce a block in .
In that case it is straightforward to convince ourselves that the additional bc‑block‑validity rules are never an obstacle to producing a new bc‑block in :
- The changes to the definition of contextual validity do not interfere with liveness, since they do not affect coinbase transactions, and therefore do not affect blocks in . That is, the bc‑block‑producer can always just omit non‑coinbase transactions that are contextually invalid.
- The Genesis bc‑block rule doesn’t apply to new bc‑blocks.
- The Valid context rule, Extension rule, and Last Final Snapshot rule are always satisfiable by referencing the same context bft‑block as the parent bc‑block.
- The Finality depth rule always allows the option of producing a stalled block, and therefore does not affect blocks in .
The instructions to an honest bc‑block‑producer allow it to produce a block in . Therefore, remains live under the same conditions as .
The additional bft‑proposal‑validity, bft‑block‑validity, bft‑finality, and honest voting rules are also not an obstacle to making, voting for, or finalizing bft‑proposals:
- Because is live, there will always be some point in time at which a fresh valid bc‑header chain that satisfies both the Linearity rule and the Tail confirmation rule exists for use in the field.
- If no fresh valid bc‑header chain is available, the Linearity rule and Tail confirmation rule allow an honest bft‑proposer to choose to be the same as in the previous bft‑block. So, if liveness of depends on an honest proposer always being able to make a proposal (as it does in adapted‑Streamlet for example), then this requirement will not be violated.
- The changes to voting are only requiring a vote to be for a proposal that could have been honestly proposed.
- The bft‑finality rules are unchanged from origbft‑finality.
Therefore, remains live under the same conditions as .
The only other possibility for a liveness issue in Crosslink 2 would be if the change to the constructions of or could cause either of them to stall, even when and are both still live.
However, liveness of and the Linearity rule together imply that at each point in time, provided there are sufficient honest bft‑proposers/validators, eventually a new bft‑block with a higher-scoring snapshot will become final in the context of the longest bft‑valid‑chain. make that more precise.
Because of the Extension rule, this new bft‑block must be a descendent of the previous final bft‑block in the context visible to bc‑block‑producers. Therefore, the new finalized chain will extend the old finalized chain.
Finally, we need to show that Stalled Mode is only triggered when it should be; that is, when the assumptions needed for liveness of are violated. Informally, that is the case because, as long as there are sufficient honest bc‑block‑producers and sufficient honest bft‑proposers/validators, the finalization point implied by the field at the tip of the bc‑best chain in any node’s view will advance fast enough for the finalization gap bound not to be hit. This depends on the value of relative to , the network delay, the hash rate of honest bc‑block‑producers, the number of honest bft‑proposers and the proportion of voting units they hold, and other details of the BFT protocol. more detailed argument needed, especially for the dependence on .
Safety argument
Not updated for Crosslink 2 below this point.
Discussion
Recall the definition of Assured Finality.
An execution of Crosslink 2 has Assured Finality iff for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , we have .
First we prove that Assured Finality is implied by Prefix Agreement of .
An execution of has Prefix Agreement at confirmation depth , iff for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , we have .
In an execution of Crosslink 2 for which the subprotocol has Prefix Agreement at confirmation depth , that execution has Assured Finality.
Proof: Suppose that we have times , and nodes , (potentially the same) such that is honest at time and is honest at time . Then, by the Local fin-depth lemma applied to each of node and node , there exist times at which node is honest and at which node is honest, such that and . By Prefix Agreement at confirmation depth , we have . Wlog due to symmetry, suppose . Then (by transitivity of ) and (as above), so by the Linear prefix lemma.
Then we prove that Assured Finality is also implied by Final Agreement of .
An execution of has Final Agreement iff for all bft‑valid blocks in honest view at time and in honest view at time , we have .
In an execution of Crosslink 2 for which the subprotocol has Final Agreement, that execution has Assured Finality.
Proof: Suppose that we have times , and nodes , (potentially the same) such that is honest at time and is honest at time . Then, by the Local fin-depth lemma applied to each of node and node , there exist times at which node is honest and at which node is honest, such that and . By Prefix Agreement at confirmation depth , we have . Wlog due to symmetry, suppose . Then (by transitivity of ) and (as above), so by the Linear prefix lemma.
By the Local ba-depth lemma, we have:
In any execution of Crosslink 2, for any confirmation depth and any node that is honest at time , there exists a time such that .
Renaming to and to in the definition of Prefix Consistency gives:
An execution of has Prefix Consistency at confirmation depth , iff for all times and all nodes , (potentially the same) such that is honest at time and is honest at time , we have that .
Since any node that is honest at time is also honest at time , and by transitivity of , we therefore have:
In any execution of Crosslink 2 that has Prefix Consistency at confirmation depth , for all times and all nodes , (potentially the same) such that is honest at time and is honest at time , we have that .
The Extension rule ensures that, informally, if a given node ’s view of its bc‑best‑chain at a depth of blocks does not roll back, then neither does its view of the bft‑final block referenced by its bc‑best‑chain, and therefore neither does its view of .
This does not by itself imply that all nodes are seeing the “same” confirmed bc‑best‑chain (up to propagation timing), or the same . If the network is partitioned and is subverted, it could be that the nodes on each side of the partition follow a different fork, and the adversary arranges for each node’s view of the last final bft‑block to be consistent with the fork it is on. It can potentially do this if it has more than one third of validators, because if the validators are partitioned in the same way as other nodes, it can vote with an additional one third of them on each side of the fork.
This is, if you think about it, unavoidable. doesn’t include the mechanisms needed to maintain finality under partition; it takes a different position on the CAP trilemma. In order to maintain finality under partition, we need not to be subverted (and to actually work!)
So what is the strongest security property we can realistically get? It is stronger than what Snap‑and‑Chat provides. Snap‑and‑Chat is unsafe even without a partition if is subverted. Ideally we would have a protocol with safety that is only limited by attacks “like” the unavoidable attack described above — which also applies to used on its own.
Proof of safety for LOGfin
In order to capture the intuition that it is hard in practice to cause a consistent partition of the kind described in the previous section, we will need to assume that the Prefix Agreement safety property holds for the relevant executions of . The structural and consensus modifications to relative to seem unlikely to have any significant effect on this property, given that we proved above that they do not affect liveness. ==TODO: that is a handwave; we should be able to do better, as we do for below.== So, to the extent that it is reasonable to assume that Prefix Agreement holds for executions of under some conditions, it should also be reasonable to assume it holds for executions of under the same conditions.
Recall that .
If , are bc‑valid blocks with , then .
Proof: Using the Extension rule, by induction on the distance between and .
Using the Prefix Lemma once for each direction, we can transfer the Prefix Agreement property to the referenced bft‑blocks:
In an execution of that has Prefix Agreement at confirmation depth , for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , we have .
Let be the sequence of transactions in the given chain , starting from genesis.
Recall that
Because takes the form , we have that . (This would be true for any well‑typed and .)
By this observation and the Prefix Agreement Lemma, we also have that, in an execution of Crosslink 2 where has the Prefix Agreement safety property at confirmation depth , for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , .
Because only considers previous state, ∘ must be a prefix-preserving map; that is, if then . Therefore:
In an execution of Crosslink 2 where has Prefix Agreement at confirmation depth , for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , .
Notice that this does not depend on any safety property of , and is an elementary proof. ([NTT2020, Theorem 2] is a much more complicated proof that takes nearly 3 pages, not counting the reliance on results from [PS2017].)
In addition, just as in Snap‑and‑Chat, safety of can be inferred from safety of , which follows from safety of . We prove this based on the Final Agreement property for executions of :
An execution of has the Final Agreement safety property iff for all origbft‑valid blocks in honest view at time and in honest view at time , we have .
The changes in relative to only add structural components and tighten bft‑block‑validity and bft‑proposal‑validity rules. So for any legal execution of there is a corresponding legal execution of , with the structural additions erased and with the same nodes honest at any given time. A safety property, by definition, only asserts that executions not satisfying the property do not occur. Safety properties of necessarily do not refer to the added structural components in . Therefore, for any safety property of , including Final Agreement, the corresponding safety property holds for .
By the definition of as above, in an execution of Crosslink 2 where has Final Agreement, for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , . Therefore, by an argument similar to the one above using the fact that ∘ is a prefix-preserving map:
In an execution of Crosslink 2 where has Final Agreement, for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , .
Proof of safety for LOGba
From the two Safety theorems and the Ledger prefix property, we immediately have:
Let be an arbitrary choice of confirmation depth for each node . Consider an execution of Crosslink 2 where either has Prefix Agreement at confirmation depth or has Final Agreement.
In such an execution, for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , either or .
Corollary: Under the same conditions, if wlog , then .
The above property is not as strong as we would like for practical uses of , because it does not say anything about rollbacks up to the finalization point, and such rollbacks may be of unbounded length. (Loosely speaking, the number of non‑Stalled Mode bc‑blocks after the consensus finalization point is bounded by , but we have also not proven that so far.)
As documented in the Model for BFT protocols section of The Crosslink 2 Construction):
For each epoch, there is a fixed number of voting units distributed between the players, which they use to vote for a bft‑proposal. We say that a voting unit has been cast for a bft‑proposal at a given time in a bft‑execution, if and only if is bft‑proposal‑valid and a ballot for authenticated by the holder of the voting unit exists at that time.
Using knowledge of ballots cast for a bft‑proposal that collectively satisfy a notarization rule at a given time in a bft‑execution, and only with such knowledge, it is possible to obtain a valid bft‑notarization‑proof . The notarization rule must require at least a two‑thirds absolute supermajority of voting units in ’s epoch to have been cast for . It may also require other conditions.
A voting unit is cast non‑honestly for an epoch’s proposal iff:
- it is cast other than by the holder of the unit (due to key compromise or any flaw in the voting protocol, for example); or
- it is double‑cast (i.e. there are two ballots casting it for distinct proposals); or
- the holder of the unit following the conditions for honest voting in , according to its view, should not have cast that vote.
An execution of has the one‑third bound on non‑honest voting property iff for every epoch, strictly fewer than one third of the total voting units for that epoch are ever cast non‑honestly.
By a well known argument often used to prove safety of BFT protocols, in an execution of Crosslink 2 where has the one‑third bound on non‑honest voting property (and assuming soundness of notarization proofs), any bft‑valid block for a given epoch in honest view must commit to the same proposal.
Proof (adapted from [CS2020, Lemma 1]): Suppose there are two bft‑proposals and , both for epoch , such that is committed to by some bft‑block‑valid block , and is committed to by some bft‑block‑valid block . This implies that and have valid notarization proofs. Let the number of voting units for epoch be . Assuming soundness of the notarization proofs, it must be that at least voting units for epoch , denoted as the set , were cast for , and at least voting units for epoch , denoted as the set , were cast for . Since there are voting units for epoch , must have size at least . In an execution of Crosslink 2 where has the one‑third bound on non‑honest voting property, must therefore include at least one voting unit that was cast honestly. Since a voting unit for epoch that is cast honestly is not double-cast, it must be that .
In the case of a network partition, votes may not be seen on both/all sides of the partition. Therefore, it is not necessarily the case that honest nodes can directly see double‑voting. The above argument does not depend on being able to do so.
Therefore, in an execution of Crosslink 2 for which has the one‑third bound on non‑honest voting property, for each epoch there will be at most one bft‑proposal‑valid proposal , and at least one third of honestly cast voting units must have been cast for it. Let be the (necessarily nonempty) set of nodes that cast these honest votes; then, for all at the times of their votes in epoch . (For simplicity, we assume that for each honest node there is only one time at which it obtains a successful check for the voting condition in epoch , which it uses for any votes that it casts in that epoch.)
Let be any bft‑block for epoch such that , where is some bft‑block‑valid block. Since , is bft‑block‑valid. So by the argument above, commits to the only bft‑proposal‑valid proposal for epoch , and was voted for in that epoch by a nonempty subset of honest nodes .
Let be any bc‑valid block. We have by definition: So, taking , each for of epoch in the result of satisfies for all in some nonempty honest set of nodes .
For an execution of Crosslink 2 in which has the Prefix Consistency property at confirmation depth , for every epoch , for every such , for every node that is honest at any time , we have . Let . Then, by transitivity of :
In an execution of Crosslink 2 where has the one‑third bound on non‑honest voting property and has the Prefix Consistency property at confirmation depth , every bc‑chain in (and therefore every snapshot that contributes to ) is, at any time , in the bc‑best‑chain of every node that is honest at time (where commits to at epoch and is the time of the first honest vote for ).
A similar (weaker) statement holds if we replace with , since the time of the first honest vote for necessarily precedes the time at which the signed is submitted as a bft‑block, which necessarily precedes . (Whether or not the notarization proof depends on the first honest vote for ’s proposal , it must depend on some honest vote for that proposal that was not made earlier than .)
Furthermore, we have
So in an execution of Crosslink 2 where has the Prefix Consistency property at confirmation depth , if node is honest at time then is also, at any time , in the bc‑best‑chain of every node that is honest at time .
If an execution of has the Prefix Consistency property at confirmation depth , then it necessarily also has it at confirmation depth . Therefore we have:
In an execution of Crosslink 2 where has the one‑third bound on non‑honest voting property and has the Prefix Consistency property at confirmation depth , every bc‑chain snapshot in (and therefore every snapshot that contributes to ) is, at any time , in the bc‑best‑chain of every node that is honest at time .
Sketch: we also need the sequence of snapshots output from fin to only be extended in the view of any node. In that case we can infer that the node does not observe a rollback in LOG_ba.
Recall that in the proof of safety for , we showed that in an execution of Crosslink 2 where (or ) has Final Agreement, for all times , and all nodes , (potentially the same) such that is honest at time and is honest at time , .
What we want to show is that, under some conditions on executions, ...
Disadvantages of Crosslink
More invasive changes
Unlike Snap‑and‑Chat, Crosslink 2 requires structural and consensus rule changes to both and . On the other hand, several of those changes are arguably necessary to fix a show‑stopping bug in Snap‑and‑Chat (not being able to spend some finalized outputs).
Finalization latency
For a given choice of , the finalization latency is higher. The snapshot of the BFT chain used to obtain is obtained from the block at depth on node ’s best chain, which will on average lead to a finalized view that is about blocks back (in ), rather than $\sigma_{\sac}}$ blocks in Snap‑and‑Chat. This is essentially the cost of ensuring that safety is given by the stronger of the safety of (at confirmations) and the safety of .
On the other hand, the relative increase in expected finalization latency is only $\frac{\mu + 1 + \sigma}{\sigma_{\sac}}},$ i.e. at most slightly more than a factor of 2 for the case $\mu = \sigma = \sigma_{\sac}}$.
More involved liveness argument
See the Liveness section above.
Every rule in Crosslink 2 is individually necessary
In order to show that Crosslink 2 is at a local optimum in the security/complexity trade‑off space, for each rule we show attacks on safety and/or liveness that could be performed if that rule were omitted or simplified.
Edit: some rules, e.g. the Linearity rule, only contribute heuristically to security in the analysis so far.
Design Analysis History
Throughout the prototypical and production-oriented development of Crosslink, we engage in analyses from third party experts on the safety and security of the design.
This section documents those reviews, their scopes, and the report results.
Mechanism Design Audit of Crosslink Zebra
2025-12-11
This design review audit was initiated as the Shielded Labs team approached the final stretch of their prototyping phase (see the Roadmap for the current status). This was useful timing between prototyping enough to have confidence the design is feasible for production versus too late in the process when the design is already "baked" to get a mechanism-design focused review of the consensus safety.
This design focused on the core safety and reliability of Crosslink as a consensus foundation, and not on other crucial concerns like privacy, usability, the code implementation, and so on.
Pre-Registration Process
Shielded Labs undertook a "pre-registration" process for this design audit by publicly committing to the scope and deliverables prior to engaging in the audit so that the public can verify we did not "shift the goal posts" after learning details from the auditor in order to influence the perception of the findings.
Precommitted Proposal for this audit.
Proposal: Mechanism Design Audit of Crosslink Zebra
Prepared for: Shielded Labs Duration: 1 week core analysis + light follow‑up outreach
Objective
Shielded Labs is designing and stewarding Crosslink v2 (Crosslink 2 consensus plus updated staking economics). This proposal covers a mechanism design–focused audit that:
- Evaluates the incentive structure faced by miners, finalizers, stakers, and the wider community.
- Assesses the Penalty for Failure to Defend (PFD) for key properties (safety, liveness, censorship resistance).
- Identifies likely equilibria and failure modes under realistic behavior.
- Produces clear recommendations to harden Crosslink v2 before or shortly after deployment.
- The work will be completed over one week, followed by targeted outreach so results can inform the broader Zcash ecosystem.
Scope
In scope: Crosslink Zebra as defined by Shielded Labs, specifically defined in this book in the Design chapter.
Questions to answer:
- What behaviors are rational for miners, finalizers, and stakers?
- What are the “good” and “bad” equilibria?
- How large is the effective PFD for safety, liveness, and censorship resistance?
- Where does the design rely on social courage instead of hard incentives?
- In general, what conditions are necessary to violate the security properties listed Security Properties
Out of scope
- Cryptographic soundness of Zcash primitives.
- Implementation bugs in node software.
- Detailed macro‑economic modeling of ZEC price or off‑chain markets.
- Privacy impacts on stakers or finalizers. Privacy protection is a top priority for Zcash generally, and a priority for Crosslink analyses in the future. However, for this initial audit we first want to focus on the general safety and reliability of the base consensus mechanism. Note that there are a set of constraints on the mechanism design which are present in order to provide privacy, and these must be satisfied for any alternatives or recommendations. These are described in our blog post Crosslink: Updated Staking Design.
Deliverables
By the end of the one‑week analysis:
- Mechanism Design Audit Report (10–15 pages)
- Role‑by‑role incentive analysis (miners, finalizers, stakers, community).
- PFD analysis for core properties under representative attack scenarios.
- Identified “bad equilibria” (e.g., PoS cartelization).
- Prioritized recommendations with concrete levers (e.g., minimal penalties, tweaks to incentives to bolster against bad outcomes, delegation tweaks, governance formalization).
- Executive Summary (2–3 pages)
- Non‑technical overview of risks, trade‑offs, and recommended changes, suitable for Shielded Labs leadership and partner orgs (ECC, ZF).
- Slide Deck (15–20 slides)
- Visual summary of findings for internal review and community calls.
- Outreach Draft
- Draft blog / forum post summarizing the results for the public Zcash community.
- Suggested agenda + talking points for a community call presenting the audit.
Work Plan & Timeline
Day 1 – Kickoff & Alignment
- 60–90 minute kickoff with Shielded Labs.
- Confirm canonical specs and design assumptions.
- Clarify constraints (e.g., “no protocol‑level slashing in V1”) and any specific questions.
- Finalize success criteria and deliverable format.
Days 2–4 – Mechanism Design Analysis
- Map incentives for each role (miners, finalizers, stakers, community), given:
- 40/40 issuance split;
- 5‑day epochs, 5–10 day unbonding;
- Emergency patch + hard‑fork constitution.
- Identify likely equilibria and failure modes (cartels, PoS capture, unbounded divergence between PoW progress and a stalled BFT subprotocol, etc.).
- Qualitative PFD modeling for safety, liveness, and censorship resistance; comparison to Zcash PoW‑only at the same issuance rate.
Day 5 – Recommendations & Drafts
- Translate analysis into concrete, ranked recommendations (high / medium / low impact & complexity).
- Produce draft audit report and executive summary.
Day 6 – Review & Finalization
- Share drafts with a small Shielded Labs review group.
- Incorporate feedback and finalize:
- Audit report
- Executive summary
- Slide deck
Day 7 – Outreach Prep
- Draft blog / forum post and call agenda.
- Finalize outreach materials in collaboration with Shielded Labs communications.
Outreach & Follow‑up
Within the same budget:
- One live presentation of findings (e.g., Zcash community call or internal Shielded Labs session).
- Asynchronous Q&A on the report (e.g., GitHub, forum thread) for 1–2 weeks after publication.
- Minor updates to slides and outreach text in response to initial feedback (no new analysis).
Crosslink Architecture Decision Records
We use an approach of documenting many design decisions during the implementation of zebra-crosslink via Architecture Decision Records, inspired by their use in upstream zebra. These are especially important for our Prototype-then-Productionize approach, since they record key decisions we should review for production readiness.
Currently ADRs are very rough and tracked on this zebra-crosslink ADR Google Sheet.
Moving forward we will begin to incorporate them into this codebase.
Crosslink Implementation
Protocol and Engineering Documentation
As we develop this specific instance, we are also aiming to produce generic implementation specification in two forms:
- The other is a set of lower-level Crosslink Implementation Requirements that engineers aim to adhere to in our implementation.
Implementation Approach
The high level roadmap has two main phases: Prototyping Phase and Productionization Phase.
Please see the Shielded Labs Crosslink Roadmap Timeline for current status, and our Blogpost for more detailed milestone plans.
During the Prototype Phase we often choose the "simplest" design alternative when faced with choices. Simplicity has multiple axes: easy to explain, easy to implement, easiest implications to understand, etc... We prioritize time to market, then easiness to explain.
We intend to revisit each of these documented decisions, and any new ones we discover, during Milestone 5 where we begin the transition from prototype to production-ready.
Style Conventions
This book uses the following set of style conventions:
- Newly introduced terms use
_markdown single-underscore format_which looks like This. - General emphasis uses
*markdown single-star format*which looks like This. Note: both newly introduced terms and general emphasis may render identically, but we never-the-less keep the source formatting distinction to improve editability, and in the future we should determine if we can consistently render them distinctly.