Merge pull request #1289 from Zokrates/backend-opt
Optimize backend integrations
This commit is contained in:
commit
10ebd604f3
48 changed files with 379 additions and 257 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -13,6 +13,7 @@ verifier.sol
|
|||
proof.json
|
||||
universal_setup.dat
|
||||
witness
|
||||
witness.json
|
||||
|
||||
# ZoKrates source files at the root of the repository
|
||||
/*.zok
|
||||
|
|
9
Cargo.lock
generated
9
Cargo.lock
generated
|
@ -2036,9 +2036,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.6.1"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
|
||||
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
|
@ -2046,9 +2046,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
|
||||
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
|
||||
dependencies = [
|
||||
"crossbeam-channel 0.5.6",
|
||||
"crossbeam-deque 0.8.2",
|
||||
|
@ -2961,7 +2961,6 @@ dependencies = [
|
|||
"ark-bls12-377",
|
||||
"byteorder",
|
||||
"cfg-if 0.1.10",
|
||||
"csv",
|
||||
"derivative",
|
||||
"num-bigint 0.2.6",
|
||||
"pairing_ce",
|
||||
|
|
1
changelogs/unreleased/1289-dark64
Normal file
1
changelogs/unreleased/1289-dark64
Normal file
|
@ -0,0 +1 @@
|
|||
Change witness format to binary, optimize backend integration code to improve proving time
|
|
@ -28,7 +28,7 @@ ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = f
|
|||
ark-bw6-761 = { version = "^0.3.0", default-features = false }
|
||||
ark-gm17 = { version = "^0.3.0", default-features = false }
|
||||
ark-groth16 = { version = "^0.3.0", default-features = false }
|
||||
ark-serialize = { version = "^0.3.0", default-features = false }
|
||||
ark-serialize = { version = "^0.3.0", default-features = false, features = ["std"] }
|
||||
ark-relations = { version = "^0.3.0", default-features = false }
|
||||
ark-marlin = { git = "https://github.com/arkworks-rs/marlin", rev = "63cfd82", default-features = false }
|
||||
ark-poly = { version = "^0.3.0", default-features = false }
|
||||
|
|
|
@ -40,11 +40,16 @@ impl<T: Field + ArkFieldExtensions> NonUniversalBackend<T, GM17> for Ark {
|
|||
}
|
||||
|
||||
impl<T: Field + ArkFieldExtensions> Backend<T, GM17> for Ark {
|
||||
fn generate_proof<'a, I: IntoIterator<Item = Statement<'a, T>>, R: RngCore + CryptoRng>(
|
||||
fn generate_proof<
|
||||
'a,
|
||||
I: IntoIterator<Item = Statement<'a, T>>,
|
||||
R: std::io::Read,
|
||||
G: RngCore + CryptoRng,
|
||||
>(
|
||||
program: ProgIterator<'a, T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
rng: &mut R,
|
||||
proving_key: R,
|
||||
rng: &mut G,
|
||||
) -> Proof<T, GM17> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
||||
|
@ -54,10 +59,9 @@ impl<T: Field + ArkFieldExtensions> Backend<T, GM17> for Ark {
|
|||
.map(parse_fr::<T>)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_unchecked(
|
||||
&mut proving_key.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
let pk =
|
||||
ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_unchecked(proving_key)
|
||||
.unwrap();
|
||||
|
||||
let proof = ArkGM17::<T::ArkEngine>::prove(&pk, computation, rng).unwrap();
|
||||
let proof_points = ProofPoints {
|
||||
|
@ -136,7 +140,10 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let proof = <Ark as Backend<Bls12_377Field, GM17>>::generate_proof(
|
||||
program, witness, keypair.pk, rng,
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Ark as Backend<Bls12_377Field, GM17>>::verify(keypair.vk, proof);
|
||||
|
||||
|
@ -160,8 +167,12 @@ mod tests {
|
|||
.execute(program.clone(), &[Bw6_761Field::from(42)])
|
||||
.unwrap();
|
||||
|
||||
let proof =
|
||||
<Ark as Backend<Bw6_761Field, GM17>>::generate_proof(program, witness, keypair.pk, rng);
|
||||
let proof = <Ark as Backend<Bw6_761Field, GM17>>::generate_proof(
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Ark as Backend<Bw6_761Field, GM17>>::verify(keypair.vk, proof);
|
||||
|
||||
assert!(ans);
|
||||
|
|
|
@ -4,6 +4,7 @@ use ark_groth16::{
|
|||
ProvingKey, VerifyingKey,
|
||||
};
|
||||
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
||||
use std::io::Read;
|
||||
use zokrates_field::ArkFieldExtensions;
|
||||
use zokrates_field::Field;
|
||||
use zokrates_proof_systems::{Backend, NonUniversalBackend, Proof, SetupKeypair};
|
||||
|
@ -17,11 +18,16 @@ use zokrates_proof_systems::groth16::{ProofPoints, VerificationKey, G16};
|
|||
use zokrates_proof_systems::Scheme;
|
||||
|
||||
impl<T: Field + ArkFieldExtensions> Backend<T, G16> for Ark {
|
||||
fn generate_proof<'a, I: IntoIterator<Item = Statement<'a, T>>, R: RngCore + CryptoRng>(
|
||||
fn generate_proof<
|
||||
'a,
|
||||
I: IntoIterator<Item = Statement<'a, T>>,
|
||||
R: Read,
|
||||
G: RngCore + CryptoRng,
|
||||
>(
|
||||
program: ProgIterator<'a, T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
rng: &mut R,
|
||||
proving_key: R,
|
||||
rng: &mut G,
|
||||
) -> Proof<T, G16> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
||||
|
@ -31,12 +37,12 @@ impl<T: Field + ArkFieldExtensions> Backend<T, G16> for Ark {
|
|||
.map(parse_fr::<T>)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_unchecked(
|
||||
&mut proving_key.as_slice(),
|
||||
)
|
||||
.unwrap();
|
||||
let pk =
|
||||
ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_unchecked(proving_key)
|
||||
.unwrap();
|
||||
|
||||
let proof = Groth16::<T::ArkEngine>::prove(&pk, computation, rng).unwrap();
|
||||
|
||||
let proof_points = ProofPoints {
|
||||
a: parse_g1::<T>(&proof.a),
|
||||
b: parse_g2::<T>(&proof.b),
|
||||
|
@ -133,7 +139,10 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let proof = <Ark as Backend<Bls12_377Field, G16>>::generate_proof(
|
||||
program, witness, keypair.pk, rng,
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Ark as Backend<Bls12_377Field, G16>>::verify(keypair.vk, proof);
|
||||
|
||||
|
@ -157,8 +166,12 @@ mod tests {
|
|||
.execute(program.clone(), &[Bw6_761Field::from(42)])
|
||||
.unwrap();
|
||||
|
||||
let proof =
|
||||
<Ark as Backend<Bw6_761Field, G16>>::generate_proof(program, witness, keypair.pk, rng);
|
||||
let proof = <Ark as Backend<Bw6_761Field, G16>>::generate_proof(
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Ark as Backend<Bw6_761Field, G16>>::verify(keypair.vk, proof);
|
||||
|
||||
assert!(ans);
|
||||
|
|
|
@ -9,7 +9,7 @@ use ark_relations::r1cs::{
|
|||
};
|
||||
use std::collections::BTreeMap;
|
||||
use zokrates_ast::common::Variable;
|
||||
use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness};
|
||||
use zokrates_ast::ir::{LinComb, ProgIterator, Statement, Witness};
|
||||
use zokrates_field::{ArkFieldExtensions, Field};
|
||||
|
||||
pub use self::parse::*;
|
||||
|
@ -39,7 +39,7 @@ impl<'a, T, I: IntoIterator<Item = Statement<'a, T>>> Computation<'a, T, I> {
|
|||
}
|
||||
|
||||
fn ark_combination<T: Field + ArkFieldExtensions>(
|
||||
l: CanonicalLinComb<T>,
|
||||
l: LinComb<T>,
|
||||
cs: &mut ConstraintSystem<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
|
||||
symbols: &mut BTreeMap<Variable, ArkVariable>,
|
||||
witness: &mut Witness<T>,
|
||||
|
@ -113,24 +113,9 @@ impl<'a, T: Field + ArkFieldExtensions, I: IntoIterator<Item = Statement<'a, T>>
|
|||
|
||||
for statement in self.program.statements {
|
||||
if let Statement::Constraint(quad, lin, _) = statement {
|
||||
let a = ark_combination(
|
||||
quad.left.clone().into_canonical(),
|
||||
&mut cs,
|
||||
&mut symbols,
|
||||
&mut witness,
|
||||
);
|
||||
let b = ark_combination(
|
||||
quad.right.clone().into_canonical(),
|
||||
&mut cs,
|
||||
&mut symbols,
|
||||
&mut witness,
|
||||
);
|
||||
let c = ark_combination(
|
||||
lin.into_canonical(),
|
||||
&mut cs,
|
||||
&mut symbols,
|
||||
&mut witness,
|
||||
);
|
||||
let a = ark_combination(quad.left, &mut cs, &mut symbols, &mut witness);
|
||||
let b = ark_combination(quad.right, &mut cs, &mut symbols, &mut witness);
|
||||
let c = ark_combination(lin, &mut cs, &mut symbols, &mut witness);
|
||||
|
||||
cs.enforce_constraint(a, b, c)?;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
|
|||
use digest::Digest;
|
||||
use rand_0_8::{CryptoRng, Error, RngCore, SeedableRng};
|
||||
use sha3::Keccak256;
|
||||
use std::io::Read;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use zokrates_field::{ArkFieldExtensions, Field};
|
||||
|
@ -206,11 +207,16 @@ impl<T: Field + ArkFieldExtensions> UniversalBackend<T, marlin::Marlin> for Ark
|
|||
}
|
||||
|
||||
impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
||||
fn generate_proof<'a, I: IntoIterator<Item = Statement<'a, T>>, R: RngCore + CryptoRng>(
|
||||
fn generate_proof<
|
||||
'a,
|
||||
I: IntoIterator<Item = Statement<'a, T>>,
|
||||
R: Read,
|
||||
G: RngCore + CryptoRng,
|
||||
>(
|
||||
program: ProgIterator<'a, T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
rng: &mut R,
|
||||
proving_key: R,
|
||||
rng: &mut G,
|
||||
) -> Proof<T, marlin::Marlin> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
|
||||
|
@ -220,7 +226,7 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
|
|||
T::ArkEngine,
|
||||
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
|
||||
>,
|
||||
>::deserialize_unchecked(&mut proving_key.as_slice())
|
||||
>::deserialize_unchecked(proving_key)
|
||||
.unwrap();
|
||||
|
||||
let public_inputs = computation.public_inputs_values();
|
||||
|
@ -418,7 +424,10 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let proof = <Ark as Backend<Bls12_377Field, Marlin>>::generate_proof(
|
||||
program, witness, keypair.pk, rng,
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Ark as Backend<Bls12_377Field, Marlin>>::verify(keypair.vk, proof);
|
||||
|
||||
|
@ -454,7 +463,10 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let proof = <Ark as Backend<Bw6_761Field, Marlin>>::generate_proof(
|
||||
program, witness, keypair.pk, rng,
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Ark as Backend<Bw6_761Field, Marlin>>::verify(keypair.vk, proof);
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ zokrates_pest_ast = { version = "0.3.0", path = "../zokrates_pest_ast" }
|
|||
cfg-if = "0.1"
|
||||
zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
csv = "1"
|
||||
serde_cbor = "0.11.2"
|
||||
num-bigint = { version = "0.2", default-features = false }
|
||||
serde_json = { version = "1.0", features = ["preserve_order"] }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::common::{Parameter, RuntimeError, Solver, Variable};
|
||||
use crate::flat::{flat_expression_from_bits, flat_expression_from_variable_summands};
|
||||
use crate::flat::flat_expression_from_bits;
|
||||
use crate::flat::{FlatDirective, FlatExpression, FlatFunctionIterator, FlatStatement};
|
||||
use crate::typed::types::{
|
||||
ConcreteGenericsAssignment, DeclarationConstant, DeclarationSignature, DeclarationType,
|
||||
|
@ -17,6 +17,7 @@ cfg_if::cfg_if! {
|
|||
if #[cfg(feature = "bellman")] {
|
||||
use pairing_ce::bn256::Bn256;
|
||||
use zokrates_embed::{bellman::{from_bellman, generate_sha256_round_constraints}};
|
||||
use crate::flat::flat_expression_from_variable_summands;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
// A variable in a constraint system
|
||||
// id > 0 for intermediate variables
|
||||
|
@ -33,28 +34,18 @@ impl Variable {
|
|||
(self.id as usize) - 1
|
||||
}
|
||||
|
||||
pub fn try_from_human_readable(s: &str) -> Result<Self, &str> {
|
||||
if s == "~one" {
|
||||
return Ok(Variable::one());
|
||||
}
|
||||
pub fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
|
||||
writer.write_all(&self.id.to_le_bytes())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
let mut public = s.split("~out_");
|
||||
match public.nth(1) {
|
||||
Some(v) => {
|
||||
let v = v.parse().map_err(|_| s)?;
|
||||
Ok(Variable::public(v))
|
||||
}
|
||||
None => {
|
||||
let mut private = s.split('_');
|
||||
match private.nth(1) {
|
||||
Some(v) => {
|
||||
let v = v.parse().map_err(|_| s)?;
|
||||
Ok(Variable::new(v))
|
||||
}
|
||||
None => Err(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn read<R: Read>(mut reader: R) -> std::io::Result<Self> {
|
||||
let mut buf = [0; std::mem::size_of::<isize>()];
|
||||
reader.read_exact(&mut buf)?;
|
||||
|
||||
Ok(Variable {
|
||||
id: isize::from_le_bytes(buf),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,54 +41,44 @@ impl<T: Field> Witness<T> {
|
|||
Witness(BTreeMap::new())
|
||||
}
|
||||
|
||||
pub fn write<W: Write>(&self, writer: W) -> io::Result<()> {
|
||||
let mut wtr = csv::WriterBuilder::new()
|
||||
.delimiter(b' ')
|
||||
.flexible(true)
|
||||
.has_headers(false)
|
||||
.from_writer(writer);
|
||||
pub fn write<W: Write>(&self, mut writer: W) -> io::Result<()> {
|
||||
let length = self.0.len();
|
||||
writer.write_all(&length.to_le_bytes())?;
|
||||
|
||||
// Write each line of the witness to the file
|
||||
for (variable, value) in &self.0 {
|
||||
wtr.serialize((variable.to_string(), value.to_dec_string()))?;
|
||||
variable.write(&mut writer)?;
|
||||
value.write(&mut writer)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read<R: Read>(mut reader: R) -> io::Result<Self> {
|
||||
let mut rdr = csv::ReaderBuilder::new()
|
||||
.delimiter(b' ')
|
||||
.flexible(true)
|
||||
.has_headers(false)
|
||||
.from_reader(&mut reader);
|
||||
let mut witness = Self::empty();
|
||||
|
||||
let map = rdr
|
||||
.deserialize::<(String, String)>()
|
||||
.map(|r| {
|
||||
r.map(|(variable, value)| {
|
||||
let variable = Variable::try_from_human_readable(&variable).map_err(|why| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Invalid variable in witness: {}", why),
|
||||
)
|
||||
})?;
|
||||
let value = T::try_from_dec_str(&value).map_err(|_| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("Invalid value in witness: {}", value),
|
||||
)
|
||||
})?;
|
||||
Ok((variable, value))
|
||||
})
|
||||
.map_err(|e| match e.into_kind() {
|
||||
csv::ErrorKind::Io(e) => e,
|
||||
e => io::Error::new(io::ErrorKind::Other, format!("{:?}", e)),
|
||||
})?
|
||||
})
|
||||
.collect::<io::Result<BTreeMap<Variable, T>>>()?;
|
||||
let mut buf = [0; std::mem::size_of::<usize>()];
|
||||
reader.read_exact(&mut buf)?;
|
||||
|
||||
Ok(Witness(map))
|
||||
let length: usize = usize::from_le_bytes(buf);
|
||||
|
||||
for _ in 0..length {
|
||||
let var = Variable::read(&mut reader)?;
|
||||
let val = T::read(&mut reader)?;
|
||||
|
||||
witness.insert(var, val);
|
||||
}
|
||||
|
||||
Ok(witness)
|
||||
}
|
||||
|
||||
pub fn write_json<W: Write>(&self, writer: W) -> io::Result<()> {
|
||||
let map = self
|
||||
.0
|
||||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), serde_json::json!(v.to_dec_string())))
|
||||
.collect::<serde_json::Map<String, serde_json::Value>>();
|
||||
|
||||
serde_json::to_writer_pretty(writer, &map)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,32 +128,29 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_value() {
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
fn serialize_json() {
|
||||
let w = Witness(
|
||||
vec![
|
||||
(Variable::new(42), Bn128Field::from(42)),
|
||||
(Variable::public(8), Bn128Field::from(8)),
|
||||
(Variable::one(), Bn128Field::from(1)),
|
||||
]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
);
|
||||
|
||||
buff.write_all("_1 123bug".as_ref()).unwrap();
|
||||
buff.set_position(0);
|
||||
let mut buf = Cursor::new(vec![]);
|
||||
w.write_json(&mut buf).unwrap();
|
||||
|
||||
assert!(Witness::<Bn128Field>::read(buff).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wrong_variable() {
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
|
||||
buff.write_all("_1bug 123".as_ref()).unwrap();
|
||||
buff.set_position(0);
|
||||
|
||||
assert!(Witness::<Bn128Field>::read(buff).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_csv() {
|
||||
let mut buff = Cursor::new(vec![]);
|
||||
buff.write_all("whatwhat".as_ref()).unwrap();
|
||||
buff.set_position(0);
|
||||
|
||||
assert!(Witness::<Bn128Field>::read(buff).is_err());
|
||||
let output = String::from_utf8(buf.into_inner()).unwrap();
|
||||
assert_eq!(
|
||||
output.as_str(),
|
||||
r#"{
|
||||
"~out_8": "8",
|
||||
"~one": "1",
|
||||
"_42": "42"
|
||||
}"#
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ wasm = ["bellman/nolog", "bellman/wasm"]
|
|||
multicore = ["bellman/multicore", "phase2/multicore"]
|
||||
|
||||
[dependencies]
|
||||
zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false }
|
||||
zokrates_field = { version = "0.5", path = "../zokrates_field", default-features = false, features = ["bellman"] }
|
||||
zokrates_ast = { version = "0.1", path = "../zokrates_ast", default-features = false }
|
||||
zokrates_proof_systems = { version = "0.1", path = "../zokrates_proof_systems", default-features = false }
|
||||
|
||||
|
|
|
@ -20,14 +20,19 @@ use zokrates_proof_systems::groth16::{ProofPoints, VerificationKey, G16};
|
|||
use zokrates_proof_systems::Scheme;
|
||||
|
||||
impl<T: Field + BellmanFieldExtensions> Backend<T, G16> for Bellman {
|
||||
fn generate_proof<'a, I: IntoIterator<Item = Statement<'a, T>>, R: RngCore + CryptoRng>(
|
||||
fn generate_proof<
|
||||
'a,
|
||||
I: IntoIterator<Item = Statement<'a, T>>,
|
||||
R: Read,
|
||||
G: RngCore + CryptoRng,
|
||||
>(
|
||||
program: ProgIterator<'a, T, I>,
|
||||
witness: Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
rng: &mut R,
|
||||
proving_key: R,
|
||||
rng: &mut G,
|
||||
) -> Proof<T, G16> {
|
||||
let computation = Computation::with_witness(program, witness);
|
||||
let params = Parameters::read(proving_key.as_slice(), true).unwrap();
|
||||
let params = Parameters::read(proving_key, true).unwrap();
|
||||
|
||||
let public_inputs: Vec<String> = computation
|
||||
.public_inputs_values()
|
||||
|
@ -108,7 +113,7 @@ impl<T: Field + BellmanFieldExtensions> MpcBackend<T, G16> for Bellman {
|
|||
}
|
||||
|
||||
fn contribute<R: Read, W: Write, G: RngCore + CryptoRng>(
|
||||
params: &mut R,
|
||||
params: R,
|
||||
rng: &mut G,
|
||||
output: &mut W,
|
||||
) -> Result<[u8; 64], String> {
|
||||
|
@ -124,8 +129,8 @@ impl<T: Field + BellmanFieldExtensions> MpcBackend<T, G16> for Bellman {
|
|||
Ok(hash)
|
||||
}
|
||||
|
||||
fn verify<'a, P: Read, R: Read, I: IntoIterator<Item = Statement<'a, T>>>(
|
||||
params: &mut P,
|
||||
fn verify<'a, R: Read, I: IntoIterator<Item = Statement<'a, T>>>(
|
||||
params: R,
|
||||
program: ProgIterator<'a, T, I>,
|
||||
phase1_radix: &mut R,
|
||||
) -> Result<Vec<[u8; 64]>, String> {
|
||||
|
@ -140,7 +145,7 @@ impl<T: Field + BellmanFieldExtensions> MpcBackend<T, G16> for Bellman {
|
|||
Ok(hashes)
|
||||
}
|
||||
|
||||
fn export_keypair<R: Read>(params: &mut R) -> Result<SetupKeypair<T, G16>, String> {
|
||||
fn export_keypair<R: Read>(params: R) -> Result<SetupKeypair<T, G16>, String> {
|
||||
let params =
|
||||
MPCParameters::<T::BellmanEngine>::read(params, true).map_err(|e| e.to_string())?;
|
||||
|
||||
|
@ -227,7 +232,10 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
let proof = <Bellman as Backend<Bn128Field, G16>>::generate_proof(
|
||||
program, witness, keypair.pk, rng,
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
let ans = <Bellman as Backend<Bn128Field, G16>>::verify(keypair.vk, proof);
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use bellman::{
|
|||
};
|
||||
use std::collections::BTreeMap;
|
||||
use zokrates_ast::common::Variable;
|
||||
use zokrates_ast::ir::{CanonicalLinComb, ProgIterator, Statement, Witness};
|
||||
use zokrates_ast::ir::{LinComb, ProgIterator, Statement, Witness};
|
||||
use zokrates_field::BellmanFieldExtensions;
|
||||
use zokrates_field::Field;
|
||||
|
||||
|
@ -45,7 +45,7 @@ impl<'a, T: Field, I: IntoIterator<Item = Statement<'a, T>>> Computation<'a, T,
|
|||
}
|
||||
|
||||
fn bellman_combination<T: BellmanFieldExtensions, CS: ConstraintSystem<T::BellmanEngine>>(
|
||||
l: CanonicalLinComb<T>,
|
||||
l: LinComb<T>,
|
||||
cs: &mut CS,
|
||||
symbols: &mut BTreeMap<Variable, BellmanVariable>,
|
||||
witness: &mut Witness<T>,
|
||||
|
@ -127,19 +127,9 @@ impl<'a, T: BellmanFieldExtensions + Field, I: IntoIterator<Item = Statement<'a,
|
|||
|
||||
for statement in self.program.statements {
|
||||
if let Statement::Constraint(quad, lin, _) = statement {
|
||||
let a = &bellman_combination(
|
||||
quad.left.into_canonical(),
|
||||
cs,
|
||||
&mut symbols,
|
||||
&mut witness,
|
||||
);
|
||||
let b = &bellman_combination(
|
||||
quad.right.into_canonical(),
|
||||
cs,
|
||||
&mut symbols,
|
||||
&mut witness,
|
||||
);
|
||||
let c = &bellman_combination(lin.into_canonical(), cs, &mut symbols, &mut witness);
|
||||
let a = &bellman_combination(quad.left, cs, &mut symbols, &mut witness);
|
||||
let b = &bellman_combination(quad.right, cs, &mut symbols, &mut witness);
|
||||
let c = &bellman_combination(lin, cs, &mut symbols, &mut witness);
|
||||
|
||||
cs.enforce(|| "Constraint", |lc| lc + a, |lc| lc + b, |lc| lc + c);
|
||||
}
|
||||
|
|
|
@ -43,20 +43,14 @@ As a next step we can create a witness file using the following command:
|
|||
|
||||
Using the flag `-a` we pass arguments to the program. Recall that our goal is to compute the hash for the number `5`. Consequently we set `a`, `b` and `c` to `0` and `d` to `5`.
|
||||
|
||||
Still here? Great! At this point, we can check the `witness` file for the return values:
|
||||
Still here? Great! At this point we can check the return values. We should see the following output:
|
||||
|
||||
```
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:13}}
|
||||
Witness:
|
||||
["263561599766550617289250058199814760685","65303172752238645975888084098459749904"]
|
||||
```
|
||||
|
||||
which should lead to the following output:
|
||||
|
||||
```sh
|
||||
~out_0 263561599766550617289250058199814760685
|
||||
~out_1 65303172752238645975888084098459749904
|
||||
```
|
||||
|
||||
Hence, by concatenating the outputs as 128 bit numbers, we arrive at the following value as the hash for our selected pre-image :
|
||||
By concatenating the outputs as 128 bit numbers, we arrive at the following value as the hash for our selected pre-image :
|
||||
`0xc6481e22c5ff4164af680b8cfaa5e8ed3120eeff89c4f307c4a6faaae059ce10`
|
||||
|
||||
## Prove knowledge of pre-image
|
||||
|
@ -78,13 +72,13 @@ Note that we now compare the result of `sha256packed` with the hard-coded correc
|
|||
So, having defined the program, Victor is now ready to compile the code:
|
||||
|
||||
```
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:17}}
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:15}}
|
||||
```
|
||||
|
||||
Based on that Victor can run the setup phase and export a verifier smart contract as a Solidity file:
|
||||
|
||||
```
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:18:19}}
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:16:17}}
|
||||
```
|
||||
|
||||
`setup` creates a `verification.key` file and a `proving.key` file. Victor gives the proving key to Peggy.
|
||||
|
@ -94,13 +88,13 @@ Based on that Victor can run the setup phase and export a verifier smart contrac
|
|||
Peggy provides the correct pre-image as an argument to the program.
|
||||
|
||||
```
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:20}}
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:18}}
|
||||
```
|
||||
|
||||
Finally, Peggy can run the command to construct the proof:
|
||||
|
||||
```
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:21}}
|
||||
{{#include ../../../zokrates_cli/examples/book/sha256_tutorial/test.sh:19}}
|
||||
```
|
||||
|
||||
As the inputs were declared as private in the program, they do not appear in the proof thanks to the zero-knowledge property of the protocol.
|
||||
|
|
|
@ -8,9 +8,7 @@ function zokrates() {
|
|||
}
|
||||
|
||||
zokrates compile -i hashexample.zok
|
||||
zokrates compute-witness -a 0 0 0 5
|
||||
|
||||
grep '~out' witness
|
||||
zokrates compute-witness -a 0 0 0 5 --verbose
|
||||
|
||||
cp -f hashexample_updated.zok hashexample.zok
|
||||
|
||||
|
|
|
@ -66,6 +66,10 @@ pub fn subcommand() -> App<'static, 'static> {
|
|||
.help("Read arguments from stdin")
|
||||
.conflicts_with("arguments")
|
||||
.required(false)
|
||||
).arg(Arg::with_name("json")
|
||||
.long("json")
|
||||
.help("Write witness in a json format for debugging purposes")
|
||||
.required(false)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -195,6 +199,19 @@ fn cli_compute<'a, T: Field, I: Iterator<Item = ir::Statement<'a, T>>>(
|
|||
.write(writer)
|
||||
.map_err(|why| format!("Could not save witness: {:?}", why))?;
|
||||
|
||||
// write witness in the json format
|
||||
if sub_matches.is_present("json") {
|
||||
let json_path = Path::new(sub_matches.value_of("output").unwrap()).with_extension("json");
|
||||
let json_file = File::create(&json_path)
|
||||
.map_err(|why| format!("Could not create {}: {}", json_path.display(), why))?;
|
||||
|
||||
let writer = BufWriter::new(json_file);
|
||||
|
||||
witness
|
||||
.write_json(writer)
|
||||
.map_err(|why| format!("Could not save {}: {:?}", json_path.display(), why))?;
|
||||
}
|
||||
|
||||
// write circom witness to file
|
||||
let wtns_path = Path::new(sub_matches.value_of("circom-witness").unwrap());
|
||||
let wtns_file = File::create(&wtns_path)
|
||||
|
|
|
@ -4,7 +4,7 @@ use rand_0_8::rngs::StdRng;
|
|||
use rand_0_8::SeedableRng;
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read, Write};
|
||||
use std::io::{BufReader, Write};
|
||||
use std::path::Path;
|
||||
#[cfg(feature = "ark")]
|
||||
use zokrates_ark::Ark;
|
||||
|
@ -163,7 +163,9 @@ fn cli_generate_proof<
|
|||
let witness_file = File::open(&witness_path)
|
||||
.map_err(|why| format!("Could not open {}: {}", witness_path.display(), why))?;
|
||||
|
||||
let witness = ir::Witness::read(witness_file)
|
||||
let witness_reader = BufReader::new(witness_file);
|
||||
|
||||
let witness = ir::Witness::read(witness_reader)
|
||||
.map_err(|why| format!("Could not load witness: {:?}", why))?;
|
||||
|
||||
let pk_path = Path::new(sub_matches.value_of("proving-key-path").unwrap());
|
||||
|
@ -172,18 +174,14 @@ fn cli_generate_proof<
|
|||
let pk_file = File::open(&pk_path)
|
||||
.map_err(|why| format!("Could not open {}: {}", pk_path.display(), why))?;
|
||||
|
||||
let mut pk: Vec<u8> = Vec::new();
|
||||
let mut pk_reader = BufReader::new(pk_file);
|
||||
pk_reader
|
||||
.read_to_end(&mut pk)
|
||||
.map_err(|why| format!("Could not read {}: {}", pk_path.display(), why))?;
|
||||
let pk_reader = BufReader::new(pk_file);
|
||||
|
||||
let mut rng = sub_matches
|
||||
.value_of("entropy")
|
||||
.map(get_rng_from_entropy)
|
||||
.unwrap_or_else(StdRng::from_entropy);
|
||||
|
||||
let proof = B::generate_proof(program, witness, pk, &mut rng);
|
||||
let proof = B::generate_proof(program, witness, pk_reader, &mut rng);
|
||||
let mut proof_file = File::create(proof_path).unwrap();
|
||||
|
||||
let proof =
|
||||
|
|
|
@ -73,7 +73,7 @@ fn cli_mpc_verify<
|
|||
let file =
|
||||
File::open(&path).map_err(|why| format!("Could not open `{}`: {}", path.display(), why))?;
|
||||
|
||||
let mut reader = BufReader::new(file);
|
||||
let reader = BufReader::new(file);
|
||||
|
||||
let radix_path = Path::new(sub_matches.value_of("radix-path").unwrap());
|
||||
let radix_file = File::open(radix_path)
|
||||
|
@ -81,7 +81,7 @@ fn cli_mpc_verify<
|
|||
|
||||
let mut radix_reader = BufReader::new(radix_file);
|
||||
|
||||
let result = B::verify(&mut reader, program, &mut radix_reader)
|
||||
let result = B::verify(reader, program, &mut radix_reader)
|
||||
.map_err(|e| format!("Verification failed: {}", e))?;
|
||||
|
||||
let contribution_count = result.len();
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
~out_0 12
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "12"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
~out_0 0
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "0"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
~out_0 1
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "1"
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
~out_0 0
|
||||
~out_1 0
|
||||
~out_2 0
|
||||
~out_3 42
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"~out_0": "0",
|
||||
"~out_1": "0",
|
||||
"~out_2": "0",
|
||||
"~out_3": "42"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
~out_0 5
|
3
zokrates_cli/tests/code/n_choose_k.expected.witness.json
Normal file
3
zokrates_cli/tests/code/n_choose_k.expected.witness.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "5"
|
||||
}
|
1
zokrates_cli/tests/code/no_return.expected.witness.json
Normal file
1
zokrates_cli/tests/code/no_return.expected.witness.json
Normal file
|
@ -0,0 +1 @@
|
|||
{}
|
|
@ -1,8 +0,0 @@
|
|||
~out_0 2
|
||||
~out_1 1
|
||||
~out_2 1
|
||||
~out_3 1
|
||||
~out_4 3
|
||||
~out_5 3
|
||||
~out_6 3
|
||||
~out_7 3
|
10
zokrates_cli/tests/code/return_array.expected.witness.json
Normal file
10
zokrates_cli/tests/code/return_array.expected.witness.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"~out_0": "2",
|
||||
"~out_1": "1",
|
||||
"~out_2": "1",
|
||||
"~out_3": "1",
|
||||
"~out_4": "3",
|
||||
"~out_5": "3",
|
||||
"~out_6": "3",
|
||||
"~out_7": "3"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
~out_0 3
|
3
zokrates_cli/tests/code/simple_add.expected.witness.json
Normal file
3
zokrates_cli/tests/code/simple_add.expected.witness.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "3"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
~out_0 24
|
3
zokrates_cli/tests/code/simple_mul.expected.witness.json
Normal file
3
zokrates_cli/tests/code/simple_mul.expected.witness.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "24"
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
~out_0 0
|
3
zokrates_cli/tests/code/taxation.expected.witness.json
Normal file
3
zokrates_cli/tests/code/taxation.expected.witness.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"~out_0": "0"
|
||||
}
|
|
@ -16,17 +16,78 @@ mod integration {
|
|||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, Read, Write};
|
||||
use std::panic;
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
use tempdir::TempDir;
|
||||
use zokrates_abi::{parse_strict, Encode};
|
||||
use zokrates_ast::ir::Witness;
|
||||
use zokrates_ast::typed::abi::Abi;
|
||||
use zokrates_field::Bn128Field;
|
||||
use zokrates_proof_systems::{
|
||||
to_token::ToToken, Marlin, Proof, SolidityCompatibleScheme, G16, GM17,
|
||||
};
|
||||
|
||||
mod helpers {
|
||||
use super::*;
|
||||
use zokrates_ast::common::Variable;
|
||||
use zokrates_field::Field;
|
||||
|
||||
pub fn parse_variable(s: &str) -> Result<Variable, &str> {
|
||||
if s == "~one" {
|
||||
return Ok(Variable::one());
|
||||
}
|
||||
|
||||
let mut public = s.split("~out_");
|
||||
match public.nth(1) {
|
||||
Some(v) => {
|
||||
let v = v.parse().map_err(|_| s)?;
|
||||
Ok(Variable::public(v))
|
||||
}
|
||||
None => {
|
||||
let mut private = s.split('_');
|
||||
match private.nth(1) {
|
||||
Some(v) => {
|
||||
let v = v.parse().map_err(|_| s)?;
|
||||
Ok(Variable::new(v))
|
||||
}
|
||||
None => Err(s),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_witness_json<T: Field, R: Read>(reader: R) -> std::io::Result<Witness<T>> {
|
||||
use std::io::{Error, ErrorKind};
|
||||
|
||||
let json: serde_json::Value = serde_json::from_reader(reader)?;
|
||||
let object = json
|
||||
.as_object()
|
||||
.ok_or_else(|| Error::new(ErrorKind::Other, "Witness must be an object"))?;
|
||||
|
||||
let mut witness = Witness::empty();
|
||||
for (k, v) in object {
|
||||
let variable = parse_variable(k).map_err(|why| {
|
||||
Error::new(
|
||||
ErrorKind::Other,
|
||||
format!("Invalid variable in witness: {}", why),
|
||||
)
|
||||
})?;
|
||||
|
||||
let value = v
|
||||
.as_str()
|
||||
.ok_or_else(|| Error::new(ErrorKind::Other, "Witness value must be a string"))
|
||||
.and_then(|v| {
|
||||
T::try_from_dec_str(v).map_err(|_| {
|
||||
Error::new(ErrorKind::Other, format!("Invalid value in witness: {}", v))
|
||||
})
|
||||
})?;
|
||||
|
||||
witness.insert(variable, value);
|
||||
}
|
||||
Ok(witness)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! map(
|
||||
{
|
||||
$($key:expr => $value:expr),+ } => {
|
||||
|
@ -101,7 +162,9 @@ mod integration {
|
|||
let program_name =
|
||||
Path::new(Path::new(path.file_stem().unwrap()).file_stem().unwrap());
|
||||
let prog = dir.join(program_name).with_extension("zok");
|
||||
let witness = dir.join(program_name).with_extension("expected.witness");
|
||||
let witness = dir
|
||||
.join(program_name)
|
||||
.with_extension("expected.witness.json");
|
||||
let json_input = dir.join(program_name).with_extension("arguments.json");
|
||||
|
||||
test_compile_and_witness(
|
||||
|
@ -250,33 +313,24 @@ mod integration {
|
|||
.unwrap();
|
||||
|
||||
// load the expected witness
|
||||
let mut expected_witness_file = File::open(&expected_witness_path).unwrap();
|
||||
let mut expected_witness = String::new();
|
||||
expected_witness_file
|
||||
.read_to_string(&mut expected_witness)
|
||||
.unwrap();
|
||||
let expected_witness_file = File::open(&expected_witness_path).unwrap();
|
||||
let expected_witness: Witness<zokrates_field::Bn128Field> =
|
||||
helpers::parse_witness_json(expected_witness_file).unwrap();
|
||||
|
||||
// load the actual witness
|
||||
let mut witness_file = File::open(&witness_path).unwrap();
|
||||
let mut witness = String::new();
|
||||
witness_file.read_to_string(&mut witness).unwrap();
|
||||
let witness_file = File::open(&witness_path).unwrap();
|
||||
let witness = Witness::<zokrates_field::Bn128Field>::read(witness_file).unwrap();
|
||||
|
||||
// load the actual inline witness
|
||||
let mut inline_witness_file = File::open(&inline_witness_path).unwrap();
|
||||
let mut inline_witness = String::new();
|
||||
inline_witness_file
|
||||
.read_to_string(&mut inline_witness)
|
||||
.unwrap();
|
||||
let inline_witness_file = File::open(&inline_witness_path).unwrap();
|
||||
let inline_witness =
|
||||
Witness::<zokrates_field::Bn128Field>::read(inline_witness_file).unwrap();
|
||||
|
||||
assert_eq!(inline_witness, witness);
|
||||
|
||||
for line in expected_witness.as_str().split('\n') {
|
||||
assert!(
|
||||
witness.contains(line),
|
||||
"Witness generation failed for {}\n\nLine \"{}\" not found in witness",
|
||||
program_path.to_str().unwrap(),
|
||||
line
|
||||
);
|
||||
for (k, v) in expected_witness.0 {
|
||||
let value = witness.0.get(&k).expect("should contain key");
|
||||
assert!(v.eq(value));
|
||||
}
|
||||
|
||||
let backends = map! {
|
||||
|
|
|
@ -29,7 +29,7 @@ ark-bn254 = { version = "^0.3.0", features = ["curve"], default-features = false
|
|||
ark-bls12-377 = { version = "^0.3.0", features = ["curve"], default-features = false }
|
||||
ark-bls12-381 = { version = "^0.3.0", features = ["curve"] }
|
||||
ark-bw6-761 = { version = "^0.3.0", default-features = false }
|
||||
ark-serialize = { version = "^0.3.0", default-features = false }
|
||||
ark-serialize = { version = "^0.3.0", default-features = false, features = ["std"] }
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.4"
|
||||
|
|
|
@ -252,4 +252,12 @@ impl Field for FieldPrime {
|
|||
fn to_biguint(&self) -> num_bigint::BigUint {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn read<R: std::io::Read>(_: R) -> std::io::Result<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn write<W: std::io::Write>(&self, _: W) -> std::io::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ extern crate num_bigint;
|
|||
|
||||
#[cfg(feature = "bellman")]
|
||||
use bellman_ce::pairing::{ff::ScalarEngine, Engine};
|
||||
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::{CheckedDiv, One, Zero};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -16,6 +15,7 @@ use std::convert::{From, TryFrom};
|
|||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::hash::Hash;
|
||||
use std::io::{Read, Write};
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
pub trait Pow<RHS> {
|
||||
|
@ -96,6 +96,10 @@ pub trait Field:
|
|||
+ num_traits::CheckedMul
|
||||
{
|
||||
const G2_TYPE: G2Type = G2Type::Fq2;
|
||||
// Read field from the reader
|
||||
fn read<R: Read>(reader: R) -> std::io::Result<Self>;
|
||||
// Write field to the writer
|
||||
fn write<W: Write>(&self, writer: W) -> std::io::Result<()>;
|
||||
/// Returns this `Field`'s contents as little-endian byte vector
|
||||
fn to_byte_vector(&self) -> Vec<u8>;
|
||||
/// Returns an element of this `Field` from a little-endian byte vector
|
||||
|
@ -145,6 +149,7 @@ mod prime_field {
|
|||
use std::convert::TryFrom;
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display};
|
||||
use std::io::{Read, Write};
|
||||
use std::ops::{Add, Div, Mul, Sub};
|
||||
|
||||
type Fr = <$v as ark_ec::PairingEngine>::Fr;
|
||||
|
@ -187,9 +192,21 @@ mod prime_field {
|
|||
self.v.into_repr().to_bytes_le()
|
||||
}
|
||||
|
||||
fn read<R: Read>(reader: R) -> std::io::Result<Self> {
|
||||
use ark_ff::FromBytes;
|
||||
Ok(FieldPrime {
|
||||
v: Fr::read(reader)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn write<W: Write>(&self, mut writer: W) -> std::io::Result<()> {
|
||||
use ark_ff::ToBytes;
|
||||
self.v.write(&mut writer)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn from_byte_vector(bytes: Vec<u8>) -> Self {
|
||||
use ark_ff::FromBytes;
|
||||
|
||||
FieldPrime {
|
||||
v: Fr::from(<Fr as PrimeField>::BigInt::read(&bytes[..]).unwrap()),
|
||||
}
|
||||
|
@ -592,9 +609,12 @@ mod prime_field {
|
|||
}
|
||||
|
||||
fn into_bellman(self) -> <Self::BellmanEngine as ScalarEngine>::Fr {
|
||||
use bellman_ce::pairing::ff::PrimeField;
|
||||
let s = self.to_dec_string();
|
||||
<Self::BellmanEngine as ScalarEngine>::Fr::from_str(&s).unwrap()
|
||||
use bellman_ce::pairing::ff::{PrimeField, PrimeFieldRepr};
|
||||
let bytes = self.to_byte_vector();
|
||||
let mut repr =
|
||||
<<Self::BellmanEngine as ScalarEngine>::Fr as PrimeField>::Repr::default();
|
||||
repr.read_le(bytes.as_slice()).unwrap();
|
||||
<Self::BellmanEngine as ScalarEngine>::Fr::from_repr(repr).unwrap()
|
||||
}
|
||||
|
||||
fn new_fq2(
|
||||
|
|
4
zokrates_js/index.d.ts
vendored
4
zokrates_js/index.d.ts
vendored
|
@ -42,7 +42,7 @@ declare module "zokrates-js" {
|
|||
}
|
||||
|
||||
export interface ComputationResult {
|
||||
witness: string;
|
||||
witness: Uint8Array;
|
||||
output: string;
|
||||
snarkjs?: {
|
||||
witness: Uint8Array;
|
||||
|
@ -90,7 +90,7 @@ declare module "zokrates-js" {
|
|||
setupWithSrs(srs: Uint8Array, program: Uint8Array): SetupKeypair;
|
||||
generateProof(
|
||||
program: Uint8Array,
|
||||
witness: string,
|
||||
witness: Uint8Array,
|
||||
provingKey: Uint8Array,
|
||||
entropy?: string
|
||||
): Proof;
|
||||
|
|
|
@ -79,15 +79,17 @@ pub struct ResolverResult {
|
|||
|
||||
#[wasm_bindgen]
|
||||
pub struct ComputationResult {
|
||||
witness: String,
|
||||
witness: Vec<u8>,
|
||||
output: String,
|
||||
snarkjs_witness: Option<Vec<u8>>,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl ComputationResult {
|
||||
pub fn witness(&self) -> JsValue {
|
||||
JsValue::from_str(&self.witness)
|
||||
pub fn witness(&self) -> js_sys::Uint8Array {
|
||||
let arr = js_sys::Uint8Array::new_with_length(self.witness.len() as u32);
|
||||
arr.copy_from(&self.witness);
|
||||
arr
|
||||
}
|
||||
|
||||
pub fn output(&self) -> JsValue {
|
||||
|
@ -360,8 +362,14 @@ mod internal {
|
|||
buffer.into_inner()
|
||||
});
|
||||
|
||||
let witness = {
|
||||
let mut buffer = Cursor::new(vec![]);
|
||||
witness.write(&mut buffer).unwrap();
|
||||
buffer.into_inner()
|
||||
};
|
||||
|
||||
Ok(ComputationResult {
|
||||
witness: format!("{}", witness),
|
||||
witness,
|
||||
output: to_string_pretty(&return_values).unwrap(),
|
||||
snarkjs_witness,
|
||||
})
|
||||
|
@ -416,15 +424,14 @@ mod internal {
|
|||
|
||||
pub fn generate_proof<T: Field, S: Scheme<T>, B: Backend<T, S>, R: RngCore + CryptoRng>(
|
||||
prog: ir::Prog<T>,
|
||||
witness: JsValue,
|
||||
witness: &[u8],
|
||||
pk: &[u8],
|
||||
rng: &mut R,
|
||||
) -> Result<JsValue, JsValue> {
|
||||
let str_witness = witness.as_string().unwrap();
|
||||
let ir_witness: ir::Witness<T> = ir::Witness::read(str_witness.as_bytes())
|
||||
let ir_witness: ir::Witness<T> = ir::Witness::read(witness)
|
||||
.map_err(|err| JsValue::from_str(&format!("Could not read witness: {}", err)))?;
|
||||
|
||||
let proof = B::generate_proof(prog, ir_witness, pk.to_vec(), rng);
|
||||
let proof = B::generate_proof(prog, ir_witness, pk, rng);
|
||||
Ok(JsValue::from_serde(&TaggedProof::<T, S>::new(proof.proof, proof.inputs)).unwrap())
|
||||
}
|
||||
|
||||
|
@ -696,7 +703,7 @@ pub fn universal_setup(curve: JsValue, size: u32, entropy: JsValue) -> Result<Ve
|
|||
#[wasm_bindgen]
|
||||
pub fn generate_proof(
|
||||
program: &[u8],
|
||||
witness: JsValue,
|
||||
witness: &[u8],
|
||||
pk: &[u8],
|
||||
entropy: JsValue,
|
||||
options: JsValue,
|
||||
|
|
|
@ -96,11 +96,16 @@ impl ToString for G2AffineFq2 {
|
|||
}
|
||||
|
||||
pub trait Backend<T: Field, S: Scheme<T>> {
|
||||
fn generate_proof<'a, I: IntoIterator<Item = ir::Statement<'a, T>>, R: RngCore + CryptoRng>(
|
||||
fn generate_proof<
|
||||
'a,
|
||||
I: IntoIterator<Item = ir::Statement<'a, T>>,
|
||||
R: Read,
|
||||
G: RngCore + CryptoRng,
|
||||
>(
|
||||
program: ir::ProgIterator<'a, T, I>,
|
||||
witness: ir::Witness<T>,
|
||||
proving_key: Vec<u8>,
|
||||
rng: &mut R,
|
||||
proving_key: R,
|
||||
rng: &mut G,
|
||||
) -> Proof<T, S>;
|
||||
|
||||
fn verify(vk: S::VerificationKey, proof: Proof<T, S>) -> bool;
|
||||
|
@ -129,16 +134,16 @@ pub trait MpcBackend<T: Field, S: Scheme<T>> {
|
|||
) -> Result<(), String>;
|
||||
|
||||
fn contribute<R: Read, W: Write, G: RngCore + CryptoRng>(
|
||||
params: &mut R,
|
||||
params: R,
|
||||
rng: &mut G,
|
||||
output: &mut W,
|
||||
) -> Result<[u8; 64], String>;
|
||||
|
||||
fn verify<'a, P: Read, R: Read, I: IntoIterator<Item = ir::Statement<'a, T>>>(
|
||||
params: &mut P,
|
||||
fn verify<'a, R: Read, I: IntoIterator<Item = ir::Statement<'a, T>>>(
|
||||
params: R,
|
||||
program: ir::ProgIterator<'a, T, I>,
|
||||
phase1_radix: &mut R,
|
||||
) -> Result<Vec<[u8; 64]>, String>;
|
||||
|
||||
fn export_keypair<R: Read>(params: &mut R) -> Result<SetupKeypair<T, S>, String>;
|
||||
fn export_keypair<R: Read>(params: R) -> Result<SetupKeypair<T, S>, String>;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@ fn generate_proof() {
|
|||
|
||||
let rng = &mut StdRng::from_entropy();
|
||||
let keypair = <Ark as NonUniversalBackend<Bn128Field, G16>>::setup(program.clone(), rng);
|
||||
let _proof =
|
||||
<Ark as Backend<Bn128Field, G16>>::generate_proof(program, witness, keypair.pk, rng);
|
||||
let _proof = <Ark as Backend<Bn128Field, G16>>::generate_proof(
|
||||
program,
|
||||
witness,
|
||||
keypair.pk.as_slice(),
|
||||
rng,
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue