{"id":13632376,"url":"https://github.com/0xPolygonZero/r1cs","last_synced_at":"2025-04-18T02:32:47.317Z","repository":{"id":57665890,"uuid":"187787559","full_name":"0xPolygonZero/r1cs","owner":"0xPolygonZero","description":"A Rust library for building R1CS gadgets","archived":false,"fork":false,"pushed_at":"2021-10-14T19:18:11.000Z","size":369,"stargazers_count":86,"open_issues_count":0,"forks_count":5,"subscribers_count":10,"default_branch":"master","last_synced_at":"2024-10-12T17:27:21.661Z","etag":null,"topics":["cryptography","r1cs","zk-snarks"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xPolygonZero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-21T07:46:15.000Z","updated_at":"2024-10-08T04:21:29.000Z","dependencies_parsed_at":"2022-09-14T13:01:27.530Z","dependency_job_id":null,"html_url":"https://github.com/0xPolygonZero/r1cs","commit_stats":null,"previous_names":["mir-protocol/rusty-gadgets","0xpolygonzero/r1cs","mir-protocol/r1cs"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygonZero%2Fr1cs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygonZero%2Fr1cs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygonZero%2Fr1cs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygonZero%2Fr1cs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xPolygonZero","download_url":"https://codeload.github.com/0xPolygonZero/r1cs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223772183,"owners_count":17199969,"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":["cryptography","r1cs","zk-snarks"],"created_at":"2024-08-01T22:03:01.818Z","updated_at":"2024-11-09T00:31:09.728Z","avatar_url":"https://github.com/0xPolygonZero.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# r1cs [![Crates.io](https://img.shields.io/crates/v/r1cs)](https://crates.io/crates/r1cs) [![docs.rs](https://docs.rs/r1cs/badge.svg)](https://docs.rs/r1cs)\n\nThis is a rust library for building R1CS gadgets over prime fields, which are useful in SNARKs and other argument systems.\n\nAn R1CS instance is defined by three matrices, `A`, `B` and `C`. These encode the following NP-complete decision problem: does there exist a witness vector `w` such that `Aw ∘ Bw = Cw`?\n\nA *gadget* for some R1CS instance takes a set of inputs, which are a subset of the witness vector. If the given inputs are valid, it extends the input set into a complete witness vector which satisfies the R1CS instance.\n\n\n## Features\n\nThe goal of this library is to make SNARK programming easy. To that end, we support a broad set of features, including some fairly high-level abstractions:\n\n- Basic operations on field elements, such as multiplication, division, and comparisons\n- Type-safe boolean operations, such as `GadgetBuilder::and` and `GadgetBuilder::bitwise_and`\n- Type-safe binary operations, such as `GadgetBuilder::binary_sum`\n- `GadgetBuilder::assert_permutation`, which efficiently verifies a permutation using an AS-Waksman network\n- Methods for sorting lists of expressions, such as `GadgetBuilder::sort_ascending`\n- Methods for working with Merkle trees, such as `GadgetBuilder::merkle_tree_root`\n- Common cryptographic constructions such as Merkle-Damgård, Davies-Meyer, and Sponge functions\n- R1CS-friendly primitives like MiMC, Poseidon and Rescue\n\n\n## Core types\n\n`Field` is a trait representing prime fields. An `Element\u003cF\u003e` is an element of the prime field `F`.\n\nA `Wire` is an element of the witness vector. An `Expression\u003cF\u003e` is a linear combination of wires.\n\nA `BooleanWire` is a `Wire` which has been constrained in such a way that it can only equal 0 or 1. Similarly, a `BooleanExpression\u003cF\u003e` is an `Expression\u003cF\u003e` which has been so constrained.\n\nA `BinaryWire` is a vector of `BooleanWire`s. Similarly, a `BinaryExpression\u003cF\u003e` is a vector of `BooleanExpression\u003cF\u003e`s.\n\n\n## Basic example\n\nHere's a simple gadget which computes the cube of a BN128 field element:\n\n```rust\n// Create a gadget which takes a single input, x, and computes x*x*x.\nlet mut builder = GadgetBuilder::\u003cBn128\u003e::new();\nlet x = builder.wire();\nlet x_exp = Expression::from(x);\nlet x_squared = builder.product(\u0026x_exp, \u0026x_exp);\nlet x_cubed = builder.product(\u0026x_squared, \u0026x_exp);\nlet gadget = builder.build();\n\n// This structure maps wires to their (field element) values. Since\n// x is our input, we will assign it a value before executing the\n// gadget. Other wires will be computed by the gadget.\nlet mut values = values!(x =\u003e 5u8.into());\n\n// Execute the gadget and assert that all constraints were satisfied.\nlet constraints_satisfied = gadget.execute(\u0026mut values);\nassert!(constraints_satisfied);\n\n// Check the result.\nassert_eq!(Element::from(125u8), x_cubed.evaluate(\u0026values));\n```\n\nThis can also be done more succinctly with `builder.exp(x_exp, 3)`, which performs exponentiation by squaring.\n\n\n## Custom fields\n\nYou can define a custom field by implementing the `Field` trait. As an example, here's the definition of `Bn128` which was referenced above:\n\n```rust\npub struct Bn128 {}\n\nimpl Field for Bn128 {\n    fn order() -\u003e BigUint {\n        BigUint::from_str(\n            \"21888242871839275222246405745257275088548364400416034343698204186575808495617\"\n        ).unwrap()\n    }\n}\n```\n\n\n## Cryptographic tools\n\nSuppose we wanted to hash a vector of `Expression`s. One approach would be to take a block cipher like MiMC, transform it into a one-way compression function using the Davies-Meyer construction, and transform that into a hash function using the Merkle-Damgård construction. We could do that like so:\n\n```rust\nfn hash\u003cF: Field\u003e(\n    builder: \u0026mut GadgetBuilder\u003cF\u003e,\n    blocks: \u0026[Expression\u003cF\u003e]\n) -\u003e Expression\u003cF\u003e {\n    let cipher = MiMCBlockCipher::default();\n    let compress = DaviesMeyer::new(cipher);\n    let hash = MerkleDamgard::new_defaults(compress);\n    hash.hash(builder, blocks)\n}\n```\n\n\n## Permutation networks\n\nTo verify that two lists are permutations of one another, you can use `assert_permutation`. This is implemented using AS-Waksman permutation networks, which permute `n` items using roughly `n log_2(n) - n` switches. Each switch involves two constraints: one \"is boolean\" check, and one constraint for routing.\n\nPermutation networks make it easy to implement sorting gadgets, which we provide in the form of `sort_ascending` and `sort_descending`.\n\n\n## Non-determinism\n\nSuppose we wish to compute the multiplicative inverse of a field element `x`. While this is possible to do in a deterministic arithmetic circuit, it is prohibitively expensive. What we can do instead is have the user compute `x_inv = 1 / x`, provide the result as a witness element, and add a constraint in the R1CS instance to verify that `x * x_inv = 1`.\n\n`GadgetBuilder` supports such non-deterministic computations via its `generator` method, which can be used like so:\n\n```rust\nfn inverse\u003cF: Field\u003e(builder: \u0026mut GadgetBuilder\u003cF\u003e, x: Expression\u003cF\u003e) -\u003e Expression\u003cF\u003e {\n    // Create a new witness element for x_inv.\n    let x_inv = builder.wire();\n\n    // Add the constraint x * x_inv = 1.\n    builder.assert_product(\u0026x, \u0026Expression::from(x_inv),\n                           \u0026Expression::one());\n\n    // Non-deterministically generate x_inv = 1 / x.\n    builder.generator(\n        x.dependencies(),\n        move |values: \u0026mut WireValues\u003cF\u003e| {\n            let x_value = x.evaluate(values);\n            let x_inv_value = x_value.multiplicative_inverse();\n            values.set(x_inv, x_inv_value);\n        },\n    );\n\n    // Output x_inv.\n    x_inv.into()\n}\n```\n\nThis is roughly equivalent to the built-in `GadgetBuilder::inverse` method, with slight modifications for readability.\n\n\n## Backends\n\nThe [r1cs-zkinterface](https://crates.io/crates/r1cs-zkinterface) crate can be used to export these gadgets to the standard zkinterface format.\n\nThere is also a direct backend for [bellman](https://crates.io/crates/bellman) via the [r1cs-bellman](https://crates.io/crates/r1cs-bellman) crate.\n\n\n## Disclaimer\n\nThis code has not been thoroughly reviewed or tested, and should not be used in any production systems.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xPolygonZero%2Fr1cs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xPolygonZero%2Fr1cs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xPolygonZero%2Fr1cs/lists"}