diff --git a/.github/scripts/verify-code-references.sh b/.github/scripts/verify-code-references.sh index 12fb665f7..223ead52e 100755 --- a/.github/scripts/verify-code-references.sh +++ b/.github/scripts/verify-code-references.sh @@ -17,11 +17,41 @@ EXIT_CODE=0 TOTAL_REFS=0 VALID_REFS=0 INVALID_REFS=0 +COMMENT_FILE="" +ERRORS_COLLECTED="" + +# Parse arguments +while [[ $# -gt 0 ]]; do + case $1 in + --pr-comment) + COMMENT_FILE="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done echo "Verifying code references in documentation..." echo "Repository root: ${REPO_ROOT}" +if [[ -n "${COMMENT_FILE}" ]]; then + echo "PR comment mode: will write to ${COMMENT_FILE}" +fi echo "" +# Function to add error to collection +add_error() { + local error_msg="$1" + if [[ -z "${ERRORS_COLLECTED}" ]]; then + ERRORS_COLLECTED="${error_msg}" + else + ERRORS_COLLECTED="${ERRORS_COLLECTED} +${error_msg}" + fi +} + # Find all markdown files with CODE_REFERENCE comments while IFS= read -r doc_file; do # Extract CODE_REFERENCE comments from this file @@ -41,11 +71,15 @@ while IFS= read -r doc_file; do TOTAL_REFS=$((TOTAL_REFS + 1)) + # Get relative path for documentation file + doc_file_rel="${doc_file#"${REPO_ROOT}"/}" + # Check if the source file exists source_file="${REPO_ROOT}/${file_path}" if [[ ! -f "$source_file" ]]; then echo -e "${RED}✗${NC} Invalid reference in ${doc_file}:${line_num}" echo " File not found: ${file_path}" + add_error "- **${doc_file_rel}:${line_num}** - File not found: \`${file_path}\`" INVALID_REFS=$((INVALID_REFS + 1)) EXIT_CODE=1 continue @@ -57,6 +91,7 @@ while IFS= read -r doc_file; do echo -e "${RED}✗${NC} Invalid reference in ${doc_file}:${line_num}" echo " Line range L${start_line}-L${end_line} exceeds file length (${total_lines} lines)" echo " File: ${file_path}" + add_error "- **${doc_file_rel}:${line_num}** - Line range L${start_line}-L${end_line} exceeds file length (${total_lines} lines) in \`${file_path}\`" INVALID_REFS=$((INVALID_REFS + 1)) EXIT_CODE=1 continue @@ -102,12 +137,14 @@ while IFS= read -r doc_file; do echo " ${file_path}#L${start_line}-L${end_line}" echo " Local code differs from GitHub (${branch})" echo " This may indicate uncommitted changes or branch divergence" + add_error "- **${doc_file_rel}:${line_num}** - Code reference to \`${file_path}#L${start_line}-L${end_line}\` differs from GitHub (\`${branch}\` branch). The referenced code may have been modified locally but not yet merged to \`${branch}\`." INVALID_REFS=$((INVALID_REFS + 1)) EXIT_CODE=1 fi else echo -e "${YELLOW}⚠${NC} Could not parse GitHub URL in ${doc_file}:${line_num}" echo " URL: ${github_url}" + add_error "- **${doc_file_rel}:${line_num}** - Could not parse GitHub URL: \`${github_url}\`" INVALID_REFS=$((INVALID_REFS + 1)) EXIT_CODE=1 fi @@ -115,12 +152,14 @@ while IFS= read -r doc_file; do echo -e "${YELLOW}⚠${NC} Mismatched line range in ${doc_file}:${line_num}" echo " CODE_REFERENCE comment specifies: L${start_line}-L${end_line}" echo " But GitHub URL has different line range" + add_error "- **${doc_file_rel}:${line_num}** - CODE_REFERENCE comment specifies L${start_line}-L${end_line} but GitHub URL has different line range" INVALID_REFS=$((INVALID_REFS + 1)) EXIT_CODE=1 fi else echo -e "${YELLOW}⚠${NC} No GitHub URL found for reference in ${doc_file}:${line_num}" echo " Expected rust reference block with GitHub URL" + add_error "- **${doc_file_rel}:${line_num}** - No GitHub URL found for reference (expected rust reference block with GitHub URL)" INVALID_REFS=$((INVALID_REFS + 1)) EXIT_CODE=1 fi @@ -145,6 +184,37 @@ if [[ $EXIT_CODE -eq 0 ]]; then echo -e "${GREEN}✓ All code references are valid!${NC}" else echo -e "${RED}✗ Some code references are invalid. Please update the documentation.${NC}" + + # If in PR comment mode, write the comment to file + if [[ -n "${COMMENT_FILE}" ]]; then + cat > "${COMMENT_FILE}" <> $GITHUB_OUTPUT + echo "Comment file created, will post to PR" + cat /tmp/pr-comment.md + else + echo "has_errors=false" >> $GITHUB_OUTPUT + echo "No errors found, no comment needed" + fi + + - name: Comment PR on verification failure + if: github.event_name == 'pull_request' && steps.verify-pr.outputs.has_errors == 'true' + uses: thollander/actions-comment-pull-request@v3 + with: + file-path: /tmp/pr-comment.md + comment-tag: code-reference-verification + + - name: Verify code references in documentation (non-PR mode) + if: github.event_name != 'pull_request' run: bash .github/scripts/verify-code-references.sh - name: Build documentation diff --git a/ledger/src/scan_state/transaction_logic.rs b/ledger/src/scan_state/transaction_logic.rs index 434f4c6a4..c83c58310 100644 --- a/ledger/src/scan_state/transaction_logic.rs +++ b/ledger/src/scan_state/transaction_logic.rs @@ -56,6 +56,10 @@ use crate::zkapps::zkapp_logic::ZkAppCommandElt; /// #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] +/// Transaction failure reasons. +/// +/// When a transaction fails, the fee is still deducted from the fee payer, +/// but no account updates are applied. pub enum TransactionFailure { Predicate, SourceNotPresent, @@ -2642,11 +2646,19 @@ pub mod zkapp_command { /// pub type SideLoadedProof = Arc; + /// Authorization methods for zkApp account updates. + /// + /// Defines how an account update is authorized to modify an account's state. + /// /// #[derive(Clone, PartialEq)] pub enum Control { + /// Verified by a zero-knowledge proof against the account's verification + /// key. Proof(SideLoadedProof), + /// Signed by the account's private key. Signature(Signature), + /// No authorization (only valid for certain operations). NoneGiven, } diff --git a/website/docs/developers/zkapps.md b/website/docs/developers/zkapps.md new file mode 100644 index 000000000..d34840164 --- /dev/null +++ b/website/docs/developers/zkapps.md @@ -0,0 +1,244 @@ +--- +sidebar_position: 6 +title: zkApps and zkApp Commands +description: + Understanding zkApps and zkApp commands in the Mina protocol implementation +slug: /developers/zkapps +--- + +# zkApps and zkApp Commands + +## Overview + +zkApps (zero-knowledge applications) are programmable smart contracts on the +Mina blockchain that leverage zero-knowledge proofs for private, verifiable +computation. A **zkApp command** is the transaction type used to interact with +zkApps, containing account updates that can be authorized by signatures or +zero-knowledge proofs. + +This document provides an entry point for developers joining the team to +understand how zkApps are implemented in the Rust codebase. + +## What is a zkApp? + +A zkApp is a smart contract on Mina that: + +- Stores state in on-chain accounts (8 field elements of app state) +- Executes logic verified by zero-knowledge proofs +- Can interact with multiple accounts atomically +- Supports custom permissions and verification keys + +Unlike traditional smart contracts that execute on-chain, zkApp logic executes +off-chain and produces a zero-knowledge proof that the computation was performed +correctly. Only the proof is verified on-chain, keeping the blockchain +lightweight. + +## What is a zkApp Command? + +A **zkApp command** (`ZkAppCommand`) is a transaction type that applies updates +to multiple accounts atomically. It consists of: + +### Structure + + + +```rust reference title="ledger/src/scan_state/transaction_logic.rs" +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L3588-L3592 +``` + +### Components + +#### 1. Fee Payer + +The account that pays for the transaction. It must be authorized with a +signature and its nonce must increase. + +#### 2. Account Updates + +A forest (list of trees) of account updates, where each `AccountUpdate`: + +- Specifies an account to modify (identified by public key and token) +- Declares preconditions that must be satisfied +- Specifies state changes (balance, app state, permissions, etc.) +- Provides authorization (signature, proof, or none) +- Can make nested calls to other accounts + +**Key type:** + + + +```rust reference title="ledger/src/scan_state/transaction_logic.rs" +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L2758-L2761 +``` + +#### 3. Memo + +Optional data field (up to 32 bytes) for auxiliary information. + +## Authorization Methods + + + +```rust reference +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L2645-L2659 +``` + +## Transaction Commitments and Signing + +zkApp commands use transaction commitments for signing: + +1. **Partial commitment** - Hash of account updates (for account update + signatures) +2. **Full commitment** - Includes memo and fee payer (for fee payer signature) + +Account updates can specify whether to use the full commitment via the +`use_full_commitment` flag. + +### Commitment Computation + + + +```rust reference title="ledger/src/generators/zkapp_command_builder.rs" +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/generators/zkapp_command_builder.rs#L11-L22 +``` + +### Signing Implementation + +The signing logic replaces dummy authorizations with valid signatures/proofs: + + + +```rust reference title="ledger/src/generators/zkapp_command_builder.rs" +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/generators/zkapp_command_builder.rs#L28-L44 +``` + + +:::note + +The actual cryptographic signature generation is currently a TODO in the +codebase (returns `Signature::dummy()`). + +::: + + +## Application Logic + +The core zkApp business logic is implemented in: + +- **[`ledger/src/zkapps/zkapp_logic.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/zkapp_logic.rs)** - + Main application logic for processing zkApp commands +- **[`ledger/src/zkapps/non_snark.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/non_snark.rs)** - + Non-SNARK verification paths +- **[`ledger/src/zkapps/snark.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/snark.rs)** - + SNARK-based verification +- **[`ledger/src/zkapps/checks.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/checks.rs)** - + Precondition and permission checks + +## Processing Pipeline + +When a zkApp command is applied to the ledger: + +1. **Validation** - Check transaction is well-formed and within cost limits +2. **Fee payer verification** - Verify fee payer signature and sufficient + balance +3. **Account update processing** - For each account update: + - Verify authorization (signature or proof) + - Check preconditions (account state, protocol state) + - Check permissions + - Apply state changes atomically +4. **Failure handling** - If any step fails, the entire command fails (except + fee is still deducted) + +**Key entry point:** +[`ledger/src/scan_state/transaction_logic.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs) +(search for `apply_zkapp_command`) + +## Cost and Weight Limits + +zkApp commands have cost limits to prevent resource exhaustion: + + + +```rust reference title="ledger/src/scan_state/transaction_logic.rs" +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L3668-L3684 +``` + +The cost considers: + +- Number of proof verifications +- Number of signature verifications +- Whether signatures verify single or paired account updates + +## Testing and Generators + +For testing, the codebase includes zkApp command generators: + +- **[`ledger/src/generators/zkapp_command.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/generators/zkapp_command.rs)** - + Generates random zkApp commands for testing +- **[`ledger/src/generators/zkapp_command_builder.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/generators/zkapp_command_builder.rs)** - + Utility functions for building and signing zkApp commands + +## Key Files Reference + +### Core Types + +- [`ledger/src/scan_state/transaction_logic.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs) - + `ZkAppCommand`, `AccountUpdate`, `Control`, `FeePayer` + +### Business Logic + +- [`ledger/src/zkapps/zkapp_logic.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/zkapp_logic.rs) - + Main zkApp processing logic +- [`ledger/src/zkapps/checks.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/checks.rs) - + Precondition and permission validation +- [`ledger/src/zkapps/snark.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/snark.rs) - + SNARK verification implementation +- [`ledger/src/zkapps/non_snark.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/non_snark.rs) - + Non-SNARK paths + +### Signing and Building + +- [`ledger/src/generators/zkapp_command_builder.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/generators/zkapp_command_builder.rs) - + Transaction signing and authorization + +### Proofs + +- [`ledger/src/proofs/zkapp.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/proofs/zkapp.rs) - + zkApp proof verification + +## Transaction Failures + + + +```rust reference title="ledger/src/scan_state/transaction_logic.rs" +https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L59-L154 +``` + +## Comparison to Other Transaction Types + +Mina has three transaction types: + +1. **[Signed Commands](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L849)** - + Simple payments and delegation changes, authorized by signature +2. **[zkApp Commands](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L3588)** - + Complex multi-account updates with proof or signature authorization +3. **[Coinbase](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs#L500)** - + Block rewards (internal, not user-submitted) + +zkApp commands are more powerful but have higher complexity and cost limits. + +## Getting Started + +To start working with zkApps in the codebase: + +1. Read the core types in + [`ledger/src/scan_state/transaction_logic.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/scan_state/transaction_logic.rs) + (search for `ZkAppCommand`) +2. Explore the application logic in + [`ledger/src/zkapps/zkapp_logic.rs`](https://github.com/o1-labs/mina-rust/blob/develop/ledger/src/zkapps/zkapp_logic.rs) +3. Review test generators in + [`ledger/src/generators/`](https://github.com/o1-labs/mina-rust/tree/develop/ledger/src/generators) +4. Study how zkApp commands flow through the transaction pool and staged ledger + +For questions, consult the inline documentation in the source files or refer to +the OCaml implementation for semantic clarity. diff --git a/website/sidebars.ts b/website/sidebars.ts index 962b0621d..f18dff9fc 100644 --- a/website/sidebars.ts +++ b/website/sidebars.ts @@ -83,6 +83,7 @@ const sidebars: SidebarsConfig = { 'developers/architecture', 'developers/circuits', 'developers/ledger-crate', + 'developers/zkapps', ], }, {