Proof Lifecycle

Proof Lifecycle - From Generation to Verification

This document describes the complete lifecycle of zero-knowledge proofs in the Roru Protocol, from generation through verification to finalization.

Lifecycle Overview

Stages

The proof lifecycle consists of five main stages:

  1. Witness Construction: Building the witness from private inputs

  2. Circuit Execution: Running the zero-knowledge circuit

  3. Proof Generation: Creating the cryptographic proof

  4. Proof Verification: Verifying the proof validity

  5. State Update: Updating the shielded state

Stage 1: Witness Construction

Witness Components

Witness Structure:

pub struct Witness {
    pub input_notes: Vec<Note>,
    pub output_notes: Vec<Note>,
    pub input_randomness: Vec<Scalar>,
    pub output_randomness: Vec<Scalar>,
    pub nullifier_keys: Vec<Scalar>,
    pub merkle_paths: Vec<MerklePath>,
    pub balance: u64,
    pub fee: u64,
}

Construction Process

Steps:

  1. Select input notes

  2. Generate output notes

  3. Collect randomness values

  4. Build Merkle paths

  5. Calculate balance

  6. Assemble witness

Construction Code:

fn construct_witness(
    inputs: &[Note],
    outputs: &[Note],
    state: &StateTree,
) -> Witness {
    let mut merkle_paths = Vec::new();
    for note in inputs {
        let path = state.get_merkle_path(note.index);
        merkle_paths.push(path);
    }
    
    Witness {
        input_notes: inputs.to_vec(),
        output_notes: outputs.to_vec(),
        input_randomness: inputs.iter().map(|n| n.randomness).collect(),
        output_randomness: outputs.iter().map(|n| n.randomness).collect(),
        nullifier_keys: inputs.iter().map(|n| n.nullifier_key).collect(),
        merkle_paths,
        balance: calculate_balance(inputs, outputs),
        fee: calculate_fee(inputs.len(), outputs.len()),
    }
}

Stage 2: Circuit Execution

Circuit Structure

Circuit Components:

  • Input validation

  • Output validation

  • Balance verification

  • Nullifier generation

  • Merkle path verification

  • Authorization check

Execution Process

Execution Steps:

  1. Load witness into circuit

  2. Execute input constraints

  3. Execute output constraints

  4. Execute balance constraints

  5. Execute nullifier constraints

  6. Execute Merkle path constraints

  7. Generate constraint system

Execution Code:

fn execute_circuit(witness: &Witness) -> ConstraintSystem {
    let mut cs = ConstraintSystem::new();
    
    // Input constraints
    for (i, note) in witness.input_notes.iter().enumerate() {
        add_input_constraints(&mut cs, note, &witness.merkle_paths[i]);
    }
    
    // Output constraints
    for note in &witness.output_notes {
        add_output_constraints(&mut cs, note);
    }
    
    // Balance constraints
    add_balance_constraints(&mut cs, &witness);
    
    // Nullifier constraints
    add_nullifier_constraints(&mut cs, &witness);
    
    cs
}

Stage 3: Proof Generation

Generation Process

Generation Steps:

  1. Load proving key

  2. Execute circuit

  3. Generate proof using Groth16

  4. Serialize proof

  5. Verify proof locally

Generation Code:

fn generate_proof(witness: &Witness, proving_key: &ProvingKey) -> Proof {
    let constraint_system = execute_circuit(witness);
    let proof = groth16::prove(proving_key, constraint_system, witness)?;
    let serialized = proof.serialize();
    
    // Local verification
    verify_proof_locally(&proof, &verifying_key)?;
    
    Proof {
        proof: serialized,
        public_inputs: extract_public_inputs(witness),
    }
}

Proof Format

Proof Structure:

pub struct Proof {
    pub a: Point,        // Proof component A
    pub b: Point,        // Proof component B
    pub c: Point,        // Proof component C
    pub public_inputs: Vec<Scalar>,  // Public inputs
}

Stage 4: Proof Verification

Verification Process

Verification Steps:

  1. Load verifying key

  2. Deserialize proof

  3. Extract public inputs

  4. Verify pairing equation

  5. Check all constraints

