This tutorial explains the core philosophy of PORTO, why it exists, and how to use it for real-world decentralized orchestration.
Traditional blockchains and Layer-2 solutions face a Throughput-Privacy Trilemma. If you want high throughput, you usually sacrifice privacy (monolithic sequencers see everything). If you want privacy, you usually sacrifice speed (Zero-Knowledge proof generation is computationally expensive).
PORTO solves this by combining two powerful technologies:
- Erlang/OTP Actor Model: For massive, fault-tolerant parallelism.
- Aleo/Leo Zero-Knowledge Layer: For mathematical confidentiality.
- Confidential Compliance: Prove you followed a rule (e.g., "I'm under my carbon quota") without revealing the private data (the exact emission numbers).
- Scalable Parallelism: Instead of one sequencer generating one proof at a time, PORTO spawns an "Actor" for every resource. These actors generate ZK proofs concurrently across all available CPU cores.
- Resilience ("Let it Crash"): If a cryptographic proof fails (meaning a rule was violated), the actor crashes. The supervision tree handles the failure, ensuring the rest of the system remains stable.
PORTO sits between your private data and the public Aleo blockchain.
- The Actor (Erlang): An isolated process that holds the "Private State" of a resource.
- The Circuit (Leo): A ZK program that defines the "Cryptographic Truth" or rules.
- The Bridge: PORTO's engine that pipes the Actor's state into the Circuit to generate a proof.
Write a Leo program in a circuits/ directory. For example, a simple eligibility check:
// circuits/src/main.leo
program eligibility.aleo {
transition verify_score(private score: u32, public threshold: u32) -> bool {
return score >= threshold;
}
}In the PORTO shell, spawn an actor to track a specific entity. Each actor is responsible for its own state and its own proofs.
% Spawn an actor for "User-42"
porto_core_app:track_resource("User-42").When the entity's state changes, PORTO triggers the Leo circuit.
- If the rule is met: A ZK proof is generated, and the state update is committed to the local Mnesia database.
- If the rule is violated: The Leo circuit returns a non-zero exit code, the Erlang actor crashes, and the update is rejected.
You can do this via the HTTP API:
curl -X POST http://localhost:8080/track \
-H "Content-Type: application/json" \
-d '{"resource_id": "User-42", "data": {"score": 750}}'Explore the examples/ directory to see PORTO in action:
- Equitable Allocation: Prove a fair distribution of resources without revealing participant identities.
- Sustainability Quota: Track resource usage against a public ceiling while keeping individual usage private.
- Service Eligibility: Verify user qualifications against a threshold without accessing sensitive personal scores.
- Monitoring: Use Erlang's built-in tools (like
observer:start()) to watch your actors scale across cores. - Cleanup: If you change your Leo circuits, run
./cleanup.shto clear old build artifacts before recompiling. - Integration: In a production setup, the proofs generated by PORTO would be submitted to the Aleo network to update global state.