--- url: /developers/tools/agent-skills.md --- # Agent Skills Zeko publishes a public agent skill for assistants that need to help users actually use Zeko. ## Install Install the public skill from [skills.sh](https://skills.sh/) with the `skills` CLI: ```bash npx skills add https://github.com/zeko-labs/zeko-skills --skill zeko ``` This installs the `zeko` skill. ## What The Skill Covers The skill is designed for real Zeko user and builder workflows: * bridge flows with Bridge CLI or Bridge SDK * faucet flows and testnet funding * endpoint discovery for Zeko, Mina gateways, and archive access * GraphQL and `curl` examples for network inspection and native transfers * sequencer, archive-node, and DA-layer orientation * zkApp development on Zeko with `o1js` or OCaml ## Example Uses * `How do I get tMINA on Zeko testnet?` * `Bridge 2 MINA from Mina to Zeko using the Bridge CLI.` * `Which endpoints should I use for live data and archive data?` * `Show me a curl example to send 1.25 MINA from one address to another.` * `Explain the sequencer, archive node, and DA layer on Zeko.` ## Related Docs * [Public Zeko skill repo](https://github.com/zeko-labs/zeko-skills) * [skills.sh CLI docs](https://skills.sh/docs/cli) * [Bridge CLI](https://docs.zeko.io/developers/tools/bridge-cli) * [Bridge SDK](https://docs.zeko.io/developers/tools/bridge-sdk) * [Faucet CLI](https://docs.zeko.io/developers/tools/faucet-cli) --- --- url: /developers/api-reference.md --- # API Reference :::warning WIP: This section is under construction. ::: Find API documentation for Zeko SDKs, smart contracts, and developer tools here. * [o1js API Reference](https://docs.o1labs.org/o1js/api-reference/Introduction) – complete API reference for the o1js TypeScript framework used to build zkApps on Zeko. --- --- url: /about/community.md --- # Community & Support :::warning WIP: This section is under construction. Content is for illustrative purposes only. ::: * Discord [**Zeko Discord Server**](https://discord.com/invite/vSDxqAchUY) - Join our community to ask questions, share ideas, and get support from other Zeko users and developers. * Telegram [**Zeko Telegram Group**](https://t.me/zekoprotocol) - For real-time discussions and updates. * Twitter [**@ZekoLabs**](https://x.com/ZekoLabs) - Follow us for the latest news and updates. --- --- url: /operators/concepts-for-operators.md --- # Concepts for Operators :::warning WIP: This section is under construction. ::: This section provides an overview of the key concepts network operators should understand when running infrastructure for Zeko. ## Network Topology Zeko operates as a Layer 2 (L2) ecosystem built on top of Mina Protocol (Layer 1). The network topology involves several interconnected components and roles: * **Sequencer**: This is a server that acts as the transaction collector and processor for the Zeko L2. The sequencer accepts transactions from users, typically via a GraphQL API. It applies these transactions to the Zeko ledger. The sequencer then posts the transaction data on the Data Availability (DA) layer and sends them to provers. It is responsible for proving the validity of transactions using zero-knowledge proofs and efficiently grouping transactions into batches. Sequencers generate a queue of pending transfer requests. They select and prove bridge transfer requests, aggregating the proofs. Once a batch is finalized, the sequencer posts the batch and receipts to the DA layer and then commits the final batch proof to the L1 zkApp (rollup contract). Currently, it's not possible to run multiple sequencers. * **Prover**: This component receives transactions from the sequencer and generates proofs for their validity. In the transaction snark binary tree, provers prove individual transactions or account updates, which are then merged. * **Data Availability (DA) Layer Nodes**: This layer is responsible for storing all the transaction data that occurs on the rollup. DA layer nodes are described as a bunch of nodes, each replicating the same storage. The sequencer sends the transaction data to the DA layer. * **L1 ZkApp (Verifier Contract)**: This is a smart contract deployed on the Mina Protocol L1. It acts as a bridge between L1 and L2. The L1 zkApp's state stores the current ledger hash of the Zeko rollup. The sequencer sends aggregated proofs of transaction batches to this L1 contract. The L1 contract verifies these proofs and updates its state to the new ledger hash. Communication from L2 to L1 also happens via posting actions to an inner account on L2, which synchronizes with the outer L1 zkApp account on commit. * **L1 Mina Nodes**: These are the standard nodes of the Mina Protocol Layer 1 network. The sequencer ultimately sends aggregated batch proofs to the L1, which update the state of the L1 zkApp. * **Archive Nodes**: These nodes index the history of the blockchain. Mina archive nodes can be used to index the history of the Zeko rollup by running a Zeko archive relay adapter that subscribes to the sequencer and relays new blocks to the archive. The overall flow involves transactions being sent to the sequencer, processed off-chain, data being stored on the DA layer, proofs being generated and aggregated, and finally, a single aggregated proof being committed to the L1 Mina zkApp to update the rollup's state. ## Role of the ZkApp (Verifier Contract) on Mina L1 The Zeko rollup is implemented as a **zkApp account** on the Mina Layer 1 blockchain. This L1 zkApp serves as the **verifier contract**. Its primary role is to act as the authoritative state anchor for the Zeko L2. * The L1 zkApp's state holds the current, verified hash of the Zeko L2 ledger. * The Zeko sequencer processes batches of transactions and generates a single, aggregated proof that represents the transition from the previous L2 ledger state (hash A) to the new L2 ledger state (hash D). * This aggregated proof (e.g., A->D) is then sent to the L1 and verified by the Zeko zkApp contract. * If the proof is valid, the L1 zkApp's state is updated to the new ledger hash (D). * This process effectively compresses the validation of a batch of transactions on L2 into the verification of a single constant-sized proof on L1. The L1 zkApp also plays a role in the bridging process, receiving actions posted on L1 for deposits and synchronizing action states with the inner L2 account on commit. ## Operator Economics :::warning WIP: This section is under construction. ::: * **Fees**: Users pay fees in MINA to the sequencer. The fees users pay are based on factors like computational work, DA, networking, and storage. The sequencer is paid fees for batch creation and proof aggregation work. --- --- url: /developers/contributing.md --- # Contributing to Zeko Development :::warning WIP: This section is under construction. ::: Contributions are welcome! Fork the repo, open a pull request, and join the Zeko developer community. * [Zeko GitHub repository](https://github.com/zeko-labs/zeko) – source code for the Zeko protocol, including the sequencer and data availability components. * [Zeko Discord](https://discord.gg/edF9vzD7en) – the primary community hub for developers and contributors. --- --- url: /background/core-blockchain-concepts.md --- # Core Blockchain Concepts *This section provides a brief overview of fundamental blockchain concepts that are helpful to understand Zeko and zkApps. If you are already familiar with how blockchain technology works, you can skip this part.* ## What is a blockchain? At its core, a **blockchain is a special kind of database**. It functions as a **decentralised digital ledger** that securely records transaction data across a distributed network of computers. Data on a blockchain is organised into **blocks**, which are arranged chronologically and secured using **cryptography**. This structure ensures that the data is **transparent, secure, and immutable**. Once data is added to a block and that block is confirmed and added to the chain, it is virtually impossible to change it. The decentralised structure means there is **no single central authority** controlling the flow of data or transactions; instead, a distributed network of computers works together to maintain the integrity of the network. This decentralisation makes large networks highly resistant to attacks. Consensus mechanisms are sets of rules that govern how nodes on the network agree on the state of the blockchain and the validity of transactions. > \[!TIP] πŸ’‘ Consensus πŸ’‘ > **Bitcoin** was the first cryptocurrency powered by blockchain technology and uses the **Proof of Work** consensus mechanism. In contrast, **Mina Protocol** is known for being a lightweight blockchain that uses a **Proof of Stake**-based consensus mechanism called **Ouroboros**. Find more about it in the [o1js documentation](https://docs.o1labs.org/o1js/). ## Wallets & Keys (Public/Private) The security and verifiability of transactions on a blockchain rely heavily on cryptography. **Public-key cryptography**, also known as asymmetric cryptography, helps establish secure and verifiable transactions between users. This involves using pairs of keys: a **public key** (which can be shared) and a **private key** (which must be kept secret). Digital signatures are used in blockchain cryptography, and verifying these signatures is part of the process nodes use to authenticate a transaction. Wallets are typically used to manage these keys and interact with the blockchain. > \[!TIP] πŸ’‘ Wallets πŸ’‘ > In the Mina and Zeko ecosystems, wallets such as [Auro wallet](https://www.aurowallet.com/) are used to manage your public and private keys. These keys are essential for signing transactions and interacting with zkApps using public-key cryptography. Refer to the [Auro Wallet documentation](https://docs.aurowallet.com/) for more information on Mina-compatible wallets. ## Blockchain Transactions A transaction on a blockchain is essentially a record of interaction or value transfer between two parties. When a transaction is initiated, it is **broadcast to a network of nodes**. Each node validates the transaction based on predefined rules, verifying digital signatures and other data. Validated transactions are then grouped together into a block. On Mina and Zeko, the fundamental data structure that transactions are built from is called an **account update**. ::: details More on Account Updates Each zkApp transaction constructed using o1js is composed of one or more `AccountUpdate` classes, which represent a set of instructions for the network, such as altering on-chain state or emitting an event. An `AccountUpdate` can include preconditions that must be met, apply updates to an account, and include assertions about its child account updates. Transactions can consist of multiple account updates, for example, one to subtract a fee and another to add a token balance. ::: --- --- url: /developers/core-developer-concepts.md --- # Core Developer Concepts :::warning WIP: This section is under construction. ::: * **o1js Deep Dive** – [o1js documentation](https://docs.o1labs.org/o1js/) * Introduction to o1js (Typescript framework for zkApps/zkPrograms). * Writing zk-circuits. * State management within zkPrograms. * Off-chain execution and proving. * **zkPrograms** – [ZkProgram guide](https://docs.o1labs.org/o1js/writing-constraint-systems/zk-program) * Structure of a zkProgram. * Defining public and private inputs. * Writing verification logic. * **Lumina SDK** – [Lumina SDK documentation](https://sdk.luminadex.com/) * Introduction to Lumina SDK (Interacting with Zeko network). * Connecting to a Zeko node. * Sending transactions. * Reading state. --- --- url: /developers/guides/create-faucet.md --- # Creating a MINA Faucet on Zeko > ⚠️ **Warning**: This guide is for educational purposes only. Do NOT deploy a faucet to mainnet as it gives away free MINA to anyone. Use only on testnets for learning purposes. ## Overview A MINA faucet is a smart contract that distributes small amounts of MINA tokens to users for testing purposes. This tutorial will guide you through creating a complete faucet implementation using o1js and smart contracts on the Zeko protocol. This is an excellent exercise for developers looking to: * Learn how to write smart contracts with o1js * Understand token management and account tracking * Practice testing smart contracts * Build user interfaces for blockchain applications ## Smart contract Architecture The faucet smart contract architecture needs to enable several important features: * Anyone can deposit MINA into the faucet * Anyone can claim only once * The faucet can update the amount of MINA available for claiming The difficulty lies in implementing a mechanism to prevent double spending : We use a trick : by extending the Faucet from `TokenContract`, we can use a tracking token to track whether a user has claimed or not. This way, we can prevent double claims by checking the balance of the tracking token. By setting approveBase and the account permissions properly, we can ensure that the tracking token cannot be transferred or used in any way other than to check if the user has claimed or not. Additionally we will emit events to enable observability and off-chain tracking of deposits and claims. ## Prerequisites Before starting, ensure you have: * Basic knowledge of TypeScript * Familiarity with blockchain concepts * Node.js and Bun installed * Understanding of o1js fundamentals ## Project Structure We'll create a faucet with the following structure: ``` faucet/ β”œβ”€β”€ package.json β”œβ”€β”€ vitest.config.ts β”œβ”€β”€ zkapp.ts # Smart contract implementation └── test/ └── zkapp.test.ts # Comprehensive test suite ``` ## Step 1: Project Setup First, create a new project and install dependencies: ```bash mkdir mina-faucet-tutorial cd mina-faucet-tutorial bun init -y ``` Install the required dependencies: ```bash bun add o1js bun add -d vitest unplugin-swc @types/bun ``` ## Step 2: Configure Testing Environment Create a `vitest.config.ts` file to configure our testing environment for o1js: ```typescript import swc from "unplugin-swc" import { defineConfig } from "vitest/config" export default defineConfig({ test: { globals: true, testTimeout: 60_000, // 60 seconds timeout for o1js operations hookTimeout: 60_000, // 60 seconds for setup/teardown pool: "forks" // Use process isolation for o1js }, plugins: [swc.vite()] }) ``` Update your `package.json` to include test scripts: ```json { "scripts": { "test": "vitest", "test:watch": "vitest --watch" }, "type": "module" } ``` ## Step 3: Implement the Faucet Smart Contract Create `zkapp.ts` with the following implementation: ```typescript import { AccountUpdate, Field, Permissions, PublicKey, State, Struct, TokenContract, UInt64, method, state } from "o1js" import type { AccountUpdateForest, DeployArgs } from "o1js" export interface FaucetDeployProps extends Exclude { amount: UInt64 } export class FaucetClaimEvent extends Struct({ eventId: Field, claimer: PublicKey, amount: UInt64 }) {} export class FaucetDepositEvent extends Struct({ eventId: Field, depositor: PublicKey, amount: UInt64 }) {} export class Faucet extends TokenContract { @state(UInt64) amount = State() events = { claim: FaucetClaimEvent, deposit: FaucetDepositEvent } async approveBase(forest: AccountUpdateForest) { forest.isEmpty().assertTrue("You can't approve any token operation") } async deploy(args: FaucetDeployProps) { await super.deploy() args.amount.assertGreaterThan(UInt64.zero, "Put a default amount") // Set the initial state of the contract this.amount.set(args.amount) // Set the permissions for the contract this.account.permissions.set({ ...Permissions.default(), send: Permissions.proofOrSignature(), setVerificationKey: Permissions.VerificationKey.none(), setPermissions: Permissions.impossible() }) } @method async deposit(amount: UInt64) { amount.assertGreaterThan( UInt64.zero, "Deposit amount must be greater than zero" ) const depositor = this.sender.getUnconstrained() // Create account update for the sender to send MINA to the contract const senderUpdate = AccountUpdate.createSigned(depositor) senderUpdate.send({ to: this.address, amount }) this.emitEvent( "deposit", new FaucetDepositEvent({ eventId: Field(0), depositor, amount }) ) } @method async claim(claimer: PublicKey) { const amount = this.amount.getAndRequireEquals() // Check if we have enough MINA const contractBalance = this.account.balance.getAndRequireEquals() contractBalance.assertGreaterThanOrEqual( amount, "Insufficient MINA balance in faucet" ) // Check if the tracking token balance of the claimer is 0 to prevent double claims const senderToken = AccountUpdate.create(claimer, this.deriveTokenId()) senderToken.account.balance.requireEquals(UInt64.zero) // Send MINA tokens to the claimer this.send({ to: claimer, amount }) // If the user hasn't claimed, mint 1 unit of the tracking token to their account this.internal.mint({ address: claimer, amount: UInt64.one }) // Emit the claim event only if it's the first claim for the sender this.emitEventIf( senderToken.account.balance.get().equals(UInt64.zero), "claim", new FaucetClaimEvent({ eventId: Field(1), claimer, amount }) ) } @method async updateAmount(newAmount: UInt64) { newAmount.assertGreaterThan( UInt64.zero, "New amount must be greater than zero" ) // Only the contract itself can update the amount (requires contract private key) const sender = this.sender.getAndRequireSignature() sender.assertEquals(this.address) // Update the amount state this.amount.set(newAmount) } } ``` ### Key Features Explained 1. **TokenContract Base**: Extends TokenContract to manage both MINA and custom tracking tokens 2. **Double-Claim Prevention**: Uses tracking tokens to ensure users can only claim once 3. **Events**: Emits events for deposits and claims for off-chain tracking 4. **Access Control**: The contract private key is required to update the faucet amount 5. **Security**: Prevents token transfers through `approveBase` method and deploy permissions ## Step 4: Comprehensive Test Suite Create `test/zkapp.test.ts` with comprehensive tests: ```typescript import { AccountUpdate, Bool, Mina, PrivateKey, type PublicKey, UInt64 } from "o1js" import { beforeAll, beforeEach, describe, expect, it } from "vitest" import { Faucet, type FaucetClaimEvent, type FaucetDepositEvent } from "../zkapp" describe("Faucet Contract", () => { const proofsEnabled = false let deployerAccount: PublicKey let deployerKey: PrivateKey let senderAccount: PublicKey let senderKey: PrivateKey let user1Account: PublicKey let user1Key: PrivateKey let user2Account: PublicKey let user2Key: PrivateKey let zkFaucetAddress: PublicKey let zkFaucetPrivateKey: PrivateKey let zkFaucet: Faucet beforeAll(async () => { if (proofsEnabled) await Faucet.compile() }) beforeEach(async () => { const Local = await Mina.LocalBlockchain({ proofsEnabled }) Mina.setActiveInstance(Local) const createTestAccount = (n: number) => ({ privateKey: Local.testAccounts[n].key, publicKey: Local.testAccounts[n] }) // Get test accounts const deployer = createTestAccount(0) const sender = createTestAccount(1) const user1 = createTestAccount(2) const user2 = createTestAccount(3) // Set accounts deployerAccount = deployer.publicKey deployerKey = deployer.privateKey senderAccount = sender.publicKey senderKey = sender.privateKey user1Account = user1.publicKey user1Key = user1.privateKey user2Account = user2.publicKey user2Key = user2.privateKey // Create zkFaucet account zkFaucetPrivateKey = PrivateKey.random() zkFaucetAddress = zkFaucetPrivateKey.toPublicKey() zkFaucet = new Faucet(zkFaucetAddress) }) describe("Deploy", () => { it("should deploy the contract with correct initial state", async () => { const faucetAmount = UInt64.from(100 * 10 ** 9) const txn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount, 1) await zkFaucet.deploy({ amount: faucetAmount }) }) await txn.prove() await txn.sign([deployerKey, zkFaucetPrivateKey]).send() const amount = zkFaucet.amount.get() expect(amount).toEqual(faucetAmount) }) it("should fail to deploy with zero amount", async () => { await expect(async () => { const txn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount) await zkFaucet.deploy({ amount: UInt64.zero }) }) await txn.prove() await txn.sign([deployerKey, zkFaucetPrivateKey]).send() }).rejects.toThrow() }) }) describe("Deposit", () => { beforeEach(async () => { const faucetAmount = UInt64.from(1000) const txn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount, 1) await zkFaucet.deploy({ amount: faucetAmount }) }) await txn.prove() await txn.sign([deployerKey, zkFaucetPrivateKey]).send() }) it("should allow deposits and emit deposit event", async () => { const depositAmount = UInt64.from(500) const initialBalance = Mina.getBalance(zkFaucetAddress) const txn = await Mina.transaction(senderAccount, async () => { await zkFaucet.deposit(depositAmount) }) await txn.prove() await txn.sign([senderKey]).send() const finalBalance = Mina.getBalance(zkFaucetAddress) expect(finalBalance.sub(initialBalance)).toEqual(depositAmount) // Check for deposit event const events = await zkFaucet.fetchEvents() const depositEvents = events.filter((e) => e.type === "deposit") expect(depositEvents).toHaveLength(1) const event = depositEvents[0].event.data as unknown as FaucetDepositEvent expect(event.depositor.toBase58()).toEqual(senderAccount.toBase58()) expect(event.amount).toEqual(depositAmount) }) it("should fail to deposit zero amount", async () => { await expect(async () => { const txn = await Mina.transaction(senderAccount, async () => { await zkFaucet.deposit(UInt64.zero) }) await txn.prove() await txn.sign([senderKey]).send() }).rejects.toThrow() }) }) describe("Claim", () => { beforeEach(async () => { const faucetAmount = UInt64.from(100 * 10 ** 9) // Deploy contract const deployTxn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount, 1) await zkFaucet.deploy({ amount: faucetAmount }) }) await deployTxn.prove() await deployTxn.sign([deployerKey, zkFaucetPrivateKey]).send() // Fund the contract const depositAmount = UInt64.from(1000 * 10 ** 9) const depositTxn = await Mina.transaction(senderAccount, async () => { await zkFaucet.deposit(depositAmount) }) await depositTxn.prove() await depositTxn.sign([senderKey]).send() }) it("should allow first-time claim and emit claim event", async () => { const initialUserBalance = Mina.getBalance(user1Account) const claimAmount = UInt64.from(100 * 10 ** 9) const txn = await Mina.transaction(user1Account, async () => { AccountUpdate.fundNewAccount(user1Account) await zkFaucet.claim(user1Account) }) await txn.prove() await txn.sign([user1Key]).send() const finalUserBalance = Mina.getBalance(user1Account) // Check that the final balance is greater after paying fees expect( finalUserBalance.toBigInt() - initialUserBalance.toBigInt() ).toBeGreaterThan(0) // Check for claim event const events = await zkFaucet.fetchEvents() const claimEvents = events.filter((e) => e.type === "claim") expect(claimEvents).toHaveLength(1) const event = claimEvents[0].event.data as unknown as FaucetClaimEvent expect(event.claimer.toBase58()).toEqual(user1Account.toBase58()) expect(event.amount).toEqual(claimAmount) }) it("should prevent double claiming from same user", async () => { // First claim should succeed const initialUserBalance = Mina.getBalance(user1Account) const firstTxn = await Mina.transaction(user1Account, async () => { AccountUpdate.fundNewAccount(user1Account) await zkFaucet.claim(user1Account) }) await firstTxn.prove() await firstTxn.sign([user1Key]).send() const firstClaimUserBalance = Mina.getBalance(user1Account) await expect(async () => { const secondTxn = await Mina.transaction(user1Account, async () => { await zkFaucet.claim(user1Account) }) await secondTxn.prove() await secondTxn.sign([user1Key]).send() }).rejects.toThrow() const secondClaimUserBalance = Mina.getBalance(user1Account) expect(secondClaimUserBalance.toBigInt()).toEqual( firstClaimUserBalance.toBigInt() ) expect( firstClaimUserBalance.toBigInt() - initialUserBalance.toBigInt() ).toBeGreaterThan(0) // Check that both claims created events const events = await zkFaucet.fetchEvents() const claimEvents = events.filter((e) => e.type === "claim") expect(claimEvents).toHaveLength(1) }) it("should allow different users to claim", async () => { const initialUser1Balance = Mina.getBalance(user1Account) const initialUser2Balance = Mina.getBalance(user2Account) // User 1 claims const txn1 = await Mina.transaction(user1Account, async () => { AccountUpdate.fundNewAccount(user1Account) await zkFaucet.claim(user1Account) }) await txn1.prove() await txn1.sign([user1Key]).send() // User 2 claims const txn2 = await Mina.transaction(user2Account, async () => { AccountUpdate.fundNewAccount(user2Account) await zkFaucet.claim(user2Account) }) await txn2.prove() await txn2.sign([user2Key]).send() const finalUser1Balance = Mina.getBalance(user1Account) const finalUser2Balance = Mina.getBalance(user2Account) expect( finalUser1Balance.toBigInt() - initialUser1Balance.toBigInt() ).toBeGreaterThan(0) expect( finalUser2Balance.toBigInt() - initialUser2Balance.toBigInt() ).toBeGreaterThan(0) // Check for both claim events const events = await zkFaucet.fetchEvents() const claimEvents = events.filter((e) => e.type === "claim") expect(claimEvents).toHaveLength(2) }) it("should fail to claim when contract has insufficient balance", async () => { // Deploy a new contract with small amount and no additional deposits const smallAmount = UInt64.from(100) const newZkAppPrivateKey = PrivateKey.random() const newZkAppAddress = newZkAppPrivateKey.toPublicKey() const newZkApp = new Faucet(newZkAppAddress) const deployTxn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount, 1) await newZkApp.deploy({ amount: smallAmount }) }) await deployTxn.prove() await deployTxn.sign([deployerKey, newZkAppPrivateKey]).send() // Don't fund the contract, so it has zero balance but wants to give 100 await expect(async () => { const txn = await Mina.transaction(user1Account, async () => { await newZkApp.claim(user1Account) }) await txn.prove() await txn.sign([user1Key]).send() }).rejects.toThrow() }) it("should prevent transfer of internal tracking token between users", async () => { // First, user1 claims to get the tracking token const claimTxn = await Mina.transaction(user1Account, async () => { AccountUpdate.fundNewAccount(user1Account) await zkFaucet.claim(user1Account) }) await claimTxn.prove() await claimTxn.sign([user1Key]).send() // Verify user1 has the tracking token (balance = 1) const user1TokenBalance = Mina.getBalance( user1Account, zkFaucet.deriveTokenId() ) expect(user1TokenBalance).toEqual(UInt64.one) // Try to transfer the tracking token from user1 to user2 - this should fail // because the contract's approveBase method prevents any token operations await expect(async () => { const transferTxn = await Mina.transaction(user1Account, async () => { AccountUpdate.fundNewAccount(user1Account, 1) // Fund for new token account creation const user1Update = AccountUpdate.createSigned( user1Account, zkFaucet.deriveTokenId() ) const user2Update = AccountUpdate.create( user2Account, zkFaucet.deriveTokenId() ) user1Update.send({ to: user2Update, amount: UInt64.one }) user2Update.account.isNew.requireEquals(Bool(true)) }) await transferTxn.prove() await transferTxn.sign([user1Key]).send() }).rejects.toThrow() // Verify balances remain unchanged after failed transfer const user1FinalTokenBalance = Mina.getBalance( user1Account, zkFaucet.deriveTokenId() ) expect(user1FinalTokenBalance).toEqual(UInt64.one) }) it("should allow claiming on behalf of someone else", async () => { // user1 will claim on behalf of user2 const initialUser2Balance = Mina.getBalance(user2Account) const claimAmount = UInt64.from(100 * 10 ** 9) // user1 initiates the transaction but claims for user2 const txn = await Mina.transaction(user1Account, async () => { AccountUpdate.fundNewAccount(user1Account) // user1 pays for account creation await zkFaucet.claim(user2Account) // but user2 receives the funds }) await txn.prove() //On the client` await txn.sign([user1Key]).send() // Check that user2 received the funds const finalUser2Balance = Mina.getBalance(user2Account) expect( finalUser2Balance.toBigInt() - initialUser2Balance.toBigInt() ).toEqual(claimAmount.toBigInt()) // Verify user2 has the tracking token (to prevent double claims) const user2TokenBalance = Mina.getBalance( user2Account, zkFaucet.deriveTokenId() ) expect(user2TokenBalance).toEqual(UInt64.one) // Check for claim event with correct claimer const events = await zkFaucet.fetchEvents() const claimEvents = events.filter((e) => e.type === "claim") expect(claimEvents).toHaveLength(1) const event = claimEvents[0].event.data as unknown as FaucetClaimEvent expect(event.claimer.toBase58()).toEqual(user2Account.toBase58()) // Event should show user2 as claimer expect(event.amount).toEqual(claimAmount) }) }) describe("Contract Balance Transfer", () => { beforeEach(async () => { const faucetAmount = UInt64.from(100 * 10 ** 9) // Deploy contract const deployTxn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount, 1) await zkFaucet.deploy({ amount: faucetAmount }) }) await deployTxn.prove() await deployTxn.sign([deployerKey, zkFaucetPrivateKey]).send() // Fund the contract with a substantial amount const depositAmount = UInt64.from(1000 * 10 ** 9) const depositTxn = await Mina.transaction(senderAccount, async () => { await zkFaucet.deposit(depositAmount) }) await depositTxn.prove() await depositTxn.sign([senderKey]).send() }) it("should transfer entire MINA balance to another wallet using contract private key", async () => { // Get initial balances const initialContractBalance = Mina.getBalance(zkFaucetAddress) const initialUser1Balance = Mina.getBalance(user1Account) // Transfer the entire contract balance to user1 using the contract's private key const txn = await Mina.transaction(deployerAccount, async () => { const contractUpdate = AccountUpdate.createSigned(zkFaucetAddress) // Transfer the entire balance (minus fees) to user1 contractUpdate.send({ to: user1Account, amount: initialContractBalance }) }) await txn.prove() await txn.sign([deployerKey, zkFaucetPrivateKey]).send() // Verify the transfer const finalContractBalance = Mina.getBalance(zkFaucetAddress) const finalUser1Balance = Mina.getBalance(user1Account) // Contract should have zero balance (or minimal amount due to account minimum) expect(finalContractBalance.toBigInt()).toBeLessThan( initialContractBalance.toBigInt() ) // User1 should have received the transferred amount const transferredAmount = finalUser1Balance.sub(initialUser1Balance) expect(transferredAmount.toBigInt()).toBeGreaterThan(0) // The transferred amount should approximately equal the initial contract balance // (allowing for some difference due to fees and account minimums) expect(transferredAmount.toBigInt()).toBeGreaterThan( (initialContractBalance.toBigInt() * BigInt(90)) / BigInt(100) ) }) }) describe("Update Amount", () => { beforeEach(async () => { const faucetAmount = UInt64.from(100 * 10 ** 9) // Deploy contract const deployTxn = await Mina.transaction(deployerAccount, async () => { AccountUpdate.fundNewAccount(deployerAccount, 1) await zkFaucet.deploy({ amount: faucetAmount }) }) await deployTxn.prove() await deployTxn.sign([deployerKey, zkFaucetPrivateKey]).send() }) it("should allow contract owner to update amount using contract private key", async () => { const initialAmount = zkFaucet.amount.get() const newAmount = UInt64.from(200 * 10 ** 9) // Update amount using contract private key const txn = await Mina.transaction(zkFaucetAddress, async () => { await zkFaucet.updateAmount(newAmount) }) await txn.prove() await txn.sign([zkFaucetPrivateKey]).send() // Verify the amount was updated const updatedAmount = zkFaucet.amount.get() expect(updatedAmount).toEqual(newAmount) expect(updatedAmount).not.toEqual(initialAmount) }) it("should fail when non-owner tries to update amount", async () => { const newAmount = UInt64.from(200 * 10 ** 9) // Try to update amount from a different account (should fail) await expect(async () => { const txn = await Mina.transaction(user1Account, async () => { await zkFaucet.updateAmount(newAmount) }) await txn.prove() await txn.sign([user1Key]).send() }).rejects.toThrow() // Verify the amount was not changed const unchangedAmount = zkFaucet.amount.get() expect(unchangedAmount).toEqual(UInt64.from(100 * 10 ** 9)) // Should still be the initial amount }) it("should fail when trying to update amount to zero", async () => { await expect(async () => { const txn = await Mina.transaction(zkFaucetAddress, async () => { await zkFaucet.updateAmount(UInt64.zero) }) await txn.prove() await txn.sign([zkFaucetPrivateKey]).send() }).rejects.toThrow() // Verify the amount was not changed const unchangedAmount = zkFaucet.amount.get() expect(unchangedAmount).toEqual(UInt64.from(100 * 10 ** 9)) // Should still be the initial amount }) }) }) ``` ## Step 5: Running the Tests Run your test suite to verify everything works correctly: ```bash bun test ``` You should see all tests passing, confirming that: * βœ… Contract deploys correctly * βœ… Users can deposit MINA to fund the faucet * βœ… Users can claim MINA (only once per user) * βœ… Double claims are prevented * βœ… Events are emitted correctly * βœ… Access control works properly ## Step 6: Key Learning Outcomes By completing this tutorial, you've learned: ### Smart Contract Development * **Token Management**: How to work with both MINA and custom tokens * **State Management**: Using on-chain state to track faucet configuration * **Access Control**: Implementing owner-only functions * **Event Emission**: Creating events for off-chain tracking ### Security Patterns * **Double-Claim Prevention**: Using tracking tokens to prevent abuse * **Balance Validation**: Ensuring sufficient funds before operations * **Permission Systems**: Restricting sensitive operations ### Testing Best Practices * **Comprehensive Coverage**: Testing all contract methods and edge cases * **Local Blockchain**: Using Mina's local blockchain for testing * **Account Management**: Working with multiple test accounts * **Event Verification**: Testing that events are emitted correctly ## Conclusion You've successfully built a complete MINA faucet smart contract with comprehensive tests. This project demonstrates fundamental smart contract patterns and provides a solid foundation for more advanced Zeko protocol development. The faucet showcases important concepts like token management, access control, event emission, and security patterns that are essential for building robust decentralized applications on the Mina Protocol using Zeko. --- --- url: /developers/examples-boilerplates.md --- # Examples & Boilerplates :::warning WIP: This section is under construction. ::: Browse ready-to-use code examples and boilerplate projects to kickstart your Zeko development. To get up and running quickly, see the [Quick Start guide](../introduction/quick-start.md) which walks through the available resources for developers, end users, and node operators. --- --- url: /about/faq.md --- # Frequently Asked Questions (FAQ) Here are answers to common questions about Zeko, Mina, and related concepts. ## General Zeko Questions * **What is Zeko?** Zeko is a Layer 2 (L2) ecosystem designed specifically for **Mina's zero-knowledge applications (zkApps)**. It provides developers with a robust platform to build and deploy zkApps with improved throughput and quick confirmation times. Zeko is meant to be a zkApp that contains a nested Mina ledger in its account state. * **What are the benefits of building on Zeko?** Key benefits include **enhanced scalability** (faster throughput than Layer 1 Mina), **rapid finality** (instant confirmation), **developer-friendliness** (seamless compatibility with Mina tools), and **interoperability** (seamless bridging to Layer 1). * **How is Zeko different from other Layer 2 solutions?** Zeko offers **seamless tooling integration**, meaning existing Mina developer tools, libraries, and even front-end browser wallets work out-of-the-box. Developers familiar with Mina can immediately begin building on Zeko without a steep learning curve, allowing for **rapid onboarding**. Zeko developers also benefit from the shared community and resources of the active Mina community. * **What kinds of applications can be built on Zeko?** A variety of applications can be built on Zeko, such as **decentralized exchanges (DEXs)**, **privacy-focused gaming platforms**, **scalable social media protocols**, and **anonymous identity solutions**, among many others. * **Can Zeko networks be customized?** Yes, Zeko's modular architecture allows you to create your own **custom rollup network** with tailored specifications. This enables application-specific optimization, control over security and governance, and acts as an innovation sandbox for experimenting with new ideas or consensus models without impacting the wider Zeko ecosystem. ## Core Concepts: zkApps, Smart Contracts, Proofs * **What is a zkApp?** A zkApp is a **zero-knowledge smart contract on Mina Protocol**. These smart contracts use zero-knowledge proofs to correct state transitions, enabling transactions to be proved off-chain and verified without revealing private data. A zkApp account is essentially a smart contract on Mina. * **What is a Smart Contract?** A smart contract is a **self-executing digital agreement** written in code and stored on a blockchain. They automate and enforce contract terms without needing intermediaries, leveraging blockchain technology for security and transparency. Smart contracts are particularly useful for parties to transact directly. * **How do zkApps leverage Zero-Knowledge Proofs (ZKPs)?** ZKPs allow a prover to convince a verifier that a statement is true without revealing any information beyond the truth of the statement itself. In the context of zkApps on Mina and Zeko, ZKPs (specifically zk-SNARKs) are used for **compressing computation** and proving that a smart contract function was executed correctly. They can also be used to hide parts of the transaction data. Mina Protocol is powered by a multi-tiered recursive zkSNARK proof that is small and constant in size. * **What is Recursion in Mina/Zeko?** Mina's custom proof system, Kimchi, supports arbitrary infinite recursive proof construction through integration with the Pickles recursive system. **Mina Protocol is the only blockchain that offers infinite recursion**. This recursion can be used to verify any zero-knowledge program as part of your zkApp. In o1js, you can use `ZkProgram()` to define the steps of a recursive program. Recursion is used internally within Mina as part of its decentralized prover and sequencing mechanism for rollups and is robustly supported by Kimchi. * **What is a zk-Rollup?** A zk-rollup is a **Layer-2 scaling solution** that increases blockchain transaction throughput without compromising security. They bundle ("roll up") many off-chain transactions into a single transaction, which is then verified and recorded on the main chain. The "zero-knowledge" aspect refers to using ZKPs to ensure the validity of all transactions in the batch without revealing their specifics. Zeko is described as a ZK Rollup on top of Mina. * **What is the Zeko Sequencer?** The sequencer is described as Zeko's "Transaction Powerhouse" or the "conductor of an orchestra". It is a server that performs several key roles: 1. **Transaction Collector**: Gathers transactions and applies them to the current state. 2. **Proof Verifier/Prover**: Proves the validity of transactions using zero-knowledge proofs. It proves that it has verified preconditions/permissions/authorization and correctly applied the transaction to the ledger. 3. **Batch Processor**: Groups transactions into batches. 4. **Layer 1 Bridge**: Sends ready batches to the main chain (Layer 1) via a smart contract to keep Layer 1 informed. The sequencer accepts transactions via GraphQL. * **What is Data Availability (DA)?** Data availability is the concept of ensuring that the required data to build the ledger's state (transactions) are shared with everyone. The proof of a transaction batch doesn't reveal how the ledger state is built, so DA is needed to prove that the necessary data has been shared, otherwise, the rollup could be stalled. It is a critical component of any rollup system, responsible for storing all transaction data that occurs on the rollup. * **How does Zeko handle Data Availability?** Zeko has a **modular Data Availability (DA) layer**. Sequencers post finished batches and receipts to the DA layer. This DA layer ensures that data has been broadcast, making it recoverable by all participants. Zeko currently uses a temporary DA-layer, a fork of an EVM chain with instant finality consensus. In the future, multiple sequencers may use the DA layer as a shared sequencing pool. ## Developer Concepts * **What are Account Updates?** An AccountUpdate is a **set of instructions for the Mina network**. Each `AccountUpdate` can make assertions about its account, apply updates, and make assertions about its child `AccountUpdates`. Transactions are structured as a list of trees of `AccountUpdates`. Permissions, preconditions, composability, and tokens are core features implemented using `AccountUpdates`. An account update includes an update part, preconditions part, and authorization part. An account update can only update one account. A transaction might consist of multiple account updates, e.g., one to subtract an amount and one to add an amount. * **What are Permissions?** Permissions are integral to zkApp development as they determine **who has the authority to interact and make changes** to a specific part of a smart contract. Different types of permissions exist for actions like changing the `zkappUri`, editing the actions state, setting the token symbol, sending MINA, setting the verification key for upgradeability, and more. Common permission types include `none` (always permitted), `signature` (permitted by the private key owner), and `proof` (permitted by a zkApp proof from executing a method). Permissions can be mixed. For zkApps, often permission is set to `proof` so that only transactions fulfilling the smart contract logic can update the state. Special `VerificationKeyPermission` types exist for upgradeability that depend on the transaction version. * **What are Actions and Reducers?** Using actions and a "lagging state" pattern, zkApps can **process concurrent state updates by multiple users**. Actions act as a built-in, "append-only" off-chain storage layer. To use actions, you declare a `reducer` object on the smart contract. A reducer takes a list of actions and reduces them into a single state. Smart contracts can dispatch actions. The "action state" is Mina's way of solving concurrency in smart contracts. **Note**: The reducer API in o1js is currently not production-safe due to a limitation in the `reduce()` method breaking if more than a hard-coded number (default: 32) of actions are pending. * **How do Custom Tokens work on Mina/Zeko?** Mina supports custom token functionality at a low level in the tech stack, treating them almost the same way as the native MINA token. This reduces boilerplate, means developers don't need to track accounts and balances themselves, and is more secure. Each account on Mina can have tokens associated with it. A token manager smart contract uses the `TokenContract` class and sets rules for minting, burning, and sending the custom token. **Minting** generates new tokens and adds them to an account's balance. **Burning** deducts tokens from an account's balance. **Sending** tokens between accounts must be approved by a zkApp. The `TokenContract.internal` namespace provides `mint`, `burn`, and `send` helper methods. Custom tokens are identified by a unique **Token id** derived from the zkApp, which is globally unique. **Token accounts** hold a balance of a specific custom token and are specified by a public key *and* a token id. The **Token Owner** is the zkApp account that created the token and is the only one that can mint, burn, or approve sending tokens. * **Are Mina and Zeko Developer Tools Compatible?** Zeko is mostly isomorphic to Mina, meaning you can use the **same tools and libraries** to develop zkApps as you would for Mina. Developers familiar with Mina can start building on Zeko immediately. ## User Information * **Is there a faucet for Zeko testnet?** Yes, there is a faucet available at https://zeko.io/faucet. ## Transaction Flow on Zeko * **What happens after I send a transaction on Zeko?** 1. You send the transaction (which includes `AccountUpdate`s) and its corresponding proof directly to the **sequencer**. On the client side, you first execute the smart contract function and then prove that you executed it correctly. The `proveTransaction` step is about proving correct execution, not primarily hiding data. 2. The sequencer receives the transaction. 3. The sequencer applies the transaction to the ledger. 4. The sequencer verifies some aspects of the transaction, such as preconditions, permissions, and that the proof/signature is valid. 5. The sequencer sends the transaction to the **Data Availability (DA) layer**. The DA layer consists of nodes replicating the same storage. This is where the individual transaction data (A, B, C, D) is sent. 6. The sequencer sends the transaction to a **prover**. This prover is needed to prove that the sequencer correctly verified the additional checks (preconditions/permissions/authorization) and applied the transaction correctly to the ledger, showing the state transition from Ledger A hash to Ledger B hash. 7. The sequencer accepts many transactions (e.g., A->B, B->C, C->D) and proves them, creating a **binary tree of proofs** until it has a single aggregated proof (e.g., A->D). This binary tree is not a Merkle tree. A transaction snark proves the transition from ledger A to ledger B. This proof compresses the validation of the whole batch of transactions into verification of a single snark. 8. The aggregated proof (e.g., A->D) is then sent to **Layer 1 (Mina)**. The zkApp's state on L1 gets updated to the new ledger hash (e.g., D). You send only the proof to L1, not the individual transactions. The proof is a constant size, achieving computation compression. 9. On L1, the aggregated proof is verified. If valid, the zkApp's state (which includes the current ledger hash) is updated. * **What are Preconditions?** Preconditions are conditions that must be true for an account update to be applied. These correspond to assertions made within an o1js method. For example, a precondition can assert the nonce of an account so a deployment transaction cannot be applied more than once. Network preconditions are not currently supported in Zeko, though a subset allowing checking the ledger hash might be supported in the future. Time preconditions are supported in Zeko. * **What is the difference between a Transaction Snark and a zkApp ZkSnark?** Both are types of ZkSnarks. A **zkApp ZkSnark** can be used to hide parts of the data. The **transaction snark** primarily uses the compression property of ZkSnarks to compress the validation of a whole batch of transactions into verifying one snark. If you hear just "snark", it likely means the zero-knowledge property (hiding) is not the primary focus. * **How are Zeko and Mina ledgers related?** Zeko's internal design aims to be a zkApp that contains a **nested Mina ledger** in its account state. Transfers of MINA between the "outer" (L1) and "inner" (L2) ledgers should be possible. The core rollup protocol doesn't handle transfer of value/MINA directly. There is a special account on L1 (outer) and a corresponding inner account on L2 that are part of the bridge between Mina and Zeko, used to sync states. Synchronization refers to syncing from L1 to L2, and Commit refers to syncing from L2 to L1. --- --- url: /users/getting-started.md --- # Getting Started Getting started with Zeko is designed to be straightforward, leveraging familiar tools from the Mina ecosystem. This section covers setting up your wallet, obtaining the necessary tokens, and connecting to the Zeko network. ## Setting up a Wallet Zeko is **mostly isomorphic to Mina**, meaning you can use the same tools and libraries as you would for Mina development. This includes using existing front-end browser wallets like **Auro Wallet**. To use Auro Wallet with Zeko, you need to [install it](https://www.aurowallet.com/) and create a wallet. :::danger When creating a new wallet, you will be given a seed phrase. This seed phrase is crucial for accessing your wallet and funds. Write it down and store it in a safe place. *Do not share it with anyone.* Having access to your seed phrase means having access to your funds. * If you lose your seed phrase, you will lose access to your wallet and funds. * If someone else gains access to your seed phrase, they can steal your funds. ::: Auro Wallet already supports Zeko, so you can use it to interact with Zeko dApps and the network without any additional setup. Select the Zeko network within your Auro Wallet to interact with Zeko dApps and the network. ### Adding the Zeko Network to Other Wallets If you are using a different wallet that supports custom networks, you can add the Zeko network manually * **Testnet URL**: `https://testnet.zeko.io` :::warning Zeko mainnet is not yet available. Stay tuned for updates on the mainnet launch. ::: ## Obtaining MINA Tokens To perform transactions and interact with dApps on Zeko, you will need tMINA tokens. * **Testnet**: For testing purposes on the Zeko testnet, you can obtain tMina tokens from the [Zeko Faucet](https://zeko.io/faucet). * **Mainnet**: Obtain Mina from a cryptocurrency exchange that supports MINA, or from other users. --- --- url: /operators/getting-started.md --- # Getting Started This section outlines the roles of different network operators, discusses required resources (to the extent available in the sources), and provides initial setup steps and tools. ## Overview of Operator Roles Running a Zeko network involves operating several types of infrastructure components. Zeko is a Layer 2 (L2) ecosystem designed for Mina's zero-knowledge applications (zkApps). It functions as a ZK Rollup on top of Mina Layer 1 (L1). The core operator roles described in the sources include: * **Sequencer**: The sequencer is a vital component, acting as the "conductor" or "Transaction Powerhouse" of the Zeko network. Its primary responsibilities include: * **Transaction Collection and Application**: The sequencer accepts transactions from users, typically via a GraphQL API, and applies them to the current state of the Zeko ledger. * **Proof Verification and Generation**: It proves the validity of transactions using zero-knowledge proofs. The sequencer sends transactions to provers and also proves its own verification of aspects like preconditions, permissions, and authorizations, as well as the correct application of the transaction to the ledger. It aggregates proofs from multiple transactions into a single proof for a batch. * **Batch Processing**: The sequencer groups transactions into batches for more efficient processing and settlement on Layer 1. * **Data Posting**: It sends the transaction data to the Data Availability (DA) layer. * **Layer 1 Commitment**: Once a batch is ready and consensus is reached on the DA layer, the sequencer posts the aggregated proof to the ZK Rollup contract on Mina L1. This updates the L1 state and officially finalizes the batch and included bridge transfers. * **Bridge Management**: The sequencer handles L1->L2 deposit and L2->L1 withdrawal transfer requests by creating transfer requests for proving and facilitating the fetching of proved account updates. * Sequencers receive fees, paid in MINA. Decentralization of sequencers is being explored through an auction model. * **Prover / Proof Generator**: These components are responsible for generating the necessary zero-knowledge proofs. * The sequencer dispatches transactions to provers. * The Zeko system model includes "Proof Generators" as actors, specifying roles like **Snark workers** (generating proofs for L2 transactions and blocks) and **Aggregators** (aggregating proofs). * Mina's underlying proof system, Kimchi, supports infinite recursive proof construction, leveraging the Pickles recursive system. Tree recursion, used internally in Mina, is supported robustly and is part of the sequencing mechanism for rollups. * **Data Availability (DA) Layer Nodes**: This layer is a critical component for storing all transaction data that occurs on the rollup. * The DA layer consists of nodes that replicate the same storage. * DA layer validators (nodes) are responsible for storing historical data, publishing data availability proofs, and ensuring that required data is broadcast so the ledger state can be built by everyone, preventing the rollup from being stalled. * Validators on the DA layer sign the hashes of the batches. * Zeko currently uses a temporary DA layer implemented as a fork of the Ethermint (EVM) chain. The initial implementation uses a set of validators jointly managed by the project teams. Future development aims to decentralize the DA layer, allowing anyone to run and validate it. ## Hardware and Software Requirements :::warning WIP: This section is under construction. ::: ## Initial Setup and Configuration :::warning WIP: This section is under construction. ::: Setting up Zeko network infrastructure involves building and running specific software components and potentially deploying smart contracts on both L1 and the DA layer. * **Building and Running the Sequencer**: * The sequencer application can be built using the `dune build` command, often specifying a profile like `devnet`. * To run the sequencer, you execute the built binary (`run.exe`), providing necessary configuration options via command-line flags or environment variables. Essential environment variables include `DA_PROVIDER`, `DA_PRIVATE_KEY`, and `MINA_PRIVATE_KEY`. Command-line options cover details such as the GraphQL port (`-p`), REST server (`--rest-server`), sequencer zkApp public key (`--zkapp-pk`), maximum pool size (`--max-pool-size`), commitment period (`--commitment-period`), DA contract address (`--da-contract-address`), and database directory (`--db-dir`). * The sequencer can also be run using a provided Docker image. * **Deploying the Rollup Contract**: * The ZK Rollup contract needs to be deployed on the Mina Layer 1 chain. This contract acts as the anchor on L1, storing the state root of the L2 ledger. * Deployment is performed using a script (`deploy.exe`) executed via `dune exec`. This requires specifying the `MINA_PRIVATE_KEY` (for the signer) and the `DUNE_PROFILE`, along with options for the REST server and test accounts path. * **Setting up the DA Layer**: * The temporary DA layer implementation is based on a fork of `go-ethereum`. Setting it up involves cloning the `dcSpark/go-ethereum` repository, checking out the `release/1.10-mina` branch, and building the `geth` binary using `make geth`. * Deploying the necessary data availability contract involves starting the local `geth` instance (`npm run geth:start`) and running a Hardhat script (`npx hardhat run scripts/deploy.ts --network dev`). * **Running the Archive Relay Adapter**: * To index the history of the Zeko rollup in a standard Mina archive node, the Zeko archive relay adapter can be used. * This adapter connects to the Zeko sequencer, subscribes to new changes (blocks), and relays them to a configured Mina archive node. * It is run using `dune exec ./archive_relay/run.exe`, requiring configuration specifying the Zeko sequencer URI (`--zeko-uri`), the archive node's host (`--archive-host`), and port (`--archive-port`). A `--bootstrap` flag can be used. * A Docker image is also available for the archive relay adapter. ### Useful Repositories and Tools Several repositories and tools are relevant for Zeko network operators: * [**Zeko Main Repository**](https://github.com/zeko-labs/zeko): The primary codebase for Zeko infrastructure components like the sequencer and prover. * [**DA Layer Repository**](https://github.com/dcSpark/go-ethereum): The temporary data availability layer's implementation is based on the `dcSpark/go-ethereum` repository fork. * [**Build System Tools**](https://dune.build/): `dune` is the build system used for compiling and running Zeko's OCaml-based components. `make` is used for building `geth` and Docker images. * [**Mina/zkApp Tools**:](https://github.com/o1-labs/o1js) `o1js` is the programming library for zkApps on Mina and Zeko. While primarily a developer tool, understanding it is crucial for debugging and interacting with zkApp logic. --- --- url: /developers/getting-started.md --- # Getting Started Developers from all backgrounds are using **Zeko** to power their zkApps and reimagine what’s possible in the zkInternet era. You already know [What is Zeko](../introduction/what-is-zeko.md) and [Why you should Build with Zeko](../introduction/why-zeko.md), so let’s get started launching your own zkApp or front-end on Zeko today. **Zeko provides a fully Mina-equivalent application layer** for building and deploying zkApps, meaning you can use the same tools and libraries and your development environment setup for building zkApps on Zeko will largely follow the standard setup for Mina zkApp development. ## Step 1 – Intro and Education > For developers new to Zeko, ZK, and Mina If you are new to building on Mina or with zkApps, it is highly recommended to **start with the official [o1js documentation](https://docs.o1labs.org/o1js/)**. Zeko is an *isomorphic zkRollup on Mina*, so we reference the deep library of Mina resources wherever relevant. > \[!TIP] πŸ’‘ Developer Environment Setup πŸ’‘ > > Follow the [o1js Getting Started guide](https://docs.o1labs.org/o1js/getting-started/what-is-a-zk-constraint-system) to set up your development environment for building zkApps. Visit the [**Zeko GitHub repo**](https://github.com/zeko-labs/zeko/tree/compatible/src/app/zeko), the source code for the Zeko protocol, including the sequencer and data availability components. ### o1js Smart Contract Language Intro **o1js** is a general-purpose zero-knowledge framework that gives you the tools to create zk proofs and write arbitrary zk programs (zkApps), leveraging a rich set of built-in provable operations. The o1js framework is packaged as a single TypeScript library that can be used in major web browsers and Node.js. > \[!TIP] πŸ’‘ o1js πŸ’‘ > > Refer to [introduction to o1js](https://docs.o1labs.org/o1js/) and the [o1js GitHub repo](https://github.com/o1-labs/o1js). ### Advantages of Using Zeko Zeko is different from Mina in several ways for developers and users: * **Near-instant confirmation of transactions** * **Dynamic parallel prover scaling** for higher throughput * **Data-availability layer** for higher storage * **Increased account updates** for greater app complexity * **Framework for launching new zkRollups and AppChains** * **Delegated zkApp and AppChain proving** *(future)* ### Power of zkApps zkApps are zero-knowledge programs that are **Turing complete**, and offer enhanced privacy with client-side execution and private inputs, have off-chain computation and composability with **no gas fees**. > \[!TIP] πŸ’‘ zkApps πŸ’‘ > Refer to [zkApps Overview for new zk-Devs](https://docs.o1labs.org/o1js/zkapps/intro) and [zkApps for Ethereum Devs](https://docs.o1labs.org/o1js/zkapps/intro). ## Step 2 – Demo zkApps and UIs > For Mina-native or ZK-adjacent devs * [**Write and Deploy a zkApp Today**](https://docs.o1labs.org/o1js/zkapps/intro) * Make sure to **[get a wallet & faucet tMINA](https://zeko.io/faucet) on Zeko** or **[Bridge tMINA](https://alpha.bridge.zeko.io) from Mina to Zeko**, and check your activity on **[ZekoScan testnet explorer](https://zekoscan.io/testnet/home)**. *(Auro wallet browser extension v2.4.1 or mobile app v2.2.0 or later are required)* * Mina devnet [faucet](https://minascan.io/devnet/home) and [MinaScan](https://minascan.io/mainnet/home) explorer may also be helpful resources * **Write your smart contract using the [zkApp CLI](https://github.com/o1-labs/zkapp-cli)** ### Taking zkApps to the Next Level > Useful links and code examples * **LuminaDex SDK for front-end swaps on Zeko and Mina** * The [SDK library](https://sdk.luminadex.com/) is designed to simplify the integration of the [LuminaDex contracts](https://github.com/Lumina-DEX/lumina/tree/main/packages/contracts) in a website. * [Beta Website](https://lumina-devnet.netlify.app/) using SDK and Lumina audited contracts. View the [Source Code on GitHub](https://github.com/Lumina-DEX/lumina/tree/main/packages/dex-ui). * [Mina Fungible token standard](https://github.com/MinaFoundation/mina-fungible-token): example code for custom token implementations * Other examples / demos: * [Prove you know the answer to a question (10 / 2 + 2 = ?)](https://github.com/RaidasGrisk/zkapp-ui) * [Off-chain voting Proof of Concept (POC)](https://github.com/Trivo25/offchain-voting-poc) * [Cryptographic Proof of NFT Endorsement](https://github.com/racampos/cpone) * [easy-mina-deploy](https://github.com/MinaPlayground/easy-mina-deploy) (deploy with one command by specifying your smart contract and keys) ## Step 3 – Accelerated Growth > For experienced developers and teams ### Advanced Tools & Tutorials Find out more about advanced tools and tutorials for zkApps development. #### Intelligence Tools and AI * [Mina Arbitrated Contracts](https://mac.sqrtxx.com/) (MAC) – a zkApp that creates zkApps * [o1js MCP server](https://github.com/o1-labs/mcp-o1js/tree/main/packages/mcp-server-o1js#usage-with-claude-desktop) (search o1js docs, codebase, Mina Discord forums with Claude & Cursor) * [zkApps AI Chatbot](https://zkappsumstad.com/) (GPT language model, extensively trained on Mina, zkApps, and o1js) #### zkApp Developer In-Depth [Tutorials](https://docs.o1labs.org/o1js/tutorials/hmac/hmac-basics) * [Deploy to a Network](https://docs.o1labs.org/o1js/zkapps/intro) * [zkApp Browser UI](https://docs.o1labs.org/o1js/zkapps/intro) #### Cross-chain signing and modular zkApp deployment using TEE * [Silvana](https://login.silvana.dev/) * [Silvana docs](https://docs.silvana.one/) ### Community The Zeko community is mostly active on Discord : * [**Zeko Discord**](https://discord.gg/edF9vzD7en) * [**Mina Discord**](https://discord.com/invite/minaprotocol) ### Production zkApps * [**ZekoTokens**](https://zekotokens.com/): Deploy tokens on Zeko * **Solis, powered by LuminaDex:** *link TBD* * **Obirium:** *link TBD* --- --- url: /about/glossary.md --- # Glossary :::tip Please refer to the [o1js documentation](https://docs.o1labs.org/o1js/) for more additional explanations of terms related to Mina and zkApps. ::: ## Account On Mina, an account is uniquely identified by an account ID, which is a tuple of a public key and a token ID. Accounts can hold a balance of the native MINA token or a specific custom token (referred to as a **Token Account**). Accounts have associated permissions and state. This is distinct from Bitcoin's UTXO model of maintaining ledger state. ## Account Update A set of instructions for the Mina network. Every zkApp transaction on Mina is composed of one or more account updates. An account update can update only one account at a time. Its structure includes update, preconditions, and authorization parts. Account Updates can make assertions about their associated account, apply updates to it, and make assertions about their child AccountUpdates. They also specify any balance changes. Authorization can be `None`, `Signature`, or `Proof`, depending on the account's permissions. ## Actions In Mina zkApps, actions act as a built-in, "append-only" off-chain storage layer. Used with the **Reducer** and a "lagging state" pattern to process concurrent state updates by multiple users. Actions are dispatched using the reducer's `dispatch` method. Communication from Layer 1 (L1) to Layer 2 (L2) in Zeko happens by posting actions to the zkApp account on L1. Account updates can be authorised by a proof to add an action. You can find more information in the [Actions & Reducers guide](https://docs.o1labs.org/o1js/zkapps/actions-and-reducers) of the o1js docs. ## Blockchain A decentralised digital ledger maintained by a distributed network of computers. Data is organised into chronologically arranged blocks secured by cryptography. Ensures data integrity through immutability via cryptography and consensus mechanisms. Transactions happen between users without intermediaries. Different types include public, private, and consortium blockchains. ## Consensus Mechanism A set of rules that govern how nodes in a distributed network come to an agreement about the state of the blockchain and the validity of transactions. Ensures that all nodes in the network have the same copy of the ledger. Examples include **Proof of Work (PoW)** and **Proof of Stake (PoS)**. ## Cryptography The science of using mathematical theories and computation to secure information. Essential for blockchain to maintain a secure, transparent, and tamper-resistant record. Includes techniques like hashing (converting data into a fixed-size string) and public-key cryptography (asymmetric cryptography for secure transactions). ## Custom Tokens Tokens built on Mina using the `TokenContract` class. Supported at a low level in the Mina tech stack, treated almost like the native MINA token. Any account on Mina can have tokens associated with it. A **Token Manager Account** is a smart contract that sets the rules for minting, burning, and sending the custom token. ## Data Availability (DA) Layer A crucial component of a rollup system responsible for storing all the transaction data that occurs on the rollup. Since the proof of a transaction batch doesn't reveal how to build the ledger's state, the DA layer is needed to prove that the necessary transaction data has been shared with everyone. In Zeko, the sequencer posts the transaction batch and receipts to the DA Layer. Zeko has a modular DA layer. Zeko currently uses a DA layer consisting of a multisig service with a few trusted parties, and aims to transition towards [Celestia](https://docs.celestia.org/learn/how-celestia-works/data-availability-layer). ## Decentralisation Information is stored across a network of computers (nodes) rather than a single central server. Refers to the distribution of control and decision-making power among users rather than a single entity. Decentralised networks are highly resistant to attacks. ## Layer 1 (L1) The base layer or main chain of a blockchain network. In the context of Zeko, this refers to the Mina Protocol blockchain. Zeko settles batches of transactions on Layer 1. Communication from L1 to L2 (bridging) happens by posting **Actions** to the zkApp account on L1. ## Layer 2 (L2) A scaling solution built on top of a **Layer 1** blockchain. Zeko is a Layer 2 ecosystem specifically designed for Mina's zkApps. Users interact with the **Sequencer** on L2. Zeko contains a nested Mina ledger as its L2 state. Communication from L2 to L1 happens via actions posted to a corresponding inner account on L2, which are synchronised on commit. ## Merkle Tree A data structure that represents a set and provides an efficient way to prove that an element is included in the set. Used for the ledger in Mina because the ledger is a set of accounts. It serves a different purpose than the transaction snark binary tree used for batch proofs. ## Mina Protocol A **Layer 1** blockchain known for its small, constant size due to recursive **Zero-Knowledge Proofs** (zk-SNARKs). Supports **zkApps** (zero-knowledge smart contracts). Offers infinite recursive proof construction through integration with the Pickles recursive system. Supports custom token functionality. The core idea is to offload transaction processing work from nodes by proving transactions off-chain on the client. ## Permissions An integral part of zkApp development that determine who has the authority to interact with and make changes to a specific part of a smart contract. Set on an account's permissions field. **Account Updates** require authorisation (Proof, Signature, or None) that must meet the permissions set on the account. `Proof` authorisation is typically required for zkApps to change state, subtract money, or add actions, proving correct execution of a method. ## Proof of Stake (PoS) A **Consensus Mechanism** where validators are chosen based on the amount of cryptocurrency they "stake" in the network. Used by newer blockchains like Ethereum. ## Proof of Work (PoW) A **Consensus Mechanism** where miners compete to solve complex mathematical problems to add blocks to the blockchain. Used by Bitcoin. Requires significant computational power and energy. ## Prover / Verifier In a **Zero-Knowledge Proof** system, the Prover is the party who wants to prove the truth of a statement. The Verifier is the party who verifies the proof without learning the secret information. ## Recursion In the context of Mina and **zkApps**, refers to the ability to verify one zero-knowledge proof inside another, enabling recursive proof construction. Mina Protocol is the only blockchain offering infinite recursion. Used internally by Mina for its decentralised prover and sequencing mechanisms. ## Reducer In o1js, an object declared on a smart contract used to take a list of **Actions** and reduce them. Currently has limitations for production applications with more than a hard-coded number of pending actions. Provides `dispatch` and `reduce` methods. ## Sequencer In **Zeko**, the sequencer is a server responsible for collecting transactions, applying them to the ledger, posting them on the **Data Availability (DA) Layer**, proving them using zero-knowledge proofs, and sending a commit to the **Layer 1 (L1)**. Users send transactions directly to the sequencer. The sequencer verifies preconditions, permissions, and authorisations and aggregates transactions into batches, creating a single proof for the batch to send to L1. ## Smart Contract A self-executing digital agreement written in code and stored on a blockchain. Operates without intermediaries. Defines the terms, rules, and conditions of an agreement. Once invoked and conditions are met, it executes automatically and immutably on the blockchain ledger. **zkApps** are zero-knowledge smart contracts on Mina. ## Token Account See [**Account**](#account). ## Token ID Unique identifiers that distinguish different types of custom tokens on Mina. Globally unique, derived from the zkApp that created the token. Derived from hashing the public key and token ID. ## Token Manager Account See [**Custom Tokens**](#custom-tokens). ## Token Owner The **zkApp** account that created, facilitates, and governs how a custom token can be used. This account is the only one that can mint, burn, or approve sending tokens. ## TokenContract Class The base class for creating **Custom Tokens** on Mina. Includes internal helper methods for core token operations like minting, burning, and sending. ## Transaction Snark In Mina/Zeko, used to prove the transition from one ledger state to another. Individual transactions or account updates form the leaves of a binary tree, which are merged into a root snark that proves the whole batch. Primarily used for compressing the computation of validating a batch of transactions into verifying a single snark. ## Zero-Knowledge Proof (ZKP) A cryptographic technology allowing verification of a statement's truth without revealing the statement itself. A method where a **Prover** convinces a **Verifier** they know something, without revealing the information. Requires completeness (property allowing an honest prover to construct a valid proof) and soundness (preventing the adversary to construct a valid proof). Used for privacy and security in digital transactions. * **zk-SNARKs**: zkSNARK is a zero knowledge succinct non-interactive argument of knowledge. It is a specific zero knowledge proof construction that works great for blockchain use cases. Succinct means that verifying of proof is cheaper than doing the calculation itself so it's great for scaling use cases, non-interactive means that prover can just upload the proof to the blockchain and it can be verified without any interaction with the prover and argument of knowledge, is a proof that not only something is true, but I am proving that I also know a witness. An example of would be proving that there exists a private key to some public key - that is trivial proof because every public key has a private key. Argument of knowledge would be to prove that I also know the private key. All of these properties are needed for the zk proofs to be viable for blockchain usecases. * **zk-STARKs**: A different type of ZKP, zkSTARKs are technically also zkSNARKs with a different tradeof: usually without trusted setup, with post-quantum safety and faster proving time, however they usually have bigger proof sizes and slower verification time. ## Zeko A **Layer 2 (L2)** ecosystem built on Mina Protocol, specifically for **zkApps**. It aims to provide improved throughput and quick confirmation times. Zeko is implemented as a zkApp on Mina's **Layer 1**, containing a nested Mina ledger within its account state. It reuses most of Mina's tooling and transaction snarks. Benefits include enhanced scalability, rapid finality, developer-friendliness, and interoperability. Supports a modular architecture for custom **zkRollups**. ## zkApp A zkApp is a zero-knowledge smart contract on Mina Protocol. These smart contracts leverage zero-knowledge proofs to ensure correct state transitions, allowing transactions to be proven off-chain and verified without revealing private data. They are primarily about proving the correct execution of the smart contract logic. zkApps on Mina enable the creation of arbitrary programs using zero-knowledge cryptography. They allow for programmable privacy and offer constant verification time for transactions. They can be built to interact with tokens, such as swapping or depositing MINA. When interacting with a zkApp, certain actions, like changing state or adding actions, require authorisation via a proof that you've correctly executed one of the contract's methods. Each zkApp transaction is composed of one or more account updates. For more information, see the [zkApps section](https://docs.o1labs.org/o1js/zkapps/intro) of the o1js docs. ## ZkProgram A construct in o1js used to define the steps of a recursive program. Methods execute off-chain. Can be embedded within a **Smart Contract** method to verify the proof of execution. Also used to prove and verify arbitrary zero knowledge programs. ## zk-Rollup A **zk-rollup** is a **Layer 2 scaling solution** for blockchain networks. Its primary purpose is to **increase transaction throughput** while maintaining security. This is achieved by **bundling ("rolling up") many off-chain transactions** into a single transaction. A **Zero-Knowledge Proof (ZKP)** is generated for this batch, which attests to the validity of all the transactions within the bundle. This single transaction and its proof are then submitted and verified on the main blockchain (Layer 1), significantly reducing the amount of data processed on-chain and leading to **faster and cheaper transactions**. --- --- url: /operators/guides-tutorials.md --- # Guides & Tutorials * [Launch a Rollup](./guides/launch-rollup.md) * [Run a DA node](./guides/da-layer.md) * [Run an archive node](./guides/archive-node.md) * [Rollup on Phala](./guides/rollup-on-phala.md) --- --- url: /users/guides-tutorials.md --- # Guides & Tutorials :::warning WIP: This section is under construction. ::: --- --- url: /developers/guides-tutorials.md --- # Guides & Tutorials * [Custom Network](./guides/custom-network.md) * [Creating a Faucet](./guides/create-faucet.md) --- --- url: /users/guides/dapp.md --- # Interacting with a Dapp :::warning WIP: This section is under construction. ::: --- --- url: /operators/guides/launch-rollup.md --- # Launch a Rollup In this guide we will create a `betternet` - an L2 Zeko Rollup for Mina Devnet. At a minimum, you need to run the following Zeko components: * `Sequencer` * `DA Layer` * `Prover` We will use [docker compose](https://docs.docker.com/reference/cli/docker/compose/) to define the whole stack in a single file. TL;DR skip to the [Bootstrap process](#bootstrap-process) ## Prerequisites ### System Requirements * Linux or macOS (Windows WSL2 works too) * At least **4 CPU cores**, **24GB RAM** ### Installed Software * `Docker` ## Overview ![Architecture](./zeko-components.png) We are going to: * Create a `sequencer` wallet and make sure it has funds. * Create a `faucet` wallet. * Create a `deployment`/`circuits` config * Deploy a created configuration * Start a `betternet` L2 stack ### Wallets Deploying a rollup the following wallets are mentioned: * `sequencer` - A wallet to commit to zkApp. ***Has to be even*** * `faucet` - A wallet that holds the funds. ***Cannot reuse sequencer's wallet*** * `da-layer` - Each `da-layer` node is started with its wallet. * `fee-payer` - A wallet that pays fees on commits. (We will use `sequencer`) * `pause` - A wallet authorised to pause rollup. ***Has to be even*** (We will use `sequencer`). ### Project Structure Layout of the project directory: ``` project-root/ └── docker-compose.yaml ``` > **Note:** `docker-compose.yaml` is using docker volumes to store data. If you prefer to mount local directories instead - change accordingly. ### Volumes/files | Volumes | Files | Purpose | | ----------------- | ----------------------- | ---------------------------------------------- | | `keys_data` | `sequencer-sk` | L1 private key to post proofs and pay fees | | `keys_data` | `sequencer-pk` | L1 Public key used in deploy step | | `keys_data` | `faucet-sk` | Secret key used to distribute tokens inside L2 | | `keys_data` | `faucet-pk` | Public key | | `keys_data` | `da-node-sk` | Private key of the DA node | | `keys_data` | `da-node-pk` | Public key of the DA node (used by sequencer) | | `initdb_data` | | Schema file(s) to bootstrap postgresql | | `postgresql_data` | | Persistent storage for postgresql | | `rabbitmq_data` | | Persistent storage for RabbitMQ | | `circuits_data` | `betternet-config.json` | Circuits config used by sequencer/prover | | `da-layer_data` | | Persistent storage for da-layer | | `sequencer_data` | | Persistent storage for sequencer | > **Note:** Keys must NOT have newlines or extra spaces. *** ### Service Overview * `postgresql` - Used by sequencer. * `rabbitmq` - Messaging layer used between the sequencer and the prover(s). * `da-layer` - Data Availability layer for the `betternet`. * `prover` - Generates zk-proofs for work submitted by the sequencer. * `sequencer` - Runs the rollup logic, batches transactions, interacts with DA layer, and posts proofs to L1. ### Ports Exposed | Service | Port | Description | | --------- | ------ | --------------------- | | sequencer | `1923` | sequencer Graphql API | | da-layer | `1924` | da-layer rpc API | | postgres | `5432` | Database | | rabbitmq | `5672` | Messaging queue | *** ## Bootstrap process ### Getting/Creating configuration files * Copy `docker-compose.yaml` to your project folder. ::: details Click to expand `docker-compose.yaml` ```yaml services: init-db: image: docker.io/zekolabs/zeko:latest container_name: init-db volumes: - initdb_data:/data/initdb - circuits_data:/data/circuits entrypoint: - sh - -c command: > "echo 'ALTER DATABASE sequencer OWNER TO sequencer;' > /data/initdb/init.sql && echo 'Bootstrap complete' && exit 0" init-config: image: docker.io/zekolabs/zeko:latest container_name: init-config working_dir: /data volumes: - circuits_data:/data/circuits - keys_data:/data/keys entrypoint: - sh - -c restart: "no" command: > "while [ ! -f /data/keys/.keys_created ]; do sleep 2; done; exit 0" init-deploy: image: docker.io/zekolabs/zeko:latest container_name: init-deploy depends_on: init-config: condition: service_completed_successfully da-layer: condition: service_started working_dir: /data volumes: - circuits_data:/data/circuits - keys_data:/data/keys entrypoint: - bash - -c restart: "no" command: > "while [ ! -f /data/circuits/.deployed ]; do sleep 2; done; exit 0" postgres: depends_on: init-db: condition: service_completed_successfully image: postgres:16 container_name: postgres environment: POSTGRES_DB: sequencer POSTGRES_USER: sequencer POSTGRES_PASSWORD: sequencer volumes: - postgresql_data:/var/lib/postgresql/data - initdb_data:/docker-entrypoint-initdb.d ports: - "5432:5432" restart: unless-stopped rabbitmq: image: rabbitmq:latest container_name: rabbitmq volumes: - rabbitmq_data:/var/lib/rabbitmq ports: - "5672:5672" restart: unless-stopped da-layer: depends_on: init-config: condition: service_completed_successfully image: docker.io/zekolabs/zeko-da:latest container_name: da-layer ports: - "1924:1924" environment: ZEKO_SIGNATURE_KIND: "testnet" entrypoint: bash -c command: | "export MINA_PRIVATE_KEY=$(cat /keys/da-layer-sk) && \\ exec zeko-da \\ run-node \\ --port 1924 \\ --db-dir /data/db \\ --network-id testnet" volumes: - da-layer_data:/data - keys_data:/keys:ro restart: always prover: image: docker.io/zekolabs/zeko:latest container_name: prover depends_on: rabbitmq: condition: service_started init-config: condition: service_completed_successfully environment: ZEKO_SIGNATURE_KIND: "testnet" ZEKO_CIRCUITS_CONFIG: "/circuits/betternet-config.json" RABBITMQ_USER: "guest" RABBITMQ_PASSWORD: "guest" volumes: - circuits_data:/circuits:ro entrypoint: bash -c command: | "exec zeko-prover \\ run-server \\ --mq-host rabbitmq:5672" restart: on-failure sequencer: image: docker.io/zekolabs/zeko:latest container_name: sequencer depends_on: init-deploy: condition: service_completed_successfully rabbitmq: condition: service_started prover: condition: service_started postgres: condition: service_started da-layer: condition: service_started environment: ZEKO_PROGRESS_STYLE: "percent" ZEKO_SIGNATURE_KIND: "testnet" ZEKO_CIRCUITS_CONFIG: "/circuits/betternet-config.json" POSTGRES_URI: "postgres://sequencer:sequencer@postgres:5432/sequencer" RABBITMQ_USER: "guest" RABBITMQ_PASSWORD: "guest" volumes: - sequencer_data:/data - circuits_data:/circuits:ro - keys_data:/keys:ro ports: - "1923:1923" entrypoint: - bash - -c command: | "export MINA_PRIVATE_KEY=$(cat /keys/sequencer-sk) && \\ export DA_LAYER_KEY=$(cat /keys/da-layer-pk) && \\ exec zeko-run \\ -p 1923 \\ --l1-uri https://gateway.mina.devnet.zeko.io \\ --archive-uri https://gateway.mina.archive.devnet.zeko.io \\ --max-pool-size 10 \\ --commitment-period 300 \\ --da-node da-layer:1924 \\ --da-quorum 1 \\ --da-key $$DA_LAYER_KEY \\ --mq-host rabbitmq:5672 \\ --db-dir /data/db \\ --checkpoints-dir /data/checkpoints \\ --postgres-uri postgresql://sequencer:sequencer@postgres:5432/sequencer \\ --fee-modifier 0.1" restart: on-failure volumes: initdb_data: postgresql_data: rabbitmq_data: circuits_data: sequencer_data: da-layer_data: keys_data: ``` * Start all services ```bash docker compose up -d ``` * Create `circuits`/`deploy` config and `sequencer`/`da-layer` keys 1. Enter `init-config` container: ```bash docker compose exec -it init-config bash ``` > **Note:** This image is used to run Zeko sequencer/prover. Additionally it contains `zeko-cli`/`zeko-deploy` binaries. 2. Create `deployment`/`circuits` config ```bash zeko-cli generate-circuits-config \ --circuits-config-output /data/circuits/betternet-config.json \ --deploy-config-output /data/circuits/betternet-deploy.json ``` 3. Create `sequencer`/`da-layer` keypairs > * `/data/keys/sequencer-pk` > * `/data/keys/sequencer-sk` > * `/data/keys/faucet-pk` > * `/data/keys/faucet-sk` > * `/data/keys/da-layer-pk` > * `/data/keys/da-layer-sk` ```bash # create `sequencer` keypair zeko-cli generate-even-key | while read label1 label2 value; do if [ "$label1" = "Private" ]; then echo "$value" > sequencer-sk elif [ "$label1" = "Public" ]; then echo "$value" > sequencer-pk fi done # create `faucet` keypair zeko-cli generate-even-key | while read label1 label2 value; do if [ "$label1" = "Private" ]; then echo "$value" > faucet-sk elif [ "$label1" = "Public" ]; then echo "$value" > faucet-pk fi done # create `da-layer` keypair zeko-cli generate-even-key | while read label1 label2 value; do if [ "$label1" = "Private" ]; then echo "$value" > da-layer-sk elif [ "$label1" = "Public" ]; then echo "$value" > da-layer-pk fi done mv {sequencer,faucet,da-layer}-{sk,pk} /data/keys touch /data/keys/.keys_created ``` ### Fund `sequencer` wallet 1. Using [Auro Wallet](https://www.aurowallet.com/) or other preferred method import sequencer key created in the previous step 2. Go to [Mina Devnet faucet](https://faucet.minaprotocol.com/) and use faucet to add funds to the `sequencer` wallet 3. After a few minutes you should be able to see the funds in your ***Auro Wallet*** ### Deploy `betternet` configuration * Enter `init-deploy` container: ```bash docker compose exec -it init-deploy bash ``` > **Note:** It should also start `da-layer` container. * From inside `init-deploy` container run deploy ```bash export MINA_PRIVATE_KEY=$(cat /data/keys/sequencer-sk) export ZEKO_DEPLOY_CONFIG=/data/circuits/betternet-deploy.json export ZEKO_CIRCUITS_CONFIG=/data/circuits/betternet-config.json export SEQUENCER_PK=$(cat /data/keys/sequencer-pk) export FAUCET_PK=$(cat /data/keys/faucet-pk) zeko-deploy --account-creation-fee 1 \ --da-keys $(cat /data/keys/da-layer-pk) \ --da-quorum 1 \ --l1-uri https://gateway.mina.devnet.zeko.io \ --pause-key $SEQUENCER_PK \ --sequencer-key $SEQUENCER_PK \ --faucet-account $FAUCET_PK \ --da-node da-layer:1924 && \ touch /data/circuits/.deployed ``` You should see the output: ``` outer secret key: EKE.. outer public key: B62.. holder secret key: EKD.. holder public key: B62.. token holder secret key: EKF... token holder public key: B62... Creating imt (* Post genesis batch *) (* Post the whole genesis diff with all the accounts *) (* Deploy contract *) ``` > **Note:** If successful,`init-deploy` container should exit with `(0)` ### Wait for zkapp transaction to succeed Check your sequencers zkApp transaction on Mina L1. See example zkApp transaction status [here](https://minascan.io/devnet/account/B62qrWCK3mn8iYvopsRRfuUL9f6h2B6ydqHAYBVuBsh7eQ1BvQsqKrE/zk-txs) ### If all the steps were performed correctly you have the following: * Sequencer exposing graphql endpoint under `http://localhost:1923/graphql` * DA layer * Prover accepting work from the sequencer. * `rabbitmq` service used by sequencer/prover. * `postgresql` service used by sequencer. ### Configure Auro wallet browser extension Import `sequencer`/`faucet` wallets into your Auro wallet. ![Import wallets](./import-wallet-to-auro.png) Add/select your newly deployed `betternet` network. ![Configure betternet network](./select-betternet-network.png) You can start sending transactions to your `sequencer`! ## Troubleshooting Check logs ```bash docker compose logs -f ``` ## Stopping the Stack ``` docker compose down ``` To remove persistent data: ``` docker compose down -v ``` --- --- url: /operators/guides/rollup-on-phala.md --- # Launch a rollup on Phala In this guide we will cover how to launch your rollup on [Phala](https://docs.phala.com/phala-cloud). ## Prerequisites You will need: * [Phala account](https://docs.phala.com/phala-cloud/getting-started/sign-up-for-cloud-account) * [Phala cli tool](https://docs.phala.com/phala-cloud/phala-cloud-cli/overview#cli-overview) ## Overview We are going to: * Create a phala CVM * Create a rollup on deployed CVM ## Bootstrap process ### Create a CVM On your accounts dashboard click `Deploy`. * Paste docker-compose.yaml contents from the [Launch a Rollup](./launch-rollup.md) guide * Select 32G instance * Add your public ssh key to be able later to connect to your CVM * Deploy! ![Deploy a CVM](./create-phala-instance.png) > **Note:** To deploy a rollup we need at least 24G of RAM, therefore we have to select 32G instance (this can be redeployed on a 16G later). ### SSH to your CVM * From your terminal login to your Phala cloud ```bash phala login ``` * Get a list of CVMs * SSH to a wanted CVM * You should be able to exec into `init-config` container ![SSH into Phala CVM](./phala-ssh.png) ### Bootstrap a rollup With a working docker setup now you can follow our [Launch a Rollup](./launch-rollup.md) guide. --- --- url: /background/layer-2-scaling.md --- # Layer 2 Scaling Solutions *Blockchain technology, while revolutionary, faces challenges related to **scalability and throughput** on the base layer (Layer 1). As networks grow and usage increases, transaction speeds can slow down and fees can rise. This can limit the types of applications that can be practically built and used.* ## The Need for Layer 2 Solutions **Layer 2 (L2) scaling solutions** are designed to address these limitations by handling transactions off the main blockchain and submitting proofs or summaries back to Layer 1. Zeko is a Layer 2 (L2) ecosystem specifically designed for Mina's zero-knowledge applications (zkApps).It provides developers with a platform to build and deploy zkApps with **improved throughput and quick confirmation times**. > \[!TIP] πŸ’‘ Zeko vs Mina πŸ’‘ > Building on Zeko offers **enhanced scalability** (faster throughput than Layer 1 Mina) and **rapid finality** (instant confirmation compared to Mina). Zeko leverages the security and tooling of Mina while offering these performance benefits. ## Introduction to Rollups Rollups are a category of Layer 2 scaling solutions. They operate by **bundling or "rolling up" many off-chain transactions** into a single transaction. This aggregated transaction is then verified and recorded on the main chain (Layer 1). This significantly reduces the amount of data that needs to be processed and stored on Layer 1, leading to faster and cheaper transactions. There are different types of rollups, including Optimistic Rollups and Zero-Knowledge (ZK) Rollups. **Zeko is a ZK Rollup**. ZK-Rollups utilize **Zero-Knowledge Proofs (ZKPs)** to ensure that \*\*all transactions within the bundled batch are valid. The process involves processing transactions off-chain. A **sequencer** acts as a transaction collector, gathering these transactions and applying them to the current state. The sequencer efficiently groups transactions into **batches** and proves their validity using zero-knowledge proofs. The transaction data itself is posted to a **Data Availability (DA) layer**. The sequencer then sends the aggregated proof of the batch to the Layer 1 via a smart contract. The ZK proof compresses the validation of the whole batch of transactions into the verification of a single zk-SNARK, which is of constant size. > \[!TIP] πŸ’‘ zk-SNARK πŸ’‘ > A zero knowledge proof. zk-SNARK is the acronym for zero knowledge succinct non-interactive argument of knowledge. ZK-Rollups offer several key advantages: * **Increased Throughput:** Batching transactions processed off-chain boosts overall transaction capacity. * **Lower Gas Fees:** A single entity verifies the transactions, which is cheaper than verifying on every node in the network. * **Privacy:** ZKPs can enhance privacy by proving validity without revealing transaction details. > \[!TIP] πŸ’‘ Zeko's Architecture πŸ’‘ > Zeko leverages Mina's recursive ZK technology, specifically the [Pickles](https://o1-labs.github.io/proof-systems/pickles/overview) recursive system, as the foundation for its ZK Rollup. Zeko's modular architecture further allows for the creation of custom zkRollups, providing developers with flexibility in choosing components like the data availability solution. --- --- url: /background/mina-protocol.md --- # Mina Protocol *This section is a brief overview of the Mina Protocol, you can find more information in the [o1js documentation](https://docs.o1labs.org/o1js/).* ## Overview of Mina's Unique Architecture Mina Protocol distinguishes itself with a unique architecture designed to be a **succinct blockchain**. At its core, Mina leverages zero-knowledge proofs (ZKPs), specifically using the **Kimchi proof system** and the **Pickles recursive system**. This allows for advanced cryptographic functions and efficient verification. > \[!TIP] πŸ’‘ Kimchi and Pickles πŸ’‘ > Find more about Kimchi and Pickles in this [o1Labs article](https://www.o1labs.org/blog/reintroducing-kimchi) and in the [Mina Book](https://o1-labs.github.io/proof-systems/kimchi/overview). A hallmark of Mina's design is its support for **arbitrary infinite recursive proof construction**. Mina is noted as being the only blockchain currently offering this capability. Recursion is fundamental to how Mina operates, being used to compress the historical blockchain data into a constant, small size. It also utilizes **tree-based recursive proofs** (described as "rollup-like") to compress transactions within blocks. Developers on Mina build **zkApps**, which are zero-knowledge smart contracts. Interactions and state changes on Mina are expressed through **Account Updates**, the fundamental data structure for transactions. These updates contain instructions for the network and require specific authorization, which can be a signature or a proof derived from executing zkApp logic. ## How Zeko Leverages Mina Zeko is a Layer 2 (L2) ecosystem purpose-built for Mina's zkApps. It operates **on top of the Mina Layer 1 (L1)** chain, providing enhanced throughput and quicker transaction confirmation times while offering a **fully Mina-equivalent application layer**. The Zeko rollup is implemented as a **zkApp account on the Mina L1 chain**, leveraging Mina's recursive capabilities and existing infrastructure. This design enables **seamless tooling integration** with existing Mina developer tools and wallets. > \[!TIP] πŸ’‘ Zeko's Architecture πŸ’‘ > For detailed information about Zeko's architecture, see the [dedicated Zeko section](../architecture/zeko-core-concepts.md). --- --- url: /introduction/quick-start.md --- # Quick Start *As Zeko has a wide target audience, this documentation is divided into sections tailored for different roles.* ## Developer Quick Start If you're a developer, head over to the [Getting Started](../developers/getting-started.md) section for development-specific instructions. ## User Quick Start If you're an end user, head over to the [Getting Started](../users/getting-started.md) section for instructions on setting up your wallet, obtaining tokens, and connecting to the Zeko network. ## Node Operator Quick Start If you're a node operator, head over to the [Getting Started](../operators/getting-started.md) section for instructions on setting up and running a Zeko node. --- --- url: /operators/guides/archive-node.md --- # Running Zeko's Archive Node This guide explains how to add the archive stack on top of an existing Zeko DA node so you can index and query historical data. > **Note:** This runbook uses a self-hosted DA node. However, you could also use a publicly available DA node. Complete [Running Zeko's DA Node](./da-layer.md) first. This runbook assumes: * your `da-layer` service is already running * your `docker-compose.yaml` already contains the `da-layer` setup from the DA node guide * your `da-layer` is reachable in Docker Compose as `da-layer:1924` Not covered in this guide: * generating DA node keys * exposing the archive services to the internet * running `archive-node-api` itself We will extend the same [docker compose](https://docs.docker.com/reference/cli/docker/compose/) file you used for the DA node. ## Prerequisites ### System Requirements * Linux or macOS (Windows WSL2 works too) * enough disk space for PostgreSQL and archive history ### Installed Software * `Docker` * a working DA node from [Running Zeko's DA Node](./da-layer.md) ## Overview ![Architecture](./da-layer.png) In the diagram above you see: * Zeko's sequencer sending transactions to `da-layer` * the optional archive stack that can index and serve historical data from your DA node The archive stack adds the following services: * `init-db` prepares the archive database schema * `postgres` stores indexed history * `archive` writes blocks into PostgreSQL * `archive-relay` reads from Zeko's sequencer and your `da-layer`, then forwards data to `archive` ### Volumes/files | Volumes | Files | Purpose | | -------------------- | ------------- | --------------------------------------------- | | `initdb_data` | | Schema file(s) to bootstrap PostgreSQL | | `postgresql_data` | | Persistent storage for PostgreSQL | | `archive_data` | | Persistent storage for `archive` | | `archive-relay_data` | | Persistent storage for `archive-relay` | | `keys_data` | `da-layer-sk` | Private key of the DA node | | `keys_data` | `da-layer-pk` | Public key of the DA node (used by sequencer) | | `da-layer_data` | | Persistent storage for da-layer | ### Service Overview * `init-db` * `postgres` * `archive` * `archive-relay` * `init-config` * `da-layer` ### Ports Exposed | Service | Port | Description | | -------- | ------ | ----------- | | postgres | `5432` | Database | *** ## Bootstrap process ### Extend `docker-compose.yaml` with archive services * Copy `docker-compose.yaml` to your project folder. ::: details Click to expand `docker-compose.yaml` ```yaml services: init-db: image: docker.io/zekolabs/zeko:latest container_name: init-db volumes: - initdb_data:/data/initdb entrypoint: - sh - -c command: > "curl -o /data/initdb/create_schema.sql 'https://raw.githubusercontent.com/zeko-labs/zeko/compatible/src/app/archive/create_schema.sql' && echo 'ALTER DATABASE archive OWNER TO archive;' > /data/initdb/init.sql && echo 'Archive database bootstrap complete' && exit 0" init-config: image: docker.io/zekolabs/zeko:latest container_name: init-config working_dir: /data volumes: - keys_data:/data/keys entrypoint: - sh - -c restart: "no" command: > "while [ ! -f /data/keys/.keys_created ]; do sleep 2; done; exit 0" postgres: depends_on: init-db: condition: service_completed_successfully image: postgres:16 container_name: postgres environment: POSTGRES_DB: archive POSTGRES_USER: archive POSTGRES_PASSWORD: archive volumes: - postgresql_data:/var/lib/postgresql/data - initdb_data:/docker-entrypoint-initdb.d ports: - "5432:5432" restart: unless-stopped da-layer: depends_on: init-config: condition: service_completed_successfully image: docker.io/zekolabs/zeko-da:latest container_name: da-layer ports: - "1924:1924" environment: ZEKO_SIGNATURE_KIND: "testnet" entrypoint: bash -c command: | "export MINA_PRIVATE_KEY=$(cat /keys/da-layer-sk) && \\ exec zeko-da \\ run-node \\ --port 1924 \\ --db-dir /data/db \\ --network-id testnet" volumes: - da-layer_data:/data - keys_data:/keys:ro restart: always archive: depends_on: postgres: condition: service_started image: zekolabs/zeko-archive-relay:latest container_name: archive entrypoint: bash -c command: | "exec zeko-archive run \\ --postgres-uri postgres://archive:archive@postgres:5432/archive" restart: always volumes: - archive_data:/data archive-relay: depends_on: archive: condition: service_started da-layer: condition: service_started image: zekolabs/zeko-archive-relay:latest container_name: archive-relay entrypoint: bash -c command: | "exec zeko-archive-relay \\ --zeko-uri \"https://testnet.zeko.io/graphql\" \\ --da-node da-layer:1924 \\ --network-id testnet \\ --db-dir /data \\ --sync-period 30 \\ --log-level Info \\ --archive-host archive \\ --archive-port 3086" volumes: - archive-relay_data:/data restart: always volumes: initdb_data: postgresql_data: archive_data: archive-relay_data: da-layer_data: keys_data: ``` ::: * Start all services ```bash docker compose up -d ``` ### If all the steps were performed correctly you have the following: * `da-layer` getting data from Zeko's L2 * `archive-relay` pulling data from `da-layer` and sending to `archive` * `archive` storing transactions in `postgresql` * `postgres` persisting the indexed history ### Synchronizing the data Synchronizing will take a long time. At the time of writing Zeko L2 testnet has 1 million transactions and would take at least a week to get it synced. Alternatively you can reach out to Zeko for the latest database or checkpoint archive that you can import in your setup and have a fully synced archive stack much faster. ### Access your data You can access the indexed data by running [archive-node-api](https://github.com/o1-labs/Archive-Node-API/) and configuring it to connect to your `archive` PostgreSQL database. --- --- url: /operators/guides/da-layer.md --- # Running Zeko's DA Node A critical component of any rollup system is the data availability layer. This layer is responsible for storing all the transaction data that occurs on the rollup. In this guide we will create a `da-layer` node that receives transaction data from the Zeko L2 rollup. Not covered in this guide: * Running the archive stack used to query historical data. See [Running Zeko's Archive Node](./archive-node.md). * Exposing your `da-layer` to the internet We will use [docker compose](https://docs.docker.com/reference/cli/docker/compose/) to define the whole stack in a single file. TL;DR skip to the [Bootstrap process](#bootstrap-process) ## Prerequisites ### System Requirements * Linux or macOS (Windows WSL2 works too) * **1 CPU core**, **2GB RAM** > **Note:** Running da-layer node does not need much ram. However to sync the full history without using snapshots and database backups, more RAM will allow quicker initial sync. ### Installed Software * `Docker` ## Overview ![Architecture](./da-layer.png) In the diagram above you see: * Zeko's sequencer sending transactions to `da-layer` * the optional archive stack that can index and serve historical data from your DA node ### Project Structure Layout of the project directory: ``` project-root/ └── docker-compose.yaml ``` > **Note:** `docker-compose.yaml` is using docker volumes to store data. If you prefer to mount local directories instead - change accordingly. ### Wallets To run a da-layer you will need: * `da-layer` - Each `da-layer` node is started with its wallet. ### Volumes/files | Volumes | Files | Purpose | | --------------- | ------------- | --------------------------------------------- | | `keys_data` | `da-layer-sk` | Private key of the DA node | | `keys_data` | `da-layer-pk` | Public key of the DA node (used by sequencer) | | `da-layer_data` | | Persistent storage for da-layer | ### Service Overview * `init-config` * `da-layer` ### Ports Exposed | Service | Port | Description | | -------- | ------ | ---------------- | | da-layer | `1924` | da-layer rpc API | *** ## Bootstrap process ### Getting/Creating configuration files * Copy `docker-compose.yaml` to your project folder. ::: details Click to expand `docker-compose.yaml` ```yaml services: init-config: image: docker.io/zekolabs/zeko:latest container_name: init-config working_dir: /data volumes: - keys_data:/data/keys entrypoint: - sh - -c restart: "no" command: > "while [ ! -f /data/keys/.keys_created ]; do sleep 2; done; exit 0" da-layer: depends_on: init-config: condition: service_completed_successfully image: docker.io/zekolabs/zeko-da:latest container_name: da-layer ports: - "1924:1924" environment: ZEKO_SIGNATURE_KIND: "testnet" entrypoint: bash -c command: | "export MINA_PRIVATE_KEY=$(cat /keys/da-layer-sk) && \\ exec zeko-da \\ run-node \\ --port 1924 \\ --db-dir /data/db \\ --network-id testnet" volumes: - da-layer_data:/data - keys_data:/keys:ro restart: always volumes: da-layer_data: keys_data: ``` * Start all services ```bash docker compose up -d ``` * Create `da-layer` keys 1. Enter `init-config` container: ```bash docker compose exec -it init-config bash ``` > **Note:** This image contains `zeko-cli` binary. 2. Create `da-layer` keypair > * `/data/keys/da-layer-pk` > * `/data/keys/da-layer-sk` > **Note:** Take note of `da-layer-pk` ```bash # create `da-layer` keypair zeko-cli generate-even-key | while read label1 label2 value; do if [ "$label1" = "Private" ]; then echo "$value" > da-layer-sk elif [ "$label1" = "Public" ]; then echo "$value" > da-layer-pk fi done mv da-layer-{sk,pk} /data/keys touch /data/keys/.keys_created ``` ### If all the steps were performed correctly you have the following: * `da-layer` getting data from Zeko's L2 ### Let Zeko know about your DA Layer In order for you to start receiving transactions from Zeko L2 sequencer you need to: * Expose your da-layer on the internet * Contact Zeko and ask to be added to DA node list. You will need to provide: * your `da-layer` public key * address:port on which Zeko's sequencer can reach your `da-layer` ### Synchronizing the data Once your DA node will be added to Zeko's Sequencer, your node will start receiving transactions. Synchronizing might take some time. It depends when did the sequencer receive a hard reset. If you want to index that data and query it through an archive API, continue with [Running Zeko's Archive Node](./archive-node.md). --- --- url: /architecture/security-model.md --- # Security Model *Zeko's security relies on a combination of the underlying Mina Protocol's security guarantees and the specific design choices within the Zeko Layer 2 architecture. The security model is built upon the interactions and properties of several key components.* ## Proof System The security of the state transitions within Zeko is fundamentally tied to the **soundness of the underlying zero-knowledge proof system**, specifically Mina's implementation of **ZK-SNARKs (Kimchi and Pickles)**. * Transaction batches processed off-chain are compressed into a **single, succinct proof** using recursion. This proof attests to the validity of all transactions and the resulting state transition from a previous ledger hash to a new one. * The L1 smart contract verifies this **root proof**. If the proof is **invalid**, the L1 consensus mechanism will **reject the transaction**, preventing an incorrect state transition from being committed on Layer 1. * Permissions on zkApps, such as requiring **proof authorization** for state changes or fund transfers, ensure that only valid computations (proven off-chain) can trigger sensitive actions. This principle is inherited by Zeko's zkApps and custom tokens. *The proof system acts as a **cryptographic guarantee** that the L2 state transitions are correct, provided the L1 correctly verifies the submitted proofs.* ::: warning ⚠️ Proof System Limitations ⚠️ State transition proofs are only as secure as the underlying proof system. ::: ## Layer 1 Consensus Zeko's security model is anchored to the **Layer 1 Mina blockchain** through the commitment of the L2 state (specifically, the rollup ledger hash) to a zkApp account on L1. * The **finality** of the committed L2 state is dependent on the **Mina L1 consensus**. A batch proof is only accepted and the L1 state updated if it is agreed upon by the L1 consensus participants. * In the event of a **rollback on Mina L1**, the Zeko L2 state must also be rolled back to a corresponding earlier state. This is necessary to maintain **consistency** and the **security of bridges** between L1 and L2. * The L1 consensus effectively **validates the work** performed by the sequencer and provers by checking the root batch proof, ensuring that invalid state transitions are not accepted onto the L1 chain. *The security of Zeko's publicly committed state inherits the strong, decentralized security properties of Mina's Layer 1 consensus.* ::: warning ⚠️ L1 Consensus Limitations ⚠️ Committed state is committed only if the L1 consensus says so, and invalid state transition gets rejected only if consensus says so. ::: ## Data Availability Layer The **Data Availability (DA) layer** is a crucial component for the **liveness and verifiability** of the Zeko rollup. * All transaction data for the processed batches is **published to the DA layer**. * This availability allows **anyone** to download the transaction data and independently **reconstruct the rollup's state**. This ability to verify the state is key to detecting malicious sequencer behavior, such as creating fraudulent state transitions. * The DA layer is also essential for facilitating **safe exits** (withdrawing funds from L2 to L1) in situations where the sequencer might be offline or non-cooperative. Users can prove their claim based on data available in the DA layer. *By ensuring that the necessary data for state reconstruction is public and accessible, the DA layer provides a critical **check-and-balance mechanism** against sequencer misbehavior and ensures the rollup's recoverability and liveness.* ::: warning ⚠️ DA Limitations ⚠️ If the DA layer fails or data is not published, it becomes **impossible to verify or reconstruct the state**, effectively halting the rollup and compromising its liveness. ::: ## Sequencer The sequencer plays a vital role in collecting, ordering, and processing transactions, and coordinating the creation and submission of batch proofs. * The sequencer applies transactions to the ledger and generates proofs. It is responsible for ensuring **preconditions, permissions, and authorizations** are met for each transaction. * It aggregates transactions into batches and generates the recursive proofs that are eventually committed to L1. * An **emergency pause mechanism**, controlled by a designated public key (potentially governed by a committee), provides a security failsafe to halt the rollup in critical situations. *The sequencer actions are ultimately subject to verification by the proof system, the DA layer, and the L1 consensus.* ::: warning ⚠️ Sequencer Limitations ⚠️ In the current single-sequencer design, a single sequencer could potentially **censor** specific user transactions by simply omitting them from batches. Future plans include implementing **shared sequencing** via an auction mechanism to decentralize this role and improve **censorship resistance and liveness**. ::: --- --- url: /users/guides/sending-tokens.md --- # Sending Tokens :::warning WIP: This section is under construction. ::: --- --- url: /background/smart-contracts.md --- # Smart Contracts ## What are Smart Contracts? A **smart contract** is a self-executing digital agreement written in code and stored on a blockchain. They automate and enforce contract terms without requiring intermediaries. Smart contracts leverage blockchain technology for increased **security** and **transparency**, streamlining processes and transactions across various industries. > \[!TIP] πŸ’‘ Smart Contracts πŸ’‘ > They can be thought of as a virtual "if-then" statement; for example, *if* a buyer sends the agreed-upon amount, *then* the smart contract automatically executes and transfers ownership of an asset from seller to buyer. This allows two parties to transact directly without needing a third party to ensure the agreement is honoured. Beyond simple transactions, smart contracts enable a wide array of use cases, including: * **Financial transactions**: Automated and secure transfers, payments, and complex financial agreements. * **Decentralized applications (DApps)**: Serving as the backbone for platforms like Decentralized Finance (DeFi) protocols (lending, borrowing, trading) and gaming platforms with in-game assets. * **Non-fungible tokens (NFTs)**: Platforms for creation, ownership, and trading of unique digital assets. * **Insurance**: Automating claims processing and payouts based on predefined conditions. * **Supply chain management**: Tracking goods, ensuring transparency, and automating processes like order fulfilment and payment. * **Intellectual property**: Managing ownership, distribution, and automating royalty payments. * **Voting systems**: Facilitating secure, transparent, and fraud-preventing voting. ## How Do Smart Contracts Work? The operation of smart contracts relies on **blockchain technology**, code execution, and decentralized consensus. Here's a simplified process: 1. **Creation and Deployment**: A developer writes the smart contract code using a language compatible with the blockchain and deploys it onto the network. 2. **Code and Conditions**: The contract contains code defining the terms, rules, and conditions of the agreement, which can range from simple payments to complex multi-step processes. 3. **Contract Invocation**: Once deployed, anyone with access to the blockchain can interact with the smart contract by calling its functions and providing necessary inputs. This is common when users interact with DeFi services and DApps via crypto wallets. 4. **Validation and Execution**: When invoked, the transaction is verified and validated by each node in the blockchain network, which guarantees secure execution. If the specified conditions are met, the task defined by the contract code is automatically executed. 5. **Immutable Record**: Upon validation and confirmation, the execution is recorded as an immutable entry on the blockchain ledger, making it transparent and auditable. 6. **Finality**: The execution of a smart contract is final and cannot be reversed, ensuring the transaction's integrity and security. ::: warning While offering many advantages like transparency, security, and efficiency, smart contracts also have potential drawbacks, including security vulnerabilities from code errors, and scalability limitations on the underlying blockchain network. These challenges are addressed with bug bounty programs, security audits, standardisation efforts, and **Layer-2 solutions** such as rollups. ::: ## Smart Contracts on Mina and Zeko : zkApps On Mina Protocol, smart contracts are called **zkApps** (zero-knowledge applications). These leverage **zero-knowledge proofs** (ZKPs) to verify state transitions, allowing transactions to be proved off-chain and verified on-chain without revealing private data. > \[!TIP] πŸ’‘ zkApps Validation and Execution πŸ’‘ > zkApps are validated client-side, which means that the network throughput is higher than other blockchains that have to validate smart contracts at the node level. ![ZkApps](./zkapps.jpg) ZKPs in zkApps are primarily used for two purposes: to hide parts of the data and to **compress the computation**. The transaction snark uses the compression property to validate a batch of transactions into the verification of a single snark. While the "zk" part can hide data, this is often a side product; the main goal in zkApps is **proving that you've executed the smart contract correctly** off-chain. **Zeko is a Layer 2 (L2) ecosystem specifically designed for Mina's zkApps**. It aims to provide a robust platform for building and deploying zkApps with improved throughput and quick confirmation times. > \[!TIP] πŸ’‘ More about zkApps πŸ’‘ > For more information on zkApps, refer to the [o1js documentation](https://docs.o1labs.org/o1js/zkapps/intro). --- --- url: /architecture/technical-architecture.md --- # Technical Architecture *This section details the core components and processes that make up the Zeko rollup, explaining how transactions are handled, proved, and committed to the Layer 1 (L1) Mina blockchain.* ## Detailed Component Breakdown Zeko functions as a **zkApp account** on Mina Protocol. It is designed to be a *nested instance* of the Mina ledger on top of itself. This architecture involves several key components working together: ### Sequencer The sequencer primary roles include: * Acting as a **Transaction Collector**, gathering transactions submitted by users. * Applying these transactions to the current state of the L2 ledger. * Acting as a **Proof Verifier**, proving the validity of transactions using *zero-knowledge proofs* to ensure only legitimate transactions enter the system. It verifies aspects such as **preconditions**, **permissions**, **proof/signature validity**, and correct authorization. * Acting as a **Batch Processor**, efficiently grouping transactions into *batches* instead of processing them one by one. * Acting as a **Layer 1 Bridge**, sending ready batches to the L1 Mina chain via a smart contract to keep L1 informed of activity on Zeko. * Posting applied transactions to the **Data Availability (DA)** layer. * Sending transactions to the **provers**. * Aggregating individual transaction proofs into a *single proof* for the batch. This is done by creating a **binary tree of proofs**, merging proofs for distinct transactions. * Accepting user transactions directly via a **GraphQL API**. ### Prover The prover is a component that proves the validity of transactions processed by the sequencer. **Transaction snarks** are used to prove the transition from one ledger state (Ledger A) to another (Ledger B). The sequencer sends transactions to one of the provers, and the prover generates the necessary proofs. While the client generates a proof for executing the *zkApp logic*, the sequencer also sends the transaction to a prover to prove the additional checks it performed, such as verifying **preconditions**, **permissions**, and **authorizations**, and proving that the transaction was applied correctly to the ledger. ### Verifier Smart Contract on Mina (L1 Rollup Contract) Zeko is implemented as a **zkApp account** on the L1 Mina blockchain. The state of this L1 zkApp stores the current *hash of the Zeko ledger*. The sequencer sends the **aggregated proof** of a batch of transactions to this L1 contract. This proof encapsulates the **state transition** of the L2 ledger (e.g., from hash A to hash D). The L1 contract verifies this proof, and if valid, updates its state to the new ledger hash, effectively *committing the batch* of L2 transactions to L1. ### Archive Zeko's architecture includes mechanisms like an **archive relay adapter** that can subscribe to the sequencer and relay new blocks to a standard Mina archive node for *historical indexing*. ## Data Availability Layer A **data availability layer (DAL)** is a critical component for any rollup system, responsible for storing all the transaction data that occurs on the rollup. The reason for a DA layer is that the *proof of a transaction batch* does not reveal the specific transactions or how the ledger's state was constructed. Therefore, it is necessary to prove that the required data (the transactions themselves) has been shared with everyone. This prevents the rollup from being stalled by operators *withholding necessary data*. Zeko employs a **modular DA-layer**. Currently, Zeko uses a temporary DA-layer built on *multisig services* with a few trusted parties, and is transitioning towards [Celestia](https://docs.celestia.org/learn/how-celestia-works/data-availability-layer). Data availability in Zeko is ensured by requiring a **public key** to sign the hashes used. The sequencer posts both the *batch of transactions* and associated **receipts** to the DA layer. A DA layer guarantees that data has been broadcast and verified by a sufficient number of participants. The DA layer should eventually be usable by *L1 apps and L2s*. ## Transaction Lifecycle The process of a user transaction on Zeko involves several steps, from initiation to final commitment on the Mina L1 chain: ```d2 grid-rows: 4 grid-columns: 3 horizontal-gap: 20 vertical-gap: 20 # First row - 3 steps (1β†’2β†’3) - Client 0,0: "1. User Initiation" { shape: rectangle style.fill: "#5098f6" style.font-color: "white" } 0,1: "2. Client-Side Proving" { shape: rectangle style.fill: "#5098f6" style.font-color: "white" } 0,2: "3. Submission to Sequencer" { shape: rectangle style.fill: "#5098f6" style.font-color: "white" } # Second row - 2 steps (5←4) - Transition 1,0: "" { style: { fill: transparent stroke: transparent } } 1,1: "5. Data Availability Posting" { shape: rectangle style.fill: "#c19432" style.font-color: "white" } 1,2: "4. Sequencer Processing" { shape: rectangle style.fill: "#c19432" style.font-color: "white" } # Third row - 3 steps (6β†’7β†’8) - L2 2,0: "6. Proving (Sequencer-Initiated)" { shape: rectangle style.fill: "#c19432" style.font-color: "white" } 2,1: "7. Batching" { shape: rectangle style.fill: "#c19432" style.font-color: "white" } 2,2: "8. Batch Proof Aggregation" { shape: rectangle style.fill: "#c19432" style.font-color: "white" } # Fourth row - 2 steps (9β†’10) - L1 3,0: "" { style: { fill: transparent stroke: transparent } } 3,1: "10. L1 State Update" { shape: rectangle style.fill: "#3da45d" style.font-color: "white" } 3,2: "9. Commitment to L1" { shape: rectangle style.fill: "#3da45d" style.font-color: "white" } # Flow connections following the new snail pattern 0,0 -> 0,1 -> 0,2 -> 1,2 -> 1,1 -> 2,0 -> 2,1 -> 2,2 -> 3,2 -> 3,1 ``` 1. **User Initiation:** A user initiates a transaction, for example, to mint tokens using a zkApp. This involves generating **account updates**, which are sets of instructions for the ledger. 2. **Client-Side Proving:** The user's client executes the *zkApp logic* and generates a **zero-knowledge proof** attesting to the correct execution of the smart contract function. This *offloads computation* from the network nodes. 3. **Submission to Sequencer:** The user sends the transaction and the generated proof directly to the Zeko sequencer, typically via a **GraphQL API** endpoint. 4. **Sequencer Processing (Verification and Application):** The sequencer accepts the transaction. It verifies certain aspects like **preconditions**, required **permissions**, and the validity of the provided *proof or signature*. If valid, the sequencer applies the account updates and the transaction to the **L2 ledger state**. 5. **Data Availability Posting:** The sequencer sends the transaction data to the **Data Availability layer**. The DA layer consists of nodes that *replicate this data storage*. 6. **Proving (Sequencer-Initiated):** The sequencer sends the transaction to a **prover** to generate proofs for the work the sequencer performed (e.g., verifying preconditions and applying the transaction to the ledger). 7. **Batching:** The sequencer groups multiple processed transactions into a **batch**. 8. **Batch Proof Aggregation:** The sequencer aggregates the individual proofs for the transactions within the batch into a *single, constant-sized proof* using a **binary tree structure**. This aggregated proof summarizes the **state transition** from the beginning to the end of the batch (e.g., Ledger A hash to Ledger D hash). 9. **Commitment to L1:** The sequencer sends the **aggregated batch proof** to the L1 Mina blockchain. This proof is verified by the **Zeko zkApp** (rollup contract) on L1. 10. **L1 State Update:** Upon successful verification of the batch proof, the L1 Zeko zkApp updates its *on-chain state* to the new **ledger hash**, thereby finalizing and committing the batch of L2 transactions to the Layer 1 blockchain. > \[!TIP] πŸ’‘ Transaction Proofs and DA πŸ’‘ > The full transaction data for the batch is sent to the DA layer, while only the *constant-sized aggregated proof* is sent to L1. ## Zeko Internal Design Zeko is meant to be a **zkApp** that contains a *nested Mina ledger* in its account state. Transfers of **Mina** and tokens between the *outer and inner ledgers* should be possible. These are the only goals for the **MVP**. The design is meant only to do this as well as possible. The MVP zkApp neither has any **data availability checks** to ensure that the witnesses necessary to operate on the zkApp are available in the network. ### Circuits * **Outer circuit** (for L1 zkApp) * **Inner circuit** (for handling transfers on the L2 side cleanly) * **Transaction wrapper circuit** (for wrapping transaction snarks) * **Action state extension circuit** (for proving one action state is an extension of another) * **Helper token owner circuit** for recording transfers processed ### zkApp design The L1 and L2 are connected by a *special account* on the L2, denoted by having a **special public key**. The L1 account is called the **outer account**, and the L2 one the **inner account**. The outer account keeps track of the **ledger hash** of the inner ledger, the hash of the *merkle list* for all **withdrawals** (L2 -> L1). **Actions** on the outer account are treated as **deposits** (L1 -> L2). The inner account keeps track, similarly, of all **deposits**. Updating the ledger hash can be done via supplying a valid **ledger transition**, i.e. *transaction snark*. The inner account must start with the *maximum amount of Mina possible* when the rollup is made. When a **deposit** happens, an action is added to the outer account, along with **MINA**. On the inner side the recipient can *finalize the deposit*, taking the MINA from the L1 account. For **withdrawals** (L2 -> L1), the same happens in reverse. ### Processing transfers The central problem we face is that we can not send **MINA** trivially. MINA accounts may have `receive != None`, and we can not prevent them from *emptying their accounts*, meaning the sequencer's submitted transaction would fail, **DoSing the rollup**. There are ways to solve this with `receipt_chain_hash`, but 1. They are *complicated*. 2. They can not work well when the `set_verification_key` permission is `Signature` or `Either`. We opt to instead push this responsibility onto the **user**. The user can *finalize the transfer* if they can prove it hasn't happened before. In a sense, we're delegating the responsibility of storing this state to the user, and must enforce they store it correctly. We can do it through **token accounts**, with a token owner that only allows storing *valid data*. We can do it by checking `receipt_chain_hash` at transfer-processing time. We can also use simpler indicators, such as `is_new`, after all, a new account can not have processed any transfers before! ### Token approach A transfer has two stages: 1. **Submission** (add action) 2. **Processing** (move funds from Zeko account to user account) During the processing, we must prove that we haven't processed the transfer already, by including a **helper account** specific to the recipient. The helper account tracks the **action state** at the time of the last transfer processing. The account update for the inner/outer account includes this as a *child*, and updates the action state to the current one. A proof that the actions between these two action states, filtered by recipient, total to the amount, must be included. If the account is new, the action state is regarded as being the *empty action state*. In essence, we are tracking *per-recipient* what transfers have been processed. We delegate the responsibility of this to the recipient themself. How do we prevent them from tampering with the data? We make the account have a **special token id**, which circuit only allows transactions in which they are *subordinate to the inner/outer account*. Thus, they can never make an update which isn't also underneath the inner/outer account. To simplify this, we make the inner/outer account the token owner, removing the need for tracking the public key of the token owner. > \[!TIP] > If you are interested in reading more of internal design, please refer to the [white paper](https://docsend.com/view/f9a6kgdr4tjwuqng). --- --- url: /operators/troubleshooting.md --- # Troubleshooting :::warning WIP: This section is under construction. ::: --- --- url: /developers/tools/bridge-cli.md --- --- --- url: /developers/tools/faucet-cli.md --- --- --- url: /developers/tools/bridge-sdk.md --- --- --- url: /index.md --- --- --- url: /users/user-concepts-explained.md --- # User Concepts Explained *This section helps end users understand some key concepts when interacting with the Zeko network.* #### Testnet vs Mainnet Zeko's architecture is **mostly isomorphic to Mina**. This means the experience of using Zeko on a test network (like devnet) is **analogous** to using Mina's own testnet compared to its Mainnet. * **Testnets** (like Zeko testnet and alphanet) are environments provided for developers and users to **test applications and features** in a setting that mimics the Mainnet, but without using real-world value. They often have faucets to obtain free test tokens, for example, the faucet on `https://zeko.io/faucet` is for the Zeko testnet instance. * **Mainnet** will be the primary, live Zeko network where transactions involve real value. Starting out on a testnet like Zeko testnet is recommended to become familiar with the network and its interactions before using the Mainnet. #### Understanding Transaction Fees When you perform transactions or interact with zkApps on Zeko, you will incur fees. These fees play a crucial role in the network's operation and are typically paid to the **sequencer**. Key points about Zeko transaction fees: * Fees on Zeko are cheaper than equivalent complex transactions on Layer 1 Mina, aiming to improve the economics of using zkApps. * The amount of the fee for Layer 2 transactions is related to the **complexity of the circuit/computation** involved in the transaction. There's an upper limit on how much complexity can be included in a batch, which limits the number of account updates per batch. * For cross-layer operations like bridging assets from L1 to L2 (deposits), the fees can be potentially higher due to the requirement for an L1 inclusion proof pool. * Fees are charged in **L1 tokens** (MINA). * Fees cover various aspects of the ZK Rollup operation, including data availability storage, batch creation, proof aggregation, and posting the batch to Layer 1. :::warning Creating a new account on Mina and on Zeko also involves paying an account creation fee of 0.1 MINA (or 0.1 tMINA on testnets). ::: Zeko aims to make the fee structure competitive within the wider rollup space. --- --- url: /developers/guides/custom-network.md --- # Using a custom Zeko network with o1js This guide will walk you through the process of using a custom Zeko network to write zkapps. If this is your first time using Mina, we recommend you start with the official [o1js documentation](https://docs.o1labs.org/o1js/). Zeko is mostly isomorpic to Mina, so you can use the same tools and libraries to develop zkapps as you would use to develop zkapps on Mina. There are only few places where you need to be specific about the network you are using. It is the same as the difference between using mainnet and testnet. ## Auro wallet custom network For the zkapp to be sending transactions to the Zeko network, you need to add and set the network in the Auro wallet. Following API calls are available in the Auro wallet to manipulate with the network: * **getting current network**: [mina\_requestnetwork](https://docs.aurowallet.com/general/reference/api-reference/methods/mina_requestnetwork) * **adding network**: [mina\_addchain](https://docs.aurowallet.com/general/reference/api-reference/methods/mina_addchain) * **switching network**: [mina\_switchchain](https://docs.aurowallet.com/general/reference/api-reference/methods/mina_switchchain) ## O1js custom network To use O1js with a custom network you need to specify it when specifying the Network. ```typescript const network = Mina.Network({ networkId: "zeko", mina: sequencerUri, archive: sequencerUri }) Mina.setActiveInstance(network) ``` --- --- url: /users/guides/zekoscan-explorer.md --- # Using Zekoscan Explorer :::warning WIP: This section is under construction. ::: [Zekoscan](https://zekoscan.io/) lets you view transactions, blocks, and account activity on the Zeko network. Use it to track your activity and explore the chain. --- --- url: /introduction/what-is-zeko.md --- # What is Zeko? *Zeko is a zk-rollup protocol built on Mina, designed for scalable, private, and secure blockchain applications.* ## High-Level Summary [Zeko](https://zeko.io/) is a cross-chain, zero-knowledge scaling protocol built on Mina that enables developers to launch fast, private, and scalable decentralized applications. It combines the privacy guarantees of zero-knowledge proofs with the efficiency of off-chain computation and the security of Mina’s succinct L1, creating a modular, universal operating system for the new internet. Zeko testnet launch represents a preview of Zeko Protocol capabilities and functionalities to come. While this version will continue to evolve over time, it provides a foundation for developers to start building and assess how to deploy more scalable, feature-rich applications on Zeko. With the release of our protocol, developers gain access to all the existing tooling and features built for Mina, plus many unique to Zeko designed to simplify the zero-knowledge development process. From proof generation, recursion, smart contract creation to decentralized storage solutions, our platform offers everything developers need to realize the potential to bring your dApp ideas to life. The Zeko team and community are passionate about decentralization and user-owned data, and their combined potential to revolutionize industries across the globe. Zeko is all about amplifying your potential as a developer; and with our launch you now have the opportunity to dive into the protocol, explore its features, and unlock the magic of zero-knowledge technology. ![Zeko Architecture](./zeko-architecture.png) ## Purpose of Zeko Zeko builds upon the most decentralised ZK settlement layer, Mina, to provide a platform for fast, cheap and versatile zkApps. Zeko places zero-knowledge proof (ZKP) capabilities into the hands of developers, massively expanding the design space for blockchain applications as we know them today. ZKPs are no longer theoretical, and now through Zeko, application developers are empowered to innovate and explore new types of decentralized applications bridging Web2 and Web3 whilst optimizing performance and user experience. Moreover, through the upcoming release of the Aligned Layer bridge and future bridges, proofs that verify on Zeko can be consumed by the EVM, dramatically upending existing paradigms for blockchain applications. Zeko allows developers to create zkRollups specifically designed for zero-knowledge applications (zkApps) that support both end user privacy and recursive proof aggregation. zkApps on Zeko are written in Typescript using o1js, an efficient and extensible zkDSL. Developers can recursively prove unlimited off-chain computation whilst also maintaining privacy over user data. Developers can write and deploy applications today to a Zeko L2 that is isomorphic to the Mina L1, or spin up their own custom zkAppChains. What makes Zeko so powerful is it’s built using o1js programming language built by the o1Labs team, which means Zeko chains will enjoy easy composability between each other and Mina itself using recursive proofs. --- --- url: /introduction/why-zeko.md --- # Why Zeko? *Zeko is a next-generation zero-knowledge (ZK) infrastructure designed to power scalable, private, and interoperable blockchain applications. Built from the ground up as Layer 2 on top of the Mina Protocol, Zeko combines the privacy-preserving capabilities of zk-SNARKs with a modular and developer-friendly design.* ## Key Benefits Zeko is *Zero-Knowledge Native*, meaning its architecture is inherently private by design. Leveraging zk-SNARKs and `o1js`, it allows developers to build applications with encrypted logic and data confidentiality. This supports **confidential computation**, like private smart contract execution and compliance reporting. In terms of *Scalability and Performance*, Zeko offloads computation off-chain, significantly reducing costs and latency. Its recursive proof system and modular **zkAppChains** architecture support both general-purpose and app-specific rollups, enabling high throughput without sacrificing privacy or decentralization. Zeko’s *Cross-Chain Interoperability* is a defining feature. Designed with cross-chain compatibility from the outset, Zeko **proofs can be verified** on other major ecosystems such as the Ethereum Virtual Machine (EVM), allowing developers to extend zero-knowledge functionality beyond the limitations of single-chain solutions. By inheriting *Mina’s succinct, decentralized architecture*, Zeko also benefits from a **lightweight** and energy-efficient infrastructure, making it ideal for sustainable scaling. Zeko further distinguishes itself with a *Developer-Friendly Stack*. With [o1js](https://docs.o1labs.org/o1js/), developers can use **Typescript** to develop smart-contracts and enjoy a low learning curve, supported by prebuilt SDKs, templates, and customizable ZKPs. This streamlines development for a wide range of use cases, including AI, DeFi, NFTs, identity, and gaming. ## Core Use Cases & Applications In *Decentralized Finance (DeFi)*, Zeko enables **private credit systems** that verify borrower credentials without revealing sensitive financial data. It powers fast, cost-efficient, and confidential **global payments** via zkRollups and supports scalable, private tokenized **RWAs**. It also allows institutions to submit regulatory **compliance proofs** without disclosing user data. For *AI and Verifiable Computation*, Zeko provides mechanisms for verifiable model execution without exposing internal logic. It facilitates **federated learning** with built-in privacy for training models, and enables secure querying of **private knowledge bases** by AI agents. Zeko also enables **Decentralized AI agents**, who can execute off-chain logic with cryptographic proof of correctness. In *Gaming and NFTs*, Zeko’s zkRollups infrastructure supports scalable, **low-latency** gameplay and **private in-game transactions**, while **zkProofs** enable fair play verification. For *Identity and Governance*, Zeko enables **ZK-based identity verification**, such as proving age or citizenship without revealing personally identifiable information. **Governance** is handled via the upcoming `$ZEKO` token, which supports protocol upgrades, sequencer elections, and gas configuration. Finally, Zeko’s support for both *zkApp Chains and modular infrastructure* means developers can build **custom L2s and L3s** optimized for specific application needsβ€”balancing privacy, scalability, and user experience. --- --- url: /users/guides/zeko-bridge.md --- # Zeko Bridge The Zeko Bridge moves assets between Mina (L1) and Zeko (L2). Use the interface that matches your job: * [Bridge UI](https://bridge.zeko.io) for interactive bridging in the browser * [Bridge CLI](/developers/tools/bridge-cli) for unattended and agent-driven bridging * [Bridge SDK](/developers/tools/bridge-sdk) for custom applications and automation ## High-Level Protocol Behavior At the protocol level, bridging is a two-step process: 1. Submit the bridge action on the source chain. 2. Claim the bridged asset on the destination chain once the protocol state makes that claim valid. The waiting time between those two steps can be long. That is normal. The bridge has to wait for chain progress, sequencer processing, archive/indexer availability, and the proof or witness data required to safely claim the asset. ## Mina To Zeko Deposits For a deposit from Mina to Zeko, the flow is: 1. Submit the deposit on Mina. 2. Wait for the deposit to settle into the bridge state. 3. Check both `canFinalizeDeposit` and `canCancelDeposit`. 4. If the deposit becomes finalizable, finalize it on Zeko. 5. If the deposit becomes cancellable, cancel it on Mina. Important protocol rules: * A cancellable deposit can never later be finalized. * Deposit claims are queue-ordered. * Cancellable deposits are skippable. * Finalizable deposits must never be skipped, because skipping them would strand user funds in the queue. This is why queue handling matters so much in both the CLI and any application built on the SDK. ## Zeko To Mina Withdrawals For a withdrawal from Zeko to Mina, the flow is: 1. Submit the withdrawal on Zeko. 2. Wait for the sequencer and indexer pipeline to make the withdrawal witnessable. 3. Finalize the withdrawal on Mina. Withdrawals are also queue-ordered, but unlike deposits they are not cancellable. The earliest pending withdrawal for the account must be finalized first. ## Why A Bridge Can Take So Long Long waits usually come from bridge state propagation rather than from the local wallet: * Mina-side settlement and finality can take time. * The Zeko sequencer can see a new action before the archive or actions API can serve the corresponding witness data. * Finalization proof generation can take a long time. As a result, a good bridge client must tolerate long unattended waits and keep following the queue until the requested operation reaches a real terminal outcome. ## Operational Model The Bridge UI, Bridge CLI, and Bridge SDK all model the same protocol: * submit first * wait for the earliest actionable queue item * finalize when finalizable * cancel immediately when cancellable * never skip a finalizable deposit The main difference is the signing model: * the [Bridge UI](https://bridge.zeko.io) waits for interactive wallet approvals * the [Bridge CLI](/developers/tools/bridge-cli) is designed for unattended execution with local keys * the [Bridge SDK](/developers/tools/bridge-sdk) exposes the underlying operations so other applications can build their own orchestration --- --- url: /architecture/zeko-core-concepts.md --- # Zeko Core Concepts *Zeko is designed as a Layer 2 (L2) ecosystem specifically for Mina's zero-knowledge applications, known as zkApps. It aims to provide a robust platform for building and deploying zkApps with significantly improved throughput and quick confirmation times compared to the Layer 1 (L1) Mina protocol.* ## How Zeko Achieves Scalability: The Rollup Mechanism At its core, Zeko functions as a **ZK Rollup**. This means it processes transactions off-chain, bundles them into batches, and then commits a cryptographic proof of the batch's validity to the Mina L1 chain. The **sequencer** is a key component in this process, acting as a transaction collector that gathers transactions and applies them to the current state. It groups these transactions into **batches** for efficient settling on L1. The sequencer then proves the validity of these batches using zero-knowledge proofs. A root SNARK proof representing the batch is created, which is then committed to the L1 zkApp's account state. This process leverages **transaction SNARKs**, which prove the transition from one ledger state to another. These proofs are composed into a binary tree structure. The root SNARK of this tree serves as a proof for the entire batch and the constant size of this proof is how Zeko compresses the computation of validating a batch of transactions. This offloads work from the main network nodes, a fundamental idea behind Mina. By committing a single, constant-size proof to L1, Zeko significantly increases transaction throughput. ```d2 direction: down # Style classes classes: { root-proof: { style.fill: "#28a745" style.stroke: "#1e7e34" style.font-color: "white" } intermediate-proof: { style.fill: "#ffc107" style.stroke: "#d39e00" style.font-color: "white" } tx-proof: { style.fill: "#17a2b8" style.stroke: "#117a8b" style.font-color: "white" } } # Binary Tree of Transaction Proofs tree: Binary Tree of Proofs { style.fill: "#f8f9fa" root: Root SNARK\nState A->E { class: root-proof } level1_left: Intermediate Proof\nState A->C { class: intermediate-proof } level1_right: Intermediate Proof\nState D->E { class: intermediate-proof } tx1: Tx SNARK 1\nState A->B { class: tx-proof } tx2: Tx SNARK 2\nState B->C { class: tx-proof } tx3: Tx SNARK 3\nState C->D { class: tx-proof } tx4: Tx SNARK 4\nState D->E { class: tx-proof } # Tree connections level1_left -> root level1_right -> root tx1 -> level1_left tx2 -> level1_left tx3 -> level1_right tx4 -> level1_right } # L1 Commitment l1: Mina L1 { style.fill: "#e8f4fd" zkapp: zkApp Account { state: Rollup State } } tree.root -> l1.zkapp: Commits Root Proof ``` ## The Role of Zero-Knowledge Proofs in Zeko Zero-knowledge proofs (ZKPs) are fundamental to Zeko, as they are to Mina and zkApps. They allow one party (the prover) to convince another party (the verifier) that a statement is true without revealing any information beyond the truth of the statement itself. In Zeko, ZKPs, specifically zk-SNARKs, are used for two primary purposes in transaction processing: 1. **Compressing Computation**: The **transaction SNARKs** compress the validation of a batch of transactions into the verification of a single proof. 2. **Proving Correct Execution**: zkApps on Mina (and thus Zeko) are primarily about proving that you have correctly executed the smart contract logic. The client first executes the smart contract function off-chain and then generates a proof that this execution was performed correctly. While zk-SNARKs *can* be used to hide parts of transaction data, the primary use in zkApps on Mina/Zeko is proving correct execution and compressing computation. Hiding data is considered a side product. These proofs must satisfy **completeness** (an honest prover can demonstrate knowledge) and **soundness** (a dishonest prover cannot convince the verifier) without revealing the sensitive information itself. Mina and Zeko benefit from the underlying **recursive proof system** ([Kimchi backed by Pickles](https://www.o1labs.org/blog/reintroducing-kimchi)), which enables arbitrary infinite recursive proof construction. This recursive capability is used internally within Mina for decentralized proving and sequencing and allows for the creation of tree-based recursive programs like the one used in the rollup aggregation. > \[!TIP] πŸ’‘ ZK Rollups πŸ’‘ > Zk-rollups utilize ZKPs to ensure the validity of all transactions in a bundled batch without necessarily disclosing the specifics of each transaction, which can enhance privacy. ## zkApps: Zeko's Smart Contracts On Mina and Zeko, smart contracts are referred to as **zkApps** or **zkApp accounts**. While the languages of the circuits is ocaml, the [o1js](https://docs.o1labs.org/o1js/) library can be used, to develop zkApps using Typescript. zkApps are zero-knowledge smart contracts that leverage ZKPs to ensure the correctness of state transitions. Developers write these contracts using the `SmartContract` class in o1js. Additionally, o1js provides the `ZkProgram()` construct, which is used to define the steps of **recursive programs**. Unlike `SmartContract` methods, `ZkProgram()` methods execute off-chain. These off-chain computations can take private inputs, which are not seen by the Mina network. After performing the desired recursive steps off-chain, the proof of execution generated by the `ZkProgram` can be verified *on-chain* within a `SmartContract` method. This allows the results or outputs of complex off-chain computations to be trustlessly verified and used, for example, to update the zkApp's on-chain state. > \[!NOTE] zkProgram and SmartContract > While the primary on-chain logic of a zkApp is defined within the `SmartContract` class, the ability to define and verify `ZkProgram`s provides a powerful way to perform arbitrary zero-knowledge programs or circuits off-chain and settle their validity on-chain. ## State Management Zeko operates as a nested instantiation of the Mina ledger within a zkApp account on the Mina L1 chain. This creates a dual-layer architecture where the L1 zkApp account serves as the **'outer' account** that tracks the state of a corresponding **'inner' account** on the L2. ```d2 direction: down L1: Mina L1 { style.fill: "#e8f4fd" outer: Outer Account { state: L2 Hash } } L2: Zeko L2 { style.fill: "#f0f8e8" inner: Inner Account { ledger: L2 State } sequencer: Sequencer } L2.sequencer -> L1.outer: Batch Proof L1.outer <-> L2.inner: Actions ``` ### Account Updates: The Transaction Building Blocks All transactions on Mina and Zeko are built from **Account Updates** - the fundamental data structure that instructs the network on state changes. Each `AccountUpdate` can alter on-chain state, emit events, change permissions, or modify balances. These updates include **preconditions** that must be satisfied, specify the exact **updates** to apply, define **balance changes**, and require appropriate **authorization** (typically a proof for zkApps). ### L2 State Transitions and Batch Proving The Zeko sequencer manages L2 state by collecting transactions composed of **Account Updates** and applying them to the ledger off-chain. Rather than processing transactions individually, the sequencer batches them together and generates a **proof** demonstrating the validity of the cumulative state transition. This root proof is then submitted to the L1 Mina chain, updating the outer zkApp's state to reflect the new L2 ledger hash and effectively committing the **entire batch** to L1. ### L1/L2 Communication Through Actions Synchronization between the outer and inner accounts occurs via Mina's **action** system. Actions are public data attached to transactions that can be processed by smart contracts using reducers. The network maintains an **actionState** - a cryptographic commitment to the history of dispatched actions - ensuring processed actions were genuinely sent to the contract. Communication flows *bidirectionally*: L1 to L2 communication involves posting actions to the L1 zkApp account, while L2 to L1 communication posts actions to the L2 inner account. During the commit process (when batch proofs are posted to L1), the action states of both accounts **synchronize**, maintaining consistency across layers. When action states are synchronised, anybody can prove on **each layer** that their action has been included using a simple Merkle proof. This architecture enables Zeko to process transactions **efficiently** off-chain while leveraging Mina's recursive proof system to compress validation and maintain the security guarantees of the L1 chain. --- --- url: /background/zero-knowledge-proofs.md --- # Zero-Knowledge Proofs *Zero-Knowledge Proofs (ZKPs) are a fundamental cryptographic concept with significant implications for blockchain technology, privacy, and scalability. They form a core part of the technology behind Mina Protocol and Layer 2 solutions built on it, such as Zeko.* ## High-Level Explanation: Proving Without Revealing Simply put, a **Zero-Knowledge Proof** allows one party, known as the **prover**, to prove to another party, the **verifier**, that a statement is true **without revealing any information about the statement itself**, beyond the fact that it is true. Think of proving you know a secret password to enter a room. With a ZKP, you can convince someone that you know the password and are therefore authorised to enter, without ever actually telling them the password itself. The verifier is convinced you possess the knowledge, but they gain no additional information about the secret. Key properties of a ZKP system include: * **Completeness:** An honest prover can construct a valid proof. * **Soundness:** An adversary can't construct a valid proof.. * **Zero-Knowledge:** The verifier learns nothing beyond the truth of the statement itself. ## Why are ZKPs Important for Scalability and Privacy? ZKPs address key challenges in blockchain networks: limited **scalability** and the need for greater **privacy**. ### Enhancing Privacy Blockchains are often public ledgers where all transactions are transparent. ZKPs enable **privacy-preserving transactions** by allowing parties to prove the validity of a transaction (e.g., that they have sufficient funds and the recipient is valid) without revealing sensitive details like the exact amount transferred or the identities of the participants. This opens up possibilities for more confidential digital interactions and applications on-chain. ### Improving Scalability One of the most impactful applications of ZKPs for scalability is in **zk-rollups**, a type of Layer 2 scaling solution. Zk-rollups process transactions off-chain, bundling (or "rolling up") hundreds or thousands of transactions into a single batch. A single ZKP is then generated to cryptographically prove the correctness of *all* transactions within that batch. This single proof is submitted to the Layer 1 blockchain, dramatically reducing the data that needs to be stored and verified on-chain. This results in significantly increased transaction throughput and lower transaction costs. ## ZKPs in Mina Protocol and Zeko Mina Protocol uniquely integrates ZKPs at its core through recursive proofs. This recursion allows proofs to verify other proofs, enabling Mina to compress its entire blockchain history into a constant-sized proof. Furthermore, Mina uses recursive tree-based proofs to aggregate and compress proofs for individual transactions within blocks. This inherent ZKP-based compression is a foundational element that Zeko leverages. In Zeko, transaction validity is proven using ZKPs, and these proofs are aggregated into larger proofs representing batches of transactions. > \[!TIP] > Mina's Proof system is explained in detail in the [Mina book](https://o1-labs.github.io/proof-systems/). You can learn more about Zeko Core Concepts in the [dedicated docs section](../architecture/zeko-core-concepts.html#the-role-of-zero-knowledge-proofs-in-zeko).