Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 36 additions & 44 deletions src/Nethermind/Nethermind.Xdc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,14 @@ DateTime RoundStarted // Round start time

**3-Chain Finalization Rule**:
```
Block N-2 (Finalized) ←─ Block N-1 ←─ Block N (Current)
QC(N-2) QC(N-1) QC(N)
Block N-2 (Finalized) ←─ Block N-1 ←─ Block N (Current) ←─ Incoming QC
QC(N-2) QC(N-1)

Finalization requires:
- An incoming QC
- 3 consecutive blocks
- 3 consecutive rounds (no gaps)
- Valid QC chain
- Valid Block and QC chain
```

---
Expand Down Expand Up @@ -241,21 +242,11 @@ Can vote if ALL of:

**Purpose**: Manage validator set transitions at epoch boundaries

**Epoch Structure**:
```
Epoch N Epoch N+1
├────────────────────┤ ├────────────────────┤
│ │ │ │
│ Regular Blocks │ │ Regular Blocks │
│ (EpochLength-Gap) │ │ │
│ │ │ │
├────────────────────┤ │ │
│ │ │ │
│ Gap (Snapshot) │────▶│ New Validators │
│ Block N*EpochLen │ │ Applied Here │
│ -Gap │ │ │
│ │ │ │
└────────────────────┘ └────────────────────┘
**Gap Number Detection**:
```csharp
IsTimeforSnapshot(blockNumber, spec):
- Is it a gap block? → TRUE
Pull master node candidates from master node contract and save a snapshot
```

**Epoch Switch Detection**:
Expand Down Expand Up @@ -287,9 +278,9 @@ class Snapshot {
```
Block Number Snapshot Usage
─────────────────────────────────────────────────────────
0 (Genesis) → GenesisMasterNodes → Epoch 0-899
900-Gap=850 → Candidates from block → Epoch 900-1799
1800-Gap=1750 → Candidates from block → Epoch 1800-2699
0 (Genesis) → GenesisMasterNodes → Round 0-899
900-Gap=450 → Candidates from block → Round 900-1799
1800-Gap=1350 → Candidates from block → Round 1800-2699
...
```

Expand Down Expand Up @@ -404,7 +395,7 @@ Phase 4: QC AGGREGATION
Phase 5: QC COMMITMENT
───────────────────────
┌────────────────────────────────┐
CommitCertificate()
CommitQC()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe they didn't agree with the use of "commit" here and suggested "process" instead . Anyway, on the Happy Path chart below, it has been changed to Process QC, so I would say to decide on one and have it both be the same

│ 1. Update HighestQC │
│ 2. Check 3-chain rule │
│ 3. Finalize grandparent? │
Expand Down Expand Up @@ -707,14 +698,14 @@ Round Leader Index Leader
Commit grandparent when three consecutive rounds exist:

```
CommitBlock(proposedBlock, proposedRound, proposedQC):
CommitBlock(proposedBlock, proposedRound, proposedQC, incomingQC):
1. parent = proposedBlock.parent
2. grandparent = parent.parent

3. Check conditions:
✓ proposedRound - 1 == parent.round
✓ proposedRound - 2 == grandparent.round
proposedRound > grandparent.round + 1
HighestCommitBlock.round < grandparent.round and HighestCommitBlock.number < grandparent.number

4. If all pass:
HighestCommitBlock = grandparent
Expand All @@ -727,12 +718,12 @@ Round N-2 Round N-1 Round N
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│Block B │◀───────│Block C │◀───────│Block D │
│Block B │◀───────│Block C │◀───────│Block D │◀───────QC(D)
│QC(A) │ │QC(B) │ │QC(C) │
└────────┘ └────────┘ └────────┘
└─── FINALIZED when Block D commits
└─── FINALIZED when Block D and incomingQC calls CommitBlock()
```

---
Expand All @@ -742,12 +733,13 @@ Round N-2 Round N-1 Round N
Prevent conflicting votes:

```
VerifyVotingRules(block, round, parentQC):
// QC is decoded from block's extraData
VerifyVotingRules(block, round, QC):
1. CurrentRound > HighestVotedRound? ✓ No double voting
2. block.round == CurrentRound? ✓ Right round
3. LockQC safety:
IF LockQC exists:
- parentQC.round > LockQC.round OR
- QC.round > LockQC.round OR
- block extends LockQC ancestor
ELSE:
- Always safe
Expand Down Expand Up @@ -776,7 +768,7 @@ Calculate next validator set:
CalculateNextEpochMasternodes(blockNumber, parentHash):
1. Load previous snapshot (gap block)
2. Get candidates from snapshot
3. Calculate penalties (forensics)
3. Calculate penalties
4. masterodes = candidates - penalties
5. Enforce maximum: Take(MaxMasternodes)
6. Return (masternodes, penalties)
Expand All @@ -786,9 +778,9 @@ CalculateNextEpochMasternodes(blockNumber, parentHash):
```
Block Number Action
─────────────────────────────────────────
0-849 Normal blocks
850 (Gap) Store snapshot with candidates
851-899 Normal blocks
0-449 Normal blocks
450 (Gap) Store snapshot with candidates
451-899 Normal blocks
900 (Epoch switch) Apply new validators from snapshot
901-1749 Use new validator set
```
Expand Down Expand Up @@ -899,7 +891,7 @@ Gap: 450 // Snapshot before epoch end
SwitchBlock: <configured> // V2 activation block
MaxMasternodes: 108 // Maximum validators
CertThreshold: 0.67 // 2/3 quorum
TimeoutPeriod: 4000ms // Round timeout
TimeoutPeriod: 10000ms // Round timeout
MinePeriod: 2000ms // Minimum block time
TimeoutSyncThreshold: 3 // SyncInfo after N timeouts
```
Expand All @@ -914,7 +906,7 @@ V2ConfigParams[] {
SwitchRound: 0,
MaxMasternodes: 108,
CertThreshold: 0.67,
TimeoutPeriod: 4000,
TimeoutPeriod: 10000,
MinePeriod: 2000
},
{
Expand Down Expand Up @@ -967,11 +959,11 @@ T+0.1s XdcBlockProducer Build block
T+0.5s XdcSealer Sign block
T+0.6s XdcBlockTree Suggest block
T+0.7s Validator Nodes Receive block
└─▶ Validate Check QC, seal
└─▶ Validate Check QC
T+0.9s VotesManager Cast votes
T+1.5s VotesManager Threshold reached
└─▶ Create QC Aggregate signatures
T+1.6s QCManager Commit QC
T+1.6s QCManager Process QC
├─▶ Update HighestQC
├─▶ Check 3-chain
└─▶ Finalize grandparent
Expand All @@ -984,16 +976,16 @@ T+1.7s XdcConsensusContext SetNewRound(N+1)
Time Component Action
──────────────────────────────────────────────────
T+0s Round N starts
T+4s TimeoutTimer Expires
T+10s TimeoutTimer Expires
└─▶ OnCountdownTimer
T+4.1s TCManager SendTimeout
T+10.1s TCManager SendTimeout
└─▶ Sign timeout
T+4.5s TCManager Collect TCs
T+5s TCManager Threshold reached
T+10.5s TCManager Collect TCs
T+11s TCManager Threshold reached
└─▶ Create TC
T+5.1s TCManager ProcessTC
T+11.1s TCManager Process TC
└─▶ Update HighestTC
T+5.2s XdcConsensusContext SetNewRound(N+1)
T+11.2s XdcConsensusContext SetNewRound(N+1)
```

---
Expand Down Expand Up @@ -1044,7 +1036,7 @@ Test: Timeout & Recovery
Setup: 5 validators, leader crashes
Steps:
1. Leader fails to propose
2. Nodes timeout after 4s
2. Nodes timeout after 10s
3. Form TC with 2f+1 timeouts
4. Advance round
5. New leader proposes
Expand Down Expand Up @@ -1102,7 +1094,7 @@ public bool VerifyVotingRules(...) {
**Solution**: Snapshot stored at Gap block before epoch end

```
Block 850 (Gap): Store snapshot with candidates
Block 450 (Gap): Store snapshot with candidates
Block 900 (Switch): Load snapshot, calculate masternodes
masterodes = snapshot.candidates - penalties
```
Expand Down