Kontor Proof-of-Retrievability (PoR)
⚠️ WARNING: This code is unaudited and experimental. Use at your own risk.
This project implements a Proof-of-Retrievability (PoR) system designed to provide economically enforceable guarantees that Storage Nodes are actually storing the data they have committed to. It is a core component for decentralized storage metaprotocols where a network of Indexers (Verifiers) must continuously audit Storage Nodes (Provers).
The system uses Nova recursive SNARKs via Microsoft's nova-snark library to generate constant-size (~10 kB) cryptographic proofs that a prover possesses a specific set of data. These proofs are efficient to verify (~30ms), making it feasible to enforce storage guarantees at scale.
Core Capabilities
- Partition files into fixed 31-byte symbols for direct field element encoding.
- Apply multi-codeword Reed-Solomon (GF(2^8)) for fault tolerance.
- Generate Poseidon Merkle trees over all symbols (data + parity).
- Create recursive SNARKs proving possession of randomly sampled symbols.
- Compress proofs to constant ~10 kB size regardless of file count or challenge count.
- Support dynamic circuit parameters with in-memory caching.
- Reconstruct original files from partial symbol availability (≥90% per codeword).
Performance Characteristics
- Proof Size: ~10 kB (constant across challenge count and file set within a shape).
- Verification Time: ~50 ms for compressed SNARK verification.
- Proving Time: Approximately linear in the number of recursive steps.
API Reference
The high-level API centers on a PorSystem object, which consolidates setup, proving, and verification concerns.
Core Interface
// Construction
Usage Example
A complete example demonstrating the API workflow:
use ;
use FileLedger;
// 1. Prepare the file with fixed Reed-Solomon encoding (231 data + 24 parity symbols per codeword)
let my_data = b"This is a test file for the PoR system.";
let = prepare_file.unwrap;
// 2. Create ledger and add the file
let mut ledger = new;
ledger.add_file.unwrap;
// 3. Create PorSystem and challenge
let system = new;
let num_challenges = 5;
let seed = from; // Deterministic seed
let challenge = new;
// 4. Generate proof using the unified API
let files = vec!;
let proof = system.prove.unwrap;
// 5. Verify the proof
let is_valid = system.verify.unwrap;
assert!;
println!;
CLI & Simulation
The project includes a CLI that simulates storage node operations with heterogeneous file sizes, staggered challenges, and multi-file proof aggregation.
Usage
# Default: small demo (100 files in ledger, node stores 10, 5 challenges)
# Large-scale test with memory profiling
Flags
--total-files-in-ledger <N>: Network size (default: 100).--files-stored-by-node <N>: Files this node stores (default: 10).--challenges-to-simulate <N>: Challenges to batch (default: 5).--file-size-distribution <TYPE>: "uniform", "mixed", or "large-heavy" (default: mixed).--no-verify: Skip verification phase.--profile-memory: Track peak memory usage.-v,-vv: Increase verbosity (debug/trace).
Benchmark Suite
Run performance benchmarks with statistical analysis and CI integration via CodSpeed:
# Run all benchmarks locally
# For CI/CD integration with CodSpeed (optional):
Development
Test Suite
Run the extensive unit and integration test suite:
Git Hooks
Enable the pre-push hook to automatically run formatting, clippy, tests, and security audits:
Errors and Failure Modes
Key error variants surfaced at API boundaries (see KontorPoRError):
InvalidInput,InvalidChallengeCount,ChallengeMismatch(e.g., non-uniformnum_challengesacross the batch).FileNotFound,FileNotInLedger,MetadataMismatch.MerkleTree,Circuit,Snark.Serialization,IO.
Documentation
- Protocol Specification - Network protocol, glossary, data types, and challenge lifecycle
- Library Architecture - Implementation details and circuit design