wip
This commit is contained in:
parent
af7097bd14
commit
59f62d2ffa
9 changed files with 386 additions and 242 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2409,6 +2409,7 @@ dependencies = [
|
|||
"ark-std",
|
||||
"bellman_ce",
|
||||
"sapling-crypto_ce",
|
||||
"zokrates_field",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -7,17 +7,16 @@ use crate::typed_absy::types::{
|
|||
ConcreteGenericsAssignment, Constant, DeclarationSignature, DeclarationType, GenericIdentifier,
|
||||
};
|
||||
use ark_bls12_377::Bls12_377;
|
||||
use ark_bw6_761::BW6_761;
|
||||
use std::collections::HashMap;
|
||||
use zokrates_embed::ark::generate_verify_constraints;
|
||||
use zokrates_embed::ark::{from_ark, generate_verify_constraints};
|
||||
use zokrates_embed::bellman::from_bellman;
|
||||
use zokrates_embed::Constraint;
|
||||
use zokrates_field::{Bn128Field, Field};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "bellman")] {
|
||||
use pairing_ce::bn256::Bn256;
|
||||
use pairing_ce::ff::{PrimeField, PrimeFieldRepr};
|
||||
use pairing_ce::Engine;
|
||||
use zokrates_embed::{bellman::generate_sha256_round_constraints, Constraint};
|
||||
use zokrates_embed::{bellman::generate_sha256_round_constraints};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,19 +132,19 @@ impl FlatEmbed {
|
|||
.inputs(vec![
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
Some(Constant::Generic(GenericIdentifier {
|
||||
name: "V",
|
||||
index: 1,
|
||||
})),
|
||||
)), // 18 + (2 * n)
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
Some(Constant::Generic(GenericIdentifier {
|
||||
GenericIdentifier {
|
||||
name: "N",
|
||||
index: 0,
|
||||
})),
|
||||
},
|
||||
)), // inputs
|
||||
DeclarationType::array((DeclarationType::FieldElement, 8)), // proof
|
||||
DeclarationType::array((DeclarationType::FieldElement, 8usize)), // proof
|
||||
DeclarationType::array((
|
||||
DeclarationType::FieldElement,
|
||||
GenericIdentifier {
|
||||
name: "V",
|
||||
index: 1,
|
||||
},
|
||||
)), // 18 + (2 * n) // vk
|
||||
])
|
||||
.outputs(vec![DeclarationType::Boolean]),
|
||||
}
|
||||
|
@ -191,7 +190,7 @@ impl FlatEmbed {
|
|||
#[cfg(feature = "bellman")]
|
||||
FlatEmbed::Sha256Round => sha256_round(),
|
||||
#[cfg(feature = "ark")]
|
||||
FlatEmbed::Verify => verify(),
|
||||
FlatEmbed::Verify => verify(generics[0] as usize),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -199,37 +198,33 @@ impl FlatEmbed {
|
|||
|
||||
// util to convert a vector of `(variable_id, coefficient)` to a flat_expression
|
||||
// we build a binary tree of additions by splitting the vector recursively
|
||||
#[cfg(feature = "bellman")]
|
||||
fn flat_expression_from_vec<T: Field, E: Engine>(v: &[(usize, E::Fr)]) -> FlatExpression<T> {
|
||||
fn flat_expression_from_vec<T: Field>(v: &[(usize, T)]) -> FlatExpression<T> {
|
||||
match v.len() {
|
||||
0 => FlatExpression::Number(T::zero()),
|
||||
1 => {
|
||||
let (key, val) = v[0];
|
||||
let mut res: Vec<u8> = vec![];
|
||||
val.into_repr().write_le(&mut res).unwrap();
|
||||
let (key, val) = v[0].clone();
|
||||
FlatExpression::Mult(
|
||||
box FlatExpression::Number(T::from_byte_vector(res)),
|
||||
box FlatExpression::Number(val),
|
||||
box FlatExpression::Identifier(FlatVariable::new(key)),
|
||||
)
|
||||
}
|
||||
n => {
|
||||
let (u, v) = v.split_at(n / 2);
|
||||
FlatExpression::Add(
|
||||
box flat_expression_from_vec::<T, E>(u),
|
||||
box flat_expression_from_vec::<T, E>(v),
|
||||
box flat_expression_from_vec::<T>(u),
|
||||
box flat_expression_from_vec::<T>(v),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "bellman")]
|
||||
fn flat_statement_from_constraint<T: Field, E: Engine>(c: Constraint<E::Fr>) -> FlatStatement<T> {
|
||||
let rhs_a = flat_expression_from_vec::<T, E>(&c.a);
|
||||
let rhs_b = flat_expression_from_vec::<T, E>(&c.b);
|
||||
let lhs = flat_expression_from_vec::<T, E>(&c.c);
|
||||
|
||||
FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
|
||||
}
|
||||
// fn flat_statement_from_constraint<T: Field, F>(c: Constraint<F>) -> FlatStatement<T> {
|
||||
// let rhs_a = flat_expression_from_vec::<T, F>(&c.a);
|
||||
// let rhs_b = flat_expression_from_vec::<T, F>(&c.b);
|
||||
// let lhs = flat_expression_from_vec::<T, F>(&c.c);
|
||||
//
|
||||
// FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
|
||||
// }
|
||||
|
||||
/// Returns a flat function which computes a sha256 round
|
||||
///
|
||||
|
@ -288,10 +283,15 @@ pub fn sha256_round<T: Field>() -> FlatFunction<T> {
|
|||
)
|
||||
});
|
||||
// insert flattened statements to represent constraints
|
||||
let constraint_statements = r1cs
|
||||
.constraints
|
||||
.into_iter()
|
||||
.map(|c| flat_statement_from_constraint::<T, Bn256>(c));
|
||||
let constraint_statements = r1cs.constraints.into_iter().map(|c| {
|
||||
let c = from_bellman::<T, Bn256>(c);
|
||||
let rhs_a = flat_expression_from_vec::<T>(c.a.as_slice());
|
||||
let rhs_b = flat_expression_from_vec::<T>(c.b.as_slice());
|
||||
let lhs = flat_expression_from_vec::<T>(c.c.as_slice());
|
||||
|
||||
FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
|
||||
});
|
||||
|
||||
// define which subset of the witness is returned
|
||||
let outputs: Vec<FlatExpression<T>> = output_indices
|
||||
.map(|o| FlatExpression::Identifier(FlatVariable::new(o)))
|
||||
|
@ -323,114 +323,99 @@ pub fn sha256_round<T: Field>() -> FlatFunction<T> {
|
|||
|
||||
#[cfg(feature = "ark")]
|
||||
pub fn verify<T: Field>(n: usize) -> FlatFunction<T> {
|
||||
unreachable!();
|
||||
//
|
||||
// let (output_index, constraints) = generate_verify_constraints(n);
|
||||
//
|
||||
// let statements = constraints
|
||||
// .into_iter()
|
||||
// .map(|c| flat_statement_from_constraint::<T, BW6_761>(c))
|
||||
// .collect();
|
||||
//
|
||||
// //indices of the arguments to the function
|
||||
// // apply an offset of `variable_count` to get the index of our dummy `input` argument
|
||||
// let input_argument_indices = input_indices
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .map(|i| i + variable_count);
|
||||
//
|
||||
// let proof_argument_indices = proof_indices
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .map(|i| i + variable_count);
|
||||
//
|
||||
// let vk_argument_indices = vk_indices.clone().into_iter().map(|i| i + variable_count);
|
||||
//
|
||||
// // define parameters to the function based on the variables
|
||||
// let proof_arguments = proof_argument_indices.clone().map(|i| FlatParameter {
|
||||
// id: FlatVariable::new(i),
|
||||
// private: true,
|
||||
// });
|
||||
//
|
||||
// let input_arguments = input_argument_indices.clone().map(|i| FlatParameter {
|
||||
// id: FlatVariable::new(i),
|
||||
// private: false,
|
||||
// });
|
||||
//
|
||||
// let vk_arguments = vk_argument_indices.clone().map(|i| FlatParameter {
|
||||
// id: FlatVariable::new(i),
|
||||
// private: true,
|
||||
// });
|
||||
//
|
||||
// let arguments = proof_arguments
|
||||
// .clone()
|
||||
// .chain(input_arguments)
|
||||
// .chain(vk_arguments)
|
||||
// .collect();
|
||||
//
|
||||
// let one_binding_statement = FlatStatement::Condition(
|
||||
// FlatExpression::Identifier(FlatVariable::new(0)),
|
||||
// FlatExpression::Number(T::from(1)),
|
||||
// );
|
||||
//
|
||||
// let input_binding_statements: Vec<_> = proof_indices
|
||||
// .clone()
|
||||
// .chain(input_indices.clone())
|
||||
// .chain(vk_indices.clone())
|
||||
// .zip(
|
||||
// proof_argument_indices
|
||||
// .clone()
|
||||
// .chain(input_argument_indices.clone())
|
||||
// .chain(vk_argument_indices.clone()),
|
||||
// )
|
||||
// .map(|(cs_index, argument_index)| {
|
||||
// FlatStatement::Condition(
|
||||
// FlatVariable::new(cs_index).into(),
|
||||
// FlatVariable::new(argument_index).into(),
|
||||
// )
|
||||
// })
|
||||
// .collect();
|
||||
//
|
||||
// let directive_outputs: Vec<FlatVariable> = output_indices
|
||||
// .clone()
|
||||
// .map(|o| FlatVariable::new(o))
|
||||
// .collect();
|
||||
//
|
||||
// let outputs: Vec<FlatExpression<T>> = directive_outputs
|
||||
// .iter()
|
||||
// .enumerate()
|
||||
// .map(|(_, o)| FlatExpression::Identifier(o.clone()))
|
||||
// .collect();
|
||||
//
|
||||
// // insert flattened statements to represent constraints
|
||||
// let constraint_statements: Vec<FlatStatement<T>> =
|
||||
// r1cs.constraints.into_iter().map(|c| to_fs(c)).collect();
|
||||
// let return_statement = FlatStatement::Return(FlatExpressionList {
|
||||
// expressions: outputs.clone(),
|
||||
// });
|
||||
//
|
||||
// // insert a directive to set the witness based on the zexe gadget and inputs
|
||||
// let directive_statement = FlatStatement::Directive(FlatDirective {
|
||||
// outputs: cs_indices.map(|i| FlatVariable::new(i)).collect(),
|
||||
// inputs: proof_argument_indices
|
||||
// .chain(input_argument_indices.clone())
|
||||
// .chain(vk_argument_indices.clone())
|
||||
// .map(|i| FlatVariable::new(i).into())
|
||||
// .collect(),
|
||||
// solver: Solver::Verify(n),
|
||||
// });
|
||||
//
|
||||
// let statements: Vec<_> = std::iter::once(directive_statement)
|
||||
// .chain(std::iter::once(one_binding_statement))
|
||||
// .chain(input_binding_statements)
|
||||
// .chain(constraint_statements)
|
||||
// .chain(std::iter::once(return_statement))
|
||||
// .collect();
|
||||
//
|
||||
// FlatFunction {
|
||||
// arguments,
|
||||
// statements,
|
||||
// }
|
||||
let (out_index, input_indices, proof_indices, vk_indices, constraints, aux_count) =
|
||||
generate_verify_constraints(n);
|
||||
|
||||
let variable_count = aux_count + 1; // aux + ~one
|
||||
let cs_indices = 0..variable_count;
|
||||
let input_indices = input_indices.into_iter();
|
||||
let proof_indices = proof_indices.into_iter();
|
||||
let vk_indices = vk_indices.into_iter();
|
||||
|
||||
// indices of the arguments to the function
|
||||
let input_argument_indices = input_indices.clone().map(|i| i + variable_count);
|
||||
|
||||
let proof_argument_indices = proof_indices.clone().map(|i| i + variable_count);
|
||||
|
||||
let vk_argument_indices = vk_indices.clone().map(|i| i + variable_count);
|
||||
|
||||
let input_arguments = input_argument_indices
|
||||
.clone()
|
||||
.map(|i| FlatParameter::private(FlatVariable::new(i)));
|
||||
|
||||
let proof_arguments = proof_argument_indices
|
||||
.clone()
|
||||
.map(|i| FlatParameter::private(FlatVariable::new(i)));
|
||||
|
||||
let vk_arguments = vk_argument_indices
|
||||
.clone()
|
||||
.map(|i| FlatParameter::private(FlatVariable::new(i)));
|
||||
|
||||
let arguments = input_arguments
|
||||
.chain(proof_arguments)
|
||||
.chain(vk_arguments)
|
||||
.collect();
|
||||
|
||||
let one_binding_statement = FlatStatement::Condition(
|
||||
FlatExpression::Identifier(FlatVariable::new(0)),
|
||||
FlatExpression::Number(T::from(1)),
|
||||
);
|
||||
|
||||
let input_binding_statements: Vec<_> = input_indices
|
||||
.chain(proof_indices)
|
||||
.chain(vk_indices)
|
||||
.zip(
|
||||
input_argument_indices
|
||||
.clone()
|
||||
.chain(proof_argument_indices.clone())
|
||||
.chain(vk_argument_indices.clone()),
|
||||
)
|
||||
.map(|(cs_index, argument_index)| {
|
||||
FlatStatement::Condition(
|
||||
FlatVariable::new(cs_index).into(),
|
||||
FlatVariable::new(argument_index).into(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let constraint_statements: Vec<FlatStatement<T>> = constraints
|
||||
.into_iter()
|
||||
.map(|c| {
|
||||
let c: Constraint<T> = from_ark::<T, Bls12_377>(c);
|
||||
let rhs_a = flat_expression_from_vec::<T>(c.a.as_slice());
|
||||
let rhs_b = flat_expression_from_vec::<T>(c.b.as_slice());
|
||||
let lhs = flat_expression_from_vec::<T>(c.c.as_slice());
|
||||
|
||||
FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b))
|
||||
})
|
||||
.collect();
|
||||
|
||||
let return_statement = FlatStatement::Return(FlatExpressionList {
|
||||
expressions: vec![FlatExpression::Identifier(FlatVariable::new(out_index))],
|
||||
});
|
||||
|
||||
// insert a directive to set the witness
|
||||
let directive_statement = FlatStatement::Directive(FlatDirective {
|
||||
outputs: cs_indices.map(FlatVariable::new).collect(),
|
||||
inputs: input_argument_indices
|
||||
.chain(proof_argument_indices)
|
||||
.chain(vk_argument_indices)
|
||||
.map(|i| FlatVariable::new(i).into())
|
||||
.collect(),
|
||||
solver: Solver::Verify(n),
|
||||
});
|
||||
|
||||
let statements: Vec<_> = std::iter::once(directive_statement)
|
||||
.chain(std::iter::once(one_binding_statement))
|
||||
.chain(input_binding_statements)
|
||||
.chain(constraint_statements)
|
||||
.chain(std::iter::once(return_statement))
|
||||
.collect();
|
||||
|
||||
FlatFunction {
|
||||
arguments,
|
||||
statements,
|
||||
}
|
||||
}
|
||||
|
||||
fn use_variable(
|
||||
|
|
|
@ -156,6 +156,10 @@ impl Importer {
|
|||
id: symbol.get_alias(),
|
||||
symbol: Symbol::Flat(FlatEmbed::U8FromBits),
|
||||
},
|
||||
"verify" => SymbolDeclaration {
|
||||
id: symbol.get_alias(),
|
||||
symbol: Symbol::Flat(FlatEmbed::Verify),
|
||||
},
|
||||
s => {
|
||||
return Err(CompileErrorInner::ImportError(
|
||||
Error::new(format!("Embed {} not found", s)).with_pos(Some(pos)),
|
||||
|
|
|
@ -144,7 +144,7 @@ impl Interpreter {
|
|||
inputs: &[T],
|
||||
) -> Result<Vec<T>, String> {
|
||||
let (expected_input_count, expected_output_count) = solver.get_signature();
|
||||
assert!(inputs.len() == expected_input_count);
|
||||
assert_eq!(inputs.len(), expected_input_count);
|
||||
|
||||
let res = match solver {
|
||||
Solver::ConditionEq => match inputs[0].is_zero() {
|
||||
|
@ -233,6 +233,10 @@ impl Interpreter {
|
|||
})
|
||||
.collect()
|
||||
}
|
||||
#[cfg(feature = "ark")]
|
||||
Solver::Verify(_n) => {
|
||||
todo!()
|
||||
}
|
||||
};
|
||||
|
||||
assert_eq!(res.len(), expected_output_count);
|
||||
|
|
|
@ -37,7 +37,7 @@ impl Solver {
|
|||
#[cfg(feature = "bellman")]
|
||||
Solver::Sha256Round => (768, 26935),
|
||||
#[cfg(feature = "ark")]
|
||||
Solver::Verify(n) => (26 + 3 * n, 56953 + 3078 * n), // TODO: update this
|
||||
Solver::Verify(n) => (26 + 3 * n, 0), // TODO: update output count
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,6 +549,7 @@ impl<'ast, 'a, T: Field> ResultFolder<'ast, T> for Propagator<'ast, 'a, T> {
|
|||
}
|
||||
}
|
||||
FlatEmbed::Sha256Round => None,
|
||||
FlatEmbed::Verify => None,
|
||||
};
|
||||
|
||||
match r {
|
||||
|
|
|
@ -10,6 +10,7 @@ wasm = ["bellman_ce/wasm", "sapling-crypto_ce/wasm"]
|
|||
multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"]
|
||||
|
||||
[dependencies]
|
||||
zokrates_field = { version = "0.4.0", path = "../zokrates_field", default-features = false }
|
||||
bellman_ce = { version = "^0.3", default-features = false }
|
||||
sapling-crypto_ce = { version = "^0.1", default-features = false }
|
||||
ark-bls12-377 = { version = "^0.2.0", features = ["curve", "r1cs"], default-features = false }
|
||||
|
|
|
@ -1,54 +1,38 @@
|
|||
use ark_bls12_377::{
|
||||
constraints::PairingVar as BLS12PairingVar, Bls12_377 as BLS12PairingEngine, Fr as BLS12Fr,
|
||||
constraints::PairingVar as BLS12PairingVar, Bls12_377 as BLS12PairingEngine, Fq as BLS12Fq,
|
||||
};
|
||||
use ark_bw6_761::Fr as BW6Fr;
|
||||
use ark_ec::PairingEngine;
|
||||
use ark_ff::{Field, UniformRand};
|
||||
use ark_ff::{BigInteger, One, PrimeField};
|
||||
use ark_r1cs_std::bits::boolean::Boolean;
|
||||
use ark_relations::{
|
||||
lc, ns,
|
||||
ns,
|
||||
r1cs::{ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, SynthesisError},
|
||||
};
|
||||
|
||||
use ark_crypto_primitives::snark::constraints::SNARKGadget;
|
||||
use ark_crypto_primitives::snark::{CircuitSpecificSetupSNARK, SNARK};
|
||||
use ark_crypto_primitives::snark::{FromFieldElementsGadget, SNARK};
|
||||
use ark_gm17::{constraints::GM17VerifierGadget, GM17};
|
||||
use ark_r1cs_std::ToBitsGadget;
|
||||
use ark_r1cs_std::ToConstraintFieldGadget;
|
||||
|
||||
use ark_r1cs_std::alloc::AllocVar;
|
||||
use ark_std::test_rng;
|
||||
|
||||
use crate::Constraint;
|
||||
use ark_r1cs_std::eq::EqGadget;
|
||||
use ark_r1cs_std::fields::fp::FpVar;
|
||||
use ark_relations::r1cs::Variable;
|
||||
use ark_std::ops::MulAssign;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct DummyCircuit<F: Field> {
|
||||
a: Option<F>,
|
||||
b: Option<F>,
|
||||
input_size: usize,
|
||||
struct DefaultCircuit {
|
||||
pub public_input_size: usize,
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> ConstraintSynthesizer<ConstraintF> for DummyCircuit<ConstraintF> {
|
||||
fn generate_constraints(
|
||||
self,
|
||||
cs: ConstraintSystemRef<ConstraintF>,
|
||||
) -> Result<(), SynthesisError> {
|
||||
let a = cs.new_witness_variable(|| self.a.ok_or(SynthesisError::AssignmentMissing))?;
|
||||
let b = cs.new_witness_variable(|| self.b.ok_or(SynthesisError::AssignmentMissing))?;
|
||||
|
||||
for _ in 0..self.input_size {
|
||||
let c = cs.new_input_variable(|| {
|
||||
let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
|
||||
let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;
|
||||
|
||||
a.mul_assign(&b);
|
||||
Ok(a)
|
||||
})?;
|
||||
cs.enforce_constraint(lc!() + a, lc!() + b, lc!() + c)?;
|
||||
impl<F: PrimeField> ConstraintSynthesizer<F> for DefaultCircuit {
|
||||
fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
|
||||
for _ in 0..self.public_input_size {
|
||||
let _ = FpVar::<F>::new_input(ns!(cs, "alloc"), || Ok(F::one()))?;
|
||||
// gadget.to_bits_le()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -56,49 +40,45 @@ impl<ConstraintF: Field> ConstraintSynthesizer<ConstraintF> for DummyCircuit<Con
|
|||
type GM17Snark = GM17<BLS12PairingEngine>;
|
||||
type VerifierGadget = GM17VerifierGadget<BLS12PairingEngine, BLS12PairingVar>;
|
||||
|
||||
// pub fn generate_verify_constraints(input_size: usize) -> (usize, Vec<Constraint<BW6Fr>>) {
|
||||
#[test]
|
||||
pub fn generate_verify_constraints() {
|
||||
let input_size: usize = 1;
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub fn generate_verify_constraints(
|
||||
public_input_size: usize,
|
||||
) -> (
|
||||
usize,
|
||||
Vec<usize>,
|
||||
Vec<usize>,
|
||||
Vec<usize>,
|
||||
Vec<Constraint<BW6Fr>>,
|
||||
usize,
|
||||
) {
|
||||
let mut rng = test_rng();
|
||||
let a = BLS12Fr::rand(&mut rng);
|
||||
let b = BLS12Fr::rand(&mut rng);
|
||||
let mut c = a.clone();
|
||||
c.mul_assign(&b);
|
||||
let circuit = DefaultCircuit { public_input_size };
|
||||
|
||||
let circuit = DummyCircuit {
|
||||
a: Some(a),
|
||||
b: Some(b),
|
||||
input_size,
|
||||
};
|
||||
|
||||
let (pk, vk) = GM17Snark::setup(circuit.clone(), &mut rng).unwrap();
|
||||
let (pk, vk) = GM17Snark::circuit_specific_setup(circuit, &mut rng).unwrap();
|
||||
let proof = GM17Snark::prove(&pk, circuit, &mut rng).unwrap();
|
||||
|
||||
let cs_sys = ConstraintSystem::<BW6Fr>::new();
|
||||
let cs = ConstraintSystemRef::new(cs_sys);
|
||||
|
||||
let input_gadget =
|
||||
<VerifierGadget as SNARKGadget<
|
||||
<BLS12PairingEngine as PairingEngine>::Fr,
|
||||
<BLS12PairingEngine as PairingEngine>::Fq,
|
||||
GM17Snark,
|
||||
>>::InputVar::new_input(ns!(cs, "alloc_inputs"), || Ok(vec![c; input_size]))
|
||||
.unwrap();
|
||||
let mut inputs = Vec::new();
|
||||
for _ in 0..public_input_size {
|
||||
inputs.push(FpVar::new_input(ns!(cs, "alloc_input"), || Ok(BLS12Fq::one())).unwrap());
|
||||
}
|
||||
|
||||
let input_indices = input_gadget
|
||||
.clone()
|
||||
.into_iter()
|
||||
.map(|f| {
|
||||
f.iter()
|
||||
.map(|b| match b {
|
||||
Boolean::Is(x) => var_to_index(x.variable()),
|
||||
Boolean::Not(x) => var_to_index(x.variable()),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect()
|
||||
let input_indices = inputs
|
||||
.iter()
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<Vec<usize>>>();
|
||||
.collect::<Vec<usize>>();
|
||||
|
||||
let input_gadget = <VerifierGadget as SNARKGadget<
|
||||
<BLS12PairingEngine as PairingEngine>::Fr,
|
||||
<BLS12PairingEngine as PairingEngine>::Fq,
|
||||
GM17Snark,
|
||||
>>::InputVar::from_field_elements(&inputs)
|
||||
.unwrap();
|
||||
|
||||
let proof_gadget = <VerifierGadget as SNARKGadget<
|
||||
<BLS12PairingEngine as PairingEngine>::Fr,
|
||||
|
@ -107,35 +87,128 @@ pub fn generate_verify_constraints() {
|
|||
>>::ProofVar::new_witness(ns!(cs, "alloc_proof"), || Ok(proof))
|
||||
.unwrap();
|
||||
|
||||
let proof_indices = proof_gadget
|
||||
.clone()
|
||||
.a
|
||||
.to_bits_le()
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|b| match b {
|
||||
Boolean::Is(x) => var_to_index(x.variable()),
|
||||
Boolean::Not(x) => var_to_index(x.variable()),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>();
|
||||
let proof_indices: Vec<usize> = vec![
|
||||
proof_gadget
|
||||
.a
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(2) // [x, y, infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
proof_gadget
|
||||
.b
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(4) // [[x0, y0], [x1, y1], infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
proof_gadget
|
||||
.c
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(2) // [x, y, infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
let vk_gadget = <VerifierGadget as SNARKGadget<
|
||||
<BLS12PairingEngine as PairingEngine>::Fr,
|
||||
<BLS12PairingEngine as PairingEngine>::Fq,
|
||||
GM17Snark,
|
||||
>>::VerifyingKeyVar::new_constant(ns!(cs, "alloc_vk"), vk.clone())
|
||||
>>::VerifyingKeyVar::new_witness(ns!(cs, "alloc_vk"), || Ok(vk.clone()))
|
||||
.unwrap();
|
||||
|
||||
// let vk_indices = vk_gadget
|
||||
// .clone()
|
||||
// .into_iter()
|
||||
// .map(|f| f.iter().map(|b| match b {
|
||||
// Boolean::Is(x) => var_to_index(x.variable()),
|
||||
// Boolean::Not(x) => var_to_index(x.variable()),
|
||||
// _ => unreachable!(),
|
||||
// }).collect())
|
||||
// .collect::<Vec<Vec<usize>>>();
|
||||
let vk_indices: Vec<usize> = vec![
|
||||
vk_gadget
|
||||
.h_g2
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(4) // [[x0, y0], [x1, y1], infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
vk_gadget
|
||||
.g_alpha_g1
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(2) // [x, y, infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
vk_gadget
|
||||
.h_beta_g2
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(4) // [[x0, y0], [x1, y1], infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
vk_gadget
|
||||
.g_gamma_g1
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(2) // [x, y, infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
vk_gadget
|
||||
.h_gamma_g2
|
||||
.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(4) // [[x0, y0], [x1, y1], infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>(),
|
||||
vk_gadget
|
||||
.query
|
||||
.iter()
|
||||
.map(|q| {
|
||||
q.to_constraint_field()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.take(2) // [x, y, infinity] - infinity
|
||||
.map(|f| match f {
|
||||
FpVar::Var(fp) => var_to_index(&fp.variable),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.collect::<Vec<usize>>()
|
||||
})
|
||||
.flatten()
|
||||
.collect::<Vec<usize>>(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<usize>>();
|
||||
|
||||
let res = <VerifierGadget as SNARKGadget<
|
||||
<BLS12PairingEngine as PairingEngine>::Fr,
|
||||
|
@ -145,13 +218,12 @@ pub fn generate_verify_constraints() {
|
|||
.unwrap();
|
||||
|
||||
let out_index = match &res {
|
||||
Boolean::Is(x) => var_to_index(x.variable()),
|
||||
Boolean::Not(x) => var_to_index(x.variable()),
|
||||
Boolean::Is(x) => var_to_index(&x.variable()),
|
||||
Boolean::Not(x) => var_to_index(&x.variable()),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
res.conditional_enforce_equal(&Boolean::constant(true), &Boolean::constant(true))
|
||||
.unwrap();
|
||||
// res.conditional_enforce_equal(&Boolean::TRUE, &Boolean::TRUE).unwrap();
|
||||
cs.finalize();
|
||||
|
||||
let matrices = cs.to_matrices().unwrap();
|
||||
|
@ -167,16 +239,62 @@ pub fn generate_verify_constraints() {
|
|||
})
|
||||
.collect();
|
||||
|
||||
assert!(cs.is_satisfied().unwrap());
|
||||
// println!("input_indices: {:?}", input_indices);
|
||||
// println!("proof_indices: {:?}", proof_indices);
|
||||
// println!("vk_indices: {:?}", vk_indices);
|
||||
// println!("out_index: {:?}", out_index);
|
||||
|
||||
println!("{}", input_indices.len());
|
||||
println!("{}", proof_indices.len());
|
||||
// println!("{}", vk_indices.len());
|
||||
assert!(
|
||||
cs.is_satisfied().unwrap(),
|
||||
"Constraint not satisfied: {}",
|
||||
cs.which_is_unsatisfied().unwrap().unwrap_or_default()
|
||||
);
|
||||
|
||||
// (out_index, constraints)
|
||||
(
|
||||
out_index,
|
||||
input_indices,
|
||||
proof_indices,
|
||||
vk_indices,
|
||||
constraints,
|
||||
cs.num_witness_variables(),
|
||||
)
|
||||
}
|
||||
|
||||
fn var_to_index(v: Variable) -> usize {
|
||||
#[test]
|
||||
fn generate_verify_constraints_test() {
|
||||
let _ = generate_verify_constraints(2);
|
||||
}
|
||||
|
||||
fn var_to_index(v: &Variable) -> usize {
|
||||
v.get_index_unchecked(0)
|
||||
.expect("Could not get variable index")
|
||||
}
|
||||
|
||||
pub fn from_ark<T: zokrates_field::Field, E: PairingEngine>(c: Constraint<E::Fq>) -> Constraint<T> {
|
||||
Constraint {
|
||||
a: c.a
|
||||
.into_iter()
|
||||
.map(|(index, fq)| {
|
||||
let mut res: Vec<u8> = vec![];
|
||||
fq.into_repr().write_le(&mut res).unwrap();
|
||||
(index, T::from_byte_vector(res))
|
||||
})
|
||||
.collect(),
|
||||
b: c.b
|
||||
.into_iter()
|
||||
.map(|(index, fq)| {
|
||||
let mut res: Vec<u8> = vec![];
|
||||
fq.into_repr().write_le(&mut res).unwrap();
|
||||
(index, T::from_byte_vector(res))
|
||||
})
|
||||
.collect(),
|
||||
c: c.c
|
||||
.into_iter()
|
||||
.map(|(index, fq)| {
|
||||
let mut res: Vec<u8> = vec![];
|
||||
fq.into_repr().write_le(&mut res).unwrap();
|
||||
(index, T::from_byte_vector(res))
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use bellman::{
|
|||
pairing::{ff::Field, Engine},
|
||||
ConstraintSystem, Index, LinearCombination, SynthesisError, Variable,
|
||||
};
|
||||
use sapling_crypto::bellman::pairing::ff::{PrimeField, PrimeFieldRepr};
|
||||
use sapling_crypto::circuit::{
|
||||
boolean::{AllocatedBit, Boolean},
|
||||
sha256::sha256_compression_function,
|
||||
|
@ -149,7 +150,7 @@ impl<E: Engine> ConstraintSystem<E> for R1CS<E::Fr> {
|
|||
AR: Into<String>,
|
||||
{
|
||||
// we don't care about the value as we're only generating the CS
|
||||
let index = self.aux_count.clone();
|
||||
let index = self.aux_count;
|
||||
let var = Variable::new_unchecked(Index::Aux(index));
|
||||
self.aux_count += 1;
|
||||
Ok(var)
|
||||
|
@ -252,6 +253,35 @@ fn var_to_index(v: Variable) -> usize {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_bellman<T: zokrates_field::Field, E: Engine>(c: Constraint<E::Fr>) -> Constraint<T> {
|
||||
Constraint {
|
||||
a: c.a
|
||||
.into_iter()
|
||||
.map(|(index, fq)| {
|
||||
let mut res: Vec<u8> = vec![];
|
||||
fq.into_repr().write_le(&mut res).unwrap();
|
||||
(index, T::from_byte_vector(res))
|
||||
})
|
||||
.collect(),
|
||||
b: c.b
|
||||
.into_iter()
|
||||
.map(|(index, fq)| {
|
||||
let mut res: Vec<u8> = vec![];
|
||||
fq.into_repr().write_le(&mut res).unwrap();
|
||||
(index, T::from_byte_vector(res))
|
||||
})
|
||||
.collect(),
|
||||
c: c.c
|
||||
.into_iter()
|
||||
.map(|(index, fq)| {
|
||||
let mut res: Vec<u8> = vec![];
|
||||
fq.into_repr().write_le(&mut res).unwrap();
|
||||
(index, T::from_byte_vector(res))
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in a new issue