Consensus
Multi-validator Byzantine fault-tolerant consensus mechanism
Consensus Mechanism
Paraloom uses distributed consensus to verify zkSNARK proofs across multiple validators.
Key Parameters
| Parameter | Value | Description |
|---|---|---|
| Threshold | 7/10 (70%) | Validators needed for consensus |
| Timeout | 30 seconds | Max time per verification |
| Byzantine Tolerance | 3/10 | Max malicious validators |
| Consensus Latency | Under 1 second | Time to reach agreement |
Components
Withdrawal Verification Coordinator
Manages consensus rounds for withdrawal verification.
pub struct WithdrawalVerificationCoordinator {
pending_verifications: HashMap<String, WithdrawalConsensus>,
validators: Arc<RwLock<HashMap<NodeId, ValidatorInfo>>>,
reputation: Arc<ReputationTracker>,
threshold: ConsensusThreshold,
}Process:
- Receive withdrawal request
- Broadcast to all registered validators
- Collect verification votes
- Reach 7/10 consensus or timeout
- Execute if approved
Leader Selection
Deterministic leader selection using stake + reputation weighting.
Formula:
weight = (stake × 0.7) + (reputation × 0.3)
leader = argmax(hash(seed || validator_id) × weight)This ensures:
- Higher staked validators are more likely to lead
- Reputation influences selection (30% weight)
- Deterministic (all nodes agree on leader)
- Rotation on each round
Reputation Tracking
Automatic reputation updates based on verification behavior.
Bounds: 100 (minimum) to 10,000 (maximum)
| Action | Reputation Change |
|---|---|
| Correct vote | +10 |
| Consensus bonus | +5 |
| Incorrect vote | -50 |
| Timeout | -30 |
| Daily decay | -0.1% |
| New validator | Start at 1,000 |
Verification Flow
Request Received
Coordinator receives withdrawal request with:
- Nullifier
- Amount
- Recipient address
- zkSNARK proof
Broadcast to Validators
Request is broadcast via gossipsub to all validators in the network.
Independent Verification
Each validator:
- Verifies proof locally (~10ms)
- Checks nullifier not spent
- Validates merkle root
- Signs verification result
Collect Votes
Coordinator collects signed votes:
APPROVE- Proof is validREJECT- Proof is invalidTIMEOUT- No response
Consensus Decision
If 7/10 validators approve:
- Mark withdrawal as approved
- Submit to bridge for execution
If less than 7/10 approve:
- Mark as rejected
- Log disagreement for analysis
Byzantine Fault Tolerance
Threat Model
The system tolerates:
- 3/10 malicious validators - Can submit wrong votes
- Network partitions - Validators may be temporarily unreachable
- Crash failures - Validators may go offline
Safety Guarantees
| Property | Guarantee |
|---|---|
| Agreement | All honest validators agree on outcome |
| Validity | If 7/10 approve, proof is valid |
| Termination | Decision is reached within timeout |
Liveness
The system makes progress as long as:
- At least 7/10 validators are online
- Network allows message delivery
- Timeout hasn't expired
Multi-Validator Compute Verification
For compute jobs, the consensus model is slightly different:
2/3 Agreement Required:
- 3 validators execute same WASM job
- Results must match exactly
- 2/3 agreement for success
Why different threshold?
- Compute jobs are deterministic (WASM)
- Lower threshold for faster execution
- Still prevents single malicious validator
pub struct ComputeVerification {
job_id: String,
validators: Vec<NodeId>,
results: HashMap<NodeId, Vec<u8>>,
required_agreement: usize, // 2 of 3
}Consensus Messages
Verification Request
pub struct VerificationRequest {
request_id: String,
proof: Vec<u8>,
public_inputs: PublicInputs,
timestamp: u64,
}Verification Vote
pub struct VerificationVote {
request_id: String,
validator_id: NodeId,
vote: Vote, // Approve, Reject, Abstain
signature: Signature,
timestamp: u64,
}Consensus Result
pub struct ConsensusResult {
request_id: String,
outcome: Outcome, // Approved, Rejected, Timeout
votes: Vec<VerificationVote>,
final_timestamp: u64,
}Configuration
Validator Configuration
[consensus]
threshold = 7
total_validators = 10
verification_timeout = 30 # seconds
reputation_bounds = [100, 10000]
[leader_selection]
stake_weight = 0.7
reputation_weight = 0.3Network Configuration
[network]
gossipsub_heartbeat = 1 # second
peer_discovery = "mdns"
max_connections = 50