Skip to content

Commit

Permalink
Add DIP-0002
Browse files Browse the repository at this point in the history
  • Loading branch information
fed-franz committed Jan 17, 2025
1 parent 5cf3987 commit deebd2d
Showing 1 changed file with 78 additions and 13 deletions.
91 changes: 78 additions & 13 deletions dips/dip-0002.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,96 @@
---

## Abstract
A concise technical summary of the proposal.
This DIP proposes to remove instant finality and introduce a finality system based on the block iteration number.

## Motivation
Describes the issue being addressed and why the proposal is necessary.
Currently, an accepted block is marked as *final* (i.e. it cannot be reverted) if it's a first-iteration candidate.
This behavior is problematic since it can produce an unrecoverable split in some cases.

For instance, consider the following case: at height H, node A accepts a block B with iteration 0, while node B accepts block B' with iteration 1; then both nodes accept a valid successor with iteration 0. At this point, both nodes have finalized their block at height H, which means the two nodes are now irrevertibly on separate branches.

An occurrence of this situation has been shown in Issue [#1093](https://github.com/dusk-network/rusk/issues/1093) ("*Unrecoverable consensus state after a split event*").

To solve this issue, finalization logic must be updated taking forks into account.

## Technical Specification
Detailed description of the proposed changes, including protocol changes, data structures, API alterations, and cryptographic considerations.
This DIP introduces the definition of *Attestation*, *Consensus Label*, and new *Finality Rules*, which in turn introduce the definition of *Instant Finality*, and *Rolling Finality*.

### Attestations
An *Attestation* is a proof of a quorum reached in a specific iteration. It consists of two aggregated signatures (one for the Validation step and one for the Ratification step) and the bitsets of the votes with respect to the corresponding committees.

Depending on wether the result of the iteration was Success (Agreement) or Fail (Nil), the Attestation can be a *Success Attestation* or a *Fail Attestation*, respectively.

### Failed Iterations field
A $FailedIterations$ field is added to the block header.
The field is an array of Attestations, with each position corresponding to an iteration.

An empty position implies there is no information on whether a quorum was reached for the corresponding iteration.

### Consensus State Labels
Each block is locally labeled by the node to indicate its state with respect to consensus.
The following labels are introduced:

- *Accepted*: the block has been accepted (i.e., it has a Success Attestation) but it has iteration $I>0$ and some of the lower iterations have an *Unknown* result (i.e., no known quorum has been reached);
- *Attested*: the block has been accepted at iteration $0$ or it has a valid Fail Attestation for all previous iterations;
- *Final*: the block is *Attested*, and all previous blocks are labeled as *Final*.

### Finality Rules
Each block can be finalized in two ways: *instant finality* and *rolling finality*.

An accepted block B has instant finality if (1) it's labeled as *Attested* and (2) its parent block is labeled as *Final*.

Blocks labeled as *Accepted* can be finalized with the so-called rolling finality.
Rolling finality refers to the finalization of a block by means of accepting other blocks on top of it (this is similar to the concept of *confirmation* in other blockchains).

Specifically, an *Accepted* block is labeled as *Final* if it's followed by $5$ consecutive *Attested* blocks.
If a block is finalized in this way, all previous non-final blocks are also finalized.


## Rationale
Discussion on the decision-making process and trade-offs considered.
There are two reasons a block can be reverted: (1) there is a lower-iteration candidate for the same round that reached a Success Quorum, or (2) a previous block is reverted.
The finalization process proposed by this DIP hinges on the probability of these two events to occur for a given block.
In particular, it aims at finalizing a block only if its probability of being reverted is negligible.

## Backwards Compatibility
Analysis of how the proposal interacts with existing features or might affect backward compatibility.
With respect to (1), it can be noted that a block at iteration $I=0$ cannot be reverted by any lower-iteration block. Nonetheless, this is also true for blocks with iteration $I>0$ when all previous iterations have reached a Fail Quorum. The *Attested* label represents both such cases.
In this respect, the introduction of Attestations, and particularly Fail Attestations, is aimed at tracking the result of previous iterations (w.r.t. the candidate iteration) in a provable manner. By including Fail Attestations in the block header, it is possible to label a new block in a deterministc way.

On the other hand, labeling a block as *Accepted* represents a situation in which there *might* be (since the Attestationis missing, the iteration result is unknown) a lower-iteration block that reached a Success Quorum; since lower-iteration blocks have higher priority, receiving such a block would replace the Accepted one.

A block is marked as *Final* if it's first-iteration and its parent block is also Final. In fact, such a block cannot possibly be reverted, since its predecessor cannot be reverted and there are no lower-iteration blocks in the same round.

The finalization of Accepted blocks rely on *confirmations* from successive blocks. This is based on the observation that each block added on top of an Accepted one inherently proves that the network is building on top it.
In particular, each successor of an Accepted block:
- increases the set of provisioners that included the block in its chain;
- increases the set of provisioners working on the branch to which the Accepted block belong;
- decreases the set of provisioners that might have accepted a better block than the Accepted one.
Therefore, each successor reduces the probability of reverting the Accepted block.

The concept of *Rolling Finality* is based on the above observations, but only leverages consecutive Attested blocks. In fact, Accepted blocks cannot be used to mark a block as Final. To understand this, consider the following example: a block B is marked as Final after accepting 5 successors, the first of which is marked as Accepted; then this Accepted block is reverted (along with all other successors); at this point, B's label has to change back to Accepted (which contradicts the fact of it being Finalized, that is, not revertable).

The threshold of 5 consecutive blocks has been chosen to be big enough to be considered as stable (although more precise probability calculations are due to properly choose this value).

## Test Cases
Practical examples and test cases for validating the proposed changes.
Finally, note that only Attestations included in the block header are considered, making the finalization process deterministic.
Due to this, nodes with the same blocks will have the same consensus state labels (and hence the same finalized blocks).


## Backwards Compatibility
While State Labels and Finality Rules are local changes, and hence backward compatible, the introduction of the $FailedIterations$ field in the block header makes this DIP a breaking change.

## Implementation
Reference to the implementation code; this may include links to PRs in external repositories.
- https://github.com/dusk-network/rusk/issues/1116: Add failed_iterations fields
- https://github.com/dusk-network/rusk/issues/1158: Introduce block "Consensus State" labels
- https://github.com/dusk-network/rusk/issues/1118: Change block's finality definition


## Security Considerations
Assessment of potential security implications and how they are addressed.
N/A

## References
Links to any related documents, discussions, or other relevant materials.
N/A

---

## Updates (Optional)
Documenting significant changes or updates to the proposal post-acceptance.
## Updates
- In accordance with the new finality definition, lower-round blocks can now be reverted (see [Allow fallback to lower-round blocks](https://github.com/dusk-network/rusk/issues/1168))
- Finality rules have been modified by the implementation of [Incremental Rolling Finality](https://github.com/dusk-network/dips/issues/11)

0 comments on commit deebd2d

Please sign in to comment.