Verification Code:

fn verify_proof(proof: &Proof, verifying_key: &VerifyingKey, state: &State) -> bool {
    // Verify pairing equation
    let pairing_check = pairing(proof.a, proof.b) == 
        pairing(proof.c, verifying_key.gamma) * 
        pairing(public_inputs, verifying_key.delta);
    
    if !pairing_check {
        return false;
    }
    
    // Verify public inputs match state
    verify_public_inputs(&proof.public_inputs, state)?;
    
    true
}

Batch Verification

Batch Process:

  1. Collect multiple proofs

  2. Batch verify using pairing

  3. Verify all public inputs

  4. Check consistency

Batch Code:

fn batch_verify(proofs: &[Proof], verifying_key: &VerifyingKey) -> bool {
    let mut batch_a = Vec::new();
    let mut batch_b = Vec::new();
    let mut batch_c = Vec::new();
    
    for proof in proofs {
        batch_a.push(proof.a);
        batch_b.push(proof.b);
        batch_c.push(proof.c);
    }
    
    batch_pairing_verify(&batch_a, &batch_b, &batch_c, verifying_key)
}

Stage 5: State Update

Update Process

Update Steps:

  1. Verify proof

  2. Check nullifiers

  3. Add new notes to tree

  4. Add nullifiers to set

  5. Update state root

  6. Publish update

Update Code:

fn update_state(
    state: &mut StateTree,
    proof: &Proof,
    nullifiers: &[Nullifier],
    new_notes: &[Note],
) -> Result<StateRoot> {
    // Verify proof
    if !verify_proof(proof, &verifying_key, state) {
        return Err(Error::InvalidProof);
    }
    
    // Check nullifiers
    for nullifier in nullifiers {
        if state.nullifier_set.contains(nullifier) {
            return Err(Error::DoubleSpend);
        }
    }
    
    // Add new notes
    for note in new_notes {
        let commitment = commit_note(note);
        state.insert_commitment(commitment)?;
    }
    
    // Add nullifiers
    for nullifier in nullifiers {
        state.nullifier_set.insert(nullifier);
    }
    
    // Update root
    let new_root = state.update_root();
    Ok(new_root)
}

Proof Storage

Storage Format

Storage Structure:

  • Proof data: Serialized proof

  • Metadata: Proof metadata

  • Timestamp: Creation time

  • Status: Verification status

Storage Locations

Storage Options:

  • Local device storage

  • Encrypted storage

  • Backup storage

  • Network storage (encrypted)

Proof Transmission

Transmission Format

Transmission Structure:

  • Proof bundle

  • Encryption

  • Signature

  • Metadata

Transmission Channels

Channels:

  • Network: Encrypted HTTP/WebSocket

  • Offline: NFC/Bluetooth/QR

  • Direct: Device-to-device

Error Handling

Error Types

Proof Errors:

  • Invalid witness

  • Circuit execution failure

  • Proof generation failure

  • Verification failure

  • State update failure

Error Recovery

Recovery Strategies:

  • Retry proof generation

  • Validate inputs

  • Check state consistency

  • Reconstruct witness

Performance

Generation Time

Typical Times:

  • Witness construction: <100ms

  • Circuit execution: 1-3 seconds

  • Proof generation: 1-2 seconds

  • Total: 2-5 seconds

Verification Time

Typical Times:

  • Proof deserialization: <10ms

  • Verification: <100ms

  • State update: <50ms

  • Total: <200ms

Security

Security Properties

Proof Security:

  • Zero-knowledge property

  • Soundness

  • Completeness

  • Non-malleability

Security Guarantees

Guarantees:

  • Cannot forge proofs

  • Cannot extract witness

  • Cannot modify proofs

  • Cryptographically secure

Conclusion

The proof lifecycle provides:

  • Completeness: All stages covered

  • Security: Cryptographic guarantees

  • Efficiency: Optimized operations

  • Reliability: Error handling

  • Privacy: Zero-knowledge property

Understanding the lifecycle is essential for proof system development.

Last updated