rings_snark/r1cs/
mod.rs

1//! Utils for r1cs
2pub mod reader;
3
4use std::io::Cursor;
5
6use ff::PrimeField;
7use serde::Deserialize;
8use serde::Serialize;
9use wasmer::Module;
10
11use crate::error::Error;
12use crate::error::Result;
13use crate::witness::calculator::WitnessCalculator;
14
15/// type of constraint
16pub(crate) type Constraint<F> = (Vec<(usize, F)>, Vec<(usize, F)>, Vec<(usize, F)>);
17
18/// R1CS
19#[derive(Clone, Debug, Serialize, Deserialize)]
20pub struct R1CS<F: PrimeField> {
21    /// number inputs of r1cs
22    pub num_inputs: usize,
23    /// number aux variable of r1cs
24    pub num_aux: usize,
25    /// number of total variables
26    pub num_variables: usize,
27    /// constraints
28    pub constraints: Vec<Constraint<F>>,
29}
30
31/// Path of a r1cs
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub enum Path {
34    /// Local filesystem path
35    Local(String),
36    /// A remote resource needs to fetch
37    Remote(String),
38}
39
40/// format of R1CS, can be bin or json format
41pub enum Format {
42    /// JSON format
43    Json,
44    /// BIN Format
45    Bin,
46}
47
48/// Define witness, which is a vector of prime field.
49pub type TyWitness<F> = Vec<F>;
50
51/// Fetch remote resources to Read
52pub(crate) async fn fetch(url: &str) -> Result<Cursor<Vec<u8>>> {
53    let resp = reqwest::get(url).await?;
54    let bytes = resp.bytes().await?;
55    Ok(Cursor::new(bytes.to_vec()))
56}
57
58/// Fetch remote r1cs
59pub async fn load_r1cs_remote<F: PrimeField>(url: &str, format: Format) -> Result<R1CS<F>> {
60    let data = fetch(url).await?;
61    let ret = match format {
62        Format::Json => reader::load_r1cs_from_json::<F, Cursor<Vec<u8>>>(data),
63        Format::Bin => reader::load_r1cs_from_bin::<F, Cursor<Vec<u8>>>(data),
64    };
65    Ok(ret)
66}
67
68/// Load local r1cs
69pub fn load_r1cs_local<F: PrimeField>(
70    path: impl AsRef<std::path::Path>,
71    format: Format,
72) -> Result<R1CS<F>> {
73    let ret = match format {
74        Format::Json => reader::load_r1cs_from_json_file::<F>(path),
75        Format::Bin => reader::load_r1cs_from_bin_file::<F>(path),
76    };
77    Ok(ret)
78}
79
80/// Load r1cs, the resource path can be remote local, and both bin and json are supported
81pub async fn load_r1cs<F: PrimeField>(path: Path, format: Format) -> Result<R1CS<F>> {
82    let ret = match path {
83        Path::Local(p) => load_r1cs_local::<F>(p, format)?,
84        Path::Remote(url) => load_r1cs_remote::<F>(&url, format).await?,
85    };
86    Ok(ret)
87}
88
89/// Fetch remote witness
90pub async fn load_witness_remote<F: PrimeField>(url: &str, format: Format) -> Result<TyWitness<F>> {
91    let data = fetch(url).await?;
92    let ret = match format {
93        Format::Json => reader::load_witness_from_bin_reader::<F, Cursor<Vec<u8>>>(data)
94            .map_err(|e| Error::WitnessFailedOnLoad(e.to_string()))?,
95        Format::Bin => reader::load_witness_from_json::<F, Cursor<Vec<u8>>>(data),
96    };
97    Ok(ret)
98}
99
100/// Load witness local
101pub fn load_witness_local<F: PrimeField>(
102    path: impl AsRef<std::path::Path>,
103    format: Format,
104) -> Result<TyWitness<F>> {
105    let ret = match format {
106        Format::Json => reader::load_witness_from_bin_file::<F>(path),
107        Format::Bin => reader::load_witness_from_json_file::<F>(path),
108    };
109    Ok(ret)
110}
111
112/// Load r1cs, the resource path can be remote local, and both bin and json are supported
113pub async fn load_witness<F: PrimeField>(path: Path, format: Format) -> Result<TyWitness<F>> {
114    match path {
115        Path::Local(p) => load_witness_local::<F>(p, format),
116        Path::Remote(url) => load_witness_remote::<F>(&url, format).await,
117    }
118}
119
120/// Load witness calculator from local path
121pub fn load_circom_witness_calculator_local(
122    path: impl AsRef<std::path::Path>,
123) -> Result<WitnessCalculator> {
124    WitnessCalculator::from_file(path).map_err(|e| Error::WASMFailedToLoad(e.to_string()))
125}
126
127/// Load witness calculator from remote path
128pub async fn load_circom_witness_calculator_remote(path: &str) -> Result<WitnessCalculator> {
129    let store = WitnessCalculator::new_store();
130    let data = fetch(path).await?;
131    let module = Module::from_binary(&store, data.get_ref().as_slice())?;
132    WitnessCalculator::from_module(module, store)
133}
134
135/// Load witness calculator from local path or remote url
136pub async fn load_circom_witness_calculator(path: Path) -> Result<WitnessCalculator> {
137    match path {
138        Path::Local(p) => load_circom_witness_calculator_local(p),
139        Path::Remote(url) => load_circom_witness_calculator_remote(&url).await,
140    }
141}