From 1c7c2349a3ea9a56aeef3bc238be26a21ea38d88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Garillot?= Date: Thu, 16 Nov 2023 09:45:10 -0500 Subject: [PATCH 1/2] test: Implement hex printing for hash_to_curve tests - Introduced a new test for hashing to the curve and printing the results in hexadecimal representation. - Incorporated 'hex' crate version '0.4' for handling hexadecimal operations. --- Cargo.toml | 2 ++ src/bn256/mod.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index dc0d61dc..eae637a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,8 @@ rand_xorshift = "0.3" ark-std = { version = "0.3" } bincode = "1.3.3" serde_json = "1.0.105" +hex = "0.4" +rand_chacha = "0.3.1" [dependencies] subtle = "2.4" diff --git a/src/bn256/mod.rs b/src/bn256/mod.rs index 3530b765..23609332 100644 --- a/src/bn256/mod.rs +++ b/src/bn256/mod.rs @@ -16,3 +16,43 @@ pub use fq12::*; pub use fq2::*; pub use fq6::*; pub use fr::*; + +#[cfg(test)] +mod test { + use pasta_curves::arithmetic::CurveExt; + use group::GroupEncoding; + use rand_core::{SeedableRng, RngCore}; + use super::G1 as Bn256Point; + + #[test] + fn test_hash_to_curve_print(){ + // the goal of this test is to generate test vectors to ensure that the ASM implementation matches the + // vanilla implementation + let num_vecs = 10; + let expected_results = [ + "e0c5a6834e0329b4f8bdc91144b3e687ac9d810a8e899415267db9cfbf61e91e", + "7052a20bee99cbe054fdd8b2e336db3ed3e9a265229e44ab8197c5eabdef2b0b", + "2f058acc133957074ac79e9b9b1867a0cf3d13df7aa7de7f48e9a6be7d96aa6d", + "b2ff44a25693b811f35e33feb3e99ad9ba0d06425a3ffd5e79cef63d20143314", + "ab2f6d71d2fde51546d8a5782aa9f707e585b84644470f0c876784dbebd30c55", + "6a4e0e30f37a8d1b92b8cf08df3735a36b4937ee455a9dc5f9283a13530db144", + "f1c69be8c5f5f9e28b0e9f76ab77651a7dcaaae371fbba66450cbcee0ed5b16b", + "e86267c2e3355d7a6f664a0ea71374406337d452a3f9a294a0594df53c08df21", + "03cf55ca983ecd8a2e2baae18d979d97d688a978d829701c66a14d7c4da58e62", + "5302c2cfe3c909e9378d08c951bb33d0813818a1baf734379aac8aaa47f38f0d" + ]; + + let mut seeded_rng = rand_chacha::ChaChaRng::seed_from_u64(0u64); + let uniform_bytes = std::iter::from_fn(|| { + let mut bytes = [0u8; 32]; + seeded_rng.fill_bytes(&mut bytes); + Some(bytes) + }).take(num_vecs).collect::>(); + let hash = Bn256Point::hash_to_curve("from_uniform_bytes"); + for i in 0..num_vecs { + let p = hash(&uniform_bytes[i]); + let expected_result = hex::decode(expected_results[i]).unwrap(); + assert_eq!(p.to_bytes().as_ref(), &expected_result[..], "hash_to_curve_print failed, expected: {}, got: {}", expected_results[i], hex::encode(p.to_bytes().as_ref())); + } + } +} \ No newline at end of file From 91f34666c78e3acaf726030be40240041ea1b8de Mon Sep 17 00:00:00 2001 From: David Nevado Date: Tue, 21 Nov 2023 17:23:39 +0100 Subject: [PATCH 2/2] fix: from_u512 --- src/derive/field.rs | 144 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 140 insertions(+), 4 deletions(-) diff --git a/src/derive/field.rs b/src/derive/field.rs index 912a888e..5ec5b9ab 100644 --- a/src/derive/field.rs +++ b/src/derive/field.rs @@ -72,10 +72,146 @@ macro_rules! field_common { // that (2^256 - 1)*c is an acceptable product for the reduction. Therefore, the // reduction always works so long as `c` is in the field; in this case it is either the // constant `R2` or `R3`. - let d0 = $field([limbs[0], limbs[1], limbs[2], limbs[3]]); - let d1 = $field([limbs[4], limbs[5], limbs[6], limbs[7]]); - // Convert to Montgomery form - d0 * $r2 + d1 * $r3 + + #[cfg(not(feature = "asm"))] + { + let d0 = $field([limbs[0], limbs[1], limbs[2], limbs[3]]); + let d1 = $field([limbs[4], limbs[5], limbs[6], limbs[7]]); + // Convert to Montgomery form + d0 * $r2 + d1 * $r3 + } + + #[cfg(feature = "asm")] + { + let v0 = { + let (r0, carry) = mac(0, limbs[0], $r2.0[0], 0); + let (r1, carry) = mac(0, limbs[0], $r2.0[1], carry); + let (r2, carry) = mac(0, limbs[0], $r2.0[2], carry); + let (r3, r4) = mac(0, limbs[0], $r2.0[3], carry); + + let (r1, carry) = mac(r1, limbs[1], $r2.0[0], 0); + let (r2, carry) = mac(r2, limbs[1], $r2.0[1], carry); + let (r3, carry) = mac(r3, limbs[1], $r2.0[2], carry); + let (r4, r5) = mac(r4, limbs[1], $r2.0[3], carry); + + let (r2, carry) = mac(r2, limbs[2], $r2.0[0], 0); + let (r3, carry) = mac(r3, limbs[2], $r2.0[1], carry); + let (r4, carry) = mac(r4, limbs[2], $r2.0[2], carry); + let (r5, r6) = mac(r5, limbs[2], $r2.0[3], carry); + + let (r3, carry) = mac(r3, limbs[3], $r2.0[0], 0); + let (r4, carry) = mac(r4, limbs[3], $r2.0[1], carry); + let (r5, carry) = mac(r5, limbs[3], $r2.0[2], carry); + let (r6, r7) = mac(r6, limbs[3], $r2.0[3], carry); + + // Montgomery reduction + let k = r0.wrapping_mul($inv); + let (_, carry) = mac(r0, k, $modulus.0[0], 0); + let (r1, carry) = mac(r1, k, $modulus.0[1], carry); + let (r2, carry) = mac(r2, k, $modulus.0[2], carry); + let (r3, carry) = mac(r3, k, $modulus.0[3], carry); + let (r4, carry2) = adc(r4, 0, carry); + + let k = r1.wrapping_mul($inv); + let (_, carry) = mac(r1, k, $modulus.0[0], 0); + let (r2, carry) = mac(r2, k, $modulus.0[1], carry); + let (r3, carry) = mac(r3, k, $modulus.0[2], carry); + let (r4, carry) = mac(r4, k, $modulus.0[3], carry); + let (r5, carry2) = adc(r5, carry2, carry); + + let k = r2.wrapping_mul($inv); + let (_, carry) = mac(r2, k, $modulus.0[0], 0); + let (r3, carry) = mac(r3, k, $modulus.0[1], carry); + let (r4, carry) = mac(r4, k, $modulus.0[2], carry); + let (r5, carry) = mac(r5, k, $modulus.0[3], carry); + let (r6, carry2) = adc(r6, carry2, carry); + + let k = r3.wrapping_mul($inv); + let (_, carry) = mac(r3, k, $modulus.0[0], 0); + let (r4, carry) = mac(r4, k, $modulus.0[1], carry); + let (r5, carry) = mac(r5, k, $modulus.0[2], carry); + let (r6, carry) = mac(r6, k, $modulus.0[3], carry); + let (r7, carry2) = adc(r7, carry2, carry); + + // Result may be within MODULUS of the correct limbsue + let (d0, borrow) = sbb(r4, $modulus.0[0], 0); + let (d1, borrow) = sbb(r5, $modulus.0[1], borrow); + let (d2, borrow) = sbb(r6, $modulus.0[2], borrow); + let (d3, borrow) = sbb(r7, $modulus.0[3], borrow); + let (_, borrow) = sbb(carry2, 0, borrow); + let (d0, carry) = adc(d0, $modulus.0[0] & borrow, 0); + let (d1, carry) = adc(d1, $modulus.0[1] & borrow, carry); + let (d2, carry) = adc(d2, $modulus.0[2] & borrow, carry); + let (d3, _) = adc(d3, $modulus.0[3] & borrow, carry); + + $field([d0, d1, d2, d3]) + }; + + let v1 = { + let (r0, carry) = mac(0, limbs[4], $r3.0[0], 0); + let (r1, carry) = mac(0, limbs[4], $r3.0[1], carry); + let (r2, carry) = mac(0, limbs[4], $r3.0[2], carry); + let (r3, r4) = mac(0, limbs[4], $r3.0[3], carry); + + let (r1, carry) = mac(r1, limbs[5], $r3.0[0], 0); + let (r2, carry) = mac(r2, limbs[5], $r3.0[1], carry); + let (r3, carry) = mac(r3, limbs[5], $r3.0[2], carry); + let (r4, r5) = mac(r4, limbs[5], $r3.0[3], carry); + + let (r2, carry) = mac(r2, limbs[6], $r3.0[0], 0); + let (r3, carry) = mac(r3, limbs[6], $r3.0[1], carry); + let (r4, carry) = mac(r4, limbs[6], $r3.0[2], carry); + let (r5, r6) = mac(r5, limbs[6], $r3.0[3], carry); + + let (r3, carry) = mac(r3, limbs[7], $r3.0[0], 0); + let (r4, carry) = mac(r4, limbs[7], $r3.0[1], carry); + let (r5, carry) = mac(r5, limbs[7], $r3.0[2], carry); + let (r6, r7) = mac(r6, limbs[7], $r3.0[3], carry); + + // Montgomery reduction + let k = r0.wrapping_mul($inv); + let (_, carry) = mac(r0, k, $modulus.0[0], 0); + let (r1, carry) = mac(r1, k, $modulus.0[1], carry); + let (r2, carry) = mac(r2, k, $modulus.0[2], carry); + let (r3, carry) = mac(r3, k, $modulus.0[3], carry); + let (r4, carry2) = adc(r4, 0, carry); + + let k = r1.wrapping_mul($inv); + let (_, carry) = mac(r1, k, $modulus.0[0], 0); + let (r2, carry) = mac(r2, k, $modulus.0[1], carry); + let (r3, carry) = mac(r3, k, $modulus.0[2], carry); + let (r4, carry) = mac(r4, k, $modulus.0[3], carry); + let (r5, carry2) = adc(r5, carry2, carry); + + let k = r2.wrapping_mul($inv); + let (_, carry) = mac(r2, k, $modulus.0[0], 0); + let (r3, carry) = mac(r3, k, $modulus.0[1], carry); + let (r4, carry) = mac(r4, k, $modulus.0[2], carry); + let (r5, carry) = mac(r5, k, $modulus.0[3], carry); + let (r6, carry2) = adc(r6, carry2, carry); + + let k = r3.wrapping_mul($inv); + let (_, carry) = mac(r3, k, $modulus.0[0], 0); + let (r4, carry) = mac(r4, k, $modulus.0[1], carry); + let (r5, carry) = mac(r5, k, $modulus.0[2], carry); + let (r6, carry) = mac(r6, k, $modulus.0[3], carry); + let (r7, carry2) = adc(r7, carry2, carry); + + // Result may be within MODULUS of the correct limbsue + let (d0, borrow) = sbb(r4, $modulus.0[0], 0); + let (d1, borrow) = sbb(r5, $modulus.0[1], borrow); + let (d2, borrow) = sbb(r6, $modulus.0[2], borrow); + let (d3, borrow) = sbb(r7, $modulus.0[3], borrow); + let (_, borrow) = sbb(carry2, 0, borrow); + let (d0, carry) = adc(d0, $modulus.0[0] & borrow, 0); + let (d1, carry) = adc(d1, $modulus.0[1] & borrow, carry); + let (d2, carry) = adc(d2, $modulus.0[2] & borrow, carry); + let (d3, _) = adc(d3, $modulus.0[3] & borrow, carry); + + $field([d0, d1, d2, d3]) + }; + v0 + v1 + } } /// Converts from an integer represented in little endian