Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduced Hopwood optimized vbSM gadget #126

Merged
merged 26 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c6b4db6
(WIP) Introduced Hopwood optimized vbSM gadget. Handle internally exc…
DanieleDiBenedetto Sep 22, 2021
011015c
Bug fix
DanieleDiBenedetto Sep 22, 2021
74d9a82
Daira's double_and_add_interal: more docu, enforcing exceptional case…
UlrichHaboeck75 Sep 23, 2021
c929373
Daira's mul_bits: extra treatment of last bit with safe add. Added docu.
UlrichHaboeck75 Sep 23, 2021
db21144
copied the corrected code of mul_bits(), double_and_add_internal() to…
UlrichHaboeck75 Sep 23, 2021
e1d0235
translated the changes of double_and_add_internal(), mul_bits() to no…
UlrichHaboeck75 Sep 23, 2021
967e8e7
Added scalar_bits_to_constant_length gadget
DanieleDiBenedetto Sep 24, 2021
53e402f
corrected `scalar_bits_to_constant_length`, added comments.
UlrichHaboeck75 Sep 24, 2021
665619b
added TODO
UlrichHaboeck75 Sep 24, 2021
1715dae
Replaced non-native field gadgets by direct arguments.
UlrichHaboeck75 Sep 26, 2021
941dadd
Simplified from_bits() for non-natives by limb-wise packing via from_…
UlrichHaboeck75 Sep 26, 2021
f9b227b
Fixed from_bits test
DanieleDiBenedetto Sep 27, 2021
139d77a
Drop the assumption on the scalar MSB being 1 for mul_bits
DanieleDiBenedetto Sep 27, 2021
71ca963
Return exactly SimulationF::size_in_bits() bits from NonNativeFieldGa…
DanieleDiBenedetto Sep 27, 2021
dc56cd0
Merge branch 'rc/audit_chain' into hopwood_optimized_sm
DanieleDiBenedetto Sep 27, 2021
e00a772
Serialized some intensive tests
DanieleDiBenedetto Sep 27, 2021
60ea587
Fix CI
DanieleDiBenedetto Sep 27, 2021
f75ee3a
Additional secure add in `mul_bits()` native and non-native.
UlrichHaboeck75 Sep 27, 2021
4016f27
mul_bits() native and non-native: additional comments on the usage of…
UlrichHaboeck75 Sep 28, 2021
1531c6d
Revert "Serialized some intensive tests"
DanieleDiBenedetto Sep 28, 2021
64bb089
Added more CI stages to avoid timeout
DanieleDiBenedetto Sep 28, 2021
be7c743
separated the ci in multiple steps to optimize timing
lander86 Sep 28, 2021
f1c79c3
fixed typo
lander86 Sep 28, 2021
8e964e8
mul_bits() native: resolved TODOs on documenting completeness.
UlrichHaboeck75 Sep 28, 2021
b0340fb
fix typos
lander86 Sep 28, 2021
1adf934
Merge branch 'hopwood_optimized_sm' of github.com:HorizenOfficial/gin…
lander86 Sep 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ script:

jobs:
include:
- name: bionic_rust-1.51.0_latest-STAGE1
env: IMAGE_TAG=bionic_rust-1.51.0_latest TESTS='000,001,003,005,006,008,009,011,012,013,014,015,016,018'
- name: bionic_rust-1.51.0_latest-STAGE2
env: IMAGE_TAG=bionic_rust-1.51.0_latest TESTS='017'
- name: bionic_rust-nightly-2021-04-25_latest
- name: bionic_rust-1.51.0_latest-CHECK
env: IMAGE_TAG=bionic_rust-1.51.0_latest TESTS='000,001,003,005,006,008,009,011,012,013,014,015,016,020'
- name: bionic_rust-1.51.0_latest-TEST
env: IMAGE_TAG=bionic_rust-1.51.0_latest TESTS='017,018'
- name: bionic_rust-1.51.0_latest-TEST_INTENSIVE
env: IMAGE_TAG=bionic_rust-1.51.0_latest TESTS='019'
- name: bionic_rust-nightly-2021-04-25_latest-CHECK
env: IMAGE_TAG=bionic_rust-nightly-2021-04-25_latest TESTS='002,004,007,010' CARGOARGS='+nightly-2021-04-25'
2 changes: 1 addition & 1 deletion algebra/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ llvm_asm = []
derive = ["algebra-derive"]

