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

feat/fixed base scalar multiplication using precomputed table #196

Merged
merged 16 commits into from
Aug 23, 2022
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
## [Unreleased]
### Added
- [\#172](https://github.com/Manta-Network/manta-rs/pull/172) Add abstract Phase 2 for Groth16 trusted setup
- [\#196](https://github.com/Manta-Network/manta-rs/pull/172) Add fixed base scalar multiplication using precomputed bases

### Changed
- [\#180](https://github.com/Manta-Network/manta-rs/pull/180) Start moving to new `arkworks` backend for `manta-crypto`
Expand Down
19 changes: 18 additions & 1 deletion manta-crypto/src/algebra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::{
key,
rand::{RngCore, Sample},
};
use core::marker::PhantomData;
use core::{borrow::Borrow, marker::PhantomData};
use manta_util::codec::{Decode, DecodeError, Encode, Read, Write};

#[cfg(feature = "serde")]
Expand All @@ -48,6 +48,23 @@ pub trait Group<COM = ()> {
fn mul(&self, scalar: &Self::Scalar, compiler: &mut COM) -> Self;
}

/// Fixed Base Scalar Multiplication using precomputed base points
pub trait FixedBaseScalarMul<COM = ()>: Group<COM> {
/// Fixed Base Point
type Base;

/// Multiply `precomputed_bases[0]` by `scalar` using precomputed base points,
/// where `precomputed_bases` are precomputed power-of-two multiples of the fixed base.
fn fixed_base_scalar_mul<I, T>(
precomputed_bases: I,
scalar: &Self::Scalar,
compiler: &mut COM,
) -> Self
where
I: IntoIterator<Item = T>,
T: Borrow<Self::Base>;
tsunrise marked this conversation as resolved.
Show resolved Hide resolved
}

/// Diffie-Hellman Key Agreement Scheme
#[cfg_attr(
feature = "serde",
Expand Down
1 change: 1 addition & 0 deletions manta-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#![forbid(missing_docs)]

extern crate alloc;
extern crate core;
tsunrise marked this conversation as resolved.
Show resolved Hide resolved

pub mod accumulator;
pub mod algebra;
Expand Down
82 changes: 81 additions & 1 deletion manta-pay/src/crypto/ecc/arkworks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

use crate::crypto::constraint::arkworks::{self, empty, full, Boolean, Fp, FpVar, R1CS};
use alloc::vec::Vec;
use core::marker::PhantomData;
use core::{borrow::Borrow, marker::PhantomData};
use manta_crypto::{
algebra,
arkworks::{
Expand All @@ -41,6 +41,7 @@ use manta_crypto::{
};
use manta_util::codec;

use manta_crypto::algebra::FixedBaseScalarMul;
#[cfg(feature = "serde")]
use {
manta_crypto::arkworks::algebra::serialize_group_element,
Expand Down Expand Up @@ -516,3 +517,82 @@ where
)
}
}

impl<C, CV> FixedBaseScalarMul<Compiler<C>> for GroupVar<C, CV>
where
C: ProjectiveCurve,
CV: CurveVar<C, ConstraintField<C>>,
{
type Base = C;

fn fixed_base_scalar_mul<I, T>(
precomputed_bases: I,
scalar: &Self::Scalar,
compiler: &mut Compiler<C>,
) -> Self
where
I: IntoIterator<Item = T>,
T: Borrow<Self::Base>,
tsunrise marked this conversation as resolved.
Show resolved Hide resolved
{
let _ = compiler;
let mut result = CV::zero();
let scalar_bits = scalar
.0
.to_bits_le()
.expect("Bit decomposition is not allowed to fail.");
for (bit, base) in scalar_bits.into_iter().zip(precomputed_bases.into_iter()) {
result = bit
.select(&(result.clone() + *base.borrow()), &result)
.expect("Conditional select is not allowed to fail. ");
}
Self::new(result)
tsunrise marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::config::Bls12_381_Edwards;
use manta_crypto::{
algebra::Group, arkworks::r1cs_std::groups::curves::twisted_edwards::AffineVar,
constraint::measure::Measure, eclair::bool::AssertEq, rand::OsRng,
};

/// Constraint Field Type
type ConstraintField<C> = <<C as ProjectiveCurve>::BaseField as Field>::BasePrimeField;

/// Compiler Type
type Compiler<C> = R1CS<ConstraintField<C>>;

/// Scalar Field Element
pub type Scalar<C> = Fp<<C as ProjectiveCurve>::ScalarField>;
tsunrise marked this conversation as resolved.
Show resolved Hide resolved

#[test]
fn fixed_base_mul() {
let mut cs = Compiler::<Bls12_381_Edwards>::for_proofs();
let scalar = Scalar::<Bls12_381_Edwards>::gen(&mut OsRng);
let base = Bls12_381_Edwards::prime_subgroup_generator();
let precomputed_table =
core::iter::successors(Some(base), |base| Some(*base + *base)).take(256);
tsunrise marked this conversation as resolved.
Show resolved Hide resolved

let base_var = Group(base.into_affine())
.as_known::<Secret, GroupVar<Bls12_381_Edwards, AffineVar<_, _>>>(&mut cs);
let scalar_var =
scalar.as_known::<Secret, ScalarVar<Bls12_381_Edwards, AffineVar<_, _>>>(&mut cs);

let ctr1 = cs.constraint_count();
let expected = base_var.mul(&scalar_var, &mut cs);
let ctr2 = cs.constraint_count();
let actual = GroupVar::fixed_base_scalar_mul(precomputed_table, &scalar_var, &mut cs);
let ctr3 = cs.constraint_count();

cs.assert_eq(&expected, &actual);
assert!(cs.is_satisfied());

#[cfg(feature = "std")]
tsunrise marked this conversation as resolved.
Show resolved Hide resolved
{
println!("variable base mul constraint: {:?}", ctr2 - ctr1);
println!("fixed base mul constraint: {:?}", ctr3 - ctr2);
}
}
}
1 change: 1 addition & 0 deletions manta-pay/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#![forbid(missing_docs)]

extern crate alloc;
extern crate core;
tsunrise marked this conversation as resolved.
Show resolved Hide resolved

pub mod crypto;
pub mod util;
Expand Down
11 changes: 6 additions & 5 deletions workspace-hack/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,12 @@ publish = false

### BEGIN HAKARI SECTION
[dependencies]
aes-gcm = { version = "0.9.4", features = ["aes", "alloc"] }
anyhow = { version = "1.0.59", features = ["std"] }
ark-serialize = { version = "0.3.0", default-features = false, features = ["ark-serialize-derive", "derive"] }
bitflags = { version = "1.3.2" }
blake3 = { version = "1.3.1", default-features = false, features = ["digest", "std"] }
byteorder = { version = "1.4.3", features = ["std"] }
crypto-common = { version = "0.1.6", default-features = false, features = ["std"] }
crypto-common = { version = "0.1.6", default-features = false, features = ["getrandom", "rand_core", "std"] }
digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = ["alloc", "block-buffer", "core-api", "mac", "std", "subtle"] }
digest-274715c4dabd11b0 = { package = "digest", version = "0.9.0", default-features = false, features = ["alloc", "std"] }
futures = { version = "0.3.21", features = ["alloc", "async-await", "executor", "futures-executor", "std"] }
Expand All @@ -40,7 +39,7 @@ ppv-lite86 = { version = "0.2.16", default-features = false, features = ["simd",
rand = { version = "0.8.5", features = ["alloc", "getrandom", "libc", "rand_chacha", "std", "std_rng"] }
rand_chacha = { version = "0.3.1", default-features = false, features = ["std"] }
rand_core = { version = "0.6.3", default-features = false, features = ["alloc", "getrandom", "std"] }
serde = { version = "1.0.141", features = ["alloc", "derive", "serde_derive", "std"] }
serde = { version = "1.0.142", features = ["alloc", "derive", "serde_derive", "std"] }
serde_json = { version = "1.0.82", features = ["alloc", "std"] }
sha2 = { version = "0.9.9", features = ["std"] }
standback = { version = "0.2.17", default-features = false, features = ["std"] }
Expand All @@ -54,12 +53,14 @@ zeroize = { version = "1.5.7", default-features = false, features = ["alloc", "z
anyhow = { version = "1.0.59", features = ["std"] }
blake3 = { version = "1.3.1", default-features = false, features = ["digest", "std"] }
cc = { version = "1.0.73", default-features = false, features = ["jobserver", "parallel"] }
crypto-common = { version = "0.1.6", default-features = false, features = ["std"] }
crypto-common = { version = "0.1.6", default-features = false, features = ["getrandom", "rand_core", "std"] }
digest-93f6ce9d446188ac = { package = "digest", version = "0.10.3", features = ["alloc", "block-buffer", "core-api", "mac", "std", "subtle"] }
generic-array = { version = "0.14.6", default-features = false, features = ["more_lengths"] }
getrandom = { version = "0.2.7", default-features = false, features = ["js", "js-sys", "std", "wasm-bindgen"] }
log = { version = "0.4.17", default-features = false, features = ["kv_unstable", "kv_unstable_std", "std", "value-bag"] }
num-traits = { version = "0.2.15", features = ["i128", "libm", "std"] }
serde = { version = "1.0.141", features = ["alloc", "derive", "serde_derive", "std"] }
rand_core = { version = "0.6.3", default-features = false, features = ["alloc", "getrandom", "std"] }
serde = { version = "1.0.142", features = ["alloc", "derive", "serde_derive", "std"] }
standback = { version = "0.2.17", default-features = false, features = ["std"] }
subtle = { version = "2.4.1", default-features = false, features = ["i128"] }
syn = { version = "1.0.98", features = ["clone-impls", "derive", "extra-traits", "fold", "full", "parsing", "printing", "proc-macro", "quote", "visit", "visit-mut"] }
Expand Down