{"id":16064406,"url":"https://github.com/tangle-network/zero-knowledge-gadgets","last_synced_at":"2025-03-27T15:31:22.148Z","repository":{"id":37891987,"uuid":"341302599","full_name":"tangle-network/zero-knowledge-gadgets","owner":"tangle-network","description":"Zero-knowledge gadgets for Webb's cross-chain blockchain applications.","archived":false,"fork":false,"pushed_at":"2023-01-20T17:59:34.000Z","size":5580,"stargazers_count":89,"open_issues_count":14,"forks_count":29,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-10-09T05:07:15.340Z","etag":null,"topics":["arkworks","blockchain","cryptocurrencies","cryptography","privacy","rust","zero-knowledge"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tangle-network.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-22T18:47:39.000Z","updated_at":"2024-09-14T18:23:33.000Z","dependencies_parsed_at":"2023-02-12T04:15:20.701Z","dependency_job_id":null,"html_url":"https://github.com/tangle-network/zero-knowledge-gadgets","commit_stats":null,"previous_names":["webb-tools/arkworks-gadgets","tangle-network/zero-knowledge-gadgets","webb-tools/zero-knowledge-gadgets"],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fzero-knowledge-gadgets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fzero-knowledge-gadgets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fzero-knowledge-gadgets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tangle-network%2Fzero-knowledge-gadgets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tangle-network","download_url":"https://codeload.github.com/tangle-network/zero-knowledge-gadgets/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245871863,"owners_count":20686277,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arkworks","blockchain","cryptocurrencies","cryptography","privacy","rust","zero-knowledge"],"created_at":"2024-10-09T05:07:12.582Z","updated_at":"2025-03-27T15:31:19.435Z","avatar_url":"https://github.com/tangle-network.png","language":"Rust","readme":"\u003cdiv align=\"center\"\u003e\n\u003ca href=\"https://www.webb.tools/\"\u003e\n\n  ![Webb Logo](./.github/assets/webb_banner_light.png#gh-light-mode-only)\n  ![Webb Logo](./.github/assets/webb_banner_dark.png#gh-dark-mode-only)\n  \u003c/a\u003e\n  \u003c/div\u003e\n\u003cp align=\"left\"\u003e\n    \u003cstrong\u003e🚀 Zero-Knowledge gadgets and circuits for privacy preserving cross-chain apps. 🚀\u003c/strong\u003e\n\u003c/p\u003e\n\n[![GitHub Workflow Status](https://img.shields.io/github/actions/workflows/status/webb-tools/zero-knowledge-gadgets/checks.yml?branch=master\u0026style=flat-square)](https://github.com/webb-tools/zero-knowledge-gadgets/actions) [![License Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0) [![Twitter](https://img.shields.io/twitter/follow/webbprotocol.svg?style=flat-square\u0026label=Twitter\u0026color=1DA1F2)](https://twitter.com/webbprotocol) [![Telegram](https://img.shields.io/badge/Telegram-gray?logo=telegram)](https://t.me/webbprotocol) [![Discord](https://img.shields.io/discord/833784453251596298.svg?style=flat-square\u0026label=Discord\u0026logo=discord)](https://discord.gg/cv8EfJu3Tn)\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\u003ch2 id=\"table-of-contents\"\u003e 📖 Table of Contents\u003c/h2\u003e\n\n\u003cdetails open=\"open\"\u003e\n  \u003csummary\u003eTable of Contents\u003c/summary\u003e\n  \u003cul\u003e\n    \u003cli\u003e\u003ca href=\"#build\"\u003e Build\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#publishing\"\u003ePublishing to crates.io\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#overview\"\u003e Project Overview \u003c/a\u003e\u003c/li\u003e\n\t\u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#gadgets\"\u003eGadgets\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#circuits\"\u003eCircuits\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#api\"\u003eAPI\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#provers\"\u003eProvers\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#verifiers\"\u003eVerifiers\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n      \u003c/ul\u003e\n    \u003cli\u003e\u003ca href=\"#circuit\"\u003eCircuits\u003c/a\u003e\u003c/li\u003e\n\t\u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#mixer\"\u003eMixer\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#mleaf\"\u003eLeaf Structure\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#mpublic\"\u003ePublic Input Structure\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#anchor\"\u003eAnchor\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#aleaf\"\u003eLeaf Structure\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#apublic\"\u003ePublic Input Structure\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t \u003cli\u003e\u003ca href=\"#vanchor\"\u003eVAnchor\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#utxo\"\u003eUTXOs\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#vpublic\"\u003ePublic Inputs\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n      \u003c/ul\u003e\n    \u003cli\u003e\u003ca href=\"#usage\"\u003e Usage Examples\u003c/a\u003e\u003c/li\u003e\n\t\u003cul\u003e\n      \u003cul\u003e\n\t\t \u003cli\u003e\u003ca href=\"#mexample\"\u003eMixer Usage Example\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cul\u003e\n\t\t \u003cli\u003e\u003ca href=\"#aexample\"\u003eAnchor Usage Example\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cul\u003e\n\t\t \u003cli\u003e\u003ca href=\"#vexample\"\u003eVAnchor Usage Example\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cul\u003e\n\t\t \u003cli\u003e\u003ca href=\"#merkle\"\u003eMerkle Tree Usage Example\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cul\u003e\n\t\t \u003cli\u003e\u003ca href=\"#param\"\u003eParameter Generation\u003c/a\u003e\u003c/li\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003c/ul\u003e\n\t\t\u003cli\u003e\u003ca href=\"#smart\"\u003e Usage in Smart Contracts\u003c/a\u003e\u003c/li\u003e\n\t\t\u003cli\u003e\u003ca href=\"#grat\"\u003e Gratitude\u003c/a\u003e\u003c/li\u003e\n\t\u003c/li\u003e\n\u003c/details\u003e\n\n\u003ch2 id=\"build\"\u003e Build \u003c/h2\u003e\n\nTo build the project run:\n```\n./scripts/build.sh\n```\nTo build for wasm target, run:\n```\n./scripts/build-wasm.sh\n```\n\nTo run the unit tests, run:\n\n```\n./scripts/test.sh\n```\n\n\u003e **Note: All commands should be run from the root directory.**\n\n\u003ch2 id=\"publishing\"\u003e Publishing to crates.io \u003c/h2\u003e\n\nFor version management, we use [cargo-workspaces](https://github.com/pksunkara/cargo-workspaces). We use the following flow:\n\n1. Use `cargo-workspaces` to bump the version of all crates, using the command `cargo ws version`. This will bump the version of all the crates in the workspace, which include:\n   - arkworks/native-gadgets\n   - arkworks/r1cs-gadgets\n   - arkworks/r1cs-circuits\n   - arkworks/setups\n   - arkworks/utils\n2. The previous step will only update the crates themself, but not their dependencies. So, for example, if `arkworks/setups` depend on `arkworks/utils`, the dependency version will not be updated. **We have to do this manually.**\n3. Commit all the changes.\n4. Publish the crates with following command: `cargo ws publish --allow-branch [current_branch] --from-git`.\n\n   The `--allow-branch` allows us to publish the crates on any branch. By default, it's only allowed on `master`. If you wish to publish from the `master`, this option is not needed.\n\n   The `--from-git` flag specifies that the crates should be published as is, bypassing the additional version bump that comes with the `cargo ws publish` command.\n\n\u003ch1 id=\"overview\"\u003e Overview \u003c/h1\u003e\n\nThis repo contains zero-knowledge gadgets \u0026 circuits for different end applications such as a mixer and an anchor that can be integrated into compatible blockchain and smart contract protocols. The repo is split into three main parts:\n\n- Intermediate modular gadgets\n- The circuits that consume these gadgets\n- Basic utilities used by the gadgets and the circuits (like parameters for Poseidon hash function)\n\n\u003ch2 id=\"gadgets\"\u003e Gadgets \u003c/h2\u003e\n\nYou can think of gadgets as intermediate computations and constraint systems that you compose to build a more complete zero-knowledge proof of knowledge statement. They can also be used as-is by simply extending the arkworks `ConstraintSynthesizer`. An example using dummy computations can be found in the [dummy circuit](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/r1cs-circuits/src/basic.rs).\n\nIn this repo you will find gadgets for:\n\n- Poseidon [Native](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/native-gadgets/src/poseidon), [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/r1cs-gadgets/src/poseidon), [PLONK](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/plonk-gadgets/src/poseidon)\n- Merkle tree [Native](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/native-gadgets/src/merkle_tree.rs), [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/r1cs-gadgets/src/merkle_tree.rs), [PLONK](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/plonk-gadgets/src/merkle_tree.rs)\n- Set [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/r1cs-gadgets/src/set.rs), [PLONK](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/plonk-gadgets/src/set.rs)\n\nPoseidon hashing function matches the [circom implementation](https://github.com/iden3/circomlib/blob/master/circuits/poseidon.circom). Implemented based on this paper: https://eprint.iacr.org/2019/458.pdf.\n\nSet membership - Used for proving that some value is inside the set in a zero-knowledge manner. That is done by first calculating the differences (denoted as `diffs`) from the `target` (a value that we are checking the membership of) and each value from the set. We then calculate the sum of products of a target and each element in the set. If one value from the `diffs` is 0 (meaning that its equal to `target`) the product will be zero, thus meaning that the `target` is in the set.\n\n\u003ch2 id=\"circuits\"\u003e Circuits \u003c/h2\u003e\n\nIn this repo you will find circuits for:\n\n- Mixer [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/r1cs-circuits/src/mixer.rs), [PLONK](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/plonk-circuits/src/mixer.rs)\n- Anchor [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/r1cs-circuits/src/anchor.rs), [PLONK](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/plonk-circuits/src/anchor.rs)\n- VAnchor [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/r1cs-circuits/src/vanchor.rs), [PLONK](https://github.com/webb-tools/zero-knowledge-gadgets/blob/master/arkworks/plonk-circuits/src/vanchor.rs)\n\n\u003ch2 id=\"api\"\u003e Setup API \u003c/h2\u003e\n\nFor the circuits implemented in this repo, we have setups in the [setup](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/circuits/src/setup) directory. This folder contains circuit-specific setup helpers for creating proofs for each circuit as well as helpers for Poseidon, Merkle tree, proving/verifying key generation, verifier helper, etc.\n\nEach application-specific folder in `arkworks/setups/[r1cs | plonk]` encapsulates the API for the full setup of a zero-knowledge proof for that circuit. There are currently application-specific gadgets for:\n\n- Mixers: [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/setups/src/r1cs/mixer), PLONK (TBA)\n- Anchors: [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/setups/src/r1cs/anchor), PLONK (TBA)\n- VAnchors: [R1CS](https://github.com/webb-tools/zero-knowledge-gadgets/tree/master/arkworks/setups/src/r1cs/vanchor), PLONK (TBA)\n\nFor tests and instantiations of the gadgets used to compose each of these larger-scale application gadgets, refer to the test.rs files within that directory. Most of the tests and implementations in this repo use Groth16 proofs and setups for the zero-knowledge gadgets. Occasionally Marlin zkSNARKs are used for intermediate gadget tests. There are no application-specific instantiations of gadgets that use Marlin however but pull requests are welcome to create them.\n\n\u003ch3 id=\"provers\"\u003e Provers \u003c/h3\u003e\n\nProvers for these zero-knowledge gadgets are meant to be used by client or server applications. These are compute-intensive and require access to random number generators.\n\n\u003ch3 id=\"verifiers\"\u003e Verifiers \u003c/h3\u003e\n\nVerifiers for these zero-knowledge gadgets are meant to be used by client, server, or blockchain applications. These verifiers are WASM compatible and can be embedded in WASM-friendly environments like blockchains that allow smart contracts which are written in Rust. The APIs are consistent across a particular proving system such as Groth16 and are straightforward to integrate into blockchain runtimes such as [Substrate](https://github.com/paritytech/substrate).\n\n\u003ch1 id=\"circuit\"\u003e Circuits \u003c/h1\u003e\n\n\u003ch2 id= \"mixer\"\u003e Mixer \u003c/h2\u003e\n\nThe mixer gadget is built to be deployed on Rust-based blockchain protocols. The motivation is that there will be an on-chain Merkle tree \u0026 escrow system where users must deposit assets to insert a leaf into the Merkle tree. This is considered a **deposit** into the mixer. Next, the user can generate a zero-knowledge proof of membership of a leaf in the Merkle tree by instantiating a Mixer circuit, populating it with the leaves on-chain, providing private and public inputs locally to the helper utilities generated from our API, and subsequently generating a zero-knowledge proof. They can then submit this proof on-chain to an on-chain verifier. This is considered a **withdrawal** from the mixer. We provide an example instantiation of the mixer circuit setup, proof process, and proof verification process below. But first, we remark on the structure of the mixer to illuminate some of our design decisions.\n\nAny instantiation of a zero-knowledge mixer circuit requires that all data provided is formatted as expected. What this means is that there is a specific structure of data that must be provided to the prover. This extends as far down to the preimage of the leaves such that if data does not adhere to the expected format or protocol then it will be impossible to generate compatible zero-knowledge proofs for on-chain verification for such proofs.\n\n\u003ch3 id=\"mleaf\" \u003e Leaf structure \u003c/h3\u003e\n\nThe structure of the mixer leaf is a hash of 2 random field elements (the secret and the nullifier) from a field (BLS381 or BN254) based on the instantiation of your circuit.\n\n\u003ch3 id=\"mpublic\"\u003e Public input structure \u003c/h3\u003e\n\nThe structure of public inputs must be the ordered array of the following data taken from Tornado Cash's design \u0026 architecture.\n\n1. Nullifier hash\n2. Merkle root\n3. Arbitrary Input (Not included in the computation)\n\nThese parameters are provided to zero-knowledge proofs as public inputs and are geared towards on-chain customizability.\n\n- Nullifier hash is the hash of the randomly generated nullifier. We are hashing it so that the preimage remains hidden, to prevent front-run attacks.\n- Merkle root is the root hash of the Merkle tree we are proving the leaf membership in.\n- For an on-chain cryptocurrency mixer, we must provide a private transaction relaying service that the user decides a prior, as well as paying the fee for that service. This data is included in arbitrary input -- by doing a hash of these values (relayer address, fee, recipient, etc.).\n\nIt's worth mentioning that all the values included in arbitrary input bind the proof to those values. This helps prevent tampering if for example, a user wants to change the recipient after proof generation. If the public inputs change for a proof submitted on-chain, the proof will fail with the underlying security of the zkSNARK. We leverage this design to provide the right incentives for users and relayers of the end application, an on-chain cryptocurrency mixer.\n\n\u003ch2 id=\"anchor\"\u003e Anchor \u003c/h2\u003e\n\nAnchor protocol is very similar to the mixer. Instead of proving the membership inside one Merkle tree, we are proving the inclusion in one of many Merkle trees. These trees can live on many different blockchains, and if the Merkle tree states are synced across chains, this will allow us to make cross-chain anonymous transactions. A higher-level overview of how Anchor works:\n\n1. We are computing the leaf commitment using the Poseidon hash function passing: `secret` (private input), `nullifier` (private input) and chain id (public input).\n2. We are computing the nullifier hash using the Poseidon hash function, passing: `nullifier` (private input)\n3. We are calculating the root hash using the calculated leaf and the path (private input)\n4. We are checking if the calculated root is inside the set (public input) using the SetGadget.\n\n\u003ch3 id=\"aleaf\"\u003e Leaf structure \u003c/h3\u003e\n\nLeaf structure is similar to that of a mixer, except we are also introducing a chain id as public input. Chain id ensures that you can only withdraw on one chain, thus preventing double-spending. So, an Anchor leaf consists of a `secret` (random value), `nullifier` (random value) and `chain_id`.\n\n\u003ch3 id=\"apublic\"\u003e Public input structure \u003c/h3\u003e\n\n1. Chain Id\n1. Nullifier hash\n1. Merkle root set\n1. Arbitrary Input\n\n- Chain Id - ensures that you only withdraw on one chain and prevents double-spending.\n- Nullifier hash is the same as in the mixer, except it's used in a multi-chain context. Meaning it will be registered on a chain that has an Id the same as Chain Id (our public input).\n- Merkle root set is an array of root hashes. It consists of a local root (root on the chain the withdrawal is made) and roots from other chains that are connected to the local one.\n- Arbitrary Input has the same purpose as the Mixers. It consists of: Recipient, Relayer, Fee, Refund, and Commitment (Commitment is used for refreshing your leaf -- meaning inserting a new leaf as a replacement for the old one if the value of commitment is non-zero).\n\n\u003ch2 id=\"vanchor\"\u003e VAnchor \u003c/h2\u003e\n\nVAnchor is short for Variable Anchor as it introduces the concept of variable deposit amounts. It supports anonymous join-split functionality which allows joining multiple previous deposits into multiple new deposits. VAnchor also supports cross-chain transactions. Higher-level overview of how VAnchor works:\n\n1. Using the input Utxos and corresponding Merkle paths, we are calculating the root hashes for each Utxo.\n2. We are checking if the root hash of each Utxo is a member of a root set. We are doing this with SetGadget.\n3. Using the output Utxos we are proving the leaf creation from passed private inputs.\n4. We are making sure that the sum of input amounts plus the public amount is equal to the sum of output amounts.\n\n\u003ch3 id=\"utxo\"\u003e UTXOs \u003c/h3\u003e\n\nUTXOs stand for unspent transaction outputs. Each UTXO represents a shielded balance that can be spent in the system. To create new UTXOs one must prove ownership over existing UTXOs that have at least as much balance as the newly created ones.\n\nUTXOs contains a value, denoting the amount contained in the UTXO, the chain ID where the UTXO is meant to be spent, and secret data relevant for creating zero-knowledge proofs of ownership and membership over.\n\nUTXOs are deposited and stored in on-chain Merkle trees first by serializing its components and then by hashing the serialized data before insertion. Each hash can be considered a commitment to a UTXO. To create new UTXOs from old ones, users must submit valid zero-knowledge proofs that satisfy constraints around the consistency of values and membership within a set of Merkle roots.\n\n\u003ch3 id=\"vpublic\"\u003e Public inputs \u003c/h3\u003e\n\n1. Public amount\n2. Arbitrary input\n3. Array of Nullifier hashes for each Utxo\n4. Array of Leaf commitments for each Utxo\n5. Chain id where the transaction is made\n6. Merkle root set\n\n- Public amount specifies the amount being deposited or withdrawn. A negative value means that we are withdrawing and positive means we are depositing.\n- Arbitrary input is not included in the computation.\n- Array of nullifier hashes relates to the input Utxos, or the Utxos we want to spend\n- Array of leaf commitments relates to the output Utxos, or the Utxos we want to deposit\n- Chain Id and Merkle root set remain the same as in the Anchor\n\n\u003ch1 id=\"usage\"\u003e Example usage of the API \u003c/h1\u003e\n\n\u003ch2 id=\"mexample\"\u003e Mixer - Generating leaf commitments and zero-knowledge proof \u003c/h2\u003e\n\n```rust\nuse arkworks_setups::{\n\tcommon::{Leaf, MixerProof},\n\tr1cs::mixer::MixerR1CSProver,\n\tCurve, MixerProver,\n};\n\n// Setting up the constants\n// Default leaf in Merkle Tree\nconst DEFAULT_LEAF: [u8; 32] = [0u8; 32];\n// Merkle tree heigth (or depth)\nconst TREE_HEIGHT: usize = 30;\n\n// Setting up the types\ntype Bn254 = ark_bn254::Bn254;\ntype MixerR1CSProver_Bn254_30 = MixerR1CSProver\u003cBn254, TREE_HEIGHT\u003e;\n\n// Random leaf creating\nlet Leaf {\n\tsecret_bytes,\n\tnullifier_bytes,\n\tleaf_bytes,\n\tnullifier_hash_bytes,\n\t..\n} = MixerR1CSProver_Bn254_30::create_random_leaf(curve, rng)?\n\n// Or in case you want to specify you own secret and nullifier\nlet Leaf {\n\tleaf_bytes,\n\tnullifier_hash_bytes,\n\t..\n} = MixerR1CSProverBn254_30::create_leaf_with_privates(\n\tcurve,\n\tsecret_bytes,\n\tnullifier_bytes,\n)?;\n\n// Proof generation\nlet MixerProof {\n\tproof,\n\t..\n} = MixerR1CSProver_Bn254_30::create_proof(\n\tcurve,\n\tsecret_bytes,\n\tnullifier_bytes,\n\tleaves,\n\tindex,\n\trecipient_bytes,\n\trelayer_bytes,\n\tfee_value,\n\trefund_value,\n\tpk_bytes,\n\tDEFAULT_LEAF,\n\trng,\n)?;\n```\n\n\u003ch2 id=\"aexample\"\u003e Anchor - Generating leaf commitments and zero-knowledge proof \u003c/h2\u003e\n\n```rust\nuse arkworks_native_gadgets::poseidon::Poseidon;\nuse arkworks_setups::{\n\tcommon::{\n\t\tsetup_params,\n\t\tsetup_tree_and_create_path,\n\t\tAnchorProof,\n\t\tLeaf,\n\t},\n\tr1cs::anchor::AnchorR1CSProver,\n\tAnchorProver, Curve,\n};\n\n// Setting up the constants\n// Default leaf used in Merkle Tree\nconst DEFAULT_LEAF: [u8; 32] = [0u8; 32];\n// Merkle tree depth (or height)\nconst TREE_DEPTH: usize = 30;\n// Number of anchors (Merkle trees we are proving the membership in)\nconst ANCHOR_CT: usize = 2;\n\ntype Bn254 = ark_bn254::Bn254;\ntype AnchorR1CSProver_Bn254_30_2 = AnchorR1CSProver\u003c\n\tBn254,\n\tTREE_DEPTH,\n\tANCHOR_CT\n\u003e;\n\n// Creating a leaf\nlet Leaf {\n\tsecret_bytes,\n\tnullifier_bytes,\n\tleaf_bytes,\n\tnullifier_hash_bytes,\n\t..\n} = AnchorR1CSProver_Bn254_30_2::create_random_leaf(\n\tcurve,\n\tchain_id,\n\trng\n)?;\n\n// Or in case you want to specify you own secret and nullifier\nlet Leaf {\n\tleaf_bytes,\n\tnullifier_hash_bytes,\n\t..\n} = AnchorR1CSProver_Bn254_30_2::create_leaf_with_privates(\n\tcurve,\n\tchain_id,\n\tsecret_bytes,\n\tnullifier_bytes,\n)?;\n\n// Creating the proof\nlet AnchorProof {\n\tproof,\n\t..\n} = AnchorR1CSProver_Bn254_30_2::create_proof(\n\tcurve,\n\tchain_id,\n\tsecret_bytes,\n\tnullifier_bytes,\n\tleaves,\n\tindex,\n\troots_raw,\n\trecipient_bytes,\n\trelayer_bytes,\n\tfee_value,\n\trefund_value,\n\tcommitment_bytes,\n\tpk_bytes,\n\tDEFAULT_LEAF,\n\trng,\n)?\n```\n\n\u003ch2 id=\"vexample\"\u003e VAnchor - Generating Utxos and zero-knowledge proof \u003c/h2\u003e\n\n```rust\nuse arkworks_setups::{\n\tcommon::{\n\t\tprove_unchecked,\n\t\tsetup_params,\n\t\tsetup_tree_and_create_path\n\t},\n\tr1cs::vanchor::VAnchorR1CSProver,\n\tutxo::Utxo,\n\tCurve, VAnchorProver,\n};\n\n// Default leaf for the Merkle Tree\nconst DEFAULT_LEAF: [u8; 32] = [0u8; 32];\n// Merkle tree depth (or heigth)\nconst TREE_DEPTH: usize = 30;\n// Number of anchors (Merkle trees we are proving the membership in)\nconst ANCHOR_CT: usize = 2;\n// Number of input transactions\nconst NUM_INS: usize = 2;\n// Number of output transactions\nconst NUM_OUTS: usize = 2;\n\ntype Bn254 = ark_bn254::Bn254;\n\ntype VAnchorProver_Bn254_30_2x2 = VAnchorR1CSProver\u003c\n\tBn254,\n\tTREE_DEPTH,\n\tANCHOR_CT,\n\tNUM_INS,\n\tNUM_OUTS\n\u003e;\n\n// Input Utxo number 1\nlet in_utxo_1 = VAnchorProver_Bn254_30_2x2::create_random_utxo(\n\tcurve,\n\tin_chain_id_1,\n\tin_amount_1,\n\tin_index_1,\n\trng,\n)?;\n\n// Input Utxo number 2\nlet in_utxo_2 = VAnchorProver_Bn254_30_2x2::create_random_utxo(\n\tcurve,\n\tin_chain_id_2,\n\tin_amount_2,\n\tin_index_2,\n\trng,\n)?;\n\n// Output Utxo number 1\nlet out_utxo_1 = VAnchorProver_Bn254_30_2x2::create_random_utxo(\n\tcurve,\n\tout_chain_id_1,\n\tout_amount_1,\n\tout_index_1,\n\trng,\n)?;\n\n// Output Utxo number 2\nlet out_utxo_2 = VAnchorProver_Bn254_30_2x2::create_random_utxo(\n\tcurve,\n\tout_chain_id_2,\n\tout_amount_2,\n\tout_index_2,\n\trng,\n)?;\n\n// Making an array of Utxos\nlet in_utxos = [in_utxo_1, in_utxo_2];\nlet out_utxos = [out_utxo_1, out_utxo_2];\n\n// Generating proof\nlet VAnchorProof {\n\tproof,\n\t..\n} = VAnchorProver_Bn254_30_2x2::create_proof(\n\tcurve,\n\tchain_id,\n\tpublic_amount,\n\text_data_hash,\n\tin_root_set,\n\tin_indices,\n\tin_leaves,\n\tin_utxos,\n\tout_utxos,\n\tpk_bytes,\n\tDEFAULT_LEAF,\n\trng,\n)?;\n```\n\n\u003ch2 id=\"merkle\"\u003e Merkle Tree - Generating the Sparse Merkle Tree and Merkle path \u003c/h2\u003e\n\n```rust\n// NOTE: This is optional and for tests only.\n// There should be an on-chain mechanism for\n// storing the roots of connected anchors,\n// and way of fetching them before passing them\n// into the circuits\nlet params3 = setup_params::\u003cBn254Fr\u003e(curve, 5, 3);\nlet poseidon3 = Poseidon::new(params3);\nlet (tree, path) = setup_tree_and_create_path::\u003c\n\tBn254Fr,\n\tPoseidon\u003cBn254Fr\u003e,\n\tTREE_DEPTH\n\u003e(\n\t\u0026poseidon3,\n\t\u0026leaves_f,\n\tindex,\n\t\u0026DEFAULT_LEAF,\n)?;\nlet root = tree.root();\n// or\nlet root = path.calculate_root(\u0026leaf, \u0026poseidon3)?\n```\n\n\u003ch2 id=\"param\"\u003e Parameter generation \u003c/h2\u003e\n\nParameter for the sage [script](https://github.com/webb-tools/bulletproof-gadgets/tree/main/src/crypto_constants/data/poseidon).\n\n\u003ch1 id=\"smart\"\u003e Usage in smart contracts \u003c/h1\u003e\n\n4 things need to be prepared before using the circuits inside an on-chain smart contract application or similar.\n\n1. Generated proving and verifying keys.\n2. Storing the verifying key inside on-chain storage.\n3. An on-chain Merkle Tree data structure.\n4. A data structure for used nullifier hashes inside on-chain storage.\n5. Functionality for long-term storage of encrypted notes that contain the preimage of the leaf commitments.\n\nOnce these points are satisfied, we can successfully implement a Mixer/Anchor/VAnchor application. In the example of Mixer, the order of events goes as follows:\n\n1. A user sends the proof along with public inputs:\n   - Nullifier Hash\n   - Merkle root\n   - Arbitrary data\n2. We check if the root is the same as the on-chain Merkle root.\n3. We verify the proof using the on-chain verifying key.\n4. We register the nullifier hash as used, to prevent a double-spending attack.\n\nExamples of implementations of these protocols:\n\n- Mixer - [Substrate Pallet](https://github.com/webb-tools/protocol-substrate/blob/main/pallets/mixer/src/lib.rs), [Cosmos (CosmWasm smart contracts)](https://github.com/webb-tools/protocol-cosmwasm/blob/main/contracts/mixer/src/contract.rs)\n- Anchor - [Substrate Pallet](https://github.com/webb-tools/protocol-substrate/blob/main/pallets/anchor/src/lib.rs), [Cosmos (CosmWasm smart contracts)](https://github.com/webb-tools/protocol-cosmwasm/blob/main/contracts/anchor/src/contract.rs), [Ethereum (Solidity smart contracts)](https://github.com/webb-tools/protocol-solidity/tree/main/contracts/anchors)\n- VAnchor [Substrate Pallet](https://github.com/webb-tools/protocol-substrate/blob/main/pallets/vanchor/src/lib.rs), [Ethereum (Solidity smart contracts)](https://github.com/webb-tools/protocol-solidity/tree/main/contracts/vanchors)\n\nLinks to relayer services for these protocols:\n\n- [Mixer/Anchor](https://github.com/webb-tools/relayer/blob/main/src/handler.rs)\n\nLinks to trusted setup ceremony examples:\n\n- [aleo-setup](https://github.com/AleoHQ/aleo-setup)\n- [celo-setup](https://github.com/celo-org/snark-setup)\n\n\u003ch1 id=\"smart\"\u003e Test \u003c/h1\u003e\n\n- You can run all the `arkworks/setups` test by running the command\n   `cargo test --features r1cs,plonk --release`\n\n- You can run a specific test by specifying the name of the test to run with the command \n   `cargo test setup_and_prove_2_anchors --features r1cs,plonk --release`\n\n\n\u003ch1 id=\"grat\"\u003e Gratitude \u003c/h1\u003e\n\nWe are grateful to the arkworks community for their open-source first approach to zero-knowledge infrastructure. Many of the gadgets here leverage tools that are found in other repos and that are open source. Specifically, we leverage the sparse Merkle tree data structures from the [ivls](https://github.com/arkworks-rs/ivls/tree/master/src/building_blocks/mt/merkle_sparse_tree) project on incrementally verifiable computation. This work would not have been possible without that.\n\nMany thanks to the following people for help and insights in both learning and implementing these gadgets \u0026 circuits:\n\n- [@weikengchen](https://github.com/weikengchen)\n- [@Pratyush](https://github.com/Pratyush)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangle-network%2Fzero-knowledge-gadgets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftangle-network%2Fzero-knowledge-gadgets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftangle-network%2Fzero-knowledge-gadgets/lists"}