bls12_377 = []
bls12_381 = []
bls12_381 = ["jubjub"]
edwards_bls12 = ["bls12_377"]
edwards_sw6 = ["sw6"]
jubjub = []
Expand Down
5 changes: 5 additions & 0 deletions algebra/src/biginteger/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,18 @@ macro_rules! bigint_impl {
}
}

// Defines a BigInt from a slice of big endian booleans.
#[inline]
fn from_bits(bits: &[bool]) -> Self {
let mut res = Self::default();
let mut acc: u64 = 0;

// convert to little endian as the limbs are in
// little endian order
let mut bits = bits.to_vec();
bits.reverse();
for (i, bits64) in bits.chunks(64).enumerate() {
// each chunk is again arranged big endian
for bit in bits64.iter().rev() {
acc <<= 1;
acc += *bit as u64;
Expand All @@ -165,6 +169,7 @@ macro_rules! bigint_impl {
res
}

// Note: Does not skip leading zeroes
#[inline]
fn to_bits(&self) -> Vec<bool> {
let mut res = Vec::with_capacity(256);
Expand Down
2 changes: 2 additions & 0 deletions algebra/src/biginteger/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ pub trait BigInteger:

/// Returns the bit representation in a big endian boolean array, without
/// leading zeros.
// TODO: the current implementation does not seem to skip leading zeroes.
// Let us check its usage and determine if a change is reasonable.
fn to_bits(&self) -> Vec<bool>;

/// Returns a vector for wnaf.
Expand Down
2 changes: 2 additions & 0 deletions algebra/src/fields/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,8 @@ impl<F: PrimeField> ToBits for F {
}
}

// Defines a prime field element from a big endian vector of booleans, which
// does not exceed the length of the modulus.
impl<F: PrimeField> FromBits for F {
#[inline]
fn read_bits(bits: Vec<bool>) -> Result<Self, Error> {
Expand Down
2 changes: 1 addition & 1 deletion ci/tests/017-cargo-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@

set -xeo pipefail

cargo $CARGOARGS test --all-features
cargo $CARGOARGS test --workspace --all-features --exclude "r1cs-std"
7 changes: 7 additions & 0 deletions ci/tests/018-cargo-test-r1cs-std-no-nonnative.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# shellcheck disable=SC2086

set -xeo pipefail

cd r1cs/gadgets/std
cargo $CARGOARGS test --features="full"
7 changes: 7 additions & 0 deletions ci/tests/019-cargo-test-r1cs-std-nonnative.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
# shellcheck disable=SC2086

set -xeo pipefail

cd r1cs/gadgets/std
cargo $CARGOARGS test nonnative --all-features
File renamed without changes.
8 changes: 5 additions & 3 deletions r1cs/gadgets/crypto/src/nizk/gm17/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ for Gm17VerifierGadget<PairingE, ConstraintF, P>
.enumerate()
{
let input_bits = input.to_bits(cs.ns(|| format!("Input {}", i)))?;
g_psi = b.mul_bits(cs.ns(|| format!("Mul {}", i)), &g_psi, input_bits.iter())?;
g_psi = b
.mul_bits(cs.ns(|| format!("Mul {}", i)), input_bits.iter())?
.add(cs.ns(|| format!("Add {}", i)), &g_psi)?;
input_len += 1;
}
// Check that the input and the query in the verification are of the
Expand Down Expand Up @@ -460,7 +462,7 @@ mod test {
use algebra::{
curves::bls12_377::Bls12_377,
fields::bls12_377::{Fq, Fr},
BitIterator, PrimeField,
ToBits,
};
use r1cs_std::{
boolean::Boolean, instantiated::bls12_377::PairingGadget as Bls12_377PairingGadget,
Expand Down Expand Up @@ -559,7 +561,7 @@ mod test {
{
let mut cs = cs.ns(|| "Allocate Input");
for (i, input) in inputs.iter().enumerate() {
let mut input_bits = BitIterator::new(input.into_repr()).collect::<Vec<_>>();
let mut input_bits = input.write_bits();
// Input must be in little-endian, but BitIterator outputs in big-endian.
input_bits.reverse();

Expand Down
8 changes: 5 additions & 3 deletions r1cs/gadgets/crypto/src/nizk/groth16/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,9 @@ for Groth16VerifierGadget<PairingE, ConstraintF, P>
.enumerate()
{
let input_bits = input.to_bits(cs.ns(|| format!("Input {}", i)))?;
g_ic = b.mul_bits(cs.ns(|| format!("Mul {}", i)), &g_ic, input_bits.iter())?;
g_ic = b
.mul_bits(cs.ns(|| format!("Mul {}", i)), input_bits.iter())?
.add(cs.ns(|| format!("Add {}", i)), &g_ic)?;
input_len += 1;
}
// Check that the input and the query in the verification are of the
Expand Down Expand Up @@ -567,7 +569,7 @@ mod test {

use super::*;
use algebra::{
BitIterator, PrimeField, UniformRand
UniformRand, ToBits,
};
use r1cs_std::{
boolean::Boolean, test_constraint_system::TestConstraintSystem
Expand Down Expand Up @@ -660,7 +662,7 @@ mod test {
{
let mut cs = cs.ns(|| "Allocate Input");
for (i, input) in inputs.into_iter().enumerate() {
let mut input_bits = BitIterator::new(input.into_repr()).collect::<Vec<_>>();
let mut input_bits = input.write_bits();
// Input must be in little-endian, but BitIterator outputs in big-endian.
input_bits.reverse();

Expand Down
22 changes: 3 additions & 19 deletions r1cs/gadgets/crypto/src/signature/schnorr/field_based_schnorr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use std::{
borrow::Borrow,
marker::PhantomData,
};
use rand::rngs::OsRng;
use primitives::signature::schnorr::field_based_schnorr::FieldBasedSchnorrPk;
use r1cs_std::alloc::ConstantGadget;

Expand Down Expand Up @@ -366,21 +365,7 @@ impl<ConstraintF, G, GG, H, HG> FieldBasedSchnorrSigVerificationGadget<Constrain
e_bits
};

// Random shift to avoid exceptional cases if add is incomplete.
// With overwhelming probability the circuit will be satisfiable,
// otherwise the prover can sample another shift by re-running
// the proof creation.
let shift = GG::alloc(cs.ns(|| "alloc random shift"), || {
let mut rng = OsRng::default();
Ok(loop {
let r = G::rand(&mut rng);
if !r.is_zero() { break(r) }
})
})?;

let neg_e_times_pk = public_key
.mul_bits(cs.ns(|| "pk * e + shift"), &shift, e_bits.as_slice().iter().rev())?
.negate(cs.ns(|| "- (pk * e + shift)"))?;
let neg_e_times_pk = public_key.mul_bits(cs.ns(|| "pk * e"), e_bits.as_slice().iter().rev())?;

//Enforce s * G and R' = s*G - e*pk
let mut s_bits = {
Expand Down Expand Up @@ -409,12 +394,11 @@ impl<ConstraintF, G, GG, H, HG> FieldBasedSchnorrSigVerificationGadget<Constrain
let g = GG::from_value(cs.ns(|| "hardcode generator"), &G::prime_subgroup_generator());
let r_prime = GG::mul_bits_fixed_base(
&g.get_constant(),
cs.ns(|| "(s * G + shift)"),
&shift,
cs.ns(|| "(s * G)"),
s_bits.as_slice()
)?
// If add is incomplete, and s * G - e * pk = 0, the circuit of the add won't be satisfiable
.add(cs.ns(|| "s * G - e * pk "), &neg_e_times_pk)?;
.sub(cs.ns(|| "s * G - e * pk "), &neg_e_times_pk)?;

let r_prime_coords = r_prime.to_field_gadget_elements(cs.ns(|| "r_prime to fes"))?;

Expand Down
12 changes: 7 additions & 5 deletions r1cs/gadgets/crypto/src/signature/schnorr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@ for SchnorrRandomizePkGadget<G, ConstraintF, GG>
.iter()
.flat_map(|b| b.into_bits_le())
.collect::<Vec<_>>();
let rand_pk = base.mul_bits(
&mut cs.ns(|| "Compute Randomizer"),
&public_key.pub_key,
randomness.iter(),
)?;
let rand_pk = {
let base_pow_rand = base.mul_bits(
&mut cs.ns(|| "Compute randomizer"),
randomness.iter(),
)?;
public_key.pub_key.add(cs.ns(|| "Randomize pk"), &base_pow_rand)
}?;
Ok(SchnorrSigGadgetPk {
pub_key: rand_pk,
_group: PhantomData,
Expand Down
32 changes: 8 additions & 24 deletions r1cs/gadgets/crypto/src/vrf/ecvrf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ use std::{
marker::PhantomData,
borrow::Borrow,
};
use rand::rngs::OsRng;
use primitives::vrf::ecvrf::FieldBasedEcVrfPk;
use r1cs_std::bits::boolean::Boolean;

Expand Down Expand Up @@ -346,42 +345,27 @@ for FieldBasedEcVrfProofVerificationGadget<ConstraintF, G, GG, FH, FHG, GH, GHG>
&G::prime_subgroup_generator()
);

// Random shift to avoid exceptional cases if add is incomplete.
// With overwhelming probability the circuit will be satisfiable,
// otherwise the prover can sample another shift by re-running
// the proof creation.
let shift = GG::alloc(cs.ns(|| "alloc random shift"), || {
let mut rng = OsRng::default();
Ok(loop {
let r = G::rand(&mut rng);
if !r.is_zero() { break(r) }
})
})?;

//Check u = g^s - pk^c
let u =
{
let neg_c_times_pk = public_key.pk
.mul_bits(cs.ns(|| "pk * c + shift"), &shift, c_bits.as_slice().iter().rev())?
.negate(cs.ns(|| "- (c * pk + shift)"))?;
let c_times_pk = public_key.pk
.mul_bits(cs.ns(|| "pk * c"), c_bits.as_slice().iter().rev())?;
GG::mul_bits_fixed_base(&g.get_constant(),
cs.ns(|| "(s * G + shift)"),
&shift,
cs.ns(|| "s * G"),
s_bits.as_slice())?
// If add is incomplete, and s * G - c * pk = 0, the circuit of the add won't be satisfiable
.add(cs.ns(|| "(s * G) - (c * pk)"), &neg_c_times_pk)?
.sub(cs.ns(|| "(s * G) - (c * pk)"), &c_times_pk)?
};

//Check v = mh^s - gamma^c
let v =
{
let neg_c_times_gamma = proof.gamma
.mul_bits(cs.ns(|| "c * gamma + shift"), &shift, c_bits.as_slice().iter().rev())?
.negate(cs.ns(|| "- (c * gamma + shift)"))?;
let c_times_gamma = proof.gamma
.mul_bits(cs.ns(|| "c * gamma"), c_bits.as_slice().iter().rev())?;
message_on_curve
.mul_bits(cs.ns(|| "(s * mh + shift)"), &shift, s_bits.as_slice().iter())?
.mul_bits(cs.ns(|| "s * mh"), s_bits.as_slice().iter())?
// If add is incomplete, and s * mh - c * gamma = 0, the circuit of the add won't be satisfiable
.add(cs.ns(|| "(s * mh) - (c * gamma"), &neg_c_times_gamma)?
.sub(cs.ns(|| "(s * mh) - (c * gamma"), &c_times_gamma)?
};

// Check c' = H(m||pk.x||u.x||v.x)
Expand Down
2 changes: 1 addition & 1 deletion r1cs/gadgets/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,4 @@ density-optimized = []
paste = "1.0"
rand = { version = "0.8.4" }
rand_xorshift = { version = "0.3.0" }
r1cs-std = { path = "../std", features = ["bls12_381", "jubjub", "tweedle", "secp256k1", "bn_382", "nonnative"] }
r1cs-std = { path = "../std", features = ["bls12_381", "jubjub", "tweedle", "secp256k1", "bn_382"] }
8 changes: 7 additions & 1 deletion r1cs/gadgets/std/src/fields/fp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,14 @@ impl<F: PrimeField> ToBitsGadget<F> for FpGadget<F> {
}
}

// Pack a slice of Boolean gadgets into one or several field elements, bundling at most
// `F::Params::CAPACITY` many in a single field element (to allow efficient unpacking).
// The bundling regards the Booleans in big endian order.
impl<F: PrimeField> FromBitsGadget<F> for FpGadget<F> {
fn from_bits<CS: ConstraintSystem<F>>(mut cs: CS, bits: &[Boolean]) -> Result<Self, SynthesisError> {
fn from_bits<CS: ConstraintSystem<F>>(
mut cs: CS,
bits: &[Boolean]
) -> Result<Self, SynthesisError> {

// We can safely pack up to CAPACITY bits
let bits = bits.chunks(F::Params::CAPACITY as usize).next().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion r1cs/gadgets/std/src/fields/nonnative/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ macro_rules! overhead {
}

/// Parameters for a specific `NonNativeFieldGadget` instantiation
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub struct NonNativeFieldParams {
/// The number of limbs (`ConstraintF` elements) used to represent a `SimulationF` element. Highest limb first.
pub num_limbs: usize,
Expand Down
Loading