diff --git a/.DS_Store b/.DS_Store
new file mode 100644
index 0000000..abc0954
Binary files /dev/null and b/.DS_Store differ
diff --git a/.idea/class.iml b/.idea/class.iml
new file mode 100644
index 0000000..e97c456
--- /dev/null
+++ b/.idea/class.iml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..247835b
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
new file mode 100644
index 0000000..6dd740c
--- /dev/null
+++ b/.idea/workspace.xml
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1599653855418
+
+
+ 1599653855418
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Cargo.toml b/Cargo.toml
index fccfae6..c4dad4d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,10 +14,24 @@ libc = "0.2.0"
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
+flame = "0.2.2"
+flamer = "0.3"
[dependencies.curv]
git = "https://github.com/KZen-networks/curv"
tag = "v0.2.6"
features = ["ec_secp256k1"]
+[dev-dependencies]
+criterion = "0.3"
+
+[[bench]]
+name = "class_group"
+harness = false
+
+[profile.dev]
+opt-level = 0
+
+[profile.release]
+opt-level = 3
\ No newline at end of file
diff --git a/ComparisonClassGroups.pdf b/ComparisonClassGroups.pdf
new file mode 100644
index 0000000..797bd9b
Binary files /dev/null and b/ComparisonClassGroups.pdf differ
diff --git a/benches/class_group.rs b/benches/class_group.rs
new file mode 100644
index 0000000..7f127ce
--- /dev/null
+++ b/benches/class_group.rs
@@ -0,0 +1,30 @@
+use criterion::{black_box, criterion_group, criterion_main, Criterion};
+use class_group::*;
+
+/*
+pub fn criterion_benchmark(c: &mut Criterion) {
+ let mut group = c.benchmark_group("sampling Exp");
+ // Configure Criterion.rs to detect smaller differences and increase sample size to improve
+ // precision and counteract the resulting noise.
+ group.significance_level(0.1).sample_size(20);
+ group.bench_function("composing exp", |b| b.iter(|| bench_compose_exp()));
+ group.finish();
+}
+*/
+
+pub fn criterion_benchmark(c: &mut Criterion) {
+ let mut group = c.benchmark_group("sampling Exp");
+ group.significance_level(0.1).sample_size(10);
+ for exp_size in (1000..7000).step_by(1000) {
+ let dest = format!("exp 2048 bits by {:?} digits number",exp_size);
+ group.bench_function(dest, |b| b.iter(|| bench_exp_only_for_a_given_det(black_box(exp_size))));
+ // group.bench_function(dest, |b| b.iter(|| bench_exp_only(black_box(exp_size))));
+
+ }
+ group.finish();
+
+}
+
+
+criterion_group!(benches, criterion_benchmark);
+criterion_main!(benches);
\ No newline at end of file
diff --git a/build.rs b/build.rs
index de0cabb..7829524 100644
--- a/build.rs
+++ b/build.rs
@@ -9,6 +9,11 @@ use std::process::Command;
fn main() {
let pari_dir = "./depend/pari";
let pari_install = format!("{}/pari", env::var("OUT_DIR").unwrap());
+ // cd depend/pari
+ // ./Configure --prefix=/path/to/out
+ // ./depend/pari/Makefile
+ // install:
+ // copy everything to /path/to/out
{
let path = fs::canonicalize(format!("{}/Configure", pari_dir)).unwrap();
let output = Command::new(path.to_str().unwrap())
diff --git a/class_profiling.html b/class_profiling.html
new file mode 100644
index 0000000..b5fc11b
--- /dev/null
+++ b/class_profiling.html
@@ -0,0 +1,435 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/depend/.DS_Store b/depend/.DS_Store
index a32f67a..5008ddf 100644
Binary files a/depend/.DS_Store and b/depend/.DS_Store differ
diff --git a/depend/pari/.idea/.gitignore b/depend/pari/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/depend/pari/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/depend/pari/.idea/misc.xml b/depend/pari/.idea/misc.xml
new file mode 100644
index 0000000..639900d
--- /dev/null
+++ b/depend/pari/.idea/misc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/depend/pari/.idea/modules.xml b/depend/pari/.idea/modules.xml
new file mode 100644
index 0000000..0a44fe4
--- /dev/null
+++ b/depend/pari/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/depend/pari/.idea/pari.iml b/depend/pari/.idea/pari.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/depend/pari/.idea/pari.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/depend/pari/.idea/vcs.xml b/depend/pari/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/depend/pari/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/depend/pari/src/gp/gp.c b/depend/pari/src/gp/gp.c
index 3b7f1c5..ab613f9 100644
--- a/depend/pari/src/gp/gp.c
+++ b/depend/pari/src/gp/gp.c
@@ -552,7 +552,9 @@ main(int argc, char **argv)
cyg_environment(argc, argv);
#endif
stdin_isatty = pari_stdin_isatty();
- pari_init_defaults();
+ /* pari_init_defaults();*/
+ /* pari_init(8000000, 500000);*/
+ /* paristack_setsize(8000000, 20000000);*/
pari_library_path = DL_DFLT_NAME;
pari_stack_init(&s_A,sizeof(*A),(void**)&A);
pari_init_opts(1000000 * sizeof(long), 0, INIT_SIGm | INIT_noPRIMEm | INIT_noIMTm);
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 0000000..595c79b
Binary files /dev/null and b/src/.DS_Store differ
diff --git a/src/lib.rs b/src/lib.rs
index ff6a6f4..ade932b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,8 +1,9 @@
-#![allow(non_upper_case_globals)]
+ #![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
+
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
extern crate libc;
@@ -17,8 +18,14 @@ use libc::c_char;
use std::ffi::CStr;
use std::ops::Neg;
use std::str;
+use crate::curv::arithmetic::traits::Samplable;
+use std::fs::File;
+
+use flame as f;
+use flamer::flame;
+
-pub mod primitives;
+//pub mod primitives;
#[derive(PartialEq, Eq, Clone, Debug, Serialize, Deserialize)]
pub struct BinaryQF {
@@ -35,6 +42,7 @@ pub struct ABDeltaTriple {
}
impl BinaryQF {
+
pub fn binary_quadratic_form_disc(abdelta_triple: &ABDeltaTriple) -> Self {
let a = abdelta_triple.a.clone();
let b = abdelta_triple.b.clone();
@@ -43,10 +51,12 @@ impl BinaryQF {
assert_eq!(delta.mod_floor(&BigInt::from(4)), BigInt::one());
assert!(delta < BigInt::zero()); // in general delta can be positive but we don't deal with that case
let c = (&b.pow(2) - &delta) / (BigInt::from(4) * &a);
+
BinaryQF { a, b, c }
}
- pub fn binary_quadratic_form_principal(delta: &BigInt) -> Self {
+
+pub fn binary_quadratic_form_principal(delta: &BigInt) -> Self {
let one = BigInt::one();
assert_eq!(delta.mod_floor(&BigInt::from(4)), BigInt::one());
assert!(delta < &BigInt::zero()); // in general delta can be positive but we don't deal with that case
@@ -58,19 +68,23 @@ impl BinaryQF {
BinaryQF::binary_quadratic_form_disc(&a_b_delta)
}
- pub fn discriminant(&self) -> BigInt {
+
+pub fn discriminant(&self) -> BigInt {
// for negative delta we compute 4ac - b^2
let abs_delta = BigInt::from(4) * &self.a * &self.c - &self.b * &self.b;
assert!(abs_delta > BigInt::zero());
-abs_delta
}
- pub fn discriminant_sqrt(&self) -> BigInt {
+
+pub fn discriminant_sqrt(&self) -> BigInt {
let disc = self.discriminant();
disc.sqrt()
}
- pub fn is_reduced(&self) -> bool {
+
+
+pub fn is_reduced(&self) -> bool {
if self.is_normal() && self.a <= self.c && !(self.a == self.c && self.b < BigInt::zero()) {
return true;
} else {
@@ -78,7 +92,9 @@ impl BinaryQF {
}
}
- pub fn normalize(&self) -> Self {
+
+
+pub fn normalize(&self) -> Self {
// assume delta<0 and a>0
let a_sub_b: BigInt = &self.a - &self.b;
let s_f = a_sub_b.div_floor(&(BigInt::from(2) * &self.a));
@@ -87,18 +103,20 @@ impl BinaryQF {
b: &self.b + BigInt::from(2) * &s_f * &self.a,
c: &self.a * &s_f.pow(2) + &self.b * &s_f + &self.c,
};
-
binary_qf
}
- pub fn is_normal(&self) -> bool {
+
+pub fn is_normal(&self) -> bool {
if self.b <= self.a && self.b > -self.a.clone() {
return true;
} else {
return false;
}
}
- pub fn primeform(quad_disc: &BigInt, q: &BigInt) -> Self {
+
+
+pub fn primeform(quad_disc: &BigInt, q: &BigInt) -> Self {
let quad_disc_gen = bn_to_gen(&quad_disc);
let q_gen = bn_to_gen(&q);
@@ -108,23 +126,27 @@ impl BinaryQF {
let bqf = BinaryQF::pari_qf_to_qf(pf);
let bqf_norm = bqf.normalize();
+ //f::dump_stdout();
bqf_norm
}
- pub fn compose(&self, qf2: &BinaryQF) -> Self {
+
+pub fn compose(&self, qf2: &BinaryQF) -> Self {
assert_eq!(self.discriminant(), qf2.discriminant());
let qf_pari_a = self.qf_to_pari_qf();
let qf_pari_b = qf2.qf_to_pari_qf();
-
+ flame::start("compose");
let qf_pari_c = unsafe { qfbcompraw(qf_pari_a, qf_pari_b) };
+ flame::end("compose");
let qf_c = BinaryQF::pari_qf_to_qf(qf_pari_c);
-
+
qf_c
}
- pub fn inverse(&self) -> Self {
+
+pub fn inverse(&self) -> Self {
BinaryQF {
a: self.a.clone(),
b: self.b.clone().neg(),
@@ -132,18 +154,20 @@ impl BinaryQF {
}
}
- pub fn rho(&self) -> Self {
+
+pub fn rho(&self) -> Self {
let qf_new = BinaryQF {
a: self.c.clone(),
b: self.b.clone().neg(),
c: self.a.clone(),
};
let h = qf_new.normalize();
-
+ //f::dump_stdout();
h
}
- pub fn reduce(&self) -> Self {
+
+pub fn reduce(&self) -> Self {
let mut h: BinaryQF;
let mut h_new = self.clone();
if !self.is_normal() {
@@ -154,21 +178,33 @@ impl BinaryQF {
let h_new = h.rho();
h = h_new;
}
+
h
}
- pub fn exp(&self, n: &BigInt) -> BinaryQF {
+
+pub fn exp(&self, n: &BigInt) -> BinaryQF {
+ //flame::start("preparing_exp");
let pari_qf = self.qf_to_pari_qf();
let pari_n = bn_to_gen(n);
-
let mut v = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
+ //flame::end("preparing_exp");
+ flame::start("exp_in_function");
+
let pari_qf_exp = unsafe { nupow(pari_qf, pari_n, &mut v) };
+ flame::end("exp_in_function");
+ //flame::start("pari_to_qf");
+
let qf_exp = BinaryQF::pari_qf_to_qf(pari_qf_exp);
+ //flame::end("pari_to_qf");
+
+ ////f::dump_stdout();
qf_exp
}
// gotoNonMax: outputs: f=phi_q^(-1)(F), a binary quadratic form of disc. delta*conductor^2
// f is non normalized
- pub fn phi_q_to_the_minus_1(&self, conductor: &BigInt) -> BinaryQF {
+
+pub fn phi_q_to_the_minus_1(&self, conductor: &BigInt) -> BinaryQF {
let two_a = &self.a * BigInt::from(2);
let b_conductor: BigInt = &self.b * conductor;
let b_new = b_conductor.mod_floor(&two_a);
@@ -181,11 +217,13 @@ impl BinaryQF {
delta,
};
let qf = BinaryQF::binary_quadratic_form_disc(&abdelta);
+ //f::dump_stdout();
qf
}
// compute (p^(2),p,-)^k in class group of disc. delta
- pub fn expo_f(p: &BigInt, delta: &BigInt, k: &BigInt) -> BinaryQF {
+
+pub fn expo_f(p: &BigInt, delta: &BigInt, k: &BigInt) -> BinaryQF {
if k == &BigInt::zero() {
return BinaryQF::binary_quadratic_form_principal(delta);
}
@@ -200,22 +238,26 @@ impl BinaryQF {
delta: delta.clone(),
};
let qf = BinaryQF::binary_quadratic_form_disc(&abdelta);
+ //f::dump_stdout();
qf
}
- pub fn discrete_log_f(p: &BigInt, delta: &BigInt, c: &BinaryQF) -> BigInt {
+
+pub fn discrete_log_f(p: &BigInt, delta: &BigInt, c: &BinaryQF) -> BigInt {
let principal_qf = BinaryQF::binary_quadratic_form_principal(delta);
if c == &principal_qf {
return BigInt::zero();
} else {
let Lk = c.b.div_floor(p);
let Lk_inv = Lk.invert(p).unwrap();
+ //f::dump_stdout();
return Lk_inv;
}
}
//we construct a pari qf from qf
- pub fn qf_to_pari_qf(&self) -> GEN {
+
+pub fn qf_to_pari_qf(&self) -> GEN {
let a = bn_to_gen(&self.a);
let b = bn_to_gen(&self.b);
let c = bn_to_gen(&self.c);
@@ -234,16 +276,17 @@ impl BinaryQF {
let a: BigInt = str::parse(&a_string).unwrap();
let b: BigInt = str::parse(&b_string).unwrap();
let c: BigInt = str::parse(&c_string).unwrap();
-
BinaryQF { a, b, c }
}
- pub fn to_bytes(&self) -> Vec {
+
+pub fn to_bytes(&self) -> Vec {
let mut a_vec = BigInt::to_vec(&self.a);
let b_vec = BigInt::to_vec(&self.b);
let c_vec = BigInt::to_vec(&self.c);
a_vec.extend_from_slice(&b_vec[..]);
a_vec.extend_from_slice(&c_vec[..]);
+ //f::dump_stdout();
a_vec
}
}
@@ -304,6 +347,7 @@ pub fn bn_to_gen(bn: &BigInt) -> GEN {
}
}
+
pub fn pari_qf_comp_to_decimal_string(pari_qf: GEN, index: usize) -> String {
let comp = unsafe { compo(pari_qf, index as i64) };
@@ -311,18 +355,93 @@ pub fn pari_qf_comp_to_decimal_string(pari_qf: GEN, index: usize) -> String {
let c_buf: *const c_char = comp_char_ptr;
let c_str: &CStr = unsafe { CStr::from_ptr(c_buf) };
let comp_str_slice: &str = c_str.to_str().unwrap();
+ //f::dump_stdout();
comp_str_slice.to_string()
}
+#[inline]
+pub fn bench_compose_exp(bits :usize) {
+
+ unsafe {
+ pari_init(20000000, 2);
+ }
+ let mut det: BigInt;
+ let x = BigInt::sample(6000);
+ det = -BigInt::sample(bits);
+ while det.mod_floor(&BigInt::from(4)) != BigInt::one() {
+ det = -BigInt::sample(bits);
+ }
+ let a_b_delta = ABDeltaTriple {
+ a: BigInt::from(2),
+ b: BigInt::from(1),
+ delta: det,
+ };
+ let group = BinaryQF::binary_quadratic_form_disc(&a_b_delta);
+ let g = group.exp(&x).reduce();
+ let gg1 = g.compose(&g).reduce();
+ //let gg2 = g.exp(&BigInt::from(2)).reduce();
+ //assert_eq!(gg1, gg2);
+}
+
+
+pub fn bench_exp_only(bits :usize){
+ unsafe {
+ pari_init(10000000, 2);
+ }
+ // let base: BigInt = BigInt::sample(2048);
+ let base= 2048;
+ let mut det: BigInt;
+ det = -BigInt::sample(base);
+ while det.mod_floor(&BigInt::from(4)) != BigInt::one() {
+ det = -BigInt::sample(base);
+ }
+ let a_b_delta = ABDeltaTriple {
+ a: BigInt::from(2),
+ b: BigInt::from(1),
+ delta: det,
+ };
+ let x: BigInt = BigInt::sample(bits as usize);
+ let group = BinaryQF::binary_quadratic_form_disc(&a_b_delta);
+ let g = group.exp(&x).reduce();
+}
+
+
+pub fn bench_exp_only_for_a_given_det(exp_size:i32){
+ unsafe {
+ pari_init(20000000, 2);
+ }
+ // let x: BigInt = BigInt::sample(6000);
+
+
+ let mut det:BigInt = str::parse("20149392707186525162590355071292053575364559848351567085354700987844093330948936280039379742871107183330808146182415920691586415080574829617024503722195777232804427670557174581127121229242207584973924825787037130000131358603651587961876409377224876056238680407347843315752681629521613772380379341182886747008940959623895895000737071932595957989286658892888724991242968836440986789551081768017186919005412288127429935094766982059615711599441803409172888758437372755538407566562462485676644100997464269306675140005421720998149066720895066941777378563169387978299301916769407006303085854796535778826115224633447713584423").unwrap();
+ //let mut det:BigInt = str::parse("2014939").unwrap();
+
+ // let mut det: BigInt = str::parse("1347310664179468558147371727982960102805371574927252724399119343247182932538452304549609704350360058405827948976558722087559341859252338031258062288910984654814255199874816496621961922792890687089794760104660404141195904459619180668507135317125790028783030121033883873501532619563806411495141846196437").unwrap();
+
+ let a_b_delta = ABDeltaTriple {
+ a: BigInt::from(2),
+ b: BigInt::from(1),
+ delta: -det,
+ };
+ let x: BigInt = BigInt::sample(exp_size as usize);
+ let group = BinaryQF::binary_quadratic_form_disc(&a_b_delta);
+ let g = group.exp(&x).reduce();
+}
+
+
+
#[cfg(test)]
mod tests {
use super::*;
extern crate libc;
use crate::curv::arithmetic::traits::Samplable;
use std::str;
+ use flame;
+
#[test]
fn test_qf_to_pari_qf_to_qf() {
+ flame::start("begin test_qf_to_pari_qf_to_qf");
unsafe {
pari_init(10000000, 2);
}
@@ -335,6 +454,8 @@ mod tests {
let pari_qf = pf.qf_to_pari_qf();
let pf2 = BinaryQF::pari_qf_to_qf(pari_qf);
assert_eq!(pf, pf2);
+ flame::end("begin test_qf_to_pari_qf_to_qf");
+
}
#[test]
@@ -380,7 +501,8 @@ mod tests {
}
#[test]
- fn test_principal_exp() {
+ //
+fn test_principal_exp() {
unsafe {
pari_init(10000000, 2);
}
@@ -395,4 +517,31 @@ mod tests {
let f_exp = f.exp(&x);
assert_eq!(f, f_exp);
}
+
+ #[test]
+ fn test_times(){
+ let bits:usize = 2048;
+ unsafe {
+ pari_init(10000000, 2);
+ }
+ let mut det: BigInt;
+ det = -BigInt::sample(bits);
+ while det.mod_floor(&BigInt::from(4)) != BigInt::one() {
+ det = -BigInt::sample(bits);
+ }
+ let a_b_delta = ABDeltaTriple {
+ a: BigInt::from(2),
+ b: BigInt::from(1),
+ delta: det,
+ };
+ let group = BinaryQF::binary_quadratic_form_disc(&a_b_delta);
+ for exp_size in (1000..7000).step_by(1000) {
+ let x: BigInt = BigInt::sample(exp_size);
+ //let y = flame::span_of("exponentiation", || group.exp(&x).reduce());
+ let y = group.exp(&x);
+ let z = y.reduce();
+ }
+ flame::dump_stdout();
+ }
+
}