General Questions
What is Leo?
Leo is a statically-typed programming language designed for building private applications on the Aleo blockchain. It compiles to Aleo instructions (bytecode) that execute as zero-knowledge proofs, enabling developers to create applications where computation is verified without revealing the underlying data.How is Leo different from other smart contract languages?
Privacy by Default:- Leo emphasizes privacy through zero-knowledge proofs
- Records provide private state management
- Computations can be verified without revealing inputs
- All types must be explicitly declared
- No implicit type coercion
- Compile-time type checking prevents many runtime errors
- Leo compiles to constraint systems
- Every operation becomes part of a mathematical proof
- Proofs are verified on-chain
Is Leo production-ready?
Leo is currently in active development. While functional and tested, it’s considered in an alpha/beta stage. Breaking changes may occur between versions. Production use should be carefully evaluated based on your risk tolerance.What blockchain does Leo run on?
Leo programs compile to Aleo instructions that execute on the Aleo blockchain. Aleo is a Layer 1 blockchain specifically designed for private applications using zero-knowledge proofs.Language Features
Does Leo support loops?
Yes, but with an important caveat: all loops must be unrollable at compile time. This is because zero-knowledge circuits cannot have dynamic control flow.Can I use recursion?
No. Leo does not support recursive function calls because:- Circuits cannot have unbounded depth
- All computation must be deterministic at compile time
- Recursion would create circuits of unknown size
What about dynamic arrays?
Leo requires array sizes to be known at compile time:Does Leo have strings?
Yes, but with limitations:- Strings are primarily for debugging
- Limited string manipulation
- Not typically stored on-chain
- No string concatenation
Can I use floating-point numbers?
No. Leo does not support floating-point arithmetic because:- ZK circuits work with finite fields
- Floating-point is non-deterministic
- Precision issues would affect proof verification
- Use fixed-point arithmetic with integers
- Scale values by powers of 10
- Use field elements for modular arithmetic
Records and Privacy
What are records?
Records are private data structures in Leo:- Private by default (encrypted on-chain)
- Owner-controlled (only owner can spend)
- Support UTXO-like model
- Enable private state management
How do records differ from structs?
| Feature | Record | Struct |
|---|---|---|
| Privacy | Private (encrypted) | Depends on usage |
| Owner field | Required | Optional |
| Storage | Off-chain (user holds) | In-memory only |
| Use case | Private state | Data organization |
Can I have public records?
No. Records are always private by default. If you need public state, use mappings instead:What happens to spent records?
When a record is consumed (used as input to a function), it’s marked as spent and cannot be used again. This prevents double-spending.Mappings and On-Chain State
When should I use mappings vs records?
Use Mappings when:- You need public, transparent state
- Multiple parties need to read the same data
- Global state tracking is required
- Compliance requires public audit trails
- Privacy is important
- Users should control their own state
- You want to hide transaction amounts
- UTXO-like model fits your use case
Can I access mappings in regular functions?
No. Mapping operations (get, set, remove) are only available in finalizer functions:Are mappings expensive?
Yes, relatively. Mapping operations:- Update on-chain state
- Require finalization
- Increase transaction costs
- Are publicly visible
Compilation and Execution
How does Leo compile?
The compilation pipeline:- Lexer: Tokenizes source code
- Parser: Builds syntax tree
- Type Checker: Validates types and semantics
- Compiler Passes: Optimizations, loop unrolling, etc.
- Code Generation: Produces Aleo instructions
- Synthesis: Creates constraint system (during proving)
What are finalizers?
Finalizers are functions that execute on-chain after proof verification:- Execute after proof verification
- Can access and modify mappings
- Can use
block.heightand other on-chain data - Can fail via assertions (rejecting the transaction)
Why do proofs take so long to generate?
Proof generation involves:- Computing the entire circuit
- Generating cryptographic witnesses
- Creating zero-knowledge proofs
- Mathematical operations on large numbers
- Keep functions small and focused
- Minimize loop iterations
- Avoid unnecessary operations
- Batch related operations
Can I parallelize proof generation?
Proof generation for a single transaction is inherently sequential. However, you can generate proofs for multiple independent transactions in parallel.Development and Tooling
What editor should I use?
Leo works with any text editor. Popular choices:- VS Code: Official Leo extension available
- Vim/Neovim: Community plugins available
- IntelliJ: Basic syntax highlighting
- Emacs: Community support
How do I debug Leo programs?
Debugging strategies:-
Use assertions liberally:
-
Check generated Aleo code:
- Simplify complex functions: Break down operations into smaller steps
-
Use verbose output:
Can I import external libraries?
Leo supports importing other Aleo programs:How do I test my Leo programs?
Leo supports testing through:-
Unit tests with input files:
Create
inputs/program.inwith test cases -
Integration tests:
Use
leo runwith specific inputs - CI/CD: Integrate Leo tests into your CI pipeline
Performance and Optimization
How can I optimize my Leo programs?
Reduce circuit complexity:- Minimize operations in hot paths
- Avoid unnecessary computations
- Use simpler types when possible (u8 vs u128)
- Combine related operations in one function
- Reduce number of separate transactions
- Smaller types = smaller circuits
- Use u8 instead of u64 when possible
- Remember loops are unrolled
- 1000-iteration loop = 1000x code size
What’s the maximum program size?
There’s no hard limit, but practical constraints:- Larger circuits take longer to prove
- Circuit complexity affects verifier costs
- Memory limitations during proving
How much does it cost to run a Leo program?
Costs depend on:- Circuit size (operations performed)
- On-chain storage usage (mappings)
- Finalization operations
- Network congestion
Advanced Topics
Can Leo programs call other programs?
Yes, through imports:What cryptographic primitives does Leo support?
- Finite field arithmetic: Built-in
fieldtype - Elliptic curves:
grouptype for curve points - Hashing: Via Aleo instructions (not directly in Leo)
- Signatures:
signaturetype - Randomness: ChaCha RNG in finalizers
Can I use Leo for DeFi applications?
Yes! Leo is well-suited for DeFi:- Private trading (hide amounts)
- Confidential transactions
- Private auctions
- Anonymous voting
- Shielded asset transfers
How do I handle errors in Leo?
Leo uses assertions rather than exceptions:Community and Contribution
How can I contribute to Leo?
See the Contributing Guide for detailed instructions. Quick start:- Fork the repository
- Create a feature branch
- Make your changes
- Run tests (
cargo test) - Format code (
cargo +nightly fmt) - Submit a pull request
Where can I get help?
- Discord: Aleo Discord
- GitHub Discussions: Leo Discussions
- Documentation: Leo Docs
Is there a Leo playground?
Check the Aleo website for online tools and playgrounds. You can also run Leo locally:Related Resources
Quick Start
Get started with Leo
Examples
Example programs
Troubleshooting
Common errors and solutions
Contributing
Help improve Leo