From ed7b345179820a34d914b1860907aaf866d24630 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 27 Jun 2022 14:39:30 -0600 Subject: [PATCH 001/160] 1: Addition BigUint - Added datatype BigUint: vector of u32 limbs - Implements addition for BigUint - Tests for addition in main.sw (this is a script) --- bignum-lib/.gitignore | 4 ++ bignum-lib/Cargo.toml | 16 ++++++++ bignum-lib/Forc.toml | 7 ++++ bignum-lib/src/big_uint.sw | 64 +++++++++++++++++++++++++++++ bignum-lib/src/helpers.sw | 10 +++++ bignum-lib/src/main.sw | 82 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 183 insertions(+) create mode 100644 bignum-lib/.gitignore create mode 100644 bignum-lib/Cargo.toml create mode 100644 bignum-lib/Forc.toml create mode 100644 bignum-lib/src/big_uint.sw create mode 100644 bignum-lib/src/helpers.sw create mode 100644 bignum-lib/src/main.sw diff --git a/bignum-lib/.gitignore b/bignum-lib/.gitignore new file mode 100644 index 0000000..d8d39c0 --- /dev/null +++ b/bignum-lib/.gitignore @@ -0,0 +1,4 @@ +out +target +Forc.lock +Cargo.lock \ No newline at end of file diff --git a/bignum-lib/Cargo.toml b/bignum-lib/Cargo.toml new file mode 100644 index 0000000..1280bcb --- /dev/null +++ b/bignum-lib/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "bignum-lib" +version = "0.1.0" +authors = ["HashCloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/bignum-lib/Forc.toml b/bignum-lib/Forc.toml new file mode 100644 index 0000000..6ca19ba --- /dev/null +++ b/bignum-lib/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["HashCloak"] +entry = "main.sw" +license = "Apache-2.0" +name = "bignum-lib" + +[dependencies] diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw new file mode 100644 index 0000000..ef24fed --- /dev/null +++ b/bignum-lib/src/big_uint.sw @@ -0,0 +1,64 @@ +library big_uint; + +dep helpers; +use helpers::*; + +use std::{assert::assert, option::*, vec::Vec}; +use std::logging::log; +use core::num::*; + +/* +Representation of a big unsigned number of arbitrary length + +Note: The largest primitive type in Sway is u64, therefore the BigUint consists of a vector with u32 entries. +When 2 BigUints are added, the result might require more than 32 bits and this will fit into a u64. +*/ +pub struct BigUint { + data: Vec, +} + +fn max(left: u64, right: u64) -> u64 { + if(left >= right) { left } else { right } +} + +/* +returns the result of the 3 numbers added together +*/ +fn add_limb(a_i: u32, b_i: u32, carry_i: u32) -> u64 { + let A_i: u64 = a_i; + let B_i: u64 = b_i; + + A_i + B_i + carry_i +} + +/* +returns the 2 bigUints added together. + +Note: This result might be 1 longer than the longest entry. +*/ +pub fn add(a: BigUint, b: BigUint) -> BigUint { + let a_vec: Vec = a.data; + let b_vec: Vec = b.data; + let len_a :u32 = a_vec.len(); + let len_b :u32 = b_vec.len(); + let max_len: u32 = max(len_a, len_b); + + let mut res: Vec = ~Vec::new::(); + let mut i = 0; + let mut carry_i: u32 = 0; + let mut z: u64 = 0; + + while i < max_len { + z = add_limb(unpack_or_0(a_vec.get(i)), unpack_or_0(b_vec.get(i)), carry_i); + + res.push(z & 0xffffffff); + carry_i = ((z>>32) & 0xffffffff); + i = i + 1; + } + + if carry_i != 0 { + res.push(carry_i); + } + + BigUint{data: res} +} \ No newline at end of file diff --git a/bignum-lib/src/helpers.sw b/bignum-lib/src/helpers.sw new file mode 100644 index 0000000..8a92abb --- /dev/null +++ b/bignum-lib/src/helpers.sw @@ -0,0 +1,10 @@ +library helpers; + +use std::option::*; + +pub fn unpack_or_0 (x: Option) -> u32 { + match x { + Option::Some(val) => val , + Option::None => 0, + } +} \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw new file mode 100644 index 0000000..62520e8 --- /dev/null +++ b/bignum-lib/src/main.sw @@ -0,0 +1,82 @@ +script; + +dep big_uint; +dep helpers; + +use ::big_uint::*; +use ::helpers::*; + +use std::{vec::Vec, option::*, assert::assert, math::*}; +use std::logging::log; +use core::num::*; + +fn main() { + assert(addition_tests_big_uint()); +} + +fn addition_tests_big_uint() -> bool { + assert(big_uint_addition()); + assert(big_uint_addition_longer_res()); + true +} + +/* +Adding 2 bignums together that should result into a result that is +9 + 3 * 2^32 + 2^64 +Which translates into the vector (9, 3, 1) +*/ +fn big_uint_addition() -> bool { + // [4294967295, 1] + // = 2^32 + 4294967295 + let mut a_data: Vec = ~Vec::new::(); + a_data.push(~u32::max()); + a_data.push(1); + let a = BigUint{data: a_data}; + + // [10, 1, 1] + // = 2^64 + 2^32 + 10 + let mut b_data: Vec = ~Vec::new::(); + b_data.push(10); + b_data.push(1); + b_data.push(1); + let b = BigUint{data: b_data}; + + // total = 18446744086594453513 + // [9, 3 , 1] = 9 + 3 * 2^32 + 2^64 + let res_bigint = add(a, b); + let res: Vec = res_bigint.data; + + assert(unpack_or_0(res.get(0)) == 9); + assert(unpack_or_0(res.get(1)) == 3); + assert(unpack_or_0(res.get(2)) == 1); + assert(res.get(3).is_none()); + + true +} + +/* +Test bigUint addition where the result has 1 more entry in the vector than the inputs +Inputs have len 1, output len 2 +*/ +fn big_uint_addition_longer_res() -> bool { + // [4294967295] = 2^32 -1 + let mut a_data: Vec = ~Vec::new::(); + a_data.push(~u32::max()); + let a = BigUint{data: a_data}; + + // [8] + let mut b_data: Vec = ~Vec::new::(); + b_data.push(8); + let b = BigUint{data: b_data}; + + // total = 2 ^ 32 + 7 + // [7, 1] + let res_bigint = add(a, b); + let res: Vec = res_bigint.data; + + assert(unpack_or_0(res.get(0)) == 7); + assert(unpack_or_0(res.get(1)) == 1); + assert(res.get(2).is_none()); + + true +} \ No newline at end of file From e0e77332ffd02b956f937e79852333c03b9a2fdd Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 27 Jun 2022 19:09:05 -0600 Subject: [PATCH 002/160] 2: Subtraction BigUint - Added subtraction for biguint - With tests - Introduced trait Zero, so we can check for "zero-being" - Added tests for addition and structured them --- bignum-lib/src/big_uint.sw | 101 ++++++++++++++++++ bignum-lib/src/helpers.sw | 4 + bignum-lib/src/main.sw | 208 +++++++++++++++++++++++++++++++++++-- 3 files changed, 307 insertions(+), 6 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index ef24fed..2a29adc 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -17,6 +17,14 @@ pub struct BigUint { data: Vec, } +impl Zero for BigUint { + fn is_zero(self) -> bool { + return self.data.len() == 0; + } +} + +// TODO BigUint zero toevoegen + fn max(left: u64, right: u64) -> u64 { if(left >= right) { left } else { right } } @@ -61,4 +69,97 @@ pub fn add(a: BigUint, b: BigUint) -> BigUint { } BigUint{data: res} +} + + +/* +returns whether the value that a represents is larger than b +*/ +fn is_bigger_or_equal(a: BigUint, b: BigUint) -> bool { + if a.data.len() > b.data.len() { + return true; + } else if a.data.len() == b.data.len() { + let mut i = a.data.len() - 1; + let mut a_is_bigger_or_equal = true; + let mut looping = true; + while i > 0 && looping { + let a_val = unpack_or_0(a.data.get(i)); + let b_val = unpack_or_0(b.data.get(i)); + if a_val > b_val { + looping = false; // we know a is bigger + } else if a_val < b_val { + a_is_bigger_or_equal = false; + looping = false; // we know b is bigger + } + // If we're not sure yet; keep looping + i = i - 1; + } + return a_is_bigger_or_equal; + } else { + return false; + } +} + +/* +returns (res_i, borrow_i); the result and the possible borrow of a_i - b_i - borrow_i +*/ +fn sub_limb(a_i: u32, b_i: u32, borrow_i: u32) -> (u32, u32) { + if (b_i + borrow_i) > a_i { + (~u32::max() - ((b_i + borrow_i) - a_i), 1) + } else { + (a_i - b_i - borrow_i, 0u32) + } +} + +/* +return Some(BigUint) if a >= b, otherwise None +*/ +pub fn sub(a: BigUint, b: BigUint) -> Option { + if is_bigger_or_equal(a, b) { + let a_vec: Vec = a.data; + let b_vec: Vec = b.data; + let len_a: u32 = a_vec.len(); + + // The resulting vector will be filled in the opposite order + // For the final result this is reversed and the leading zeroes will be disregarded + let mut res: Vec = ~Vec::new::(); + let mut i = 0; + let mut borrow_i: u32 = 0; + let mut x: u32 = 0; + + while i < len_a { + let sub_limb_res = sub_limb(unpack_or_0(a_vec.get(i)), unpack_or_0(b_vec.get(i)), borrow_i); + x = sub_limb_res.0; + borrow_i = sub_limb_res.1; + res.push(x); + i = i + 1; + } + + // Return the result without trailing zeroes + // Vectors are not yet mutable, so we create a new one and fill it up until possible trailing zeroes + let mut most_significant_bit_index = len_a - 1; + let mut index_found = false; + while !index_found && most_significant_bit_index > 0 { + if (unpack_or_0(res.get(most_significant_bit_index)) != 0) { + index_found = true; + } else { + most_significant_bit_index = most_significant_bit_index - 1; + } + } + + let mut normalized_res: Vec = ~Vec::new::(); + let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(res.get(0) )== 0; + if(!res_is_zero) { + let mut j = 0; + while j <= most_significant_bit_index { + normalized_res.push(unpack_or_0(res.get(j))); + j = j + 1; + } + + } + + return Option::Some(BigUint{data: normalized_res}); + } else { + return Option::None::(); + } } \ No newline at end of file diff --git a/bignum-lib/src/helpers.sw b/bignum-lib/src/helpers.sw index 8a92abb..e667788 100644 --- a/bignum-lib/src/helpers.sw +++ b/bignum-lib/src/helpers.sw @@ -7,4 +7,8 @@ pub fn unpack_or_0 (x: Option) -> u32 { Option::Some(val) => val , Option::None => 0, } +} + +pub trait Zero { + fn is_zero(self) -> bool; } \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index 62520e8..4761820 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -10,13 +10,21 @@ use std::{vec::Vec, option::*, assert::assert, math::*}; use std::logging::log; use core::num::*; +/* +All tests for bignum lib +*/ fn main() { - assert(addition_tests_big_uint()); + assert(biguint_addition_tests()); + assert(biguint_subtraction_tests()); } -fn addition_tests_big_uint() -> bool { - assert(big_uint_addition()); - assert(big_uint_addition_longer_res()); +// ADDITION BIGUINT +fn biguint_addition_tests() -> bool { + assert(biguint_addition()); + assert(biguint_addition_longer_res()); + assert(biguint_addition_with_zero()); + assert(biguint_addition_to_zero()); + assert(biguint_addition_zeros()); true } @@ -25,7 +33,7 @@ Adding 2 bignums together that should result into a result that is 9 + 3 * 2^32 + 2^64 Which translates into the vector (9, 3, 1) */ -fn big_uint_addition() -> bool { +fn biguint_addition() -> bool { // [4294967295, 1] // = 2^32 + 4294967295 let mut a_data: Vec = ~Vec::new::(); @@ -58,7 +66,7 @@ fn big_uint_addition() -> bool { Test bigUint addition where the result has 1 more entry in the vector than the inputs Inputs have len 1, output len 2 */ -fn big_uint_addition_longer_res() -> bool { +fn biguint_addition_longer_res() -> bool { // [4294967295] = 2^32 -1 let mut a_data: Vec = ~Vec::new::(); a_data.push(~u32::max()); @@ -78,5 +86,193 @@ fn big_uint_addition_longer_res() -> bool { assert(unpack_or_0(res.get(1)) == 1); assert(res.get(2).is_none()); + true +} + +/* +1 + 0 = 1 +*/ +fn biguint_addition_with_zero() -> bool { + // a = 1 =[1] + let mut a_data: Vec = ~Vec::new::(); + a_data.push(1); + let a = BigUint{data: a_data}; + + // b = 0 + let mut b_data: Vec = ~Vec::new::(); + let b = BigUint{data: b_data}; + + // total = 1 + let res_bigint = add(a, b); + let res: Vec = res_bigint.data; + + assert(unpack_or_0(res.get(0)) == 1); + assert(res.get(1).is_none()); + + true +} + +/* +[0] + [4, 1] = [4,1] +*/ +fn biguint_addition_to_zero() -> bool { + // a = 0 + let mut a_data: Vec = ~Vec::new::(); + let a = BigUint{data: a_data}; + + // b = [4,1] + let mut b_data: Vec = ~Vec::new::(); + b_data.push(4); + b_data.push(1); + let b = BigUint{data: b_data}; + + // total = [4,1] + let res_bigint = add(a, b); + let res: Vec = res_bigint.data; + + assert(unpack_or_0(res.get(0)) == 4); + assert(unpack_or_0(res.get(1)) == 1); + assert(res.get(2).is_none()); + + true +} + +fn biguint_addition_zeros() -> bool { + // a = 0 + let mut a_data: Vec = ~Vec::new::(); + let a = BigUint{data: a_data}; + + // b = 0 + let mut b_data: Vec = ~Vec::new::(); + let b = BigUint{data: b_data}; + + // total = 0 + let res_bigint = add(a, b); + + assert(res_bigint.is_zero()); + + true +} + +// SUBTRACTION BIGUINT +fn biguint_subtraction_tests() -> bool { + assert(biguint_subtraction_result_none()); + + assert(biguint_subtraction_from_0()); + assert(biguint_subtraction_to_0()); + + assert(biguint_subtraction_res_same_len()); + assert(biguint_subtraction_shorter_len()); + true +} + +/* +when the first value is smaller than the second, result is None +[200, 10] - [100, 12] +*/ +fn biguint_subtraction_result_none() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(200); + a_data.push(10); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(100); + b_data.push(12); + let b = BigUint{data: b_data}; + + let res_bigint = sub(a, b); + + assert(res_bigint.is_none()); + + true +} + +/* +[] - [1] should return None +*/ +fn biguint_subtraction_from_0() -> bool { + let mut a_data: Vec = ~Vec::new::(); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(1); + let b = BigUint{data: b_data}; + + let res_bigint = sub(a, b); + + assert(res_bigint.is_none()); + + true +} + +/* +[1]-[1] should return the BigUint that is zero ([]) +*/ +fn biguint_subtraction_to_0() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(1); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(1); + let b = BigUint{data: b_data}; + + let res_bigint = sub(a, b); + + assert(res_bigint.is_some()); + assert(res_bigint.unwrap().is_zero()); + + true +} + +/* +[3,4,8] - [5,0,5] has a resulting vector of the same length: +[2^32 - 2, 3, 3] +*/ +fn biguint_subtraction_res_same_len() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(3); + a_data.push(4); + a_data.push(8); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(5); + b_data.push(0); + b_data.push(5); + let b = BigUint{data: b_data}; + + let res_bigint = sub(a, b); + let res_vec = res_bigint.unwrap().data; + + assert(unpack_or_0(res_vec.get(0)) == ~u32::max() - 2); + assert(unpack_or_0(res_vec.get(1)) == 3); + assert(unpack_or_0(res_vec.get(2)) == 3); + + true +} + +/* +when result of subtraction has trailing zeroes, we return a shorter result vector +[20, 15] - [2, 15] = [18, 0] = [18] +*/ +fn biguint_subtraction_shorter_len() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(20); + a_data.push(15); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(2); + b_data.push(15); + let b = BigUint{data: b_data}; + + let res_bigint = sub(a, b); + let res_vec = res_bigint.unwrap().data; + + assert(unpack_or_0(res_vec.get(0)) == 18); + assert(res_vec.get(1).is_none()); + true } \ No newline at end of file From ee0fc8a1d584b08cd059f12b965d6a090de58ed9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 27 Jun 2022 19:12:44 -0600 Subject: [PATCH 003/160] Removed old TODO --- bignum-lib/src/big_uint.sw | 2 -- 1 file changed, 2 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index 2a29adc..d078cc1 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -23,8 +23,6 @@ impl Zero for BigUint { } } -// TODO BigUint zero toevoegen - fn max(left: u64, right: u64) -> u64 { if(left >= right) { left } else { right } } From 1b367c493a0b1764e58314ad15dbc90099c92379 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 28 Jun 2022 09:05:28 -0600 Subject: [PATCH 004/160] Fix PR comment: make sure the edge case of 2 elements of length 1 for subtraction is covered. - i >= 0 instead of i > 0 - test added for 2 elements of len 1 - added code for edge case 0 - 0 = 0 - test added for 0 - 0 = 0 --- bignum-lib/src/big_uint.sw | 21 ++++++++++++------ bignum-lib/src/main.sw | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 6 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index d078cc1..6e458a3 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -77,10 +77,13 @@ fn is_bigger_or_equal(a: BigUint, b: BigUint) -> bool { if a.data.len() > b.data.len() { return true; } else if a.data.len() == b.data.len() { + if a.data.len() == 0 { + return true; + } let mut i = a.data.len() - 1; let mut a_is_bigger_or_equal = true; let mut looping = true; - while i > 0 && looping { + while i >= 0 && looping { let a_val = unpack_or_0(a.data.get(i)); let b_val = unpack_or_0(b.data.get(i)); if a_val > b_val { @@ -88,9 +91,12 @@ fn is_bigger_or_equal(a: BigUint, b: BigUint) -> bool { } else if a_val < b_val { a_is_bigger_or_equal = false; looping = false; // we know b is bigger + } else if a_val == b_val && i == 0 { + looping = false; // we have seen all elements and a & b are equal + } else { + // If we're not sure yet and the index is not yet 0; keep looping + i = i - 1; } - // If we're not sure yet; keep looping - i = i - 1; } return a_is_bigger_or_equal; } else { @@ -113,13 +119,16 @@ fn sub_limb(a_i: u32, b_i: u32, borrow_i: u32) -> (u32, u32) { return Some(BigUint) if a >= b, otherwise None */ pub fn sub(a: BigUint, b: BigUint) -> Option { + // Special case 0 - 0 = 0 + if(a.data.len() == 0 && b.data.len() == 0) { + return Option::Some(BigUint{data: ~Vec::new::()}); + } + if is_bigger_or_equal(a, b) { let a_vec: Vec = a.data; let b_vec: Vec = b.data; let len_a: u32 = a_vec.len(); - // The resulting vector will be filled in the opposite order - // For the final result this is reversed and the leading zeroes will be disregarded let mut res: Vec = ~Vec::new::(); let mut i = 0; let mut borrow_i: u32 = 0; @@ -146,7 +155,7 @@ pub fn sub(a: BigUint, b: BigUint) -> Option { } let mut normalized_res: Vec = ~Vec::new::(); - let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(res.get(0) )== 0; + let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(res.get(0)) == 0; if(!res_is_zero) { let mut j = 0; while j <= most_significant_bit_index { diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index 4761820..c9d78fb 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -157,12 +157,15 @@ fn biguint_addition_zeros() -> bool { // SUBTRACTION BIGUINT fn biguint_subtraction_tests() -> bool { assert(biguint_subtraction_result_none()); + assert(big_uint_subtraction_result_none_2()); assert(biguint_subtraction_from_0()); assert(biguint_subtraction_to_0()); + assert(biguint_subtraction_zeros()); assert(biguint_subtraction_res_same_len()); assert(biguint_subtraction_shorter_len()); + true } @@ -188,6 +191,26 @@ fn biguint_subtraction_result_none() -> bool { true } +/* +This should also work for length 1 +[6] - [8] should give None +*/ +fn big_uint_subtraction_result_none_2() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(6); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(8); + let b = BigUint{data: b_data}; + + let res_bigint = sub(a, b); + + assert(res_bigint.is_none()); + + true +} + /* [] - [1] should return None */ @@ -274,5 +297,26 @@ fn biguint_subtraction_shorter_len() -> bool { assert(unpack_or_0(res_vec.get(0)) == 18); assert(res_vec.get(1).is_none()); + true +} + +/* +0 - 0 = 0 +*/ +fn biguint_subtraction_zeros() -> bool { + // a = 0 + let mut a_data: Vec = ~Vec::new::(); + let a = BigUint{data: a_data}; + + // b = 0 + let mut b_data: Vec = ~Vec::new::(); + let b = BigUint{data: b_data}; + + // total = 0 + let res_bigint = sub(a, b); + + assert(res_bigint.is_some()); + assert(res_bigint.unwrap().is_zero()); + true } \ No newline at end of file From c081e2cccd27d74a43788edfbc8d66f8cac2bc9a Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 28 Jun 2022 18:07:38 -0600 Subject: [PATCH 005/160] Prep for 3: Karatsuba multiplication. - Added the schoolbook mult from the swayPractice repo that works for 2 tests (not extensively tested though) - Added data that can be used for a test case, with the values that would be used in the first iteration of Karatsuba --- bignum-lib/src/big_uint.sw | 56 ++++++++++++++- bignum-lib/src/main.sw | 143 ++++++++++++++++++++++++++++++++++++- 2 files changed, 197 insertions(+), 2 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index 6e458a3..1aa754f 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -169,4 +169,58 @@ pub fn sub(a: BigUint, b: BigUint) -> Option { } else { return Option::None::(); } -} \ No newline at end of file +} + +/* +Not optimized +*/ +pub fn schoolbook_mult(a: BigUint, b: BigUint) -> BigUint { + let a_vec: Vec = a.data; + let b_vec: Vec = b.data; + let a_len = a_vec.len(); + let b_len = b_vec.len(); + + let mut res_vec: Vec = ~Vec::new::(); + + let mut i = 0; + let mut k = 0; + let mut prod_coeff: u64 = 0; + let mut prod_carry: u64 = 0; + let mut temp: u64 = 0; + let base: u64 = 0x100000000; + let mut temp = 0u64; + + while k <= (b_len + a_len) { + prod_coeff = prod_carry; + prod_carry = 0; + while i <= k { + temp = unpack_or_0(a_vec.get(i)) * unpack_or_0(b_vec.get(k-i)); + if temp >= base { + prod_carry += ((temp >> 32) & 0xffffffff); + temp = (temp & 0xffffffff); + } + prod_coeff = prod_coeff + temp; + if prod_coeff >= base { + prod_carry += ((prod_coeff >> 32) & 0xffffffff); + prod_coeff = (prod_coeff & 0xffffffff); + } + i += 1; + } + res_vec.push(prod_coeff); + i = 0; + k += 1; + } + + BigUint{ data: res_vec} +} + +//https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ +/* +pub fn karatsuba_mult(a: BigUint, b: BigUint) -> BigUint { + if(a.data.len() == 1 || b.data.len() == 1) { + // in this case it's not worth it? + } + + let n = max(a.data.len(), b.data.len()); +} +*/ \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index c9d78fb..a84583e 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -16,6 +16,7 @@ All tests for bignum lib fn main() { assert(biguint_addition_tests()); assert(biguint_subtraction_tests()); + assert(biguint_mult_tests()); } // ADDITION BIGUINT @@ -319,4 +320,144 @@ fn biguint_subtraction_zeros() -> bool { assert(res_bigint.unwrap().is_zero()); true -} \ No newline at end of file +} + +fn biguint_mult_tests() -> bool { + assert(biguint_schoolbook_mult()); + assert(test_from_swayPractice_repo()); + true +} + +/* +Example input & output for Karatsuba with BigUint + +X = (1+2*2^32 + 3*2^64 + 4*2^96) = [1,2,3,4] +Y = (100+200*2^32 + 300*2^64 + 400*2^96) = [100,200,300,400] +When calculating X*Y +The result = 10043362780126293152582135998281912347988259896158629291622500 + +This is written in base 2^32 as follows: +29514790528243204098500 * 2^128 + 2000 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 +And therefore translates to data vector +[100, 400, 1000, 2000, 29514790528243204098500] + +—— + +Applying Karatsuba would work as follows + +Ac = (3+4*2^32) * (300+400*2^32) += 29514790528243204096900 +Bd = (1+2*2^32)*(100+200*2^32) += 7378697631201807564900 +Ad+bc = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - ac - bd += ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - (3+4*2^32) * (300+400*2^32) - (1+2*2^32)*(100+200*2^32) +=29514790526525217178200 + +Then, take as result +Ac * 2^128 + (ad+bc) * 2^64 + Bd + +Check that this is correct: + = 29514790528243204096900 * 2^128 + 29514790526525217178200 * 2^64 + 7378697631201807564900 + = 10043362780126293152582135998281912347988259896158629291622500 + +*/ + +//TODO make this test run with schoolbook, so this example can be used for Karatsuba mult +fn biguint_schoolbook_mult() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(1); + a_data.push(2); + a_data.push(3); + a_data.push(4); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(100); + b_data.push(200); + b_data.push(300); + b_data.push(400); + let b = BigUint{data: b_data}; + + // let res_bigint = schoolbook_mult(a, b); + + // log(res_bigint.data.len()); + + true +} + +fn test_from_swayPractice_repo() -> bool { +// [2^32 - 1, 2^16] = (2^32 - 1) + 2^16 * 2^32 + let mut a_data: Vec = ~Vec::new::(); + a_data.push(4294967295); + a_data.push(65536); + let a = BigUint{data: a_data}; + +// [2^32-1, 2^18, 2^30] = (2^32 - 1) + 2^18 * 2^32 + 2^30 * 2^64 + let mut b_data: Vec = ~Vec::new::(); + b_data.push(4294967295); + b_data.push(262144); + b_data.push(1073741824); + let b = BigUint{data: b_data}; + + let res_bigint = schoolbook_mult(a, b); + let res = res_bigint.data; + + //res = ((2^32 - 1) + 2^16 * 2^32) * ((2^32 - 1) + 2^18 * 2^32 + 2^30 * 2^64) + // = 5575271370224683131653871446489760217956353 + // 16384 * 2^128 + 1073741827 * 2^96 + 3221553152 * 2^64 + 4294639614 * 2^32 + 1 + // [1, 4294639614, 3221553152, 1073741827, 16384] + match res.get(0) { + Option::Some(r0) =>{ + assert(r0 == 1); + }, + Option::None => { + log(1000000000); + }, + } + + match res.get(1) { + Option::Some(r1) =>{ + assert(r1 == 4294639614); + }, + Option::None => { + log(1000000000); + }, + } + + match res.get(2) { + Option::Some(r2) =>{ + assert(r2 == 3221553152); + }, + Option::None => { + log(1000000000); + }, + } + + match res.get(3) { + Option::Some(r3) =>{ + assert(r3 == 1073741827); + }, + Option::None => { + log(1000000000); + }, + } + + match res.get(4) { + Option::Some(r4) =>{ + assert(r4 == 16384); + }, + Option::None => { + log(1000000000); + }, + } + + match res.get(5) { + Option::Some(r5) =>{ + assert(r5 == 0); + }, + Option::None => { + log(1000000000); + }, + } + true +} From e08ec14bf599b4fddf30c0f289a9be5b80bdcb6d Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 29 Jun 2022 16:14:45 -0600 Subject: [PATCH 006/160] Larger test works now, which can be used for a small Karatsuba example. --- bignum-lib/src/main.sw | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index a84583e..b742483 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -337,10 +337,9 @@ When calculating X*Y The result = 10043362780126293152582135998281912347988259896158629291622500 This is written in base 2^32 as follows: -29514790528243204098500 * 2^128 + 2000 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 +1600 * 2^192 + 2400 * 2^160 + 2500 * 2^128 + 2000 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 And therefore translates to data vector -[100, 400, 1000, 2000, 29514790528243204098500] - +[100, 400, 1000, 2000, 2500, 2400, 1600] —— Applying Karatsuba would work as follows @@ -361,8 +360,6 @@ Check that this is correct: = 10043362780126293152582135998281912347988259896158629291622500 */ - -//TODO make this test run with schoolbook, so this example can be used for Karatsuba mult fn biguint_schoolbook_mult() -> bool { let mut a_data: Vec = ~Vec::new::(); a_data.push(1); @@ -378,9 +375,16 @@ fn biguint_schoolbook_mult() -> bool { b_data.push(400); let b = BigUint{data: b_data}; - // let res_bigint = schoolbook_mult(a, b); - - // log(res_bigint.data.len()); + let res_bigint = schoolbook_mult(a, b); + let res_vec = res_bigint.data; + + assert(unpack_or_0(res_vec.get(0)) == 100); + assert(unpack_or_0(res_vec.get(1)) == 400); + assert(unpack_or_0(res_vec.get(2)) == 1000); + assert(unpack_or_0(res_vec.get(3)) == 2000); + assert(unpack_or_0(res_vec.get(4)) == 2500); + assert(unpack_or_0(res_vec.get(5)) == 2400); + assert(unpack_or_0(res_vec.get(6)) == 1600); true } From 940cdd685122b1168b5c1f01e7fc59232accf563 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 29 Jun 2022 17:12:18 -0600 Subject: [PATCH 007/160] WIP Karatsuba just 1 level deep - A function to try out how Karatsuba would work splitting 1 time. Assumes a perfect scenario where x and y have the same length which is a multiple of 2. - Working on going through the code step by step to see if it is doing the expected thing, according to the test data above the testcase that is called "biguint_schoolbook_mult" --- bignum-lib/src/big_uint.sw | 76 ++++++++++++++++++++++++++++++++++---- bignum-lib/src/helpers.sw | 22 ++++++++++- bignum-lib/src/main.sw | 34 +++++++++++++++++ 3 files changed, 124 insertions(+), 8 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index 1aa754f..e286570 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -214,13 +214,75 @@ pub fn schoolbook_mult(a: BigUint, b: BigUint) -> BigUint { BigUint{ data: res_vec} } -//https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ /* -pub fn karatsuba_mult(a: BigUint, b: BigUint) -> BigUint { - if(a.data.len() == 1 || b.data.len() == 1) { - // in this case it's not worth it? - } +Splits the coeff vector 1 time in the middle + +Assumes x,y are of same length which is a multiple of 2 +*/ +pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> BigUint { + // x.len==y.len==2n + let n = x.data.len() >> 1; + + let mut a_data: Vec = copy_vec_from_to(x.data, 0, n); + let mut b_data: Vec = copy_vec_from_to(x.data, n, x.data.len()); + let mut c_data: Vec = copy_vec_from_to(y.data, 0, n); + let mut d_data: Vec = copy_vec_from_to(y.data, 0, y.data.len()); + + let a: BigUint = BigUint{ data: a_data }; + let b: BigUint = BigUint{ data: b_data }; + let c: BigUint = BigUint{ data: c_data }; + let d: BigUint = BigUint{ data: d_data }; + + let ac: BigUint = schoolbook_mult(a, c); + let bd: BigUint = schoolbook_mult(b, d); + let mut temp: BigUint = schoolbook_mult(add(a, b), add(c, d)); // (a+b)*(c+d) + let temp2: BigUint = sub(temp, ac); // (a+b)*(c+d) - ac + + print_vec(ac.data); + // [100, 400, 400] = 100 + 400 * 3^32 + 400 * 2^64 + - let n = max(a.data.len(), b.data.len()); + // print_vec(bd.data); + // print_vec(temp.data); + // log(temp2.is_none()); + + + // // unchecked unwrap 2x + // let ab_plus_bc: BigUint = sub(temp2.unwrap(), bd).unwrap(); // (a+b)*(c+d) - ac - bd + + // // The result would be ac * 2^128 + (ad+bc) * 2^64 + Bd + // // r * 2^64 for r=[r0,r1] = [0,0,r0,r1] + // let mut highest = ~Vec::new::(); + // highest.push(0); + // highest.push(0); + // highest.push(0); + // highest.push(0); + // let mut i = 0; + // // we know this length, actually + // let ac_len = ac.data.len(); + // while i < ac_len { + // highest.push(unpack_or_0(ac.data.get(i))); + // i += 1; + // } + + // let mut middle = ~Vec::new::(); + // middle.push(0); + // middle.push(0); + // let mut i = 0; + // let ab_plus_bc_len = ab_plus_bc.data.len(); + // while i < ab_plus_bc_len { + // middle.push(unpack_or_0(ab_plus_bc.data.get(i))); + // i += 1; + // } + + // //summed + // let highest_bigint = BigUint{ data: highest }; + // let middle_bigint = BigUint{ data: middle }; + // temp = add(highest_bigint, middle_bigint); + // return add(temp, bd); + + let mut t: Vec = ~Vec::new::(); + return BigUint{data: t}; } -*/ \ No newline at end of file + +//https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ diff --git a/bignum-lib/src/helpers.sw b/bignum-lib/src/helpers.sw index e667788..4b3cd59 100644 --- a/bignum-lib/src/helpers.sw +++ b/bignum-lib/src/helpers.sw @@ -1,6 +1,7 @@ library helpers; -use std::option::*; +use std::{option::*, vec::Vec}; +use std::logging::log; pub fn unpack_or_0 (x: Option) -> u32 { match x { @@ -11,4 +12,23 @@ pub fn unpack_or_0 (x: Option) -> u32 { pub trait Zero { fn is_zero(self) -> bool; +} + +pub fn copy_vec_from_to(vec: Vec, start: u64, end: u64) -> Vec { + let mut res_vec: Vec = ~Vec::new::(); + let mut i = start; + while i < end { + res_vec.push(unpack_or_0(vec.get(i))); + i += 1; + } + res_vec +} + +// TODO remove, just for testing +pub fn print_vec(vec: Vec) { + let mut i = 0; + while i < vec.len() { + log(unpack_or_0(vec.get(i))); + i += 1; + } } \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index b742483..bc17c21 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -325,6 +325,39 @@ fn biguint_subtraction_zeros() -> bool { fn biguint_mult_tests() -> bool { assert(biguint_schoolbook_mult()); assert(test_from_swayPractice_repo()); + + // The new function + assert(biguint_mult_karatsuba_1_level()); + + true +} + +fn biguint_mult_karatsuba_1_level() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(1); + a_data.push(2); + a_data.push(3); + a_data.push(4); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(100); + b_data.push(200); + b_data.push(300); + b_data.push(400); + let b = BigUint{data: b_data}; + + let res_bigint = karatsuba_1_level_deep(a, b); + // let res_vec = res_bigint.data; + + // assert(unpack_or_0(res_vec.get(0)) == 100); + // assert(unpack_or_0(res_vec.get(1)) == 400); + // assert(unpack_or_0(res_vec.get(2)) == 1000); + // assert(unpack_or_0(res_vec.get(3)) == 2000); + // assert(unpack_or_0(res_vec.get(4)) == 2500); + // assert(unpack_or_0(res_vec.get(5)) == 2400); + // assert(unpack_or_0(res_vec.get(6)) == 1600); + true } @@ -346,6 +379,7 @@ Applying Karatsuba would work as follows Ac = (3+4*2^32) * (300+400*2^32) = 29514790528243204096900 += 7379438837559361382900 Bd = (1+2*2^32)*(100+200*2^32) = 7378697631201807564900 Ad+bc = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - ac - bd From 73436f98b5b3fbaac9cdd65742600777a13356c8 Mon Sep 17 00:00:00 2001 From: Manish Date: Thu, 30 Jun 2022 18:19:28 +0530 Subject: [PATCH 008/160] mod operation --- bignum-lib/src/main.sw | 2 + bignum-lib/src/mod_arithmetic.sw | 105 +++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 bignum-lib/src/mod_arithmetic.sw diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index bc17c21..dd64b34 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -2,9 +2,11 @@ script; dep big_uint; dep helpers; +dep mod_arithmetic; use ::big_uint::*; use ::helpers::*; +use ::mod_arithmetic::*; use std::{vec::Vec, option::*, assert::assert, math::*}; use std::logging::log; diff --git a/bignum-lib/src/mod_arithmetic.sw b/bignum-lib/src/mod_arithmetic.sw new file mode 100644 index 0000000..951b0de --- /dev/null +++ b/bignum-lib/src/mod_arithmetic.sw @@ -0,0 +1,105 @@ +library mod_arithmetic; + +dep helpers; +dep big_uint; + +use helpers::*; +use big_uint::*; + +use std::{assert::assert, option::*, vec::Vec}; +use std::logging::log; +use core::num::*; + +//returns true if two BigUint are equal +pub fn is_equal (a: BigUint, b: BigUint) -> bool { + + if a.data.len() == 0 || b.data.len() == 0 { + return false; + } + else if a.data.len() != b.data.len() { + return false; + } else { + + let mut flag = true; + let mut i = a.data.len() - 1; + while(i >= 0 && flag) { + if unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i)) { + flag = false; + } + i-=1; + } + + return flag; + } +} + +//multiplication of BigUint with u32 integer + +pub fn sclar_multiplication (a: BigUint, b: u32) -> BigUint { + + let mut i = 0; + let mut res: Vec = ~Vec::new::(); + let mut a_i: u64 = 0; + let mut carry: u64 = 0; + + while i < a.data.len() { + a_i = unpack_or_0(a.data.get(i))*b + carry; + res.push( a_i & 0xffffffff); + carry = ((a_i >> 32) & 0xffffffff); + + i += 1; + } + + if carry != 0 { + res.push(carry); + } + + BigUint { + data: res + } +} + +pub fn mod (a: BigUint, n: BigUint) -> BigUint { + + //if a==n (a<=n & n<=a) then (a mod n) = 0 + // if a < n then (a mod n) = a + //if a > n then a (mod n) = r where a = qn + r + // case1: if number of limbs are same + // case2: if numner of limbs are unequal + if is_equal (a, n){ + let mut a: Vec = ~Vec::new::(); + a.push(0u32); + + return BigUint { + data: a + }; + } else if is_bigger_or_equal(n,a) { + return a; + } else { + + let len_a = a.data.len(); + let len_n = n.data.len(); + let mut k: u32 = 1; + let mut nk: BigUint = n; + if len_a == len_n { + //let mut quotient: u32 = 1<<16; + while is_bigger_or_equal(a, nk) { + + k += 1; + nk = sclar_multiplication(n, i); + } + nk = sclar_multiplication(n, k-1); + //let res: BigUint = sub (a, nk); + + return sub(a, nk); + } else { + return sclar_multiplication(n, k); + } + } +} + + + +// pub fn mod_add (a: BigUint, b: BigUint) -> BigUint { + +// } \ No newline at end of file From c45a666b59b6ccbd6386c7dd38d7df36f6ddbabd Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 30 Jun 2022 09:03:56 -0600 Subject: [PATCH 009/160] 1-Level Karatsuba for vector of length 2n finished up. This is not doing any checks and some unsafe unwrapping. --- bignum-lib/src/big_uint.sw | 112 ++++++++++++++----------------------- bignum-lib/src/helpers.sw | 26 +++++++++ bignum-lib/src/main.sw | 34 ++++++----- 3 files changed, 89 insertions(+), 83 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index e286570..362dc5b 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -143,27 +143,7 @@ pub fn sub(a: BigUint, b: BigUint) -> Option { } // Return the result without trailing zeroes - // Vectors are not yet mutable, so we create a new one and fill it up until possible trailing zeroes - let mut most_significant_bit_index = len_a - 1; - let mut index_found = false; - while !index_found && most_significant_bit_index > 0 { - if (unpack_or_0(res.get(most_significant_bit_index)) != 0) { - index_found = true; - } else { - most_significant_bit_index = most_significant_bit_index - 1; - } - } - - let mut normalized_res: Vec = ~Vec::new::(); - let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(res.get(0)) == 0; - if(!res_is_zero) { - let mut j = 0; - while j <= most_significant_bit_index { - normalized_res.push(unpack_or_0(res.get(j))); - j = j + 1; - } - - } + let normalized_res = normalized(res); return Option::Some(BigUint{data: normalized_res}); } else { @@ -214,6 +194,13 @@ pub fn schoolbook_mult(a: BigUint, b: BigUint) -> BigUint { BigUint{ data: res_vec} } + +fn normalized_biguint(a: BigUint) -> BigUint { + let vec = a.data; + let normalized_data = normalized(vec); + BigUint{ data: normalized_data } +} + /* Splits the coeff vector 1 time in the middle @@ -226,63 +213,50 @@ pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> BigUint { let mut a_data: Vec = copy_vec_from_to(x.data, 0, n); let mut b_data: Vec = copy_vec_from_to(x.data, n, x.data.len()); let mut c_data: Vec = copy_vec_from_to(y.data, 0, n); - let mut d_data: Vec = copy_vec_from_to(y.data, 0, y.data.len()); + let mut d_data: Vec = copy_vec_from_to(y.data, n, y.data.len()); let a: BigUint = BigUint{ data: a_data }; let b: BigUint = BigUint{ data: b_data }; let c: BigUint = BigUint{ data: c_data }; let d: BigUint = BigUint{ data: d_data }; - let ac: BigUint = schoolbook_mult(a, c); - let bd: BigUint = schoolbook_mult(b, d); + let ac: BigUint = schoolbook_mult(a, c); + let bd: BigUint = schoolbook_mult(b, d); let mut temp: BigUint = schoolbook_mult(add(a, b), add(c, d)); // (a+b)*(c+d) let temp2: BigUint = sub(temp, ac); // (a+b)*(c+d) - ac + // unchecked unwrap 2x + let ab_plus_bc: Option = sub(normalized_biguint(temp2.unwrap()), normalized_biguint(bd)).unwrap(); // (a+b)*(c+d) - ac - bd + + // The result would be db * 2^128 + (ad+bc) * 2^64 + ac + // r * 2^64 for r=[r0,r1] = [0,0,r0,r1] + let mut highest = ~Vec::new::(); + highest.push(0); + highest.push(0); + highest.push(0); + highest.push(0); + let mut i = 0; + // we know this length, actually + let bd_len = bd.data.len(); + while i < bd_len { + highest.push(unpack_or_0(bd.data.get(i))); + i += 1; + } - print_vec(ac.data); - // [100, 400, 400] = 100 + 400 * 3^32 + 400 * 2^64 - - - // print_vec(bd.data); - // print_vec(temp.data); - // log(temp2.is_none()); - - - // // unchecked unwrap 2x - // let ab_plus_bc: BigUint = sub(temp2.unwrap(), bd).unwrap(); // (a+b)*(c+d) - ac - bd - - // // The result would be ac * 2^128 + (ad+bc) * 2^64 + Bd - // // r * 2^64 for r=[r0,r1] = [0,0,r0,r1] - // let mut highest = ~Vec::new::(); - // highest.push(0); - // highest.push(0); - // highest.push(0); - // highest.push(0); - // let mut i = 0; - // // we know this length, actually - // let ac_len = ac.data.len(); - // while i < ac_len { - // highest.push(unpack_or_0(ac.data.get(i))); - // i += 1; - // } - - // let mut middle = ~Vec::new::(); - // middle.push(0); - // middle.push(0); - // let mut i = 0; - // let ab_plus_bc_len = ab_plus_bc.data.len(); - // while i < ab_plus_bc_len { - // middle.push(unpack_or_0(ab_plus_bc.data.get(i))); - // i += 1; - // } - - // //summed - // let highest_bigint = BigUint{ data: highest }; - // let middle_bigint = BigUint{ data: middle }; - // temp = add(highest_bigint, middle_bigint); - // return add(temp, bd); - - let mut t: Vec = ~Vec::new::(); - return BigUint{data: t}; + let mut middle = ~Vec::new::(); + middle.push(0); + middle.push(0); + let mut i = 0; + let ab_plus_bc_len = ab_plus_bc.data.len(); + while i < ab_plus_bc_len { + middle.push(unpack_or_0(ab_plus_bc.data.get(i))); + i += 1; + } + + //summed + let highest_bigint = BigUint{ data: highest }; + let middle_bigint = BigUint{ data: middle }; + temp = add(highest_bigint, middle_bigint); + return add(temp, ac); } //https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ diff --git a/bignum-lib/src/helpers.sw b/bignum-lib/src/helpers.sw index 4b3cd59..254c79a 100644 --- a/bignum-lib/src/helpers.sw +++ b/bignum-lib/src/helpers.sw @@ -24,6 +24,32 @@ pub fn copy_vec_from_to(vec: Vec, start: u64, end: u64) -> Vec { res_vec } +// Vectors are not yet mutable, so we create a new one and fill it up until possible trailing zeroes +pub fn normalized(vec: Vec) -> Vec { + let mut most_significant_bit_index = vec.len() - 1; + let mut index_found = false; + while !index_found && most_significant_bit_index > 0 { + if (unpack_or_0(vec.get(most_significant_bit_index)) != 0) { + index_found = true; + } else { + most_significant_bit_index = most_significant_bit_index - 1; + } + } + + let mut normalized_res: Vec = ~Vec::new::(); + let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(vec.get(0)) == 0; + if(!res_is_zero) { + let mut j = 0; + while j <= most_significant_bit_index { + normalized_res.push(unpack_or_0(vec.get(j))); + j = j + 1; + } + + } + normalized_res +} + + // TODO remove, just for testing pub fn print_vec(vec: Vec) { let mut i = 0; diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index bc17c21..62dde4c 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -328,7 +328,7 @@ fn biguint_mult_tests() -> bool { // The new function assert(biguint_mult_karatsuba_1_level()); - + true } @@ -348,15 +348,15 @@ fn biguint_mult_karatsuba_1_level() -> bool { let b = BigUint{data: b_data}; let res_bigint = karatsuba_1_level_deep(a, b); - // let res_vec = res_bigint.data; + let res_vec = res_bigint.data; - // assert(unpack_or_0(res_vec.get(0)) == 100); - // assert(unpack_or_0(res_vec.get(1)) == 400); - // assert(unpack_or_0(res_vec.get(2)) == 1000); - // assert(unpack_or_0(res_vec.get(3)) == 2000); - // assert(unpack_or_0(res_vec.get(4)) == 2500); - // assert(unpack_or_0(res_vec.get(5)) == 2400); - // assert(unpack_or_0(res_vec.get(6)) == 1600); + assert(unpack_or_0(res_vec.get(0)) == 100); + assert(unpack_or_0(res_vec.get(1)) == 400); + assert(unpack_or_0(res_vec.get(2)) == 1000); + assert(unpack_or_0(res_vec.get(3)) == 2000); + assert(unpack_or_0(res_vec.get(4)) == 2500); + assert(unpack_or_0(res_vec.get(5)) == 2400); + assert(unpack_or_0(res_vec.get(6)) == 1600); true } @@ -366,6 +366,12 @@ Example input & output for Karatsuba with BigUint X = (1+2*2^32 + 3*2^64 + 4*2^96) = [1,2,3,4] Y = (100+200*2^32 + 300*2^64 + 400*2^96) = [100,200,300,400] + +a = [1, 2] +b = [3, 4] +c = [100, 200] +d = [300, 400] + When calculating X*Y The result = 10043362780126293152582135998281912347988259896158629291622500 @@ -377,15 +383,15 @@ And therefore translates to data vector Applying Karatsuba would work as follows -Ac = (3+4*2^32) * (300+400*2^32) -= 29514790528243204096900 -= 7379438837559361382900 -Bd = (1+2*2^32)*(100+200*2^32) +Ac = (1+2*2^32)*(100+200*2^32) = 7378697631201807564900 -Ad+bc = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - ac - bd +Bd = (3+4*2^32) * (300+400*2^32) += 29514790528243204096900 +Ad+bc = (a+b)*(c+d) - a*c - b*d = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - ac - bd = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - (3+4*2^32) * (300+400*2^32) - (1+2*2^32)*(100+200*2^32) =29514790526525217178200 + Then, take as result Ac * 2^128 + (ad+bc) * 2^64 + Bd From fd3d655d9d91dd0aafbb5f47a8dd2cbd909b36d9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 30 Jun 2022 11:22:14 -0600 Subject: [PATCH 010/160] Added some checks wrt working of the 1 level deep mult. - Length of x should be a multiple of 2 - At 2 places an unwrap was being done, it is now asserted first that this should be possible --- bignum-lib/src/big_uint.sw | 22 +++++++++++++-------- bignum-lib/src/main.sw | 39 ++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index 362dc5b..bdfe295 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -206,8 +206,11 @@ Splits the coeff vector 1 time in the middle Assumes x,y are of same length which is a multiple of 2 */ -pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> BigUint { - // x.len==y.len==2n +pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> Option { + // length of x should be even + if (x.data.len() >> 1) << 1 != x.data.len() { //masking with 1 bit didn't work + return Option::None::(); + } let n = x.data.len() >> 1; let mut a_data: Vec = copy_vec_from_to(x.data, 0, n); @@ -224,24 +227,28 @@ pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> BigUint { let bd: BigUint = schoolbook_mult(b, d); let mut temp: BigUint = schoolbook_mult(add(a, b), add(c, d)); // (a+b)*(c+d) let temp2: BigUint = sub(temp, ac); // (a+b)*(c+d) - ac - // unchecked unwrap 2x - let ab_plus_bc: Option = sub(normalized_biguint(temp2.unwrap()), normalized_biguint(bd)).unwrap(); // (a+b)*(c+d) - ac - bd + assert(temp2.is_some()); + let ab_plus_bc_wrapped: Option = sub(normalized_biguint(temp2.unwrap()), normalized_biguint(bd)); // (a+b)*(c+d) - ac - bd + assert(ab_plus_bc_wrapped.is_some()); + let ab_plus_bc = ab_plus_bc_wrapped.unwrap(); - // The result would be db * 2^128 + (ad+bc) * 2^64 + ac + // The result would be bd * 2^128 + (ad+bc) * 2^64 + ac // r * 2^64 for r=[r0,r1] = [0,0,r0,r1] + + // highest represents bd * 2^128 let mut highest = ~Vec::new::(); highest.push(0); highest.push(0); highest.push(0); highest.push(0); let mut i = 0; - // we know this length, actually let bd_len = bd.data.len(); while i < bd_len { highest.push(unpack_or_0(bd.data.get(i))); i += 1; } + // middle represents (ad+bc) * 2^64 let mut middle = ~Vec::new::(); middle.push(0); middle.push(0); @@ -252,11 +259,10 @@ pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> BigUint { i += 1; } - //summed let highest_bigint = BigUint{ data: highest }; let middle_bigint = BigUint{ data: middle }; temp = add(highest_bigint, middle_bigint); - return add(temp, ac); + return Option::Some(add(temp, ac)); } //https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index 62dde4c..71ef47d 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -326,9 +326,8 @@ fn biguint_mult_tests() -> bool { assert(biguint_schoolbook_mult()); assert(test_from_swayPractice_repo()); - // The new function assert(biguint_mult_karatsuba_1_level()); - + assert(biguint_mult_karatsuba_1_level_diff_len()); true } @@ -347,8 +346,8 @@ fn biguint_mult_karatsuba_1_level() -> bool { b_data.push(400); let b = BigUint{data: b_data}; - let res_bigint = karatsuba_1_level_deep(a, b); - let res_vec = res_bigint.data; + let res_bigint = karatsuba_1_level_deep_diff_len(a, b); + let res_vec = res_bigint.unwrap().data; assert(unpack_or_0(res_vec.get(0)) == 100); assert(unpack_or_0(res_vec.get(1)) == 400); @@ -361,6 +360,38 @@ fn biguint_mult_karatsuba_1_level() -> bool { true } +fn biguint_mult_karatsuba_1_level_diff_len() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(1); + a_data.push(2); + a_data.push(3); + a_data.push(4); + let a = BigUint{data: a_data}; + + let mut b_data: Vec = ~Vec::new::(); + b_data.push(100); + b_data.push(200); + b_data.push(300); + // b_data.push(400); + let b = BigUint{data: b_data}; + + let res_bigint = karatsuba_1_level_deep_diff_len(a, b); + let vec = res_bigint.unwrap().data; + + assert(unpack_or_0(vec.get(0)) == 100); + assert(unpack_or_0(vec.get(1)) == 400); + assert(unpack_or_0(vec.get(2)) == 1000); + assert(unpack_or_0(vec.get(3)) == 1600); + assert(unpack_or_0(vec.get(4)) == 1700); + assert(unpack_or_0(vec.get(5)) == 1200); + + // [100, 400, 1000, 1600, 1700, 1200] + // 1200 * 2^160 + 1700 * 2^128 + 1600 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 + //1753801965375563525736782247188546140446222870118500 + + true +} + /* Example input & output for Karatsuba with BigUint From 744da98e4bc29c7972ba827cc4e330eaf9543369 Mon Sep 17 00:00:00 2001 From: Manish Date: Thu, 30 Jun 2022 18:19:28 +0530 Subject: [PATCH 011/160] mod operation --- bignum-lib/src/main.sw | 2 + bignum-lib/src/mod_arithmetic.sw | 105 +++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 bignum-lib/src/mod_arithmetic.sw diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index 71ef47d..d1dd850 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -2,9 +2,11 @@ script; dep big_uint; dep helpers; +dep mod_arithmetic; use ::big_uint::*; use ::helpers::*; +use ::mod_arithmetic::*; use std::{vec::Vec, option::*, assert::assert, math::*}; use std::logging::log; diff --git a/bignum-lib/src/mod_arithmetic.sw b/bignum-lib/src/mod_arithmetic.sw new file mode 100644 index 0000000..951b0de --- /dev/null +++ b/bignum-lib/src/mod_arithmetic.sw @@ -0,0 +1,105 @@ +library mod_arithmetic; + +dep helpers; +dep big_uint; + +use helpers::*; +use big_uint::*; + +use std::{assert::assert, option::*, vec::Vec}; +use std::logging::log; +use core::num::*; + +//returns true if two BigUint are equal +pub fn is_equal (a: BigUint, b: BigUint) -> bool { + + if a.data.len() == 0 || b.data.len() == 0 { + return false; + } + else if a.data.len() != b.data.len() { + return false; + } else { + + let mut flag = true; + let mut i = a.data.len() - 1; + while(i >= 0 && flag) { + if unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i)) { + flag = false; + } + i-=1; + } + + return flag; + } +} + +//multiplication of BigUint with u32 integer + +pub fn sclar_multiplication (a: BigUint, b: u32) -> BigUint { + + let mut i = 0; + let mut res: Vec = ~Vec::new::(); + let mut a_i: u64 = 0; + let mut carry: u64 = 0; + + while i < a.data.len() { + a_i = unpack_or_0(a.data.get(i))*b + carry; + res.push( a_i & 0xffffffff); + carry = ((a_i >> 32) & 0xffffffff); + + i += 1; + } + + if carry != 0 { + res.push(carry); + } + + BigUint { + data: res + } +} + +pub fn mod (a: BigUint, n: BigUint) -> BigUint { + + //if a==n (a<=n & n<=a) then (a mod n) = 0 + // if a < n then (a mod n) = a + //if a > n then a (mod n) = r where a = qn + r + // case1: if number of limbs are same + // case2: if numner of limbs are unequal + if is_equal (a, n){ + let mut a: Vec = ~Vec::new::(); + a.push(0u32); + + return BigUint { + data: a + }; + } else if is_bigger_or_equal(n,a) { + return a; + } else { + + let len_a = a.data.len(); + let len_n = n.data.len(); + let mut k: u32 = 1; + let mut nk: BigUint = n; + if len_a == len_n { + //let mut quotient: u32 = 1<<16; + while is_bigger_or_equal(a, nk) { + + k += 1; + nk = sclar_multiplication(n, i); + } + nk = sclar_multiplication(n, k-1); + //let res: BigUint = sub (a, nk); + + return sub(a, nk); + } else { + return sclar_multiplication(n, k); + } + } +} + + + +// pub fn mod_add (a: BigUint, b: BigUint) -> BigUint { + +// } \ No newline at end of file From 4c0d80ed980b9fad2af20b868302b2ffc913c31b Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 30 Jun 2022 11:28:00 -0600 Subject: [PATCH 012/160] Updated comment --- bignum-lib/src/big_uint.sw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index bdfe295..ac21abb 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -202,9 +202,9 @@ fn normalized_biguint(a: BigUint) -> BigUint { } /* -Splits the coeff vector 1 time in the middle +Splits the coeff vector 1 time in the middle and uses Karatsuba method to calculate result. -Assumes x,y are of same length which is a multiple of 2 +Assumes length of x is a multiple of 2 */ pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> Option { // length of x should be even From 1fd2716fcccf10e7e87914d9bb061d5cedea0b64 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 30 Jun 2022 17:35:30 -0600 Subject: [PATCH 013/160] Worked on modular arithmetic. - a very naive implementation with 2 tests. Where modular reduction is done, the result is wrong by 1 - can't figure out why yet. - added a comment about the "zero" definition for BigUint which we should get straight Note that I added an equals function in the big_uint and named the mod function biguint_mod2, this is mainly because the compiler wouldn't stop giving issues. I think 'forc clean' doesn't actually clean everything :( --- bignum-lib/src/big_uint.sw | 50 +++++++++++++++++++++++- bignum-lib/src/main.sw | 67 +++++++++++++++++++++++++++++--- bignum-lib/src/mod_arithmetic.sw | 18 +++++++-- 3 files changed, 125 insertions(+), 10 deletions(-) diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw index ac21abb..d3c6944 100644 --- a/bignum-lib/src/big_uint.sw +++ b/bignum-lib/src/big_uint.sw @@ -23,6 +23,12 @@ impl Zero for BigUint { } } +pub fn get_zero() -> BigUint { + // Currently this is an empty vector, but could also be vector with the single coefficient 0; + // arithemtic code has to be adapted to his! + BigUint{data: ~Vec::new::()} +} + fn max(left: u64, right: u64) -> u64 { if(left >= right) { left } else { right } } @@ -93,9 +99,11 @@ fn is_bigger_or_equal(a: BigUint, b: BigUint) -> bool { looping = false; // we know b is bigger } else if a_val == b_val && i == 0 { looping = false; // we have seen all elements and a & b are equal - } else { + } else if i > 0 { // If we're not sure yet and the index is not yet 0; keep looping i = i - 1; + } else { // this is just a safeguard. There should be no other case than aboce + looping = false; } } return a_is_bigger_or_equal; @@ -266,3 +274,43 @@ pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> Option { } //https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ + +fn equals(a: BigUint, b: BigUint) -> bool { + if a.is_zero() && b.is_zero() { + true + } else if a.data.len() != b.data.len() { + false + } else { + let mut i = 0; + let mut equal = true; + let mut loop = true; + while i < a.data.len() && loop { + if (unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i))) { + equal = false; + loop = false; + } + i += 1; + } + equal + } +} + +// Very naive, subtracting n until it's not possible anymore +pub fn biguint_mod2(a: BigUint, n: BigUint) -> BigUint { + let mut nk: BigUint = n; + let mut temp: BigUint = get_zero(); + + if equals(a, n) { + return get_zero(); + } + + let mut ak: BigUint = a; + + while is_bigger_or_equal(ak, n) { + temp = add(nk, n); + nk = temp; + ak = sub(a, nk).unwrap(); + } + + normalized_biguint(ak) +} \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw index d1dd850..cc74b80 100644 --- a/bignum-lib/src/main.sw +++ b/bignum-lib/src/main.sw @@ -1,12 +1,12 @@ -script; + script; dep big_uint; dep helpers; -dep mod_arithmetic; +// dep mod_arithmetic; use ::big_uint::*; use ::helpers::*; -use ::mod_arithmetic::*; +// use ::mod_arithmetic::*; use std::{vec::Vec, option::*, assert::assert, math::*}; use std::logging::log; @@ -19,6 +19,7 @@ fn main() { assert(biguint_addition_tests()); assert(biguint_subtraction_tests()); assert(biguint_mult_tests()); + assert(biguint_mod_tests()); } // ADDITION BIGUINT @@ -348,7 +349,7 @@ fn biguint_mult_karatsuba_1_level() -> bool { b_data.push(400); let b = BigUint{data: b_data}; - let res_bigint = karatsuba_1_level_deep_diff_len(a, b); + let res_bigint = karatsuba_1_level_deep(a, b); let res_vec = res_bigint.unwrap().data; assert(unpack_or_0(res_vec.get(0)) == 100); @@ -377,7 +378,7 @@ fn biguint_mult_karatsuba_1_level_diff_len() -> bool { // b_data.push(400); let b = BigUint{data: b_data}; - let res_bigint = karatsuba_1_level_deep_diff_len(a, b); + let res_bigint = karatsuba_1_level_deep(a, b); let vec = res_bigint.unwrap().data; assert(unpack_or_0(vec.get(0)) == 100); @@ -538,3 +539,59 @@ fn test_from_swayPractice_repo() -> bool { } true } + +fn biguint_mod_tests() -> bool { + assert(biguint_biguint_mod1()); + true +} + +/* +Modular reduction example +100 + 400 * 2^32 += 1717986918500 +[100, 400] + +1717986918500 mod (2^32+1) = 4294966997 +[1,1] +res +[4294966997] +4294966996 + +mod 12629315258213599 => 1717986918500 +[2579031263, 2940491] +res +[100, 400] +*/ +fn biguint_biguint_mod1() -> bool { + let mut a_data: Vec = ~Vec::new::(); + a_data.push(100); + a_data.push(400); + let a = BigUint{data: a_data}; + + // Case 1: 1717986918500 mod (2^32+1) = 4294966997 + let mut b_data: Vec = ~Vec::new::(); + b_data.push(1); + b_data.push(1); + let b = BigUint{data: b_data}; + + let mut res_bigint = biguint_mod2(a, b); + let mut res_vec = res_bigint.data; + + // TODO the output is now 4294966996..? + // assert(unpack_or_0(res_vec.get(0)) == 4294966997); + log(res_vec.get(0)); + + // Case 2: Should stay the same, because n > a + let mut c_data: Vec = ~Vec::new::(); + c_data.push(2579031263); + c_data.push(2940491); + let c = BigUint{data: c_data}; + + res_bigint = biguint_mod2(a, c); + res_vec = res_bigint.data; + + assert(unpack_or_0(res_vec.get(0)) == 100); + assert(unpack_or_0(res_vec.get(1)) == 400); + + true +} diff --git a/bignum-lib/src/mod_arithmetic.sw b/bignum-lib/src/mod_arithmetic.sw index 951b0de..99e0cff 100644 --- a/bignum-lib/src/mod_arithmetic.sw +++ b/bignum-lib/src/mod_arithmetic.sw @@ -10,9 +10,16 @@ use std::{assert::assert, option::*, vec::Vec}; use std::logging::log; use core::num::*; + //returns true if two BigUint are equal pub fn is_equal (a: BigUint, b: BigUint) -> bool { + // @Manish currently BigUint is interpreted as 0 when the data.len() == 0 + // a and b could be equal if they are both 0. This can be checked with .is_zero() + // (the Zero trait is defined in helpers.sw, and the implementation of is_zero in big_uint.sw) + // This is not taking into account the case BigUint{data = [0]}, ie a coefficient vector with only a 0 + // so we should decide what 0 really is :D + // I implemented like this, because we always remove trailing zeroes, therefore 0 ends up being a BigUint with an empty vector if a.data.len() == 0 || b.data.len() == 0 { return false; } @@ -21,10 +28,10 @@ pub fn is_equal (a: BigUint, b: BigUint) -> bool { } else { let mut flag = true; - let mut i = a.data.len() - 1; - while(i >= 0 && flag) { + let mut i = a.data.len() - 1; // if we change the first if check, we have to be careful here + while(i > 0 && flag) { if unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i)) { - flag = false; + flag = false; } i-=1; } @@ -35,7 +42,10 @@ pub fn is_equal (a: BigUint, b: BigUint) -> bool { //multiplication of BigUint with u32 integer -pub fn sclar_multiplication (a: BigUint, b: u32) -> BigUint { +pub fn scalar_multiplication (a: BigUint, b: u32) -> BigUint { + if b == 0 { + return get_zero(); + } let mut i = 0; let mut res: Vec = ~Vec::new::(); From 713c3253ff1066105c0d2a9f115c44f13d7338da Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 1 Jul 2022 16:33:04 -0600 Subject: [PATCH 014/160] This starts the arithmetic functionality finite field with p = 2^255-19 and elements represented radix 51. - Radix-51 representation - Zero element - Carry_propagate function - Corresponding tests and test_helpers functions --- .gitignore | 5 ++ edwards25519/Cargo.toml | 16 +++++++ edwards25519/Forc.toml | 7 +++ edwards25519/src/field_element.sw | 41 ++++++++++++++++ edwards25519/src/main.sw | 79 +++++++++++++++++++++++++++++++ edwards25519/src/test_helpers.sw | 24 ++++++++++ 6 files changed, 172 insertions(+) create mode 100644 edwards25519/Cargo.toml create mode 100644 edwards25519/Forc.toml create mode 100644 edwards25519/src/field_element.sw create mode 100644 edwards25519/src/main.sw create mode 100644 edwards25519/src/test_helpers.sw diff --git a/.gitignore b/.gitignore index 088ba6b..d6426e4 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,8 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk + +*/Cargo.lock +*/Forc.lock + +*/out/* \ No newline at end of file diff --git a/edwards25519/Cargo.toml b/edwards25519/Cargo.toml new file mode 100644 index 0000000..bd7cae6 --- /dev/null +++ b/edwards25519/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "edwards25519" +version = "0.1.0" +authors = ["HashCloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/edwards25519/Forc.toml b/edwards25519/Forc.toml new file mode 100644 index 0000000..14b5b02 --- /dev/null +++ b/edwards25519/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["HashCloak"] +entry = "main.sw" +license = "Apache-2.0" +name = "edwards25519" + +[dependencies] diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw new file mode 100644 index 0000000..61b6562 --- /dev/null +++ b/edwards25519/src/field_element.sw @@ -0,0 +1,41 @@ +library field_element; + +// Radix 51 representation of an integer: +// l0 + l1*2^51 + l2*2^102 + l3*2^153 + l4*2^204 +pub struct Element { + l0: u64, + l1: u64, + l2: u64, + l3: u64, + l4: u64, +} + +// = (1 << 51) - 1 +// But using the above expression gives the error "Could not evaluate initializer to a const declaration." +const mask_low_51_bits: u64 = 2251799813685247; +const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; + +// Do 1 round of carrying +pub fn carry_propagate(e: Element) -> Element { + // all ci have at most 13 bits + let c0 = e.l0 >> 51; + let c1 = e.l1 >> 51; + let c2 = e.l2 >> 51; + let c3 = e.l3 >> 51; + // c4 represents what carries over to the 2^255 element + // since we're working 2^255 - 19, this will carry over to the first element, + // multiplied by 19 + let c4 = e.l4 >> 51; + + // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and + // the final l0 will be at most 52 bits. Similarly for the rest. + + // c4 * 19 is at most 13 + 5 = 18 bits => l0 is at most 52 bits + let new_l0 = (e.l0 & mask_low_51_bits) + c4 * 19; + Element{ l0: new_l0, + l1: (e.l1 & mask_low_51_bits) + c0, + l2: (e.l2 & mask_low_51_bits) + c1, + l3: (e.l3 & mask_low_51_bits) + c2, + l4: (e.l4 & mask_low_51_bits) + c3 + } +} \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw new file mode 100644 index 0000000..73abe1b --- /dev/null +++ b/edwards25519/src/main.sw @@ -0,0 +1,79 @@ +script; + +dep field_element; +dep test_helpers; + +use ::field_element::*; +use ::test_helpers::*; + +use std::{assert::assert, option::*, vec::Vec}; +use std::logging::log; + +fn main() { + assert(test_helpers()); + assert(test_carry_propagate()); +} + +fn test_helpers() -> bool { + assert(test_get_zero()); + true +} + +fn test_get_zero() -> bool { + res_equals(zero, Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }); + true +} + +fn test_carry_propagate() -> bool { + assert(test_carry_propogate_1()); + assert(test_carry_propogate_2()); + true +} + +fn test_carry_propogate_1() -> bool { + /* + 2^51 + 2 = 2251799813685250 + + 2251799813685250 + + 2251799813685250 * 2^51 + + 2251799813685250 * 2^102 + + 2251799813685250 * 2^153 + + 2251799813685250 * 2^204 + mod 2^255-19 + */ + let e = Element{ + l0: 2251799813685250, + l1: 2251799813685250, + l2: 2251799813685250, + l3: 2251799813685250, + l4: 2251799813685250 }; + + let res = carry_propagate(e); + + /* equals + 21 + + 3 * 2^51 + + 3 * 2^102 + + 3 * 2^153 + + 3 * 2^204 + */ + res_equals(res, Element{ l0: 21, l1: 3, l2: 3, l3: 3, l4: 3 }); + + true +} + +fn test_carry_propogate_2() -> bool { + // 2251799813685250 = 2 + 2^51 + let e = Element{ + l0: 2251799813685250, + l1: 0, + l2: 0, + l3: 0, + l4: 0 }; + + let res = carry_propagate(e); + + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); + + true +} \ No newline at end of file diff --git a/edwards25519/src/test_helpers.sw b/edwards25519/src/test_helpers.sw new file mode 100644 index 0000000..5d83260 --- /dev/null +++ b/edwards25519/src/test_helpers.sw @@ -0,0 +1,24 @@ +library test_helpers; + +dep field_element; + +use field_element::*; +use std::logging::log; +use std::assert::assert; + +pub fn print_el(e: Element) { + log(e.l0); + log(e.l1); + log(e.l2); + log(e.l3); + log(e.l4); +} + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert(res.l0 == should_be.l0); + assert(res.l1 == should_be.l1); + assert(res.l2 == should_be.l2); + assert(res.l3 == should_be.l3); + assert(res.l4 == should_be.l4); + true +} \ No newline at end of file From a83e6d427728dc3ac5c3c279a42acc86b20222ed Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 1 Jul 2022 17:33:57 -0600 Subject: [PATCH 015/160] Added mod_25519 with tests. Also improved the tests for carry_propagate. --- edwards25519/src/field_element.sw | 31 ++++++- edwards25519/src/main.sw | 133 ++++++++++++++++++++++++++---- 2 files changed, 148 insertions(+), 16 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 61b6562..0f12b7d 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -15,7 +15,15 @@ pub struct Element { const mask_low_51_bits: u64 = 2251799813685247; const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; -// Do 1 round of carrying +/*Do 1 round of carrying +This return an element of which all li have at most 52 bits. +So the elm is at most: + (2^52 - 1) + + (2^52 - 1) * 2^51 + + (2^52 - 1) * 2^102 + + (2^52 - 1) * 2^153 + + (2^52 - 1) * 2^204 + */ pub fn carry_propagate(e: Element) -> Element { // all ci have at most 13 bits let c0 = e.l0 >> 51; @@ -38,4 +46,25 @@ pub fn carry_propagate(e: Element) -> Element { l3: (e.l3 & mask_low_51_bits) + c2, l4: (e.l4 & mask_low_51_bits) + c3 } +} + +/* +return reduced element mod 2^255-19 +*/ +pub fn mod_25519(e: Element) -> Element { + let red: Element = carry_propagate(e); + + //Determine whether *red* is already completely reduced mod 2^255-19 or not + // if v >= 2^255 - 19 => v + 19 >= 2^255 + let mut carry0 = (red.l0 + 19) >> 51; + carry0 = (red.l1 + carry0) >> 51; + carry0 = (red.l2 + carry0) >> 51; + carry0 = (red.l3 + carry0) >> 51; + carry0 = (red.l4 + carry0) >> 51; + + if carry0 == 1 { // not sure if == 1 is necessary + carry_propagate(red) + } else { + red + } } \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 73abe1b..e5e2d6e 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -8,10 +8,12 @@ use ::test_helpers::*; use std::{assert::assert, option::*, vec::Vec}; use std::logging::log; +use core::num::*; + fn main() { assert(test_helpers()); - assert(test_carry_propagate()); + assert(test_reductions()); } fn test_helpers() -> bool { @@ -24,13 +26,90 @@ fn test_get_zero() -> bool { true } -fn test_carry_propagate() -> bool { - assert(test_carry_propogate_1()); - assert(test_carry_propogate_2()); +fn test_reductions() -> bool { + assert(test_carry_propagate_1()); + assert(test_carry_propagate_2()); + assert(test_mod_25519()); + assert(test_mod_25519_2()); + assert(test_mod_25519_3()); true } -fn test_carry_propogate_1() -> bool { +fn test_carry_propagate_1() -> bool { + /* + 2^64 -1 = 18446744073709551615 + + 18446744073709551615 + + 18446744073709551615 * 2^51 + + 18446744073709551615 * 2^102 + + 18446744073709551615 * 2^153 + + 18446744073709551615 * 2^204 + */ + let e = Element{ + l0: ~u64::max(), + l1: ~u64::max(), + l2: ~u64::max(), + l3: ~u64::max(), + l4: ~u64::max() }; + + let res = carry_propagate(e); + + // Each limb has a carry of 8191 and a coeff of 2251799813685247 + // So after a round of reduction this is + /* equals + 2251799813685247 + (19*8191) + + (2251799813685247 + 8191) * 2^51 + + (2251799813685247 + 8191) * 2^102 + + (2251799813685247 + 8191) * 2^153 + + (2251799813685247 + 8191) * 2^204 + = 57896044618868696584113898827420068118245036358148060739095062128926159691756 + */ + res_equals(res, Element{ + l0: 2251799813685247 + (19*8191), + l1: 2251799813685247 + 8191, + l2: 2251799813685247 + 8191, + l3: 2251799813685247 + 8191, + l4: 2251799813685247 + 8191 + }); + + // Note that this result is >2^255-19 because the function only does 1 round of reduction + + true +} + +fn test_carry_propagate_2() -> bool { + // 2251799813685250 = 2 + 2^51 + let e = Element{ + l0: 2251799813685250, + l1: 0, + l2: 0, + l3: 0, + l4: 0 }; + + let res = carry_propagate(e); + + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); + + true +} + +fn test_mod_25519() -> bool { + // 2251799813685250 = 2 + 2^51 + let e = Element{ + l0: 2251799813685250, + l1: 0, + l2: 0, + l3: 0, + l4: 0 }; + + let res = mod_25519(e); + + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); + + true +} + +fn test_mod_25519_2() -> bool { /* 2^51 + 2 = 2251799813685250 @@ -48,7 +127,7 @@ fn test_carry_propogate_1() -> bool { l3: 2251799813685250, l4: 2251799813685250 }; - let res = carry_propagate(e); + let res = mod_25519(e); /* equals 21 + @@ -62,18 +141,42 @@ fn test_carry_propogate_1() -> bool { true } -fn test_carry_propogate_2() -> bool { - // 2251799813685250 = 2 + 2^51 +fn test_mod_25519_3() -> bool { + /* + 2^64 -1 = 18446744073709551615 + + 18446744073709551615 + + 18446744073709551615 * 2^51 + + 18446744073709551615 * 2^102 + + 18446744073709551615 * 2^153 + + 18446744073709551615 * 2^204 + mod 2^255 -19 + = 210598872328406323076114191610044025327778719366270124969594871807 + */ let e = Element{ - l0: 2251799813685250, - l1: 0, - l2: 0, - l3: 0, - l4: 0 }; + l0: ~u64::max(), + l1: ~u64::max(), + l2: ~u64::max(), + l3: ~u64::max(), + l4: ~u64::max() }; - let res = carry_propagate(e); + let res = mod_25519(e); - res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); + /* + 155647 + + 8191 * 2^51 + + 8191 * 2^102 + + 8191 * 2^153 + + 8191 * 2^204 + = 210598872328406323076114191610044025327778719366270124969594871807 + */ + res_equals(res, Element{ + l0: 155647, + l1: 8191, + l2: 8191, + l3: 8191, + l4: 8191 + }); true } \ No newline at end of file From 807ff00798662c51f26de1cd0fdd2c132da21cd9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 1 Jul 2022 17:57:45 -0600 Subject: [PATCH 016/160] WIP addition mod p. The a+a test reveals that reduction is probably not correct - should be cheched. --- edwards25519/src/field_element.sw | 19 ++++- edwards25519/src/main.sw | 125 ++++++++++++++++++++++++++++++ 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 0f12b7d..bfc6b3f 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -61,10 +61,27 @@ pub fn mod_25519(e: Element) -> Element { carry0 = (red.l2 + carry0) >> 51; carry0 = (red.l3 + carry0) >> 51; carry0 = (red.l4 + carry0) >> 51; - + // TODO: is this above correct? + // The addition test test_add_a_to_a doesn't seem to reduce correctly. Should check + if carry0 == 1 { // not sure if == 1 is necessary carry_propagate(red) } else { red } +} + +/* +return a + b mod 2^255 - 19 +*/ +pub fn add(a: Element, b: Element) -> Element { + let temp = Element{ + l0: a.l0 + b.l0, + l1: a.l1 + b.l1, + l2: a.l2 + b.l2, + l3: a.l3 + b.l3, + l4: a.l4 + b.l4 + }; + + mod_25519(temp) } \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index e5e2d6e..d574baf 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -14,6 +14,7 @@ use core::num::*; fn main() { assert(test_helpers()); assert(test_reductions()); + assert(tests_add()); } fn test_helpers() -> bool { @@ -178,5 +179,129 @@ fn test_mod_25519_3() -> bool { l4: 8191 }); + true +} + +fn tests_add() -> bool { + assert(test_add_to_0()); + assert(test_add_0()); + assert(test_add_a_to_b()); + assert(test_add_a_to_a()); + true + +} + +fn test_add_to_0() -> bool { + let b = Element{ + l0: 8191, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }; + + let res = add(zero, b); + + assert(res_equals(res, b)); + true +} + +fn test_add_0() -> bool { + let b = Element{ + l0: 8191, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }; + + let res = add(b, zero); + + assert(res_equals(res, b)); + true +} + +fn test_add_a_to_b() -> bool { + // coefficients are 2^51-1 + /* + 2251799813685247 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 2251799813685247 * 2^153 + + 2251799813685247 * 2^204 + = 57896044618658097711785492504343953926634992332820282019728792003956564819967 + */ + let a = Element{ + l0: 2251799813685247, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + // random + /* + 8191 + + 225179 * 2^51 + + 155647 * 2^102 + + 81918191 * 2^153 + + 85247 * 2^204 + = 2191786359344073644698773448800701597704682582429191096092436996095 + */ + let b = Element{ + l0: 8191, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }; + + // a+b mod 2^255 -19 + // should be 2191786359344073644698773448800701597704682582429191096092436996113 + let res = add(a,b); + + /* + 8209 + + 225179 * 2^51 + + 155647 * 2^102 + + 81918191 * 2^153 + + 85247 * 2^204 + = 2191786359344073644698773448800701597704682582429191096092436996113 + */ + res_equals(res, Element{ + l0: 8209, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }); + + true +} + +fn test_add_a_to_a() -> bool { + // coefficients are 2^51-1 + /* + 2251799813685247 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 2251799813685247 * 2^153 + + 2251799813685247 * 2^204 + = 57896044618658097711785492504343953926634992332820282019728792003956564819967 + */ + let a = Element{ + l0: 2251799813685247, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + // a+a mod 2^255 -19 + // should be + let res = add(a, a); + + print_el(res); + true } \ No newline at end of file From 83352d50f0380b2946a57223aa734e33a69fae05 Mon Sep 17 00:00:00 2001 From: Manish Date: Sat, 2 Jul 2022 13:51:26 +0530 Subject: [PATCH 017/160] changes in mod_25519 --- edwards25519/src/field_element.sw | 19 ++++++++++++++++--- edwards25519/src/main.sw | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index bfc6b3f..4020172 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -14,7 +14,7 @@ pub struct Element { // But using the above expression gives the error "Could not evaluate initializer to a const declaration." const mask_low_51_bits: u64 = 2251799813685247; const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; - +const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; /*Do 1 round of carrying This return an element of which all li have at most 52 bits. So the elm is at most: @@ -52,7 +52,7 @@ pub fn carry_propagate(e: Element) -> Element { return reduced element mod 2^255-19 */ pub fn mod_25519(e: Element) -> Element { - let red: Element = carry_propagate(e); + let mut red: Element = carry_propagate(e); //Determine whether *red* is already completely reduced mod 2^255-19 or not // if v >= 2^255 - 19 => v + 19 >= 2^255 @@ -64,11 +64,24 @@ pub fn mod_25519(e: Element) -> Element { // TODO: is this above correct? // The addition test test_add_a_to_a doesn't seem to reduce correctly. Should check - if carry0 == 1 { // not sure if == 1 is necessary + if carry0 != 0 { // not sure if == 1 is necessary carry_propagate(red) } else { red } + + // red.l0 += 19*carry0; + // red.l1 += red.l0 >>51; + // red.l0 += red.l0 & mask_low_51_bits; + // red.l2 += red.l1 >>51; + // red.l1 += red.l1 & mask_low_51_bits; + // red.l3 += red.l2 >>51; + // red.l2 += red.l2 & mask_low_51_bits; + // red.l4 += red.l3 >>51; + // red.l3 += red.l3 & mask_low_51_bits; + // red.l4 += red.l4 >>51; + + return red; } /* diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index d574baf..bc483af 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -32,7 +32,7 @@ fn test_reductions() -> bool { assert(test_carry_propagate_2()); assert(test_mod_25519()); assert(test_mod_25519_2()); - assert(test_mod_25519_3()); + //assert(test_mod_25519_3()); true } From d37238292e1b3ae723d4c58c29657fb401b85226 Mon Sep 17 00:00:00 2001 From: Manish Date: Mon, 4 Jul 2022 17:49:25 +0530 Subject: [PATCH 018/160] subtraction and multiplication --- edwards25519/src/field_element.sw | 159 +++++++++++++++++++++++++++++- edwards25519/src/main.sw | 4 +- edwards25519/src/test_helpers.sw | 8 +- 3 files changed, 166 insertions(+), 5 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 4020172..f6e0cec 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -1,5 +1,6 @@ library field_element; +use std::u128::*; // Radix 51 representation of an integer: // l0 + l1*2^51 + l2*2^102 + l3*2^153 + l4*2^204 pub struct Element { @@ -96,5 +97,159 @@ pub fn add(a: Element, b: Element) -> Element { l4: a.l4 + b.l4 }; - mod_25519(temp) -} \ No newline at end of file + //mod_25519(temp) + carry_propagate(temp) //need to be checked +} + +//subtract fn returns a - b +pub fn subtract(a: Element, b: Element) -> Element { + // we add 2*p to avoid any underflow and then subtract b + let res: Element = Element { + l0: (a.l0 + 0xFFFFFFFFFFFDA) - b.l0, + l1: (a.l1 + 0xFFFFFFFFFFFFE) - b.l1, + l2: (a.l2 + 0xFFFFFFFFFFFFE) - b.l2, + l3: (a.l3 + 0xFFFFFFFFFFFFE) - b.l3, + l4: (a.l4 +0xFFFFFFFFFFFFE ) - b.l4 + }; + + carry_propagate(res) +} + +//negate return negaive of an element(-a) +pub fn negate (a: Element) -> Element { + subtract(zero,a) + +} + +//returns 128-bit product of a and b +pub fn multiply64 (a: u64, b: u64) -> U128 { + let mask32 = (1<<32) - 1; + let a0 = a & mask32; + let a1 = a >> 32; + let b0 = b & mask32; + let b1 = b >> 32; + + let w0 = a0*b0; + let t = a1*b0 + (w0 >> 32); + let mut w1 = t & mask32; + let w2 = t >> 32; + + w1 += a0*b1; + + U128 { + upper: a1*b1 + w2 + (w1 >>32), + lower: a*b + } +} + +//returns sum with carry of a and b +pub fn add64 (a: u64, b:u64, carry: u64) -> (u64, u64) { + let sum = a + b + carry; + // let carryOut = ((a & b) | ((x | y) &^ sum)) >> 63; //dont know if NOT Operator is there otherwise needs to be defined manually + + // (sum, carryOut) + (0,0) +} + +//returns res + a * b +pub fn add_multiply64 (res: U128, a: u64, b: u64) -> U128 { + let mut mul_res: U128 = multiply64(a, b); + let add_res: (u64, u64) = add64(mul_res.lower, res.lower, 0); + let add_res2: (u64, u64) = add64(mul_res.upper, res.upper, add_res.1); + + U128{ + upper: add_res.0, + lower: add_res2.0 + } +} + +//right shift by 51 +pub fn shiftRightBy51(a: U128) -> u64 { + (a.upper <<(64-51)) | (a.lower >> 51) +} + +//returns a*b +pub fn multiply (a: Element, b: Element) -> Element { + + //https://cs.opensource.google/go/go/+/master:src/crypto/internal/edwards25519/field/fe_generic.go;l=34;bpv=0?q=feMul&sq=&ss=go%2Fgo + + let a0 = a.l0; + let a1 = a.l1; + let a2 = a.l2; + let a3 = a.l3; + let a4 = a.l4; + + let b0 = b.l0; + let b1 = b.l1; + let b2 = b.l2; + let b3 = b.l3; + let b4 = b.l4; + + let a1_19 = a1 * 19; + let a2_19 = a2 * 19; + let a3_19 = a3 * 19; + let a4_19 = a4 * 19; + + // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) + let mut r0: U128 = multiply64(a0, b0); + r0 = add_multiply64(r0, a1_19, b4); + r0 = add_multiply64(r0, a2_19, b3); + r0 = add_multiply64(r0, a3_19, b2); + r0 = add_multiply64(r0, a4_19, b1); + + // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) + let mut r1: U128 = multiply64(a0, b1); + r1 = add_multiply64(r1, a1, b0); + r1 = add_multiply64(r1, a2_19, b4); + r1 = add_multiply64(r1, a3_19, b3); + r1 = add_multiply64(r1, a4_19, b2); + + // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) + let mut r2: U128 = multiply64(a0, b2); + r2 = add_multiply64(r2, a1, b1); + r2 = add_multiply64(r2, a2, b0); + r2 = add_multiply64(r2, a3_19, b4); + r2 = add_multiply64(r2, a4_19, b3); + + // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 + let mut r3: U128 = multiply64(a0, b3); + r3 = add_multiply64(r3, a1, b2); + r3 = add_multiply64(r3, a2, b1); + r3 = add_multiply64(r3, a3, b0); + r3 = add_multiply64(r3, a4_19, b4); + + // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + let mut r4: U128 = multiply64(a0, b4); + r4 = add_multiply64(r4, a1, b3); + r4 = add_multiply64(r4, a2, b2); + r4 = add_multiply64(r4, a3, b1); + r4 = add_multiply64(r4, a4, b0); + + let c0 = shiftRightBy51(r0); + let c1 = shiftRightBy51(r1); + let c2 = shiftRightBy51(r2); + let c3 = shiftRightBy51(r3); + let c4 = shiftRightBy51(r4); + + let rr0 = r0.lower & mask_low_51_bits + c4*19; + let rr1 = r1.lower & mask_low_51_bits + c0; + let rr2 = r2.lower & mask_low_51_bits + c1; + let rr3 = r3.lower & mask_low_51_bits + c2; + let rr4 = r4.lower & mask_low_51_bits + c3; + + let res: Element = Element { + l0: rr0, + l1: rr1, + l2: rr2, + l3: rr3, + l4: rr4 + }; + + carry_propagate(res) + +} + +//returns square of an Element +// pub fn square(a: Element) -> Element { +// multiply(a,a) +// } \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index bc483af..51f8b82 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -28,8 +28,8 @@ fn test_get_zero() -> bool { } fn test_reductions() -> bool { - assert(test_carry_propagate_1()); - assert(test_carry_propagate_2()); + //assert(test_carry_propagate_1()); + //assert(test_carry_propagate_2()); assert(test_mod_25519()); assert(test_mod_25519_2()); //assert(test_mod_25519_3()); diff --git a/edwards25519/src/test_helpers.sw b/edwards25519/src/test_helpers.sw index 5d83260..bdf3839 100644 --- a/edwards25519/src/test_helpers.sw +++ b/edwards25519/src/test_helpers.sw @@ -21,4 +21,10 @@ pub fn res_equals(res: Element, should_be: Element) -> bool { assert(res.l3 == should_be.l3); assert(res.l4 == should_be.l4); true -} \ No newline at end of file +} + +//converts element into array of bytes + +// pub fn bytes_convert (a: Element) -> [u8;32] { +// let a_mod = mod_25519(a); +// } \ No newline at end of file From 5056489abf2f6ed5a9dcd5ea5b46be218ac6d676 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 4 Jul 2022 09:48:23 -0600 Subject: [PATCH 019/160] - Fixed the mod_25519 function (it was not reduces enough rounds in some situations) - Added extra test for mod that represents this situation - Both addition tests are now working --- edwards25519/src/field_element.sw | 32 +++++++++++------- edwards25519/src/main.sw | 56 +++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index bfc6b3f..a75da87 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -48,27 +48,33 @@ pub fn carry_propagate(e: Element) -> Element { } } +/* +returns a carry element neq 0 if the e represents a number larger than 2^255 -19 +*/ +fn get_carry(e: Element) -> u32 { + let mut carry = (e.l0 + 19) >> 51; + carry = (e.l1 + carry) >> 51; + carry = (e.l2 + carry) >> 51; + carry = (e.l3 + carry) >> 51; + carry = (e.l4 + carry) >> 51; + carry +} + /* return reduced element mod 2^255-19 */ pub fn mod_25519(e: Element) -> Element { - let red: Element = carry_propagate(e); + let mut red: Element = carry_propagate(e); //Determine whether *red* is already completely reduced mod 2^255-19 or not // if v >= 2^255 - 19 => v + 19 >= 2^255 - let mut carry0 = (red.l0 + 19) >> 51; - carry0 = (red.l1 + carry0) >> 51; - carry0 = (red.l2 + carry0) >> 51; - carry0 = (red.l3 + carry0) >> 51; - carry0 = (red.l4 + carry0) >> 51; - // TODO: is this above correct? - // The addition test test_add_a_to_a doesn't seem to reduce correctly. Should check - - if carry0 == 1 { // not sure if == 1 is necessary - carry_propagate(red) - } else { - red + // keep reducing as long as it's necessary + let mut carry = get_carry(red); + while carry != 0 { + red = carry_propagate(red); + carry = get_carry(red); } + red } /* diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index d574baf..fa8e657 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -33,6 +33,7 @@ fn test_reductions() -> bool { assert(test_mod_25519()); assert(test_mod_25519_2()); assert(test_mod_25519_3()); + assert(test_mod_25519_4()); true } @@ -182,6 +183,40 @@ fn test_mod_25519_3() -> bool { true } +fn test_mod_25519_4() -> bool { + /* + 4503599627370494 + + 4503599627370494 * 2^51 + + 4503599627370494 * 2^102 + + 4503599627370494 * 2^153 + + 4503599627370494 * 2^204 + mod 2^255 - 19 + + = 36 + */ + let e = Element{ + l0: 4503599627370494, + l1: 4503599627370494, + l2: 4503599627370494, + l3: 4503599627370494, + l4: 4503599627370494 }; + + let res = mod_25519(e); + + /* + should be 36 + */ + res_equals(res, Element{ + l0: 36, + l1: 0, + l2: 0, + l3: 0, + l4: 0 + }); + + true +} + fn tests_add() -> bool { assert(test_add_to_0()); assert(test_add_0()); @@ -297,11 +332,26 @@ fn test_add_a_to_a() -> bool { l4: 2251799813685247 }; - // a+a mod 2^255 -19 - // should be + /* a+a mod 2^255 -19 = + double all coefficients gives: + 4503599627370494 + + 4503599627370494 * 2^51 + + 4503599627370494 * 2^102 + + 4503599627370494 * 2^153 + + 4503599627370494 * 2^204 + mod 2^255 - 19 + + = 36 + */ let res = add(a, a); - print_el(res); + res_equals(res, Element{ + l0: 36, + l1: 0, + l2: 0, + l3: 0, + l4: 0 + }); true } \ No newline at end of file From 72066ef5d1742d8401a3ee90ab2a341c04e67697 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 4 Jul 2022 11:06:20 -0600 Subject: [PATCH 020/160] Addition to merge --- edwards25519/src/field_element.sw | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 8db8370..50cf2d0 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -90,8 +90,7 @@ pub fn add(a: Element, b: Element) -> Element { l4: a.l4 + b.l4 }; - //mod_25519(temp) - carry_propagate(temp) //need to be checked + mod_25519(temp) } //subtract fn returns a - b From fb794d89d1867ff8c7f3a58f8a7711165122aa8f Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 4 Jul 2022 12:18:20 -0600 Subject: [PATCH 021/160] Scalar multiplication with a scalar with max 32 bits. - Added scalar mult function - With corresponding tests --- edwards25519/src/field_element.sw | 46 ++++++++++++- edwards25519/src/main.sw | 108 ++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 50cf2d0..58afb85 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -1,6 +1,7 @@ library field_element; use std::u128::*; + // Radix 51 representation of an integer: // l0 + l1*2^51 + l2*2^102 + l3*2^153 + l4*2^204 pub struct Element { @@ -244,4 +245,47 @@ pub fn multiply (a: Element, b: Element) -> Element { //returns square of an Element // pub fn square(a: Element) -> Element { // multiply(a,a) -// } \ No newline at end of file +// } + +// For a bignumber <= 102 bits stored in U128, +// return the 51 bit coefficient and 51 bit carry +fn get_coeff_and_carry(y: U128) -> (u64, u64) { + let coeff: u64 = y.lower & mask_low_51_bits; + let carry: u64 = (y.upper << 13 & mask_low_51_bits) | y.lower >> 51; + (coeff, carry) +} + +// returns e with all limbs multiplied by scalar x, reduced p +pub fn scalar_mult(e: Element, x: u32) -> Element { + let scalar_u128: U128 = ~U128::from(0, x); + + // e is radix 51, so all limbs have max 51 bits. The scalar has max 32 bits. + // Their multiplication has max 84 bits and is stored as (upper, lower) in U128 + let l0_temp: U128 = ~U128::from(0, e.l0) * scalar_u128; + let l1_temp: U128 = ~U128::from(0, e.l1) * scalar_u128; + let l2_temp: U128 = ~U128::from(0, e.l2) * scalar_u128; + let l3_temp: U128 = ~U128::from(0, e.l3) * scalar_u128; + let l4_temp: U128 = ~U128::from(0, e.l4) * scalar_u128; + + let (coeff0, carry0) = get_coeff_and_carry(l0_temp); + let (coeff1, carry1) = get_coeff_and_carry(l1_temp); + let (coeff2, carry2) = get_coeff_and_carry(l2_temp); + let (coeff3, carry3) = get_coeff_and_carry(l3_temp); + let (coeff4, carry4) = get_coeff_and_carry(l4_temp); + + let res0: u64 = coeff0 + 19 * carry4; + let res1: u64 = coeff1 + carry0; + let res2: u64 = coeff2 + carry1; + let res3: u64 = coeff3 + carry2; + let res4: u64 = coeff4 + carry3; + + let res: Element = Element { + l0: res0, + l1: res1, + l2: res2, + l3: res3, + l4: res4 + }; + + res +} \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index fa8e657..6150fb6 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -15,6 +15,7 @@ fn main() { assert(test_helpers()); assert(test_reductions()); assert(tests_add()); + assert(tests_scalar_mult()); } fn test_helpers() -> bool { @@ -353,5 +354,112 @@ fn test_add_a_to_a() -> bool { l4: 0 }); + true +} + +fn tests_scalar_mult() -> bool { + assert(test_mult_by_0()); + assert(test_mult_by_1()); + assert(test_mult_by_2()); + assert(test_mult_by_large_scalar()); + true +} + +fn test_mult_by_0() -> bool { + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let res: Element = scalar_mult(a, 0); + res_equals(res, zero); + true +} + +fn test_mult_by_1() -> bool { + let a = Element{ + l0: 79611, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 555555333333222, + l4: 2251799813685247 + }; + + let res: Element = scalar_mult(a, 1); + res_equals(res, a); + true +} + +fn test_mult_by_2() -> bool { + /* + 79611 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 555555333333222 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 79611, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 555555333333222, + l4: 2251799813685247 + }; + + /* 57896044618658058976409158941982667984400415217654165675094330160006532591113 + =[159241, + 2251799813685246, + 2251799813685247, + 1111110666666445, + 2251799813685246] */ + let res: Element = scalar_mult(a, 2); + + res_equals(res, Element{ + l0: 159241, + l1: 2251799813685246, + l2: 2251799813685247, + l3: 1111110666666445, + l4: 2251799813685246 + }); + + true +} + +fn test_mult_by_large_scalar() -> bool { + /* + 79611 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 555555333333222 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 79611, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 555555333333222, + l4: 2251799813685247 + }; + + /* + 248661618146997193275445770277948644497863737508141907291226725252005565483705230608645 + reduced mod 2^255 - 19 + = 57895961435070841628109209456323569962738033236635300844883400985433276860639 + = [342008245700831, 2251795518717953, 2251799813685247, 536152338865944, 2251796578355658] + */ + // Largest scalar input possible is 2^32 -1 = 4294967295 + let res: Element = scalar_mult(a, 4294967295); + + res_equals(res, Element{ + l0: 342008245700831, + l1: 2251795518717953, + l2: 2251799813685247, + l3: 536152338865944, + l4: 2251796578355658 + }); + true } \ No newline at end of file From afdb84d8515789ae210e8d43dacb90ff0f7fe6d9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 4 Jul 2022 18:20:49 -0600 Subject: [PATCH 022/160] - Renamed mod_25519 to reduced, since it follows the 'reduced' function implementation from the go implementation - Made the implementation constant (following the ref impl) - Replaced the * 19 by the function times19 - Replaced the mod_25519 call in the addition function with the propagate_carry call - Fixed the addition test that was using a test element too big --- edwards25519/src/field_element.sw | 44 +++++++++++---- edwards25519/src/main.sw | 91 ++++++++++++++++++++----------- 2 files changed, 92 insertions(+), 43 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 58afb85..c6bcf0e 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -17,6 +17,12 @@ pub struct Element { const mask_low_51_bits: u64 = 2251799813685247; const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; + +// from NaCl impl https://cr.yp.to/ecdh.html#use +fn times19(x: u64) -> u64 { + (x << 4) + (x << 1) + x +} + /*Do 1 round of carrying This return an element of which all li have at most 52 bits. So the elm is at most: @@ -41,7 +47,7 @@ pub fn carry_propagate(e: Element) -> Element { // the final l0 will be at most 52 bits. Similarly for the rest. // c4 * 19 is at most 13 + 5 = 18 bits => l0 is at most 52 bits - let new_l0 = (e.l0 & mask_low_51_bits) + c4 * 19; + let new_l0 = (e.l0 & mask_low_51_bits) + times19(c4); Element{ l0: new_l0, l1: (e.l1 & mask_low_51_bits) + c0, l2: (e.l2 & mask_low_51_bits) + c1, @@ -54,7 +60,7 @@ pub fn carry_propagate(e: Element) -> Element { returns a carry element neq 0 if the e represents a number larger than 2^255 -19 */ fn get_carry(e: Element) -> u32 { - let mut carry = (e.l0 + 19) >> 51; + let mut carry = times19(e.l0) >> 51; carry = (e.l1 + carry) >> 51; carry = (e.l2 + carry) >> 51; carry = (e.l3 + carry) >> 51; @@ -65,18 +71,34 @@ fn get_carry(e: Element) -> u32 { /* return reduced element mod 2^255-19 */ -pub fn mod_25519(e: Element) -> Element { +pub fn reduce(e: Element) -> Element { let mut red: Element = carry_propagate(e); //Determine whether *red* is already completely reduced mod 2^255-19 or not // if v >= 2^255 - 19 => v + 19 >= 2^255 - // keep reducing as long as it's necessary - let mut carry = get_carry(red); - while carry != 0 { - red = carry_propagate(red); - carry = get_carry(red); + let mut carry = (red.l0 + 19) >> 51; + carry = (red.l1 + carry) >> 51; + carry = (red.l2 + carry) >> 51; + carry = (red.l3 + carry) >> 51; + carry = (red.l4 + carry) >> 51; + + let mut v0 = red.l0 + times19(carry); + let mut v1 = red.l1 + (v0 >> 51); + v0 = v0 & mask_low_51_bits; + let mut v2 = red.l2 + (v1 >> 51); + v1 = v1 & mask_low_51_bits; + let mut v3 = red.l3 + (v2 >> 51); + v2 = v2 & mask_low_51_bits; + let mut v4 = (red.l4 + (v3 >> 51)) & mask_low_51_bits; + v3 = v3 & mask_low_51_bits; + + Element{ + l0: v0, + l1: v1, + l2: v2, + l3: v3, + l4: v4 } - red } /* @@ -91,7 +113,7 @@ pub fn add(a: Element, b: Element) -> Element { l4: a.l4 + b.l4 }; - mod_25519(temp) + carry_propagate(temp) } //subtract fn returns a - b @@ -273,7 +295,7 @@ pub fn scalar_mult(e: Element, x: u32) -> Element { let (coeff3, carry3) = get_coeff_and_carry(l3_temp); let (coeff4, carry4) = get_coeff_and_carry(l4_temp); - let res0: u64 = coeff0 + 19 * carry4; + let res0: u64 = coeff0 + times19(carry4); let res1: u64 = coeff1 + carry0; let res2: u64 = coeff2 + carry1; let res3: u64 = coeff3 + carry2; diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 6150fb6..e3ed5c7 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -31,10 +31,10 @@ fn test_get_zero() -> bool { fn test_reductions() -> bool { assert(test_carry_propagate_1()); assert(test_carry_propagate_2()); - assert(test_mod_25519()); - assert(test_mod_25519_2()); - assert(test_mod_25519_3()); - assert(test_mod_25519_4()); + assert(test_reduce()); + assert(test_reduce_2()); + assert(test_reduce_3()); + assert(test_reduce_4()); true } @@ -96,7 +96,7 @@ fn test_carry_propagate_2() -> bool { true } -fn test_mod_25519() -> bool { +fn test_reduce() -> bool { // 2251799813685250 = 2 + 2^51 let e = Element{ l0: 2251799813685250, @@ -105,14 +105,14 @@ fn test_mod_25519() -> bool { l3: 0, l4: 0 }; - let res = mod_25519(e); + let res = reduce(e); res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); true } -fn test_mod_25519_2() -> bool { +fn test_reduce_2() -> bool { /* 2^51 + 2 = 2251799813685250 @@ -130,7 +130,7 @@ fn test_mod_25519_2() -> bool { l3: 2251799813685250, l4: 2251799813685250 }; - let res = mod_25519(e); + let res = reduce(e); /* equals 21 + @@ -144,7 +144,7 @@ fn test_mod_25519_2() -> bool { true } -fn test_mod_25519_3() -> bool { +fn test_reduce_3() -> bool { /* 2^64 -1 = 18446744073709551615 @@ -163,7 +163,7 @@ fn test_mod_25519_3() -> bool { l3: ~u64::max(), l4: ~u64::max() }; - let res = mod_25519(e); + let res = reduce(e); /* 155647 + @@ -184,7 +184,7 @@ fn test_mod_25519_3() -> bool { true } -fn test_mod_25519_4() -> bool { +fn test_reduce_4() -> bool { /* 4503599627370494 + 4503599627370494 * 2^51 + @@ -202,7 +202,7 @@ fn test_mod_25519_4() -> bool { l3: 4503599627370494, l4: 4503599627370494 }; - let res = mod_25519(e); + let res = reduce(e); /* should be 36 @@ -316,42 +316,30 @@ fn test_add_a_to_b() -> bool { } fn test_add_a_to_a() -> bool { - // coefficients are 2^51-1 + // 2^255 - 20 (the largest number) expressed in radix-51 /* - 2251799813685247 + + 2251799813685228 + 2251799813685247 * 2^51 + 2251799813685247 * 2^102 + 2251799813685247 * 2^153 + 2251799813685247 * 2^204 - = 57896044618658097711785492504343953926634992332820282019728792003956564819967 */ let a = Element{ - l0: 2251799813685247, + l0: 2251799813685228, l1: 2251799813685247, l2: 2251799813685247, l3: 2251799813685247, l4: 2251799813685247 }; - /* a+a mod 2^255 -19 = - double all coefficients gives: - 4503599627370494 + - 4503599627370494 * 2^51 + - 4503599627370494 * 2^102 + - 4503599627370494 * 2^153 + - 4503599627370494 * 2^204 - mod 2^255 - 19 - - = 36 - */ let res = add(a, a); res_equals(res, Element{ - l0: 36, - l1: 0, - l2: 0, - l3: 0, - l4: 0 + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 }); true @@ -361,6 +349,7 @@ fn tests_scalar_mult() -> bool { assert(test_mult_by_0()); assert(test_mult_by_1()); assert(test_mult_by_2()); + assert(test_mult_by_2_again()); assert(test_mult_by_large_scalar()); true } @@ -428,6 +417,44 @@ fn test_mult_by_2() -> bool { true } +fn test_mult_by_2_again() -> bool { + // 2^255 - 20 (the largest number) expressed in radix-51 + /* + 2251799813685228 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 2251799813685247 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 2251799813685228, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + + let res: Element = scalar_mult(a, 2); + + /* + 2251799813685227 + 2251799813685247* 2^51 + + 2251799813685247* 2^102 + + 2251799813685247* 2^153 + + 2251799813685247 * 2^204 + */ + res_equals(res, Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }); + + true +} + fn test_mult_by_large_scalar() -> bool { /* 79611 + From 58fe02542fb18156ced7992e2da5aa85d1108062 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 4 Jul 2022 18:49:06 -0600 Subject: [PATCH 023/160] Added constant time equals function with tests. --- edwards25519/src/field_element.sw | 12 +++++++++ edwards25519/src/main.sw | 44 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index c6bcf0e..126c7d3 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -310,4 +310,16 @@ pub fn scalar_mult(e: Element, x: u32) -> Element { }; res +} + +// Constant time equals +pub fn equals(a: Element, b: Element) -> bool { + let mut res: u64 = 0; + res = res + (a.l0 ^ b.l0); + res = res + (a.l1 ^ b.l1); + res = res + (a.l2 ^ b.l2); + res = res + (a.l3 ^ b.l3); + res = res + (a.l4 ^ b.l4); + + res == 0 } \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index e3ed5c7..2e52707 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -20,6 +20,7 @@ fn main() { fn test_helpers() -> bool { assert(test_get_zero()); + assert(test_equals()); true } @@ -28,6 +29,49 @@ fn test_get_zero() -> bool { true } +fn test_equals() -> bool { + let zero_equals_zero = equals(zero, zero); + let zero_equals_one = equals(zero, one); + let one_equals_one = equals(one, one); + + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + let b = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + let c = Element{ + l0: 60, + l1: 5, + l2: 2251799813685247, + l3: 500, + l4: 100 + }; + let a_equals_a = equals(a,a); + let a_equals_b = equals(a,b); //a and b have same coefficients + let a_equals_c = equals(a,c); + let b_equals_c = equals(b,c); + + assert(zero_equals_zero); + assert(!zero_equals_one); + assert(one_equals_one); + + assert(a_equals_a); + assert(a_equals_b); + assert(!a_equals_c); + assert(!b_equals_c); + + true +} + fn test_reductions() -> bool { assert(test_carry_propagate_1()); assert(test_carry_propagate_2()); From 78e4c50b1b0978ae8c2d711e007927add57426b2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 4 Jul 2022 19:37:46 -0600 Subject: [PATCH 024/160] Start on curve arithmetic --- edwards25519/src/ge25519.sw | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 edwards25519/src/ge25519.sw diff --git a/edwards25519/src/ge25519.sw b/edwards25519/src/ge25519.sw new file mode 100644 index 0000000..299e3fb --- /dev/null +++ b/edwards25519/src/ge25519.sw @@ -0,0 +1,67 @@ +library ge25519; + +use field_element::*; + +/* Point representation with extended coordinates, they satisfy: + x=X/Z + y=Y/Z + x*y=T/Z + See https://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html +*/ +pub struct Ge25519 { + x: Element, + y: Element, + z: Element, + t: Element +} + +// Completed point (https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html) +pub struct Ge25519_p1p1 { + x: Element, + y: Element, + z: Element, + t: Element +} + +/* Projective point. Satisfies: + x=X/Z + y=Y/Z +- https://www.hyperelliptic.org/EFD/g1p/auto-twisted-projective.html +- https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html +*/ +pub struct Ge25519_p2 { + x: Element, + y: Element, + z: Element +} + +pub struct Ge25519_aff { + x: Element, + y: Element +} + +/* +http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd +*/ +pub fn double(p: Ge25519_p2) -> Ge25519_p1p1 { + let a = square(p.x); + let b = square(p.y); + let mut c = square(p.z); + c = add(c, c); + let d = negate(a); + + let mut res_x = add(p.x, p.y); + res_x = square(res_x); + res_x = subtract(res_x, a); + res_x = subtract(res_x, b); + let res_z = add(d, b); + let res_t = subtract(res_z, c); + let res_y = subtract(d, b); + + Ge25519_p1p1 { + x: res_x, + y: res_y, + z: res_Z, + t: res_t + } +} \ No newline at end of file From 720273f2788a550248a8ecbd62f11370356ea55e Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 5 Jul 2022 12:46:49 +0530 Subject: [PATCH 025/160] multiply64 changed, a*19 replaced by times19(a), subtraction & multiply64 test added --- edwards25519/src/field_element.sw | 36 ++--- edwards25519/src/main.sw | 258 +++++++++++++++++++++++++++++- edwards25519/src/test_helpers.sw | 6 + 3 files changed, 272 insertions(+), 28 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 126c7d3..d07021f 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -124,10 +124,11 @@ pub fn subtract(a: Element, b: Element) -> Element { l1: (a.l1 + 0xFFFFFFFFFFFFE) - b.l1, l2: (a.l2 + 0xFFFFFFFFFFFFE) - b.l2, l3: (a.l3 + 0xFFFFFFFFFFFFE) - b.l3, - l4: (a.l4 +0xFFFFFFFFFFFFE ) - b.l4 + l4: (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 }; - carry_propagate(res) + //carry_propagate(res) + reduce(res) } //negate return negaive of an element(-a) @@ -138,23 +139,12 @@ pub fn negate (a: Element) -> Element { //returns 128-bit product of a and b pub fn multiply64 (a: u64, b: u64) -> U128 { - let mask32 = (1<<32) - 1; - let a0 = a & mask32; - let a1 = a >> 32; - let b0 = b & mask32; - let b1 = b >> 32; - - let w0 = a0*b0; - let t = a1*b0 + (w0 >> 32); - let mut w1 = t & mask32; - let w2 = t >> 32; - - w1 += a0*b1; - - U128 { - upper: a1*b1 + w2 + (w1 >>32), - lower: a*b - } + + let A: U128 = U128 {upper: 0, lower: a}; + let B: U128 = U128 {upper: 0, lower: b}; + let AB: U128 = A*B; + return AB + } //returns sum with carry of a and b @@ -200,10 +190,10 @@ pub fn multiply (a: Element, b: Element) -> Element { let b3 = b.l3; let b4 = b.l4; - let a1_19 = a1 * 19; - let a2_19 = a2 * 19; - let a3_19 = a3 * 19; - let a4_19 = a4 * 19; + let a1_19 = times19(a1); + let a2_19 = times19(a2); + let a3_19 = times19(a3); + let a4_19 = times19(a4); // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) let mut r0: U128 = multiply64(a0, b0); diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 2e52707..ac26d33 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -9,13 +9,18 @@ use ::test_helpers::*; use std::{assert::assert, option::*, vec::Vec}; use std::logging::log; use core::num::*; +use std::u128::*; fn main() { - assert(test_helpers()); - assert(test_reductions()); - assert(tests_add()); - assert(tests_scalar_mult()); + // assert(test_helpers()); + // assert(test_reductions()); + // assert(tests_add()); + // assert(tests_scalar_mult()); + // assert(tests_substract()); + assert(tests_multiply64()); + // assert(tests_multiply()); + } fn test_helpers() -> bool { @@ -533,4 +538,247 @@ fn test_mult_by_large_scalar() -> bool { }); true -} \ No newline at end of file +} + +fn tests_substract() -> bool { + assert(test_subtraction_by_0()); + assert(test_subtraction_by_1()); + assert(test_subtraction_by_max()); + assert(test_subtraction_random()); + true +} + +fn test_subtraction_by_0() -> bool { + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let res: Element = subtract(a, zero); + res_equals(res, a); + + true +} + +fn test_subtraction_by_1() -> bool { + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let b = Element{ + l0: 2251799813685246, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let res: Element = subtract(a, one); + res_equals(res, b); + //print_el(res); + true +} + +fn test_subtraction_by_max() -> bool { + + //using GP-PARI one can convert a number into arbitrary base using the command digits(number, base) + + /* + 2^255 - 21 = 57896044618658097711785492504343953926634992332820282019728792003956564819947 + = [2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685227] + = Element { + 2251799813685227, + 2251799813685247, + 2251799813685247, + 2251799813685247, + 2251799813685247 + } + */ + + let a = Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + /* + 2^255 - 20 = 57896044618658097711785492504343953926634992332820282019728792003956564819948 + = [2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685228] + = Element { + 2251799813685228, + 2251799813685247, + 2251799813685247, + 2251799813685247, + 2251799813685247 + } + */ + + let b = Element { + l0: 2251799813685228, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + let res: Element = subtract(a, b); + let res2: Element = subtract(b,a); + res_equals(res, b); + res_equals(res2, one); + true +} + +fn test_subtraction_random() -> bool { + /* + subtraction of random 2 numbers generated using GP-PARI + + a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 + = [50591579140481, 601879629470779, 595911506101250, 1303372017735434, 1292655137982008] + = Element { + 1292655137982008, + 1303372017735434, + 595911506101250, + 601879629470779, + 50591579140481 + } + + b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 + = [137209507300112, 293961277766182, 335483569739384, 807899991388824, 1360902863141127] + = Element { + 1360902863141127, + 807899991388824, + 335483569739384, + 293961277766182, + 137209507300112 + } + + b - a = 2227034305193647043917155265022785584227666213349054009788224516815197975247 + = [86617928159630, 1943881461980650, 1991371877323381, 1756327787338638, 68247725159119] + = Element { + 68247725159119, + 1756327787338638, + 1991371877323381, + 1943881461980650, + 86617928159630 + } + a - b + p = 55669010313464450667868337239321168342407326119471228009940567487141366844702 + = [2165181885525617, 307918351704597, 260427936361866, 495472026346609, 2183552088526110] + = Element { + 2183552088526110, + 495472026346609, + 260427936361866, + 307918351704597, + 2165181885525617 + } + */ + + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; + + let b = Element { + l0: 1360902863141127, + l1: 807899991388824, + l2: 335483569739384, + l3: 293961277766182, + l4: 137209507300112 + }; + + let a_minus_b = Element { + l0: 2183552088526110, + l1: 495472026346609, + l2: 260427936361866, + l3: 307918351704597, + l4: 2165181885525617 + }; + + let b_minus_a = Element { + l0: 68247725159119, + l1: 1756327787338638, + l2: 1991371877323381, + l3: 1943881461980650, + l4: 86617928159630 + }; + + let res: Element = subtract(a, b); + let res2: Element = subtract(b,a); + res_equals(res, a_minus_b); + res_equals(res2, b_minus_a); + //print_el(res2); + true +} + +fn tests_multiply() -> bool { + //assert(test_multiply_by_0()); + //assert(test_multiply_by_1()); + true +} + +fn test_multiply_by_0() -> bool { + + //a = 2^255 - 21 + let a = Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + let res: Element = multiply(a, zero); + res_equals(res, zero); + true +} + + +fn tests_multiply64() -> bool { + assert(test_multiply64_random()); + true +} + +fn test_multiply64_random()-> bool{ + let a = 9837491998535547791; + let b = 10009796384580774444; +/* +a*b = 98471291840283423519614919326553453204 + = [5338139427034470684, 5960040633016627860] +*/ + let ab: U128 = U128 { + upper: 5338139427034470684, + lower: 5960040633016627860 + }; + + let res = multiply64(a, b); + assert(res == ab); + //print_U128(res); + + true +} + +//--------------------------------------------------------------------------------------------------------------- +// fn test_multiply_by_1() -> bool { + +// //a = 2^255 - 21 +// let a = Element{ +// l0: 2251799813685227, +// l1: 2251799813685247, +// l2: 2251799813685247, +// l3: 2251799813685247, +// l4: 2251799813685247 +// }; +// let res: Element = multiply(a, one); +// res_equals(res, a); +// true +// } \ No newline at end of file diff --git a/edwards25519/src/test_helpers.sw b/edwards25519/src/test_helpers.sw index bdf3839..013d8ff 100644 --- a/edwards25519/src/test_helpers.sw +++ b/edwards25519/src/test_helpers.sw @@ -5,6 +5,7 @@ dep field_element; use field_element::*; use std::logging::log; use std::assert::assert; +use std::u128::*; pub fn print_el(e: Element) { log(e.l0); @@ -23,6 +24,11 @@ pub fn res_equals(res: Element, should_be: Element) -> bool { true } +pub fn print_U128(a: U128) { + log(a.upper); + log(a.lower); +} + //converts element into array of bytes // pub fn bytes_convert (a: Element) -> [u8;32] { From 8496a3a527ffe33c96fabf030b072fe076c0dfa5 Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 5 Jul 2022 18:03:49 +0530 Subject: [PATCH 026/160] overflow for fn multiply fixed --- edwards25519/src/field_element.sw | 64 ++++++--- edwards25519/src/main.sw | 218 ++++++++++++++++++++++++------ 2 files changed, 226 insertions(+), 56 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index d07021f..9896918 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -144,16 +144,19 @@ pub fn multiply64 (a: u64, b: u64) -> U128 { let B: U128 = U128 {upper: 0, lower: b}; let AB: U128 = A*B; return AB - + } //returns sum with carry of a and b -pub fn add64 (a: u64, b:u64, carry: u64) -> (u64, u64) { - let sum = a + b + carry; - // let carryOut = ((a & b) | ((x | y) &^ sum)) >> 63; //dont know if NOT Operator is there otherwise needs to be defined manually +pub fn add64 (a: u64, b: u64, carry: u64) -> (u64, u64) { + let A:U128 = U128{upper: 0, lower: a}; + let B:U128 = U128{upper: 0, lower: b}; - // (sum, carryOut) - (0,0) + let sum: u64 = (A+B).lower; + let notSum = ~u64::max() - sum; + let carryOut = ((a & b) | ((a | b) & sum)) >> 63; + + (sum, carryOut) } //returns res + a * b @@ -190,10 +193,10 @@ pub fn multiply (a: Element, b: Element) -> Element { let b3 = b.l3; let b4 = b.l4; - let a1_19 = times19(a1); - let a2_19 = times19(a2); - let a3_19 = times19(a3); - let a4_19 = times19(a4); + let a1_19 = 19*a1; + let a2_19 = 19*a2; + let a3_19 = 19*a3; + let a4_19 = 19*a4; // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) let mut r0: U128 = multiply64(a0, b0); @@ -223,7 +226,7 @@ pub fn multiply (a: Element, b: Element) -> Element { r3 = add_multiply64(r3, a3, b0); r3 = add_multiply64(r3, a4_19, b4); - // r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 + //r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 let mut r4: U128 = multiply64(a0, b4); r4 = add_multiply64(r4, a1, b3); r4 = add_multiply64(r4, a2, b2); @@ -236,11 +239,36 @@ pub fn multiply (a: Element, b: Element) -> Element { let c3 = shiftRightBy51(r3); let c4 = shiftRightBy51(r4); - let rr0 = r0.lower & mask_low_51_bits + c4*19; - let rr1 = r1.lower & mask_low_51_bits + c0; - let rr2 = r2.lower & mask_low_51_bits + c1; - let rr3 = r3.lower & mask_low_51_bits + c2; - let rr4 = r4.lower & mask_low_51_bits + c3; +//Overflow is happning here i think + + let r0_mask: U128 = U128{upper: 0, lower: r0.lower & mask_low_51_bits}; + let c4_19 = U128{upper: 0, lower: c4} * U128{upper: 0, lower: 19}; + let rr0 = (r0_mask + c4_19).lower; + + let r1_mask: U128 = U128{upper: 0, lower: r1.lower & mask_low_51_bits}; + let c00 = U128{upper: 0, lower: c0}; + let rr1 = (r1_mask + c00).lower; + + let r2_mask: U128 = U128{upper: 0, lower: r2.lower & mask_low_51_bits}; + let c11 = U128{upper: 0, lower: c1}; + let rr2 = (r2_mask + c11).lower; + + let r3_mask: U128 = U128{upper: 0, lower: r3.lower & mask_low_51_bits}; + let c22 = U128{upper: 0, lower: c2}; + let rr3 = (r3_mask + c22).lower; + + let r4_mask: U128 = U128{upper: 0, lower: r4.lower & mask_low_51_bits}; + let c33 = U128{upper: 0, lower: c3}; + let rr4 = (r4_mask + c33).lower; + + + + + //let rr0 = (r0.lower & mask_low_51_bits) + 19*c4; + // let rr1 = (r1.lower & mask_low_51_bits) + c0; + // let rr2 = (r2.lower & mask_low_51_bits) + c1; + // let rr3 = (r3.lower & mask_low_51_bits) + c2; + // let rr4 = (r4.lower & mask_low_51_bits) + c3; let res: Element = Element { l0: rr0, @@ -251,7 +279,7 @@ pub fn multiply (a: Element, b: Element) -> Element { }; carry_propagate(res) - + //reduce(res) } //returns square of an Element @@ -285,7 +313,7 @@ pub fn scalar_mult(e: Element, x: u32) -> Element { let (coeff3, carry3) = get_coeff_and_carry(l3_temp); let (coeff4, carry4) = get_coeff_and_carry(l4_temp); - let res0: u64 = coeff0 + times19(carry4); + let res0: u64 = coeff0 + carry4*19; let res1: u64 = coeff1 + carry0; let res2: u64 = coeff2 + carry1; let res3: u64 = coeff3 + carry2; diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index ac26d33..781c667 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -18,8 +18,11 @@ fn main() { // assert(tests_add()); // assert(tests_scalar_mult()); // assert(tests_substract()); - assert(tests_multiply64()); - // assert(tests_multiply()); + // assert(tests_multiply64()); + assert(tests_multiply()); + //assert(tests_add64()); + // assert(tests_add_multiply64()); + // assert(tests_shiftRightBy51()); } @@ -76,7 +79,7 @@ fn test_equals() -> bool { true } - +//------------------------------------------------------------------------------------------------ fn test_reductions() -> bool { assert(test_carry_propagate_1()); assert(test_carry_propagate_2()); @@ -266,7 +269,7 @@ fn test_reduce_4() -> bool { true } - +//------------------------------------------------------------------------------------------- fn tests_add() -> bool { assert(test_add_to_0()); assert(test_add_0()); @@ -393,7 +396,7 @@ fn test_add_a_to_a() -> bool { true } - +//-------------------------------------------------------------------------------------------- fn tests_scalar_mult() -> bool { assert(test_mult_by_0()); assert(test_mult_by_1()); @@ -539,7 +542,7 @@ fn test_mult_by_large_scalar() -> bool { true } - +//-------------------------------------------------------------------------------------------- fn tests_substract() -> bool { assert(test_subtraction_by_0()); assert(test_subtraction_by_1()); @@ -720,10 +723,117 @@ fn test_subtraction_random() -> bool { //print_el(res2); true } +//------------------------------------------------------------------------------------------------------------- +fn tests_multiply64() -> bool { + assert(test_multiply64_random()); + true +} + +fn test_multiply64_random()-> bool{ + let a = 9837491998535547791; + let b = 10009796384580774444; +/* +a*b = 98471291840283423519614919326553453204 + = [5338139427034470684, 5960040633016627860] +*/ + let ab: U128 = U128 { + upper: 5338139427034470684, + lower: 5960040633016627860 + }; + + let res = multiply64(a, b); + assert(res == ab); + //print_U128(res); + + true +} +//---------------------------------------------------------------------------------------------------- +fn tests_add64() -> bool { + assert(test_add64_random()); + true +} + +fn test_add64_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = add64(a, b, 0); + let a_plus_b: (u64,u64) = (1, 1400544309406770619); + + log(res.0); + log(res.1); + true +} +//------------------------------------------------------------------------------------------------------------ +fn tests_add_multiply64() -> bool { + assert(test_add_multiply64_random()); + assert(test_add_multiply64_max()); + true +} +fn test_add_multiply64_max() -> bool { + /* + random 51 bit number a = 496009164746885 + a*19 = 9424174130190815 + random 107 bit number r = 46428403129198069714856710112646 + + res = [2770292668654, 9024291134538729057] + */ + + let a = 496009164746885; + let b = a*19; + let r = U128{upper: 2516888776885, lower: 8614063320694916486}; + + let mut res = add_multiply64(r,a,b); + // res = add_multiply64(r,a,b); + // res = add_multiply64(r,a,b); + // res = add_multiply64(r,a,b); + // res = add_multiply64(r,a,b); + print_U128(res); + true + +} + +fn test_add_multiply64_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + /* + a*b = 98471291840283423519614919326553453204 + = [5338139427034470684, 5960040633016627860] + + random r = 10598342506117936052 + ab + r = 98471291840283423530213261832671389256 + = [5338139427034470684, 16558383139134563912] + + */ + let r:U128 = U128{upper: 0, lower: 10598342506117936052}; + let res = add_multiply64(r, a, b); + + print_U128(res); + + true + + + +} +//----------------------------------------------------------------------------------------------------- + +fn tests_shiftRightBy51() -> bool { + assert(test_shiftRightBy51_random()); + true +} + +fn test_shiftRightBy51_random() -> bool { + + let a = U128{upper: 16, lower:0}; + let res = shiftRightBy51(a); + log(res); + true +} +//---------------------------------------------------------------------------------------------------- fn tests_multiply() -> bool { //assert(test_multiply_by_0()); - //assert(test_multiply_by_1()); + assert(test_multiply_by_1()); + // assert(test_multiply_random()); true } @@ -742,43 +852,75 @@ fn test_multiply_by_0() -> bool { true } +fn test_multiply_by_1() -> bool { -fn tests_multiply64() -> bool { - assert(test_multiply64_random()); - true -} - -fn test_multiply64_random()-> bool{ - let a = 9837491998535547791; - let b = 10009796384580774444; -/* -a*b = 98471291840283423519614919326553453204 - = [5338139427034470684, 5960040633016627860] -*/ - let ab: U128 = U128 { - upper: 5338139427034470684, - lower: 5960040633016627860 + //a = 2^255 - 21 + let a = Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 }; - - let res = multiply64(a, b); - assert(res == ab); - //print_U128(res); - + let res: Element = multiply(a, one); + print_el(res); + res_equals(res, a); true } -//--------------------------------------------------------------------------------------------------------------- -// fn test_multiply_by_1() -> bool { +// fn test_multiply_random() -> bool { +// /* +// a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 +// = [50591579140481, 601879629470779, 595911506101250, 1303372017735434, 1292655137982008] +// = Element { +// 1292655137982008, +// 1303372017735434, +// 595911506101250, +// 601879629470779, +// 50591579140481 +// } + +// b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 +// = [137209507300112, 293961277766182, 335483569739384, 807899991388824, 1360902863141127] +// = Element { +// 1360902863141127, +// 807899991388824, +// 335483569739384, +// 293961277766182, +// 137209507300112 +// } + +// ab mod p = 26419211797770492947925431317169526880133696901606348938375383866077151145114 +// = [1027544741541094, 806477788321681, 355992668009873, 1000789340506524, 896638975913114] + +// */ + +// let a = Element { +// l0: 1292655137982008, +// l1: 1303372017735434, +// l2: 595911506101250, +// l3: 601879629470779, +// l4: 50591579140481 +// }; + +// let b = Element { +// l0: 1360902863141127, +// l1: 807899991388824, +// l2: 335483569739384, +// l3: 293961277766182, +// l4: 137209507300112 +// }; -// //a = 2^255 - 21 -// let a = Element{ -// l0: 2251799813685227, -// l1: 2251799813685247, -// l2: 2251799813685247, -// l3: 2251799813685247, -// l4: 2251799813685247 +// let ab = Element { +// l0: 896638975913114, +// l1: 1000789340506524, +// l2: 355992668009873, +// l3: 806477788321681, +// l4: 1027544741541094 // }; -// let res: Element = multiply(a, one); -// res_equals(res, a); + +// let res: Element = multiply(a, b); +// //print_el(res); +// res_equals(res, ab); // true // } \ No newline at end of file From 64bb529ae95376cacf3b12c969958e4e1fe07edb Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 5 Jul 2022 18:09:28 -0600 Subject: [PATCH 027/160] - Fixed multiplication of 2 field elements by fixing add64 and add_multiply_64 - Replaced *19 with times19 from the NaCl impl - Added tests and organized tests into which ones work if all ran at the same time and the mult test that...: - Mult tests only work when ran 1 at a time -> open issue --- edwards25519/src/field_element.sw | 55 +--- edwards25519/src/main.sw | 460 +++++++++++++++++++++++++----- edwards25519/src/test_helpers.sw | 6 + 3 files changed, 404 insertions(+), 117 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 9896918..8830608 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -151,23 +151,24 @@ pub fn multiply64 (a: u64, b: u64) -> U128 { pub fn add64 (a: u64, b: u64, carry: u64) -> (u64, u64) { let A:U128 = U128{upper: 0, lower: a}; let B:U128 = U128{upper: 0, lower: b}; + let Carry: U128 = U128 { upper: 0, lower: carry }; - let sum: u64 = (A+B).lower; + let sum: u64 = (A+B+Carry).lower; let notSum = ~u64::max() - sum; - let carryOut = ((a & b) | ((a | b) & sum)) >> 63; + let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; (sum, carryOut) } //returns res + a * b pub fn add_multiply64 (res: U128, a: u64, b: u64) -> U128 { - let mut mul_res: U128 = multiply64(a, b); + let mul_res: U128 = multiply64(a, b); let add_res: (u64, u64) = add64(mul_res.lower, res.lower, 0); let add_res2: (u64, u64) = add64(mul_res.upper, res.upper, add_res.1); U128{ - upper: add_res.0, - lower: add_res2.0 + upper: add_res2.0, + lower: add_res.0 } } @@ -193,10 +194,10 @@ pub fn multiply (a: Element, b: Element) -> Element { let b3 = b.l3; let b4 = b.l4; - let a1_19 = 19*a1; - let a2_19 = 19*a2; - let a3_19 = 19*a3; - let a4_19 = 19*a4; + let a1_19 = times19(a1); + let a2_19 = times19(a2); + let a3_19 = times19(a3); + let a4_19 = times19(a4); // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) let mut r0: U128 = multiply64(a0, b0); @@ -239,36 +240,11 @@ pub fn multiply (a: Element, b: Element) -> Element { let c3 = shiftRightBy51(r3); let c4 = shiftRightBy51(r4); -//Overflow is happning here i think - - let r0_mask: U128 = U128{upper: 0, lower: r0.lower & mask_low_51_bits}; - let c4_19 = U128{upper: 0, lower: c4} * U128{upper: 0, lower: 19}; - let rr0 = (r0_mask + c4_19).lower; - - let r1_mask: U128 = U128{upper: 0, lower: r1.lower & mask_low_51_bits}; - let c00 = U128{upper: 0, lower: c0}; - let rr1 = (r1_mask + c00).lower; - - let r2_mask: U128 = U128{upper: 0, lower: r2.lower & mask_low_51_bits}; - let c11 = U128{upper: 0, lower: c1}; - let rr2 = (r2_mask + c11).lower; - - let r3_mask: U128 = U128{upper: 0, lower: r3.lower & mask_low_51_bits}; - let c22 = U128{upper: 0, lower: c2}; - let rr3 = (r3_mask + c22).lower; - - let r4_mask: U128 = U128{upper: 0, lower: r4.lower & mask_low_51_bits}; - let c33 = U128{upper: 0, lower: c3}; - let rr4 = (r4_mask + c33).lower; - - - - - //let rr0 = (r0.lower & mask_low_51_bits) + 19*c4; - // let rr1 = (r1.lower & mask_low_51_bits) + c0; - // let rr2 = (r2.lower & mask_low_51_bits) + c1; - // let rr3 = (r3.lower & mask_low_51_bits) + c2; - // let rr4 = (r4.lower & mask_low_51_bits) + c3; + let rr0 = (r0.lower & mask_low_51_bits) + times19(c4); + let rr1 = (r1.lower & mask_low_51_bits) + c0; + let rr2 = (r2.lower & mask_low_51_bits) + c1; + let rr3 = (r3.lower & mask_low_51_bits) + c2; + let rr4 = (r4.lower & mask_low_51_bits) + c3; let res: Element = Element { l0: rr0, @@ -279,7 +255,6 @@ pub fn multiply (a: Element, b: Element) -> Element { }; carry_propagate(res) - //reduce(res) } //returns square of an Element diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 781c667..062a502 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -13,16 +13,21 @@ use std::u128::*; fn main() { - // assert(test_helpers()); - // assert(test_reductions()); - // assert(tests_add()); - // assert(tests_scalar_mult()); - // assert(tests_substract()); - // assert(tests_multiply64()); - assert(tests_multiply()); - //assert(tests_add64()); - // assert(tests_add_multiply64()); - // assert(tests_shiftRightBy51()); + // THESE TESTS ARE ALL OK + assert(test_helpers()); + assert(test_reductions()); + assert(tests_add()); + assert(tests_scalar_mult()); + assert(tests_multiply64()); + assert(tests_add64()); + assert(tests_add_multiply64()); + assert(tests_shiftRightBy51()); + assert(tests_substract()); + + // Multiply functions only test OK if ran 1 at a time. (?!) + // assert(tests_multiply()); + + // NOT OK } @@ -585,7 +590,6 @@ fn test_subtraction_by_1() -> bool { let res: Element = subtract(a, one); res_equals(res, b); - //print_el(res); true } @@ -750,6 +754,7 @@ a*b = 98471291840283423519614919326553453204 //---------------------------------------------------------------------------------------------------- fn tests_add64() -> bool { assert(test_add64_random()); + assert(test_add64_random_with_carry()); true } @@ -757,18 +762,68 @@ fn test_add64_random() -> bool { let a = 9837491998535547791; let b = 10009796384580774444; let res:(u64,u64) = add64(a, b, 0); - let a_plus_b: (u64,u64) = (1, 1400544309406770619); + let a_plus_b: (u64,u64) = (1400544309406770619, 1); - log(res.0); - log(res.1); + assert(res.0 == a_plus_b.0); + assert(res.1 == a_plus_b.1); + true +} + +fn test_add64_random_with_carry() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = add64(a, b, 1); + let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); + + assert(res.0 == a_plus_b_and_carry.0); + assert(res.1 == a_plus_b_and_carry.1); true } //------------------------------------------------------------------------------------------------------------ fn tests_add_multiply64() -> bool { - assert(test_add_multiply64_random()); - assert(test_add_multiply64_max()); + assert(test_add_multiply64()); + assert(test_add_multiply64_2()); + // assert(test_add_multiply64_random()); + // assert(test_add_multiply64_max()); true } + +fn test_add_multiply64() -> bool { + let a = 496009164746885; + let b = 24764068336973246; + //ab=12283204851556881218686606838710 + + let r = U128{upper: 2516888776885, lower: 8614063320694916486}; + //r=46428403129198069714856710112646 + + // should be + //58711607980754950933543316951356 + //[10881738262824685884, 3182762646142] + let mut res = add_multiply64(r,a,b); + equals_U128(res, 10881738262824685884, 3182762646142); + + true +} + +fn test_add_multiply64_2() -> bool { + let a = 24764068336973246; + let b = 137209507300112; + //ab=3397865615262403032595436803552 + + // r= 1759178078333803271346890843016 + //[16956620749643293576, 95365234715] + let r = U128{upper: 95365234715, lower: 16956620749643293576}; + + // should be + //5157043693596206303942327646568 + //[18148778710141221224, 279563898809] + let mut res = add_multiply64(r,a,b); + + equals_U128(res, 18148778710141221224, 279563898809); + + true +} + fn test_add_multiply64_max() -> bool { /* random 51 bit number a = 496009164746885 @@ -788,6 +843,8 @@ fn test_add_multiply64_max() -> bool { // res = add_multiply64(r,a,b); // res = add_multiply64(r,a,b); print_U128(res); + //5338139427034470685 + //16558383139134563912 true } @@ -809,7 +866,8 @@ fn test_add_multiply64_random() -> bool { let res = add_multiply64(r, a, b); print_U128(res); - +//2770292668654 +//9024291134538729057 true @@ -819,6 +877,8 @@ fn test_add_multiply64_random() -> bool { fn tests_shiftRightBy51() -> bool { assert(test_shiftRightBy51_random()); + assert(test_shiftRightBy51_random_2()); + assert(test_shiftRightBy51_random_3()); true } @@ -826,13 +886,44 @@ fn test_shiftRightBy51_random() -> bool { let a = U128{upper: 16, lower:0}; let res = shiftRightBy51(a); - log(res); + assert(res == 131072); + true +} + +fn test_shiftRightBy51_random_2() -> bool { + /* +456464 + (349323232 << 64) = 6443876259705066799772399376 + +>>51 = 2861655916544 + */ + let a = U128{upper: 349323232, lower:456464}; + let res = shiftRightBy51(a); + assert(res == 2861655916544); + true +} + +fn test_shiftRightBy51_random_3() -> bool { + /* +18446744073709551615 + (349323232 << 64) = 6443876278151810873481494527 + +>>51 = 2861655924735 + */ + let a = U128{upper: 349323232, lower:18446744073709551615}; + let res = shiftRightBy51(a); + assert(res == 2861655924735); true } + //---------------------------------------------------------------------------------------------------- fn tests_multiply() -> bool { - //assert(test_multiply_by_0()); - assert(test_multiply_by_1()); + // assert(test_multiply_by_0()); + // assert(test_multiply_1_by_1()); + // assert(test_multiply_by_1_small()); + // assert(test_multiply_by_1_large()); + // assert(test_multiply_small_elms()); + // assert(test_multiply_small_elms_2()); + // assert(test_multiply_small_elms_3()); + assert(test_multiply_elms_4()); // assert(test_multiply_random()); true } @@ -852,7 +943,28 @@ fn test_multiply_by_0() -> bool { true } -fn test_multiply_by_1() -> bool { +fn test_multiply_1_by_1() -> bool { + let res: Element = multiply(one, one); + res_equals(res, one); + + true +} + +fn test_multiply_by_1_small() -> bool { + + let a = Element{ + l0: 10, + l1: 11, + l2: 12, + l3: 13, + l4: 14 + }; + let res: Element = multiply(a, one); + res_equals(res, a); + true +} + +fn test_multiply_by_1_large() -> bool { //a = 2^255 - 21 let a = Element{ @@ -863,64 +975,258 @@ fn test_multiply_by_1() -> bool { l4: 2251799813685247 }; let res: Element = multiply(a, one); - print_el(res); res_equals(res, a); true } -// fn test_multiply_random() -> bool { -// /* -// a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 -// = [50591579140481, 601879629470779, 595911506101250, 1303372017735434, 1292655137982008] -// = Element { -// 1292655137982008, -// 1303372017735434, -// 595911506101250, -// 601879629470779, -// 50591579140481 -// } - -// b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 -// = [137209507300112, 293961277766182, 335483569739384, 807899991388824, 1360902863141127] -// = Element { -// 1360902863141127, -// 807899991388824, -// 335483569739384, -// 293961277766182, -// 137209507300112 -// } - -// ab mod p = 26419211797770492947925431317169526880133696901606348938375383866077151145114 -// = [1027544741541094, 806477788321681, 355992668009873, 1000789340506524, 896638975913114] - -// */ +fn test_multiply_small_elms() -> bool { + +/* +10 + +11 * 2^51 + +12 * 2^102 + +13 * 2^153 + +14 * 2^204 += +359954121914013970155159550104308900255525248390881418617552906 +*/ + let a = Element{ + l0: 10, + l1: 11, + l2: 12, + l3: 13, + l4: 14 + }; +/* +2 + +3 * 2^51 + +4 * 2^102 + +5 * 2^153 + +6 * 2^204 += +154266052248863123541936069103167134583173917060132914191138818 +*/ + let b = Element{ + l0: 2, + l1: 3, + l2: 4, + l3: 5, + l4: 6 + }; + let res: Element = multiply(a, b); + + // = 5913532002873104218298081466563921672602110506934768320078942312 + // = [4200, 3719, 2909, 1752, 230] + res_equals(res, Element { + l0: 4200, + l1: 3719, + l2: 2909, + l3: 1752, + l4: 230 + }); + true +} + +fn test_multiply_small_elms_2() -> bool { + +/* +10 + +11 * 2^51 + +12 * 2^102 + +1292655137982008 * 2^153 + +14 * 2^204 += +374713634419208422705277081530098872100895088375962880689831946 +*/ + let a = Element{ + l0: 10, + l1: 11, + l2: 12, + l3: 1292655137982008, + l4: 14 + }; +/* +2 + +3 * 2^51 + +4 * 2^102 + +5 * 2^153 + +6 * 2^204 += +154266052248863123541936069103167134583173917060132914191138818 +*/ + let b = Element{ + l0: 2, + l1: 3, + l2: 4, + l3: 5, + l4: 6 + }; + let res: Element = multiply(a, b); + +//41810357909193713957696946830561922437378062290049323977762016618127807079743 +//[1414398498170175, 1205048169289895, 995697840409273, 333510462280559, 1626165600260968] + res_equals(res, Element { + l0: 1414398498170175, + l1: 1205048169289895, + l2: 995697840409273, + l3: 333510462280559, + l4: 1626165600260968 + }); + true +} + +fn test_multiply_small_elms_3() -> bool { + +/* +1292655137982008 + +1303372017735434 * 2^51 + +595911506101250 * 2^102 + +601879629470779 * 2^153 + +50591579140481 * 2^204 += +1300760531839662334344262085631565818852980666446405835776058138544728770104 +*/ + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; +/* +2 + +3 * 2^51 + +4 * 2^102 + +5 * 2^153 + +6 * 2^204 += +154266052248863123541936069103167134583173917060132914191138818 +*/ + let b = Element{ + l0: 2, + l1: 3, + l2: 4, + l3: 5, + l4: 6 + }; + let res: Element = multiply(a, b); + +//14111756534184466847966592306453182667710228607558444947423180242606813803383 +//[1954506281775991, 334157138245186, 376444288997219, 169499236944723, 548860478185542] res_equals(res, Element { + res_equals(res, Element { + l0: 1954506281775991, + l1: 334157138245186, + l2: 376444288997219, + l3: 169499236944723, + l4: 548860478185542 + }); + true +} + +fn test_multiply_elms_4() -> bool { + +/* +1292655137982008 + +1303372017735434 * 2^51 + +595911506101250 * 2^102 + +601879629470779 * 2^153 + +50591579140481 * 2^204 += +1300760531839662334344262085631565818852980666446405835776058138544728770104 +*/ + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; +/* +1360902863141127 + +807899991388824 * 2^51 + +335483569739384 * 2^102 + +293961277766182 * 2^153 + +137209507300112 * 2^204 += +3527794837033309378261417350654351403080646879795459845564282655359926745351 +*/ + let b = Element { + l0: 1360902863141127, + l1: 807899991388824, + l2: 335483569739384, + l3: 293961277766182, + l4: 137209507300112 + }; + let res: Element = multiply(a, b); + +//26419211797770492947925431317169526880133696901606348938375383866077151145114 +//[896638975913114, 1000789340506524, 355992668009873, 806477788321681, 1027544741541094] + res_equals(res, Element { + l0: 896638975913114, + l1: 1000789340506524, + l2: 355992668009873, + l3: 806477788321681, + l4: 1027544741541094 + }); + true +} + +/* +fn test_multiply_random() -> bool { + /* + a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 + = [1292655137982008, 1303372017735434, 595911506101250, 601879629470779, 50591579140481] + = Element { + 1292655137982008, + 1303372017735434, + 595911506101250, + 601879629470779, + 50591579140481 + } + + b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 + = [1360902863141127, 807899991388824, 335483569739384, 293961277766182, 137209507300112] + = Element { + 1360902863141127, + 807899991388824, + 335483569739384, + 293961277766182, + 137209507300112 + } + + ab mod p = 26419211797770492947925431317169526880133696901606348938375383866077151145114 + = [896638975913114, 1000789340506524, 355992668009873, 806477788321681, 1027544741541094] + + */ -// let a = Element { -// l0: 1292655137982008, -// l1: 1303372017735434, -// l2: 595911506101250, -// l3: 601879629470779, -// l4: 50591579140481 -// }; - -// let b = Element { -// l0: 1360902863141127, -// l1: 807899991388824, -// l2: 335483569739384, -// l3: 293961277766182, -// l4: 137209507300112 -// }; - -// let ab = Element { -// l0: 896638975913114, -// l1: 1000789340506524, -// l2: 355992668009873, -// l3: 806477788321681, -// l4: 1027544741541094 -// }; - -// let res: Element = multiply(a, b); -// //print_el(res); -// res_equals(res, ab); -// true -// } \ No newline at end of file + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; + + let b = Element { + l0: 1360902863141127, + l1: 807899991388824, + l2: 335483569739384, + l3: 293961277766182, + l4: 137209507300112 + }; + + let ab = Element { + l0: 896638975913114, + l1: 1000789340506524, + l2: 355992668009873, + l3: 806477788321681, + l4: 1027544741541094 + }; + + + let res: Element = multiply(a, b); + // print_el(res); + res_equals(res, ab); + true +} +*/ \ No newline at end of file diff --git a/edwards25519/src/test_helpers.sw b/edwards25519/src/test_helpers.sw index 013d8ff..b92a9e9 100644 --- a/edwards25519/src/test_helpers.sw +++ b/edwards25519/src/test_helpers.sw @@ -29,6 +29,12 @@ pub fn print_U128(a: U128) { log(a.lower); } +pub fn equals_U128(res: U128, lower: u64, upper: u64) -> bool { + assert(res.upper == upper); + assert(res.lower == lower); + true +} + //converts element into array of bytes // pub fn bytes_convert (a: Element) -> [u8;32] { From ac73088f9b6ede2f7d574178685e519c8ff91e9f Mon Sep 17 00:00:00 2001 From: Manish Date: Wed, 6 Jul 2022 17:55:02 +0530 Subject: [PATCH 028/160] fn inverse added, tests for fn square added --- edwards25519/src/field_element.sw | 98 +++++++++++++++++++++++++++++-- edwards25519/src/main.sw | 72 ++++++++++++++++++++--- 2 files changed, 155 insertions(+), 15 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 8830608..bc7e40a 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -177,6 +177,12 @@ pub fn shiftRightBy51(a: U128) -> u64 { (a.upper <<(64-51)) | (a.lower >> 51) } +//returns square of an Element +pub fn square(a: Element) -> Element { + multiply(a,a) +} + + //returns a*b pub fn multiply (a: Element, b: Element) -> Element { @@ -257,11 +263,6 @@ pub fn multiply (a: Element, b: Element) -> Element { carry_propagate(res) } -//returns square of an Element -// pub fn square(a: Element) -> Element { -// multiply(a,a) -// } - // For a bignumber <= 102 bits stored in U128, // return the 51 bit coefficient and 51 bit carry fn get_coeff_and_carry(y: U128) -> (u64, u64) { @@ -315,4 +316,89 @@ pub fn equals(a: Element, b: Element) -> bool { res = res + (a.l4 ^ b.l4); res == 0 -} \ No newline at end of file +} + +// //a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p +// pub fn inverse(a: Element) -> Element { +// let mut i = 0; +// let z2 = square(a); //2 +// let mut t = square(z2); //4 +// t = square(t); //8 +// let z9 = multiply(t,a); //9 +// let z11 = multiply(z9, z2); //11 +// t = square(z11); //22 + +// let z2_5_0 = multiply(t, z9); //31 +// t = square(z2_5_0); // 62 = 2^6 - 2^1 +// while i < 4 { +// t = square(t); // 2^10 - 2^5 +// i+=1; +// } + +// let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 + +// t = square(z2_10_0); //2^11 - 2^1 +// i = 0; +// while i < 9 { +// t = square(t); //2^20 - 2^10 +// i += 1; +// } + +// let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 + +// t = square(z2_20_0); //2^21 - 2^1 +// i = 0; +// while i < 19 { +// t = square(t); //2^40 - 2^20 +// i += 1; +// } + +// t = multiply(t, z2_20_0); //2^40 - 2^0 + +// i = 0; +// while i < 10 { +// t = square(t); //2^50 - 2^10 +// } + +// let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 + +// t = square(z2_50_0); //2^51 - 2^1 + +// i = 0; +// while i < 49 { +// t = square(t); //2^100 - 2^50 +// i += 1; +// } + +// let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 + +// t = square(z2_100_0); //2^101 - 2^1 + +// i = 0; +// while i < 99 { +// t = square(t); //2^200 - 2^100 +// i += 1; +// } + +// t = multiply(t, z2_100_0); //2^200 - 2^0 + +// t = square(t); //2^201 - 2^1 + +// i = 0; +// while i < 49 { +// t = square(t); //2^250 - 2^50 +// i += 1; +// } + +// t = multiply(t, z2_50_0); //2^250 - 2^0 + +// i = 0; +// while i < 5 { +// t = square(t); //2^255 - 2^5 +// i += 1; +// } + +// t = multiply(t, z11); //2^255 - 21 = p - 2 + +// return t; +// } \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 062a502..d49f290 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -15,17 +15,18 @@ use std::u128::*; fn main() { // THESE TESTS ARE ALL OK assert(test_helpers()); - assert(test_reductions()); - assert(tests_add()); - assert(tests_scalar_mult()); - assert(tests_multiply64()); - assert(tests_add64()); - assert(tests_add_multiply64()); - assert(tests_shiftRightBy51()); - assert(tests_substract()); + // assert(test_reductions()); + // assert(tests_add()); + // assert(tests_scalar_mult()); + // assert(tests_multiply64()); + // assert(tests_add64()); + // assert(tests_add_multiply64()); + // assert(tests_shiftRightBy51()); + // assert(tests_substract()); // Multiply functions only test OK if ran 1 at a time. (?!) // assert(tests_multiply()); + // assert(tests_square()); // NOT OK @@ -1229,4 +1230,57 @@ fn test_multiply_random() -> bool { res_equals(res, ab); true } -*/ \ No newline at end of file +*/ +//--------------------------------------------------------------------------------------------------------- + +fn tests_square() -> bool { + // assert(test_square_one()); + // assert(test_square_zero()); + assert(test_square_random()); + true +} + +fn test_square_one() -> bool { + let res: Element = square(one); + res_equals(res, one); + true +} + +fn test_square_zero() -> bool { + let res: Element = square(zero); + res_equals(res, zero); + true +} + +fn test_square_random() -> bool { + /* + a = 10406084254717298682985401286246103758749877058048555650117556132341049525816 + = [404732633123850, 312158315551803, 595911506101250, 1303372017735434, 1292655137982008] + + a^2 = 108286589516275277577373161473966445398256506358898379115846293425853328039181187715348880647692926795184739504006825065723361671067040986483318450465856 + + a^2 mod p = 31042580993865580304222384966530826020546840941977848835924726765219788840807 + = [1207365348681671, 713663780369466, 912635275234964, 596790797966485, 2144628324130663] + + */ + + let a: Element = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 312158315551803, + l4: 404732633123850 + }; + + let a_square: Element = Element { + l0: 2144628324130663, + l1: 596790797966485, + l2: 912635275234964, + l3: 713663780369466, + l4: 1207365348681671 + }; + + let res: Element = square(a); + res_equals(res, a_square); + true +} \ No newline at end of file From da305181a77f3c6898571c7632b4cae3c2345c4a Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 6 Jul 2022 08:10:17 -0600 Subject: [PATCH 029/160] Run the multiply test --- edwards25519/src/main.sw | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index d49f290..e9c3741 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -14,7 +14,7 @@ use std::u128::*; fn main() { // THESE TESTS ARE ALL OK - assert(test_helpers()); + // assert(test_helpers()); // assert(test_reductions()); // assert(tests_add()); // assert(tests_scalar_mult()); @@ -25,10 +25,9 @@ fn main() { // assert(tests_substract()); // Multiply functions only test OK if ran 1 at a time. (?!) - // assert(tests_multiply()); + assert(tests_multiply()); // assert(tests_square()); - // NOT OK } From 20e7a71ee58030a264d714cc365e71f28e889f11 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 6 Jul 2022 17:38:29 -0600 Subject: [PATCH 030/160] Start on arithmetic for BLS12-381. - Fp definition and added several constants - Add of 2 Fp's -> this is WIP - Several smaller helper functions that have to be tested --- .gitattributes | 1 + bls12-381/Cargo.toml | 16 ++++ bls12-381/Forc.toml | 7 ++ bls12-381/src/fp.sw | 163 ++++++++++++++++++++++++++++++++++ bls12-381/src/main.sw | 135 ++++++++++++++++++++++++++++ bls12-381/src/test_helpers.sw | 24 +++++ 6 files changed, 346 insertions(+) create mode 100644 .gitattributes create mode 100644 bls12-381/Cargo.toml create mode 100644 bls12-381/Forc.toml create mode 100644 bls12-381/src/fp.sw create mode 100644 bls12-381/src/main.sw create mode 100644 bls12-381/src/test_helpers.sw diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1948c70 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sw linguist-language=Rust diff --git a/bls12-381/Cargo.toml b/bls12-381/Cargo.toml new file mode 100644 index 0000000..27d6243 --- /dev/null +++ b/bls12-381/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "bls12-381" +version = "0.1.0" +authors = ["HashCloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/bls12-381/Forc.toml b/bls12-381/Forc.toml new file mode 100644 index 0000000..d3112bb --- /dev/null +++ b/bls12-381/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["HashCloak"] +entry = "main.sw" +license = "Apache-2.0" +name = "bls12-381" + +[dependencies] diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw new file mode 100644 index 0000000..8f86b3c --- /dev/null +++ b/bls12-381/src/fp.sw @@ -0,0 +1,163 @@ +library fp; + +use std::u128::*; + +/* +Follows implementations +https://github.com/zkcrypto/bls12_381 +https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src + +Standard +https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-02.html#rfc.section.4.2.2 +Naming of variables follows this standard + +Additionally specifically on the instantiation of the curve +https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381 + +*/ + +// Stores field element with max 384 bits +pub struct Fp { + ls: [u64; 6], +} + +const ZERO: Fp = Fp {ls: [0, 0, 0, 0, 0, 0]}; + +/* + p = 0x1a0111ea 397fe69a 4b1ba7b6 434bacd7 64774b84 f38512bf 6730d2a0 f6b0f624 1eabfffe b153ffff b9feffff ffffaaab + = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 + (381 bits) +*/ +const MODULUS: Fp = Fp { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a] +}; + +/* + r : 0x73eda753 299d7d48 3339d808 09a1d805 53bda402 fffe5bfe ffffffff 00000001 + 52435875175126190479447740508185965837690552500527637822603658699938581184513 + 255 bits prime order of first group +*/ +const R: Fp = Fp { + ls: [0xffffffff00000001, + 0x53bda402fffe5bfe, + 0x3339d80809a1d805, + 0x73eda753299d7d48, + 0, + 0] +}; + +/* + x: 0x17f1d3a7 3197d794 2695638c 4fa9ac0f c3688c4f 9774b905 a14e3a3f 171bac58 6c55e83f f97a1aef fb3af00a db22c6bb + 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 +*/ +const G1_GENERATOR_X: Fp = Fp { + ls: [0xfb3af00adb22c6bb, + 0x6c55e83ff97a1aef, + 0xa14e3a3f171bac58, + 0xc3688c4f9774b905, + 0x2695638c4fa9ac0f, + 0x17f1d3a73197d794] +}; + +/* + y: 0x08b3f481 e3aaa0f1 a09e30ed 741d8ae4 fcf5e095 d5d00af6 00db18cb 2c04b3ed d03cc744 a2888ae4 0caa2329 46c5e7e1 + 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 +*/ +const G1_GENERATOR_Y: Fp = Fp { + ls: [0xcaa232946c5e7e1, + 0xd03cc744a2888ae4, + 0xdb18cb2c04b3ed, + 0xfcf5e095d5d00af6, + 0xa09e30ed741d8ae4, + 0x8b3f481e3aaa0f1] +}; + +// INV = -(q^{-1} mod 2^64) mod 2^64 +const INV: u64 = 0x89f3fffcfffcfffd; + +//TODO GET TESTS +//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? +//returns sum with carry of a and b +fn adc (a: u64, b: u64, carry: u64) -> (u64, u64) { + let A:U128 = U128{upper: 0, lower: a}; + let B:U128 = U128{upper: 0, lower: b}; + let Carry: U128 = U128 { upper: 0, lower: carry }; + + let sum: u64 = (A+B+Carry).lower; + let notSum = ~u64::max() - sum; + let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; + + (sum, carryOut) +} + +pub trait Add { + pub fn add(self, other: Self) -> Self; +} + +// TODO TEST +// If x >= y: x-y, else max::U128 - (y-x) +fn subtract_wrap(x: U128, y: U128) -> U128 { + if y > x { + ~U128::max() - (y - x) + } else { + x - y + } +} + +//TODO TEST +/// Compute a - (b + borrow), returning the result and the new borrow. +fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let a_128: U128 = U128 { lower: a, upper: 0}; + let b_128: U128 = U128 { lower: b, upper: 0}; + let borrow_128: U128 = U128 { lower: borrow >> 63, upper: 0}; + + let ret: U128 = subtract_wrap(a_128, b_128 + borrow_128); + (ret.lower, ret.upper) //(result, borrow) +} + +//TODO TEST +fn not(input: u64) -> u64 { + ~u64::max() - input +} + +// from https://github.com/zkcrypto/bls12_381 +//TODO TEST +// If a >= p, return a-p, else return a +fn subtract_p(a: Fp) -> Fp { + let (r0, borrow) = sbb(a.ls[0], MODULUS.ls[0], 0); + let (r1, borrow) = sbb(a.ls[1], MODULUS.ls[1], borrow); + let (r2, borrow) = sbb(a.ls[2], MODULUS.ls[2], borrow); + let (r3, borrow) = sbb(a.ls[3], MODULUS.ls[3], borrow); + let (r4, borrow) = sbb(a.ls[4], MODULUS.ls[4], borrow); + let (r5, borrow) = sbb(a.ls[5], MODULUS.ls[5], borrow); + + // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise + // borrow = 0x000...ls00. Thus, we use it as a mask! + let r0 = (a.ls[0] & borrow) | (r0 & not(borrow)); + let r1 = (a.ls[1] & borrow) | (r1 & not(borrow)); + let r2 = (a.ls[2] & borrow) | (r2 & not(borrow)); + let r3 = (a.ls[3] & borrow) | (r3 & not(borrow)); + let r4 = (a.ls[4] & borrow) | (r4 & not(borrow)); + let r5 = (a.ls[5] & borrow) | (r5 & not(borrow)); + + Fp{ ls: [r0, r1, r2, r3, r4, r5]} + } + +impl Add for Fp { + pub fn add(self, rhs: Self) -> Self { + let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); + let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); + let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); + let (d3, carry) = adc(self.ls[3], rhs.ls[3], carry); + let (d4, carry) = adc(self.ls[4], rhs.ls[4], carry); + let (d5, _) = adc(self.ls[5], rhs.ls[5], carry); + + //subtract p if needed + subtract_p(Fp{ ls: [d0, d1, d2, d3, d4, d5] }) + } +} diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw new file mode 100644 index 0000000..0edce1e --- /dev/null +++ b/bls12-381/src/main.sw @@ -0,0 +1,135 @@ +script; + +dep fp; +dep test_helpers; + +use std::{assert::assert}; +use ::fp::*; +use ::test_helpers::*; +use std::logging::log; + +fn main() { + assert(test_add()); +} + +fn test_add() -> bool { + assert(test_add_zero_to_zero()); + assert(test_add_zero_to_random()); + assert(test_add_random_to_zero()); + assert(test_add_random_to_small()); + assert(test_add_random_to_large()); + // assert(test_add_2_randoms()); + true +} + +fn test_add_zero_to_zero() -> bool { + let res: Fp = ZERO.add(ZERO); + equals_fp(res, ZERO); + true +} + +fn test_add_zero_to_random() -> bool { + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + let res: Fp = random.add(ZERO); + equals_fp(res, random); + true +} + +fn test_add_random_to_zero() -> bool { + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + /* +4478030004447473542 +2814704111667093002 +15884408734010272158 +17001047363111187578 +932823543034528547 +1051481384684610845 + */ + let res: Fp = ZERO.add(random); + equals_fp(res, random); + true +} + +fn test_add_random_to_small() -> bool { + let small = Fp { + ls: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6] + }; + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + let res: Fp = small.add(random); + equals_fp(res, Fp { + ls: [4478030004447473543, + 2814704111667093004, + 15884408734010272161, + 17001047363111187582, + 932823543034528552, + 1051481384684610851] + }); + true +} + +// TODO continue here and next test +fn test_add_random_to_large() -> bool { + let large = Fp { + ls: [~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max()] + }; + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + let res: Fp = large.add(random); + print_fp(res); + + true +} + +fn test_add_2_randoms() -> bool { + let random_1 = Fp { + ls: [0x3e2528903ca1ef86,0x270fd67a03bf9e0a,0xdc70c19599cb699e,0xebefda8057d5747a,0xcf20e11f0b1c323,0xe979cbf960fe51d] + }; + + let random_2 = Fp { + ls: [0xbaf0ad04a3886e99,0x332e25612ced0991,0x8e95f86c79cd2d4,0xc27bdcacbb447470,0xe7dfe7df4c4d002c,0x7b33227cbdf0de43] + }; +/* +a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 +b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 +a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 +[13387723108140499808, +7110911959168982110, +7018803425472956901, +2577695370959560254, +1826757397030539319, +859395849761138905] + +a+b< p is true +*/ + let res: Fp = random_1.add(random_2); + print_fp(res); +// this seems to be incorrect + true +} \ No newline at end of file diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw new file mode 100644 index 0000000..719a22d --- /dev/null +++ b/bls12-381/src/test_helpers.sw @@ -0,0 +1,24 @@ +library test_helpers; + +dep fp; + +use fp::*; +use std::{logging::log, assert::assert}; + +pub fn print_fp(a: Fp) { + log(a.ls[0]); + log(a.ls[1]); + log(a.ls[2]); + log(a.ls[3]); + log(a.ls[4]); + log(a.ls[5]); +} + +pub fn equals_fp(a: Fp, b: Fp) { + assert(a.ls[0] == b.ls[0]); + assert(a.ls[1] == b.ls[1]); + assert(a.ls[2] == b.ls[2]); + assert(a.ls[3] == b.ls[3]); + assert(a.ls[4] == b.ls[4]); + assert(a.ls[5] == b.ls[5]); +} \ No newline at end of file From e05058d75c1aeb35337a4d803d011d34e284122c Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 7 Jul 2022 15:47:46 -0600 Subject: [PATCH 031/160] - Renaming to be in line with blst impl - Added missing tests - Addition works Also here there seems to be a performance bottle neck. I can't run both subtract_p and the add tests at the same time. Therefore, one of the subtract_p tests is commented out. --- bls12-381/src/fp.sw | 164 ++------------------------ bls12-381/src/main.sw | 211 ++++++++++++++++++++++++++++------ bls12-381/src/test_helpers.sw | 8 +- 3 files changed, 187 insertions(+), 196 deletions(-) diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw index 8f86b3c..c7687a0 100644 --- a/bls12-381/src/fp.sw +++ b/bls12-381/src/fp.sw @@ -1,163 +1,15 @@ library fp; -use std::u128::*; - -/* -Follows implementations -https://github.com/zkcrypto/bls12_381 -https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src - -Standard -https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-02.html#rfc.section.4.2.2 -Naming of variables follows this standard - -Additionally specifically on the instantiation of the curve -https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381 - -*/ - -// Stores field element with max 384 bits -pub struct Fp { - ls: [u64; 6], -} +dep vec384; -const ZERO: Fp = Fp {ls: [0, 0, 0, 0, 0, 0]}; - -/* - p = 0x1a0111ea 397fe69a 4b1ba7b6 434bacd7 64774b84 f38512bf 6730d2a0 f6b0f624 1eabfffe b153ffff b9feffff ffffaaab - = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 - (381 bits) -*/ -const MODULUS: Fp = Fp { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a] -}; - -/* - r : 0x73eda753 299d7d48 3339d808 09a1d805 53bda402 fffe5bfe ffffffff 00000001 - 52435875175126190479447740508185965837690552500527637822603658699938581184513 - 255 bits prime order of first group -*/ -const R: Fp = Fp { - ls: [0xffffffff00000001, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48, - 0, - 0] -}; - -/* - x: 0x17f1d3a7 3197d794 2695638c 4fa9ac0f c3688c4f 9774b905 a14e3a3f 171bac58 6c55e83f f97a1aef fb3af00a db22c6bb - 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 -*/ -const G1_GENERATOR_X: Fp = Fp { - ls: [0xfb3af00adb22c6bb, - 0x6c55e83ff97a1aef, - 0xa14e3a3f171bac58, - 0xc3688c4f9774b905, - 0x2695638c4fa9ac0f, - 0x17f1d3a73197d794] -}; +use ::vec384::*; +use std::u128::*; /* - y: 0x08b3f481 e3aaa0f1 a09e30ed 741d8ae4 fcf5e095 d5d00af6 00db18cb 2c04b3ed d03cc744 a2888ae4 0caa2329 46c5e7e1 - 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 +Reference implementation +https://github.com/supranational/blst */ -const G1_GENERATOR_Y: Fp = Fp { - ls: [0xcaa232946c5e7e1, - 0xd03cc744a2888ae4, - 0xdb18cb2c04b3ed, - 0xfcf5e095d5d00af6, - 0xa09e30ed741d8ae4, - 0x8b3f481e3aaa0f1] -}; - -// INV = -(q^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0x89f3fffcfffcfffd; - -//TODO GET TESTS -//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? -//returns sum with carry of a and b -fn adc (a: u64, b: u64, carry: u64) -> (u64, u64) { - let A:U128 = U128{upper: 0, lower: a}; - let B:U128 = U128{upper: 0, lower: b}; - let Carry: U128 = U128 { upper: 0, lower: carry }; - - let sum: u64 = (A+B+Carry).lower; - let notSum = ~u64::max() - sum; - let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; - - (sum, carryOut) -} - -pub trait Add { - pub fn add(self, other: Self) -> Self; -} - -// TODO TEST -// If x >= y: x-y, else max::U128 - (y-x) -fn subtract_wrap(x: U128, y: U128) -> U128 { - if y > x { - ~U128::max() - (y - x) - } else { - x - y - } -} - -//TODO TEST -/// Compute a - (b + borrow), returning the result and the new borrow. -fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = U128 { lower: a, upper: 0}; - let b_128: U128 = U128 { lower: b, upper: 0}; - let borrow_128: U128 = U128 { lower: borrow >> 63, upper: 0}; - - let ret: U128 = subtract_wrap(a_128, b_128 + borrow_128); - (ret.lower, ret.upper) //(result, borrow) -} - -//TODO TEST -fn not(input: u64) -> u64 { - ~u64::max() - input -} - -// from https://github.com/zkcrypto/bls12_381 -//TODO TEST -// If a >= p, return a-p, else return a -fn subtract_p(a: Fp) -> Fp { - let (r0, borrow) = sbb(a.ls[0], MODULUS.ls[0], 0); - let (r1, borrow) = sbb(a.ls[1], MODULUS.ls[1], borrow); - let (r2, borrow) = sbb(a.ls[2], MODULUS.ls[2], borrow); - let (r3, borrow) = sbb(a.ls[3], MODULUS.ls[3], borrow); - let (r4, borrow) = sbb(a.ls[4], MODULUS.ls[4], borrow); - let (r5, borrow) = sbb(a.ls[5], MODULUS.ls[5], borrow); - - // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise - // borrow = 0x000...ls00. Thus, we use it as a mask! - let r0 = (a.ls[0] & borrow) | (r0 & not(borrow)); - let r1 = (a.ls[1] & borrow) | (r1 & not(borrow)); - let r2 = (a.ls[2] & borrow) | (r2 & not(borrow)); - let r3 = (a.ls[3] & borrow) | (r3 & not(borrow)); - let r4 = (a.ls[4] & borrow) | (r4 & not(borrow)); - let r5 = (a.ls[5] & borrow) | (r5 & not(borrow)); - - Fp{ ls: [r0, r1, r2, r3, r4, r5]} - } - -impl Add for Fp { - pub fn add(self, rhs: Self) -> Self { - let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); - let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); - let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); - let (d3, carry) = adc(self.ls[3], rhs.ls[3], carry); - let (d4, carry) = adc(self.ls[4], rhs.ls[4], carry); - let (d5, _) = adc(self.ls[5], rhs.ls[5], carry); - //subtract p if needed - subtract_p(Fp{ ls: [d0, d1, d2, d3, d4, d5] }) - } -} +pub fn add_fp(a: vec384, b: vec384) -> vec384 { + add_mod_384(a, b, BLS12_381_P) +} \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 0edce1e..75aa72b 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -1,15 +1,132 @@ script; +dep vec384; dep fp; dep test_helpers; -use std::{assert::assert}; +use std::{assert::assert, u128::*}; use ::fp::*; +use ::vec384::*; use ::test_helpers::*; use std::logging::log; fn main() { assert(test_add()); + assert(test_helpers()); +} + +fn test_helpers() -> bool { + assert(test_not()); + assert(tests_subtract_wrap()); + assert(tests_sbb()); + assert(tests_adc()); + assert(tests_subtract_p()); + true +} + +fn test_not() -> bool { + let res = not(18417751708719972248); + assert(res == 28992364989579367); + true +} + +fn tests_subtract_wrap() -> bool { + let mut res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 80, upper: 0}); + assert(res.lower == 20); + assert(res.upper == 0); + + res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 230, upper: 0}); + let res_should_be = ~U128::max() - U128 { lower: 130, upper: 0}; + assert(res == res_should_be); + true +} + +fn tests_sbb() -> bool { + // 0-0-0 should give (0,0) + let mut res = sbb(0, 0, 0); + assert(res.0 == 0); + assert(res.1 == 0); + + // 0-1-0 should give (-1, 1) + res = sbb(0, 1, 0); + assert(res.0 == ~u64::max() - 1); + assert(res.1 == 1); + + // 0-1-1 should give (-2, 1) + res = sbb(0, 1, 1); + assert(res.0 == ~u64::max() - 2); + assert(res.1 == 1); + + // a-0-1 should give (a-1, 0) + let a = 435983458; + res = sbb(a, 0, 1); + assert(res.0 == a-1); + assert(res.1 == 0); + true +} + +fn tests_adc() -> bool { + assert(test_adc_random()); + assert(test_adc_random_with_carry()); + true +} + +fn test_adc_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = adc(a, b, 0); + let a_plus_b: (u64,u64) = (1400544309406770619, 1); + + assert(res.0 == a_plus_b.0); + assert(res.1 == a_plus_b.1); + true +} + +fn test_adc_random_with_carry() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = adc(a, b, 1); + let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); + + assert(res.0 == a_plus_b_and_carry.0); + assert(res.1 == a_plus_b_and_carry.1); + true +} + +/* +These tests won't run at the same time... +*/ +fn tests_subtract_p() -> bool { + // assert(test_subtract_p_smaller()); + assert(test_subtract_p_larger()); + true +} + +fn test_subtract_p_smaller() -> bool { + let a_smaller_than_p = vec384 { + ls: [13402431016077863508, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + }; + let res = subtract_p(a_smaller_than_p, BLS12_381_P); + equals_vec384(res, a_smaller_than_p); + true +} + +fn test_subtract_p_larger() -> bool { + // p+200 + let a_larger_than_p = vec384 { ls: [13402431016077863795, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866]}; + let res = subtract_p(a_larger_than_p, BLS12_381_P); + equals_vec384(res, vec384 { ls: [200,0,0,0,0,0] }); + true } fn test_add() -> bool { @@ -17,19 +134,19 @@ fn test_add() -> bool { assert(test_add_zero_to_random()); assert(test_add_random_to_zero()); assert(test_add_random_to_small()); - assert(test_add_random_to_large()); - // assert(test_add_2_randoms()); + assert(test_add_larger_than_p()); + assert(test_add_2_randoms()); true } fn test_add_zero_to_zero() -> bool { - let res: Fp = ZERO.add(ZERO); - equals_fp(res, ZERO); + let res: vec384 = add_fp(ZERO, ZERO); + equals_vec384(res, ZERO); true } fn test_add_zero_to_random() -> bool { - let random = Fp { + let random = vec384 { ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, @@ -37,13 +154,13 @@ fn test_add_zero_to_random() -> bool { 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; - let res: Fp = random.add(ZERO); - equals_fp(res, random); + let res: vec384 = add_fp(random, ZERO); + equals_vec384(res, random); true } fn test_add_random_to_zero() -> bool { - let random = Fp { + let random = vec384 { ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, @@ -59,16 +176,16 @@ fn test_add_random_to_zero() -> bool { 932823543034528547 1051481384684610845 */ - let res: Fp = ZERO.add(random); - equals_fp(res, random); + let res: vec384 = add_fp(ZERO, random); + equals_vec384(res, random); true } fn test_add_random_to_small() -> bool { - let small = Fp { + let small = vec384 { ls: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6] }; - let random = Fp { + let random = vec384 { ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, @@ -76,8 +193,8 @@ fn test_add_random_to_small() -> bool { 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; - let res: Fp = small.add(random); - equals_fp(res, Fp { + let res: vec384 = add_fp(small, random); + equals_vec384(res, vec384 { ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, @@ -88,32 +205,50 @@ fn test_add_random_to_small() -> bool { true } -// TODO continue here and next test -fn test_add_random_to_large() -> bool { - let large = Fp { - ls: [~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max()] - }; - let random = Fp { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] +fn test_add_larger_than_p() -> bool { + /* + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 + + + 100 + is a little bit larger than p + */ + //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + let a = vec384 { + ls: [13402431016077863508, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] }; - let res: Fp = large.add(random); - print_fp(res); + let b = vec384 { ls: [100,0,0,0,0,0] }; + +// should be 13 + let res: vec384 = add_fp(a, b); + equals_vec384(res, vec384 {ls: [13,0,0,0,0,0]}); true } fn test_add_2_randoms() -> bool { - let random_1 = Fp { - ls: [0x3e2528903ca1ef86,0x270fd67a03bf9e0a,0xdc70c19599cb699e,0xebefda8057d5747a,0xcf20e11f0b1c323,0xe979cbf960fe51d] + //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] + let random_1 = vec384 { + ls: [4510245898505151773, + 8849327944066866226, + 11451510199254766964, + 782624411996506985, + 9666712539018543006, + 17492304704872943] }; - let random_2 = Fp { - ls: [0xbaf0ad04a3886e99,0x332e25612ced0991,0x8e95f86c79cd2d4,0xc27bdcacbb447470,0xe7dfe7df4c4d002c,0x7b33227cbdf0de43] +//[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + let random_2 = vec384 { + ls: [8877477209635348035, + 16708328088811667500, + 14014037299927741552, + 1795070958963053268, + 10606788931721547929, + 841903545056265961] }; /* a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 @@ -128,8 +263,12 @@ a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894 a+b< p is true */ - let res: Fp = random_1.add(random_2); - print_fp(res); -// this seems to be incorrect + let res: vec384 = add_fp(random_1, random_2); + equals_vec384(res, vec384{ ls: [13387723108140499808, + 7110911959168982110, + 7018803425472956901, + 2577695370959560254, + 1826757397030539319, + 859395849761138905] }); true } \ No newline at end of file diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 719a22d..0acdaec 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -1,11 +1,11 @@ library test_helpers; -dep fp; +dep vec384; -use fp::*; +use vec384::*; use std::{logging::log, assert::assert}; -pub fn print_fp(a: Fp) { +pub fn print_vec384(a: vec384) { log(a.ls[0]); log(a.ls[1]); log(a.ls[2]); @@ -14,7 +14,7 @@ pub fn print_fp(a: Fp) { log(a.ls[5]); } -pub fn equals_fp(a: Fp, b: Fp) { +pub fn equals_vec384(a: vec384, b: vec384) { assert(a.ls[0] == b.ls[0]); assert(a.ls[1] == b.ls[1]); assert(a.ls[2] == b.ls[2]); From 26ae8d6bf1a64def5631bd1917d2740bca289f76 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 7 Jul 2022 16:21:28 -0600 Subject: [PATCH 032/160] The actual vec384 code. --- bls12-381/src/vec384.sw | 97 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 bls12-381/src/vec384.sw diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw new file mode 100644 index 0000000..327791c --- /dev/null +++ b/bls12-381/src/vec384.sw @@ -0,0 +1,97 @@ +library vec384; + +use std::u128::*; + +// Stores field element with max 384 bits +pub struct vec384 { + ls: [u64; 6], +} + +const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; + +/* + z = -0xd201000000010000 + (z-1)^2 * (z^4 - z^2 + 1)/3 + z + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 + (381 bits) +*/ +const BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a] +}; + +// If x >= y: x-y, else max::U128 - (y-x) +pub fn subtract_wrap(x: U128, y: U128) -> U128 { + if y > x { + ~U128::max() - (y - x) + } else { + x - y + } +} + +/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). +pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let a_128: U128 = U128 { lower: a, upper: 0}; + let b_128: U128 = U128 { lower: b, upper: 0}; + let borrow_128: U128 = U128 { lower: borrow, upper: 0}; + + let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); + (res.lower, res.upper >> 63) //(result, borrow) +} + +pub fn not(input: u64) -> u64 { + ~u64::max() - input +} + +// from https://github.com/zkcrypto/bls12_381 +// If a >= p, return a-p, else return a +pub fn subtract_p(a: vec384 , p: vec384) -> vec384 { + let (r0, borrow) = sbb(a.ls[0], p.ls[0], 0); + let (r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); + let (r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); + let (r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); + let (r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); + let (r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); + + // If underflow occurred on the final limb, borrow = 1, otherwise + // borrow = 0. We convert it into a mask. + let mut mask = borrow * ~u64::max(); + let r0 = (a.ls[0] & mask) | (r0 & not(mask)); + let r1 = (a.ls[1] & mask) | (r1 & not(mask)); + let r2 = (a.ls[2] & mask) | (r2 & not(mask)); + let r3 = (a.ls[3] & mask) | (r3 & not(mask)); + let r4 = (a.ls[4] & mask) | (r4 & not(mask)); + let r5 = (a.ls[5] & mask) | (r5 & not(mask)); + + vec384{ ls: [r0, r1, r2, r3, r4, r5]} +} + +//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? +//returns sum with carry of a and b +pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { + let a_128 :U128 = U128 { upper: 0, lower: a }; + let b_128 :U128 = U128 { upper: 0, lower: b }; + let c_128: U128 = U128 { upper: 0, lower: carry }; + + let sum: u64 = (a_128 + b_128 + c_128).lower; + let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; + + (sum, carry_res) +} + +pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { + let (d0, carry) = adc(a.ls[0], b.ls[0], 0); + let (d1, carry) = adc(a.ls[1], b.ls[1], carry); + let (d2, carry) = adc(a.ls[2], b.ls[2], carry); + let (d3, carry) = adc(a.ls[3], b.ls[3], carry); + let (d4, carry) = adc(a.ls[4], b.ls[4], carry); + let (d5, _) = adc(a.ls[5], b.ls[5], carry); + + //subtract p if needed + subtract_p(vec384{ ls: [d0, d1, d2, d3, d4, d5] }, p) +} + From 4f19992d8dcedbd370642accfd58619d7270391e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 7 Jul 2022 18:15:28 -0600 Subject: [PATCH 033/160] - Implemented sub_fp - Added tests. Note that not all tests can run at the same time. However, they all pass separately. - Fixed subtract_wrap function --- bls12-381/src/fp.sw | 4 + bls12-381/src/main.sw | 177 +++++++++++++++++++++++++++++++++++++--- bls12-381/src/vec384.sw | 45 +++++++++- 3 files changed, 212 insertions(+), 14 deletions(-) diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw index c7687a0..ea2135e 100644 --- a/bls12-381/src/fp.sw +++ b/bls12-381/src/fp.sw @@ -12,4 +12,8 @@ https://github.com/supranational/blst pub fn add_fp(a: vec384, b: vec384) -> vec384 { add_mod_384(a, b, BLS12_381_P) +} + +pub fn sub_fp(a: vec384, b: vec384) -> vec384 { + sub_mod_384(a, b, BLS12_381_P) } \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 75aa72b..eddd4f7 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -11,7 +11,9 @@ use ::test_helpers::*; use std::logging::log; fn main() { - assert(test_add()); + // Don't run all add and sub tests at the same time... + // assert(test_add_fp()); + // assert(test_sub_fp()); assert(test_helpers()); } @@ -20,7 +22,8 @@ fn test_helpers() -> bool { assert(tests_subtract_wrap()); assert(tests_sbb()); assert(tests_adc()); - assert(tests_subtract_p()); + assert(test_neg()); + assert(test_subtract_p()); true } @@ -37,7 +40,10 @@ fn tests_subtract_wrap() -> bool { res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 230, upper: 0}); let res_should_be = ~U128::max() - U128 { lower: 130, upper: 0}; - assert(res == res_should_be); + // 2^128 - 230 = 340282366920938463463374607431768211226 + // [18446744073709551486, 18446744073709551615] + assert(res.lower == 18446744073709551486); + assert(res.upper == 18446744073709551615); true } @@ -47,14 +53,14 @@ fn tests_sbb() -> bool { assert(res.0 == 0); assert(res.1 == 0); - // 0-1-0 should give (-1, 1) + // 0-1-0 should give (2^64 -1, 1) res = sbb(0, 1, 0); - assert(res.0 == ~u64::max() - 1); + assert(res.0 == ~u64::max()); assert(res.1 == 1); - // 0-1-1 should give (-2, 1) + // 0-1-1 should give (2^64 -2, 1) res = sbb(0, 1, 1); - assert(res.0 == ~u64::max() - 2); + assert(res.0 == ~u64::max() - 1); assert(res.1 == 1); // a-0-1 should give (a-1, 0) @@ -93,11 +99,8 @@ fn test_adc_random_with_carry() -> bool { true } -/* -These tests won't run at the same time... -*/ -fn tests_subtract_p() -> bool { - // assert(test_subtract_p_smaller()); +fn test_subtract_p() -> bool { + assert(test_subtract_p_smaller()); assert(test_subtract_p_larger()); true } @@ -129,7 +132,7 @@ fn test_subtract_p_larger() -> bool { true } -fn test_add() -> bool { +fn test_add_fp() -> bool { assert(test_add_zero_to_zero()); assert(test_add_zero_to_random()); assert(test_add_random_to_zero()); @@ -271,4 +274,152 @@ a+b< p is true 1826757397030539319, 859395849761138905] }); true +} + +fn test_neg() -> bool { + assert(test_neg_p()); + assert(test_neg_1()); + assert(test_neg_random()); + true +} + +// neg(p, p) should result in 0 +fn test_neg_p() -> bool { + let p = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a] + }; + let res = neg(p, BLS12_381_P); + equals_vec384(res, ZERO); + true +} + +fn test_neg_1() -> bool { + /* p (=BLS12_381_P) + [13402431016077863595, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + */ + let res = neg(vec384 { ls: [1,0,0,0,0,0] }, BLS12_381_P); + let p_minus_1 = vec384 { + ls: [13402431016077863594, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + }; + + equals_vec384(res, p_minus_1); + true +} + +fn test_neg_random() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + + // p-r = + // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 + let res = neg(r, BLS12_381_P); + equals_vec384(res, vec384 { + ls: [343185552611564426, + 2882282484148780005, + 6545683898001206309, + 12914691390957992833, + 41210333997197102, + 1273825819919628179] + }); + true +} + +fn test_sub_fp() -> bool { + // assert(test_sub_zero_from_zero()); + // assert(test_sub_zero_from_random()); + // assert(test_sub_random_from_zero()); + // assert(test_sub_random_from_small()); + assert(test_sub_2_randoms()); + assert(test_sub_2_randoms_reverse()); + true +} + +fn test_sub_zero_from_zero() -> bool { + let res = sub_fp(ZERO, ZERO); + equals_vec384(res, ZERO); + true +} + +fn test_sub_zero_from_random() -> bool { + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let res = sub_fp(r, ZERO); + equals_vec384(res, r); + true +} + +fn test_sub_random_from_zero() -> bool { + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let res = sub_fp(ZERO, r); + // p-r (is the same as 0-r mod p) + equals_vec384(res, vec384 { + ls: [343185552611564426, + 2882282484148780005, + 6545683898001206309, + 12914691390957992833, + 41210333997197102, + 1273825819919628179] + }); + true +} + +fn test_sub_random_from_small() -> bool { + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let small = vec384 { + ls: [1, 2, 3, 4, 5, 6] + }; + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + + let res: vec384 = sub_fp(small, r); + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + equals_vec384(res, vec384{ ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185]}); + true +} + +fn test_sub_2_randoms() -> bool { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let res: vec384 = sub_fp(a, b); + equals_vec384(res, vec384{ ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019]}); + true +} + +fn test_sub_2_randoms_reverse() -> bool { + // Same a,b from test_sub_2_randoms only subtract the other way around + let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; + let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let res: vec384 = sub_fp(b, a); + equals_vec384(res, vec384{ ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846]}); + true } \ No newline at end of file diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index 327791c..f981752 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -27,7 +27,16 @@ const BLS12_381_P: vec384 = vec384 { // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { - ~U128::max() - (y - x) + ~U128::max() - (y - x - U128 { lower: 1, upper: 0}) + } else { + x - y + } +} + +// If x >= y: x-y, else max::U64 - (y-x) +pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { + if y > x { + ~u64::max() - (y - x - 1) } else { x - y } @@ -83,6 +92,7 @@ pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { (sum, carry_res) } +// from https://github.com/zkcrypto/bls12_381 pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { let (d0, carry) = adc(a.ls[0], b.ls[0], 0); let (d1, carry) = adc(a.ls[1], b.ls[1], carry); @@ -95,3 +105,36 @@ pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { subtract_p(vec384{ ls: [d0, d1, d2, d3, d4, d5] }, p) } +// from https://github.com/zkcrypto/bls12_381 +pub fn neg(a: vec384, p: vec384) -> vec384 { + let (d0, borrow) = sbb(p.ls[0], a.ls[0], 0); + let (d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); + let (d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); + let (d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); + let (d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); + let (d5, _) = sbb(p.ls[5], a.ls[5], borrow); + + // We need a mask that's 0 when a==p and 2^65-1 otherwise + // TODO improve this + let mut a_is_p = 0; + if (a.ls[0] | a.ls[1] | a.ls[2] | a.ls[3] | a.ls[4] | a.ls[5]) == 0 { + a_is_p = 1; //don't know is there's a native conversion + } else { + a_is_p = 0; + } + + let mask = subtract_wrap_64(a_is_p, 1); + + vec384{ ls: [ + d0 & mask, + d1 & mask, + d2 & mask, + d3 & mask, + d4 & mask, + d5 & mask, + ]} +} + +pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { + add_mod_384(a, neg(b, p), p) +} \ No newline at end of file From a029fa108956a759a7552f157e942b275c8064ea Mon Sep 17 00:00:00 2001 From: Manish Date: Fri, 8 Jul 2022 18:06:55 +0530 Subject: [PATCH 034/160] montgomery reduction --- bls12-381/src/vec384.sw | 83 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index f981752..6406230 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -23,6 +23,8 @@ const BLS12_381_P: vec384 = vec384 { 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] }; +/// INV = -(P^{-1} mod 2^64) mod 2^64 +const INV: u64 = 0x89f3fffcfffcfffd; // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { @@ -137,4 +139,83 @@ pub fn neg(a: vec384, p: vec384) -> vec384 { pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { add_mod_384(a, neg(b, p), p) -} \ No newline at end of file +} + +//returns the result and new carry of a + b*c + carry +pub fn mac (a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let A: U128 = U128 {upper: 0, lower: a}; + let B: U128 = U128 {upper: 0, lower: b}; + let C: U128 = U128 {upper: 0, lower: c}; + let CARRY: U128 = U128 {upper: 0, lower: carry}; + let res: U128 = A + B * C + CARRY; + (res.lower, res.upper) +} + +//returns a*b mod(2^64) +pub fn multiply_wrap(a: u64, b:u64) -> u64 { + let A: U128 = U128{upper: 0, lower: a}; + let B: U128 = U128{upper: 0, lower: b}; + + (A*B).lower +} + +// from https://github.com/zkcrypto/bls12_381 +pub fn montgomery_reduction(t: [u64;12]) -> vec384 { + let mut k = multiply_wrap(t[0], INV); + + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); + let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); + let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); + let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); + let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); + let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); + let r6_7: (u64, u64) = adc(t[6], 0, r5.1); + + let k = multiply_wrap(r1.0, INV); + let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); + let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); + let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); + let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); + + let k = multiply_wrap(r2.0, INV); + let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); + let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); + let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); + + let k = multiply_wrap(r3.0, INV); + let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); + let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); + let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); + + let k = multiply_wrap(r4.0, INV); + let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); + let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); + let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); + + let k = multiply_wrap(r5.0, INV); + let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); + let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); + let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); + let r11_12 = adc(t[11], r10_11.1, r10.1); + + subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) + +} From 63b191b37b2e5b3525ad8f6013d3072c03cd3e79 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 8 Jul 2022 17:35:17 -0600 Subject: [PATCH 035/160] - added the add and subtract for fp2 with tests - added mul_by_3, mul_by_8 and lshift with tests All tests pass but cannot be run all at the same time. --- bls12-381/src/fp.sw | 28 +++++++++ bls12-381/src/main.sw | 125 +++++++++++++++++++++++++++++++++++++++- bls12-381/src/vec384.sw | 26 +++++++++ 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw index ea2135e..5f16d71 100644 --- a/bls12-381/src/fp.sw +++ b/bls12-381/src/fp.sw @@ -10,10 +10,38 @@ Reference implementation https://github.com/supranational/blst */ +// Fp + pub fn add_fp(a: vec384, b: vec384) -> vec384 { add_mod_384(a, b, BLS12_381_P) } pub fn sub_fp(a: vec384, b: vec384) -> vec384 { sub_mod_384(a, b, BLS12_381_P) +} + +pub fn mul_by_3_fp(a: vec384) -> vec384 { + mul_by_3_mod_384(a, BLS12_381_P) +} + +pub fn mul_by_8_fp(a: vec384) -> vec384 { + mul_by_8_mod_384(a, BLS12_381_P) +} + +pub fn lshift_fp(a: vec384, count: u64) -> vec384 { + lshift_mod_384(a, count, BLS12_381_P) +} + +// Fp2 + +pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = add_mod_384(a.r, b.r, BLS12_381_P); + let res_i = add_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); + let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } } \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index eddd4f7..d999e14 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -11,10 +11,76 @@ use ::test_helpers::*; use std::logging::log; fn main() { - // Don't run all add and sub tests at the same time... + // assert(fp_tests()); + assert(fp2_tests()); +} + +fn fp_tests() -> bool { + // Don't run all tests at the same time... + // assert(test_add_fp()); // assert(test_sub_fp()); - assert(test_helpers()); + // assert(test_helpers()); + assert(tests_mul_by_3_fp()); + assert(tests_mul_by_8_fp()); + assert(test_lshift_p()); + + true +} + +fn fp2_tests() -> bool { + assert(tests_add_fp2()); + assert(tests_sub_fp2()); + true +} + +fn tests_add_fp2() -> bool { + // the function should add the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; + let a_1 = vec384x { r: r_1, i: i_1 }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; + let a_2 = vec384x { r: r_2, i: i_2 }; + + let res = add_fp2(a_1, a_2); + + // real part + //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 + // i part + //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 + equals_vec384(res.r, vec384{ ls:[17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] }); + equals_vec384(res.i, vec384{ ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219]}); + true +} + +fn tests_sub_fp2() -> bool { + // the function should subtract the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; + let a_1 = vec384x { r: r_1, i: i_1 }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; + let a_2 = vec384x { r: r_2, i: i_2 }; + + let res = sub_fp2(a_1, a_2); + //real + //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 + //i + //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 + equals_vec384(res.r, vec384{ ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376]}); + equals_vec384(res.i, vec384{ ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341]}); + true } fn test_helpers() -> bool { @@ -422,4 +488,59 @@ fn test_sub_2_randoms_reverse() -> bool { let res: vec384 = sub_fp(b, a); equals_vec384(res, vec384{ ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846]}); true +} + +fn tests_mul_by_3_fp() -> bool { + //3*0=0 + let three_times_0 = mul_by_3_fp(ZERO); + equals_vec384(three_times_0, ZERO); + + // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 + let a = vec384 { ls: [5598198260030196614, 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475]}; + // a*3 mod p should be + //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 + let res = mul_by_3_fp(a); + equals_vec384(res, vec384 { ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694]}); + true +} + +fn tests_mul_by_8_fp() -> bool { + //8*0=0 + let eight_times_0 = mul_by_8_fp(ZERO); + equals_vec384(eight_times_0, ZERO); + + // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 + let a = vec384 { ls: [4748578380656466952, 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211]}; + // a*8 mod p should be + //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 + let res = mul_by_8_fp(a); + equals_vec384(res, vec384 { ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227]}); + true +} + +fn test_lshift_p() -> bool { + assert(test_1_lshift_p()); + assert(test_250_lshift_p()); + true +} + +fn test_1_lshift_p() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let res = lshift_fp(r, 1); + // 1 leftshift is *2 + //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 + equals_vec384(res, vec384{ ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374]}); + true +} + +fn test_250_lshift_p() -> bool { + //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 + let a = vec384 { ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937]}; + // leftshift 250 mod p + //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 + let res = lshift_fp(a, 250); + equals_vec384(res, vec384 { ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179]}); + true } \ No newline at end of file diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index 6406230..098728d 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -3,10 +3,17 @@ library vec384; use std::u128::*; // Stores field element with max 384 bits +// element in fp pub struct vec384 { ls: [u64; 6], } +// element in fp2 +pub struct vec384x { + r: vec384, //"real" part + i: vec384 //"imaginary" part +} + const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; /* @@ -219,3 +226,22 @@ pub fn montgomery_reduction(t: [u64;12]) -> vec384 { subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) } + +pub fn mul_by_3_mod_384(a: vec384, p: vec384) -> vec384 { + let temp = add_mod_384(a, a, p); + add_mod_384(temp, a, p) +} + +pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { + let mut i = 0; + let mut a_temp: vec384 = a; + while i < n { + a_temp = add_mod_384(a_temp, a_temp, p); + i += 1; + } + a_temp +} + +pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { + lshift_mod_384(a, 3, p) +} \ No newline at end of file From 6fcc761fdca5f2140f42f7e75301c1456ce74828 Mon Sep 17 00:00:00 2001 From: Manish Date: Mon, 11 Jul 2022 18:37:12 +0530 Subject: [PATCH 036/160] tests for montgomery not working --- bls12-381/src/main.sw | 64 ++++++++++++++++++++++++++++++- bls12-381/src/vec384.sw | 12 +++--- edwards25519/src/field_element.sw | 6 +-- edwards25519/src/main.sw | 12 +++--- 4 files changed, 79 insertions(+), 15 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index d999e14..d63b5ea 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -12,7 +12,10 @@ use std::logging::log; fn main() { // assert(fp_tests()); - assert(fp2_tests()); + // assert(fp2_tests()); + // assert(tests_montgomery_reduction()); + assert(test_multiply_wrap()); + assert(test_mac()); } fn fp_tests() -> bool { @@ -543,4 +546,63 @@ fn test_250_lshift_p() -> bool { let res = lshift_fp(a, 250); equals_vec384(res, vec384 { ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179]}); true +} + +fn test_mac() -> bool { + let a = 13282407956253574712; + let b = 7557322358563246340; + let c = 14991082624209354397; + + let res = mac(a,b,c,0); + assert(res.0 == 15211181400380206508); + assert(res.1 == 6141595689857899799); + + let carry = 1234555432334; + let res2 = mac(a,b,c,carry); + assert(res2.0 == 15211182634935638842); + assert(res2.1 == 6141595689857899799); + + true +} + +fn tests_montgomery_reduction() -> bool { + + // assert(test_montgomery_reduction_small()); + assert(test_montgomery_reduction_random()); + true + +} + +fn test_montgomery_reduction_small() -> bool { + let a: [u64;12] = [10,0,0,0,0,0,0,0,0,0,0,0]; + let res = montgomery_reduction(a); + let aModP: vec384 = vec384{ls: [10,0,0,0,0,0]}; + equals_vec384(res, aModP); + //print_vec384(res); + true +} +fn test_montgomery_reduction_random() -> bool { + + /* + a = 718573336991290032951448074998609563086566731583964696014352685991840357574242396134892012284985388079194282315681159870763888514734256711565361623988 + = [988628306351829, 5278298332222909972, 8614063320694916486, 4063307077606482163, 959683757796537189, 2169871353760194456, 6743270311476307786, 10598342506117936052] + */ + let a: [u64;12] = [10598342506117936052, 6743270311476307786, 2169871353760194456, 959683757796537189, 4063307077606482163, 8614063320694916486, 5278298332222909972, 988628306351829, 0, 0, 0, 0]; + + let ls: [u64;6] = [12961372860169786431, 10261575420116144142, 13643274042195959755, 209306746091908816, 4698088373397879190, 611003071541516788]; + let aModP: vec384 = vec384{ls: ls}; + + let res: vec384 = montgomery_reduction(a); + + equals_vec384(res, aModP); + //print_vec384(res); + true +} + +fn test_multiply_wrap() -> bool { + let a: u64 = 562706585515371056; + let b: u64 = 2854579515609623853; + let res: u64 = multiply_wrap(a, b); + assert(res == 2259604989141998192); + true } \ No newline at end of file diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index 098728d..a05c42a 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -14,7 +14,7 @@ pub struct vec384x { i: vec384 //"imaginary" part } -const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; +pub const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; /* z = -0xd201000000010000 @@ -22,7 +22,7 @@ const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 (381 bits) */ -const BLS12_381_P: vec384 = vec384 { +pub const BLS12_381_P: vec384 = vec384 { ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, @@ -31,7 +31,7 @@ const BLS12_381_P: vec384 = vec384 { 0x1a0111ea397fe69a] }; /// INV = -(P^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0x89f3fffcfffcfffd; +pub const INV: u64 = 0x89f3fffcfffcfffd; // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { @@ -154,7 +154,7 @@ pub fn mac (a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { let B: U128 = U128 {upper: 0, lower: b}; let C: U128 = U128 {upper: 0, lower: c}; let CARRY: U128 = U128 {upper: 0, lower: carry}; - let res: U128 = A + B * C + CARRY; + let res: U128 = A + (B * C) + CARRY; (res.lower, res.upper) } @@ -168,8 +168,8 @@ pub fn multiply_wrap(a: u64, b:u64) -> u64 { // from https://github.com/zkcrypto/bls12_381 pub fn montgomery_reduction(t: [u64;12]) -> vec384 { - let mut k = multiply_wrap(t[0], INV); - + let k = multiply_wrap(t[0], INV); + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index bc7e40a..73a8888 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -14,9 +14,9 @@ pub struct Element { // = (1 << 51) - 1 // But using the above expression gives the error "Could not evaluate initializer to a const declaration." -const mask_low_51_bits: u64 = 2251799813685247; -const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; -const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; +pub const mask_low_51_bits: u64 = 2251799813685247; +pub const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; +pub const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; // from NaCl impl https://cr.yp.to/ecdh.html#use fn times19(x: u64) -> u64 { diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index e9c3741..5032bbb 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -14,7 +14,7 @@ use std::u128::*; fn main() { // THESE TESTS ARE ALL OK - // assert(test_helpers()); + assert(test_helpers()); // assert(test_reductions()); // assert(tests_add()); // assert(tests_scalar_mult()); @@ -25,8 +25,9 @@ fn main() { // assert(tests_substract()); // Multiply functions only test OK if ran 1 at a time. (?!) - assert(tests_multiply()); + // assert(tests_multiply()); // assert(tests_square()); + // assert(tests_inverse()); } @@ -1171,7 +1172,7 @@ fn test_multiply_elms_4() -> bool { true } -/* + fn test_multiply_random() -> bool { /* a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 @@ -1229,7 +1230,7 @@ fn test_multiply_random() -> bool { res_equals(res, ab); true } -*/ + //--------------------------------------------------------------------------------------------------------- fn tests_square() -> bool { @@ -1282,4 +1283,5 @@ fn test_square_random() -> bool { let res: Element = square(a); res_equals(res, a_square); true -} \ No newline at end of file +} + From 2e031087fbd41e3e06d1943f2c9120428750f1e7 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 12 Jul 2022 11:37:30 -0600 Subject: [PATCH 037/160] - Added a part of the function signatures from the blst that we should implement - Added some constants - Renamed files to be more in line with blst impl --- bls12-381/src/consts.sw | 18 +++++ bls12-381/src/definitions.sw | 22 ++++++ bls12-381/src/ec1.sw | 67 +++++++++++++++++ bls12-381/src/fields.sw | 106 +++++++++++++++++++++++++++ bls12-381/src/fp.sw | 47 ------------ bls12-381/src/main.sw | 12 +-- bls12-381/src/test_helpers.sw | 4 +- bls12-381/src/{vec384.sw => vect.sw} | 80 +++++++++++++++++++- 8 files changed, 298 insertions(+), 58 deletions(-) create mode 100644 bls12-381/src/consts.sw create mode 100644 bls12-381/src/definitions.sw create mode 100644 bls12-381/src/ec1.sw create mode 100644 bls12-381/src/fields.sw delete mode 100644 bls12-381/src/fp.sw rename bls12-381/src/{vec384.sw => vect.sw} (86%) diff --git a/bls12-381/src/consts.sw b/bls12-381/src/consts.sw new file mode 100644 index 0000000..0a6c840 --- /dev/null +++ b/bls12-381/src/consts.sw @@ -0,0 +1,18 @@ +library consts; + +/* + R = 2**384 % p + = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 +*/ +pub const ONE_MONT_P: [u64; 6] = [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, +]; + +// -1/P +// -p^(-1) mod 2^64 +pub const P0: u64 = 0x89f3fffcfffcfffd; diff --git a/bls12-381/src/definitions.sw b/bls12-381/src/definitions.sw new file mode 100644 index 0000000..f09b9aa --- /dev/null +++ b/bls12-381/src/definitions.sw @@ -0,0 +1,22 @@ +library definitions; + +pub struct fp { + ls: [u64; 6] +} + +pub struct p1 { + x: fp, y: fp, z: fp +} +pub struct p1_affine { + x: fp, y: fp +} + +pub struct BLS12_381_G1 { + value: p1_affine, +} + +pub struct POINTonE1 { + x: [u64; 6], + y: [u64; 6], + z: [u64; 6] +} diff --git a/bls12-381/src/ec1.sw b/bls12-381/src/ec1.sw new file mode 100644 index 0000000..989216b --- /dev/null +++ b/bls12-381/src/ec1.sw @@ -0,0 +1,67 @@ +library ec1; + +dep fields; +dep consts; + +use ::fields::*; +use ::consts::*; + +/* + y^2 = x^3 + B + +B = (4 << 384) % P += 1514052131932888505822357196874193114600527104240479143842906308145652716846165732392247483508051665748635331395571 + +According to Zcash impl this is equal to 4 + */ +const B_E1: vec384 = { + ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, + 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, + 0x8ec9733bbf78ab2f, 0x09d645513d83de7e] +}; + +const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ + /* + (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905 + a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P + = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 + */ + x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75`], + /* + (0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af6 + 00db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 << 384) % P + = 1806233535529883172442092828064561001318757138177058380995827434860385074092408792531060859215838632649768391090801 + */ + y: [0xbaac93d50ce72271, 0x8c22631a7918fd8e, 0xdd595f13570725ce, 0x51ac582950405194, 0xe1c8c3fad0059c0, 0xbbc3efc5008a26a], + z: ONE_MONT_P +}; + +const BLS12_381_NEG_G1: POINTonE1 = { /* negative generator [in Montgomery] */ + /* + (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905 + a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P + = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 + */ + x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75], + /* + (0x114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c9 + 6655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca << 384) % P + = 2196176019691784220975696997671343155238125681761949504336230701263646576398429071911626769913177031388125881468986 + */ + y: [0xff526c2af318883a, 0x92899ce4383b0270, 0x89d7738d9fa9d055, 0x12caf35ba344c12a, 0x3cff1b76964b5317, 0xe44d2ede9774430], + z: ONE_MONT_P +}; + +// TODO: why is mul by b equal to *4? +// value of b is 4 << 384 mod p +pub fn mul_by_b_onE1(in: vec384) -> vec384 { + lshift_fp(in, 2) +} + +pub fn mul_by_4b_onE1(in: vec384) -> vec384 { + lshift_fp(in, 4) +} + +pub fn POINTonE1_cneg(in: vec384, cbit: u64) -> vec384 { + cneg_mod_384(in, cbit, BLS12_381_P) +} \ No newline at end of file diff --git a/bls12-381/src/fields.sw b/bls12-381/src/fields.sw new file mode 100644 index 0000000..8448921 --- /dev/null +++ b/bls12-381/src/fields.sw @@ -0,0 +1,106 @@ +library fields; + +dep vect; +dep consts; + +use vect::*; +use consts::*; +use std::u128::*; + +/* +Reference implementation +https://github.com/supranational/blst +*/ + +// Fp + +pub fn add_fp(a: vec384, b: vec384) -> vec384 { + add_mod_384(a, b, BLS12_381_P) +} + +pub fn sub_fp(a: vec384, b: vec384) -> vec384 { + sub_mod_384(a, b, BLS12_381_P) +} + +pub fn mul_by_3_fp(a: vec384) -> vec384 { + mul_by_3_mod_384(a, BLS12_381_P) +} + +pub fn mul_by_8_fp(a: vec384) -> vec384 { + mul_by_8_mod_384(a, BLS12_381_P) +} + +pub fn lshift_fp(a: vec384, count: u64) -> vec384 { + lshift_mod_384(a, count, BLS12_381_P) +} + +pub fn rshift_fp(a: vec384, count: u64) -> vec384 { + rshift_mod_384(a, count, BLS12_381_P) +} + +pub fn div_by_2_fp(a: vec384) -> vec384 { + div_by_2_mod_384(a, BLS12_381_P) +} + +pub fn mul_fp(a: vec384, b: vec384) -> vec384 { + mul_mont_384(a, b, BLS12_381_P, P0) +} + +pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { + sqr_mont_384(a, b, BLS12_381_P, P0) +} + +// conditional negation +pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { + cneg_mod_384(a, flag, BLS12_381_P) +} + +pub fn from_fp(a: vec384) -> vec384 { + from_mont_384(a, BLS12_381_P, P0) +} + +pub fn redc_fp(a: vec768) -> vec384 { + redc_mont_384(a, BLS12_381_P, P0) +} + +// Fp2 + +pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = add_mod_384(a.r, b.r, BLS12_381_P); + let res_i = add_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); + let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn mul_by_3_fp2(a: vec384x) -> vec384x { + mul_by_3_mod_384x(a, BLS12_381_P) +} + +pub fn mul_by_8_fp2(a: vec384x) -> vec384x { + mul_by_8_mod_384x(a, BLS12_381_P) +} + +pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { + let res_r = lshift_mod_384(a.r, count, BLS12_381_P); + let res_i = lshift_mod_384(a.i, count, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn mul_fp2(a: vec384x, b: vec384x) -> vec384x { + mul_mont_384x(a, b, BLS12_381_P, P0) +} + +pub fn sqr_fp2(a: vec384x) -> vec384x { + sqr_mont_384x(a, BLS12_381_P, P0) +} + +pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { + let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); + let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} \ No newline at end of file diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw deleted file mode 100644 index 5f16d71..0000000 --- a/bls12-381/src/fp.sw +++ /dev/null @@ -1,47 +0,0 @@ -library fp; - -dep vec384; - -use ::vec384::*; -use std::u128::*; - -/* -Reference implementation -https://github.com/supranational/blst -*/ - -// Fp - -pub fn add_fp(a: vec384, b: vec384) -> vec384 { - add_mod_384(a, b, BLS12_381_P) -} - -pub fn sub_fp(a: vec384, b: vec384) -> vec384 { - sub_mod_384(a, b, BLS12_381_P) -} - -pub fn mul_by_3_fp(a: vec384) -> vec384 { - mul_by_3_mod_384(a, BLS12_381_P) -} - -pub fn mul_by_8_fp(a: vec384) -> vec384 { - mul_by_8_mod_384(a, BLS12_381_P) -} - -pub fn lshift_fp(a: vec384, count: u64) -> vec384 { - lshift_mod_384(a, count, BLS12_381_P) -} - -// Fp2 - -pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { - let res_r = add_mod_384(a.r, b.r, BLS12_381_P); - let res_i = add_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } -} - -pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { - let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); - let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } -} \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index d63b5ea..1d57c63 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -1,12 +1,14 @@ script; -dep vec384; -dep fp; +dep vect; +dep fields; dep test_helpers; +dep consts; -use std::{assert::assert, u128::*}; -use ::fp::*; -use ::vec384::*; +use std::{assert::assert, u128::*, option::*}; +use ::fields::*; +use ::vect::*; +use ::consts::*; use ::test_helpers::*; use std::logging::log; diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 0acdaec..9f1c8d6 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -1,8 +1,8 @@ library test_helpers; -dep vec384; +dep vect; -use vec384::*; +use vect::*; use std::{logging::log, assert::assert}; pub fn print_vec384(a: vec384) { diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vect.sw similarity index 86% rename from bls12-381/src/vec384.sw rename to bls12-381/src/vect.sw index a05c42a..a4e4875 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vect.sw @@ -1,6 +1,6 @@ -library vec384; +library vect; -use std::u128::*; +use std::{u128::*, vec::Vec}; // Stores field element with max 384 bits // element in fp @@ -8,13 +8,19 @@ pub struct vec384 { ls: [u64; 6], } +pub struct vec768 { + ls: [u64; 12], +} + // element in fp2 pub struct vec384x { r: vec384, //"real" part i: vec384 //"imaginary" part } +//TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; +pub const ZERO_X: vec384x = vec384x { r: ZERO, i: ZERO }; /* z = -0xd201000000010000 @@ -33,6 +39,33 @@ pub const BLS12_381_P: vec384 = vec384 { /// INV = -(P^{-1} mod 2^64) mod 2^64 pub const INV: u64 = 0x89f3fffcfffcfffd; + + +// START FUNCTIONS + + + +pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + +pub fn sqr_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + +pub fn redc_mont_384(a: vec768, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + +pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + + // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { @@ -227,11 +260,20 @@ pub fn montgomery_reduction(t: [u64;12]) -> vec384 { } +pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { + lshift_mod_384(a, 3, p) +} + pub fn mul_by_3_mod_384(a: vec384, p: vec384) -> vec384 { let temp = add_mod_384(a, a, p); add_mod_384(temp, a, p) } +pub fn cneg_mod_384(a: vec384, flag: u64, p: vec384) -> vec384 { + //TODO + ZERO +} + pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { let mut i = 0; let mut a_temp: vec384 = a; @@ -242,6 +284,36 @@ pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { a_temp } -pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { - lshift_mod_384(a, 3, p) +pub fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { + //TODO + ZERO +} + +pub fn div_by_2_mod_384(a: vec384, p: vec384) -> vec384 { + //TODO + ZERO +} + + + + + +pub fn mul_by_8_mod_384x(a: vec384x, p: vec384) -> vec384x { + //TODO + ZERO_X +} + +pub fn mul_by_3_mod_384x(a: vec384x, p: vec384) -> vec384x { + //TODO + ZERO_X +} + +pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { + //TODO. Has a non-assembly impl in blst in src/no_asm.h + ZERO_X +} + +pub fn sqr_mont_384x(a: vec384x, p: vec384, n0: u64) -> vec384x { + //TODO. Has a non-assembly impl in blst in src/vect.c + ZERO_X } \ No newline at end of file From 82af47b6b272bc88f7eeec25c9e5dba559c5fdbd Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 12 Jul 2022 18:44:14 -0600 Subject: [PATCH 038/160] - Implemented add_ mod_n, with tests that are equal to add_fp. More test have to be added for other values of n - Added TODOs to indicate where we can work on --- bls12-381/src/ec1.sw | 20 ++++++-- bls12-381/src/fields.sw | 21 +++++++- bls12-381/src/main.sw | 90 +++++++++++++++++++++++++++++++++-- bls12-381/src/test_helpers.sw | 11 ++++- bls12-381/src/vect.sw | 66 ++++++++++++++++++++++++- 5 files changed, 198 insertions(+), 10 deletions(-) diff --git a/bls12-381/src/ec1.sw b/bls12-381/src/ec1.sw index 989216b..adb3a2a 100644 --- a/bls12-381/src/ec1.sw +++ b/bls12-381/src/ec1.sw @@ -52,16 +52,30 @@ const BLS12_381_NEG_G1: POINTonE1 = { /* negative generator [in Montgomery] * z: ONE_MONT_P }; +// TODO TEST // TODO: why is mul by b equal to *4? // value of b is 4 << 384 mod p pub fn mul_by_b_onE1(in: vec384) -> vec384 { lshift_fp(in, 2) } +// TODO TEST pub fn mul_by_4b_onE1(in: vec384) -> vec384 { lshift_fp(in, 4) } -pub fn POINTonE1_cneg(in: vec384, cbit: u64) -> vec384 { - cneg_mod_384(in, cbit, BLS12_381_P) -} \ No newline at end of file +// TODO TEST +pub fn POINTonE1_cneg(p: POINTonE1, cbit: u64) -> vec384 { + cneg_fp(p.y, cbit) +} + +// TODO TEST +pub fn blst_p1_cneg(a: POINTonE1, cbit: u32) -> vec384 { + POINTonE1_cneg(a, is_zero(cbit) ^1) +} + +pub fn POINTonE1_from_Jacobian(in: POINTonE1) -> POINTonE1 { + //TODO + POINTonE1 { x: ONE_MONT_P, y: ONE_MONT_P, z: ONE_MONT_P } +} + diff --git a/bls12-381/src/fields.sw b/bls12-381/src/fields.sw index 8448921..22d8e43 100644 --- a/bls12-381/src/fields.sw +++ b/bls12-381/src/fields.sw @@ -34,31 +34,38 @@ pub fn lshift_fp(a: vec384, count: u64) -> vec384 { lshift_mod_384(a, count, BLS12_381_P) } +//TODO TEST pub fn rshift_fp(a: vec384, count: u64) -> vec384 { rshift_mod_384(a, count, BLS12_381_P) } +//TODO TEST pub fn div_by_2_fp(a: vec384) -> vec384 { div_by_2_mod_384(a, BLS12_381_P) } +//TODO TEST pub fn mul_fp(a: vec384, b: vec384) -> vec384 { mul_mont_384(a, b, BLS12_381_P, P0) } +//TODO TEST pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { sqr_mont_384(a, b, BLS12_381_P, P0) } +//TODO TEST // conditional negation pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { cneg_mod_384(a, flag, BLS12_381_P) } +//TODO TEST pub fn from_fp(a: vec384) -> vec384 { from_mont_384(a, BLS12_381_P, P0) } +//TODO TEST pub fn redc_fp(a: vec768) -> vec384 { redc_mont_384(a, BLS12_381_P, P0) } @@ -77,30 +84,42 @@ pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { vec384x { r: res_r, i: res_i } } +//TODO TEST pub fn mul_by_3_fp2(a: vec384x) -> vec384x { mul_by_3_mod_384x(a, BLS12_381_P) } +//TODO TEST pub fn mul_by_8_fp2(a: vec384x) -> vec384x { mul_by_8_mod_384x(a, BLS12_381_P) } +//TODO TEST pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { let res_r = lshift_mod_384(a.r, count, BLS12_381_P); let res_i = lshift_mod_384(a.i, count, BLS12_381_P); vec384x { r: res_r, i: res_i } } +//TODO TEST pub fn mul_fp2(a: vec384x, b: vec384x) -> vec384x { mul_mont_384x(a, b, BLS12_381_P, P0) } +//TODO TEST pub fn sqr_fp2(a: vec384x) -> vec384x { sqr_mont_384x(a, BLS12_381_P, P0) } +//TODO TEST pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); vec384x { r: res_r, i: res_i } -} \ No newline at end of file +} + +pub fn reciprocal_fp(inp: vec384x) -> vec384x { + //TODO + ZERO_X +} + diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 1d57c63..7a80775 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -5,7 +5,7 @@ dep fields; dep test_helpers; dep consts; -use std::{assert::assert, u128::*, option::*}; +use std::{assert::assert, u128::*, option::*, vec::Vec}; use ::fields::*; use ::vect::*; use ::consts::*; @@ -16,8 +16,9 @@ fn main() { // assert(fp_tests()); // assert(fp2_tests()); // assert(tests_montgomery_reduction()); - assert(test_multiply_wrap()); - assert(test_mac()); + // assert(test_multiply_wrap()); + // assert(test_mac()); + assert(vect_subfunctions_tests()); } fn fp_tests() -> bool { @@ -39,6 +40,16 @@ fn fp2_tests() -> bool { true } +fn vect_subfunctions_tests() -> bool { + // add_mod_n tests. They have the same test values as add_fp + // which should be correct, but of course add_mod_n should do more + assert(test_add_zero_to_zero_addn()); + assert(test_add_zero_to_random_addn()); + assert(test_add_random_to_small_addn()); + + true +} + fn tests_add_fp2() -> bool { // the function should add the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 @@ -219,6 +230,79 @@ fn test_add_zero_to_zero() -> bool { true } +fn get_test_vectors() -> (Vec, Vec) { + let mut zero_vec = ~Vec::new::(); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + (zero_vec, p_vec) +} + +fn test_add_zero_to_zero_addn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_add_zero_to_random_addn() -> bool { + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let (zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_add_random_to_small_addn() -> bool { + let mut small_vec = ~Vec::new::(); + small_vec.push(0x1); + small_vec.push(0x2); + small_vec.push(0x3); + small_vec.push(0x4); + small_vec.push(0x5); + small_vec.push(0x6); + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let mut res_vec = ~Vec::new::(); + res_vec.push(4478030004447473543); + res_vec.push(2814704111667093004); + res_vec.push(15884408734010272161); + res_vec.push(17001047363111187582); + res_vec.push(932823543034528552); + res_vec.push(1051481384684610851); + + let (_, p_vec) = get_test_vectors(); + + let res = add_mod_n(small_vec, random_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + true +} + fn test_add_zero_to_random() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 9f1c8d6..5ff6c73 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -3,7 +3,7 @@ library test_helpers; dep vect; use vect::*; -use std::{logging::log, assert::assert}; +use std::{logging::log, assert::assert, vec::Vec}; pub fn print_vec384(a: vec384) { log(a.ls[0]); @@ -21,4 +21,13 @@ pub fn equals_vec384(a: vec384, b: vec384) { assert(a.ls[3] == b.ls[3]); assert(a.ls[4] == b.ls[4]); assert(a.ls[5] == b.ls[5]); +} + +pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { + let mut i = 0; + while i < n { + assert(unpack_or_0(a.get(i)) == unpack_or_0(a.get(i))); + i += 1; + } + true } \ No newline at end of file diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index a4e4875..d0141d4 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -1,6 +1,6 @@ library vect; -use std::{u128::*, vec::Vec}; +use std::{u128::*, vec::Vec, option::*}; // Stores field element with max 384 bits // element in fp @@ -43,10 +43,59 @@ pub const INV: u64 = 0x89f3fffcfffcfffd; // START FUNCTIONS +pub fn unpack_or_0(x: Option) -> u64 { + match x { + Option::Some(val) => val , + Option::None => 0, + } +} + +pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { + let mut limbx: u64 = 0; + let mut carry: u64 = 0; + let mut tmp = ~Vec::new::(); + let mut i = 0; + while i < n { + let (limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); + tmp.insert(i, limb); + carry = temp_carry; + i += 1; + } + + let mut ret = ~Vec::new::(); + let mut borrow: u64 = 0; + i = 0; + while i < n { + let (limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); + ret.insert(i, limb); + borrow = temp_borrow; + i += 1; + } + + let mask: u64 = borrow * ~u64::max(); + let mut res = ~Vec::new::(); + i = 0; + while i < n { + let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); + res.insert(i, value); + i += 1; + } + res +} pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { - //TODO + //WIP ELENA + // vec384 aa, bb, cc; + + // add_mod_n(aa, a[0], a[1], p, NLIMBS(384)); + // add_mod_n(bb, b[0], b[1], p, NLIMBS(384)); + // mul_mont_n(bb, bb, aa, p, n0, NLIMBS(384)); + // mul_mont_n(aa, a[0], b[0], p, n0, NLIMBS(384)); + // mul_mont_n(cc, a[1], b[1], p, n0, NLIMBS(384)); + // sub_mod_n(ret[0], aa, cc, p, NLIMBS(384)); + // sub_mod_n(ret[1], bb, aa, p, NLIMBS(384)); + // sub_mod_n(ret[1], ret[1], cc, p, NLIMBS(384)); ZERO } @@ -65,6 +114,19 @@ pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { ZERO } +// Original impl: +// static inline bool_t is_zero(limb_t l) +// { return (~l & (l - 1)) >> (LIMB_T_BITS - 1); } +//TODO +pub fn is_zero(l: u64) -> u64 { + // (~l & (l-1)) >> 63 + 0 +} + +pub fn vec_is_zero(a: Vec, num: u64) -> u64 { + //TODO + 0 +} // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { From f447d7e6bccb2cc1bf5dc23ab33bcce5163a3efb Mon Sep 17 00:00:00 2001 From: Manish Date: Wed, 13 Jul 2022 19:32:20 +0530 Subject: [PATCH 039/160] montgomery removed --- bls12-381/src/main.sw | 35 ------------------------- bls12-381/src/vect.sw | 60 ------------------------------------------- 2 files changed, 95 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 7a80775..3c9c251 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -15,7 +15,6 @@ use std::logging::log; fn main() { // assert(fp_tests()); // assert(fp2_tests()); - // assert(tests_montgomery_reduction()); // assert(test_multiply_wrap()); // assert(test_mac()); assert(vect_subfunctions_tests()); @@ -651,40 +650,6 @@ fn test_mac() -> bool { true } -fn tests_montgomery_reduction() -> bool { - - // assert(test_montgomery_reduction_small()); - assert(test_montgomery_reduction_random()); - true - -} - -fn test_montgomery_reduction_small() -> bool { - let a: [u64;12] = [10,0,0,0,0,0,0,0,0,0,0,0]; - let res = montgomery_reduction(a); - let aModP: vec384 = vec384{ls: [10,0,0,0,0,0]}; - equals_vec384(res, aModP); - //print_vec384(res); - true -} -fn test_montgomery_reduction_random() -> bool { - - /* - a = 718573336991290032951448074998609563086566731583964696014352685991840357574242396134892012284985388079194282315681159870763888514734256711565361623988 - = [988628306351829, 5278298332222909972, 8614063320694916486, 4063307077606482163, 959683757796537189, 2169871353760194456, 6743270311476307786, 10598342506117936052] - */ - let a: [u64;12] = [10598342506117936052, 6743270311476307786, 2169871353760194456, 959683757796537189, 4063307077606482163, 8614063320694916486, 5278298332222909972, 988628306351829, 0, 0, 0, 0]; - - let ls: [u64;6] = [12961372860169786431, 10261575420116144142, 13643274042195959755, 209306746091908816, 4698088373397879190, 611003071541516788]; - let aModP: vec384 = vec384{ls: ls}; - - let res: vec384 = montgomery_reduction(a); - - equals_vec384(res, aModP); - //print_vec384(res); - true -} - fn test_multiply_wrap() -> bool { let a: u64 = 562706585515371056; let b: u64 = 2854579515609623853; diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index d0141d4..d6c4466 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -261,66 +261,6 @@ pub fn multiply_wrap(a: u64, b:u64) -> u64 { (A*B).lower } -// from https://github.com/zkcrypto/bls12_381 -pub fn montgomery_reduction(t: [u64;12]) -> vec384 { - let k = multiply_wrap(t[0], INV); - - let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); - let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); - let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); - let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); - let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); - let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); - let r6_7: (u64, u64) = adc(t[6], 0, r5.1); - - let k = multiply_wrap(r1.0, INV); - let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); - let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); - let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); - let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); - let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); - - let k = multiply_wrap(r2.0, INV); - let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); - let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); - let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); - let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); - - let k = multiply_wrap(r3.0, INV); - let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); - let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); - let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); - - let k = multiply_wrap(r4.0, INV); - let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); - let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); - let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); - let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); - - let k = multiply_wrap(r5.0, INV); - let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); - let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); - let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); - let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); - let r11_12 = adc(t[11], r10_11.1, r10.1); - - subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) - -} pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { lshift_mod_384(a, 3, p) From 05e0048a89e83ef8fa0d9c3a631547642270321c Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 11:29:15 -0600 Subject: [PATCH 040/160] - Added mult_mon_n with tests. - Note that not all tests can be ran at the same time, gives error outOfGas. - Added to readme how to start fuel-core --- README.md | 9 + bls12-381/src/main.sw | 454 ++++++++++++++++++++++++++++-------------- bls12-381/src/vect.sw | 95 +++++++++ 3 files changed, 409 insertions(+), 149 deletions(-) diff --git a/README.md b/README.md index 6639299..b5cb961 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,11 @@ # fuel-crypto Various Cryptographic Primitives in Sway for the Fuel VM + +# Run script +First, run a fuel-core +`` ./target/debug/fuel-core --ip 127.0.0.1 --port 4000`` +Then: +`` +forc build +forc run +`` \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 3c9c251..347d5f6 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -5,7 +5,7 @@ dep fields; dep test_helpers; dep consts; -use std::{assert::assert, u128::*, option::*, vec::Vec}; +use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; use ::vect::*; use ::consts::*; @@ -40,28 +40,53 @@ fn fp2_tests() -> bool { } fn vect_subfunctions_tests() -> bool { + // NOTE: Don't run all at the same time, because will run out of gas + // add_mod_n tests. They have the same test values as add_fp // which should be correct, but of course add_mod_n should do more - assert(test_add_zero_to_zero_addn()); - assert(test_add_zero_to_random_addn()); + // assert(test_add_zero_to_zero_addn()); + // assert(test_add_zero_to_random_addn()); assert(test_add_random_to_small_addn()); + // assert(test_mul_mont_n_by_zero()); + // assert(test_mul_mont_n_zero_by_one()); + // assert(test_mul_mont_n_one_by_one()); + assert(test_mul_mont_n_random_by_one()); + assert(test_mul_mont_n_random_by_random()); true } fn tests_add_fp2() -> bool { // the function should add the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; - let a_1 = vec384x { r: r_1, i: i_1 }; - + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; - let a_2 = vec384x { r: r_2, i: i_2 }; + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; let res = add_fp2(a_1, a_2); @@ -69,32 +94,58 @@ fn tests_add_fp2() -> bool { //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 // i part //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 - equals_vec384(res.r, vec384{ ls:[17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] }); - equals_vec384(res.i, vec384{ ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219]}); + equals_vec384(res.r, vec384 { + ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] + }); + equals_vec384(res.i, vec384 { + ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] + }); true } fn tests_sub_fp2() -> bool { // the function should subtract the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; - let a_1 = vec384x { r: r_1, i: i_1 }; - + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; - let a_2 = vec384x { r: r_2, i: i_2 }; + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; let res = sub_fp2(a_1, a_2); //real //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 //i //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 - equals_vec384(res.r, vec384{ ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376]}); - equals_vec384(res.i, vec384{ ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341]}); + equals_vec384(res.r, vec384 { + ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] + }); + equals_vec384(res.i, vec384 { + ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] + }); true } @@ -115,12 +166,24 @@ fn test_not() -> bool { } fn tests_subtract_wrap() -> bool { - let mut res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 80, upper: 0}); + let mut res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 80, upper: 0 + }); assert(res.lower == 20); assert(res.upper == 0); - res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 230, upper: 0}); - let res_should_be = ~U128::max() - U128 { lower: 130, upper: 0}; + res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 230, upper: 0 + }); + let res_should_be = ~U128::max() - U128 { + lower: 130, upper: 0 + }; // 2^128 - 230 = 340282366920938463463374607431768211226 // [18446744073709551486, 18446744073709551615] assert(res.lower == 18446744073709551486); @@ -147,7 +210,7 @@ fn tests_sbb() -> bool { // a-0-1 should give (a-1, 0) let a = 435983458; res = sbb(a, 0, 1); - assert(res.0 == a-1); + assert(res.0 == a - 1); assert(res.1 == 0); true } @@ -161,8 +224,8 @@ fn tests_adc() -> bool { fn test_adc_random() -> bool { let a = 9837491998535547791; let b = 10009796384580774444; - let res:(u64,u64) = adc(a, b, 0); - let a_plus_b: (u64,u64) = (1400544309406770619, 1); + let res: (u64, u64) = adc(a, b, 0); + let a_plus_b: (u64, u64) = (1400544309406770619, 1); assert(res.0 == a_plus_b.0); assert(res.1 == a_plus_b.1); @@ -172,8 +235,8 @@ fn test_adc_random() -> bool { fn test_adc_random_with_carry() -> bool { let a = 9837491998535547791; let b = 10009796384580774444; - let res:(u64,u64) = adc(a, b, 1); - let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); + let res: (u64, u64) = adc(a, b, 1); + let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); assert(res.0 == a_plus_b_and_carry.0); assert(res.1 == a_plus_b_and_carry.1); @@ -187,13 +250,9 @@ fn test_subtract_p() -> bool { } fn test_subtract_p_smaller() -> bool { - let a_smaller_than_p = vec384 { + let a_smaller_than_p = vec384 { ls: [13402431016077863508, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] }; let res = subtract_p(a_smaller_than_p, BLS12_381_P); equals_vec384(res, a_smaller_than_p); @@ -201,15 +260,15 @@ fn test_subtract_p_smaller() -> bool { } fn test_subtract_p_larger() -> bool { - // p+200 - let a_larger_than_p = vec384 { ls: [13402431016077863795, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866]}; + // p+200 + let a_larger_than_p = vec384 { + ls: [13402431016077863795, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; let res = subtract_p(a_larger_than_p, BLS12_381_P); - equals_vec384(res, vec384 { ls: [200,0,0,0,0,0] }); + equals_vec384(res, vec384 { + ls: [200, 0, 0, 0, 0, 0] + }); true } @@ -245,13 +304,100 @@ fn get_test_vectors() -> (Vec, Vec) { p_vec.push(0x64774b84f38512bf); p_vec.push(0x4b1ba7b6434bacd7); p_vec.push(0x1a0111ea397fe69a); - + (zero_vec, p_vec) } +fn test_mul_mont_n_by_zero() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn get_one_vec() -> Vec { + let mut one_vec = ~Vec::new::(); + one_vec.push(1); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec +} + +fn test_mul_mont_n_zero_by_one() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_mul_mont_n_one_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); + equals_vec(res, one_vec, 6); + true +} + + +fn test_mul_mont_n_random_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); +//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r_vec = ~Vec::new::(); + r_vec.push(0x54439c4ae7869f30); + r_vec.push(0xa7fdefad55c032ba); + r_vec.push(0x21282f739c0a15e7); + r_vec.push(0x6cc7a6e8c38430ff); + r_vec.push(0x50db69783b321139); + r_vec.push(0xba78745dadd17a93); + let one_vec = get_one_vec(); + + let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); + equals_vec(res, r_vec, 6); + true +} + +fn test_mul_mont_n_random_by_random() -> bool { + let(_, p_vec) = get_test_vectors(); +//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(0x54439c4ae7869f30); + r1_vec.push(0xa7fdefad55c032ba); + r1_vec.push(0x21282f739c0a15e7); + r1_vec.push(0x6cc7a6e8c38430ff); + r1_vec.push(0x50db69783b321139); + r1_vec.push(0xba78745dadd17a93); +//845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(0xeb6f61c69e4c7eef); + r2_vec.push(0xa70784fb3f9ac549); + r2_vec.push(0x91f41a633e1d9601); + r2_vec.push(0xf89a44e9a52e99e); + r2_vec.push(0x1eb242ddd39638bc); + r2_vec.push(0x57e6ed499f0c7c1); + +//1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + let mut res_vec = ~Vec::new::(); + res_vec.push(0x42863c4b7ea22ad7); + res_vec.push(0x27627bfa644b580d); + res_vec.push(0x16930ecb9e3a308f); + res_vec.push(0xd5802a33c5512d6a); + res_vec.push(0x19591b38f5515036); + res_vec.push(0x7546b2615f748cd); + let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); + equals_vec(res, res_vec, 6); + true +} + fn test_add_zero_to_zero_addn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - + let(zero_vec, p_vec) = get_test_vectors(); + let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); equals_vec(res, zero_vec, 6); true @@ -265,7 +411,7 @@ fn test_add_zero_to_random_addn() -> bool { random_vec.push(0xebefda8057d5747a); random_vec.push(0xcf20e11f0b1c323); random_vec.push(0xe979cbf960fe51d); - let (zero_vec, p_vec) = get_test_vectors(); + let(zero_vec, p_vec) = get_test_vectors(); let res = add_mod_n(random_vec, zero_vec, p_vec, 6); equals_vec(res, random_vec, 6); @@ -295,7 +441,7 @@ fn test_add_random_to_small_addn() -> bool { res_vec.push(932823543034528552); res_vec.push(1051481384684610851); - let (_, p_vec) = get_test_vectors(); + let(_, p_vec) = get_test_vectors(); let res = add_mod_n(small_vec, random_vec, p_vec, 6); equals_vec(res, res_vec, 6); @@ -305,11 +451,7 @@ fn test_add_random_to_small_addn() -> bool { fn test_add_zero_to_random() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; let res: vec384 = add_fp(random, ZERO); equals_vec384(res, random); @@ -319,11 +461,7 @@ fn test_add_zero_to_random() -> bool { fn test_add_random_to_zero() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; /* 4478030004447473542 @@ -340,24 +478,16 @@ fn test_add_random_to_zero() -> bool { fn test_add_random_to_small() -> bool { let small = vec384 { - ls: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6] + ls: [0x1, + 0x2, 0x3, 0x4, 0x5, 0x6] }; let random = vec384 { ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; let res: vec384 = add_fp(small, random); equals_vec384(res, vec384 { - ls: [4478030004447473543, - 2814704111667093004, - 15884408734010272161, - 17001047363111187582, - 932823543034528552, - 1051481384684610851] + ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] }); true } @@ -372,18 +502,19 @@ fn test_add_larger_than_p() -> bool { //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] let a = vec384 { ls: [13402431016077863508, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] }; - let b = vec384 { ls: [100,0,0,0,0,0] }; + let b = vec384 { + ls: [100, + 0, 0, 0, 0, 0] + }; -// should be 13 + // should be 13 let res: vec384 = add_fp(a, b); - equals_vec384(res, vec384 {ls: [13,0,0,0,0,0]}); + equals_vec384(res, vec384 { + ls: [13, 0, 0, 0, 0, 0] + }); true } @@ -391,23 +522,15 @@ fn test_add_2_randoms() -> bool { //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] let random_1 = vec384 { ls: [4510245898505151773, - 8849327944066866226, - 11451510199254766964, - 782624411996506985, - 9666712539018543006, - 17492304704872943] + 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] }; -//[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] let random_2 = vec384 { - ls: [8877477209635348035, - 16708328088811667500, - 14014037299927741552, - 1795070958963053268, - 10606788931721547929, - 841903545056265961] - }; -/* + ls: [8877477209635348035, + 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + }; + /* a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 @@ -421,12 +544,9 @@ a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894 a+b< p is true */ let res: vec384 = add_fp(random_1, random_2); - equals_vec384(res, vec384{ ls: [13387723108140499808, - 7110911959168982110, - 7018803425472956901, - 2577695370959560254, - 1826757397030539319, - 859395849761138905] }); + equals_vec384(res, vec384 { + ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] + }); true } @@ -441,11 +561,7 @@ fn test_neg() -> bool { fn test_neg_p() -> bool { let p = vec384 { ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a] + 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] }; let res = neg(p, BLS12_381_P); equals_vec384(res, ZERO); @@ -461,14 +577,13 @@ fn test_neg_1() -> bool { 5412103778470702295, 1873798617647539866] */ - let res = neg(vec384 { ls: [1,0,0,0,0,0] }, BLS12_381_P); + let res = neg(vec384 { + ls: [1, 0, 0, 0, 0, 0] + }, + BLS12_381_P); let p_minus_1 = vec384 { ls: [13402431016077863594, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] }; equals_vec384(res, p_minus_1); @@ -478,18 +593,16 @@ fn test_neg_1() -> bool { fn test_neg_random() -> bool { //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; - // p-r = + // p-r = // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 let res = neg(r, BLS12_381_P); equals_vec384(res, vec384 { - ls: [343185552611564426, - 2882282484148780005, - 6545683898001206309, - 12914691390957992833, - 41210333997197102, - 1273825819919628179] + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] }); true } @@ -511,23 +624,24 @@ fn test_sub_zero_from_zero() -> bool { } fn test_sub_zero_from_random() -> bool { - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res = sub_fp(r, ZERO); equals_vec384(res, r); true } fn test_sub_random_from_zero() -> bool { - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res = sub_fp(ZERO, r); // p-r (is the same as 0-r mod p) equals_vec384(res, vec384 { - ls: [343185552611564426, - 2882282484148780005, - 6545683898001206309, - 12914691390957992833, - 41210333997197102, - 1273825819919628179] + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] }); true } @@ -536,45 +650,67 @@ fn test_sub_random_from_small() -> bool { // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 let small = vec384 { - ls: [1, 2, 3, 4, 5, 6] + ls: [1, + 2, 3, 4, 5, 6] }; //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res: vec384 = sub_fp(small, r); //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - equals_vec384(res, vec384{ ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185]}); + equals_vec384(res, vec384 { + ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + }); true } fn test_sub_2_randoms() -> bool { //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; - //res = + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + //res = //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] let res: vec384 = sub_fp(a, b); - equals_vec384(res, vec384{ ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019]}); + equals_vec384(res, vec384 { + ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + }); true } fn test_sub_2_randoms_reverse() -> bool { // Same a,b from test_sub_2_randoms only subtract the other way around - let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; - let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; - - //res = + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + + //res = //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p + // => mod p //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] let res: vec384 = sub_fp(b, a); - equals_vec384(res, vec384{ ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846]}); + equals_vec384(res, vec384 { + ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + }); true } @@ -584,11 +720,16 @@ fn tests_mul_by_3_fp() -> bool { equals_vec384(three_times_0, ZERO); // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 - let a = vec384 { ls: [5598198260030196614, 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475]}; + let a = vec384 { + ls: [5598198260030196614, + 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] + }; // a*3 mod p should be //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 let res = mul_by_3_fp(a); - equals_vec384(res, vec384 { ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694]}); + equals_vec384(res, vec384 { + ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] + }); true } @@ -598,11 +739,16 @@ fn tests_mul_by_8_fp() -> bool { equals_vec384(eight_times_0, ZERO); // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 - let a = vec384 { ls: [4748578380656466952, 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211]}; + let a = vec384 { + ls: [4748578380656466952, + 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] + }; // a*8 mod p should be //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 let res = mul_by_8_fp(a); - equals_vec384(res, vec384 { ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227]}); + equals_vec384(res, vec384 { + ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] + }); true } @@ -615,21 +761,31 @@ fn test_lshift_p() -> bool { fn test_1_lshift_p() -> bool { //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res = lshift_fp(r, 1); // 1 leftshift is *2 //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 - equals_vec384(res, vec384{ ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374]}); + equals_vec384(res, vec384 { + ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] + }); true } fn test_250_lshift_p() -> bool { //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 - let a = vec384 { ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937]}; + let a = vec384 { + ls: [13749239540608708580, + 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] + }; // leftshift 250 mod p //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 let res = lshift_fp(a, 250); - equals_vec384(res, vec384 { ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179]}); + equals_vec384(res, vec384 { + ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] + }); true } @@ -638,12 +794,12 @@ fn test_mac() -> bool { let b = 7557322358563246340; let c = 14991082624209354397; - let res = mac(a,b,c,0); + let res = mac(a, b, c, 0); assert(res.0 == 15211181400380206508); assert(res.1 == 6141595689857899799); let carry = 1234555432334; - let res2 = mac(a,b,c,carry); + let res2 = mac(a, b, c, carry); assert(res2.0 == 15211182634935638842); assert(res2.1 == 6141595689857899799); @@ -656,4 +812,4 @@ fn test_multiply_wrap() -> bool { let res: u64 = multiply_wrap(a, b); assert(res == 2259604989141998192); true -} \ No newline at end of file +} diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index d6c4466..ccb02e0 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -57,6 +57,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut i = 0; while i < n { + // sum with carry of a and b. Returns result and new carry let (limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); tmp.insert(i, limb); carry = temp_carry; @@ -67,6 +68,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut borrow: u64 = 0; i = 0; while i < n { + // sum with borrow of a and b. Returns result and new borrow let (limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); ret.insert(i, limb); borrow = temp_borrow; @@ -84,6 +86,97 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { res } +pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { + let mut mx: U128 = U128 { lower: unpack_or_0(b.get(0)), upper: 0}; + let mut hi: U128 = U128 { lower: 0, upper: 0}; + let mut tmp: Vec = ~Vec::new::(); + let mut i = 0; + while i < n { + let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; + let limbx = mx * ai + hi; + tmp.insert(i, limbx.lower); + hi = U128{ lower: limbx.upper, upper: 0}; + i += 1; + } + + mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; + tmp.insert(i, hi.lower); + + let mut carry: u64 = 0; + let mut j = 0; + let mut limbx: U128 = U128 { lower: 0, upper: 0}; + while true { + let p0: U128 = U128 {lower: unpack_or_0(p.get(0)), upper: 0}; + let tmp0: U128 = U128 {lower: unpack_or_0(tmp.get(0)), upper: 0}; + limbx = (mx * p0) + tmp0; + hi = U128{ lower: limbx.upper, upper: 0}; + i = 1; + while i < n { + let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; + let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + limbx = (mx * pi) + tmpi; + tmp.insert( i-1, limbx.lower); + hi = U128{ lower: limbx.upper, upper: 0}; + i += 1; + } + limbx = U128 { lower: unpack_or_0(tmp.get(i)), upper: 0} + (hi + U128{lower: carry, upper: 0}); + tmp.insert(i-1, limbx.lower); + carry = limbx.lower; + + j += 1; + if j == n { + break; + } + + mx = U128 {lower: unpack_or_0(b.get(j)), upper: 0}; + hi = U128 { lower: 0, upper: 0}; + i = 0; + while i < n { + let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; + let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + limbx = (mx * (ai + hi)) + tmpi; + tmp.insert(i, limbx.lower); + hi = U128{ lower: limbx.upper, upper: 0}; + i += 1; + } + + mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; + limbx = hi + U128{lower: carry, upper: 0}; + tmp.insert(i, limbx.lower); + carry = limbx.upper; + } + + let mut borrow: u64 = 0; + i = 0; + let mut ret: Vec = ~Vec::new::(); + while i < n { + let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; + let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + let pi_w_borrow = pi + U128{lower: borrow, upper:0}; + // Prevent underflow. When U256 arithmetic is available we can create sbb_256 + let (sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { + (tmpi - pi_w_borrow, 0) + } else { + (~U128::max() - (pi_w_borrow - tmpi - U128 { lower: 1, upper: 0}), 1) + }; + limbx = sub_res; + borrow = b_res; + ret.insert(i, limbx.lower); + borrow = limbx.upper & 0x1; + i += 1; + } + + let mask: u64 = borrow * ~u64::max(); + i = 0; + let mut res: Vec = ~Vec::new::(); + while i < n { + let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); + res.insert(i, value); + i += 1; + } + res +} + pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { //WIP ELENA // vec384 aa, bb, cc; @@ -128,6 +221,7 @@ pub fn vec_is_zero(a: Vec, num: u64) -> u64 { 0 } +// TODO rewrite without if branch // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { @@ -137,6 +231,7 @@ pub fn subtract_wrap(x: U128, y: U128) -> U128 { } } +// TODO rewrite without if branch // If x >= y: x-y, else max::U64 - (y-x) pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { if y > x { From 6f95358396e92858053f8585b40f793f33e88123 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 12:12:31 -0600 Subject: [PATCH 041/160] Formatted (forc fmt) --- bls12-381/src/consts.sw | 10 +- bls12-381/src/definitions.sw | 19 ++- bls12-381/src/ec1.sw | 8 +- bls12-381/src/fields.sw | 35 ++-- bls12-381/src/main.sw | 9 +- bls12-381/src/test_helpers.sw | 4 +- bls12-381/src/vect.sw | 295 ++++++++++++++++++++++------------ 7 files changed, 240 insertions(+), 140 deletions(-) diff --git a/bls12-381/src/consts.sw b/bls12-381/src/consts.sw index 0a6c840..18e6433 100644 --- a/bls12-381/src/consts.sw +++ b/bls12-381/src/consts.sw @@ -4,14 +4,8 @@ library consts; R = 2**384 % p = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 */ -pub const ONE_MONT_P: [u64; 6] = [ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, -]; +pub const ONE_MONT_P: [u64; +6] = [0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493, ]; // -1/P // -p^(-1) mod 2^64 diff --git a/bls12-381/src/definitions.sw b/bls12-381/src/definitions.sw index f09b9aa..cb81d90 100644 --- a/bls12-381/src/definitions.sw +++ b/bls12-381/src/definitions.sw @@ -1,14 +1,18 @@ library definitions; pub struct fp { - ls: [u64; 6] + ls: [u64; + 6], } pub struct p1 { - x: fp, y: fp, z: fp + x: fp, + y: fp, + z: fp, } pub struct p1_affine { - x: fp, y: fp + x: fp, + y: fp, } pub struct BLS12_381_G1 { @@ -16,7 +20,10 @@ pub struct BLS12_381_G1 { } pub struct POINTonE1 { - x: [u64; 6], - y: [u64; 6], - z: [u64; 6] + x: [u64; + 6], + y: [u64; + 6], + z: [u64; + 6], } diff --git a/bls12-381/src/ec1.sw b/bls12-381/src/ec1.sw index adb3a2a..f3c5bad 100644 --- a/bls12-381/src/ec1.sw +++ b/bls12-381/src/ec1.sw @@ -14,11 +14,7 @@ B = (4 << 384) % P According to Zcash impl this is equal to 4 */ -const B_E1: vec384 = { - ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, - 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, - 0x8ec9733bbf78ab2f, 0x09d645513d83de7e] -}; +const B_E1: vec384 = {ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e]}; const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ /* @@ -26,7 +22,7 @@ const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 */ - x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75`], + x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75], /* (0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af6 00db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 << 384) % P diff --git a/bls12-381/src/fields.sw b/bls12-381/src/fields.sw index 22d8e43..889b35c 100644 --- a/bls12-381/src/fields.sw +++ b/bls12-381/src/fields.sw @@ -30,12 +30,12 @@ pub fn mul_by_8_fp(a: vec384) -> vec384 { mul_by_8_mod_384(a, BLS12_381_P) } -pub fn lshift_fp(a: vec384, count: u64) -> vec384 { +pub fn lshift_fp(a: vec384, count: u64) -> vec384 { lshift_mod_384(a, count, BLS12_381_P) } //TODO TEST -pub fn rshift_fp(a: vec384, count: u64) -> vec384 { +pub fn rshift_fp(a: vec384, count: u64) -> vec384 { rshift_mod_384(a, count, BLS12_381_P) } @@ -45,28 +45,28 @@ pub fn div_by_2_fp(a: vec384) -> vec384 { } //TODO TEST -pub fn mul_fp(a: vec384, b: vec384) -> vec384 { +pub fn mul_fp(a: vec384, b: vec384) -> vec384 { mul_mont_384(a, b, BLS12_381_P, P0) } //TODO TEST -pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { +pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { sqr_mont_384(a, b, BLS12_381_P, P0) } //TODO TEST // conditional negation -pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { +pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { cneg_mod_384(a, flag, BLS12_381_P) } //TODO TEST -pub fn from_fp(a: vec384) -> vec384 { +pub fn from_fp(a: vec384) -> vec384 { from_mont_384(a, BLS12_381_P, P0) } //TODO TEST -pub fn redc_fp(a: vec768) -> vec384 { +pub fn redc_fp(a: vec768) -> vec384 { redc_mont_384(a, BLS12_381_P, P0) } @@ -75,13 +75,19 @@ pub fn redc_fp(a: vec768) -> vec384 { pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { let res_r = add_mod_384(a.r, b.r, BLS12_381_P); let res_i = add_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } //TODO TEST @@ -98,7 +104,10 @@ pub fn mul_by_8_fp2(a: vec384x) -> vec384x { pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { let res_r = lshift_mod_384(a.r, count, BLS12_381_P); let res_i = lshift_mod_384(a.i, count, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } //TODO TEST @@ -115,11 +124,13 @@ pub fn sqr_fp2(a: vec384x) -> vec384x { pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } pub fn reciprocal_fp(inp: vec384x) -> vec384x { //TODO ZERO_X } - diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 347d5f6..80a55e4 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -345,10 +345,9 @@ fn test_mul_mont_n_one_by_one() -> bool { true } - fn test_mul_mont_n_random_by_one() -> bool { let(_, p_vec) = get_test_vectors(); -//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r_vec = ~Vec::new::(); r_vec.push(0x54439c4ae7869f30); r_vec.push(0xa7fdefad55c032ba); @@ -365,7 +364,7 @@ fn test_mul_mont_n_random_by_one() -> bool { fn test_mul_mont_n_random_by_random() -> bool { let(_, p_vec) = get_test_vectors(); -//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); r1_vec.push(0x54439c4ae7869f30); r1_vec.push(0xa7fdefad55c032ba); @@ -373,7 +372,7 @@ fn test_mul_mont_n_random_by_random() -> bool { r1_vec.push(0x6cc7a6e8c38430ff); r1_vec.push(0x50db69783b321139); r1_vec.push(0xba78745dadd17a93); -//845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 let mut r2_vec = ~Vec::new::(); r2_vec.push(0xeb6f61c69e4c7eef); r2_vec.push(0xa70784fb3f9ac549); @@ -382,7 +381,7 @@ fn test_mul_mont_n_random_by_random() -> bool { r2_vec.push(0x1eb242ddd39638bc); r2_vec.push(0x57e6ed499f0c7c1); -//1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 let mut res_vec = ~Vec::new::(); res_vec.push(0x42863c4b7ea22ad7); res_vec.push(0x27627bfa644b580d); diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 5ff6c73..26e0a47 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -3,7 +3,7 @@ library test_helpers; dep vect; use vect::*; -use std::{logging::log, assert::assert, vec::Vec}; +use std::{assert::assert, logging::log, vec::Vec}; pub fn print_vec384(a: vec384) { log(a.ls[0]); @@ -30,4 +30,4 @@ pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { i += 1; } true -} \ No newline at end of file +} diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index ccb02e0..0c37c16 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -1,26 +1,32 @@ library vect; -use std::{u128::*, vec::Vec, option::*}; +use std::{option::*, u128::*, vec::Vec}; // Stores field element with max 384 bits // element in fp pub struct vec384 { - ls: [u64; 6], + ls: [u64; + 6], } pub struct vec768 { - ls: [u64; 12], + ls: [u64; + 12], } // element in fp2 pub struct vec384x { r: vec384, //"real" part - i: vec384 //"imaginary" part + i: vec384, //"imaginary" part } //TODO: remove these. Only for developing and testing atm -pub const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; -pub const ZERO_X: vec384x = vec384x { r: ZERO, i: ZERO }; +pub const ZERO: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0] +}; +pub const ZERO_X: vec384x = vec384x { + r: ZERO, i: ZERO +}; /* z = -0xd201000000010000 @@ -29,24 +35,16 @@ pub const ZERO_X: vec384x = vec384x { r: ZERO, i: ZERO }; (381 bits) */ pub const BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a] + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] }; /// INV = -(P^{-1} mod 2^64) mod 2^64 pub const INV: u64 = 0x89f3fffcfffcfffd; - - // START FUNCTIONS pub fn unpack_or_0(x: Option) -> u64 { match x { - Option::Some(val) => val , - Option::None => 0, + Option::Some(val) => val, Option::None => 0, } } @@ -58,7 +56,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut i = 0; while i < n { // sum with carry of a and b. Returns result and new carry - let (limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); + let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); tmp.insert(i, limb); carry = temp_carry; i += 1; @@ -69,7 +67,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { i = 0; while i < n { // sum with borrow of a and b. Returns result and new borrow - let (limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); + let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); ret.insert(i, limb); borrow = temp_borrow; i += 1; @@ -87,40 +85,75 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { } pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { - let mut mx: U128 = U128 { lower: unpack_or_0(b.get(0)), upper: 0}; - let mut hi: U128 = U128 { lower: 0, upper: 0}; + let mut mx: U128 = U128 { + lower: unpack_or_0(b.get(0)), + upper: 0, + }; + let mut hi: U128 = U128 { + lower: 0, + upper: 0, + }; let mut tmp: Vec = ~Vec::new::(); let mut i = 0; while i < n { - let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; + let ai: U128 = U128 { + lower: unpack_or_0(a.get(i)), upper: 0 + }; let limbx = mx * ai + hi; tmp.insert(i, limbx.lower); - hi = U128{ lower: limbx.upper, upper: 0}; + hi = U128 { + lower: limbx.upper, upper: 0 + }; i += 1; } - mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; + mx = U128 { + lower: n0, upper: 0 + } + * U128 { + lower: unpack_or_0(tmp.get(0)), upper: 0 + }; tmp.insert(i, hi.lower); let mut carry: u64 = 0; let mut j = 0; - let mut limbx: U128 = U128 { lower: 0, upper: 0}; + let mut limbx: U128 = U128 { + lower: 0, + upper: 0, + }; while true { - let p0: U128 = U128 {lower: unpack_or_0(p.get(0)), upper: 0}; - let tmp0: U128 = U128 {lower: unpack_or_0(tmp.get(0)), upper: 0}; + let p0: U128 = U128 { + lower: unpack_or_0(p.get(0)), upper: 0 + }; + let tmp0: U128 = U128 { + lower: unpack_or_0(tmp.get(0)), upper: 0 + }; limbx = (mx * p0) + tmp0; - hi = U128{ lower: limbx.upper, upper: 0}; + hi = U128 { + lower: limbx.upper, upper: 0 + }; i = 1; while i < n { - let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; - let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + let pi: U128 = U128 { + lower: unpack_or_0(p.get(i)), upper: 0 + }; + let tmpi: U128 = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 + }; limbx = (mx * pi) + tmpi; - tmp.insert( i-1, limbx.lower); - hi = U128{ lower: limbx.upper, upper: 0}; - i += 1; + tmp.insert(i - 1, limbx.lower); + hi = U128 { + lower: limbx.upper, upper: 0 + }; + i += 1; + } + limbx = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 } - limbx = U128 { lower: unpack_or_0(tmp.get(i)), upper: 0} + (hi + U128{lower: carry, upper: 0}); - tmp.insert(i-1, limbx.lower); + + (hi + U128 { + lower: carry, upper: 0 + }); + tmp.insert(i - 1, limbx.lower); carry = limbx.lower; j += 1; @@ -128,20 +161,37 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec break; } - mx = U128 {lower: unpack_or_0(b.get(j)), upper: 0}; - hi = U128 { lower: 0, upper: 0}; + mx = U128 { + lower: unpack_or_0(b.get(j)), upper: 0 + }; + hi = U128 { + lower: 0, upper: 0 + }; i = 0; while i < n { - let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; - let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + let ai: U128 = U128 { + lower: unpack_or_0(a.get(i)), upper: 0 + }; + let tmpi: U128 = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 + }; limbx = (mx * (ai + hi)) + tmpi; tmp.insert(i, limbx.lower); - hi = U128{ lower: limbx.upper, upper: 0}; + hi = U128 { + lower: limbx.upper, upper: 0 + }; i += 1; } - mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; - limbx = hi + U128{lower: carry, upper: 0}; + mx = U128 { + lower: n0, upper: 0 + } + * U128 { + lower: unpack_or_0(tmp.get(0)), upper: 0 + }; + limbx = hi + U128 { + lower: carry, upper: 0 + }; tmp.insert(i, limbx.lower); carry = limbx.upper; } @@ -150,14 +200,22 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec i = 0; let mut ret: Vec = ~Vec::new::(); while i < n { - let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; - let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; - let pi_w_borrow = pi + U128{lower: borrow, upper:0}; + let pi: U128 = U128 { + lower: unpack_or_0(p.get(i)), upper: 0 + }; + let tmpi: U128 = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 + }; + let pi_w_borrow = pi + U128 { + lower: borrow, upper: 0 + }; // Prevent underflow. When U256 arithmetic is available we can create sbb_256 - let (sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { + let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { (tmpi - pi_w_borrow, 0) } else { - (~U128::max() - (pi_w_borrow - tmpi - U128 { lower: 1, upper: 0}), 1) + (~U128::max() - (pi_w_borrow - tmpi - U128 { + lower: 1, upper: 0 + }), 1) }; limbx = sub_res; borrow = b_res; @@ -212,7 +270,7 @@ pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { // { return (~l & (l - 1)) >> (LIMB_T_BITS - 1); } //TODO pub fn is_zero(l: u64) -> u64 { - // (~l & (l-1)) >> 63 + // (~l & (l-1)) >> 63 0 } @@ -225,7 +283,9 @@ pub fn vec_is_zero(a: Vec, num: u64) -> u64 { // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { - ~U128::max() - (y - x - U128 { lower: 1, upper: 0}) + ~U128::max() - (y - x - U128 { + lower: 1, upper: 0 + }) } else { x - y } @@ -243,9 +303,18 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { /// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = U128 { lower: a, upper: 0}; - let b_128: U128 = U128 { lower: b, upper: 0}; - let borrow_128: U128 = U128 { lower: borrow, upper: 0}; + let a_128: U128 = U128 { + lower: a, + upper: 0, + }; + let b_128: U128 = U128 { + lower: b, + upper: 0, + }; + let borrow_128: U128 = U128 { + lower: borrow, + upper: 0, + }; let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); (res.lower, res.upper >> 63) //(result, borrow) @@ -257,13 +326,13 @@ pub fn not(input: u64) -> u64 { // from https://github.com/zkcrypto/bls12_381 // If a >= p, return a-p, else return a -pub fn subtract_p(a: vec384 , p: vec384) -> vec384 { - let (r0, borrow) = sbb(a.ls[0], p.ls[0], 0); - let (r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); - let (r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); - let (r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); - let (r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); - let (r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); +pub fn subtract_p(a: vec384, p: vec384) -> vec384 { + let(r0, borrow) = sbb(a.ls[0], p.ls[0], 0); + let(r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); + let(r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); + let(r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); + let(r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); + let(r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); // If underflow occurred on the final limb, borrow = 1, otherwise // borrow = 0. We convert it into a mask. @@ -275,43 +344,58 @@ pub fn subtract_p(a: vec384 , p: vec384) -> vec384 { let r4 = (a.ls[4] & mask) | (r4 & not(mask)); let r5 = (a.ls[5] & mask) | (r5 & not(mask)); - vec384{ ls: [r0, r1, r2, r3, r4, r5]} + vec384 { + ls: [r0, + r1, r2, r3, r4, r5] + } } - + //TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? //returns sum with carry of a and b pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - let a_128 :U128 = U128 { upper: 0, lower: a }; - let b_128 :U128 = U128 { upper: 0, lower: b }; - let c_128: U128 = U128 { upper: 0, lower: carry }; + let a_128: U128 = U128 { + upper: 0, + lower: a, + }; + let b_128: U128 = U128 { + upper: 0, + lower: b, + }; + let c_128: U128 = U128 { + upper: 0, + lower: carry, + }; let sum: u64 = (a_128 + b_128 + c_128).lower; - let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; + let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; (sum, carry_res) } // from https://github.com/zkcrypto/bls12_381 pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { - let (d0, carry) = adc(a.ls[0], b.ls[0], 0); - let (d1, carry) = adc(a.ls[1], b.ls[1], carry); - let (d2, carry) = adc(a.ls[2], b.ls[2], carry); - let (d3, carry) = adc(a.ls[3], b.ls[3], carry); - let (d4, carry) = adc(a.ls[4], b.ls[4], carry); - let (d5, _) = adc(a.ls[5], b.ls[5], carry); + let(d0, carry) = adc(a.ls[0], b.ls[0], 0); + let(d1, carry) = adc(a.ls[1], b.ls[1], carry); + let(d2, carry) = adc(a.ls[2], b.ls[2], carry); + let(d3, carry) = adc(a.ls[3], b.ls[3], carry); + let(d4, carry) = adc(a.ls[4], b.ls[4], carry); + let(d5, _) = adc(a.ls[5], b.ls[5], carry); //subtract p if needed - subtract_p(vec384{ ls: [d0, d1, d2, d3, d4, d5] }, p) + subtract_p(vec384 { + ls: [d0, d1, d2, d3, d4, d5] + }, + p) } // from https://github.com/zkcrypto/bls12_381 pub fn neg(a: vec384, p: vec384) -> vec384 { - let (d0, borrow) = sbb(p.ls[0], a.ls[0], 0); - let (d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); - let (d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); - let (d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); - let (d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); - let (d5, _) = sbb(p.ls[5], a.ls[5], borrow); + let(d0, borrow) = sbb(p.ls[0], a.ls[0], 0); + let(d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); + let(d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); + let(d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); + let(d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); + let(d5, _) = sbb(p.ls[5], a.ls[5], borrow); // We need a mask that's 0 when a==p and 2^65-1 otherwise // TODO improve this @@ -324,14 +408,10 @@ pub fn neg(a: vec384, p: vec384) -> vec384 { let mask = subtract_wrap_64(a_is_p, 1); - vec384{ ls: [ - d0 & mask, - d1 & mask, - d2 & mask, - d3 & mask, - d4 & mask, - d5 & mask, - ]} + vec384 { + ls: [d0 & mask, + d1 & mask, d2 & mask, d3 & mask, d4 & mask, d5 & mask, ] + } } pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { @@ -339,24 +419,41 @@ pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { } //returns the result and new carry of a + b*c + carry -pub fn mac (a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { - let A: U128 = U128 {upper: 0, lower: a}; - let B: U128 = U128 {upper: 0, lower: b}; - let C: U128 = U128 {upper: 0, lower: c}; - let CARRY: U128 = U128 {upper: 0, lower: carry}; +pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let A: U128 = U128 { + upper: 0, + lower: a, + }; + let B: U128 = U128 { + upper: 0, + lower: b, + }; + let C: U128 = U128 { + upper: 0, + lower: c, + }; + let CARRY: U128 = U128 { + upper: 0, + lower: carry, + }; let res: U128 = A + (B * C) + CARRY; (res.lower, res.upper) } -//returns a*b mod(2^64) -pub fn multiply_wrap(a: u64, b:u64) -> u64 { - let A: U128 = U128{upper: 0, lower: a}; - let B: U128 = U128{upper: 0, lower: b}; +//returns a*b mod(2^64) +pub fn multiply_wrap(a: u64, b: u64) -> u64 { + let A: U128 = U128 { + upper: 0, + lower: a, + }; + let B: U128 = U128 { + upper: 0, + lower: b, + }; - (A*B).lower + (A * B).lower } - pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { lshift_mod_384(a, 3, p) } @@ -391,10 +488,6 @@ pub fn div_by_2_mod_384(a: vec384, p: vec384) -> vec384 { ZERO } - - - - pub fn mul_by_8_mod_384x(a: vec384x, p: vec384) -> vec384x { //TODO ZERO_X @@ -413,4 +506,4 @@ pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { pub fn sqr_mont_384x(a: vec384x, p: vec384, n0: u64) -> vec384x { //TODO. Has a non-assembly impl in blst in src/vect.c ZERO_X -} \ No newline at end of file +} From a809c69d476f8e086fa8042c2905b7c0a63bdcdd Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 14:25:18 -0600 Subject: [PATCH 042/160] Added sub_mod_n with tests --- bls12-381/src/main.sw | 160 ++++++++++++++++++++++++++++++++++++++++++ bls12-381/src/vect.sw | 25 +++++++ 2 files changed, 185 insertions(+) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 80a55e4..c7505d6 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -53,6 +53,14 @@ fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_one_by_one()); assert(test_mul_mont_n_random_by_one()); assert(test_mul_mont_n_random_by_random()); + + // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added + // assert(test_sub_zero_from_zero_subn()); + // assert(test_sub_zero_from_random_subn()); + // assert(test_sub_random_from_zero_subn()); + // assert(test_sub_random_from_small_subn()); + assert(test_sub_2_randoms_subn()); + assert(test_sub_2_randoms_reverse_subn()); true } @@ -447,6 +455,158 @@ fn test_add_random_to_small_addn() -> bool { true } +fn test_sub_zero_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_sub_zero_from_random_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + + let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_sub_random_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(13059245463466299169); + random_vec.push(17774603101077980186); + random_vec.push(889990675562875390); + random_vec.push(12771390643166271294); + random_vec.push(5370893444473505192); + random_vec.push(599972797727911687); + + let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); + // p-r (is the same as 0-r mod p) + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564426); + res_vec.push(2882282484148780005); + res_vec.push(6545683898001206309); + res_vec.push(12914691390957992833); + res_vec.push(41210333997197102); + res_vec.push(1273825819919628179); + equals_vec(res, res_vec, 6); + true +} + +fn test_sub_random_from_small_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let mut small_vec = ~Vec::new::(); + small_vec.push(1); + small_vec.push(2); + small_vec.push(3); + small_vec.push(4); + small_vec.push(5); + small_vec.push(6); + + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let mut r_vec = ~Vec::new::(); + r_vec.push(13059245463466299169); + r_vec.push(17774603101077980186); + r_vec.push(889990675562875390); + r_vec.push(12771390643166271294); + r_vec.push(5370893444473505192); + r_vec.push(599972797727911687); + + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564427); + res_vec.push(2882282484148780007); + res_vec.push(6545683898001206312); + res_vec.push(12914691390957992837); + res_vec.push(41210333997197107); + res_vec.push(1273825819919628185); + + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + let res = sub_mod_n(small_vec, r_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn get_r1_r2_vecs() -> (Vec, Vec) { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let mut r1_vec = ~Vec::new::(); + r1_vec.push(10587454305359941416); + r1_vec.push(4615625447881587853); + r1_vec.push(9368308553698906485); + r1_vec.push(9494054596162055604); + r1_vec.push(377309137954328098); + r1_vec.push(766262085408033194); + + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let mut r2_vec = ~Vec::new::(); + r2_vec.push(13403040667047958534); + r2_vec.push(405585388298286396); + r2_vec.push(7295341050629342949); + r2_vec.push(1749456428444609784); + r2_vec.push(1856600841951774635); + r2_vec.push(296809876162753174); + + (r1_vec, r2_vec) +} + +fn test_sub_2_randoms_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let mut res_vec = ~Vec::new::(); + res_vec.push(15631157712021534498); + res_vec.push(4210040059583301456); + res_vec.push(2072967503069563536); + res_vec.push(7744598167717445820); + res_vec.push(16967452369712105079); + res_vec.push(469452209245280019); + + let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn test_sub_2_randoms_reverse_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let mut res_vec = ~Vec::new::(); + res_vec.push(16218017377765880713); + res_vec.push(16446845525643458734); + res_vec.push(5362707070494518163); + res_vec.push(17941483866406818307); + res_vec.push(6891395482468148831); + res_vec.push(1404346408402259846); + + let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + fn test_add_zero_to_random() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 0c37c16..f47bf1d 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -235,6 +235,31 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { + let mut limbx: u64 = 0; + let mut borrow: u64 = 0; + let mut i = 0; + let mut ret = ~Vec::new::(); + + while i < n { + let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), borrow); + ret.insert(i, limb); + borrow = temp_borrow; + i += 1; + } + + let mask: u64 = borrow * ~u64::max(); + let mut res = ~Vec::new::(); + let mut carry: u64 = 0; + while i < n { + let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(ret.get(i)), unpack_or_0(p.get(i)) & mask, carry); + res.insert(i, limb); + carry = temp_carry; + i += 1; + } + res +} + pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { //WIP ELENA // vec384 aa, bb, cc; From ec64c6209d28083a12b999b7a26019af03e9b8bc Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 16:06:26 -0600 Subject: [PATCH 043/160] Reorganized and split up tests in multiple files for clearity --- bls12-381/src/main.sw | 941 +----------------- bls12-381/src/tests/tests_helpers.sw | 295 ++++++ bls12-381/src/tests/tests_vect_fp.sw | 214 ++++ bls12-381/src/tests/tests_vect_fp2.sw | 106 ++ .../src/tests/tests_vect_subfunctions.sw | 344 +++++++ 5 files changed, 971 insertions(+), 929 deletions(-) create mode 100644 bls12-381/src/tests/tests_helpers.sw create mode 100644 bls12-381/src/tests/tests_vect_fp.sw create mode 100644 bls12-381/src/tests/tests_vect_fp2.sw create mode 100644 bls12-381/src/tests/tests_vect_subfunctions.sw diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index c7505d6..1d75162 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -4,6 +4,10 @@ dep vect; dep fields; dep test_helpers; dep consts; +dep tests/tests_vect_fp; +dep tests/tests_vect_fp2; +dep tests/tests_vect_subfunctions; +dep tests/tests_helpers; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -12,940 +16,19 @@ use ::consts::*; use ::test_helpers::*; use std::logging::log; +use ::tests_vect_fp::fp_tests; +use ::tests_vect_fp2::fp2_tests; +use ::tests_vect_subfunctions::vect_subfunctions_tests; +use ::tests_helpers::test_helpers; + fn main() { + log(78); // assert(fp_tests()); // assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); - assert(vect_subfunctions_tests()); -} - -fn fp_tests() -> bool { - // Don't run all tests at the same time... - - // assert(test_add_fp()); - // assert(test_sub_fp()); - // assert(test_helpers()); - assert(tests_mul_by_3_fp()); - assert(tests_mul_by_8_fp()); - assert(test_lshift_p()); - - true -} - -fn fp2_tests() -> bool { - assert(tests_add_fp2()); - assert(tests_sub_fp2()); - true -} - -fn vect_subfunctions_tests() -> bool { - // NOTE: Don't run all at the same time, because will run out of gas - - // add_mod_n tests. They have the same test values as add_fp - // which should be correct, but of course add_mod_n should do more - // assert(test_add_zero_to_zero_addn()); - // assert(test_add_zero_to_random_addn()); - assert(test_add_random_to_small_addn()); - - // assert(test_mul_mont_n_by_zero()); - // assert(test_mul_mont_n_zero_by_one()); - // assert(test_mul_mont_n_one_by_one()); - assert(test_mul_mont_n_random_by_one()); - assert(test_mul_mont_n_random_by_random()); - - // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added - // assert(test_sub_zero_from_zero_subn()); - // assert(test_sub_zero_from_random_subn()); - // assert(test_sub_random_from_zero_subn()); - // assert(test_sub_random_from_small_subn()); - assert(test_sub_2_randoms_subn()); - assert(test_sub_2_randoms_reverse_subn()); - true -} - -fn tests_add_fp2() -> bool { - // the function should add the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; - - //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { - ls: [16448140995118783999, - 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] - }; - //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { - ls: [1139524850979729662, - 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] - }; - let a_2 = vec384x { - r: r_2, - i: i_2, - }; - - let res = add_fp2(a_1, a_2); - - // real part - //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 - // i part - //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 - equals_vec384(res.r, vec384 { - ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] - }); - equals_vec384(res.i, vec384 { - ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] - }); - true -} - -fn tests_sub_fp2() -> bool { - // the function should subtract the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; - - //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { - ls: [16448140995118783999, - 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] - }; - //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { - ls: [1139524850979729662, - 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] - }; - let a_2 = vec384x { - r: r_2, - i: i_2, - }; - - let res = sub_fp2(a_1, a_2); - //real - //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 - //i - //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 - equals_vec384(res.r, vec384 { - ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] - }); - equals_vec384(res.i, vec384 { - ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] - }); - true -} - -fn test_helpers() -> bool { - assert(test_not()); - assert(tests_subtract_wrap()); - assert(tests_sbb()); - assert(tests_adc()); - assert(test_neg()); - assert(test_subtract_p()); - true -} - -fn test_not() -> bool { - let res = not(18417751708719972248); - assert(res == 28992364989579367); - true -} - -fn tests_subtract_wrap() -> bool { - let mut res = subtract_wrap(U128 { - lower: 100, upper: 0 - }, - U128 { - lower: 80, upper: 0 - }); - assert(res.lower == 20); - assert(res.upper == 0); - - res = subtract_wrap(U128 { - lower: 100, upper: 0 - }, - U128 { - lower: 230, upper: 0 - }); - let res_should_be = ~U128::max() - U128 { - lower: 130, upper: 0 - }; - // 2^128 - 230 = 340282366920938463463374607431768211226 - // [18446744073709551486, 18446744073709551615] - assert(res.lower == 18446744073709551486); - assert(res.upper == 18446744073709551615); - true -} - -fn tests_sbb() -> bool { - // 0-0-0 should give (0,0) - let mut res = sbb(0, 0, 0); - assert(res.0 == 0); - assert(res.1 == 0); - - // 0-1-0 should give (2^64 -1, 1) - res = sbb(0, 1, 0); - assert(res.0 == ~u64::max()); - assert(res.1 == 1); - - // 0-1-1 should give (2^64 -2, 1) - res = sbb(0, 1, 1); - assert(res.0 == ~u64::max() - 1); - assert(res.1 == 1); - - // a-0-1 should give (a-1, 0) - let a = 435983458; - res = sbb(a, 0, 1); - assert(res.0 == a - 1); - assert(res.1 == 0); - true -} - -fn tests_adc() -> bool { - assert(test_adc_random()); - assert(test_adc_random_with_carry()); - true -} - -fn test_adc_random() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res: (u64, u64) = adc(a, b, 0); - let a_plus_b: (u64, u64) = (1400544309406770619, 1); - - assert(res.0 == a_plus_b.0); - assert(res.1 == a_plus_b.1); - true -} - -fn test_adc_random_with_carry() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res: (u64, u64) = adc(a, b, 1); - let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); - - assert(res.0 == a_plus_b_and_carry.0); - assert(res.1 == a_plus_b_and_carry.1); - true -} - -fn test_subtract_p() -> bool { - assert(test_subtract_p_smaller()); - assert(test_subtract_p_larger()); - true -} - -fn test_subtract_p_smaller() -> bool { - let a_smaller_than_p = vec384 { - ls: [13402431016077863508, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - let res = subtract_p(a_smaller_than_p, BLS12_381_P); - equals_vec384(res, a_smaller_than_p); - true -} - -fn test_subtract_p_larger() -> bool { - // p+200 - let a_larger_than_p = vec384 { - ls: [13402431016077863795, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - let res = subtract_p(a_larger_than_p, BLS12_381_P); - equals_vec384(res, vec384 { - ls: [200, 0, 0, 0, 0, 0] - }); - true -} - -fn test_add_fp() -> bool { - assert(test_add_zero_to_zero()); - assert(test_add_zero_to_random()); - assert(test_add_random_to_zero()); - assert(test_add_random_to_small()); - assert(test_add_larger_than_p()); - assert(test_add_2_randoms()); - true -} - -fn test_add_zero_to_zero() -> bool { - let res: vec384 = add_fp(ZERO, ZERO); - equals_vec384(res, ZERO); - true -} - -fn get_test_vectors() -> (Vec, Vec) { - let mut zero_vec = ~Vec::new::(); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - - let mut p_vec = ~Vec::new::(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - (zero_vec, p_vec) -} - -fn test_mul_mont_n_by_zero() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn get_one_vec() -> Vec { - let mut one_vec = ~Vec::new::(); - one_vec.push(1); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec -} - -fn test_mul_mont_n_zero_by_one() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - let one_vec = get_one_vec(); - - let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_mul_mont_n_one_by_one() -> bool { - let(_, p_vec) = get_test_vectors(); - let one_vec = get_one_vec(); - - let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); - equals_vec(res, one_vec, 6); - true -} - -fn test_mul_mont_n_random_by_one() -> bool { - let(_, p_vec) = get_test_vectors(); - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r_vec = ~Vec::new::(); - r_vec.push(0x54439c4ae7869f30); - r_vec.push(0xa7fdefad55c032ba); - r_vec.push(0x21282f739c0a15e7); - r_vec.push(0x6cc7a6e8c38430ff); - r_vec.push(0x50db69783b321139); - r_vec.push(0xba78745dadd17a93); - let one_vec = get_one_vec(); - - let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); - equals_vec(res, r_vec, 6); - true -} - -fn test_mul_mont_n_random_by_random() -> bool { - let(_, p_vec) = get_test_vectors(); - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new::(); - r1_vec.push(0x54439c4ae7869f30); - r1_vec.push(0xa7fdefad55c032ba); - r1_vec.push(0x21282f739c0a15e7); - r1_vec.push(0x6cc7a6e8c38430ff); - r1_vec.push(0x50db69783b321139); - r1_vec.push(0xba78745dadd17a93); - //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new::(); - r2_vec.push(0xeb6f61c69e4c7eef); - r2_vec.push(0xa70784fb3f9ac549); - r2_vec.push(0x91f41a633e1d9601); - r2_vec.push(0xf89a44e9a52e99e); - r2_vec.push(0x1eb242ddd39638bc); - r2_vec.push(0x57e6ed499f0c7c1); - - //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 - let mut res_vec = ~Vec::new::(); - res_vec.push(0x42863c4b7ea22ad7); - res_vec.push(0x27627bfa644b580d); - res_vec.push(0x16930ecb9e3a308f); - res_vec.push(0xd5802a33c5512d6a); - res_vec.push(0x19591b38f5515036); - res_vec.push(0x7546b2615f748cd); - let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); - equals_vec(res, res_vec, 6); - true -} - -fn test_add_zero_to_zero_addn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_add_zero_to_random_addn() -> bool { - let mut random_vec = ~Vec::new::(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - let(zero_vec, p_vec) = get_test_vectors(); - - let res = add_mod_n(random_vec, zero_vec, p_vec, 6); - equals_vec(res, random_vec, 6); - true -} - -fn test_add_random_to_small_addn() -> bool { - let mut small_vec = ~Vec::new::(); - small_vec.push(0x1); - small_vec.push(0x2); - small_vec.push(0x3); - small_vec.push(0x4); - small_vec.push(0x5); - small_vec.push(0x6); - let mut random_vec = ~Vec::new::(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - let mut res_vec = ~Vec::new::(); - res_vec.push(4478030004447473543); - res_vec.push(2814704111667093004); - res_vec.push(15884408734010272161); - res_vec.push(17001047363111187582); - res_vec.push(932823543034528552); - res_vec.push(1051481384684610851); - - let(_, p_vec) = get_test_vectors(); - - let res = add_mod_n(small_vec, random_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - true -} - -fn test_sub_zero_from_zero_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_sub_zero_from_random_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let mut random_vec = ~Vec::new::(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - - let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); - equals_vec(res, random_vec, 6); - true -} - -fn test_sub_random_from_zero_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let mut random_vec = ~Vec::new::(); - random_vec.push(13059245463466299169); - random_vec.push(17774603101077980186); - random_vec.push(889990675562875390); - random_vec.push(12771390643166271294); - random_vec.push(5370893444473505192); - random_vec.push(599972797727911687); - - let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); - // p-r (is the same as 0-r mod p) - let mut res_vec = ~Vec::new::(); - res_vec.push(343185552611564426); - res_vec.push(2882282484148780005); - res_vec.push(6545683898001206309); - res_vec.push(12914691390957992833); - res_vec.push(41210333997197102); - res_vec.push(1273825819919628179); - equals_vec(res, res_vec, 6); - true -} - -fn test_sub_random_from_small_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 - //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let mut small_vec = ~Vec::new::(); - small_vec.push(1); - small_vec.push(2); - small_vec.push(3); - small_vec.push(4); - small_vec.push(5); - small_vec.push(6); - - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let mut r_vec = ~Vec::new::(); - r_vec.push(13059245463466299169); - r_vec.push(17774603101077980186); - r_vec.push(889990675562875390); - r_vec.push(12771390643166271294); - r_vec.push(5370893444473505192); - r_vec.push(599972797727911687); - - let mut res_vec = ~Vec::new::(); - res_vec.push(343185552611564427); - res_vec.push(2882282484148780007); - res_vec.push(6545683898001206312); - res_vec.push(12914691390957992837); - res_vec.push(41210333997197107); - res_vec.push(1273825819919628185); - - //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 - let res = sub_mod_n(small_vec, r_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn get_r1_r2_vecs() -> (Vec, Vec) { - //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 - //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let mut r1_vec = ~Vec::new::(); - r1_vec.push(10587454305359941416); - r1_vec.push(4615625447881587853); - r1_vec.push(9368308553698906485); - r1_vec.push(9494054596162055604); - r1_vec.push(377309137954328098); - r1_vec.push(766262085408033194); - - //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 - //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let mut r2_vec = ~Vec::new::(); - r2_vec.push(13403040667047958534); - r2_vec.push(405585388298286396); - r2_vec.push(7295341050629342949); - r2_vec.push(1749456428444609784); - r2_vec.push(1856600841951774635); - r2_vec.push(296809876162753174); - - (r1_vec, r2_vec) -} - -fn test_sub_2_randoms_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); - - //res = - //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let mut res_vec = ~Vec::new::(); - res_vec.push(15631157712021534498); - res_vec.push(4210040059583301456); - res_vec.push(2072967503069563536); - res_vec.push(7744598167717445820); - res_vec.push(16967452369712105079); - res_vec.push(469452209245280019); - - let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn test_sub_2_randoms_reverse_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); - - //res = - //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p - //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 - //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let mut res_vec = ~Vec::new::(); - res_vec.push(16218017377765880713); - res_vec.push(16446845525643458734); - res_vec.push(5362707070494518163); - res_vec.push(17941483866406818307); - res_vec.push(6891395482468148831); - res_vec.push(1404346408402259846); - - let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn test_add_zero_to_random() -> bool { - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - let res: vec384 = add_fp(random, ZERO); - equals_vec384(res, random); - true -} - -fn test_add_random_to_zero() -> bool { - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - /* -4478030004447473542 -2814704111667093002 -15884408734010272158 -17001047363111187578 -932823543034528547 -1051481384684610845 - */ - let res: vec384 = add_fp(ZERO, random); - equals_vec384(res, random); - true -} - -fn test_add_random_to_small() -> bool { - let small = vec384 { - ls: [0x1, - 0x2, 0x3, 0x4, 0x5, 0x6] - }; - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - let res: vec384 = add_fp(small, random); - equals_vec384(res, vec384 { - ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] - }); - true -} - -fn test_add_larger_than_p() -> bool { - /* - 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 - + - 100 - is a little bit larger than p - */ - //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - let a = vec384 { - ls: [13402431016077863508, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - - let b = vec384 { - ls: [100, - 0, 0, 0, 0, 0] - }; - - // should be 13 - let res: vec384 = add_fp(a, b); - equals_vec384(res, vec384 { - ls: [13, 0, 0, 0, 0, 0] - }); - true -} - -fn test_add_2_randoms() -> bool { - //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] - let random_1 = vec384 { - ls: [4510245898505151773, - 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] - }; - - //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] - let random_2 = vec384 { - ls: [8877477209635348035, - 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] - }; - /* -a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 -b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 -a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 -[13387723108140499808, -7110911959168982110, -7018803425472956901, -2577695370959560254, -1826757397030539319, -859395849761138905] - -a+b< p is true -*/ - let res: vec384 = add_fp(random_1, random_2); - equals_vec384(res, vec384 { - ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] - }); - true -} - -fn test_neg() -> bool { - assert(test_neg_p()); - assert(test_neg_1()); - assert(test_neg_random()); - true -} - -// neg(p, p) should result in 0 -fn test_neg_p() -> bool { - let p = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] - }; - let res = neg(p, BLS12_381_P); - equals_vec384(res, ZERO); - true -} - -fn test_neg_1() -> bool { - /* p (=BLS12_381_P) - [13402431016077863595, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] - */ - let res = neg(vec384 { - ls: [1, 0, 0, 0, 0, 0] - }, - BLS12_381_P); - let p_minus_1 = vec384 { - ls: [13402431016077863594, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - - equals_vec384(res, p_minus_1); - true -} - -fn test_neg_random() -> bool { - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - - // p-r = - // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 - let res = neg(r, BLS12_381_P); - equals_vec384(res, vec384 { - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] - }); - true -} - -fn test_sub_fp() -> bool { - // assert(test_sub_zero_from_zero()); - // assert(test_sub_zero_from_random()); - // assert(test_sub_random_from_zero()); - // assert(test_sub_random_from_small()); - assert(test_sub_2_randoms()); - assert(test_sub_2_randoms_reverse()); - true -} - -fn test_sub_zero_from_zero() -> bool { - let res = sub_fp(ZERO, ZERO); - equals_vec384(res, ZERO); - true -} - -fn test_sub_zero_from_random() -> bool { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = sub_fp(r, ZERO); - equals_vec384(res, r); - true -} - -fn test_sub_random_from_zero() -> bool { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = sub_fp(ZERO, r); - // p-r (is the same as 0-r mod p) - equals_vec384(res, vec384 { - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] - }); - true -} - -fn test_sub_random_from_small() -> bool { - // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 - //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let small = vec384 { - ls: [1, - 2, 3, 4, 5, 6] - }; - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - - let res: vec384 = sub_fp(small, r); - //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 - //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - equals_vec384(res, vec384 { - ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - }); - true -} - -fn test_sub_2_randoms() -> bool { - //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 - //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let a = vec384 { - ls: [10587454305359941416, - 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - }; - //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 - //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let b = vec384 { - ls: [13403040667047958534, - 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - }; - //res = - //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let res: vec384 = sub_fp(a, b); - equals_vec384(res, vec384 { - ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - }); - true -} - -fn test_sub_2_randoms_reverse() -> bool { - // Same a,b from test_sub_2_randoms only subtract the other way around - let a = vec384 { - ls: [10587454305359941416, - 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - }; - let b = vec384 { - ls: [13403040667047958534, - 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - }; - - //res = - //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p - //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 - //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let res: vec384 = sub_fp(b, a); - equals_vec384(res, vec384 { - ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - }); - true -} - -fn tests_mul_by_3_fp() -> bool { - //3*0=0 - let three_times_0 = mul_by_3_fp(ZERO); - equals_vec384(three_times_0, ZERO); - - // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 - let a = vec384 { - ls: [5598198260030196614, - 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] - }; - // a*3 mod p should be - //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 - let res = mul_by_3_fp(a); - equals_vec384(res, vec384 { - ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] - }); - true -} - -fn tests_mul_by_8_fp() -> bool { - //8*0=0 - let eight_times_0 = mul_by_8_fp(ZERO); - equals_vec384(eight_times_0, ZERO); - - // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 - let a = vec384 { - ls: [4748578380656466952, - 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] - }; - // a*8 mod p should be - //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 - let res = mul_by_8_fp(a); - equals_vec384(res, vec384 { - ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] - }); - true -} - -fn test_lshift_p() -> bool { - assert(test_1_lshift_p()); - assert(test_250_lshift_p()); - true -} - -fn test_1_lshift_p() -> bool { - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = lshift_fp(r, 1); - // 1 leftshift is *2 - //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 - equals_vec384(res, vec384 { - ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] - }); - true -} - -fn test_250_lshift_p() -> bool { - //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 - let a = vec384 { - ls: [13749239540608708580, - 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] - }; - // leftshift 250 mod p - //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 - let res = lshift_fp(a, 250); - equals_vec384(res, vec384 { - ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] - }); - true + // assert(vect_subfunctions_tests()); + assert(test_helpers()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_helpers.sw b/bls12-381/src/tests/tests_helpers.sw new file mode 100644 index 0000000..6eabbf0 --- /dev/null +++ b/bls12-381/src/tests/tests_helpers.sw @@ -0,0 +1,295 @@ +library tests_helpers; + + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::{assert::assert, u128::*}; + +pub fn test_helpers() -> bool { + assert(test_not()); + assert(tests_subtract_wrap()); + assert(tests_sbb()); + assert(tests_adc()); + assert(test_neg()); + assert(test_subtract_p()); + true +} + +fn test_not() -> bool { + let res = not(18417751708719972248); + assert(res == 28992364989579367); + true +} + +fn tests_subtract_wrap() -> bool { + let mut res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 80, upper: 0 + }); + assert(res.lower == 20); + assert(res.upper == 0); + + res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 230, upper: 0 + }); + let res_should_be = ~U128::max() - U128 { + lower: 130, upper: 0 + }; + // 2^128 - 230 = 340282366920938463463374607431768211226 + // [18446744073709551486, 18446744073709551615] + assert(res.lower == 18446744073709551486); + assert(res.upper == 18446744073709551615); + true +} + +fn tests_sbb() -> bool { + // 0-0-0 should give (0,0) + let mut res = sbb(0, 0, 0); + assert(res.0 == 0); + assert(res.1 == 0); + + // 0-1-0 should give (2^64 -1, 1) + res = sbb(0, 1, 0); + assert(res.0 == ~u64::max()); + assert(res.1 == 1); + + // 0-1-1 should give (2^64 -2, 1) + res = sbb(0, 1, 1); + assert(res.0 == ~u64::max() - 1); + assert(res.1 == 1); + + // a-0-1 should give (a-1, 0) + let a = 435983458; + res = sbb(a, 0, 1); + assert(res.0 == a - 1); + assert(res.1 == 0); + true +} + +fn tests_adc() -> bool { + assert(test_adc_random()); + assert(test_adc_random_with_carry()); + true +} + +fn test_adc_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res: (u64, u64) = adc(a, b, 0); + let a_plus_b: (u64, u64) = (1400544309406770619, 1); + + assert(res.0 == a_plus_b.0); + assert(res.1 == a_plus_b.1); + true +} + +fn test_adc_random_with_carry() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res: (u64, u64) = adc(a, b, 1); + let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); + + assert(res.0 == a_plus_b_and_carry.0); + assert(res.1 == a_plus_b_and_carry.1); + true +} + +fn test_subtract_p() -> bool { + assert(test_subtract_p_smaller()); + assert(test_subtract_p_larger()); + true +} + +fn test_subtract_p_smaller() -> bool { + let a_smaller_than_p = vec384 { + ls: [13402431016077863508, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + let res = subtract_p(a_smaller_than_p, BLS12_381_P); + equals_vec384(res, a_smaller_than_p); + true +} + +fn test_subtract_p_larger() -> bool { + // p+200 + let a_larger_than_p = vec384 { + ls: [13402431016077863795, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + let res = subtract_p(a_larger_than_p, BLS12_381_P); + equals_vec384(res, vec384 { + ls: [200, 0, 0, 0, 0, 0] + }); + true +} + +fn test_neg() -> bool { + assert(test_neg_p()); + assert(test_neg_1()); + assert(test_neg_random()); + true +} + +// neg(p, p) should result in 0 +fn test_neg_p() -> bool { + let p = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] + }; + let res = neg(p, BLS12_381_P); + equals_vec384(res, ZERO); + true +} + +fn test_neg_1() -> bool { + /* p (=BLS12_381_P) + [13402431016077863595, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + */ + let res = neg(vec384 { + ls: [1, 0, 0, 0, 0, 0] + }, + BLS12_381_P); + let p_minus_1 = vec384 { + ls: [13402431016077863594, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + + equals_vec384(res, p_minus_1); + true +} + +fn test_neg_random() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + + // p-r = + // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 + let res = neg(r, BLS12_381_P); + equals_vec384(res, vec384 { + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] + }); + true +} + +fn test_sub_fp() -> bool { + // assert(test_sub_zero_from_zero()); + // assert(test_sub_zero_from_random()); + // assert(test_sub_random_from_zero()); + // assert(test_sub_random_from_small()); + assert(test_sub_2_randoms()); + assert(test_sub_2_randoms_reverse()); + true +} + +fn test_sub_zero_from_zero() -> bool { + let res = sub_fp(ZERO, ZERO); + equals_vec384(res, ZERO); + true +} + +fn test_sub_zero_from_random() -> bool { + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + let res = sub_fp(r, ZERO); + equals_vec384(res, r); + true +} + +fn test_sub_random_from_zero() -> bool { + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + let res = sub_fp(ZERO, r); + // p-r (is the same as 0-r mod p) + equals_vec384(res, vec384 { + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] + }); + true +} + +fn test_sub_random_from_small() -> bool { + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let small = vec384 { + ls: [1, + 2, 3, 4, 5, 6] + }; + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + + let res: vec384 = sub_fp(small, r); + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + equals_vec384(res, vec384 { + ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + }); + true +} + +fn test_sub_2_randoms() -> bool { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let res: vec384 = sub_fp(a, b); + equals_vec384(res, vec384 { + ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + }); + true +} + +fn test_sub_2_randoms_reverse() -> bool { + // Same a,b from test_sub_2_randoms only subtract the other way around + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let res: vec384 = sub_fp(b, a); + equals_vec384(res, vec384 { + ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + }); + true +} diff --git a/bls12-381/src/tests/tests_vect_fp.sw b/bls12-381/src/tests/tests_vect_fp.sw new file mode 100644 index 0000000..c0a607b --- /dev/null +++ b/bls12-381/src/tests/tests_vect_fp.sw @@ -0,0 +1,214 @@ +library tests_vect_fp; + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::assert::assert; + +pub fn fp_tests() -> bool { + // Don't run all tests at the same time... + + // assert(test_add_fp()); + // assert(test_sub_fp()); + // assert(test_helpers()); + // assert(tests_mul_by_3_fp()); + // assert(tests_mul_by_8_fp()); + assert(test_lshift_p()); + + true +} + +fn test_add_fp() -> bool { + assert(test_add_zero_to_zero()); + assert(test_add_zero_to_random()); + assert(test_add_random_to_zero()); + assert(test_add_random_to_small()); + assert(test_add_larger_than_p()); + assert(test_add_2_randoms()); + true +} + +fn test_add_zero_to_zero() -> bool { + let res: vec384 = add_fp(ZERO, ZERO); + equals_vec384(res, ZERO); + true +} + +fn test_add_zero_to_random() -> bool { + let random = vec384 { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] + }; + let res: vec384 = add_fp(random, ZERO); + equals_vec384(res, random); + true +} + +fn test_add_random_to_zero() -> bool { + let random = vec384 { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] + }; + /* +4478030004447473542 +2814704111667093002 +15884408734010272158 +17001047363111187578 +932823543034528547 +1051481384684610845 + */ + let res: vec384 = add_fp(ZERO, random); + equals_vec384(res, random); + true +} + +fn test_add_random_to_small() -> bool { + let small = vec384 { + ls: [0x1, + 0x2, 0x3, 0x4, 0x5, 0x6] + }; + let random = vec384 { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] + }; + let res: vec384 = add_fp(small, random); + equals_vec384(res, vec384 { + ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] + }); + true +} + +fn test_add_larger_than_p() -> bool { + /* + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 + + + 100 + is a little bit larger than p + */ + //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + let a = vec384 { + ls: [13402431016077863508, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + + let b = vec384 { + ls: [100, + 0, 0, 0, 0, 0] + }; + + // should be 13 + let res: vec384 = add_fp(a, b); + equals_vec384(res, vec384 { + ls: [13, 0, 0, 0, 0, 0] + }); + true +} + +fn test_add_2_randoms() -> bool { + //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] + let random_1 = vec384 { + ls: [4510245898505151773, + 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] + }; + + //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + let random_2 = vec384 { + ls: [8877477209635348035, + 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + }; + /* +a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 +b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 +a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 +[13387723108140499808, +7110911959168982110, +7018803425472956901, +2577695370959560254, +1826757397030539319, +859395849761138905] + +a+b< p is true +*/ + let res: vec384 = add_fp(random_1, random_2); + equals_vec384(res, vec384 { + ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] + }); + true +} + + +fn tests_mul_by_3_fp() -> bool { + //3*0=0 + let three_times_0 = mul_by_3_fp(ZERO); + equals_vec384(three_times_0, ZERO); + + // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 + let a = vec384 { + ls: [5598198260030196614, + 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] + }; + // a*3 mod p should be + //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 + let res = mul_by_3_fp(a); + equals_vec384(res, vec384 { + ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] + }); + true +} + +fn tests_mul_by_8_fp() -> bool { + //8*0=0 + let eight_times_0 = mul_by_8_fp(ZERO); + equals_vec384(eight_times_0, ZERO); + + // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 + let a = vec384 { + ls: [4748578380656466952, + 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] + }; + // a*8 mod p should be + //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 + let res = mul_by_8_fp(a); + equals_vec384(res, vec384 { + ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] + }); + true +} + +fn test_lshift_p() -> bool { + assert(test_1_lshift_p()); + assert(test_250_lshift_p()); + true +} + +fn test_1_lshift_p() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + let res = lshift_fp(r, 1); + // 1 leftshift is *2 + //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 + equals_vec384(res, vec384 { + ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] + }); + true +} + +fn test_250_lshift_p() -> bool { + //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 + let a = vec384 { + ls: [13749239540608708580, + 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] + }; + // leftshift 250 mod p + //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 + let res = lshift_fp(a, 250); + equals_vec384(res, vec384 { + ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] + }); + true +} diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls12-381/src/tests/tests_vect_fp2.sw new file mode 100644 index 0000000..e3104a3 --- /dev/null +++ b/bls12-381/src/tests/tests_vect_fp2.sw @@ -0,0 +1,106 @@ +library tests_vect_fp2; + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::assert::assert; + +pub fn fp2_tests() -> bool { + assert(tests_add_fp2()); + // assert(tests_sub_fp2()); + true +} + +fn tests_add_fp2() -> bool { + // the function should add the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; + + let res = add_fp2(a_1, a_2); + + // real part + //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 + // i part + //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 + equals_vec384(res.r, vec384 { + ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] + }); + equals_vec384(res.i, vec384 { + ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] + }); + true +} + +fn tests_sub_fp2() -> bool { + // the function should subtract the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; + + let res = sub_fp2(a_1, a_2); + //real + //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 + //i + //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 + equals_vec384(res.r, vec384 { + ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] + }); + equals_vec384(res.i, vec384 { + ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] + }); + true +} diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw new file mode 100644 index 0000000..6431ad6 --- /dev/null +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -0,0 +1,344 @@ +library tests_vect_subfunctions; + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::{assert::assert, vec::Vec}; + +pub fn vect_subfunctions_tests() -> bool { + // NOTE: Don't run all at the same time, because will run out of gas + + // add_mod_n tests. They have the same test values as add_fp + // which should be correct, but of course add_mod_n should do more + // assert(test_add_zero_to_zero_addn()); + // assert(test_add_zero_to_random_addn()); + assert(test_add_random_to_small_addn()); + + // assert(test_mul_mont_n_by_zero()); + // assert(test_mul_mont_n_zero_by_one()); + // assert(test_mul_mont_n_one_by_one()); + assert(test_mul_mont_n_random_by_one()); + assert(test_mul_mont_n_random_by_random()); + + // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added + // assert(test_sub_zero_from_zero_subn()); + // assert(test_sub_zero_from_random_subn()); + // assert(test_sub_random_from_zero_subn()); + // assert(test_sub_random_from_small_subn()); + assert(test_sub_2_randoms_subn()); + assert(test_sub_2_randoms_reverse_subn()); + true +} + + +fn get_test_vectors() -> (Vec, Vec) { + let mut zero_vec = ~Vec::new::(); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + (zero_vec, p_vec) +} + +fn test_mul_mont_n_by_zero() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn get_one_vec() -> Vec { + let mut one_vec = ~Vec::new::(); + one_vec.push(1); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec +} + +fn test_mul_mont_n_zero_by_one() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_mul_mont_n_one_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); + equals_vec(res, one_vec, 6); + true +} + +fn test_mul_mont_n_random_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r_vec = ~Vec::new::(); + r_vec.push(0x54439c4ae7869f30); + r_vec.push(0xa7fdefad55c032ba); + r_vec.push(0x21282f739c0a15e7); + r_vec.push(0x6cc7a6e8c38430ff); + r_vec.push(0x50db69783b321139); + r_vec.push(0xba78745dadd17a93); + let one_vec = get_one_vec(); + + let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); + equals_vec(res, r_vec, 6); + true +} + +fn test_mul_mont_n_random_by_random() -> bool { + let(_, p_vec) = get_test_vectors(); + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(0x54439c4ae7869f30); + r1_vec.push(0xa7fdefad55c032ba); + r1_vec.push(0x21282f739c0a15e7); + r1_vec.push(0x6cc7a6e8c38430ff); + r1_vec.push(0x50db69783b321139); + r1_vec.push(0xba78745dadd17a93); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(0xeb6f61c69e4c7eef); + r2_vec.push(0xa70784fb3f9ac549); + r2_vec.push(0x91f41a633e1d9601); + r2_vec.push(0xf89a44e9a52e99e); + r2_vec.push(0x1eb242ddd39638bc); + r2_vec.push(0x57e6ed499f0c7c1); + + //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + let mut res_vec = ~Vec::new::(); + res_vec.push(0x42863c4b7ea22ad7); + res_vec.push(0x27627bfa644b580d); + res_vec.push(0x16930ecb9e3a308f); + res_vec.push(0xd5802a33c5512d6a); + res_vec.push(0x19591b38f5515036); + res_vec.push(0x7546b2615f748cd); + let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); + equals_vec(res, res_vec, 6); + true +} + +fn test_add_zero_to_zero_addn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_add_zero_to_random_addn() -> bool { + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let(zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_add_random_to_small_addn() -> bool { + let mut small_vec = ~Vec::new::(); + small_vec.push(0x1); + small_vec.push(0x2); + small_vec.push(0x3); + small_vec.push(0x4); + small_vec.push(0x5); + small_vec.push(0x6); + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let mut res_vec = ~Vec::new::(); + res_vec.push(4478030004447473543); + res_vec.push(2814704111667093004); + res_vec.push(15884408734010272161); + res_vec.push(17001047363111187582); + res_vec.push(932823543034528552); + res_vec.push(1051481384684610851); + + let(_, p_vec) = get_test_vectors(); + + let res = add_mod_n(small_vec, random_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + true +} + +fn test_sub_zero_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_sub_zero_from_random_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + + let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_sub_random_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(13059245463466299169); + random_vec.push(17774603101077980186); + random_vec.push(889990675562875390); + random_vec.push(12771390643166271294); + random_vec.push(5370893444473505192); + random_vec.push(599972797727911687); + + let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); + // p-r (is the same as 0-r mod p) + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564426); + res_vec.push(2882282484148780005); + res_vec.push(6545683898001206309); + res_vec.push(12914691390957992833); + res_vec.push(41210333997197102); + res_vec.push(1273825819919628179); + equals_vec(res, res_vec, 6); + true +} + +fn test_sub_random_from_small_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let mut small_vec = ~Vec::new::(); + small_vec.push(1); + small_vec.push(2); + small_vec.push(3); + small_vec.push(4); + small_vec.push(5); + small_vec.push(6); + + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let mut r_vec = ~Vec::new::(); + r_vec.push(13059245463466299169); + r_vec.push(17774603101077980186); + r_vec.push(889990675562875390); + r_vec.push(12771390643166271294); + r_vec.push(5370893444473505192); + r_vec.push(599972797727911687); + + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564427); + res_vec.push(2882282484148780007); + res_vec.push(6545683898001206312); + res_vec.push(12914691390957992837); + res_vec.push(41210333997197107); + res_vec.push(1273825819919628185); + + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + let res = sub_mod_n(small_vec, r_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn get_r1_r2_vecs() -> (Vec, Vec) { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let mut r1_vec = ~Vec::new::(); + r1_vec.push(10587454305359941416); + r1_vec.push(4615625447881587853); + r1_vec.push(9368308553698906485); + r1_vec.push(9494054596162055604); + r1_vec.push(377309137954328098); + r1_vec.push(766262085408033194); + + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let mut r2_vec = ~Vec::new::(); + r2_vec.push(13403040667047958534); + r2_vec.push(405585388298286396); + r2_vec.push(7295341050629342949); + r2_vec.push(1749456428444609784); + r2_vec.push(1856600841951774635); + r2_vec.push(296809876162753174); + + (r1_vec, r2_vec) +} + +fn test_sub_2_randoms_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let mut res_vec = ~Vec::new::(); + res_vec.push(15631157712021534498); + res_vec.push(4210040059583301456); + res_vec.push(2072967503069563536); + res_vec.push(7744598167717445820); + res_vec.push(16967452369712105079); + res_vec.push(469452209245280019); + + let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn test_sub_2_randoms_reverse_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let mut res_vec = ~Vec::new::(); + res_vec.push(16218017377765880713); + res_vec.push(16446845525643458734); + res_vec.push(5362707070494518163); + res_vec.push(17941483866406818307); + res_vec.push(6891395482468148831); + res_vec.push(1404346408402259846); + + let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} From 0f751364051fa41e153a59f5b93d4274b6175a7b Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 17:17:38 -0600 Subject: [PATCH 044/160] - Renames the test_helpers file to tests_small_functions - Started on mul_mont_384x --- bls12-381/src/consts.sw | 2 + bls12-381/src/main.sw | 9 ++- ...ts_helpers.sw => tests_small_functions.sw} | 4 +- bls12-381/src/tests/tests_vect_fp.sw | 1 - bls12-381/src/tests/tests_vect_fp2.sw | 67 ++++++++++++++----- bls12-381/src/vect.sw | 37 ++++++---- 6 files changed, 82 insertions(+), 38 deletions(-) rename bls12-381/src/tests/{tests_helpers.sw => tests_small_functions.sw} (99%) diff --git a/bls12-381/src/consts.sw b/bls12-381/src/consts.sw index 18e6433..16808a7 100644 --- a/bls12-381/src/consts.sw +++ b/bls12-381/src/consts.sw @@ -1,5 +1,7 @@ library consts; +pub const NLIMBS_384 = 6; + /* R = 2**384 % p = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 1d75162..0885c13 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -7,7 +7,7 @@ dep consts; dep tests/tests_vect_fp; dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; -dep tests/tests_helpers; +dep tests/tests_small_functions; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -19,16 +19,15 @@ use std::logging::log; use ::tests_vect_fp::fp_tests; use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; -use ::tests_helpers::test_helpers; +use ::tests_small_functions::tests_small_functions; fn main() { - log(78); // assert(fp_tests()); - // assert(fp2_tests()); + assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); // assert(vect_subfunctions_tests()); - assert(test_helpers()); + // assert(tests_small_functions()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_helpers.sw b/bls12-381/src/tests/tests_small_functions.sw similarity index 99% rename from bls12-381/src/tests/tests_helpers.sw rename to bls12-381/src/tests/tests_small_functions.sw index 6eabbf0..8586169 100644 --- a/bls12-381/src/tests/tests_helpers.sw +++ b/bls12-381/src/tests/tests_small_functions.sw @@ -1,4 +1,4 @@ -library tests_helpers; +library tests_small_functions; use ::fields::*; @@ -7,7 +7,7 @@ use ::test_helpers::*; use std::{assert::assert, u128::*}; -pub fn test_helpers() -> bool { +pub fn tests_small_functions() -> bool { assert(test_not()); assert(tests_subtract_wrap()); assert(tests_sbb()); diff --git a/bls12-381/src/tests/tests_vect_fp.sw b/bls12-381/src/tests/tests_vect_fp.sw index c0a607b..7391af2 100644 --- a/bls12-381/src/tests/tests_vect_fp.sw +++ b/bls12-381/src/tests/tests_vect_fp.sw @@ -11,7 +11,6 @@ pub fn fp_tests() -> bool { // assert(test_add_fp()); // assert(test_sub_fp()); - // assert(test_helpers()); // assert(tests_mul_by_3_fp()); // assert(tests_mul_by_8_fp()); assert(test_lshift_p()); diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls12-381/src/tests/tests_vect_fp2.sw index e3104a3..771c603 100644 --- a/bls12-381/src/tests/tests_vect_fp2.sw +++ b/bls12-381/src/tests/tests_vect_fp2.sw @@ -3,18 +3,17 @@ library tests_vect_fp2; use ::fields::*; use ::vect::*; use ::test_helpers::*; - +use std::logging::log; use std::assert::assert; pub fn fp2_tests() -> bool { - assert(tests_add_fp2()); + // assert(tests_add_fp2()); // assert(tests_sub_fp2()); + assert(tests_mul_fp2()); true } -fn tests_add_fp2() -> bool { - // the function should add the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 +fn get_a1() -> vec384x { let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] @@ -28,6 +27,13 @@ fn tests_add_fp2() -> bool { r: r_1, i: i_1, }; + a_1 +} + +fn tests_add_fp2() -> bool { + // the function should add the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let a_1 = get_a1(); //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 let r_2 = vec384 { @@ -62,19 +68,7 @@ fn tests_add_fp2() -> bool { fn tests_sub_fp2() -> bool { // the function should subtract the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; + let a_1 = get_a1(); //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 let r_2 = vec384 { @@ -104,3 +98,40 @@ fn tests_sub_fp2() -> bool { }); true } + +fn tests_mul_fp2() -> bool { + // assert(mul_fp2_by_zero()); + assert(mul_fp2_by_one()); + // assert(mul_fp2_by_small()); + true +} + +fn mul_fp2_by_zero() -> bool { + let a_1 = get_a1(); + let res = mul_fp2(a_1, ZERO_X); + equals_vec384(res.r, ZERO); + equals_vec384(res.i, ZERO); + true +} + +fn mul_fp2_by_one() -> bool { + let a_1 = get_a1(); + let one_384 = vec384 {ls: [1, 0, 0, 0, 0, 0]}; + let one = vec384x {r: one_384, i: one_384 }; + + let res = mul_fp2(a_1, one); + print_vec384(res.r); + // equals_vec384(res.r, a_1.r); + // equals_vec384(res.i, a_1.i); + true +} + +// fn mul_fp2_by_small() -> bool { +// let small = vec384 { +// ls: [0x1, +// 0x2, 0x3, 0x4, 0x5, 0x6] +// }; +// let smallx = vec384x {r: small, i: small }; + +// true +// } \ No newline at end of file diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index f47bf1d..9a73235 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -1,6 +1,9 @@ library vect; +dep consts; + use std::{option::*, u128::*, vec::Vec}; +use consts::*; // Stores field element with max 384 bits // element in fp @@ -260,18 +263,8 @@ pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { res } +// TODO pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { - //WIP ELENA - // vec384 aa, bb, cc; - - // add_mod_n(aa, a[0], a[1], p, NLIMBS(384)); - // add_mod_n(bb, b[0], b[1], p, NLIMBS(384)); - // mul_mont_n(bb, bb, aa, p, n0, NLIMBS(384)); - // mul_mont_n(aa, a[0], b[0], p, n0, NLIMBS(384)); - // mul_mont_n(cc, a[1], b[1], p, n0, NLIMBS(384)); - // sub_mod_n(ret[0], aa, cc, p, NLIMBS(384)); - // sub_mod_n(ret[1], bb, aa, p, NLIMBS(384)); - // sub_mod_n(ret[1], ret[1], cc, p, NLIMBS(384)); ZERO } @@ -523,8 +516,28 @@ pub fn mul_by_3_mod_384x(a: vec384x, p: vec384) -> vec384x { ZERO_X } +fn to_vec(v: vec384) -> Vec { + let mut res = ~Vec::new::(); + let mut i = 0; + while i < 6 { + res.push(v.ls[i]); + i += 1; + } + res +} + pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { - //TODO. Has a non-assembly impl in blst in src/no_asm.h + let a0_vec = to_vec(a.r); + let a1_vec = to_vec(a.i); + let b0_vec = to_vec(b.r); + let b1_vec = to_vec(b.i); + let p_vec = to_vec(p); + + let mut aa = add_mod_n(a0_vec, a1_vec, p_vec, NLIMBS_384); + let mut bb = add_mod_n(b0_vec, b1_vec, p_vec, NLIMBS_384); + // let bb_temp = mul_mont_n(bb, aa, p_vec, n0, NLIMBS_384); + // aa = mul_mont_n(a0_vec, b0_vec, p_vec, n0, NLIMBS_384); + ZERO_X } From 0ef586a0591f82b5d8348beb7cd826dc0e1b8bd5 Mon Sep 17 00:00:00 2001 From: Manish Date: Thu, 14 Jul 2022 18:42:14 +0530 Subject: [PATCH 045/160] redc_mont_n added(testing not done yet) --- bls12-381/src/test_helpers.sw | 9 +++ bls12-381/src/tests/tests_vect_fp2.sw | 9 ++- .../src/tests/tests_vect_subfunctions.sw | 46 ++++++++++++--- bls12-381/src/vect.sw | 57 +++++++++++++++++++ 4 files changed, 112 insertions(+), 9 deletions(-) diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 26e0a47..4478fba 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -31,3 +31,12 @@ pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { } true } +pub fn print_vec(a: Vec) { + let mut i = 0; + let l = a.len(); + while i < l { + log(unpack_or_0(a.get(i))); + i += 1; + } + +} diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls12-381/src/tests/tests_vect_fp2.sw index 771c603..6cc8bfd 100644 --- a/bls12-381/src/tests/tests_vect_fp2.sw +++ b/bls12-381/src/tests/tests_vect_fp2.sw @@ -116,8 +116,13 @@ fn mul_fp2_by_zero() -> bool { fn mul_fp2_by_one() -> bool { let a_1 = get_a1(); - let one_384 = vec384 {ls: [1, 0, 0, 0, 0, 0]}; - let one = vec384x {r: one_384, i: one_384 }; + let one_384 = vec384 { + ls: [1, 0, 0, 0, 0, 0] + }; + let one = vec384x { + r: one_384, + i: one_384, + }; let res = mul_fp2(a_1, one); print_vec384(res.r); diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 6431ad6..9bc50ce 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -3,7 +3,7 @@ library tests_vect_subfunctions; use ::fields::*; use ::vect::*; use ::test_helpers::*; - +use std::logging::log; use std::{assert::assert, vec::Vec}; pub fn vect_subfunctions_tests() -> bool { @@ -28,10 +28,11 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_random_from_small_subn()); assert(test_sub_2_randoms_subn()); assert(test_sub_2_randoms_reverse_subn()); + + // assert(test_redc_mont_n_384()); true } - fn get_test_vectors() -> (Vec, Vec) { let mut zero_vec = ~Vec::new::(); zero_vec.push(0); @@ -300,8 +301,8 @@ fn get_r1_r2_vecs() -> (Vec, Vec) { } fn test_sub_2_randoms_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); + let(zero_vec, p_vec) = get_test_vectors(); + let(r1_vec, r2_vec) = get_r1_r2_vecs(); //res = //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 @@ -321,15 +322,15 @@ fn test_sub_2_randoms_subn() -> bool { } fn test_sub_2_randoms_reverse_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); + let(zero_vec, p_vec) = get_test_vectors(); + let(r1_vec, r2_vec) = get_r1_r2_vecs(); //res = //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 // => mod p //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new::(); res_vec.push(16218017377765880713); res_vec.push(16446845525643458734); res_vec.push(5362707070494518163); @@ -340,5 +341,36 @@ fn test_sub_2_randoms_reverse_subn() -> bool { let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); equals_vec(res, res_vec, 6); + true +} + +fn test_redc_mont_n_384() -> bool { + let mut a_vec: Vec = ~Vec::new::(); + a_vec.push(10); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + let mut res_vec: Vec = ~Vec::new::(); + res_vec.push(10); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + //print_vec(res_vec); + let test_vec = get_test_vectors(); + let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + print_vec(res); + log(unpack_or_0(res.get(0))); + + true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 9a73235..1364534 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -23,6 +23,11 @@ pub struct vec384x { i: vec384, //"imaginary" part } +//converts a u64 into U128 +pub fn u_128(a: u64) -> U128 { + U128{upper: 0, lower: a} +} + //TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0] @@ -273,6 +278,58 @@ pub fn sqr_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { ZERO } + +pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { + let mut j = 0; + let mut i = 1; + let mut b: Vec = a; + let mut tmp: Vec = ~Vec::new::(); + while j < n { + let mut mx: U128 = (u_128(n0) * u_128(unpack_or_0(b.get(0)))); + let mut limbx = mx * u_128(unpack_or_0(p.get(0))) + u_128(unpack_or_0(b.get(0))); + let mut hi = limbx.upper; + i = 1; + while i < n { + limbx = mx * u_128(unpack_or_0(p.get(i))) + u_128(hi) + u_128(unpack_or_0(b.get(i))); + tmp.insert(i-1, limbx.lower); + hi = limbx.upper; + i += 1; + } + tmp.insert(i-1, hi); + j += 1; + b = tmp; + } + + let mut tmp2: Vec = ~Vec::new::(); + i = 0; + let mut carry = 0; + while i < n { + let mut limbx = u_128(unpack_or_0(a.get(n+i))) + u_128(unpack_or_0(tmp.get(i))) + u_128(carry); + tmp2.insert(i, limbx.lower); + carry = limbx.upper; + i += 1; + } + + let mut borrow = 0; + let mut res: Vec = ~Vec::new::(); + i = 0; + while i < n { + let mut limbx = u_128(unpack_or_0(tmp2.get(i))) - (u_128(unpack_or_0(p.get(i))) + u_128(borrow)); + res.push(limbx.lower); + borrow = limbx.upper & 1; + i += 1; + } + + let mut mask = carry - borrow; + let mut result: Vec = ~Vec::new::(); + i = 0; + while i < n { + result.push((unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask)); + i += 1; + } + result +} + pub fn redc_mont_384(a: vec768, p: vec384, n0: u64) -> vec384 { //TODO ZERO From bd4a93e8e134860bbe68a96b6dab6b5734cbf063 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 14 Jul 2022 16:22:35 -0600 Subject: [PATCH 046/160] Better readability --- bls12-381/src/vect.sw | 111 +++++++++--------------------------------- 1 file changed, 24 insertions(+), 87 deletions(-) diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 9a73235..8070512 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -88,74 +88,38 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { } pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { - let mut mx: U128 = U128 { - lower: unpack_or_0(b.get(0)), - upper: 0, - }; - let mut hi: U128 = U128 { - lower: 0, - upper: 0, - }; + let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); + let mut hi: U128 = ~U128::from(0, 0); let mut tmp: Vec = ~Vec::new::(); let mut i = 0; while i < n { - let ai: U128 = U128 { - lower: unpack_or_0(a.get(i)), upper: 0 - }; + let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let limbx = mx * ai + hi; tmp.insert(i, limbx.lower); - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i += 1; } - mx = U128 { - lower: n0, upper: 0 - } - * U128 { - lower: unpack_or_0(tmp.get(0)), upper: 0 - }; + mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); tmp.insert(i, hi.lower); - let mut carry: u64 = 0; let mut j = 0; - let mut limbx: U128 = U128 { - lower: 0, - upper: 0, - }; + let mut limbx: U128 = ~U128::from(0, 0); while true { - let p0: U128 = U128 { - lower: unpack_or_0(p.get(0)), upper: 0 - }; - let tmp0: U128 = U128 { - lower: unpack_or_0(tmp.get(0)), upper: 0 - }; + let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); + let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); limbx = (mx * p0) + tmp0; - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i = 1; while i < n { - let pi: U128 = U128 { - lower: unpack_or_0(p.get(i)), upper: 0 - }; - let tmpi: U128 = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - }; + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); limbx = (mx * pi) + tmpi; tmp.insert(i - 1, limbx.lower); - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i += 1; } - limbx = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - } - + (hi + U128 { - lower: carry, upper: 0 - }); + limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); tmp.insert(i - 1, limbx.lower); carry = limbx.lower; @@ -163,62 +127,35 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec if j == n { break; } - - mx = U128 { - lower: unpack_or_0(b.get(j)), upper: 0 - }; - hi = U128 { - lower: 0, upper: 0 - }; + mx = ~U128::from(0, unpack_or_0(b.get(j))); + hi = ~U128::from(0, 0); i = 0; while i < n { - let ai: U128 = U128 { - lower: unpack_or_0(a.get(i)), upper: 0 - }; - let tmpi: U128 = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - }; + let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); limbx = (mx * (ai + hi)) + tmpi; tmp.insert(i, limbx.lower); - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i += 1; } - mx = U128 { - lower: n0, upper: 0 - } - * U128 { - lower: unpack_or_0(tmp.get(0)), upper: 0 - }; - limbx = hi + U128 { - lower: carry, upper: 0 - }; + mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + limbx = hi + ~U128::from(0, carry); tmp.insert(i, limbx.lower); carry = limbx.upper; } - let mut borrow: u64 = 0; i = 0; let mut ret: Vec = ~Vec::new::(); while i < n { - let pi: U128 = U128 { - lower: unpack_or_0(p.get(i)), upper: 0 - }; - let tmpi: U128 = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - }; - let pi_w_borrow = pi + U128 { - lower: borrow, upper: 0 - }; + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + let pi_w_borrow = pi + ~U128::from(0, borrow); // Prevent underflow. When U256 arithmetic is available we can create sbb_256 let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { (tmpi - pi_w_borrow, 0) } else { - (~U128::max() - (pi_w_borrow - tmpi - U128 { - lower: 1, upper: 0 - }), 1) + (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0,1)), 1) }; limbx = sub_res; borrow = b_res; From 4d69f8104b97da42c530e7dfd94080d4fec0531f Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 14 Jul 2022 16:26:37 -0600 Subject: [PATCH 047/160] Testing field_element library through contract --- edwards25519/Forc.toml | 2 +- edwards25519/src/field_element.sw | 2 +- edwards25519/src/test_helpers.sw | 6 --- test_contract/.gitignore | 4 ++ test_contract/Cargo.toml | 16 +++++++ test_contract/Forc.toml | 8 ++++ test_contract/src/main.sw | 25 +++++++++++ test_contract/src/test_helpers.sw | 41 ++++++++++++++++++ test_contract/tests/harness.rs | 71 +++++++++++++++++++++++++++++++ 9 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 test_contract/.gitignore create mode 100644 test_contract/Cargo.toml create mode 100644 test_contract/Forc.toml create mode 100644 test_contract/src/main.sw create mode 100644 test_contract/src/test_helpers.sw create mode 100644 test_contract/tests/harness.rs diff --git a/edwards25519/Forc.toml b/edwards25519/Forc.toml index 14b5b02..25dabbc 100644 --- a/edwards25519/Forc.toml +++ b/edwards25519/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["HashCloak"] -entry = "main.sw" +entry = "field_element.sw" license = "Apache-2.0" name = "edwards25519" diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index bc7e40a..8173cd3 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -184,7 +184,7 @@ pub fn square(a: Element) -> Element { //returns a*b -pub fn multiply (a: Element, b: Element) -> Element { +pub fn multiply(a: Element, b: Element) -> Element { //https://cs.opensource.google/go/go/+/master:src/crypto/internal/edwards25519/field/fe_generic.go;l=34;bpv=0?q=feMul&sq=&ss=go%2Fgo diff --git a/edwards25519/src/test_helpers.sw b/edwards25519/src/test_helpers.sw index b92a9e9..92f10f6 100644 --- a/edwards25519/src/test_helpers.sw +++ b/edwards25519/src/test_helpers.sw @@ -34,9 +34,3 @@ pub fn equals_U128(res: U128, lower: u64, upper: u64) -> bool { assert(res.lower == lower); true } - -//converts element into array of bytes - -// pub fn bytes_convert (a: Element) -> [u8;32] { -// let a_mod = mod_25519(a); -// } \ No newline at end of file diff --git a/test_contract/.gitignore b/test_contract/.gitignore new file mode 100644 index 0000000..1a6c732 --- /dev/null +++ b/test_contract/.gitignore @@ -0,0 +1,4 @@ +out +target +Cargo.lock +Forc.lock \ No newline at end of file diff --git a/test_contract/Cargo.toml b/test_contract/Cargo.toml new file mode 100644 index 0000000..bccc8fd --- /dev/null +++ b/test_contract/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "test_edwards25519" +version = "0.1.0" +authors = ["Hashcloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.16.1" +fuels-abigen-macro = "0.16.1" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/test_contract/Forc.toml b/test_contract/Forc.toml new file mode 100644 index 0000000..cbf0708 --- /dev/null +++ b/test_contract/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Hashcloak"] +entry = "main.sw" +license = "Apache-2.0" +name = "test_edwards25519" + +[dependencies] +edwards25519 = { path = "../edwards25519" } \ No newline at end of file diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw new file mode 100644 index 0000000..5b8af41 --- /dev/null +++ b/test_contract/src/main.sw @@ -0,0 +1,25 @@ +contract; +dep test_helpers; + +use edwards25519::*; + +use std::assert::assert; +use std::u128::*; + +use ::test_helpers::*; + +abi EdContract { + #[storage()]fn equals(a: Element, b: Element) -> bool; + #[storage()]fn multiply(a: Element, b: Element) -> Element; + +} + +impl EdContract for Contract { + #[storage()]fn equals(a: Element, b: Element) -> bool { + equals(a, b) + } + + #[storage()]fn multiply(a: Element, b: Element) -> Element { + multiply(a, b) + } +} \ No newline at end of file diff --git a/test_contract/src/test_helpers.sw b/test_contract/src/test_helpers.sw new file mode 100644 index 0000000..b325e3e --- /dev/null +++ b/test_contract/src/test_helpers.sw @@ -0,0 +1,41 @@ +library test_helpers; + +use edwards25519::*; + +use std::logging::log; +use std::assert::assert; +use std::u128::*; + +pub fn print_el(e: Element) { + log(e.l0); + log(e.l1); + log(e.l2); + log(e.l3); + log(e.l4); +} + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert(res.l0 == should_be.l0); + assert(res.l1 == should_be.l1); + assert(res.l2 == should_be.l2); + assert(res.l3 == should_be.l3); + assert(res.l4 == should_be.l4); + true +} + +pub fn print_U128(a: U128) { + log(a.upper); + log(a.lower); +} + +pub fn equals_U128(res: U128, lower: u64, upper: u64) -> bool { + assert(res.upper == upper); + assert(res.lower == lower); + true +} + +//converts element into array of bytes + +// pub fn bytes_convert (a: Element) -> [u8;32] { +// let a_mod = mod_25519(a); +// } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs new file mode 100644 index 0000000..a309be3 --- /dev/null +++ b/test_contract/tests/harness.rs @@ -0,0 +1,71 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_single_wallet().await; + + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = EdContract::new(id.to_string(), wallet); + + (instance, id) +} + +const zero: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_equals() { + let a = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + let b = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + + let (_instance, _id) = get_contract_instance().await; + + let a_b_equal = _instance.equals(a, b).call().await.unwrap().value; + assert!(a_b_equal); +} + +#[tokio::test] +async fn test_multiply_by_0() { + let (_instance, _id) = get_contract_instance().await; + + //a = 2^255 - 21 + let a = Element{ + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let res = _instance.multiply(a, zero) + .tx_params(TxParameters::new(None, Some(100), None, None)) + .call().await.unwrap().value; + + assert!(res_equals(res, zero)); +} \ No newline at end of file From 2bad092c9c86f9867fadae3dac15dd9af062db5e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 15 Jul 2022 07:45:12 -0600 Subject: [PATCH 048/160] Making sure there is no recursion happening by accident in the contract --- edwards25519/src/field_element.sw | 4 ++-- test_contract/src/main.sw | 8 ++++---- test_contract/tests/harness.rs | 11 ++++++----- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 8173cd3..04e36b9 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -15,8 +15,8 @@ pub struct Element { // = (1 << 51) - 1 // But using the above expression gives the error "Could not evaluate initializer to a const declaration." const mask_low_51_bits: u64 = 2251799813685247; -const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; -const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; +pub const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; +pub const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; // from NaCl impl https://cr.yp.to/ecdh.html#use fn times19(x: u64) -> u64 { diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 5b8af41..357855e 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -9,17 +9,17 @@ use std::u128::*; use ::test_helpers::*; abi EdContract { - #[storage()]fn equals(a: Element, b: Element) -> bool; - #[storage()]fn multiply(a: Element, b: Element) -> Element; + #[storage()]fn equals_test(a: Element, b: Element) -> bool; + #[storage()]fn multiply_test(a: Element, b: Element) -> Element; } impl EdContract for Contract { - #[storage()]fn equals(a: Element, b: Element) -> bool { + #[storage()]fn equals_test(a: Element, b: Element) -> bool { equals(a, b) } - #[storage()]fn multiply(a: Element, b: Element) -> Element { + #[storage()]fn multiply_test(a: Element, b: Element) -> Element { multiply(a, b) } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index a309be3..41c7db6 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -5,8 +5,9 @@ use fuels_abigen_macro::abigen; abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); async fn get_contract_instance() -> (EdContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_single_wallet().await; + let mut wallets = + launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let wallet = wallets.pop().unwrap(); let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) .await @@ -47,7 +48,7 @@ async fn test_equals() { let (_instance, _id) = get_contract_instance().await; - let a_b_equal = _instance.equals(a, b).call().await.unwrap().value; + let a_b_equal = _instance.equals_test(a, b).call().await.unwrap().value; assert!(a_b_equal); } @@ -63,8 +64,8 @@ async fn test_multiply_by_0() { l_3: 2251799813685247, l_4: 2251799813685247 }; - let res = _instance.multiply(a, zero) - .tx_params(TxParameters::new(None, Some(100), None, None)) + let res = _instance.multiply_test(a, zero) + .tx_params(TxParameters::new(None, Some(100000), None, None)) .call().await.unwrap().value; assert!(res_equals(res, zero)); From 3046b37d6a9fc53263ffdbb37f752592f1a6bac5 Mon Sep 17 00:00:00 2001 From: Manish Date: Fri, 15 Jul 2022 19:22:05 +0530 Subject: [PATCH 049/160] overflow issue in redc_mont_n --- bls12-381/src/main.sw | 4 +- .../src/tests/tests_vect_subfunctions.sw | 43 +++++++++----- bls12-381/src/vect.sw | 58 ++++++++++++------- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 0885c13..77406fd 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -23,10 +23,10 @@ use ::tests_small_functions::tests_small_functions; fn main() { // assert(fp_tests()); - assert(fp2_tests()); + // assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); - // assert(vect_subfunctions_tests()); + assert(vect_subfunctions_tests()); // assert(tests_small_functions()); } diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 9bc50ce..eb648bd 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -13,23 +13,23 @@ pub fn vect_subfunctions_tests() -> bool { // which should be correct, but of course add_mod_n should do more // assert(test_add_zero_to_zero_addn()); // assert(test_add_zero_to_random_addn()); - assert(test_add_random_to_small_addn()); + // assert(test_add_random_to_small_addn()); // assert(test_mul_mont_n_by_zero()); // assert(test_mul_mont_n_zero_by_one()); // assert(test_mul_mont_n_one_by_one()); - assert(test_mul_mont_n_random_by_one()); - assert(test_mul_mont_n_random_by_random()); + // assert(test_mul_mont_n_random_by_one()); + // assert(test_mul_mont_n_random_by_random()); // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added // assert(test_sub_zero_from_zero_subn()); // assert(test_sub_zero_from_random_subn()); // assert(test_sub_random_from_zero_subn()); // assert(test_sub_random_from_small_subn()); - assert(test_sub_2_randoms_subn()); - assert(test_sub_2_randoms_reverse_subn()); + // assert(test_sub_2_randoms_subn()); + // assert(test_sub_2_randoms_reverse_subn()); - // assert(test_redc_mont_n_384()); + assert(test_redc_mont_n_384()); true } @@ -359,17 +359,32 @@ fn test_redc_mont_n_384() -> bool { a_vec.push(0); a_vec.push(0); let mut res_vec: Vec = ~Vec::new::(); - res_vec.push(10); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - //print_vec(res_vec); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + + // let mut p_vec = ~Vec::new::(); + // p_vec.push(0xb9feffffffffaaab); + // p_vec.push(0x1eabfffeb153ffff); + // p_vec.push(0x6730d2a0f6b0f624); + // p_vec.push(0x64774b84f38512bf); + // p_vec.push(0x4b1ba7b6434bacd7); + // p_vec.push(0x1a0111ea397fe69a); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + + log(a_vec.get(0)); let test_vec = get_test_vectors(); let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); print_vec(res); - log(unpack_or_0(res.get(0))); + //log(unpack_or_0(res.get(0))); true diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 5b7a90b..12fc115 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -4,7 +4,7 @@ dep consts; use std::{option::*, u128::*, vec::Vec}; use consts::*; - +use std::logging::log; // Stores field element with max 384 bits // element in fp pub struct vec384 { @@ -23,10 +23,7 @@ pub struct vec384x { i: vec384, //"imaginary" part } -//converts a u64 into U128 -pub fn u_128(a: u64) -> U128 { - U128{upper: 0, lower: a} -} + //TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 { @@ -220,28 +217,35 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut j = 0; let mut i = 1; let mut b: Vec = a; + //let mut limbx: U128 = ~U128::from(0,0); let mut tmp: Vec = ~Vec::new::(); while j < n { - let mut mx: U128 = (u_128(n0) * u_128(unpack_or_0(b.get(0)))); - let mut limbx = mx * u_128(unpack_or_0(p.get(0))) + u_128(unpack_or_0(b.get(0))); - let mut hi = limbx.upper; + let mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(b.get(0)))).lower; + let mx: U128 = ~U128::from(0, mx_temp) ; + let mut limbx = mx * ~U128::from(0, unpack_or_0(p.get(0))) + ~U128::from(0, unpack_or_0(b.get(0))); + let mut hi: U128 = ~U128::from(0, limbx.upper); i = 1; while i < n { - limbx = mx * u_128(unpack_or_0(p.get(i))) + u_128(hi) + u_128(unpack_or_0(b.get(i))); + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); + limbx = (mx * pi + hi) + bi; tmp.insert(i-1, limbx.lower); - hi = limbx.upper; + hi = ~U128::from(0, limbx.upper); i += 1; } - tmp.insert(i-1, hi); - j += 1; + tmp.insert(i-1, hi.lower); b = tmp; + j += 1; } let mut tmp2: Vec = ~Vec::new::(); - i = 0; let mut carry = 0; + i = 0; while i < n { - let mut limbx = u_128(unpack_or_0(a.get(n+i))) + u_128(unpack_or_0(tmp.get(i))) + u_128(carry); + let ani: U128 = ~U128::from(0, unpack_or_0(a.get(n+i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + let carryi: U128 = ~U128::from(0, carry); + let limbx = ani + (tmpi + carryi); tmp2.insert(i, limbx.lower); carry = limbx.upper; i += 1; @@ -251,19 +255,33 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut res: Vec = ~Vec::new::(); i = 0; while i < n { - let mut limbx = u_128(unpack_or_0(tmp2.get(i))) - (u_128(unpack_or_0(p.get(i))) + u_128(borrow)); - res.push(limbx.lower); - borrow = limbx.upper & 1; + let tmp2i: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let borrow_i: U128 = ~U128::from(0, borrow); + let pi_w_borrow = pi + borrow_i; + // Prevent underflow. When U256 arithmetic is available we can create sbb_256 + let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmp2i { + (tmp2i - pi_w_borrow, 0) + } else { + (~U128::max() - (pi_w_borrow - tmp2i - ~U128::from(0,1)), 1) + }; + let mut limbx = sub_res; + //borrow = b_res; + borrow = limbx.upper & 0x1; + res.insert(i, limbx.lower); i += 1; } - - let mut mask = carry - borrow; + //arithmetic overflow is happning + //let mut mask = carry - borrow; + let mask: u64 = borrow * ~u64::max(); let mut result: Vec = ~Vec::new::(); i = 0; while i < n { - result.push((unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask)); + let result_i = (unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask); + result.insert(i, result_i); i += 1; } + result } From 300fd4227ba8d2af7146b4e99daa2cfbf08aa532 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 15 Jul 2022 14:09:07 -0600 Subject: [PATCH 050/160] Debugging mul_mont_n --- .../src/tests/tests_vect_subfunctions.sw | 13 +++-- bls12-381/src/vect.sw | 54 ++++++++++++++++--- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index eb648bd..983990c 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -5,6 +5,8 @@ use ::vect::*; use ::test_helpers::*; use std::logging::log; use std::{assert::assert, vec::Vec}; +use ::consts::*; + pub fn vect_subfunctions_tests() -> bool { // NOTE: Don't run all at the same time, because will run out of gas @@ -17,7 +19,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_by_zero()); // assert(test_mul_mont_n_zero_by_one()); - // assert(test_mul_mont_n_one_by_one()); + assert(test_mul_mont_n_one_by_one()); // assert(test_mul_mont_n_random_by_one()); // assert(test_mul_mont_n_random_by_random()); @@ -29,7 +31,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_2_randoms_subn()); // assert(test_sub_2_randoms_reverse_subn()); - assert(test_redc_mont_n_384()); + // assert(test_redc_mont_n_384()); true } @@ -56,7 +58,7 @@ fn get_test_vectors() -> (Vec, Vec) { fn test_mul_mont_n_by_zero() -> bool { let(zero_vec, p_vec) = get_test_vectors(); - let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); + let res = mul_mont_n(zero_vec, zero_vec, p_vec, P0, 6); equals_vec(res, zero_vec, 6); true } @@ -76,16 +78,17 @@ fn test_mul_mont_n_zero_by_one() -> bool { let(zero_vec, p_vec) = get_test_vectors(); let one_vec = get_one_vec(); - let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); + let res = mul_mont_n(zero_vec, one_vec, p_vec, P0, 6); equals_vec(res, zero_vec, 6); true } fn test_mul_mont_n_one_by_one() -> bool { + log(1); let(_, p_vec) = get_test_vectors(); let one_vec = get_one_vec(); - let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); + let res = mul_mont_n(one_vec, one_vec, p_vec, P0, 6); equals_vec(res, one_vec, 6); true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 12fc115..8f93acf 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -102,6 +102,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec i += 1; } +//0x89f3fffcfffcfffd * 1 mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); tmp.insert(i, hi.lower); let mut carry: u64 = 0; @@ -110,15 +111,32 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec while true { let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); + log(mx);//000000000000000089f3fffcfffcfffd + //2: 3947442df695f8f1286adb92d9d113e8 + log(p0);//0000000000000000b9feffffffffaaab + //2: 0000000000000000b9feffffffffaaab + log(tmp0);//00000000000000000000000000000001 + //2: 00000000000000006a4aaa14be07a408 + //1: 16^^643abe09d200a404ffffffffffffffff + //2: 16^^299d8e4220faed31901f94fb2b3b54280000000000000000 + //this is 190 bits instead of fitting into 128 limbx = (mx * p0) + tmp0; + log(limbx);//643abe09d200a4050000000000000000 + //2: f21393888e24ec0f0000000000000000 hi = ~U128::from(0, limbx.upper); + log(hi);//0000000000000000643abe09d200a405 + //2: 0000000000000000f21393888e24ec0f i = 1; while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - limbx = (mx * pi) + tmpi; + log(pi);//00000000000000001eabfffeb153ffff + log(tmpi);//00000000000000000000000000000000 + limbx = (mx * pi + hi) + tmpi; + log(limbx);//108747eeefa29c0f6a4aaa14be07a408 tmp.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); + log(hi);//0000000000000000108747eeefa29c0f i += 1; } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); @@ -131,21 +149,34 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } mx = ~U128::from(0, unpack_or_0(b.get(j))); hi = ~U128::from(0, 0); + log(mx);//00000000000000006730d2a0f6b0f624 + log(hi);//00000000000000000000000000000000 i = 0; while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 + log(tmpi);//0000000000000000379b7b3fafdc26ed limbx = (mx * (ai + hi)) + tmpi; + log(limbx);//000000000000000064774b84f38512bf tmp.insert(i, limbx.lower); hi = ~U128::from(0, limbx.upper); + log(hi);//00000000000000000000000000000000 i += 1; } mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) limbx = hi + ~U128::from(0, carry); + log(limbx);//00000000000000003623991cf3a341e8 tmp.insert(i, limbx.lower); + log(tmp);//00000000000000004b1ba7b6434bacd7 carry = limbx.upper; + log(carry);//00000000000000000000000000000000 + + //Conclusion so far: mx will become really large and then overflow in next iteration } + /* let mut borrow: u64 = 0; i = 0; let mut ret: Vec = ~Vec::new::(); @@ -165,15 +196,24 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec borrow = limbx.upper & 0x1; i += 1; } +log(carry); +log(borrow); + let mask: u64 = if carry >= borrow { + carry-borrow + } else { + ~u64::max()-1 + }; + */ +// mask = carry - borrow; + // let mask: u64 = borrow * ~u64::max(); - let mask: u64 = borrow * ~u64::max(); i = 0; let mut res: Vec = ~Vec::new::(); - while i < n { - let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); - res.insert(i, value); - i += 1; - } + // while i < n { + // let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); + // res.insert(i, value); + // i += 1; + // } res } From 5ecc807d83ad65a3b1146fceb5d3d3f53f473523 Mon Sep 17 00:00:00 2001 From: Manish Date: Mon, 18 Jul 2022 19:20:20 +0530 Subject: [PATCH 051/160] mul_mont_n and redc_mont_n debugging --- .../src/tests/tests_vect_subfunctions.sw | 152 ++++++++++++++---- bls12-381/src/vect.sw | 91 ++++++----- 2 files changed, 173 insertions(+), 70 deletions(-) diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 983990c..901b352 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -19,7 +19,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_by_zero()); // assert(test_mul_mont_n_zero_by_one()); - assert(test_mul_mont_n_one_by_one()); + // assert(test_mul_mont_n_one_by_one()); // assert(test_mul_mont_n_random_by_one()); // assert(test_mul_mont_n_random_by_random()); @@ -31,7 +31,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_2_randoms_subn()); // assert(test_sub_2_randoms_reverse_subn()); - // assert(test_redc_mont_n_384()); + assert(tests_redc_mont()); true } @@ -84,12 +84,13 @@ fn test_mul_mont_n_zero_by_one() -> bool { } fn test_mul_mont_n_one_by_one() -> bool { - log(1); let(_, p_vec) = get_test_vectors(); let one_vec = get_one_vec(); let res = mul_mont_n(one_vec, one_vec, p_vec, P0, 6); equals_vec(res, one_vec, 6); + //print_vec(res); + // print_vec(one_vec); true } @@ -105,7 +106,8 @@ fn test_mul_mont_n_random_by_one() -> bool { r_vec.push(0xba78745dadd17a93); let one_vec = get_one_vec(); - let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); + let res = mul_mont_n(r_vec, one_vec, p_vec, P0, 6); + print_vec(res); equals_vec(res, r_vec, 6); true } @@ -347,9 +349,16 @@ fn test_sub_2_randoms_reverse_subn() -> bool { true } -fn test_redc_mont_n_384() -> bool { +fn tests_redc_mont() -> bool { + assert(test_redc_mont_n_small()); + // assert(test_redc_mont_n_p()); + // assert(test_redc_mont_n_random()); + // assert(test_redc_mont_n_random_large()); + + true +} +fn test_redc_mont_n_small() -> bool { let mut a_vec: Vec = ~Vec::new::(); - a_vec.push(10); a_vec.push(0); a_vec.push(0); a_vec.push(0); @@ -361,34 +370,117 @@ fn test_redc_mont_n_384() -> bool { a_vec.push(0); a_vec.push(0); a_vec.push(0); + a_vec.push(10); let mut res_vec: Vec = ~Vec::new::(); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - - // let mut p_vec = ~Vec::new::(); - // p_vec.push(0xb9feffffffffaaab); - // p_vec.push(0x1eabfffeb153ffff); - // p_vec.push(0x6730d2a0f6b0f624); - // p_vec.push(0x64774b84f38512bf); - // p_vec.push(0x4b1ba7b6434bacd7); - // p_vec.push(0x1a0111ea397fe69a); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - - log(a_vec.get(0)); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(10); let test_vec = get_test_vectors(); let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); - print_vec(res); - //log(unpack_or_0(res.get(0))); + equals_vec(res, res_vec, 6); + true +} + +fn test_redc_mont_n_p() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + let test_vec = get_test_vectors(); + let res = redc_mont_n(p_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + //equals_vec(res, get_test_vectors().0, 6); + print_vec(res); + true +} + +fn test_redc_mont_n_random() -> bool { + /* + a_vec = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 + = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] + (using GP Pari) + a_vec mod P = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 + = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] + */ + let mut a_vec = ~Vec::new::(); + a_vec.push(13282407956253574712); + a_vec.push(7557322358563246340); + a_vec.push(14991082624209354397); + a_vec.push(6631139461101160670); + a_vec.push(10719928016004921607); + a_vec.push(1730705806359781376); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + let mut result = ~Vec::new::(); + result.push(13282407956253574712); + result.push(7557322358563246340); + result.push(14991082624209354397); + result.push(6631139461101160670); + result.push(10719928016004921607); + result.push(1730705806359781376); + + let test_vec = get_test_vectors(); + let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + print_vec(res); + //equals_vec(res, result, 6); + true + +} + +fn test_redc_mont_n_random_large() -> bool { + + /* + a = random({2^384}) = 21380795309672530537064108666460268360580493838230277925224860893329212391422460281305468429766194371347271041959862 + = [10009796384580774444, 9837491998535547791, 12861376030615125811, 15982738825684268908, 17984324540840297179, 13142370077570254774] + + a mod p = 1368747533564193569975159537780747577796079738535238498564570212709054138968270959092030284121116051157799679160927 + = [640803296343075113, 1223717179891587930, 13558174375960666486, 15697854105282963640, 6933616983254254301, 1470447218309591647] + + + + */ + let mut a_vec = ~Vec::new::(); + a_vec.push(13142370077570254774); + a_vec.push(17984324540840297179); + a_vec.push(15982738825684268908); + a_vec.push(12861376030615125811); + a_vec.push(9837491998535547791); + a_vec.push(10009796384580774444); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + + let mut result = ~Vec::new::(); + result.push(1470447218309591647); + result.push(6933616983254254301); + result.push(15697854105282963640); + result.push(13558174375960666486); + result.push(1223717179891587930); + result.push(640803296343075113); + + let test_vec = get_test_vectors(); + let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + //equals_vec(res, result, 6); + print_vec(res); true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 8f93acf..4c31ccb 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -93,6 +93,8 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, 0); let mut tmp: Vec = ~Vec::new::(); + let mut tmp2: Vec = ~Vec::new::();//new vector + let mut tmp3: Vec = ~Vec::new::();//new vector let mut i = 0; while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); @@ -103,7 +105,9 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } //0x89f3fffcfffcfffd * 1 - mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0)))).lower; + let mut mx: U128 = ~U128::from(0, mx_temp); + //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); tmp.insert(i, hi.lower); let mut carry: u64 = 0; let mut j = 0; @@ -111,36 +115,36 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec while true { let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); - log(mx);//000000000000000089f3fffcfffcfffd + //log(mx);//000000000000000089f3fffcfffcfffd //2: 3947442df695f8f1286adb92d9d113e8 - log(p0);//0000000000000000b9feffffffffaaab + //log(p0);//0000000000000000b9feffffffffaaab //2: 0000000000000000b9feffffffffaaab - log(tmp0);//00000000000000000000000000000001 + //log(tmp0);//00000000000000000000000000000001 //2: 00000000000000006a4aaa14be07a408 //1: 16^^643abe09d200a404ffffffffffffffff //2: 16^^299d8e4220faed31901f94fb2b3b54280000000000000000 //this is 190 bits instead of fitting into 128 limbx = (mx * p0) + tmp0; - log(limbx);//643abe09d200a4050000000000000000 + //log(limbx);//643abe09d200a4050000000000000000 //2: f21393888e24ec0f0000000000000000 hi = ~U128::from(0, limbx.upper); - log(hi);//0000000000000000643abe09d200a405 + //log(hi);//0000000000000000643abe09d200a405 //2: 0000000000000000f21393888e24ec0f i = 1; while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - log(pi);//00000000000000001eabfffeb153ffff - log(tmpi);//00000000000000000000000000000000 + //log(pi);//00000000000000001eabfffeb153ffff + //log(tmpi);//00000000000000000000000000000000 limbx = (mx * pi + hi) + tmpi; - log(limbx);//108747eeefa29c0f6a4aaa14be07a408 - tmp.insert(i - 1, limbx.lower); + //log(limbx);//108747eeefa29c0f6a4aaa14be07a408 + tmp2.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); - log(hi);//0000000000000000108747eeefa29c0f + //log(hi);//0000000000000000108747eeefa29c0f i += 1; } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); - tmp.insert(i - 1, limbx.lower); + tmp2.insert(i - 1, limbx.lower); carry = limbx.lower; j += 1; @@ -149,40 +153,42 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } mx = ~U128::from(0, unpack_or_0(b.get(j))); hi = ~U128::from(0, 0); - log(mx);//00000000000000006730d2a0f6b0f624 - log(hi);//00000000000000000000000000000000 + //log(mx);//00000000000000006730d2a0f6b0f624 + //log(hi);//00000000000000000000000000000000 i = 0; while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 - log(tmpi);//0000000000000000379b7b3fafdc26ed - limbx = (mx * (ai + hi)) + tmpi; - log(limbx);//000000000000000064774b84f38512bf - tmp.insert(i, limbx.lower); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); + //log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 + //log(tmpi);//0000000000000000379b7b3fafdc26ed + limbx = (mx * ai + hi) + tmpi; + //log(limbx);//000000000000000064774b84f38512bf + tmp3.insert(i, limbx.lower); hi = ~U128::from(0, limbx.upper); - log(hi);//00000000000000000000000000000000 + //log(hi);//00000000000000000000000000000000 i += 1; } + let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp3.get(0)))).lower; + let mut mx: U128 = ~U128::from(0, mx_temp); - mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); - log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) + //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + //log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) limbx = hi + ~U128::from(0, carry); - log(limbx);//00000000000000003623991cf3a341e8 - tmp.insert(i, limbx.lower); - log(tmp);//00000000000000004b1ba7b6434bacd7 + //log(limbx);//00000000000000003623991cf3a341e8 + tmp3.insert(i, limbx.lower); + //log(tmp);//00000000000000004b1ba7b6434bacd7 carry = limbx.upper; - log(carry);//00000000000000000000000000000000 + //log(carry);//00000000000000000000000000000000 //Conclusion so far: mx will become really large and then overflow in next iteration } - /* + let mut borrow: u64 = 0; i = 0; let mut ret: Vec = ~Vec::new::(); while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp3.get(i))); let pi_w_borrow = pi + ~U128::from(0, borrow); // Prevent underflow. When U256 arithmetic is available we can create sbb_256 let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { @@ -191,29 +197,29 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0,1)), 1) }; limbx = sub_res; - borrow = b_res; + //borrow = b_res; ret.insert(i, limbx.lower); borrow = limbx.upper & 0x1; i += 1; } -log(carry); -log(borrow); + //log(carry); + //log(borrow); let mask: u64 = if carry >= borrow { carry-borrow } else { - ~u64::max()-1 + ~u64::max() - (borrow - carry - 1) }; - */ + // mask = carry - borrow; // let mask: u64 = borrow * ~u64::max(); i = 0; let mut res: Vec = ~Vec::new::(); - // while i < n { - // let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); - // res.insert(i, value); - // i += 1; - // } + while i < n { + let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp3.get(i)) & mask); + res.insert(i, value); + i += 1; + } res } @@ -313,7 +319,12 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { } //arithmetic overflow is happning //let mut mask = carry - borrow; - let mask: u64 = borrow * ~u64::max(); + //let mask: u64 = borrow * ~u64::max(); + let mut mask = if carry >= borrow { + carry - borrow + } else { + ~u64::max() - (borrow - carry - 1) + }; let mut result: Vec = ~Vec::new::(); i = 0; while i < n { From 3f6181c99e9fbf597096d1d4c2575732748df221 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 16:27:15 -0600 Subject: [PATCH 052/160] - Tests go through script again for now, since contract testing doesn't support much - Split up tests in different files - Some code and test cleanup + ran formatter as far as possible --- .gitignore | 3 +- edwards25519/Forc.toml | 2 +- edwards25519/src/field_element.sw | 354 ++--- edwards25519/src/ge25519.sw | 12 +- edwards25519/src/main.sw | 1287 +------------------ edwards25519/src/tests/tests_add.sw | 133 ++ edwards25519/src/tests/tests_helpers64.sw | 102 ++ edwards25519/src/tests/tests_multiply.sw | 321 +++++ edwards25519/src/tests/tests_of_helpers.sw | 59 + edwards25519/src/tests/tests_reductions.sw | 195 +++ edwards25519/src/tests/tests_rshift.sw | 45 + edwards25519/src/tests/tests_scalar_mult.sw | 151 +++ edwards25519/src/tests/tests_square.sw | 57 + edwards25519/src/tests/tests_sub.sw | 182 +++ 14 files changed, 1464 insertions(+), 1439 deletions(-) create mode 100644 edwards25519/src/tests/tests_add.sw create mode 100644 edwards25519/src/tests/tests_helpers64.sw create mode 100644 edwards25519/src/tests/tests_multiply.sw create mode 100644 edwards25519/src/tests/tests_of_helpers.sw create mode 100644 edwards25519/src/tests/tests_reductions.sw create mode 100644 edwards25519/src/tests/tests_rshift.sw create mode 100644 edwards25519/src/tests/tests_scalar_mult.sw create mode 100644 edwards25519/src/tests/tests_square.sw create mode 100644 edwards25519/src/tests/tests_sub.sw diff --git a/.gitignore b/.gitignore index d6426e4..2b898f5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ Cargo.lock */Cargo.lock */Forc.lock -*/out/* \ No newline at end of file +*/out/* +*/target/* \ No newline at end of file diff --git a/edwards25519/Forc.toml b/edwards25519/Forc.toml index 25dabbc..14b5b02 100644 --- a/edwards25519/Forc.toml +++ b/edwards25519/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["HashCloak"] -entry = "field_element.sw" +entry = "main.sw" license = "Apache-2.0" name = "edwards25519" diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 04e36b9..580f477 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -15,8 +15,12 @@ pub struct Element { // = (1 << 51) - 1 // But using the above expression gives the error "Could not evaluate initializer to a const declaration." const mask_low_51_bits: u64 = 2251799813685247; -pub const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; -pub const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; +pub const zero: Element = Element { + l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 +}; +pub const one: Element = Element { + l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 +}; // from NaCl impl https://cr.yp.to/ecdh.html#use fn times19(x: u64) -> u64 { @@ -24,7 +28,7 @@ fn times19(x: u64) -> u64 { } /*Do 1 round of carrying -This return an element of which all li have at most 52 bits. +This returns an element of which all li have at most 52 bits. So the elm is at most: (2^52 - 1) + (2^52 - 1) * 2^51 + @@ -34,25 +38,26 @@ So the elm is at most: */ pub fn carry_propagate(e: Element) -> Element { // all ci have at most 13 bits - let c0 = e.l0 >> 51; - let c1 = e.l1 >> 51; - let c2 = e.l2 >> 51; - let c3 = e.l3 >> 51; + let c0 = e.l0 >> 51; + let c1 = e.l1 >> 51; + let c2 = e.l2 >> 51; + let c3 = e.l3 >> 51; // c4 represents what carries over to the 2^255 element - // since we're working 2^255 - 19, this will carry over to the first element, + // since we're working 2^255 - 19, this will carry over to the first element, // multiplied by 19 - let c4 = e.l4 >> 51; + let c4 = e.l4 >> 51; - // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and - // the final l0 will be at most 52 bits. Similarly for the rest. + // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and + // the final l0 will be at most 52 bits. Similarly for the rest. // c4 * 19 is at most 13 + 5 = 18 bits => l0 is at most 52 bits let new_l0 = (e.l0 & mask_low_51_bits) + times19(c4); - Element{ l0: new_l0, - l1: (e.l1 & mask_low_51_bits) + c0, - l2: (e.l2 & mask_low_51_bits) + c1, - l3: (e.l3 & mask_low_51_bits) + c2, - l4: (e.l4 & mask_low_51_bits) + c3 + Element { + l0: new_l0, + l1: (e.l1 & mask_low_51_bits) + c0, + l2: (e.l2 & mask_low_51_bits) + c1, + l3: (e.l3 & mask_low_51_bits) + c2, + l4: (e.l4 & mask_low_51_bits) + c3, } } @@ -92,12 +97,12 @@ pub fn reduce(e: Element) -> Element { let mut v4 = (red.l4 + (v3 >> 51)) & mask_low_51_bits; v3 = v3 & mask_low_51_bits; - Element{ - l0: v0, - l1: v1, - l2: v2, - l3: v3, - l4: v4 + Element { + l0: v0, + l1: v1, + l2: v2, + l3: v3, + l4: v4, } } @@ -105,12 +110,12 @@ pub fn reduce(e: Element) -> Element { return a + b mod 2^255 - 19 */ pub fn add(a: Element, b: Element) -> Element { - let temp = Element{ - l0: a.l0 + b.l0, - l1: a.l1 + b.l1, - l2: a.l2 + b.l2, - l3: a.l3 + b.l3, - l4: a.l4 + b.l4 + let temp = Element { + l0: a.l0 + b.l0, + l1: a.l1 + b.l1, + l2: a.l2 + b.l2, + l3: a.l3 + b.l3, + l4: a.l4 + b.l4, }; carry_propagate(temp) @@ -120,11 +125,11 @@ pub fn add(a: Element, b: Element) -> Element { pub fn subtract(a: Element, b: Element) -> Element { // we add 2*p to avoid any underflow and then subtract b let res: Element = Element { - l0: (a.l0 + 0xFFFFFFFFFFFDA) - b.l0, - l1: (a.l1 + 0xFFFFFFFFFFFFE) - b.l1, - l2: (a.l2 + 0xFFFFFFFFFFFFE) - b.l2, - l3: (a.l3 + 0xFFFFFFFFFFFFE) - b.l3, - l4: (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + l0: (a.l0 + 0xFFFFFFFFFFFDA) - b.l0, + l1: (a.l1 + 0xFFFFFFFFFFFFE) - b.l1, + l2: (a.l2 + 0xFFFFFFFFFFFFE) - b.l2, + l3: (a.l3 + 0xFFFFFFFFFFFFE) - b.l3, + l4: (a.l4 + 0xFFFFFFFFFFFFE) - b.l4, }; //carry_propagate(res) @@ -132,113 +137,122 @@ pub fn subtract(a: Element, b: Element) -> Element { } //negate return negaive of an element(-a) -pub fn negate (a: Element) -> Element { - subtract(zero,a) - +pub fn negate(a: Element) -> Element { + subtract(zero, a) } //returns 128-bit product of a and b -pub fn multiply64 (a: u64, b: u64) -> U128 { - - let A: U128 = U128 {upper: 0, lower: a}; - let B: U128 = U128 {upper: 0, lower: b}; - let AB: U128 = A*B; - return AB - +pub fn multiply64(a: u64, b: u64) -> U128 { + let A: U128 = U128 { + upper: 0, + lower: a, + }; + let B: U128 = U128 { + upper: 0, + lower: b, + }; + A * B } //returns sum with carry of a and b -pub fn add64 (a: u64, b: u64, carry: u64) -> (u64, u64) { - let A:U128 = U128{upper: 0, lower: a}; - let B:U128 = U128{upper: 0, lower: b}; - let Carry: U128 = U128 { upper: 0, lower: carry }; +pub fn add64(a: u64, b: u64, carry: u64) -> (u64, u64) { + let A: U128 = U128 { + upper: 0, + lower: a, + }; + let B: U128 = U128 { + upper: 0, + lower: b, + }; + let Carry: U128 = U128 { + upper: 0, + lower: carry, + }; - let sum: u64 = (A+B+Carry).lower; + let sum: u64 = (A + B + Carry).lower; let notSum = ~u64::max() - sum; - let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; + let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; (sum, carryOut) } -//returns res + a * b -pub fn add_multiply64 (res: U128, a: u64, b: u64) -> U128 { +//returns res + a * b +pub fn add_multiply64(res: U128, a: u64, b: u64) -> U128 { let mul_res: U128 = multiply64(a, b); let add_res: (u64, u64) = add64(mul_res.lower, res.lower, 0); let add_res2: (u64, u64) = add64(mul_res.upper, res.upper, add_res.1); - U128{ + U128 { upper: add_res2.0, - lower: add_res.0 - } + lower: add_res.0, + } } //right shift by 51 pub fn shiftRightBy51(a: U128) -> u64 { - (a.upper <<(64-51)) | (a.lower >> 51) + (a.upper <<(64 - 51)) | (a.lower >> 51) } //returns square of an Element pub fn square(a: Element) -> Element { - multiply(a,a) + multiply(a, a) } - //returns a*b pub fn multiply(a: Element, b: Element) -> Element { - //https://cs.opensource.google/go/go/+/master:src/crypto/internal/edwards25519/field/fe_generic.go;l=34;bpv=0?q=feMul&sq=&ss=go%2Fgo - + let a0 = a.l0; - let a1 = a.l1; - let a2 = a.l2; - let a3 = a.l3; - let a4 = a.l4; - - let b0 = b.l0; - let b1 = b.l1; - let b2 = b.l2; - let b3 = b.l3; - let b4 = b.l4; - - let a1_19 = times19(a1); - let a2_19 = times19(a2); - let a3_19 = times19(a3); - let a4_19 = times19(a4); + let a1 = a.l1; + let a2 = a.l2; + let a3 = a.l3; + let a4 = a.l4; + + let b0 = b.l0; + let b1 = b.l1; + let b2 = b.l2; + let b3 = b.l3; + let b4 = b.l4; + + let a1_19 = times19(a1); + let a2_19 = times19(a2); + let a3_19 = times19(a3); + let a4_19 = times19(a4); // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) let mut r0: U128 = multiply64(a0, b0); - r0 = add_multiply64(r0, a1_19, b4); - r0 = add_multiply64(r0, a2_19, b3); - r0 = add_multiply64(r0, a3_19, b2); - r0 = add_multiply64(r0, a4_19, b1); + r0 = add_multiply64(r0, a1_19, b4); + r0 = add_multiply64(r0, a2_19, b3); + r0 = add_multiply64(r0, a3_19, b2); + r0 = add_multiply64(r0, a4_19, b1); // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) - let mut r1: U128 = multiply64(a0, b1); - r1 = add_multiply64(r1, a1, b0); - r1 = add_multiply64(r1, a2_19, b4); - r1 = add_multiply64(r1, a3_19, b3); - r1 = add_multiply64(r1, a4_19, b2); + let mut r1: U128 = multiply64(a0, b1); + r1 = add_multiply64(r1, a1, b0); + r1 = add_multiply64(r1, a2_19, b4); + r1 = add_multiply64(r1, a3_19, b3); + r1 = add_multiply64(r1, a4_19, b2); // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) - let mut r2: U128 = multiply64(a0, b2); - r2 = add_multiply64(r2, a1, b1); - r2 = add_multiply64(r2, a2, b0); - r2 = add_multiply64(r2, a3_19, b4); - r2 = add_multiply64(r2, a4_19, b3); + let mut r2: U128 = multiply64(a0, b2); + r2 = add_multiply64(r2, a1, b1); + r2 = add_multiply64(r2, a2, b0); + r2 = add_multiply64(r2, a3_19, b4); + r2 = add_multiply64(r2, a4_19, b3); // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 - let mut r3: U128 = multiply64(a0, b3); - r3 = add_multiply64(r3, a1, b2); - r3 = add_multiply64(r3, a2, b1); - r3 = add_multiply64(r3, a3, b0); - r3 = add_multiply64(r3, a4_19, b4); + let mut r3: U128 = multiply64(a0, b3); + r3 = add_multiply64(r3, a1, b2); + r3 = add_multiply64(r3, a2, b1); + r3 = add_multiply64(r3, a3, b0); + r3 = add_multiply64(r3, a4_19, b4); //r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 - let mut r4: U128 = multiply64(a0, b4); - r4 = add_multiply64(r4, a1, b3); - r4 = add_multiply64(r4, a2, b2); - r4 = add_multiply64(r4, a3, b1); - r4 = add_multiply64(r4, a4, b0); + let mut r4: U128 = multiply64(a0, b4); + r4 = add_multiply64(r4, a1, b3); + r4 = add_multiply64(r4, a2, b2); + r4 = add_multiply64(r4, a3, b1); + r4 = add_multiply64(r4, a4, b0); let c0 = shiftRightBy51(r0); let c1 = shiftRightBy51(r1); @@ -265,7 +279,7 @@ pub fn multiply(a: Element, b: Element) -> Element { // For a bignumber <= 102 bits stored in U128, // return the 51 bit coefficient and 51 bit carry -fn get_coeff_and_carry(y: U128) -> (u64, u64) { +pub fn get_coeff_and_carry(y: U128) -> (u64, u64) { let coeff: u64 = y.lower & mask_low_51_bits; let carry: u64 = (y.upper << 13 & mask_low_51_bits) | y.lower >> 51; (coeff, carry) @@ -318,87 +332,89 @@ pub fn equals(a: Element, b: Element) -> bool { res == 0 } -// //a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p -// pub fn inverse(a: Element) -> Element { -// let mut i = 0; -// let z2 = square(a); //2 -// let mut t = square(z2); //4 -// t = square(t); //8 -// let z9 = multiply(t,a); //9 -// let z11 = multiply(z9, z2); //11 -// t = square(z11); //22 - -// let z2_5_0 = multiply(t, z9); //31 -// t = square(z2_5_0); // 62 = 2^6 - 2^1 -// while i < 4 { -// t = square(t); // 2^10 - 2^5 -// i+=1; -// } - -// let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 - -// t = square(z2_10_0); //2^11 - 2^1 -// i = 0; -// while i < 9 { -// t = square(t); //2^20 - 2^10 -// i += 1; -// } - -// let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 - -// t = square(z2_20_0); //2^21 - 2^1 -// i = 0; -// while i < 19 { -// t = square(t); //2^40 - 2^20 -// i += 1; -// } - -// t = multiply(t, z2_20_0); //2^40 - 2^0 +/* +//a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p +pub fn inverse(a: Element) -> Element { + let mut i = 0; + let z2 = square(a); //2 + let mut t = square(z2); //4 + t = square(t); //8 + let z9 = multiply(t,a); //9 + let z11 = multiply(z9, z2); //11 + t = square(z11); //22 + + let z2_5_0 = multiply(t, z9); //31 + t = square(z2_5_0); // 62 = 2^6 - 2^1 + while i < 4 { + t = square(t); // 2^10 - 2^5 + i+=1; + } + + let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 + + t = square(z2_10_0); //2^11 - 2^1 + i = 0; + while i < 9 { + t = square(t); //2^20 - 2^10 + i += 1; + } + + let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 + + t = square(z2_20_0); //2^21 - 2^1 + i = 0; + while i < 19 { + t = square(t); //2^40 - 2^20 + i += 1; + } + + t = multiply(t, z2_20_0); //2^40 - 2^0 -// i = 0; -// while i < 10 { -// t = square(t); //2^50 - 2^10 -// } + i = 0; + while i < 10 { + t = square(t); //2^50 - 2^10 + } -// let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 + let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 -// t = square(z2_50_0); //2^51 - 2^1 + t = square(z2_50_0); //2^51 - 2^1 -// i = 0; -// while i < 49 { -// t = square(t); //2^100 - 2^50 -// i += 1; -// } + i = 0; + while i < 49 { + t = square(t); //2^100 - 2^50 + i += 1; + } -// let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 + let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 -// t = square(z2_100_0); //2^101 - 2^1 + t = square(z2_100_0); //2^101 - 2^1 -// i = 0; -// while i < 99 { -// t = square(t); //2^200 - 2^100 -// i += 1; -// } + i = 0; + while i < 99 { + t = square(t); //2^200 - 2^100 + i += 1; + } -// t = multiply(t, z2_100_0); //2^200 - 2^0 + t = multiply(t, z2_100_0); //2^200 - 2^0 -// t = square(t); //2^201 - 2^1 + t = square(t); //2^201 - 2^1 -// i = 0; -// while i < 49 { -// t = square(t); //2^250 - 2^50 -// i += 1; -// } + i = 0; + while i < 49 { + t = square(t); //2^250 - 2^50 + i += 1; + } -// t = multiply(t, z2_50_0); //2^250 - 2^0 + t = multiply(t, z2_50_0); //2^250 - 2^0 -// i = 0; -// while i < 5 { -// t = square(t); //2^255 - 2^5 -// i += 1; -// } + i = 0; + while i < 5 { + t = square(t); //2^255 - 2^5 + i += 1; + } -// t = multiply(t, z11); //2^255 - 21 = p - 2 + t = multiply(t, z11); //2^255 - 21 = p - 2 -// return t; -// } \ No newline at end of file + return t; +} +*/ \ No newline at end of file diff --git a/edwards25519/src/ge25519.sw b/edwards25519/src/ge25519.sw index 299e3fb..c5a6cb7 100644 --- a/edwards25519/src/ge25519.sw +++ b/edwards25519/src/ge25519.sw @@ -12,7 +12,7 @@ pub struct Ge25519 { x: Element, y: Element, z: Element, - t: Element + t: Element, } // Completed point (https://doc-internal.dalek.rs/curve25519_dalek/backend/serial/curve_models/index.html) @@ -20,7 +20,7 @@ pub struct Ge25519_p1p1 { x: Element, y: Element, z: Element, - t: Element + t: Element, } /* Projective point. Satisfies: @@ -32,12 +32,12 @@ pub struct Ge25519_p1p1 { pub struct Ge25519_p2 { x: Element, y: Element, - z: Element + z: Element, } pub struct Ge25519_aff { x: Element, - y: Element + y: Element, } /* @@ -62,6 +62,6 @@ pub fn double(p: Ge25519_p2) -> Ge25519_p1p1 { x: res_x, y: res_y, z: res_Z, - t: res_t + t: res_t, } -} \ No newline at end of file +} diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index e9c3741..73a6a7b 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -3,6 +3,27 @@ script; dep field_element; dep test_helpers; +// Import all tests +dep tests/tests_add; +dep tests/tests_helpers64; +dep tests/tests_multiply; +dep tests/tests_of_helpers; +dep tests/tests_reductions; +dep tests/tests_rshift; +dep tests/tests_scalar_mult; +dep tests/tests_square; +dep tests/tests_sub; + +use ::tests_add::tests_add; +use ::tests_helpers64::test_helpers64; +use ::tests_multiply::tests_multiply; +use ::tests_of_helpers::test_helpers; +use ::tests_reductions::test_reductions; +use ::tests_rshift::tests_shiftRightBy51; +use ::tests_scalar_mult::tests_scalar_mult; +use ::tests_square::tests_square; +use ::tests_sub::tests_substract; + use ::field_element::*; use ::test_helpers::*; @@ -13,1273 +34,15 @@ use std::u128::*; fn main() { - // THESE TESTS ARE ALL OK // assert(test_helpers()); - // assert(test_reductions()); // assert(tests_add()); - // assert(tests_scalar_mult()); - // assert(tests_multiply64()); - // assert(tests_add64()); - // assert(tests_add_multiply64()); + // assert(test_helpers64()); + // assert(test_reductions()); // assert(tests_shiftRightBy51()); + // assert(tests_scalar_mult()); // assert(tests_substract()); - // Multiply functions only test OK if ran 1 at a time. (?!) + // Multiply tests can't run all at the same time assert(tests_multiply()); // assert(tests_square()); - - -} - -fn test_helpers() -> bool { - assert(test_get_zero()); - assert(test_equals()); - true -} - -fn test_get_zero() -> bool { - res_equals(zero, Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }); - true -} - -fn test_equals() -> bool { - let zero_equals_zero = equals(zero, zero); - let zero_equals_one = equals(zero, one); - let one_equals_one = equals(one, one); - - let a = Element{ - l0: 2251799813685247, - l1: 5, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 100 - }; - let b = Element{ - l0: 2251799813685247, - l1: 5, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 100 - }; - let c = Element{ - l0: 60, - l1: 5, - l2: 2251799813685247, - l3: 500, - l4: 100 - }; - let a_equals_a = equals(a,a); - let a_equals_b = equals(a,b); //a and b have same coefficients - let a_equals_c = equals(a,c); - let b_equals_c = equals(b,c); - - assert(zero_equals_zero); - assert(!zero_equals_one); - assert(one_equals_one); - - assert(a_equals_a); - assert(a_equals_b); - assert(!a_equals_c); - assert(!b_equals_c); - - true -} -//------------------------------------------------------------------------------------------------ -fn test_reductions() -> bool { - assert(test_carry_propagate_1()); - assert(test_carry_propagate_2()); - assert(test_reduce()); - assert(test_reduce_2()); - assert(test_reduce_3()); - assert(test_reduce_4()); - true -} - -fn test_carry_propagate_1() -> bool { - /* - 2^64 -1 = 18446744073709551615 - - 18446744073709551615 + - 18446744073709551615 * 2^51 + - 18446744073709551615 * 2^102 + - 18446744073709551615 * 2^153 + - 18446744073709551615 * 2^204 - */ - let e = Element{ - l0: ~u64::max(), - l1: ~u64::max(), - l2: ~u64::max(), - l3: ~u64::max(), - l4: ~u64::max() }; - - let res = carry_propagate(e); - - // Each limb has a carry of 8191 and a coeff of 2251799813685247 - // So after a round of reduction this is - /* equals - 2251799813685247 + (19*8191) + - (2251799813685247 + 8191) * 2^51 + - (2251799813685247 + 8191) * 2^102 + - (2251799813685247 + 8191) * 2^153 + - (2251799813685247 + 8191) * 2^204 - = 57896044618868696584113898827420068118245036358148060739095062128926159691756 - */ - res_equals(res, Element{ - l0: 2251799813685247 + (19*8191), - l1: 2251799813685247 + 8191, - l2: 2251799813685247 + 8191, - l3: 2251799813685247 + 8191, - l4: 2251799813685247 + 8191 - }); - - // Note that this result is >2^255-19 because the function only does 1 round of reduction - - true } - -fn test_carry_propagate_2() -> bool { - // 2251799813685250 = 2 + 2^51 - let e = Element{ - l0: 2251799813685250, - l1: 0, - l2: 0, - l3: 0, - l4: 0 }; - - let res = carry_propagate(e); - - res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); - - true -} - -fn test_reduce() -> bool { - // 2251799813685250 = 2 + 2^51 - let e = Element{ - l0: 2251799813685250, - l1: 0, - l2: 0, - l3: 0, - l4: 0 }; - - let res = reduce(e); - - res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); - - true -} - -fn test_reduce_2() -> bool { - /* - 2^51 + 2 = 2251799813685250 - - 2251799813685250 + - 2251799813685250 * 2^51 + - 2251799813685250 * 2^102 + - 2251799813685250 * 2^153 + - 2251799813685250 * 2^204 - mod 2^255-19 - */ - let e = Element{ - l0: 2251799813685250, - l1: 2251799813685250, - l2: 2251799813685250, - l3: 2251799813685250, - l4: 2251799813685250 }; - - let res = reduce(e); - - /* equals - 21 + - 3 * 2^51 + - 3 * 2^102 + - 3 * 2^153 + - 3 * 2^204 - */ - res_equals(res, Element{ l0: 21, l1: 3, l2: 3, l3: 3, l4: 3 }); - - true -} - -fn test_reduce_3() -> bool { - /* - 2^64 -1 = 18446744073709551615 - - 18446744073709551615 + - 18446744073709551615 * 2^51 + - 18446744073709551615 * 2^102 + - 18446744073709551615 * 2^153 + - 18446744073709551615 * 2^204 - mod 2^255 -19 - = 210598872328406323076114191610044025327778719366270124969594871807 - */ - let e = Element{ - l0: ~u64::max(), - l1: ~u64::max(), - l2: ~u64::max(), - l3: ~u64::max(), - l4: ~u64::max() }; - - let res = reduce(e); - - /* - 155647 + - 8191 * 2^51 + - 8191 * 2^102 + - 8191 * 2^153 + - 8191 * 2^204 - = 210598872328406323076114191610044025327778719366270124969594871807 - */ - res_equals(res, Element{ - l0: 155647, - l1: 8191, - l2: 8191, - l3: 8191, - l4: 8191 - }); - - true -} - -fn test_reduce_4() -> bool { - /* - 4503599627370494 + - 4503599627370494 * 2^51 + - 4503599627370494 * 2^102 + - 4503599627370494 * 2^153 + - 4503599627370494 * 2^204 - mod 2^255 - 19 - - = 36 - */ - let e = Element{ - l0: 4503599627370494, - l1: 4503599627370494, - l2: 4503599627370494, - l3: 4503599627370494, - l4: 4503599627370494 }; - - let res = reduce(e); - - /* - should be 36 - */ - res_equals(res, Element{ - l0: 36, - l1: 0, - l2: 0, - l3: 0, - l4: 0 - }); - - true -} -//------------------------------------------------------------------------------------------- -fn tests_add() -> bool { - assert(test_add_to_0()); - assert(test_add_0()); - assert(test_add_a_to_b()); - assert(test_add_a_to_a()); - true - -} - -fn test_add_to_0() -> bool { - let b = Element{ - l0: 8191, - l1: 225179, - l2: 155647, - l3: 81918191, - l4: 85247 - }; - - let res = add(zero, b); - - assert(res_equals(res, b)); - true -} - -fn test_add_0() -> bool { - let b = Element{ - l0: 8191, - l1: 225179, - l2: 155647, - l3: 81918191, - l4: 85247 - }; - - let res = add(b, zero); - - assert(res_equals(res, b)); - true -} - -fn test_add_a_to_b() -> bool { - // coefficients are 2^51-1 - /* - 2251799813685247 + - 2251799813685247 * 2^51 + - 2251799813685247 * 2^102 + - 2251799813685247 * 2^153 + - 2251799813685247 * 2^204 - = 57896044618658097711785492504343953926634992332820282019728792003956564819967 - */ - let a = Element{ - l0: 2251799813685247, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - - // random - /* - 8191 + - 225179 * 2^51 + - 155647 * 2^102 + - 81918191 * 2^153 + - 85247 * 2^204 - = 2191786359344073644698773448800701597704682582429191096092436996095 - */ - let b = Element{ - l0: 8191, - l1: 225179, - l2: 155647, - l3: 81918191, - l4: 85247 - }; - - // a+b mod 2^255 -19 - // should be 2191786359344073644698773448800701597704682582429191096092436996113 - let res = add(a,b); - - /* - 8209 + - 225179 * 2^51 + - 155647 * 2^102 + - 81918191 * 2^153 + - 85247 * 2^204 - = 2191786359344073644698773448800701597704682582429191096092436996113 - */ - res_equals(res, Element{ - l0: 8209, - l1: 225179, - l2: 155647, - l3: 81918191, - l4: 85247 - }); - - true -} - -fn test_add_a_to_a() -> bool { - // 2^255 - 20 (the largest number) expressed in radix-51 - /* - 2251799813685228 + - 2251799813685247 * 2^51 + - 2251799813685247 * 2^102 + - 2251799813685247 * 2^153 + - 2251799813685247 * 2^204 - */ - let a = Element{ - l0: 2251799813685228, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - - let res = add(a, a); - - res_equals(res, Element{ - l0: 2251799813685227, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }); - - true -} -//-------------------------------------------------------------------------------------------- -fn tests_scalar_mult() -> bool { - assert(test_mult_by_0()); - assert(test_mult_by_1()); - assert(test_mult_by_2()); - assert(test_mult_by_2_again()); - assert(test_mult_by_large_scalar()); - true -} - -fn test_mult_by_0() -> bool { - let a = Element{ - l0: 2251799813685247, - l1: 5, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 100 - }; - - let res: Element = scalar_mult(a, 0); - res_equals(res, zero); - true -} - -fn test_mult_by_1() -> bool { - let a = Element{ - l0: 79611, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 555555333333222, - l4: 2251799813685247 - }; - - let res: Element = scalar_mult(a, 1); - res_equals(res, a); - true -} - -fn test_mult_by_2() -> bool { - /* - 79611 + - 2251799813685247 * 2^51 + - 2251799813685247 * 2^102 + - 555555333333222 * 2^153 + - 2251799813685247 * 2^204 - */ - let a = Element{ - l0: 79611, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 555555333333222, - l4: 2251799813685247 - }; - - /* 57896044618658058976409158941982667984400415217654165675094330160006532591113 - =[159241, - 2251799813685246, - 2251799813685247, - 1111110666666445, - 2251799813685246] */ - let res: Element = scalar_mult(a, 2); - - res_equals(res, Element{ - l0: 159241, - l1: 2251799813685246, - l2: 2251799813685247, - l3: 1111110666666445, - l4: 2251799813685246 - }); - - true -} - -fn test_mult_by_2_again() -> bool { - // 2^255 - 20 (the largest number) expressed in radix-51 - /* - 2251799813685228 + - 2251799813685247 * 2^51 + - 2251799813685247 * 2^102 + - 2251799813685247 * 2^153 + - 2251799813685247 * 2^204 - */ - let a = Element{ - l0: 2251799813685228, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - - - let res: Element = scalar_mult(a, 2); - - /* - 2251799813685227 - 2251799813685247* 2^51 + - 2251799813685247* 2^102 + - 2251799813685247* 2^153 + - 2251799813685247 * 2^204 - */ - res_equals(res, Element{ - l0: 2251799813685227, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }); - - true -} - -fn test_mult_by_large_scalar() -> bool { - /* - 79611 + - 2251799813685247 * 2^51 + - 2251799813685247 * 2^102 + - 555555333333222 * 2^153 + - 2251799813685247 * 2^204 - */ - let a = Element{ - l0: 79611, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 555555333333222, - l4: 2251799813685247 - }; - - /* - 248661618146997193275445770277948644497863737508141907291226725252005565483705230608645 - reduced mod 2^255 - 19 - = 57895961435070841628109209456323569962738033236635300844883400985433276860639 - = [342008245700831, 2251795518717953, 2251799813685247, 536152338865944, 2251796578355658] - */ - // Largest scalar input possible is 2^32 -1 = 4294967295 - let res: Element = scalar_mult(a, 4294967295); - - res_equals(res, Element{ - l0: 342008245700831, - l1: 2251795518717953, - l2: 2251799813685247, - l3: 536152338865944, - l4: 2251796578355658 - }); - - true -} -//-------------------------------------------------------------------------------------------- -fn tests_substract() -> bool { - assert(test_subtraction_by_0()); - assert(test_subtraction_by_1()); - assert(test_subtraction_by_max()); - assert(test_subtraction_random()); - true -} - -fn test_subtraction_by_0() -> bool { - let a = Element{ - l0: 2251799813685247, - l1: 5, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 100 - }; - - let res: Element = subtract(a, zero); - res_equals(res, a); - - true -} - -fn test_subtraction_by_1() -> bool { - let a = Element{ - l0: 2251799813685247, - l1: 5, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 100 - }; - - let b = Element{ - l0: 2251799813685246, - l1: 5, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 100 - }; - - let res: Element = subtract(a, one); - res_equals(res, b); - true -} - -fn test_subtraction_by_max() -> bool { - - //using GP-PARI one can convert a number into arbitrary base using the command digits(number, base) - - /* - 2^255 - 21 = 57896044618658097711785492504343953926634992332820282019728792003956564819947 - = [2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685227] - = Element { - 2251799813685227, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247 - } - */ - - let a = Element{ - l0: 2251799813685227, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - - /* - 2^255 - 20 = 57896044618658097711785492504343953926634992332820282019728792003956564819948 - = [2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685228] - = Element { - 2251799813685228, - 2251799813685247, - 2251799813685247, - 2251799813685247, - 2251799813685247 - } - */ - - let b = Element { - l0: 2251799813685228, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - - let res: Element = subtract(a, b); - let res2: Element = subtract(b,a); - res_equals(res, b); - res_equals(res2, one); - true -} - -fn test_subtraction_random() -> bool { - /* - subtraction of random 2 numbers generated using GP-PARI - - a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 - = [50591579140481, 601879629470779, 595911506101250, 1303372017735434, 1292655137982008] - = Element { - 1292655137982008, - 1303372017735434, - 595911506101250, - 601879629470779, - 50591579140481 - } - - b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 - = [137209507300112, 293961277766182, 335483569739384, 807899991388824, 1360902863141127] - = Element { - 1360902863141127, - 807899991388824, - 335483569739384, - 293961277766182, - 137209507300112 - } - - b - a = 2227034305193647043917155265022785584227666213349054009788224516815197975247 - = [86617928159630, 1943881461980650, 1991371877323381, 1756327787338638, 68247725159119] - = Element { - 68247725159119, - 1756327787338638, - 1991371877323381, - 1943881461980650, - 86617928159630 - } - a - b + p = 55669010313464450667868337239321168342407326119471228009940567487141366844702 - = [2165181885525617, 307918351704597, 260427936361866, 495472026346609, 2183552088526110] - = Element { - 2183552088526110, - 495472026346609, - 260427936361866, - 307918351704597, - 2165181885525617 - } - */ - - let a = Element { - l0: 1292655137982008, - l1: 1303372017735434, - l2: 595911506101250, - l3: 601879629470779, - l4: 50591579140481 - }; - - let b = Element { - l0: 1360902863141127, - l1: 807899991388824, - l2: 335483569739384, - l3: 293961277766182, - l4: 137209507300112 - }; - - let a_minus_b = Element { - l0: 2183552088526110, - l1: 495472026346609, - l2: 260427936361866, - l3: 307918351704597, - l4: 2165181885525617 - }; - - let b_minus_a = Element { - l0: 68247725159119, - l1: 1756327787338638, - l2: 1991371877323381, - l3: 1943881461980650, - l4: 86617928159630 - }; - - let res: Element = subtract(a, b); - let res2: Element = subtract(b,a); - res_equals(res, a_minus_b); - res_equals(res2, b_minus_a); - //print_el(res2); - true -} -//------------------------------------------------------------------------------------------------------------- -fn tests_multiply64() -> bool { - assert(test_multiply64_random()); - true -} - -fn test_multiply64_random()-> bool{ - let a = 9837491998535547791; - let b = 10009796384580774444; -/* -a*b = 98471291840283423519614919326553453204 - = [5338139427034470684, 5960040633016627860] -*/ - let ab: U128 = U128 { - upper: 5338139427034470684, - lower: 5960040633016627860 - }; - - let res = multiply64(a, b); - assert(res == ab); - //print_U128(res); - - true -} -//---------------------------------------------------------------------------------------------------- -fn tests_add64() -> bool { - assert(test_add64_random()); - assert(test_add64_random_with_carry()); - true -} - -fn test_add64_random() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res:(u64,u64) = add64(a, b, 0); - let a_plus_b: (u64,u64) = (1400544309406770619, 1); - - assert(res.0 == a_plus_b.0); - assert(res.1 == a_plus_b.1); - true -} - -fn test_add64_random_with_carry() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res:(u64,u64) = add64(a, b, 1); - let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); - - assert(res.0 == a_plus_b_and_carry.0); - assert(res.1 == a_plus_b_and_carry.1); - true -} -//------------------------------------------------------------------------------------------------------------ -fn tests_add_multiply64() -> bool { - assert(test_add_multiply64()); - assert(test_add_multiply64_2()); - // assert(test_add_multiply64_random()); - // assert(test_add_multiply64_max()); - true -} - -fn test_add_multiply64() -> bool { - let a = 496009164746885; - let b = 24764068336973246; - //ab=12283204851556881218686606838710 - - let r = U128{upper: 2516888776885, lower: 8614063320694916486}; - //r=46428403129198069714856710112646 - - // should be - //58711607980754950933543316951356 - //[10881738262824685884, 3182762646142] - let mut res = add_multiply64(r,a,b); - equals_U128(res, 10881738262824685884, 3182762646142); - - true -} - -fn test_add_multiply64_2() -> bool { - let a = 24764068336973246; - let b = 137209507300112; - //ab=3397865615262403032595436803552 - - // r= 1759178078333803271346890843016 - //[16956620749643293576, 95365234715] - let r = U128{upper: 95365234715, lower: 16956620749643293576}; - - // should be - //5157043693596206303942327646568 - //[18148778710141221224, 279563898809] - let mut res = add_multiply64(r,a,b); - - equals_U128(res, 18148778710141221224, 279563898809); - - true -} - -fn test_add_multiply64_max() -> bool { - /* - random 51 bit number a = 496009164746885 - a*19 = 9424174130190815 - random 107 bit number r = 46428403129198069714856710112646 - - res = [2770292668654, 9024291134538729057] - */ - - let a = 496009164746885; - let b = a*19; - let r = U128{upper: 2516888776885, lower: 8614063320694916486}; - - let mut res = add_multiply64(r,a,b); - // res = add_multiply64(r,a,b); - // res = add_multiply64(r,a,b); - // res = add_multiply64(r,a,b); - // res = add_multiply64(r,a,b); - print_U128(res); - //5338139427034470685 - //16558383139134563912 - true - -} - -fn test_add_multiply64_random() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - /* - a*b = 98471291840283423519614919326553453204 - = [5338139427034470684, 5960040633016627860] - - random r = 10598342506117936052 - - ab + r = 98471291840283423530213261832671389256 - = [5338139427034470684, 16558383139134563912] - - */ - let r:U128 = U128{upper: 0, lower: 10598342506117936052}; - let res = add_multiply64(r, a, b); - - print_U128(res); -//2770292668654 -//9024291134538729057 - true - - - -} -//----------------------------------------------------------------------------------------------------- - -fn tests_shiftRightBy51() -> bool { - assert(test_shiftRightBy51_random()); - assert(test_shiftRightBy51_random_2()); - assert(test_shiftRightBy51_random_3()); - true -} - -fn test_shiftRightBy51_random() -> bool { - - let a = U128{upper: 16, lower:0}; - let res = shiftRightBy51(a); - assert(res == 131072); - true -} - -fn test_shiftRightBy51_random_2() -> bool { - /* -456464 + (349323232 << 64) = 6443876259705066799772399376 - ->>51 = 2861655916544 - */ - let a = U128{upper: 349323232, lower:456464}; - let res = shiftRightBy51(a); - assert(res == 2861655916544); - true -} - -fn test_shiftRightBy51_random_3() -> bool { - /* -18446744073709551615 + (349323232 << 64) = 6443876278151810873481494527 - ->>51 = 2861655924735 - */ - let a = U128{upper: 349323232, lower:18446744073709551615}; - let res = shiftRightBy51(a); - assert(res == 2861655924735); - true -} - -//---------------------------------------------------------------------------------------------------- -fn tests_multiply() -> bool { - // assert(test_multiply_by_0()); - // assert(test_multiply_1_by_1()); - // assert(test_multiply_by_1_small()); - // assert(test_multiply_by_1_large()); - // assert(test_multiply_small_elms()); - // assert(test_multiply_small_elms_2()); - // assert(test_multiply_small_elms_3()); - assert(test_multiply_elms_4()); - // assert(test_multiply_random()); - true -} - -fn test_multiply_by_0() -> bool { - - //a = 2^255 - 21 - let a = Element{ - l0: 2251799813685227, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - let res: Element = multiply(a, zero); - res_equals(res, zero); - true -} - -fn test_multiply_1_by_1() -> bool { - let res: Element = multiply(one, one); - res_equals(res, one); - - true -} - -fn test_multiply_by_1_small() -> bool { - - let a = Element{ - l0: 10, - l1: 11, - l2: 12, - l3: 13, - l4: 14 - }; - let res: Element = multiply(a, one); - res_equals(res, a); - true -} - -fn test_multiply_by_1_large() -> bool { - - //a = 2^255 - 21 - let a = Element{ - l0: 2251799813685227, - l1: 2251799813685247, - l2: 2251799813685247, - l3: 2251799813685247, - l4: 2251799813685247 - }; - let res: Element = multiply(a, one); - res_equals(res, a); - true -} - -fn test_multiply_small_elms() -> bool { - -/* -10 + -11 * 2^51 + -12 * 2^102 + -13 * 2^153 + -14 * 2^204 -= -359954121914013970155159550104308900255525248390881418617552906 -*/ - let a = Element{ - l0: 10, - l1: 11, - l2: 12, - l3: 13, - l4: 14 - }; -/* -2 + -3 * 2^51 + -4 * 2^102 + -5 * 2^153 + -6 * 2^204 -= -154266052248863123541936069103167134583173917060132914191138818 -*/ - let b = Element{ - l0: 2, - l1: 3, - l2: 4, - l3: 5, - l4: 6 - }; - let res: Element = multiply(a, b); - - // = 5913532002873104218298081466563921672602110506934768320078942312 - // = [4200, 3719, 2909, 1752, 230] - res_equals(res, Element { - l0: 4200, - l1: 3719, - l2: 2909, - l3: 1752, - l4: 230 - }); - true -} - -fn test_multiply_small_elms_2() -> bool { - -/* -10 + -11 * 2^51 + -12 * 2^102 + -1292655137982008 * 2^153 + -14 * 2^204 -= -374713634419208422705277081530098872100895088375962880689831946 -*/ - let a = Element{ - l0: 10, - l1: 11, - l2: 12, - l3: 1292655137982008, - l4: 14 - }; -/* -2 + -3 * 2^51 + -4 * 2^102 + -5 * 2^153 + -6 * 2^204 -= -154266052248863123541936069103167134583173917060132914191138818 -*/ - let b = Element{ - l0: 2, - l1: 3, - l2: 4, - l3: 5, - l4: 6 - }; - let res: Element = multiply(a, b); - -//41810357909193713957696946830561922437378062290049323977762016618127807079743 -//[1414398498170175, 1205048169289895, 995697840409273, 333510462280559, 1626165600260968] - res_equals(res, Element { - l0: 1414398498170175, - l1: 1205048169289895, - l2: 995697840409273, - l3: 333510462280559, - l4: 1626165600260968 - }); - true -} - -fn test_multiply_small_elms_3() -> bool { - -/* -1292655137982008 + -1303372017735434 * 2^51 + -595911506101250 * 2^102 + -601879629470779 * 2^153 + -50591579140481 * 2^204 -= -1300760531839662334344262085631565818852980666446405835776058138544728770104 -*/ - let a = Element { - l0: 1292655137982008, - l1: 1303372017735434, - l2: 595911506101250, - l3: 601879629470779, - l4: 50591579140481 - }; -/* -2 + -3 * 2^51 + -4 * 2^102 + -5 * 2^153 + -6 * 2^204 -= -154266052248863123541936069103167134583173917060132914191138818 -*/ - let b = Element{ - l0: 2, - l1: 3, - l2: 4, - l3: 5, - l4: 6 - }; - let res: Element = multiply(a, b); - -//14111756534184466847966592306453182667710228607558444947423180242606813803383 -//[1954506281775991, 334157138245186, 376444288997219, 169499236944723, 548860478185542] res_equals(res, Element { - res_equals(res, Element { - l0: 1954506281775991, - l1: 334157138245186, - l2: 376444288997219, - l3: 169499236944723, - l4: 548860478185542 - }); - true -} - -fn test_multiply_elms_4() -> bool { - -/* -1292655137982008 + -1303372017735434 * 2^51 + -595911506101250 * 2^102 + -601879629470779 * 2^153 + -50591579140481 * 2^204 -= -1300760531839662334344262085631565818852980666446405835776058138544728770104 -*/ - let a = Element { - l0: 1292655137982008, - l1: 1303372017735434, - l2: 595911506101250, - l3: 601879629470779, - l4: 50591579140481 - }; -/* -1360902863141127 + -807899991388824 * 2^51 + -335483569739384 * 2^102 + -293961277766182 * 2^153 + -137209507300112 * 2^204 -= -3527794837033309378261417350654351403080646879795459845564282655359926745351 -*/ - let b = Element { - l0: 1360902863141127, - l1: 807899991388824, - l2: 335483569739384, - l3: 293961277766182, - l4: 137209507300112 - }; - let res: Element = multiply(a, b); - -//26419211797770492947925431317169526880133696901606348938375383866077151145114 -//[896638975913114, 1000789340506524, 355992668009873, 806477788321681, 1027544741541094] - res_equals(res, Element { - l0: 896638975913114, - l1: 1000789340506524, - l2: 355992668009873, - l3: 806477788321681, - l4: 1027544741541094 - }); - true -} - -/* -fn test_multiply_random() -> bool { - /* - a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 - = [1292655137982008, 1303372017735434, 595911506101250, 601879629470779, 50591579140481] - = Element { - 1292655137982008, - 1303372017735434, - 595911506101250, - 601879629470779, - 50591579140481 - } - - b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 - = [1360902863141127, 807899991388824, 335483569739384, 293961277766182, 137209507300112] - = Element { - 1360902863141127, - 807899991388824, - 335483569739384, - 293961277766182, - 137209507300112 - } - - ab mod p = 26419211797770492947925431317169526880133696901606348938375383866077151145114 - = [896638975913114, 1000789340506524, 355992668009873, 806477788321681, 1027544741541094] - - */ - - let a = Element { - l0: 1292655137982008, - l1: 1303372017735434, - l2: 595911506101250, - l3: 601879629470779, - l4: 50591579140481 - }; - - let b = Element { - l0: 1360902863141127, - l1: 807899991388824, - l2: 335483569739384, - l3: 293961277766182, - l4: 137209507300112 - }; - - let ab = Element { - l0: 896638975913114, - l1: 1000789340506524, - l2: 355992668009873, - l3: 806477788321681, - l4: 1027544741541094 - }; - - - let res: Element = multiply(a, b); - // print_el(res); - res_equals(res, ab); - true -} -*/ -//--------------------------------------------------------------------------------------------------------- - -fn tests_square() -> bool { - // assert(test_square_one()); - // assert(test_square_zero()); - assert(test_square_random()); - true -} - -fn test_square_one() -> bool { - let res: Element = square(one); - res_equals(res, one); - true -} - -fn test_square_zero() -> bool { - let res: Element = square(zero); - res_equals(res, zero); - true -} - -fn test_square_random() -> bool { - /* - a = 10406084254717298682985401286246103758749877058048555650117556132341049525816 - = [404732633123850, 312158315551803, 595911506101250, 1303372017735434, 1292655137982008] - - a^2 = 108286589516275277577373161473966445398256506358898379115846293425853328039181187715348880647692926795184739504006825065723361671067040986483318450465856 - - a^2 mod p = 31042580993865580304222384966530826020546840941977848835924726765219788840807 - = [1207365348681671, 713663780369466, 912635275234964, 596790797966485, 2144628324130663] - - */ - - let a: Element = Element { - l0: 1292655137982008, - l1: 1303372017735434, - l2: 595911506101250, - l3: 312158315551803, - l4: 404732633123850 - }; - - let a_square: Element = Element { - l0: 2144628324130663, - l1: 596790797966485, - l2: 912635275234964, - l3: 713663780369466, - l4: 1207365348681671 - }; - - let res: Element = square(a); - res_equals(res, a_square); - true -} \ No newline at end of file diff --git a/edwards25519/src/tests/tests_add.sw b/edwards25519/src/tests/tests_add.sw new file mode 100644 index 0000000..d57963a --- /dev/null +++ b/edwards25519/src/tests/tests_add.sw @@ -0,0 +1,133 @@ +library tests_add; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; +use std::u128::*; + +pub fn tests_add() -> bool { + assert(test_add_to_0()); + assert(test_add_0()); + assert(test_add_a_to_b()); + assert(test_add_a_to_a()); + true + +} + +fn test_add_to_0() -> bool { + let b = Element{ + l0: 8191, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }; + + let res = add(zero, b); + + assert(res_equals(res, b)); + true +} + +fn test_add_0() -> bool { + let b = Element{ + l0: 8191, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }; + + let res = add(b, zero); + + assert(res_equals(res, b)); + true +} + +fn test_add_a_to_b() -> bool { + // coefficients are 2^51-1 + /* + 2251799813685247 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 2251799813685247 * 2^153 + + 2251799813685247 * 2^204 + = 57896044618658097711785492504343953926634992332820282019728792003956564819967 + */ + let a = Element{ + l0: 2251799813685247, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + // random + /* + 8191 + + 225179 * 2^51 + + 155647 * 2^102 + + 81918191 * 2^153 + + 85247 * 2^204 + = 2191786359344073644698773448800701597704682582429191096092436996095 + */ + let b = Element{ + l0: 8191, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }; + + // a+b mod 2^255 -19 + // should be 2191786359344073644698773448800701597704682582429191096092436996113 + let res = add(a,b); + + /* + 8209 + + 225179 * 2^51 + + 155647 * 2^102 + + 81918191 * 2^153 + + 85247 * 2^204 + = 2191786359344073644698773448800701597704682582429191096092436996113 + */ + res_equals(res, Element{ + l0: 8209, + l1: 225179, + l2: 155647, + l3: 81918191, + l4: 85247 + }); + + true +} + +fn test_add_a_to_a() -> bool { + // 2^255 - 20 (the largest number) expressed in radix-51 + /* + 2251799813685228 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 2251799813685247 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 2251799813685228, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + let res = add(a, a); + + res_equals(res, Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }); + + true +} \ No newline at end of file diff --git a/edwards25519/src/tests/tests_helpers64.sw b/edwards25519/src/tests/tests_helpers64.sw new file mode 100644 index 0000000..2de6622 --- /dev/null +++ b/edwards25519/src/tests/tests_helpers64.sw @@ -0,0 +1,102 @@ +library tests_helpers64; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; +use std::u128::*; + +pub fn test_helpers64() -> bool { + assert(tests_multiply64()); + assert(tests_add64()); + assert(tests_add_multiply64()); + true +} + + +fn tests_multiply64() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; +/* +a*b = 98471291840283423519614919326553453204 + = [5338139427034470684, 5960040633016627860] +*/ + let ab: U128 = U128 { + upper: 5338139427034470684, + lower: 5960040633016627860 + }; + + let res = multiply64(a, b); + assert(res == ab); + + true +} + +fn tests_add64() -> bool { + assert(test_add64_random()); + assert(test_add64_random_with_carry()); + true +} + +fn test_add64_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = add64(a, b, 0); + let a_plus_b: (u64,u64) = (1400544309406770619, 1); + + assert(res.0 == a_plus_b.0); + assert(res.1 == a_plus_b.1); + true +} + +fn test_add64_random_with_carry() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = add64(a, b, 1); + let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); + + assert(res.0 == a_plus_b_and_carry.0); + assert(res.1 == a_plus_b_and_carry.1); + true +} + +fn tests_add_multiply64() -> bool { + assert(test_add_multiply64()); + assert(test_add_multiply64_2()); + true +} + +fn test_add_multiply64() -> bool { + let a = 496009164746885; + let b = 24764068336973246; + //ab=12283204851556881218686606838710 + + let r = U128{upper: 2516888776885, lower: 8614063320694916486}; + //r=46428403129198069714856710112646 + + // should be + //58711607980754950933543316951356 + //[10881738262824685884, 3182762646142] + let mut res = add_multiply64(r,a,b); + equals_U128(res, 10881738262824685884, 3182762646142); + + true +} + +fn test_add_multiply64_2() -> bool { + let a = 24764068336973246; + let b = 137209507300112; + //ab=3397865615262403032595436803552 + + // r= 1759178078333803271346890843016 + //[16956620749643293576, 95365234715] + let r = U128{upper: 95365234715, lower: 16956620749643293576}; + + // should be + //5157043693596206303942327646568 + //[18148778710141221224, 279563898809] + let mut res = add_multiply64(r,a,b); + + equals_U128(res, 18148778710141221224, 279563898809); + + true +} \ No newline at end of file diff --git a/edwards25519/src/tests/tests_multiply.sw b/edwards25519/src/tests/tests_multiply.sw new file mode 100644 index 0000000..d29bf2e --- /dev/null +++ b/edwards25519/src/tests/tests_multiply.sw @@ -0,0 +1,321 @@ +library tests_multiply; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; + +pub fn tests_multiply() -> bool { + // assert(test_multiply_by_0()); + // assert(test_multiply_1_by_1()); + // assert(test_multiply_by_1_small()); + // assert(test_multiply_by_1_large()); + assert(test_multiply_small_elms()); + assert(test_multiply_small_elms_2()); + assert(test_multiply_small_elms_3()); + assert(test_multiply_elms_4()); + // assert(test_multiply_random()); + true +} + +fn test_multiply_by_0() -> bool { + + //a = 2^255 - 21 + let a = Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + let res: Element = multiply(a, zero); + res_equals(res, zero); + true +} + +fn test_multiply_1_by_1() -> bool { + let res: Element = multiply(one, one); + res_equals(res, one); + + true +} + +fn test_multiply_by_1_small() -> bool { + + let a = Element{ + l0: 10, + l1: 11, + l2: 12, + l3: 13, + l4: 14 + }; + let res: Element = multiply(a, one); + res_equals(res, a); + true +} + +fn test_multiply_by_1_large() -> bool { + + //a = 2^255 - 21 + let a = Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + let res: Element = multiply(a, one); + res_equals(res, a); + true +} + +fn test_multiply_small_elms() -> bool { + +/* +10 + +11 * 2^51 + +12 * 2^102 + +13 * 2^153 + +14 * 2^204 += +359954121914013970155159550104308900255525248390881418617552906 +*/ + let a = Element{ + l0: 10, + l1: 11, + l2: 12, + l3: 13, + l4: 14 + }; +/* +2 + +3 * 2^51 + +4 * 2^102 + +5 * 2^153 + +6 * 2^204 += +154266052248863123541936069103167134583173917060132914191138818 +*/ + let b = Element{ + l0: 2, + l1: 3, + l2: 4, + l3: 5, + l4: 6 + }; + let res: Element = multiply(a, b); + + // = 5913532002873104218298081466563921672602110506934768320078942312 + // = [4200, 3719, 2909, 1752, 230] + res_equals(res, Element { + l0: 4200, + l1: 3719, + l2: 2909, + l3: 1752, + l4: 230 + }); + true +} + +fn test_multiply_small_elms_2() -> bool { + +/* +10 + +11 * 2^51 + +12 * 2^102 + +1292655137982008 * 2^153 + +14 * 2^204 += +374713634419208422705277081530098872100895088375962880689831946 +*/ + let a = Element{ + l0: 10, + l1: 11, + l2: 12, + l3: 1292655137982008, + l4: 14 + }; +/* +2 + +3 * 2^51 + +4 * 2^102 + +5 * 2^153 + +6 * 2^204 += +154266052248863123541936069103167134583173917060132914191138818 +*/ + let b = Element{ + l0: 2, + l1: 3, + l2: 4, + l3: 5, + l4: 6 + }; + let res: Element = multiply(a, b); + +//41810357909193713957696946830561922437378062290049323977762016618127807079743 +//[1414398498170175, 1205048169289895, 995697840409273, 333510462280559, 1626165600260968] + res_equals(res, Element { + l0: 1414398498170175, + l1: 1205048169289895, + l2: 995697840409273, + l3: 333510462280559, + l4: 1626165600260968 + }); + true +} + +fn test_multiply_small_elms_3() -> bool { + +/* +1292655137982008 + +1303372017735434 * 2^51 + +595911506101250 * 2^102 + +601879629470779 * 2^153 + +50591579140481 * 2^204 += +1300760531839662334344262085631565818852980666446405835776058138544728770104 +*/ + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; +/* +2 + +3 * 2^51 + +4 * 2^102 + +5 * 2^153 + +6 * 2^204 += +154266052248863123541936069103167134583173917060132914191138818 +*/ + let b = Element{ + l0: 2, + l1: 3, + l2: 4, + l3: 5, + l4: 6 + }; + let res: Element = multiply(a, b); + +//14111756534184466847966592306453182667710228607558444947423180242606813803383 +//[1954506281775991, 334157138245186, 376444288997219, 169499236944723, 548860478185542] res_equals(res, Element { + res_equals(res, Element { + l0: 1954506281775991, + l1: 334157138245186, + l2: 376444288997219, + l3: 169499236944723, + l4: 548860478185542 + }); + true +} + +fn test_multiply_elms_4() -> bool { + +/* +1292655137982008 + +1303372017735434 * 2^51 + +595911506101250 * 2^102 + +601879629470779 * 2^153 + +50591579140481 * 2^204 += +1300760531839662334344262085631565818852980666446405835776058138544728770104 +*/ + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; +/* +1360902863141127 + +807899991388824 * 2^51 + +335483569739384 * 2^102 + +293961277766182 * 2^153 + +137209507300112 * 2^204 += +3527794837033309378261417350654351403080646879795459845564282655359926745351 +*/ + let b = Element { + l0: 1360902863141127, + l1: 807899991388824, + l2: 335483569739384, + l3: 293961277766182, + l4: 137209507300112 + }; + let res: Element = multiply(a, b); + +//26419211797770492947925431317169526880133696901606348938375383866077151145114 +//[896638975913114, 1000789340506524, 355992668009873, 806477788321681, 1027544741541094] + res_equals(res, Element { + l0: 896638975913114, + l1: 1000789340506524, + l2: 355992668009873, + l3: 806477788321681, + l4: 1027544741541094 + }); + true +} + +/* +fn test_multiply_random() -> bool { + /* + a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 + = [1292655137982008, 1303372017735434, 595911506101250, 601879629470779, 50591579140481] + = Element { + 1292655137982008, + 1303372017735434, + 595911506101250, + 601879629470779, + 50591579140481 + } + + b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 + = [1360902863141127, 807899991388824, 335483569739384, 293961277766182, 137209507300112] + = Element { + 1360902863141127, + 807899991388824, + 335483569739384, + 293961277766182, + 137209507300112 + } + + ab mod p = 26419211797770492947925431317169526880133696901606348938375383866077151145114 + = [896638975913114, 1000789340506524, 355992668009873, 806477788321681, 1027544741541094] + + */ + + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; + + let b = Element { + l0: 1360902863141127, + l1: 807899991388824, + l2: 335483569739384, + l3: 293961277766182, + l4: 137209507300112 + }; + + let ab = Element { + l0: 896638975913114, + l1: 1000789340506524, + l2: 355992668009873, + l3: 806477788321681, + l4: 1027544741541094 + }; + + + let res: Element = multiply(a, b); + // print_el(res); + res_equals(res, ab); + true +} +*/ \ No newline at end of file diff --git a/edwards25519/src/tests/tests_of_helpers.sw b/edwards25519/src/tests/tests_of_helpers.sw new file mode 100644 index 0000000..e558767 --- /dev/null +++ b/edwards25519/src/tests/tests_of_helpers.sw @@ -0,0 +1,59 @@ +library tests_of_helpers; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; + +pub fn test_helpers() -> bool { + assert(test_get_zero()); + assert(test_equals()); + true +} + +fn test_get_zero() -> bool { + res_equals(zero, Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }); + true +} + +fn test_equals() -> bool { + let zero_equals_zero = equals(zero, zero); + let zero_equals_one = equals(zero, one); + let one_equals_one = equals(one, one); + + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + let b = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + let c = Element{ + l0: 60, + l1: 5, + l2: 2251799813685247, + l3: 500, + l4: 100 + }; + let a_equals_a = equals(a,a); + let a_equals_b = equals(a,b); //a and b have same coefficients + let a_equals_c = equals(a,c); + let b_equals_c = equals(b,c); + + assert(zero_equals_zero); + assert(!zero_equals_one); + assert(one_equals_one); + + assert(a_equals_a); + assert(a_equals_b); + assert(!a_equals_c); + assert(!b_equals_c); + + true +} diff --git a/edwards25519/src/tests/tests_reductions.sw b/edwards25519/src/tests/tests_reductions.sw new file mode 100644 index 0000000..52ec605 --- /dev/null +++ b/edwards25519/src/tests/tests_reductions.sw @@ -0,0 +1,195 @@ +library tests_reductions; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; + +pub fn test_reductions() -> bool { + assert(test_carry_propagate_1()); + assert(test_carry_propagate_2()); + assert(test_reduce()); + assert(test_reduce_2()); + assert(test_reduce_3()); + assert(test_reduce_4()); + true +} + +fn test_carry_propagate_1() -> bool { + /* + 2^64 -1 = 18446744073709551615 + + 18446744073709551615 + + 18446744073709551615 * 2^51 + + 18446744073709551615 * 2^102 + + 18446744073709551615 * 2^153 + + 18446744073709551615 * 2^204 + */ + let e = Element{ + l0: ~u64::max(), + l1: ~u64::max(), + l2: ~u64::max(), + l3: ~u64::max(), + l4: ~u64::max() }; + + let res = carry_propagate(e); + + // Each limb has a carry of 8191 and a coeff of 2251799813685247 + // So after a round of reduction this is + /* equals + 2251799813685247 + (19*8191) + + (2251799813685247 + 8191) * 2^51 + + (2251799813685247 + 8191) * 2^102 + + (2251799813685247 + 8191) * 2^153 + + (2251799813685247 + 8191) * 2^204 + = 57896044618868696584113898827420068118245036358148060739095062128926159691756 + */ + res_equals(res, Element{ + l0: 2251799813685247 + (19*8191), + l1: 2251799813685247 + 8191, + l2: 2251799813685247 + 8191, + l3: 2251799813685247 + 8191, + l4: 2251799813685247 + 8191 + }); + + // Note that this result is >2^255-19 because the function only does 1 round of reduction + + true +} + +fn test_carry_propagate_2() -> bool { + // 2251799813685250 = 2 + 2^51 + let e = Element{ + l0: 2251799813685250, + l1: 0, + l2: 0, + l3: 0, + l4: 0 }; + + let res = carry_propagate(e); + + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); + + true +} + +fn test_reduce() -> bool { + // 2251799813685250 = 2 + 2^51 + let e = Element{ + l0: 2251799813685250, + l1: 0, + l2: 0, + l3: 0, + l4: 0 }; + + let res = reduce(e); + + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); + + true +} + +fn test_reduce_2() -> bool { + /* + 2^51 + 2 = 2251799813685250 + + 2251799813685250 + + 2251799813685250 * 2^51 + + 2251799813685250 * 2^102 + + 2251799813685250 * 2^153 + + 2251799813685250 * 2^204 + mod 2^255-19 + */ + let e = Element{ + l0: 2251799813685250, + l1: 2251799813685250, + l2: 2251799813685250, + l3: 2251799813685250, + l4: 2251799813685250 }; + + let res = reduce(e); + + /* equals + 21 + + 3 * 2^51 + + 3 * 2^102 + + 3 * 2^153 + + 3 * 2^204 + */ + res_equals(res, Element{ l0: 21, l1: 3, l2: 3, l3: 3, l4: 3 }); + + true +} + +fn test_reduce_3() -> bool { + /* + 2^64 -1 = 18446744073709551615 + + 18446744073709551615 + + 18446744073709551615 * 2^51 + + 18446744073709551615 * 2^102 + + 18446744073709551615 * 2^153 + + 18446744073709551615 * 2^204 + mod 2^255 -19 + = 210598872328406323076114191610044025327778719366270124969594871807 + */ + let e = Element{ + l0: ~u64::max(), + l1: ~u64::max(), + l2: ~u64::max(), + l3: ~u64::max(), + l4: ~u64::max() }; + + let res = reduce(e); + + /* + 155647 + + 8191 * 2^51 + + 8191 * 2^102 + + 8191 * 2^153 + + 8191 * 2^204 + = 210598872328406323076114191610044025327778719366270124969594871807 + */ + res_equals(res, Element{ + l0: 155647, + l1: 8191, + l2: 8191, + l3: 8191, + l4: 8191 + }); + + true +} + +fn test_reduce_4() -> bool { + /* + 4503599627370494 + + 4503599627370494 * 2^51 + + 4503599627370494 * 2^102 + + 4503599627370494 * 2^153 + + 4503599627370494 * 2^204 + mod 2^255 - 19 + + = 36 + */ + let e = Element{ + l0: 4503599627370494, + l1: 4503599627370494, + l2: 4503599627370494, + l3: 4503599627370494, + l4: 4503599627370494 }; + + let res = reduce(e); + + /* + should be 36 + */ + res_equals(res, Element{ + l0: 36, + l1: 0, + l2: 0, + l3: 0, + l4: 0 + }); + + true +} diff --git a/edwards25519/src/tests/tests_rshift.sw b/edwards25519/src/tests/tests_rshift.sw new file mode 100644 index 0000000..d9b3e14 --- /dev/null +++ b/edwards25519/src/tests/tests_rshift.sw @@ -0,0 +1,45 @@ +library tests_rshift; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; +use std::u128::*; + +pub fn tests_shiftRightBy51() -> bool { + assert(test_shiftRightBy51_random()); + assert(test_shiftRightBy51_random_2()); + assert(test_shiftRightBy51_random_3()); + true +} + +fn test_shiftRightBy51_random() -> bool { + + let a = U128{upper: 16, lower:0}; + let res = shiftRightBy51(a); + assert(res == 131072); + true +} + +fn test_shiftRightBy51_random_2() -> bool { + /* +456464 + (349323232 << 64) = 6443876259705066799772399376 + +>>51 = 2861655916544 + */ + let a = U128{upper: 349323232, lower:456464}; + let res = shiftRightBy51(a); + assert(res == 2861655916544); + true +} + +fn test_shiftRightBy51_random_3() -> bool { + /* +18446744073709551615 + (349323232 << 64) = 6443876278151810873481494527 + +>>51 = 2861655924735 + */ + let a = U128{upper: 349323232, lower:18446744073709551615}; + let res = shiftRightBy51(a); + assert(res == 2861655924735); + true +} diff --git a/edwards25519/src/tests/tests_scalar_mult.sw b/edwards25519/src/tests/tests_scalar_mult.sw new file mode 100644 index 0000000..3d552a6 --- /dev/null +++ b/edwards25519/src/tests/tests_scalar_mult.sw @@ -0,0 +1,151 @@ +library tests_scalar_mult; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; + +pub fn tests_scalar_mult() -> bool { + assert(test_mult_by_0()); + assert(test_mult_by_1()); + assert(test_mult_by_2()); + assert(test_mult_by_2_again()); + assert(test_mult_by_large_scalar()); + true +} + +fn test_mult_by_0() -> bool { + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let res: Element = scalar_mult(a, 0); + res_equals(res, zero); + true +} + +fn test_mult_by_1() -> bool { + let a = Element{ + l0: 79611, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 555555333333222, + l4: 2251799813685247 + }; + + let res: Element = scalar_mult(a, 1); + res_equals(res, a); + true +} + +fn test_mult_by_2() -> bool { + /* + 79611 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 555555333333222 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 79611, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 555555333333222, + l4: 2251799813685247 + }; + + /* 57896044618658058976409158941982667984400415217654165675094330160006532591113 + =[159241, + 2251799813685246, + 2251799813685247, + 1111110666666445, + 2251799813685246] */ + let res: Element = scalar_mult(a, 2); + + res_equals(res, Element{ + l0: 159241, + l1: 2251799813685246, + l2: 2251799813685247, + l3: 1111110666666445, + l4: 2251799813685246 + }); + + true +} + +fn test_mult_by_2_again() -> bool { + // 2^255 - 20 (the largest number) expressed in radix-51 + /* + 2251799813685228 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 2251799813685247 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 2251799813685228, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + + let res: Element = scalar_mult(a, 2); + + /* + 2251799813685227 + 2251799813685247* 2^51 + + 2251799813685247* 2^102 + + 2251799813685247* 2^153 + + 2251799813685247 * 2^204 + */ + res_equals(res, Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }); + + true +} + +fn test_mult_by_large_scalar() -> bool { + /* + 79611 + + 2251799813685247 * 2^51 + + 2251799813685247 * 2^102 + + 555555333333222 * 2^153 + + 2251799813685247 * 2^204 + */ + let a = Element{ + l0: 79611, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 555555333333222, + l4: 2251799813685247 + }; + + /* + 248661618146997193275445770277948644497863737508141907291226725252005565483705230608645 + reduced mod 2^255 - 19 + = 57895961435070841628109209456323569962738033236635300844883400985433276860639 + = [342008245700831, 2251795518717953, 2251799813685247, 536152338865944, 2251796578355658] + */ + // Largest scalar input possible is 2^32 -1 = 4294967295 + let res: Element = scalar_mult(a, 4294967295); + + res_equals(res, Element{ + l0: 342008245700831, + l1: 2251795518717953, + l2: 2251799813685247, + l3: 536152338865944, + l4: 2251796578355658 + }); + + true +} \ No newline at end of file diff --git a/edwards25519/src/tests/tests_square.sw b/edwards25519/src/tests/tests_square.sw new file mode 100644 index 0000000..31afee9 --- /dev/null +++ b/edwards25519/src/tests/tests_square.sw @@ -0,0 +1,57 @@ +library tests_square; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; + +pub fn tests_square() -> bool { + // assert(test_square_one()); + // assert(test_square_zero()); + assert(test_square_random()); + true +} + +fn test_square_one() -> bool { + let res: Element = square(one); + res_equals(res, one); + true +} + +fn test_square_zero() -> bool { + let res: Element = square(zero); + res_equals(res, zero); + true +} + +fn test_square_random() -> bool { + /* + a = 10406084254717298682985401286246103758749877058048555650117556132341049525816 + = [404732633123850, 312158315551803, 595911506101250, 1303372017735434, 1292655137982008] + + a^2 = 108286589516275277577373161473966445398256506358898379115846293425853328039181187715348880647692926795184739504006825065723361671067040986483318450465856 + + a^2 mod p = 31042580993865580304222384966530826020546840941977848835924726765219788840807 + = [1207365348681671, 713663780369466, 912635275234964, 596790797966485, 2144628324130663] + + */ + + let a: Element = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 312158315551803, + l4: 404732633123850 + }; + + let a_square: Element = Element { + l0: 2144628324130663, + l1: 596790797966485, + l2: 912635275234964, + l3: 713663780369466, + l4: 1207365348681671 + }; + + let res: Element = square(a); + res_equals(res, a_square); + true +} \ No newline at end of file diff --git a/edwards25519/src/tests/tests_sub.sw b/edwards25519/src/tests/tests_sub.sw new file mode 100644 index 0000000..3d77443 --- /dev/null +++ b/edwards25519/src/tests/tests_sub.sw @@ -0,0 +1,182 @@ +library tests_sub; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; + +pub fn tests_substract() -> bool { + assert(test_subtraction_by_0()); + assert(test_subtraction_by_1()); + assert(test_subtraction_by_max()); + assert(test_subtraction_random()); + true +} + +fn test_subtraction_by_0() -> bool { + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let res: Element = subtract(a, zero); + res_equals(res, a); + + true +} + +fn test_subtraction_by_1() -> bool { + let a = Element{ + l0: 2251799813685247, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let b = Element{ + l0: 2251799813685246, + l1: 5, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 100 + }; + + let res: Element = subtract(a, one); + res_equals(res, b); + true +} + +fn test_subtraction_by_max() -> bool { + + /* + 2^255 - 21 = 57896044618658097711785492504343953926634992332820282019728792003956564819947 + = [2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685227] + = Element { + 2251799813685227, + 2251799813685247, + 2251799813685247, + 2251799813685247, + 2251799813685247 + } + */ + + let a = Element{ + l0: 2251799813685227, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + /* + 2^255 - 20 = 57896044618658097711785492504343953926634992332820282019728792003956564819948 + = [2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685228] + = Element { + 2251799813685228, + 2251799813685247, + 2251799813685247, + 2251799813685247, + 2251799813685247 + } + */ + + let b = Element { + l0: 2251799813685228, + l1: 2251799813685247, + l2: 2251799813685247, + l3: 2251799813685247, + l4: 2251799813685247 + }; + + let res: Element = subtract(a, b); + let res2: Element = subtract(b,a); + res_equals(res, b); + res_equals(res2, one); + true +} + +fn test_subtraction_random() -> bool { + /* + subtraction of random 2 numbers generated using GP-PARI + + a = random({2^251}) = 1300760531839662334344262085631565818852980666446405835776058138544728770104 + = [50591579140481, 601879629470779, 595911506101250, 1303372017735434, 1292655137982008] + = Element { + 1292655137982008, + 1303372017735434, + 595911506101250, + 601879629470779, + 50591579140481 + } + + b = random({2^251}) = 3527794837033309378261417350654351403080646879795459845564282655359926745351 + = [137209507300112, 293961277766182, 335483569739384, 807899991388824, 1360902863141127] + = Element { + 1360902863141127, + 807899991388824, + 335483569739384, + 293961277766182, + 137209507300112 + } + + b - a = 2227034305193647043917155265022785584227666213349054009788224516815197975247 + = [86617928159630, 1943881461980650, 1991371877323381, 1756327787338638, 68247725159119] + = Element { + 68247725159119, + 1756327787338638, + 1991371877323381, + 1943881461980650, + 86617928159630 + } + a - b + p = 55669010313464450667868337239321168342407326119471228009940567487141366844702 + = [2165181885525617, 307918351704597, 260427936361866, 495472026346609, 2183552088526110] + = Element { + 2183552088526110, + 495472026346609, + 260427936361866, + 307918351704597, + 2165181885525617 + } + */ + + let a = Element { + l0: 1292655137982008, + l1: 1303372017735434, + l2: 595911506101250, + l3: 601879629470779, + l4: 50591579140481 + }; + + let b = Element { + l0: 1360902863141127, + l1: 807899991388824, + l2: 335483569739384, + l3: 293961277766182, + l4: 137209507300112 + }; + + let a_minus_b = Element { + l0: 2183552088526110, + l1: 495472026346609, + l2: 260427936361866, + l3: 307918351704597, + l4: 2165181885525617 + }; + + let b_minus_a = Element { + l0: 68247725159119, + l1: 1756327787338638, + l2: 1991371877323381, + l3: 1943881461980650, + l4: 86617928159630 + }; + + let res: Element = subtract(a, b); + let res2: Element = subtract(b,a); + res_equals(res, a_minus_b); + res_equals(res2, b_minus_a); + true +} \ No newline at end of file From de6cc51edcdddc7998c3c91f4c91e27c23d1c266 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 17:15:26 -0600 Subject: [PATCH 053/160] Added a test for the inverse function (which hasn't been tested yet). But it doesn't terminate. This is an example of what we need to be able to run, but currently doesn't seem possible. --- edwards25519/src/field_element.sw | 5 ++--- edwards25519/src/main.sw | 5 +++++ edwards25519/src/tests/tests_multiply.sw | 6 +++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 580f477..45100a5 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -303,7 +303,7 @@ pub fn scalar_mult(e: Element, x: u32) -> Element { let (coeff3, carry3) = get_coeff_and_carry(l3_temp); let (coeff4, carry4) = get_coeff_and_carry(l4_temp); - let res0: u64 = coeff0 + carry4*19; + let res0: u64 = coeff0 + times19(carry4); let res1: u64 = coeff1 + carry0; let res2: u64 = coeff2 + carry1; let res3: u64 = coeff3 + carry2; @@ -332,7 +332,7 @@ pub fn equals(a: Element, b: Element) -> bool { res == 0 } -/* + //a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p pub fn inverse(a: Element) -> Element { let mut i = 0; @@ -417,4 +417,3 @@ pub fn inverse(a: Element) -> Element { return t; } -*/ \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 73a6a7b..0cb9c92 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -13,6 +13,7 @@ dep tests/tests_rshift; dep tests/tests_scalar_mult; dep tests/tests_square; dep tests/tests_sub; +dep tests/tests_inverse; use ::tests_add::tests_add; use ::tests_helpers64::test_helpers64; @@ -23,6 +24,7 @@ use ::tests_rshift::tests_shiftRightBy51; use ::tests_scalar_mult::tests_scalar_mult; use ::tests_square::tests_square; use ::tests_sub::tests_substract; +use ::tests_inverse::tests_inverse; use ::field_element::*; use ::test_helpers::*; @@ -45,4 +47,7 @@ fn main() { // Multiply tests can't run all at the same time assert(tests_multiply()); // assert(tests_square()); + + //Doesnt' terminate + // assert(tests_inverse()); } diff --git a/edwards25519/src/tests/tests_multiply.sw b/edwards25519/src/tests/tests_multiply.sw index d29bf2e..76fe138 100644 --- a/edwards25519/src/tests/tests_multiply.sw +++ b/edwards25519/src/tests/tests_multiply.sw @@ -9,9 +9,9 @@ pub fn tests_multiply() -> bool { // assert(test_multiply_1_by_1()); // assert(test_multiply_by_1_small()); // assert(test_multiply_by_1_large()); - assert(test_multiply_small_elms()); - assert(test_multiply_small_elms_2()); - assert(test_multiply_small_elms_3()); + // assert(test_multiply_small_elms()); + // assert(test_multiply_small_elms_2()); + // assert(test_multiply_small_elms_3()); assert(test_multiply_elms_4()); // assert(test_multiply_random()); true From 2076b2f5ddb1e6c5faa5b5fb1ce0375d9f9df27b Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 17:15:26 -0600 Subject: [PATCH 054/160] Added a test for the inverse function (which hasn't been tested yet). But it doesn't terminate. This is an example of what we need to be able to run, but currently doesn't seem possible. --- edwards25519/src/field_element.sw | 5 ++- edwards25519/src/main.sw | 5 +++ edwards25519/src/tests/tests_inverse.sw | 40 ++++++++++++++++++++++++ edwards25519/src/tests/tests_multiply.sw | 6 ++-- 4 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 edwards25519/src/tests/tests_inverse.sw diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 580f477..45100a5 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -303,7 +303,7 @@ pub fn scalar_mult(e: Element, x: u32) -> Element { let (coeff3, carry3) = get_coeff_and_carry(l3_temp); let (coeff4, carry4) = get_coeff_and_carry(l4_temp); - let res0: u64 = coeff0 + carry4*19; + let res0: u64 = coeff0 + times19(carry4); let res1: u64 = coeff1 + carry0; let res2: u64 = coeff2 + carry1; let res3: u64 = coeff3 + carry2; @@ -332,7 +332,7 @@ pub fn equals(a: Element, b: Element) -> bool { res == 0 } -/* + //a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p pub fn inverse(a: Element) -> Element { let mut i = 0; @@ -417,4 +417,3 @@ pub fn inverse(a: Element) -> Element { return t; } -*/ \ No newline at end of file diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 73a6a7b..0cb9c92 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -13,6 +13,7 @@ dep tests/tests_rshift; dep tests/tests_scalar_mult; dep tests/tests_square; dep tests/tests_sub; +dep tests/tests_inverse; use ::tests_add::tests_add; use ::tests_helpers64::test_helpers64; @@ -23,6 +24,7 @@ use ::tests_rshift::tests_shiftRightBy51; use ::tests_scalar_mult::tests_scalar_mult; use ::tests_square::tests_square; use ::tests_sub::tests_substract; +use ::tests_inverse::tests_inverse; use ::field_element::*; use ::test_helpers::*; @@ -45,4 +47,7 @@ fn main() { // Multiply tests can't run all at the same time assert(tests_multiply()); // assert(tests_square()); + + //Doesnt' terminate + // assert(tests_inverse()); } diff --git a/edwards25519/src/tests/tests_inverse.sw b/edwards25519/src/tests/tests_inverse.sw new file mode 100644 index 0000000..1c1e007 --- /dev/null +++ b/edwards25519/src/tests/tests_inverse.sw @@ -0,0 +1,40 @@ +library tests_inverse; + +use ::field_element::*; +use std::assert::assert; +use ::test_helpers::*; +use std::u128::*; + +pub fn tests_inverse() -> bool { + assert(test_inverse_random()); + true +} + +fn test_inverse_random() -> bool { + /* +4521863078758786565316692829643046466943720546816241094731251542329584501189 +[715325916561861, 1128975921026318, 1696955067652624, 2081297221826529, 175872643896950] + +res +21685099821915697185699787072152716570859124738499628703633803656742289717999 +[2187613694507759, 1614434677729781, 1594711943325299, 378203143193209, 843416921835783] + */ + let a = Element { + l0: 715325916561861, + l1: 1128975921026318, + l2: 1696955067652624, + l3: 2081297221826529, + l4: 175872643896950 + }; + let res: Element = inverse(a); + let res_check = Element { + l0: 2187613694507759, + l1: 1614434677729781, + l2: 1594711943325299, + l3: 378203143193209, + l4: 843416921835783 + } + print_el(res); + //res_equals(res, res_check); + true +} \ No newline at end of file diff --git a/edwards25519/src/tests/tests_multiply.sw b/edwards25519/src/tests/tests_multiply.sw index d29bf2e..76fe138 100644 --- a/edwards25519/src/tests/tests_multiply.sw +++ b/edwards25519/src/tests/tests_multiply.sw @@ -9,9 +9,9 @@ pub fn tests_multiply() -> bool { // assert(test_multiply_1_by_1()); // assert(test_multiply_by_1_small()); // assert(test_multiply_by_1_large()); - assert(test_multiply_small_elms()); - assert(test_multiply_small_elms_2()); - assert(test_multiply_small_elms_3()); + // assert(test_multiply_small_elms()); + // assert(test_multiply_small_elms_2()); + // assert(test_multiply_small_elms_3()); assert(test_multiply_elms_4()); // assert(test_multiply_random()); true From cdf198658cd369d995cbb9a45015293a11e8a162 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 18:05:27 -0600 Subject: [PATCH 055/160] Fixes for most of the warnings --- edwards25519/src/field_element.sw | 84 ++++++++------------- edwards25519/src/main.sw | 13 ++-- edwards25519/src/test_helpers.sw | 11 ++- edwards25519/src/tests/tests_add.sw | 12 +-- edwards25519/src/tests/tests_helpers64.sw | 8 +- edwards25519/src/tests/tests_inverse.sw | 4 +- edwards25519/src/tests/tests_multiply.sw | 36 ++++----- edwards25519/src/tests/tests_of_helpers.sw | 11 ++- edwards25519/src/tests/tests_reductions.sw | 25 ++---- edwards25519/src/tests/tests_rshift.sw | 20 ++--- edwards25519/src/tests/tests_scalar_mult.sw | 18 ++--- edwards25519/src/tests/tests_square.sw | 13 ++-- edwards25519/src/tests/tests_sub.sw | 19 ++--- 13 files changed, 102 insertions(+), 172 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 45100a5..25c2544 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -14,13 +14,10 @@ pub struct Element { // = (1 << 51) - 1 // But using the above expression gives the error "Could not evaluate initializer to a const declaration." -const mask_low_51_bits: u64 = 2251799813685247; -pub const zero: Element = Element { +const MASK_LOW_51_BITS: u64 = 2251799813685247; +pub const ZERO: Element = Element { l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; -pub const one: Element = Element { - l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 -}; // from NaCl impl https://cr.yp.to/ecdh.html#use fn times19(x: u64) -> u64 { @@ -51,13 +48,13 @@ pub fn carry_propagate(e: Element) -> Element { // the final l0 will be at most 52 bits. Similarly for the rest. // c4 * 19 is at most 13 + 5 = 18 bits => l0 is at most 52 bits - let new_l0 = (e.l0 & mask_low_51_bits) + times19(c4); + let new_l0 = (e.l0 & MASK_LOW_51_BITS) + times19(c4); Element { l0: new_l0, - l1: (e.l1 & mask_low_51_bits) + c0, - l2: (e.l2 & mask_low_51_bits) + c1, - l3: (e.l3 & mask_low_51_bits) + c2, - l4: (e.l4 & mask_low_51_bits) + c3, + l1: (e.l1 & MASK_LOW_51_BITS) + c0, + l2: (e.l2 & MASK_LOW_51_BITS) + c1, + l3: (e.l3 & MASK_LOW_51_BITS) + c2, + l4: (e.l4 & MASK_LOW_51_BITS) + c3, } } @@ -89,13 +86,13 @@ pub fn reduce(e: Element) -> Element { let mut v0 = red.l0 + times19(carry); let mut v1 = red.l1 + (v0 >> 51); - v0 = v0 & mask_low_51_bits; + v0 = v0 & MASK_LOW_51_BITS; let mut v2 = red.l2 + (v1 >> 51); - v1 = v1 & mask_low_51_bits; + v1 = v1 & MASK_LOW_51_BITS; let mut v3 = red.l3 + (v2 >> 51); - v2 = v2 & mask_low_51_bits; - let mut v4 = (red.l4 + (v3 >> 51)) & mask_low_51_bits; - v3 = v3 & mask_low_51_bits; + v2 = v2 & MASK_LOW_51_BITS; + let mut v4 = (red.l4 + (v3 >> 51)) & MASK_LOW_51_BITS; + v3 = v3 & MASK_LOW_51_BITS; Element { l0: v0, @@ -138,38 +135,23 @@ pub fn subtract(a: Element, b: Element) -> Element { //negate return negaive of an element(-a) pub fn negate(a: Element) -> Element { - subtract(zero, a) + subtract(ZERO, a) } //returns 128-bit product of a and b pub fn multiply64(a: u64, b: u64) -> U128 { - let A: U128 = U128 { - upper: 0, - lower: a, - }; - let B: U128 = U128 { - upper: 0, - lower: b, - }; - A * B + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + a_128 * b_128 } //returns sum with carry of a and b pub fn add64(a: u64, b: u64, carry: u64) -> (u64, u64) { - let A: U128 = U128 { - upper: 0, - lower: a, - }; - let B: U128 = U128 { - upper: 0, - lower: b, - }; - let Carry: U128 = U128 { - upper: 0, - lower: carry, - }; + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let carry_128: U128 = ~U128::from(0, carry); - let sum: u64 = (A + B + Carry).lower; + let sum: u64 = (a_128 + b_128 + carry_128).lower; let notSum = ~u64::max() - sum; let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; @@ -189,7 +171,7 @@ pub fn add_multiply64(res: U128, a: u64, b: u64) -> U128 { } //right shift by 51 -pub fn shiftRightBy51(a: U128) -> u64 { +pub fn shift_right_by51(a: U128) -> u64 { (a.upper <<(64 - 51)) | (a.lower >> 51) } @@ -254,17 +236,17 @@ pub fn multiply(a: Element, b: Element) -> Element { r4 = add_multiply64(r4, a3, b1); r4 = add_multiply64(r4, a4, b0); - let c0 = shiftRightBy51(r0); - let c1 = shiftRightBy51(r1); - let c2 = shiftRightBy51(r2); - let c3 = shiftRightBy51(r3); - let c4 = shiftRightBy51(r4); + let c0 = shift_right_by51(r0); + let c1 = shift_right_by51(r1); + let c2 = shift_right_by51(r2); + let c3 = shift_right_by51(r3); + let c4 = shift_right_by51(r4); - let rr0 = (r0.lower & mask_low_51_bits) + times19(c4); - let rr1 = (r1.lower & mask_low_51_bits) + c0; - let rr2 = (r2.lower & mask_low_51_bits) + c1; - let rr3 = (r3.lower & mask_low_51_bits) + c2; - let rr4 = (r4.lower & mask_low_51_bits) + c3; + let rr0 = (r0.lower & MASK_LOW_51_BITS) + times19(c4); + let rr1 = (r1.lower & MASK_LOW_51_BITS) + c0; + let rr2 = (r2.lower & MASK_LOW_51_BITS) + c1; + let rr3 = (r3.lower & MASK_LOW_51_BITS) + c2; + let rr4 = (r4.lower & MASK_LOW_51_BITS) + c3; let res: Element = Element { l0: rr0, @@ -280,8 +262,8 @@ pub fn multiply(a: Element, b: Element) -> Element { // For a bignumber <= 102 bits stored in U128, // return the 51 bit coefficient and 51 bit carry pub fn get_coeff_and_carry(y: U128) -> (u64, u64) { - let coeff: u64 = y.lower & mask_low_51_bits; - let carry: u64 = (y.upper << 13 & mask_low_51_bits) | y.lower >> 51; + let coeff: u64 = y.lower & MASK_LOW_51_BITS; + let carry: u64 = (y.upper << 13 & MASK_LOW_51_BITS) | y.lower >> 51; (coeff, carry) } diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 0cb9c92..3062d2c 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -20,7 +20,7 @@ use ::tests_helpers64::test_helpers64; use ::tests_multiply::tests_multiply; use ::tests_of_helpers::test_helpers; use ::tests_reductions::test_reductions; -use ::tests_rshift::tests_shiftRightBy51; +use ::tests_rshift::tests_shift_right_by51; use ::tests_scalar_mult::tests_scalar_mult; use ::tests_square::tests_square; use ::tests_sub::tests_substract; @@ -34,18 +34,17 @@ use std::logging::log; use core::num::*; use std::u128::*; - fn main() { // assert(test_helpers()); // assert(tests_add()); // assert(test_helpers64()); - // assert(test_reductions()); - // assert(tests_shiftRightBy51()); - // assert(tests_scalar_mult()); - // assert(tests_substract()); + assert(test_reductions()); + assert(tests_shift_right_by51()); + assert(tests_scalar_mult()); + assert(tests_substract()); // Multiply tests can't run all at the same time - assert(tests_multiply()); + // assert(tests_multiply()); // assert(tests_square()); //Doesnt' terminate diff --git a/edwards25519/src/test_helpers.sw b/edwards25519/src/test_helpers.sw index 92f10f6..aa91f0c 100644 --- a/edwards25519/src/test_helpers.sw +++ b/edwards25519/src/test_helpers.sw @@ -7,6 +7,10 @@ use std::logging::log; use std::assert::assert; use std::u128::*; +pub const ONE: Element = Element { + l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 +}; + pub fn print_el(e: Element) { log(e.l0); log(e.l1); @@ -24,12 +28,7 @@ pub fn res_equals(res: Element, should_be: Element) -> bool { true } -pub fn print_U128(a: U128) { - log(a.upper); - log(a.lower); -} - -pub fn equals_U128(res: U128, lower: u64, upper: u64) -> bool { +pub fn equals_u128(res: U128, lower: u64, upper: u64) -> bool { assert(res.upper == upper); assert(res.lower == lower); true diff --git a/edwards25519/src/tests/tests_add.sw b/edwards25519/src/tests/tests_add.sw index d57963a..9a4cece 100644 --- a/edwards25519/src/tests/tests_add.sw +++ b/edwards25519/src/tests/tests_add.sw @@ -23,7 +23,7 @@ fn test_add_to_0() -> bool { l4: 85247 }; - let res = add(zero, b); + let res = add(ZERO, b); assert(res_equals(res, b)); true @@ -38,7 +38,7 @@ fn test_add_0() -> bool { l4: 85247 }; - let res = add(b, zero); + let res = add(b, ZERO); assert(res_equals(res, b)); true @@ -97,9 +97,7 @@ fn test_add_a_to_b() -> bool { l2: 155647, l3: 81918191, l4: 85247 - }); - - true + }) } fn test_add_a_to_a() -> bool { @@ -127,7 +125,5 @@ fn test_add_a_to_a() -> bool { l2: 2251799813685247, l3: 2251799813685247, l4: 2251799813685247 - }); - - true + }) } \ No newline at end of file diff --git a/edwards25519/src/tests/tests_helpers64.sw b/edwards25519/src/tests/tests_helpers64.sw index 2de6622..727946a 100644 --- a/edwards25519/src/tests/tests_helpers64.sw +++ b/edwards25519/src/tests/tests_helpers64.sw @@ -77,9 +77,7 @@ fn test_add_multiply64() -> bool { //58711607980754950933543316951356 //[10881738262824685884, 3182762646142] let mut res = add_multiply64(r,a,b); - equals_U128(res, 10881738262824685884, 3182762646142); - - true + equals_u128(res, 10881738262824685884, 3182762646142) } fn test_add_multiply64_2() -> bool { @@ -96,7 +94,5 @@ fn test_add_multiply64_2() -> bool { //[18148778710141221224, 279563898809] let mut res = add_multiply64(r,a,b); - equals_U128(res, 18148778710141221224, 279563898809); - - true + equals_u128(res, 18148778710141221224, 279563898809) } \ No newline at end of file diff --git a/edwards25519/src/tests/tests_inverse.sw b/edwards25519/src/tests/tests_inverse.sw index 1c1e007..0ddbe89 100644 --- a/edwards25519/src/tests/tests_inverse.sw +++ b/edwards25519/src/tests/tests_inverse.sw @@ -33,8 +33,8 @@ res l2: 1594711943325299, l3: 378203143193209, l4: 843416921835783 - } - print_el(res); + }; + // print_el(res); //res_equals(res, res_check); true } \ No newline at end of file diff --git a/edwards25519/src/tests/tests_multiply.sw b/edwards25519/src/tests/tests_multiply.sw index 76fe138..4ca82a8 100644 --- a/edwards25519/src/tests/tests_multiply.sw +++ b/edwards25519/src/tests/tests_multiply.sw @@ -27,16 +27,13 @@ fn test_multiply_by_0() -> bool { l3: 2251799813685247, l4: 2251799813685247 }; - let res: Element = multiply(a, zero); - res_equals(res, zero); - true + let res: Element = multiply(a, ZERO); + res_equals(res, ZERO) } fn test_multiply_1_by_1() -> bool { - let res: Element = multiply(one, one); - res_equals(res, one); - - true + let res: Element = multiply(ONE, ONE); + res_equals(res, ONE) } fn test_multiply_by_1_small() -> bool { @@ -48,9 +45,8 @@ fn test_multiply_by_1_small() -> bool { l3: 13, l4: 14 }; - let res: Element = multiply(a, one); - res_equals(res, a); - true + let res: Element = multiply(a, ONE); + res_equals(res, a) } fn test_multiply_by_1_large() -> bool { @@ -63,9 +59,8 @@ fn test_multiply_by_1_large() -> bool { l3: 2251799813685247, l4: 2251799813685247 }; - let res: Element = multiply(a, one); - res_equals(res, a); - true + let res: Element = multiply(a, ONE); + res_equals(res, a) } fn test_multiply_small_elms() -> bool { @@ -112,8 +107,7 @@ fn test_multiply_small_elms() -> bool { l2: 2909, l3: 1752, l4: 230 - }); - true + }) } fn test_multiply_small_elms_2() -> bool { @@ -160,8 +154,7 @@ fn test_multiply_small_elms_2() -> bool { l2: 995697840409273, l3: 333510462280559, l4: 1626165600260968 - }); - true + }) } fn test_multiply_small_elms_3() -> bool { @@ -208,8 +201,7 @@ fn test_multiply_small_elms_3() -> bool { l2: 376444288997219, l3: 169499236944723, l4: 548860478185542 - }); - true + }) } fn test_multiply_elms_4() -> bool { @@ -256,8 +248,7 @@ fn test_multiply_elms_4() -> bool { l2: 355992668009873, l3: 806477788321681, l4: 1027544741541094 - }); - true + }) } /* @@ -315,7 +306,6 @@ fn test_multiply_random() -> bool { let res: Element = multiply(a, b); // print_el(res); - res_equals(res, ab); - true + res_equals(res, ab) } */ \ No newline at end of file diff --git a/edwards25519/src/tests/tests_of_helpers.sw b/edwards25519/src/tests/tests_of_helpers.sw index e558767..365b638 100644 --- a/edwards25519/src/tests/tests_of_helpers.sw +++ b/edwards25519/src/tests/tests_of_helpers.sw @@ -11,14 +11,13 @@ pub fn test_helpers() -> bool { } fn test_get_zero() -> bool { - res_equals(zero, Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }); - true + res_equals(ZERO, Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }) } fn test_equals() -> bool { - let zero_equals_zero = equals(zero, zero); - let zero_equals_one = equals(zero, one); - let one_equals_one = equals(one, one); + let zero_equals_zero = equals(ZERO, ZERO); + let zero_equals_one = equals(ZERO, ONE); + let ONE_equals_one = equals(ONE, ONE); let a = Element{ l0: 2251799813685247, @@ -48,7 +47,7 @@ fn test_equals() -> bool { assert(zero_equals_zero); assert(!zero_equals_one); - assert(one_equals_one); + assert(ONE_equals_one); assert(a_equals_a); assert(a_equals_b); diff --git a/edwards25519/src/tests/tests_reductions.sw b/edwards25519/src/tests/tests_reductions.sw index 52ec605..b7fce5b 100644 --- a/edwards25519/src/tests/tests_reductions.sw +++ b/edwards25519/src/tests/tests_reductions.sw @@ -49,11 +49,8 @@ fn test_carry_propagate_1() -> bool { l2: 2251799813685247 + 8191, l3: 2251799813685247 + 8191, l4: 2251799813685247 + 8191 - }); - + }) // Note that this result is >2^255-19 because the function only does 1 round of reduction - - true } fn test_carry_propagate_2() -> bool { @@ -67,9 +64,7 @@ fn test_carry_propagate_2() -> bool { let res = carry_propagate(e); - res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); - - true + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }) } fn test_reduce() -> bool { @@ -83,9 +78,7 @@ fn test_reduce() -> bool { let res = reduce(e); - res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }); - - true + res_equals(res, Element{ l0: 2, l1: 1, l2: 0, l3: 0, l4: 0 }) } fn test_reduce_2() -> bool { @@ -115,9 +108,7 @@ fn test_reduce_2() -> bool { 3 * 2^153 + 3 * 2^204 */ - res_equals(res, Element{ l0: 21, l1: 3, l2: 3, l3: 3, l4: 3 }); - - true + res_equals(res, Element{ l0: 21, l1: 3, l2: 3, l3: 3, l4: 3 }) } fn test_reduce_3() -> bool { @@ -155,9 +146,7 @@ fn test_reduce_3() -> bool { l2: 8191, l3: 8191, l4: 8191 - }); - - true + }) } fn test_reduce_4() -> bool { @@ -189,7 +178,5 @@ fn test_reduce_4() -> bool { l2: 0, l3: 0, l4: 0 - }); - - true + }) } diff --git a/edwards25519/src/tests/tests_rshift.sw b/edwards25519/src/tests/tests_rshift.sw index d9b3e14..4cc6506 100644 --- a/edwards25519/src/tests/tests_rshift.sw +++ b/edwards25519/src/tests/tests_rshift.sw @@ -5,41 +5,41 @@ use std::assert::assert; use ::test_helpers::*; use std::u128::*; -pub fn tests_shiftRightBy51() -> bool { - assert(test_shiftRightBy51_random()); - assert(test_shiftRightBy51_random_2()); - assert(test_shiftRightBy51_random_3()); +pub fn tests_shift_right_by51() -> bool { + assert(test_shift_right_by51_random()); + assert(test_shift_right_by51_random_2()); + assert(test_shift_right_by51_random_3()); true } -fn test_shiftRightBy51_random() -> bool { +fn test_shift_right_by51_random() -> bool { let a = U128{upper: 16, lower:0}; - let res = shiftRightBy51(a); + let res = shift_right_by51(a); assert(res == 131072); true } -fn test_shiftRightBy51_random_2() -> bool { +fn test_shift_right_by51_random_2() -> bool { /* 456464 + (349323232 << 64) = 6443876259705066799772399376 >>51 = 2861655916544 */ let a = U128{upper: 349323232, lower:456464}; - let res = shiftRightBy51(a); + let res = shift_right_by51(a); assert(res == 2861655916544); true } -fn test_shiftRightBy51_random_3() -> bool { +fn test_shift_right_by51_random_3() -> bool { /* 18446744073709551615 + (349323232 << 64) = 6443876278151810873481494527 >>51 = 2861655924735 */ let a = U128{upper: 349323232, lower:18446744073709551615}; - let res = shiftRightBy51(a); + let res = shift_right_by51(a); assert(res == 2861655924735); true } diff --git a/edwards25519/src/tests/tests_scalar_mult.sw b/edwards25519/src/tests/tests_scalar_mult.sw index 3d552a6..89aea19 100644 --- a/edwards25519/src/tests/tests_scalar_mult.sw +++ b/edwards25519/src/tests/tests_scalar_mult.sw @@ -23,8 +23,7 @@ fn test_mult_by_0() -> bool { }; let res: Element = scalar_mult(a, 0); - res_equals(res, zero); - true + res_equals(res, ZERO) } fn test_mult_by_1() -> bool { @@ -37,8 +36,7 @@ fn test_mult_by_1() -> bool { }; let res: Element = scalar_mult(a, 1); - res_equals(res, a); - true + res_equals(res, a) } fn test_mult_by_2() -> bool { @@ -71,9 +69,7 @@ fn test_mult_by_2() -> bool { l2: 2251799813685247, l3: 1111110666666445, l4: 2251799813685246 - }); - - true + }) } fn test_mult_by_2_again() -> bool { @@ -109,9 +105,7 @@ fn test_mult_by_2_again() -> bool { l2: 2251799813685247, l3: 2251799813685247, l4: 2251799813685247 - }); - - true + }) } fn test_mult_by_large_scalar() -> bool { @@ -145,7 +139,5 @@ fn test_mult_by_large_scalar() -> bool { l2: 2251799813685247, l3: 536152338865944, l4: 2251796578355658 - }); - - true + }) } \ No newline at end of file diff --git a/edwards25519/src/tests/tests_square.sw b/edwards25519/src/tests/tests_square.sw index 31afee9..109e30f 100644 --- a/edwards25519/src/tests/tests_square.sw +++ b/edwards25519/src/tests/tests_square.sw @@ -12,15 +12,13 @@ pub fn tests_square() -> bool { } fn test_square_one() -> bool { - let res: Element = square(one); - res_equals(res, one); - true + let res: Element = square(ONE); + res_equals(res, ONE) } fn test_square_zero() -> bool { - let res: Element = square(zero); - res_equals(res, zero); - true + let res: Element = square(ZERO); + res_equals(res, ZERO) } fn test_square_random() -> bool { @@ -52,6 +50,5 @@ fn test_square_random() -> bool { }; let res: Element = square(a); - res_equals(res, a_square); - true + res_equals(res, a_square) } \ No newline at end of file diff --git a/edwards25519/src/tests/tests_sub.sw b/edwards25519/src/tests/tests_sub.sw index 3d77443..1c867af 100644 --- a/edwards25519/src/tests/tests_sub.sw +++ b/edwards25519/src/tests/tests_sub.sw @@ -21,10 +21,8 @@ fn test_subtraction_by_0() -> bool { l4: 100 }; - let res: Element = subtract(a, zero); - res_equals(res, a); - - true + let res: Element = subtract(a, ZERO); + res_equals(res, a) } fn test_subtraction_by_1() -> bool { @@ -44,9 +42,8 @@ fn test_subtraction_by_1() -> bool { l4: 100 }; - let res: Element = subtract(a, one); - res_equals(res, b); - true + let res: Element = subtract(a, ONE); + res_equals(res, b) } fn test_subtraction_by_max() -> bool { @@ -93,9 +90,7 @@ fn test_subtraction_by_max() -> bool { let res: Element = subtract(a, b); let res2: Element = subtract(b,a); - res_equals(res, b); - res_equals(res2, one); - true + res_equals(res, b) && res_equals(res2, ONE) } fn test_subtraction_random() -> bool { @@ -176,7 +171,5 @@ fn test_subtraction_random() -> bool { let res: Element = subtract(a, b); let res2: Element = subtract(b,a); - res_equals(res, a_minus_b); - res_equals(res2, b_minus_a); - true + res_equals(res, a_minus_b) && res_equals(res2, b_minus_a) } \ No newline at end of file From 2893b44afbbd1349c15a07d9dc4fecd59330bbb1 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 18:15:16 -0600 Subject: [PATCH 056/160] Cleanup & TODO added --- edwards25519/src/field_element.sw | 7 ++----- edwards25519/src/ge25519.sw | 1 + edwards25519/src/main.sw | 10 +++++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 25c2544..ba1e3da 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -15,6 +15,7 @@ pub struct Element { // = (1 << 51) - 1 // But using the above expression gives the error "Could not evaluate initializer to a const declaration." const MASK_LOW_51_BITS: u64 = 2251799813685247; + pub const ZERO: Element = Element { l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; @@ -129,7 +130,6 @@ pub fn subtract(a: Element, b: Element) -> Element { l4: (a.l4 + 0xFFFFFFFFFFFFE) - b.l4, }; - //carry_propagate(res) reduce(res) } @@ -164,10 +164,7 @@ pub fn add_multiply64(res: U128, a: u64, b: u64) -> U128 { let add_res: (u64, u64) = add64(mul_res.lower, res.lower, 0); let add_res2: (u64, u64) = add64(mul_res.upper, res.upper, add_res.1); - U128 { - upper: add_res2.0, - lower: add_res.0, - } + ~U128::from(add_res2.0, add_res.0) } //right shift by 51 diff --git a/edwards25519/src/ge25519.sw b/edwards25519/src/ge25519.sw index c5a6cb7..10e2f01 100644 --- a/edwards25519/src/ge25519.sw +++ b/edwards25519/src/ge25519.sw @@ -43,6 +43,7 @@ pub struct Ge25519_aff { /* http://www.hyperelliptic.org/EFD/g1p/auto-twisted-extended-1.html#doubling-dbl-2008-hwcd */ +// TODO TEST! pub fn double(p: Ge25519_p2) -> Ge25519_p1p1 { let a = square(p.x); let b = square(p.y); diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 3062d2c..960a33c 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -38,13 +38,13 @@ fn main() { // assert(test_helpers()); // assert(tests_add()); // assert(test_helpers64()); - assert(test_reductions()); - assert(tests_shift_right_by51()); - assert(tests_scalar_mult()); - assert(tests_substract()); + // assert(test_reductions()); + // assert(tests_shift_right_by51()); + // assert(tests_scalar_mult()); + // assert(tests_substract()); // Multiply tests can't run all at the same time - // assert(tests_multiply()); + assert(tests_multiply()); // assert(tests_square()); //Doesnt' terminate From e9e4d1369edd829ed0f6d198cb994bfd4b355df2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 18:38:45 -0600 Subject: [PATCH 057/160] Small fixes --- bls12-381/src/vect.sw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 4c31ccb..e2c08c9 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -145,8 +145,8 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); tmp2.insert(i - 1, limbx.lower); - carry = limbx.lower; + carry = limbx.upper; j += 1; if j == n { break; @@ -199,7 +199,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec limbx = sub_res; //borrow = b_res; ret.insert(i, limbx.lower); - borrow = limbx.upper & 0x1; + borrow = b_res & 0x1; i += 1; } //log(carry); From a48e7d0280799b94a97b3bb04174b69fe24efd20 Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 19 Jul 2022 17:32:18 +0530 Subject: [PATCH 058/160] few comments added --- edwards25519/src/field_element.sw | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index ba1e3da..6d9d947 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -119,7 +119,7 @@ pub fn add(a: Element, b: Element) -> Element { carry_propagate(temp) } -//subtract fn returns a - b +//subtract fn returns a - b mod 2^255 - 19 pub fn subtract(a: Element, b: Element) -> Element { // we add 2*p to avoid any underflow and then subtract b let res: Element = Element { @@ -133,7 +133,7 @@ pub fn subtract(a: Element, b: Element) -> Element { reduce(res) } -//negate return negaive of an element(-a) +//negate return negaive of an element(-a) mod 2^255 - 19 pub fn negate(a: Element) -> Element { subtract(ZERO, a) } @@ -311,7 +311,7 @@ pub fn equals(a: Element, b: Element) -> bool { res == 0 } - +//Testing not done //a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p pub fn inverse(a: Element) -> Element { let mut i = 0; From 9e987f9debc69147b20bc3c7cc8f7286dc172cfd Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 19 Jul 2022 19:50:58 +0530 Subject: [PATCH 059/160] bignum-lib removed --- bignum-lib/.gitignore | 4 - bignum-lib/Cargo.toml | 16 - bignum-lib/Forc.toml | 7 - bignum-lib/src/big_uint.sw | 316 ---------------- bignum-lib/src/helpers.sw | 60 ---- bignum-lib/src/main.sw | 597 ------------------------------- bignum-lib/src/mod_arithmetic.sw | 115 ------ 7 files changed, 1115 deletions(-) delete mode 100644 bignum-lib/.gitignore delete mode 100644 bignum-lib/Cargo.toml delete mode 100644 bignum-lib/Forc.toml delete mode 100644 bignum-lib/src/big_uint.sw delete mode 100644 bignum-lib/src/helpers.sw delete mode 100644 bignum-lib/src/main.sw delete mode 100644 bignum-lib/src/mod_arithmetic.sw diff --git a/bignum-lib/.gitignore b/bignum-lib/.gitignore deleted file mode 100644 index d8d39c0..0000000 --- a/bignum-lib/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -out -target -Forc.lock -Cargo.lock \ No newline at end of file diff --git a/bignum-lib/Cargo.toml b/bignum-lib/Cargo.toml deleted file mode 100644 index 1280bcb..0000000 --- a/bignum-lib/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "bignum-lib" -version = "0.1.0" -authors = ["HashCloak"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/bignum-lib/Forc.toml b/bignum-lib/Forc.toml deleted file mode 100644 index 6ca19ba..0000000 --- a/bignum-lib/Forc.toml +++ /dev/null @@ -1,7 +0,0 @@ -[project] -authors = ["HashCloak"] -entry = "main.sw" -license = "Apache-2.0" -name = "bignum-lib" - -[dependencies] diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw deleted file mode 100644 index d3c6944..0000000 --- a/bignum-lib/src/big_uint.sw +++ /dev/null @@ -1,316 +0,0 @@ -library big_uint; - -dep helpers; -use helpers::*; - -use std::{assert::assert, option::*, vec::Vec}; -use std::logging::log; -use core::num::*; - -/* -Representation of a big unsigned number of arbitrary length - -Note: The largest primitive type in Sway is u64, therefore the BigUint consists of a vector with u32 entries. -When 2 BigUints are added, the result might require more than 32 bits and this will fit into a u64. -*/ -pub struct BigUint { - data: Vec, -} - -impl Zero for BigUint { - fn is_zero(self) -> bool { - return self.data.len() == 0; - } -} - -pub fn get_zero() -> BigUint { - // Currently this is an empty vector, but could also be vector with the single coefficient 0; - // arithemtic code has to be adapted to his! - BigUint{data: ~Vec::new::()} -} - -fn max(left: u64, right: u64) -> u64 { - if(left >= right) { left } else { right } -} - -/* -returns the result of the 3 numbers added together -*/ -fn add_limb(a_i: u32, b_i: u32, carry_i: u32) -> u64 { - let A_i: u64 = a_i; - let B_i: u64 = b_i; - - A_i + B_i + carry_i -} - -/* -returns the 2 bigUints added together. - -Note: This result might be 1 longer than the longest entry. -*/ -pub fn add(a: BigUint, b: BigUint) -> BigUint { - let a_vec: Vec = a.data; - let b_vec: Vec = b.data; - let len_a :u32 = a_vec.len(); - let len_b :u32 = b_vec.len(); - let max_len: u32 = max(len_a, len_b); - - let mut res: Vec = ~Vec::new::(); - let mut i = 0; - let mut carry_i: u32 = 0; - let mut z: u64 = 0; - - while i < max_len { - z = add_limb(unpack_or_0(a_vec.get(i)), unpack_or_0(b_vec.get(i)), carry_i); - - res.push(z & 0xffffffff); - carry_i = ((z>>32) & 0xffffffff); - i = i + 1; - } - - if carry_i != 0 { - res.push(carry_i); - } - - BigUint{data: res} -} - - -/* -returns whether the value that a represents is larger than b -*/ -fn is_bigger_or_equal(a: BigUint, b: BigUint) -> bool { - if a.data.len() > b.data.len() { - return true; - } else if a.data.len() == b.data.len() { - if a.data.len() == 0 { - return true; - } - let mut i = a.data.len() - 1; - let mut a_is_bigger_or_equal = true; - let mut looping = true; - while i >= 0 && looping { - let a_val = unpack_or_0(a.data.get(i)); - let b_val = unpack_or_0(b.data.get(i)); - if a_val > b_val { - looping = false; // we know a is bigger - } else if a_val < b_val { - a_is_bigger_or_equal = false; - looping = false; // we know b is bigger - } else if a_val == b_val && i == 0 { - looping = false; // we have seen all elements and a & b are equal - } else if i > 0 { - // If we're not sure yet and the index is not yet 0; keep looping - i = i - 1; - } else { // this is just a safeguard. There should be no other case than aboce - looping = false; - } - } - return a_is_bigger_or_equal; - } else { - return false; - } -} - -/* -returns (res_i, borrow_i); the result and the possible borrow of a_i - b_i - borrow_i -*/ -fn sub_limb(a_i: u32, b_i: u32, borrow_i: u32) -> (u32, u32) { - if (b_i + borrow_i) > a_i { - (~u32::max() - ((b_i + borrow_i) - a_i), 1) - } else { - (a_i - b_i - borrow_i, 0u32) - } -} - -/* -return Some(BigUint) if a >= b, otherwise None -*/ -pub fn sub(a: BigUint, b: BigUint) -> Option { - // Special case 0 - 0 = 0 - if(a.data.len() == 0 && b.data.len() == 0) { - return Option::Some(BigUint{data: ~Vec::new::()}); - } - - if is_bigger_or_equal(a, b) { - let a_vec: Vec = a.data; - let b_vec: Vec = b.data; - let len_a: u32 = a_vec.len(); - - let mut res: Vec = ~Vec::new::(); - let mut i = 0; - let mut borrow_i: u32 = 0; - let mut x: u32 = 0; - - while i < len_a { - let sub_limb_res = sub_limb(unpack_or_0(a_vec.get(i)), unpack_or_0(b_vec.get(i)), borrow_i); - x = sub_limb_res.0; - borrow_i = sub_limb_res.1; - res.push(x); - i = i + 1; - } - - // Return the result without trailing zeroes - let normalized_res = normalized(res); - - return Option::Some(BigUint{data: normalized_res}); - } else { - return Option::None::(); - } -} - -/* -Not optimized -*/ -pub fn schoolbook_mult(a: BigUint, b: BigUint) -> BigUint { - let a_vec: Vec = a.data; - let b_vec: Vec = b.data; - let a_len = a_vec.len(); - let b_len = b_vec.len(); - - let mut res_vec: Vec = ~Vec::new::(); - - let mut i = 0; - let mut k = 0; - let mut prod_coeff: u64 = 0; - let mut prod_carry: u64 = 0; - let mut temp: u64 = 0; - let base: u64 = 0x100000000; - let mut temp = 0u64; - - while k <= (b_len + a_len) { - prod_coeff = prod_carry; - prod_carry = 0; - while i <= k { - temp = unpack_or_0(a_vec.get(i)) * unpack_or_0(b_vec.get(k-i)); - if temp >= base { - prod_carry += ((temp >> 32) & 0xffffffff); - temp = (temp & 0xffffffff); - } - prod_coeff = prod_coeff + temp; - if prod_coeff >= base { - prod_carry += ((prod_coeff >> 32) & 0xffffffff); - prod_coeff = (prod_coeff & 0xffffffff); - } - i += 1; - } - res_vec.push(prod_coeff); - i = 0; - k += 1; - } - - BigUint{ data: res_vec} -} - - -fn normalized_biguint(a: BigUint) -> BigUint { - let vec = a.data; - let normalized_data = normalized(vec); - BigUint{ data: normalized_data } -} - -/* -Splits the coeff vector 1 time in the middle and uses Karatsuba method to calculate result. - -Assumes length of x is a multiple of 2 -*/ -pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> Option { - // length of x should be even - if (x.data.len() >> 1) << 1 != x.data.len() { //masking with 1 bit didn't work - return Option::None::(); - } - let n = x.data.len() >> 1; - - let mut a_data: Vec = copy_vec_from_to(x.data, 0, n); - let mut b_data: Vec = copy_vec_from_to(x.data, n, x.data.len()); - let mut c_data: Vec = copy_vec_from_to(y.data, 0, n); - let mut d_data: Vec = copy_vec_from_to(y.data, n, y.data.len()); - - let a: BigUint = BigUint{ data: a_data }; - let b: BigUint = BigUint{ data: b_data }; - let c: BigUint = BigUint{ data: c_data }; - let d: BigUint = BigUint{ data: d_data }; - - let ac: BigUint = schoolbook_mult(a, c); - let bd: BigUint = schoolbook_mult(b, d); - let mut temp: BigUint = schoolbook_mult(add(a, b), add(c, d)); // (a+b)*(c+d) - let temp2: BigUint = sub(temp, ac); // (a+b)*(c+d) - ac - assert(temp2.is_some()); - let ab_plus_bc_wrapped: Option = sub(normalized_biguint(temp2.unwrap()), normalized_biguint(bd)); // (a+b)*(c+d) - ac - bd - assert(ab_plus_bc_wrapped.is_some()); - let ab_plus_bc = ab_plus_bc_wrapped.unwrap(); - - // The result would be bd * 2^128 + (ad+bc) * 2^64 + ac - // r * 2^64 for r=[r0,r1] = [0,0,r0,r1] - - // highest represents bd * 2^128 - let mut highest = ~Vec::new::(); - highest.push(0); - highest.push(0); - highest.push(0); - highest.push(0); - let mut i = 0; - let bd_len = bd.data.len(); - while i < bd_len { - highest.push(unpack_or_0(bd.data.get(i))); - i += 1; - } - - // middle represents (ad+bc) * 2^64 - let mut middle = ~Vec::new::(); - middle.push(0); - middle.push(0); - let mut i = 0; - let ab_plus_bc_len = ab_plus_bc.data.len(); - while i < ab_plus_bc_len { - middle.push(unpack_or_0(ab_plus_bc.data.get(i))); - i += 1; - } - - let highest_bigint = BigUint{ data: highest }; - let middle_bigint = BigUint{ data: middle }; - temp = add(highest_bigint, middle_bigint); - return Option::Some(add(temp, ac)); -} - -//https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ - -fn equals(a: BigUint, b: BigUint) -> bool { - if a.is_zero() && b.is_zero() { - true - } else if a.data.len() != b.data.len() { - false - } else { - let mut i = 0; - let mut equal = true; - let mut loop = true; - while i < a.data.len() && loop { - if (unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i))) { - equal = false; - loop = false; - } - i += 1; - } - equal - } -} - -// Very naive, subtracting n until it's not possible anymore -pub fn biguint_mod2(a: BigUint, n: BigUint) -> BigUint { - let mut nk: BigUint = n; - let mut temp: BigUint = get_zero(); - - if equals(a, n) { - return get_zero(); - } - - let mut ak: BigUint = a; - - while is_bigger_or_equal(ak, n) { - temp = add(nk, n); - nk = temp; - ak = sub(a, nk).unwrap(); - } - - normalized_biguint(ak) -} \ No newline at end of file diff --git a/bignum-lib/src/helpers.sw b/bignum-lib/src/helpers.sw deleted file mode 100644 index 254c79a..0000000 --- a/bignum-lib/src/helpers.sw +++ /dev/null @@ -1,60 +0,0 @@ -library helpers; - -use std::{option::*, vec::Vec}; -use std::logging::log; - -pub fn unpack_or_0 (x: Option) -> u32 { - match x { - Option::Some(val) => val , - Option::None => 0, - } -} - -pub trait Zero { - fn is_zero(self) -> bool; -} - -pub fn copy_vec_from_to(vec: Vec, start: u64, end: u64) -> Vec { - let mut res_vec: Vec = ~Vec::new::(); - let mut i = start; - while i < end { - res_vec.push(unpack_or_0(vec.get(i))); - i += 1; - } - res_vec -} - -// Vectors are not yet mutable, so we create a new one and fill it up until possible trailing zeroes -pub fn normalized(vec: Vec) -> Vec { - let mut most_significant_bit_index = vec.len() - 1; - let mut index_found = false; - while !index_found && most_significant_bit_index > 0 { - if (unpack_or_0(vec.get(most_significant_bit_index)) != 0) { - index_found = true; - } else { - most_significant_bit_index = most_significant_bit_index - 1; - } - } - - let mut normalized_res: Vec = ~Vec::new::(); - let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(vec.get(0)) == 0; - if(!res_is_zero) { - let mut j = 0; - while j <= most_significant_bit_index { - normalized_res.push(unpack_or_0(vec.get(j))); - j = j + 1; - } - - } - normalized_res -} - - -// TODO remove, just for testing -pub fn print_vec(vec: Vec) { - let mut i = 0; - while i < vec.len() { - log(unpack_or_0(vec.get(i))); - i += 1; - } -} \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw deleted file mode 100644 index cc74b80..0000000 --- a/bignum-lib/src/main.sw +++ /dev/null @@ -1,597 +0,0 @@ - script; - -dep big_uint; -dep helpers; -// dep mod_arithmetic; - -use ::big_uint::*; -use ::helpers::*; -// use ::mod_arithmetic::*; - -use std::{vec::Vec, option::*, assert::assert, math::*}; -use std::logging::log; -use core::num::*; - -/* -All tests for bignum lib -*/ -fn main() { - assert(biguint_addition_tests()); - assert(biguint_subtraction_tests()); - assert(biguint_mult_tests()); - assert(biguint_mod_tests()); -} - -// ADDITION BIGUINT -fn biguint_addition_tests() -> bool { - assert(biguint_addition()); - assert(biguint_addition_longer_res()); - assert(biguint_addition_with_zero()); - assert(biguint_addition_to_zero()); - assert(biguint_addition_zeros()); - true -} - -/* -Adding 2 bignums together that should result into a result that is -9 + 3 * 2^32 + 2^64 -Which translates into the vector (9, 3, 1) -*/ -fn biguint_addition() -> bool { - // [4294967295, 1] - // = 2^32 + 4294967295 - let mut a_data: Vec = ~Vec::new::(); - a_data.push(~u32::max()); - a_data.push(1); - let a = BigUint{data: a_data}; - - // [10, 1, 1] - // = 2^64 + 2^32 + 10 - let mut b_data: Vec = ~Vec::new::(); - b_data.push(10); - b_data.push(1); - b_data.push(1); - let b = BigUint{data: b_data}; - - // total = 18446744086594453513 - // [9, 3 , 1] = 9 + 3 * 2^32 + 2^64 - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 9); - assert(unpack_or_0(res.get(1)) == 3); - assert(unpack_or_0(res.get(2)) == 1); - assert(res.get(3).is_none()); - - true -} - -/* -Test bigUint addition where the result has 1 more entry in the vector than the inputs -Inputs have len 1, output len 2 -*/ -fn biguint_addition_longer_res() -> bool { - // [4294967295] = 2^32 -1 - let mut a_data: Vec = ~Vec::new::(); - a_data.push(~u32::max()); - let a = BigUint{data: a_data}; - - // [8] - let mut b_data: Vec = ~Vec::new::(); - b_data.push(8); - let b = BigUint{data: b_data}; - - // total = 2 ^ 32 + 7 - // [7, 1] - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 7); - assert(unpack_or_0(res.get(1)) == 1); - assert(res.get(2).is_none()); - - true -} - -/* -1 + 0 = 1 -*/ -fn biguint_addition_with_zero() -> bool { - // a = 1 =[1] - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - let a = BigUint{data: a_data}; - - // b = 0 - let mut b_data: Vec = ~Vec::new::(); - let b = BigUint{data: b_data}; - - // total = 1 - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 1); - assert(res.get(1).is_none()); - - true -} - -/* -[0] + [4, 1] = [4,1] -*/ -fn biguint_addition_to_zero() -> bool { - // a = 0 - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - // b = [4,1] - let mut b_data: Vec = ~Vec::new::(); - b_data.push(4); - b_data.push(1); - let b = BigUint{data: b_data}; - - // total = [4,1] - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 4); - assert(unpack_or_0(res.get(1)) == 1); - assert(res.get(2).is_none()); - - true -} - -fn biguint_addition_zeros() -> bool { - // a = 0 - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - // b = 0 - let mut b_data: Vec = ~Vec::new::(); - let b = BigUint{data: b_data}; - - // total = 0 - let res_bigint = add(a, b); - - assert(res_bigint.is_zero()); - - true -} - -// SUBTRACTION BIGUINT -fn biguint_subtraction_tests() -> bool { - assert(biguint_subtraction_result_none()); - assert(big_uint_subtraction_result_none_2()); - - assert(biguint_subtraction_from_0()); - assert(biguint_subtraction_to_0()); - assert(biguint_subtraction_zeros()); - - assert(biguint_subtraction_res_same_len()); - assert(biguint_subtraction_shorter_len()); - - true -} - -/* -when the first value is smaller than the second, result is None -[200, 10] - [100, 12] -*/ -fn biguint_subtraction_result_none() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(200); - a_data.push(10); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(12); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_none()); - - true -} - -/* -This should also work for length 1 -[6] - [8] should give None -*/ -fn big_uint_subtraction_result_none_2() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(6); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(8); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_none()); - - true -} - -/* -[] - [1] should return None -*/ -fn biguint_subtraction_from_0() -> bool { - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(1); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_none()); - - true -} - -/* -[1]-[1] should return the BigUint that is zero ([]) -*/ -fn biguint_subtraction_to_0() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(1); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_some()); - assert(res_bigint.unwrap().is_zero()); - - true -} - -/* -[3,4,8] - [5,0,5] has a resulting vector of the same length: -[2^32 - 2, 3, 3] -*/ -fn biguint_subtraction_res_same_len() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(3); - a_data.push(4); - a_data.push(8); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(5); - b_data.push(0); - b_data.push(5); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - let res_vec = res_bigint.unwrap().data; - - assert(unpack_or_0(res_vec.get(0)) == ~u32::max() - 2); - assert(unpack_or_0(res_vec.get(1)) == 3); - assert(unpack_or_0(res_vec.get(2)) == 3); - - true -} - -/* -when result of subtraction has trailing zeroes, we return a shorter result vector -[20, 15] - [2, 15] = [18, 0] = [18] -*/ -fn biguint_subtraction_shorter_len() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(20); - a_data.push(15); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(2); - b_data.push(15); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - let res_vec = res_bigint.unwrap().data; - - assert(unpack_or_0(res_vec.get(0)) == 18); - assert(res_vec.get(1).is_none()); - - true -} - -/* -0 - 0 = 0 -*/ -fn biguint_subtraction_zeros() -> bool { - // a = 0 - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - // b = 0 - let mut b_data: Vec = ~Vec::new::(); - let b = BigUint{data: b_data}; - - // total = 0 - let res_bigint = sub(a, b); - - assert(res_bigint.is_some()); - assert(res_bigint.unwrap().is_zero()); - - true -} - -fn biguint_mult_tests() -> bool { - assert(biguint_schoolbook_mult()); - assert(test_from_swayPractice_repo()); - - assert(biguint_mult_karatsuba_1_level()); - assert(biguint_mult_karatsuba_1_level_diff_len()); - true -} - -fn biguint_mult_karatsuba_1_level() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - a_data.push(2); - a_data.push(3); - a_data.push(4); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(200); - b_data.push(300); - b_data.push(400); - let b = BigUint{data: b_data}; - - let res_bigint = karatsuba_1_level_deep(a, b); - let res_vec = res_bigint.unwrap().data; - - assert(unpack_or_0(res_vec.get(0)) == 100); - assert(unpack_or_0(res_vec.get(1)) == 400); - assert(unpack_or_0(res_vec.get(2)) == 1000); - assert(unpack_or_0(res_vec.get(3)) == 2000); - assert(unpack_or_0(res_vec.get(4)) == 2500); - assert(unpack_or_0(res_vec.get(5)) == 2400); - assert(unpack_or_0(res_vec.get(6)) == 1600); - - true -} - -fn biguint_mult_karatsuba_1_level_diff_len() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - a_data.push(2); - a_data.push(3); - a_data.push(4); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(200); - b_data.push(300); - // b_data.push(400); - let b = BigUint{data: b_data}; - - let res_bigint = karatsuba_1_level_deep(a, b); - let vec = res_bigint.unwrap().data; - - assert(unpack_or_0(vec.get(0)) == 100); - assert(unpack_or_0(vec.get(1)) == 400); - assert(unpack_or_0(vec.get(2)) == 1000); - assert(unpack_or_0(vec.get(3)) == 1600); - assert(unpack_or_0(vec.get(4)) == 1700); - assert(unpack_or_0(vec.get(5)) == 1200); - - // [100, 400, 1000, 1600, 1700, 1200] - // 1200 * 2^160 + 1700 * 2^128 + 1600 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 - //1753801965375563525736782247188546140446222870118500 - - true -} - -/* -Example input & output for Karatsuba with BigUint - -X = (1+2*2^32 + 3*2^64 + 4*2^96) = [1,2,3,4] -Y = (100+200*2^32 + 300*2^64 + 400*2^96) = [100,200,300,400] - -a = [1, 2] -b = [3, 4] -c = [100, 200] -d = [300, 400] - -When calculating X*Y -The result = 10043362780126293152582135998281912347988259896158629291622500 - -This is written in base 2^32 as follows: -1600 * 2^192 + 2400 * 2^160 + 2500 * 2^128 + 2000 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 -And therefore translates to data vector -[100, 400, 1000, 2000, 2500, 2400, 1600] -—— - -Applying Karatsuba would work as follows - -Ac = (1+2*2^32)*(100+200*2^32) -= 7378697631201807564900 -Bd = (3+4*2^32) * (300+400*2^32) -= 29514790528243204096900 -Ad+bc = (a+b)*(c+d) - a*c - b*d = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - ac - bd -= ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - (3+4*2^32) * (300+400*2^32) - (1+2*2^32)*(100+200*2^32) -=29514790526525217178200 - - -Then, take as result -Ac * 2^128 + (ad+bc) * 2^64 + Bd - -Check that this is correct: - = 29514790528243204096900 * 2^128 + 29514790526525217178200 * 2^64 + 7378697631201807564900 - = 10043362780126293152582135998281912347988259896158629291622500 - -*/ -fn biguint_schoolbook_mult() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - a_data.push(2); - a_data.push(3); - a_data.push(4); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(200); - b_data.push(300); - b_data.push(400); - let b = BigUint{data: b_data}; - - let res_bigint = schoolbook_mult(a, b); - let res_vec = res_bigint.data; - - assert(unpack_or_0(res_vec.get(0)) == 100); - assert(unpack_or_0(res_vec.get(1)) == 400); - assert(unpack_or_0(res_vec.get(2)) == 1000); - assert(unpack_or_0(res_vec.get(3)) == 2000); - assert(unpack_or_0(res_vec.get(4)) == 2500); - assert(unpack_or_0(res_vec.get(5)) == 2400); - assert(unpack_or_0(res_vec.get(6)) == 1600); - - true -} - -fn test_from_swayPractice_repo() -> bool { -// [2^32 - 1, 2^16] = (2^32 - 1) + 2^16 * 2^32 - let mut a_data: Vec = ~Vec::new::(); - a_data.push(4294967295); - a_data.push(65536); - let a = BigUint{data: a_data}; - -// [2^32-1, 2^18, 2^30] = (2^32 - 1) + 2^18 * 2^32 + 2^30 * 2^64 - let mut b_data: Vec = ~Vec::new::(); - b_data.push(4294967295); - b_data.push(262144); - b_data.push(1073741824); - let b = BigUint{data: b_data}; - - let res_bigint = schoolbook_mult(a, b); - let res = res_bigint.data; - - //res = ((2^32 - 1) + 2^16 * 2^32) * ((2^32 - 1) + 2^18 * 2^32 + 2^30 * 2^64) - // = 5575271370224683131653871446489760217956353 - // 16384 * 2^128 + 1073741827 * 2^96 + 3221553152 * 2^64 + 4294639614 * 2^32 + 1 - // [1, 4294639614, 3221553152, 1073741827, 16384] - match res.get(0) { - Option::Some(r0) =>{ - assert(r0 == 1); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(1) { - Option::Some(r1) =>{ - assert(r1 == 4294639614); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(2) { - Option::Some(r2) =>{ - assert(r2 == 3221553152); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(3) { - Option::Some(r3) =>{ - assert(r3 == 1073741827); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(4) { - Option::Some(r4) =>{ - assert(r4 == 16384); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(5) { - Option::Some(r5) =>{ - assert(r5 == 0); - }, - Option::None => { - log(1000000000); - }, - } - true -} - -fn biguint_mod_tests() -> bool { - assert(biguint_biguint_mod1()); - true -} - -/* -Modular reduction example -100 + 400 * 2^32 -= 1717986918500 -[100, 400] - -1717986918500 mod (2^32+1) = 4294966997 -[1,1] -res -[4294966997] -4294966996 - -mod 12629315258213599 => 1717986918500 -[2579031263, 2940491] -res -[100, 400] -*/ -fn biguint_biguint_mod1() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(100); - a_data.push(400); - let a = BigUint{data: a_data}; - - // Case 1: 1717986918500 mod (2^32+1) = 4294966997 - let mut b_data: Vec = ~Vec::new::(); - b_data.push(1); - b_data.push(1); - let b = BigUint{data: b_data}; - - let mut res_bigint = biguint_mod2(a, b); - let mut res_vec = res_bigint.data; - - // TODO the output is now 4294966996..? - // assert(unpack_or_0(res_vec.get(0)) == 4294966997); - log(res_vec.get(0)); - - // Case 2: Should stay the same, because n > a - let mut c_data: Vec = ~Vec::new::(); - c_data.push(2579031263); - c_data.push(2940491); - let c = BigUint{data: c_data}; - - res_bigint = biguint_mod2(a, c); - res_vec = res_bigint.data; - - assert(unpack_or_0(res_vec.get(0)) == 100); - assert(unpack_or_0(res_vec.get(1)) == 400); - - true -} diff --git a/bignum-lib/src/mod_arithmetic.sw b/bignum-lib/src/mod_arithmetic.sw deleted file mode 100644 index 99e0cff..0000000 --- a/bignum-lib/src/mod_arithmetic.sw +++ /dev/null @@ -1,115 +0,0 @@ -library mod_arithmetic; - -dep helpers; -dep big_uint; - -use helpers::*; -use big_uint::*; - -use std::{assert::assert, option::*, vec::Vec}; -use std::logging::log; -use core::num::*; - - -//returns true if two BigUint are equal -pub fn is_equal (a: BigUint, b: BigUint) -> bool { - - // @Manish currently BigUint is interpreted as 0 when the data.len() == 0 - // a and b could be equal if they are both 0. This can be checked with .is_zero() - // (the Zero trait is defined in helpers.sw, and the implementation of is_zero in big_uint.sw) - // This is not taking into account the case BigUint{data = [0]}, ie a coefficient vector with only a 0 - // so we should decide what 0 really is :D - // I implemented like this, because we always remove trailing zeroes, therefore 0 ends up being a BigUint with an empty vector - if a.data.len() == 0 || b.data.len() == 0 { - return false; - } - else if a.data.len() != b.data.len() { - return false; - } else { - - let mut flag = true; - let mut i = a.data.len() - 1; // if we change the first if check, we have to be careful here - while(i > 0 && flag) { - if unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i)) { - flag = false; - } - i-=1; - } - - return flag; - } -} - -//multiplication of BigUint with u32 integer - -pub fn scalar_multiplication (a: BigUint, b: u32) -> BigUint { - if b == 0 { - return get_zero(); - } - - let mut i = 0; - let mut res: Vec = ~Vec::new::(); - let mut a_i: u64 = 0; - let mut carry: u64 = 0; - - while i < a.data.len() { - a_i = unpack_or_0(a.data.get(i))*b + carry; - res.push( a_i & 0xffffffff); - carry = ((a_i >> 32) & 0xffffffff); - - i += 1; - } - - if carry != 0 { - res.push(carry); - } - - BigUint { - data: res - } -} - -pub fn mod (a: BigUint, n: BigUint) -> BigUint { - - //if a==n (a<=n & n<=a) then (a mod n) = 0 - // if a < n then (a mod n) = a - //if a > n then a (mod n) = r where a = qn + r - // case1: if number of limbs are same - // case2: if numner of limbs are unequal - if is_equal (a, n){ - let mut a: Vec = ~Vec::new::(); - a.push(0u32); - - return BigUint { - data: a - }; - } else if is_bigger_or_equal(n,a) { - return a; - } else { - - let len_a = a.data.len(); - let len_n = n.data.len(); - let mut k: u32 = 1; - let mut nk: BigUint = n; - if len_a == len_n { - //let mut quotient: u32 = 1<<16; - while is_bigger_or_equal(a, nk) { - - k += 1; - nk = sclar_multiplication(n, i); - } - nk = sclar_multiplication(n, k-1); - //let res: BigUint = sub (a, nk); - - return sub(a, nk); - } else { - return sclar_multiplication(n, k); - } - } -} - - - -// pub fn mod_add (a: BigUint, b: BigUint) -> BigUint { - -// } \ No newline at end of file From 9df07fbc803ccf334f20bb03c86f0302d0ec01e6 Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 19 Jul 2022 19:57:17 +0530 Subject: [PATCH 060/160] bignum-lib removed --- bignum-lib/.gitignore | 4 - bignum-lib/Cargo.toml | 16 - bignum-lib/Forc.toml | 7 - bignum-lib/src/big_uint.sw | 316 ---------------- bignum-lib/src/helpers.sw | 60 ---- bignum-lib/src/main.sw | 597 ------------------------------- bignum-lib/src/mod_arithmetic.sw | 115 ------ 7 files changed, 1115 deletions(-) delete mode 100644 bignum-lib/.gitignore delete mode 100644 bignum-lib/Cargo.toml delete mode 100644 bignum-lib/Forc.toml delete mode 100644 bignum-lib/src/big_uint.sw delete mode 100644 bignum-lib/src/helpers.sw delete mode 100644 bignum-lib/src/main.sw delete mode 100644 bignum-lib/src/mod_arithmetic.sw diff --git a/bignum-lib/.gitignore b/bignum-lib/.gitignore deleted file mode 100644 index d8d39c0..0000000 --- a/bignum-lib/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -out -target -Forc.lock -Cargo.lock \ No newline at end of file diff --git a/bignum-lib/Cargo.toml b/bignum-lib/Cargo.toml deleted file mode 100644 index 1280bcb..0000000 --- a/bignum-lib/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "bignum-lib" -version = "0.1.0" -authors = ["HashCloak"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/bignum-lib/Forc.toml b/bignum-lib/Forc.toml deleted file mode 100644 index 6ca19ba..0000000 --- a/bignum-lib/Forc.toml +++ /dev/null @@ -1,7 +0,0 @@ -[project] -authors = ["HashCloak"] -entry = "main.sw" -license = "Apache-2.0" -name = "bignum-lib" - -[dependencies] diff --git a/bignum-lib/src/big_uint.sw b/bignum-lib/src/big_uint.sw deleted file mode 100644 index d3c6944..0000000 --- a/bignum-lib/src/big_uint.sw +++ /dev/null @@ -1,316 +0,0 @@ -library big_uint; - -dep helpers; -use helpers::*; - -use std::{assert::assert, option::*, vec::Vec}; -use std::logging::log; -use core::num::*; - -/* -Representation of a big unsigned number of arbitrary length - -Note: The largest primitive type in Sway is u64, therefore the BigUint consists of a vector with u32 entries. -When 2 BigUints are added, the result might require more than 32 bits and this will fit into a u64. -*/ -pub struct BigUint { - data: Vec, -} - -impl Zero for BigUint { - fn is_zero(self) -> bool { - return self.data.len() == 0; - } -} - -pub fn get_zero() -> BigUint { - // Currently this is an empty vector, but could also be vector with the single coefficient 0; - // arithemtic code has to be adapted to his! - BigUint{data: ~Vec::new::()} -} - -fn max(left: u64, right: u64) -> u64 { - if(left >= right) { left } else { right } -} - -/* -returns the result of the 3 numbers added together -*/ -fn add_limb(a_i: u32, b_i: u32, carry_i: u32) -> u64 { - let A_i: u64 = a_i; - let B_i: u64 = b_i; - - A_i + B_i + carry_i -} - -/* -returns the 2 bigUints added together. - -Note: This result might be 1 longer than the longest entry. -*/ -pub fn add(a: BigUint, b: BigUint) -> BigUint { - let a_vec: Vec = a.data; - let b_vec: Vec = b.data; - let len_a :u32 = a_vec.len(); - let len_b :u32 = b_vec.len(); - let max_len: u32 = max(len_a, len_b); - - let mut res: Vec = ~Vec::new::(); - let mut i = 0; - let mut carry_i: u32 = 0; - let mut z: u64 = 0; - - while i < max_len { - z = add_limb(unpack_or_0(a_vec.get(i)), unpack_or_0(b_vec.get(i)), carry_i); - - res.push(z & 0xffffffff); - carry_i = ((z>>32) & 0xffffffff); - i = i + 1; - } - - if carry_i != 0 { - res.push(carry_i); - } - - BigUint{data: res} -} - - -/* -returns whether the value that a represents is larger than b -*/ -fn is_bigger_or_equal(a: BigUint, b: BigUint) -> bool { - if a.data.len() > b.data.len() { - return true; - } else if a.data.len() == b.data.len() { - if a.data.len() == 0 { - return true; - } - let mut i = a.data.len() - 1; - let mut a_is_bigger_or_equal = true; - let mut looping = true; - while i >= 0 && looping { - let a_val = unpack_or_0(a.data.get(i)); - let b_val = unpack_or_0(b.data.get(i)); - if a_val > b_val { - looping = false; // we know a is bigger - } else if a_val < b_val { - a_is_bigger_or_equal = false; - looping = false; // we know b is bigger - } else if a_val == b_val && i == 0 { - looping = false; // we have seen all elements and a & b are equal - } else if i > 0 { - // If we're not sure yet and the index is not yet 0; keep looping - i = i - 1; - } else { // this is just a safeguard. There should be no other case than aboce - looping = false; - } - } - return a_is_bigger_or_equal; - } else { - return false; - } -} - -/* -returns (res_i, borrow_i); the result and the possible borrow of a_i - b_i - borrow_i -*/ -fn sub_limb(a_i: u32, b_i: u32, borrow_i: u32) -> (u32, u32) { - if (b_i + borrow_i) > a_i { - (~u32::max() - ((b_i + borrow_i) - a_i), 1) - } else { - (a_i - b_i - borrow_i, 0u32) - } -} - -/* -return Some(BigUint) if a >= b, otherwise None -*/ -pub fn sub(a: BigUint, b: BigUint) -> Option { - // Special case 0 - 0 = 0 - if(a.data.len() == 0 && b.data.len() == 0) { - return Option::Some(BigUint{data: ~Vec::new::()}); - } - - if is_bigger_or_equal(a, b) { - let a_vec: Vec = a.data; - let b_vec: Vec = b.data; - let len_a: u32 = a_vec.len(); - - let mut res: Vec = ~Vec::new::(); - let mut i = 0; - let mut borrow_i: u32 = 0; - let mut x: u32 = 0; - - while i < len_a { - let sub_limb_res = sub_limb(unpack_or_0(a_vec.get(i)), unpack_or_0(b_vec.get(i)), borrow_i); - x = sub_limb_res.0; - borrow_i = sub_limb_res.1; - res.push(x); - i = i + 1; - } - - // Return the result without trailing zeroes - let normalized_res = normalized(res); - - return Option::Some(BigUint{data: normalized_res}); - } else { - return Option::None::(); - } -} - -/* -Not optimized -*/ -pub fn schoolbook_mult(a: BigUint, b: BigUint) -> BigUint { - let a_vec: Vec = a.data; - let b_vec: Vec = b.data; - let a_len = a_vec.len(); - let b_len = b_vec.len(); - - let mut res_vec: Vec = ~Vec::new::(); - - let mut i = 0; - let mut k = 0; - let mut prod_coeff: u64 = 0; - let mut prod_carry: u64 = 0; - let mut temp: u64 = 0; - let base: u64 = 0x100000000; - let mut temp = 0u64; - - while k <= (b_len + a_len) { - prod_coeff = prod_carry; - prod_carry = 0; - while i <= k { - temp = unpack_or_0(a_vec.get(i)) * unpack_or_0(b_vec.get(k-i)); - if temp >= base { - prod_carry += ((temp >> 32) & 0xffffffff); - temp = (temp & 0xffffffff); - } - prod_coeff = prod_coeff + temp; - if prod_coeff >= base { - prod_carry += ((prod_coeff >> 32) & 0xffffffff); - prod_coeff = (prod_coeff & 0xffffffff); - } - i += 1; - } - res_vec.push(prod_coeff); - i = 0; - k += 1; - } - - BigUint{ data: res_vec} -} - - -fn normalized_biguint(a: BigUint) -> BigUint { - let vec = a.data; - let normalized_data = normalized(vec); - BigUint{ data: normalized_data } -} - -/* -Splits the coeff vector 1 time in the middle and uses Karatsuba method to calculate result. - -Assumes length of x is a multiple of 2 -*/ -pub fn karatsuba_1_level_deep(x: BigUint, y: BigUint) -> Option { - // length of x should be even - if (x.data.len() >> 1) << 1 != x.data.len() { //masking with 1 bit didn't work - return Option::None::(); - } - let n = x.data.len() >> 1; - - let mut a_data: Vec = copy_vec_from_to(x.data, 0, n); - let mut b_data: Vec = copy_vec_from_to(x.data, n, x.data.len()); - let mut c_data: Vec = copy_vec_from_to(y.data, 0, n); - let mut d_data: Vec = copy_vec_from_to(y.data, n, y.data.len()); - - let a: BigUint = BigUint{ data: a_data }; - let b: BigUint = BigUint{ data: b_data }; - let c: BigUint = BigUint{ data: c_data }; - let d: BigUint = BigUint{ data: d_data }; - - let ac: BigUint = schoolbook_mult(a, c); - let bd: BigUint = schoolbook_mult(b, d); - let mut temp: BigUint = schoolbook_mult(add(a, b), add(c, d)); // (a+b)*(c+d) - let temp2: BigUint = sub(temp, ac); // (a+b)*(c+d) - ac - assert(temp2.is_some()); - let ab_plus_bc_wrapped: Option = sub(normalized_biguint(temp2.unwrap()), normalized_biguint(bd)); // (a+b)*(c+d) - ac - bd - assert(ab_plus_bc_wrapped.is_some()); - let ab_plus_bc = ab_plus_bc_wrapped.unwrap(); - - // The result would be bd * 2^128 + (ad+bc) * 2^64 + ac - // r * 2^64 for r=[r0,r1] = [0,0,r0,r1] - - // highest represents bd * 2^128 - let mut highest = ~Vec::new::(); - highest.push(0); - highest.push(0); - highest.push(0); - highest.push(0); - let mut i = 0; - let bd_len = bd.data.len(); - while i < bd_len { - highest.push(unpack_or_0(bd.data.get(i))); - i += 1; - } - - // middle represents (ad+bc) * 2^64 - let mut middle = ~Vec::new::(); - middle.push(0); - middle.push(0); - let mut i = 0; - let ab_plus_bc_len = ab_plus_bc.data.len(); - while i < ab_plus_bc_len { - middle.push(unpack_or_0(ab_plus_bc.data.get(i))); - i += 1; - } - - let highest_bigint = BigUint{ data: highest }; - let middle_bigint = BigUint{ data: middle }; - temp = add(highest_bigint, middle_bigint); - return Option::Some(add(temp, ac)); -} - -//https://aquarchitect.github.io/swift-algorithm-club/Karatsuba%20Multiplication/ - -fn equals(a: BigUint, b: BigUint) -> bool { - if a.is_zero() && b.is_zero() { - true - } else if a.data.len() != b.data.len() { - false - } else { - let mut i = 0; - let mut equal = true; - let mut loop = true; - while i < a.data.len() && loop { - if (unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i))) { - equal = false; - loop = false; - } - i += 1; - } - equal - } -} - -// Very naive, subtracting n until it's not possible anymore -pub fn biguint_mod2(a: BigUint, n: BigUint) -> BigUint { - let mut nk: BigUint = n; - let mut temp: BigUint = get_zero(); - - if equals(a, n) { - return get_zero(); - } - - let mut ak: BigUint = a; - - while is_bigger_or_equal(ak, n) { - temp = add(nk, n); - nk = temp; - ak = sub(a, nk).unwrap(); - } - - normalized_biguint(ak) -} \ No newline at end of file diff --git a/bignum-lib/src/helpers.sw b/bignum-lib/src/helpers.sw deleted file mode 100644 index 254c79a..0000000 --- a/bignum-lib/src/helpers.sw +++ /dev/null @@ -1,60 +0,0 @@ -library helpers; - -use std::{option::*, vec::Vec}; -use std::logging::log; - -pub fn unpack_or_0 (x: Option) -> u32 { - match x { - Option::Some(val) => val , - Option::None => 0, - } -} - -pub trait Zero { - fn is_zero(self) -> bool; -} - -pub fn copy_vec_from_to(vec: Vec, start: u64, end: u64) -> Vec { - let mut res_vec: Vec = ~Vec::new::(); - let mut i = start; - while i < end { - res_vec.push(unpack_or_0(vec.get(i))); - i += 1; - } - res_vec -} - -// Vectors are not yet mutable, so we create a new one and fill it up until possible trailing zeroes -pub fn normalized(vec: Vec) -> Vec { - let mut most_significant_bit_index = vec.len() - 1; - let mut index_found = false; - while !index_found && most_significant_bit_index > 0 { - if (unpack_or_0(vec.get(most_significant_bit_index)) != 0) { - index_found = true; - } else { - most_significant_bit_index = most_significant_bit_index - 1; - } - } - - let mut normalized_res: Vec = ~Vec::new::(); - let res_is_zero = most_significant_bit_index == 0 && unpack_or_0(vec.get(0)) == 0; - if(!res_is_zero) { - let mut j = 0; - while j <= most_significant_bit_index { - normalized_res.push(unpack_or_0(vec.get(j))); - j = j + 1; - } - - } - normalized_res -} - - -// TODO remove, just for testing -pub fn print_vec(vec: Vec) { - let mut i = 0; - while i < vec.len() { - log(unpack_or_0(vec.get(i))); - i += 1; - } -} \ No newline at end of file diff --git a/bignum-lib/src/main.sw b/bignum-lib/src/main.sw deleted file mode 100644 index cc74b80..0000000 --- a/bignum-lib/src/main.sw +++ /dev/null @@ -1,597 +0,0 @@ - script; - -dep big_uint; -dep helpers; -// dep mod_arithmetic; - -use ::big_uint::*; -use ::helpers::*; -// use ::mod_arithmetic::*; - -use std::{vec::Vec, option::*, assert::assert, math::*}; -use std::logging::log; -use core::num::*; - -/* -All tests for bignum lib -*/ -fn main() { - assert(biguint_addition_tests()); - assert(biguint_subtraction_tests()); - assert(biguint_mult_tests()); - assert(biguint_mod_tests()); -} - -// ADDITION BIGUINT -fn biguint_addition_tests() -> bool { - assert(biguint_addition()); - assert(biguint_addition_longer_res()); - assert(biguint_addition_with_zero()); - assert(biguint_addition_to_zero()); - assert(biguint_addition_zeros()); - true -} - -/* -Adding 2 bignums together that should result into a result that is -9 + 3 * 2^32 + 2^64 -Which translates into the vector (9, 3, 1) -*/ -fn biguint_addition() -> bool { - // [4294967295, 1] - // = 2^32 + 4294967295 - let mut a_data: Vec = ~Vec::new::(); - a_data.push(~u32::max()); - a_data.push(1); - let a = BigUint{data: a_data}; - - // [10, 1, 1] - // = 2^64 + 2^32 + 10 - let mut b_data: Vec = ~Vec::new::(); - b_data.push(10); - b_data.push(1); - b_data.push(1); - let b = BigUint{data: b_data}; - - // total = 18446744086594453513 - // [9, 3 , 1] = 9 + 3 * 2^32 + 2^64 - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 9); - assert(unpack_or_0(res.get(1)) == 3); - assert(unpack_or_0(res.get(2)) == 1); - assert(res.get(3).is_none()); - - true -} - -/* -Test bigUint addition where the result has 1 more entry in the vector than the inputs -Inputs have len 1, output len 2 -*/ -fn biguint_addition_longer_res() -> bool { - // [4294967295] = 2^32 -1 - let mut a_data: Vec = ~Vec::new::(); - a_data.push(~u32::max()); - let a = BigUint{data: a_data}; - - // [8] - let mut b_data: Vec = ~Vec::new::(); - b_data.push(8); - let b = BigUint{data: b_data}; - - // total = 2 ^ 32 + 7 - // [7, 1] - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 7); - assert(unpack_or_0(res.get(1)) == 1); - assert(res.get(2).is_none()); - - true -} - -/* -1 + 0 = 1 -*/ -fn biguint_addition_with_zero() -> bool { - // a = 1 =[1] - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - let a = BigUint{data: a_data}; - - // b = 0 - let mut b_data: Vec = ~Vec::new::(); - let b = BigUint{data: b_data}; - - // total = 1 - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 1); - assert(res.get(1).is_none()); - - true -} - -/* -[0] + [4, 1] = [4,1] -*/ -fn biguint_addition_to_zero() -> bool { - // a = 0 - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - // b = [4,1] - let mut b_data: Vec = ~Vec::new::(); - b_data.push(4); - b_data.push(1); - let b = BigUint{data: b_data}; - - // total = [4,1] - let res_bigint = add(a, b); - let res: Vec = res_bigint.data; - - assert(unpack_or_0(res.get(0)) == 4); - assert(unpack_or_0(res.get(1)) == 1); - assert(res.get(2).is_none()); - - true -} - -fn biguint_addition_zeros() -> bool { - // a = 0 - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - // b = 0 - let mut b_data: Vec = ~Vec::new::(); - let b = BigUint{data: b_data}; - - // total = 0 - let res_bigint = add(a, b); - - assert(res_bigint.is_zero()); - - true -} - -// SUBTRACTION BIGUINT -fn biguint_subtraction_tests() -> bool { - assert(biguint_subtraction_result_none()); - assert(big_uint_subtraction_result_none_2()); - - assert(biguint_subtraction_from_0()); - assert(biguint_subtraction_to_0()); - assert(biguint_subtraction_zeros()); - - assert(biguint_subtraction_res_same_len()); - assert(biguint_subtraction_shorter_len()); - - true -} - -/* -when the first value is smaller than the second, result is None -[200, 10] - [100, 12] -*/ -fn biguint_subtraction_result_none() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(200); - a_data.push(10); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(12); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_none()); - - true -} - -/* -This should also work for length 1 -[6] - [8] should give None -*/ -fn big_uint_subtraction_result_none_2() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(6); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(8); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_none()); - - true -} - -/* -[] - [1] should return None -*/ -fn biguint_subtraction_from_0() -> bool { - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(1); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_none()); - - true -} - -/* -[1]-[1] should return the BigUint that is zero ([]) -*/ -fn biguint_subtraction_to_0() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(1); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - - assert(res_bigint.is_some()); - assert(res_bigint.unwrap().is_zero()); - - true -} - -/* -[3,4,8] - [5,0,5] has a resulting vector of the same length: -[2^32 - 2, 3, 3] -*/ -fn biguint_subtraction_res_same_len() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(3); - a_data.push(4); - a_data.push(8); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(5); - b_data.push(0); - b_data.push(5); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - let res_vec = res_bigint.unwrap().data; - - assert(unpack_or_0(res_vec.get(0)) == ~u32::max() - 2); - assert(unpack_or_0(res_vec.get(1)) == 3); - assert(unpack_or_0(res_vec.get(2)) == 3); - - true -} - -/* -when result of subtraction has trailing zeroes, we return a shorter result vector -[20, 15] - [2, 15] = [18, 0] = [18] -*/ -fn biguint_subtraction_shorter_len() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(20); - a_data.push(15); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(2); - b_data.push(15); - let b = BigUint{data: b_data}; - - let res_bigint = sub(a, b); - let res_vec = res_bigint.unwrap().data; - - assert(unpack_or_0(res_vec.get(0)) == 18); - assert(res_vec.get(1).is_none()); - - true -} - -/* -0 - 0 = 0 -*/ -fn biguint_subtraction_zeros() -> bool { - // a = 0 - let mut a_data: Vec = ~Vec::new::(); - let a = BigUint{data: a_data}; - - // b = 0 - let mut b_data: Vec = ~Vec::new::(); - let b = BigUint{data: b_data}; - - // total = 0 - let res_bigint = sub(a, b); - - assert(res_bigint.is_some()); - assert(res_bigint.unwrap().is_zero()); - - true -} - -fn biguint_mult_tests() -> bool { - assert(biguint_schoolbook_mult()); - assert(test_from_swayPractice_repo()); - - assert(biguint_mult_karatsuba_1_level()); - assert(biguint_mult_karatsuba_1_level_diff_len()); - true -} - -fn biguint_mult_karatsuba_1_level() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - a_data.push(2); - a_data.push(3); - a_data.push(4); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(200); - b_data.push(300); - b_data.push(400); - let b = BigUint{data: b_data}; - - let res_bigint = karatsuba_1_level_deep(a, b); - let res_vec = res_bigint.unwrap().data; - - assert(unpack_or_0(res_vec.get(0)) == 100); - assert(unpack_or_0(res_vec.get(1)) == 400); - assert(unpack_or_0(res_vec.get(2)) == 1000); - assert(unpack_or_0(res_vec.get(3)) == 2000); - assert(unpack_or_0(res_vec.get(4)) == 2500); - assert(unpack_or_0(res_vec.get(5)) == 2400); - assert(unpack_or_0(res_vec.get(6)) == 1600); - - true -} - -fn biguint_mult_karatsuba_1_level_diff_len() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - a_data.push(2); - a_data.push(3); - a_data.push(4); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(200); - b_data.push(300); - // b_data.push(400); - let b = BigUint{data: b_data}; - - let res_bigint = karatsuba_1_level_deep(a, b); - let vec = res_bigint.unwrap().data; - - assert(unpack_or_0(vec.get(0)) == 100); - assert(unpack_or_0(vec.get(1)) == 400); - assert(unpack_or_0(vec.get(2)) == 1000); - assert(unpack_or_0(vec.get(3)) == 1600); - assert(unpack_or_0(vec.get(4)) == 1700); - assert(unpack_or_0(vec.get(5)) == 1200); - - // [100, 400, 1000, 1600, 1700, 1200] - // 1200 * 2^160 + 1700 * 2^128 + 1600 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 - //1753801965375563525736782247188546140446222870118500 - - true -} - -/* -Example input & output for Karatsuba with BigUint - -X = (1+2*2^32 + 3*2^64 + 4*2^96) = [1,2,3,4] -Y = (100+200*2^32 + 300*2^64 + 400*2^96) = [100,200,300,400] - -a = [1, 2] -b = [3, 4] -c = [100, 200] -d = [300, 400] - -When calculating X*Y -The result = 10043362780126293152582135998281912347988259896158629291622500 - -This is written in base 2^32 as follows: -1600 * 2^192 + 2400 * 2^160 + 2500 * 2^128 + 2000 * 2^96 + 1000 * 2^64 +400 * 2^32 + 100 -And therefore translates to data vector -[100, 400, 1000, 2000, 2500, 2400, 1600] -—— - -Applying Karatsuba would work as follows - -Ac = (1+2*2^32)*(100+200*2^32) -= 7378697631201807564900 -Bd = (3+4*2^32) * (300+400*2^32) -= 29514790528243204096900 -Ad+bc = (a+b)*(c+d) - a*c - b*d = ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - ac - bd -= ((3+4*2^32) + (1+2*2^32)) * ((100+200*2^32) + (300+400*2^32)) - (3+4*2^32) * (300+400*2^32) - (1+2*2^32)*(100+200*2^32) -=29514790526525217178200 - - -Then, take as result -Ac * 2^128 + (ad+bc) * 2^64 + Bd - -Check that this is correct: - = 29514790528243204096900 * 2^128 + 29514790526525217178200 * 2^64 + 7378697631201807564900 - = 10043362780126293152582135998281912347988259896158629291622500 - -*/ -fn biguint_schoolbook_mult() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(1); - a_data.push(2); - a_data.push(3); - a_data.push(4); - let a = BigUint{data: a_data}; - - let mut b_data: Vec = ~Vec::new::(); - b_data.push(100); - b_data.push(200); - b_data.push(300); - b_data.push(400); - let b = BigUint{data: b_data}; - - let res_bigint = schoolbook_mult(a, b); - let res_vec = res_bigint.data; - - assert(unpack_or_0(res_vec.get(0)) == 100); - assert(unpack_or_0(res_vec.get(1)) == 400); - assert(unpack_or_0(res_vec.get(2)) == 1000); - assert(unpack_or_0(res_vec.get(3)) == 2000); - assert(unpack_or_0(res_vec.get(4)) == 2500); - assert(unpack_or_0(res_vec.get(5)) == 2400); - assert(unpack_or_0(res_vec.get(6)) == 1600); - - true -} - -fn test_from_swayPractice_repo() -> bool { -// [2^32 - 1, 2^16] = (2^32 - 1) + 2^16 * 2^32 - let mut a_data: Vec = ~Vec::new::(); - a_data.push(4294967295); - a_data.push(65536); - let a = BigUint{data: a_data}; - -// [2^32-1, 2^18, 2^30] = (2^32 - 1) + 2^18 * 2^32 + 2^30 * 2^64 - let mut b_data: Vec = ~Vec::new::(); - b_data.push(4294967295); - b_data.push(262144); - b_data.push(1073741824); - let b = BigUint{data: b_data}; - - let res_bigint = schoolbook_mult(a, b); - let res = res_bigint.data; - - //res = ((2^32 - 1) + 2^16 * 2^32) * ((2^32 - 1) + 2^18 * 2^32 + 2^30 * 2^64) - // = 5575271370224683131653871446489760217956353 - // 16384 * 2^128 + 1073741827 * 2^96 + 3221553152 * 2^64 + 4294639614 * 2^32 + 1 - // [1, 4294639614, 3221553152, 1073741827, 16384] - match res.get(0) { - Option::Some(r0) =>{ - assert(r0 == 1); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(1) { - Option::Some(r1) =>{ - assert(r1 == 4294639614); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(2) { - Option::Some(r2) =>{ - assert(r2 == 3221553152); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(3) { - Option::Some(r3) =>{ - assert(r3 == 1073741827); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(4) { - Option::Some(r4) =>{ - assert(r4 == 16384); - }, - Option::None => { - log(1000000000); - }, - } - - match res.get(5) { - Option::Some(r5) =>{ - assert(r5 == 0); - }, - Option::None => { - log(1000000000); - }, - } - true -} - -fn biguint_mod_tests() -> bool { - assert(biguint_biguint_mod1()); - true -} - -/* -Modular reduction example -100 + 400 * 2^32 -= 1717986918500 -[100, 400] - -1717986918500 mod (2^32+1) = 4294966997 -[1,1] -res -[4294966997] -4294966996 - -mod 12629315258213599 => 1717986918500 -[2579031263, 2940491] -res -[100, 400] -*/ -fn biguint_biguint_mod1() -> bool { - let mut a_data: Vec = ~Vec::new::(); - a_data.push(100); - a_data.push(400); - let a = BigUint{data: a_data}; - - // Case 1: 1717986918500 mod (2^32+1) = 4294966997 - let mut b_data: Vec = ~Vec::new::(); - b_data.push(1); - b_data.push(1); - let b = BigUint{data: b_data}; - - let mut res_bigint = biguint_mod2(a, b); - let mut res_vec = res_bigint.data; - - // TODO the output is now 4294966996..? - // assert(unpack_or_0(res_vec.get(0)) == 4294966997); - log(res_vec.get(0)); - - // Case 2: Should stay the same, because n > a - let mut c_data: Vec = ~Vec::new::(); - c_data.push(2579031263); - c_data.push(2940491); - let c = BigUint{data: c_data}; - - res_bigint = biguint_mod2(a, c); - res_vec = res_bigint.data; - - assert(unpack_or_0(res_vec.get(0)) == 100); - assert(unpack_or_0(res_vec.get(1)) == 400); - - true -} diff --git a/bignum-lib/src/mod_arithmetic.sw b/bignum-lib/src/mod_arithmetic.sw deleted file mode 100644 index 99e0cff..0000000 --- a/bignum-lib/src/mod_arithmetic.sw +++ /dev/null @@ -1,115 +0,0 @@ -library mod_arithmetic; - -dep helpers; -dep big_uint; - -use helpers::*; -use big_uint::*; - -use std::{assert::assert, option::*, vec::Vec}; -use std::logging::log; -use core::num::*; - - -//returns true if two BigUint are equal -pub fn is_equal (a: BigUint, b: BigUint) -> bool { - - // @Manish currently BigUint is interpreted as 0 when the data.len() == 0 - // a and b could be equal if they are both 0. This can be checked with .is_zero() - // (the Zero trait is defined in helpers.sw, and the implementation of is_zero in big_uint.sw) - // This is not taking into account the case BigUint{data = [0]}, ie a coefficient vector with only a 0 - // so we should decide what 0 really is :D - // I implemented like this, because we always remove trailing zeroes, therefore 0 ends up being a BigUint with an empty vector - if a.data.len() == 0 || b.data.len() == 0 { - return false; - } - else if a.data.len() != b.data.len() { - return false; - } else { - - let mut flag = true; - let mut i = a.data.len() - 1; // if we change the first if check, we have to be careful here - while(i > 0 && flag) { - if unpack_or_0(a.data.get(i)) != unpack_or_0(b.data.get(i)) { - flag = false; - } - i-=1; - } - - return flag; - } -} - -//multiplication of BigUint with u32 integer - -pub fn scalar_multiplication (a: BigUint, b: u32) -> BigUint { - if b == 0 { - return get_zero(); - } - - let mut i = 0; - let mut res: Vec = ~Vec::new::(); - let mut a_i: u64 = 0; - let mut carry: u64 = 0; - - while i < a.data.len() { - a_i = unpack_or_0(a.data.get(i))*b + carry; - res.push( a_i & 0xffffffff); - carry = ((a_i >> 32) & 0xffffffff); - - i += 1; - } - - if carry != 0 { - res.push(carry); - } - - BigUint { - data: res - } -} - -pub fn mod (a: BigUint, n: BigUint) -> BigUint { - - //if a==n (a<=n & n<=a) then (a mod n) = 0 - // if a < n then (a mod n) = a - //if a > n then a (mod n) = r where a = qn + r - // case1: if number of limbs are same - // case2: if numner of limbs are unequal - if is_equal (a, n){ - let mut a: Vec = ~Vec::new::(); - a.push(0u32); - - return BigUint { - data: a - }; - } else if is_bigger_or_equal(n,a) { - return a; - } else { - - let len_a = a.data.len(); - let len_n = n.data.len(); - let mut k: u32 = 1; - let mut nk: BigUint = n; - if len_a == len_n { - //let mut quotient: u32 = 1<<16; - while is_bigger_or_equal(a, nk) { - - k += 1; - nk = sclar_multiplication(n, i); - } - nk = sclar_multiplication(n, k-1); - //let res: BigUint = sub (a, nk); - - return sub(a, nk); - } else { - return sclar_multiplication(n, k); - } - } -} - - - -// pub fn mod_add (a: BigUint, b: BigUint) -> BigUint { - -// } \ No newline at end of file From 0b7d36f7594d072c09537440bfb6a0a177fd4a87 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 19 Jul 2022 19:04:29 -0600 Subject: [PATCH 061/160] - Added mul_temp, the zkcrypto multiplication algorithm. Just to check whether we get the same output as that implementation - and yes we do. - Added accompanying test. - Updated .gitignore --- .gitignore | 3 +- bls12-381/src/main.sw | 4 + bls12-381/src/tests/tests_temp_mul.sw | 117 ++++++++++++++++++++ bls12-381/src/vect.sw | 148 +++++++++++++++++++++++--- 4 files changed, 254 insertions(+), 18 deletions(-) create mode 100644 bls12-381/src/tests/tests_temp_mul.sw diff --git a/.gitignore b/.gitignore index d6426e4..2b898f5 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ Cargo.lock */Cargo.lock */Forc.lock -*/out/* \ No newline at end of file +*/out/* +*/target/* \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 77406fd..8203d87 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -8,6 +8,7 @@ dep tests/tests_vect_fp; dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; dep tests/tests_small_functions; +dep tests/tests_temp_mul; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -20,6 +21,7 @@ use ::tests_vect_fp::fp_tests; use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; use ::tests_small_functions::tests_small_functions; +use ::tests_temp_mul::tests_temp_mul; fn main() { // assert(fp_tests()); @@ -28,6 +30,8 @@ fn main() { // assert(test_mac()); assert(vect_subfunctions_tests()); // assert(tests_small_functions()); + + // assert(tests_temp_mul()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_temp_mul.sw b/bls12-381/src/tests/tests_temp_mul.sw new file mode 100644 index 0000000..a1f5583 --- /dev/null +++ b/bls12-381/src/tests/tests_temp_mul.sw @@ -0,0 +1,117 @@ +library tests_temp_mul; + +use ::vect::*; +use std::{assert::assert, vec::Vec}; +use ::test_helpers::*; + +pub fn tests_temp_mul() -> bool { + assert(test_mul_temp_by_2()); + true +} + +fn test_temp_mul_random_by_random() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); + + //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + //12684677789208411253122026388948849483224138949631185589801456383786133679073 + let res_vec = vec384 { + ls: [4793585148327242455, 2837967030551533581, 1626660158106644623, 15384342728939744618, 1826521055323312182, 528164867630647501] + }; + // let mut res_vec = ~Vec::new::(); + // res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 + // res_vec.push(0x27627bfa644b580d);//2837967030551533581 + // res_vec.push(0x16930ecb9e3a308f);//1626660158106644623 + // res_vec.push(0xd5802a33c5512d6a);//15384342728939744618 + // res_vec.push(0x19591b38f5515036);//1826521055323312182 + // res_vec.push(0x7546b2615f748cd);//528164867630647501 + + let res = mul_temp(r1_vec, r2_vec, p_vec, 6); + print_vec384(res); +/* +16484308011771146774 + +12795119582497094196 * 2^64 + +7495239071060242083 * 2^128 + +6228288009955243706 * 2^192 + +334445847756758381 * 2^256 + +1343304342180463133 * 2^320 + +16484308011771146774 + 12795119582497094196 * 2**64 +7495239071060242083 * 2**128 +6228288009955243706 * 2**192 +334445847756758381 * 2**256 +1343304342180463133 * 2**320 += +2869280660193735394861207574210601737447645641788161081095242677999752664315845687657572464353026167520041778459158 +Same result as zkcrypto! + +and this is not the same result as blst +*/ + // equals_vec384(res, res_vec); + + true +} + +fn test_mul_temp_by_2() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + //2367106380816923637832389518823092703674202766714323478820851269126356623723913304989534316437425836090100832620729 + //[9172416622910853305, 14987574562624449790, 13213778230238218784, + //15872153713916140599, 9712154313263354644, 1108202597211161767] + let mut r1_vec = ~Vec::new::(); + r1_vec.push(9172416622910853305); + r1_vec.push(14987574562624449790); + r1_vec.push(13213778230238218784); + r1_vec.push(15872153713916140599); + r1_vec.push(9712154313263354644); + r1_vec.push(1108202597211161767); + + let mut vec_2 = ~Vec::new::(); + vec_2.push(2); + vec_2.push(0); + vec_2.push(0); + vec_2.push(0); + vec_2.push(0); + vec_2.push(0); + +//731803206412179882246989211910281250791522713489639072309644402128681596956988745536381003745836008142307392681671 +//[4942402229743843015, 9318263540022139389, 545137813202804253, +//6058225393708017072, 14012204848056006994, 342606576774783668] + let res = mul_temp(r1_vec, vec_2, p_vec, 6); + print_vec384(res); + /* + 11360606136736300744 + 10320420748134520786 + 17912563010296520217 + 16145629554006184624 + 12933232110729028586 + 1518885514198738558 + Same result as zkcrypto! + + */ + true +} \ No newline at end of file diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index e2c08c9..eb1dbc9 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -223,6 +223,131 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +// from https://github.com/zkcrypto/bls12_381 +pub fn montgomery_reduction(t: [u64;12]) -> vec384 { + let k = multiply_wrap(t[0], INV); + + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); + let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); + let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); + let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); + let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); + let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); + let r6_7: (u64, u64) = adc(t[6], 0, r5.1); + + let k = multiply_wrap(r1.0, INV); + let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); + let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); + let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); + let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); + + let k = multiply_wrap(r2.0, INV); + let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); + let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); + let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); + + let k = multiply_wrap(r3.0, INV); + let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); + let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); + let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); + + let k = multiply_wrap(r4.0, INV); + let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); + let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); + let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); + + let k = multiply_wrap(r5.0, INV); + let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); + let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); + let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); + let r11_12 = adc(t[11], r10_11.1, r10.1); + + subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) + +} + +// Naive multiplication implementation following zkcrypto. +// stand-in until we figure our how to make mul_mont_n work +pub fn mul_temp(a: Vec, b: Vec, p: Vec, n: u64) -> vec384 { + + let a0 = unpack_or_0(a.get(0)); + let a1 = unpack_or_0(a.get(1)); + let a2 = unpack_or_0(a.get(2)); + let a3 = unpack_or_0(a.get(3)); + let a4 = unpack_or_0(a.get(4)); + let a5 = unpack_or_0(a.get(5)); + + let b0 = unpack_or_0(b.get(0)); + let b1 = unpack_or_0(b.get(1)); + let b2 = unpack_or_0(b.get(2)); + let b3 = unpack_or_0(b.get(3)); + let b4 = unpack_or_0(b.get(4)); + let b5 = unpack_or_0(b.get(5)); + + let (t0, carry) = mac(0, a0, b0, 0); + let (t1, carry) = mac(0, a0, b1, carry); + let (t2, carry) = mac(0, a0, b2, carry); + let (t3, carry) = mac(0, a0, b3, carry); + let (t4, carry) = mac(0, a0, b4, carry); + let (t5, t6) = mac(0, a0, b5, carry); + + let (t1, carry) = mac(t1, a1, b0, 0); + let (t2, carry) = mac(t2, a1, b1, carry); + let (t3, carry) = mac(t3, a1, b2, carry); + let (t4, carry) = mac(t4, a1, b3, carry); + let (t5, carry) = mac(t5, a1, b4, carry); + let (t6, t7) = mac(t6, a1, b5, carry); + + let (t2, carry) = mac(t2, a2, b0, 0); + let (t3, carry) = mac(t3, a2, b1, carry); + let (t4, carry) = mac(t4, a2, b2, carry); + let (t5, carry) = mac(t5, a2, b3, carry); + let (t6, carry) = mac(t6, a2, b4, carry); + let (t7, t8) = mac(t7, a2, b5, carry); + + let (t3, carry) = mac(t3, a3, b0, 0); + let (t4, carry) = mac(t4, a3, b1, carry); + let (t5, carry) = mac(t5, a3, b2, carry); + let (t6, carry) = mac(t6, a3, b3, carry); + let (t7, carry) = mac(t7, a3, b4, carry); + let (t8, t9) = mac(t8, a3, b5, carry); + + let (t4, carry) = mac(t4, a4, b0, 0); + let (t5, carry) = mac(t5, a4, b1, carry); + let (t6, carry) = mac(t6, a4, b2, carry); + let (t7, carry) = mac(t7, a4, b3, carry); + let (t8, carry) = mac(t8, a4, b4, carry); + let (t9, t10) = mac(t9, a4, b5, carry); + + let (t5, carry) = mac(t5, a5, b0, 0); + let (t6, carry) = mac(t6, a5, b1, carry); + let (t7, carry) = mac(t7, a5, b2, carry); + let (t8, carry) = mac(t8, a5, b3, carry); + let (t9, carry) = mac(t9, a5, b4, carry); + let (t10, t11) = mac(t10, a5, b5, carry); + + let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + montgomery_reduction(res) +} + pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut limbx: u64 = 0; let mut borrow: u64 = 0; @@ -501,23 +626,12 @@ pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { //returns the result and new carry of a + b*c + carry pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { - let A: U128 = U128 { - upper: 0, - lower: a, - }; - let B: U128 = U128 { - upper: 0, - lower: b, - }; - let C: U128 = U128 { - upper: 0, - lower: c, - }; - let CARRY: U128 = U128 { - upper: 0, - lower: carry, - }; - let res: U128 = A + (B * C) + CARRY; + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let c_128: U128 = ~U128::from(0, c); + let carry_128: U128 = ~U128::from(0, carry); + + let res: U128 = a_128 + (b_128 * c_128) + carry_128; (res.lower, res.upper) } From f7f4d8b3e433ada81a23509a0184d9a5d1f58e8c Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 19 Jul 2022 20:42:48 -0600 Subject: [PATCH 062/160] Temporary montgomery multiplication from nccgroup. To test similar to them with the 'from' and 'to' montgomery form. --- bls12-381/src/main.sw | 5 +- bls12-381/src/tests/tests_temp_fe_mont_mul.sw | 73 ++++++++++++ bls12-381/src/vect.sw | 111 ++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 bls12-381/src/tests/tests_temp_fe_mont_mul.sw diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 8203d87..604d0fe 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -9,6 +9,7 @@ dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; dep tests/tests_small_functions; dep tests/tests_temp_mul; +dep tests/tests_temp_fe_mont_mul; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -22,16 +23,18 @@ use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; use ::tests_small_functions::tests_small_functions; use ::tests_temp_mul::tests_temp_mul; +use ::tests_temp_fe_mont_mul::tests_temp_fe_mont_mul; fn main() { // assert(fp_tests()); // assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); - assert(vect_subfunctions_tests()); + // assert(vect_subfunctions_tests()); // assert(tests_small_functions()); // assert(tests_temp_mul()); + assert(tests_temp_fe_mont_mul()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw new file mode 100644 index 0000000..cf68518 --- /dev/null +++ b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw @@ -0,0 +1,73 @@ +library tests_temp_fe_mont_mul; + +use ::vect::*; +use std::{assert::assert, vec::Vec}; +use ::test_helpers::*; + +pub fn tests_temp_fe_mont_mul() -> bool { + assert(test_temp_mul_random_by_random()); + true +} + +fn test_temp_mul_random_by_random() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); + + // a * b mod p + //941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 + //[16494539950903960225, 6909894500484332639, 10854278113294925999, 10279541547892741855, 12499445441687670930, 440910865060157199] + let a_mont = fe_to_mont(r1_vec); + let b_mont = fe_to_mont(r2_vec); + let res = temp_fe_mont_mul(a_mont, b_mont); + let res_norm = fe_to_norm(res); + print_vec(res_norm); +/* +current output... +18417799008695130381 +18138064264643904941 +8275434384499309183 +7900175912883409568 +10537467630215797999 +*/ + true +} + +/* +Note: from the reference impl, you can see it's being tested as follows: + + + let a_big = rnd_big_mod_n(); + let b_big = rnd_big_mod_n(); + fe_to_mont(&mut a_mont, &big_to_6u64(&a_big)); + fe_to_mont(&mut b_mont, &big_to_6u64(&b_big)); + + let expected = (&a_big * &b_big) % &(*N_BIG); + fe_mont_mul(&mut actual_mont, &a_mont, &b_mont); + + fe_to_norm(&mut actual_norm, &actual_mont); + assert_eq!(big_to_6u64(&expected), actual_norm); + +So there is a conversion to and from the mont form +*/ diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index eb1dbc9..91cf495 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -223,6 +223,117 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +fn zero_vec() -> Vec { + let mut temp: Vec = ~Vec::new::(); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp +} + +// Effectively a_mont = (a_norm * R) mod N +pub fn fe_to_mont(a: Vec) -> Vec { + let mut BLS12_381_RR: Vec = ~Vec::new::(); + BLS12_381_RR.push(0xf4df1f341c341746); + BLS12_381_RR.push(0x0a76e6a609d104f1); + BLS12_381_RR.push(0x8de5476c4c95b6d5); + BLS12_381_RR.push(0x67eb88a9939d83c0); + BLS12_381_RR.push(0x9a793e85b519952d); + BLS12_381_RR.push(0x11988fe592cae3aa); + temp_fe_mont_mul(a, BLS12_381_RR) +} + +// Effectively a_norm = (a_mont * R^{-1}) mod N +pub fn fe_to_norm(a: Vec) -> Vec { + let mut ONE: Vec = ~Vec::new::(); + ONE.push(0x1); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + temp_fe_mont_mul(a, ONE) +} + +// temporary mont mult impl from https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ +// with repo https://github.com/nccgroup/pairing +pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { + let mut temp: Vec = zero_vec(); + let mut i = 0; + let mut j = 0; + let mut carry = 0u64; + while i < 6 { + carry = 0; + while j < 6 { + let aj: U128 = ~U128::from(0, unpack_or_0(a.get(j))); + let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); + let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); + let carry_128 = ~U128::from(0, carry); + let hilo: U128 = aj + bi + temp_ij + carry_128; + temp.remove(i+j); + temp.insert(i+j, hilo.lower); + carry = hilo.upper; + j += 1; + } + let mut t = unpack_or_0(temp.get(i+6)); + temp.remove(i+6); + temp.insert(i+6, t+carry); + + let m: u64 = multiply_wrap(unpack_or_0(temp.get(i)), P0); + let m_128 = ~U128::from(0, m); + + carry = 0; + j = 0; + while j < 6 { + let nj: U128 = ~U128::from(0, BLS12_381_P.ls[j]); + let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); + let carry_128 = ~U128::from(0, carry); + let hilo: U128 = m_128 + nj + temp_ij + carry_128; + temp.remove(i+j); + temp.insert(i+j, hilo.lower); + carry = hilo.upper; + j += 1; + } + t = unpack_or_0(temp.get(i+6)); + temp.remove(i+6); + temp.insert(i+6, t+carry); + i += 1; + } + + let mut dec: Vec = zero_vec(); + let mut borrow = 0u64; + j = 0; + while j < 6 { + let (diff, borrow_t0) = sbb(unpack_or_0(temp.get(j + 6)), BLS12_381_P.ls[j], borrow); + dec.insert(j, diff); + borrow = borrow_t0; + j += 1; + } + + let mask: u64 = if borrow == 1 { + ~u64::max() - 1 + } else { + 0 + }; + let mut result: Vec = zero_vec(); + j = 0; + while j < 6 { + let entry = (unpack_or_0(temp.get(j+6)) & mask) | (not(mask) & unpack_or_0(dec.get(j))); + result.insert(j, entry); + j += 1; + } + result +} + // from https://github.com/zkcrypto/bls12_381 pub fn montgomery_reduction(t: [u64;12]) -> vec384 { let k = multiply_wrap(t[0], INV); From beeb298e4506d272de5376b753ec4d27ff0224df Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 20 Jul 2022 14:53:08 -0600 Subject: [PATCH 063/160] temp_fe_mont_mul works and added comments to test. --- bls12-381/src/tests/tests_temp_fe_mont_mul.sw | 66 +++++++++++++++---- bls12-381/src/vect.sw | 8 +-- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw index cf68518..f7de638 100644 --- a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw @@ -3,6 +3,7 @@ library tests_temp_fe_mont_mul; use ::vect::*; use std::{assert::assert, vec::Vec}; use ::test_helpers::*; +use std::logging::log; pub fn tests_temp_fe_mont_mul() -> bool { assert(test_temp_mul_random_by_random()); @@ -35,21 +36,64 @@ fn test_temp_mul_random_by_random() -> bool { r2_vec.push(2211903887497377980); r2_vec.push(395875676649998273); - // a * b mod p - //941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 - //[16494539950903960225, 6909894500484332639, 10854278113294925999, 10279541547892741855, 12499445441687670930, 440910865060157199] let a_mont = fe_to_mont(r1_vec); + // print_vec(a_mont); + /* +17993655965713306301 +15604842006860479165 +10837926002905938402 +13429498400065700031 +1823694494885156540 +933350646299434799 + */ + let b_mont = fe_to_mont(r2_vec); + // print_vec(b_mont); + /* +5720430457560562798 +2568557665684583703 +15870134958983808442 +14065062413899436375 +12262047246709729804 +1303068506660090079 + */ + let res = temp_fe_mont_mul(a_mont, b_mont); - let res_norm = fe_to_norm(res); - print_vec(res_norm); + print_vec(res); + /* +8042921339150017446 +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 + */ + + /* + This is what res has as a value at this point, but running all the operations gives the error + out of gas, so just run with this known value. All intermediate steps are correct with + the ncc ref implementation + */ + let mut intermediate_res_vec = ~Vec::new::(); + intermediate_res_vec.push(8042921339150017446); + intermediate_res_vec.push(4899742317194411181); + intermediate_res_vec.push(11922910400151252689); + intermediate_res_vec.push(7736564210120511729); + intermediate_res_vec.push(10892349319971706476); + intermediate_res_vec.push(542573957820843489); + // let res_norm = fe_to_norm(res); + // let res_norm = fe_to_norm(intermediate_res_vec); + // print_vec(res_norm); /* -current output... -18417799008695130381 -18138064264643904941 -8275434384499309183 -7900175912883409568 -10537467630215797999 +16494539950903960225 + +6909894500484332639 * 2^64 + +10854278113294925999 * 2^128 + +10279541547892741855 * 2^192 + +12499445441687670930 * 2^256 + +440910865060157199 *2^320 + +941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 +which is a*b mod p */ true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 91cf495..c28a2ee 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -24,7 +24,6 @@ pub struct vec384x { } - //TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0] @@ -273,12 +272,13 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let mut carry = 0u64; while i < 6 { carry = 0; + j = 0; while j < 6 { let aj: U128 = ~U128::from(0, unpack_or_0(a.get(j))); let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); let carry_128 = ~U128::from(0, carry); - let hilo: U128 = aj + bi + temp_ij + carry_128; + let hilo: U128 = aj * bi + temp_ij + carry_128; temp.remove(i+j); temp.insert(i+j, hilo.lower); carry = hilo.upper; @@ -297,7 +297,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let nj: U128 = ~U128::from(0, BLS12_381_P.ls[j]); let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); let carry_128 = ~U128::from(0, carry); - let hilo: U128 = m_128 + nj + temp_ij + carry_128; + let hilo: U128 = m_128 * nj + temp_ij + carry_128; temp.remove(i+j); temp.insert(i+j, hilo.lower); carry = hilo.upper; @@ -320,7 +320,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { } let mask: u64 = if borrow == 1 { - ~u64::max() - 1 + ~u64::max() } else { 0 }; From e999d8c72ea232a0fd5ff489b3a9e20b7020d26a Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 20 Jul 2022 18:05:13 -0600 Subject: [PATCH 064/160] Trying to use temp_fe_mont_mul and the conversions as a temporary replacement for temp_mul_mont_n, but the test runs out of gas. --- bls12-381/src/tests/tests_temp_fe_mont_mul.sw | 66 ++++++++- .../src/tests/tests_vect_subfunctions.sw | 137 ++++++++++++++---- bls12-381/src/vect.sw | 120 ++++++++++----- 3 files changed, 248 insertions(+), 75 deletions(-) diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw index f7de638..62b47bf 100644 --- a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw @@ -6,7 +6,61 @@ use ::test_helpers::*; use std::logging::log; pub fn tests_temp_fe_mont_mul() -> bool { - assert(test_temp_mul_random_by_random()); + // assert(test_temp_mul_random_by_random()); + assert(test_temp_mul_mont_n()); + true +} + +fn test_temp_mul_mont_n() -> bool { + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); + + //Sway can't handle this. Error: + /* + { + "Panic": { + "id": "0000000000000000000000000000000000000000000000000000000000000000", + "is": 10352, + "pc": 169804, + "reason": { + "instruction": { + "imm06": 0, + "imm12": 0, + "imm18": 0, + "imm24": 0, + "op": 96, + "ra": 0, + "rb": 0, + "rc": 0, + "rd": 0 + }, + "reason": "OutOfGas" + } + } + }, + { + "ScriptResult": { + "gas_used": 100000000, + "result": "Panic" + } + } + */ + let res = temp_mul_mont_n(r1_vec, r2_vec); + print_vec(res); true } @@ -36,7 +90,7 @@ fn test_temp_mul_random_by_random() -> bool { r2_vec.push(2211903887497377980); r2_vec.push(395875676649998273); - let a_mont = fe_to_mont(r1_vec); + // let a_mont = fe_to_mont(r1_vec); // print_vec(a_mont); /* 17993655965713306301 @@ -47,7 +101,7 @@ fn test_temp_mul_random_by_random() -> bool { 933350646299434799 */ - let b_mont = fe_to_mont(r2_vec); + // let b_mont = fe_to_mont(r2_vec); // print_vec(b_mont); /* 5720430457560562798 @@ -58,8 +112,8 @@ fn test_temp_mul_random_by_random() -> bool { 1303068506660090079 */ - let res = temp_fe_mont_mul(a_mont, b_mont); - print_vec(res); + // let res = temp_fe_mont_mul(a_mont, b_mont); + // print_vec(res); /* 8042921339150017446 4899742317194411181 @@ -82,7 +136,7 @@ fn test_temp_mul_random_by_random() -> bool { intermediate_res_vec.push(10892349319971706476); intermediate_res_vec.push(542573957820843489); // let res_norm = fe_to_norm(res); - // let res_norm = fe_to_norm(intermediate_res_vec); + let res_norm = fe_to_norm(intermediate_res_vec); // print_vec(res_norm); /* 16494539950903960225 + diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 901b352..ac19eb1 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -22,6 +22,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_one_by_one()); // assert(test_mul_mont_n_random_by_one()); // assert(test_mul_mont_n_random_by_random()); + assert(test_mont_mul_partial()); // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added // assert(test_sub_zero_from_zero_subn()); @@ -31,7 +32,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_2_randoms_subn()); // assert(test_sub_2_randoms_reverse_subn()); - assert(tests_redc_mont()); + // assert(tests_redc_mont()); true } @@ -98,17 +99,26 @@ fn test_mul_mont_n_random_by_one() -> bool { let(_, p_vec) = get_test_vectors(); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r_vec = ~Vec::new::(); - r_vec.push(0x54439c4ae7869f30); - r_vec.push(0xa7fdefad55c032ba); - r_vec.push(0x21282f739c0a15e7); - r_vec.push(0x6cc7a6e8c38430ff); - r_vec.push(0x50db69783b321139); - r_vec.push(0xba78745dadd17a93); + r_vec.push(0x54439c4ae7869f30); //6071868568151433008 + r_vec.push(0xa7fdefad55c032ba); //12105094901188801210 + r_vec.push(0x21282f739c0a15e7); //2389211775905699303 + r_vec.push(0x6cc7a6e8c38430ff); //7838417195104481535 + r_vec.push(0x50db69783b321139); //5826366508043997497 + r_vec.push(0xba78745dadd17a93); //13436617433956842131 let one_vec = get_one_vec(); let res = mul_mont_n(r_vec, one_vec, p_vec, P0, 6); - print_vec(res); - equals_vec(res, r_vec, 6); + // print_vec(res); + /* + + */ + // let b = equals_vec(res, r_vec, 6); + // log(b); + let mut i = 0; + while i < 6 { + assert(unpack_or_0(res.get(i)) == unpack_or_0(r_vec.get(i))); + i += 1; + } true } @@ -116,31 +126,100 @@ fn test_mul_mont_n_random_by_random() -> bool { let(_, p_vec) = get_test_vectors(); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); - r1_vec.push(0x54439c4ae7869f30); - r1_vec.push(0xa7fdefad55c032ba); - r1_vec.push(0x21282f739c0a15e7); - r1_vec.push(0x6cc7a6e8c38430ff); - r1_vec.push(0x50db69783b321139); - r1_vec.push(0xba78745dadd17a93); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 let mut r2_vec = ~Vec::new::(); - r2_vec.push(0xeb6f61c69e4c7eef); - r2_vec.push(0xa70784fb3f9ac549); - r2_vec.push(0x91f41a633e1d9601); - r2_vec.push(0xf89a44e9a52e99e); - r2_vec.push(0x1eb242ddd39638bc); - r2_vec.push(0x57e6ed499f0c7c1); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + //[4793585148327242455, 2837967030551533581, 1626660158106644623, + //15384342728939744618, 1826521055323312182, 528164867630647501] + + // mult by p0 + //241244430210532575562827373868655963084727802841779217074318408842127082994632785925923353131362216879147315212775676243090892648326992525470904388378004276874316175983655739522130737118499414971959740231422333803704862166384557102941841719958128272 + // mod p + //1233002344306172478209354248697859329250780126726480993298462574958424022710616415994206080732967265541051783400711 +//[1734233419737550087, 7827676449723675145, 5835727259298429301, 3992373620040751347, 13994230039556723943, 577251792061825638] let mut res_vec = ~Vec::new::(); - res_vec.push(0x42863c4b7ea22ad7); - res_vec.push(0x27627bfa644b580d); - res_vec.push(0x16930ecb9e3a308f); - res_vec.push(0xd5802a33c5512d6a); - res_vec.push(0x19591b38f5515036); - res_vec.push(0x7546b2615f748cd); - let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); - equals_vec(res, res_vec, 6); + res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 + res_vec.push(0x27627bfa644b580d);//2837967030551533581 + res_vec.push(0x16930ecb9e3a308f);//1626660158106644623 + res_vec.push(0xd5802a33c5512d6a);//15384342728939744618 + res_vec.push(0x19591b38f5515036);//1826521055323312182 + res_vec.push(0x7546b2615f748cd);//528164867630647501 + let res = mul_mont_n(r1_vec, r2_vec, p_vec, P0, 6); + print_vec(res); + /* +10466566815393401694 +14579313370948138685 +11816151785009594293 +7246864926219872143 +15908820384664990112 +328568623818015453 + +blst impl +3517150968681791168 +13347192682519393737 +4541454005160136609 +16590274403525876995 +17086414653262144931 +16572945458942657492 + */ + // equals_vec(res, res_vec, 6); + + true +} + +fn test_mont_mul_partial() -> bool { + let(_, p_vec) = get_test_vectors(); + + let mut intermediate_res_vec = ~Vec::new::(); + intermediate_res_vec.push(8042921339150017446); + intermediate_res_vec.push(4899742317194411181); + intermediate_res_vec.push(11922910400151252689); + intermediate_res_vec.push(7736564210120511729); + intermediate_res_vec.push(10892349319971706476); + intermediate_res_vec.push(542573957820843489); + + let mut ONE: Vec = ~Vec::new::(); + ONE.push(0x1); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + + let res = mul_mont_n(intermediate_res_vec, ONE, p_vec, P0, 6); + print_vec(res); + +/* +Should be +16494539950903960225 +6909894500484332639 +10854278113294925999 +10279541547892741855 +12499445441687670930 +440910865060157199 + +//Current output is: +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 +0 +This is almost the input vector... +*/ true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index c28a2ee..cafaa6a 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -92,9 +92,10 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, 0); let mut tmp: Vec = ~Vec::new::(); - let mut tmp2: Vec = ~Vec::new::();//new vector - let mut tmp3: Vec = ~Vec::new::();//new vector + let mut tmp2: Vec = ~Vec::new::(); + let mut tmp3: Vec = ~Vec::new::(); let mut i = 0; + while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let limbx = mx * ai + hi; @@ -102,44 +103,33 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec hi = ~U128::from(0, limbx.upper); i += 1; } + tmp.insert(i, hi.lower); -//0x89f3fffcfffcfffd * 1 let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0)))).lower; let mut mx: U128 = ~U128::from(0, mx_temp); - //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); - tmp.insert(i, hi.lower); let mut carry: u64 = 0; let mut j = 0; let mut limbx: U128 = ~U128::from(0, 0); while true { let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); - //log(mx);//000000000000000089f3fffcfffcfffd - //2: 3947442df695f8f1286adb92d9d113e8 - //log(p0);//0000000000000000b9feffffffffaaab - //2: 0000000000000000b9feffffffffaaab - //log(tmp0);//00000000000000000000000000000001 - //2: 00000000000000006a4aaa14be07a408 - //1: 16^^643abe09d200a404ffffffffffffffff - //2: 16^^299d8e4220faed31901f94fb2b3b54280000000000000000 - //this is 190 bits instead of fitting into 128 limbx = (mx * p0) + tmp0; - //log(limbx);//643abe09d200a4050000000000000000 - //2: f21393888e24ec0f0000000000000000 hi = ~U128::from(0, limbx.upper); - //log(hi);//0000000000000000643abe09d200a405 - //2: 0000000000000000f21393888e24ec0f i = 1; + + //just to be sure copying this over + let mut k = 0; + while k < 12 { + tmp2.push(unpack_or_0(tmp.get(k))); + k += 1; + } + while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - //log(pi);//00000000000000001eabfffeb153ffff - //log(tmpi);//00000000000000000000000000000000 limbx = (mx * pi + hi) + tmpi; - //log(limbx);//108747eeefa29c0f6a4aaa14be07a408 tmp2.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); - //log(hi);//0000000000000000108747eeefa29c0f i += 1; } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); @@ -152,34 +142,29 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } mx = ~U128::from(0, unpack_or_0(b.get(j))); hi = ~U128::from(0, 0); - //log(mx);//00000000000000006730d2a0f6b0f624 - //log(hi);//00000000000000000000000000000000 i = 0; + + //just to be sure copying this over + k = 0; + while k < 12 { + tmp3.push(unpack_or_0(tmp2.get(k))); + k += 1; + } + while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); - //log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 - //log(tmpi);//0000000000000000379b7b3fafdc26ed limbx = (mx * ai + hi) + tmpi; - //log(limbx);//000000000000000064774b84f38512bf tmp3.insert(i, limbx.lower); hi = ~U128::from(0, limbx.upper); - //log(hi);//00000000000000000000000000000000 i += 1; } let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp3.get(0)))).lower; let mut mx: U128 = ~U128::from(0, mx_temp); - //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); - //log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) limbx = hi + ~U128::from(0, carry); - //log(limbx);//00000000000000003623991cf3a341e8 tmp3.insert(i, limbx.lower); - //log(tmp);//00000000000000004b1ba7b6434bacd7 carry = limbx.upper; - //log(carry);//00000000000000000000000000000000 - - //Conclusion so far: mx will become really large and then overflow in next iteration } let mut borrow: u64 = 0; @@ -201,17 +186,38 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec borrow = b_res & 0x1; i += 1; } - //log(carry); - //log(borrow); + + /*ret: +9944055374826099202 +9712768888634044113 +300889636556430029 +3653011359556993965 +13577214253059692810 +16572945456062011749 +0..0 + */ + + /*tmp3: +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 +0 +0 +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 + */ + let mask: u64 = if carry >= borrow { carry-borrow } else { ~u64::max() - (borrow - carry - 1) }; -// mask = carry - borrow; - // let mask: u64 = borrow * ~u64::max(); - i = 0; let mut res: Vec = ~Vec::new::(); while i < n { @@ -239,6 +245,19 @@ fn zero_vec() -> Vec { temp } +/* +The mul_mont_n is not working yet, so this would be a temporary solution but using montgomery mult. +*/ +pub fn temp_mul_mont_n(a: Vec, b: Vec) -> Vec { + // To mont form + let a_mont = fe_to_mont(a); + let b_mont = fe_to_mont(b); + // Mult + let res = temp_fe_mont_mul(a_mont, b_mont); + // Transform back + fe_to_norm(res) +} + // Effectively a_mont = (a_norm * R) mod N pub fn fe_to_mont(a: Vec) -> Vec { let mut BLS12_381_RR: Vec = ~Vec::new::(); @@ -319,6 +338,27 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { j += 1; } + + /*temp: +0..0 +16494539950903960225 +6909894500484332639 +10854278113294925999 +10279541547892741855 +12499445441687670930 +440910865060157199 + */ + + /*dec: +3092108934826096630 +4699752988967124064 +3418603539730844299 +3040203587478029344 +7087341663216968635 +17013856321122168949 +0..0 + */ + let mask: u64 = if borrow == 1 { ~u64::max() } else { From 1216bca3fa9ad75777b7aeb2cffa092c787ac6b4 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 12:51:06 -0600 Subject: [PATCH 065/160] Multiply and square tests through contracts. First steps. --- edwards25519/Forc.toml | 2 +- test_contract/src/main.sw | 14 +- test_contract/tests/harness.rs | 74 +------- test_contract/tests/multiply/mod.rs | 275 ++++++++++++++++++++++++++++ test_contract/tests/square/mod.rs | 54 ++++++ 5 files changed, 341 insertions(+), 78 deletions(-) create mode 100644 test_contract/tests/multiply/mod.rs create mode 100644 test_contract/tests/square/mod.rs diff --git a/edwards25519/Forc.toml b/edwards25519/Forc.toml index 14b5b02..25dabbc 100644 --- a/edwards25519/Forc.toml +++ b/edwards25519/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["HashCloak"] -entry = "main.sw" +entry = "field_element.sw" license = "Apache-2.0" name = "edwards25519" diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 357855e..563fc6b 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -9,17 +9,21 @@ use std::u128::*; use ::test_helpers::*; abi EdContract { - #[storage()]fn equals_test(a: Element, b: Element) -> bool; - #[storage()]fn multiply_test(a: Element, b: Element) -> Element; - + #[storage()]fn equals(a: Element, b: Element) -> bool; + #[storage()]fn multiply(a: Element, b: Element) -> Element; + #[storage()]fn square(a: Element) -> Element; } impl EdContract for Contract { - #[storage()]fn equals_test(a: Element, b: Element) -> bool { + #[storage()]fn equals(a: Element, b: Element) -> bool { equals(a, b) } - #[storage()]fn multiply_test(a: Element, b: Element) -> Element { + #[storage()]fn multiply(a: Element, b: Element) -> Element { multiply(a, b) } + + #[storage()]fn square(a: Element) -> Element { + square(a) + } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index 41c7db6..f60f4c2 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -1,72 +1,2 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -// Load abi from json -abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); - -async fn get_contract_instance() -> (EdContract, ContractId) { - let mut wallets = - launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; - let wallet = wallets.pop().unwrap(); - - let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - - let instance = EdContract::new(id.to_string(), wallet); - - (instance, id) -} - -const zero: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; - -pub fn res_equals(res: Element, should_be: Element) -> bool { - assert!(res.l_0 == should_be.l_0); - assert!(res.l_1 == should_be.l_1); - assert!(res.l_2 == should_be.l_2); - assert!(res.l_3 == should_be.l_3); - assert!(res.l_4 == should_be.l_4); - true -} - -#[tokio::test] -async fn test_equals() { - let a = Element{ - l_0: 2251799813685247, - l_1: 5, - l_2: 2251799813685247, - l_3: 2251799813685247, - l_4: 100 - }; - let b = Element{ - l_0: 2251799813685247, - l_1: 5, - l_2: 2251799813685247, - l_3: 2251799813685247, - l_4: 100 - }; - - let (_instance, _id) = get_contract_instance().await; - - let a_b_equal = _instance.equals_test(a, b).call().await.unwrap().value; - assert!(a_b_equal); -} - -#[tokio::test] -async fn test_multiply_by_0() { - let (_instance, _id) = get_contract_instance().await; - - //a = 2^255 - 21 - let a = Element{ - l_0: 2251799813685227, - l_1: 2251799813685247, - l_2: 2251799813685247, - l_3: 2251799813685247, - l_4: 2251799813685247 - }; - let res = _instance.multiply_test(a, zero) - .tx_params(TxParameters::new(None, Some(100000), None, None)) - .call().await.unwrap().value; - - assert!(res_equals(res, zero)); -} \ No newline at end of file +mod square; +mod multiply; \ No newline at end of file diff --git a/test_contract/tests/multiply/mod.rs b/test_contract/tests/multiply/mod.rs new file mode 100644 index 0000000..97237b8 --- /dev/null +++ b/test_contract/tests/multiply/mod.rs @@ -0,0 +1,275 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = + launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let wallet = wallets.pop().unwrap(); + + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = EdContract::new(id.to_string(), wallet); + + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_equals() { + let a = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + let b = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + + let (_instance, _id) = get_contract_instance().await; + + let a_b_equal = _instance.equals(a, b).call().await.unwrap().value; + assert!(a_b_equal); +} + +#[tokio::test] +async fn test_multiply_by_0() { + let (_instance, _id) = get_contract_instance().await; + + //a = 2^255 - 21 + let a = Element{ + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let res = _instance.multiply(a, ZERO) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, ZERO)); +} + +#[tokio::test] +async fn test_multiply_1_by_1() { + let (_instance, _id) = get_contract_instance().await; + + //a = 2^255 - 21 + let a = Element{ + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let res = _instance.multiply(ONE, ONE) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, ONE)); +} + +#[tokio::test] +async fn test_multiply_by_1_small() { + let (_instance, _id) = get_contract_instance().await; + + let a = Element{ + l_0: 10, + l_1: 11, + l_2: 12, + l_3: 13, + l_4: 14 + }; + let res = _instance.multiply(a, ONE) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let expected_res = Element { + l_0: 10, + l_1: 11, + l_2: 12, + l_3: 13, + l_4: 14 + }; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_multiply_by_1_large() { + let (_instance, _id) = get_contract_instance().await; + let a = Element{ + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let res = _instance.multiply(a, ONE) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let expected_res = Element { + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_multiply_small_elms() { + let (_instance, _id) = get_contract_instance().await; + let a = Element{ + l_0: 10, + l_1: 11, + l_2: 12, + l_3: 13, + l_4: 14 + }; + let b = Element{ + l_0: 2, + l_1: 3, + l_2: 4, + l_3: 5, + l_4: 6 + }; + let res = _instance.multiply(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let expected_res = Element{ + l_0: 4200, + l_1: 3719, + l_2: 2909, + l_3: 1752, + l_4: 230 + }; + assert!(res_equals(res, expected_res)); +} + + +#[tokio::test] +async fn test_multiply_small_elms_2() { + let (_instance, _id) = get_contract_instance().await; + let a = Element{ + l_0: 10, + l_1: 11, + l_2: 12, + l_3: 1292655137982008, + l_4: 14 + }; + let b = Element{ + l_0: 2, + l_1: 3, + l_2: 4, + l_3: 5, + l_4: 6 + }; + let res = _instance.multiply(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let expected_res = Element{ + l_0: 1414398498170175, + l_1: 1205048169289895, + l_2: 995697840409273, + l_3: 333510462280559, + l_4: 1626165600260968 + }; + assert!(res_equals(res, expected_res)); +} + + +#[tokio::test] +async fn test_multiply_small_elms_3() { + let (_instance, _id) = get_contract_instance().await; + let a = Element{ + l_0: 1292655137982008, + l_1: 1303372017735434, + l_2: 595911506101250, + l_3: 601879629470779, + l_4: 50591579140481 + }; + let b = Element{ + l_0: 2, + l_1: 3, + l_2: 4, + l_3: 5, + l_4: 6 + }; + let res = _instance.multiply(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let expected_res = Element{ + l_0: 1954506281775991, + l_1: 334157138245186, + l_2: 376444288997219, + l_3: 169499236944723, + l_4: 548860478185542 + }; + assert!(res_equals(res, expected_res)); +} + + +#[tokio::test] +async fn test_multiply_elms_4() { + let (_instance, _id) = get_contract_instance().await; + let a = Element{ + l_0: 1292655137982008, + l_1: 1303372017735434, + l_2: 595911506101250, + l_3: 601879629470779, + l_4: 50591579140481 + }; + let b = Element{ + l_0: 1360902863141127, + l_1: 807899991388824, + l_2: 335483569739384, + l_3: 293961277766182, + l_4: 137209507300112 + }; + let res = _instance.multiply(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + let expected_res = Element{ + l_0: 896638975913114, + l_1: 1000789340506524, + l_2: 355992668009873, + l_3: 806477788321681, + l_4: 1027544741541094 + }; + assert!(res_equals(res, expected_res)); +} diff --git a/test_contract/tests/square/mod.rs b/test_contract/tests/square/mod.rs new file mode 100644 index 0000000..9a53d2e --- /dev/null +++ b/test_contract/tests/square/mod.rs @@ -0,0 +1,54 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +// Load abi from json +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = + launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let wallet = wallets.pop().unwrap(); + + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) + .await + .unwrap(); + + let instance = EdContract::new(id.to_string(), wallet); + + (instance, id) +} + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_square1() { + let a = Element{ + l_0: 1292655137982008, + l_1: 1303372017735434, + l_2: 595911506101250, + l_3: 312158315551803, + l_4: 404732633123850 + }; + let a_square = Element{ + l_0: 2144628324130663, + l_1: 596790797966485, + l_2: 912635275234964, + l_3: 713663780369466, + l_4: 1207365348681671 + }; + + let (_instance, _id) = get_contract_instance().await; + + let squared_res = _instance.square(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(squared_res, a_square)); +} \ No newline at end of file From cc7acbf201a887869e0533415f9b5b9295d501f2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 13:09:33 -0600 Subject: [PATCH 066/160] Moved subtraction tests --- test_contract/src/main.sw | 5 + test_contract/tests/harness.rs | 3 +- test_contract/tests/multiply/mod.rs | 11 +- test_contract/tests/square/mod.rs | 11 +- test_contract/tests/subtract/mod.rs | 175 ++++++++++++++++++++++++++++ 5 files changed, 186 insertions(+), 19 deletions(-) create mode 100644 test_contract/tests/subtract/mod.rs diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 563fc6b..7ff5dfe 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -12,6 +12,7 @@ abi EdContract { #[storage()]fn equals(a: Element, b: Element) -> bool; #[storage()]fn multiply(a: Element, b: Element) -> Element; #[storage()]fn square(a: Element) -> Element; + #[storage()]fn subtract(a: Element, b: Element) -> Element; } impl EdContract for Contract { @@ -26,4 +27,8 @@ impl EdContract for Contract { #[storage()]fn square(a: Element) -> Element { square(a) } + + #[storage()]fn subtract(a: Element, b: Element) -> Element { + subtract(a, b) + } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index f60f4c2..76041bf 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -1,2 +1,3 @@ mod square; -mod multiply; \ No newline at end of file +mod multiply; +mod subtract; \ No newline at end of file diff --git a/test_contract/tests/multiply/mod.rs b/test_contract/tests/multiply/mod.rs index 97237b8..f392acb 100644 --- a/test_contract/tests/multiply/mod.rs +++ b/test_contract/tests/multiply/mod.rs @@ -1,20 +1,13 @@ use fuels::{prelude::*, tx::ContractId}; use fuels_abigen_macro::abigen; -// Load abi from json abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); async fn get_contract_instance() -> (EdContract, ContractId) { - let mut wallets = - launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; let wallet = wallets.pop().unwrap(); - - let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); let instance = EdContract::new(id.to_string(), wallet); - (instance, id) } diff --git a/test_contract/tests/square/mod.rs b/test_contract/tests/square/mod.rs index 9a53d2e..777db9c 100644 --- a/test_contract/tests/square/mod.rs +++ b/test_contract/tests/square/mod.rs @@ -1,20 +1,13 @@ use fuels::{prelude::*, tx::ContractId}; use fuels_abigen_macro::abigen; -// Load abi from json abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); async fn get_contract_instance() -> (EdContract, ContractId) { - let mut wallets = - launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; let wallet = wallets.pop().unwrap(); - - let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()) - .await - .unwrap(); - + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); let instance = EdContract::new(id.to_string(), wallet); - (instance, id) } diff --git a/test_contract/tests/subtract/mod.rs b/test_contract/tests/subtract/mod.rs new file mode 100644 index 0000000..8e877e8 --- /dev/null +++ b/test_contract/tests/subtract/mod.rs @@ -0,0 +1,175 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_subtraction_by_0() { + let a = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + let expected_res = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + + let (_instance, _id) = get_contract_instance().await; + + let subtract_res = _instance.subtract(a, ZERO) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(subtract_res, expected_res)); +} + +#[tokio::test] +async fn test_subtraction_by_1() { + let a = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + let expected_res = Element{ + l_0: 2251799813685246, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + + let (_instance, _id) = get_contract_instance().await; + + let subtract_res = _instance.subtract(a, ONE) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(subtract_res, expected_res)); +} + +#[tokio::test] +async fn test_subtraction_by_max() { + let a = Element{ + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let b = Element{ + l_0: 2251799813685228, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let expected_res = Element{ + l_0: 2251799813685228, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let (_instance, _id) = get_contract_instance().await; + + let subtract_res = _instance.subtract(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(subtract_res, expected_res)); +} + +#[tokio::test] +async fn test_subtraction_random() { + let a = Element{ + l_0: 1292655137982008, + l_1: 1303372017735434, + l_2: 595911506101250, + l_3: 601879629470779, + l_4: 50591579140481 + }; + let b = Element{ + l_0: 1360902863141127, + l_1: 807899991388824, + l_2: 335483569739384, + l_3: 293961277766182, + l_4: 137209507300112 + }; + let expected_res = Element{ + l_0: 2183552088526110, + l_1: 495472026346609, + l_2: 260427936361866, + l_3: 307918351704597, + l_4: 2165181885525617 + }; + let (_instance, _id) = get_contract_instance().await; + + let subtract_res = _instance.subtract(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(subtract_res, expected_res)); +} + +#[tokio::test] +async fn test_subtraction_random2() { + let a = Element{ + l_0: 1292655137982008, + l_1: 1303372017735434, + l_2: 595911506101250, + l_3: 601879629470779, + l_4: 50591579140481 + }; + let b = Element{ + l_0: 1360902863141127, + l_1: 807899991388824, + l_2: 335483569739384, + l_3: 293961277766182, + l_4: 137209507300112 + }; + let expected_res = Element{ + l_0: 68247725159119, + l_1: 1756327787338638, + l_2: 1991371877323381, + l_3: 1943881461980650, + l_4: 86617928159630 + }; + let (_instance, _id) = get_contract_instance().await; + + let subtract_res = _instance.subtract(b, a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(subtract_res, expected_res)); +} \ No newline at end of file From 52bd8962da77ea8a95107bd37cf09b15d4a72aaa Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 14:08:19 -0600 Subject: [PATCH 067/160] Moved addition tests --- test_contract/src/main.sw | 6 ++ test_contract/tests/add/mod.rs | 142 ++++++++++++++++++++++++++++ test_contract/tests/harness.rs | 3 +- test_contract/tests/multiply/mod.rs | 2 +- 4 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 test_contract/tests/add/mod.rs diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 7ff5dfe..ff95ddf 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -13,6 +13,8 @@ abi EdContract { #[storage()]fn multiply(a: Element, b: Element) -> Element; #[storage()]fn square(a: Element) -> Element; #[storage()]fn subtract(a: Element, b: Element) -> Element; + #[storage()]fn add(a: Element, b: Element) -> Element; + } impl EdContract for Contract { @@ -31,4 +33,8 @@ impl EdContract for Contract { #[storage()]fn subtract(a: Element, b: Element) -> Element { subtract(a, b) } + + #[storage()]fn add(a: Element, b: Element) -> Element { + add(a, b) + } } \ No newline at end of file diff --git a/test_contract/tests/add/mod.rs b/test_contract/tests/add/mod.rs new file mode 100644 index 0000000..ca33b7f --- /dev/null +++ b/test_contract/tests/add/mod.rs @@ -0,0 +1,142 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_add_to_0() { + let a = Element{ + l_0: 8191, + l_1: 225179, + l_2: 155647, + l_3: 81918191, + l_4: 85247 + }; + let expected_res = Element{ + l_0: 8191, + l_1: 225179, + l_2: 155647, + l_3: 81918191, + l_4: 85247 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add(ZERO, a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_add_0() { + let a = Element{ + l_0: 8191, + l_1: 225179, + l_2: 155647, + l_3: 81918191, + l_4: 85247 + }; + let expected_res = Element{ + l_0: 8191, + l_1: 225179, + l_2: 155647, + l_3: 81918191, + l_4: 85247 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add(a, ZERO) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_add_a_to_b() { + let a = Element{ + l_0: 2251799813685247, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let b = Element{ + l_0: 8191, + l_1: 225179, + l_2: 155647, + l_3: 81918191, + l_4: 85247 + }; + let expected_res = Element{ + l_0: 8209, + l_1: 225179, + l_2: 155647, + l_3: 81918191, + l_4: 85247 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_add_a_to_a() { + let a = Element{ + l_0: 2251799813685228, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let a_again = Element{ + l_0: 2251799813685228, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + let expected_res = Element{ + l_0: 2251799813685227, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 2251799813685247 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add(a, a_again) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index 76041bf..0fa2f6a 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -1,3 +1,4 @@ mod square; mod multiply; -mod subtract; \ No newline at end of file +mod subtract; +mod add; \ No newline at end of file diff --git a/test_contract/tests/multiply/mod.rs b/test_contract/tests/multiply/mod.rs index f392acb..5e2f16e 100644 --- a/test_contract/tests/multiply/mod.rs +++ b/test_contract/tests/multiply/mod.rs @@ -4,7 +4,7 @@ use fuels_abigen_macro::abigen; abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); async fn get_contract_instance() -> (EdContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1000000))).await; + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; let wallet = wallets.pop().unwrap(); let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); let instance = EdContract::new(id.to_string(), wallet); From 4b35e1ec1ad855a3bf02ff86026bcc3d40bb3356 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 14:24:18 -0600 Subject: [PATCH 068/160] Converted reduction tests --- test_contract/src/main.sw | 10 ++ test_contract/tests/harness.rs | 3 +- test_contract/tests/reductions/mod.rs | 182 ++++++++++++++++++++++++++ 3 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 test_contract/tests/reductions/mod.rs diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index ff95ddf..7848217 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -14,6 +14,8 @@ abi EdContract { #[storage()]fn square(a: Element) -> Element; #[storage()]fn subtract(a: Element, b: Element) -> Element; #[storage()]fn add(a: Element, b: Element) -> Element; + #[storage()]fn carry_propagate(a: Element) -> Element; + #[storage()]fn reduce(a: Element) -> Element; } @@ -37,4 +39,12 @@ impl EdContract for Contract { #[storage()]fn add(a: Element, b: Element) -> Element { add(a, b) } + + #[storage()]fn carry_propagate(a: Element) -> Element { + carry_propagate(a) + } + + #[storage()]fn reduce(a: Element) -> Element { + reduce(a) + } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index 0fa2f6a..3c85303 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -1,4 +1,5 @@ mod square; mod multiply; mod subtract; -mod add; \ No newline at end of file +mod add; +mod reductions; \ No newline at end of file diff --git a/test_contract/tests/reductions/mod.rs b/test_contract/tests/reductions/mod.rs new file mode 100644 index 0000000..b310e0e --- /dev/null +++ b/test_contract/tests/reductions/mod.rs @@ -0,0 +1,182 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_carry_propagate_1() { + let a = Element{ + l_0: u64::MAX, + l_1: u64::MAX, + l_2: u64::MAX, + l_3: u64::MAX, + l_4: u64::MAX + }; + let expected_res = Element{ + l_0: 2251799813685247 + (19*8191), + l_1: 2251799813685247 + 8191, + l_2: 2251799813685247 + 8191, + l_3: 2251799813685247 + 8191, + l_4: 2251799813685247 + 8191 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.carry_propagate(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_carry_propagate_2() { + let a = Element{ + l_0: 2251799813685250, + l_1: 0, + l_2: 0, + l_3: 0, + l_4: 0 + }; + let expected_res = Element{ + l_0: 2, + l_1: 1, + l_2: 0, + l_3: 0, + l_4: 0 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.carry_propagate(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_reduce() { + let a = Element{ + l_0: 2251799813685250, + l_1: 0, + l_2: 0, + l_3: 0, + l_4: 0 + }; + let expected_res = Element{ + l_0: 2, + l_1: 1, + l_2: 0, + l_3: 0, + l_4: 0 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.reduce(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_reduce_2() { + let a = Element{ + l_0: 2251799813685250, + l_1: 2251799813685250, + l_2: 2251799813685250, + l_3: 2251799813685250, + l_4: 2251799813685250 + }; + let expected_res = Element{ + l_0: 21, + l_1: 3, + l_2: 3, + l_3: 3, + l_4: 3 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.reduce(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_reduce_3() { + let a = Element{ + l_0: u64::MAX, + l_1: u64::MAX, + l_2: u64::MAX, + l_3: u64::MAX, + l_4: u64::MAX + }; + let expected_res = Element{ + l_0: 155647, + l_1: 8191, + l_2: 8191, + l_3: 8191, + l_4: 8191 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.reduce(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_reduce_4() { + let a = Element{ + l_0: 4503599627370494, + l_1: 4503599627370494, + l_2: 4503599627370494, + l_3: 4503599627370494, + l_4: 4503599627370494 + }; + let expected_res = Element{ + l_0: 36, + l_1: 0, + l_2: 0, + l_3: 0, + l_4: 0 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.reduce(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + + From 4c2acc3ca28e7769467294eceb2faca35676f064 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 16:38:31 -0600 Subject: [PATCH 069/160] Converted helpers64 and scalar_mult to testing with Rust. --- test_contract/src/main.sw | 20 +++++ test_contract/tests/harness.rs | 4 +- test_contract/tests/helpers64/mod.rs | 101 +++++++++++++++++++++ test_contract/tests/scalar_mult/mod.rs | 120 +++++++++++++++++++++++++ 4 files changed, 244 insertions(+), 1 deletion(-) create mode 100644 test_contract/tests/helpers64/mod.rs create mode 100644 test_contract/tests/scalar_mult/mod.rs diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 7848217..3caa958 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -16,6 +16,10 @@ abi EdContract { #[storage()]fn add(a: Element, b: Element) -> Element; #[storage()]fn carry_propagate(a: Element) -> Element; #[storage()]fn reduce(a: Element) -> Element; + #[storage()]fn multiply64(a: u64, b: u64) -> U128; + #[storage()]fn add64(a: u64, b: u64, carry: u64) -> (u64, u64); + #[storage()]fn add_multiply64(res: U128, a: u64, b: u64) -> U128; + #[storage()]fn scalar_mult(a: Element, x: u32) -> Element; } @@ -47,4 +51,20 @@ impl EdContract for Contract { #[storage()]fn reduce(a: Element) -> Element { reduce(a) } + + #[storage()]fn multiply64(a: u64, b: u64) -> U128 { + multiply64(a, b) + } + + #[storage()]fn add64(a: u64, b: u64, carry: u64) -> (u64, u64) { + add64(a, b, carry) + } + + #[storage()]fn add_multiply64(res: U128, a: u64, b: u64) -> U128 { + add_multiply64(res, a, b) + } + + #[storage()]fn scalar_mult(a: Element, x: u32) -> Element { + scalar_mult(a, x) + } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index 3c85303..9bddcab 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -2,4 +2,6 @@ mod square; mod multiply; mod subtract; mod add; -mod reductions; \ No newline at end of file +mod reductions; +mod helpers64; +mod scalar_mult; \ No newline at end of file diff --git a/test_contract/tests/helpers64/mod.rs b/test_contract/tests/helpers64/mod.rs new file mode 100644 index 0000000..086a957 --- /dev/null +++ b/test_contract/tests/helpers64/mod.rs @@ -0,0 +1,101 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn tests_multiply64() { + let a = 9837491998535547791; + let b = 10009796384580774444; + // let ab = 98471291840283423519614919326553453204; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.multiply64(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res.lower == 5960040633016627860); + assert!(res.upper == 5338139427034470684); +} + +#[tokio::test] +async fn test_add64_random() { + let a = 9837491998535547791; + let b = 10009796384580774444; + let aplusb_carry: (u64, u64) = (1400544309406770619, 1); + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add64(a, b, 0) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res == aplusb_carry); +} + +#[tokio::test] +async fn test_add64_random_with_carry() { + let a = 9837491998535547791; + let b = 10009796384580774444; + let aplusb_carry: (u64, u64) = (1400544309406770620, 1); + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add64(a, b, 1) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res == aplusb_carry); +} + +#[tokio::test] +async fn test_add_multiply64() { + let a = 496009164746885; + let b = 24764068336973246; + let r: U128 = U128{upper: 2516888776885, lower: 8614063320694916486}; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_multiply64(r, a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res.lower == 10881738262824685884); + assert!(res.upper == 3182762646142); +} + +#[tokio::test] +async fn test_add_multiply64_2() { + let a = 24764068336973246; + let b = 137209507300112; + let r: U128 = U128{upper: 95365234715, lower: 16956620749643293576}; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_multiply64(r, a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res.lower == 18148778710141221224); + assert!(res.upper == 279563898809); +} \ No newline at end of file diff --git a/test_contract/tests/scalar_mult/mod.rs b/test_contract/tests/scalar_mult/mod.rs new file mode 100644 index 0000000..c1b87ab --- /dev/null +++ b/test_contract/tests/scalar_mult/mod.rs @@ -0,0 +1,120 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_mult_by_0() { + let a = Element{ + l_0: 2251799813685247, + l_1: 5, + l_2: 2251799813685247, + l_3: 2251799813685247, + l_4: 100 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.scalar_mult(a, 0) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, ZERO)); +} + +#[tokio::test] +async fn test_mult_by_1() { + let a = Element{ + l_0: 79611, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 555555333333222, + l_4: 2251799813685247 + }; + let expected_res = Element{ + l_0: 79611, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 555555333333222, + l_4: 2251799813685247 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.scalar_mult(a, 1) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_mult_by_2() { + let a = Element{ + l_0: 79611, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 555555333333222, + l_4: 2251799813685247 + }; + let expected_res = Element{ + l_0: 159241, + l_1: 2251799813685246, + l_2: 2251799813685247, + l_3: 1111110666666445, + l_4: 2251799813685246 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.scalar_mult(a, 2) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_mult_by_large_scalar() { + let a = Element{ + l_0: 79611, + l_1: 2251799813685247, + l_2: 2251799813685247, + l_3: 555555333333222, + l_4: 2251799813685247 + }; + let expected_res = Element{ + l_0: 342008245700831, + l_1: 2251795518717953, + l_2: 2251799813685247, + l_3: 536152338865944, + l_4: 2251796578355658 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.scalar_mult(a, 4294967295) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From 62b194100df3d67e8cda3816988dd3318667479d Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 16:47:52 -0600 Subject: [PATCH 070/160] Converted rshift tests to Rust --- test_contract/src/main.sw | 5 +++ test_contract/tests/harness.rs | 3 +- test_contract/tests/rshift/mod.rs | 62 +++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test_contract/tests/rshift/mod.rs diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 3caa958..88d6c88 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -20,6 +20,7 @@ abi EdContract { #[storage()]fn add64(a: u64, b: u64, carry: u64) -> (u64, u64); #[storage()]fn add_multiply64(res: U128, a: u64, b: u64) -> U128; #[storage()]fn scalar_mult(a: Element, x: u32) -> Element; + #[storage()]fn shift_right_by51(a: U128) -> u64; } @@ -67,4 +68,8 @@ impl EdContract for Contract { #[storage()]fn scalar_mult(a: Element, x: u32) -> Element { scalar_mult(a, x) } + + #[storage()]fn shift_right_by51(a: U128) -> u64 { + shift_right_by51(a) + } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index 9bddcab..82e631a 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -4,4 +4,5 @@ mod subtract; mod add; mod reductions; mod helpers64; -mod scalar_mult; \ No newline at end of file +mod scalar_mult; +mod rshift; \ No newline at end of file diff --git a/test_contract/tests/rshift/mod.rs b/test_contract/tests/rshift/mod.rs new file mode 100644 index 0000000..9c50ff3 --- /dev/null +++ b/test_contract/tests/rshift/mod.rs @@ -0,0 +1,62 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_shift_right_by51_random() { + let a: U128 = U128{upper: 16, lower: 0}; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.shift_right_by51(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res == 131072); +} + +#[tokio::test] +async fn test_shift_right_by51_random_2() { + let a: U128 = U128{upper: 349323232, lower: 456464}; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.shift_right_by51(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res == 2861655916544); +} + +#[tokio::test] +async fn test_shift_right_by51_random_3() { + let a: U128 = U128{upper: 349323232, lower: 18446744073709551615}; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.shift_right_by51(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res == 2861655924735); +} \ No newline at end of file From ac8906b9a72ad1233668081393dd986f0e5d5b74 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 16:58:56 -0600 Subject: [PATCH 071/160] Updated README --- README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/README.md b/README.md index 6639299..74f83cd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,17 @@ # fuel-crypto Various Cryptographic Primitives in Sway for the Fuel VM + +# Testing + + Make sure `fuel-core` is up to date. This can be done with [fuelup](https://github.com/FuelLabs/fuelup). Also, make sure there's only 1 `fuel-core` installed. + +## Edwards25519 + + The testing is done in Rust; the testfiles are in `/test_contract`. In `main.sw` the contract makes the connection with the library code in edward25519. This in turn can be tested in the `/test_contract/tests` folder. + + To run tests for edwards25519 folder: + ``` + cd test_contract + forc test + ``` + From a8ee37800d9cc8af7cdc0e964b8ef5d7469c4be3 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 16:59:32 -0600 Subject: [PATCH 072/160] Additions README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 74f83cd..39b19ab 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,13 @@ Various Cryptographic Primitives in Sway for the Fuel VM # Testing - Make sure `fuel-core` is up to date. This can be done with [fuelup](https://github.com/FuelLabs/fuelup). Also, make sure there's only 1 `fuel-core` installed. + Make sure `fuel-core` is up to date. This can be done with [fuelup](https://github.com/FuelLabs/fuelup). Also, make sure there's only 1 `fuel-core` installed (check this with `which -a fuel-core`). ## Edwards25519 - The testing is done in Rust; the testfiles are in `/test_contract`. In `main.sw` the contract makes the connection with the library code in edward25519. This in turn can be tested in the `/test_contract/tests` folder. + The testing is done in Rust; the testfiles are in `/test_contract`. See reference in [Sway documentation](https://fuellabs.github.io/sway/v0.17.0/testing/testing-with-rust.html). + + In `main.sw` the contract makes the connection with the library code in edward25519. This in turn can be tested in the `/test_contract/tests` folder. To run tests for edwards25519 folder: ``` From 5f5d2a166dde1b8019debf6ab6fed4c1ad041543 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 21 Jul 2022 17:39:23 -0600 Subject: [PATCH 073/160] - Changed a line in the inverse implementation (field_element.sw) - Added a test for inverse - Running the inverse function partially gives an error: this is commented in the code --- edwards25519/src/field_element.sw | 191 ++++++++++++++++++++--------- test_contract/src/main.sw | 7 ++ test_contract/tests/harness.rs | 17 +-- test_contract/tests/inverse/mod.rs | 56 +++++++++ 4 files changed, 206 insertions(+), 65 deletions(-) create mode 100644 test_contract/tests/inverse/mod.rs diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 6d9d947..c5b2bcc 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -318,81 +318,158 @@ pub fn inverse(a: Element) -> Element { let z2 = square(a); //2 let mut t = square(z2); //4 t = square(t); //8 - let z9 = multiply(t,a); //9 - let z11 = multiply(z9, z2); //11 - t = square(z11); //22 - - let z2_5_0 = multiply(t, z9); //31 - t = square(z2_5_0); // 62 = 2^6 - 2^1 - while i < 4 { - t = square(t); // 2^10 - 2^5 - i+=1; - } - let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 +// Comment Elena: when I run inverse until here, it gives me the error: Immediate18TooLarge - t = square(z2_10_0); //2^11 - 2^1 - i = 0; - while i < 9 { - t = square(t); //2^20 - 2^10 - i += 1; - } - let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 + // let z9 = multiply(t,a); //9 + // let z11 = multiply(z9, z2); //11 + // t = square(z11); //22 - t = square(z2_20_0); //2^21 - 2^1 - i = 0; - while i < 19 { - t = square(t); //2^40 - 2^20 - i += 1; - } + // let z2_5_0 = multiply(t, z9); //31 + // t = square(z2_5_0); // 62 = 2^6 - 2^1 + // while i < 4 { + // t = square(t); // 2^10 - 2^5 + // i+=1; + // } + + // let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 + + // t = square(z2_10_0); //2^11 - 2^1 + // i = 0; + // while i < 9 { + // t = square(t); //2^20 - 2^10 + // i += 1; + // } + + // let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 + + // t = square(z2_20_0); //2^21 - 2^1 + // i = 0; + // while i < 19 { + // t = square(t); //2^40 - 2^20 + // i += 1; + // } + + // t = multiply(t, z2_20_0); //2^40 - 2^0 - t = multiply(t, z2_20_0); //2^40 - 2^0 + // t = square(t); // 2^41 - 2^1 - i = 0; - while i < 10 { - t = square(t); //2^50 - 2^10 - } + // i = 0; + // while i < 10 { + // t = square(t); //2^50 - 2^10 + // } - let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 + // let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 - t = square(z2_50_0); //2^51 - 2^1 + // t = square(z2_50_0); //2^51 - 2^1 - i = 0; - while i < 49 { - t = square(t); //2^100 - 2^50 - i += 1; - } + // i = 0; + // while i < 49 { + // t = square(t); //2^100 - 2^50 + // i += 1; + // } - let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 + // let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 - t = square(z2_100_0); //2^101 - 2^1 + // t = square(z2_100_0); //2^101 - 2^1 - i = 0; - while i < 99 { - t = square(t); //2^200 - 2^100 - i += 1; - } + // i = 0; + // while i < 99 { + // t = square(t); //2^200 - 2^100 + // i += 1; + // } - t = multiply(t, z2_100_0); //2^200 - 2^0 + // t = multiply(t, z2_100_0); //2^200 - 2^0 - t = square(t); //2^201 - 2^1 + // t = square(t); //2^201 - 2^1 - i = 0; - while i < 49 { - t = square(t); //2^250 - 2^50 - i += 1; - } + // i = 0; + // while i < 49 { + // t = square(t); //2^250 - 2^50 + // i += 1; + // } - t = multiply(t, z2_50_0); //2^250 - 2^0 + // t = multiply(t, z2_50_0); //2^250 - 2^0 - i = 0; - while i < 5 { - t = square(t); //2^255 - 2^5 - i += 1; - } + // i = 0; + // while i < 5 { + // t = square(t); //2^255 - 2^5 + // i += 1; + // } - t = multiply(t, z11); //2^255 - 21 = p - 2 + // t = multiply(t, z11); //2^255 - 21 = p - 2 return t; } + +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +/* +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + + t.Square(&z2) // 4 + + t.Square(&t) // 8 + + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +}*/ diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index 88d6c88..b32ea31 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -22,6 +22,9 @@ abi EdContract { #[storage()]fn scalar_mult(a: Element, x: u32) -> Element; #[storage()]fn shift_right_by51(a: U128) -> u64; + #[storage()]fn inverse(a: Element) -> Element; + + } impl EdContract for Contract { @@ -72,4 +75,8 @@ impl EdContract for Contract { #[storage()]fn shift_right_by51(a: U128) -> u64 { shift_right_by51(a) } + + #[storage()]fn inverse(a: Element) -> Element { + inverse(a) + } } \ No newline at end of file diff --git a/test_contract/tests/harness.rs b/test_contract/tests/harness.rs index 82e631a..f98eff0 100644 --- a/test_contract/tests/harness.rs +++ b/test_contract/tests/harness.rs @@ -1,8 +1,9 @@ -mod square; -mod multiply; -mod subtract; -mod add; -mod reductions; -mod helpers64; -mod scalar_mult; -mod rshift; \ No newline at end of file +// mod square; +// mod multiply; +// mod subtract; +// mod add; +// mod reductions; +// mod helpers64; +// mod scalar_mult; +// mod rshift; +mod inverse; \ No newline at end of file diff --git a/test_contract/tests/inverse/mod.rs b/test_contract/tests/inverse/mod.rs new file mode 100644 index 0000000..91a4576 --- /dev/null +++ b/test_contract/tests/inverse/mod.rs @@ -0,0 +1,56 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(EdContract, "out/debug/test_edwards25519-abi.json"); + +async fn get_contract_instance() -> (EdContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/test_edwards25519.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = EdContract::new(id.to_string(), wallet); + (instance, id) +} + +const ZERO: Element = Element{ l_0: 0, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; +const ONE: Element = Element{ l_0: 1, l_1: 0, l_2: 0, l_3: 0, l_4: 0 }; + +pub fn res_equals(res: Element, should_be: Element) -> bool { + assert!(res.l_0 == should_be.l_0); + assert!(res.l_1 == should_be.l_1); + assert!(res.l_2 == should_be.l_2); + assert!(res.l_3 == should_be.l_3); + assert!(res.l_4 == should_be.l_4); + true +} + +#[tokio::test] +async fn test_inverse_random() { + /* + TO_LIMB_T(0xf4df1f341c341746), TO_LIMB_T(0x0a76e6a609d104f1), + TO_LIMB_T(0x8de5476c4c95b6d5), TO_LIMB_T(0x67eb88a9939d83c0), + TO_LIMB_T(0x9a793e85b519952d), TO_LIMB_T(0x11988fe592cae3aa) + */ + let a = Element{ + l_0: 715325916561861, + l_1: 1128975921026318, + l_2: 1696955067652624, + l_3: 2081297221826529, + l_4: 175872643896950 + }; + let expected_res = Element{ + l_0: 2187613694507759, + l_1: 1614434677729781, + l_2: 1594711943325299, + l_3: 378203143193209, + l_4: 843416921835783 + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.inverse(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From 701da35490f74b70ac441d9a54673db10396cd37 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 6 Jul 2022 17:38:29 -0600 Subject: [PATCH 074/160] Start on arithmetic for BLS12-381. - Fp definition and added several constants - Add of 2 Fp's -> this is WIP - Several smaller helper functions that have to be tested --- .gitattributes | 1 + bls12-381/Cargo.toml | 16 ++++ bls12-381/Forc.toml | 7 ++ bls12-381/src/fp.sw | 163 ++++++++++++++++++++++++++++++++++ bls12-381/src/main.sw | 135 ++++++++++++++++++++++++++++ bls12-381/src/test_helpers.sw | 24 +++++ 6 files changed, 346 insertions(+) create mode 100644 .gitattributes create mode 100644 bls12-381/Cargo.toml create mode 100644 bls12-381/Forc.toml create mode 100644 bls12-381/src/fp.sw create mode 100644 bls12-381/src/main.sw create mode 100644 bls12-381/src/test_helpers.sw diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1948c70 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sw linguist-language=Rust diff --git a/bls12-381/Cargo.toml b/bls12-381/Cargo.toml new file mode 100644 index 0000000..27d6243 --- /dev/null +++ b/bls12-381/Cargo.toml @@ -0,0 +1,16 @@ +[project] +name = "bls12-381" +version = "0.1.0" +authors = ["HashCloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = "0.15" +fuels-abigen-macro = "0.15" +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/bls12-381/Forc.toml b/bls12-381/Forc.toml new file mode 100644 index 0000000..d3112bb --- /dev/null +++ b/bls12-381/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["HashCloak"] +entry = "main.sw" +license = "Apache-2.0" +name = "bls12-381" + +[dependencies] diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw new file mode 100644 index 0000000..8f86b3c --- /dev/null +++ b/bls12-381/src/fp.sw @@ -0,0 +1,163 @@ +library fp; + +use std::u128::*; + +/* +Follows implementations +https://github.com/zkcrypto/bls12_381 +https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src + +Standard +https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-02.html#rfc.section.4.2.2 +Naming of variables follows this standard + +Additionally specifically on the instantiation of the curve +https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381 + +*/ + +// Stores field element with max 384 bits +pub struct Fp { + ls: [u64; 6], +} + +const ZERO: Fp = Fp {ls: [0, 0, 0, 0, 0, 0]}; + +/* + p = 0x1a0111ea 397fe69a 4b1ba7b6 434bacd7 64774b84 f38512bf 6730d2a0 f6b0f624 1eabfffe b153ffff b9feffff ffffaaab + = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 + (381 bits) +*/ +const MODULUS: Fp = Fp { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a] +}; + +/* + r : 0x73eda753 299d7d48 3339d808 09a1d805 53bda402 fffe5bfe ffffffff 00000001 + 52435875175126190479447740508185965837690552500527637822603658699938581184513 + 255 bits prime order of first group +*/ +const R: Fp = Fp { + ls: [0xffffffff00000001, + 0x53bda402fffe5bfe, + 0x3339d80809a1d805, + 0x73eda753299d7d48, + 0, + 0] +}; + +/* + x: 0x17f1d3a7 3197d794 2695638c 4fa9ac0f c3688c4f 9774b905 a14e3a3f 171bac58 6c55e83f f97a1aef fb3af00a db22c6bb + 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 +*/ +const G1_GENERATOR_X: Fp = Fp { + ls: [0xfb3af00adb22c6bb, + 0x6c55e83ff97a1aef, + 0xa14e3a3f171bac58, + 0xc3688c4f9774b905, + 0x2695638c4fa9ac0f, + 0x17f1d3a73197d794] +}; + +/* + y: 0x08b3f481 e3aaa0f1 a09e30ed 741d8ae4 fcf5e095 d5d00af6 00db18cb 2c04b3ed d03cc744 a2888ae4 0caa2329 46c5e7e1 + 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 +*/ +const G1_GENERATOR_Y: Fp = Fp { + ls: [0xcaa232946c5e7e1, + 0xd03cc744a2888ae4, + 0xdb18cb2c04b3ed, + 0xfcf5e095d5d00af6, + 0xa09e30ed741d8ae4, + 0x8b3f481e3aaa0f1] +}; + +// INV = -(q^{-1} mod 2^64) mod 2^64 +const INV: u64 = 0x89f3fffcfffcfffd; + +//TODO GET TESTS +//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? +//returns sum with carry of a and b +fn adc (a: u64, b: u64, carry: u64) -> (u64, u64) { + let A:U128 = U128{upper: 0, lower: a}; + let B:U128 = U128{upper: 0, lower: b}; + let Carry: U128 = U128 { upper: 0, lower: carry }; + + let sum: u64 = (A+B+Carry).lower; + let notSum = ~u64::max() - sum; + let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; + + (sum, carryOut) +} + +pub trait Add { + pub fn add(self, other: Self) -> Self; +} + +// TODO TEST +// If x >= y: x-y, else max::U128 - (y-x) +fn subtract_wrap(x: U128, y: U128) -> U128 { + if y > x { + ~U128::max() - (y - x) + } else { + x - y + } +} + +//TODO TEST +/// Compute a - (b + borrow), returning the result and the new borrow. +fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let a_128: U128 = U128 { lower: a, upper: 0}; + let b_128: U128 = U128 { lower: b, upper: 0}; + let borrow_128: U128 = U128 { lower: borrow >> 63, upper: 0}; + + let ret: U128 = subtract_wrap(a_128, b_128 + borrow_128); + (ret.lower, ret.upper) //(result, borrow) +} + +//TODO TEST +fn not(input: u64) -> u64 { + ~u64::max() - input +} + +// from https://github.com/zkcrypto/bls12_381 +//TODO TEST +// If a >= p, return a-p, else return a +fn subtract_p(a: Fp) -> Fp { + let (r0, borrow) = sbb(a.ls[0], MODULUS.ls[0], 0); + let (r1, borrow) = sbb(a.ls[1], MODULUS.ls[1], borrow); + let (r2, borrow) = sbb(a.ls[2], MODULUS.ls[2], borrow); + let (r3, borrow) = sbb(a.ls[3], MODULUS.ls[3], borrow); + let (r4, borrow) = sbb(a.ls[4], MODULUS.ls[4], borrow); + let (r5, borrow) = sbb(a.ls[5], MODULUS.ls[5], borrow); + + // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise + // borrow = 0x000...ls00. Thus, we use it as a mask! + let r0 = (a.ls[0] & borrow) | (r0 & not(borrow)); + let r1 = (a.ls[1] & borrow) | (r1 & not(borrow)); + let r2 = (a.ls[2] & borrow) | (r2 & not(borrow)); + let r3 = (a.ls[3] & borrow) | (r3 & not(borrow)); + let r4 = (a.ls[4] & borrow) | (r4 & not(borrow)); + let r5 = (a.ls[5] & borrow) | (r5 & not(borrow)); + + Fp{ ls: [r0, r1, r2, r3, r4, r5]} + } + +impl Add for Fp { + pub fn add(self, rhs: Self) -> Self { + let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); + let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); + let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); + let (d3, carry) = adc(self.ls[3], rhs.ls[3], carry); + let (d4, carry) = adc(self.ls[4], rhs.ls[4], carry); + let (d5, _) = adc(self.ls[5], rhs.ls[5], carry); + + //subtract p if needed + subtract_p(Fp{ ls: [d0, d1, d2, d3, d4, d5] }) + } +} diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw new file mode 100644 index 0000000..0edce1e --- /dev/null +++ b/bls12-381/src/main.sw @@ -0,0 +1,135 @@ +script; + +dep fp; +dep test_helpers; + +use std::{assert::assert}; +use ::fp::*; +use ::test_helpers::*; +use std::logging::log; + +fn main() { + assert(test_add()); +} + +fn test_add() -> bool { + assert(test_add_zero_to_zero()); + assert(test_add_zero_to_random()); + assert(test_add_random_to_zero()); + assert(test_add_random_to_small()); + assert(test_add_random_to_large()); + // assert(test_add_2_randoms()); + true +} + +fn test_add_zero_to_zero() -> bool { + let res: Fp = ZERO.add(ZERO); + equals_fp(res, ZERO); + true +} + +fn test_add_zero_to_random() -> bool { + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + let res: Fp = random.add(ZERO); + equals_fp(res, random); + true +} + +fn test_add_random_to_zero() -> bool { + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + /* +4478030004447473542 +2814704111667093002 +15884408734010272158 +17001047363111187578 +932823543034528547 +1051481384684610845 + */ + let res: Fp = ZERO.add(random); + equals_fp(res, random); + true +} + +fn test_add_random_to_small() -> bool { + let small = Fp { + ls: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6] + }; + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + let res: Fp = small.add(random); + equals_fp(res, Fp { + ls: [4478030004447473543, + 2814704111667093004, + 15884408734010272161, + 17001047363111187582, + 932823543034528552, + 1051481384684610851] + }); + true +} + +// TODO continue here and next test +fn test_add_random_to_large() -> bool { + let large = Fp { + ls: [~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max()] + }; + let random = Fp { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, + 0xdc70c19599cb699e, + 0xebefda8057d5747a, + 0xcf20e11f0b1c323, + 0xe979cbf960fe51d] + }; + let res: Fp = large.add(random); + print_fp(res); + + true +} + +fn test_add_2_randoms() -> bool { + let random_1 = Fp { + ls: [0x3e2528903ca1ef86,0x270fd67a03bf9e0a,0xdc70c19599cb699e,0xebefda8057d5747a,0xcf20e11f0b1c323,0xe979cbf960fe51d] + }; + + let random_2 = Fp { + ls: [0xbaf0ad04a3886e99,0x332e25612ced0991,0x8e95f86c79cd2d4,0xc27bdcacbb447470,0xe7dfe7df4c4d002c,0x7b33227cbdf0de43] + }; +/* +a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 +b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 +a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 +[13387723108140499808, +7110911959168982110, +7018803425472956901, +2577695370959560254, +1826757397030539319, +859395849761138905] + +a+b< p is true +*/ + let res: Fp = random_1.add(random_2); + print_fp(res); +// this seems to be incorrect + true +} \ No newline at end of file diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw new file mode 100644 index 0000000..719a22d --- /dev/null +++ b/bls12-381/src/test_helpers.sw @@ -0,0 +1,24 @@ +library test_helpers; + +dep fp; + +use fp::*; +use std::{logging::log, assert::assert}; + +pub fn print_fp(a: Fp) { + log(a.ls[0]); + log(a.ls[1]); + log(a.ls[2]); + log(a.ls[3]); + log(a.ls[4]); + log(a.ls[5]); +} + +pub fn equals_fp(a: Fp, b: Fp) { + assert(a.ls[0] == b.ls[0]); + assert(a.ls[1] == b.ls[1]); + assert(a.ls[2] == b.ls[2]); + assert(a.ls[3] == b.ls[3]); + assert(a.ls[4] == b.ls[4]); + assert(a.ls[5] == b.ls[5]); +} \ No newline at end of file From 7401f185a47db3fd7bc2cf04973cfb26fd5b4233 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 7 Jul 2022 15:47:46 -0600 Subject: [PATCH 075/160] - Renaming to be in line with blst impl - Added missing tests - Addition works Also here there seems to be a performance bottle neck. I can't run both subtract_p and the add tests at the same time. Therefore, one of the subtract_p tests is commented out. --- bls12-381/src/fp.sw | 164 ++------------------------ bls12-381/src/main.sw | 211 ++++++++++++++++++++++++++++------ bls12-381/src/test_helpers.sw | 8 +- 3 files changed, 187 insertions(+), 196 deletions(-) diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw index 8f86b3c..c7687a0 100644 --- a/bls12-381/src/fp.sw +++ b/bls12-381/src/fp.sw @@ -1,163 +1,15 @@ library fp; -use std::u128::*; - -/* -Follows implementations -https://github.com/zkcrypto/bls12_381 -https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src - -Standard -https://tools.ietf.org/id/draft-yonezawa-pairing-friendly-curves-02.html#rfc.section.4.2.2 -Naming of variables follows this standard - -Additionally specifically on the instantiation of the curve -https://github.com/zcash/librustzcash/tree/6e0364cd42a2b3d2b958a54771ef51a8db79dd29/pairing/src/bls12_381 - -*/ - -// Stores field element with max 384 bits -pub struct Fp { - ls: [u64; 6], -} +dep vec384; -const ZERO: Fp = Fp {ls: [0, 0, 0, 0, 0, 0]}; - -/* - p = 0x1a0111ea 397fe69a 4b1ba7b6 434bacd7 64774b84 f38512bf 6730d2a0 f6b0f624 1eabfffe b153ffff b9feffff ffffaaab - = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 - (381 bits) -*/ -const MODULUS: Fp = Fp { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a] -}; - -/* - r : 0x73eda753 299d7d48 3339d808 09a1d805 53bda402 fffe5bfe ffffffff 00000001 - 52435875175126190479447740508185965837690552500527637822603658699938581184513 - 255 bits prime order of first group -*/ -const R: Fp = Fp { - ls: [0xffffffff00000001, - 0x53bda402fffe5bfe, - 0x3339d80809a1d805, - 0x73eda753299d7d48, - 0, - 0] -}; - -/* - x: 0x17f1d3a7 3197d794 2695638c 4fa9ac0f c3688c4f 9774b905 a14e3a3f 171bac58 6c55e83f f97a1aef fb3af00a db22c6bb - 3685416753713387016781088315183077757961620795782546409894578378688607592378376318836054947676345821548104185464507 -*/ -const G1_GENERATOR_X: Fp = Fp { - ls: [0xfb3af00adb22c6bb, - 0x6c55e83ff97a1aef, - 0xa14e3a3f171bac58, - 0xc3688c4f9774b905, - 0x2695638c4fa9ac0f, - 0x17f1d3a73197d794] -}; +use ::vec384::*; +use std::u128::*; /* - y: 0x08b3f481 e3aaa0f1 a09e30ed 741d8ae4 fcf5e095 d5d00af6 00db18cb 2c04b3ed d03cc744 a2888ae4 0caa2329 46c5e7e1 - 1339506544944476473020471379941921221584933875938349620426543736416511423956333506472724655353366534992391756441569 +Reference implementation +https://github.com/supranational/blst */ -const G1_GENERATOR_Y: Fp = Fp { - ls: [0xcaa232946c5e7e1, - 0xd03cc744a2888ae4, - 0xdb18cb2c04b3ed, - 0xfcf5e095d5d00af6, - 0xa09e30ed741d8ae4, - 0x8b3f481e3aaa0f1] -}; - -// INV = -(q^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0x89f3fffcfffcfffd; - -//TODO GET TESTS -//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? -//returns sum with carry of a and b -fn adc (a: u64, b: u64, carry: u64) -> (u64, u64) { - let A:U128 = U128{upper: 0, lower: a}; - let B:U128 = U128{upper: 0, lower: b}; - let Carry: U128 = U128 { upper: 0, lower: carry }; - - let sum: u64 = (A+B+Carry).lower; - let notSum = ~u64::max() - sum; - let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; - - (sum, carryOut) -} - -pub trait Add { - pub fn add(self, other: Self) -> Self; -} - -// TODO TEST -// If x >= y: x-y, else max::U128 - (y-x) -fn subtract_wrap(x: U128, y: U128) -> U128 { - if y > x { - ~U128::max() - (y - x) - } else { - x - y - } -} - -//TODO TEST -/// Compute a - (b + borrow), returning the result and the new borrow. -fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = U128 { lower: a, upper: 0}; - let b_128: U128 = U128 { lower: b, upper: 0}; - let borrow_128: U128 = U128 { lower: borrow >> 63, upper: 0}; - - let ret: U128 = subtract_wrap(a_128, b_128 + borrow_128); - (ret.lower, ret.upper) //(result, borrow) -} - -//TODO TEST -fn not(input: u64) -> u64 { - ~u64::max() - input -} - -// from https://github.com/zkcrypto/bls12_381 -//TODO TEST -// If a >= p, return a-p, else return a -fn subtract_p(a: Fp) -> Fp { - let (r0, borrow) = sbb(a.ls[0], MODULUS.ls[0], 0); - let (r1, borrow) = sbb(a.ls[1], MODULUS.ls[1], borrow); - let (r2, borrow) = sbb(a.ls[2], MODULUS.ls[2], borrow); - let (r3, borrow) = sbb(a.ls[3], MODULUS.ls[3], borrow); - let (r4, borrow) = sbb(a.ls[4], MODULUS.ls[4], borrow); - let (r5, borrow) = sbb(a.ls[5], MODULUS.ls[5], borrow); - - // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise - // borrow = 0x000...ls00. Thus, we use it as a mask! - let r0 = (a.ls[0] & borrow) | (r0 & not(borrow)); - let r1 = (a.ls[1] & borrow) | (r1 & not(borrow)); - let r2 = (a.ls[2] & borrow) | (r2 & not(borrow)); - let r3 = (a.ls[3] & borrow) | (r3 & not(borrow)); - let r4 = (a.ls[4] & borrow) | (r4 & not(borrow)); - let r5 = (a.ls[5] & borrow) | (r5 & not(borrow)); - - Fp{ ls: [r0, r1, r2, r3, r4, r5]} - } - -impl Add for Fp { - pub fn add(self, rhs: Self) -> Self { - let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); - let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); - let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); - let (d3, carry) = adc(self.ls[3], rhs.ls[3], carry); - let (d4, carry) = adc(self.ls[4], rhs.ls[4], carry); - let (d5, _) = adc(self.ls[5], rhs.ls[5], carry); - //subtract p if needed - subtract_p(Fp{ ls: [d0, d1, d2, d3, d4, d5] }) - } -} +pub fn add_fp(a: vec384, b: vec384) -> vec384 { + add_mod_384(a, b, BLS12_381_P) +} \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 0edce1e..75aa72b 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -1,15 +1,132 @@ script; +dep vec384; dep fp; dep test_helpers; -use std::{assert::assert}; +use std::{assert::assert, u128::*}; use ::fp::*; +use ::vec384::*; use ::test_helpers::*; use std::logging::log; fn main() { assert(test_add()); + assert(test_helpers()); +} + +fn test_helpers() -> bool { + assert(test_not()); + assert(tests_subtract_wrap()); + assert(tests_sbb()); + assert(tests_adc()); + assert(tests_subtract_p()); + true +} + +fn test_not() -> bool { + let res = not(18417751708719972248); + assert(res == 28992364989579367); + true +} + +fn tests_subtract_wrap() -> bool { + let mut res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 80, upper: 0}); + assert(res.lower == 20); + assert(res.upper == 0); + + res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 230, upper: 0}); + let res_should_be = ~U128::max() - U128 { lower: 130, upper: 0}; + assert(res == res_should_be); + true +} + +fn tests_sbb() -> bool { + // 0-0-0 should give (0,0) + let mut res = sbb(0, 0, 0); + assert(res.0 == 0); + assert(res.1 == 0); + + // 0-1-0 should give (-1, 1) + res = sbb(0, 1, 0); + assert(res.0 == ~u64::max() - 1); + assert(res.1 == 1); + + // 0-1-1 should give (-2, 1) + res = sbb(0, 1, 1); + assert(res.0 == ~u64::max() - 2); + assert(res.1 == 1); + + // a-0-1 should give (a-1, 0) + let a = 435983458; + res = sbb(a, 0, 1); + assert(res.0 == a-1); + assert(res.1 == 0); + true +} + +fn tests_adc() -> bool { + assert(test_adc_random()); + assert(test_adc_random_with_carry()); + true +} + +fn test_adc_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = adc(a, b, 0); + let a_plus_b: (u64,u64) = (1400544309406770619, 1); + + assert(res.0 == a_plus_b.0); + assert(res.1 == a_plus_b.1); + true +} + +fn test_adc_random_with_carry() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res:(u64,u64) = adc(a, b, 1); + let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); + + assert(res.0 == a_plus_b_and_carry.0); + assert(res.1 == a_plus_b_and_carry.1); + true +} + +/* +These tests won't run at the same time... +*/ +fn tests_subtract_p() -> bool { + // assert(test_subtract_p_smaller()); + assert(test_subtract_p_larger()); + true +} + +fn test_subtract_p_smaller() -> bool { + let a_smaller_than_p = vec384 { + ls: [13402431016077863508, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + }; + let res = subtract_p(a_smaller_than_p, BLS12_381_P); + equals_vec384(res, a_smaller_than_p); + true +} + +fn test_subtract_p_larger() -> bool { + // p+200 + let a_larger_than_p = vec384 { ls: [13402431016077863795, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866]}; + let res = subtract_p(a_larger_than_p, BLS12_381_P); + equals_vec384(res, vec384 { ls: [200,0,0,0,0,0] }); + true } fn test_add() -> bool { @@ -17,19 +134,19 @@ fn test_add() -> bool { assert(test_add_zero_to_random()); assert(test_add_random_to_zero()); assert(test_add_random_to_small()); - assert(test_add_random_to_large()); - // assert(test_add_2_randoms()); + assert(test_add_larger_than_p()); + assert(test_add_2_randoms()); true } fn test_add_zero_to_zero() -> bool { - let res: Fp = ZERO.add(ZERO); - equals_fp(res, ZERO); + let res: vec384 = add_fp(ZERO, ZERO); + equals_vec384(res, ZERO); true } fn test_add_zero_to_random() -> bool { - let random = Fp { + let random = vec384 { ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, @@ -37,13 +154,13 @@ fn test_add_zero_to_random() -> bool { 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; - let res: Fp = random.add(ZERO); - equals_fp(res, random); + let res: vec384 = add_fp(random, ZERO); + equals_vec384(res, random); true } fn test_add_random_to_zero() -> bool { - let random = Fp { + let random = vec384 { ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, @@ -59,16 +176,16 @@ fn test_add_random_to_zero() -> bool { 932823543034528547 1051481384684610845 */ - let res: Fp = ZERO.add(random); - equals_fp(res, random); + let res: vec384 = add_fp(ZERO, random); + equals_vec384(res, random); true } fn test_add_random_to_small() -> bool { - let small = Fp { + let small = vec384 { ls: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6] }; - let random = Fp { + let random = vec384 { ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, @@ -76,8 +193,8 @@ fn test_add_random_to_small() -> bool { 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; - let res: Fp = small.add(random); - equals_fp(res, Fp { + let res: vec384 = add_fp(small, random); + equals_vec384(res, vec384 { ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, @@ -88,32 +205,50 @@ fn test_add_random_to_small() -> bool { true } -// TODO continue here and next test -fn test_add_random_to_large() -> bool { - let large = Fp { - ls: [~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max(), ~u64::max()] - }; - let random = Fp { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] +fn test_add_larger_than_p() -> bool { + /* + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 + + + 100 + is a little bit larger than p + */ + //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + let a = vec384 { + ls: [13402431016077863508, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] }; - let res: Fp = large.add(random); - print_fp(res); + let b = vec384 { ls: [100,0,0,0,0,0] }; + +// should be 13 + let res: vec384 = add_fp(a, b); + equals_vec384(res, vec384 {ls: [13,0,0,0,0,0]}); true } fn test_add_2_randoms() -> bool { - let random_1 = Fp { - ls: [0x3e2528903ca1ef86,0x270fd67a03bf9e0a,0xdc70c19599cb699e,0xebefda8057d5747a,0xcf20e11f0b1c323,0xe979cbf960fe51d] + //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] + let random_1 = vec384 { + ls: [4510245898505151773, + 8849327944066866226, + 11451510199254766964, + 782624411996506985, + 9666712539018543006, + 17492304704872943] }; - let random_2 = Fp { - ls: [0xbaf0ad04a3886e99,0x332e25612ced0991,0x8e95f86c79cd2d4,0xc27bdcacbb447470,0xe7dfe7df4c4d002c,0x7b33227cbdf0de43] +//[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + let random_2 = vec384 { + ls: [8877477209635348035, + 16708328088811667500, + 14014037299927741552, + 1795070958963053268, + 10606788931721547929, + 841903545056265961] }; /* a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 @@ -128,8 +263,12 @@ a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894 a+b< p is true */ - let res: Fp = random_1.add(random_2); - print_fp(res); -// this seems to be incorrect + let res: vec384 = add_fp(random_1, random_2); + equals_vec384(res, vec384{ ls: [13387723108140499808, + 7110911959168982110, + 7018803425472956901, + 2577695370959560254, + 1826757397030539319, + 859395849761138905] }); true } \ No newline at end of file diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 719a22d..0acdaec 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -1,11 +1,11 @@ library test_helpers; -dep fp; +dep vec384; -use fp::*; +use vec384::*; use std::{logging::log, assert::assert}; -pub fn print_fp(a: Fp) { +pub fn print_vec384(a: vec384) { log(a.ls[0]); log(a.ls[1]); log(a.ls[2]); @@ -14,7 +14,7 @@ pub fn print_fp(a: Fp) { log(a.ls[5]); } -pub fn equals_fp(a: Fp, b: Fp) { +pub fn equals_vec384(a: vec384, b: vec384) { assert(a.ls[0] == b.ls[0]); assert(a.ls[1] == b.ls[1]); assert(a.ls[2] == b.ls[2]); From 5a03247d9b37728d3d3b5f835697424499d74ba5 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 7 Jul 2022 16:21:28 -0600 Subject: [PATCH 076/160] The actual vec384 code. --- bls12-381/src/vec384.sw | 97 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 bls12-381/src/vec384.sw diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw new file mode 100644 index 0000000..327791c --- /dev/null +++ b/bls12-381/src/vec384.sw @@ -0,0 +1,97 @@ +library vec384; + +use std::u128::*; + +// Stores field element with max 384 bits +pub struct vec384 { + ls: [u64; 6], +} + +const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; + +/* + z = -0xd201000000010000 + (z-1)^2 * (z^4 - z^2 + 1)/3 + z + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 + (381 bits) +*/ +const BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a] +}; + +// If x >= y: x-y, else max::U128 - (y-x) +pub fn subtract_wrap(x: U128, y: U128) -> U128 { + if y > x { + ~U128::max() - (y - x) + } else { + x - y + } +} + +/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). +pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let a_128: U128 = U128 { lower: a, upper: 0}; + let b_128: U128 = U128 { lower: b, upper: 0}; + let borrow_128: U128 = U128 { lower: borrow, upper: 0}; + + let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); + (res.lower, res.upper >> 63) //(result, borrow) +} + +pub fn not(input: u64) -> u64 { + ~u64::max() - input +} + +// from https://github.com/zkcrypto/bls12_381 +// If a >= p, return a-p, else return a +pub fn subtract_p(a: vec384 , p: vec384) -> vec384 { + let (r0, borrow) = sbb(a.ls[0], p.ls[0], 0); + let (r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); + let (r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); + let (r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); + let (r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); + let (r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); + + // If underflow occurred on the final limb, borrow = 1, otherwise + // borrow = 0. We convert it into a mask. + let mut mask = borrow * ~u64::max(); + let r0 = (a.ls[0] & mask) | (r0 & not(mask)); + let r1 = (a.ls[1] & mask) | (r1 & not(mask)); + let r2 = (a.ls[2] & mask) | (r2 & not(mask)); + let r3 = (a.ls[3] & mask) | (r3 & not(mask)); + let r4 = (a.ls[4] & mask) | (r4 & not(mask)); + let r5 = (a.ls[5] & mask) | (r5 & not(mask)); + + vec384{ ls: [r0, r1, r2, r3, r4, r5]} +} + +//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? +//returns sum with carry of a and b +pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { + let a_128 :U128 = U128 { upper: 0, lower: a }; + let b_128 :U128 = U128 { upper: 0, lower: b }; + let c_128: U128 = U128 { upper: 0, lower: carry }; + + let sum: u64 = (a_128 + b_128 + c_128).lower; + let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; + + (sum, carry_res) +} + +pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { + let (d0, carry) = adc(a.ls[0], b.ls[0], 0); + let (d1, carry) = adc(a.ls[1], b.ls[1], carry); + let (d2, carry) = adc(a.ls[2], b.ls[2], carry); + let (d3, carry) = adc(a.ls[3], b.ls[3], carry); + let (d4, carry) = adc(a.ls[4], b.ls[4], carry); + let (d5, _) = adc(a.ls[5], b.ls[5], carry); + + //subtract p if needed + subtract_p(vec384{ ls: [d0, d1, d2, d3, d4, d5] }, p) +} + From dfe0024f2ac8fb43ef20cff2e203dd0d03ffe8ff Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 7 Jul 2022 18:15:28 -0600 Subject: [PATCH 077/160] - Implemented sub_fp - Added tests. Note that not all tests can run at the same time. However, they all pass separately. - Fixed subtract_wrap function --- bls12-381/src/fp.sw | 4 + bls12-381/src/main.sw | 177 +++++++++++++++++++++++++++++++++++++--- bls12-381/src/vec384.sw | 45 +++++++++- 3 files changed, 212 insertions(+), 14 deletions(-) diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw index c7687a0..ea2135e 100644 --- a/bls12-381/src/fp.sw +++ b/bls12-381/src/fp.sw @@ -12,4 +12,8 @@ https://github.com/supranational/blst pub fn add_fp(a: vec384, b: vec384) -> vec384 { add_mod_384(a, b, BLS12_381_P) +} + +pub fn sub_fp(a: vec384, b: vec384) -> vec384 { + sub_mod_384(a, b, BLS12_381_P) } \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 75aa72b..eddd4f7 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -11,7 +11,9 @@ use ::test_helpers::*; use std::logging::log; fn main() { - assert(test_add()); + // Don't run all add and sub tests at the same time... + // assert(test_add_fp()); + // assert(test_sub_fp()); assert(test_helpers()); } @@ -20,7 +22,8 @@ fn test_helpers() -> bool { assert(tests_subtract_wrap()); assert(tests_sbb()); assert(tests_adc()); - assert(tests_subtract_p()); + assert(test_neg()); + assert(test_subtract_p()); true } @@ -37,7 +40,10 @@ fn tests_subtract_wrap() -> bool { res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 230, upper: 0}); let res_should_be = ~U128::max() - U128 { lower: 130, upper: 0}; - assert(res == res_should_be); + // 2^128 - 230 = 340282366920938463463374607431768211226 + // [18446744073709551486, 18446744073709551615] + assert(res.lower == 18446744073709551486); + assert(res.upper == 18446744073709551615); true } @@ -47,14 +53,14 @@ fn tests_sbb() -> bool { assert(res.0 == 0); assert(res.1 == 0); - // 0-1-0 should give (-1, 1) + // 0-1-0 should give (2^64 -1, 1) res = sbb(0, 1, 0); - assert(res.0 == ~u64::max() - 1); + assert(res.0 == ~u64::max()); assert(res.1 == 1); - // 0-1-1 should give (-2, 1) + // 0-1-1 should give (2^64 -2, 1) res = sbb(0, 1, 1); - assert(res.0 == ~u64::max() - 2); + assert(res.0 == ~u64::max() - 1); assert(res.1 == 1); // a-0-1 should give (a-1, 0) @@ -93,11 +99,8 @@ fn test_adc_random_with_carry() -> bool { true } -/* -These tests won't run at the same time... -*/ -fn tests_subtract_p() -> bool { - // assert(test_subtract_p_smaller()); +fn test_subtract_p() -> bool { + assert(test_subtract_p_smaller()); assert(test_subtract_p_larger()); true } @@ -129,7 +132,7 @@ fn test_subtract_p_larger() -> bool { true } -fn test_add() -> bool { +fn test_add_fp() -> bool { assert(test_add_zero_to_zero()); assert(test_add_zero_to_random()); assert(test_add_random_to_zero()); @@ -271,4 +274,152 @@ a+b< p is true 1826757397030539319, 859395849761138905] }); true +} + +fn test_neg() -> bool { + assert(test_neg_p()); + assert(test_neg_1()); + assert(test_neg_random()); + true +} + +// neg(p, p) should result in 0 +fn test_neg_p() -> bool { + let p = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a] + }; + let res = neg(p, BLS12_381_P); + equals_vec384(res, ZERO); + true +} + +fn test_neg_1() -> bool { + /* p (=BLS12_381_P) + [13402431016077863595, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + */ + let res = neg(vec384 { ls: [1,0,0,0,0,0] }, BLS12_381_P); + let p_minus_1 = vec384 { + ls: [13402431016077863594, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + }; + + equals_vec384(res, p_minus_1); + true +} + +fn test_neg_random() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + + // p-r = + // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 + let res = neg(r, BLS12_381_P); + equals_vec384(res, vec384 { + ls: [343185552611564426, + 2882282484148780005, + 6545683898001206309, + 12914691390957992833, + 41210333997197102, + 1273825819919628179] + }); + true +} + +fn test_sub_fp() -> bool { + // assert(test_sub_zero_from_zero()); + // assert(test_sub_zero_from_random()); + // assert(test_sub_random_from_zero()); + // assert(test_sub_random_from_small()); + assert(test_sub_2_randoms()); + assert(test_sub_2_randoms_reverse()); + true +} + +fn test_sub_zero_from_zero() -> bool { + let res = sub_fp(ZERO, ZERO); + equals_vec384(res, ZERO); + true +} + +fn test_sub_zero_from_random() -> bool { + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let res = sub_fp(r, ZERO); + equals_vec384(res, r); + true +} + +fn test_sub_random_from_zero() -> bool { + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let res = sub_fp(ZERO, r); + // p-r (is the same as 0-r mod p) + equals_vec384(res, vec384 { + ls: [343185552611564426, + 2882282484148780005, + 6545683898001206309, + 12914691390957992833, + 41210333997197102, + 1273825819919628179] + }); + true +} + +fn test_sub_random_from_small() -> bool { + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let small = vec384 { + ls: [1, 2, 3, 4, 5, 6] + }; + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + + let res: vec384 = sub_fp(small, r); + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + equals_vec384(res, vec384{ ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185]}); + true +} + +fn test_sub_2_randoms() -> bool { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let res: vec384 = sub_fp(a, b); + equals_vec384(res, vec384{ ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019]}); + true +} + +fn test_sub_2_randoms_reverse() -> bool { + // Same a,b from test_sub_2_randoms only subtract the other way around + let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; + let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let res: vec384 = sub_fp(b, a); + equals_vec384(res, vec384{ ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846]}); + true } \ No newline at end of file diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index 327791c..f981752 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -27,7 +27,16 @@ const BLS12_381_P: vec384 = vec384 { // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { - ~U128::max() - (y - x) + ~U128::max() - (y - x - U128 { lower: 1, upper: 0}) + } else { + x - y + } +} + +// If x >= y: x-y, else max::U64 - (y-x) +pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { + if y > x { + ~u64::max() - (y - x - 1) } else { x - y } @@ -83,6 +92,7 @@ pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { (sum, carry_res) } +// from https://github.com/zkcrypto/bls12_381 pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { let (d0, carry) = adc(a.ls[0], b.ls[0], 0); let (d1, carry) = adc(a.ls[1], b.ls[1], carry); @@ -95,3 +105,36 @@ pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { subtract_p(vec384{ ls: [d0, d1, d2, d3, d4, d5] }, p) } +// from https://github.com/zkcrypto/bls12_381 +pub fn neg(a: vec384, p: vec384) -> vec384 { + let (d0, borrow) = sbb(p.ls[0], a.ls[0], 0); + let (d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); + let (d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); + let (d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); + let (d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); + let (d5, _) = sbb(p.ls[5], a.ls[5], borrow); + + // We need a mask that's 0 when a==p and 2^65-1 otherwise + // TODO improve this + let mut a_is_p = 0; + if (a.ls[0] | a.ls[1] | a.ls[2] | a.ls[3] | a.ls[4] | a.ls[5]) == 0 { + a_is_p = 1; //don't know is there's a native conversion + } else { + a_is_p = 0; + } + + let mask = subtract_wrap_64(a_is_p, 1); + + vec384{ ls: [ + d0 & mask, + d1 & mask, + d2 & mask, + d3 & mask, + d4 & mask, + d5 & mask, + ]} +} + +pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { + add_mod_384(a, neg(b, p), p) +} \ No newline at end of file From d9242ea34e6f018dca93f0bc05045e919e86d1ea Mon Sep 17 00:00:00 2001 From: Manish Date: Fri, 8 Jul 2022 18:06:55 +0530 Subject: [PATCH 078/160] montgomery reduction --- bls12-381/src/vec384.sw | 83 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index f981752..6406230 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -23,6 +23,8 @@ const BLS12_381_P: vec384 = vec384 { 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] }; +/// INV = -(P^{-1} mod 2^64) mod 2^64 +const INV: u64 = 0x89f3fffcfffcfffd; // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { @@ -137,4 +139,83 @@ pub fn neg(a: vec384, p: vec384) -> vec384 { pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { add_mod_384(a, neg(b, p), p) -} \ No newline at end of file +} + +//returns the result and new carry of a + b*c + carry +pub fn mac (a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let A: U128 = U128 {upper: 0, lower: a}; + let B: U128 = U128 {upper: 0, lower: b}; + let C: U128 = U128 {upper: 0, lower: c}; + let CARRY: U128 = U128 {upper: 0, lower: carry}; + let res: U128 = A + B * C + CARRY; + (res.lower, res.upper) +} + +//returns a*b mod(2^64) +pub fn multiply_wrap(a: u64, b:u64) -> u64 { + let A: U128 = U128{upper: 0, lower: a}; + let B: U128 = U128{upper: 0, lower: b}; + + (A*B).lower +} + +// from https://github.com/zkcrypto/bls12_381 +pub fn montgomery_reduction(t: [u64;12]) -> vec384 { + let mut k = multiply_wrap(t[0], INV); + + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); + let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); + let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); + let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); + let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); + let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); + let r6_7: (u64, u64) = adc(t[6], 0, r5.1); + + let k = multiply_wrap(r1.0, INV); + let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); + let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); + let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); + let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); + + let k = multiply_wrap(r2.0, INV); + let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); + let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); + let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); + + let k = multiply_wrap(r3.0, INV); + let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); + let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); + let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); + + let k = multiply_wrap(r4.0, INV); + let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); + let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); + let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); + + let k = multiply_wrap(r5.0, INV); + let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); + let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); + let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); + let r11_12 = adc(t[11], r10_11.1, r10.1); + + subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) + +} From 6369569bb48361c557d92c9d57b90036ad1cd1e3 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 8 Jul 2022 17:35:17 -0600 Subject: [PATCH 079/160] - added the add and subtract for fp2 with tests - added mul_by_3, mul_by_8 and lshift with tests All tests pass but cannot be run all at the same time. --- bls12-381/src/fp.sw | 28 +++++++++ bls12-381/src/main.sw | 125 +++++++++++++++++++++++++++++++++++++++- bls12-381/src/vec384.sw | 26 +++++++++ 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw index ea2135e..5f16d71 100644 --- a/bls12-381/src/fp.sw +++ b/bls12-381/src/fp.sw @@ -10,10 +10,38 @@ Reference implementation https://github.com/supranational/blst */ +// Fp + pub fn add_fp(a: vec384, b: vec384) -> vec384 { add_mod_384(a, b, BLS12_381_P) } pub fn sub_fp(a: vec384, b: vec384) -> vec384 { sub_mod_384(a, b, BLS12_381_P) +} + +pub fn mul_by_3_fp(a: vec384) -> vec384 { + mul_by_3_mod_384(a, BLS12_381_P) +} + +pub fn mul_by_8_fp(a: vec384) -> vec384 { + mul_by_8_mod_384(a, BLS12_381_P) +} + +pub fn lshift_fp(a: vec384, count: u64) -> vec384 { + lshift_mod_384(a, count, BLS12_381_P) +} + +// Fp2 + +pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = add_mod_384(a.r, b.r, BLS12_381_P); + let res_i = add_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); + let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } } \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index eddd4f7..d999e14 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -11,10 +11,76 @@ use ::test_helpers::*; use std::logging::log; fn main() { - // Don't run all add and sub tests at the same time... + // assert(fp_tests()); + assert(fp2_tests()); +} + +fn fp_tests() -> bool { + // Don't run all tests at the same time... + // assert(test_add_fp()); // assert(test_sub_fp()); - assert(test_helpers()); + // assert(test_helpers()); + assert(tests_mul_by_3_fp()); + assert(tests_mul_by_8_fp()); + assert(test_lshift_p()); + + true +} + +fn fp2_tests() -> bool { + assert(tests_add_fp2()); + assert(tests_sub_fp2()); + true +} + +fn tests_add_fp2() -> bool { + // the function should add the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; + let a_1 = vec384x { r: r_1, i: i_1 }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; + let a_2 = vec384x { r: r_2, i: i_2 }; + + let res = add_fp2(a_1, a_2); + + // real part + //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 + // i part + //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 + equals_vec384(res.r, vec384{ ls:[17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] }); + equals_vec384(res.i, vec384{ ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219]}); + true +} + +fn tests_sub_fp2() -> bool { + // the function should subtract the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; + let a_1 = vec384x { r: r_1, i: i_1 }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; + let a_2 = vec384x { r: r_2, i: i_2 }; + + let res = sub_fp2(a_1, a_2); + //real + //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 + //i + //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 + equals_vec384(res.r, vec384{ ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376]}); + equals_vec384(res.i, vec384{ ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341]}); + true } fn test_helpers() -> bool { @@ -422,4 +488,59 @@ fn test_sub_2_randoms_reverse() -> bool { let res: vec384 = sub_fp(b, a); equals_vec384(res, vec384{ ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846]}); true +} + +fn tests_mul_by_3_fp() -> bool { + //3*0=0 + let three_times_0 = mul_by_3_fp(ZERO); + equals_vec384(three_times_0, ZERO); + + // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 + let a = vec384 { ls: [5598198260030196614, 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475]}; + // a*3 mod p should be + //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 + let res = mul_by_3_fp(a); + equals_vec384(res, vec384 { ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694]}); + true +} + +fn tests_mul_by_8_fp() -> bool { + //8*0=0 + let eight_times_0 = mul_by_8_fp(ZERO); + equals_vec384(eight_times_0, ZERO); + + // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 + let a = vec384 { ls: [4748578380656466952, 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211]}; + // a*8 mod p should be + //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 + let res = mul_by_8_fp(a); + equals_vec384(res, vec384 { ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227]}); + true +} + +fn test_lshift_p() -> bool { + assert(test_1_lshift_p()); + assert(test_250_lshift_p()); + true +} + +fn test_1_lshift_p() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let res = lshift_fp(r, 1); + // 1 leftshift is *2 + //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 + equals_vec384(res, vec384{ ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374]}); + true +} + +fn test_250_lshift_p() -> bool { + //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 + let a = vec384 { ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937]}; + // leftshift 250 mod p + //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 + let res = lshift_fp(a, 250); + equals_vec384(res, vec384 { ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179]}); + true } \ No newline at end of file diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index 6406230..098728d 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -3,10 +3,17 @@ library vec384; use std::u128::*; // Stores field element with max 384 bits +// element in fp pub struct vec384 { ls: [u64; 6], } +// element in fp2 +pub struct vec384x { + r: vec384, //"real" part + i: vec384 //"imaginary" part +} + const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; /* @@ -219,3 +226,22 @@ pub fn montgomery_reduction(t: [u64;12]) -> vec384 { subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) } + +pub fn mul_by_3_mod_384(a: vec384, p: vec384) -> vec384 { + let temp = add_mod_384(a, a, p); + add_mod_384(temp, a, p) +} + +pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { + let mut i = 0; + let mut a_temp: vec384 = a; + while i < n { + a_temp = add_mod_384(a_temp, a_temp, p); + i += 1; + } + a_temp +} + +pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { + lshift_mod_384(a, 3, p) +} \ No newline at end of file From ac90c31b36f07fc405b8c03ab384dc7eb3f28dff Mon Sep 17 00:00:00 2001 From: Manish Date: Mon, 11 Jul 2022 18:37:12 +0530 Subject: [PATCH 080/160] tests for montgomery not working --- bls12-381/src/main.sw | 64 +++++++++++++++++++++++++++++++++++++++- bls12-381/src/vec384.sw | 12 ++++---- edwards25519/src/main.sw | 7 +++-- 3 files changed, 73 insertions(+), 10 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index d999e14..d63b5ea 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -12,7 +12,10 @@ use std::logging::log; fn main() { // assert(fp_tests()); - assert(fp2_tests()); + // assert(fp2_tests()); + // assert(tests_montgomery_reduction()); + assert(test_multiply_wrap()); + assert(test_mac()); } fn fp_tests() -> bool { @@ -543,4 +546,63 @@ fn test_250_lshift_p() -> bool { let res = lshift_fp(a, 250); equals_vec384(res, vec384 { ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179]}); true +} + +fn test_mac() -> bool { + let a = 13282407956253574712; + let b = 7557322358563246340; + let c = 14991082624209354397; + + let res = mac(a,b,c,0); + assert(res.0 == 15211181400380206508); + assert(res.1 == 6141595689857899799); + + let carry = 1234555432334; + let res2 = mac(a,b,c,carry); + assert(res2.0 == 15211182634935638842); + assert(res2.1 == 6141595689857899799); + + true +} + +fn tests_montgomery_reduction() -> bool { + + // assert(test_montgomery_reduction_small()); + assert(test_montgomery_reduction_random()); + true + +} + +fn test_montgomery_reduction_small() -> bool { + let a: [u64;12] = [10,0,0,0,0,0,0,0,0,0,0,0]; + let res = montgomery_reduction(a); + let aModP: vec384 = vec384{ls: [10,0,0,0,0,0]}; + equals_vec384(res, aModP); + //print_vec384(res); + true +} +fn test_montgomery_reduction_random() -> bool { + + /* + a = 718573336991290032951448074998609563086566731583964696014352685991840357574242396134892012284985388079194282315681159870763888514734256711565361623988 + = [988628306351829, 5278298332222909972, 8614063320694916486, 4063307077606482163, 959683757796537189, 2169871353760194456, 6743270311476307786, 10598342506117936052] + */ + let a: [u64;12] = [10598342506117936052, 6743270311476307786, 2169871353760194456, 959683757796537189, 4063307077606482163, 8614063320694916486, 5278298332222909972, 988628306351829, 0, 0, 0, 0]; + + let ls: [u64;6] = [12961372860169786431, 10261575420116144142, 13643274042195959755, 209306746091908816, 4698088373397879190, 611003071541516788]; + let aModP: vec384 = vec384{ls: ls}; + + let res: vec384 = montgomery_reduction(a); + + equals_vec384(res, aModP); + //print_vec384(res); + true +} + +fn test_multiply_wrap() -> bool { + let a: u64 = 562706585515371056; + let b: u64 = 2854579515609623853; + let res: u64 = multiply_wrap(a, b); + assert(res == 2259604989141998192); + true } \ No newline at end of file diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vec384.sw index 098728d..a05c42a 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vec384.sw @@ -14,7 +14,7 @@ pub struct vec384x { i: vec384 //"imaginary" part } -const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; +pub const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; /* z = -0xd201000000010000 @@ -22,7 +22,7 @@ const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 (381 bits) */ -const BLS12_381_P: vec384 = vec384 { +pub const BLS12_381_P: vec384 = vec384 { ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, @@ -31,7 +31,7 @@ const BLS12_381_P: vec384 = vec384 { 0x1a0111ea397fe69a] }; /// INV = -(P^{-1} mod 2^64) mod 2^64 -const INV: u64 = 0x89f3fffcfffcfffd; +pub const INV: u64 = 0x89f3fffcfffcfffd; // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { @@ -154,7 +154,7 @@ pub fn mac (a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { let B: U128 = U128 {upper: 0, lower: b}; let C: U128 = U128 {upper: 0, lower: c}; let CARRY: U128 = U128 {upper: 0, lower: carry}; - let res: U128 = A + B * C + CARRY; + let res: U128 = A + (B * C) + CARRY; (res.lower, res.upper) } @@ -168,8 +168,8 @@ pub fn multiply_wrap(a: u64, b:u64) -> u64 { // from https://github.com/zkcrypto/bls12_381 pub fn montgomery_reduction(t: [u64;12]) -> vec384 { - let mut k = multiply_wrap(t[0], INV); - + let k = multiply_wrap(t[0], INV); + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); diff --git a/edwards25519/src/main.sw b/edwards25519/src/main.sw index 960a33c..81a1aaa 100644 --- a/edwards25519/src/main.sw +++ b/edwards25519/src/main.sw @@ -35,7 +35,7 @@ use core::num::*; use std::u128::*; fn main() { - // assert(test_helpers()); + // assert(tests_add()); // assert(test_helpers64()); // assert(test_reductions()); @@ -43,10 +43,11 @@ fn main() { // assert(tests_scalar_mult()); // assert(tests_substract()); - // Multiply tests can't run all at the same time - assert(tests_multiply()); + // assert(tests_square()); + // assert(tests_inverse()); //Doesnt' terminate // assert(tests_inverse()); } + From a1a346e541e7f687e3aadbbbd5df213e0368c4be Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 12 Jul 2022 11:37:30 -0600 Subject: [PATCH 081/160] - Added a part of the function signatures from the blst that we should implement - Added some constants - Renamed files to be more in line with blst impl --- bls12-381/src/consts.sw | 18 +++++ bls12-381/src/definitions.sw | 22 ++++++ bls12-381/src/ec1.sw | 67 +++++++++++++++++ bls12-381/src/fields.sw | 106 +++++++++++++++++++++++++++ bls12-381/src/fp.sw | 47 ------------ bls12-381/src/main.sw | 12 +-- bls12-381/src/test_helpers.sw | 4 +- bls12-381/src/{vec384.sw => vect.sw} | 80 +++++++++++++++++++- 8 files changed, 298 insertions(+), 58 deletions(-) create mode 100644 bls12-381/src/consts.sw create mode 100644 bls12-381/src/definitions.sw create mode 100644 bls12-381/src/ec1.sw create mode 100644 bls12-381/src/fields.sw delete mode 100644 bls12-381/src/fp.sw rename bls12-381/src/{vec384.sw => vect.sw} (86%) diff --git a/bls12-381/src/consts.sw b/bls12-381/src/consts.sw new file mode 100644 index 0000000..0a6c840 --- /dev/null +++ b/bls12-381/src/consts.sw @@ -0,0 +1,18 @@ +library consts; + +/* + R = 2**384 % p + = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 +*/ +pub const ONE_MONT_P: [u64; 6] = [ + 0x760900000002fffd, + 0xebf4000bc40c0002, + 0x5f48985753c758ba, + 0x77ce585370525745, + 0x5c071a97a256ec6d, + 0x15f65ec3fa80e493, +]; + +// -1/P +// -p^(-1) mod 2^64 +pub const P0: u64 = 0x89f3fffcfffcfffd; diff --git a/bls12-381/src/definitions.sw b/bls12-381/src/definitions.sw new file mode 100644 index 0000000..f09b9aa --- /dev/null +++ b/bls12-381/src/definitions.sw @@ -0,0 +1,22 @@ +library definitions; + +pub struct fp { + ls: [u64; 6] +} + +pub struct p1 { + x: fp, y: fp, z: fp +} +pub struct p1_affine { + x: fp, y: fp +} + +pub struct BLS12_381_G1 { + value: p1_affine, +} + +pub struct POINTonE1 { + x: [u64; 6], + y: [u64; 6], + z: [u64; 6] +} diff --git a/bls12-381/src/ec1.sw b/bls12-381/src/ec1.sw new file mode 100644 index 0000000..989216b --- /dev/null +++ b/bls12-381/src/ec1.sw @@ -0,0 +1,67 @@ +library ec1; + +dep fields; +dep consts; + +use ::fields::*; +use ::consts::*; + +/* + y^2 = x^3 + B + +B = (4 << 384) % P += 1514052131932888505822357196874193114600527104240479143842906308145652716846165732392247483508051665748635331395571 + +According to Zcash impl this is equal to 4 + */ +const B_E1: vec384 = { + ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, + 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, + 0x8ec9733bbf78ab2f, 0x09d645513d83de7e] +}; + +const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ + /* + (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905 + a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P + = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 + */ + x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75`], + /* + (0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af6 + 00db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 << 384) % P + = 1806233535529883172442092828064561001318757138177058380995827434860385074092408792531060859215838632649768391090801 + */ + y: [0xbaac93d50ce72271, 0x8c22631a7918fd8e, 0xdd595f13570725ce, 0x51ac582950405194, 0xe1c8c3fad0059c0, 0xbbc3efc5008a26a], + z: ONE_MONT_P +}; + +const BLS12_381_NEG_G1: POINTonE1 = { /* negative generator [in Montgomery] */ + /* + (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905 + a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P + = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 + */ + x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75], + /* + (0x114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c9 + 6655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca << 384) % P + = 2196176019691784220975696997671343155238125681761949504336230701263646576398429071911626769913177031388125881468986 + */ + y: [0xff526c2af318883a, 0x92899ce4383b0270, 0x89d7738d9fa9d055, 0x12caf35ba344c12a, 0x3cff1b76964b5317, 0xe44d2ede9774430], + z: ONE_MONT_P +}; + +// TODO: why is mul by b equal to *4? +// value of b is 4 << 384 mod p +pub fn mul_by_b_onE1(in: vec384) -> vec384 { + lshift_fp(in, 2) +} + +pub fn mul_by_4b_onE1(in: vec384) -> vec384 { + lshift_fp(in, 4) +} + +pub fn POINTonE1_cneg(in: vec384, cbit: u64) -> vec384 { + cneg_mod_384(in, cbit, BLS12_381_P) +} \ No newline at end of file diff --git a/bls12-381/src/fields.sw b/bls12-381/src/fields.sw new file mode 100644 index 0000000..8448921 --- /dev/null +++ b/bls12-381/src/fields.sw @@ -0,0 +1,106 @@ +library fields; + +dep vect; +dep consts; + +use vect::*; +use consts::*; +use std::u128::*; + +/* +Reference implementation +https://github.com/supranational/blst +*/ + +// Fp + +pub fn add_fp(a: vec384, b: vec384) -> vec384 { + add_mod_384(a, b, BLS12_381_P) +} + +pub fn sub_fp(a: vec384, b: vec384) -> vec384 { + sub_mod_384(a, b, BLS12_381_P) +} + +pub fn mul_by_3_fp(a: vec384) -> vec384 { + mul_by_3_mod_384(a, BLS12_381_P) +} + +pub fn mul_by_8_fp(a: vec384) -> vec384 { + mul_by_8_mod_384(a, BLS12_381_P) +} + +pub fn lshift_fp(a: vec384, count: u64) -> vec384 { + lshift_mod_384(a, count, BLS12_381_P) +} + +pub fn rshift_fp(a: vec384, count: u64) -> vec384 { + rshift_mod_384(a, count, BLS12_381_P) +} + +pub fn div_by_2_fp(a: vec384) -> vec384 { + div_by_2_mod_384(a, BLS12_381_P) +} + +pub fn mul_fp(a: vec384, b: vec384) -> vec384 { + mul_mont_384(a, b, BLS12_381_P, P0) +} + +pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { + sqr_mont_384(a, b, BLS12_381_P, P0) +} + +// conditional negation +pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { + cneg_mod_384(a, flag, BLS12_381_P) +} + +pub fn from_fp(a: vec384) -> vec384 { + from_mont_384(a, BLS12_381_P, P0) +} + +pub fn redc_fp(a: vec768) -> vec384 { + redc_mont_384(a, BLS12_381_P, P0) +} + +// Fp2 + +pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = add_mod_384(a.r, b.r, BLS12_381_P); + let res_i = add_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { + let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); + let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn mul_by_3_fp2(a: vec384x) -> vec384x { + mul_by_3_mod_384x(a, BLS12_381_P) +} + +pub fn mul_by_8_fp2(a: vec384x) -> vec384x { + mul_by_8_mod_384x(a, BLS12_381_P) +} + +pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { + let res_r = lshift_mod_384(a.r, count, BLS12_381_P); + let res_i = lshift_mod_384(a.i, count, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} + +pub fn mul_fp2(a: vec384x, b: vec384x) -> vec384x { + mul_mont_384x(a, b, BLS12_381_P, P0) +} + +pub fn sqr_fp2(a: vec384x) -> vec384x { + sqr_mont_384x(a, BLS12_381_P, P0) +} + +pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { + let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); + let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); + vec384x { r: res_r, i: res_i } +} \ No newline at end of file diff --git a/bls12-381/src/fp.sw b/bls12-381/src/fp.sw deleted file mode 100644 index 5f16d71..0000000 --- a/bls12-381/src/fp.sw +++ /dev/null @@ -1,47 +0,0 @@ -library fp; - -dep vec384; - -use ::vec384::*; -use std::u128::*; - -/* -Reference implementation -https://github.com/supranational/blst -*/ - -// Fp - -pub fn add_fp(a: vec384, b: vec384) -> vec384 { - add_mod_384(a, b, BLS12_381_P) -} - -pub fn sub_fp(a: vec384, b: vec384) -> vec384 { - sub_mod_384(a, b, BLS12_381_P) -} - -pub fn mul_by_3_fp(a: vec384) -> vec384 { - mul_by_3_mod_384(a, BLS12_381_P) -} - -pub fn mul_by_8_fp(a: vec384) -> vec384 { - mul_by_8_mod_384(a, BLS12_381_P) -} - -pub fn lshift_fp(a: vec384, count: u64) -> vec384 { - lshift_mod_384(a, count, BLS12_381_P) -} - -// Fp2 - -pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { - let res_r = add_mod_384(a.r, b.r, BLS12_381_P); - let res_i = add_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } -} - -pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { - let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); - let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } -} \ No newline at end of file diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index d63b5ea..1d57c63 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -1,12 +1,14 @@ script; -dep vec384; -dep fp; +dep vect; +dep fields; dep test_helpers; +dep consts; -use std::{assert::assert, u128::*}; -use ::fp::*; -use ::vec384::*; +use std::{assert::assert, u128::*, option::*}; +use ::fields::*; +use ::vect::*; +use ::consts::*; use ::test_helpers::*; use std::logging::log; diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 0acdaec..9f1c8d6 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -1,8 +1,8 @@ library test_helpers; -dep vec384; +dep vect; -use vec384::*; +use vect::*; use std::{logging::log, assert::assert}; pub fn print_vec384(a: vec384) { diff --git a/bls12-381/src/vec384.sw b/bls12-381/src/vect.sw similarity index 86% rename from bls12-381/src/vec384.sw rename to bls12-381/src/vect.sw index a05c42a..a4e4875 100644 --- a/bls12-381/src/vec384.sw +++ b/bls12-381/src/vect.sw @@ -1,6 +1,6 @@ -library vec384; +library vect; -use std::u128::*; +use std::{u128::*, vec::Vec}; // Stores field element with max 384 bits // element in fp @@ -8,13 +8,19 @@ pub struct vec384 { ls: [u64; 6], } +pub struct vec768 { + ls: [u64; 12], +} + // element in fp2 pub struct vec384x { r: vec384, //"real" part i: vec384 //"imaginary" part } +//TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; +pub const ZERO_X: vec384x = vec384x { r: ZERO, i: ZERO }; /* z = -0xd201000000010000 @@ -33,6 +39,33 @@ pub const BLS12_381_P: vec384 = vec384 { /// INV = -(P^{-1} mod 2^64) mod 2^64 pub const INV: u64 = 0x89f3fffcfffcfffd; + + +// START FUNCTIONS + + + +pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + +pub fn sqr_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + +pub fn redc_mont_384(a: vec768, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + +pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { + //TODO + ZERO +} + + // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { @@ -227,11 +260,20 @@ pub fn montgomery_reduction(t: [u64;12]) -> vec384 { } +pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { + lshift_mod_384(a, 3, p) +} + pub fn mul_by_3_mod_384(a: vec384, p: vec384) -> vec384 { let temp = add_mod_384(a, a, p); add_mod_384(temp, a, p) } +pub fn cneg_mod_384(a: vec384, flag: u64, p: vec384) -> vec384 { + //TODO + ZERO +} + pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { let mut i = 0; let mut a_temp: vec384 = a; @@ -242,6 +284,36 @@ pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { a_temp } -pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { - lshift_mod_384(a, 3, p) +pub fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { + //TODO + ZERO +} + +pub fn div_by_2_mod_384(a: vec384, p: vec384) -> vec384 { + //TODO + ZERO +} + + + + + +pub fn mul_by_8_mod_384x(a: vec384x, p: vec384) -> vec384x { + //TODO + ZERO_X +} + +pub fn mul_by_3_mod_384x(a: vec384x, p: vec384) -> vec384x { + //TODO + ZERO_X +} + +pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { + //TODO. Has a non-assembly impl in blst in src/no_asm.h + ZERO_X +} + +pub fn sqr_mont_384x(a: vec384x, p: vec384, n0: u64) -> vec384x { + //TODO. Has a non-assembly impl in blst in src/vect.c + ZERO_X } \ No newline at end of file From abf1452d9a25bc9d09fb2ea407887610d2bc7f74 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 12 Jul 2022 18:44:14 -0600 Subject: [PATCH 082/160] - Implemented add_ mod_n, with tests that are equal to add_fp. More test have to be added for other values of n - Added TODOs to indicate where we can work on --- bls12-381/src/ec1.sw | 20 ++++++-- bls12-381/src/fields.sw | 21 +++++++- bls12-381/src/main.sw | 90 +++++++++++++++++++++++++++++++++-- bls12-381/src/test_helpers.sw | 11 ++++- bls12-381/src/vect.sw | 66 ++++++++++++++++++++++++- 5 files changed, 198 insertions(+), 10 deletions(-) diff --git a/bls12-381/src/ec1.sw b/bls12-381/src/ec1.sw index 989216b..adb3a2a 100644 --- a/bls12-381/src/ec1.sw +++ b/bls12-381/src/ec1.sw @@ -52,16 +52,30 @@ const BLS12_381_NEG_G1: POINTonE1 = { /* negative generator [in Montgomery] * z: ONE_MONT_P }; +// TODO TEST // TODO: why is mul by b equal to *4? // value of b is 4 << 384 mod p pub fn mul_by_b_onE1(in: vec384) -> vec384 { lshift_fp(in, 2) } +// TODO TEST pub fn mul_by_4b_onE1(in: vec384) -> vec384 { lshift_fp(in, 4) } -pub fn POINTonE1_cneg(in: vec384, cbit: u64) -> vec384 { - cneg_mod_384(in, cbit, BLS12_381_P) -} \ No newline at end of file +// TODO TEST +pub fn POINTonE1_cneg(p: POINTonE1, cbit: u64) -> vec384 { + cneg_fp(p.y, cbit) +} + +// TODO TEST +pub fn blst_p1_cneg(a: POINTonE1, cbit: u32) -> vec384 { + POINTonE1_cneg(a, is_zero(cbit) ^1) +} + +pub fn POINTonE1_from_Jacobian(in: POINTonE1) -> POINTonE1 { + //TODO + POINTonE1 { x: ONE_MONT_P, y: ONE_MONT_P, z: ONE_MONT_P } +} + diff --git a/bls12-381/src/fields.sw b/bls12-381/src/fields.sw index 8448921..22d8e43 100644 --- a/bls12-381/src/fields.sw +++ b/bls12-381/src/fields.sw @@ -34,31 +34,38 @@ pub fn lshift_fp(a: vec384, count: u64) -> vec384 { lshift_mod_384(a, count, BLS12_381_P) } +//TODO TEST pub fn rshift_fp(a: vec384, count: u64) -> vec384 { rshift_mod_384(a, count, BLS12_381_P) } +//TODO TEST pub fn div_by_2_fp(a: vec384) -> vec384 { div_by_2_mod_384(a, BLS12_381_P) } +//TODO TEST pub fn mul_fp(a: vec384, b: vec384) -> vec384 { mul_mont_384(a, b, BLS12_381_P, P0) } +//TODO TEST pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { sqr_mont_384(a, b, BLS12_381_P, P0) } +//TODO TEST // conditional negation pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { cneg_mod_384(a, flag, BLS12_381_P) } +//TODO TEST pub fn from_fp(a: vec384) -> vec384 { from_mont_384(a, BLS12_381_P, P0) } +//TODO TEST pub fn redc_fp(a: vec768) -> vec384 { redc_mont_384(a, BLS12_381_P, P0) } @@ -77,30 +84,42 @@ pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { vec384x { r: res_r, i: res_i } } +//TODO TEST pub fn mul_by_3_fp2(a: vec384x) -> vec384x { mul_by_3_mod_384x(a, BLS12_381_P) } +//TODO TEST pub fn mul_by_8_fp2(a: vec384x) -> vec384x { mul_by_8_mod_384x(a, BLS12_381_P) } +//TODO TEST pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { let res_r = lshift_mod_384(a.r, count, BLS12_381_P); let res_i = lshift_mod_384(a.i, count, BLS12_381_P); vec384x { r: res_r, i: res_i } } +//TODO TEST pub fn mul_fp2(a: vec384x, b: vec384x) -> vec384x { mul_mont_384x(a, b, BLS12_381_P, P0) } +//TODO TEST pub fn sqr_fp2(a: vec384x) -> vec384x { sqr_mont_384x(a, BLS12_381_P, P0) } +//TODO TEST pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); vec384x { r: res_r, i: res_i } -} \ No newline at end of file +} + +pub fn reciprocal_fp(inp: vec384x) -> vec384x { + //TODO + ZERO_X +} + diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 1d57c63..7a80775 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -5,7 +5,7 @@ dep fields; dep test_helpers; dep consts; -use std::{assert::assert, u128::*, option::*}; +use std::{assert::assert, u128::*, option::*, vec::Vec}; use ::fields::*; use ::vect::*; use ::consts::*; @@ -16,8 +16,9 @@ fn main() { // assert(fp_tests()); // assert(fp2_tests()); // assert(tests_montgomery_reduction()); - assert(test_multiply_wrap()); - assert(test_mac()); + // assert(test_multiply_wrap()); + // assert(test_mac()); + assert(vect_subfunctions_tests()); } fn fp_tests() -> bool { @@ -39,6 +40,16 @@ fn fp2_tests() -> bool { true } +fn vect_subfunctions_tests() -> bool { + // add_mod_n tests. They have the same test values as add_fp + // which should be correct, but of course add_mod_n should do more + assert(test_add_zero_to_zero_addn()); + assert(test_add_zero_to_random_addn()); + assert(test_add_random_to_small_addn()); + + true +} + fn tests_add_fp2() -> bool { // the function should add the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 @@ -219,6 +230,79 @@ fn test_add_zero_to_zero() -> bool { true } +fn get_test_vectors() -> (Vec, Vec) { + let mut zero_vec = ~Vec::new::(); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + (zero_vec, p_vec) +} + +fn test_add_zero_to_zero_addn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_add_zero_to_random_addn() -> bool { + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let (zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_add_random_to_small_addn() -> bool { + let mut small_vec = ~Vec::new::(); + small_vec.push(0x1); + small_vec.push(0x2); + small_vec.push(0x3); + small_vec.push(0x4); + small_vec.push(0x5); + small_vec.push(0x6); + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let mut res_vec = ~Vec::new::(); + res_vec.push(4478030004447473543); + res_vec.push(2814704111667093004); + res_vec.push(15884408734010272161); + res_vec.push(17001047363111187582); + res_vec.push(932823543034528552); + res_vec.push(1051481384684610851); + + let (_, p_vec) = get_test_vectors(); + + let res = add_mod_n(small_vec, random_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + true +} + fn test_add_zero_to_random() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 9f1c8d6..5ff6c73 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -3,7 +3,7 @@ library test_helpers; dep vect; use vect::*; -use std::{logging::log, assert::assert}; +use std::{logging::log, assert::assert, vec::Vec}; pub fn print_vec384(a: vec384) { log(a.ls[0]); @@ -21,4 +21,13 @@ pub fn equals_vec384(a: vec384, b: vec384) { assert(a.ls[3] == b.ls[3]); assert(a.ls[4] == b.ls[4]); assert(a.ls[5] == b.ls[5]); +} + +pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { + let mut i = 0; + while i < n { + assert(unpack_or_0(a.get(i)) == unpack_or_0(a.get(i))); + i += 1; + } + true } \ No newline at end of file diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index a4e4875..d0141d4 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -1,6 +1,6 @@ library vect; -use std::{u128::*, vec::Vec}; +use std::{u128::*, vec::Vec, option::*}; // Stores field element with max 384 bits // element in fp @@ -43,10 +43,59 @@ pub const INV: u64 = 0x89f3fffcfffcfffd; // START FUNCTIONS +pub fn unpack_or_0(x: Option) -> u64 { + match x { + Option::Some(val) => val , + Option::None => 0, + } +} + +pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { + let mut limbx: u64 = 0; + let mut carry: u64 = 0; + let mut tmp = ~Vec::new::(); + let mut i = 0; + while i < n { + let (limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); + tmp.insert(i, limb); + carry = temp_carry; + i += 1; + } + + let mut ret = ~Vec::new::(); + let mut borrow: u64 = 0; + i = 0; + while i < n { + let (limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); + ret.insert(i, limb); + borrow = temp_borrow; + i += 1; + } + + let mask: u64 = borrow * ~u64::max(); + let mut res = ~Vec::new::(); + i = 0; + while i < n { + let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); + res.insert(i, value); + i += 1; + } + res +} pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { - //TODO + //WIP ELENA + // vec384 aa, bb, cc; + + // add_mod_n(aa, a[0], a[1], p, NLIMBS(384)); + // add_mod_n(bb, b[0], b[1], p, NLIMBS(384)); + // mul_mont_n(bb, bb, aa, p, n0, NLIMBS(384)); + // mul_mont_n(aa, a[0], b[0], p, n0, NLIMBS(384)); + // mul_mont_n(cc, a[1], b[1], p, n0, NLIMBS(384)); + // sub_mod_n(ret[0], aa, cc, p, NLIMBS(384)); + // sub_mod_n(ret[1], bb, aa, p, NLIMBS(384)); + // sub_mod_n(ret[1], ret[1], cc, p, NLIMBS(384)); ZERO } @@ -65,6 +114,19 @@ pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { ZERO } +// Original impl: +// static inline bool_t is_zero(limb_t l) +// { return (~l & (l - 1)) >> (LIMB_T_BITS - 1); } +//TODO +pub fn is_zero(l: u64) -> u64 { + // (~l & (l-1)) >> 63 + 0 +} + +pub fn vec_is_zero(a: Vec, num: u64) -> u64 { + //TODO + 0 +} // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { From 0cb248bf4b83cf5b1d16d61dbdd453d195d6067a Mon Sep 17 00:00:00 2001 From: Manish Date: Wed, 13 Jul 2022 19:32:20 +0530 Subject: [PATCH 083/160] montgomery removed --- bls12-381/src/main.sw | 35 ------------------------- bls12-381/src/vect.sw | 60 ------------------------------------------- 2 files changed, 95 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 7a80775..3c9c251 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -15,7 +15,6 @@ use std::logging::log; fn main() { // assert(fp_tests()); // assert(fp2_tests()); - // assert(tests_montgomery_reduction()); // assert(test_multiply_wrap()); // assert(test_mac()); assert(vect_subfunctions_tests()); @@ -651,40 +650,6 @@ fn test_mac() -> bool { true } -fn tests_montgomery_reduction() -> bool { - - // assert(test_montgomery_reduction_small()); - assert(test_montgomery_reduction_random()); - true - -} - -fn test_montgomery_reduction_small() -> bool { - let a: [u64;12] = [10,0,0,0,0,0,0,0,0,0,0,0]; - let res = montgomery_reduction(a); - let aModP: vec384 = vec384{ls: [10,0,0,0,0,0]}; - equals_vec384(res, aModP); - //print_vec384(res); - true -} -fn test_montgomery_reduction_random() -> bool { - - /* - a = 718573336991290032951448074998609563086566731583964696014352685991840357574242396134892012284985388079194282315681159870763888514734256711565361623988 - = [988628306351829, 5278298332222909972, 8614063320694916486, 4063307077606482163, 959683757796537189, 2169871353760194456, 6743270311476307786, 10598342506117936052] - */ - let a: [u64;12] = [10598342506117936052, 6743270311476307786, 2169871353760194456, 959683757796537189, 4063307077606482163, 8614063320694916486, 5278298332222909972, 988628306351829, 0, 0, 0, 0]; - - let ls: [u64;6] = [12961372860169786431, 10261575420116144142, 13643274042195959755, 209306746091908816, 4698088373397879190, 611003071541516788]; - let aModP: vec384 = vec384{ls: ls}; - - let res: vec384 = montgomery_reduction(a); - - equals_vec384(res, aModP); - //print_vec384(res); - true -} - fn test_multiply_wrap() -> bool { let a: u64 = 562706585515371056; let b: u64 = 2854579515609623853; diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index d0141d4..d6c4466 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -261,66 +261,6 @@ pub fn multiply_wrap(a: u64, b:u64) -> u64 { (A*B).lower } -// from https://github.com/zkcrypto/bls12_381 -pub fn montgomery_reduction(t: [u64;12]) -> vec384 { - let k = multiply_wrap(t[0], INV); - - let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); - let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); - let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); - let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); - let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); - let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); - let r6_7: (u64, u64) = adc(t[6], 0, r5.1); - - let k = multiply_wrap(r1.0, INV); - let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); - let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); - let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); - let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); - let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); - - let k = multiply_wrap(r2.0, INV); - let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); - let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); - let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); - let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); - - let k = multiply_wrap(r3.0, INV); - let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); - let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); - let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); - - let k = multiply_wrap(r4.0, INV); - let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); - let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); - let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); - let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); - - let k = multiply_wrap(r5.0, INV); - let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); - let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); - let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); - let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); - let r11_12 = adc(t[11], r10_11.1, r10.1); - - subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) - -} pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { lshift_mod_384(a, 3, p) From 50213dc6eef1092a9744dff6be4cea2f4722b031 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 11:29:15 -0600 Subject: [PATCH 084/160] - Added mult_mon_n with tests. - Note that not all tests can be ran at the same time, gives error outOfGas. - Added to readme how to start fuel-core --- bls12-381/src/main.sw | 454 ++++++++++++++++++++++++++++-------------- bls12-381/src/vect.sw | 95 +++++++++ 2 files changed, 400 insertions(+), 149 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 3c9c251..347d5f6 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -5,7 +5,7 @@ dep fields; dep test_helpers; dep consts; -use std::{assert::assert, u128::*, option::*, vec::Vec}; +use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; use ::vect::*; use ::consts::*; @@ -40,28 +40,53 @@ fn fp2_tests() -> bool { } fn vect_subfunctions_tests() -> bool { + // NOTE: Don't run all at the same time, because will run out of gas + // add_mod_n tests. They have the same test values as add_fp // which should be correct, but of course add_mod_n should do more - assert(test_add_zero_to_zero_addn()); - assert(test_add_zero_to_random_addn()); + // assert(test_add_zero_to_zero_addn()); + // assert(test_add_zero_to_random_addn()); assert(test_add_random_to_small_addn()); + // assert(test_mul_mont_n_by_zero()); + // assert(test_mul_mont_n_zero_by_one()); + // assert(test_mul_mont_n_one_by_one()); + assert(test_mul_mont_n_random_by_one()); + assert(test_mul_mont_n_random_by_random()); true } fn tests_add_fp2() -> bool { // the function should add the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; - let a_1 = vec384x { r: r_1, i: i_1 }; - + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; - let a_2 = vec384x { r: r_2, i: i_2 }; + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; let res = add_fp2(a_1, a_2); @@ -69,32 +94,58 @@ fn tests_add_fp2() -> bool { //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 // i part //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 - equals_vec384(res.r, vec384{ ls:[17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] }); - equals_vec384(res.i, vec384{ ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219]}); + equals_vec384(res.r, vec384 { + ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] + }); + equals_vec384(res.i, vec384 { + ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] + }); true } fn tests_sub_fp2() -> bool { // the function should subtract the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096]}; + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { ls: [8306319196692453748, 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780]}; - let a_1 = vec384x { r: r_1, i: i_1 }; - + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { ls: [16448140995118783999, 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585]}; + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { ls: [1139524850979729662, 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304]}; - let a_2 = vec384x { r: r_2, i: i_2 }; + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; let res = sub_fp2(a_1, a_2); //real //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 //i //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 - equals_vec384(res.r, vec384{ ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376]}); - equals_vec384(res.i, vec384{ ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341]}); + equals_vec384(res.r, vec384 { + ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] + }); + equals_vec384(res.i, vec384 { + ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] + }); true } @@ -115,12 +166,24 @@ fn test_not() -> bool { } fn tests_subtract_wrap() -> bool { - let mut res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 80, upper: 0}); + let mut res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 80, upper: 0 + }); assert(res.lower == 20); assert(res.upper == 0); - res = subtract_wrap(U128 { lower: 100, upper: 0}, U128 { lower: 230, upper: 0}); - let res_should_be = ~U128::max() - U128 { lower: 130, upper: 0}; + res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 230, upper: 0 + }); + let res_should_be = ~U128::max() - U128 { + lower: 130, upper: 0 + }; // 2^128 - 230 = 340282366920938463463374607431768211226 // [18446744073709551486, 18446744073709551615] assert(res.lower == 18446744073709551486); @@ -147,7 +210,7 @@ fn tests_sbb() -> bool { // a-0-1 should give (a-1, 0) let a = 435983458; res = sbb(a, 0, 1); - assert(res.0 == a-1); + assert(res.0 == a - 1); assert(res.1 == 0); true } @@ -161,8 +224,8 @@ fn tests_adc() -> bool { fn test_adc_random() -> bool { let a = 9837491998535547791; let b = 10009796384580774444; - let res:(u64,u64) = adc(a, b, 0); - let a_plus_b: (u64,u64) = (1400544309406770619, 1); + let res: (u64, u64) = adc(a, b, 0); + let a_plus_b: (u64, u64) = (1400544309406770619, 1); assert(res.0 == a_plus_b.0); assert(res.1 == a_plus_b.1); @@ -172,8 +235,8 @@ fn test_adc_random() -> bool { fn test_adc_random_with_carry() -> bool { let a = 9837491998535547791; let b = 10009796384580774444; - let res:(u64,u64) = adc(a, b, 1); - let a_plus_b_and_carry: (u64,u64) = (1400544309406770620, 1); + let res: (u64, u64) = adc(a, b, 1); + let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); assert(res.0 == a_plus_b_and_carry.0); assert(res.1 == a_plus_b_and_carry.1); @@ -187,13 +250,9 @@ fn test_subtract_p() -> bool { } fn test_subtract_p_smaller() -> bool { - let a_smaller_than_p = vec384 { + let a_smaller_than_p = vec384 { ls: [13402431016077863508, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] }; let res = subtract_p(a_smaller_than_p, BLS12_381_P); equals_vec384(res, a_smaller_than_p); @@ -201,15 +260,15 @@ fn test_subtract_p_smaller() -> bool { } fn test_subtract_p_larger() -> bool { - // p+200 - let a_larger_than_p = vec384 { ls: [13402431016077863795, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866]}; + // p+200 + let a_larger_than_p = vec384 { + ls: [13402431016077863795, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; let res = subtract_p(a_larger_than_p, BLS12_381_P); - equals_vec384(res, vec384 { ls: [200,0,0,0,0,0] }); + equals_vec384(res, vec384 { + ls: [200, 0, 0, 0, 0, 0] + }); true } @@ -245,13 +304,100 @@ fn get_test_vectors() -> (Vec, Vec) { p_vec.push(0x64774b84f38512bf); p_vec.push(0x4b1ba7b6434bacd7); p_vec.push(0x1a0111ea397fe69a); - + (zero_vec, p_vec) } +fn test_mul_mont_n_by_zero() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn get_one_vec() -> Vec { + let mut one_vec = ~Vec::new::(); + one_vec.push(1); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec +} + +fn test_mul_mont_n_zero_by_one() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_mul_mont_n_one_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); + equals_vec(res, one_vec, 6); + true +} + + +fn test_mul_mont_n_random_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); +//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r_vec = ~Vec::new::(); + r_vec.push(0x54439c4ae7869f30); + r_vec.push(0xa7fdefad55c032ba); + r_vec.push(0x21282f739c0a15e7); + r_vec.push(0x6cc7a6e8c38430ff); + r_vec.push(0x50db69783b321139); + r_vec.push(0xba78745dadd17a93); + let one_vec = get_one_vec(); + + let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); + equals_vec(res, r_vec, 6); + true +} + +fn test_mul_mont_n_random_by_random() -> bool { + let(_, p_vec) = get_test_vectors(); +//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(0x54439c4ae7869f30); + r1_vec.push(0xa7fdefad55c032ba); + r1_vec.push(0x21282f739c0a15e7); + r1_vec.push(0x6cc7a6e8c38430ff); + r1_vec.push(0x50db69783b321139); + r1_vec.push(0xba78745dadd17a93); +//845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(0xeb6f61c69e4c7eef); + r2_vec.push(0xa70784fb3f9ac549); + r2_vec.push(0x91f41a633e1d9601); + r2_vec.push(0xf89a44e9a52e99e); + r2_vec.push(0x1eb242ddd39638bc); + r2_vec.push(0x57e6ed499f0c7c1); + +//1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + let mut res_vec = ~Vec::new::(); + res_vec.push(0x42863c4b7ea22ad7); + res_vec.push(0x27627bfa644b580d); + res_vec.push(0x16930ecb9e3a308f); + res_vec.push(0xd5802a33c5512d6a); + res_vec.push(0x19591b38f5515036); + res_vec.push(0x7546b2615f748cd); + let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); + equals_vec(res, res_vec, 6); + true +} + fn test_add_zero_to_zero_addn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - + let(zero_vec, p_vec) = get_test_vectors(); + let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); equals_vec(res, zero_vec, 6); true @@ -265,7 +411,7 @@ fn test_add_zero_to_random_addn() -> bool { random_vec.push(0xebefda8057d5747a); random_vec.push(0xcf20e11f0b1c323); random_vec.push(0xe979cbf960fe51d); - let (zero_vec, p_vec) = get_test_vectors(); + let(zero_vec, p_vec) = get_test_vectors(); let res = add_mod_n(random_vec, zero_vec, p_vec, 6); equals_vec(res, random_vec, 6); @@ -295,7 +441,7 @@ fn test_add_random_to_small_addn() -> bool { res_vec.push(932823543034528552); res_vec.push(1051481384684610851); - let (_, p_vec) = get_test_vectors(); + let(_, p_vec) = get_test_vectors(); let res = add_mod_n(small_vec, random_vec, p_vec, 6); equals_vec(res, res_vec, 6); @@ -305,11 +451,7 @@ fn test_add_random_to_small_addn() -> bool { fn test_add_zero_to_random() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; let res: vec384 = add_fp(random, ZERO); equals_vec384(res, random); @@ -319,11 +461,7 @@ fn test_add_zero_to_random() -> bool { fn test_add_random_to_zero() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; /* 4478030004447473542 @@ -340,24 +478,16 @@ fn test_add_random_to_zero() -> bool { fn test_add_random_to_small() -> bool { let small = vec384 { - ls: [0x1, 0x2, 0x3, 0x4, 0x5, 0x6] + ls: [0x1, + 0x2, 0x3, 0x4, 0x5, 0x6] }; let random = vec384 { ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, - 0xdc70c19599cb699e, - 0xebefda8057d5747a, - 0xcf20e11f0b1c323, - 0xe979cbf960fe51d] + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] }; let res: vec384 = add_fp(small, random); equals_vec384(res, vec384 { - ls: [4478030004447473543, - 2814704111667093004, - 15884408734010272161, - 17001047363111187582, - 932823543034528552, - 1051481384684610851] + ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] }); true } @@ -372,18 +502,19 @@ fn test_add_larger_than_p() -> bool { //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] let a = vec384 { ls: [13402431016077863508, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] }; - let b = vec384 { ls: [100,0,0,0,0,0] }; + let b = vec384 { + ls: [100, + 0, 0, 0, 0, 0] + }; -// should be 13 + // should be 13 let res: vec384 = add_fp(a, b); - equals_vec384(res, vec384 {ls: [13,0,0,0,0,0]}); + equals_vec384(res, vec384 { + ls: [13, 0, 0, 0, 0, 0] + }); true } @@ -391,23 +522,15 @@ fn test_add_2_randoms() -> bool { //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] let random_1 = vec384 { ls: [4510245898505151773, - 8849327944066866226, - 11451510199254766964, - 782624411996506985, - 9666712539018543006, - 17492304704872943] + 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] }; -//[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] let random_2 = vec384 { - ls: [8877477209635348035, - 16708328088811667500, - 14014037299927741552, - 1795070958963053268, - 10606788931721547929, - 841903545056265961] - }; -/* + ls: [8877477209635348035, + 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + }; + /* a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 @@ -421,12 +544,9 @@ a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894 a+b< p is true */ let res: vec384 = add_fp(random_1, random_2); - equals_vec384(res, vec384{ ls: [13387723108140499808, - 7110911959168982110, - 7018803425472956901, - 2577695370959560254, - 1826757397030539319, - 859395849761138905] }); + equals_vec384(res, vec384 { + ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] + }); true } @@ -441,11 +561,7 @@ fn test_neg() -> bool { fn test_neg_p() -> bool { let p = vec384 { ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a] + 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] }; let res = neg(p, BLS12_381_P); equals_vec384(res, ZERO); @@ -461,14 +577,13 @@ fn test_neg_1() -> bool { 5412103778470702295, 1873798617647539866] */ - let res = neg(vec384 { ls: [1,0,0,0,0,0] }, BLS12_381_P); + let res = neg(vec384 { + ls: [1, 0, 0, 0, 0, 0] + }, + BLS12_381_P); let p_minus_1 = vec384 { ls: [13402431016077863594, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] }; equals_vec384(res, p_minus_1); @@ -478,18 +593,16 @@ fn test_neg_1() -> bool { fn test_neg_random() -> bool { //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; - // p-r = + // p-r = // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 let res = neg(r, BLS12_381_P); equals_vec384(res, vec384 { - ls: [343185552611564426, - 2882282484148780005, - 6545683898001206309, - 12914691390957992833, - 41210333997197102, - 1273825819919628179] + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] }); true } @@ -511,23 +624,24 @@ fn test_sub_zero_from_zero() -> bool { } fn test_sub_zero_from_random() -> bool { - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res = sub_fp(r, ZERO); equals_vec384(res, r); true } fn test_sub_random_from_zero() -> bool { - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res = sub_fp(ZERO, r); // p-r (is the same as 0-r mod p) equals_vec384(res, vec384 { - ls: [343185552611564426, - 2882282484148780005, - 6545683898001206309, - 12914691390957992833, - 41210333997197102, - 1273825819919628179] + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] }); true } @@ -536,45 +650,67 @@ fn test_sub_random_from_small() -> bool { // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 let small = vec384 { - ls: [1, 2, 3, 4, 5, 6] + ls: [1, + 2, 3, 4, 5, 6] }; //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res: vec384 = sub_fp(small, r); //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - equals_vec384(res, vec384{ ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185]}); + equals_vec384(res, vec384 { + ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + }); true } fn test_sub_2_randoms() -> bool { //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; - //res = + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + //res = //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] let res: vec384 = sub_fp(a, b); - equals_vec384(res, vec384{ ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019]}); + equals_vec384(res, vec384 { + ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + }); true } fn test_sub_2_randoms_reverse() -> bool { // Same a,b from test_sub_2_randoms only subtract the other way around - let a = vec384 {ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194]}; - let b = vec384 {ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174]}; - - //res = + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + + //res = //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p + // => mod p //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] let res: vec384 = sub_fp(b, a); - equals_vec384(res, vec384{ ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846]}); + equals_vec384(res, vec384 { + ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + }); true } @@ -584,11 +720,16 @@ fn tests_mul_by_3_fp() -> bool { equals_vec384(three_times_0, ZERO); // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 - let a = vec384 { ls: [5598198260030196614, 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475]}; + let a = vec384 { + ls: [5598198260030196614, + 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] + }; // a*3 mod p should be //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 let res = mul_by_3_fp(a); - equals_vec384(res, vec384 { ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694]}); + equals_vec384(res, vec384 { + ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] + }); true } @@ -598,11 +739,16 @@ fn tests_mul_by_8_fp() -> bool { equals_vec384(eight_times_0, ZERO); // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 - let a = vec384 { ls: [4748578380656466952, 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211]}; + let a = vec384 { + ls: [4748578380656466952, + 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] + }; // a*8 mod p should be //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 let res = mul_by_8_fp(a); - equals_vec384(res, vec384 { ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227]}); + equals_vec384(res, vec384 { + ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] + }); true } @@ -615,21 +761,31 @@ fn test_lshift_p() -> bool { fn test_1_lshift_p() -> bool { //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 {ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687]}; + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; let res = lshift_fp(r, 1); // 1 leftshift is *2 //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 - equals_vec384(res, vec384{ ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374]}); + equals_vec384(res, vec384 { + ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] + }); true } fn test_250_lshift_p() -> bool { //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 - let a = vec384 { ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937]}; + let a = vec384 { + ls: [13749239540608708580, + 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] + }; // leftshift 250 mod p //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 let res = lshift_fp(a, 250); - equals_vec384(res, vec384 { ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179]}); + equals_vec384(res, vec384 { + ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] + }); true } @@ -638,12 +794,12 @@ fn test_mac() -> bool { let b = 7557322358563246340; let c = 14991082624209354397; - let res = mac(a,b,c,0); + let res = mac(a, b, c, 0); assert(res.0 == 15211181400380206508); assert(res.1 == 6141595689857899799); let carry = 1234555432334; - let res2 = mac(a,b,c,carry); + let res2 = mac(a, b, c, carry); assert(res2.0 == 15211182634935638842); assert(res2.1 == 6141595689857899799); @@ -656,4 +812,4 @@ fn test_multiply_wrap() -> bool { let res: u64 = multiply_wrap(a, b); assert(res == 2259604989141998192); true -} \ No newline at end of file +} diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index d6c4466..ccb02e0 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -57,6 +57,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut i = 0; while i < n { + // sum with carry of a and b. Returns result and new carry let (limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); tmp.insert(i, limb); carry = temp_carry; @@ -67,6 +68,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut borrow: u64 = 0; i = 0; while i < n { + // sum with borrow of a and b. Returns result and new borrow let (limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); ret.insert(i, limb); borrow = temp_borrow; @@ -84,6 +86,97 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { res } +pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { + let mut mx: U128 = U128 { lower: unpack_or_0(b.get(0)), upper: 0}; + let mut hi: U128 = U128 { lower: 0, upper: 0}; + let mut tmp: Vec = ~Vec::new::(); + let mut i = 0; + while i < n { + let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; + let limbx = mx * ai + hi; + tmp.insert(i, limbx.lower); + hi = U128{ lower: limbx.upper, upper: 0}; + i += 1; + } + + mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; + tmp.insert(i, hi.lower); + + let mut carry: u64 = 0; + let mut j = 0; + let mut limbx: U128 = U128 { lower: 0, upper: 0}; + while true { + let p0: U128 = U128 {lower: unpack_or_0(p.get(0)), upper: 0}; + let tmp0: U128 = U128 {lower: unpack_or_0(tmp.get(0)), upper: 0}; + limbx = (mx * p0) + tmp0; + hi = U128{ lower: limbx.upper, upper: 0}; + i = 1; + while i < n { + let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; + let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + limbx = (mx * pi) + tmpi; + tmp.insert( i-1, limbx.lower); + hi = U128{ lower: limbx.upper, upper: 0}; + i += 1; + } + limbx = U128 { lower: unpack_or_0(tmp.get(i)), upper: 0} + (hi + U128{lower: carry, upper: 0}); + tmp.insert(i-1, limbx.lower); + carry = limbx.lower; + + j += 1; + if j == n { + break; + } + + mx = U128 {lower: unpack_or_0(b.get(j)), upper: 0}; + hi = U128 { lower: 0, upper: 0}; + i = 0; + while i < n { + let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; + let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + limbx = (mx * (ai + hi)) + tmpi; + tmp.insert(i, limbx.lower); + hi = U128{ lower: limbx.upper, upper: 0}; + i += 1; + } + + mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; + limbx = hi + U128{lower: carry, upper: 0}; + tmp.insert(i, limbx.lower); + carry = limbx.upper; + } + + let mut borrow: u64 = 0; + i = 0; + let mut ret: Vec = ~Vec::new::(); + while i < n { + let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; + let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + let pi_w_borrow = pi + U128{lower: borrow, upper:0}; + // Prevent underflow. When U256 arithmetic is available we can create sbb_256 + let (sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { + (tmpi - pi_w_borrow, 0) + } else { + (~U128::max() - (pi_w_borrow - tmpi - U128 { lower: 1, upper: 0}), 1) + }; + limbx = sub_res; + borrow = b_res; + ret.insert(i, limbx.lower); + borrow = limbx.upper & 0x1; + i += 1; + } + + let mask: u64 = borrow * ~u64::max(); + i = 0; + let mut res: Vec = ~Vec::new::(); + while i < n { + let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); + res.insert(i, value); + i += 1; + } + res +} + pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { //WIP ELENA // vec384 aa, bb, cc; @@ -128,6 +221,7 @@ pub fn vec_is_zero(a: Vec, num: u64) -> u64 { 0 } +// TODO rewrite without if branch // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { @@ -137,6 +231,7 @@ pub fn subtract_wrap(x: U128, y: U128) -> U128 { } } +// TODO rewrite without if branch // If x >= y: x-y, else max::U64 - (y-x) pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { if y > x { From 11d7039a274738fec0c74a37ed5c7cf4c46d3a43 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 12:12:31 -0600 Subject: [PATCH 085/160] Formatted (forc fmt) --- bls12-381/src/consts.sw | 10 +- bls12-381/src/definitions.sw | 19 ++- bls12-381/src/ec1.sw | 8 +- bls12-381/src/fields.sw | 35 ++-- bls12-381/src/main.sw | 9 +- bls12-381/src/test_helpers.sw | 4 +- bls12-381/src/vect.sw | 295 ++++++++++++++++++++++------------ 7 files changed, 240 insertions(+), 140 deletions(-) diff --git a/bls12-381/src/consts.sw b/bls12-381/src/consts.sw index 0a6c840..18e6433 100644 --- a/bls12-381/src/consts.sw +++ b/bls12-381/src/consts.sw @@ -4,14 +4,8 @@ library consts; R = 2**384 % p = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 */ -pub const ONE_MONT_P: [u64; 6] = [ - 0x760900000002fffd, - 0xebf4000bc40c0002, - 0x5f48985753c758ba, - 0x77ce585370525745, - 0x5c071a97a256ec6d, - 0x15f65ec3fa80e493, -]; +pub const ONE_MONT_P: [u64; +6] = [0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493, ]; // -1/P // -p^(-1) mod 2^64 diff --git a/bls12-381/src/definitions.sw b/bls12-381/src/definitions.sw index f09b9aa..cb81d90 100644 --- a/bls12-381/src/definitions.sw +++ b/bls12-381/src/definitions.sw @@ -1,14 +1,18 @@ library definitions; pub struct fp { - ls: [u64; 6] + ls: [u64; + 6], } pub struct p1 { - x: fp, y: fp, z: fp + x: fp, + y: fp, + z: fp, } pub struct p1_affine { - x: fp, y: fp + x: fp, + y: fp, } pub struct BLS12_381_G1 { @@ -16,7 +20,10 @@ pub struct BLS12_381_G1 { } pub struct POINTonE1 { - x: [u64; 6], - y: [u64; 6], - z: [u64; 6] + x: [u64; + 6], + y: [u64; + 6], + z: [u64; + 6], } diff --git a/bls12-381/src/ec1.sw b/bls12-381/src/ec1.sw index adb3a2a..f3c5bad 100644 --- a/bls12-381/src/ec1.sw +++ b/bls12-381/src/ec1.sw @@ -14,11 +14,7 @@ B = (4 << 384) % P According to Zcash impl this is equal to 4 */ -const B_E1: vec384 = { - ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, - 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, - 0x8ec9733bbf78ab2f, 0x09d645513d83de7e] -}; +const B_E1: vec384 = {ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e]}; const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ /* @@ -26,7 +22,7 @@ const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 */ - x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75`], + x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75], /* (0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af6 00db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 << 384) % P diff --git a/bls12-381/src/fields.sw b/bls12-381/src/fields.sw index 22d8e43..889b35c 100644 --- a/bls12-381/src/fields.sw +++ b/bls12-381/src/fields.sw @@ -30,12 +30,12 @@ pub fn mul_by_8_fp(a: vec384) -> vec384 { mul_by_8_mod_384(a, BLS12_381_P) } -pub fn lshift_fp(a: vec384, count: u64) -> vec384 { +pub fn lshift_fp(a: vec384, count: u64) -> vec384 { lshift_mod_384(a, count, BLS12_381_P) } //TODO TEST -pub fn rshift_fp(a: vec384, count: u64) -> vec384 { +pub fn rshift_fp(a: vec384, count: u64) -> vec384 { rshift_mod_384(a, count, BLS12_381_P) } @@ -45,28 +45,28 @@ pub fn div_by_2_fp(a: vec384) -> vec384 { } //TODO TEST -pub fn mul_fp(a: vec384, b: vec384) -> vec384 { +pub fn mul_fp(a: vec384, b: vec384) -> vec384 { mul_mont_384(a, b, BLS12_381_P, P0) } //TODO TEST -pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { +pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { sqr_mont_384(a, b, BLS12_381_P, P0) } //TODO TEST // conditional negation -pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { +pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { cneg_mod_384(a, flag, BLS12_381_P) } //TODO TEST -pub fn from_fp(a: vec384) -> vec384 { +pub fn from_fp(a: vec384) -> vec384 { from_mont_384(a, BLS12_381_P, P0) } //TODO TEST -pub fn redc_fp(a: vec768) -> vec384 { +pub fn redc_fp(a: vec768) -> vec384 { redc_mont_384(a, BLS12_381_P, P0) } @@ -75,13 +75,19 @@ pub fn redc_fp(a: vec768) -> vec384 { pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { let res_r = add_mod_384(a.r, b.r, BLS12_381_P); let res_i = add_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } //TODO TEST @@ -98,7 +104,10 @@ pub fn mul_by_8_fp2(a: vec384x) -> vec384x { pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { let res_r = lshift_mod_384(a.r, count, BLS12_381_P); let res_i = lshift_mod_384(a.i, count, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } //TODO TEST @@ -115,11 +124,13 @@ pub fn sqr_fp2(a: vec384x) -> vec384x { pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); - vec384x { r: res_r, i: res_i } + vec384x { + r: res_r, + i: res_i, + } } pub fn reciprocal_fp(inp: vec384x) -> vec384x { //TODO ZERO_X } - diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 347d5f6..80a55e4 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -345,10 +345,9 @@ fn test_mul_mont_n_one_by_one() -> bool { true } - fn test_mul_mont_n_random_by_one() -> bool { let(_, p_vec) = get_test_vectors(); -//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r_vec = ~Vec::new::(); r_vec.push(0x54439c4ae7869f30); r_vec.push(0xa7fdefad55c032ba); @@ -365,7 +364,7 @@ fn test_mul_mont_n_random_by_one() -> bool { fn test_mul_mont_n_random_by_random() -> bool { let(_, p_vec) = get_test_vectors(); -//28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); r1_vec.push(0x54439c4ae7869f30); r1_vec.push(0xa7fdefad55c032ba); @@ -373,7 +372,7 @@ fn test_mul_mont_n_random_by_random() -> bool { r1_vec.push(0x6cc7a6e8c38430ff); r1_vec.push(0x50db69783b321139); r1_vec.push(0xba78745dadd17a93); -//845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 let mut r2_vec = ~Vec::new::(); r2_vec.push(0xeb6f61c69e4c7eef); r2_vec.push(0xa70784fb3f9ac549); @@ -382,7 +381,7 @@ fn test_mul_mont_n_random_by_random() -> bool { r2_vec.push(0x1eb242ddd39638bc); r2_vec.push(0x57e6ed499f0c7c1); -//1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 let mut res_vec = ~Vec::new::(); res_vec.push(0x42863c4b7ea22ad7); res_vec.push(0x27627bfa644b580d); diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 5ff6c73..26e0a47 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -3,7 +3,7 @@ library test_helpers; dep vect; use vect::*; -use std::{logging::log, assert::assert, vec::Vec}; +use std::{assert::assert, logging::log, vec::Vec}; pub fn print_vec384(a: vec384) { log(a.ls[0]); @@ -30,4 +30,4 @@ pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { i += 1; } true -} \ No newline at end of file +} diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index ccb02e0..0c37c16 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -1,26 +1,32 @@ library vect; -use std::{u128::*, vec::Vec, option::*}; +use std::{option::*, u128::*, vec::Vec}; // Stores field element with max 384 bits // element in fp pub struct vec384 { - ls: [u64; 6], + ls: [u64; + 6], } pub struct vec768 { - ls: [u64; 12], + ls: [u64; + 12], } // element in fp2 pub struct vec384x { r: vec384, //"real" part - i: vec384 //"imaginary" part + i: vec384, //"imaginary" part } //TODO: remove these. Only for developing and testing atm -pub const ZERO: vec384 = vec384 {ls: [0, 0, 0, 0, 0, 0]}; -pub const ZERO_X: vec384x = vec384x { r: ZERO, i: ZERO }; +pub const ZERO: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0] +}; +pub const ZERO_X: vec384x = vec384x { + r: ZERO, i: ZERO +}; /* z = -0xd201000000010000 @@ -29,24 +35,16 @@ pub const ZERO_X: vec384x = vec384x { r: ZERO, i: ZERO }; (381 bits) */ pub const BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a] + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] }; /// INV = -(P^{-1} mod 2^64) mod 2^64 pub const INV: u64 = 0x89f3fffcfffcfffd; - - // START FUNCTIONS pub fn unpack_or_0(x: Option) -> u64 { match x { - Option::Some(val) => val , - Option::None => 0, + Option::Some(val) => val, Option::None => 0, } } @@ -58,7 +56,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut i = 0; while i < n { // sum with carry of a and b. Returns result and new carry - let (limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); + let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); tmp.insert(i, limb); carry = temp_carry; i += 1; @@ -69,7 +67,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { i = 0; while i < n { // sum with borrow of a and b. Returns result and new borrow - let (limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); + let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); ret.insert(i, limb); borrow = temp_borrow; i += 1; @@ -87,40 +85,75 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { } pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { - let mut mx: U128 = U128 { lower: unpack_or_0(b.get(0)), upper: 0}; - let mut hi: U128 = U128 { lower: 0, upper: 0}; + let mut mx: U128 = U128 { + lower: unpack_or_0(b.get(0)), + upper: 0, + }; + let mut hi: U128 = U128 { + lower: 0, + upper: 0, + }; let mut tmp: Vec = ~Vec::new::(); let mut i = 0; while i < n { - let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; + let ai: U128 = U128 { + lower: unpack_or_0(a.get(i)), upper: 0 + }; let limbx = mx * ai + hi; tmp.insert(i, limbx.lower); - hi = U128{ lower: limbx.upper, upper: 0}; + hi = U128 { + lower: limbx.upper, upper: 0 + }; i += 1; } - mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; + mx = U128 { + lower: n0, upper: 0 + } + * U128 { + lower: unpack_or_0(tmp.get(0)), upper: 0 + }; tmp.insert(i, hi.lower); let mut carry: u64 = 0; let mut j = 0; - let mut limbx: U128 = U128 { lower: 0, upper: 0}; + let mut limbx: U128 = U128 { + lower: 0, + upper: 0, + }; while true { - let p0: U128 = U128 {lower: unpack_or_0(p.get(0)), upper: 0}; - let tmp0: U128 = U128 {lower: unpack_or_0(tmp.get(0)), upper: 0}; + let p0: U128 = U128 { + lower: unpack_or_0(p.get(0)), upper: 0 + }; + let tmp0: U128 = U128 { + lower: unpack_or_0(tmp.get(0)), upper: 0 + }; limbx = (mx * p0) + tmp0; - hi = U128{ lower: limbx.upper, upper: 0}; + hi = U128 { + lower: limbx.upper, upper: 0 + }; i = 1; while i < n { - let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; - let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + let pi: U128 = U128 { + lower: unpack_or_0(p.get(i)), upper: 0 + }; + let tmpi: U128 = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 + }; limbx = (mx * pi) + tmpi; - tmp.insert( i-1, limbx.lower); - hi = U128{ lower: limbx.upper, upper: 0}; - i += 1; + tmp.insert(i - 1, limbx.lower); + hi = U128 { + lower: limbx.upper, upper: 0 + }; + i += 1; + } + limbx = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 } - limbx = U128 { lower: unpack_or_0(tmp.get(i)), upper: 0} + (hi + U128{lower: carry, upper: 0}); - tmp.insert(i-1, limbx.lower); + + (hi + U128 { + lower: carry, upper: 0 + }); + tmp.insert(i - 1, limbx.lower); carry = limbx.lower; j += 1; @@ -128,20 +161,37 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec break; } - mx = U128 {lower: unpack_or_0(b.get(j)), upper: 0}; - hi = U128 { lower: 0, upper: 0}; + mx = U128 { + lower: unpack_or_0(b.get(j)), upper: 0 + }; + hi = U128 { + lower: 0, upper: 0 + }; i = 0; while i < n { - let ai: U128 = U128 {lower: unpack_or_0(a.get(i)), upper: 0}; - let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; + let ai: U128 = U128 { + lower: unpack_or_0(a.get(i)), upper: 0 + }; + let tmpi: U128 = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 + }; limbx = (mx * (ai + hi)) + tmpi; tmp.insert(i, limbx.lower); - hi = U128{ lower: limbx.upper, upper: 0}; + hi = U128 { + lower: limbx.upper, upper: 0 + }; i += 1; } - mx = U128 { lower: n0, upper: 0} * U128 { lower: unpack_or_0(tmp.get(0)), upper: 0}; - limbx = hi + U128{lower: carry, upper: 0}; + mx = U128 { + lower: n0, upper: 0 + } + * U128 { + lower: unpack_or_0(tmp.get(0)), upper: 0 + }; + limbx = hi + U128 { + lower: carry, upper: 0 + }; tmp.insert(i, limbx.lower); carry = limbx.upper; } @@ -150,14 +200,22 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec i = 0; let mut ret: Vec = ~Vec::new::(); while i < n { - let pi: U128 = U128 {lower: unpack_or_0(p.get(i)), upper: 0}; - let tmpi: U128 = U128 {lower: unpack_or_0(tmp.get(i)), upper: 0}; - let pi_w_borrow = pi + U128{lower: borrow, upper:0}; + let pi: U128 = U128 { + lower: unpack_or_0(p.get(i)), upper: 0 + }; + let tmpi: U128 = U128 { + lower: unpack_or_0(tmp.get(i)), upper: 0 + }; + let pi_w_borrow = pi + U128 { + lower: borrow, upper: 0 + }; // Prevent underflow. When U256 arithmetic is available we can create sbb_256 - let (sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { + let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { (tmpi - pi_w_borrow, 0) } else { - (~U128::max() - (pi_w_borrow - tmpi - U128 { lower: 1, upper: 0}), 1) + (~U128::max() - (pi_w_borrow - tmpi - U128 { + lower: 1, upper: 0 + }), 1) }; limbx = sub_res; borrow = b_res; @@ -212,7 +270,7 @@ pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { // { return (~l & (l - 1)) >> (LIMB_T_BITS - 1); } //TODO pub fn is_zero(l: u64) -> u64 { - // (~l & (l-1)) >> 63 + // (~l & (l-1)) >> 63 0 } @@ -225,7 +283,9 @@ pub fn vec_is_zero(a: Vec, num: u64) -> u64 { // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { - ~U128::max() - (y - x - U128 { lower: 1, upper: 0}) + ~U128::max() - (y - x - U128 { + lower: 1, upper: 0 + }) } else { x - y } @@ -243,9 +303,18 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { /// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = U128 { lower: a, upper: 0}; - let b_128: U128 = U128 { lower: b, upper: 0}; - let borrow_128: U128 = U128 { lower: borrow, upper: 0}; + let a_128: U128 = U128 { + lower: a, + upper: 0, + }; + let b_128: U128 = U128 { + lower: b, + upper: 0, + }; + let borrow_128: U128 = U128 { + lower: borrow, + upper: 0, + }; let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); (res.lower, res.upper >> 63) //(result, borrow) @@ -257,13 +326,13 @@ pub fn not(input: u64) -> u64 { // from https://github.com/zkcrypto/bls12_381 // If a >= p, return a-p, else return a -pub fn subtract_p(a: vec384 , p: vec384) -> vec384 { - let (r0, borrow) = sbb(a.ls[0], p.ls[0], 0); - let (r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); - let (r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); - let (r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); - let (r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); - let (r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); +pub fn subtract_p(a: vec384, p: vec384) -> vec384 { + let(r0, borrow) = sbb(a.ls[0], p.ls[0], 0); + let(r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); + let(r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); + let(r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); + let(r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); + let(r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); // If underflow occurred on the final limb, borrow = 1, otherwise // borrow = 0. We convert it into a mask. @@ -275,43 +344,58 @@ pub fn subtract_p(a: vec384 , p: vec384) -> vec384 { let r4 = (a.ls[4] & mask) | (r4 & not(mask)); let r5 = (a.ls[5] & mask) | (r5 & not(mask)); - vec384{ ls: [r0, r1, r2, r3, r4, r5]} + vec384 { + ls: [r0, + r1, r2, r3, r4, r5] + } } - + //TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? //returns sum with carry of a and b pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - let a_128 :U128 = U128 { upper: 0, lower: a }; - let b_128 :U128 = U128 { upper: 0, lower: b }; - let c_128: U128 = U128 { upper: 0, lower: carry }; + let a_128: U128 = U128 { + upper: 0, + lower: a, + }; + let b_128: U128 = U128 { + upper: 0, + lower: b, + }; + let c_128: U128 = U128 { + upper: 0, + lower: carry, + }; let sum: u64 = (a_128 + b_128 + c_128).lower; - let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; + let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; (sum, carry_res) } // from https://github.com/zkcrypto/bls12_381 pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { - let (d0, carry) = adc(a.ls[0], b.ls[0], 0); - let (d1, carry) = adc(a.ls[1], b.ls[1], carry); - let (d2, carry) = adc(a.ls[2], b.ls[2], carry); - let (d3, carry) = adc(a.ls[3], b.ls[3], carry); - let (d4, carry) = adc(a.ls[4], b.ls[4], carry); - let (d5, _) = adc(a.ls[5], b.ls[5], carry); + let(d0, carry) = adc(a.ls[0], b.ls[0], 0); + let(d1, carry) = adc(a.ls[1], b.ls[1], carry); + let(d2, carry) = adc(a.ls[2], b.ls[2], carry); + let(d3, carry) = adc(a.ls[3], b.ls[3], carry); + let(d4, carry) = adc(a.ls[4], b.ls[4], carry); + let(d5, _) = adc(a.ls[5], b.ls[5], carry); //subtract p if needed - subtract_p(vec384{ ls: [d0, d1, d2, d3, d4, d5] }, p) + subtract_p(vec384 { + ls: [d0, d1, d2, d3, d4, d5] + }, + p) } // from https://github.com/zkcrypto/bls12_381 pub fn neg(a: vec384, p: vec384) -> vec384 { - let (d0, borrow) = sbb(p.ls[0], a.ls[0], 0); - let (d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); - let (d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); - let (d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); - let (d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); - let (d5, _) = sbb(p.ls[5], a.ls[5], borrow); + let(d0, borrow) = sbb(p.ls[0], a.ls[0], 0); + let(d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); + let(d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); + let(d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); + let(d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); + let(d5, _) = sbb(p.ls[5], a.ls[5], borrow); // We need a mask that's 0 when a==p and 2^65-1 otherwise // TODO improve this @@ -324,14 +408,10 @@ pub fn neg(a: vec384, p: vec384) -> vec384 { let mask = subtract_wrap_64(a_is_p, 1); - vec384{ ls: [ - d0 & mask, - d1 & mask, - d2 & mask, - d3 & mask, - d4 & mask, - d5 & mask, - ]} + vec384 { + ls: [d0 & mask, + d1 & mask, d2 & mask, d3 & mask, d4 & mask, d5 & mask, ] + } } pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { @@ -339,24 +419,41 @@ pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { } //returns the result and new carry of a + b*c + carry -pub fn mac (a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { - let A: U128 = U128 {upper: 0, lower: a}; - let B: U128 = U128 {upper: 0, lower: b}; - let C: U128 = U128 {upper: 0, lower: c}; - let CARRY: U128 = U128 {upper: 0, lower: carry}; +pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let A: U128 = U128 { + upper: 0, + lower: a, + }; + let B: U128 = U128 { + upper: 0, + lower: b, + }; + let C: U128 = U128 { + upper: 0, + lower: c, + }; + let CARRY: U128 = U128 { + upper: 0, + lower: carry, + }; let res: U128 = A + (B * C) + CARRY; (res.lower, res.upper) } -//returns a*b mod(2^64) -pub fn multiply_wrap(a: u64, b:u64) -> u64 { - let A: U128 = U128{upper: 0, lower: a}; - let B: U128 = U128{upper: 0, lower: b}; +//returns a*b mod(2^64) +pub fn multiply_wrap(a: u64, b: u64) -> u64 { + let A: U128 = U128 { + upper: 0, + lower: a, + }; + let B: U128 = U128 { + upper: 0, + lower: b, + }; - (A*B).lower + (A * B).lower } - pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { lshift_mod_384(a, 3, p) } @@ -391,10 +488,6 @@ pub fn div_by_2_mod_384(a: vec384, p: vec384) -> vec384 { ZERO } - - - - pub fn mul_by_8_mod_384x(a: vec384x, p: vec384) -> vec384x { //TODO ZERO_X @@ -413,4 +506,4 @@ pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { pub fn sqr_mont_384x(a: vec384x, p: vec384, n0: u64) -> vec384x { //TODO. Has a non-assembly impl in blst in src/vect.c ZERO_X -} \ No newline at end of file +} From a7c3cc3bc74a07cd8c3b51df4f1f3816f58df414 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 14:25:18 -0600 Subject: [PATCH 086/160] Added sub_mod_n with tests --- bls12-381/src/main.sw | 160 ++++++++++++++++++++++++++++++++++++++++++ bls12-381/src/vect.sw | 25 +++++++ 2 files changed, 185 insertions(+) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 80a55e4..c7505d6 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -53,6 +53,14 @@ fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_one_by_one()); assert(test_mul_mont_n_random_by_one()); assert(test_mul_mont_n_random_by_random()); + + // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added + // assert(test_sub_zero_from_zero_subn()); + // assert(test_sub_zero_from_random_subn()); + // assert(test_sub_random_from_zero_subn()); + // assert(test_sub_random_from_small_subn()); + assert(test_sub_2_randoms_subn()); + assert(test_sub_2_randoms_reverse_subn()); true } @@ -447,6 +455,158 @@ fn test_add_random_to_small_addn() -> bool { true } +fn test_sub_zero_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_sub_zero_from_random_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + + let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_sub_random_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(13059245463466299169); + random_vec.push(17774603101077980186); + random_vec.push(889990675562875390); + random_vec.push(12771390643166271294); + random_vec.push(5370893444473505192); + random_vec.push(599972797727911687); + + let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); + // p-r (is the same as 0-r mod p) + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564426); + res_vec.push(2882282484148780005); + res_vec.push(6545683898001206309); + res_vec.push(12914691390957992833); + res_vec.push(41210333997197102); + res_vec.push(1273825819919628179); + equals_vec(res, res_vec, 6); + true +} + +fn test_sub_random_from_small_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let mut small_vec = ~Vec::new::(); + small_vec.push(1); + small_vec.push(2); + small_vec.push(3); + small_vec.push(4); + small_vec.push(5); + small_vec.push(6); + + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let mut r_vec = ~Vec::new::(); + r_vec.push(13059245463466299169); + r_vec.push(17774603101077980186); + r_vec.push(889990675562875390); + r_vec.push(12771390643166271294); + r_vec.push(5370893444473505192); + r_vec.push(599972797727911687); + + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564427); + res_vec.push(2882282484148780007); + res_vec.push(6545683898001206312); + res_vec.push(12914691390957992837); + res_vec.push(41210333997197107); + res_vec.push(1273825819919628185); + + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + let res = sub_mod_n(small_vec, r_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn get_r1_r2_vecs() -> (Vec, Vec) { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let mut r1_vec = ~Vec::new::(); + r1_vec.push(10587454305359941416); + r1_vec.push(4615625447881587853); + r1_vec.push(9368308553698906485); + r1_vec.push(9494054596162055604); + r1_vec.push(377309137954328098); + r1_vec.push(766262085408033194); + + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let mut r2_vec = ~Vec::new::(); + r2_vec.push(13403040667047958534); + r2_vec.push(405585388298286396); + r2_vec.push(7295341050629342949); + r2_vec.push(1749456428444609784); + r2_vec.push(1856600841951774635); + r2_vec.push(296809876162753174); + + (r1_vec, r2_vec) +} + +fn test_sub_2_randoms_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let mut res_vec = ~Vec::new::(); + res_vec.push(15631157712021534498); + res_vec.push(4210040059583301456); + res_vec.push(2072967503069563536); + res_vec.push(7744598167717445820); + res_vec.push(16967452369712105079); + res_vec.push(469452209245280019); + + let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn test_sub_2_randoms_reverse_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let mut res_vec = ~Vec::new::(); + res_vec.push(16218017377765880713); + res_vec.push(16446845525643458734); + res_vec.push(5362707070494518163); + res_vec.push(17941483866406818307); + res_vec.push(6891395482468148831); + res_vec.push(1404346408402259846); + + let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + fn test_add_zero_to_random() -> bool { let random = vec384 { ls: [0x3e2528903ca1ef86, diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 0c37c16..f47bf1d 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -235,6 +235,31 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { + let mut limbx: u64 = 0; + let mut borrow: u64 = 0; + let mut i = 0; + let mut ret = ~Vec::new::(); + + while i < n { + let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), borrow); + ret.insert(i, limb); + borrow = temp_borrow; + i += 1; + } + + let mask: u64 = borrow * ~u64::max(); + let mut res = ~Vec::new::(); + let mut carry: u64 = 0; + while i < n { + let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(ret.get(i)), unpack_or_0(p.get(i)) & mask, carry); + res.insert(i, limb); + carry = temp_carry; + i += 1; + } + res +} + pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { //WIP ELENA // vec384 aa, bb, cc; From 79627b6ef882e28a964bd4eb27ca36fd3fd73c7b Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 16:06:26 -0600 Subject: [PATCH 087/160] Reorganized and split up tests in multiple files for clearity --- bls12-381/src/main.sw | 941 +----------------- bls12-381/src/tests/tests_helpers.sw | 295 ++++++ bls12-381/src/tests/tests_vect_fp.sw | 214 ++++ bls12-381/src/tests/tests_vect_fp2.sw | 106 ++ .../src/tests/tests_vect_subfunctions.sw | 344 +++++++ 5 files changed, 971 insertions(+), 929 deletions(-) create mode 100644 bls12-381/src/tests/tests_helpers.sw create mode 100644 bls12-381/src/tests/tests_vect_fp.sw create mode 100644 bls12-381/src/tests/tests_vect_fp2.sw create mode 100644 bls12-381/src/tests/tests_vect_subfunctions.sw diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index c7505d6..1d75162 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -4,6 +4,10 @@ dep vect; dep fields; dep test_helpers; dep consts; +dep tests/tests_vect_fp; +dep tests/tests_vect_fp2; +dep tests/tests_vect_subfunctions; +dep tests/tests_helpers; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -12,940 +16,19 @@ use ::consts::*; use ::test_helpers::*; use std::logging::log; +use ::tests_vect_fp::fp_tests; +use ::tests_vect_fp2::fp2_tests; +use ::tests_vect_subfunctions::vect_subfunctions_tests; +use ::tests_helpers::test_helpers; + fn main() { + log(78); // assert(fp_tests()); // assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); - assert(vect_subfunctions_tests()); -} - -fn fp_tests() -> bool { - // Don't run all tests at the same time... - - // assert(test_add_fp()); - // assert(test_sub_fp()); - // assert(test_helpers()); - assert(tests_mul_by_3_fp()); - assert(tests_mul_by_8_fp()); - assert(test_lshift_p()); - - true -} - -fn fp2_tests() -> bool { - assert(tests_add_fp2()); - assert(tests_sub_fp2()); - true -} - -fn vect_subfunctions_tests() -> bool { - // NOTE: Don't run all at the same time, because will run out of gas - - // add_mod_n tests. They have the same test values as add_fp - // which should be correct, but of course add_mod_n should do more - // assert(test_add_zero_to_zero_addn()); - // assert(test_add_zero_to_random_addn()); - assert(test_add_random_to_small_addn()); - - // assert(test_mul_mont_n_by_zero()); - // assert(test_mul_mont_n_zero_by_one()); - // assert(test_mul_mont_n_one_by_one()); - assert(test_mul_mont_n_random_by_one()); - assert(test_mul_mont_n_random_by_random()); - - // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added - // assert(test_sub_zero_from_zero_subn()); - // assert(test_sub_zero_from_random_subn()); - // assert(test_sub_random_from_zero_subn()); - // assert(test_sub_random_from_small_subn()); - assert(test_sub_2_randoms_subn()); - assert(test_sub_2_randoms_reverse_subn()); - true -} - -fn tests_add_fp2() -> bool { - // the function should add the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; - - //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { - ls: [16448140995118783999, - 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] - }; - //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { - ls: [1139524850979729662, - 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] - }; - let a_2 = vec384x { - r: r_2, - i: i_2, - }; - - let res = add_fp2(a_1, a_2); - - // real part - //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 - // i part - //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 - equals_vec384(res.r, vec384 { - ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] - }); - equals_vec384(res.i, vec384 { - ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] - }); - true -} - -fn tests_sub_fp2() -> bool { - // the function should subtract the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; - - //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { - ls: [16448140995118783999, - 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] - }; - //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { - ls: [1139524850979729662, - 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] - }; - let a_2 = vec384x { - r: r_2, - i: i_2, - }; - - let res = sub_fp2(a_1, a_2); - //real - //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 - //i - //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 - equals_vec384(res.r, vec384 { - ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] - }); - equals_vec384(res.i, vec384 { - ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] - }); - true -} - -fn test_helpers() -> bool { - assert(test_not()); - assert(tests_subtract_wrap()); - assert(tests_sbb()); - assert(tests_adc()); - assert(test_neg()); - assert(test_subtract_p()); - true -} - -fn test_not() -> bool { - let res = not(18417751708719972248); - assert(res == 28992364989579367); - true -} - -fn tests_subtract_wrap() -> bool { - let mut res = subtract_wrap(U128 { - lower: 100, upper: 0 - }, - U128 { - lower: 80, upper: 0 - }); - assert(res.lower == 20); - assert(res.upper == 0); - - res = subtract_wrap(U128 { - lower: 100, upper: 0 - }, - U128 { - lower: 230, upper: 0 - }); - let res_should_be = ~U128::max() - U128 { - lower: 130, upper: 0 - }; - // 2^128 - 230 = 340282366920938463463374607431768211226 - // [18446744073709551486, 18446744073709551615] - assert(res.lower == 18446744073709551486); - assert(res.upper == 18446744073709551615); - true -} - -fn tests_sbb() -> bool { - // 0-0-0 should give (0,0) - let mut res = sbb(0, 0, 0); - assert(res.0 == 0); - assert(res.1 == 0); - - // 0-1-0 should give (2^64 -1, 1) - res = sbb(0, 1, 0); - assert(res.0 == ~u64::max()); - assert(res.1 == 1); - - // 0-1-1 should give (2^64 -2, 1) - res = sbb(0, 1, 1); - assert(res.0 == ~u64::max() - 1); - assert(res.1 == 1); - - // a-0-1 should give (a-1, 0) - let a = 435983458; - res = sbb(a, 0, 1); - assert(res.0 == a - 1); - assert(res.1 == 0); - true -} - -fn tests_adc() -> bool { - assert(test_adc_random()); - assert(test_adc_random_with_carry()); - true -} - -fn test_adc_random() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res: (u64, u64) = adc(a, b, 0); - let a_plus_b: (u64, u64) = (1400544309406770619, 1); - - assert(res.0 == a_plus_b.0); - assert(res.1 == a_plus_b.1); - true -} - -fn test_adc_random_with_carry() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res: (u64, u64) = adc(a, b, 1); - let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); - - assert(res.0 == a_plus_b_and_carry.0); - assert(res.1 == a_plus_b_and_carry.1); - true -} - -fn test_subtract_p() -> bool { - assert(test_subtract_p_smaller()); - assert(test_subtract_p_larger()); - true -} - -fn test_subtract_p_smaller() -> bool { - let a_smaller_than_p = vec384 { - ls: [13402431016077863508, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - let res = subtract_p(a_smaller_than_p, BLS12_381_P); - equals_vec384(res, a_smaller_than_p); - true -} - -fn test_subtract_p_larger() -> bool { - // p+200 - let a_larger_than_p = vec384 { - ls: [13402431016077863795, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - let res = subtract_p(a_larger_than_p, BLS12_381_P); - equals_vec384(res, vec384 { - ls: [200, 0, 0, 0, 0, 0] - }); - true -} - -fn test_add_fp() -> bool { - assert(test_add_zero_to_zero()); - assert(test_add_zero_to_random()); - assert(test_add_random_to_zero()); - assert(test_add_random_to_small()); - assert(test_add_larger_than_p()); - assert(test_add_2_randoms()); - true -} - -fn test_add_zero_to_zero() -> bool { - let res: vec384 = add_fp(ZERO, ZERO); - equals_vec384(res, ZERO); - true -} - -fn get_test_vectors() -> (Vec, Vec) { - let mut zero_vec = ~Vec::new::(); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - - let mut p_vec = ~Vec::new::(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - (zero_vec, p_vec) -} - -fn test_mul_mont_n_by_zero() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn get_one_vec() -> Vec { - let mut one_vec = ~Vec::new::(); - one_vec.push(1); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec -} - -fn test_mul_mont_n_zero_by_one() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - let one_vec = get_one_vec(); - - let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_mul_mont_n_one_by_one() -> bool { - let(_, p_vec) = get_test_vectors(); - let one_vec = get_one_vec(); - - let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); - equals_vec(res, one_vec, 6); - true -} - -fn test_mul_mont_n_random_by_one() -> bool { - let(_, p_vec) = get_test_vectors(); - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r_vec = ~Vec::new::(); - r_vec.push(0x54439c4ae7869f30); - r_vec.push(0xa7fdefad55c032ba); - r_vec.push(0x21282f739c0a15e7); - r_vec.push(0x6cc7a6e8c38430ff); - r_vec.push(0x50db69783b321139); - r_vec.push(0xba78745dadd17a93); - let one_vec = get_one_vec(); - - let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); - equals_vec(res, r_vec, 6); - true -} - -fn test_mul_mont_n_random_by_random() -> bool { - let(_, p_vec) = get_test_vectors(); - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new::(); - r1_vec.push(0x54439c4ae7869f30); - r1_vec.push(0xa7fdefad55c032ba); - r1_vec.push(0x21282f739c0a15e7); - r1_vec.push(0x6cc7a6e8c38430ff); - r1_vec.push(0x50db69783b321139); - r1_vec.push(0xba78745dadd17a93); - //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new::(); - r2_vec.push(0xeb6f61c69e4c7eef); - r2_vec.push(0xa70784fb3f9ac549); - r2_vec.push(0x91f41a633e1d9601); - r2_vec.push(0xf89a44e9a52e99e); - r2_vec.push(0x1eb242ddd39638bc); - r2_vec.push(0x57e6ed499f0c7c1); - - //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 - let mut res_vec = ~Vec::new::(); - res_vec.push(0x42863c4b7ea22ad7); - res_vec.push(0x27627bfa644b580d); - res_vec.push(0x16930ecb9e3a308f); - res_vec.push(0xd5802a33c5512d6a); - res_vec.push(0x19591b38f5515036); - res_vec.push(0x7546b2615f748cd); - let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); - equals_vec(res, res_vec, 6); - true -} - -fn test_add_zero_to_zero_addn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_add_zero_to_random_addn() -> bool { - let mut random_vec = ~Vec::new::(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - let(zero_vec, p_vec) = get_test_vectors(); - - let res = add_mod_n(random_vec, zero_vec, p_vec, 6); - equals_vec(res, random_vec, 6); - true -} - -fn test_add_random_to_small_addn() -> bool { - let mut small_vec = ~Vec::new::(); - small_vec.push(0x1); - small_vec.push(0x2); - small_vec.push(0x3); - small_vec.push(0x4); - small_vec.push(0x5); - small_vec.push(0x6); - let mut random_vec = ~Vec::new::(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - let mut res_vec = ~Vec::new::(); - res_vec.push(4478030004447473543); - res_vec.push(2814704111667093004); - res_vec.push(15884408734010272161); - res_vec.push(17001047363111187582); - res_vec.push(932823543034528552); - res_vec.push(1051481384684610851); - - let(_, p_vec) = get_test_vectors(); - - let res = add_mod_n(small_vec, random_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - true -} - -fn test_sub_zero_from_zero_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_sub_zero_from_random_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let mut random_vec = ~Vec::new::(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - - let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); - equals_vec(res, random_vec, 6); - true -} - -fn test_sub_random_from_zero_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let mut random_vec = ~Vec::new::(); - random_vec.push(13059245463466299169); - random_vec.push(17774603101077980186); - random_vec.push(889990675562875390); - random_vec.push(12771390643166271294); - random_vec.push(5370893444473505192); - random_vec.push(599972797727911687); - - let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); - // p-r (is the same as 0-r mod p) - let mut res_vec = ~Vec::new::(); - res_vec.push(343185552611564426); - res_vec.push(2882282484148780005); - res_vec.push(6545683898001206309); - res_vec.push(12914691390957992833); - res_vec.push(41210333997197102); - res_vec.push(1273825819919628179); - equals_vec(res, res_vec, 6); - true -} - -fn test_sub_random_from_small_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 - //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let mut small_vec = ~Vec::new::(); - small_vec.push(1); - small_vec.push(2); - small_vec.push(3); - small_vec.push(4); - small_vec.push(5); - small_vec.push(6); - - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let mut r_vec = ~Vec::new::(); - r_vec.push(13059245463466299169); - r_vec.push(17774603101077980186); - r_vec.push(889990675562875390); - r_vec.push(12771390643166271294); - r_vec.push(5370893444473505192); - r_vec.push(599972797727911687); - - let mut res_vec = ~Vec::new::(); - res_vec.push(343185552611564427); - res_vec.push(2882282484148780007); - res_vec.push(6545683898001206312); - res_vec.push(12914691390957992837); - res_vec.push(41210333997197107); - res_vec.push(1273825819919628185); - - //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 - let res = sub_mod_n(small_vec, r_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn get_r1_r2_vecs() -> (Vec, Vec) { - //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 - //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let mut r1_vec = ~Vec::new::(); - r1_vec.push(10587454305359941416); - r1_vec.push(4615625447881587853); - r1_vec.push(9368308553698906485); - r1_vec.push(9494054596162055604); - r1_vec.push(377309137954328098); - r1_vec.push(766262085408033194); - - //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 - //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let mut r2_vec = ~Vec::new::(); - r2_vec.push(13403040667047958534); - r2_vec.push(405585388298286396); - r2_vec.push(7295341050629342949); - r2_vec.push(1749456428444609784); - r2_vec.push(1856600841951774635); - r2_vec.push(296809876162753174); - - (r1_vec, r2_vec) -} - -fn test_sub_2_randoms_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); - - //res = - //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let mut res_vec = ~Vec::new::(); - res_vec.push(15631157712021534498); - res_vec.push(4210040059583301456); - res_vec.push(2072967503069563536); - res_vec.push(7744598167717445820); - res_vec.push(16967452369712105079); - res_vec.push(469452209245280019); - - let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn test_sub_2_randoms_reverse_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); - - //res = - //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p - //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 - //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let mut res_vec = ~Vec::new::(); - res_vec.push(16218017377765880713); - res_vec.push(16446845525643458734); - res_vec.push(5362707070494518163); - res_vec.push(17941483866406818307); - res_vec.push(6891395482468148831); - res_vec.push(1404346408402259846); - - let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn test_add_zero_to_random() -> bool { - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - let res: vec384 = add_fp(random, ZERO); - equals_vec384(res, random); - true -} - -fn test_add_random_to_zero() -> bool { - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - /* -4478030004447473542 -2814704111667093002 -15884408734010272158 -17001047363111187578 -932823543034528547 -1051481384684610845 - */ - let res: vec384 = add_fp(ZERO, random); - equals_vec384(res, random); - true -} - -fn test_add_random_to_small() -> bool { - let small = vec384 { - ls: [0x1, - 0x2, 0x3, 0x4, 0x5, 0x6] - }; - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - let res: vec384 = add_fp(small, random); - equals_vec384(res, vec384 { - ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] - }); - true -} - -fn test_add_larger_than_p() -> bool { - /* - 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 - + - 100 - is a little bit larger than p - */ - //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - let a = vec384 { - ls: [13402431016077863508, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - - let b = vec384 { - ls: [100, - 0, 0, 0, 0, 0] - }; - - // should be 13 - let res: vec384 = add_fp(a, b); - equals_vec384(res, vec384 { - ls: [13, 0, 0, 0, 0, 0] - }); - true -} - -fn test_add_2_randoms() -> bool { - //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] - let random_1 = vec384 { - ls: [4510245898505151773, - 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] - }; - - //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] - let random_2 = vec384 { - ls: [8877477209635348035, - 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] - }; - /* -a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 -b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 -a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 -[13387723108140499808, -7110911959168982110, -7018803425472956901, -2577695370959560254, -1826757397030539319, -859395849761138905] - -a+b< p is true -*/ - let res: vec384 = add_fp(random_1, random_2); - equals_vec384(res, vec384 { - ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] - }); - true -} - -fn test_neg() -> bool { - assert(test_neg_p()); - assert(test_neg_1()); - assert(test_neg_random()); - true -} - -// neg(p, p) should result in 0 -fn test_neg_p() -> bool { - let p = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] - }; - let res = neg(p, BLS12_381_P); - equals_vec384(res, ZERO); - true -} - -fn test_neg_1() -> bool { - /* p (=BLS12_381_P) - [13402431016077863595, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] - */ - let res = neg(vec384 { - ls: [1, 0, 0, 0, 0, 0] - }, - BLS12_381_P); - let p_minus_1 = vec384 { - ls: [13402431016077863594, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - - equals_vec384(res, p_minus_1); - true -} - -fn test_neg_random() -> bool { - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - - // p-r = - // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 - let res = neg(r, BLS12_381_P); - equals_vec384(res, vec384 { - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] - }); - true -} - -fn test_sub_fp() -> bool { - // assert(test_sub_zero_from_zero()); - // assert(test_sub_zero_from_random()); - // assert(test_sub_random_from_zero()); - // assert(test_sub_random_from_small()); - assert(test_sub_2_randoms()); - assert(test_sub_2_randoms_reverse()); - true -} - -fn test_sub_zero_from_zero() -> bool { - let res = sub_fp(ZERO, ZERO); - equals_vec384(res, ZERO); - true -} - -fn test_sub_zero_from_random() -> bool { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = sub_fp(r, ZERO); - equals_vec384(res, r); - true -} - -fn test_sub_random_from_zero() -> bool { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = sub_fp(ZERO, r); - // p-r (is the same as 0-r mod p) - equals_vec384(res, vec384 { - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] - }); - true -} - -fn test_sub_random_from_small() -> bool { - // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 - //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let small = vec384 { - ls: [1, - 2, 3, 4, 5, 6] - }; - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - - let res: vec384 = sub_fp(small, r); - //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 - //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - equals_vec384(res, vec384 { - ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - }); - true -} - -fn test_sub_2_randoms() -> bool { - //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 - //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let a = vec384 { - ls: [10587454305359941416, - 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - }; - //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 - //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let b = vec384 { - ls: [13403040667047958534, - 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - }; - //res = - //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let res: vec384 = sub_fp(a, b); - equals_vec384(res, vec384 { - ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - }); - true -} - -fn test_sub_2_randoms_reverse() -> bool { - // Same a,b from test_sub_2_randoms only subtract the other way around - let a = vec384 { - ls: [10587454305359941416, - 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - }; - let b = vec384 { - ls: [13403040667047958534, - 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - }; - - //res = - //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p - //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 - //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let res: vec384 = sub_fp(b, a); - equals_vec384(res, vec384 { - ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - }); - true -} - -fn tests_mul_by_3_fp() -> bool { - //3*0=0 - let three_times_0 = mul_by_3_fp(ZERO); - equals_vec384(three_times_0, ZERO); - - // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 - let a = vec384 { - ls: [5598198260030196614, - 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] - }; - // a*3 mod p should be - //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 - let res = mul_by_3_fp(a); - equals_vec384(res, vec384 { - ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] - }); - true -} - -fn tests_mul_by_8_fp() -> bool { - //8*0=0 - let eight_times_0 = mul_by_8_fp(ZERO); - equals_vec384(eight_times_0, ZERO); - - // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 - let a = vec384 { - ls: [4748578380656466952, - 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] - }; - // a*8 mod p should be - //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 - let res = mul_by_8_fp(a); - equals_vec384(res, vec384 { - ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] - }); - true -} - -fn test_lshift_p() -> bool { - assert(test_1_lshift_p()); - assert(test_250_lshift_p()); - true -} - -fn test_1_lshift_p() -> bool { - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = lshift_fp(r, 1); - // 1 leftshift is *2 - //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 - equals_vec384(res, vec384 { - ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] - }); - true -} - -fn test_250_lshift_p() -> bool { - //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 - let a = vec384 { - ls: [13749239540608708580, - 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] - }; - // leftshift 250 mod p - //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 - let res = lshift_fp(a, 250); - equals_vec384(res, vec384 { - ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] - }); - true + // assert(vect_subfunctions_tests()); + assert(test_helpers()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_helpers.sw b/bls12-381/src/tests/tests_helpers.sw new file mode 100644 index 0000000..6eabbf0 --- /dev/null +++ b/bls12-381/src/tests/tests_helpers.sw @@ -0,0 +1,295 @@ +library tests_helpers; + + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::{assert::assert, u128::*}; + +pub fn test_helpers() -> bool { + assert(test_not()); + assert(tests_subtract_wrap()); + assert(tests_sbb()); + assert(tests_adc()); + assert(test_neg()); + assert(test_subtract_p()); + true +} + +fn test_not() -> bool { + let res = not(18417751708719972248); + assert(res == 28992364989579367); + true +} + +fn tests_subtract_wrap() -> bool { + let mut res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 80, upper: 0 + }); + assert(res.lower == 20); + assert(res.upper == 0); + + res = subtract_wrap(U128 { + lower: 100, upper: 0 + }, + U128 { + lower: 230, upper: 0 + }); + let res_should_be = ~U128::max() - U128 { + lower: 130, upper: 0 + }; + // 2^128 - 230 = 340282366920938463463374607431768211226 + // [18446744073709551486, 18446744073709551615] + assert(res.lower == 18446744073709551486); + assert(res.upper == 18446744073709551615); + true +} + +fn tests_sbb() -> bool { + // 0-0-0 should give (0,0) + let mut res = sbb(0, 0, 0); + assert(res.0 == 0); + assert(res.1 == 0); + + // 0-1-0 should give (2^64 -1, 1) + res = sbb(0, 1, 0); + assert(res.0 == ~u64::max()); + assert(res.1 == 1); + + // 0-1-1 should give (2^64 -2, 1) + res = sbb(0, 1, 1); + assert(res.0 == ~u64::max() - 1); + assert(res.1 == 1); + + // a-0-1 should give (a-1, 0) + let a = 435983458; + res = sbb(a, 0, 1); + assert(res.0 == a - 1); + assert(res.1 == 0); + true +} + +fn tests_adc() -> bool { + assert(test_adc_random()); + assert(test_adc_random_with_carry()); + true +} + +fn test_adc_random() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res: (u64, u64) = adc(a, b, 0); + let a_plus_b: (u64, u64) = (1400544309406770619, 1); + + assert(res.0 == a_plus_b.0); + assert(res.1 == a_plus_b.1); + true +} + +fn test_adc_random_with_carry() -> bool { + let a = 9837491998535547791; + let b = 10009796384580774444; + let res: (u64, u64) = adc(a, b, 1); + let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); + + assert(res.0 == a_plus_b_and_carry.0); + assert(res.1 == a_plus_b_and_carry.1); + true +} + +fn test_subtract_p() -> bool { + assert(test_subtract_p_smaller()); + assert(test_subtract_p_larger()); + true +} + +fn test_subtract_p_smaller() -> bool { + let a_smaller_than_p = vec384 { + ls: [13402431016077863508, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + let res = subtract_p(a_smaller_than_p, BLS12_381_P); + equals_vec384(res, a_smaller_than_p); + true +} + +fn test_subtract_p_larger() -> bool { + // p+200 + let a_larger_than_p = vec384 { + ls: [13402431016077863795, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + let res = subtract_p(a_larger_than_p, BLS12_381_P); + equals_vec384(res, vec384 { + ls: [200, 0, 0, 0, 0, 0] + }); + true +} + +fn test_neg() -> bool { + assert(test_neg_p()); + assert(test_neg_1()); + assert(test_neg_random()); + true +} + +// neg(p, p) should result in 0 +fn test_neg_p() -> bool { + let p = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] + }; + let res = neg(p, BLS12_381_P); + equals_vec384(res, ZERO); + true +} + +fn test_neg_1() -> bool { + /* p (=BLS12_381_P) + [13402431016077863595, + 2210141511517208575, + 7435674573564081700, + 7239337960414712511, + 5412103778470702295, + 1873798617647539866] + */ + let res = neg(vec384 { + ls: [1, 0, 0, 0, 0, 0] + }, + BLS12_381_P); + let p_minus_1 = vec384 { + ls: [13402431016077863594, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + + equals_vec384(res, p_minus_1); + true +} + +fn test_neg_random() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + + // p-r = + // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 + let res = neg(r, BLS12_381_P); + equals_vec384(res, vec384 { + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] + }); + true +} + +fn test_sub_fp() -> bool { + // assert(test_sub_zero_from_zero()); + // assert(test_sub_zero_from_random()); + // assert(test_sub_random_from_zero()); + // assert(test_sub_random_from_small()); + assert(test_sub_2_randoms()); + assert(test_sub_2_randoms_reverse()); + true +} + +fn test_sub_zero_from_zero() -> bool { + let res = sub_fp(ZERO, ZERO); + equals_vec384(res, ZERO); + true +} + +fn test_sub_zero_from_random() -> bool { + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + let res = sub_fp(r, ZERO); + equals_vec384(res, r); + true +} + +fn test_sub_random_from_zero() -> bool { + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + let res = sub_fp(ZERO, r); + // p-r (is the same as 0-r mod p) + equals_vec384(res, vec384 { + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] + }); + true +} + +fn test_sub_random_from_small() -> bool { + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let small = vec384 { + ls: [1, + 2, 3, 4, 5, 6] + }; + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + + let res: vec384 = sub_fp(small, r); + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + equals_vec384(res, vec384 { + ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] + }); + true +} + +fn test_sub_2_randoms() -> bool { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let res: vec384 = sub_fp(a, b); + equals_vec384(res, vec384 { + ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + }); + true +} + +fn test_sub_2_randoms_reverse() -> bool { + // Same a,b from test_sub_2_randoms only subtract the other way around + let a = vec384 { + ls: [10587454305359941416, + 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + }; + let b = vec384 { + ls: [13403040667047958534, + 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + }; + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let res: vec384 = sub_fp(b, a); + equals_vec384(res, vec384 { + ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + }); + true +} diff --git a/bls12-381/src/tests/tests_vect_fp.sw b/bls12-381/src/tests/tests_vect_fp.sw new file mode 100644 index 0000000..c0a607b --- /dev/null +++ b/bls12-381/src/tests/tests_vect_fp.sw @@ -0,0 +1,214 @@ +library tests_vect_fp; + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::assert::assert; + +pub fn fp_tests() -> bool { + // Don't run all tests at the same time... + + // assert(test_add_fp()); + // assert(test_sub_fp()); + // assert(test_helpers()); + // assert(tests_mul_by_3_fp()); + // assert(tests_mul_by_8_fp()); + assert(test_lshift_p()); + + true +} + +fn test_add_fp() -> bool { + assert(test_add_zero_to_zero()); + assert(test_add_zero_to_random()); + assert(test_add_random_to_zero()); + assert(test_add_random_to_small()); + assert(test_add_larger_than_p()); + assert(test_add_2_randoms()); + true +} + +fn test_add_zero_to_zero() -> bool { + let res: vec384 = add_fp(ZERO, ZERO); + equals_vec384(res, ZERO); + true +} + +fn test_add_zero_to_random() -> bool { + let random = vec384 { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] + }; + let res: vec384 = add_fp(random, ZERO); + equals_vec384(res, random); + true +} + +fn test_add_random_to_zero() -> bool { + let random = vec384 { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] + }; + /* +4478030004447473542 +2814704111667093002 +15884408734010272158 +17001047363111187578 +932823543034528547 +1051481384684610845 + */ + let res: vec384 = add_fp(ZERO, random); + equals_vec384(res, random); + true +} + +fn test_add_random_to_small() -> bool { + let small = vec384 { + ls: [0x1, + 0x2, 0x3, 0x4, 0x5, 0x6] + }; + let random = vec384 { + ls: [0x3e2528903ca1ef86, + 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] + }; + let res: vec384 = add_fp(small, random); + equals_vec384(res, vec384 { + ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] + }); + true +} + +fn test_add_larger_than_p() -> bool { + /* + 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 + + + 100 + is a little bit larger than p + */ + //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + let a = vec384 { + ls: [13402431016077863508, + 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] + }; + + let b = vec384 { + ls: [100, + 0, 0, 0, 0, 0] + }; + + // should be 13 + let res: vec384 = add_fp(a, b); + equals_vec384(res, vec384 { + ls: [13, 0, 0, 0, 0, 0] + }); + true +} + +fn test_add_2_randoms() -> bool { + //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] + let random_1 = vec384 { + ls: [4510245898505151773, + 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] + }; + + //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + let random_2 = vec384 { + ls: [8877477209635348035, + 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] + }; + /* +a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 +b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 +a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 +[13387723108140499808, +7110911959168982110, +7018803425472956901, +2577695370959560254, +1826757397030539319, +859395849761138905] + +a+b< p is true +*/ + let res: vec384 = add_fp(random_1, random_2); + equals_vec384(res, vec384 { + ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] + }); + true +} + + +fn tests_mul_by_3_fp() -> bool { + //3*0=0 + let three_times_0 = mul_by_3_fp(ZERO); + equals_vec384(three_times_0, ZERO); + + // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 + let a = vec384 { + ls: [5598198260030196614, + 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] + }; + // a*3 mod p should be + //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 + let res = mul_by_3_fp(a); + equals_vec384(res, vec384 { + ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] + }); + true +} + +fn tests_mul_by_8_fp() -> bool { + //8*0=0 + let eight_times_0 = mul_by_8_fp(ZERO); + equals_vec384(eight_times_0, ZERO); + + // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 + let a = vec384 { + ls: [4748578380656466952, + 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] + }; + // a*8 mod p should be + //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 + let res = mul_by_8_fp(a); + equals_vec384(res, vec384 { + ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] + }); + true +} + +fn test_lshift_p() -> bool { + assert(test_1_lshift_p()); + assert(test_250_lshift_p()); + true +} + +fn test_1_lshift_p() -> bool { + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + let r = vec384 { + ls: [13059245463466299169, + 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] + }; + let res = lshift_fp(r, 1); + // 1 leftshift is *2 + //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 + equals_vec384(res, vec384 { + ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] + }); + true +} + +fn test_250_lshift_p() -> bool { + //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 + let a = vec384 { + ls: [13749239540608708580, + 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] + }; + // leftshift 250 mod p + //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 + let res = lshift_fp(a, 250); + equals_vec384(res, vec384 { + ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] + }); + true +} diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls12-381/src/tests/tests_vect_fp2.sw new file mode 100644 index 0000000..e3104a3 --- /dev/null +++ b/bls12-381/src/tests/tests_vect_fp2.sw @@ -0,0 +1,106 @@ +library tests_vect_fp2; + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::assert::assert; + +pub fn fp2_tests() -> bool { + assert(tests_add_fp2()); + // assert(tests_sub_fp2()); + true +} + +fn tests_add_fp2() -> bool { + // the function should add the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; + + let res = add_fp2(a_1, a_2); + + // real part + //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 + // i part + //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 + equals_vec384(res.r, vec384 { + ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] + }); + equals_vec384(res.i, vec384 { + ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] + }); + true +} + +fn tests_sub_fp2() -> bool { + // the function should subtract the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let r_1 = vec384 { + ls: [14795151457364307190, + 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] + }; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { + ls: [8306319196692453748, + 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + + //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 + let r_2 = vec384 { + ls: [16448140995118783999, + 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] + }; + //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 + let i_2 = vec384 { + ls: [1139524850979729662, + 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] + }; + let a_2 = vec384x { + r: r_2, + i: i_2, + }; + + let res = sub_fp2(a_1, a_2); + //real + //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 + //i + //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 + equals_vec384(res.r, vec384 { + ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] + }); + equals_vec384(res.i, vec384 { + ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] + }); + true +} diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw new file mode 100644 index 0000000..6431ad6 --- /dev/null +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -0,0 +1,344 @@ +library tests_vect_subfunctions; + +use ::fields::*; +use ::vect::*; +use ::test_helpers::*; + +use std::{assert::assert, vec::Vec}; + +pub fn vect_subfunctions_tests() -> bool { + // NOTE: Don't run all at the same time, because will run out of gas + + // add_mod_n tests. They have the same test values as add_fp + // which should be correct, but of course add_mod_n should do more + // assert(test_add_zero_to_zero_addn()); + // assert(test_add_zero_to_random_addn()); + assert(test_add_random_to_small_addn()); + + // assert(test_mul_mont_n_by_zero()); + // assert(test_mul_mont_n_zero_by_one()); + // assert(test_mul_mont_n_one_by_one()); + assert(test_mul_mont_n_random_by_one()); + assert(test_mul_mont_n_random_by_random()); + + // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added + // assert(test_sub_zero_from_zero_subn()); + // assert(test_sub_zero_from_random_subn()); + // assert(test_sub_random_from_zero_subn()); + // assert(test_sub_random_from_small_subn()); + assert(test_sub_2_randoms_subn()); + assert(test_sub_2_randoms_reverse_subn()); + true +} + + +fn get_test_vectors() -> (Vec, Vec) { + let mut zero_vec = ~Vec::new::(); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + (zero_vec, p_vec) +} + +fn test_mul_mont_n_by_zero() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn get_one_vec() -> Vec { + let mut one_vec = ~Vec::new::(); + one_vec.push(1); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec.push(0); + one_vec +} + +fn test_mul_mont_n_zero_by_one() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_mul_mont_n_one_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); + let one_vec = get_one_vec(); + + let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); + equals_vec(res, one_vec, 6); + true +} + +fn test_mul_mont_n_random_by_one() -> bool { + let(_, p_vec) = get_test_vectors(); + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r_vec = ~Vec::new::(); + r_vec.push(0x54439c4ae7869f30); + r_vec.push(0xa7fdefad55c032ba); + r_vec.push(0x21282f739c0a15e7); + r_vec.push(0x6cc7a6e8c38430ff); + r_vec.push(0x50db69783b321139); + r_vec.push(0xba78745dadd17a93); + let one_vec = get_one_vec(); + + let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); + equals_vec(res, r_vec, 6); + true +} + +fn test_mul_mont_n_random_by_random() -> bool { + let(_, p_vec) = get_test_vectors(); + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(0x54439c4ae7869f30); + r1_vec.push(0xa7fdefad55c032ba); + r1_vec.push(0x21282f739c0a15e7); + r1_vec.push(0x6cc7a6e8c38430ff); + r1_vec.push(0x50db69783b321139); + r1_vec.push(0xba78745dadd17a93); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(0xeb6f61c69e4c7eef); + r2_vec.push(0xa70784fb3f9ac549); + r2_vec.push(0x91f41a633e1d9601); + r2_vec.push(0xf89a44e9a52e99e); + r2_vec.push(0x1eb242ddd39638bc); + r2_vec.push(0x57e6ed499f0c7c1); + + //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + let mut res_vec = ~Vec::new::(); + res_vec.push(0x42863c4b7ea22ad7); + res_vec.push(0x27627bfa644b580d); + res_vec.push(0x16930ecb9e3a308f); + res_vec.push(0xd5802a33c5512d6a); + res_vec.push(0x19591b38f5515036); + res_vec.push(0x7546b2615f748cd); + let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); + equals_vec(res, res_vec, 6); + true +} + +fn test_add_zero_to_zero_addn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_add_zero_to_random_addn() -> bool { + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let(zero_vec, p_vec) = get_test_vectors(); + + let res = add_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_add_random_to_small_addn() -> bool { + let mut small_vec = ~Vec::new::(); + small_vec.push(0x1); + small_vec.push(0x2); + small_vec.push(0x3); + small_vec.push(0x4); + small_vec.push(0x5); + small_vec.push(0x6); + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + let mut res_vec = ~Vec::new::(); + res_vec.push(4478030004447473543); + res_vec.push(2814704111667093004); + res_vec.push(15884408734010272161); + res_vec.push(17001047363111187582); + res_vec.push(932823543034528552); + res_vec.push(1051481384684610851); + + let(_, p_vec) = get_test_vectors(); + + let res = add_mod_n(small_vec, random_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + true +} + +fn test_sub_zero_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); + equals_vec(res, zero_vec, 6); + true +} + +fn test_sub_zero_from_random_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(0x3e2528903ca1ef86); + random_vec.push(0x270fd67a03bf9e0a); + random_vec.push(0xdc70c19599cb699e); + random_vec.push(0xebefda8057d5747a); + random_vec.push(0xcf20e11f0b1c323); + random_vec.push(0xe979cbf960fe51d); + + let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); + equals_vec(res, random_vec, 6); + true +} + +fn test_sub_random_from_zero_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + + let mut random_vec = ~Vec::new::(); + random_vec.push(13059245463466299169); + random_vec.push(17774603101077980186); + random_vec.push(889990675562875390); + random_vec.push(12771390643166271294); + random_vec.push(5370893444473505192); + random_vec.push(599972797727911687); + + let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); + // p-r (is the same as 0-r mod p) + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564426); + res_vec.push(2882282484148780005); + res_vec.push(6545683898001206309); + res_vec.push(12914691390957992833); + res_vec.push(41210333997197102); + res_vec.push(1273825819919628179); + equals_vec(res, res_vec, 6); + true +} + +fn test_sub_random_from_small_subn() -> bool { + let(zero_vec, p_vec) = get_test_vectors(); + // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 + //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 + let mut small_vec = ~Vec::new::(); + small_vec.push(1); + small_vec.push(2); + small_vec.push(3); + small_vec.push(4); + small_vec.push(5); + small_vec.push(6); + + //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 + let mut r_vec = ~Vec::new::(); + r_vec.push(13059245463466299169); + r_vec.push(17774603101077980186); + r_vec.push(889990675562875390); + r_vec.push(12771390643166271294); + r_vec.push(5370893444473505192); + r_vec.push(599972797727911687); + + let mut res_vec = ~Vec::new::(); + res_vec.push(343185552611564427); + res_vec.push(2882282484148780007); + res_vec.push(6545683898001206312); + res_vec.push(12914691390957992837); + res_vec.push(41210333997197107); + res_vec.push(1273825819919628185); + + //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 + let res = sub_mod_n(small_vec, r_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn get_r1_r2_vecs() -> (Vec, Vec) { + //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 + //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] + let mut r1_vec = ~Vec::new::(); + r1_vec.push(10587454305359941416); + r1_vec.push(4615625447881587853); + r1_vec.push(9368308553698906485); + r1_vec.push(9494054596162055604); + r1_vec.push(377309137954328098); + r1_vec.push(766262085408033194); + + //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 + //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] + let mut r2_vec = ~Vec::new::(); + r2_vec.push(13403040667047958534); + r2_vec.push(405585388298286396); + r2_vec.push(7295341050629342949); + r2_vec.push(1749456428444609784); + r2_vec.push(1856600841951774635); + r2_vec.push(296809876162753174); + + (r1_vec, r2_vec) +} + +fn test_sub_2_randoms_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] + let mut res_vec = ~Vec::new::(); + res_vec.push(15631157712021534498); + res_vec.push(4210040059583301456); + res_vec.push(2072967503069563536); + res_vec.push(7744598167717445820); + res_vec.push(16967452369712105079); + res_vec.push(469452209245280019); + + let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} + +fn test_sub_2_randoms_reverse_subn() -> bool { + let (zero_vec, p_vec) = get_test_vectors(); + let (r1_vec, r2_vec) = get_r1_r2_vecs(); + + //res = + //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 + // => mod p + //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 + //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] + let mut res_vec = ~Vec::new::(); + res_vec.push(16218017377765880713); + res_vec.push(16446845525643458734); + res_vec.push(5362707070494518163); + res_vec.push(17941483866406818307); + res_vec.push(6891395482468148831); + res_vec.push(1404346408402259846); + + let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); + equals_vec(res, res_vec, 6); + + true +} From 070baf771cf7ba972decf014458d9701e3c9f38f Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 13 Jul 2022 17:17:38 -0600 Subject: [PATCH 088/160] - Renames the test_helpers file to tests_small_functions - Started on mul_mont_384x --- bls12-381/src/consts.sw | 2 + bls12-381/src/main.sw | 9 ++- ...ts_helpers.sw => tests_small_functions.sw} | 4 +- bls12-381/src/tests/tests_vect_fp.sw | 1 - bls12-381/src/tests/tests_vect_fp2.sw | 67 ++++++++++++++----- bls12-381/src/vect.sw | 37 ++++++---- 6 files changed, 82 insertions(+), 38 deletions(-) rename bls12-381/src/tests/{tests_helpers.sw => tests_small_functions.sw} (99%) diff --git a/bls12-381/src/consts.sw b/bls12-381/src/consts.sw index 18e6433..16808a7 100644 --- a/bls12-381/src/consts.sw +++ b/bls12-381/src/consts.sw @@ -1,5 +1,7 @@ library consts; +pub const NLIMBS_384 = 6; + /* R = 2**384 % p = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 1d75162..0885c13 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -7,7 +7,7 @@ dep consts; dep tests/tests_vect_fp; dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; -dep tests/tests_helpers; +dep tests/tests_small_functions; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -19,16 +19,15 @@ use std::logging::log; use ::tests_vect_fp::fp_tests; use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; -use ::tests_helpers::test_helpers; +use ::tests_small_functions::tests_small_functions; fn main() { - log(78); // assert(fp_tests()); - // assert(fp2_tests()); + assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); // assert(vect_subfunctions_tests()); - assert(test_helpers()); + // assert(tests_small_functions()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_helpers.sw b/bls12-381/src/tests/tests_small_functions.sw similarity index 99% rename from bls12-381/src/tests/tests_helpers.sw rename to bls12-381/src/tests/tests_small_functions.sw index 6eabbf0..8586169 100644 --- a/bls12-381/src/tests/tests_helpers.sw +++ b/bls12-381/src/tests/tests_small_functions.sw @@ -1,4 +1,4 @@ -library tests_helpers; +library tests_small_functions; use ::fields::*; @@ -7,7 +7,7 @@ use ::test_helpers::*; use std::{assert::assert, u128::*}; -pub fn test_helpers() -> bool { +pub fn tests_small_functions() -> bool { assert(test_not()); assert(tests_subtract_wrap()); assert(tests_sbb()); diff --git a/bls12-381/src/tests/tests_vect_fp.sw b/bls12-381/src/tests/tests_vect_fp.sw index c0a607b..7391af2 100644 --- a/bls12-381/src/tests/tests_vect_fp.sw +++ b/bls12-381/src/tests/tests_vect_fp.sw @@ -11,7 +11,6 @@ pub fn fp_tests() -> bool { // assert(test_add_fp()); // assert(test_sub_fp()); - // assert(test_helpers()); // assert(tests_mul_by_3_fp()); // assert(tests_mul_by_8_fp()); assert(test_lshift_p()); diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls12-381/src/tests/tests_vect_fp2.sw index e3104a3..771c603 100644 --- a/bls12-381/src/tests/tests_vect_fp2.sw +++ b/bls12-381/src/tests/tests_vect_fp2.sw @@ -3,18 +3,17 @@ library tests_vect_fp2; use ::fields::*; use ::vect::*; use ::test_helpers::*; - +use std::logging::log; use std::assert::assert; pub fn fp2_tests() -> bool { - assert(tests_add_fp2()); + // assert(tests_add_fp2()); // assert(tests_sub_fp2()); + assert(tests_mul_fp2()); true } -fn tests_add_fp2() -> bool { - // the function should add the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 +fn get_a1() -> vec384x { let r_1 = vec384 { ls: [14795151457364307190, 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] @@ -28,6 +27,13 @@ fn tests_add_fp2() -> bool { r: r_1, i: i_1, }; + a_1 +} + +fn tests_add_fp2() -> bool { + // the function should add the "real" and "imaginary" part separately + //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 + let a_1 = get_a1(); //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 let r_2 = vec384 { @@ -62,19 +68,7 @@ fn tests_add_fp2() -> bool { fn tests_sub_fp2() -> bool { // the function should subtract the "real" and "imaginary" part separately //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; + let a_1 = get_a1(); //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 let r_2 = vec384 { @@ -104,3 +98,40 @@ fn tests_sub_fp2() -> bool { }); true } + +fn tests_mul_fp2() -> bool { + // assert(mul_fp2_by_zero()); + assert(mul_fp2_by_one()); + // assert(mul_fp2_by_small()); + true +} + +fn mul_fp2_by_zero() -> bool { + let a_1 = get_a1(); + let res = mul_fp2(a_1, ZERO_X); + equals_vec384(res.r, ZERO); + equals_vec384(res.i, ZERO); + true +} + +fn mul_fp2_by_one() -> bool { + let a_1 = get_a1(); + let one_384 = vec384 {ls: [1, 0, 0, 0, 0, 0]}; + let one = vec384x {r: one_384, i: one_384 }; + + let res = mul_fp2(a_1, one); + print_vec384(res.r); + // equals_vec384(res.r, a_1.r); + // equals_vec384(res.i, a_1.i); + true +} + +// fn mul_fp2_by_small() -> bool { +// let small = vec384 { +// ls: [0x1, +// 0x2, 0x3, 0x4, 0x5, 0x6] +// }; +// let smallx = vec384x {r: small, i: small }; + +// true +// } \ No newline at end of file diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index f47bf1d..9a73235 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -1,6 +1,9 @@ library vect; +dep consts; + use std::{option::*, u128::*, vec::Vec}; +use consts::*; // Stores field element with max 384 bits // element in fp @@ -260,18 +263,8 @@ pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { res } +// TODO pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { - //WIP ELENA - // vec384 aa, bb, cc; - - // add_mod_n(aa, a[0], a[1], p, NLIMBS(384)); - // add_mod_n(bb, b[0], b[1], p, NLIMBS(384)); - // mul_mont_n(bb, bb, aa, p, n0, NLIMBS(384)); - // mul_mont_n(aa, a[0], b[0], p, n0, NLIMBS(384)); - // mul_mont_n(cc, a[1], b[1], p, n0, NLIMBS(384)); - // sub_mod_n(ret[0], aa, cc, p, NLIMBS(384)); - // sub_mod_n(ret[1], bb, aa, p, NLIMBS(384)); - // sub_mod_n(ret[1], ret[1], cc, p, NLIMBS(384)); ZERO } @@ -523,8 +516,28 @@ pub fn mul_by_3_mod_384x(a: vec384x, p: vec384) -> vec384x { ZERO_X } +fn to_vec(v: vec384) -> Vec { + let mut res = ~Vec::new::(); + let mut i = 0; + while i < 6 { + res.push(v.ls[i]); + i += 1; + } + res +} + pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { - //TODO. Has a non-assembly impl in blst in src/no_asm.h + let a0_vec = to_vec(a.r); + let a1_vec = to_vec(a.i); + let b0_vec = to_vec(b.r); + let b1_vec = to_vec(b.i); + let p_vec = to_vec(p); + + let mut aa = add_mod_n(a0_vec, a1_vec, p_vec, NLIMBS_384); + let mut bb = add_mod_n(b0_vec, b1_vec, p_vec, NLIMBS_384); + // let bb_temp = mul_mont_n(bb, aa, p_vec, n0, NLIMBS_384); + // aa = mul_mont_n(a0_vec, b0_vec, p_vec, n0, NLIMBS_384); + ZERO_X } From 9d63ca718e94f7a5236dfd2316a7a40ab0c74326 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 14 Jul 2022 16:22:35 -0600 Subject: [PATCH 089/160] Better readability --- bls12-381/src/vect.sw | 111 +++++++++--------------------------------- 1 file changed, 24 insertions(+), 87 deletions(-) diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 9a73235..8070512 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -88,74 +88,38 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { } pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { - let mut mx: U128 = U128 { - lower: unpack_or_0(b.get(0)), - upper: 0, - }; - let mut hi: U128 = U128 { - lower: 0, - upper: 0, - }; + let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); + let mut hi: U128 = ~U128::from(0, 0); let mut tmp: Vec = ~Vec::new::(); let mut i = 0; while i < n { - let ai: U128 = U128 { - lower: unpack_or_0(a.get(i)), upper: 0 - }; + let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let limbx = mx * ai + hi; tmp.insert(i, limbx.lower); - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i += 1; } - mx = U128 { - lower: n0, upper: 0 - } - * U128 { - lower: unpack_or_0(tmp.get(0)), upper: 0 - }; + mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); tmp.insert(i, hi.lower); - let mut carry: u64 = 0; let mut j = 0; - let mut limbx: U128 = U128 { - lower: 0, - upper: 0, - }; + let mut limbx: U128 = ~U128::from(0, 0); while true { - let p0: U128 = U128 { - lower: unpack_or_0(p.get(0)), upper: 0 - }; - let tmp0: U128 = U128 { - lower: unpack_or_0(tmp.get(0)), upper: 0 - }; + let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); + let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); limbx = (mx * p0) + tmp0; - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i = 1; while i < n { - let pi: U128 = U128 { - lower: unpack_or_0(p.get(i)), upper: 0 - }; - let tmpi: U128 = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - }; + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); limbx = (mx * pi) + tmpi; tmp.insert(i - 1, limbx.lower); - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i += 1; } - limbx = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - } - + (hi + U128 { - lower: carry, upper: 0 - }); + limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); tmp.insert(i - 1, limbx.lower); carry = limbx.lower; @@ -163,62 +127,35 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec if j == n { break; } - - mx = U128 { - lower: unpack_or_0(b.get(j)), upper: 0 - }; - hi = U128 { - lower: 0, upper: 0 - }; + mx = ~U128::from(0, unpack_or_0(b.get(j))); + hi = ~U128::from(0, 0); i = 0; while i < n { - let ai: U128 = U128 { - lower: unpack_or_0(a.get(i)), upper: 0 - }; - let tmpi: U128 = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - }; + let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); limbx = (mx * (ai + hi)) + tmpi; tmp.insert(i, limbx.lower); - hi = U128 { - lower: limbx.upper, upper: 0 - }; + hi = ~U128::from(0, limbx.upper); i += 1; } - mx = U128 { - lower: n0, upper: 0 - } - * U128 { - lower: unpack_or_0(tmp.get(0)), upper: 0 - }; - limbx = hi + U128 { - lower: carry, upper: 0 - }; + mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + limbx = hi + ~U128::from(0, carry); tmp.insert(i, limbx.lower); carry = limbx.upper; } - let mut borrow: u64 = 0; i = 0; let mut ret: Vec = ~Vec::new::(); while i < n { - let pi: U128 = U128 { - lower: unpack_or_0(p.get(i)), upper: 0 - }; - let tmpi: U128 = U128 { - lower: unpack_or_0(tmp.get(i)), upper: 0 - }; - let pi_w_borrow = pi + U128 { - lower: borrow, upper: 0 - }; + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + let pi_w_borrow = pi + ~U128::from(0, borrow); // Prevent underflow. When U256 arithmetic is available we can create sbb_256 let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { (tmpi - pi_w_borrow, 0) } else { - (~U128::max() - (pi_w_borrow - tmpi - U128 { - lower: 1, upper: 0 - }), 1) + (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0,1)), 1) }; limbx = sub_res; borrow = b_res; From 94eaae1c6cd5cf86c6c2bf3e6b59ba3fd8b150f0 Mon Sep 17 00:00:00 2001 From: Manish Date: Thu, 14 Jul 2022 18:42:14 +0530 Subject: [PATCH 090/160] redc_mont_n added(testing not done yet) --- bls12-381/src/test_helpers.sw | 9 +++ bls12-381/src/tests/tests_vect_fp2.sw | 9 ++- .../src/tests/tests_vect_subfunctions.sw | 46 ++++++++++++--- bls12-381/src/vect.sw | 57 +++++++++++++++++++ 4 files changed, 112 insertions(+), 9 deletions(-) diff --git a/bls12-381/src/test_helpers.sw b/bls12-381/src/test_helpers.sw index 26e0a47..4478fba 100644 --- a/bls12-381/src/test_helpers.sw +++ b/bls12-381/src/test_helpers.sw @@ -31,3 +31,12 @@ pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { } true } +pub fn print_vec(a: Vec) { + let mut i = 0; + let l = a.len(); + while i < l { + log(unpack_or_0(a.get(i))); + i += 1; + } + +} diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls12-381/src/tests/tests_vect_fp2.sw index 771c603..6cc8bfd 100644 --- a/bls12-381/src/tests/tests_vect_fp2.sw +++ b/bls12-381/src/tests/tests_vect_fp2.sw @@ -116,8 +116,13 @@ fn mul_fp2_by_zero() -> bool { fn mul_fp2_by_one() -> bool { let a_1 = get_a1(); - let one_384 = vec384 {ls: [1, 0, 0, 0, 0, 0]}; - let one = vec384x {r: one_384, i: one_384 }; + let one_384 = vec384 { + ls: [1, 0, 0, 0, 0, 0] + }; + let one = vec384x { + r: one_384, + i: one_384, + }; let res = mul_fp2(a_1, one); print_vec384(res.r); diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 6431ad6..9bc50ce 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -3,7 +3,7 @@ library tests_vect_subfunctions; use ::fields::*; use ::vect::*; use ::test_helpers::*; - +use std::logging::log; use std::{assert::assert, vec::Vec}; pub fn vect_subfunctions_tests() -> bool { @@ -28,10 +28,11 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_random_from_small_subn()); assert(test_sub_2_randoms_subn()); assert(test_sub_2_randoms_reverse_subn()); + + // assert(test_redc_mont_n_384()); true } - fn get_test_vectors() -> (Vec, Vec) { let mut zero_vec = ~Vec::new::(); zero_vec.push(0); @@ -300,8 +301,8 @@ fn get_r1_r2_vecs() -> (Vec, Vec) { } fn test_sub_2_randoms_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); + let(zero_vec, p_vec) = get_test_vectors(); + let(r1_vec, r2_vec) = get_r1_r2_vecs(); //res = //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 @@ -321,15 +322,15 @@ fn test_sub_2_randoms_subn() -> bool { } fn test_sub_2_randoms_reverse_subn() -> bool { - let (zero_vec, p_vec) = get_test_vectors(); - let (r1_vec, r2_vec) = get_r1_r2_vecs(); + let(zero_vec, p_vec) = get_test_vectors(); + let(r1_vec, r2_vec) = get_r1_r2_vecs(); //res = //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 // => mod p //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new::(); res_vec.push(16218017377765880713); res_vec.push(16446845525643458734); res_vec.push(5362707070494518163); @@ -340,5 +341,36 @@ fn test_sub_2_randoms_reverse_subn() -> bool { let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); equals_vec(res, res_vec, 6); + true +} + +fn test_redc_mont_n_384() -> bool { + let mut a_vec: Vec = ~Vec::new::(); + a_vec.push(10); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + let mut res_vec: Vec = ~Vec::new::(); + res_vec.push(10); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + //print_vec(res_vec); + let test_vec = get_test_vectors(); + let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + print_vec(res); + log(unpack_or_0(res.get(0))); + + true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 8070512..5b7a90b 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -23,6 +23,11 @@ pub struct vec384x { i: vec384, //"imaginary" part } +//converts a u64 into U128 +pub fn u_128(a: u64) -> U128 { + U128{upper: 0, lower: a} +} + //TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0] @@ -210,6 +215,58 @@ pub fn sqr_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { ZERO } + +pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { + let mut j = 0; + let mut i = 1; + let mut b: Vec = a; + let mut tmp: Vec = ~Vec::new::(); + while j < n { + let mut mx: U128 = (u_128(n0) * u_128(unpack_or_0(b.get(0)))); + let mut limbx = mx * u_128(unpack_or_0(p.get(0))) + u_128(unpack_or_0(b.get(0))); + let mut hi = limbx.upper; + i = 1; + while i < n { + limbx = mx * u_128(unpack_or_0(p.get(i))) + u_128(hi) + u_128(unpack_or_0(b.get(i))); + tmp.insert(i-1, limbx.lower); + hi = limbx.upper; + i += 1; + } + tmp.insert(i-1, hi); + j += 1; + b = tmp; + } + + let mut tmp2: Vec = ~Vec::new::(); + i = 0; + let mut carry = 0; + while i < n { + let mut limbx = u_128(unpack_or_0(a.get(n+i))) + u_128(unpack_or_0(tmp.get(i))) + u_128(carry); + tmp2.insert(i, limbx.lower); + carry = limbx.upper; + i += 1; + } + + let mut borrow = 0; + let mut res: Vec = ~Vec::new::(); + i = 0; + while i < n { + let mut limbx = u_128(unpack_or_0(tmp2.get(i))) - (u_128(unpack_or_0(p.get(i))) + u_128(borrow)); + res.push(limbx.lower); + borrow = limbx.upper & 1; + i += 1; + } + + let mut mask = carry - borrow; + let mut result: Vec = ~Vec::new::(); + i = 0; + while i < n { + result.push((unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask)); + i += 1; + } + result +} + pub fn redc_mont_384(a: vec768, p: vec384, n0: u64) -> vec384 { //TODO ZERO From f1b365b3b54213b03390fd14e852fa7653e332f4 Mon Sep 17 00:00:00 2001 From: Manish Date: Fri, 15 Jul 2022 19:22:05 +0530 Subject: [PATCH 091/160] overflow issue in redc_mont_n --- bls12-381/src/main.sw | 4 +- .../src/tests/tests_vect_subfunctions.sw | 43 +++++++++----- bls12-381/src/vect.sw | 58 ++++++++++++------- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 0885c13..77406fd 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -23,10 +23,10 @@ use ::tests_small_functions::tests_small_functions; fn main() { // assert(fp_tests()); - assert(fp2_tests()); + // assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); - // assert(vect_subfunctions_tests()); + assert(vect_subfunctions_tests()); // assert(tests_small_functions()); } diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 9bc50ce..eb648bd 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -13,23 +13,23 @@ pub fn vect_subfunctions_tests() -> bool { // which should be correct, but of course add_mod_n should do more // assert(test_add_zero_to_zero_addn()); // assert(test_add_zero_to_random_addn()); - assert(test_add_random_to_small_addn()); + // assert(test_add_random_to_small_addn()); // assert(test_mul_mont_n_by_zero()); // assert(test_mul_mont_n_zero_by_one()); // assert(test_mul_mont_n_one_by_one()); - assert(test_mul_mont_n_random_by_one()); - assert(test_mul_mont_n_random_by_random()); + // assert(test_mul_mont_n_random_by_one()); + // assert(test_mul_mont_n_random_by_random()); // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added // assert(test_sub_zero_from_zero_subn()); // assert(test_sub_zero_from_random_subn()); // assert(test_sub_random_from_zero_subn()); // assert(test_sub_random_from_small_subn()); - assert(test_sub_2_randoms_subn()); - assert(test_sub_2_randoms_reverse_subn()); + // assert(test_sub_2_randoms_subn()); + // assert(test_sub_2_randoms_reverse_subn()); - // assert(test_redc_mont_n_384()); + assert(test_redc_mont_n_384()); true } @@ -359,17 +359,32 @@ fn test_redc_mont_n_384() -> bool { a_vec.push(0); a_vec.push(0); let mut res_vec: Vec = ~Vec::new::(); - res_vec.push(10); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - //print_vec(res_vec); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + // res_vec.push(0); + + // let mut p_vec = ~Vec::new::(); + // p_vec.push(0xb9feffffffffaaab); + // p_vec.push(0x1eabfffeb153ffff); + // p_vec.push(0x6730d2a0f6b0f624); + // p_vec.push(0x64774b84f38512bf); + // p_vec.push(0x4b1ba7b6434bacd7); + // p_vec.push(0x1a0111ea397fe69a); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + // p_vec.push(0); + + log(a_vec.get(0)); let test_vec = get_test_vectors(); let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); print_vec(res); - log(unpack_or_0(res.get(0))); + //log(unpack_or_0(res.get(0))); true diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 5b7a90b..12fc115 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -4,7 +4,7 @@ dep consts; use std::{option::*, u128::*, vec::Vec}; use consts::*; - +use std::logging::log; // Stores field element with max 384 bits // element in fp pub struct vec384 { @@ -23,10 +23,7 @@ pub struct vec384x { i: vec384, //"imaginary" part } -//converts a u64 into U128 -pub fn u_128(a: u64) -> U128 { - U128{upper: 0, lower: a} -} + //TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 { @@ -220,28 +217,35 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut j = 0; let mut i = 1; let mut b: Vec = a; + //let mut limbx: U128 = ~U128::from(0,0); let mut tmp: Vec = ~Vec::new::(); while j < n { - let mut mx: U128 = (u_128(n0) * u_128(unpack_or_0(b.get(0)))); - let mut limbx = mx * u_128(unpack_or_0(p.get(0))) + u_128(unpack_or_0(b.get(0))); - let mut hi = limbx.upper; + let mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(b.get(0)))).lower; + let mx: U128 = ~U128::from(0, mx_temp) ; + let mut limbx = mx * ~U128::from(0, unpack_or_0(p.get(0))) + ~U128::from(0, unpack_or_0(b.get(0))); + let mut hi: U128 = ~U128::from(0, limbx.upper); i = 1; while i < n { - limbx = mx * u_128(unpack_or_0(p.get(i))) + u_128(hi) + u_128(unpack_or_0(b.get(i))); + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); + limbx = (mx * pi + hi) + bi; tmp.insert(i-1, limbx.lower); - hi = limbx.upper; + hi = ~U128::from(0, limbx.upper); i += 1; } - tmp.insert(i-1, hi); - j += 1; + tmp.insert(i-1, hi.lower); b = tmp; + j += 1; } let mut tmp2: Vec = ~Vec::new::(); - i = 0; let mut carry = 0; + i = 0; while i < n { - let mut limbx = u_128(unpack_or_0(a.get(n+i))) + u_128(unpack_or_0(tmp.get(i))) + u_128(carry); + let ani: U128 = ~U128::from(0, unpack_or_0(a.get(n+i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + let carryi: U128 = ~U128::from(0, carry); + let limbx = ani + (tmpi + carryi); tmp2.insert(i, limbx.lower); carry = limbx.upper; i += 1; @@ -251,19 +255,33 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut res: Vec = ~Vec::new::(); i = 0; while i < n { - let mut limbx = u_128(unpack_or_0(tmp2.get(i))) - (u_128(unpack_or_0(p.get(i))) + u_128(borrow)); - res.push(limbx.lower); - borrow = limbx.upper & 1; + let tmp2i: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); + let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); + let borrow_i: U128 = ~U128::from(0, borrow); + let pi_w_borrow = pi + borrow_i; + // Prevent underflow. When U256 arithmetic is available we can create sbb_256 + let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmp2i { + (tmp2i - pi_w_borrow, 0) + } else { + (~U128::max() - (pi_w_borrow - tmp2i - ~U128::from(0,1)), 1) + }; + let mut limbx = sub_res; + //borrow = b_res; + borrow = limbx.upper & 0x1; + res.insert(i, limbx.lower); i += 1; } - - let mut mask = carry - borrow; + //arithmetic overflow is happning + //let mut mask = carry - borrow; + let mask: u64 = borrow * ~u64::max(); let mut result: Vec = ~Vec::new::(); i = 0; while i < n { - result.push((unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask)); + let result_i = (unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask); + result.insert(i, result_i); i += 1; } + result } From 743c24981d169cb942fa6fd3dae5c14d202d33cf Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 15 Jul 2022 14:09:07 -0600 Subject: [PATCH 092/160] Debugging mul_mont_n --- .../src/tests/tests_vect_subfunctions.sw | 13 +++-- bls12-381/src/vect.sw | 54 ++++++++++++++++--- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index eb648bd..983990c 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -5,6 +5,8 @@ use ::vect::*; use ::test_helpers::*; use std::logging::log; use std::{assert::assert, vec::Vec}; +use ::consts::*; + pub fn vect_subfunctions_tests() -> bool { // NOTE: Don't run all at the same time, because will run out of gas @@ -17,7 +19,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_by_zero()); // assert(test_mul_mont_n_zero_by_one()); - // assert(test_mul_mont_n_one_by_one()); + assert(test_mul_mont_n_one_by_one()); // assert(test_mul_mont_n_random_by_one()); // assert(test_mul_mont_n_random_by_random()); @@ -29,7 +31,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_2_randoms_subn()); // assert(test_sub_2_randoms_reverse_subn()); - assert(test_redc_mont_n_384()); + // assert(test_redc_mont_n_384()); true } @@ -56,7 +58,7 @@ fn get_test_vectors() -> (Vec, Vec) { fn test_mul_mont_n_by_zero() -> bool { let(zero_vec, p_vec) = get_test_vectors(); - let res = mul_mont_n(zero_vec, zero_vec, p_vec, 1, 6); + let res = mul_mont_n(zero_vec, zero_vec, p_vec, P0, 6); equals_vec(res, zero_vec, 6); true } @@ -76,16 +78,17 @@ fn test_mul_mont_n_zero_by_one() -> bool { let(zero_vec, p_vec) = get_test_vectors(); let one_vec = get_one_vec(); - let res = mul_mont_n(zero_vec, one_vec, p_vec, 1, 6); + let res = mul_mont_n(zero_vec, one_vec, p_vec, P0, 6); equals_vec(res, zero_vec, 6); true } fn test_mul_mont_n_one_by_one() -> bool { + log(1); let(_, p_vec) = get_test_vectors(); let one_vec = get_one_vec(); - let res = mul_mont_n(one_vec, one_vec, p_vec, 1, 6); + let res = mul_mont_n(one_vec, one_vec, p_vec, P0, 6); equals_vec(res, one_vec, 6); true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 12fc115..8f93acf 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -102,6 +102,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec i += 1; } +//0x89f3fffcfffcfffd * 1 mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); tmp.insert(i, hi.lower); let mut carry: u64 = 0; @@ -110,15 +111,32 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec while true { let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); + log(mx);//000000000000000089f3fffcfffcfffd + //2: 3947442df695f8f1286adb92d9d113e8 + log(p0);//0000000000000000b9feffffffffaaab + //2: 0000000000000000b9feffffffffaaab + log(tmp0);//00000000000000000000000000000001 + //2: 00000000000000006a4aaa14be07a408 + //1: 16^^643abe09d200a404ffffffffffffffff + //2: 16^^299d8e4220faed31901f94fb2b3b54280000000000000000 + //this is 190 bits instead of fitting into 128 limbx = (mx * p0) + tmp0; + log(limbx);//643abe09d200a4050000000000000000 + //2: f21393888e24ec0f0000000000000000 hi = ~U128::from(0, limbx.upper); + log(hi);//0000000000000000643abe09d200a405 + //2: 0000000000000000f21393888e24ec0f i = 1; while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - limbx = (mx * pi) + tmpi; + log(pi);//00000000000000001eabfffeb153ffff + log(tmpi);//00000000000000000000000000000000 + limbx = (mx * pi + hi) + tmpi; + log(limbx);//108747eeefa29c0f6a4aaa14be07a408 tmp.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); + log(hi);//0000000000000000108747eeefa29c0f i += 1; } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); @@ -131,21 +149,34 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } mx = ~U128::from(0, unpack_or_0(b.get(j))); hi = ~U128::from(0, 0); + log(mx);//00000000000000006730d2a0f6b0f624 + log(hi);//00000000000000000000000000000000 i = 0; while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 + log(tmpi);//0000000000000000379b7b3fafdc26ed limbx = (mx * (ai + hi)) + tmpi; + log(limbx);//000000000000000064774b84f38512bf tmp.insert(i, limbx.lower); hi = ~U128::from(0, limbx.upper); + log(hi);//00000000000000000000000000000000 i += 1; } mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) limbx = hi + ~U128::from(0, carry); + log(limbx);//00000000000000003623991cf3a341e8 tmp.insert(i, limbx.lower); + log(tmp);//00000000000000004b1ba7b6434bacd7 carry = limbx.upper; + log(carry);//00000000000000000000000000000000 + + //Conclusion so far: mx will become really large and then overflow in next iteration } + /* let mut borrow: u64 = 0; i = 0; let mut ret: Vec = ~Vec::new::(); @@ -165,15 +196,24 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec borrow = limbx.upper & 0x1; i += 1; } +log(carry); +log(borrow); + let mask: u64 = if carry >= borrow { + carry-borrow + } else { + ~u64::max()-1 + }; + */ +// mask = carry - borrow; + // let mask: u64 = borrow * ~u64::max(); - let mask: u64 = borrow * ~u64::max(); i = 0; let mut res: Vec = ~Vec::new::(); - while i < n { - let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); - res.insert(i, value); - i += 1; - } + // while i < n { + // let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); + // res.insert(i, value); + // i += 1; + // } res } From cc3ad80a40070fe12ac88882459104d2beb6f00e Mon Sep 17 00:00:00 2001 From: Manish Date: Mon, 18 Jul 2022 19:20:20 +0530 Subject: [PATCH 093/160] mul_mont_n and redc_mont_n debugging --- .../src/tests/tests_vect_subfunctions.sw | 152 ++++++++++++++---- bls12-381/src/vect.sw | 91 ++++++----- 2 files changed, 173 insertions(+), 70 deletions(-) diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 983990c..901b352 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -19,7 +19,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_by_zero()); // assert(test_mul_mont_n_zero_by_one()); - assert(test_mul_mont_n_one_by_one()); + // assert(test_mul_mont_n_one_by_one()); // assert(test_mul_mont_n_random_by_one()); // assert(test_mul_mont_n_random_by_random()); @@ -31,7 +31,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_2_randoms_subn()); // assert(test_sub_2_randoms_reverse_subn()); - // assert(test_redc_mont_n_384()); + assert(tests_redc_mont()); true } @@ -84,12 +84,13 @@ fn test_mul_mont_n_zero_by_one() -> bool { } fn test_mul_mont_n_one_by_one() -> bool { - log(1); let(_, p_vec) = get_test_vectors(); let one_vec = get_one_vec(); let res = mul_mont_n(one_vec, one_vec, p_vec, P0, 6); equals_vec(res, one_vec, 6); + //print_vec(res); + // print_vec(one_vec); true } @@ -105,7 +106,8 @@ fn test_mul_mont_n_random_by_one() -> bool { r_vec.push(0xba78745dadd17a93); let one_vec = get_one_vec(); - let res = mul_mont_n(r_vec, one_vec, p_vec, 1, 6); + let res = mul_mont_n(r_vec, one_vec, p_vec, P0, 6); + print_vec(res); equals_vec(res, r_vec, 6); true } @@ -347,9 +349,16 @@ fn test_sub_2_randoms_reverse_subn() -> bool { true } -fn test_redc_mont_n_384() -> bool { +fn tests_redc_mont() -> bool { + assert(test_redc_mont_n_small()); + // assert(test_redc_mont_n_p()); + // assert(test_redc_mont_n_random()); + // assert(test_redc_mont_n_random_large()); + + true +} +fn test_redc_mont_n_small() -> bool { let mut a_vec: Vec = ~Vec::new::(); - a_vec.push(10); a_vec.push(0); a_vec.push(0); a_vec.push(0); @@ -361,34 +370,117 @@ fn test_redc_mont_n_384() -> bool { a_vec.push(0); a_vec.push(0); a_vec.push(0); + a_vec.push(10); let mut res_vec: Vec = ~Vec::new::(); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - // res_vec.push(0); - - // let mut p_vec = ~Vec::new::(); - // p_vec.push(0xb9feffffffffaaab); - // p_vec.push(0x1eabfffeb153ffff); - // p_vec.push(0x6730d2a0f6b0f624); - // p_vec.push(0x64774b84f38512bf); - // p_vec.push(0x4b1ba7b6434bacd7); - // p_vec.push(0x1a0111ea397fe69a); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - // p_vec.push(0); - - log(a_vec.get(0)); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(0); + res_vec.push(10); let test_vec = get_test_vectors(); let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); - print_vec(res); - //log(unpack_or_0(res.get(0))); + equals_vec(res, res_vec, 6); + true +} + +fn test_redc_mont_n_p() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + p_vec.push(0); + let test_vec = get_test_vectors(); + let res = redc_mont_n(p_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + //equals_vec(res, get_test_vectors().0, 6); + print_vec(res); + true +} + +fn test_redc_mont_n_random() -> bool { + /* + a_vec = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 + = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] + (using GP Pari) + a_vec mod P = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 + = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] + */ + let mut a_vec = ~Vec::new::(); + a_vec.push(13282407956253574712); + a_vec.push(7557322358563246340); + a_vec.push(14991082624209354397); + a_vec.push(6631139461101160670); + a_vec.push(10719928016004921607); + a_vec.push(1730705806359781376); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + let mut result = ~Vec::new::(); + result.push(13282407956253574712); + result.push(7557322358563246340); + result.push(14991082624209354397); + result.push(6631139461101160670); + result.push(10719928016004921607); + result.push(1730705806359781376); + + let test_vec = get_test_vectors(); + let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + print_vec(res); + //equals_vec(res, result, 6); + true + +} + +fn test_redc_mont_n_random_large() -> bool { + + /* + a = random({2^384}) = 21380795309672530537064108666460268360580493838230277925224860893329212391422460281305468429766194371347271041959862 + = [10009796384580774444, 9837491998535547791, 12861376030615125811, 15982738825684268908, 17984324540840297179, 13142370077570254774] + + a mod p = 1368747533564193569975159537780747577796079738535238498564570212709054138968270959092030284121116051157799679160927 + = [640803296343075113, 1223717179891587930, 13558174375960666486, 15697854105282963640, 6933616983254254301, 1470447218309591647] + + + + */ + let mut a_vec = ~Vec::new::(); + a_vec.push(13142370077570254774); + a_vec.push(17984324540840297179); + a_vec.push(15982738825684268908); + a_vec.push(12861376030615125811); + a_vec.push(9837491998535547791); + a_vec.push(10009796384580774444); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + a_vec.push(0); + + let mut result = ~Vec::new::(); + result.push(1470447218309591647); + result.push(6933616983254254301); + result.push(15697854105282963640); + result.push(13558174375960666486); + result.push(1223717179891587930); + result.push(640803296343075113); + + let test_vec = get_test_vectors(); + let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); + //equals_vec(res, result, 6); + print_vec(res); true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 8f93acf..4c31ccb 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -93,6 +93,8 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, 0); let mut tmp: Vec = ~Vec::new::(); + let mut tmp2: Vec = ~Vec::new::();//new vector + let mut tmp3: Vec = ~Vec::new::();//new vector let mut i = 0; while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); @@ -103,7 +105,9 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } //0x89f3fffcfffcfffd * 1 - mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0)))).lower; + let mut mx: U128 = ~U128::from(0, mx_temp); + //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); tmp.insert(i, hi.lower); let mut carry: u64 = 0; let mut j = 0; @@ -111,36 +115,36 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec while true { let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); - log(mx);//000000000000000089f3fffcfffcfffd + //log(mx);//000000000000000089f3fffcfffcfffd //2: 3947442df695f8f1286adb92d9d113e8 - log(p0);//0000000000000000b9feffffffffaaab + //log(p0);//0000000000000000b9feffffffffaaab //2: 0000000000000000b9feffffffffaaab - log(tmp0);//00000000000000000000000000000001 + //log(tmp0);//00000000000000000000000000000001 //2: 00000000000000006a4aaa14be07a408 //1: 16^^643abe09d200a404ffffffffffffffff //2: 16^^299d8e4220faed31901f94fb2b3b54280000000000000000 //this is 190 bits instead of fitting into 128 limbx = (mx * p0) + tmp0; - log(limbx);//643abe09d200a4050000000000000000 + //log(limbx);//643abe09d200a4050000000000000000 //2: f21393888e24ec0f0000000000000000 hi = ~U128::from(0, limbx.upper); - log(hi);//0000000000000000643abe09d200a405 + //log(hi);//0000000000000000643abe09d200a405 //2: 0000000000000000f21393888e24ec0f i = 1; while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - log(pi);//00000000000000001eabfffeb153ffff - log(tmpi);//00000000000000000000000000000000 + //log(pi);//00000000000000001eabfffeb153ffff + //log(tmpi);//00000000000000000000000000000000 limbx = (mx * pi + hi) + tmpi; - log(limbx);//108747eeefa29c0f6a4aaa14be07a408 - tmp.insert(i - 1, limbx.lower); + //log(limbx);//108747eeefa29c0f6a4aaa14be07a408 + tmp2.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); - log(hi);//0000000000000000108747eeefa29c0f + //log(hi);//0000000000000000108747eeefa29c0f i += 1; } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); - tmp.insert(i - 1, limbx.lower); + tmp2.insert(i - 1, limbx.lower); carry = limbx.lower; j += 1; @@ -149,40 +153,42 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } mx = ~U128::from(0, unpack_or_0(b.get(j))); hi = ~U128::from(0, 0); - log(mx);//00000000000000006730d2a0f6b0f624 - log(hi);//00000000000000000000000000000000 + //log(mx);//00000000000000006730d2a0f6b0f624 + //log(hi);//00000000000000000000000000000000 i = 0; while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 - log(tmpi);//0000000000000000379b7b3fafdc26ed - limbx = (mx * (ai + hi)) + tmpi; - log(limbx);//000000000000000064774b84f38512bf - tmp.insert(i, limbx.lower); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); + //log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 + //log(tmpi);//0000000000000000379b7b3fafdc26ed + limbx = (mx * ai + hi) + tmpi; + //log(limbx);//000000000000000064774b84f38512bf + tmp3.insert(i, limbx.lower); hi = ~U128::from(0, limbx.upper); - log(hi);//00000000000000000000000000000000 + //log(hi);//00000000000000000000000000000000 i += 1; } + let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp3.get(0)))).lower; + let mut mx: U128 = ~U128::from(0, mx_temp); - mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); - log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) + //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); + //log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) limbx = hi + ~U128::from(0, carry); - log(limbx);//00000000000000003623991cf3a341e8 - tmp.insert(i, limbx.lower); - log(tmp);//00000000000000004b1ba7b6434bacd7 + //log(limbx);//00000000000000003623991cf3a341e8 + tmp3.insert(i, limbx.lower); + //log(tmp);//00000000000000004b1ba7b6434bacd7 carry = limbx.upper; - log(carry);//00000000000000000000000000000000 + //log(carry);//00000000000000000000000000000000 //Conclusion so far: mx will become really large and then overflow in next iteration } - /* + let mut borrow: u64 = 0; i = 0; let mut ret: Vec = ~Vec::new::(); while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); + let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp3.get(i))); let pi_w_borrow = pi + ~U128::from(0, borrow); // Prevent underflow. When U256 arithmetic is available we can create sbb_256 let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { @@ -191,29 +197,29 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0,1)), 1) }; limbx = sub_res; - borrow = b_res; + //borrow = b_res; ret.insert(i, limbx.lower); borrow = limbx.upper & 0x1; i += 1; } -log(carry); -log(borrow); + //log(carry); + //log(borrow); let mask: u64 = if carry >= borrow { carry-borrow } else { - ~u64::max()-1 + ~u64::max() - (borrow - carry - 1) }; - */ + // mask = carry - borrow; // let mask: u64 = borrow * ~u64::max(); i = 0; let mut res: Vec = ~Vec::new::(); - // while i < n { - // let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); - // res.insert(i, value); - // i += 1; - // } + while i < n { + let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp3.get(i)) & mask); + res.insert(i, value); + i += 1; + } res } @@ -313,7 +319,12 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { } //arithmetic overflow is happning //let mut mask = carry - borrow; - let mask: u64 = borrow * ~u64::max(); + //let mask: u64 = borrow * ~u64::max(); + let mut mask = if carry >= borrow { + carry - borrow + } else { + ~u64::max() - (borrow - carry - 1) + }; let mut result: Vec = ~Vec::new::(); i = 0; while i < n { From 8ee7924ecb5fc3f9ef777032a0029c0792d5fbe4 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 18 Jul 2022 18:38:45 -0600 Subject: [PATCH 094/160] Small fixes --- bls12-381/src/vect.sw | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 4c31ccb..e2c08c9 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -145,8 +145,8 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); tmp2.insert(i - 1, limbx.lower); - carry = limbx.lower; + carry = limbx.upper; j += 1; if j == n { break; @@ -199,7 +199,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec limbx = sub_res; //borrow = b_res; ret.insert(i, limbx.lower); - borrow = limbx.upper & 0x1; + borrow = b_res & 0x1; i += 1; } //log(carry); From d235764f50bfb2c0d22584d5a8ca0e2fcf9347af Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 19 Jul 2022 19:04:29 -0600 Subject: [PATCH 095/160] - Added mul_temp, the zkcrypto multiplication algorithm. Just to check whether we get the same output as that implementation - and yes we do. - Added accompanying test. - Updated .gitignore --- bls12-381/src/main.sw | 4 + bls12-381/src/tests/tests_temp_mul.sw | 117 ++++++++++++++++++++ bls12-381/src/vect.sw | 148 +++++++++++++++++++++++--- 3 files changed, 252 insertions(+), 17 deletions(-) create mode 100644 bls12-381/src/tests/tests_temp_mul.sw diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 77406fd..8203d87 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -8,6 +8,7 @@ dep tests/tests_vect_fp; dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; dep tests/tests_small_functions; +dep tests/tests_temp_mul; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -20,6 +21,7 @@ use ::tests_vect_fp::fp_tests; use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; use ::tests_small_functions::tests_small_functions; +use ::tests_temp_mul::tests_temp_mul; fn main() { // assert(fp_tests()); @@ -28,6 +30,8 @@ fn main() { // assert(test_mac()); assert(vect_subfunctions_tests()); // assert(tests_small_functions()); + + // assert(tests_temp_mul()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_temp_mul.sw b/bls12-381/src/tests/tests_temp_mul.sw new file mode 100644 index 0000000..a1f5583 --- /dev/null +++ b/bls12-381/src/tests/tests_temp_mul.sw @@ -0,0 +1,117 @@ +library tests_temp_mul; + +use ::vect::*; +use std::{assert::assert, vec::Vec}; +use ::test_helpers::*; + +pub fn tests_temp_mul() -> bool { + assert(test_mul_temp_by_2()); + true +} + +fn test_temp_mul_random_by_random() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); + + //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + //12684677789208411253122026388948849483224138949631185589801456383786133679073 + let res_vec = vec384 { + ls: [4793585148327242455, 2837967030551533581, 1626660158106644623, 15384342728939744618, 1826521055323312182, 528164867630647501] + }; + // let mut res_vec = ~Vec::new::(); + // res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 + // res_vec.push(0x27627bfa644b580d);//2837967030551533581 + // res_vec.push(0x16930ecb9e3a308f);//1626660158106644623 + // res_vec.push(0xd5802a33c5512d6a);//15384342728939744618 + // res_vec.push(0x19591b38f5515036);//1826521055323312182 + // res_vec.push(0x7546b2615f748cd);//528164867630647501 + + let res = mul_temp(r1_vec, r2_vec, p_vec, 6); + print_vec384(res); +/* +16484308011771146774 + +12795119582497094196 * 2^64 + +7495239071060242083 * 2^128 + +6228288009955243706 * 2^192 + +334445847756758381 * 2^256 + +1343304342180463133 * 2^320 + +16484308011771146774 + 12795119582497094196 * 2**64 +7495239071060242083 * 2**128 +6228288009955243706 * 2**192 +334445847756758381 * 2**256 +1343304342180463133 * 2**320 += +2869280660193735394861207574210601737447645641788161081095242677999752664315845687657572464353026167520041778459158 +Same result as zkcrypto! + +and this is not the same result as blst +*/ + // equals_vec384(res, res_vec); + + true +} + +fn test_mul_temp_by_2() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + //2367106380816923637832389518823092703674202766714323478820851269126356623723913304989534316437425836090100832620729 + //[9172416622910853305, 14987574562624449790, 13213778230238218784, + //15872153713916140599, 9712154313263354644, 1108202597211161767] + let mut r1_vec = ~Vec::new::(); + r1_vec.push(9172416622910853305); + r1_vec.push(14987574562624449790); + r1_vec.push(13213778230238218784); + r1_vec.push(15872153713916140599); + r1_vec.push(9712154313263354644); + r1_vec.push(1108202597211161767); + + let mut vec_2 = ~Vec::new::(); + vec_2.push(2); + vec_2.push(0); + vec_2.push(0); + vec_2.push(0); + vec_2.push(0); + vec_2.push(0); + +//731803206412179882246989211910281250791522713489639072309644402128681596956988745536381003745836008142307392681671 +//[4942402229743843015, 9318263540022139389, 545137813202804253, +//6058225393708017072, 14012204848056006994, 342606576774783668] + let res = mul_temp(r1_vec, vec_2, p_vec, 6); + print_vec384(res); + /* + 11360606136736300744 + 10320420748134520786 + 17912563010296520217 + 16145629554006184624 + 12933232110729028586 + 1518885514198738558 + Same result as zkcrypto! + + */ + true +} \ No newline at end of file diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index e2c08c9..eb1dbc9 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -223,6 +223,131 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +// from https://github.com/zkcrypto/bls12_381 +pub fn montgomery_reduction(t: [u64;12]) -> vec384 { + let k = multiply_wrap(t[0], INV); + + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); + let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); + let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); + let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); + let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); + let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); + let r6_7: (u64, u64) = adc(t[6], 0, r5.1); + + let k = multiply_wrap(r1.0, INV); + let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); + let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); + let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); + let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); + + let k = multiply_wrap(r2.0, INV); + let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); + let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); + let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); + let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); + + let k = multiply_wrap(r3.0, INV); + let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); + let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); + let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); + let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); + + let k = multiply_wrap(r4.0, INV); + let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); + let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); + let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); + let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); + + let k = multiply_wrap(r5.0, INV); + let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); + let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); + let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); + let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); + let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); + let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); + let r11_12 = adc(t[11], r10_11.1, r10.1); + + subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) + +} + +// Naive multiplication implementation following zkcrypto. +// stand-in until we figure our how to make mul_mont_n work +pub fn mul_temp(a: Vec, b: Vec, p: Vec, n: u64) -> vec384 { + + let a0 = unpack_or_0(a.get(0)); + let a1 = unpack_or_0(a.get(1)); + let a2 = unpack_or_0(a.get(2)); + let a3 = unpack_or_0(a.get(3)); + let a4 = unpack_or_0(a.get(4)); + let a5 = unpack_or_0(a.get(5)); + + let b0 = unpack_or_0(b.get(0)); + let b1 = unpack_or_0(b.get(1)); + let b2 = unpack_or_0(b.get(2)); + let b3 = unpack_or_0(b.get(3)); + let b4 = unpack_or_0(b.get(4)); + let b5 = unpack_or_0(b.get(5)); + + let (t0, carry) = mac(0, a0, b0, 0); + let (t1, carry) = mac(0, a0, b1, carry); + let (t2, carry) = mac(0, a0, b2, carry); + let (t3, carry) = mac(0, a0, b3, carry); + let (t4, carry) = mac(0, a0, b4, carry); + let (t5, t6) = mac(0, a0, b5, carry); + + let (t1, carry) = mac(t1, a1, b0, 0); + let (t2, carry) = mac(t2, a1, b1, carry); + let (t3, carry) = mac(t3, a1, b2, carry); + let (t4, carry) = mac(t4, a1, b3, carry); + let (t5, carry) = mac(t5, a1, b4, carry); + let (t6, t7) = mac(t6, a1, b5, carry); + + let (t2, carry) = mac(t2, a2, b0, 0); + let (t3, carry) = mac(t3, a2, b1, carry); + let (t4, carry) = mac(t4, a2, b2, carry); + let (t5, carry) = mac(t5, a2, b3, carry); + let (t6, carry) = mac(t6, a2, b4, carry); + let (t7, t8) = mac(t7, a2, b5, carry); + + let (t3, carry) = mac(t3, a3, b0, 0); + let (t4, carry) = mac(t4, a3, b1, carry); + let (t5, carry) = mac(t5, a3, b2, carry); + let (t6, carry) = mac(t6, a3, b3, carry); + let (t7, carry) = mac(t7, a3, b4, carry); + let (t8, t9) = mac(t8, a3, b5, carry); + + let (t4, carry) = mac(t4, a4, b0, 0); + let (t5, carry) = mac(t5, a4, b1, carry); + let (t6, carry) = mac(t6, a4, b2, carry); + let (t7, carry) = mac(t7, a4, b3, carry); + let (t8, carry) = mac(t8, a4, b4, carry); + let (t9, t10) = mac(t9, a4, b5, carry); + + let (t5, carry) = mac(t5, a5, b0, 0); + let (t6, carry) = mac(t6, a5, b1, carry); + let (t7, carry) = mac(t7, a5, b2, carry); + let (t8, carry) = mac(t8, a5, b3, carry); + let (t9, carry) = mac(t9, a5, b4, carry); + let (t10, t11) = mac(t10, a5, b5, carry); + + let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + montgomery_reduction(res) +} + pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut limbx: u64 = 0; let mut borrow: u64 = 0; @@ -501,23 +626,12 @@ pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { //returns the result and new carry of a + b*c + carry pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { - let A: U128 = U128 { - upper: 0, - lower: a, - }; - let B: U128 = U128 { - upper: 0, - lower: b, - }; - let C: U128 = U128 { - upper: 0, - lower: c, - }; - let CARRY: U128 = U128 { - upper: 0, - lower: carry, - }; - let res: U128 = A + (B * C) + CARRY; + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let c_128: U128 = ~U128::from(0, c); + let carry_128: U128 = ~U128::from(0, carry); + + let res: U128 = a_128 + (b_128 * c_128) + carry_128; (res.lower, res.upper) } From eee70db7c61c174c2218ea3585aa2fb7f8b94eb2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 19 Jul 2022 20:42:48 -0600 Subject: [PATCH 096/160] Temporary montgomery multiplication from nccgroup. To test similar to them with the 'from' and 'to' montgomery form. --- bls12-381/src/main.sw | 5 +- bls12-381/src/tests/tests_temp_fe_mont_mul.sw | 73 ++++++++++++ bls12-381/src/vect.sw | 111 ++++++++++++++++++ 3 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 bls12-381/src/tests/tests_temp_fe_mont_mul.sw diff --git a/bls12-381/src/main.sw b/bls12-381/src/main.sw index 8203d87..604d0fe 100644 --- a/bls12-381/src/main.sw +++ b/bls12-381/src/main.sw @@ -9,6 +9,7 @@ dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; dep tests/tests_small_functions; dep tests/tests_temp_mul; +dep tests/tests_temp_fe_mont_mul; use std::{assert::assert, option::*, u128::*, vec::Vec}; use ::fields::*; @@ -22,16 +23,18 @@ use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; use ::tests_small_functions::tests_small_functions; use ::tests_temp_mul::tests_temp_mul; +use ::tests_temp_fe_mont_mul::tests_temp_fe_mont_mul; fn main() { // assert(fp_tests()); // assert(fp2_tests()); // assert(test_multiply_wrap()); // assert(test_mac()); - assert(vect_subfunctions_tests()); + // assert(vect_subfunctions_tests()); // assert(tests_small_functions()); // assert(tests_temp_mul()); + assert(tests_temp_fe_mont_mul()); } fn test_mac() -> bool { diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw new file mode 100644 index 0000000..cf68518 --- /dev/null +++ b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw @@ -0,0 +1,73 @@ +library tests_temp_fe_mont_mul; + +use ::vect::*; +use std::{assert::assert, vec::Vec}; +use ::test_helpers::*; + +pub fn tests_temp_fe_mont_mul() -> bool { + assert(test_temp_mul_random_by_random()); + true +} + +fn test_temp_mul_random_by_random() -> bool { + let mut p_vec = ~Vec::new::(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); + + // a * b mod p + //941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 + //[16494539950903960225, 6909894500484332639, 10854278113294925999, 10279541547892741855, 12499445441687670930, 440910865060157199] + let a_mont = fe_to_mont(r1_vec); + let b_mont = fe_to_mont(r2_vec); + let res = temp_fe_mont_mul(a_mont, b_mont); + let res_norm = fe_to_norm(res); + print_vec(res_norm); +/* +current output... +18417799008695130381 +18138064264643904941 +8275434384499309183 +7900175912883409568 +10537467630215797999 +*/ + true +} + +/* +Note: from the reference impl, you can see it's being tested as follows: + + + let a_big = rnd_big_mod_n(); + let b_big = rnd_big_mod_n(); + fe_to_mont(&mut a_mont, &big_to_6u64(&a_big)); + fe_to_mont(&mut b_mont, &big_to_6u64(&b_big)); + + let expected = (&a_big * &b_big) % &(*N_BIG); + fe_mont_mul(&mut actual_mont, &a_mont, &b_mont); + + fe_to_norm(&mut actual_norm, &actual_mont); + assert_eq!(big_to_6u64(&expected), actual_norm); + +So there is a conversion to and from the mont form +*/ diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index eb1dbc9..91cf495 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -223,6 +223,117 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +fn zero_vec() -> Vec { + let mut temp: Vec = ~Vec::new::(); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp.push(0); + temp +} + +// Effectively a_mont = (a_norm * R) mod N +pub fn fe_to_mont(a: Vec) -> Vec { + let mut BLS12_381_RR: Vec = ~Vec::new::(); + BLS12_381_RR.push(0xf4df1f341c341746); + BLS12_381_RR.push(0x0a76e6a609d104f1); + BLS12_381_RR.push(0x8de5476c4c95b6d5); + BLS12_381_RR.push(0x67eb88a9939d83c0); + BLS12_381_RR.push(0x9a793e85b519952d); + BLS12_381_RR.push(0x11988fe592cae3aa); + temp_fe_mont_mul(a, BLS12_381_RR) +} + +// Effectively a_norm = (a_mont * R^{-1}) mod N +pub fn fe_to_norm(a: Vec) -> Vec { + let mut ONE: Vec = ~Vec::new::(); + ONE.push(0x1); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + temp_fe_mont_mul(a, ONE) +} + +// temporary mont mult impl from https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ +// with repo https://github.com/nccgroup/pairing +pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { + let mut temp: Vec = zero_vec(); + let mut i = 0; + let mut j = 0; + let mut carry = 0u64; + while i < 6 { + carry = 0; + while j < 6 { + let aj: U128 = ~U128::from(0, unpack_or_0(a.get(j))); + let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); + let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); + let carry_128 = ~U128::from(0, carry); + let hilo: U128 = aj + bi + temp_ij + carry_128; + temp.remove(i+j); + temp.insert(i+j, hilo.lower); + carry = hilo.upper; + j += 1; + } + let mut t = unpack_or_0(temp.get(i+6)); + temp.remove(i+6); + temp.insert(i+6, t+carry); + + let m: u64 = multiply_wrap(unpack_or_0(temp.get(i)), P0); + let m_128 = ~U128::from(0, m); + + carry = 0; + j = 0; + while j < 6 { + let nj: U128 = ~U128::from(0, BLS12_381_P.ls[j]); + let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); + let carry_128 = ~U128::from(0, carry); + let hilo: U128 = m_128 + nj + temp_ij + carry_128; + temp.remove(i+j); + temp.insert(i+j, hilo.lower); + carry = hilo.upper; + j += 1; + } + t = unpack_or_0(temp.get(i+6)); + temp.remove(i+6); + temp.insert(i+6, t+carry); + i += 1; + } + + let mut dec: Vec = zero_vec(); + let mut borrow = 0u64; + j = 0; + while j < 6 { + let (diff, borrow_t0) = sbb(unpack_or_0(temp.get(j + 6)), BLS12_381_P.ls[j], borrow); + dec.insert(j, diff); + borrow = borrow_t0; + j += 1; + } + + let mask: u64 = if borrow == 1 { + ~u64::max() - 1 + } else { + 0 + }; + let mut result: Vec = zero_vec(); + j = 0; + while j < 6 { + let entry = (unpack_or_0(temp.get(j+6)) & mask) | (not(mask) & unpack_or_0(dec.get(j))); + result.insert(j, entry); + j += 1; + } + result +} + // from https://github.com/zkcrypto/bls12_381 pub fn montgomery_reduction(t: [u64;12]) -> vec384 { let k = multiply_wrap(t[0], INV); From dfeeea23b41dc7d4a358ff2adbb80eb34ecb7859 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 20 Jul 2022 14:53:08 -0600 Subject: [PATCH 097/160] temp_fe_mont_mul works and added comments to test. --- bls12-381/src/tests/tests_temp_fe_mont_mul.sw | 66 +++++++++++++++---- bls12-381/src/vect.sw | 8 +-- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw index cf68518..f7de638 100644 --- a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw @@ -3,6 +3,7 @@ library tests_temp_fe_mont_mul; use ::vect::*; use std::{assert::assert, vec::Vec}; use ::test_helpers::*; +use std::logging::log; pub fn tests_temp_fe_mont_mul() -> bool { assert(test_temp_mul_random_by_random()); @@ -35,21 +36,64 @@ fn test_temp_mul_random_by_random() -> bool { r2_vec.push(2211903887497377980); r2_vec.push(395875676649998273); - // a * b mod p - //941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 - //[16494539950903960225, 6909894500484332639, 10854278113294925999, 10279541547892741855, 12499445441687670930, 440910865060157199] let a_mont = fe_to_mont(r1_vec); + // print_vec(a_mont); + /* +17993655965713306301 +15604842006860479165 +10837926002905938402 +13429498400065700031 +1823694494885156540 +933350646299434799 + */ + let b_mont = fe_to_mont(r2_vec); + // print_vec(b_mont); + /* +5720430457560562798 +2568557665684583703 +15870134958983808442 +14065062413899436375 +12262047246709729804 +1303068506660090079 + */ + let res = temp_fe_mont_mul(a_mont, b_mont); - let res_norm = fe_to_norm(res); - print_vec(res_norm); + print_vec(res); + /* +8042921339150017446 +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 + */ + + /* + This is what res has as a value at this point, but running all the operations gives the error + out of gas, so just run with this known value. All intermediate steps are correct with + the ncc ref implementation + */ + let mut intermediate_res_vec = ~Vec::new::(); + intermediate_res_vec.push(8042921339150017446); + intermediate_res_vec.push(4899742317194411181); + intermediate_res_vec.push(11922910400151252689); + intermediate_res_vec.push(7736564210120511729); + intermediate_res_vec.push(10892349319971706476); + intermediate_res_vec.push(542573957820843489); + // let res_norm = fe_to_norm(res); + // let res_norm = fe_to_norm(intermediate_res_vec); + // print_vec(res_norm); /* -current output... -18417799008695130381 -18138064264643904941 -8275434384499309183 -7900175912883409568 -10537467630215797999 +16494539950903960225 + +6909894500484332639 * 2^64 + +10854278113294925999 * 2^128 + +10279541547892741855 * 2^192 + +12499445441687670930 * 2^256 + +440910865060157199 *2^320 + +941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 +which is a*b mod p */ true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index 91cf495..c28a2ee 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -24,7 +24,6 @@ pub struct vec384x { } - //TODO: remove these. Only for developing and testing atm pub const ZERO: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0] @@ -273,12 +272,13 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let mut carry = 0u64; while i < 6 { carry = 0; + j = 0; while j < 6 { let aj: U128 = ~U128::from(0, unpack_or_0(a.get(j))); let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); let carry_128 = ~U128::from(0, carry); - let hilo: U128 = aj + bi + temp_ij + carry_128; + let hilo: U128 = aj * bi + temp_ij + carry_128; temp.remove(i+j); temp.insert(i+j, hilo.lower); carry = hilo.upper; @@ -297,7 +297,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let nj: U128 = ~U128::from(0, BLS12_381_P.ls[j]); let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); let carry_128 = ~U128::from(0, carry); - let hilo: U128 = m_128 + nj + temp_ij + carry_128; + let hilo: U128 = m_128 * nj + temp_ij + carry_128; temp.remove(i+j); temp.insert(i+j, hilo.lower); carry = hilo.upper; @@ -320,7 +320,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { } let mask: u64 = if borrow == 1 { - ~u64::max() - 1 + ~u64::max() } else { 0 }; From 8b55d304ad8877e2f3606b828181ec704e6e4dc1 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 20 Jul 2022 18:05:13 -0600 Subject: [PATCH 098/160] Trying to use temp_fe_mont_mul and the conversions as a temporary replacement for temp_mul_mont_n, but the test runs out of gas. --- bls12-381/src/tests/tests_temp_fe_mont_mul.sw | 66 ++++++++- .../src/tests/tests_vect_subfunctions.sw | 137 ++++++++++++++---- bls12-381/src/vect.sw | 120 ++++++++++----- 3 files changed, 248 insertions(+), 75 deletions(-) diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw index f7de638..62b47bf 100644 --- a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls12-381/src/tests/tests_temp_fe_mont_mul.sw @@ -6,7 +6,61 @@ use ::test_helpers::*; use std::logging::log; pub fn tests_temp_fe_mont_mul() -> bool { - assert(test_temp_mul_random_by_random()); + // assert(test_temp_mul_random_by_random()); + assert(test_temp_mul_mont_n()); + true +} + +fn test_temp_mul_mont_n() -> bool { + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 + let mut r1_vec = ~Vec::new::(); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); + //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 + let mut r2_vec = ~Vec::new::(); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); + + //Sway can't handle this. Error: + /* + { + "Panic": { + "id": "0000000000000000000000000000000000000000000000000000000000000000", + "is": 10352, + "pc": 169804, + "reason": { + "instruction": { + "imm06": 0, + "imm12": 0, + "imm18": 0, + "imm24": 0, + "op": 96, + "ra": 0, + "rb": 0, + "rc": 0, + "rd": 0 + }, + "reason": "OutOfGas" + } + } + }, + { + "ScriptResult": { + "gas_used": 100000000, + "result": "Panic" + } + } + */ + let res = temp_mul_mont_n(r1_vec, r2_vec); + print_vec(res); true } @@ -36,7 +90,7 @@ fn test_temp_mul_random_by_random() -> bool { r2_vec.push(2211903887497377980); r2_vec.push(395875676649998273); - let a_mont = fe_to_mont(r1_vec); + // let a_mont = fe_to_mont(r1_vec); // print_vec(a_mont); /* 17993655965713306301 @@ -47,7 +101,7 @@ fn test_temp_mul_random_by_random() -> bool { 933350646299434799 */ - let b_mont = fe_to_mont(r2_vec); + // let b_mont = fe_to_mont(r2_vec); // print_vec(b_mont); /* 5720430457560562798 @@ -58,8 +112,8 @@ fn test_temp_mul_random_by_random() -> bool { 1303068506660090079 */ - let res = temp_fe_mont_mul(a_mont, b_mont); - print_vec(res); + // let res = temp_fe_mont_mul(a_mont, b_mont); + // print_vec(res); /* 8042921339150017446 4899742317194411181 @@ -82,7 +136,7 @@ fn test_temp_mul_random_by_random() -> bool { intermediate_res_vec.push(10892349319971706476); intermediate_res_vec.push(542573957820843489); // let res_norm = fe_to_norm(res); - // let res_norm = fe_to_norm(intermediate_res_vec); + let res_norm = fe_to_norm(intermediate_res_vec); // print_vec(res_norm); /* 16494539950903960225 + diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls12-381/src/tests/tests_vect_subfunctions.sw index 901b352..ac19eb1 100644 --- a/bls12-381/src/tests/tests_vect_subfunctions.sw +++ b/bls12-381/src/tests/tests_vect_subfunctions.sw @@ -22,6 +22,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_mul_mont_n_one_by_one()); // assert(test_mul_mont_n_random_by_one()); // assert(test_mul_mont_n_random_by_random()); + assert(test_mont_mul_partial()); // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added // assert(test_sub_zero_from_zero_subn()); @@ -31,7 +32,7 @@ pub fn vect_subfunctions_tests() -> bool { // assert(test_sub_2_randoms_subn()); // assert(test_sub_2_randoms_reverse_subn()); - assert(tests_redc_mont()); + // assert(tests_redc_mont()); true } @@ -98,17 +99,26 @@ fn test_mul_mont_n_random_by_one() -> bool { let(_, p_vec) = get_test_vectors(); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r_vec = ~Vec::new::(); - r_vec.push(0x54439c4ae7869f30); - r_vec.push(0xa7fdefad55c032ba); - r_vec.push(0x21282f739c0a15e7); - r_vec.push(0x6cc7a6e8c38430ff); - r_vec.push(0x50db69783b321139); - r_vec.push(0xba78745dadd17a93); + r_vec.push(0x54439c4ae7869f30); //6071868568151433008 + r_vec.push(0xa7fdefad55c032ba); //12105094901188801210 + r_vec.push(0x21282f739c0a15e7); //2389211775905699303 + r_vec.push(0x6cc7a6e8c38430ff); //7838417195104481535 + r_vec.push(0x50db69783b321139); //5826366508043997497 + r_vec.push(0xba78745dadd17a93); //13436617433956842131 let one_vec = get_one_vec(); let res = mul_mont_n(r_vec, one_vec, p_vec, P0, 6); - print_vec(res); - equals_vec(res, r_vec, 6); + // print_vec(res); + /* + + */ + // let b = equals_vec(res, r_vec, 6); + // log(b); + let mut i = 0; + while i < 6 { + assert(unpack_or_0(res.get(i)) == unpack_or_0(r_vec.get(i))); + i += 1; + } true } @@ -116,31 +126,100 @@ fn test_mul_mont_n_random_by_random() -> bool { let(_, p_vec) = get_test_vectors(); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); - r1_vec.push(0x54439c4ae7869f30); - r1_vec.push(0xa7fdefad55c032ba); - r1_vec.push(0x21282f739c0a15e7); - r1_vec.push(0x6cc7a6e8c38430ff); - r1_vec.push(0x50db69783b321139); - r1_vec.push(0xba78745dadd17a93); + r1_vec.push(6071868568151433008); + r1_vec.push(12105094901188801210); + r1_vec.push(2389211775905699303); + r1_vec.push(7838417195104481535); + r1_vec.push(5826366508043997497); + r1_vec.push(13436617433956842131); //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 let mut r2_vec = ~Vec::new::(); - r2_vec.push(0xeb6f61c69e4c7eef); - r2_vec.push(0xa70784fb3f9ac549); - r2_vec.push(0x91f41a633e1d9601); - r2_vec.push(0xf89a44e9a52e99e); - r2_vec.push(0x1eb242ddd39638bc); - r2_vec.push(0x57e6ed499f0c7c1); + r2_vec.push(16964885827015180015); + r2_vec.push(12035734743809705289); + r2_vec.push(10517060043363161601); + r2_vec.push(1119606639881808286); + r2_vec.push(2211903887497377980); + r2_vec.push(395875676649998273); //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 + //[4793585148327242455, 2837967030551533581, 1626660158106644623, + //15384342728939744618, 1826521055323312182, 528164867630647501] + + // mult by p0 + //241244430210532575562827373868655963084727802841779217074318408842127082994632785925923353131362216879147315212775676243090892648326992525470904388378004276874316175983655739522130737118499414971959740231422333803704862166384557102941841719958128272 + // mod p + //1233002344306172478209354248697859329250780126726480993298462574958424022710616415994206080732967265541051783400711 +//[1734233419737550087, 7827676449723675145, 5835727259298429301, 3992373620040751347, 13994230039556723943, 577251792061825638] let mut res_vec = ~Vec::new::(); - res_vec.push(0x42863c4b7ea22ad7); - res_vec.push(0x27627bfa644b580d); - res_vec.push(0x16930ecb9e3a308f); - res_vec.push(0xd5802a33c5512d6a); - res_vec.push(0x19591b38f5515036); - res_vec.push(0x7546b2615f748cd); - let res = mul_mont_n(r1_vec, r2_vec, p_vec, 1, 6); - equals_vec(res, res_vec, 6); + res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 + res_vec.push(0x27627bfa644b580d);//2837967030551533581 + res_vec.push(0x16930ecb9e3a308f);//1626660158106644623 + res_vec.push(0xd5802a33c5512d6a);//15384342728939744618 + res_vec.push(0x19591b38f5515036);//1826521055323312182 + res_vec.push(0x7546b2615f748cd);//528164867630647501 + let res = mul_mont_n(r1_vec, r2_vec, p_vec, P0, 6); + print_vec(res); + /* +10466566815393401694 +14579313370948138685 +11816151785009594293 +7246864926219872143 +15908820384664990112 +328568623818015453 + +blst impl +3517150968681791168 +13347192682519393737 +4541454005160136609 +16590274403525876995 +17086414653262144931 +16572945458942657492 + */ + // equals_vec(res, res_vec, 6); + + true +} + +fn test_mont_mul_partial() -> bool { + let(_, p_vec) = get_test_vectors(); + + let mut intermediate_res_vec = ~Vec::new::(); + intermediate_res_vec.push(8042921339150017446); + intermediate_res_vec.push(4899742317194411181); + intermediate_res_vec.push(11922910400151252689); + intermediate_res_vec.push(7736564210120511729); + intermediate_res_vec.push(10892349319971706476); + intermediate_res_vec.push(542573957820843489); + + let mut ONE: Vec = ~Vec::new::(); + ONE.push(0x1); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + ONE.push(0); + + let res = mul_mont_n(intermediate_res_vec, ONE, p_vec, P0, 6); + print_vec(res); + +/* +Should be +16494539950903960225 +6909894500484332639 +10854278113294925999 +10279541547892741855 +12499445441687670930 +440910865060157199 + +//Current output is: +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 +0 +This is almost the input vector... +*/ true } diff --git a/bls12-381/src/vect.sw b/bls12-381/src/vect.sw index c28a2ee..cafaa6a 100644 --- a/bls12-381/src/vect.sw +++ b/bls12-381/src/vect.sw @@ -92,9 +92,10 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, 0); let mut tmp: Vec = ~Vec::new::(); - let mut tmp2: Vec = ~Vec::new::();//new vector - let mut tmp3: Vec = ~Vec::new::();//new vector + let mut tmp2: Vec = ~Vec::new::(); + let mut tmp3: Vec = ~Vec::new::(); let mut i = 0; + while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let limbx = mx * ai + hi; @@ -102,44 +103,33 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec hi = ~U128::from(0, limbx.upper); i += 1; } + tmp.insert(i, hi.lower); -//0x89f3fffcfffcfffd * 1 let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0)))).lower; let mut mx: U128 = ~U128::from(0, mx_temp); - //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); - tmp.insert(i, hi.lower); let mut carry: u64 = 0; let mut j = 0; let mut limbx: U128 = ~U128::from(0, 0); while true { let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); - //log(mx);//000000000000000089f3fffcfffcfffd - //2: 3947442df695f8f1286adb92d9d113e8 - //log(p0);//0000000000000000b9feffffffffaaab - //2: 0000000000000000b9feffffffffaaab - //log(tmp0);//00000000000000000000000000000001 - //2: 00000000000000006a4aaa14be07a408 - //1: 16^^643abe09d200a404ffffffffffffffff - //2: 16^^299d8e4220faed31901f94fb2b3b54280000000000000000 - //this is 190 bits instead of fitting into 128 limbx = (mx * p0) + tmp0; - //log(limbx);//643abe09d200a4050000000000000000 - //2: f21393888e24ec0f0000000000000000 hi = ~U128::from(0, limbx.upper); - //log(hi);//0000000000000000643abe09d200a405 - //2: 0000000000000000f21393888e24ec0f i = 1; + + //just to be sure copying this over + let mut k = 0; + while k < 12 { + tmp2.push(unpack_or_0(tmp.get(k))); + k += 1; + } + while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - //log(pi);//00000000000000001eabfffeb153ffff - //log(tmpi);//00000000000000000000000000000000 limbx = (mx * pi + hi) + tmpi; - //log(limbx);//108747eeefa29c0f6a4aaa14be07a408 tmp2.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); - //log(hi);//0000000000000000108747eeefa29c0f i += 1; } limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); @@ -152,34 +142,29 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec } mx = ~U128::from(0, unpack_or_0(b.get(j))); hi = ~U128::from(0, 0); - //log(mx);//00000000000000006730d2a0f6b0f624 - //log(hi);//00000000000000000000000000000000 i = 0; + + //just to be sure copying this over + k = 0; + while k < 12 { + tmp3.push(unpack_or_0(tmp2.get(k))); + k += 1; + } + while i < n { let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); - //log(ai);//379b7b3fafdc26ed5d4f098d2923b9a3 - //log(tmpi);//0000000000000000379b7b3fafdc26ed limbx = (mx * ai + hi) + tmpi; - //log(limbx);//000000000000000064774b84f38512bf tmp3.insert(i, limbx.lower); hi = ~U128::from(0, limbx.upper); - //log(hi);//00000000000000000000000000000000 i += 1; } let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp3.get(0)))).lower; let mut mx: U128 = ~U128::from(0, mx_temp); - //mx = ~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0))); - //log(mx);//3623991cf3a341e8622385e49d0feeb0 (126 bits) limbx = hi + ~U128::from(0, carry); - //log(limbx);//00000000000000003623991cf3a341e8 tmp3.insert(i, limbx.lower); - //log(tmp);//00000000000000004b1ba7b6434bacd7 carry = limbx.upper; - //log(carry);//00000000000000000000000000000000 - - //Conclusion so far: mx will become really large and then overflow in next iteration } let mut borrow: u64 = 0; @@ -201,17 +186,38 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec borrow = b_res & 0x1; i += 1; } - //log(carry); - //log(borrow); + + /*ret: +9944055374826099202 +9712768888634044113 +300889636556430029 +3653011359556993965 +13577214253059692810 +16572945456062011749 +0..0 + */ + + /*tmp3: +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 +0 +0 +4899742317194411181 +11922910400151252689 +7736564210120511729 +10892349319971706476 +542573957820843489 + */ + let mask: u64 = if carry >= borrow { carry-borrow } else { ~u64::max() - (borrow - carry - 1) }; -// mask = carry - borrow; - // let mask: u64 = borrow * ~u64::max(); - i = 0; let mut res: Vec = ~Vec::new::(); while i < n { @@ -239,6 +245,19 @@ fn zero_vec() -> Vec { temp } +/* +The mul_mont_n is not working yet, so this would be a temporary solution but using montgomery mult. +*/ +pub fn temp_mul_mont_n(a: Vec, b: Vec) -> Vec { + // To mont form + let a_mont = fe_to_mont(a); + let b_mont = fe_to_mont(b); + // Mult + let res = temp_fe_mont_mul(a_mont, b_mont); + // Transform back + fe_to_norm(res) +} + // Effectively a_mont = (a_norm * R) mod N pub fn fe_to_mont(a: Vec) -> Vec { let mut BLS12_381_RR: Vec = ~Vec::new::(); @@ -319,6 +338,27 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { j += 1; } + + /*temp: +0..0 +16494539950903960225 +6909894500484332639 +10854278113294925999 +10279541547892741855 +12499445441687670930 +440910865060157199 + */ + + /*dec: +3092108934826096630 +4699752988967124064 +3418603539730844299 +3040203587478029344 +7087341663216968635 +17013856321122168949 +0..0 + */ + let mask: u64 = if borrow == 1 { ~u64::max() } else { From 6685301c5b077b56fd2d555c39a1f1b68c010b70 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 22 Jul 2022 10:35:53 -0600 Subject: [PATCH 099/160] Fix rebase! --- edwards25519/src/field_element.sw | 468 +++++++++++++++++------------- 1 file changed, 270 insertions(+), 198 deletions(-) diff --git a/edwards25519/src/field_element.sw b/edwards25519/src/field_element.sw index 73a8888..a22875e 100644 --- a/edwards25519/src/field_element.sw +++ b/edwards25519/src/field_element.sw @@ -14,9 +14,11 @@ pub struct Element { // = (1 << 51) - 1 // But using the above expression gives the error "Could not evaluate initializer to a const declaration." -pub const mask_low_51_bits: u64 = 2251799813685247; -pub const zero: Element = Element{ l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 }; -pub const one: Element = Element{ l0: 1, l1: 0, l2: 0, l3: 0, l4: 0 }; +const MASK_LOW_51_BITS: u64 = 2251799813685247; + +pub const ZERO: Element = Element { + l0: 0, l1: 0, l2: 0, l3: 0, l4: 0 +}; // from NaCl impl https://cr.yp.to/ecdh.html#use fn times19(x: u64) -> u64 { @@ -24,7 +26,7 @@ fn times19(x: u64) -> u64 { } /*Do 1 round of carrying -This return an element of which all li have at most 52 bits. +This returns an element of which all li have at most 52 bits. So the elm is at most: (2^52 - 1) + (2^52 - 1) * 2^51 + @@ -34,25 +36,26 @@ So the elm is at most: */ pub fn carry_propagate(e: Element) -> Element { // all ci have at most 13 bits - let c0 = e.l0 >> 51; - let c1 = e.l1 >> 51; - let c2 = e.l2 >> 51; - let c3 = e.l3 >> 51; + let c0 = e.l0 >> 51; + let c1 = e.l1 >> 51; + let c2 = e.l2 >> 51; + let c3 = e.l3 >> 51; // c4 represents what carries over to the 2^255 element - // since we're working 2^255 - 19, this will carry over to the first element, + // since we're working 2^255 - 19, this will carry over to the first element, // multiplied by 19 - let c4 = e.l4 >> 51; + let c4 = e.l4 >> 51; - // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and - // the final l0 will be at most 52 bits. Similarly for the rest. + // c4 is at most 64 - 51 = 13 bits, so c4*19 is at most 18 bits, and + // the final l0 will be at most 52 bits. Similarly for the rest. // c4 * 19 is at most 13 + 5 = 18 bits => l0 is at most 52 bits - let new_l0 = (e.l0 & mask_low_51_bits) + times19(c4); - Element{ l0: new_l0, - l1: (e.l1 & mask_low_51_bits) + c0, - l2: (e.l2 & mask_low_51_bits) + c1, - l3: (e.l3 & mask_low_51_bits) + c2, - l4: (e.l4 & mask_low_51_bits) + c3 + let new_l0 = (e.l0 & MASK_LOW_51_BITS) + times19(c4); + Element { + l0: new_l0, + l1: (e.l1 & MASK_LOW_51_BITS) + c0, + l2: (e.l2 & MASK_LOW_51_BITS) + c1, + l3: (e.l3 & MASK_LOW_51_BITS) + c2, + l4: (e.l4 & MASK_LOW_51_BITS) + c3, } } @@ -84,20 +87,20 @@ pub fn reduce(e: Element) -> Element { let mut v0 = red.l0 + times19(carry); let mut v1 = red.l1 + (v0 >> 51); - v0 = v0 & mask_low_51_bits; + v0 = v0 & MASK_LOW_51_BITS; let mut v2 = red.l2 + (v1 >> 51); - v1 = v1 & mask_low_51_bits; + v1 = v1 & MASK_LOW_51_BITS; let mut v3 = red.l3 + (v2 >> 51); - v2 = v2 & mask_low_51_bits; - let mut v4 = (red.l4 + (v3 >> 51)) & mask_low_51_bits; - v3 = v3 & mask_low_51_bits; - - Element{ - l0: v0, - l1: v1, - l2: v2, - l3: v3, - l4: v4 + v2 = v2 & MASK_LOW_51_BITS; + let mut v4 = (red.l4 + (v3 >> 51)) & MASK_LOW_51_BITS; + v3 = v3 & MASK_LOW_51_BITS; + + Element { + l0: v0, + l1: v1, + l2: v2, + l3: v3, + l4: v4, } } @@ -105,152 +108,142 @@ pub fn reduce(e: Element) -> Element { return a + b mod 2^255 - 19 */ pub fn add(a: Element, b: Element) -> Element { - let temp = Element{ - l0: a.l0 + b.l0, - l1: a.l1 + b.l1, - l2: a.l2 + b.l2, - l3: a.l3 + b.l3, - l4: a.l4 + b.l4 + let temp = Element { + l0: a.l0 + b.l0, + l1: a.l1 + b.l1, + l2: a.l2 + b.l2, + l3: a.l3 + b.l3, + l4: a.l4 + b.l4, }; carry_propagate(temp) } -//subtract fn returns a - b +//subtract fn returns a - b mod 2^255 - 19 pub fn subtract(a: Element, b: Element) -> Element { // we add 2*p to avoid any underflow and then subtract b let res: Element = Element { - l0: (a.l0 + 0xFFFFFFFFFFFDA) - b.l0, - l1: (a.l1 + 0xFFFFFFFFFFFFE) - b.l1, - l2: (a.l2 + 0xFFFFFFFFFFFFE) - b.l2, - l3: (a.l3 + 0xFFFFFFFFFFFFE) - b.l3, - l4: (a.l4 + 0xFFFFFFFFFFFFE) - b.l4 + l0: (a.l0 + 0xFFFFFFFFFFFDA) - b.l0, + l1: (a.l1 + 0xFFFFFFFFFFFFE) - b.l1, + l2: (a.l2 + 0xFFFFFFFFFFFFE) - b.l2, + l3: (a.l3 + 0xFFFFFFFFFFFFE) - b.l3, + l4: (a.l4 + 0xFFFFFFFFFFFFE) - b.l4, }; - //carry_propagate(res) reduce(res) } -//negate return negaive of an element(-a) -pub fn negate (a: Element) -> Element { - subtract(zero,a) - +//negate return negaive of an element(-a) mod 2^255 - 19 +pub fn negate(a: Element) -> Element { + subtract(ZERO, a) } //returns 128-bit product of a and b -pub fn multiply64 (a: u64, b: u64) -> U128 { - - let A: U128 = U128 {upper: 0, lower: a}; - let B: U128 = U128 {upper: 0, lower: b}; - let AB: U128 = A*B; - return AB - +pub fn multiply64(a: u64, b: u64) -> U128 { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + a_128 * b_128 } //returns sum with carry of a and b -pub fn add64 (a: u64, b: u64, carry: u64) -> (u64, u64) { - let A:U128 = U128{upper: 0, lower: a}; - let B:U128 = U128{upper: 0, lower: b}; - let Carry: U128 = U128 { upper: 0, lower: carry }; +pub fn add64(a: u64, b: u64, carry: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let carry_128: U128 = ~U128::from(0, carry); - let sum: u64 = (A+B+Carry).lower; + let sum: u64 = (a_128 + b_128 + carry_128).lower; let notSum = ~u64::max() - sum; - let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; + let carryOut = ((a & b) | ((a | b) & notSum)) >> 63; (sum, carryOut) } -//returns res + a * b -pub fn add_multiply64 (res: U128, a: u64, b: u64) -> U128 { +//returns res + a * b +pub fn add_multiply64(res: U128, a: u64, b: u64) -> U128 { let mul_res: U128 = multiply64(a, b); let add_res: (u64, u64) = add64(mul_res.lower, res.lower, 0); let add_res2: (u64, u64) = add64(mul_res.upper, res.upper, add_res.1); - U128{ - upper: add_res2.0, - lower: add_res.0 - } + ~U128::from(add_res2.0, add_res.0) } //right shift by 51 -pub fn shiftRightBy51(a: U128) -> u64 { - (a.upper <<(64-51)) | (a.lower >> 51) +pub fn shift_right_by51(a: U128) -> u64 { + (a.upper <<(64 - 51)) | (a.lower >> 51) } //returns square of an Element pub fn square(a: Element) -> Element { - multiply(a,a) + multiply(a, a) } - //returns a*b -pub fn multiply (a: Element, b: Element) -> Element { - +pub fn multiply(a: Element, b: Element) -> Element { //https://cs.opensource.google/go/go/+/master:src/crypto/internal/edwards25519/field/fe_generic.go;l=34;bpv=0?q=feMul&sq=&ss=go%2Fgo - + let a0 = a.l0; - let a1 = a.l1; - let a2 = a.l2; - let a3 = a.l3; - let a4 = a.l4; - - let b0 = b.l0; - let b1 = b.l1; - let b2 = b.l2; - let b3 = b.l3; - let b4 = b.l4; - - let a1_19 = times19(a1); - let a2_19 = times19(a2); - let a3_19 = times19(a3); - let a4_19 = times19(a4); + let a1 = a.l1; + let a2 = a.l2; + let a3 = a.l3; + let a4 = a.l4; + + let b0 = b.l0; + let b1 = b.l1; + let b2 = b.l2; + let b3 = b.l3; + let b4 = b.l4; + + let a1_19 = times19(a1); + let a2_19 = times19(a2); + let a3_19 = times19(a3); + let a4_19 = times19(a4); // r0 = a0×b0 + 19×(a1×b4 + a2×b3 + a3×b2 + a4×b1) let mut r0: U128 = multiply64(a0, b0); - r0 = add_multiply64(r0, a1_19, b4); - r0 = add_multiply64(r0, a2_19, b3); - r0 = add_multiply64(r0, a3_19, b2); - r0 = add_multiply64(r0, a4_19, b1); + r0 = add_multiply64(r0, a1_19, b4); + r0 = add_multiply64(r0, a2_19, b3); + r0 = add_multiply64(r0, a3_19, b2); + r0 = add_multiply64(r0, a4_19, b1); // r1 = a0×b1 + a1×b0 + 19×(a2×b4 + a3×b3 + a4×b2) - let mut r1: U128 = multiply64(a0, b1); - r1 = add_multiply64(r1, a1, b0); - r1 = add_multiply64(r1, a2_19, b4); - r1 = add_multiply64(r1, a3_19, b3); - r1 = add_multiply64(r1, a4_19, b2); + let mut r1: U128 = multiply64(a0, b1); + r1 = add_multiply64(r1, a1, b0); + r1 = add_multiply64(r1, a2_19, b4); + r1 = add_multiply64(r1, a3_19, b3); + r1 = add_multiply64(r1, a4_19, b2); // r2 = a0×b2 + a1×b1 + a2×b0 + 19×(a3×b4 + a4×b3) - let mut r2: U128 = multiply64(a0, b2); - r2 = add_multiply64(r2, a1, b1); - r2 = add_multiply64(r2, a2, b0); - r2 = add_multiply64(r2, a3_19, b4); - r2 = add_multiply64(r2, a4_19, b3); + let mut r2: U128 = multiply64(a0, b2); + r2 = add_multiply64(r2, a1, b1); + r2 = add_multiply64(r2, a2, b0); + r2 = add_multiply64(r2, a3_19, b4); + r2 = add_multiply64(r2, a4_19, b3); // r3 = a0×b3 + a1×b2 + a2×b1 + a3×b0 + 19×a4×b4 - let mut r3: U128 = multiply64(a0, b3); - r3 = add_multiply64(r3, a1, b2); - r3 = add_multiply64(r3, a2, b1); - r3 = add_multiply64(r3, a3, b0); - r3 = add_multiply64(r3, a4_19, b4); + let mut r3: U128 = multiply64(a0, b3); + r3 = add_multiply64(r3, a1, b2); + r3 = add_multiply64(r3, a2, b1); + r3 = add_multiply64(r3, a3, b0); + r3 = add_multiply64(r3, a4_19, b4); //r4 = a0×b4 + a1×b3 + a2×b2 + a3×b1 + a4×b0 - let mut r4: U128 = multiply64(a0, b4); - r4 = add_multiply64(r4, a1, b3); - r4 = add_multiply64(r4, a2, b2); - r4 = add_multiply64(r4, a3, b1); - r4 = add_multiply64(r4, a4, b0); - - let c0 = shiftRightBy51(r0); - let c1 = shiftRightBy51(r1); - let c2 = shiftRightBy51(r2); - let c3 = shiftRightBy51(r3); - let c4 = shiftRightBy51(r4); - - let rr0 = (r0.lower & mask_low_51_bits) + times19(c4); - let rr1 = (r1.lower & mask_low_51_bits) + c0; - let rr2 = (r2.lower & mask_low_51_bits) + c1; - let rr3 = (r3.lower & mask_low_51_bits) + c2; - let rr4 = (r4.lower & mask_low_51_bits) + c3; + let mut r4: U128 = multiply64(a0, b4); + r4 = add_multiply64(r4, a1, b3); + r4 = add_multiply64(r4, a2, b2); + r4 = add_multiply64(r4, a3, b1); + r4 = add_multiply64(r4, a4, b0); + + let c0 = shift_right_by51(r0); + let c1 = shift_right_by51(r1); + let c2 = shift_right_by51(r2); + let c3 = shift_right_by51(r3); + let c4 = shift_right_by51(r4); + + let rr0 = (r0.lower & MASK_LOW_51_BITS) + times19(c4); + let rr1 = (r1.lower & MASK_LOW_51_BITS) + c0; + let rr2 = (r2.lower & MASK_LOW_51_BITS) + c1; + let rr3 = (r3.lower & MASK_LOW_51_BITS) + c2; + let rr4 = (r4.lower & MASK_LOW_51_BITS) + c3; let res: Element = Element { l0: rr0, @@ -265,9 +258,9 @@ pub fn multiply (a: Element, b: Element) -> Element { // For a bignumber <= 102 bits stored in U128, // return the 51 bit coefficient and 51 bit carry -fn get_coeff_and_carry(y: U128) -> (u64, u64) { - let coeff: u64 = y.lower & mask_low_51_bits; - let carry: u64 = (y.upper << 13 & mask_low_51_bits) | y.lower >> 51; +pub fn get_coeff_and_carry(y: U128) -> (u64, u64) { + let coeff: u64 = y.lower & MASK_LOW_51_BITS; + let carry: u64 = (y.upper << 13 & MASK_LOW_51_BITS) | y.lower >> 51; (coeff, carry) } @@ -289,7 +282,7 @@ pub fn scalar_mult(e: Element, x: u32) -> Element { let (coeff3, carry3) = get_coeff_and_carry(l3_temp); let (coeff4, carry4) = get_coeff_and_carry(l4_temp); - let res0: u64 = coeff0 + carry4*19; + let res0: u64 = coeff0 + times19(carry4); let res1: u64 = coeff1 + carry0; let res2: u64 = coeff2 + carry1; let res3: u64 = coeff3 + carry2; @@ -318,87 +311,166 @@ pub fn equals(a: Element, b: Element) -> bool { res == 0 } -// //a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p -// pub fn inverse(a: Element) -> Element { -// let mut i = 0; -// let z2 = square(a); //2 -// let mut t = square(z2); //4 -// t = square(t); //8 -// let z9 = multiply(t,a); //9 -// let z11 = multiply(z9, z2); //11 -// t = square(z11); //22 - -// let z2_5_0 = multiply(t, z9); //31 -// t = square(z2_5_0); // 62 = 2^6 - 2^1 -// while i < 4 { -// t = square(t); // 2^10 - 2^5 -// i+=1; -// } - -// let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 - -// t = square(z2_10_0); //2^11 - 2^1 -// i = 0; -// while i < 9 { -// t = square(t); //2^20 - 2^10 -// i += 1; -// } - -// let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 - -// t = square(z2_20_0); //2^21 - 2^1 -// i = 0; -// while i < 19 { -// t = square(t); //2^40 - 2^20 -// i += 1; -// } - -// t = multiply(t, z2_20_0); //2^40 - 2^0 +/* +//Testing not done +//a^(-1) mod p = a^(p-2) mod p by Fermat's theorem, Hence we calculate a^(p-2) mod p +pub fn inverse(a: Element) -> Element { + let mut i = 0; + let z2 = square(a); //2 + let mut t = square(z2); //4 + t = square(t); //8 + +// Comment Elena: when I run inverse until here, it gives me the error: Immediate18TooLarge + + + // let z9 = multiply(t,a); //9 + // let z11 = multiply(z9, z2); //11 + // t = square(z11); //22 + + // let z2_5_0 = multiply(t, z9); //31 + // t = square(z2_5_0); // 62 = 2^6 - 2^1 + // while i < 4 { + // t = square(t); // 2^10 - 2^5 + // i+=1; + // } + + // let z2_10_0 = multiply(t, z2_5_0); // 2^10 - 2^0 + + // t = square(z2_10_0); //2^11 - 2^1 + // i = 0; + // while i < 9 { + // t = square(t); //2^20 - 2^10 + // i += 1; + // } + + // let z2_20_0 = multiply(t, z2_10_0); //2^20 - 2^0 + + // t = square(z2_20_0); //2^21 - 2^1 + // i = 0; + // while i < 19 { + // t = square(t); //2^40 - 2^20 + // i += 1; + // } + + // t = multiply(t, z2_20_0); //2^40 - 2^0 + + // t = square(t); // 2^41 - 2^1 -// i = 0; -// while i < 10 { -// t = square(t); //2^50 - 2^10 -// } + // i = 0; + // while i < 10 { + // t = square(t); //2^50 - 2^10 + // } -// let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 + // let z2_50_0 = multiply(t, z2_10_0); //2^50 - 2^0 -// t = square(z2_50_0); //2^51 - 2^1 + // t = square(z2_50_0); //2^51 - 2^1 -// i = 0; -// while i < 49 { -// t = square(t); //2^100 - 2^50 -// i += 1; -// } + // i = 0; + // while i < 49 { + // t = square(t); //2^100 - 2^50 + // i += 1; + // } -// let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 + // let z2_100_0 = multiply(t, z2_50_0);//2^100 - 2^0 -// t = square(z2_100_0); //2^101 - 2^1 + // t = square(z2_100_0); //2^101 - 2^1 -// i = 0; -// while i < 99 { -// t = square(t); //2^200 - 2^100 -// i += 1; -// } + // i = 0; + // while i < 99 { + // t = square(t); //2^200 - 2^100 + // i += 1; + // } -// t = multiply(t, z2_100_0); //2^200 - 2^0 + // t = multiply(t, z2_100_0); //2^200 - 2^0 -// t = square(t); //2^201 - 2^1 + // t = square(t); //2^201 - 2^1 -// i = 0; -// while i < 49 { -// t = square(t); //2^250 - 2^50 -// i += 1; -// } + // i = 0; + // while i < 49 { + // t = square(t); //2^250 - 2^50 + // i += 1; + // } -// t = multiply(t, z2_50_0); //2^250 - 2^0 + // t = multiply(t, z2_50_0); //2^250 - 2^0 -// i = 0; -// while i < 5 { -// t = square(t); //2^255 - 2^5 -// i += 1; -// } + // i = 0; + // while i < 5 { + // t = square(t); //2^255 - 2^5 + // i += 1; + // } -// t = multiply(t, z11); //2^255 - 21 = p - 2 + // t = multiply(t, z11); //2^255 - 21 = p - 2 -// return t; -// } \ No newline at end of file + return t; +} +*/ +// Invert sets v = 1/z mod p, and returns v. +// +// If z == 0, Invert returns v = 0. +/* +func (v *Element) Invert(z *Element) *Element { + // Inversion is implemented as exponentiation with exponent p − 2. It uses the + // same sequence of 255 squarings and 11 multiplications as [Curve25519]. + var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t Element + + z2.Square(z) // 2 + + t.Square(&z2) // 4 + + t.Square(&t) // 8 + + z9.Multiply(&t, z) // 9 + z11.Multiply(&z9, &z2) // 11 + t.Square(&z11) // 22 + z2_5_0.Multiply(&t, &z9) // 31 = 2^5 - 2^0 + + t.Square(&z2_5_0) // 2^6 - 2^1 + for i := 0; i < 4; i++ { + t.Square(&t) // 2^10 - 2^5 + } + z2_10_0.Multiply(&t, &z2_5_0) // 2^10 - 2^0 + + t.Square(&z2_10_0) // 2^11 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^20 - 2^10 + } + z2_20_0.Multiply(&t, &z2_10_0) // 2^20 - 2^0 + + t.Square(&z2_20_0) // 2^21 - 2^1 + for i := 0; i < 19; i++ { + t.Square(&t) // 2^40 - 2^20 + } + t.Multiply(&t, &z2_20_0) // 2^40 - 2^0 + + t.Square(&t) // 2^41 - 2^1 + for i := 0; i < 9; i++ { + t.Square(&t) // 2^50 - 2^10 + } + z2_50_0.Multiply(&t, &z2_10_0) // 2^50 - 2^0 + + t.Square(&z2_50_0) // 2^51 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^100 - 2^50 + } + z2_100_0.Multiply(&t, &z2_50_0) // 2^100 - 2^0 + + t.Square(&z2_100_0) // 2^101 - 2^1 + for i := 0; i < 99; i++ { + t.Square(&t) // 2^200 - 2^100 + } + t.Multiply(&t, &z2_100_0) // 2^200 - 2^0 + + t.Square(&t) // 2^201 - 2^1 + for i := 0; i < 49; i++ { + t.Square(&t) // 2^250 - 2^50 + } + t.Multiply(&t, &z2_50_0) // 2^250 - 2^0 + + t.Square(&t) // 2^251 - 2^1 + t.Square(&t) // 2^252 - 2^2 + t.Square(&t) // 2^253 - 2^3 + t.Square(&t) // 2^254 - 2^4 + t.Square(&t) // 2^255 - 2^5 + + return v.Multiply(&t, &z11) // 2^255 - 21 +}*/ From 3020dc81ac575d02843fffa18334604962074123 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 22 Jul 2022 11:03:13 -0600 Subject: [PATCH 100/160] Start converting script tests to contract. Also renamed bls12-381 folder to bls to be able to import correctly. --- {bls12-381 => bls}/Cargo.toml | 2 +- {bls12-381 => bls}/Forc.toml | 4 +- {bls12-381 => bls}/src/consts.sw | 0 {bls12-381 => bls}/src/definitions.sw | 0 {bls12-381 => bls}/src/ec1.sw | 0 {bls12-381 => bls}/src/fields.sw | 0 {bls12-381 => bls}/src/main.sw | 0 {bls12-381 => bls}/src/test_helpers.sw | 0 .../src/tests/tests_small_functions.sw | 0 .../src/tests/tests_temp_fe_mont_mul.sw | 0 .../src/tests/tests_temp_mul.sw | 0 {bls12-381 => bls}/src/tests/tests_vect_fp.sw | 0 .../src/tests/tests_vect_fp2.sw | 0 .../src/tests/tests_vect_subfunctions.sw | 0 {bls12-381 => bls}/src/vect.sw | 0 tests-bls/.gitignore | 2 + tests-bls/Cargo.toml | 15 +++++++ tests-bls/Forc.toml | 8 ++++ tests-bls/src/main.sw | 41 +++++++++++++++++++ tests-bls/tests/harness.rs | 31 ++++++++++++++ tests-bls/tests/tests_fp/mod.rs | 27 ++++++++++++ 21 files changed, 127 insertions(+), 3 deletions(-) rename {bls12-381 => bls}/Cargo.toml (93%) rename {bls12-381 => bls}/Forc.toml (66%) rename {bls12-381 => bls}/src/consts.sw (100%) rename {bls12-381 => bls}/src/definitions.sw (100%) rename {bls12-381 => bls}/src/ec1.sw (100%) rename {bls12-381 => bls}/src/fields.sw (100%) rename {bls12-381 => bls}/src/main.sw (100%) rename {bls12-381 => bls}/src/test_helpers.sw (100%) rename {bls12-381 => bls}/src/tests/tests_small_functions.sw (100%) rename {bls12-381 => bls}/src/tests/tests_temp_fe_mont_mul.sw (100%) rename {bls12-381 => bls}/src/tests/tests_temp_mul.sw (100%) rename {bls12-381 => bls}/src/tests/tests_vect_fp.sw (100%) rename {bls12-381 => bls}/src/tests/tests_vect_fp2.sw (100%) rename {bls12-381 => bls}/src/tests/tests_vect_subfunctions.sw (100%) rename {bls12-381 => bls}/src/vect.sw (100%) create mode 100644 tests-bls/.gitignore create mode 100644 tests-bls/Cargo.toml create mode 100644 tests-bls/Forc.toml create mode 100644 tests-bls/src/main.sw create mode 100644 tests-bls/tests/harness.rs create mode 100644 tests-bls/tests/tests_fp/mod.rs diff --git a/bls12-381/Cargo.toml b/bls/Cargo.toml similarity index 93% rename from bls12-381/Cargo.toml rename to bls/Cargo.toml index 27d6243..2b4e1f1 100644 --- a/bls12-381/Cargo.toml +++ b/bls/Cargo.toml @@ -1,5 +1,5 @@ [project] -name = "bls12-381" +name = "bls" version = "0.1.0" authors = ["HashCloak"] edition = "2021" diff --git a/bls12-381/Forc.toml b/bls/Forc.toml similarity index 66% rename from bls12-381/Forc.toml rename to bls/Forc.toml index d3112bb..e943a80 100644 --- a/bls12-381/Forc.toml +++ b/bls/Forc.toml @@ -1,7 +1,7 @@ [project] authors = ["HashCloak"] -entry = "main.sw" +entry = "fields.sw" license = "Apache-2.0" -name = "bls12-381" +name = "bls" [dependencies] diff --git a/bls12-381/src/consts.sw b/bls/src/consts.sw similarity index 100% rename from bls12-381/src/consts.sw rename to bls/src/consts.sw diff --git a/bls12-381/src/definitions.sw b/bls/src/definitions.sw similarity index 100% rename from bls12-381/src/definitions.sw rename to bls/src/definitions.sw diff --git a/bls12-381/src/ec1.sw b/bls/src/ec1.sw similarity index 100% rename from bls12-381/src/ec1.sw rename to bls/src/ec1.sw diff --git a/bls12-381/src/fields.sw b/bls/src/fields.sw similarity index 100% rename from bls12-381/src/fields.sw rename to bls/src/fields.sw diff --git a/bls12-381/src/main.sw b/bls/src/main.sw similarity index 100% rename from bls12-381/src/main.sw rename to bls/src/main.sw diff --git a/bls12-381/src/test_helpers.sw b/bls/src/test_helpers.sw similarity index 100% rename from bls12-381/src/test_helpers.sw rename to bls/src/test_helpers.sw diff --git a/bls12-381/src/tests/tests_small_functions.sw b/bls/src/tests/tests_small_functions.sw similarity index 100% rename from bls12-381/src/tests/tests_small_functions.sw rename to bls/src/tests/tests_small_functions.sw diff --git a/bls12-381/src/tests/tests_temp_fe_mont_mul.sw b/bls/src/tests/tests_temp_fe_mont_mul.sw similarity index 100% rename from bls12-381/src/tests/tests_temp_fe_mont_mul.sw rename to bls/src/tests/tests_temp_fe_mont_mul.sw diff --git a/bls12-381/src/tests/tests_temp_mul.sw b/bls/src/tests/tests_temp_mul.sw similarity index 100% rename from bls12-381/src/tests/tests_temp_mul.sw rename to bls/src/tests/tests_temp_mul.sw diff --git a/bls12-381/src/tests/tests_vect_fp.sw b/bls/src/tests/tests_vect_fp.sw similarity index 100% rename from bls12-381/src/tests/tests_vect_fp.sw rename to bls/src/tests/tests_vect_fp.sw diff --git a/bls12-381/src/tests/tests_vect_fp2.sw b/bls/src/tests/tests_vect_fp2.sw similarity index 100% rename from bls12-381/src/tests/tests_vect_fp2.sw rename to bls/src/tests/tests_vect_fp2.sw diff --git a/bls12-381/src/tests/tests_vect_subfunctions.sw b/bls/src/tests/tests_vect_subfunctions.sw similarity index 100% rename from bls12-381/src/tests/tests_vect_subfunctions.sw rename to bls/src/tests/tests_vect_subfunctions.sw diff --git a/bls12-381/src/vect.sw b/bls/src/vect.sw similarity index 100% rename from bls12-381/src/vect.sw rename to bls/src/vect.sw diff --git a/tests-bls/.gitignore b/tests-bls/.gitignore new file mode 100644 index 0000000..77d3844 --- /dev/null +++ b/tests-bls/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/tests-bls/Cargo.toml b/tests-bls/Cargo.toml new file mode 100644 index 0000000..7eb8cc1 --- /dev/null +++ b/tests-bls/Cargo.toml @@ -0,0 +1,15 @@ +[project] +name = "tests-bls" +version = "0.1.0" +authors = ["Hashcloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = { version = "0.17", features = ["fuel-core-lib"] } +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/tests-bls/Forc.toml b/tests-bls/Forc.toml new file mode 100644 index 0000000..af7d324 --- /dev/null +++ b/tests-bls/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Hashcloak"] +entry = "main.sw" +license = "Apache-2.0" +name = "tests-bls" + +[dependencies] +bls = { path = "../bls" } diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw new file mode 100644 index 0000000..36668b1 --- /dev/null +++ b/tests-bls/src/main.sw @@ -0,0 +1,41 @@ +contract; + +use bls::*; +//need to import vect.sw + +abi BlsContract { + #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; + #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; + #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; + #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; + #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; + #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; + +} + +impl BlsContract for Contract { + #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { + add_fp(a, b) + } + + #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { + add_fp(a, b) + } + + #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { + mul_by_3_fp(a) + } + + #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { + mul_by_8_fp(a) + } + + #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { + lshift_fp(a, count) + } + + #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { + rshift_fp(a, count) + } + +} \ No newline at end of file diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs new file mode 100644 index 0000000..2bbc1a8 --- /dev/null +++ b/tests-bls/tests/harness.rs @@ -0,0 +1,31 @@ +use fuels::{prelude::*, tx::ContractId}; + +// Load abi from json +abigen!(MyContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "./out/debug/tests-bls.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "./out/debug/tests-bls-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/tests-bls/tests/tests_fp/mod.rs b/tests-bls/tests/tests_fp/mod.rs new file mode 100644 index 0000000..93b7a77 --- /dev/null +++ b/tests-bls/tests/tests_fp/mod.rs @@ -0,0 +1,27 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub const ZERO: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0] +}; + +#[tokio::test] +async fn test_add_zero_to_zero() { + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add(ZERO, ZERO) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, ZERO)); +} \ No newline at end of file From 12a762def2c2f929517f1f7093435902a388bd93 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 22 Jul 2022 11:31:11 -0600 Subject: [PATCH 101/160] Trying to import multiple libs from bls --- bls/Forc.toml | 2 +- bls/src/lib.sw | 4 ++ tests-bls/src/main.sw | 124 ++++++++++++++++++++++++++------ tests-bls/tests/harness.rs | 32 +-------- tests-bls/tests/tests_fp/mod.rs | 22 +++++- 5 files changed, 129 insertions(+), 55 deletions(-) create mode 100644 bls/src/lib.sw diff --git a/bls/Forc.toml b/bls/Forc.toml index e943a80..1d4bc7e 100644 --- a/bls/Forc.toml +++ b/bls/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["HashCloak"] -entry = "fields.sw" +entry = "lib.sw" license = "Apache-2.0" name = "bls" diff --git a/bls/src/lib.sw b/bls/src/lib.sw new file mode 100644 index 0000000..181c42a --- /dev/null +++ b/bls/src/lib.sw @@ -0,0 +1,4 @@ +library bls; + +dep fields; +dep vect; \ No newline at end of file diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 36668b1..4bc7453 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -1,41 +1,123 @@ contract; use bls::*; -//need to import vect.sw abi BlsContract { + //Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; - #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; - #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; - #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; + // #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; + // #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; + // #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; + // #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; + // #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; + // #[storage()]fn div_by_2_fp(a: vec384) -> vec384; + // #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384; + // #[storage()]fn sqr_fp(a: vec384) -> vec384; + // #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384; + // #[storage()]fn from_fp(a: vec384) -> vec384; + // #[storage()]fn redc_fp(a: vec384) -> vec384; + // // Fp2 + // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384; + // #[storage()]fn sub_fp2(a: vec384, b: vec384) -> vec384; + // #[storage()]fn mul_by_3_fp2(a: vec384) -> vec384; + // #[storage()]fn mul_by_8_fp2(a: vec384) -> vec384; + // #[storage()]fn lshift_fp2(a: vec384, count: u64) -> vec384; + // #[storage()]fn rshift_fp2(a: vec384, count: u64) -> vec384; + // #[storage()]fn div_by_2_f2(a: vec384) -> vec384; + // #[storage()]fn mul_fp2(a: vec384, b: vec384) -> vec384; + // #[storage()]fn sqr_fp2(a: vec384) -> vec384; + // #[storage()]fn cneg_fp2(a: vec384, flag: u64) -> vec384; } impl BlsContract for Contract { + // Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { add_fp(a, b) } - #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { - add_fp(a, b) - } + // #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { + // add_fp(a, b) + // } - #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { - mul_by_3_fp(a) - } + // #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { + // mul_by_3_fp(a) + // } - #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { - mul_by_8_fp(a) - } + // #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { + // mul_by_8_fp(a) + // } - #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { - lshift_fp(a, count) - } + // #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { + // lshift_fp(a, count) + // } - #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { - rshift_fp(a, count) - } + // #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { + // rshift_fp(a, count) + // } + + // #[storage()]fn div_by_2_fp(a: vec384) -> vec384 { + // div_by_2_fp(a) + // } + + // #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384 { + // mul_fp(a, b) + // } + + // #[storage()]fn sqr_fp(a: vec384) -> vec384 { + // sqr_fp(a) + // } + + // #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384 { + // cneg_fp(a, flag) + // } + + // #[storage()]fn from_fp(a: vec384) -> vec384 { + // from_fp(a) + // } + + // #[storage()]fn redc_fp(a: vec384) -> vec384 { + // redc_fp(a) + // } + + // // Fp2 + // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384 { + // add_fp2(a, b) + // } + + // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384 { + // add_fp2(a, b) + // } + + // #[storage()]fn mul_by_3_fp2(a: vec384) -> vec384 { + // mul_by_3_fp2(a) + // } + + // #[storage()]fn mul_by_8_fp2(a: vec384) -> vec384 { + // mul_by_8_fp2(a) + // } + + // #[storage()]fn lshift_fp2(a: vec384, count: u64) -> vec384 { + // lshift_fp2(a, count) + // } + + // #[storage()]fn rshift_fp2(a: vec384, count: u64) -> vec384 { + // rshift_fp2(a, count) + // } + + // #[storage()]fn div_by_2_fp2(a: vec384) -> vec384 { + // div_by_2_fp2(a) + // } + + // #[storage()]fn mul_fp2(a: vec384, b: vec384) -> vec384 { + // mul_fp2(a, b) + // } + + // #[storage()]fn sqr_fp2(a: vec384) -> vec384 { + // sqr_fp2(a) + // } + // #[storage()]fn cneg_fp2(a: vec384, flag: u64) -> vec384 { + // cneg_fp2(a, flag) + // } } \ No newline at end of file diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 2bbc1a8..689c777 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,31 +1 @@ -use fuels::{prelude::*, tx::ContractId}; - -// Load abi from json -abigen!(MyContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (MyContract, ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_wallet().await; - - let id = Contract::deploy( - "./out/debug/tests-bls.bin", - &wallet, - TxParameters::default(), - StorageConfiguration::with_storage_path(Some( - "./out/debug/tests-bls-storage_slots.json".to_string(), - )), - ) - .await - .unwrap(); - - let instance = MyContract::new(id.to_string(), wallet); - - (instance, id) -} - -#[tokio::test] -async fn can_get_contract_id() { - let (_instance, _id) = get_contract_instance().await; - - // Now you have an instance of your contract you can use to test each function -} +mod tests_fp; \ No newline at end of file diff --git a/tests-bls/tests/tests_fp/mod.rs b/tests-bls/tests/tests_fp/mod.rs index 93b7a77..16aaa31 100644 --- a/tests-bls/tests/tests_fp/mod.rs +++ b/tests-bls/tests/tests_fp/mod.rs @@ -19,9 +19,27 @@ pub const ZERO: vec384 = vec384 { async fn test_add_zero_to_zero() { let (_instance, _id) = get_contract_instance().await; - let res = _instance.add(ZERO, ZERO) + let res = _instance.add_fp(ZERO, ZERO) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(res_equals(res, ZERO)); -} \ No newline at end of file +} + +// #[tokio::test] +// async fn test_add_zero_to_random() { +// let random = vec384{ +// ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] +// }; +// let expected_res = vec384{ +// ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] +// }; + +// let (_instance, _id) = get_contract_instance().await; + +// let res = _instance.add_fp(random, ZERO) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// assert!(res_equals(res, expected_res)); +// } \ No newline at end of file From 45d2a74ef0debffc74cc356076ed3e903a555a76 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 22 Jul 2022 13:42:00 -0600 Subject: [PATCH 102/160] - A single test for bls working through contract - Ran forc fmt - Using an older SDK version in tests-bls for the moment (should be upgraded for both bls and edwards testing) --- README.md | 7 + bls/src/lib.sw | 2 +- bls/src/test_helpers.sw | 1 - bls/src/tests/tests_small_functions.sw | 1 - bls/src/tests/tests_temp_fe_mont_mul.sw | 6 +- bls/src/tests/tests_temp_mul.sw | 21 ++- bls/src/tests/tests_vect_fp.sw | 1 - bls/src/tests/tests_vect_subfunctions.sw | 28 ++- bls/src/vect.sw | 224 +++++++++++------------ tests-bls/Cargo.toml | 3 +- tests-bls/src/main.sw | 2 +- tests-bls/tests/tests_fp/mod.rs | 25 ++- 12 files changed, 165 insertions(+), 156 deletions(-) diff --git a/README.md b/README.md index 39b19ab..536042f 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,10 @@ Various Cryptographic Primitives in Sway for the Fuel VM forc test ``` +## BLS + + To run tests for bls folder: + ``` + cd tests-bls + forc test + ``` diff --git a/bls/src/lib.sw b/bls/src/lib.sw index 181c42a..c69d70c 100644 --- a/bls/src/lib.sw +++ b/bls/src/lib.sw @@ -1,4 +1,4 @@ library bls; dep fields; -dep vect; \ No newline at end of file +dep vect; diff --git a/bls/src/test_helpers.sw b/bls/src/test_helpers.sw index 4478fba..0d25a7a 100644 --- a/bls/src/test_helpers.sw +++ b/bls/src/test_helpers.sw @@ -38,5 +38,4 @@ pub fn print_vec(a: Vec) { log(unpack_or_0(a.get(i))); i += 1; } - } diff --git a/bls/src/tests/tests_small_functions.sw b/bls/src/tests/tests_small_functions.sw index 8586169..6889e18 100644 --- a/bls/src/tests/tests_small_functions.sw +++ b/bls/src/tests/tests_small_functions.sw @@ -1,6 +1,5 @@ library tests_small_functions; - use ::fields::*; use ::vect::*; use ::test_helpers::*; diff --git a/bls/src/tests/tests_temp_fe_mont_mul.sw b/bls/src/tests/tests_temp_fe_mont_mul.sw index 62b47bf..c09904b 100644 --- a/bls/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls/src/tests/tests_temp_fe_mont_mul.sw @@ -72,7 +72,7 @@ fn test_temp_mul_random_by_random() -> bool { p_vec.push(0x64774b84f38512bf); p_vec.push(0x4b1ba7b6434bacd7); p_vec.push(0x1a0111ea397fe69a); - + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); r1_vec.push(6071868568151433008); @@ -92,7 +92,7 @@ fn test_temp_mul_random_by_random() -> bool { // let a_mont = fe_to_mont(r1_vec); // print_vec(a_mont); - /* + /* 17993655965713306301 15604842006860479165 10837926002905938402 @@ -138,7 +138,7 @@ fn test_temp_mul_random_by_random() -> bool { // let res_norm = fe_to_norm(res); let res_norm = fe_to_norm(intermediate_res_vec); // print_vec(res_norm); -/* + /* 16494539950903960225 + 6909894500484332639 * 2^64 + 10854278113294925999 * 2^128 + diff --git a/bls/src/tests/tests_temp_mul.sw b/bls/src/tests/tests_temp_mul.sw index a1f5583..e7ba638 100644 --- a/bls/src/tests/tests_temp_mul.sw +++ b/bls/src/tests/tests_temp_mul.sw @@ -17,7 +17,7 @@ fn test_temp_mul_random_by_random() -> bool { p_vec.push(0x64774b84f38512bf); p_vec.push(0x4b1ba7b6434bacd7); p_vec.push(0x1a0111ea397fe69a); - + //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); r1_vec.push(6071868568151433008); @@ -38,7 +38,8 @@ fn test_temp_mul_random_by_random() -> bool { //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 //12684677789208411253122026388948849483224138949631185589801456383786133679073 let res_vec = vec384 { - ls: [4793585148327242455, 2837967030551533581, 1626660158106644623, 15384342728939744618, 1826521055323312182, 528164867630647501] + ls: [4793585148327242455, + 2837967030551533581, 1626660158106644623, 15384342728939744618, 1826521055323312182, 528164867630647501] }; // let mut res_vec = ~Vec::new::(); // res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 @@ -50,7 +51,7 @@ fn test_temp_mul_random_by_random() -> bool { let res = mul_temp(r1_vec, r2_vec, p_vec, 6); print_vec384(res); -/* + /* 16484308011771146774 + 12795119582497094196 * 2^64 + 7495239071060242083 * 2^128 + @@ -66,7 +67,7 @@ Same result as zkcrypto! and this is not the same result as blst */ // equals_vec384(res, res_vec); - + true } @@ -78,9 +79,9 @@ fn test_mul_temp_by_2() -> bool { p_vec.push(0x64774b84f38512bf); p_vec.push(0x4b1ba7b6434bacd7); p_vec.push(0x1a0111ea397fe69a); - + //2367106380816923637832389518823092703674202766714323478820851269126356623723913304989534316437425836090100832620729 - //[9172416622910853305, 14987574562624449790, 13213778230238218784, + //[9172416622910853305, 14987574562624449790, 13213778230238218784, //15872153713916140599, 9712154313263354644, 1108202597211161767] let mut r1_vec = ~Vec::new::(); r1_vec.push(9172416622910853305); @@ -98,9 +99,9 @@ fn test_mul_temp_by_2() -> bool { vec_2.push(0); vec_2.push(0); -//731803206412179882246989211910281250791522713489639072309644402128681596956988745536381003745836008142307392681671 -//[4942402229743843015, 9318263540022139389, 545137813202804253, -//6058225393708017072, 14012204848056006994, 342606576774783668] + //731803206412179882246989211910281250791522713489639072309644402128681596956988745536381003745836008142307392681671 + //[4942402229743843015, 9318263540022139389, 545137813202804253, + //6058225393708017072, 14012204848056006994, 342606576774783668] let res = mul_temp(r1_vec, vec_2, p_vec, 6); print_vec384(res); /* @@ -114,4 +115,4 @@ fn test_mul_temp_by_2() -> bool { */ true -} \ No newline at end of file +} diff --git a/bls/src/tests/tests_vect_fp.sw b/bls/src/tests/tests_vect_fp.sw index 7391af2..300ca1b 100644 --- a/bls/src/tests/tests_vect_fp.sw +++ b/bls/src/tests/tests_vect_fp.sw @@ -136,7 +136,6 @@ a+b< p is true true } - fn tests_mul_by_3_fp() -> bool { //3*0=0 let three_times_0 = mul_by_3_fp(ZERO); diff --git a/bls/src/tests/tests_vect_subfunctions.sw b/bls/src/tests/tests_vect_subfunctions.sw index ac19eb1..c238531 100644 --- a/bls/src/tests/tests_vect_subfunctions.sw +++ b/bls/src/tests/tests_vect_subfunctions.sw @@ -7,7 +7,6 @@ use std::logging::log; use std::{assert::assert, vec::Vec}; use ::consts::*; - pub fn vect_subfunctions_tests() -> bool { // NOTE: Don't run all at the same time, because will run out of gas @@ -142,21 +141,21 @@ fn test_mul_mont_n_random_by_random() -> bool { r2_vec.push(395875676649998273); //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 - //[4793585148327242455, 2837967030551533581, 1626660158106644623, + //[4793585148327242455, 2837967030551533581, 1626660158106644623, //15384342728939744618, 1826521055323312182, 528164867630647501] // mult by p0 //241244430210532575562827373868655963084727802841779217074318408842127082994632785925923353131362216879147315212775676243090892648326992525470904388378004276874316175983655739522130737118499414971959740231422333803704862166384557102941841719958128272 // mod p //1233002344306172478209354248697859329250780126726480993298462574958424022710616415994206080732967265541051783400711 -//[1734233419737550087, 7827676449723675145, 5835727259298429301, 3992373620040751347, 13994230039556723943, 577251792061825638] + //[1734233419737550087, 7827676449723675145, 5835727259298429301, 3992373620040751347, 13994230039556723943, 577251792061825638] let mut res_vec = ~Vec::new::(); - res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 - res_vec.push(0x27627bfa644b580d);//2837967030551533581 - res_vec.push(0x16930ecb9e3a308f);//1626660158106644623 - res_vec.push(0xd5802a33c5512d6a);//15384342728939744618 - res_vec.push(0x19591b38f5515036);//1826521055323312182 - res_vec.push(0x7546b2615f748cd);//528164867630647501 + res_vec.push(0x42863c4b7ea22ad7); //4793585148327242455 + res_vec.push(0x27627bfa644b580d); //2837967030551533581 + res_vec.push(0x16930ecb9e3a308f); //1626660158106644623 + res_vec.push(0xd5802a33c5512d6a); //15384342728939744618 + res_vec.push(0x19591b38f5515036); //1826521055323312182 + res_vec.push(0x7546b2615f748cd); //528164867630647501 let res = mul_mont_n(r1_vec, r2_vec, p_vec, P0, 6); print_vec(res); /* @@ -176,7 +175,7 @@ blst impl 16572945458942657492 */ // equals_vec(res, res_vec, 6); - + true } @@ -202,7 +201,7 @@ fn test_mont_mul_partial() -> bool { let res = mul_mont_n(intermediate_res_vec, ONE, p_vec, P0, 6); print_vec(res); -/* + /* Should be 16494539950903960225 6909894500484332639 @@ -464,7 +463,6 @@ fn test_redc_mont_n_small() -> bool { } fn test_redc_mont_n_p() -> bool { - let mut p_vec = ~Vec::new::(); p_vec.push(0xb9feffffffffaaab); p_vec.push(0x1eabfffeb153ffff); @@ -494,13 +492,13 @@ fn test_redc_mont_n_random() -> bool { = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] */ let mut a_vec = ~Vec::new::(); - + a_vec.push(13282407956253574712); a_vec.push(7557322358563246340); a_vec.push(14991082624209354397); a_vec.push(6631139461101160670); a_vec.push(10719928016004921607); - a_vec.push(1730705806359781376); + a_vec.push(1730705806359781376); a_vec.push(0); a_vec.push(0); a_vec.push(0); @@ -520,11 +518,9 @@ fn test_redc_mont_n_random() -> bool { print_vec(res); //equals_vec(res, result, 6); true - } fn test_redc_mont_n_random_large() -> bool { - /* a = random({2^384}) = 21380795309672530537064108666460268360580493838230277925224860893329212391422460281305468429766194371347271041959862 = [10009796384580774444, 9837491998535547791, 12861376030615125811, 15982738825684268908, 17984324540840297179, 13142370077570254774] diff --git a/bls/src/vect.sw b/bls/src/vect.sw index cafaa6a..4dcbca2 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -4,7 +4,7 @@ dep consts; use std::{option::*, u128::*, vec::Vec}; use consts::*; -use std::logging::log; + // Stores field element with max 384 bits // element in fp pub struct vec384 { @@ -23,8 +23,7 @@ pub struct vec384x { i: vec384, //"imaginary" part } - -//TODO: remove these. Only for developing and testing atm +//TODO: remove these. Only for developing (as placeholder return values) and testing atm pub const ZERO: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0] }; @@ -88,6 +87,18 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { res } + +/* +WIP + +This is following the blst implementation. + +It's unclear why the output that the blst gives would be the correct one. + +For example: temp_fe_mont_mul implements montgomery mult following ncc impl does give the right "montgomery output", +which has conversions before and after to perform a complete multiplication. +But this intermediate value doesn't correspond to what the blst impl outputs. +*/ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, 0); @@ -178,10 +189,9 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { (tmpi - pi_w_borrow, 0) } else { - (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0,1)), 1) + (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0, 1)), 1) }; limbx = sub_res; - //borrow = b_res; ret.insert(i, limbx.lower); borrow = b_res & 0x1; i += 1; @@ -213,7 +223,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec */ let mask: u64 = if carry >= borrow { - carry-borrow + carry - borrow } else { ~u64::max() - (borrow - carry - 1) }; @@ -228,6 +238,9 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec res } +// TEMP MONTGOMERY MULT FROM NCC impl +// Repo: https://github.com/nccgroup/pairing +// Blogpost: https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ fn zero_vec() -> Vec { let mut temp: Vec = ~Vec::new::(); temp.push(0); @@ -288,7 +301,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let mut temp: Vec = zero_vec(); let mut i = 0; let mut j = 0; - let mut carry = 0u64; + let mut carry = 0u64; while i < 6 { carry = 0; j = 0; @@ -298,14 +311,14 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); let carry_128 = ~U128::from(0, carry); let hilo: U128 = aj * bi + temp_ij + carry_128; - temp.remove(i+j); - temp.insert(i+j, hilo.lower); + temp.remove(i + j); + temp.insert(i + j, hilo.lower); carry = hilo.upper; j += 1; } - let mut t = unpack_or_0(temp.get(i+6)); - temp.remove(i+6); - temp.insert(i+6, t+carry); + let mut t = unpack_or_0(temp.get(i + 6)); + temp.remove(i + 6); + temp.insert(i + 6, t + carry); let m: u64 = multiply_wrap(unpack_or_0(temp.get(i)), P0); let m_128 = ~U128::from(0, m); @@ -317,14 +330,14 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); let carry_128 = ~U128::from(0, carry); let hilo: U128 = m_128 * nj + temp_ij + carry_128; - temp.remove(i+j); - temp.insert(i+j, hilo.lower); + temp.remove(i + j); + temp.insert(i + j, hilo.lower); carry = hilo.upper; j += 1; } - t = unpack_or_0(temp.get(i+6)); - temp.remove(i+6); - temp.insert(i+6, t+carry); + t = unpack_or_0(temp.get(i + 6)); + temp.remove(i + 6); + temp.insert(i + 6, t + carry); i += 1; } @@ -332,14 +345,13 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let mut borrow = 0u64; j = 0; while j < 6 { - let (diff, borrow_t0) = sbb(unpack_or_0(temp.get(j + 6)), BLS12_381_P.ls[j], borrow); + let(diff, borrow_t0) = sbb(unpack_or_0(temp.get(j + 6)), BLS12_381_P.ls[j], borrow); dec.insert(j, diff); borrow = borrow_t0; j += 1; } - - /*temp: + /*temp: 0..0 16494539950903960225 6909894500484332639 @@ -349,7 +361,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { 440910865060157199 */ - /*dec: + /*dec: 3092108934826096630 4699752988967124064 3418603539730844299 @@ -367,7 +379,7 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { let mut result: Vec = zero_vec(); j = 0; while j < 6 { - let entry = (unpack_or_0(temp.get(j+6)) & mask) | (not(mask) & unpack_or_0(dec.get(j))); + let entry = (unpack_or_0(temp.get(j + 6)) & mask) | (not(mask) & unpack_or_0(dec.get(j))); result.insert(j, entry); j += 1; } @@ -375,9 +387,10 @@ pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { } // from https://github.com/zkcrypto/bls12_381 -pub fn montgomery_reduction(t: [u64;12]) -> vec384 { +pub fn montgomery_reduction(t: [u64; +12]) -> vec384 { let k = multiply_wrap(t[0], INV); - + let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); @@ -431,14 +444,16 @@ pub fn montgomery_reduction(t: [u64;12]) -> vec384 { let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); let r11_12 = adc(t[11], r10_11.1, r10.1); - subtract_p(vec384{ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}, BLS12_381_P) - + subtract_p(vec384 { + ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0] + }, + BLS12_381_P) } -// Naive multiplication implementation following zkcrypto. -// stand-in until we figure our how to make mul_mont_n work +// TEMP NAIVE MULT IMPL +// Naive multiplication implementation following zkcrypto. +// Can be used as stand-in until we figure our how to make mul_mont_n work or the NCC mult with conversions before and after is feasible pub fn mul_temp(a: Vec, b: Vec, p: Vec, n: u64) -> vec384 { - let a0 = unpack_or_0(a.get(0)); let a1 = unpack_or_0(a.get(1)); let a2 = unpack_or_0(a.get(2)); @@ -453,49 +468,50 @@ pub fn mul_temp(a: Vec, b: Vec, p: Vec, n: u64) -> vec384 { let b4 = unpack_or_0(b.get(4)); let b5 = unpack_or_0(b.get(5)); - let (t0, carry) = mac(0, a0, b0, 0); - let (t1, carry) = mac(0, a0, b1, carry); - let (t2, carry) = mac(0, a0, b2, carry); - let (t3, carry) = mac(0, a0, b3, carry); - let (t4, carry) = mac(0, a0, b4, carry); - let (t5, t6) = mac(0, a0, b5, carry); - - let (t1, carry) = mac(t1, a1, b0, 0); - let (t2, carry) = mac(t2, a1, b1, carry); - let (t3, carry) = mac(t3, a1, b2, carry); - let (t4, carry) = mac(t4, a1, b3, carry); - let (t5, carry) = mac(t5, a1, b4, carry); - let (t6, t7) = mac(t6, a1, b5, carry); - - let (t2, carry) = mac(t2, a2, b0, 0); - let (t3, carry) = mac(t3, a2, b1, carry); - let (t4, carry) = mac(t4, a2, b2, carry); - let (t5, carry) = mac(t5, a2, b3, carry); - let (t6, carry) = mac(t6, a2, b4, carry); - let (t7, t8) = mac(t7, a2, b5, carry); - - let (t3, carry) = mac(t3, a3, b0, 0); - let (t4, carry) = mac(t4, a3, b1, carry); - let (t5, carry) = mac(t5, a3, b2, carry); - let (t6, carry) = mac(t6, a3, b3, carry); - let (t7, carry) = mac(t7, a3, b4, carry); - let (t8, t9) = mac(t8, a3, b5, carry); - - let (t4, carry) = mac(t4, a4, b0, 0); - let (t5, carry) = mac(t5, a4, b1, carry); - let (t6, carry) = mac(t6, a4, b2, carry); - let (t7, carry) = mac(t7, a4, b3, carry); - let (t8, carry) = mac(t8, a4, b4, carry); - let (t9, t10) = mac(t9, a4, b5, carry); - - let (t5, carry) = mac(t5, a5, b0, 0); - let (t6, carry) = mac(t6, a5, b1, carry); - let (t7, carry) = mac(t7, a5, b2, carry); - let (t8, carry) = mac(t8, a5, b3, carry); - let (t9, carry) = mac(t9, a5, b4, carry); - let (t10, t11) = mac(t10, a5, b5, carry); - - let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + let(t0, carry) = mac(0, a0, b0, 0); + let(t1, carry) = mac(0, a0, b1, carry); + let(t2, carry) = mac(0, a0, b2, carry); + let(t3, carry) = mac(0, a0, b3, carry); + let(t4, carry) = mac(0, a0, b4, carry); + let(t5, t6) = mac(0, a0, b5, carry); + + let(t1, carry) = mac(t1, a1, b0, 0); + let(t2, carry) = mac(t2, a1, b1, carry); + let(t3, carry) = mac(t3, a1, b2, carry); + let(t4, carry) = mac(t4, a1, b3, carry); + let(t5, carry) = mac(t5, a1, b4, carry); + let(t6, t7) = mac(t6, a1, b5, carry); + + let(t2, carry) = mac(t2, a2, b0, 0); + let(t3, carry) = mac(t3, a2, b1, carry); + let(t4, carry) = mac(t4, a2, b2, carry); + let(t5, carry) = mac(t5, a2, b3, carry); + let(t6, carry) = mac(t6, a2, b4, carry); + let(t7, t8) = mac(t7, a2, b5, carry); + + let(t3, carry) = mac(t3, a3, b0, 0); + let(t4, carry) = mac(t4, a3, b1, carry); + let(t5, carry) = mac(t5, a3, b2, carry); + let(t6, carry) = mac(t6, a3, b3, carry); + let(t7, carry) = mac(t7, a3, b4, carry); + let(t8, t9) = mac(t8, a3, b5, carry); + + let(t4, carry) = mac(t4, a4, b0, 0); + let(t5, carry) = mac(t5, a4, b1, carry); + let(t6, carry) = mac(t6, a4, b2, carry); + let(t7, carry) = mac(t7, a4, b3, carry); + let(t8, carry) = mac(t8, a4, b4, carry); + let(t9, t10) = mac(t9, a4, b5, carry); + + let(t5, carry) = mac(t5, a5, b0, 0); + let(t6, carry) = mac(t6, a5, b1, carry); + let(t7, carry) = mac(t7, a5, b2, carry); + let(t8, carry) = mac(t8, a5, b3, carry); + let(t9, carry) = mac(t9, a5, b4, carry); + let(t10, t11) = mac(t10, a5, b5, carry); + + let res: [u64; + 12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduction(res) } @@ -534,7 +550,6 @@ pub fn sqr_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { ZERO } - pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut j = 0; let mut i = 1; @@ -543,7 +558,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut tmp: Vec = ~Vec::new::(); while j < n { let mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(b.get(0)))).lower; - let mx: U128 = ~U128::from(0, mx_temp) ; + let mx: U128 = ~U128::from(0, mx_temp); let mut limbx = mx * ~U128::from(0, unpack_or_0(p.get(0))) + ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, limbx.upper); i = 1; @@ -551,11 +566,11 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); limbx = (mx * pi + hi) + bi; - tmp.insert(i-1, limbx.lower); + tmp.insert(i - 1, limbx.lower); hi = ~U128::from(0, limbx.upper); i += 1; } - tmp.insert(i-1, hi.lower); + tmp.insert(i - 1, hi.lower); b = tmp; j += 1; } @@ -564,7 +579,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut carry = 0; i = 0; while i < n { - let ani: U128 = ~U128::from(0, unpack_or_0(a.get(n+i))); + let ani: U128 = ~U128::from(0, unpack_or_0(a.get(n + i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); let carryi: U128 = ~U128::from(0, carry); let limbx = ani + (tmpi + carryi); @@ -585,7 +600,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmp2i { (tmp2i - pi_w_borrow, 0) } else { - (~U128::max() - (pi_w_borrow - tmp2i - ~U128::from(0,1)), 1) + (~U128::max() - (pi_w_borrow - tmp2i - ~U128::from(0, 1)), 1) }; let mut limbx = sub_res; //borrow = b_res; @@ -597,10 +612,10 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { //let mut mask = carry - borrow; //let mask: u64 = borrow * ~u64::max(); let mut mask = if carry >= borrow { - carry - borrow - } else { - ~u64::max() - (borrow - carry - 1) - }; + carry - borrow + } else { + ~u64::max() - (borrow - carry - 1) + }; let mut result: Vec = ~Vec::new::(); i = 0; while i < n { @@ -660,18 +675,9 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { /// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = U128 { - lower: a, - upper: 0, - }; - let b_128: U128 = U128 { - lower: b, - upper: 0, - }; - let borrow_128: U128 = U128 { - lower: borrow, - upper: 0, - }; + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let borrow_128: U128 = ~U128::from(0, borrow); let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); (res.lower, res.upper >> 63) //(result, borrow) @@ -710,20 +716,11 @@ pub fn subtract_p(a: vec384, p: vec384) -> vec384 { //TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? //returns sum with carry of a and b pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - let a_128: U128 = U128 { - upper: 0, - lower: a, - }; - let b_128: U128 = U128 { - upper: 0, - lower: b, - }; - let c_128: U128 = U128 { - upper: 0, - lower: carry, - }; + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let carry_128: U128 = ~U128::from(0, carry); - let sum: u64 = (a_128 + b_128 + c_128).lower; + let sum: u64 = (a_128 + b_128 + carry_128).lower; let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; (sum, carry_res) @@ -788,16 +785,10 @@ pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { //returns a*b mod(2^64) pub fn multiply_wrap(a: u64, b: u64) -> u64 { - let A: U128 = U128 { - upper: 0, - lower: a, - }; - let B: U128 = U128 { - upper: 0, - lower: b, - }; + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); - (A * B).lower + (a_128 * b_128).lower } pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { @@ -854,6 +845,7 @@ fn to_vec(v: vec384) -> Vec { res } +// TODO pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { let a0_vec = to_vec(a.r); let a1_vec = to_vec(a.i); diff --git a/tests-bls/Cargo.toml b/tests-bls/Cargo.toml index 7eb8cc1..ceec775 100644 --- a/tests-bls/Cargo.toml +++ b/tests-bls/Cargo.toml @@ -6,7 +6,8 @@ edition = "2021" license = "Apache-2.0" [dependencies] -fuels = { version = "0.17", features = ["fuel-core-lib"] } +fuels = "0.16.1" +fuels-abigen-macro = "0.16.1" tokio = { version = "1.12", features = ["rt", "macros"] } [[test]] diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 4bc7453..80b5251 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -1,6 +1,6 @@ contract; -use bls::*; +use bls::{fields::*, vect::*}; abi BlsContract { //Fp diff --git a/tests-bls/tests/tests_fp/mod.rs b/tests-bls/tests/tests_fp/mod.rs index 16aaa31..77898ad 100644 --- a/tests-bls/tests/tests_fp/mod.rs +++ b/tests-bls/tests/tests_fp/mod.rs @@ -11,19 +11,34 @@ async fn get_contract_instance() -> (BlsContract, ContractId) { (instance, id) } -pub const ZERO: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0] -}; +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} #[tokio::test] async fn test_add_zero_to_zero() { + let ZERO_1: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let ZERO_2: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let ZERO_3: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; let (_instance, _id) = get_contract_instance().await; - let res = _instance.add_fp(ZERO, ZERO) + let res = _instance.add_fp(ZERO_1, ZERO_2) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - assert!(res_equals(res, ZERO)); + assert!(res_equals(res, ZERO_3)); } // #[tokio::test] From 0df4a33549392b02080328fa50d20779f0b6f019 Mon Sep 17 00:00:00 2001 From: Manish Date: Mon, 25 Jul 2022 21:49:22 +0530 Subject: [PATCH 103/160] test for sub, mul_by_x_fp --- bls/src/tests/tests_vect_fp2.sw | 5 +- bls/src/vect.sw | 7 +- tests-bls/src/main.sw | 37 +++++------ tests-bls/tests/harness.rs | 5 +- tests-bls/tests/tests_fp/mod.rs | 109 +++++++------------------------- 5 files changed, 45 insertions(+), 118 deletions(-) diff --git a/bls/src/tests/tests_vect_fp2.sw b/bls/src/tests/tests_vect_fp2.sw index 48cbfde..6cc8bfd 100644 --- a/bls/src/tests/tests_vect_fp2.sw +++ b/bls/src/tests/tests_vect_fp2.sw @@ -117,8 +117,7 @@ fn mul_fp2_by_zero() -> bool { fn mul_fp2_by_one() -> bool { let a_1 = get_a1(); let one_384 = vec384 { - ls: [1, - 0, 0, 0, 0, 0] + ls: [1, 0, 0, 0, 0, 0] }; let one = vec384x { r: one_384, @@ -140,4 +139,4 @@ fn mul_fp2_by_one() -> bool { // let smallx = vec384x {r: small, i: small }; // true -// } +// } \ No newline at end of file diff --git a/bls/src/vect.sw b/bls/src/vect.sw index 4bb9a63..4dcbca2 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -87,6 +87,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { res } + /* WIP @@ -239,7 +240,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec // TEMP MONTGOMERY MULT FROM NCC impl // Repo: https://github.com/nccgroup/pairing -// Blogpost: https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ +// Blogpost: https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ fn zero_vec() -> Vec { let mut temp: Vec = ~Vec::new::(); temp.push(0); @@ -715,9 +716,9 @@ pub fn subtract_p(a: vec384, p: vec384) -> vec384 { //TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? //returns sum with carry of a and b pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); + let a_128: U128 = ~U128::from(0, a); let b_128: U128 = ~U128::from(0, b); - let carry_128: U128 = ~U128::from(0, carry); + let carry_128: U128 = ~U128::from(0, carry); let sum: u64 = (a_128 + b_128 + carry_128).lower; let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index ded4277..80b5251 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -1,15 +1,14 @@ contract; use bls::{fields::*, vect::*}; -use std::vec::*; + abi BlsContract { //Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; - #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; - #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; - // #[storage()]fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec; + // #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; + // #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; + // #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; + // #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; // #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; // #[storage()]fn div_by_2_fp(a: vec384) -> vec384; // #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384; @@ -37,24 +36,20 @@ impl BlsContract for Contract { add_fp(a, b) } - #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384 { - sub_fp(a, b) - } - - #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { - mul_by_3_fp(a) - } + // #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { + // add_fp(a, b) + // } - #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { - mul_by_8_fp(a) - } + // #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { + // mul_by_3_fp(a) + // } - #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { - lshift_fp(a, count) - } + // #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { + // mul_by_8_fp(a) + // } - // #[storage()]fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { - // temp_fe_mont_mul(a, b) + // #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { + // lshift_fp(a, count) // } // #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 034b212..689c777 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,4 +1 @@ -mod tests_fp; -mod tests_sub_fp; -mod tests_mul_by_x_fp; -// mod tests_temp_fe_mont_mul; \ No newline at end of file +mod tests_fp; \ No newline at end of file diff --git a/tests-bls/tests/tests_fp/mod.rs b/tests-bls/tests/tests_fp/mod.rs index 2dfd7cb..77898ad 100644 --- a/tests-bls/tests/tests_fp/mod.rs +++ b/tests-bls/tests/tests_fp/mod.rs @@ -23,103 +23,38 @@ pub fn res_equals(res: vec384, should_be: vec384) -> bool { #[tokio::test] async fn test_add_zero_to_zero() { - let zero_1: vec384 = vec384 { + let ZERO_1: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0].to_vec() }; - let zero_2: vec384 = vec384 { + let ZERO_2: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0].to_vec() }; - let zero_3: vec384 = vec384 { + let ZERO_3: vec384 = vec384 { ls: [0, 0, 0, 0, 0, 0].to_vec() }; let (_instance, _id) = get_contract_instance().await; - let res = _instance.add_fp(zero_1, zero_2) + let res = _instance.add_fp(ZERO_1, ZERO_2) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - assert!(res_equals(res, zero_3)); + assert!(res_equals(res, ZERO_3)); } -#[tokio::test] -async fn test_add_zero_to_random() { - let random = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let expected_res = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let zero_4: vec384 = vec384 { - ls:[0,0,0,0,0,0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(random, zero_4) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_add_random_to_random() { - let random1 = vec384{ - ls: [13282407956253574712, 7557322358563246340, 14991082624209354397, 6631139461101160670, 10719928016004921607, 865352903179890688].to_vec() - }; - let random2 = vec384{ - ls: [13142370077570254774, 17984324540840297179, 15982738825684268908, 12861376030615125811, 9837491998535547791, 625612274036298402].to_vec() - }; - let expected_res = vec384{ - ls: [7978033960114277870, 7094902825693991904, 12527077376184071690, 1045771418006734866, 2110675940830917783, 1490965177216189091].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(random1, random2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_add_random_to_small() { - let small = vec384 { - ls: [0x1, - 0x2, 0x3, 0x4, 0x5, 0x6].to_vec() - }; - let random = vec384 { - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let expected_res = vec384{ - ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(small, random) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_add_larger_than_p() { - let a = vec384 { - ls: [13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() - }; - - let b = vec384 { - ls: [100, - 0, 0, 0, 0, 0].to_vec() - }; - let expected_res = vec384{ - ls: [13, 0, 0, 0, 0, 0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(a, b) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} \ No newline at end of file +// #[tokio::test] +// async fn test_add_zero_to_random() { +// let random = vec384{ +// ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] +// }; +// let expected_res = vec384{ +// ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] +// }; + +// let (_instance, _id) = get_contract_instance().await; + +// let res = _instance.add_fp(random, ZERO) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// assert!(res_equals(res, expected_res)); +// } \ No newline at end of file From 892b82791a9e47ca104979901c9238ab307a1579 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 25 Jul 2022 17:30:56 -0600 Subject: [PATCH 104/160] - Finished converting tests_add_fp - Added sub and mul_by_x tests to harness.rs so they are run --- bls/src/fields.sw | 4 +- bls/src/vect.sw | 2 +- tests-bls/src/main.sw | 82 +++++++++--------- tests-bls/tests/harness.rs | 5 +- tests-bls/tests/tests_add_fp/mod.rs | 126 ++++++++++++++++++++++++++++ tests-bls/tests/tests_fp/mod.rs | 60 ------------- 6 files changed, 174 insertions(+), 105 deletions(-) create mode 100644 tests-bls/tests/tests_add_fp/mod.rs delete mode 100644 tests-bls/tests/tests_fp/mod.rs diff --git a/bls/src/fields.sw b/bls/src/fields.sw index 889b35c..50ebf54 100644 --- a/bls/src/fields.sw +++ b/bls/src/fields.sw @@ -50,8 +50,8 @@ pub fn mul_fp(a: vec384, b: vec384) -> vec384 { } //TODO TEST -pub fn sqr_fp(a: vec384, b: vec384) -> vec384 { - sqr_mont_384(a, b, BLS12_381_P, P0) +pub fn sqr_fp(a: vec384) -> vec384 { + sqr_mont_384(a, BLS12_381_P, P0) } //TODO TEST diff --git a/bls/src/vect.sw b/bls/src/vect.sw index 4dcbca2..e76d861 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -545,7 +545,7 @@ pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { ZERO } -pub fn sqr_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { +pub fn sqr_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { //TODO ZERO } diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 80b5251..9160619 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -5,16 +5,16 @@ use bls::{fields::*, vect::*}; abi BlsContract { //Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; - // #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; - // #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; - // #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; - // #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; - // #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; - // #[storage()]fn div_by_2_fp(a: vec384) -> vec384; - // #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384; - // #[storage()]fn sqr_fp(a: vec384) -> vec384; - // #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384; - // #[storage()]fn from_fp(a: vec384) -> vec384; + #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; + #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; + #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; + #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; + #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; + #[storage()]fn div_by_2_fp(a: vec384) -> vec384; + #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384; + #[storage()]fn sqr_fp(a: vec384) -> vec384; + #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384; + #[storage()]fn from_fp(a: vec384) -> vec384; // #[storage()]fn redc_fp(a: vec384) -> vec384; // // Fp2 @@ -35,46 +35,46 @@ impl BlsContract for Contract { #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { add_fp(a, b) } + + #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384 { + sub_fp(a, b) + } - // #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { - // add_fp(a, b) - // } - - // #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { - // mul_by_3_fp(a) - // } + #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { + mul_by_3_fp(a) + } - // #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { - // mul_by_8_fp(a) - // } + #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { + mul_by_8_fp(a) + } - // #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { - // lshift_fp(a, count) - // } + #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { + lshift_fp(a, count) + } - // #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { - // rshift_fp(a, count) - // } + #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { + rshift_fp(a, count) + } - // #[storage()]fn div_by_2_fp(a: vec384) -> vec384 { - // div_by_2_fp(a) - // } + #[storage()]fn div_by_2_fp(a: vec384) -> vec384 { + div_by_2_fp(a) + } - // #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384 { - // mul_fp(a, b) - // } + #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384 { + mul_fp(a, b) + } - // #[storage()]fn sqr_fp(a: vec384) -> vec384 { - // sqr_fp(a) - // } + #[storage()]fn sqr_fp(a: vec384) -> vec384 { + sqr_fp(a) + } - // #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384 { - // cneg_fp(a, flag) - // } + #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384 { + cneg_fp(a, flag) + } - // #[storage()]fn from_fp(a: vec384) -> vec384 { - // from_fp(a) - // } + #[storage()]fn from_fp(a: vec384) -> vec384 { + from_fp(a) + } // #[storage()]fn redc_fp(a: vec384) -> vec384 { // redc_fp(a) diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 689c777..e1a2190 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1 +1,4 @@ -mod tests_fp; \ No newline at end of file +mod tests_add_fp; +mod tests_mul_by_x_fp; +mod tests_sub_fp; +mod tests_temp_fe_mont_mul; \ No newline at end of file diff --git a/tests-bls/tests/tests_add_fp/mod.rs b/tests-bls/tests/tests_add_fp/mod.rs new file mode 100644 index 0000000..733c6fe --- /dev/null +++ b/tests-bls/tests/tests_add_fp/mod.rs @@ -0,0 +1,126 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +#[tokio::test] +async fn test_add_zero_to_zero() { + let ZERO_1: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let ZERO_2: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let ZERO_3: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_fp(ZERO_1, ZERO_2) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, ZERO_3)); +} + +#[tokio::test] +async fn test_add_zero_to_random() { + let random = vec384{ + ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() + }; + let zero = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let expected_res = vec384{ + ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_fp(random, zero) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_add_random_to_small() { + let small = vec384{ + ls: [1, 2, 3, 4, 5, 6].to_vec() + }; + let random = vec384{ + ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() + }; + let expected_res = vec384{ + ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851].to_vec() + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_fp(small, random) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_add_larger_than_p() { + let a = vec384{ + ls: [13402431016077863508,2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() + }; + let b = vec384{ + ls: [100,0,0,0,0,0].to_vec() + }; + let expected_res = vec384{ + ls: [13, 0,0,0,0,0].to_vec() + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_fp(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_add_2_randoms() { + let random_1 = vec384{ + ls: [4510245898505151773,8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943].to_vec() + }; + let random_2 = vec384{ + ls: [8877477209635348035,16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961].to_vec() + }; + let expected_res = vec384{ + ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905].to_vec() + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_fp(random_1, random_2) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} diff --git a/tests-bls/tests/tests_fp/mod.rs b/tests-bls/tests/tests_fp/mod.rs deleted file mode 100644 index 77898ad..0000000 --- a/tests-bls/tests/tests_fp/mod.rs +++ /dev/null @@ -1,60 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_add_zero_to_zero() { - let ZERO_1: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let ZERO_2: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let ZERO_3: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(ZERO_1, ZERO_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, ZERO_3)); -} - -// #[tokio::test] -// async fn test_add_zero_to_random() { -// let random = vec384{ -// ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] -// }; -// let expected_res = vec384{ -// ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] -// }; - -// let (_instance, _id) = get_contract_instance().await; - -// let res = _instance.add_fp(random, ZERO) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// assert!(res_equals(res, expected_res)); -// } \ No newline at end of file From ae06f20f8efbb49f8687061c631cf8995ceff69e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 25 Jul 2022 18:08:42 -0600 Subject: [PATCH 105/160] - Split up l_shift tests - Trying to implement temp_fe_mont_mul test, but doesn't recognize vec --- tests-bls/src/main.sw | 9 +++ tests-bls/tests/harness.rs | 3 +- tests-bls/tests/tests_l_shift/mod.rs | 56 +++++++++++++++++++ tests-bls/tests/tests_mul_by_x_fp/mod.rs | 35 ------------ tests-bls/tests/tests_temp_fe_mont_mul/mod.rs | 26 ++++----- 5 files changed, 80 insertions(+), 49 deletions(-) create mode 100644 tests-bls/tests/tests_l_shift/mod.rs diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 9160619..5d15cd5 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -1,6 +1,8 @@ contract; use bls::{fields::*, vect::*}; +// unsure why this isn't working, bit it's needed for temp_fe_mont_mul +// use std::vec::Vec; abi BlsContract { //Fp @@ -17,6 +19,9 @@ abi BlsContract { #[storage()]fn from_fp(a: vec384) -> vec384; // #[storage()]fn redc_fp(a: vec384) -> vec384; + // Temp mul functions + // #[storage()]fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec; + // // Fp2 // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384; // #[storage()]fn sub_fp2(a: vec384, b: vec384) -> vec384; @@ -76,6 +81,10 @@ impl BlsContract for Contract { from_fp(a) } + // #[storage()]fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { + // temp_fe_mont_mul(a, b) + // } + // #[storage()]fn redc_fp(a: vec384) -> vec384 { // redc_fp(a) // } diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index e1a2190..a8ceb23 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,4 +1,5 @@ mod tests_add_fp; mod tests_mul_by_x_fp; mod tests_sub_fp; -mod tests_temp_fe_mont_mul; \ No newline at end of file +mod tests_l_shift; +// mod tests_temp_fe_mont_mul; \ No newline at end of file diff --git a/tests-bls/tests/tests_l_shift/mod.rs b/tests-bls/tests/tests_l_shift/mod.rs new file mode 100644 index 0000000..928b4b2 --- /dev/null +++ b/tests-bls/tests/tests_l_shift/mod.rs @@ -0,0 +1,56 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +#[tokio::test] +async fn test_1_lshift_p() { + let r = vec384 { + ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() + }; + let expected_res = vec384{ + ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.lshift_fp(r,1) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_250_lshift_p() { + let a = vec384 { + ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937].to_vec() + }; + let expected_res = vec384{ + ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.lshift_fp(a, 250) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file diff --git a/tests-bls/tests/tests_mul_by_x_fp/mod.rs b/tests-bls/tests/tests_mul_by_x_fp/mod.rs index b77e821..c3fb249 100644 --- a/tests-bls/tests/tests_mul_by_x_fp/mod.rs +++ b/tests-bls/tests/tests_mul_by_x_fp/mod.rs @@ -93,39 +93,4 @@ async fn tests_mul_by_8_fp() { .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(res_equals(res, expected_res)); -} - - -#[tokio::test] -async fn test_1_lshift_p() { - let r = vec384 { - ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() - }; - let expected_res = vec384{ - ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.lshift_fp(r,1) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_250_lshift_p() { - let a = vec384 { - ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937].to_vec() - }; - let expected_res = vec384{ - ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.lshift_fp(a, 250) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); } \ No newline at end of file diff --git a/tests-bls/tests/tests_temp_fe_mont_mul/mod.rs b/tests-bls/tests/tests_temp_fe_mont_mul/mod.rs index 393a06b..3b85702 100644 --- a/tests-bls/tests/tests_temp_fe_mont_mul/mod.rs +++ b/tests-bls/tests/tests_temp_fe_mont_mul/mod.rs @@ -21,17 +21,17 @@ pub fn res_equals(res: vec384, should_be: vec384) -> bool { true } -// #[tokio::test] -// async fn temp_fe_mont_mul_random() { -// let p_vec = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec(); -// let r1_vec = [17993655965713306301, 15604842006860479165, 10837926002905938402, 13429498400065700031, 1823694494885156540, 933350646299434799].to_vec(); -// let r2_vec = [5720430457560562798, 2568557665684583703, 15870134958983808442, 14065062413899436375, 12262047246709729804, 1303068506660090079].to_vec(); -// let expected_res = [8042921339150017446, 4899742317194411181, 11922910400151252689, 7736564210120511729, 10892349319971706476, 542573957820843489].to_vec() -// let (_instance, _id) = get_contract_instance().await; +#[tokio::test] +async fn test_temp_mul_random_by_random() { + let p_vec = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec(); + let r1_vec = [17993655965713306301, 15604842006860479165, 10837926002905938402, 13429498400065700031, 1823694494885156540, 933350646299434799].to_vec(); + let r2_vec = [5720430457560562798, 2568557665684583703, 15870134958983808442, 14065062413899436375, 12262047246709729804, 1303068506660090079].to_vec(); + let expected_res = [8042921339150017446, 4899742317194411181, 11922910400151252689, 7736564210120511729, 10892349319971706476, 542573957820843489].to_vec(); + let (_instance, _id) = get_contract_instance().await; -// let res = _instance.temp_fe_mont_mul(r1_vec, r2_vec) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// assert!(res_equals(res, expected_res)); -// } \ No newline at end of file + let res = _instance.temp_fe_mont_mul(r1_vec, r2_vec) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From f65f332c35afa1773060d80a950d4fe49e9690a7 Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 26 Jul 2022 18:00:38 +0530 Subject: [PATCH 106/160] test for temp_fe_mont_mul goes outOfGas --- bls/src/vect.sw | 27 +++++++++++++++++-- tests-bls/src/main.sw | 8 +++--- tests-bls/tests/harness.rs | 8 +++--- .../mod.rs | 19 ++++++++----- 4 files changed, 46 insertions(+), 16 deletions(-) rename tests-bls/tests/{tests_temp_fe_mont_mul => tests_temp_mul_mont_n}/mod.rs (58%) diff --git a/bls/src/vect.sw b/bls/src/vect.sw index e76d861..3ac0e63 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -261,14 +261,37 @@ fn zero_vec() -> Vec { /* The mul_mont_n is not working yet, so this would be a temporary solution but using montgomery mult. */ -pub fn temp_mul_mont_n(a: Vec, b: Vec) -> Vec { +//pub fn temp_mul_mont_n(a: Vec, b: Vec) -> Vec { +pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { + let mut a: Vec = ~Vec::new::(); + a.push(a_vec.ls[0]); + a.push(a_vec.ls[1]); + a.push(a_vec.ls[2]); + a.push(a_vec.ls[3]); + a.push(a_vec.ls[4]); + a.push(a_vec.ls[5]); + + let mut b: Vec = ~Vec::new::(); + b.push(b_vec.ls[0]); + b.push(b_vec.ls[1]); + b.push(b_vec.ls[2]); + b.push(b_vec.ls[3]); + b.push(b_vec.ls[4]); + b.push(b_vec.ls[5]); + + // To mont form let a_mont = fe_to_mont(a); let b_mont = fe_to_mont(b); // Mult let res = temp_fe_mont_mul(a_mont, b_mont); // Transform back - fe_to_norm(res) + let res = fe_to_norm(res); + let res_vec = vec384{ + ls: [unpack_or_0(res.get(0)),unpack_or_0(res.get(1)),unpack_or_0(res.get(2)),unpack_or_0(res.get(3)),unpack_or_0(res.get(4)),unpack_or_0(res.get(5))] + }; + + res_vec } // Effectively a_mont = (a_norm * R) mod N diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 5d15cd5..1f7c30a 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -20,7 +20,7 @@ abi BlsContract { // #[storage()]fn redc_fp(a: vec384) -> vec384; // Temp mul functions - // #[storage()]fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec; + #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384; // // Fp2 // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384; @@ -81,9 +81,9 @@ impl BlsContract for Contract { from_fp(a) } - // #[storage()]fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { - // temp_fe_mont_mul(a, b) - // } + #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384 { + temp_mul_mont_n(a, b) + } // #[storage()]fn redc_fp(a: vec384) -> vec384 { // redc_fp(a) diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index a8ceb23..c310b06 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,5 +1,5 @@ mod tests_add_fp; -mod tests_mul_by_x_fp; -mod tests_sub_fp; -mod tests_l_shift; -// mod tests_temp_fe_mont_mul; \ No newline at end of file +// mod tests_mul_by_x_fp; +// mod tests_sub_fp; +// mod tests_l_shift; +//mod tests_temp_mul_mont_n; \ No newline at end of file diff --git a/tests-bls/tests/tests_temp_fe_mont_mul/mod.rs b/tests-bls/tests/tests_temp_mul_mont_n/mod.rs similarity index 58% rename from tests-bls/tests/tests_temp_fe_mont_mul/mod.rs rename to tests-bls/tests/tests_temp_mul_mont_n/mod.rs index 3b85702..987e357 100644 --- a/tests-bls/tests/tests_temp_fe_mont_mul/mod.rs +++ b/tests-bls/tests/tests_temp_mul_mont_n/mod.rs @@ -4,7 +4,7 @@ use fuels_abigen_macro::abigen; abigen!(BlsContract, "out/debug/tests-bls-abi.json"); async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(100_000_000))).await; let wallet = wallets.pop().unwrap(); let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); let instance = BlsContract::new(id.to_string(), wallet); @@ -23,13 +23,20 @@ pub fn res_equals(res: vec384, should_be: vec384) -> bool { #[tokio::test] async fn test_temp_mul_random_by_random() { - let p_vec = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec(); - let r1_vec = [17993655965713306301, 15604842006860479165, 10837926002905938402, 13429498400065700031, 1823694494885156540, 933350646299434799].to_vec(); - let r2_vec = [5720430457560562798, 2568557665684583703, 15870134958983808442, 14065062413899436375, 12262047246709729804, 1303068506660090079].to_vec(); - let expected_res = [8042921339150017446, 4899742317194411181, 11922910400151252689, 7736564210120511729, 10892349319971706476, 542573957820843489].to_vec(); + //let p_vec: [u64;6] = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a]; + let r1_vec = vec384 { + ls: [6071868568151433008, 12105094901188801210, 2389211775905699303, 7838417195104481535, 5826366508043997497, 13436617433956842131].to_vec() + }; + let r2_vec = vec384{ + ls: [16964885827015180015, 12035734743809705289, 10517060043363161601, 1119606639881808286, 2211903887497377980, 395875676649998273].to_vec() + }; + + let expected_res = vec384 { + ls: [16494539950903960225, 6909894500484332639, 10854278113294925999, 10279541547892741855, 12499445441687670930, 440910865060157199].to_vec() + }; let (_instance, _id) = get_contract_instance().await; - let res = _instance.temp_fe_mont_mul(r1_vec, r2_vec) + let res = _instance.temp_mul_mont_n(r1_vec, r2_vec) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; From 7c755ea22c4ab92688d58c330b97a98d599837ee Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 27 Jul 2022 18:02:50 -0600 Subject: [PATCH 107/160] Converted tests for subfunctions in vect to contract testing. --- tests-bls/src/main.sw | 36 ++- tests-bls/tests/harness.rs | 5 +- tests-bls/tests/tests_small_functions/mod.rs | 219 +++++++++++++++++++ 3 files changed, 257 insertions(+), 3 deletions(-) create mode 100644 tests-bls/tests/tests_small_functions/mod.rs diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 1f7c30a..8b97e23 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -2,9 +2,17 @@ contract; use bls::{fields::*, vect::*}; // unsure why this isn't working, bit it's needed for temp_fe_mont_mul -// use std::vec::Vec; +use std::u128::*; abi BlsContract { + //Small helper functions + #[storage()]fn not(input: u64) -> u64; + #[storage()]fn subtract_wrap(x: U128, y: U128) -> U128; + #[storage()]fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64); + #[storage()]fn adc(a: u64, b: u64, carry: u64) -> (u64, u64); + #[storage()]fn subtract_p(a: vec384, p: vec384) -> vec384; + #[storage()]fn neg(a: vec384, p: vec384) -> vec384; + //Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; @@ -36,6 +44,32 @@ abi BlsContract { } impl BlsContract for Contract { + + //Small helper functions + #[storage()]fn not(input: u64) -> u64 { + not(input) + } + + #[storage()]fn subtract_wrap(x: U128, y: U128) -> U128 { + subtract_wrap(x, y) + } + + #[storage()]fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + sbb(a, b, borrow) + } + + #[storage()]fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { + adc(a, b, carry) + } + + #[storage()]fn subtract_p(a: vec384, p: vec384) -> vec384 { + subtract_p(a, p) + } + + #[storage()]fn neg(a: vec384, p: vec384) -> vec384 { + neg(a, p) + } + // Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { add_fp(a, b) diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index c310b06..9d5f26e 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,5 +1,6 @@ -mod tests_add_fp; +// mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; -//mod tests_temp_mul_mont_n; \ No newline at end of file +// mod tests_temp_mul_mont_n; +mod tests_small_functions; \ No newline at end of file diff --git a/tests-bls/tests/tests_small_functions/mod.rs b/tests-bls/tests/tests_small_functions/mod.rs new file mode 100644 index 0000000..31675b2 --- /dev/null +++ b/tests-bls/tests/tests_small_functions/mod.rs @@ -0,0 +1,219 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +#[tokio::test] +async fn test_not() { + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.not(18417751708719972248) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res == 28992364989579367); +} + +#[tokio::test] +async fn tests_subtract_wrap() { + let (_instance, _id) = get_contract_instance().await; + + let res1 = _instance.subtract_wrap(U128{upper: 0, lower: 100}, U128{upper: 0, lower: 80}) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res1.lower == 20); + assert!(res1.upper == 0); + + let res2 = _instance.subtract_wrap(U128{upper: 0, lower: 100}, U128{upper: 0, lower: 230}) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res2.lower == 18446744073709551486); + assert!(res2.upper == 18446744073709551615); +} + +#[tokio::test] +async fn tests_sbb() { + let (_instance, _id) = get_contract_instance().await; + + let res1 = _instance.sbb(0,0,0) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let res2 = _instance.sbb(0,1,0) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let res3 = _instance.sbb(0,1,1) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + let a = 435983458; + let res4 = _instance.sbb(a,0,1) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res1.0 == 0); + assert!(res1.1 == 0); + + assert!(res2.0 == u64::MAX); + assert!(res2.1 == 1); + + assert!(res3.0 == u64::MAX - 1); + assert!(res3.1 == 1); + + assert!(res4.0 == a-1); + assert!(res4.1 == 0); +} + +#[tokio::test] +async fn test_adc_random() { + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.adc(9837491998535547791, 10009796384580774444, 0) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res.0 == 1400544309406770619); + assert!(res.1 == 1); +} + +#[tokio::test] +async fn test_adc_random_with_carry() { + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.adc(9837491998535547791, 10009796384580774444, 1) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res.0 == 1400544309406770620); + assert!(res.1 == 1); +} + +#[tokio::test] +async fn test_subtract_p_smaller() { + let BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + let a_smaller_than_p = vec384 { + ls: [13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() + }; + let expected_res = vec384 { + ls: [13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() + }; + + let res = _instance.subtract_p(a_smaller_than_p, BLS12_381_P) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_subtract_p_larger() { + let BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + let a_larger_than_p = vec384 { // p+ 200 + ls: [13402431016077863795, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() + }; + let expected_res = vec384 { + ls: [200, 0, 0, 0, 0, 0].to_vec() + }; + + let res = _instance.subtract_p(a_larger_than_p, BLS12_381_P) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_neg_p() { + let BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + let p: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let zero: vec384 = vec384 { + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + + let res = _instance.neg(p, BLS12_381_P) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, zero)); +} + +#[tokio::test] +async fn test_neg_1() { + let BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + let one: vec384 = vec384 { + ls: [1, 0, 0, 0, 0, 0].to_vec() + }; + let expected_res = vec384 { // p-1 + ls: [13402431016077863594, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() + }; + + let res = _instance.neg(one, BLS12_381_P) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_neg_random() { + let BLS12_381_P: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + let r = vec384 { + ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() + }; + let expected_res = vec384 { // p-r + ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179].to_vec() + }; + + let res = _instance.neg(r, BLS12_381_P) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From 8284a2fcd4d27e037ead7300e04bbcb8d0fa57fa Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 27 Jul 2022 18:55:27 -0600 Subject: [PATCH 108/160] Trying out to test with local fuel-core node. --- tests-bls/tests/harness.rs | 4 ++-- tests-bls/tests/tests_add_fp/mod.rs | 27 +++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 9d5f26e..133cb74 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,6 +1,6 @@ -// mod tests_add_fp; +mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; // mod tests_temp_mul_mont_n; -mod tests_small_functions; \ No newline at end of file +// mod tests_small_functions; \ No newline at end of file diff --git a/tests-bls/tests/tests_add_fp/mod.rs b/tests-bls/tests/tests_add_fp/mod.rs index 733c6fe..148a046 100644 --- a/tests-bls/tests/tests_add_fp/mod.rs +++ b/tests-bls/tests/tests_add_fp/mod.rs @@ -4,8 +4,31 @@ use fuels_abigen_macro::abigen; abigen!(BlsContract, "out/debug/tests-bls-abi.json"); async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); + + // This is the address of a running node. + let server_address = "127.0.0.1:4000" + .parse() + .expect("Unable to parse socket address"); + + // Create the provider using the client. + let provider = Provider::connect(server_address).await.unwrap(); + + // Create the wallet. + let wallet = LocalWallet::new_random(Some(provider)); + let num_assets = 1; + let coins_per_asset = 100_000_000; + let amount_per_coin = 1; + + let (coins, asset_ids) = setup_multiple_assets_coins( + wallet.address(), + num_assets, + coins_per_asset, + amount_per_coin, + ); + + + // let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + // let wallet = wallets.pop().unwrap(); let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); let instance = BlsContract::new(id.to_string(), wallet); (instance, id) From e5bf863bd772256620b76f9843292619b8b13df9 Mon Sep 17 00:00:00 2001 From: Manish Date: Thu, 28 Jul 2022 11:02:00 +0530 Subject: [PATCH 109/160] rshift_mod_384 testing --- bls/src/vect.sw | 51 ++++++++++++++++++++- tests-bls/src/main.sw | 5 +- tests-bls/tests/harness.rs | 3 +- tests-bls/tests/tests_rshift_mod_384/mod.rs | 42 +++++++++++++++++ 4 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 tests-bls/tests/tests_rshift_mod_384/mod.rs diff --git a/bls/src/vect.sw b/bls/src/vect.sw index 3ac0e63..62e3d8e 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -839,8 +839,55 @@ pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { } pub fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { - //TODO - ZERO + let mut limbx: U128 = ~U128::from(0, 0); + let mut mask = 0; + let mut carry = 0; + let mut limb = 0; + let mut next = 0; + let mut i = 0; + let mut m = n; + //let mut res_vec: (u64, u64, u64, u64, u64, u64) = (0,0,0,0,0,0); + let mut res_vec: Vec = ~Vec::new::(); + while m > 0 { + + if a.ls[0] & 1 > 0 { + mask = 1<<64 - 1; + } else { + mask = 0; + } + //mask = 0 - (a.ls[0] & 1); + //launder(mask)?? + carry = 0; + i = 0; + while i < 6 { + limbx = ~U128::from(0,a.ls[i]) + (~U128::from(0,(p.ls[i] & mask)) + ~U128::from(0,carry)); + //res_vec.i = limbx; + res_vec.insert(i, limbx.lower); + carry = limbx.upper; + i += 1; + } + //next = res_vec.0; + next = unpack_or_0(res_vec.get(0)); + i = 0; + while i < 5 { + limb = next >> 1; + //next = res_vec.(i+1); + next = unpack_or_0(res_vec.get(i+1)); + //res_vec.i = limb | next << 31; + res_vec.remove(i); + res_vec.insert(i,limb | next << 31); + i += 1; + } + //res_vec.i = next >> 1 | carry << 31; + res_vec.remove(i); + res_vec.insert(i,next >> 1 | carry << 31); + m -= 1; + } + vec384 { + //ls: [res_vec.0, res_vec.1, res_vec.2, res_vec.3, res_vec.4, res_vec.5], + ls: [unpack_or_0(res_vec.get(0)), unpack_or_0(res_vec.get(1)), unpack_or_0(res_vec.get(2)), unpack_or_0(res_vec.get(3)), unpack_or_0(res_vec.get(4)), unpack_or_0(res_vec.get(5))], + } + // ZERO } pub fn div_by_2_mod_384(a: vec384, p: vec384) -> vec384 { diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 1f7c30a..1913bbb 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -21,7 +21,7 @@ abi BlsContract { // Temp mul functions #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384; - + #[storage()]fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384; // // Fp2 // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384; // #[storage()]fn sub_fp2(a: vec384, b: vec384) -> vec384; @@ -85,6 +85,9 @@ impl BlsContract for Contract { temp_mul_mont_n(a, b) } + #[storage()]fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { + rshift_mod_384(a, n, p) + } // #[storage()]fn redc_fp(a: vec384) -> vec384 { // redc_fp(a) // } diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index c310b06..b50be2b 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -2,4 +2,5 @@ mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; -//mod tests_temp_mul_mont_n; \ No newline at end of file +//mod tests_temp_mul_mont_n; +mod tests_rshift_mod_384; \ No newline at end of file diff --git a/tests-bls/tests/tests_rshift_mod_384/mod.rs b/tests-bls/tests/tests_rshift_mod_384/mod.rs new file mode 100644 index 0000000..02eb77b --- /dev/null +++ b/tests-bls/tests/tests_rshift_mod_384/mod.rs @@ -0,0 +1,42 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(100_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +#[tokio::test] +async fn test_1_rshift_mod_384() { + let r_vec: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let p: vec384 = vec384 { + ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() + }; + let expected_res = vec384{ + ls: [0, 0, 0, 0, 0, 0].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.rshift_mod_384(r_vec,1, p) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From 7e7ee9b647fc44002344b0d9b18e4083ea44b163 Mon Sep 17 00:00:00 2001 From: Manish Date: Thu, 28 Jul 2022 14:51:20 +0530 Subject: [PATCH 110/160] harness file modified --- tests-bls/tests/harness.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 6a531ca..faeb66d 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -2,10 +2,6 @@ mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; -<<<<<<< HEAD //mod tests_temp_mul_mont_n; -mod tests_rshift_mod_384; -======= -// mod tests_temp_mul_mont_n; +// mod tests_rshift_mod_384; // mod tests_small_functions; ->>>>>>> 8284a2fcd4d27e037ead7300e04bbcb8d0fa57fa From 51031ce7da315cd7e58aa29a6260112894cfb75e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 28 Jul 2022 14:15:46 -0600 Subject: [PATCH 111/160] - Converted the temp_mul tests - Removed script test files that are already converted so we know what is left --- bls/src/tests/tests_small_functions.sw | 294 ------------------------- bls/src/tests/tests_temp_mul.sw | 118 ---------- bls/src/tests/tests_vect_fp.sw | 212 ------------------ bls/src/vect.sw | 41 ++++ tests-bls/src/main.sw | 9 + tests-bls/tests/harness.rs | 6 +- tests-bls/tests/tests_temp_mul/mod.rs | 101 +++++++++ 7 files changed, 154 insertions(+), 627 deletions(-) delete mode 100644 bls/src/tests/tests_small_functions.sw delete mode 100644 bls/src/tests/tests_temp_mul.sw delete mode 100644 bls/src/tests/tests_vect_fp.sw create mode 100644 tests-bls/tests/tests_temp_mul/mod.rs diff --git a/bls/src/tests/tests_small_functions.sw b/bls/src/tests/tests_small_functions.sw deleted file mode 100644 index 6889e18..0000000 --- a/bls/src/tests/tests_small_functions.sw +++ /dev/null @@ -1,294 +0,0 @@ -library tests_small_functions; - -use ::fields::*; -use ::vect::*; -use ::test_helpers::*; - -use std::{assert::assert, u128::*}; - -pub fn tests_small_functions() -> bool { - assert(test_not()); - assert(tests_subtract_wrap()); - assert(tests_sbb()); - assert(tests_adc()); - assert(test_neg()); - assert(test_subtract_p()); - true -} - -fn test_not() -> bool { - let res = not(18417751708719972248); - assert(res == 28992364989579367); - true -} - -fn tests_subtract_wrap() -> bool { - let mut res = subtract_wrap(U128 { - lower: 100, upper: 0 - }, - U128 { - lower: 80, upper: 0 - }); - assert(res.lower == 20); - assert(res.upper == 0); - - res = subtract_wrap(U128 { - lower: 100, upper: 0 - }, - U128 { - lower: 230, upper: 0 - }); - let res_should_be = ~U128::max() - U128 { - lower: 130, upper: 0 - }; - // 2^128 - 230 = 340282366920938463463374607431768211226 - // [18446744073709551486, 18446744073709551615] - assert(res.lower == 18446744073709551486); - assert(res.upper == 18446744073709551615); - true -} - -fn tests_sbb() -> bool { - // 0-0-0 should give (0,0) - let mut res = sbb(0, 0, 0); - assert(res.0 == 0); - assert(res.1 == 0); - - // 0-1-0 should give (2^64 -1, 1) - res = sbb(0, 1, 0); - assert(res.0 == ~u64::max()); - assert(res.1 == 1); - - // 0-1-1 should give (2^64 -2, 1) - res = sbb(0, 1, 1); - assert(res.0 == ~u64::max() - 1); - assert(res.1 == 1); - - // a-0-1 should give (a-1, 0) - let a = 435983458; - res = sbb(a, 0, 1); - assert(res.0 == a - 1); - assert(res.1 == 0); - true -} - -fn tests_adc() -> bool { - assert(test_adc_random()); - assert(test_adc_random_with_carry()); - true -} - -fn test_adc_random() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res: (u64, u64) = adc(a, b, 0); - let a_plus_b: (u64, u64) = (1400544309406770619, 1); - - assert(res.0 == a_plus_b.0); - assert(res.1 == a_plus_b.1); - true -} - -fn test_adc_random_with_carry() -> bool { - let a = 9837491998535547791; - let b = 10009796384580774444; - let res: (u64, u64) = adc(a, b, 1); - let a_plus_b_and_carry: (u64, u64) = (1400544309406770620, 1); - - assert(res.0 == a_plus_b_and_carry.0); - assert(res.1 == a_plus_b_and_carry.1); - true -} - -fn test_subtract_p() -> bool { - assert(test_subtract_p_smaller()); - assert(test_subtract_p_larger()); - true -} - -fn test_subtract_p_smaller() -> bool { - let a_smaller_than_p = vec384 { - ls: [13402431016077863508, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - let res = subtract_p(a_smaller_than_p, BLS12_381_P); - equals_vec384(res, a_smaller_than_p); - true -} - -fn test_subtract_p_larger() -> bool { - // p+200 - let a_larger_than_p = vec384 { - ls: [13402431016077863795, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - let res = subtract_p(a_larger_than_p, BLS12_381_P); - equals_vec384(res, vec384 { - ls: [200, 0, 0, 0, 0, 0] - }); - true -} - -fn test_neg() -> bool { - assert(test_neg_p()); - assert(test_neg_1()); - assert(test_neg_random()); - true -} - -// neg(p, p) should result in 0 -fn test_neg_p() -> bool { - let p = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] - }; - let res = neg(p, BLS12_381_P); - equals_vec384(res, ZERO); - true -} - -fn test_neg_1() -> bool { - /* p (=BLS12_381_P) - [13402431016077863595, - 2210141511517208575, - 7435674573564081700, - 7239337960414712511, - 5412103778470702295, - 1873798617647539866] - */ - let res = neg(vec384 { - ls: [1, 0, 0, 0, 0, 0] - }, - BLS12_381_P); - let p_minus_1 = vec384 { - ls: [13402431016077863594, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - - equals_vec384(res, p_minus_1); - true -} - -fn test_neg_random() -> bool { - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - - // p-r = - // 2720875437369649573148521964151583897899892592621214021322106212316714352791230421498192551507387765661230553193354 - let res = neg(r, BLS12_381_P); - equals_vec384(res, vec384 { - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] - }); - true -} - -fn test_sub_fp() -> bool { - // assert(test_sub_zero_from_zero()); - // assert(test_sub_zero_from_random()); - // assert(test_sub_random_from_zero()); - // assert(test_sub_random_from_small()); - assert(test_sub_2_randoms()); - assert(test_sub_2_randoms_reverse()); - true -} - -fn test_sub_zero_from_zero() -> bool { - let res = sub_fp(ZERO, ZERO); - equals_vec384(res, ZERO); - true -} - -fn test_sub_zero_from_random() -> bool { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = sub_fp(r, ZERO); - equals_vec384(res, r); - true -} - -fn test_sub_random_from_zero() -> bool { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = sub_fp(ZERO, r); - // p-r (is the same as 0-r mod p) - equals_vec384(res, vec384 { - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179] - }); - true -} - -fn test_sub_random_from_small() -> bool { - // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 - //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let small = vec384 { - ls: [1, - 2, 3, 4, 5, 6] - }; - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - - let res: vec384 = sub_fp(small, r); - //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 - //[343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - equals_vec384(res, vec384 { - ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185] - }); - true -} - -fn test_sub_2_randoms() -> bool { - //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 - //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let a = vec384 { - ls: [10587454305359941416, - 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - }; - //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 - //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let b = vec384 { - ls: [13403040667047958534, - 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - }; - //res = - //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let res: vec384 = sub_fp(a, b); - equals_vec384(res, vec384 { - ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - }); - true -} - -fn test_sub_2_randoms_reverse() -> bool { - // Same a,b from test_sub_2_randoms only subtract the other way around - let a = vec384 { - ls: [10587454305359941416, - 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - }; - let b = vec384 { - ls: [13403040667047958534, - 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - }; - - //res = - //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p - //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 - //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let res: vec384 = sub_fp(b, a); - equals_vec384(res, vec384 { - ls: [16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - }); - true -} diff --git a/bls/src/tests/tests_temp_mul.sw b/bls/src/tests/tests_temp_mul.sw deleted file mode 100644 index e7ba638..0000000 --- a/bls/src/tests/tests_temp_mul.sw +++ /dev/null @@ -1,118 +0,0 @@ -library tests_temp_mul; - -use ::vect::*; -use std::{assert::assert, vec::Vec}; -use ::test_helpers::*; - -pub fn tests_temp_mul() -> bool { - assert(test_mul_temp_by_2()); - true -} - -fn test_temp_mul_random_by_random() -> bool { - let mut p_vec = ~Vec::new::(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new::(); - r1_vec.push(6071868568151433008); - r1_vec.push(12105094901188801210); - r1_vec.push(2389211775905699303); - r1_vec.push(7838417195104481535); - r1_vec.push(5826366508043997497); - r1_vec.push(13436617433956842131); - //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new::(); - r2_vec.push(16964885827015180015); - r2_vec.push(12035734743809705289); - r2_vec.push(10517060043363161601); - r2_vec.push(1119606639881808286); - r2_vec.push(2211903887497377980); - r2_vec.push(395875676649998273); - - //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 - //12684677789208411253122026388948849483224138949631185589801456383786133679073 - let res_vec = vec384 { - ls: [4793585148327242455, - 2837967030551533581, 1626660158106644623, 15384342728939744618, 1826521055323312182, 528164867630647501] - }; - // let mut res_vec = ~Vec::new::(); - // res_vec.push(0x42863c4b7ea22ad7);//4793585148327242455 - // res_vec.push(0x27627bfa644b580d);//2837967030551533581 - // res_vec.push(0x16930ecb9e3a308f);//1626660158106644623 - // res_vec.push(0xd5802a33c5512d6a);//15384342728939744618 - // res_vec.push(0x19591b38f5515036);//1826521055323312182 - // res_vec.push(0x7546b2615f748cd);//528164867630647501 - - let res = mul_temp(r1_vec, r2_vec, p_vec, 6); - print_vec384(res); - /* -16484308011771146774 + -12795119582497094196 * 2^64 + -7495239071060242083 * 2^128 + -6228288009955243706 * 2^192 + -334445847756758381 * 2^256 + -1343304342180463133 * 2^320 - -16484308011771146774 + 12795119582497094196 * 2**64 +7495239071060242083 * 2**128 +6228288009955243706 * 2**192 +334445847756758381 * 2**256 +1343304342180463133 * 2**320 -= -2869280660193735394861207574210601737447645641788161081095242677999752664315845687657572464353026167520041778459158 -Same result as zkcrypto! - -and this is not the same result as blst -*/ - // equals_vec384(res, res_vec); - - true -} - -fn test_mul_temp_by_2() -> bool { - let mut p_vec = ~Vec::new::(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - //2367106380816923637832389518823092703674202766714323478820851269126356623723913304989534316437425836090100832620729 - //[9172416622910853305, 14987574562624449790, 13213778230238218784, - //15872153713916140599, 9712154313263354644, 1108202597211161767] - let mut r1_vec = ~Vec::new::(); - r1_vec.push(9172416622910853305); - r1_vec.push(14987574562624449790); - r1_vec.push(13213778230238218784); - r1_vec.push(15872153713916140599); - r1_vec.push(9712154313263354644); - r1_vec.push(1108202597211161767); - - let mut vec_2 = ~Vec::new::(); - vec_2.push(2); - vec_2.push(0); - vec_2.push(0); - vec_2.push(0); - vec_2.push(0); - vec_2.push(0); - - //731803206412179882246989211910281250791522713489639072309644402128681596956988745536381003745836008142307392681671 - //[4942402229743843015, 9318263540022139389, 545137813202804253, - //6058225393708017072, 14012204848056006994, 342606576774783668] - let res = mul_temp(r1_vec, vec_2, p_vec, 6); - print_vec384(res); - /* - 11360606136736300744 - 10320420748134520786 - 17912563010296520217 - 16145629554006184624 - 12933232110729028586 - 1518885514198738558 - Same result as zkcrypto! - - */ - true -} diff --git a/bls/src/tests/tests_vect_fp.sw b/bls/src/tests/tests_vect_fp.sw deleted file mode 100644 index 300ca1b..0000000 --- a/bls/src/tests/tests_vect_fp.sw +++ /dev/null @@ -1,212 +0,0 @@ -library tests_vect_fp; - -use ::fields::*; -use ::vect::*; -use ::test_helpers::*; - -use std::assert::assert; - -pub fn fp_tests() -> bool { - // Don't run all tests at the same time... - - // assert(test_add_fp()); - // assert(test_sub_fp()); - // assert(tests_mul_by_3_fp()); - // assert(tests_mul_by_8_fp()); - assert(test_lshift_p()); - - true -} - -fn test_add_fp() -> bool { - assert(test_add_zero_to_zero()); - assert(test_add_zero_to_random()); - assert(test_add_random_to_zero()); - assert(test_add_random_to_small()); - assert(test_add_larger_than_p()); - assert(test_add_2_randoms()); - true -} - -fn test_add_zero_to_zero() -> bool { - let res: vec384 = add_fp(ZERO, ZERO); - equals_vec384(res, ZERO); - true -} - -fn test_add_zero_to_random() -> bool { - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - let res: vec384 = add_fp(random, ZERO); - equals_vec384(res, random); - true -} - -fn test_add_random_to_zero() -> bool { - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - /* -4478030004447473542 -2814704111667093002 -15884408734010272158 -17001047363111187578 -932823543034528547 -1051481384684610845 - */ - let res: vec384 = add_fp(ZERO, random); - equals_vec384(res, random); - true -} - -fn test_add_random_to_small() -> bool { - let small = vec384 { - ls: [0x1, - 0x2, 0x3, 0x4, 0x5, 0x6] - }; - let random = vec384 { - ls: [0x3e2528903ca1ef86, - 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d] - }; - let res: vec384 = add_fp(small, random); - equals_vec384(res, vec384 { - ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851] - }); - true -} - -fn test_add_larger_than_p() -> bool { - /* - 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559700 - + - 100 - is a little bit larger than p - */ - //[13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - let a = vec384 { - ls: [13402431016077863508, - 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866] - }; - - let b = vec384 { - ls: [100, - 0, 0, 0, 0, 0] - }; - - // should be 13 - let res: vec384 = add_fp(a, b); - equals_vec384(res, vec384 { - ls: [13, 0, 0, 0, 0, 0] - }); - true -} - -fn test_add_2_randoms() -> bool { - //[4510245898505151773, 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] - let random_1 = vec384 { - ls: [4510245898505151773, - 8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943] - }; - - //[8877477209635348035, 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] - let random_2 = vec384 { - ls: [8877477209635348035, - 16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961] - }; - /* -a=37363336077986948456666213736586466128287562369519105825429602984091321919274233302919361890839579644111801541917 -b=1798295057736039902482424641059918570220554796267905001254827923367760771974871956830417883729301310309317980773955 -a+b=1835658393814026850939090854796505036348842358637424107080257526351852093894146190133337245620140889953429782315872 -[13387723108140499808, -7110911959168982110, -7018803425472956901, -2577695370959560254, -1826757397030539319, -859395849761138905] - -a+b< p is true -*/ - let res: vec384 = add_fp(random_1, random_2); - equals_vec384(res, vec384 { - ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905] - }); - true -} - -fn tests_mul_by_3_fp() -> bool { - //3*0=0 - let three_times_0 = mul_by_3_fp(ZERO); - equals_vec384(three_times_0, ZERO); - - // 3311078190518289289936277681023239947232202294966126226561271980448667165835391482457451698237502148041582301891462 - let a = vec384 { - ls: [5598198260030196614, - 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475] - }; - // a*3 mod p should be - //1928415461111533082973253391597911528582841245020362909019699669097938196524498718486979836454475116048958360554812 - let res = mul_by_3_fp(a); - equals_vec384(res, vec384 { - ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694] - }); - true -} - -fn tests_mul_by_8_fp() -> bool { - //8*0=0 - let eight_times_0 = mul_by_8_fp(ZERO); - equals_vec384(eight_times_0, ZERO); - - // 2157040060242996582487091204805473379530946954236593619635912200349069530691884182763342898014216243417047961230344 - let a = vec384 { - ls: [4748578380656466952, - 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211] - }; - // a*8 mod p should be - //1246682261057303086225570335500170410020044354136717415759065058296429643571722004335992667597667291184806599603604 - let res = mul_by_8_fp(a); - equals_vec384(res, vec384 { - ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227] - }); - true -} - -fn test_lshift_p() -> bool { - assert(test_1_lshift_p()); - assert(test_250_lshift_p()); - true -} - -fn test_1_lshift_p() -> bool { - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - //[13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687] - }; - let res = lshift_fp(r, 1); - // 1 leftshift is *2 - //2563068235704035640538535723168640517313980454635587728019903847614634595399214885888990155243255796753327438732866 - equals_vec384(res, vec384 { - ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374] - }); - true -} - -fn test_250_lshift_p() -> bool { - //3801089353888592548165443178944616809833017335235566378191862939584686528734180895181864917846967916907395374952420 - let a = vec384 { - ls: [13749239540608708580, - 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937] - }; - // leftshift 250 mod p - //879994519659111629345302542423123869141449003108211674743509876497540102414622865945836408424086377077979782833710 - let res = lshift_fp(a, 250); - equals_vec384(res, vec384 { - ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179] - }); - true -} diff --git a/bls/src/vect.sw b/bls/src/vect.sw index 62e3d8e..3c89fdc 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -294,6 +294,7 @@ pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { res_vec } +// Same functionality as mul_temp // Effectively a_mont = (a_norm * R) mod N pub fn fe_to_mont(a: Vec) -> Vec { let mut BLS12_381_RR: Vec = ~Vec::new::(); @@ -473,6 +474,46 @@ pub fn montgomery_reduction(t: [u64; BLS12_381_P) } +pub fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { + let mut a_temp: Vec = ~Vec::new::(); + a_temp.push(a.ls[0]); + a_temp.push(a.ls[1]); + a_temp.push(a.ls[2]); + a_temp.push(a.ls[3]); + a_temp.push(a.ls[4]); + a_temp.push(a.ls[5]); + + let mut b_temp: Vec = ~Vec::new::(); + b_temp.push(b.ls[0]); + b_temp.push(b.ls[1]); + b_temp.push(b.ls[2]); + b_temp.push(b.ls[3]); + b_temp.push(b.ls[4]); + b_temp.push(b.ls[5]); + + let mut p_temp: Vec = ~Vec::new::(); + p_temp.push(p.ls[0]); + p_temp.push(p.ls[1]); + p_temp.push(p.ls[2]); + p_temp.push(p.ls[3]); + p_temp.push(p.ls[4]); + p_temp.push(p.ls[5]); + + // mul_temp and temp_fe_mont_mul give the same result + + // mul_temp(a_temp, b_temp, p_temp, n) + let temp_vec = temp_fe_mont_mul(a_temp, b_temp); + vec384 { + ls: [unpack_or_0(temp_vec.get(0)), + unpack_or_0(temp_vec.get(1)), + unpack_or_0(temp_vec.get(2)), + unpack_or_0(temp_vec.get(3)), + unpack_or_0(temp_vec.get(4)), + unpack_or_0(temp_vec.get(5)) + ] + } +} +// Same functionality as fe_to_mont // TEMP NAIVE MULT IMPL // Naive multiplication implementation following zkcrypto. // Can be used as stand-in until we figure our how to make mul_mont_n work or the NCC mult with conversions before and after is feasible diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 9175b2c..3a9b894 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -30,6 +30,9 @@ abi BlsContract { // Temp mul functions #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384; #[storage()]fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384; + #[storage()]fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384; + + // // Fp2 // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384; // #[storage()]fn sub_fp2(a: vec384, b: vec384) -> vec384; @@ -115,6 +118,7 @@ impl BlsContract for Contract { from_fp(a) } + // Temp mul functions #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384 { temp_mul_mont_n(a, b) } @@ -122,6 +126,11 @@ impl BlsContract for Contract { #[storage()]fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { rshift_mod_384(a, n, p) } + + #[storage()]fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { + mul_temp_wrapper(a, b, p, n) + } + // #[storage()]fn redc_fp(a: vec384) -> vec384 { // redc_fp(a) // } diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index faeb66d..46b9b9f 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,7 +1,7 @@ -mod tests_add_fp; +// mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; -//mod tests_temp_mul_mont_n; +// mod tests_temp_mul_mont_n; // mod tests_rshift_mod_384; -// mod tests_small_functions; +mod tests_temp_mul; diff --git a/tests-bls/tests/tests_temp_mul/mod.rs b/tests-bls/tests/tests_temp_mul/mod.rs new file mode 100644 index 0000000..9ef87ff --- /dev/null +++ b/tests-bls/tests/tests_temp_mul/mod.rs @@ -0,0 +1,101 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +#[tokio::test] +async fn test_temp_mul_random_by_random() { + let p_vec: vec384 = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a].to_vec() + }; + let r1_vec: vec384 = vec384 { + ls: [6071868568151433008, + 12105094901188801210, + 2389211775905699303, + 7838417195104481535, + 5826366508043997497, + 13436617433956842131].to_vec() + }; + let r2_vec: vec384 = vec384 { + ls: [16964885827015180015, + 12035734743809705289, + 10517060043363161601, + 1119606639881808286, + 2211903887497377980, + 395875676649998273].to_vec() + }; + // this is the expected result according to the zkcrypto impl. This is multiplication on montgomery forms + let expected_res: vec384 = vec384 { + ls: [16484308011771146774, 12795119582497094196, 7495239071060242083, + 6228288009955243706, 334445847756758381, 1343304342180463133].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.mul_temp_wrapper(r1_vec, r2_vec, p_vec, 6) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); + + //zkcrypto impl gives this res as well. So it's not a "standard" mul + //[16484308011771146774, 12795119582497094196, 7495239071060242083, + // 6228288009955243706, 334445847756758381, 1343304342180463133] +} + +#[tokio::test] +async fn test_mul_temp_by_2() { + let p_vec: vec384 = vec384 { + ls: [0xb9feffffffffaaab, + 0x1eabfffeb153ffff, + 0x6730d2a0f6b0f624, + 0x64774b84f38512bf, + 0x4b1ba7b6434bacd7, + 0x1a0111ea397fe69a].to_vec() + }; + + //2367106380816923637832389518823092703674202766714323478820851269126356623723913304989534316437425836090100832620729 + let r1_vec: vec384 = vec384 { + ls: [9172416622910853305, 14987574562624449790, + 13213778230238218784, 15872153713916140599, + 9712154313263354644, 1108202597211161767].to_vec() + }; + let vec_2: vec384 = vec384 { + ls: [2,0,0,0,0,0].to_vec() + }; + + // this is the expected result according to the zkcrypto impl. This is multiplication on montgomery forms + let expected_res: vec384 = vec384 { + ls: [11360606136736300744, 10320420748134520786, 17912563010296520217, + 16145629554006184624, 12933232110729028586, 1518885514198738558].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.mul_temp_wrapper(r1_vec, vec_2, p_vec, 6) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From a43b44197d9d1d742a884c63bf7100101ae095ae Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 28 Jul 2022 15:26:13 -0600 Subject: [PATCH 112/160] - Converted vect_fp2 tests to contract testing - Added file for test_vect_subfunctions but vectors aren't supported yet in contracts so we can't test these functions for now - Added comments about what's left to convert in testing and why it's not possible yet --- bls/src/tests/tests_temp_fe_mont_mul.sw | 3 + bls/src/tests/tests_vect_fp2.sw | 142 ------------------ bls/src/tests/tests_vect_subfunctions.sw | 2 + tests-bls/src/main.sw | 25 +-- tests-bls/tests/harness.rs | 6 +- tests-bls/tests/tests_temp_mul_mont_n/mod.rs | 1 + tests-bls/tests/tests_vect_fp2/mod.rs | 104 +++++++++++++ .../tests/tests_vect_subfunctions/mod.rs | 70 +++++++++ 8 files changed, 200 insertions(+), 153 deletions(-) delete mode 100644 bls/src/tests/tests_vect_fp2.sw create mode 100644 tests-bls/tests/tests_vect_fp2/mod.rs create mode 100644 tests-bls/tests/tests_vect_subfunctions/mod.rs diff --git a/bls/src/tests/tests_temp_fe_mont_mul.sw b/bls/src/tests/tests_temp_fe_mont_mul.sw index c09904b..ace909c 100644 --- a/bls/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls/src/tests/tests_temp_fe_mont_mul.sw @@ -5,6 +5,9 @@ use std::{assert::assert, vec::Vec}; use ::test_helpers::*; use std::logging::log; +// COMMENT: this runs out of gas in contract testing as well +// Keeping this for now, because it hasn't been converted yet + pub fn tests_temp_fe_mont_mul() -> bool { // assert(test_temp_mul_random_by_random()); assert(test_temp_mul_mont_n()); diff --git a/bls/src/tests/tests_vect_fp2.sw b/bls/src/tests/tests_vect_fp2.sw deleted file mode 100644 index 6cc8bfd..0000000 --- a/bls/src/tests/tests_vect_fp2.sw +++ /dev/null @@ -1,142 +0,0 @@ -library tests_vect_fp2; - -use ::fields::*; -use ::vect::*; -use ::test_helpers::*; -use std::logging::log; -use std::assert::assert; - -pub fn fp2_tests() -> bool { - // assert(tests_add_fp2()); - // assert(tests_sub_fp2()); - assert(tests_mul_fp2()); - true -} - -fn get_a1() -> vec384x { - let r_1 = vec384 { - ls: [14795151457364307190, - 6622185142386025417, 17709159039044576520, 1719961663313476946, 4148264363906786574, 980769587779429096] - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, - 10328470218072223240, 3451314819045096133, 17542580433704256157, 9684937745078445131, 867989271079206780] - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; - a_1 -} - -fn tests_add_fp2() -> bool { - // the function should add the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let a_1 = get_a1(); - - //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { - ls: [16448140995118783999, - 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] - }; - //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { - ls: [1139524850979729662, - 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] - }; - let a_2 = vec384x { - r: r_2, - i: i_2, - }; - - let res = add_fp2(a_1, a_2); - - // real part - //2137877704498232127807411464212375191436759017985494258559699678267614550583327465580539722964369097290996936745034 - // i part - //2102225208623713295441506445599106284617920054928136723527572025496914411577416973498409298745656779262154860486599 - equals_vec384(res.r, vec384 { - ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815] - }); - equals_vec384(res.i, vec384 { - ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219] - }); - true -} - -fn tests_sub_fp2() -> bool { - // the function should subtract the "real" and "imaginary" part separately - //2094911124722355591130592080039857597898930618341226282859888392249028304430218244612311046228146839310359642074358 - let a_1 = get_a1(); - - //4045376134997543930094609209908421750094711219583275861031869422142617896643947085410916305865237922018531567230463 - let r_2 = vec384 { - ls: [16448140995118783999, - 9520526689676604696, 7916863578364318753, 8691145487628551970, 16531338352426028355, 1893914179705411585] - }; - //4250620933501754476426212648635705132171856148319059449262917285281574574065816436709319684883958930577072278499582 - let i_2 = vec384 { - ls: [1139524850979729662, - 10226030227531743340, 16078343496594203218, 16066350528929326807, 17232578759082026236, 1990003151713484304] - }; - let a_2 = vec384x { - r: r_2, - i: i_2, - }; - - let res = sub_fp2(a_1, a_2); - //real - //2051944544946479054453772695867340004361102218696958307160077106230442058277109023644082369491924581329722347403682 - //i - //1605802452063539129424660799799504333387973398168033595665853727181828564427459828965145187235770246183798848607009 - equals_vec384(res.r, vec384 { - ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376] - }); - equals_vec384(res.i, vec384 { - ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341] - }); - true -} - -fn tests_mul_fp2() -> bool { - // assert(mul_fp2_by_zero()); - assert(mul_fp2_by_one()); - // assert(mul_fp2_by_small()); - true -} - -fn mul_fp2_by_zero() -> bool { - let a_1 = get_a1(); - let res = mul_fp2(a_1, ZERO_X); - equals_vec384(res.r, ZERO); - equals_vec384(res.i, ZERO); - true -} - -fn mul_fp2_by_one() -> bool { - let a_1 = get_a1(); - let one_384 = vec384 { - ls: [1, 0, 0, 0, 0, 0] - }; - let one = vec384x { - r: one_384, - i: one_384, - }; - - let res = mul_fp2(a_1, one); - print_vec384(res.r); - // equals_vec384(res.r, a_1.r); - // equals_vec384(res.i, a_1.i); - true -} - -// fn mul_fp2_by_small() -> bool { -// let small = vec384 { -// ls: [0x1, -// 0x2, 0x3, 0x4, 0x5, 0x6] -// }; -// let smallx = vec384x {r: small, i: small }; - -// true -// } \ No newline at end of file diff --git a/bls/src/tests/tests_vect_subfunctions.sw b/bls/src/tests/tests_vect_subfunctions.sw index c238531..21b9ce7 100644 --- a/bls/src/tests/tests_vect_subfunctions.sw +++ b/bls/src/tests/tests_vect_subfunctions.sw @@ -7,6 +7,8 @@ use std::logging::log; use std::{assert::assert, vec::Vec}; use ::consts::*; +// COMMENT: these tests can't be converted to contract testing yet because they don't support Vec yet + pub fn vect_subfunctions_tests() -> bool { // NOTE: Don't run all at the same time, because will run out of gas diff --git a/tests-bls/src/main.sw b/tests-bls/src/main.sw index 3a9b894..bb11425 100644 --- a/tests-bls/src/main.sw +++ b/tests-bls/src/main.sw @@ -1,7 +1,6 @@ contract; use bls::{fields::*, vect::*}; -// unsure why this isn't working, bit it's needed for temp_fe_mont_mul use std::u128::*; abi BlsContract { @@ -12,6 +11,9 @@ abi BlsContract { #[storage()]fn adc(a: u64, b: u64, carry: u64) -> (u64, u64); #[storage()]fn subtract_p(a: vec384, p: vec384) -> vec384; #[storage()]fn neg(a: vec384, p: vec384) -> vec384; + + // Vec can't be used yet here WIP in Sway https://github.com/FuelLabs/fuels-rs/issues/353 + // #[storage()]fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec; //Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; @@ -34,8 +36,8 @@ abi BlsContract { // // Fp2 - // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384; - // #[storage()]fn sub_fp2(a: vec384, b: vec384) -> vec384; + #[storage()]fn add_fp2(a: vec384x, b: vec384x) -> vec384x; + #[storage()]fn sub_fp2(a: vec384x, b: vec384x) -> vec384x; // #[storage()]fn mul_by_3_fp2(a: vec384) -> vec384; // #[storage()]fn mul_by_8_fp2(a: vec384) -> vec384; // #[storage()]fn lshift_fp2(a: vec384, count: u64) -> vec384; @@ -73,6 +75,11 @@ impl BlsContract for Contract { neg(a, p) } +// Vec can't be used yet here WIP in Sway https://github.com/FuelLabs/fuels-rs/issues/353 + // #[storage()]fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { + // add_mod_n(a, b, p, n) + // } + // Fp #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { add_fp(a, b) @@ -136,13 +143,13 @@ impl BlsContract for Contract { // } // // Fp2 - // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384 { - // add_fp2(a, b) - // } + #[storage()]fn add_fp2(a: vec384x, b: vec384x) -> vec384x { + add_fp2(a, b) + } - // #[storage()]fn add_fp2(a: vec384, b: vec384) -> vec384 { - // add_fp2(a, b) - // } + #[storage()]fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { + sub_fp2(a, b) + } // #[storage()]fn mul_by_3_fp2(a: vec384) -> vec384 { // mul_by_3_fp2(a) diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 46b9b9f..779c5fb 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -2,6 +2,8 @@ // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; -// mod tests_temp_mul_mont_n; // mod tests_rshift_mod_384; -mod tests_temp_mul; +// mod tests_temp_mul; +// mod tests_vect_subfunctions; +mod tests_vect_fp2; +// mod tests_temp_mul_mont_n; gives error OutOfGas diff --git a/tests-bls/tests/tests_temp_mul_mont_n/mod.rs b/tests-bls/tests/tests_temp_mul_mont_n/mod.rs index 987e357..196a43f 100644 --- a/tests-bls/tests/tests_temp_mul_mont_n/mod.rs +++ b/tests-bls/tests/tests_temp_mul_mont_n/mod.rs @@ -21,6 +21,7 @@ pub fn res_equals(res: vec384, should_be: vec384) -> bool { true } +// Gives error OutOfGas. We need to run locally in order to increase the gas limit #[tokio::test] async fn test_temp_mul_random_by_random() { //let p_vec: [u64;6] = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a]; diff --git a/tests-bls/tests/tests_vect_fp2/mod.rs b/tests-bls/tests/tests_vect_fp2/mod.rs new file mode 100644 index 0000000..3714e00 --- /dev/null +++ b/tests-bls/tests/tests_vect_fp2/mod.rs @@ -0,0 +1,104 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(100_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +fn get_a1() -> vec384x { + let r_1 = vec384 { + ls: [14795151457364307190, 6622185142386025417, + 17709159039044576520, 1719961663313476946, + 4148264363906786574, 980769587779429096].to_vec() + }; + //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 + let i_1 = vec384 { + ls: [8306319196692453748, 10328470218072223240, + 3451314819045096133, 17542580433704256157, + 9684937745078445131, 867989271079206780].to_vec() + }; + let a_1 = vec384x { + r: r_1, + i: i_1, + }; + a_1 +} + + +fn get_a2() -> vec384x { + let r2_vec = vec384{ + ls: [16448140995118783999, 9520526689676604696, + 7916863578364318753, 8691145487628551970, + 16531338352426028355, 1893914179705411585].to_vec() + }; + + let i2_vec = vec384{ + ls: [1139524850979729662, 10226030227531743340, + 16078343496594203218, 16066350528929326807, + 17232578759082026236, 1990003151713484304].to_vec() + }; + + let a_2 = vec384x { + r: r2_vec, + i: i2_vec, + }; + a_2 +} + +#[tokio::test] +async fn tests_add_fp2() { + let a_1 = get_a1(); + let a_2 = get_a2(); + + let expected_r = vec384 { + ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815].to_vec() + }; + let expected_i = vec384 { + ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.add_fp2(a_1, a_2) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res.r, expected_r)); + assert!(res_equals(res.i, expected_i)); +} + +#[tokio::test] +async fn tests_sub_fp2() { + let a_1 = get_a1(); + let a_2 = get_a2(); + + let expected_r = vec384 { + ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376].to_vec() + }; + let expected_i = vec384 { + ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.sub_fp2(a_1, a_2) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res.r, expected_r)); + assert!(res_equals(res.i, expected_i)); +} \ No newline at end of file diff --git a/tests-bls/tests/tests_vect_subfunctions/mod.rs b/tests-bls/tests/tests_vect_subfunctions/mod.rs new file mode 100644 index 0000000..2acb2f9 --- /dev/null +++ b/tests-bls/tests/tests_vect_subfunctions/mod.rs @@ -0,0 +1,70 @@ +use fuels::{prelude::*, tx::ContractId}; +use fuels_abigen_macro::abigen; + +abigen!(BlsContract, "out/debug/tests-bls-abi.json"); + +async fn get_contract_instance() -> (BlsContract, ContractId) { + let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; + let wallet = wallets.pop().unwrap(); + let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); + let instance = BlsContract::new(id.to_string(), wallet); + (instance, id) +} + +pub fn res_equals(res: vec384, should_be: vec384) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + +fn get_test_vectors() -> (Vec, Vec) { + let mut zero_vec = Vec::new(); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + zero_vec.push(0); + + let mut p_vec = Vec::new(); + p_vec.push(0xb9feffffffffaaab); + p_vec.push(0x1eabfffeb153ffff); + p_vec.push(0x6730d2a0f6b0f624); + p_vec.push(0x64774b84f38512bf); + p_vec.push(0x4b1ba7b6434bacd7); + p_vec.push(0x1a0111ea397fe69a); + + (zero_vec, p_vec) +} + +// TODO This can't run yet, because in the contract we can't use Vec +// #[tokio::test] +// async fn test_add_zero_to_zero_addn() { +// let (_instance, _id) = get_contract_instance().await; +// let mut zero_vec = Vec::new(); +// zero_vec.push(0); +// zero_vec.push(0); +// zero_vec.push(0); +// zero_vec.push(0); +// zero_vec.push(0); +// zero_vec.push(0); +// let(zero_vec1, p_vec) = get_test_vectors(); + +// let mut expected_res = Vec::new(); +// expected_res.push(0); +// expected_res.push(0); +// expected_res.push(0); +// expected_res.push(0); +// expected_res.push(0); +// expected_res.push(0); + +// let res = _instance.add_mod_n(zero_vec, zero_vec1, p_vec, 6) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// assert!(res_equals(res, expected_res)); +// } \ No newline at end of file From 03f54166f7361e628865ebe2965170822f1597c3 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 28 Jul 2022 20:15:46 -0600 Subject: [PATCH 113/160] Making a start with new folders --- bls12_381/.gitignore | 2 + bls12_381/Cargo.toml | 15 +++ bls12_381/Forc.toml | 7 ++ bls12_381/src/fp.sw | 131 ++++++++++++++++++++++++++ bls12_381/src/lib.sw | 3 + bls12_381/tests/harness.rs | 31 ++++++ tests_bls12_381/.gitignore | 2 + tests_bls12_381/Cargo.toml | 15 +++ tests_bls12_381/Forc.toml | 8 ++ tests_bls12_381/src/main.sw | 25 +++++ tests_bls12_381/tests/harness.rs | 1 + tests_bls12_381/tests/tests_fp/mod.rs | 45 +++++++++ 12 files changed, 285 insertions(+) create mode 100644 bls12_381/.gitignore create mode 100644 bls12_381/Cargo.toml create mode 100644 bls12_381/Forc.toml create mode 100644 bls12_381/src/fp.sw create mode 100644 bls12_381/src/lib.sw create mode 100644 bls12_381/tests/harness.rs create mode 100644 tests_bls12_381/.gitignore create mode 100644 tests_bls12_381/Cargo.toml create mode 100644 tests_bls12_381/Forc.toml create mode 100644 tests_bls12_381/src/main.sw create mode 100644 tests_bls12_381/tests/harness.rs create mode 100644 tests_bls12_381/tests/tests_fp/mod.rs diff --git a/bls12_381/.gitignore b/bls12_381/.gitignore new file mode 100644 index 0000000..77d3844 --- /dev/null +++ b/bls12_381/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/bls12_381/Cargo.toml b/bls12_381/Cargo.toml new file mode 100644 index 0000000..5f74e37 --- /dev/null +++ b/bls12_381/Cargo.toml @@ -0,0 +1,15 @@ +[project] +name = "bls12_381" +version = "0.1.0" +authors = ["Hashcloak"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = { version = "0.17", features = ["fuel-core-lib"] } +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/bls12_381/Forc.toml b/bls12_381/Forc.toml new file mode 100644 index 0000000..ae041b9 --- /dev/null +++ b/bls12_381/Forc.toml @@ -0,0 +1,7 @@ +[project] +authors = ["Hashcloak"] +entry = "lib.sw" +license = "Apache-2.0" +name = "bls12_381" + +[dependencies] diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw new file mode 100644 index 0000000..b83683e --- /dev/null +++ b/bls12_381/src/fp.sw @@ -0,0 +1,131 @@ +library fp; + +use std::{u128::*}; + +// Little endian big integer with 6 limbs +// in Montgomery form (!) +pub struct Fp{ls: [u64;6]} + +/// p = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 +pub const MODULUS: [u64; 6] = [ + 0xb9fe_ffff_ffff_aaab, + 0x1eab_fffe_b153_ffff, + 0x6730_d2a0_f6b0_f624, + 0x6477_4b84_f385_12bf, + 0x4b1b_a7b6_434b_acd7, + 0x1a01_11ea_397f_e69a, +]; + +/// INV = -(P^{-1} mod 2^64) mod 2^64 +pub const INV: u64 = 0x89f3_fffc_fffc_fffd; + +/// R = 2^384 mod p +const R: Fp = Fp{ls: [ + 0x7609_0000_0002_fffd, + 0xebf4_000b_c40c_0002, + 0x5f48_9857_53c7_58ba, + 0x77ce_5853_7052_5745, + 0x5c07_1a97_a256_ec6d, + 0x15f6_5ec3_fa80_e493, +]}; + +/// R2 = 2^(384*2) mod p +const R2: Fp = Fp{ls: [ + 0xf4df_1f34_1c34_1746, + 0x0a76_e6a6_09d1_04f1, + 0x8de5_476c_4c95_b6d5, + 0x67eb_88a9_939d_83c0, + 0x9a79_3e85_b519_952d, + 0x1198_8fe5_92ca_e3aa, +]}; + +/// R3 = 2^(384*3) mod p +const R3: Fp = Fp{ls: [ + 0xed48_ac6b_d94c_a1e0, + 0x315f_831e_03a7_adf8, + 0x9a53_352a_615e_29dd, + 0x34c0_4e5e_921e_1761, + 0x2512_d435_6572_4728, + 0x0aa6_3460_9175_5d4d, +]}; + +fn not(input: u64) -> u64 { + ~u64::max() - input +} + +// TODO rewrite without if branch +// If x >= y: x-y, else max::U128 - (y-x) +pub fn subtract_wrap(x: U128, y: U128) -> U128 { + if y > x { + ~U128::max() - (y - x - U128 { + lower: 1, upper: 0 + }) + } else { + x - y + } +} + +/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). +pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let borrow_128: U128 = ~U128::from(0, borrow); + + let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); + (res.lower, res.upper >> 63) //(result, borrow) +} + +// If a >= p, return a-p, else return a +pub fn subtract_p(a: Fp) -> Fp { + let(r0, borrow) = sbb(a.ls[0], MODULUS[0], 0); + let(r1, borrow) = sbb(a.ls[1], MODULUS[1], borrow); + let(r2, borrow) = sbb(a.ls[2], MODULUS[2], borrow); + let(r3, borrow) = sbb(a.ls[3], MODULUS[3], borrow); + let(r4, borrow) = sbb(a.ls[4], MODULUS[4], borrow); + let(r5, borrow) = sbb(a.ls[5], MODULUS[5], borrow); + + // If underflow occurred on the final limb, borrow = 1, otherwise + // borrow = 0. We convert it into a mask. + let mut mask = borrow * ~u64::max(); + let r0 = (a.ls[0] & mask) | (r0 & not(mask)); + let r1 = (a.ls[1] & mask) | (r1 & not(mask)); + let r2 = (a.ls[2] & mask) | (r2 & not(mask)); + let r3 = (a.ls[3] & mask) | (r3 & not(mask)); + let r4 = (a.ls[4] & mask) | (r4 & not(mask)); + let r5 = (a.ls[5] & mask) | (r5 & not(mask)); + + Fp { + ls: [r0, r1, r2, r3, r4, r5] + } +} + +//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? +//returns sum with carry of a and b +pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let carry_128: U128 = ~U128::from(0, carry); + + let sum: u64 = (a_128 + b_128 + carry_128).lower; + let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; + + (sum, carry_res) +} + +impl Fp { + + #[inline] + pub fn add(self, rhs: Fp) -> Fp { + let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); + let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); + let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); + let (d3, carry) = adc(self.ls[3], rhs.ls[3], carry); + let (d4, carry) = adc(self.ls[4], rhs.ls[4], carry); + let (d5, _) = adc(self.ls[5], rhs.ls[5], carry); + + // Attempt to subtract the modulus, to ensure the value + // is smaller than the modulus. + subtract_p(Fp{ls:[d0, d1, d2, d3, d4, d5]}) + } + +} \ No newline at end of file diff --git a/bls12_381/src/lib.sw b/bls12_381/src/lib.sw new file mode 100644 index 0000000..3d3a47e --- /dev/null +++ b/bls12_381/src/lib.sw @@ -0,0 +1,3 @@ +library bls12_381; + +dep fp; \ No newline at end of file diff --git a/bls12_381/tests/harness.rs b/bls12_381/tests/harness.rs new file mode 100644 index 0000000..120637e --- /dev/null +++ b/bls12_381/tests/harness.rs @@ -0,0 +1,31 @@ +use fuels::{prelude::*, tx::ContractId}; + +// Load abi from json +abigen!(MyContract, "out/debug/bls12-381-abi.json"); + +async fn get_contract_instance() -> (MyContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "./out/debug/bls12-381.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(Some( + "./out/debug/bls12-381-storage_slots.json".to_string(), + )), + ) + .await + .unwrap(); + + let instance = MyContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (_instance, _id) = get_contract_instance().await; + + // Now you have an instance of your contract you can use to test each function +} diff --git a/tests_bls12_381/.gitignore b/tests_bls12_381/.gitignore new file mode 100644 index 0000000..77d3844 --- /dev/null +++ b/tests_bls12_381/.gitignore @@ -0,0 +1,2 @@ +out +target diff --git a/tests_bls12_381/Cargo.toml b/tests_bls12_381/Cargo.toml new file mode 100644 index 0000000..d8aa39e --- /dev/null +++ b/tests_bls12_381/Cargo.toml @@ -0,0 +1,15 @@ +[project] +name = "tests_bls12_381" +version = "0.1.0" +authors = ["Elena Fuentes Bongenaar"] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +fuels = { version = "0.17", features = ["fuel-core-lib"] } +tokio = { version = "1.12", features = ["rt", "macros"] } + +[[test]] +harness = true +name = "integration_tests" +path = "tests/harness.rs" diff --git a/tests_bls12_381/Forc.toml b/tests_bls12_381/Forc.toml new file mode 100644 index 0000000..2271d6f --- /dev/null +++ b/tests_bls12_381/Forc.toml @@ -0,0 +1,8 @@ +[project] +authors = ["Elena Fuentes Bongenaar"] +entry = "main.sw" +license = "Apache-2.0" +name = "tests_bls12_381" + +[dependencies] +bls12_381 = { path = "../bls12_381" } diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw new file mode 100644 index 0000000..e1f5d55 --- /dev/null +++ b/tests_bls12_381/src/main.sw @@ -0,0 +1,25 @@ +contract; + +use bls12_381::{fp::*}; + +abi BlsTestContract { + #[storage(write)]fn initialize_counter(value: u64) -> u64; + #[storage(read, write)]fn increment_counter(amount: u64) -> u64; +} + +storage { + counter: u64 = 0, +} + +impl BlsTestContract for Contract { + #[storage(write)]fn initialize_counter(value: u64) -> u64 { + storage.counter = value; + value + } + + #[storage(read, write)]fn increment_counter(amount: u64) -> u64 { + let incremented = storage.counter + amount; + storage.counter = incremented; + incremented + } +} diff --git a/tests_bls12_381/tests/harness.rs b/tests_bls12_381/tests/harness.rs new file mode 100644 index 0000000..689c777 --- /dev/null +++ b/tests_bls12_381/tests/harness.rs @@ -0,0 +1 @@ +mod tests_fp; \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs new file mode 100644 index 0000000..a736adb --- /dev/null +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -0,0 +1,45 @@ +use fuels::{prelude::*, tx::ContractId}; + +// Load abi from json +abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); + +async fn get_contract_instance() -> (BlsTestContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "./out/debug/tests_bls12_381.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(None) + ) + .await + .unwrap(); + + let instance = BlsTestContract::new(id.to_string(), wallet); + + (instance, id) +} + +#[tokio::test] +async fn can_get_contract_id() { + let (contract_instance, _id) = get_contract_instance().await; + // Now you have an instance of your contract you can use to test each function + + let result = contract_instance + .initialize_counter(42) + .call() + .await + .unwrap(); + + assert_eq!(42, result.value); + + // Call `increment_counter()` method in our deployed contract. + let result = contract_instance + .increment_counter(10) + .call() + .await + .unwrap(); + + assert_eq!(52, result.value); +} From 43658ab44cd70b704df20a4f34f252a280ceae39 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 29 Jul 2022 11:02:29 -0600 Subject: [PATCH 114/160] Added add and sub for Fp --- bls12_381/src/fp.sw | 43 ++++++++++++++++-- tests_bls12_381/src/main.sw | 19 +++----- tests_bls12_381/tests/tests_fp/mod.rs | 63 ++++++++++++++++++++------- 3 files changed, 93 insertions(+), 32 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index b83683e..ba9dae0 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -65,6 +65,16 @@ pub fn subtract_wrap(x: U128, y: U128) -> U128 { } } +// TODO rewrite without if branch +// If x >= y: x-y, else max::U64 - (y-x) +pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { + if y > x { + ~u64::max() - (y - x - 1) + } else { + x - y + } +} + /// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { let a_128: U128 = ~U128::from(0, a); @@ -113,9 +123,31 @@ pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { } impl Fp { + pub fn neg(self) -> Fp { + let(d0, borrow) = sbb(MODULUS[0], self.ls[0], 0); + let(d1, borrow) = sbb(MODULUS[1], self.ls[1], borrow); + let(d2, borrow) = sbb(MODULUS[2], self.ls[2], borrow); + let(d3, borrow) = sbb(MODULUS[3], self.ls[3], borrow); + let(d4, borrow) = sbb(MODULUS[4], self.ls[4], borrow); + let(d5, _) = sbb(MODULUS[5], self.ls[5], borrow); + + // We need a mask that's 0 when a==p and 2^65-1 otherwise + // TODO improve this + let mut a_is_p = 0; + if (self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3] | self.ls[4] | self.ls[5]) == 0 { + a_is_p = 1; //don't know is there's a native conversion + } else { + a_is_p = 0; + } + + let mask = subtract_wrap_64(a_is_p, 1); + + Fp { + ls: [d0 & mask, d1 & mask, d2 & mask, d3 & mask, d4 & mask, d5 & mask] + } + } - #[inline] - pub fn add(self, rhs: Fp) -> Fp { + fn add(self, rhs: Fp) -> Fp { let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); @@ -127,5 +159,10 @@ impl Fp { // is smaller than the modulus. subtract_p(Fp{ls:[d0, d1, d2, d3, d4, d5]}) } +} -} \ No newline at end of file +impl Fp { + fn sub(self, rhs: Fp) -> Fp { + (rhs.neg()).add(self) + } +} diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index e1f5d55..6fb22d4 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -3,23 +3,16 @@ contract; use bls12_381::{fp::*}; abi BlsTestContract { - #[storage(write)]fn initialize_counter(value: u64) -> u64; - #[storage(read, write)]fn increment_counter(amount: u64) -> u64; -} - -storage { - counter: u64 = 0, + #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; } impl BlsTestContract for Contract { - #[storage(write)]fn initialize_counter(value: u64) -> u64 { - storage.counter = value; - value + #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp { + a.add(b) } - #[storage(read, write)]fn increment_counter(amount: u64) -> u64 { - let incremented = storage.counter + amount; - storage.counter = incremented; - incremented + #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { + a.sub(b) } } diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index a736adb..e412d25 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -21,25 +21,56 @@ async fn get_contract_instance() -> (BlsTestContract, ContractId) { (instance, id) } + +pub fn res_equals(res: Fp, should_be: Fp) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} + #[tokio::test] -async fn can_get_contract_id() { +async fn test_add_fps() { + let small = Fp{ + ls: [1, 2, 3, 4, 5, 6].to_vec() + }; + let random = Fp{ + ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() + }; + let expected_res = Fp{ + ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851].to_vec() + }; + let (contract_instance, _id) = get_contract_instance().await; - // Now you have an instance of your contract you can use to test each function - let result = contract_instance - .initialize_counter(42) - .call() - .await - .unwrap(); + let res = contract_instance.add_fp(small, random) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); +} - assert_eq!(42, result.value); +#[tokio::test] +async fn test_sub_fps() { + let a = Fp { + ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194].to_vec() + }; - // Call `increment_counter()` method in our deployed contract. - let result = contract_instance - .increment_counter(10) - .call() - .await - .unwrap(); + let b = Fp { + ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174].to_vec() + }; + let expected_res = Fp { + ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; - assert_eq!(52, result.value); -} + let res = _instance.sub_fp(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); +} \ No newline at end of file From 25fb4877922bb59fe4016cb6e1bc9f37e1d3a2a8 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 29 Jul 2022 15:32:25 -0600 Subject: [PATCH 115/160] Added montgomery multiplication with test --- bls12_381/src/fp.sw | 218 ++++++++++++++++++++++---- tests_bls12_381/src/main.sw | 6 + tests_bls12_381/tests/tests_fp/mod.rs | 36 ++++- 3 files changed, 231 insertions(+), 29 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index ba9dae0..3bbe77d 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -1,6 +1,6 @@ library fp; -use std::{u128::*}; +use std::{option::*, u128::*, vec::Vec}; // Little endian big integer with 6 limbs // in Montgomery form (!) @@ -85,30 +85,6 @@ pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { (res.lower, res.upper >> 63) //(result, borrow) } -// If a >= p, return a-p, else return a -pub fn subtract_p(a: Fp) -> Fp { - let(r0, borrow) = sbb(a.ls[0], MODULUS[0], 0); - let(r1, borrow) = sbb(a.ls[1], MODULUS[1], borrow); - let(r2, borrow) = sbb(a.ls[2], MODULUS[2], borrow); - let(r3, borrow) = sbb(a.ls[3], MODULUS[3], borrow); - let(r4, borrow) = sbb(a.ls[4], MODULUS[4], borrow); - let(r5, borrow) = sbb(a.ls[5], MODULUS[5], borrow); - - // If underflow occurred on the final limb, borrow = 1, otherwise - // borrow = 0. We convert it into a mask. - let mut mask = borrow * ~u64::max(); - let r0 = (a.ls[0] & mask) | (r0 & not(mask)); - let r1 = (a.ls[1] & mask) | (r1 & not(mask)); - let r2 = (a.ls[2] & mask) | (r2 & not(mask)); - let r3 = (a.ls[3] & mask) | (r3 & not(mask)); - let r4 = (a.ls[4] & mask) | (r4 & not(mask)); - let r5 = (a.ls[5] & mask) | (r5 & not(mask)); - - Fp { - ls: [r0, r1, r2, r3, r4, r5] - } -} - //TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? //returns sum with carry of a and b pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { @@ -122,7 +98,45 @@ pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { (sum, carry_res) } + +//returns the result and new carry of a + b*c + carry +pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let c_128: U128 = ~U128::from(0, c); + let carry_128: U128 = ~U128::from(0, carry); + + let res: U128 = a_128 + (b_128 * c_128) + carry_128; + (res.lower, res.upper) +} + +//returns a*b mod(2^64) +pub fn multiply_wrap(a: u64, b: u64) -> u64 { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + + (a_128 * b_128).lower +} + impl Fp { + pub fn zero() -> Fp { + Fp{ls: [0, 0, 0, 0, 0, 0]} + } + + pub fn one() -> Fp { + R + } + + // TODO the u64 should be compared with ct_eq, but is not existing in Sway (yet) + fn ct_eq(self, other: Self) -> bool { + (self.ls[0] == other.ls[0]) + && (self.ls[1] == other.ls[1]) + && (self.ls[2] == other.ls[2]) + && (self.ls[3] == other.ls[3]) + && (self.ls[4] == other.ls[4]) + && (self.ls[5] == other.ls[5]) + } + pub fn neg(self) -> Fp { let(d0, borrow) = sbb(MODULUS[0], self.ls[0], 0); let(d1, borrow) = sbb(MODULUS[1], self.ls[1], borrow); @@ -134,7 +148,7 @@ impl Fp { // We need a mask that's 0 when a==p and 2^65-1 otherwise // TODO improve this let mut a_is_p = 0; - if (self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3] | self.ls[4] | self.ls[5]) == 0 { + if (self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3] | self.ls[4] | self.ls[5] == 0) { a_is_p = 1; //don't know is there's a native conversion } else { a_is_p = 0; @@ -147,6 +161,36 @@ impl Fp { } } + // If a >= p, return a-p, else return a + pub fn subtract_p(self) -> Fp { + let(r0, borrow) = sbb(self.ls[0], MODULUS[0], 0); + let(r1, borrow) = sbb(self.ls[1], MODULUS[1], borrow); + let(r2, borrow) = sbb(self.ls[2], MODULUS[2], borrow); + let(r3, borrow) = sbb(self.ls[3], MODULUS[3], borrow); + let(r4, borrow) = sbb(self.ls[4], MODULUS[4], borrow); + let(r5, borrow) = sbb(self.ls[5], MODULUS[5], borrow); + + // If underflow occurred on the final limb, borrow = 1, otherwise + // borrow = 0. We convert it into a mask. + let mut mask = borrow * ~u64::max(); + let r0 = (self.ls[0] & mask) | (r0 & not(mask)); + let r1 = (self.ls[1] & mask) | (r1 & not(mask)); + let r2 = (self.ls[2] & mask) | (r2 & not(mask)); + let r3 = (self.ls[3] & mask) | (r3 & not(mask)); + let r4 = (self.ls[4] & mask) | (r4 & not(mask)); + let r5 = (self.ls[5] & mask) | (r5 & not(mask)); + + Fp { + ls: [r0, r1, r2, r3, r4, r5] + } + } +} + +impl Fp { + pub fn is_zero(self) -> bool { + self.ct_eq(~Fp::zero()) + } + fn add(self, rhs: Fp) -> Fp { let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); @@ -157,7 +201,68 @@ impl Fp { // Attempt to subtract the modulus, to ensure the value // is smaller than the modulus. - subtract_p(Fp{ls:[d0, d1, d2, d3, d4, d5]}) + (Fp{ls:[d0, d1, d2, d3, d4, d5]}).subtract_p() + } + + pub fn mul(self, rhs: Fp) -> Fp { + let self0 = self.ls[0]; + let self1 = self.ls[1]; + let self2 = self.ls[2]; + let self3 = self.ls[3]; + let self4 = self.ls[4]; + let self5 = self.ls[5]; + + let rhs0 = rhs.ls[0]; + let rhs1 = rhs.ls[1]; + let rhs2 = rhs.ls[2]; + let rhs3 = rhs.ls[3]; + let rhs4 = rhs.ls[4]; + let rhs5 = rhs.ls[5]; + + let(t0, carry) = mac(0, self0, rhs0, 0); + let(t1, carry) = mac(0, self0, rhs1, carry); + let(t2, carry) = mac(0, self0, rhs2, carry); + let(t3, carry) = mac(0, self0, rhs3, carry); + let(t4, carry) = mac(0, self0, rhs4, carry); + let(t5, t6) = mac(0, self0, rhs5, carry); + + let(t1, carry) = mac(t1, self1, rhs0, 0); + let(t2, carry) = mac(t2, self1, rhs1, carry); + let(t3, carry) = mac(t3, self1, rhs2, carry); + let(t4, carry) = mac(t4, self1, rhs3, carry); + let(t5, carry) = mac(t5, self1, rhs4, carry); + let(t6, t7) = mac(t6, self1, rhs5, carry); + + let(t2, carry) = mac(t2, self2, rhs0, 0); + let(t3, carry) = mac(t3, self2, rhs1, carry); + let(t4, carry) = mac(t4, self2, rhs2, carry); + let(t5, carry) = mac(t5, self2, rhs3, carry); + let(t6, carry) = mac(t6, self2, rhs4, carry); + let(t7, t8) = mac(t7, self2, rhs5, carry); + + let(t3, carry) = mac(t3, self3, rhs0, 0); + let(t4, carry) = mac(t4, self3, rhs1, carry); + let(t5, carry) = mac(t5, self3, rhs2, carry); + let(t6, carry) = mac(t6, self3, rhs3, carry); + let(t7, carry) = mac(t7, self3, rhs4, carry); + let(t8, t9) = mac(t8, self3, rhs5, carry); + + let(t4, carry) = mac(t4, self4, rhs0, 0); + let(t5, carry) = mac(t5, self4, rhs1, carry); + let(t6, carry) = mac(t6, self4, rhs2, carry); + let(t7, carry) = mac(t7, self4, rhs3, carry); + let(t8, carry) = mac(t8, self4, rhs4, carry); + let(t9, t10) = mac(t9, self4, rhs5, carry); + + let(t5, carry) = mac(t5, self5, rhs0, 0); + let(t6, carry) = mac(t6, self5, rhs1, carry); + let(t7, carry) = mac(t7, self5, rhs2, carry); + let(t8, carry) = mac(t8, self5, rhs3, carry); + let(t9, carry) = mac(t9, self5, rhs4, carry); + let(t10, t11) = mac(t10, self5, rhs5, carry); + + let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + montgomery_reduce(res) } } @@ -166,3 +271,62 @@ impl Fp { (rhs.neg()).add(self) } } + +pub fn montgomery_reduce(t: [u64;12]) -> Fp { + let k = multiply_wrap(t[0], INV); + + let r0: (u64, u64) = mac(t[0], k, MODULUS[0], 0); + let r1: (u64, u64) = mac(t[1], k, MODULUS[1], r0.1); + let r2: (u64, u64) = mac(t[2], k, MODULUS[2], r1.1); + let r3: (u64, u64) = mac(t[3], k, MODULUS[3], r2.1); + let r4: (u64, u64) = mac(t[4], k, MODULUS[4], r3.1); + let r5: (u64, u64) = mac(t[5], k, MODULUS[5], r4.1); + let r6_7: (u64, u64) = adc(t[6], 0, r5.1); + + let k = multiply_wrap(r1.0, INV); + let r0: (u64, u64) = mac(r1.0, k, MODULUS[0], 0); + let r2: (u64, u64) = mac(r2.0, k, MODULUS[1], r0.1); + let r3: (u64, u64) = mac(r3.0, k, MODULUS[2], r2.1); + let r4: (u64, u64) = mac(r4.0, k, MODULUS[3], r3.1); + let r5: (u64, u64) = mac(r5.0, k, MODULUS[4], r4.1); + let r6: (u64, u64) = mac(r6_7.0, k, MODULUS[5], r5.1); + let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); + + let k = multiply_wrap(r2.0, INV); + let r0: (u64, u64) = mac(r2.0, k, MODULUS[0], 0); + let r3: (u64, u64) = mac(r3.0, k, MODULUS[1], r0.1); + let r4: (u64, u64) = mac(r4.0, k, MODULUS[2], r3.1); + let r5: (u64, u64) = mac(r5.0, k, MODULUS[3], r4.1); + let r6: (u64, u64) = mac(r6.0, k, MODULUS[4], r5.1); + let r7: (u64, u64) = mac(r7_8.0, k, MODULUS[5], r6.1); + let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); + + let k = multiply_wrap(r3.0, INV); + let r0: (u64, u64) = mac(r3.0, k, MODULUS[0], 0); + let r4: (u64, u64) = mac(r4.0, k, MODULUS[1], r0.1); + let r5: (u64, u64) = mac(r5.0, k, MODULUS[2], r4.1); + let r6: (u64, u64) = mac(r6.0, k, MODULUS[3], r5.1); + let r7: (u64, u64) = mac(r7.0, k, MODULUS[4], r6.1); + let r8: (u64, u64) = mac(r8_9.0, k, MODULUS[5], r7.1); + let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); + + let k = multiply_wrap(r4.0, INV); + let r0: (u64, u64) = mac(r4.0, k, MODULUS[0], 0); + let r5: (u64, u64) = mac(r5.0, k, MODULUS[1], r0.1); + let r6: (u64, u64) = mac(r6.0, k, MODULUS[2], r5.1); + let r7: (u64, u64) = mac(r7.0, k, MODULUS[3], r6.1); + let r8: (u64, u64) = mac(r8.0, k, MODULUS[4], r7.1); + let r9: (u64, u64) = mac(r9_10.0, k, MODULUS[5], r8.1); + let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); + + let k = multiply_wrap(r5.0, INV); + let r0: (u64, u64) = mac(r5.0, k, MODULUS[0], 0); + let r6: (u64, u64) = mac(r6.0, k, MODULUS[1], r0.1); + let r7: (u64, u64) = mac(r7.0, k, MODULUS[2], r6.1); + let r8: (u64, u64) = mac(r8.0, k, MODULUS[3], r7.1); + let r9: (u64, u64) = mac(r9.0, k, MODULUS[4], r8.1); + let r10: (u64, u64) = mac(r10_11.0, k, MODULUS[5], r9.1); + let r11_12 = adc(t[11], r10_11.1, r10.1); + + (Fp { ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}).subtract_p() +} \ No newline at end of file diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 6fb22d4..8713617 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -5,6 +5,8 @@ use bls12_381::{fp::*}; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; + } impl BlsTestContract for Contract { @@ -15,4 +17,8 @@ impl BlsTestContract for Contract { #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { a.sub(b) } + + #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { + a.mul(b) + } } diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index e412d25..c96f2a0 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -33,7 +33,7 @@ pub fn res_equals(res: Fp, should_be: Fp) -> bool { } #[tokio::test] -async fn test_add_fps() { +async fn test_add_fp() { let small = Fp{ ls: [1, 2, 3, 4, 5, 6].to_vec() }; @@ -55,7 +55,7 @@ async fn test_add_fps() { } #[tokio::test] -async fn test_sub_fps() { +async fn test_sub_fp() { let a = Fp { ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194].to_vec() }; @@ -73,4 +73,36 @@ async fn test_sub_fps() { .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(res_equals(res, expected_res)); +} + +#[tokio::test] +async fn test_mul_fp() { + let r1_vec: Fp = Fp { + ls: [6071868568151433008, + 12105094901188801210, + 2389211775905699303, + 7838417195104481535, + 5826366508043997497, + 13436617433956842131].to_vec() + }; + let r2_vec: Fp = Fp { + ls: [16964885827015180015, + 12035734743809705289, + 10517060043363161601, + 1119606639881808286, + 2211903887497377980, + 395875676649998273].to_vec() + }; + // this is the expected result according to the zkcrypto impl. This is multiplication on montgomery forms + let expected_res: Fp = Fp { + ls: [16484308011771146774, 12795119582497094196, 7495239071060242083, + 6228288009955243706, 334445847756758381, 1343304342180463133].to_vec() + }; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.mul_fp(r1_vec, r2_vec) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, expected_res)); } \ No newline at end of file From 014505922543a0287d4e2ef73cde9f5d53cb8eb2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 29 Jul 2022 16:25:53 -0600 Subject: [PATCH 116/160] Added squaring in Fp --- bls12_381/src/fp.sw | 50 +++++++++++++++++++++++++++ tests_bls12_381/src/main.sw | 7 +++- tests_bls12_381/tests/tests_fp/mod.rs | 43 +++++++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 3bbe77d..857088a 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -264,6 +264,56 @@ impl Fp { let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) } + + pub fn square(self) -> Fp { + let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); + let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); + let (t3, carry) = mac(0, self.ls[0], self.ls[3], carry); + let (t4, carry) = mac(0, self.ls[0], self.ls[4], carry); + let (t5, t6) = mac(0, self.ls[0], self.ls[5], carry); + + let (t3, carry) = mac(t3, self.ls[1], self.ls[2], 0); + let (t4, carry) = mac(t4, self.ls[1], self.ls[3], carry); + let (t5, carry) = mac(t5, self.ls[1], self.ls[4], carry); + let (t6, t7) = mac(t6, self.ls[1], self.ls[5], carry); + + let (t5, carry) = mac(t5, self.ls[2], self.ls[3], 0); + let (t6, carry) = mac(t6, self.ls[2], self.ls[4], carry); + let (t7, t8) = mac(t7, self.ls[2], self.ls[5], carry); + + let (t7, carry) = mac(t7, self.ls[3], self.ls[4], 0); + let (t8, t9) = mac(t8, self.ls[3], self.ls[5], carry); + + let (t9, t10) = mac(t9, self.ls[4], self.ls[5], 0); + + let t11 = t10 >> 63; + let t10 = (t10 << 1) | (t9 >> 63); + let t9 = (t9 << 1) | (t8 >> 63); + let t8 = (t8 << 1) | (t7 >> 63); + let t7 = (t7 << 1) | (t6 >> 63); + let t6 = (t6 << 1) | (t5 >> 63); + let t5 = (t5 << 1) | (t4 >> 63); + let t4 = (t4 << 1) | (t3 >> 63); + let t3 = (t3 << 1) | (t2 >> 63); + let t2 = (t2 << 1) | (t1 >> 63); + let t1 = t1 << 1; + + let (t0, carry) = mac(0, self.ls[0], self.ls[0], 0); + let (t1, carry) = adc(t1, 0, carry); + let (t2, carry) = mac(t2, self.ls[1], self.ls[1], carry); + let (t3, carry) = adc(t3, 0, carry); + let (t4, carry) = mac(t4, self.ls[2], self.ls[2], carry); + let (t5, carry) = adc(t5, 0, carry); + let (t6, carry) = mac(t6, self.ls[3], self.ls[3], carry); + let (t7, carry) = adc(t7, 0, carry); + let (t8, carry) = mac(t8, self.ls[4], self.ls[4], carry); + let (t9, carry) = adc(t9, 0, carry); + let (t10, carry) = mac(t10, self.ls[5], self.ls[5], carry); + let (t11, _) = adc(t11, 0, carry); + + let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + montgomery_reduce(res) + } } impl Fp { diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 8713617..501888d 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -6,6 +6,7 @@ abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn square_fp(a: Fp) -> Fp; } @@ -21,4 +22,8 @@ impl BlsTestContract for Contract { #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { a.mul(b) } -} + + #[storage(read, write)]fn square_fp(a: Fp) -> Fp { + a.square() + } +} \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index c96f2a0..f1137ff 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -75,6 +75,7 @@ async fn test_sub_fp() { assert!(res_equals(res, expected_res)); } +//WORKS, but smart to comment out when wanting to test other things #[tokio::test] async fn test_mul_fp() { let r1_vec: Fp = Fp { @@ -105,4 +106,46 @@ async fn test_mul_fp() { .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(res_equals(res, expected_res)); +} + +//WORKS, but smart to comment out when wanting to test other things +#[tokio::test] +async fn test_square_fp() { + let r1_1: Fp = Fp { + ls: [6071868568151433008, + 12105094901188801210, + 2389211775905699303, + 7838417195104481535, + 5826366508043997497, + 13436617433956842131].to_vec() + }; + let r1_2: Fp = Fp { + ls: [6071868568151433008, + 12105094901188801210, + 2389211775905699303, + 7838417195104481535, + 5826366508043997497, + 13436617433956842131].to_vec() + }; + let r1_3: Fp = Fp { + ls: [6071868568151433008, + 12105094901188801210, + 2389211775905699303, + 7838417195104481535, + 5826366508043997497, + 13436617433956842131].to_vec() + }; + + let (_instance, _id) = get_contract_instance().await; + + let expected_res = _instance.mul_fp(r1_1, r1_2) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + let res = _instance.square_fp(r1_3) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res, expected_res)); } \ No newline at end of file From 369697055ac05ee4d0f62f9dfc8016f67fe38088 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 29 Jul 2022 17:50:15 -0600 Subject: [PATCH 117/160] This runs a local fuel-core node for contract testing. In version fuels 0.19 it will be possible to adjust the gas limit. This can possibly help us run multiplication tests. --- tests-bls/Cargo.toml | 2 +- tests-bls/tests/harness.rs | 4 +-- tests-bls/tests/tests_add_fp/mod.rs | 40 ++++++++++++++++------------- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/tests-bls/Cargo.toml b/tests-bls/Cargo.toml index ceec775..c942e4a 100644 --- a/tests-bls/Cargo.toml +++ b/tests-bls/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "Apache-2.0" [dependencies] -fuels = "0.16.1" +fuels = "0.18" fuels-abigen-macro = "0.16.1" tokio = { version = "1.12", features = ["rt", "macros"] } diff --git a/tests-bls/tests/harness.rs b/tests-bls/tests/harness.rs index 779c5fb..16a61ad 100644 --- a/tests-bls/tests/harness.rs +++ b/tests-bls/tests/harness.rs @@ -1,9 +1,9 @@ -// mod tests_add_fp; +mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; // mod tests_rshift_mod_384; // mod tests_temp_mul; // mod tests_vect_subfunctions; -mod tests_vect_fp2; +// mod tests_vect_fp2; // mod tests_temp_mul_mont_n; gives error OutOfGas diff --git a/tests-bls/tests/tests_add_fp/mod.rs b/tests-bls/tests/tests_add_fp/mod.rs index 148a046..46cbd1e 100644 --- a/tests-bls/tests/tests_add_fp/mod.rs +++ b/tests-bls/tests/tests_add_fp/mod.rs @@ -1,23 +1,16 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; +use fuels::{ + prelude::*, + tx::{ConsensusParameters, ContractId}, +}; abigen!(BlsContract, "out/debug/tests-bls-abi.json"); async fn get_contract_instance() -> (BlsContract, ContractId) { - - // This is the address of a running node. - let server_address = "127.0.0.1:4000" - .parse() - .expect("Unable to parse socket address"); - - // Create the provider using the client. - let provider = Provider::connect(server_address).await.unwrap(); - // Create the wallet. - let wallet = LocalWallet::new_random(Some(provider)); + let mut wallet = LocalWallet::new_random(None); let num_assets = 1; - let coins_per_asset = 100_000_000; - let amount_per_coin = 1; + let coins_per_asset = 100; + let amount_per_coin = 100000; let (coins, asset_ids) = setup_multiple_assets_coins( wallet.address(), @@ -26,11 +19,22 @@ async fn get_contract_instance() -> (BlsContract, ContractId) { amount_per_coin, ); + let _consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); // Can't use this for now :( + + let (client, addr) = setup_test_client(coins, None).await; + + let provider = Provider::new(client); + wallet.set_provider(provider.clone()); - // let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - // let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); + let id = Contract::deploy( + "./out/debug/tests-bls.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::default(), + ) + .await + .unwrap(); + let instance = BlsContractBuilder::new(id.to_string(), wallet).build(); (instance, id) } From edc32c31073ffd3384a873b1ba682037e89dbec9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 29 Jul 2022 19:34:56 -0600 Subject: [PATCH 118/160] Adjusted tests for mul and square to align with zkcrypto tests. This shows that square is not giving the desired result. Unclear why --- bls12_381/src/fp.sw | 2 + tests_bls12_381/tests/tests_fp/mod.rs | 113 ++++++++++++++------------ 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 857088a..5c33682 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -265,6 +265,8 @@ impl Fp { montgomery_reduce(res) } +// TODO fix. +// This is not giving the correct output, but I can't see any difference with the zkcrypto impl pub fn square(self) -> Fp { let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index f1137ff..ceb6a7a 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -75,77 +75,84 @@ async fn test_sub_fp() { assert!(res_equals(res, expected_res)); } -//WORKS, but smart to comment out when wanting to test other things +// WORKS, but smart to comment out when wanting to test other things #[tokio::test] async fn test_mul_fp() { - let r1_vec: Fp = Fp { - ls: [6071868568151433008, - 12105094901188801210, - 2389211775905699303, - 7838417195104481535, - 5826366508043997497, - 13436617433956842131].to_vec() - }; - let r2_vec: Fp = Fp { - ls: [16964885827015180015, - 12035734743809705289, - 10517060043363161601, - 1119606639881808286, - 2211903887497377980, - 395875676649998273].to_vec() - }; - // this is the expected result according to the zkcrypto impl. This is multiplication on montgomery forms - let expected_res: Fp = Fp { - ls: [16484308011771146774, 12795119582497094196, 7495239071060242083, - 6228288009955243706, 334445847756758381, 1343304342180463133].to_vec() - }; + let a = Fp{ ls:[ + 0x0397_a383_2017_0cd4, + 0x734c_1b2c_9e76_1d30, + 0x5ed2_55ad_9a48_beb5, + 0x095a_3c6b_22a7_fcfc, + 0x2294_ce75_d4e2_6a27, + 0x1333_8bd8_7001_1ebb, + ].to_vec()}; + let b = Fp{ ls:[ + 0xb9c3_c7c5_b119_6af7, + 0x2580_e208_6ce3_35c1, + 0xf49a_ed3d_8a57_ef42, + 0x41f2_81e4_9846_e878, + 0xe076_2346_c384_52ce, + 0x0652_e893_26e5_7dc0, + ].to_vec()}; + let c = Fp{ ls:[ + 0xf96e_f3d7_11ab_5355, + 0xe8d4_59ea_00f1_48dd, + 0x53f7_354a_5f00_fa78, + 0x9e34_a4f3_125c_5f83, + 0x3fbe_0c47_ca74_c19e, + 0x01b0_6a8b_bd4a_dfe4, + ].to_vec()}; let (_instance, _id) = get_contract_instance().await; - let res = _instance.mul_fp(r1_vec, r2_vec) + let res = _instance.mul_fp(a, b) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); + assert!(res_equals(res, c)); } -//WORKS, but smart to comment out when wanting to test other things #[tokio::test] async fn test_square_fp() { - let r1_1: Fp = Fp { - ls: [6071868568151433008, - 12105094901188801210, - 2389211775905699303, - 7838417195104481535, - 5826366508043997497, - 13436617433956842131].to_vec() + let a: Fp = Fp { + ls: [0xd215_d276_8e83_191b,//15138237129114720539 + 0x5085_d80f_8fb2_8261,//5802281256283701857 + 0xce9a_032d_df39_3a56,//14887215013780077142 + 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 }; - let r1_2: Fp = Fp { - ls: [6071868568151433008, - 12105094901188801210, - 2389211775905699303, - 7838417195104481535, - 5826366508043997497, - 13436617433956842131].to_vec() + + let a_again: Fp = Fp { + ls: [0xd215_d276_8e83_191b, + 0x5085_d80f_8fb2_8261,//5802281256283701857 + 0xce9a_032d_df39_3a56,//14887215013780077142 + 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 }; - let r1_3: Fp = Fp { - ls: [6071868568151433008, - 12105094901188801210, - 2389211775905699303, - 7838417195104481535, - 5826366508043997497, - 13436617433956842131].to_vec() + + let expected_res: Fp = Fp { + ls: [0x33d9_c42a_3cb3_e235, + 0xdad1_1a09_4c4c_d455, + 0xa2f1_44bd_729a_aeba, + 0xd415_0932_be9f_feac, + 0xe27b_c7c4_7d44_ee50, + 0x14b6_a78d_3ec7_a560].to_vec() }; let (_instance, _id) = get_contract_instance().await; - let expected_res = _instance.mul_fp(r1_1, r1_2) + let res = _instance.mul_fp(a, a_again) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - let res = _instance.square_fp(r1_3) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - + //fails :( assert!(res_equals(res, expected_res)); -} \ No newline at end of file + + // print res of square + //[1902911976314425853, 13352981833795642672, 10289086307533160637, 13100812750071813769, 2610533423338883854, 1302806150312138448] + // print of mult + //[3736233051566629429, 15767412397637948501, 11741241283993841338, + // 15282131024102817452, 16319857321436311120, 1492564551605396832] + +} From e158f3d30883cbdf73cc2ba1c07c9e1974ef0c81 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Sat, 30 Jul 2022 12:21:46 -0600 Subject: [PATCH 119/160] - Started on Fp2 arithmetic - Test for fp2 gives error Immediate18TooLarge - Other functions (add, sub, neg, square) have to be tested still --- bls12_381/src/fp.sw | 120 +++++++++++++++++- bls12_381/src/fp2.sw | 102 ++++++++++++++++ bls12_381/src/lib.sw | 3 +- tests_bls12_381/src/main.sw | 13 +- tests_bls12_381/tests/harness.rs | 3 +- tests_bls12_381/tests/tests_fp/mod.rs | 162 ++++++++++++------------- tests_bls12_381/tests/tests_fp2/mod.rs | 84 +++++++++++++ 7 files changed, 400 insertions(+), 87 deletions(-) create mode 100644 bls12_381/src/fp2.sw create mode 100644 tests_bls12_381/tests/tests_fp2/mod.rs diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 5c33682..2f23818 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -127,8 +127,8 @@ impl Fp { R } - // TODO the u64 should be compared with ct_eq, but is not existing in Sway (yet) - fn ct_eq(self, other: Self) -> bool { + // TODO to make this constant time the u64 should be compared with ct_eq, but is not existing in Sway (yet) + fn eq(self, other: Self) -> bool { (self.ls[0] == other.ls[0]) && (self.ls[1] == other.ls[1]) && (self.ls[2] == other.ls[2]) @@ -186,9 +186,13 @@ impl Fp { } } +pub fn from_raw_unchecked(v: [u64; 6]) -> Fp { + Fp{ ls: v } +} + impl Fp { pub fn is_zero(self) -> bool { - self.ct_eq(~Fp::zero()) + self.eq(~Fp::zero()) } fn add(self, rhs: Fp) -> Fp { @@ -322,6 +326,116 @@ impl Fp { fn sub(self, rhs: Fp) -> Fp { (rhs.neg()).add(self) } + +//TODO implement this one for T=6. Also, T=2 has to be tested still + /// Returns `c = a.zip(b).fold(0, |acc, (a_i, b_i)| acc + a_i * b_i)`. + /// + /// Implements Algorithm 2 from Patrick Longa's + /// [ePrint 2022-367](https://eprint.iacr.org/2022/367) §3. + // pub fn sum_of_products(a: [Fp; T], b: [Fp; T]) -> Fp { //Elena T = 6 or T = 2 + // // For a single `a x b` multiplication, operand scanning (schoolbook) takes each + // // limb of `a` in turn, and multiplies it by all of the limbs of `b` to compute + // // the result as a double-width intermediate representation, which is then fully + // // reduced at the end. Here however we have pairs of multiplications (a_i, b_i), + // // the results of which are summed. + // // + // // The intuition for this algorithm is two-fold: + // // - We can interleave the operand scanning for each pair, by processing the jth + // // limb of each `a_i` together. As these have the same offset within the overall + // // operand scanning flow, their results can be summed directly. + // // - We can interleave the multiplication and reduction steps, resulting in a + // // single bitshift by the limb size after each iteration. This means we only + // // need to store a single extra limb overall, instead of keeping around all the + // // intermediate results and eventually having twice as many limbs. + + // // Algorithm 2, line 2 + // let (u0, u1, u2, u3, u4, u5) = // Elena range and fold dont seem to exist in Sway + // (0..6).fold((0, 0, 0, 0, 0, 0), |(u0, u1, u2, u3, u4, u5), j| { + // // Algorithm 2, line 3 + // // For each pair in the overall sum of products: + // let (t0, t1, t2, t3, t4, t5, t6) = (0..T).fold( + // (u0, u1, u2, u3, u4, u5, 0), + // |(t0, t1, t2, t3, t4, t5, t6), i| { + // // Compute digit_j x row and accumulate into `u`. + // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + // let (t6, _) = adc(t6, 0, carry); + + // (t0, t1, t2, t3, t4, t5, t6) + // }, + // ); + + // // Algorithm 2, lines 4-5 + // // This is a single step of the usual Montgomery reduction process. + // let k = multiply_wrap(t0, INV); + // let (_, carry) = mac(t0, k, MODULUS[0], 0); + // let (r1, carry) = mac(t1, k, MODULUS[1], carry); + // let (r2, carry) = mac(t2, k, MODULUS[2], carry); + // let (r3, carry) = mac(t3, k, MODULUS[3], carry); + // let (r4, carry) = mac(t4, k, MODULUS[4], carry); + // let (r5, carry) = mac(t5, k, MODULUS[5], carry); + // let (r6, _) = adc(t6, 0, carry); + + // (r1, r2, r3, r4, r5, r6) + // }); + + // // Because we represent F_p elements in non-redundant form, we need a final + // // conditional subtraction to ensure the output is in range. + // (Fp([u0, u1, u2, u3, u4, u5])).subtract_p() + // } + +// fold unpacked for the case that T = 2 + pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { + let u0 = 0; + let u1 = 0; + let u2 = 0; + let u3 = 0; + let u4 = 0; + let u5 = 0; + let mut j = 0; + + while j < 6 { + let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); + + let mut i = 0; + + let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + let (t6, _) = adc(t6, 0, carry); + + i = 1; + let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + let (t6, _) = adc(t6, 0, carry); + + let k = multiply_wrap(t0, INV); + let (_, carry) = mac(t0, k, MODULUS[0], 0); + let (u1, carry) = mac(t1, k, MODULUS[1], carry); + let (u2, carry) = mac(t2, k, MODULUS[2], carry); + let (u3, carry) = mac(t3, k, MODULUS[3], carry); + let (u4, carry) = mac(t4, k, MODULUS[4], carry); + let (u5, carry) = mac(t5, k, MODULUS[5], carry); + let (u6, _) = adc(t6, 0, carry); + + j += 1; + } + + // Because we represent F_p elements in non-redundant form, we need a final + // conditional subtraction to ensure the output is in range. + (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() + } } pub fn montgomery_reduce(t: [u64;12]) -> Fp { diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw new file mode 100644 index 0000000..f83cd09 --- /dev/null +++ b/bls12_381/src/fp2.sw @@ -0,0 +1,102 @@ +library fp2; + +dep fp; +use fp::*; + +pub struct Fp2 { + c0: Fp, //"real" part + c1: Fp, //"imaginary" part +} + +impl Fp2 { + fn from(f: Fp) -> Fp2 { + Fp2 { + c0: f, + c1: ~Fp::zero(), + } + } + + pub fn zero() -> Fp2 { + Fp2 { + c0: ~Fp::zero(), + c1: ~Fp::zero(), + } + } + + pub fn one() -> Fp2 { + Fp2 { + c0: ~Fp::one(), + c1: ~Fp::zero(), + } + } + + + fn eq(self, other: Self) -> bool { + self.c0.eq(other.c0) && self.c1.eq(other.c1) + } + +//TODO test + pub fn square(self) -> Fp2 { + // Complex squaring: + // + // v0 = c0 * c1 + // c0' = (c0 + c1) * (c0 + \beta*c1) - v0 - \beta * v0 + // c1' = 2 * v0 + // + // In BLS12-381's F_{p^2}, our \beta is -1 so we + // can modify this formula: + // + // c0' = (c0 + c1) * (c0 - c1) + // c1' = 2 * c0 * c1 + + let a = (self.c0).add(self.c1); + let b = (self.c0).sub(self.c1); + let c = (self.c0).add(self.c0); + + Fp2 { + c0: (a).mul(b), + c1: (c).mul(self.c1), + } + } + + pub fn mul(self, rhs: Fp2) -> Fp2 { + // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) + // computes the result as: + // + // a·b = (a_0 b_0 + a_1 b_1 β) + (a_0 b_1 + a_1 b_0)i + // + // In BLS12-381's F_{p^2}, our β is -1, so the resulting F_{p^2} element is: + // + // c_0 = a_0 b_0 - a_1 b_1 + // c_1 = a_0 b_1 + a_1 b_0 + // + // Each of these is a "sum of products", which we can compute efficiently. + + Fp2 { + c0: ~Fp::sum_of_products_2([self.c0, self.c1.neg()], [rhs.c0, rhs.c1]), + c1: ~Fp::sum_of_products_2([self.c0, self.c1], [rhs.c1, rhs.c0]), + } + } +//TODO test + pub fn add(self, rhs: Fp2) -> Fp2 { + Fp2 { + c0: (self.c0).add(rhs.c0), + c1: (self.c1).add(rhs.c1), + } + } +//TODO test + pub fn sub(self, rhs: Fp2) -> Fp2 { + Fp2 { + c0: (self.c0).sub(rhs.c0), + c1: (self.c1).sub(rhs.c1), + } + } +//TODO test + pub fn neg(self) -> Fp2 { + Fp2 { + c0: (self.c0).neg(), + c1: (self.c1).neg(), + } + } + +} \ No newline at end of file diff --git a/bls12_381/src/lib.sw b/bls12_381/src/lib.sw index 3d3a47e..aaa9f10 100644 --- a/bls12_381/src/lib.sw +++ b/bls12_381/src/lib.sw @@ -1,3 +1,4 @@ library bls12_381; -dep fp; \ No newline at end of file +dep fp; +dep fp2; \ No newline at end of file diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 501888d..81552bc 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,12 +1,15 @@ contract; -use bls12_381::{fp::*}; +use bls12_381::{fp::*, fp2::*}; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn square_fp(a: Fp) -> Fp; + #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp; + + #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; } @@ -26,4 +29,12 @@ impl BlsTestContract for Contract { #[storage(read, write)]fn square_fp(a: Fp) -> Fp { a.square() } + + #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp { + from_raw_unchecked(v) + } + + #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { + a.mul(b) + } } \ No newline at end of file diff --git a/tests_bls12_381/tests/harness.rs b/tests_bls12_381/tests/harness.rs index 689c777..3ca35f3 100644 --- a/tests_bls12_381/tests/harness.rs +++ b/tests_bls12_381/tests/harness.rs @@ -1 +1,2 @@ -mod tests_fp; \ No newline at end of file +// mod tests_fp; +mod tests_fp2; \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index ceb6a7a..cfbdebc 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -75,84 +75,84 @@ async fn test_sub_fp() { assert!(res_equals(res, expected_res)); } -// WORKS, but smart to comment out when wanting to test other things -#[tokio::test] -async fn test_mul_fp() { - let a = Fp{ ls:[ - 0x0397_a383_2017_0cd4, - 0x734c_1b2c_9e76_1d30, - 0x5ed2_55ad_9a48_beb5, - 0x095a_3c6b_22a7_fcfc, - 0x2294_ce75_d4e2_6a27, - 0x1333_8bd8_7001_1ebb, - ].to_vec()}; - let b = Fp{ ls:[ - 0xb9c3_c7c5_b119_6af7, - 0x2580_e208_6ce3_35c1, - 0xf49a_ed3d_8a57_ef42, - 0x41f2_81e4_9846_e878, - 0xe076_2346_c384_52ce, - 0x0652_e893_26e5_7dc0, - ].to_vec()}; - let c = Fp{ ls:[ - 0xf96e_f3d7_11ab_5355, - 0xe8d4_59ea_00f1_48dd, - 0x53f7_354a_5f00_fa78, - 0x9e34_a4f3_125c_5f83, - 0x3fbe_0c47_ca74_c19e, - 0x01b0_6a8b_bd4a_dfe4, - ].to_vec()}; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_fp(a, b) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, c)); -} - -#[tokio::test] -async fn test_square_fp() { - let a: Fp = Fp { - ls: [0xd215_d276_8e83_191b,//15138237129114720539 - 0x5085_d80f_8fb2_8261,//5802281256283701857 - 0xce9a_032d_df39_3a56,//14887215013780077142 - 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 - 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 - 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 - }; - - let a_again: Fp = Fp { - ls: [0xd215_d276_8e83_191b, - 0x5085_d80f_8fb2_8261,//5802281256283701857 - 0xce9a_032d_df39_3a56,//14887215013780077142 - 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 - 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 - 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 - }; - - let expected_res: Fp = Fp { - ls: [0x33d9_c42a_3cb3_e235, - 0xdad1_1a09_4c4c_d455, - 0xa2f1_44bd_729a_aeba, - 0xd415_0932_be9f_feac, - 0xe27b_c7c4_7d44_ee50, - 0x14b6_a78d_3ec7_a560].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_fp(a, a_again) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - //fails :( - assert!(res_equals(res, expected_res)); - - // print res of square - //[1902911976314425853, 13352981833795642672, 10289086307533160637, 13100812750071813769, 2610533423338883854, 1302806150312138448] - // print of mult - //[3736233051566629429, 15767412397637948501, 11741241283993841338, - // 15282131024102817452, 16319857321436311120, 1492564551605396832] - -} +// // WORKS, but smart to comment out when wanting to test other things +// #[tokio::test] +// async fn test_mul_fp() { +// let a = Fp{ ls:[ +// 0x0397_a383_2017_0cd4, +// 0x734c_1b2c_9e76_1d30, +// 0x5ed2_55ad_9a48_beb5, +// 0x095a_3c6b_22a7_fcfc, +// 0x2294_ce75_d4e2_6a27, +// 0x1333_8bd8_7001_1ebb, +// ].to_vec()}; +// let b = Fp{ ls:[ +// 0xb9c3_c7c5_b119_6af7, +// 0x2580_e208_6ce3_35c1, +// 0xf49a_ed3d_8a57_ef42, +// 0x41f2_81e4_9846_e878, +// 0xe076_2346_c384_52ce, +// 0x0652_e893_26e5_7dc0, +// ].to_vec()}; +// let c = Fp{ ls:[ +// 0xf96e_f3d7_11ab_5355, +// 0xe8d4_59ea_00f1_48dd, +// 0x53f7_354a_5f00_fa78, +// 0x9e34_a4f3_125c_5f83, +// 0x3fbe_0c47_ca74_c19e, +// 0x01b0_6a8b_bd4a_dfe4, +// ].to_vec()}; +// let (_instance, _id) = get_contract_instance().await; + +// let res = _instance.mul_fp(a, b) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// assert!(res_equals(res, c)); +// } + +// #[tokio::test] +// async fn test_square_fp() { +// let a: Fp = Fp { +// ls: [0xd215_d276_8e83_191b,//15138237129114720539 +// 0x5085_d80f_8fb2_8261,//5802281256283701857 +// 0xce9a_032d_df39_3a56,//14887215013780077142 +// 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 +// 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 +// 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 +// }; + +// let a_again: Fp = Fp { +// ls: [0xd215_d276_8e83_191b, +// 0x5085_d80f_8fb2_8261,//5802281256283701857 +// 0xce9a_032d_df39_3a56,//14887215013780077142 +// 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 +// 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 +// 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 +// }; + +// let expected_res: Fp = Fp { +// ls: [0x33d9_c42a_3cb3_e235, +// 0xdad1_1a09_4c4c_d455, +// 0xa2f1_44bd_729a_aeba, +// 0xd415_0932_be9f_feac, +// 0xe27b_c7c4_7d44_ee50, +// 0x14b6_a78d_3ec7_a560].to_vec() +// }; + +// let (_instance, _id) = get_contract_instance().await; + +// let res = _instance.mul_fp(a, a_again) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// //fails :( +// assert!(res_equals(res, expected_res)); + +// // print res of square +// //[1902911976314425853, 13352981833795642672, 10289086307533160637, 13100812750071813769, 2610533423338883854, 1302806150312138448] +// // print of mult +// //[3736233051566629429, 15767412397637948501, 11741241283993841338, +// // 15282131024102817452, 16319857321436311120, 1492564551605396832] + +// } diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs new file mode 100644 index 0000000..44f4cc4 --- /dev/null +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -0,0 +1,84 @@ +use fuels::{prelude::*, tx::ContractId}; + +// Load abi from json +abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); + +async fn get_contract_instance() -> (BlsTestContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "./out/debug/tests_bls12_381.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(None) + ) + .await + .unwrap(); + + let instance = BlsTestContract::new(id.to_string(), wallet); + + (instance, id) +} + + +//Errors: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262256, span: Span { src (ptr): 0x600012cb7b50, path: None, start: 0, end: 0, as_str(): "" } }' +// #[tokio::test] +// fn test_multiplication() { +// let a = Fp2 { +// c0: fp_from_raw_unchecked([ +// 0xc9a2_1831_63ee_70d4, +// 0xbc37_70a7_196b_5c91, +// 0xa247_f8c1_304c_5f44, +// 0xb01f_c2a3_726c_80b5, +// 0xe1d2_93e5_bbd9_19c9, +// 0x04b7_8e80_020e_f2ca, +// ]), +// c1: fp_from_raw_unchecked([ +// 0x952e_a446_0462_618f, +// 0x238d_5edd_f025_c62f, +// 0xf6c9_4b01_2ea9_2e72, +// 0x03ce_24ea_c1c9_3808, +// 0x0559_50f9_45da_483c, +// 0x010a_768d_0df4_eabc, +// ]), +// }; +// let b = Fp2 { +// c0: fp_from_raw_unchecked([ +// 0xa1e0_9175_a4d2_c1fe, +// 0x8b33_acfc_204e_ff12, +// 0xe244_15a1_1b45_6e42, +// 0x61d9_96b1_b6ee_1936, +// 0x1164_dbe8_667c_853c, +// 0x0788_557a_cc7d_9c79, +// ]), +// c1: fp_from_raw_unchecked([ +// 0xda6a_87cc_6f48_fa36, +// 0x0fc7_b488_277c_1903, +// 0x9445_ac4a_dc44_8187, +// 0x0261_6d5b_c909_9209, +// 0xdbed_4677_2db5_8d48, +// 0x11b9_4d50_76c7_b7b1, +// ]), +// }; +// let c = Fp2 { +// c0: fp_from_raw_unchecked([ +// 0xf597_483e_27b4_e0f7, +// 0x610f_badf_811d_ae5f, +// 0x8432_af91_7714_327a, +// 0x6a9a_9603_cf88_f09e, +// 0xf05a_7bf8_bad0_eb01, +// 0x0954_9131_c003_ffae, +// ]), +// c1: fp_from_raw_unchecked([ +// 0x963b_02d0_f93d_37cd, +// 0xc95c_e1cd_b30a_73d4, +// 0x3087_25fa_3126_f9b8, +// 0x56da_3c16_7fab_0d50, +// 0x6b50_86b5_f4b6_d6af, +// 0x09c3_9f06_2f18_e9f2, +// ]), +// }; + +// assert_eq!(mul_fp2(a, b), c); +// } \ No newline at end of file From 539750cb72a7b1ff459eb97988915ec9f800efd1 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 1 Aug 2022 14:48:08 -0600 Subject: [PATCH 120/160] Square in Fp is working. Test in Rust added. --- README.md | 9 +++ bls12_381/src/fp.sw | 97 +++++++++++++-------------- tests_bls12_381/tests/tests_fp/mod.rs | 82 +++++++++++----------- 3 files changed, 96 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 536042f..a1c05b8 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,15 @@ Various Cryptographic Primitives in Sway for the Fuel VM # Testing +## Spin Up a Fuel node +From [here](https://fuellabs.github.io/sway/v0.19.0/introduction/overview.html). +In a separate tab in your terminal, spin up a local Fuel node: + + +`fuel-core --db-type in-memory` + +This starts a Fuel node with a volatile database that will be cleared when shut down (good for testing purposes). + Make sure `fuel-core` is up to date. This can be done with [fuelup](https://github.com/FuelLabs/fuelup). Also, make sure there's only 1 `fuel-core` installed (check this with `which -a fuel-core`). ## Edwards25519 diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 2f23818..af54cf6 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -85,17 +85,14 @@ pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { (res.lower, res.upper >> 63) //(result, borrow) } -//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? //returns sum with carry of a and b pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { let a_128: U128 = ~U128::from(0, a); let b_128: U128 = ~U128::from(0, b); let carry_128: U128 = ~U128::from(0, carry); - let sum: u64 = (a_128 + b_128 + carry_128).lower; - let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; - - (sum, carry_res) + let sum = a_128 + b_128 + carry_128; + (sum.lower, sum.upper) } @@ -269,8 +266,6 @@ impl Fp { montgomery_reduce(res) } -// TODO fix. -// This is not giving the correct output, but I can't see any difference with the zkcrypto impl pub fn square(self) -> Fp { let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); @@ -389,53 +384,53 @@ impl Fp { // } // fold unpacked for the case that T = 2 - pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { - let u0 = 0; - let u1 = 0; - let u2 = 0; - let u3 = 0; - let u4 = 0; - let u5 = 0; - let mut j = 0; - - while j < 6 { - let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); - - let mut i = 0; + // pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { + // let u0 = 0; + // let u1 = 0; + // let u2 = 0; + // let u3 = 0; + // let u4 = 0; + // let u5 = 0; + // let mut j = 0; + + // while j < 6 { + // let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); + + // let mut i = 0; - let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - let (t6, _) = adc(t6, 0, carry); - - i = 1; - let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - let (t6, _) = adc(t6, 0, carry); - - let k = multiply_wrap(t0, INV); - let (_, carry) = mac(t0, k, MODULUS[0], 0); - let (u1, carry) = mac(t1, k, MODULUS[1], carry); - let (u2, carry) = mac(t2, k, MODULUS[2], carry); - let (u3, carry) = mac(t3, k, MODULUS[3], carry); - let (u4, carry) = mac(t4, k, MODULUS[4], carry); - let (u5, carry) = mac(t5, k, MODULUS[5], carry); - let (u6, _) = adc(t6, 0, carry); + // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + // let (t6, _) = adc(t6, 0, carry); + + // i = 1; + // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + // let (t6, _) = adc(t6, 0, carry); + + // let k = multiply_wrap(t0, INV); + // let (_, carry) = mac(t0, k, MODULUS[0], 0); + // let (u1, carry) = mac(t1, k, MODULUS[1], carry); + // let (u2, carry) = mac(t2, k, MODULUS[2], carry); + // let (u3, carry) = mac(t3, k, MODULUS[3], carry); + // let (u4, carry) = mac(t4, k, MODULUS[4], carry); + // let (u5, carry) = mac(t5, k, MODULUS[5], carry); + // let (u6, _) = adc(t6, 0, carry); - j += 1; - } + // j += 1; + // } - // Because we represent F_p elements in non-redundant form, we need a final - // conditional subtraction to ensure the output is in range. - (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() - } + // // Because we represent F_p elements in non-redundant form, we need a final + // // conditional subtraction to ensure the output is in range. + // (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() + // } } pub fn montgomery_reduce(t: [u64;12]) -> Fp { diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index cfbdebc..31df4d8 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -111,48 +111,48 @@ async fn test_sub_fp() { // assert!(res_equals(res, c)); // } -// #[tokio::test] -// async fn test_square_fp() { -// let a: Fp = Fp { -// ls: [0xd215_d276_8e83_191b,//15138237129114720539 -// 0x5085_d80f_8fb2_8261,//5802281256283701857 -// 0xce9a_032d_df39_3a56,//14887215013780077142 -// 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 -// 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 -// 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 -// }; - -// let a_again: Fp = Fp { -// ls: [0xd215_d276_8e83_191b, -// 0x5085_d80f_8fb2_8261,//5802281256283701857 -// 0xce9a_032d_df39_3a56,//14887215013780077142 -// 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 -// 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 -// 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 -// }; - -// let expected_res: Fp = Fp { -// ls: [0x33d9_c42a_3cb3_e235, -// 0xdad1_1a09_4c4c_d455, -// 0xa2f1_44bd_729a_aeba, -// 0xd415_0932_be9f_feac, -// 0xe27b_c7c4_7d44_ee50, -// 0x14b6_a78d_3ec7_a560].to_vec() -// }; +#[tokio::test] +async fn test_square_fp() { + let a: Fp = Fp { + ls: [0xd215_d276_8e83_191b,//15138237129114720539 + 0x5085_d80f_8fb2_8261,//5802281256283701857 + 0xce9a_032d_df39_3a56,//14887215013780077142 + 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 + }; -// let (_instance, _id) = get_contract_instance().await; + let a_again: Fp = Fp { + ls: [0xd215_d276_8e83_191b, + 0x5085_d80f_8fb2_8261,//5802281256283701857 + 0xce9a_032d_df39_3a56,//14887215013780077142 + 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 + }; -// let res = _instance.mul_fp(a, a_again) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// //fails :( -// assert!(res_equals(res, expected_res)); + let expected_res: Fp = Fp { + ls: [0x33d9_c42a_3cb3_e235, + 0xdad1_1a09_4c4c_d455, + 0xa2f1_44bd_729a_aeba, + 0xd415_0932_be9f_feac, + 0xe27b_c7c4_7d44_ee50, + 0x14b6_a78d_3ec7_a560].to_vec() + }; -// // print res of square -// //[1902911976314425853, 13352981833795642672, 10289086307533160637, 13100812750071813769, 2610533423338883854, 1302806150312138448] -// // print of mult -// //[3736233051566629429, 15767412397637948501, 11741241283993841338, -// // 15282131024102817452, 16319857321436311120, 1492564551605396832] + let (_instance, _id) = get_contract_instance().await; -// } + let res = _instance.square_fp(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + //fails :( + assert!(res_equals(res, expected_res)); + + // print res of square + //[1902911976314425853, 13352981833795642672, 10289086307533160637, 13100812750071813769, 2610533423338883854, 1302806150312138448] + // print of mult + //[3736233051566629429, 15767412397637948501, 11741241283993841338, + // 15282131024102817452, 16319857321436311120, 1492564551605396832] + +} From 03ad0ea33fbfa5af65302ee672f98b9b330ec407 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 1 Aug 2022 15:06:42 -0600 Subject: [PATCH 121/160] This file is only for testing purposes. When testing through contracts we're not able to print intermediate values, however through running a script we are. So this can be used for debugging. --- bls12_381/src/main.sw | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 bls12_381/src/main.sw diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw new file mode 100644 index 0000000..022510d --- /dev/null +++ b/bls12_381/src/main.sw @@ -0,0 +1,48 @@ +script; + +dep fp; + +use ::fp::*; +use std::{assert::assert}; +use std::logging::log; + +//this is a temporary file for test purposes. +// Logging in a library is easier when testing with a script. When testing through a contract that's not possible + +fn main () { + assert(test_square_fp()); +} + +pub fn res_equals(a: Fp, b: Fp) -> bool { + assert(a.ls[0] == b.ls[0]); + assert(a.ls[1] == b.ls[1]); + assert(a.ls[2] == b.ls[2]); + assert(a.ls[3] == b.ls[3]); + assert(a.ls[4] == b.ls[4]); + assert(a.ls[5] == b.ls[5]); + true +} + +fn test_square_fp() -> bool { + let a: Fp = Fp { + ls: [0xd215_d276_8e83_191b, + 0x5085_d80f_8fb2_8261, + 0xce9a_032d_df39_3a56, + 0x3e9c_4fff_2ca0_c4bb, + 0x6436_b6f7_f4d9_5dfb, + 0x1060_6628_ad4a_4d90] + }; + + let expected_res: Fp = Fp { + ls: [0x33d9_c42a_3cb3_e235, + 0xdad1_1a09_4c4c_d455, + 0xa2f1_44bd_729a_aeba, + 0xd415_0932_be9f_feac, + 0xe27b_c7c4_7d44_ee50, + 0x14b6_a78d_3ec7_a560] + }; + + let res = a.square(); + res_equals(res, expected_res); + true +} \ No newline at end of file From e804a3235a20914cc891681c7fb26a0c355cd9d9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 1 Aug 2022 19:16:50 -0600 Subject: [PATCH 122/160] Testing with custom gas limit --- tests-bls/tests/tests_add_fp/mod.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests-bls/tests/tests_add_fp/mod.rs b/tests-bls/tests/tests_add_fp/mod.rs index 46cbd1e..db40a88 100644 --- a/tests-bls/tests/tests_add_fp/mod.rs +++ b/tests-bls/tests/tests_add_fp/mod.rs @@ -5,7 +5,7 @@ use fuels::{ abigen!(BlsContract, "out/debug/tests-bls-abi.json"); -async fn get_contract_instance() -> (BlsContract, ContractId) { +async fn get_contract_instance() -> (BlsContract, Bech32ContractId) { // Create the wallet. let mut wallet = LocalWallet::new_random(None); let num_assets = 1; @@ -19,10 +19,14 @@ async fn get_contract_instance() -> (BlsContract, ContractId) { amount_per_coin, ); - let _consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); // Can't use this for now :( - - let (client, addr) = setup_test_client(coins, None).await; + // configure the gas limit + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); + // Here's the important part. This will be running a `fuel-core` that will live through this test. + // The configured coins are the same as before, I'm just passing them to it. + let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; + + // Important. Make sure the random wallet you created above uses this provider you created just now. let provider = Provider::new(client); wallet.set_provider(provider.clone()); @@ -30,11 +34,11 @@ async fn get_contract_instance() -> (BlsContract, ContractId) { "./out/debug/tests-bls.bin", &wallet, TxParameters::default(), - StorageConfiguration::default(), + StorageConfiguration::default(), // <--- new stuff from 0.18 ) .await .unwrap(); - let instance = BlsContractBuilder::new(id.to_string(), wallet).build(); + let instance = BlsContractBuilder::new(id.to_string(), wallet).build(); // <-- notice the `.build()` coming from `0.18` here (instance, id) } From 630a8fa04835df5fd3667474cb5fa42d447d0acb Mon Sep 17 00:00:00 2001 From: Manish Date: Tue, 2 Aug 2022 18:11:35 +0530 Subject: [PATCH 123/160] tests added for mul(failing), add, sub, neg for fp2 --- bls12_381/src/fp.sw | 304 ++++++++++++------------- bls12_381/src/fp2.sw | 81 +++++-- tests_bls12_381/src/main.sw | 32 ++- tests_bls12_381/tests/tests_fp/mod.rs | 16 +- tests_bls12_381/tests/tests_fp2/mod.rs | 270 ++++++++++++++++++++++ 5 files changed, 511 insertions(+), 192 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index af54cf6..f64af93 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -205,116 +205,116 @@ impl Fp { (Fp{ls:[d0, d1, d2, d3, d4, d5]}).subtract_p() } - pub fn mul(self, rhs: Fp) -> Fp { - let self0 = self.ls[0]; - let self1 = self.ls[1]; - let self2 = self.ls[2]; - let self3 = self.ls[3]; - let self4 = self.ls[4]; - let self5 = self.ls[5]; - - let rhs0 = rhs.ls[0]; - let rhs1 = rhs.ls[1]; - let rhs2 = rhs.ls[2]; - let rhs3 = rhs.ls[3]; - let rhs4 = rhs.ls[4]; - let rhs5 = rhs.ls[5]; - - let(t0, carry) = mac(0, self0, rhs0, 0); - let(t1, carry) = mac(0, self0, rhs1, carry); - let(t2, carry) = mac(0, self0, rhs2, carry); - let(t3, carry) = mac(0, self0, rhs3, carry); - let(t4, carry) = mac(0, self0, rhs4, carry); - let(t5, t6) = mac(0, self0, rhs5, carry); - - let(t1, carry) = mac(t1, self1, rhs0, 0); - let(t2, carry) = mac(t2, self1, rhs1, carry); - let(t3, carry) = mac(t3, self1, rhs2, carry); - let(t4, carry) = mac(t4, self1, rhs3, carry); - let(t5, carry) = mac(t5, self1, rhs4, carry); - let(t6, t7) = mac(t6, self1, rhs5, carry); - - let(t2, carry) = mac(t2, self2, rhs0, 0); - let(t3, carry) = mac(t3, self2, rhs1, carry); - let(t4, carry) = mac(t4, self2, rhs2, carry); - let(t5, carry) = mac(t5, self2, rhs3, carry); - let(t6, carry) = mac(t6, self2, rhs4, carry); - let(t7, t8) = mac(t7, self2, rhs5, carry); - - let(t3, carry) = mac(t3, self3, rhs0, 0); - let(t4, carry) = mac(t4, self3, rhs1, carry); - let(t5, carry) = mac(t5, self3, rhs2, carry); - let(t6, carry) = mac(t6, self3, rhs3, carry); - let(t7, carry) = mac(t7, self3, rhs4, carry); - let(t8, t9) = mac(t8, self3, rhs5, carry); - - let(t4, carry) = mac(t4, self4, rhs0, 0); - let(t5, carry) = mac(t5, self4, rhs1, carry); - let(t6, carry) = mac(t6, self4, rhs2, carry); - let(t7, carry) = mac(t7, self4, rhs3, carry); - let(t8, carry) = mac(t8, self4, rhs4, carry); - let(t9, t10) = mac(t9, self4, rhs5, carry); - - let(t5, carry) = mac(t5, self5, rhs0, 0); - let(t6, carry) = mac(t6, self5, rhs1, carry); - let(t7, carry) = mac(t7, self5, rhs2, carry); - let(t8, carry) = mac(t8, self5, rhs3, carry); - let(t9, carry) = mac(t9, self5, rhs4, carry); - let(t10, t11) = mac(t10, self5, rhs5, carry); - - let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; - montgomery_reduce(res) - } + // pub fn mul(self, rhs: Fp) -> Fp { + // let self0 = self.ls[0]; + // let self1 = self.ls[1]; + // let self2 = self.ls[2]; + // let self3 = self.ls[3]; + // let self4 = self.ls[4]; + // let self5 = self.ls[5]; + + // let rhs0 = rhs.ls[0]; + // let rhs1 = rhs.ls[1]; + // let rhs2 = rhs.ls[2]; + // let rhs3 = rhs.ls[3]; + // let rhs4 = rhs.ls[4]; + // let rhs5 = rhs.ls[5]; + + // let(t0, carry) = mac(0, self0, rhs0, 0); + // let(t1, carry) = mac(0, self0, rhs1, carry); + // let(t2, carry) = mac(0, self0, rhs2, carry); + // let(t3, carry) = mac(0, self0, rhs3, carry); + // let(t4, carry) = mac(0, self0, rhs4, carry); + // let(t5, t6) = mac(0, self0, rhs5, carry); + + // let(t1, carry) = mac(t1, self1, rhs0, 0); + // let(t2, carry) = mac(t2, self1, rhs1, carry); + // let(t3, carry) = mac(t3, self1, rhs2, carry); + // let(t4, carry) = mac(t4, self1, rhs3, carry); + // let(t5, carry) = mac(t5, self1, rhs4, carry); + // let(t6, t7) = mac(t6, self1, rhs5, carry); + + // let(t2, carry) = mac(t2, self2, rhs0, 0); + // let(t3, carry) = mac(t3, self2, rhs1, carry); + // let(t4, carry) = mac(t4, self2, rhs2, carry); + // let(t5, carry) = mac(t5, self2, rhs3, carry); + // let(t6, carry) = mac(t6, self2, rhs4, carry); + // let(t7, t8) = mac(t7, self2, rhs5, carry); + + // let(t3, carry) = mac(t3, self3, rhs0, 0); + // let(t4, carry) = mac(t4, self3, rhs1, carry); + // let(t5, carry) = mac(t5, self3, rhs2, carry); + // let(t6, carry) = mac(t6, self3, rhs3, carry); + // let(t7, carry) = mac(t7, self3, rhs4, carry); + // let(t8, t9) = mac(t8, self3, rhs5, carry); + + // let(t4, carry) = mac(t4, self4, rhs0, 0); + // let(t5, carry) = mac(t5, self4, rhs1, carry); + // let(t6, carry) = mac(t6, self4, rhs2, carry); + // let(t7, carry) = mac(t7, self4, rhs3, carry); + // let(t8, carry) = mac(t8, self4, rhs4, carry); + // let(t9, t10) = mac(t9, self4, rhs5, carry); + + // let(t5, carry) = mac(t5, self5, rhs0, 0); + // let(t6, carry) = mac(t6, self5, rhs1, carry); + // let(t7, carry) = mac(t7, self5, rhs2, carry); + // let(t8, carry) = mac(t8, self5, rhs3, carry); + // let(t9, carry) = mac(t9, self5, rhs4, carry); + // let(t10, t11) = mac(t10, self5, rhs5, carry); + + // let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + // montgomery_reduce(res) + // } - pub fn square(self) -> Fp { - let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); - let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); - let (t3, carry) = mac(0, self.ls[0], self.ls[3], carry); - let (t4, carry) = mac(0, self.ls[0], self.ls[4], carry); - let (t5, t6) = mac(0, self.ls[0], self.ls[5], carry); - - let (t3, carry) = mac(t3, self.ls[1], self.ls[2], 0); - let (t4, carry) = mac(t4, self.ls[1], self.ls[3], carry); - let (t5, carry) = mac(t5, self.ls[1], self.ls[4], carry); - let (t6, t7) = mac(t6, self.ls[1], self.ls[5], carry); - - let (t5, carry) = mac(t5, self.ls[2], self.ls[3], 0); - let (t6, carry) = mac(t6, self.ls[2], self.ls[4], carry); - let (t7, t8) = mac(t7, self.ls[2], self.ls[5], carry); - - let (t7, carry) = mac(t7, self.ls[3], self.ls[4], 0); - let (t8, t9) = mac(t8, self.ls[3], self.ls[5], carry); - - let (t9, t10) = mac(t9, self.ls[4], self.ls[5], 0); - - let t11 = t10 >> 63; - let t10 = (t10 << 1) | (t9 >> 63); - let t9 = (t9 << 1) | (t8 >> 63); - let t8 = (t8 << 1) | (t7 >> 63); - let t7 = (t7 << 1) | (t6 >> 63); - let t6 = (t6 << 1) | (t5 >> 63); - let t5 = (t5 << 1) | (t4 >> 63); - let t4 = (t4 << 1) | (t3 >> 63); - let t3 = (t3 << 1) | (t2 >> 63); - let t2 = (t2 << 1) | (t1 >> 63); - let t1 = t1 << 1; - - let (t0, carry) = mac(0, self.ls[0], self.ls[0], 0); - let (t1, carry) = adc(t1, 0, carry); - let (t2, carry) = mac(t2, self.ls[1], self.ls[1], carry); - let (t3, carry) = adc(t3, 0, carry); - let (t4, carry) = mac(t4, self.ls[2], self.ls[2], carry); - let (t5, carry) = adc(t5, 0, carry); - let (t6, carry) = mac(t6, self.ls[3], self.ls[3], carry); - let (t7, carry) = adc(t7, 0, carry); - let (t8, carry) = mac(t8, self.ls[4], self.ls[4], carry); - let (t9, carry) = adc(t9, 0, carry); - let (t10, carry) = mac(t10, self.ls[5], self.ls[5], carry); - let (t11, _) = adc(t11, 0, carry); - - let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; - montgomery_reduce(res) - } + // pub fn square(self) -> Fp { + // let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); + // let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); + // let (t3, carry) = mac(0, self.ls[0], self.ls[3], carry); + // let (t4, carry) = mac(0, self.ls[0], self.ls[4], carry); + // let (t5, t6) = mac(0, self.ls[0], self.ls[5], carry); + + // let (t3, carry) = mac(t3, self.ls[1], self.ls[2], 0); + // let (t4, carry) = mac(t4, self.ls[1], self.ls[3], carry); + // let (t5, carry) = mac(t5, self.ls[1], self.ls[4], carry); + // let (t6, t7) = mac(t6, self.ls[1], self.ls[5], carry); + + // let (t5, carry) = mac(t5, self.ls[2], self.ls[3], 0); + // let (t6, carry) = mac(t6, self.ls[2], self.ls[4], carry); + // let (t7, t8) = mac(t7, self.ls[2], self.ls[5], carry); + + // let (t7, carry) = mac(t7, self.ls[3], self.ls[4], 0); + // let (t8, t9) = mac(t8, self.ls[3], self.ls[5], carry); + + // let (t9, t10) = mac(t9, self.ls[4], self.ls[5], 0); + + // let t11 = t10 >> 63; + // let t10 = (t10 << 1) | (t9 >> 63); + // let t9 = (t9 << 1) | (t8 >> 63); + // let t8 = (t8 << 1) | (t7 >> 63); + // let t7 = (t7 << 1) | (t6 >> 63); + // let t6 = (t6 << 1) | (t5 >> 63); + // let t5 = (t5 << 1) | (t4 >> 63); + // let t4 = (t4 << 1) | (t3 >> 63); + // let t3 = (t3 << 1) | (t2 >> 63); + // let t2 = (t2 << 1) | (t1 >> 63); + // let t1 = t1 << 1; + + // let (t0, carry) = mac(0, self.ls[0], self.ls[0], 0); + // let (t1, carry) = adc(t1, 0, carry); + // let (t2, carry) = mac(t2, self.ls[1], self.ls[1], carry); + // let (t3, carry) = adc(t3, 0, carry); + // let (t4, carry) = mac(t4, self.ls[2], self.ls[2], carry); + // let (t5, carry) = adc(t5, 0, carry); + // let (t6, carry) = mac(t6, self.ls[3], self.ls[3], carry); + // let (t7, carry) = adc(t7, 0, carry); + // let (t8, carry) = mac(t8, self.ls[4], self.ls[4], carry); + // let (t9, carry) = adc(t9, 0, carry); + // let (t10, carry) = mac(t10, self.ls[5], self.ls[5], carry); + // let (t11, _) = adc(t11, 0, carry); + + // let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + // montgomery_reduce(res) + // } } impl Fp { @@ -383,54 +383,54 @@ impl Fp { // (Fp([u0, u1, u2, u3, u4, u5])).subtract_p() // } -// fold unpacked for the case that T = 2 - // pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { - // let u0 = 0; - // let u1 = 0; - // let u2 = 0; - // let u3 = 0; - // let u4 = 0; - // let u5 = 0; - // let mut j = 0; +//fold unpacked for the case that T = 2 + pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { + let u0 = 0; + let u1 = 0; + let u2 = 0; + let u3 = 0; + let u4 = 0; + let u5 = 0; + let mut j = 0; - // while j < 6 { - // let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); + while j < 6 { + let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); - // let mut i = 0; + let mut i = 0; - // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - // let (t6, _) = adc(t6, 0, carry); - - // i = 1; - // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - // let (t6, _) = adc(t6, 0, carry); - - // let k = multiply_wrap(t0, INV); - // let (_, carry) = mac(t0, k, MODULUS[0], 0); - // let (u1, carry) = mac(t1, k, MODULUS[1], carry); - // let (u2, carry) = mac(t2, k, MODULUS[2], carry); - // let (u3, carry) = mac(t3, k, MODULUS[3], carry); - // let (u4, carry) = mac(t4, k, MODULUS[4], carry); - // let (u5, carry) = mac(t5, k, MODULUS[5], carry); - // let (u6, _) = adc(t6, 0, carry); + let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + let (t6, _) = adc(t6, 0, carry); + + i = 1; + let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + let (t6, _) = adc(t6, 0, carry); + + let k = multiply_wrap(t0, INV); + let (_, carry) = mac(t0, k, MODULUS[0], 0); + let (u1, carry) = mac(t1, k, MODULUS[1], carry); + let (u2, carry) = mac(t2, k, MODULUS[2], carry); + let (u3, carry) = mac(t3, k, MODULUS[3], carry); + let (u4, carry) = mac(t4, k, MODULUS[4], carry); + let (u5, carry) = mac(t5, k, MODULUS[5], carry); + let (u6, _) = adc(t6, 0, carry); - // j += 1; - // } + j += 1; + } - // // Because we represent F_p elements in non-redundant form, we need a final - // // conditional subtraction to ensure the output is in range. - // (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() - // } + // Because we represent F_p elements in non-redundant form, we need a final + // conditional subtraction to ensure the output is in range. + (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() + } } pub fn montgomery_reduce(t: [u64;12]) -> Fp { diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index f83cd09..37e1a20 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -35,29 +35,29 @@ impl Fp2 { self.c0.eq(other.c0) && self.c1.eq(other.c1) } -//TODO test - pub fn square(self) -> Fp2 { - // Complex squaring: - // - // v0 = c0 * c1 - // c0' = (c0 + c1) * (c0 + \beta*c1) - v0 - \beta * v0 - // c1' = 2 * v0 - // - // In BLS12-381's F_{p^2}, our \beta is -1 so we - // can modify this formula: - // - // c0' = (c0 + c1) * (c0 - c1) - // c1' = 2 * c0 * c1 +// //TODO test +// pub fn square(self) -> Fp2 { +// // Complex squaring: +// // +// // v0 = c0 * c1 +// // c0' = (c0 + c1) * (c0 + \beta*c1) - v0 - \beta * v0 +// // c1' = 2 * v0 +// // +// // In BLS12-381's F_{p^2}, our \beta is -1 so we +// // can modify this formula: +// // +// // c0' = (c0 + c1) * (c0 - c1) +// // c1' = 2 * c0 * c1 - let a = (self.c0).add(self.c1); - let b = (self.c0).sub(self.c1); - let c = (self.c0).add(self.c0); +// let a = (self.c0).add(self.c1); +// let b = (self.c0).sub(self.c1); +// let c = (self.c0).add(self.c0); - Fp2 { - c0: (a).mul(b), - c1: (c).mul(self.c1), - } - } +// Fp2 { +// c0: (a).mul(b), +// c1: (c).mul(self.c1), +// } +// } pub fn mul(self, rhs: Fp2) -> Fp2 { // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) @@ -76,22 +76,55 @@ impl Fp2 { c0: ~Fp::sum_of_products_2([self.c0, self.c1.neg()], [rhs.c0, rhs.c1]), c1: ~Fp::sum_of_products_2([self.c0, self.c1], [rhs.c1, rhs.c0]), } + //-------------------------------------------- + // From zcash impl + // fn mul_assign(&mut self, other: &Self) { + // let mut aa = self.c0; + // aa.mul_assign(&other.c0); + // let mut bb = self.c1; + // bb.mul_assign(&other.c1); + // let mut o = other.c0; + // o.add_assign(&other.c1); + // self.c1.add_assign(&self.c0); + // self.c1.mul_assign(&o); + // self.c1.sub_assign(&aa); + // self.c1.sub_assign(&bb); + // self.c0 = aa; + // self.c0.sub_assign(&bb); + //------------------------------------ + // let mut aa = self.c0; + // let mut aa = aa.mul(rhs.c0); + // let mut bb = self.c1; + // let mut bb = bb.mul(rhs.c1); + // let mut o = rhs.c0; + // let mut o = o.add(rhs.c1); + // let mut c1 = self.c1.add(self.c0); + // let mut c1 = self.c1.mul(o); + // let mut c1 = self.c1.sub(aa); + // let mut c1 = self.c1.sub(bb); + // let mut c0 = aa; + // let mut c1 = self.c0.sub(bb); + + // Fp2{ + // c0: c0, + // c1: c1 + // } } -//TODO test + pub fn add(self, rhs: Fp2) -> Fp2 { Fp2 { c0: (self.c0).add(rhs.c0), c1: (self.c1).add(rhs.c1), } } -//TODO test + pub fn sub(self, rhs: Fp2) -> Fp2 { Fp2 { c0: (self.c0).sub(rhs.c0), c1: (self.c1).sub(rhs.c1), } } -//TODO test + pub fn neg(self) -> Fp2 { Fp2 { c0: (self.c0).neg(), diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 81552bc..75d4f70 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -5,11 +5,15 @@ use bls12_381::{fp::*, fp2::*}; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; - #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; - #[storage(read, write)]fn square_fp(a: Fp) -> Fp; + // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; + // #[storage(read, write)]fn square_fp(a: Fp) -> Fp; #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp; #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; + // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; + // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; + // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; + } @@ -22,13 +26,13 @@ impl BlsTestContract for Contract { a.sub(b) } - #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { - a.mul(b) - } + // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { + // a.mul(b) + // } - #[storage(read, write)]fn square_fp(a: Fp) -> Fp { - a.square() - } + // #[storage(read, write)]fn square_fp(a: Fp) -> Fp { + // a.square() + // } #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp { from_raw_unchecked(v) @@ -37,4 +41,16 @@ impl BlsTestContract for Contract { #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { a.mul(b) } + + // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { + // a.add(b) + // } + + // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 { + // a.sub(b) + // } + + // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2 { + // a.neg() + // } } \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index 31df4d8..307a6d9 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -122,14 +122,14 @@ async fn test_square_fp() { 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 }; - let a_again: Fp = Fp { - ls: [0xd215_d276_8e83_191b, - 0x5085_d80f_8fb2_8261,//5802281256283701857 - 0xce9a_032d_df39_3a56,//14887215013780077142 - 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 - 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 - 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 - }; + // let a_again: Fp = Fp { + // ls: [0xd215_d276_8e83_191b, + // 0x5085_d80f_8fb2_8261,//5802281256283701857 + // 0xce9a_032d_df39_3a56,//14887215013780077142 + // 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + // 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + // 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 + // }; let expected_res: Fp = Fp { ls: [0x33d9_c42a_3cb3_e235, diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index 44f4cc4..d1ecd02 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -22,6 +22,276 @@ async fn get_contract_instance() -> (BlsTestContract, ContractId) { } +pub fn res_equals(res: Fp, should_be: Fp) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} +// #[tokio::test] +// async fn test_add_fp2() { + +// let a = Fp2 { +// c_0: Fp{ls: [ +// 0xc9a2_1831_63ee_70d4, +// 0xbc37_70a7_196b_5c91, +// 0xa247_f8c1_304c_5f44, +// 0xb01f_c2a3_726c_80b5, +// 0xe1d2_93e5_bbd9_19c9, +// 0x04b7_8e80_020e_f2ca, +// ].to_vec()}, +// c_1: Fp{ls: [ +// 0x952e_a446_0462_618f, +// 0x238d_5edd_f025_c62f, +// 0xf6c9_4b01_2ea9_2e72, +// 0x03ce_24ea_c1c9_3808, +// 0x0559_50f9_45da_483c, +// 0x010a_768d_0df4_eabc, +// ].to_vec()}, +// }; +// let b = Fp2 { +// c_0: Fp{ls: [ +// 0xa1e0_9175_a4d2_c1fe, +// 0x8b33_acfc_204e_ff12, +// 0xe244_15a1_1b45_6e42, +// 0x61d9_96b1_b6ee_1936, +// 0x1164_dbe8_667c_853c, +// 0x0788_557a_cc7d_9c79, +// ].to_vec()}, +// c_1: Fp{ls: [ +// 0xda6a_87cc_6f48_fa36, +// 0x0fc7_b488_277c_1903, +// 0x9445_ac4a_dc44_8187, +// 0x0261_6d5b_c909_9209, +// 0xdbed_4677_2db5_8d48, +// 0x11b9_4d50_76c7_b7b1, +// ].to_vec()}, +// }; +// let c = Fp2 { +// c_0: Fp{ls: [ +// 0x6b82_a9a7_08c1_32d2, +// 0x476b_1da3_39ba_5ba4, +// 0x848c_0e62_4b91_cd87, +// 0x11f9_5955_295a_99ec, +// 0xf337_6fce_2255_9f06, +// 0x0c3f_e3fa_ce8c_8f43, +// ].to_vec()}, +// c_1: Fp{ls: [ +// 0x6f99_2c12_73ab_5bc5, +// 0x3355_1366_17a1_df33, +// 0x8b0e_f74c_0aed_aff9, +// 0x062f_9246_8ad2_ca12, +// 0xe146_9770_738f_d584, +// 0x12c3_c3dd_84bc_a26d, +// ].to_vec()}, +// }; + +// let (contract_instance, _id) = get_contract_instance().await; + +// let res = contract_instance.add_fp2(a, b) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; + +// assert!(res_equals(res.c_0, c.c_0)); +// assert!(res_equals(res.c_1, c.c_1)); +// } + +// #[tokio::test] +// async fn test_sub_fp2() { + +// let a = Fp2 { +// c_0: Fp{ ls: [ +// 0xc9a2_1831_63ee_70d4, +// 0xbc37_70a7_196b_5c91, +// 0xa247_f8c1_304c_5f44, +// 0xb01f_c2a3_726c_80b5, +// 0xe1d2_93e5_bbd9_19c9, +// 0x04b7_8e80_020e_f2ca, +// ].to_vec()}, +// c_1: Fp{ ls: [ +// 0x952e_a446_0462_618f, +// 0x238d_5edd_f025_c62f, +// 0xf6c9_4b01_2ea9_2e72, +// 0x03ce_24ea_c1c9_3808, +// 0x0559_50f9_45da_483c, +// 0x010a_768d_0df4_eabc, +// ].to_vec()}, +// }; +// let b = Fp2 { +// c_0: Fp{ ls: [ +// 0xa1e0_9175_a4d2_c1fe, +// 0x8b33_acfc_204e_ff12, +// 0xe244_15a1_1b45_6e42, +// 0x61d9_96b1_b6ee_1936, +// 0x1164_dbe8_667c_853c, +// 0x0788_557a_cc7d_9c79, +// ].to_vec()}, +// c_1: Fp{ ls: [ +// 0xda6a_87cc_6f48_fa36, +// 0x0fc7_b488_277c_1903, +// 0x9445_ac4a_dc44_8187, +// 0x0261_6d5b_c909_9209, +// 0xdbed_4677_2db5_8d48, +// 0x11b9_4d50_76c7_b7b1, +// ].to_vec()}, +// }; +// let c = Fp2 { +// c_0: Fp{ ls: [ +// 0xe1c0_86bb_bf1b_5981, +// 0x4faf_c3a9_aa70_5d7e, +// 0x2734_b5c1_0bb7_e726, +// 0xb2bd_7776_af03_7a3e, +// 0x1b89_5fb3_98a8_4164, +// 0x1730_4aef_6f11_3cec, +// ].to_vec()}, +// c_1: Fp{ ls: [ +// 0x74c3_1c79_9519_1204, +// 0x3271_aa54_79fd_ad2b, +// 0xc9b4_7157_4915_a30f, +// 0x65e4_0313_ec44_b8be, +// 0x7487_b238_5b70_67cb, +// 0x0952_3b26_d0ad_19a4, +// ].to_vec()}, +// }; + +// let (contract_instance, _id) = get_contract_instance().await; + +// let res = contract_instance.sub_fp2(a, b) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; + +// assert!(res_equals(res.c_0, c.c_0)); +// assert!(res_equals(res.c_1, c.c_1)); +// } + + +// #[tokio::test] +// async fn test_neg_fp2() { + +// let a = Fp2 { +// c_0: Fp{ls: [ +// 0xc9a2_1831_63ee_70d4, +// 0xbc37_70a7_196b_5c91, +// 0xa247_f8c1_304c_5f44, +// 0xb01f_c2a3_726c_80b5, +// 0xe1d2_93e5_bbd9_19c9, +// 0x04b7_8e80_020e_f2ca, +// ].to_vec()}, +// c_1: Fp{ls: [ +// 0x952e_a446_0462_618f, +// 0x238d_5edd_f025_c62f, +// 0xf6c9_4b01_2ea9_2e72, +// 0x03ce_24ea_c1c9_3808, +// 0x0559_50f9_45da_483c, +// 0x010a_768d_0df4_eabc, +// ].to_vec()}, +// }; +// let b = Fp2 { +// c_0: Fp{ls: [ +// 0xf05c_e7ce_9c11_39d7, +// 0x6274_8f57_97e8_a36d, +// 0xc4e8_d9df_c664_96df, +// 0xb457_88e1_8118_9209, +// 0x6949_13d0_8772_930d, +// 0x1549_836a_3770_f3cf, +// ].to_vec()}, +// c_1: Fp{ls: [ +// 0x24d0_5bb9_fb9d_491c, +// 0xfb1e_a120_c12e_39d0, +// 0x7067_879f_c807_c7b1, +// 0x60a9_269a_31bb_dab6, +// 0x45c2_56bc_fd71_649b, +// 0x18f6_9b5d_2b8a_fbde, +// ].to_vec()}, +// }; + + +// let (contract_instance, _id) = get_contract_instance().await; + +// let res = contract_instance.neg_fp2(a) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; + +// assert!(res_equals(res.c_0, b.c_0)); +// assert!(res_equals(res.c_1, b.c_1)); +// } +#[tokio::test] +async fn test_mul_fp2() { + + let a = Fp2 { + c_0: Fp{ls: [ + 0xc9a2_1831_63ee_70d4, + 0xbc37_70a7_196b_5c91, + 0xa247_f8c1_304c_5f44, + 0xb01f_c2a3_726c_80b5, + 0xe1d2_93e5_bbd9_19c9, + 0x04b7_8e80_020e_f2ca, + ].to_vec()}, + c_1: Fp{ls: [ + 0x952e_a446_0462_618f, + 0x238d_5edd_f025_c62f, + 0xf6c9_4b01_2ea9_2e72, + 0x03ce_24ea_c1c9_3808, + 0x0559_50f9_45da_483c, + 0x010a_768d_0df4_eabc, + ].to_vec()}, + }; + let b = Fp2 { + c_0: Fp{ls: [ + 0xa1e0_9175_a4d2_c1fe, + 0x8b33_acfc_204e_ff12, + 0xe244_15a1_1b45_6e42, + 0x61d9_96b1_b6ee_1936, + 0x1164_dbe8_667c_853c, + 0x0788_557a_cc7d_9c79, + ].to_vec()}, + c_1: Fp{ls: [ + 0xda6a_87cc_6f48_fa36, + 0x0fc7_b488_277c_1903, + 0x9445_ac4a_dc44_8187, + 0x0261_6d5b_c909_9209, + 0xdbed_4677_2db5_8d48, + 0x11b9_4d50_76c7_b7b1, + ].to_vec()}, + }; + let c = Fp2 { + c_0: Fp{ls: [ + 0xf597_483e_27b4_e0f7, + 0x610f_badf_811d_ae5f, + 0x8432_af91_7714_327a, + 0x6a9a_9603_cf88_f09e, + 0xf05a_7bf8_bad0_eb01, + 0x0954_9131_c003_ffae, + ].to_vec()}, + c_1: Fp{ls: [ + 0x963b_02d0_f93d_37cd, + 0xc95c_e1cd_b30a_73d4, + 0x3087_25fa_3126_f9b8, + 0x56da_3c16_7fab_0d50, + 0x6b50_86b5_f4b6_d6af, + 0x09c3_9f06_2f18_e9f2, + ].to_vec()}, + }; + + let (contract_instance, _id) = get_contract_instance().await; + + let res = contract_instance.mul_fp2(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + print!("{:?}",res); + assert!(res_equals(res.c_0, c.c_0)); + assert!(res_equals(res.c_1, c.c_1)); + + //output of res = Fp2 { c_0: Fp { ls: [0, 0, 0, 0, 0, 0] }, c_1: Fp { ls: [0, 0, 0, 0, 0, 0] } } +} + //Errors: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262256, span: Span { src (ptr): 0x600012cb7b50, path: None, start: 0, end: 0, as_str(): "" } }' // #[tokio::test] // fn test_multiplication() { From 29e33041338336385a5ac8bde8873165e06684e7 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 2 Aug 2022 14:54:29 -0600 Subject: [PATCH 124/160] - Fp and Fp2 are implementing various traits; these have been added - Using +, -, *, == instead of function names add sub mul eq wherever possible - Updated fuels to 0.19 - Uncommented functions and tests that work - Added comments why some functions or tests won't run --- bls12_381/src/fp.sw | 273 +++++++------ bls12_381/src/fp2.sw | 97 +++-- tests-bls/Cargo.toml | 2 +- tests-bls/tests/tests_temp_mul_mont_n/mod.rs | 80 +++- tests_bls12_381/src/main.sw | 41 +- tests_bls12_381/tests/tests_fp/mod.rs | 80 ++-- tests_bls12_381/tests/tests_fp2/mod.rs | 386 +++++++++---------- 7 files changed, 538 insertions(+), 421 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index f64af93..749bdd3 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -1,6 +1,7 @@ library fp; use std::{option::*, u128::*, vec::Vec}; +use core::ops::{Eq, Add, Subtract, Multiply}; // Little endian big integer with 6 limbs // in Montgomery form (!) @@ -49,6 +50,17 @@ const R3: Fp = Fp{ls: [ 0x0aa6_3460_9175_5d4d, ]}; +// type Choice doesn't seem to exist in Sway, so we use a bool +fn conditional_select(a: u64, b: u64, choice: bool) -> u64 { + // TODO make constant time impl + let mut mask = 0; + if (choice) { + mask = ~u64::max(); + } + + b ^ (mask & (a ^ b)) +} + fn not(input: u64) -> u64 { ~u64::max() - input } @@ -125,7 +137,7 @@ impl Fp { } // TODO to make this constant time the u64 should be compared with ct_eq, but is not existing in Sway (yet) - fn eq(self, other: Self) -> bool { + pub fn eq(self, other: Self) -> bool { (self.ls[0] == other.ls[0]) && (self.ls[1] == other.ls[1]) && (self.ls[2] == other.ls[2]) @@ -133,6 +145,18 @@ impl Fp { && (self.ls[4] == other.ls[4]) && (self.ls[5] == other.ls[5]) } + + // type Choice doesn't seem to exist in Sway, so we use a bool + fn conditional_select(a: Self, b: Self, choice: bool) -> Self { + Fp{ ls: [ + conditional_select(a.ls[0], b.ls[0], choice), + conditional_select(a.ls[1], b.ls[1], choice), + conditional_select(a.ls[2], b.ls[2], choice), + conditional_select(a.ls[3], b.ls[3], choice), + conditional_select(a.ls[4], b.ls[4], choice), + conditional_select(a.ls[5], b.ls[5], choice), + ]} + } pub fn neg(self) -> Fp { let(d0, borrow) = sbb(MODULUS[0], self.ls[0], 0); @@ -205,116 +229,116 @@ impl Fp { (Fp{ls:[d0, d1, d2, d3, d4, d5]}).subtract_p() } - // pub fn mul(self, rhs: Fp) -> Fp { - // let self0 = self.ls[0]; - // let self1 = self.ls[1]; - // let self2 = self.ls[2]; - // let self3 = self.ls[3]; - // let self4 = self.ls[4]; - // let self5 = self.ls[5]; - - // let rhs0 = rhs.ls[0]; - // let rhs1 = rhs.ls[1]; - // let rhs2 = rhs.ls[2]; - // let rhs3 = rhs.ls[3]; - // let rhs4 = rhs.ls[4]; - // let rhs5 = rhs.ls[5]; - - // let(t0, carry) = mac(0, self0, rhs0, 0); - // let(t1, carry) = mac(0, self0, rhs1, carry); - // let(t2, carry) = mac(0, self0, rhs2, carry); - // let(t3, carry) = mac(0, self0, rhs3, carry); - // let(t4, carry) = mac(0, self0, rhs4, carry); - // let(t5, t6) = mac(0, self0, rhs5, carry); - - // let(t1, carry) = mac(t1, self1, rhs0, 0); - // let(t2, carry) = mac(t2, self1, rhs1, carry); - // let(t3, carry) = mac(t3, self1, rhs2, carry); - // let(t4, carry) = mac(t4, self1, rhs3, carry); - // let(t5, carry) = mac(t5, self1, rhs4, carry); - // let(t6, t7) = mac(t6, self1, rhs5, carry); - - // let(t2, carry) = mac(t2, self2, rhs0, 0); - // let(t3, carry) = mac(t3, self2, rhs1, carry); - // let(t4, carry) = mac(t4, self2, rhs2, carry); - // let(t5, carry) = mac(t5, self2, rhs3, carry); - // let(t6, carry) = mac(t6, self2, rhs4, carry); - // let(t7, t8) = mac(t7, self2, rhs5, carry); - - // let(t3, carry) = mac(t3, self3, rhs0, 0); - // let(t4, carry) = mac(t4, self3, rhs1, carry); - // let(t5, carry) = mac(t5, self3, rhs2, carry); - // let(t6, carry) = mac(t6, self3, rhs3, carry); - // let(t7, carry) = mac(t7, self3, rhs4, carry); - // let(t8, t9) = mac(t8, self3, rhs5, carry); - - // let(t4, carry) = mac(t4, self4, rhs0, 0); - // let(t5, carry) = mac(t5, self4, rhs1, carry); - // let(t6, carry) = mac(t6, self4, rhs2, carry); - // let(t7, carry) = mac(t7, self4, rhs3, carry); - // let(t8, carry) = mac(t8, self4, rhs4, carry); - // let(t9, t10) = mac(t9, self4, rhs5, carry); - - // let(t5, carry) = mac(t5, self5, rhs0, 0); - // let(t6, carry) = mac(t6, self5, rhs1, carry); - // let(t7, carry) = mac(t7, self5, rhs2, carry); - // let(t8, carry) = mac(t8, self5, rhs3, carry); - // let(t9, carry) = mac(t9, self5, rhs4, carry); - // let(t10, t11) = mac(t10, self5, rhs5, carry); - - // let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; - // montgomery_reduce(res) - // } + pub fn mul(self, rhs: Fp) -> Fp { + let self0 = self.ls[0]; + let self1 = self.ls[1]; + let self2 = self.ls[2]; + let self3 = self.ls[3]; + let self4 = self.ls[4]; + let self5 = self.ls[5]; + + let rhs0 = rhs.ls[0]; + let rhs1 = rhs.ls[1]; + let rhs2 = rhs.ls[2]; + let rhs3 = rhs.ls[3]; + let rhs4 = rhs.ls[4]; + let rhs5 = rhs.ls[5]; + + let(t0, carry) = mac(0, self0, rhs0, 0); + let(t1, carry) = mac(0, self0, rhs1, carry); + let(t2, carry) = mac(0, self0, rhs2, carry); + let(t3, carry) = mac(0, self0, rhs3, carry); + let(t4, carry) = mac(0, self0, rhs4, carry); + let(t5, t6) = mac(0, self0, rhs5, carry); + + let(t1, carry) = mac(t1, self1, rhs0, 0); + let(t2, carry) = mac(t2, self1, rhs1, carry); + let(t3, carry) = mac(t3, self1, rhs2, carry); + let(t4, carry) = mac(t4, self1, rhs3, carry); + let(t5, carry) = mac(t5, self1, rhs4, carry); + let(t6, t7) = mac(t6, self1, rhs5, carry); + + let(t2, carry) = mac(t2, self2, rhs0, 0); + let(t3, carry) = mac(t3, self2, rhs1, carry); + let(t4, carry) = mac(t4, self2, rhs2, carry); + let(t5, carry) = mac(t5, self2, rhs3, carry); + let(t6, carry) = mac(t6, self2, rhs4, carry); + let(t7, t8) = mac(t7, self2, rhs5, carry); + + let(t3, carry) = mac(t3, self3, rhs0, 0); + let(t4, carry) = mac(t4, self3, rhs1, carry); + let(t5, carry) = mac(t5, self3, rhs2, carry); + let(t6, carry) = mac(t6, self3, rhs3, carry); + let(t7, carry) = mac(t7, self3, rhs4, carry); + let(t8, t9) = mac(t8, self3, rhs5, carry); + + let(t4, carry) = mac(t4, self4, rhs0, 0); + let(t5, carry) = mac(t5, self4, rhs1, carry); + let(t6, carry) = mac(t6, self4, rhs2, carry); + let(t7, carry) = mac(t7, self4, rhs3, carry); + let(t8, carry) = mac(t8, self4, rhs4, carry); + let(t9, t10) = mac(t9, self4, rhs5, carry); + + let(t5, carry) = mac(t5, self5, rhs0, 0); + let(t6, carry) = mac(t6, self5, rhs1, carry); + let(t7, carry) = mac(t7, self5, rhs2, carry); + let(t8, carry) = mac(t8, self5, rhs3, carry); + let(t9, carry) = mac(t9, self5, rhs4, carry); + let(t10, t11) = mac(t10, self5, rhs5, carry); + + let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + montgomery_reduce(res) + } - // pub fn square(self) -> Fp { - // let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); - // let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); - // let (t3, carry) = mac(0, self.ls[0], self.ls[3], carry); - // let (t4, carry) = mac(0, self.ls[0], self.ls[4], carry); - // let (t5, t6) = mac(0, self.ls[0], self.ls[5], carry); - - // let (t3, carry) = mac(t3, self.ls[1], self.ls[2], 0); - // let (t4, carry) = mac(t4, self.ls[1], self.ls[3], carry); - // let (t5, carry) = mac(t5, self.ls[1], self.ls[4], carry); - // let (t6, t7) = mac(t6, self.ls[1], self.ls[5], carry); - - // let (t5, carry) = mac(t5, self.ls[2], self.ls[3], 0); - // let (t6, carry) = mac(t6, self.ls[2], self.ls[4], carry); - // let (t7, t8) = mac(t7, self.ls[2], self.ls[5], carry); - - // let (t7, carry) = mac(t7, self.ls[3], self.ls[4], 0); - // let (t8, t9) = mac(t8, self.ls[3], self.ls[5], carry); - - // let (t9, t10) = mac(t9, self.ls[4], self.ls[5], 0); - - // let t11 = t10 >> 63; - // let t10 = (t10 << 1) | (t9 >> 63); - // let t9 = (t9 << 1) | (t8 >> 63); - // let t8 = (t8 << 1) | (t7 >> 63); - // let t7 = (t7 << 1) | (t6 >> 63); - // let t6 = (t6 << 1) | (t5 >> 63); - // let t5 = (t5 << 1) | (t4 >> 63); - // let t4 = (t4 << 1) | (t3 >> 63); - // let t3 = (t3 << 1) | (t2 >> 63); - // let t2 = (t2 << 1) | (t1 >> 63); - // let t1 = t1 << 1; - - // let (t0, carry) = mac(0, self.ls[0], self.ls[0], 0); - // let (t1, carry) = adc(t1, 0, carry); - // let (t2, carry) = mac(t2, self.ls[1], self.ls[1], carry); - // let (t3, carry) = adc(t3, 0, carry); - // let (t4, carry) = mac(t4, self.ls[2], self.ls[2], carry); - // let (t5, carry) = adc(t5, 0, carry); - // let (t6, carry) = mac(t6, self.ls[3], self.ls[3], carry); - // let (t7, carry) = adc(t7, 0, carry); - // let (t8, carry) = mac(t8, self.ls[4], self.ls[4], carry); - // let (t9, carry) = adc(t9, 0, carry); - // let (t10, carry) = mac(t10, self.ls[5], self.ls[5], carry); - // let (t11, _) = adc(t11, 0, carry); - - // let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; - // montgomery_reduce(res) - // } + pub fn square(self) -> Fp { + let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); + let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); + let (t3, carry) = mac(0, self.ls[0], self.ls[3], carry); + let (t4, carry) = mac(0, self.ls[0], self.ls[4], carry); + let (t5, t6) = mac(0, self.ls[0], self.ls[5], carry); + + let (t3, carry) = mac(t3, self.ls[1], self.ls[2], 0); + let (t4, carry) = mac(t4, self.ls[1], self.ls[3], carry); + let (t5, carry) = mac(t5, self.ls[1], self.ls[4], carry); + let (t6, t7) = mac(t6, self.ls[1], self.ls[5], carry); + + let (t5, carry) = mac(t5, self.ls[2], self.ls[3], 0); + let (t6, carry) = mac(t6, self.ls[2], self.ls[4], carry); + let (t7, t8) = mac(t7, self.ls[2], self.ls[5], carry); + + let (t7, carry) = mac(t7, self.ls[3], self.ls[4], 0); + let (t8, t9) = mac(t8, self.ls[3], self.ls[5], carry); + + let (t9, t10) = mac(t9, self.ls[4], self.ls[5], 0); + + let t11 = t10 >> 63; + let t10 = (t10 << 1) | (t9 >> 63); + let t9 = (t9 << 1) | (t8 >> 63); + let t8 = (t8 << 1) | (t7 >> 63); + let t7 = (t7 << 1) | (t6 >> 63); + let t6 = (t6 << 1) | (t5 >> 63); + let t5 = (t5 << 1) | (t4 >> 63); + let t4 = (t4 << 1) | (t3 >> 63); + let t3 = (t3 << 1) | (t2 >> 63); + let t2 = (t2 << 1) | (t1 >> 63); + let t1 = t1 << 1; + + let (t0, carry) = mac(0, self.ls[0], self.ls[0], 0); + let (t1, carry) = adc(t1, 0, carry); + let (t2, carry) = mac(t2, self.ls[1], self.ls[1], carry); + let (t3, carry) = adc(t3, 0, carry); + let (t4, carry) = mac(t4, self.ls[2], self.ls[2], carry); + let (t5, carry) = adc(t5, 0, carry); + let (t6, carry) = mac(t6, self.ls[3], self.ls[3], carry); + let (t7, carry) = adc(t7, 0, carry); + let (t8, carry) = mac(t8, self.ls[4], self.ls[4], carry); + let (t9, carry) = adc(t9, 0, carry); + let (t10, carry) = mac(t10, self.ls[5], self.ls[5], carry); + let (t11, _) = adc(t11, 0, carry); + + let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; + montgomery_reduce(res) + } } impl Fp { @@ -322,7 +346,9 @@ impl Fp { (rhs.neg()).add(self) } -//TODO implement this one for T=6. Also, T=2 has to be tested still +//TODO implement this one for T=6 when sum_of_products_2 is working correctly. +// (sum_of_products_2 can be tested through testing fp2 multiplication, but this is not running atm because of Immediate18TooLarge) + /// Returns `c = a.zip(b).fold(0, |acc, (a_i, b_i)| acc + a_i * b_i)`. /// /// Implements Algorithm 2 from Patrick Longa's @@ -383,6 +409,7 @@ impl Fp { // (Fp([u0, u1, u2, u3, u4, u5])).subtract_p() // } +// This will be tested when fp2 multiplication is tested. This is not working atm because of Immediate18TooLarge error //fold unpacked for the case that T = 2 pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { let u0 = 0; @@ -433,6 +460,30 @@ impl Fp { } } +impl Eq for Fp { + fn eq(self, other: Self) -> bool { + self.eq(other) + } +} + +impl Add for Fp { + fn add(self, other: Self) -> Self { + self.add(other) + } +} + +impl Subtract for Fp { + fn subtract(self, other: Self) -> Self { + self.sub(other) + } +} + +impl Multiply for Fp { + fn multiply(self, other: Self) -> Self { + self.mul(other) + } +} + pub fn montgomery_reduce(t: [u64;12]) -> Fp { let k = multiply_wrap(t[0], INV); diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index 37e1a20..9b7a3e2 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -2,10 +2,11 @@ library fp2; dep fp; use fp::*; +use core::ops::{Eq, Add, Subtract, Multiply}; pub struct Fp2 { - c0: Fp, //"real" part - c1: Fp, //"imaginary" part + c0: Fp, + c1: Fp, } impl Fp2 { @@ -30,34 +31,33 @@ impl Fp2 { } } - fn eq(self, other: Self) -> bool { - self.c0.eq(other.c0) && self.c1.eq(other.c1) + self.c0 == other.c0 && self.c1 == other.c1 } // //TODO test -// pub fn square(self) -> Fp2 { -// // Complex squaring: -// // -// // v0 = c0 * c1 -// // c0' = (c0 + c1) * (c0 + \beta*c1) - v0 - \beta * v0 -// // c1' = 2 * v0 -// // -// // In BLS12-381's F_{p^2}, our \beta is -1 so we -// // can modify this formula: -// // -// // c0' = (c0 + c1) * (c0 - c1) -// // c1' = 2 * c0 * c1 - -// let a = (self.c0).add(self.c1); -// let b = (self.c0).sub(self.c1); -// let c = (self.c0).add(self.c0); - -// Fp2 { -// c0: (a).mul(b), -// c1: (c).mul(self.c1), -// } -// } + pub fn square(self) -> Fp2 { + // Complex squaring: + // + // v0 = c0 * c1 + // c0' = (c0 + c1) * (c0 + \beta*c1) - v0 - \beta * v0 + // c1' = 2 * v0 + // + // In BLS12-381's F_{p^2}, our \beta is -1 so we + // can modify this formula: + // + // c0' = (c0 + c1) * (c0 - c1) + // c1' = 2 * c0 * c1 + + let a = self.c0 + self.c1; + let b = self.c0 - self.c1; + let c = self.c0 + self.c0; + + Fp2 { + c0: a * b, + c1: c * self.c1, + } + } pub fn mul(self, rhs: Fp2) -> Fp2 { // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) @@ -113,15 +113,15 @@ impl Fp2 { pub fn add(self, rhs: Fp2) -> Fp2 { Fp2 { - c0: (self.c0).add(rhs.c0), - c1: (self.c1).add(rhs.c1), + c0: self.c0 + rhs.c0, + c1: self.c1 + rhs.c1, } } pub fn sub(self, rhs: Fp2) -> Fp2 { Fp2 { - c0: (self.c0).sub(rhs.c0), - c1: (self.c1).sub(rhs.c1), + c0: self.c0 - rhs.c0, + c1: self.c1 - rhs.c1, } } @@ -132,4 +132,41 @@ impl Fp2 { } } + // Is not tested directly, but will be indirectly + pub fn mul_by_nonresidue(self) -> Fp2 { + // Multiply a + bu by u + 1, getting + // au + a + bu^2 + bu + // and because u^2 = -1, we get + // (a - b) + (a + b)u + + Fp2 { + c0: self.c0 - self.c1, + c1: self.c0 + self.c1, + } + } + +} + +impl Eq for Fp2 { + fn eq(self, other: Self) -> bool { + self.eq(other) + } +} + +impl Add for Fp2 { + fn add(self, other: Self) -> Self { + self.add(other) + } +} + +impl Subtract for Fp2 { + fn subtract(self, other: Self) -> Self { + self.sub(other) + } +} + +impl Multiply for Fp2 { + fn multiply(self, other: Self) -> Self { + self.mul(other) + } } \ No newline at end of file diff --git a/tests-bls/Cargo.toml b/tests-bls/Cargo.toml index c942e4a..1ea4990 100644 --- a/tests-bls/Cargo.toml +++ b/tests-bls/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "Apache-2.0" [dependencies] -fuels = "0.18" +fuels = "0.19" fuels-abigen-macro = "0.16.1" tokio = { version = "1.12", features = ["rt", "macros"] } diff --git a/tests-bls/tests/tests_temp_mul_mont_n/mod.rs b/tests-bls/tests/tests_temp_mul_mont_n/mod.rs index 196a43f..46df062 100644 --- a/tests-bls/tests/tests_temp_mul_mont_n/mod.rs +++ b/tests-bls/tests/tests_temp_mul_mont_n/mod.rs @@ -1,13 +1,44 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; +use fuels::{ + prelude::*, + tx::{ConsensusParameters, ContractId}, +}; abigen!(BlsContract, "out/debug/tests-bls-abi.json"); -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(100_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); +async fn get_contract_instance() -> (BlsContract, Bech32ContractId) { + // Create the wallet. + let mut wallet = LocalWallet::new_random(None); + let num_assets = 1; + let coins_per_asset = 100; + let amount_per_coin = 100000; + + let (coins, asset_ids) = setup_multiple_assets_coins( + wallet.address(), + num_assets, + coins_per_asset, + amount_per_coin, + ); + + // configure the gas limit + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(10_000_000_000_000); + + // Here's the important part. This will be running a `fuel-core` that will live through this test. + // The configured coins are the same as before, I'm just passing them to it. + let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; + + // Important. Make sure the random wallet you created above uses this provider you created just now. + let provider = Provider::new(client); + wallet.set_provider(provider.clone()); + + let id = Contract::deploy( + "./out/debug/tests-bls.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::default(), // <--- new stuff from 0.18 + ) + .await + .unwrap(); + let instance = BlsContractBuilder::new(id.to_string(), wallet).build(); // <-- notice the `.build()` coming from `0.18` here (instance, id) } @@ -21,19 +52,30 @@ pub fn res_equals(res: vec384, should_be: vec384) -> bool { true } -// Gives error OutOfGas. We need to run locally in order to increase the gas limit +//runs with gas limit 10_000_000_000_000 +// I would think this does a "normal" mult... but it doesnt. However, our zkcrypto functions are being tested against +// zkcrypto tests so thats OK. With this test at least we know how to increase the gas limit. And that a very high limit is probably needed. #[tokio::test] async fn test_temp_mul_random_by_random() { +// 15893342109957185315274996980159955840696869464618597139081654135225976620298280402004730099734930472282685911264653 +// [7601317525063134605, 14737835108041207235, 7856501253924799053, 9728524752340033442, 8018744563895365642, 7440748395322036726] + + //let p_vec: [u64;6] = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a]; let r1_vec = vec384 { - ls: [6071868568151433008, 12105094901188801210, 2389211775905699303, 7838417195104481535, 5826366508043997497, 13436617433956842131].to_vec() + ls: [7601317525063134605, 14737835108041207235, 7856501253924799053, 9728524752340033442, 8018744563895365642, 7440748395322036726].to_vec() }; + +// 6426056301875987760035045131419826427959545715777668602170085103660258490882518289245959835486066380634045485171465 +// [2100109755352105737, 8370746840931066636, 11596494770511871063, 3039720716978434317, 16449625404618362957, 3008471584241360315] let r2_vec = vec384{ - ls: [16964885827015180015, 12035734743809705289, 10517060043363161601, 1119606639881808286, 2211903887497377980, 395875676649998273].to_vec() + ls: [2100109755352105737, 8370746840931066636, 11596494770511871063, 3039720716978434317, 16449625404618362957, 3008471584241360315].to_vec() }; + //662295453570983325530111016671619871152537908715293912221215151084869461019373230933077596861385628632414151952313 + //[8398368441850316729, 11909455072033861112, 10407834670867800778, 5873847235982413757, 1304857104357117827, 310065296480341730] let expected_res = vec384 { - ls: [16494539950903960225, 6909894500484332639, 10854278113294925999, 10279541547892741855, 12499445441687670930, 440910865060157199].to_vec() + ls: [8398368441850316729, 11909455072033861112, 10407834670867800778, 5873847235982413757, 1304857104357117827, 310065296480341730].to_vec() }; let (_instance, _id) = get_contract_instance().await; @@ -41,5 +83,19 @@ async fn test_temp_mul_random_by_random() { .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); + println!("{}", res.ls[0]); + println!("{}", res.ls[1]); + println!("{}", res.ls[2]); + println!("{}", res.ls[2]); + println!("{}", res.ls[4]); + println!("{}", res.ls[5]); + /*-> different outcome +9333873115146394089 +4782551559207793765 +10050393911427975672 +10050393911427975672 +1218813032832674028 +1486933856237831752 + */ + // assert!(res_equals(res, expected_res)); } \ No newline at end of file diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 75d4f70..1e77aba 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -9,25 +9,26 @@ abi BlsTestContract { // #[storage(read, write)]fn square_fp(a: Fp) -> Fp; #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp; - #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; - // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; - // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; - // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; + // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; + // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; + #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; + #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; + #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; } impl BlsTestContract for Contract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp { - a.add(b) + a + b } #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { - a.sub(b) + a - b } // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { - // a.mul(b) + // a * b // } // #[storage(read, write)]fn square_fp(a: Fp) -> Fp { @@ -38,19 +39,23 @@ impl BlsTestContract for Contract { from_raw_unchecked(v) } - #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { - a.mul(b) - } - - // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { - // a.add(b) + // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { + // a.square() // } - // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 { - // a.sub(b) + // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { + // a * b // } - // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2 { - // a.neg() - // } + #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { + a + b + } + + #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 { + a - b + } + + #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2 { + a.neg() + } } \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index 307a6d9..9133b33 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -111,48 +111,42 @@ async fn test_sub_fp() { // assert!(res_equals(res, c)); // } -#[tokio::test] -async fn test_square_fp() { - let a: Fp = Fp { - ls: [0xd215_d276_8e83_191b,//15138237129114720539 - 0x5085_d80f_8fb2_8261,//5802281256283701857 - 0xce9a_032d_df39_3a56,//14887215013780077142 - 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 - 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 - 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 - }; - - // let a_again: Fp = Fp { - // ls: [0xd215_d276_8e83_191b, - // 0x5085_d80f_8fb2_8261,//5802281256283701857 - // 0xce9a_032d_df39_3a56,//14887215013780077142 - // 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 - // 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 - // 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 - // }; - - let expected_res: Fp = Fp { - ls: [0x33d9_c42a_3cb3_e235, - 0xdad1_1a09_4c4c_d455, - 0xa2f1_44bd_729a_aeba, - 0xd415_0932_be9f_feac, - 0xe27b_c7c4_7d44_ee50, - 0x14b6_a78d_3ec7_a560].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.square_fp(a) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - //fails :( - assert!(res_equals(res, expected_res)); +// // WORKS, but smart to comment out when wanting to test other things +// #[tokio::test] +// async fn test_square_fp() { +// let a: Fp = Fp { +// ls: [0xd215_d276_8e83_191b,//15138237129114720539 +// 0x5085_d80f_8fb2_8261,//5802281256283701857 +// 0xce9a_032d_df39_3a56,//14887215013780077142 +// 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 +// 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 +// 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 +// }; + +// // let a_again: Fp = Fp { +// // ls: [0xd215_d276_8e83_191b, +// // 0x5085_d80f_8fb2_8261,//5802281256283701857 +// // 0xce9a_032d_df39_3a56,//14887215013780077142 +// // 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 +// // 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 +// // 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 +// // }; + +// let expected_res: Fp = Fp { +// ls: [0x33d9_c42a_3cb3_e235, +// 0xdad1_1a09_4c4c_d455, +// 0xa2f1_44bd_729a_aeba, +// 0xd415_0932_be9f_feac, +// 0xe27b_c7c4_7d44_ee50, +// 0x14b6_a78d_3ec7_a560].to_vec() +// }; - // print res of square - //[1902911976314425853, 13352981833795642672, 10289086307533160637, 13100812750071813769, 2610533423338883854, 1302806150312138448] - // print of mult - //[3736233051566629429, 15767412397637948501, 11741241283993841338, - // 15282131024102817452, 16319857321436311120, 1492564551605396832] +// let (_instance, _id) = get_contract_instance().await; -} +// let res = _instance.square_fp(a) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// //fails :( +// assert!(res_equals(res, expected_res)); +// } diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index d1ecd02..12d0e43 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -31,198 +31,9 @@ pub fn res_equals(res: Fp, should_be: Fp) -> bool { assert!(res.ls[5] == should_be.ls[5]); true } -// #[tokio::test] -// async fn test_add_fp2() { - -// let a = Fp2 { -// c_0: Fp{ls: [ -// 0xc9a2_1831_63ee_70d4, -// 0xbc37_70a7_196b_5c91, -// 0xa247_f8c1_304c_5f44, -// 0xb01f_c2a3_726c_80b5, -// 0xe1d2_93e5_bbd9_19c9, -// 0x04b7_8e80_020e_f2ca, -// ].to_vec()}, -// c_1: Fp{ls: [ -// 0x952e_a446_0462_618f, -// 0x238d_5edd_f025_c62f, -// 0xf6c9_4b01_2ea9_2e72, -// 0x03ce_24ea_c1c9_3808, -// 0x0559_50f9_45da_483c, -// 0x010a_768d_0df4_eabc, -// ].to_vec()}, -// }; -// let b = Fp2 { -// c_0: Fp{ls: [ -// 0xa1e0_9175_a4d2_c1fe, -// 0x8b33_acfc_204e_ff12, -// 0xe244_15a1_1b45_6e42, -// 0x61d9_96b1_b6ee_1936, -// 0x1164_dbe8_667c_853c, -// 0x0788_557a_cc7d_9c79, -// ].to_vec()}, -// c_1: Fp{ls: [ -// 0xda6a_87cc_6f48_fa36, -// 0x0fc7_b488_277c_1903, -// 0x9445_ac4a_dc44_8187, -// 0x0261_6d5b_c909_9209, -// 0xdbed_4677_2db5_8d48, -// 0x11b9_4d50_76c7_b7b1, -// ].to_vec()}, -// }; -// let c = Fp2 { -// c_0: Fp{ls: [ -// 0x6b82_a9a7_08c1_32d2, -// 0x476b_1da3_39ba_5ba4, -// 0x848c_0e62_4b91_cd87, -// 0x11f9_5955_295a_99ec, -// 0xf337_6fce_2255_9f06, -// 0x0c3f_e3fa_ce8c_8f43, -// ].to_vec()}, -// c_1: Fp{ls: [ -// 0x6f99_2c12_73ab_5bc5, -// 0x3355_1366_17a1_df33, -// 0x8b0e_f74c_0aed_aff9, -// 0x062f_9246_8ad2_ca12, -// 0xe146_9770_738f_d584, -// 0x12c3_c3dd_84bc_a26d, -// ].to_vec()}, -// }; - -// let (contract_instance, _id) = get_contract_instance().await; - -// let res = contract_instance.add_fp2(a, b) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; - -// assert!(res_equals(res.c_0, c.c_0)); -// assert!(res_equals(res.c_1, c.c_1)); -// } - -// #[tokio::test] -// async fn test_sub_fp2() { -// let a = Fp2 { -// c_0: Fp{ ls: [ -// 0xc9a2_1831_63ee_70d4, -// 0xbc37_70a7_196b_5c91, -// 0xa247_f8c1_304c_5f44, -// 0xb01f_c2a3_726c_80b5, -// 0xe1d2_93e5_bbd9_19c9, -// 0x04b7_8e80_020e_f2ca, -// ].to_vec()}, -// c_1: Fp{ ls: [ -// 0x952e_a446_0462_618f, -// 0x238d_5edd_f025_c62f, -// 0xf6c9_4b01_2ea9_2e72, -// 0x03ce_24ea_c1c9_3808, -// 0x0559_50f9_45da_483c, -// 0x010a_768d_0df4_eabc, -// ].to_vec()}, -// }; -// let b = Fp2 { -// c_0: Fp{ ls: [ -// 0xa1e0_9175_a4d2_c1fe, -// 0x8b33_acfc_204e_ff12, -// 0xe244_15a1_1b45_6e42, -// 0x61d9_96b1_b6ee_1936, -// 0x1164_dbe8_667c_853c, -// 0x0788_557a_cc7d_9c79, -// ].to_vec()}, -// c_1: Fp{ ls: [ -// 0xda6a_87cc_6f48_fa36, -// 0x0fc7_b488_277c_1903, -// 0x9445_ac4a_dc44_8187, -// 0x0261_6d5b_c909_9209, -// 0xdbed_4677_2db5_8d48, -// 0x11b9_4d50_76c7_b7b1, -// ].to_vec()}, -// }; -// let c = Fp2 { -// c_0: Fp{ ls: [ -// 0xe1c0_86bb_bf1b_5981, -// 0x4faf_c3a9_aa70_5d7e, -// 0x2734_b5c1_0bb7_e726, -// 0xb2bd_7776_af03_7a3e, -// 0x1b89_5fb3_98a8_4164, -// 0x1730_4aef_6f11_3cec, -// ].to_vec()}, -// c_1: Fp{ ls: [ -// 0x74c3_1c79_9519_1204, -// 0x3271_aa54_79fd_ad2b, -// 0xc9b4_7157_4915_a30f, -// 0x65e4_0313_ec44_b8be, -// 0x7487_b238_5b70_67cb, -// 0x0952_3b26_d0ad_19a4, -// ].to_vec()}, -// }; - -// let (contract_instance, _id) = get_contract_instance().await; - -// let res = contract_instance.sub_fp2(a, b) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; - -// assert!(res_equals(res.c_0, c.c_0)); -// assert!(res_equals(res.c_1, c.c_1)); -// } - - -// #[tokio::test] -// async fn test_neg_fp2() { - -// let a = Fp2 { -// c_0: Fp{ls: [ -// 0xc9a2_1831_63ee_70d4, -// 0xbc37_70a7_196b_5c91, -// 0xa247_f8c1_304c_5f44, -// 0xb01f_c2a3_726c_80b5, -// 0xe1d2_93e5_bbd9_19c9, -// 0x04b7_8e80_020e_f2ca, -// ].to_vec()}, -// c_1: Fp{ls: [ -// 0x952e_a446_0462_618f, -// 0x238d_5edd_f025_c62f, -// 0xf6c9_4b01_2ea9_2e72, -// 0x03ce_24ea_c1c9_3808, -// 0x0559_50f9_45da_483c, -// 0x010a_768d_0df4_eabc, -// ].to_vec()}, -// }; -// let b = Fp2 { -// c_0: Fp{ls: [ -// 0xf05c_e7ce_9c11_39d7, -// 0x6274_8f57_97e8_a36d, -// 0xc4e8_d9df_c664_96df, -// 0xb457_88e1_8118_9209, -// 0x6949_13d0_8772_930d, -// 0x1549_836a_3770_f3cf, -// ].to_vec()}, -// c_1: Fp{ls: [ -// 0x24d0_5bb9_fb9d_491c, -// 0xfb1e_a120_c12e_39d0, -// 0x7067_879f_c807_c7b1, -// 0x60a9_269a_31bb_dab6, -// 0x45c2_56bc_fd71_649b, -// 0x18f6_9b5d_2b8a_fbde, -// ].to_vec()}, -// }; - - -// let (contract_instance, _id) = get_contract_instance().await; - -// let res = contract_instance.neg_fp2(a) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; - -// assert!(res_equals(res.c_0, b.c_0)); -// assert!(res_equals(res.c_1, b.c_1)); -// } #[tokio::test] -async fn test_mul_fp2() { +async fn test_add_fp2() { let a = Fp2 { c_0: Fp{ls: [ @@ -262,37 +73,157 @@ async fn test_mul_fp2() { }; let c = Fp2 { c_0: Fp{ls: [ - 0xf597_483e_27b4_e0f7, - 0x610f_badf_811d_ae5f, - 0x8432_af91_7714_327a, - 0x6a9a_9603_cf88_f09e, - 0xf05a_7bf8_bad0_eb01, - 0x0954_9131_c003_ffae, + 0x6b82_a9a7_08c1_32d2, + 0x476b_1da3_39ba_5ba4, + 0x848c_0e62_4b91_cd87, + 0x11f9_5955_295a_99ec, + 0xf337_6fce_2255_9f06, + 0x0c3f_e3fa_ce8c_8f43, ].to_vec()}, c_1: Fp{ls: [ - 0x963b_02d0_f93d_37cd, - 0xc95c_e1cd_b30a_73d4, - 0x3087_25fa_3126_f9b8, - 0x56da_3c16_7fab_0d50, - 0x6b50_86b5_f4b6_d6af, - 0x09c3_9f06_2f18_e9f2, + 0x6f99_2c12_73ab_5bc5, + 0x3355_1366_17a1_df33, + 0x8b0e_f74c_0aed_aff9, + 0x062f_9246_8ad2_ca12, + 0xe146_9770_738f_d584, + 0x12c3_c3dd_84bc_a26d, + ].to_vec()}, + }; + + let (contract_instance, _id) = get_contract_instance().await; + + let res = contract_instance.add_fp2(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res.c_0, c.c_0)); + assert!(res_equals(res.c_1, c.c_1)); +} + +#[tokio::test] +async fn test_sub_fp2() { + + let a = Fp2 { + c_0: Fp{ ls: [ + 0xc9a2_1831_63ee_70d4, + 0xbc37_70a7_196b_5c91, + 0xa247_f8c1_304c_5f44, + 0xb01f_c2a3_726c_80b5, + 0xe1d2_93e5_bbd9_19c9, + 0x04b7_8e80_020e_f2ca, + ].to_vec()}, + c_1: Fp{ ls: [ + 0x952e_a446_0462_618f, + 0x238d_5edd_f025_c62f, + 0xf6c9_4b01_2ea9_2e72, + 0x03ce_24ea_c1c9_3808, + 0x0559_50f9_45da_483c, + 0x010a_768d_0df4_eabc, + ].to_vec()}, + }; + let b = Fp2 { + c_0: Fp{ ls: [ + 0xa1e0_9175_a4d2_c1fe, + 0x8b33_acfc_204e_ff12, + 0xe244_15a1_1b45_6e42, + 0x61d9_96b1_b6ee_1936, + 0x1164_dbe8_667c_853c, + 0x0788_557a_cc7d_9c79, + ].to_vec()}, + c_1: Fp{ ls: [ + 0xda6a_87cc_6f48_fa36, + 0x0fc7_b488_277c_1903, + 0x9445_ac4a_dc44_8187, + 0x0261_6d5b_c909_9209, + 0xdbed_4677_2db5_8d48, + 0x11b9_4d50_76c7_b7b1, + ].to_vec()}, + }; + let c = Fp2 { + c_0: Fp{ ls: [ + 0xe1c0_86bb_bf1b_5981, + 0x4faf_c3a9_aa70_5d7e, + 0x2734_b5c1_0bb7_e726, + 0xb2bd_7776_af03_7a3e, + 0x1b89_5fb3_98a8_4164, + 0x1730_4aef_6f11_3cec, + ].to_vec()}, + c_1: Fp{ ls: [ + 0x74c3_1c79_9519_1204, + 0x3271_aa54_79fd_ad2b, + 0xc9b4_7157_4915_a30f, + 0x65e4_0313_ec44_b8be, + 0x7487_b238_5b70_67cb, + 0x0952_3b26_d0ad_19a4, ].to_vec()}, }; let (contract_instance, _id) = get_contract_instance().await; - let res = contract_instance.mul_fp2(a, b) + let res = contract_instance.sub_fp2(a, b) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - print!("{:?}",res); + assert!(res_equals(res.c_0, c.c_0)); assert!(res_equals(res.c_1, c.c_1)); +} - //output of res = Fp2 { c_0: Fp { ls: [0, 0, 0, 0, 0, 0] }, c_1: Fp { ls: [0, 0, 0, 0, 0, 0] } } + +#[tokio::test] +async fn test_neg_fp2() { + + let a = Fp2 { + c_0: Fp{ls: [ + 0xc9a2_1831_63ee_70d4, + 0xbc37_70a7_196b_5c91, + 0xa247_f8c1_304c_5f44, + 0xb01f_c2a3_726c_80b5, + 0xe1d2_93e5_bbd9_19c9, + 0x04b7_8e80_020e_f2ca, + ].to_vec()}, + c_1: Fp{ls: [ + 0x952e_a446_0462_618f, + 0x238d_5edd_f025_c62f, + 0xf6c9_4b01_2ea9_2e72, + 0x03ce_24ea_c1c9_3808, + 0x0559_50f9_45da_483c, + 0x010a_768d_0df4_eabc, + ].to_vec()}, + }; + let b = Fp2 { + c_0: Fp{ls: [ + 0xf05c_e7ce_9c11_39d7, + 0x6274_8f57_97e8_a36d, + 0xc4e8_d9df_c664_96df, + 0xb457_88e1_8118_9209, + 0x6949_13d0_8772_930d, + 0x1549_836a_3770_f3cf, + ].to_vec()}, + c_1: Fp{ls: [ + 0x24d0_5bb9_fb9d_491c, + 0xfb1e_a120_c12e_39d0, + 0x7067_879f_c807_c7b1, + 0x60a9_269a_31bb_dab6, + 0x45c2_56bc_fd71_649b, + 0x18f6_9b5d_2b8a_fbde, + ].to_vec()}, + }; + + + let (contract_instance, _id) = get_contract_instance().await; + + let res = contract_instance.neg_fp2(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(res_equals(res.c_0, b.c_0)); + assert!(res_equals(res.c_1, b.c_1)); } -//Errors: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262256, span: Span { src (ptr): 0x600012cb7b50, path: None, start: 0, end: 0, as_str(): "" } }' +// BLOCKED thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262256, span: Span { src (ptr): 0x600012cb7b50, path: None, start: 0, end: 0, as_str(): "" } }' // #[tokio::test] // fn test_multiplication() { // let a = Fp2 { @@ -351,4 +282,47 @@ async fn test_mul_fp2() { // }; // assert_eq!(mul_fp2(a, b), c); +// } + +// BLOCKED Gives error: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262151, span: Span { src (ptr): 0x600013668f70, path: None, start: 0, end: 0, as_str(): "" } }', sway-core/src/asm_lang/virtual_ops.rs:866:18 +// #[test] +// fn test_squaring() { +// let a = Fp2 { +// c0: fp_from_raw_unchecked([ +// 0xc9a2_1831_63ee_70d4, +// 0xbc37_70a7_196b_5c91, +// 0xa247_f8c1_304c_5f44, +// 0xb01f_c2a3_726c_80b5, +// 0xe1d2_93e5_bbd9_19c9, +// 0x04b7_8e80_020e_f2ca, +// ]), +// c1: fp_from_raw_unchecked([ +// 0x952e_a446_0462_618f, +// 0x238d_5edd_f025_c62f, +// 0xf6c9_4b01_2ea9_2e72, +// 0x03ce_24ea_c1c9_3808, +// 0x0559_50f9_45da_483c, +// 0x010a_768d_0df4_eabc, +// ]), +// }; +// let b = Fp2 { +// c0: fp_from_raw_unchecked([ +// 0xa1e0_9175_a4d2_c1fe, +// 0x8b33_acfc_204e_ff12, +// 0xe244_15a1_1b45_6e42, +// 0x61d9_96b1_b6ee_1936, +// 0x1164_dbe8_667c_853c, +// 0x0788_557a_cc7d_9c79, +// ]), +// c1: fp_from_raw_unchecked([ +// 0xda6a_87cc_6f48_fa36, +// 0x0fc7_b488_277c_1903, +// 0x9445_ac4a_dc44_8187, +// 0x0261_6d5b_c909_9209, +// 0xdbed_4677_2db5_8d48, +// 0x11b9_4d50_76c7_b7b1, +// ]), +// }; + +// assert_eq!(a.square_fp2(), b); // } \ No newline at end of file From 951ab99c01684f53eef1a34968425c152aa5eb6b Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 2 Aug 2022 17:55:23 -0600 Subject: [PATCH 125/160] - Added Choice and CtOption. However, it's unclear how we can make these implementations constant time - Started fp6 and g1 with a few initial functions - Choice and CtOption are used in Fp invert; this is a WIP --- bls12_381/src/choice.sw | 79 ++++++++++++++++++++++++++++++++++++++ bls12_381/src/fp.sw | 84 +++++++++++++++++++++++++++++++---------- bls12_381/src/fp6.sw | 70 ++++++++++++++++++++++++++++++++++ bls12_381/src/g1.sw | 46 ++++++++++++++++++++++ 4 files changed, 260 insertions(+), 19 deletions(-) create mode 100644 bls12_381/src/choice.sw create mode 100644 bls12_381/src/fp6.sw create mode 100644 bls12_381/src/g1.sw diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw new file mode 100644 index 0000000..2714bf8 --- /dev/null +++ b/bls12_381/src/choice.sw @@ -0,0 +1,79 @@ +library choice; + +use std::{option::*}; + +/////////////// IMPORTANT /////////////// + +// All of this is coming from the dalek cryptograhpy project +// see https://github.com/dalek-cryptography/subtle/blob/main/src/lib.rs + +// The intention is that these implementations will provide constant time functionality. +// However, it's not clear how to achieve this in Sway. +// So we use the traits and names, but have to fill out the correct implementations when we know have +// and Sway supports this. + +/////////////// IMPORTANT /////////////// + +/// The `Choice` struct represents a choice for use in conditional assignment. +/// +/// It is a wrapper around a `u8`, which should have the value either `1` (true) +/// or `0` (false). + +pub struct Choice { c: u8 } + +impl Choice { + pub fn unwrap_u8(self) -> u8 { + self.c + } + + pub fn from(input: u8) -> Choice { + Choice{ c: input} + } +} + + +/// The `CtOption` type represents an optional value similar to the +/// [`Option`](core::option::Option) type but is intended for +/// use in constant time APIs. + +pub struct CtOption { + value: T, + is_some: Choice, +} + +impl CtOption { + /// This method is used to construct a new `CtOption` and takes + /// a value of type `T`, and a `Choice` that determines whether + /// the optional value should be `Some` or not. If `is_some` is + /// false, the value will still be stored but its value is never + /// exposed. + pub fn new(value: T, is_some: Choice) -> CtOption { + CtOption { + value: value, + is_some: is_some, + } + } + + pub fn new(value: T, is_some: bool) -> CtOption { + match is_some { + true => CtOption {value: value, is_some: Choice{ c: 1 },}, + false => CtOption {value: value, is_some: Choice{ c: 0 },}, + } + + } +} + +// impl From> for Option { +// fn from(source: CtOption) -> Option { +// if source.is_some().unwrap_u8() == 1u8 { +// Option::Some(source.value) +// } else { +// None +// } +// } +// } + +// This should have constant time implementations, but not sure atm how to do this in Sway +pub trait ConditionallySelectable { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self; +} \ No newline at end of file diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 749bdd3..38d382c 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -1,5 +1,8 @@ library fp; +dep choice; + +use choice::*; use std::{option::*, u128::*, vec::Vec}; use core::ops::{Eq, Add, Subtract, Multiply}; @@ -50,15 +53,43 @@ const R3: Fp = Fp{ls: [ 0x0aa6_3460_9175_5d4d, ]}; -// type Choice doesn't seem to exist in Sway, so we use a bool -fn conditional_select(a: u64, b: u64, choice: bool) -> u64 { - // TODO make constant time impl - let mut mask = 0; - if (choice) { - mask = ~u64::max(); +impl ConditionallySelectable for u64 { + // TODO How can we do this in Sway in constant time? + pub fn conditional_select(a: u64, b: u64, choice: Choice) -> u64 { + // From original impl: + + // if choice = 0, mask = (-0) = 0000...0000 + // if choice = 1, mask = (-1) = 1111...1111 + + // let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t; + // a ^ (mask & (a ^ b)) + +// Apparently this doesn't work in Sway? + // match choice { + // Choice(0) => a, + // Choice(1) => b, + // } + + // TODO improve. + if (choice.unwrap_u8() == 0) { + a + } else { + b + } } +} - b ^ (mask & (a ^ b)) +impl ConditionallySelectable for Fp { + fn conditional_select(a: Fp, b: Fp, choice: Choice) -> Fp { + Fp{ ls: [ + ~u64::conditional_select(a.ls[0], b.ls[0], choice), + ~u64::conditional_select(a.ls[1], b.ls[1], choice), + ~u64::conditional_select(a.ls[2], b.ls[2], choice), + ~u64::conditional_select(a.ls[3], b.ls[3], choice), + ~u64::conditional_select(a.ls[4], b.ls[4], choice), + ~u64::conditional_select(a.ls[5], b.ls[5], choice), + ]} + } } fn not(input: u64) -> u64 { @@ -145,18 +176,6 @@ impl Fp { && (self.ls[4] == other.ls[4]) && (self.ls[5] == other.ls[5]) } - - // type Choice doesn't seem to exist in Sway, so we use a bool - fn conditional_select(a: Self, b: Self, choice: bool) -> Self { - Fp{ ls: [ - conditional_select(a.ls[0], b.ls[0], choice), - conditional_select(a.ls[1], b.ls[1], choice), - conditional_select(a.ls[2], b.ls[2], choice), - conditional_select(a.ls[3], b.ls[3], choice), - conditional_select(a.ls[4], b.ls[4], choice), - conditional_select(a.ls[5], b.ls[5], choice), - ]} - } pub fn neg(self) -> Fp { let(d0, borrow) = sbb(MODULUS[0], self.ls[0], 0); @@ -346,6 +365,12 @@ impl Fp { (rhs.neg()).add(self) } + +//TODO implement this from zkcrypto + pub fn pow_vartime(self, by: [u64; 6]) -> Self { + ~Fp::zero() + } + //TODO implement this one for T=6 when sum_of_products_2 is working correctly. // (sum_of_products_2 can be tested through testing fp2 multiplication, but this is not running atm because of Immediate18TooLarge) @@ -460,6 +485,27 @@ impl Fp { } } +impl Fp { + +//TODO pow_vartime has to be implemented + CtOption is not constant time + /// Computes the multiplicative inverse of this field + /// element, returning None in the case that this element + /// is zero. + pub fn invert(self) -> CtOption { + // Exponentiate by p - 2 + let t = self.pow_vartime([ + 0xb9fe_ffff_ffff_aaa9, + 0x1eab_fffe_b153_ffff, + 0x6730_d2a0_f6b0_f624, + 0x6477_4b84_f385_12bf, + 0x4b1b_a7b6_434b_acd7, + 0x1a01_11ea_397f_e69a, + ]); + + ~CtOption::new(t, !self.is_zero()) + } +} + impl Eq for Fp { fn eq(self, other: Self) -> bool { self.eq(other) diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw new file mode 100644 index 0000000..ba86eaa --- /dev/null +++ b/bls12_381/src/fp6.sw @@ -0,0 +1,70 @@ +library fp6; + +dep fp2; +use fp2::*; + +pub struct Fp6 { + c0: Fp2, + c1: Fp2, + c2: Fp2, +} + + +impl Fp6 { + fn from(f: Fp) -> Fp6 { + Fp6 { + c0: ~Fp2::from(f), + c1: ~Fp2::zero(), + c2: ~Fp2::zero(), + } + } + + fn from(f: Fp2) -> Fp6 { + Fp6 { + c0: f, + c1: ~Fp2::zero(), + c2: ~Fp2::zero(), + } + } + + pub fn zero() -> Self { + Fp6 { + c0: ~Fp2::zero(), + c1: ~Fp2::zero(), + c2: ~Fp2::zero(), + } + } + + pub fn one() -> Self { + Fp6 { + c0: ~Fp2::one(), + c1: ~Fp2::zero(), + c2: ~Fp2::zero(), + } + } + +//TODO test (but zkcrypto doesnt have a dedicated test, so will be tested implicitly) + pub fn mul_by_1(self, c1: Fp2) -> Fp6 { + let b_b = self.c1 * c1; + + let t1 = (self.c1 + self.c2) * c1 - b_b; + let t1 = t1.mul_by_nonresidue(); + + let t2 = (self.c0 + self.c1) * c1 - b_b; + + Fp6 { + c0: t1, + c1: t2, + c2: b_b, + } + } + + // Is not tested + fn conditional_select(a: Fp6, b: Fp6, choice: Choice) -> Fp6 { + Fp6 { + c0: ~Fp2::conditional_select(a.c0, b.c0, choice), + c1: ~Fp2::conditional_select(a.c1, b.c1, choice), + c2: ~Fp2::conditional_select(a.c2, b.c2, choice), + } + } +} \ No newline at end of file diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw new file mode 100644 index 0000000..ce861d3 --- /dev/null +++ b/bls12_381/src/g1.sw @@ -0,0 +1,46 @@ +library g1; + +// Comment from zkcrypto +/// This is an element of $\mathbb{G}_1$ represented in the affine coordinate space. +/// It is ideal to keep elements in this representation to reduce memory usage and +/// improve performance through the use of mixed curve model arithmetic. +/// +/// Values of `G1Affine` are guaranteed to be in the $q$-order subgroup unless an +/// "unchecked" API was misused. +pub struct G1Affine { + pub x: Fp, + pub y: Fp, + infinity: Choice, +} + +pub struct G1Projective { + pub x: Fp, + pub y: Fp, + pub z: Fp, +} + +// TODO: trying to get this to work, seems like a good starting point +// fn from(p: G1Projective) -> G1Affine { +// let zinv = p.z.invert().unwrap_or(~Fp::zero()); +// let x = p.x * zinv; +// let y = p.y * zinv; + +// let tmp = G1Affine { +// x, +// y, +// infinity: Choice::from(0u8), +// }; + +// G1Affine::conditional_select(&tmp, &G1Affine::identity(), zinv.is_zero()) +// } + +impl G1Affine { + /// Returns the identity of the group: the point at infinity. + pub fn identity() -> G1Affine { + G1Affine { + x: Fp::zero(), + y: Fp::one(), + infinity: Choice::from(1u8), + } + } +} \ No newline at end of file From 6a95611f66340216737f0c72ab7c47fefb96e6ff Mon Sep 17 00:00:00 2001 From: Manish Date: Wed, 3 Aug 2022 19:22:41 +0530 Subject: [PATCH 126/160] add, sub, neg, mul_by_01 for fp6 and sum_of_products_6 in fp(testing not done yet) --- bls12_381/src/fp.sw | 44 ++++++- bls12_381/src/fp6.sw | 42 +++++++ bls12_381/src/lib.sw | 3 +- tests_bls12_381/src/main.sw | 3 +- tests_bls12_381/tests/harness.rs | 3 +- tests_bls12_381/tests/tests_fp6/mod.rs | 168 +++++++++++++++++++++++++ 6 files changed, 258 insertions(+), 5 deletions(-) create mode 100644 tests_bls12_381/tests/tests_fp6/mod.rs diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 38d382c..f9efcf5 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -55,7 +55,7 @@ const R3: Fp = Fp{ls: [ impl ConditionallySelectable for u64 { // TODO How can we do this in Sway in constant time? - pub fn conditional_select(a: u64, b: u64, choice: Choice) -> u64 { + fn conditional_select(a: u64, b: u64, choice: Choice) -> u64 { // From original impl: // if choice = 0, mask = (-0) = 0000...0000 @@ -483,6 +483,48 @@ impl Fp { // conditional subtraction to ensure the output is in range. (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() } + + // //TODO: Testing not done + // pub fn sum_of_products_6(a: [Fp; 6], b: [Fp; 6]) -> Fp { + // let u0 = 0; + // let u1 = 0; + // let u2 = 0; + // let u3 = 0; + // let u4 = 0; + // let u5 = 0; + // let mut j = 0; + + // while j < 6 { + // let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); + + // let mut i = 0; + // while i < 6 { + // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + // let (t6, _) = adc(t6, 0, carry); + // i += 1; + // } + // let k = multiply_wrap(t0, INV); + // let (_, carry) = mac(t0, k, MODULUS[0], 0); + // let (u1, carry) = mac(t1, k, MODULUS[1], carry); + // let (u2, carry) = mac(t2, k, MODULUS[2], carry); + // let (u3, carry) = mac(t3, k, MODULUS[3], carry); + // let (u4, carry) = mac(t4, k, MODULUS[4], carry); + // let (u5, carry) = mac(t5, k, MODULUS[5], carry); + // let (u6, _) = adc(t6, 0, carry); + + // j += 1; + // } + + // // Because we represent F_p elements in non-redundant form, we need a final + // // conditional subtraction to ensure the output is in range. + // (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() + // } + } impl Fp { diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index ba86eaa..4ca47cb 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -58,6 +58,48 @@ impl Fp6 { c2: b_b, } } + //TODO: Testing + pub fn mul_by_01(self, c0: Fp2, c1: Fp2) -> Fp6 { + let a_a = self.c0 * c0; + let b_b = self.c1 * c1; + + let t1 = (self.c1 + self.c2) * c1 - b_b; + let t1 = t1.mul_by_nonresidue() + a_a; + + let t2 = (c0 + c1) * (self.c0 +self.c1) - a_a -b_b; + + let t3 = (self.c0 + self.c2) * c0 - a_a + b_b; + + Fp6 { + c0: t1, + c1: t2, + c3: t3, + } + } + //TODO: Testing + pub fn add(self, rhs: Fp6) -> Fp6 { + Fp6 { + c0: self.c0 + rhs.c0, + c1: self.c1 + rhs.c1, + c2: self.c2 + rhs.c2, + } + } + //TODO: Testing + pub fn sub(self, rhs: Fp6) -> Fp6 { + Fp6 { + c0: self.c0 - rhs.c0, + c1: self.c1 - rhs.c1, + c2: self.c2 - rhs.c2, + } + } + //TODO: Testing + pub fn neg(self) -> Fp6 { + Fp6 { + c0: self.c0.neg(), + c1: self.c1.neg(), + c2: self.c2.neg(), + } + } // Is not tested fn conditional_select(a: Fp6, b: Fp6, choice: Choice) -> Fp6 { diff --git a/bls12_381/src/lib.sw b/bls12_381/src/lib.sw index aaa9f10..9be59c9 100644 --- a/bls12_381/src/lib.sw +++ b/bls12_381/src/lib.sw @@ -1,4 +1,5 @@ library bls12_381; dep fp; -dep fp2; \ No newline at end of file +dep fp2; +dep fp6; \ No newline at end of file diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 1e77aba..86ca764 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,7 +1,6 @@ contract; -use bls12_381::{fp::*, fp2::*}; - +use bls12_381::{fp::*, fp2::*, fp6::*}; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; diff --git a/tests_bls12_381/tests/harness.rs b/tests_bls12_381/tests/harness.rs index 3ca35f3..4c540a5 100644 --- a/tests_bls12_381/tests/harness.rs +++ b/tests_bls12_381/tests/harness.rs @@ -1,2 +1,3 @@ // mod tests_fp; -mod tests_fp2; \ No newline at end of file +mod tests_fp2; +// mod tests_fp6; \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp6/mod.rs b/tests_bls12_381/tests/tests_fp6/mod.rs new file mode 100644 index 0000000..6a456ef --- /dev/null +++ b/tests_bls12_381/tests/tests_fp6/mod.rs @@ -0,0 +1,168 @@ +use fuels::{prelude::*, tx::ContractId}; + +// Load abi from json +abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); + +async fn get_contract_instance() -> (BlsTestContract, ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "./out/debug/tests_bls12_381.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(None) + ) + .await + .unwrap(); + + let instance = BlsTestContract::new(id.to_string(), wallet); + + (instance, id) +} + + +pub fn res_equals(res: Fp2, should_be: Fp2) -> bool { + + let c0_res = res.c_0; + let c1_res = res.c_1; + let c0_should_be = should_be.c_0; + let c1_should_be = should_be.c_1; + + assert!(c0_res.ls[0] == c0_should_be.ls[0]); + assert!(c0_res.ls[1] == c0_should_be.ls[1]); + assert!(c0_res.ls[2] == c0_should_be.ls[2]); + assert!(c0_res.ls[3] == c0_should_be.ls[3]); + assert!(c0_res.ls[4] == c0_should_be.ls[4]); + assert!(c0_res.ls[5] == c0_should_be.ls[5]); + + assert!(c1_res.ls[0] == c1_should_be.ls[0]); + assert!(c1_res.ls[1] == c1_should_be.ls[1]); + assert!(c1_res.ls[2] == c1_should_be.ls[2]); + assert!(c1_res.ls[3] == c1_should_be.ls[3]); + assert!(c1_res.ls[4] == c1_should_be.ls[4]); + assert!(c1_res.ls[5] == c1_should_be.ls[5]); + true +} + +fn get_a() -> Fp6 { + let a = Fp6 { + c_0: Fp2 { + c_0: Fp{ls: [ + 0x47f9_cb98_b1b8_2d58, + 0x5fe9_11eb_a3aa_1d9d, + 0x96bf_1b5f_4dd8_1db3, + 0x8100_d27c_c925_9f5b, + 0xafa2_0b96_7464_0eab, + 0x09bb_cea7_d8d9_497d, + ].to_vec()}, + c_1: Fp{ls: [ + 0x0303_cb98_b166_2daa, + 0xd931_10aa_0a62_1d5a, + 0xbfa9_820c_5be4_a468, + 0x0ba3_643e_cb05_a348, + 0xdc35_34bb_1f1c_25a6, + 0x06c3_05bb_19c0_e1c1, + ].to_vec()}, + }, + c_1: Fp2 { + c_0: Fp{ls: [ + 0x46f9_cb98_b162_d858, + 0x0be9_109c_f7aa_1d57, + 0xc791_bc55_fece_41d2, + 0xf84c_5770_4e38_5ec2, + 0xcb49_c1d9_c010_e60f, + 0x0acd_b8e1_58bf_e3c8, + ].to_vec()}, + c_1: Fp{ls: [ + 0x8aef_cb98_b15f_8306, + 0x3ea1_108f_e4f2_1d54, + 0xcf79_f69f_a1b7_df3b, + 0xe4f5_4aa1_d16b_1a3c, + 0xba5e_4ef8_6105_a679, + 0x0ed8_6c07_97be_e5cf, + ].to_vec()}, + }, + c_2: Fp2 { + c_0: Fp{ls: [ + 0xcee5_cb98_b15c_2db4, + 0x7159_1082_d23a_1d51, + 0xd762_30e9_44a1_7ca4, + 0xd19e_3dd3_549d_d5b6, + 0xa972_dc17_01fa_66e3, + 0x12e3_1f2d_d6bd_e7d6, + ].to_vec()}, + c_1: Fp{ls: [ + 0xad2a_cb98_b173_2d9d, + 0x2cfd_10dd_0696_1d64, + 0x0739_6b86_c6ef_24e8, + 0xbd76_e2fd_b1bf_c820, + 0x6afe_a7f6_de94_d0d5, + 0x1099_4b0c_5744_c040, + ].to_vec()}, + }, + }; + + a +} + +fn get_b() -> Fp6 { + let b = Fp6 { + c_0: Fp2 { + c_0: Fp{ ls: [ + 0xf120_cb98_b16f_d84b, + 0x5fb5_10cf_f3de_1d61, + 0x0f21_a5d0_69d8_c251, + 0xaa1f_d62f_34f2_839a, + 0x5a13_3515_7f89_913f, + 0x14a3_fe32_9643_c247, + ].to_vec()}, + c_1: Fp{ ls: [ + 0x3516_cb98_b16c_82f9, + 0x926d_10c2_e126_1d5f, + 0x1709_e01a_0cc2_5fba, + 0x96c8_c960_b825_3f14, + 0x4927_c234_207e_51a9, + 0x18ae_b158_d542_c44e, + ].to_vec()}, + }, + c_1: Fp2 { + c_0: Fp{ ls: [ + 0xbf0d_cb98_b169_82fc, + 0xa679_10b7_1d1a_1d5c, + 0xb7c1_47c2_b8fb_06ff, + 0x1efa_710d_47d2_e7ce, + 0xed20_a79c_7e27_653c, + 0x02b8_5294_dac1_dfba, + ].to_vec()}, + c_1: Fp{ ls: [ + 0x9d52_cb98_b180_82e5, + 0x621d_1111_5176_1d6f, + 0xe798_8260_3b48_af43, + 0x0ad3_1637_a4f4_da37, + 0xaeac_737c_5ac1_cf2e, + 0x006e_7e73_5b48_b824, + ].to_vec()}, + }, + c_2: Fp2 { + c_0: Fp{ ls: [ + 0xe148_cb98_b17d_2d93, + 0x94d5_1104_3ebe_1d6c, + 0xef80_bca9_de32_4cac, + 0xf77c_0969_2827_95b1, + 0x9dc1_009a_fbb6_8f97, + 0x0479_3199_9a47_ba2b, + ].to_vec()}, + c_1: Fp{ ls: [ + 0x253e_cb98_b179_d841, + 0xc78d_10f7_2c06_1d6a, + 0xf768_f6f3_811b_ea15, + 0xe424_fc9a_ab5a_512b, + 0x8cd5_8db9_9cab_5001, + 0x0883_e4bf_d946_bc32, + ].to_vec()}, + }, + }; + + b +} From a8ec3d421c9ed6b3487b81d4660436733d8c03b6 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 08:05:54 -0600 Subject: [PATCH 127/160] Compile fixes --- bls12_381/src/fp6.sw | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 4ca47cb..669b66c 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -1,7 +1,12 @@ library fp6; dep fp2; +dep fp; +dep choice; + +use fp::*; use fp2::*; +use choice::*; pub struct Fp6 { c0: Fp2, @@ -73,7 +78,7 @@ impl Fp6 { Fp6 { c0: t1, c1: t2, - c3: t3, + c2: t3, } } //TODO: Testing @@ -101,12 +106,12 @@ impl Fp6 { } } - // Is not tested - fn conditional_select(a: Fp6, b: Fp6, choice: Choice) -> Fp6 { - Fp6 { - c0: ~Fp2::conditional_select(a.c0, b.c0, choice), - c1: ~Fp2::conditional_select(a.c1, b.c1, choice), - c2: ~Fp2::conditional_select(a.c2, b.c2, choice), - } - } + // // Is not tested + // fn conditional_select(a: Fp6, b: Fp6, choice: Choice) -> Fp6 { + // Fp6 { + // c0: ~Fp2::conditional_select(a.c0, b.c0, choice), + // c1: ~Fp2::conditional_select(a.c1, b.c1, choice), + // c2: ~Fp2::conditional_select(a.c2, b.c2, choice), + // } + // } } \ No newline at end of file From 1ddf3b411e8e9c77cfecdd616e438655b3d744f9 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 11:16:58 -0600 Subject: [PATCH 128/160] To try to run something on the droplet. --- bls/Forc.toml | 2 +- bls/src/main.sw | 12 ++---------- bls/src/tests/tests_temp_fe_mont_mul.sw | 5 +++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/bls/Forc.toml b/bls/Forc.toml index 1d4bc7e..762289c 100644 --- a/bls/Forc.toml +++ b/bls/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["HashCloak"] -entry = "lib.sw" +entry = "main.sw" license = "Apache-2.0" name = "bls" diff --git a/bls/src/main.sw b/bls/src/main.sw index 604d0fe..28dc79e 100644 --- a/bls/src/main.sw +++ b/bls/src/main.sw @@ -4,11 +4,7 @@ dep vect; dep fields; dep test_helpers; dep consts; -dep tests/tests_vect_fp; -dep tests/tests_vect_fp2; dep tests/tests_vect_subfunctions; -dep tests/tests_small_functions; -dep tests/tests_temp_mul; dep tests/tests_temp_fe_mont_mul; use std::{assert::assert, option::*, u128::*, vec::Vec}; @@ -18,23 +14,19 @@ use ::consts::*; use ::test_helpers::*; use std::logging::log; -use ::tests_vect_fp::fp_tests; -use ::tests_vect_fp2::fp2_tests; use ::tests_vect_subfunctions::vect_subfunctions_tests; -use ::tests_small_functions::tests_small_functions; -use ::tests_temp_mul::tests_temp_mul; use ::tests_temp_fe_mont_mul::tests_temp_fe_mont_mul; fn main() { // assert(fp_tests()); // assert(fp2_tests()); // assert(test_multiply_wrap()); - // assert(test_mac()); + assert(test_mac()); // assert(vect_subfunctions_tests()); // assert(tests_small_functions()); // assert(tests_temp_mul()); - assert(tests_temp_fe_mont_mul()); + // assert(tests_temp_fe_mont_mul()); } fn test_mac() -> bool { diff --git a/bls/src/tests/tests_temp_fe_mont_mul.sw b/bls/src/tests/tests_temp_fe_mont_mul.sw index ace909c..5f52726 100644 --- a/bls/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls/src/tests/tests_temp_fe_mont_mul.sw @@ -10,10 +10,10 @@ use std::logging::log; pub fn tests_temp_fe_mont_mul() -> bool { // assert(test_temp_mul_random_by_random()); - assert(test_temp_mul_mont_n()); + // assert(test_temp_mul_mont_n()); true } - +/* fn test_temp_mul_mont_n() -> bool { //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 let mut r1_vec = ~Vec::new::(); @@ -172,3 +172,4 @@ Note: from the reference impl, you can see it's being tested as follows: So there is a conversion to and from the mont form */ +*/ \ No newline at end of file From 9c78652c71dfc08c712e84f94919ca23b6163573 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 12:03:27 -0600 Subject: [PATCH 129/160] Create a new vector has changed in newer versions of Sway --- bls/src/vect.sw | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/bls/src/vect.sw b/bls/src/vect.sw index 3c89fdc..397097d 100644 --- a/bls/src/vect.sw +++ b/bls/src/vect.sw @@ -54,7 +54,7 @@ pub fn unpack_or_0(x: Option) -> u64 { pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut limbx: u64 = 0; let mut carry: u64 = 0; - let mut tmp = ~Vec::new::(); + let mut tmp = ~Vec::new(); let mut i = 0; while i < n { @@ -65,7 +65,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { i += 1; } - let mut ret = ~Vec::new::(); + let mut ret = ~Vec::new(); let mut borrow: u64 = 0; i = 0; while i < n { @@ -77,7 +77,7 @@ pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { } let mask: u64 = borrow * ~u64::max(); - let mut res = ~Vec::new::(); + let mut res = ~Vec::new(); i = 0; while i < n { let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); @@ -102,9 +102,9 @@ But this intermediate value doesn't correspond to what the blst impl outputs. pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); let mut hi: U128 = ~U128::from(0, 0); - let mut tmp: Vec = ~Vec::new::(); - let mut tmp2: Vec = ~Vec::new::(); - let mut tmp3: Vec = ~Vec::new::(); + let mut tmp: Vec = ~Vec::new(); + let mut tmp2: Vec = ~Vec::new(); + let mut tmp3: Vec = ~Vec::new(); let mut i = 0; while i < n { @@ -180,7 +180,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec let mut borrow: u64 = 0; i = 0; - let mut ret: Vec = ~Vec::new::(); + let mut ret: Vec = ~Vec::new(); while i < n { let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp3.get(i))); @@ -229,7 +229,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec }; i = 0; - let mut res: Vec = ~Vec::new::(); + let mut res: Vec = ~Vec::new(); while i < n { let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp3.get(i)) & mask); res.insert(i, value); @@ -242,7 +242,7 @@ pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec // Repo: https://github.com/nccgroup/pairing // Blogpost: https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ fn zero_vec() -> Vec { - let mut temp: Vec = ~Vec::new::(); + let mut temp: Vec = ~Vec::new(); temp.push(0); temp.push(0); temp.push(0); @@ -263,7 +263,7 @@ The mul_mont_n is not working yet, so this would be a temporary solution but usi */ //pub fn temp_mul_mont_n(a: Vec, b: Vec) -> Vec { pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { - let mut a: Vec = ~Vec::new::(); + let mut a: Vec = ~Vec::new(); a.push(a_vec.ls[0]); a.push(a_vec.ls[1]); a.push(a_vec.ls[2]); @@ -271,7 +271,7 @@ pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { a.push(a_vec.ls[4]); a.push(a_vec.ls[5]); - let mut b: Vec = ~Vec::new::(); + let mut b: Vec = ~Vec::new(); b.push(b_vec.ls[0]); b.push(b_vec.ls[1]); b.push(b_vec.ls[2]); @@ -297,7 +297,7 @@ pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { // Same functionality as mul_temp // Effectively a_mont = (a_norm * R) mod N pub fn fe_to_mont(a: Vec) -> Vec { - let mut BLS12_381_RR: Vec = ~Vec::new::(); + let mut BLS12_381_RR: Vec = ~Vec::new(); BLS12_381_RR.push(0xf4df1f341c341746); BLS12_381_RR.push(0x0a76e6a609d104f1); BLS12_381_RR.push(0x8de5476c4c95b6d5); @@ -309,7 +309,7 @@ pub fn fe_to_mont(a: Vec) -> Vec { // Effectively a_norm = (a_mont * R^{-1}) mod N pub fn fe_to_norm(a: Vec) -> Vec { - let mut ONE: Vec = ~Vec::new::(); + let mut ONE: Vec = ~Vec::new(); ONE.push(0x1); ONE.push(0); ONE.push(0); @@ -475,7 +475,7 @@ pub fn montgomery_reduction(t: [u64; } pub fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { - let mut a_temp: Vec = ~Vec::new::(); + let mut a_temp: Vec = ~Vec::new(); a_temp.push(a.ls[0]); a_temp.push(a.ls[1]); a_temp.push(a.ls[2]); @@ -483,7 +483,7 @@ pub fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { a_temp.push(a.ls[4]); a_temp.push(a.ls[5]); - let mut b_temp: Vec = ~Vec::new::(); + let mut b_temp: Vec = ~Vec::new(); b_temp.push(b.ls[0]); b_temp.push(b.ls[1]); b_temp.push(b.ls[2]); @@ -491,7 +491,7 @@ pub fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { b_temp.push(b.ls[4]); b_temp.push(b.ls[5]); - let mut p_temp: Vec = ~Vec::new::(); + let mut p_temp: Vec = ~Vec::new(); p_temp.push(p.ls[0]); p_temp.push(p.ls[1]); p_temp.push(p.ls[2]); @@ -583,7 +583,7 @@ pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { let mut limbx: u64 = 0; let mut borrow: u64 = 0; let mut i = 0; - let mut ret = ~Vec::new::(); + let mut ret = ~Vec::new(); while i < n { let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), borrow); @@ -593,7 +593,7 @@ pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { } let mask: u64 = borrow * ~u64::max(); - let mut res = ~Vec::new::(); + let mut res = ~Vec::new(); let mut carry: u64 = 0; while i < n { let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(ret.get(i)), unpack_or_0(p.get(i)) & mask, carry); @@ -619,7 +619,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { let mut i = 1; let mut b: Vec = a; //let mut limbx: U128 = ~U128::from(0,0); - let mut tmp: Vec = ~Vec::new::(); + let mut tmp: Vec = ~Vec::new(); while j < n { let mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(b.get(0)))).lower; let mx: U128 = ~U128::from(0, mx_temp); @@ -639,7 +639,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { j += 1; } - let mut tmp2: Vec = ~Vec::new::(); + let mut tmp2: Vec = ~Vec::new(); let mut carry = 0; i = 0; while i < n { @@ -653,7 +653,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { } let mut borrow = 0; - let mut res: Vec = ~Vec::new::(); + let mut res: Vec = ~Vec::new(); i = 0; while i < n { let tmp2i: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); @@ -680,7 +680,7 @@ pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { } else { ~u64::max() - (borrow - carry - 1) }; - let mut result: Vec = ~Vec::new::(); + let mut result: Vec = ~Vec::new(); i = 0; while i < n { let result_i = (unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask); @@ -888,7 +888,7 @@ pub fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { let mut i = 0; let mut m = n; //let mut res_vec: (u64, u64, u64, u64, u64, u64) = (0,0,0,0,0,0); - let mut res_vec: Vec = ~Vec::new::(); + let mut res_vec: Vec = ~Vec::new(); while m > 0 { if a.ls[0] & 1 > 0 { @@ -947,7 +947,7 @@ pub fn mul_by_3_mod_384x(a: vec384x, p: vec384) -> vec384x { } fn to_vec(v: vec384) -> Vec { - let mut res = ~Vec::new::(); + let mut res = ~Vec::new(); let mut i = 0; while i < 6 { res.push(v.ls[i]); From f2c30ed56f71087dc1e176169d0d7b56017cb06e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 12:08:26 -0600 Subject: [PATCH 130/160] More fixes for newer Sway version --- bls/src/tests/tests_temp_fe_mont_mul.sw | 12 ++--- bls/src/tests/tests_vect_subfunctions.sw | 60 ++++++++++++------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/bls/src/tests/tests_temp_fe_mont_mul.sw b/bls/src/tests/tests_temp_fe_mont_mul.sw index 5f52726..e7554ec 100644 --- a/bls/src/tests/tests_temp_fe_mont_mul.sw +++ b/bls/src/tests/tests_temp_fe_mont_mul.sw @@ -16,7 +16,7 @@ pub fn tests_temp_fe_mont_mul() -> bool { /* fn test_temp_mul_mont_n() -> bool { //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new::(); + let mut r1_vec = ~Vec::new(); r1_vec.push(6071868568151433008); r1_vec.push(12105094901188801210); r1_vec.push(2389211775905699303); @@ -24,7 +24,7 @@ fn test_temp_mul_mont_n() -> bool { r1_vec.push(5826366508043997497); r1_vec.push(13436617433956842131); //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new::(); + let mut r2_vec = ~Vec::new(); r2_vec.push(16964885827015180015); r2_vec.push(12035734743809705289); r2_vec.push(10517060043363161601); @@ -68,7 +68,7 @@ fn test_temp_mul_mont_n() -> bool { } fn test_temp_mul_random_by_random() -> bool { - let mut p_vec = ~Vec::new::(); + let mut p_vec = ~Vec::new(); p_vec.push(0xb9feffffffffaaab); p_vec.push(0x1eabfffeb153ffff); p_vec.push(0x6730d2a0f6b0f624); @@ -77,7 +77,7 @@ fn test_temp_mul_random_by_random() -> bool { p_vec.push(0x1a0111ea397fe69a); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new::(); + let mut r1_vec = ~Vec::new(); r1_vec.push(6071868568151433008); r1_vec.push(12105094901188801210); r1_vec.push(2389211775905699303); @@ -85,7 +85,7 @@ fn test_temp_mul_random_by_random() -> bool { r1_vec.push(5826366508043997497); r1_vec.push(13436617433956842131); //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new::(); + let mut r2_vec = ~Vec::new(); r2_vec.push(16964885827015180015); r2_vec.push(12035734743809705289); r2_vec.push(10517060043363161601); @@ -131,7 +131,7 @@ fn test_temp_mul_random_by_random() -> bool { out of gas, so just run with this known value. All intermediate steps are correct with the ncc ref implementation */ - let mut intermediate_res_vec = ~Vec::new::(); + let mut intermediate_res_vec = ~Vec::new(); intermediate_res_vec.push(8042921339150017446); intermediate_res_vec.push(4899742317194411181); intermediate_res_vec.push(11922910400151252689); diff --git a/bls/src/tests/tests_vect_subfunctions.sw b/bls/src/tests/tests_vect_subfunctions.sw index 21b9ce7..16d31ca 100644 --- a/bls/src/tests/tests_vect_subfunctions.sw +++ b/bls/src/tests/tests_vect_subfunctions.sw @@ -38,7 +38,7 @@ pub fn vect_subfunctions_tests() -> bool { } fn get_test_vectors() -> (Vec, Vec) { - let mut zero_vec = ~Vec::new::(); + let mut zero_vec = ~Vec::new(); zero_vec.push(0); zero_vec.push(0); zero_vec.push(0); @@ -46,7 +46,7 @@ fn get_test_vectors() -> (Vec, Vec) { zero_vec.push(0); zero_vec.push(0); - let mut p_vec = ~Vec::new::(); + let mut p_vec = ~Vec::new(); p_vec.push(0xb9feffffffffaaab); p_vec.push(0x1eabfffeb153ffff); p_vec.push(0x6730d2a0f6b0f624); @@ -66,7 +66,7 @@ fn test_mul_mont_n_by_zero() -> bool { } fn get_one_vec() -> Vec { - let mut one_vec = ~Vec::new::(); + let mut one_vec = ~Vec::new(); one_vec.push(1); one_vec.push(0); one_vec.push(0); @@ -99,7 +99,7 @@ fn test_mul_mont_n_one_by_one() -> bool { fn test_mul_mont_n_random_by_one() -> bool { let(_, p_vec) = get_test_vectors(); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r_vec = ~Vec::new::(); + let mut r_vec = ~Vec::new(); r_vec.push(0x54439c4ae7869f30); //6071868568151433008 r_vec.push(0xa7fdefad55c032ba); //12105094901188801210 r_vec.push(0x21282f739c0a15e7); //2389211775905699303 @@ -126,7 +126,7 @@ fn test_mul_mont_n_random_by_one() -> bool { fn test_mul_mont_n_random_by_random() -> bool { let(_, p_vec) = get_test_vectors(); //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new::(); + let mut r1_vec = ~Vec::new(); r1_vec.push(6071868568151433008); r1_vec.push(12105094901188801210); r1_vec.push(2389211775905699303); @@ -134,7 +134,7 @@ fn test_mul_mont_n_random_by_random() -> bool { r1_vec.push(5826366508043997497); r1_vec.push(13436617433956842131); //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new::(); + let mut r2_vec = ~Vec::new(); r2_vec.push(16964885827015180015); r2_vec.push(12035734743809705289); r2_vec.push(10517060043363161601); @@ -151,7 +151,7 @@ fn test_mul_mont_n_random_by_random() -> bool { // mod p //1233002344306172478209354248697859329250780126726480993298462574958424022710616415994206080732967265541051783400711 //[1734233419737550087, 7827676449723675145, 5835727259298429301, 3992373620040751347, 13994230039556723943, 577251792061825638] - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new(); res_vec.push(0x42863c4b7ea22ad7); //4793585148327242455 res_vec.push(0x27627bfa644b580d); //2837967030551533581 res_vec.push(0x16930ecb9e3a308f); //1626660158106644623 @@ -184,7 +184,7 @@ blst impl fn test_mont_mul_partial() -> bool { let(_, p_vec) = get_test_vectors(); - let mut intermediate_res_vec = ~Vec::new::(); + let mut intermediate_res_vec = ~Vec::new(); intermediate_res_vec.push(8042921339150017446); intermediate_res_vec.push(4899742317194411181); intermediate_res_vec.push(11922910400151252689); @@ -192,7 +192,7 @@ fn test_mont_mul_partial() -> bool { intermediate_res_vec.push(10892349319971706476); intermediate_res_vec.push(542573957820843489); - let mut ONE: Vec = ~Vec::new::(); + let mut ONE: Vec = ~Vec::new(); ONE.push(0x1); ONE.push(0); ONE.push(0); @@ -233,7 +233,7 @@ fn test_add_zero_to_zero_addn() -> bool { } fn test_add_zero_to_random_addn() -> bool { - let mut random_vec = ~Vec::new::(); + let mut random_vec = ~Vec::new(); random_vec.push(0x3e2528903ca1ef86); random_vec.push(0x270fd67a03bf9e0a); random_vec.push(0xdc70c19599cb699e); @@ -248,21 +248,21 @@ fn test_add_zero_to_random_addn() -> bool { } fn test_add_random_to_small_addn() -> bool { - let mut small_vec = ~Vec::new::(); + let mut small_vec = ~Vec::new(); small_vec.push(0x1); small_vec.push(0x2); small_vec.push(0x3); small_vec.push(0x4); small_vec.push(0x5); small_vec.push(0x6); - let mut random_vec = ~Vec::new::(); + let mut random_vec = ~Vec::new(); random_vec.push(0x3e2528903ca1ef86); random_vec.push(0x270fd67a03bf9e0a); random_vec.push(0xdc70c19599cb699e); random_vec.push(0xebefda8057d5747a); random_vec.push(0xcf20e11f0b1c323); random_vec.push(0xe979cbf960fe51d); - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new(); res_vec.push(4478030004447473543); res_vec.push(2814704111667093004); res_vec.push(15884408734010272161); @@ -288,7 +288,7 @@ fn test_sub_zero_from_zero_subn() -> bool { fn test_sub_zero_from_random_subn() -> bool { let(zero_vec, p_vec) = get_test_vectors(); - let mut random_vec = ~Vec::new::(); + let mut random_vec = ~Vec::new(); random_vec.push(0x3e2528903ca1ef86); random_vec.push(0x270fd67a03bf9e0a); random_vec.push(0xdc70c19599cb699e); @@ -304,7 +304,7 @@ fn test_sub_zero_from_random_subn() -> bool { fn test_sub_random_from_zero_subn() -> bool { let(zero_vec, p_vec) = get_test_vectors(); - let mut random_vec = ~Vec::new::(); + let mut random_vec = ~Vec::new(); random_vec.push(13059245463466299169); random_vec.push(17774603101077980186); random_vec.push(889990675562875390); @@ -314,7 +314,7 @@ fn test_sub_random_from_zero_subn() -> bool { let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); // p-r (is the same as 0-r mod p) - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new(); res_vec.push(343185552611564426); res_vec.push(2882282484148780005); res_vec.push(6545683898001206309); @@ -329,7 +329,7 @@ fn test_sub_random_from_small_subn() -> bool { let(zero_vec, p_vec) = get_test_vectors(); // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let mut small_vec = ~Vec::new::(); + let mut small_vec = ~Vec::new(); small_vec.push(1); small_vec.push(2); small_vec.push(3); @@ -338,7 +338,7 @@ fn test_sub_random_from_small_subn() -> bool { small_vec.push(6); //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let mut r_vec = ~Vec::new::(); + let mut r_vec = ~Vec::new(); r_vec.push(13059245463466299169); r_vec.push(17774603101077980186); r_vec.push(889990675562875390); @@ -346,7 +346,7 @@ fn test_sub_random_from_small_subn() -> bool { r_vec.push(5370893444473505192); r_vec.push(599972797727911687); - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new(); res_vec.push(343185552611564427); res_vec.push(2882282484148780007); res_vec.push(6545683898001206312); @@ -364,7 +364,7 @@ fn test_sub_random_from_small_subn() -> bool { fn get_r1_r2_vecs() -> (Vec, Vec) { //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let mut r1_vec = ~Vec::new::(); + let mut r1_vec = ~Vec::new(); r1_vec.push(10587454305359941416); r1_vec.push(4615625447881587853); r1_vec.push(9368308553698906485); @@ -374,7 +374,7 @@ fn get_r1_r2_vecs() -> (Vec, Vec) { //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let mut r2_vec = ~Vec::new::(); + let mut r2_vec = ~Vec::new(); r2_vec.push(13403040667047958534); r2_vec.push(405585388298286396); r2_vec.push(7295341050629342949); @@ -392,7 +392,7 @@ fn test_sub_2_randoms_subn() -> bool { //res = //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new(); res_vec.push(15631157712021534498); res_vec.push(4210040059583301456); res_vec.push(2072967503069563536); @@ -415,7 +415,7 @@ fn test_sub_2_randoms_reverse_subn() -> bool { // => mod p //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let mut res_vec = ~Vec::new::(); + let mut res_vec = ~Vec::new(); res_vec.push(16218017377765880713); res_vec.push(16446845525643458734); res_vec.push(5362707070494518163); @@ -438,7 +438,7 @@ fn tests_redc_mont() -> bool { true } fn test_redc_mont_n_small() -> bool { - let mut a_vec: Vec = ~Vec::new::(); + let mut a_vec: Vec = ~Vec::new(); a_vec.push(0); a_vec.push(0); a_vec.push(0); @@ -451,7 +451,7 @@ fn test_redc_mont_n_small() -> bool { a_vec.push(0); a_vec.push(0); a_vec.push(10); - let mut res_vec: Vec = ~Vec::new::(); + let mut res_vec: Vec = ~Vec::new(); res_vec.push(0); res_vec.push(0); res_vec.push(0); @@ -465,7 +465,7 @@ fn test_redc_mont_n_small() -> bool { } fn test_redc_mont_n_p() -> bool { - let mut p_vec = ~Vec::new::(); + let mut p_vec = ~Vec::new(); p_vec.push(0xb9feffffffffaaab); p_vec.push(0x1eabfffeb153ffff); p_vec.push(0x6730d2a0f6b0f624); @@ -493,7 +493,7 @@ fn test_redc_mont_n_random() -> bool { a_vec mod P = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] */ - let mut a_vec = ~Vec::new::(); + let mut a_vec = ~Vec::new(); a_vec.push(13282407956253574712); a_vec.push(7557322358563246340); @@ -507,7 +507,7 @@ fn test_redc_mont_n_random() -> bool { a_vec.push(0); a_vec.push(0); a_vec.push(0); - let mut result = ~Vec::new::(); + let mut result = ~Vec::new(); result.push(13282407956253574712); result.push(7557322358563246340); result.push(14991082624209354397); @@ -533,7 +533,7 @@ fn test_redc_mont_n_random_large() -> bool { */ - let mut a_vec = ~Vec::new::(); + let mut a_vec = ~Vec::new(); a_vec.push(13142370077570254774); a_vec.push(17984324540840297179); a_vec.push(15982738825684268908); @@ -547,7 +547,7 @@ fn test_redc_mont_n_random_large() -> bool { a_vec.push(0); a_vec.push(0); - let mut result = ~Vec::new::(); + let mut result = ~Vec::new(); result.push(1470447218309591647); result.push(6933616983254254301); result.push(15697854105282963640); From 125d7e0371d1c057110f522941e524a8d623fcc2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 14:57:00 -0600 Subject: [PATCH 131/160] To test contract with custom gas limit in tests-bls --- bls/Forc.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bls/Forc.toml b/bls/Forc.toml index 762289c..1d4bc7e 100644 --- a/bls/Forc.toml +++ b/bls/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["HashCloak"] -entry = "main.sw" +entry = "lib.sw" license = "Apache-2.0" name = "bls" From 6eea1309fffd21c3cac41c1fc71d462f2471adc8 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 17:36:28 -0600 Subject: [PATCH 132/160] - Commented out some functions which can't compile yet (heavy in fp6) - Added some smaller functions which will be tested indirectly when used in other functions - Added test for mul in fp6 which can't be run yet :( --- bls12_381/src/fp6.sw | 113 +++++++++++++++++- bls12_381/src/g1.sw | 152 +++++++++++++++++++++++++ tests_bls12_381/Cargo.toml | 1 + tests_bls12_381/src/main.sw | 14 ++- tests_bls12_381/tests/tests_fp6/mod.rs | 18 +++ tests_bls12_381/tests/tests_g1/mod.rs | 8 ++ 6 files changed, 299 insertions(+), 7 deletions(-) create mode 100644 tests_bls12_381/tests/tests_g1/mod.rs diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 669b66c..c71d185 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -8,6 +8,8 @@ use fp::*; use fp2::*; use choice::*; +use core::ops::{Multiply}; + pub struct Fp6 { c0: Fp2, c1: Fp2, @@ -46,7 +48,7 @@ impl Fp6 { c1: ~Fp2::zero(), c2: ~Fp2::zero(), } - } + }/* //TODO test (but zkcrypto doesnt have a dedicated test, so will be tested implicitly) pub fn mul_by_1(self, c1: Fp2) -> Fp6 { @@ -63,7 +65,7 @@ impl Fp6 { c2: b_b, } } - //TODO: Testing + //TODO: Testing. Has no dedicated tests in zkcrypto pub fn mul_by_01(self, c0: Fp2, c1: Fp2) -> Fp6 { let a_a = self.c0 * c0; let b_b = self.c1 * c1; @@ -81,7 +83,8 @@ impl Fp6 { c2: t3, } } - //TODO: Testing + */ + //TODO: Testing. Has no dedicated tests in zkcrypto pub fn add(self, rhs: Fp6) -> Fp6 { Fp6 { c0: self.c0 + rhs.c0, @@ -89,7 +92,7 @@ impl Fp6 { c2: self.c2 + rhs.c2, } } - //TODO: Testing + //TODO: Testing. Has no dedicated tests in zkcrypto pub fn sub(self, rhs: Fp6) -> Fp6 { Fp6 { c0: self.c0 - rhs.c0, @@ -97,7 +100,7 @@ impl Fp6 { c2: self.c2 - rhs.c2, } } - //TODO: Testing + //TODO: Testing. Has no dedicated tests in zkcrypto pub fn neg(self) -> Fp6 { Fp6 { c0: self.c0.neg(), @@ -114,4 +117,102 @@ impl Fp6 { // c2: ~Fp2::conditional_select(a.c2, b.c2, choice), // } // } -} \ No newline at end of file +/* Can't compile if this is uncommented atm... + fn mul_interleaved(self, b: Self) -> Self { + // The intuition for this algorithm is that we can look at F_p^6 as a direct + // extension of F_p^2, and express the overall operations down to the base field + // F_p instead of only over F_p^2. This enables us to interleave multiplications + // and reductions, ensuring that we don't require double-width intermediate + // representations (with around twice as many limbs as F_p elements). + + // We want to express the multiplication c = a x b, where a = (a_0, a_1, a_2) is + // an element of F_p^6, and a_i = (a_i,0, a_i,1) is an element of F_p^2. The fully + // expanded multiplication is given by (2022-376 §5): + // + // c_0,0 = a_0,0 b_0,0 - a_0,1 b_0,1 + a_1,0 b_2,0 - a_1,1 b_2,1 + a_2,0 b_1,0 - a_2,1 b_1,1 + // - a_1,0 b_2,1 - a_1,1 b_2,0 - a_2,0 b_1,1 - a_2,1 b_1,0. + // = a_0,0 b_0,0 - a_0,1 b_0,1 + a_1,0 (b_2,0 - b_2,1) - a_1,1 (b_2,0 + b_2,1) + // + a_2,0 (b_1,0 - b_1,1) - a_2,1 (b_1,0 + b_1,1). + // + // c_0,1 = a_0,0 b_0,1 + a_0,1 b_0,0 + a_1,0 b_2,1 + a_1,1 b_2,0 + a_2,0 b_1,1 + a_2,1 b_1,0 + // + a_1,0 b_2,0 - a_1,1 b_2,1 + a_2,0 b_1,0 - a_2,1 b_1,1. + // = a_0,0 b_0,1 + a_0,1 b_0,0 + a_1,0(b_2,0 + b_2,1) + a_1,1(b_2,0 - b_2,1) + // + a_2,0(b_1,0 + b_1,1) + a_2,1(b_1,0 - b_1,1). + // + // c_1,0 = a_0,0 b_1,0 - a_0,1 b_1,1 + a_1,0 b_0,0 - a_1,1 b_0,1 + a_2,0 b_2,0 - a_2,1 b_2,1 + // - a_2,0 b_2,1 - a_2,1 b_2,0. + // = a_0,0 b_1,0 - a_0,1 b_1,1 + a_1,0 b_0,0 - a_1,1 b_0,1 + a_2,0(b_2,0 - b_2,1) + // - a_2,1(b_2,0 + b_2,1). + // + // c_1,1 = a_0,0 b_1,1 + a_0,1 b_1,0 + a_1,0 b_0,1 + a_1,1 b_0,0 + a_2,0 b_2,1 + a_2,1 b_2,0 + // + a_2,0 b_2,0 - a_2,1 b_2,1 + // = a_0,0 b_1,1 + a_0,1 b_1,0 + a_1,0 b_0,1 + a_1,1 b_0,0 + a_2,0(b_2,0 + b_2,1) + // + a_2,1(b_2,0 - b_2,1). + // + // c_2,0 = a_0,0 b_2,0 - a_0,1 b_2,1 + a_1,0 b_1,0 - a_1,1 b_1,1 + a_2,0 b_0,0 - a_2,1 b_0,1. + // c_2,1 = a_0,0 b_2,1 + a_0,1 b_2,0 + a_1,0 b_1,1 + a_1,1 b_1,0 + a_2,0 b_0,1 + a_2,1 b_0,0. + // + // Each of these is a "sum of products", which we can compute efficiently. + + let a = self; + let b10_p_b11 = b.c1.c0 + b.c1.c1; + let b10_m_b11 = b.c1.c0 - b.c1.c1; + let b20_p_b21 = b.c2.c0 + b.c2.c1; + let b20_m_b21 = b.c2.c0 - b.c2.c1; + + Fp6 { + c0: Fp2 { + c0: ~Fp::sum_of_products_6( + [a.c0.c0, a.c0.c1.neg(), a.c1.c0, a.c1.c1.neg(), a.c2.c0, a.c2.c1.neg()], + [b.c0.c0, b.c0.c1, b20_m_b21, b20_p_b21, b10_m_b11, b10_p_b11], + ), + c1: ~Fp::sum_of_products_6( + [a.c0.c0, a.c0.c1, a.c1.c0, a.c1.c1, a.c2.c0, a.c2.c1], + [b.c0.c1, b.c0.c0, b20_p_b21, b20_m_b21, b10_p_b11, b10_m_b11], + ), + }, + c1: Fp2 { + c0: ~Fp::sum_of_products_6( + [a.c0.c0, a.c0.c1.neg(), a.c1.c0, a.c1.c1.neg(), a.c2.c0, a.c2.c1.neg()], + [b.c1.c0, b.c1.c1, b.c0.c0, b.c0.c1, b20_m_b21, b20_p_b21], + ), + c1: ~Fp::sum_of_products_6( + [a.c0.c0, a.c0.c1, a.c1.c0, a.c1.c1, a.c2.c0, a.c2.c1], + [b.c1.c1, b.c1.c0, b.c0.c1, b.c0.c0, b20_p_b21, b20_m_b21], + ), + }, + c2: Fp2 { + c0: ~Fp::sum_of_products_6( + [a.c0.c0, a.c0.c1.neg(), a.c1.c0, a.c1.c1.neg(), a.c2.c0, a.c2.c1.neg()], + [b.c2.c0, b.c2.c1, b.c1.c0, b.c1.c1, b.c0.c0, b.c0.c1], + ), + c1: ~Fp::sum_of_products_6( + [a.c0.c0, a.c0.c1, a.c1.c0, a.c1.c1, a.c2.c0, a.c2.c1], + [b.c2.c1, b.c2.c0, b.c1.c1, b.c1.c0, b.c0.c1, b.c0.c0], + ), + }, + } + } + + pub fn square(self) -> Fp6 { + let s0 = self.c0.square(); + let ab = self.c0 * self.c1; + let s1 = ab + ab; + let s2 = (self.c0 - self.c1 + self.c2).square(); + let bc = self.c1 * self.c2; + let s3 = bc + bc; + let s4 = self.c2.square(); + + Fp6 { + c0: s3.mul_by_nonresidue() + s0, + c1: s4.mul_by_nonresidue() + s1, + c2: s1 + s2 + s3 - s0 - s4, + } + }*/ +} + +// impl Multiply for Fp6 { +// fn multiply(self, other: Self) -> Self { +// self.mul_interleaved(other) +// } +// } \ No newline at end of file diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index ce861d3..9ef828b 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -19,6 +19,12 @@ pub struct G1Projective { pub z: Fp, } +fn mul_by_3b(a: Fp) -> Fp { + let a = a + a; // 2 + let a = a + a; // 4 + a + a + a // 12 +} + // TODO: trying to get this to work, seems like a good starting point // fn from(p: G1Projective) -> G1Affine { // let zinv = p.z.invert().unwrap_or(~Fp::zero()); @@ -43,4 +49,150 @@ impl G1Affine { infinity: Choice::from(1u8), } } + + pub fn generator() -> G1Affine { + G1Affine { + x: ~Fp::from_raw_unchecked([ + 0x5cb3_8790_fd53_0c16, + 0x7817_fc67_9976_fff5, + 0x154f_95c7_143b_a1c1, + 0xf0ae_6acd_f3d0_e747, + 0xedce_6ecc_21db_f440, + 0x1201_7741_9e0b_fb75, + ]), + y: ~Fp::from_raw_unchecked([ + 0xbaac_93d5_0ce7_2271, + 0x8c22_631a_7918_fd8e, + 0xdd59_5f13_5707_25ce, + 0x51ac_5829_5040_5194, + 0x0e1c_8c3f_ad00_59c0, + 0x0bbc_3efc_5008_a26a, + ]), + infinity: ~Choice::from(0u8), + } + } +} + + +impl ConditionallySelectable for G1Projective { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + G1Projective { + x: ~Fp::conditional_select(a.x, b.x, choice), + y: ~Fp::conditional_select(a.y, b.y, choice), + z: ~Fp::conditional_select(a.z, b.z, choice), + } + } +} + +impl G1Projective { + /// Returns the identity of the group: the point at infinity. + pub fn identity() -> G1Projective { + G1Projective { + x: ~Fp::zero(), + y: ~Fp::one(), + z: ~Fp::zero(), + } + } + + /// Returns a fixed generator of the group. See [`notes::design`](notes/design/index.html#fixed-generators) + /// for how this generator is chosen. + pub fn generator() -> G1Projective { + G1Projective { + x: ~Fp::from_raw_unchecked([ + 0x5cb3_8790_fd53_0c16, + 0x7817_fc67_9976_fff5, + 0x154f_95c7_143b_a1c1, + 0xf0ae_6acd_f3d0_e747, + 0xedce_6ecc_21db_f440, + 0x1201_7741_9e0b_fb75, + ]), + y: ~Fp::from_raw_unchecked([ + 0xbaac_93d5_0ce7_2271, + 0x8c22_631a_7918_fd8e, + 0xdd59_5f13_5707_25ce, + 0x51ac_5829_5040_5194, + 0x0e1c_8c3f_ad00_59c0, + 0x0bbc_3efc_5008_a26a, + ]), + z: ~Fp::one(), + } + } +/* + /// Computes the doubling of this point. + pub fn double(self) -> G1Projective { + // Algorithm 9, https://eprint.iacr.org/2015/1060.pdf + + let t0 = self.y.square(); + let z3 = t0 + t0; + let z3 = z3 + z3; + let z3 = z3 + z3; + let t1 = self.y * self.z; + let t2 = self.z.square(); + let t2 = mul_by_3b(t2); + let x3 = t2 * z3; + let y3 = t0 + t2; + let z3 = t1 * z3; + let t1 = t2 + t2; + let t2 = t1 + t2; + let t0 = t0 - t2; + let y3 = t0 * y3; + let y3 = x3 + y3; + let t1 = self.x * self.y; + let x3 = t0 * t1; + let x3 = x3 + x3; + + let tmp = G1Projective { + x: x3, + y: y3, + z: z3, + }; + + ~G1Projective::conditional_select(tmp, G1Projective::identity(), self.is_identity()) + } + + /// Adds this point to another point. + pub fn add(self, rhs: G1Projective) -> G1Projective { + // Algorithm 7, https://eprint.iacr.org/2015/1060.pdf + + let t0 = self.x * rhs.x; + let t1 = self.y * rhs.y; + let t2 = self.z * rhs.z; + let t3 = self.x + self.y; + let t4 = rhs.x + rhs.y; + let t3 = t3 * t4; + let t4 = t0 + t1; + let t3 = t3 - t4; + let t4 = self.y + self.z; + let x3 = rhs.y + rhs.z; + let t4 = t4 * x3; + let x3 = t1 + t2; + let t4 = t4 - x3; + let x3 = self.x + self.z; + let y3 = rhs.x + rhs.z; + let x3 = x3 * y3; + let y3 = t0 + t2; + let y3 = x3 - y3; + let x3 = t0 + t0; + let t0 = x3 + t0; + let t2 = mul_by_3b(t2); + let z3 = t1 + t2; + let t1 = t1 - t2; + let y3 = mul_by_3b(y3); + let x3 = t4 * y3; + let t2 = t3 * t1; + let x3 = t2 - x3; + let y3 = y3 * t0; + let t1 = t1 * z3; + let y3 = t1 + y3; + let t0 = t0 * t3; + let z3 = z3 * t4; + let z3 = z3 + t0; + + G1Projective { + x: x3, + y: y3, + z: z3, + } + } +*/ } \ No newline at end of file diff --git a/tests_bls12_381/Cargo.toml b/tests_bls12_381/Cargo.toml index d8aa39e..e0b8cd6 100644 --- a/tests_bls12_381/Cargo.toml +++ b/tests_bls12_381/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Elena Fuentes Bongenaar"] edition = "2021" license = "Apache-2.0" +# change to 0.19 [dependencies] fuels = { version = "0.17", features = ["fuel-core-lib"] } tokio = { version = "1.12", features = ["rt", "macros"] } diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 86ca764..889737d 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,6 +1,7 @@ contract; use bls12_381::{fp::*, fp2::*, fp6::*}; + abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; @@ -14,7 +15,10 @@ abi BlsTestContract { #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; - +// These can't be compiled yet.. + // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6; + // #[storage(read, write)]fn square_fp6(a: Fp6) -> Fp6; + } impl BlsTestContract for Contract { @@ -57,4 +61,12 @@ impl BlsTestContract for Contract { #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2 { a.neg() } + + // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6 { + // a * b + // } + + // #[storage(read, write)]fn square_fp6(a: Fp6) -> Fp6 { + // a.square() + // } } \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp6/mod.rs b/tests_bls12_381/tests/tests_fp6/mod.rs index 6a456ef..9eba0d9 100644 --- a/tests_bls12_381/tests/tests_fp6/mod.rs +++ b/tests_bls12_381/tests/tests_fp6/mod.rs @@ -166,3 +166,21 @@ fn get_b() -> Fp6 { b } + + +// #[tokio::test] +// async fn test_square_fp6() { +// let (contract_instance, _id) = get_contract_instance().await; + +// let res_square = contract_instance.square_fp6(get_a()) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; + +// let res_expected = contract_instance.mul_fp6(get_a(), get_a()) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; + +// // assert!();TODO +// } \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_g1/mod.rs b/tests_bls12_381/tests/tests_g1/mod.rs new file mode 100644 index 0000000..5ae316f --- /dev/null +++ b/tests_bls12_381/tests/tests_g1/mod.rs @@ -0,0 +1,8 @@ + + + +// fn test_projective_negation_and_subtraction() { +// let a = G1Projective::generator().double(); +// assert_eq!(a + (-a), G1Projective::identity()); +// assert_eq!(a + (-a), a - a); +// } \ No newline at end of file From a08fd73cc391fdbb9c75d93237b7af328eed45ce Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 3 Aug 2022 17:52:38 -0600 Subject: [PATCH 133/160] - Extract useful functions to utils.sw - Commented out mul of fp2 since it seems to slow down compilation and testing significantly --- bls12_381/src/fp.sw | 28 ++-------------------------- bls12_381/src/fp2.sw | 14 +++++++------- bls12_381/src/util.sw | 30 ++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 33 deletions(-) create mode 100644 bls12_381/src/util.sw diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index f9efcf5..99cd401 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -1,8 +1,10 @@ library fp; dep choice; +dep util; use choice::*; +use util::*; use std::{option::*, u128::*, vec::Vec}; use core::ops::{Eq, Add, Subtract, Multiply}; @@ -53,32 +55,6 @@ const R3: Fp = Fp{ls: [ 0x0aa6_3460_9175_5d4d, ]}; -impl ConditionallySelectable for u64 { - // TODO How can we do this in Sway in constant time? - fn conditional_select(a: u64, b: u64, choice: Choice) -> u64 { - // From original impl: - - // if choice = 0, mask = (-0) = 0000...0000 - // if choice = 1, mask = (-1) = 1111...1111 - - // let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t; - // a ^ (mask & (a ^ b)) - -// Apparently this doesn't work in Sway? - // match choice { - // Choice(0) => a, - // Choice(1) => b, - // } - - // TODO improve. - if (choice.unwrap_u8() == 0) { - a - } else { - b - } - } -} - impl ConditionallySelectable for Fp { fn conditional_select(a: Fp, b: Fp, choice: Choice) -> Fp { Fp{ ls: [ diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index 9b7a3e2..8ce5fae 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -58,7 +58,7 @@ impl Fp2 { c1: c * self.c1, } } - +/* pub fn mul(self, rhs: Fp2) -> Fp2 { // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) // computes the result as: @@ -110,7 +110,7 @@ impl Fp2 { // c1: c1 // } } - +*/ pub fn add(self, rhs: Fp2) -> Fp2 { Fp2 { c0: self.c0 + rhs.c0, @@ -165,8 +165,8 @@ impl Subtract for Fp2 { } } -impl Multiply for Fp2 { - fn multiply(self, other: Self) -> Self { - self.mul(other) - } -} \ No newline at end of file +// impl Multiply for Fp2 { +// fn multiply(self, other: Self) -> Self { +// self.mul(other) +// } +// } \ No newline at end of file diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw new file mode 100644 index 0000000..3da42a9 --- /dev/null +++ b/bls12_381/src/util.sw @@ -0,0 +1,30 @@ +library util; + +dep choice; +use choice::*; + +impl ConditionallySelectable for u64 { + // TODO How can we do this in Sway in constant time? + fn conditional_select(a: u64, b: u64, choice: Choice) -> u64 { + // From original impl: + + // if choice = 0, mask = (-0) = 0000...0000 + // if choice = 1, mask = (-1) = 1111...1111 + + // let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t; + // a ^ (mask & (a ^ b)) + +// Apparently this doesn't work in Sway? + // match choice { + // Choice(0) => a, + // Choice(1) => b, + // } + + // TODO improve. + if (choice.unwrap_u8() == 0) { + a + } else { + b + } + } +} \ No newline at end of file From a96872a2a0638ba29d66b12f1f4e13cc06bb7afc Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 4 Aug 2022 09:43:29 -0600 Subject: [PATCH 134/160] Fuel-rs to version 0.19 in tests_bls12_381. Works in testfile for fp, fp2 and fp6. --- bls12_381/src/fp6.sw | 8 ++- tests_bls12_381/Cargo.toml | 2 +- tests_bls12_381/src/main.sw | 5 ++ tests_bls12_381/tests/tests_fp/mod.rs | 9 ++-- tests_bls12_381/tests/tests_fp2/mod.rs | 9 ++-- tests_bls12_381/tests/tests_fp6/mod.rs | 74 ++++++++++++++++++++++++-- 6 files changed, 94 insertions(+), 13 deletions(-) diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index c71d185..59354c1 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -8,7 +8,7 @@ use fp::*; use fp2::*; use choice::*; -use core::ops::{Multiply}; +use core::ops::{Add, Multiply}; pub struct Fp6 { c0: Fp2, @@ -211,6 +211,12 @@ impl Fp6 { }*/ } +impl Add for Fp6 { + fn add(self, other: Self) -> Self { + self.add(other) + } +} + // impl Multiply for Fp6 { // fn multiply(self, other: Self) -> Self { // self.mul_interleaved(other) diff --git a/tests_bls12_381/Cargo.toml b/tests_bls12_381/Cargo.toml index e0b8cd6..3a1a75e 100644 --- a/tests_bls12_381/Cargo.toml +++ b/tests_bls12_381/Cargo.toml @@ -7,7 +7,7 @@ license = "Apache-2.0" # change to 0.19 [dependencies] -fuels = { version = "0.17", features = ["fuel-core-lib"] } +fuels = { version = "0.19", features = ["fuel-core-lib"] } tokio = { version = "1.12", features = ["rt", "macros"] } [[test]] diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 889737d..5a1e036 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -15,6 +15,7 @@ abi BlsTestContract { #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; + #[storage(read, write)]fn add_fp6(a: Fp6, b: Fp6) -> Fp6; // These can't be compiled yet.. // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6; // #[storage(read, write)]fn square_fp6(a: Fp6) -> Fp6; @@ -62,6 +63,10 @@ impl BlsTestContract for Contract { a.neg() } + #[storage(read, write)]fn add_fp6(a: Fp6, b: Fp6) -> Fp6 { + a + b + } + // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6 { // a * b // } diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index 9133b33..dc17120 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -1,9 +1,12 @@ -use fuels::{prelude::*, tx::ContractId}; +use fuels::{ + prelude::*, + tx::{ConsensusParameters, ContractId}, +}; // Load abi from json abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); -async fn get_contract_instance() -> (BlsTestContract, ContractId) { +async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { // Launch a local network and deploy the contract let wallet = launch_provider_and_get_wallet().await; @@ -16,7 +19,7 @@ async fn get_contract_instance() -> (BlsTestContract, ContractId) { .await .unwrap(); - let instance = BlsTestContract::new(id.to_string(), wallet); + let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); (instance, id) } diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index 12d0e43..fa0cf06 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -1,9 +1,12 @@ -use fuels::{prelude::*, tx::ContractId}; +use fuels::{ + prelude::*, + tx::{ConsensusParameters, ContractId}, +}; // Load abi from json abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); -async fn get_contract_instance() -> (BlsTestContract, ContractId) { +async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { // Launch a local network and deploy the contract let wallet = launch_provider_and_get_wallet().await; @@ -16,7 +19,7 @@ async fn get_contract_instance() -> (BlsTestContract, ContractId) { .await .unwrap(); - let instance = BlsTestContract::new(id.to_string(), wallet); + let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); (instance, id) } diff --git a/tests_bls12_381/tests/tests_fp6/mod.rs b/tests_bls12_381/tests/tests_fp6/mod.rs index 9eba0d9..4ab52a4 100644 --- a/tests_bls12_381/tests/tests_fp6/mod.rs +++ b/tests_bls12_381/tests/tests_fp6/mod.rs @@ -1,9 +1,12 @@ -use fuels::{prelude::*, tx::ContractId}; +use fuels::{ + prelude::*, + tx::{ConsensusParameters, ContractId}, +}; // Load abi from json abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); -async fn get_contract_instance() -> (BlsTestContract, ContractId) { +async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { // Launch a local network and deploy the contract let wallet = launch_provider_and_get_wallet().await; @@ -16,7 +19,7 @@ async fn get_contract_instance() -> (BlsTestContract, ContractId) { .await .unwrap(); - let instance = BlsTestContract::new(id.to_string(), wallet); + let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); (instance, id) } @@ -44,7 +47,7 @@ pub fn res_equals(res: Fp2, should_be: Fp2) -> bool { assert!(c1_res.ls[5] == c1_should_be.ls[5]); true } - +/* fn get_a() -> Fp6 { let a = Fp6 { c_0: Fp2 { @@ -166,7 +169,68 @@ fn get_b() -> Fp6 { b } - +*/ +#[tokio::test] +async fn test_fp6() { + let (contract_instance, _id) = get_contract_instance().await; + let a = Fp6 { + c_0: Fp2 { + c_0: Fp{ls: [ + 0x47f9_cb98_b1b8_2d58, + 0x5fe9_11eb_a3aa_1d9d, + 0x96bf_1b5f_4dd8_1db3, + 0x8100_d27c_c925_9f5b, + 0xafa2_0b96_7464_0eab, + 0x09bb_cea7_d8d9_497d, + ].to_vec()}, + c_1: Fp{ls: [ + 0x0303_cb98_b166_2daa, + 0xd931_10aa_0a62_1d5a, + 0xbfa9_820c_5be4_a468, + 0x0ba3_643e_cb05_a348, + 0xdc35_34bb_1f1c_25a6, + 0x06c3_05bb_19c0_e1c1, + ].to_vec()}, + }, + c_1: Fp2 { + c_0: Fp{ls: [ + 0x46f9_cb98_b162_d858, + 0x0be9_109c_f7aa_1d57, + 0xc791_bc55_fece_41d2, + 0xf84c_5770_4e38_5ec2, + 0xcb49_c1d9_c010_e60f, + 0x0acd_b8e1_58bf_e3c8, + ].to_vec()}, + c_1: Fp{ls: [ + 0x8aef_cb98_b15f_8306, + 0x3ea1_108f_e4f2_1d54, + 0xcf79_f69f_a1b7_df3b, + 0xe4f5_4aa1_d16b_1a3c, + 0xba5e_4ef8_6105_a679, + 0x0ed8_6c07_97be_e5cf, + ].to_vec()}, + }, + c_2: Fp2 { + c_0: Fp{ls: [ + 0xcee5_cb98_b15c_2db4, + 0x7159_1082_d23a_1d51, + 0xd762_30e9_44a1_7ca4, + 0xd19e_3dd3_549d_d5b6, + 0xa972_dc17_01fa_66e3, + 0x12e3_1f2d_d6bd_e7d6, + ].to_vec()}, + c_1: Fp{ls: [ + 0xad2a_cb98_b173_2d9d, + 0x2cfd_10dd_0696_1d64, + 0x0739_6b86_c6ef_24e8, + 0xbd76_e2fd_b1bf_c820, + 0x6afe_a7f6_de94_d0d5, + 0x1099_4b0c_5744_c040, + ].to_vec()}, + }, + }; + assert!(true); +} // #[tokio::test] // async fn test_square_fp6() { From 0b74ed1b498ef7df6900d1e2d8ec1aae27d98612 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 4 Aug 2022 12:15:55 -0600 Subject: [PATCH 135/160] - Start on scalar.sw - Moved some functions to util.sw so it can be used in multiple places --- bls12_381/src/fp.sw | 50 +------- bls12_381/src/fp2.sw | 3 +- bls12_381/src/lib.sw | 3 +- bls12_381/src/scalar.sw | 146 ++++++++++++++++++++++ bls12_381/src/util.sw | 45 +++++++ tests_bls12_381/src/main.sw | 7 +- tests_bls12_381/tests/harness.rs | 5 +- tests_bls12_381/tests/tests_fp6/mod.rs | 38 +++--- tests_bls12_381/tests/tests_scalar/mod.rs | 84 +++++++++++++ 9 files changed, 309 insertions(+), 72 deletions(-) create mode 100644 bls12_381/src/scalar.sw create mode 100644 tests_bls12_381/tests/tests_scalar/mod.rs diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 99cd401..bf93eba 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -72,18 +72,6 @@ fn not(input: u64) -> u64 { ~u64::max() - input } -// TODO rewrite without if branch -// If x >= y: x-y, else max::U128 - (y-x) -pub fn subtract_wrap(x: U128, y: U128) -> U128 { - if y > x { - ~U128::max() - (y - x - U128 { - lower: 1, upper: 0 - }) - } else { - x - y - } -} - // TODO rewrite without if branch // If x >= y: x-y, else max::U64 - (y-x) pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { @@ -94,37 +82,6 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { } } -/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). -pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - let borrow_128: U128 = ~U128::from(0, borrow); - - let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); - (res.lower, res.upper >> 63) //(result, borrow) -} - -//returns sum with carry of a and b -pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - let carry_128: U128 = ~U128::from(0, carry); - - let sum = a_128 + b_128 + carry_128; - (sum.lower, sum.upper) -} - - -//returns the result and new carry of a + b*c + carry -pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - let c_128: U128 = ~U128::from(0, c); - let carry_128: U128 = ~U128::from(0, carry); - - let res: U128 = a_128 + (b_128 * c_128) + carry_128; - (res.lower, res.upper) -} //returns a*b mod(2^64) pub fn multiply_wrap(a: u64, b: u64) -> u64 { @@ -223,7 +180,7 @@ impl Fp { // is smaller than the modulus. (Fp{ls:[d0, d1, d2, d3, d4, d5]}).subtract_p() } - +/* pub fn mul(self, rhs: Fp) -> Fp { let self0 = self.ls[0]; let self1 = self.ls[1]; @@ -334,6 +291,7 @@ impl Fp { let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) } + */ } impl Fp { @@ -541,7 +499,7 @@ impl Subtract for Fp { self.sub(other) } } - +/* impl Multiply for Fp { fn multiply(self, other: Self) -> Self { self.mul(other) @@ -605,4 +563,4 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r11_12 = adc(t[11], r10_11.1, r10.1); (Fp { ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}).subtract_p() -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index 8ce5fae..f8d7855 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -34,7 +34,7 @@ impl Fp2 { fn eq(self, other: Self) -> bool { self.c0 == other.c0 && self.c1 == other.c1 } - +/* // //TODO test pub fn square(self) -> Fp2 { // Complex squaring: @@ -58,6 +58,7 @@ impl Fp2 { c1: c * self.c1, } } + */ /* pub fn mul(self, rhs: Fp2) -> Fp2 { // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) diff --git a/bls12_381/src/lib.sw b/bls12_381/src/lib.sw index 9be59c9..8ed37e4 100644 --- a/bls12_381/src/lib.sw +++ b/bls12_381/src/lib.sw @@ -2,4 +2,5 @@ library bls12_381; dep fp; dep fp2; -dep fp6; \ No newline at end of file +dep fp6; +dep scalar; \ No newline at end of file diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw new file mode 100644 index 0000000..6e21a23 --- /dev/null +++ b/bls12_381/src/scalar.sw @@ -0,0 +1,146 @@ +library scalar; + +dep choice; +dep util; + +use choice::*; +use util::*; + +use core::ops::{Eq, Add, Subtract, Multiply}; + +pub struct Scalar { ls: [u64; 4] } + +/// Constant representing the modulus +/// q = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 +pub const MODULUS_SCALAR: Scalar = Scalar{ ls: [ + 0xffff_ffff_0000_0001, + 0x53bd_a402_fffe_5bfe, + 0x3339_d808_09a1_d805, + 0x73ed_a753_299d_7d48, +]}; + +/// The modulus as u32 limbs. +const MODULUS_LIMBS_32: [u32; 8] = [ + 0x0000_0001, + 0xffff_ffff, + 0xfffe_5bfe, + 0x53bd_a402, + 0x09a1_d805, + 0x3339_d808, + 0x299d_7d48, + 0x73ed_a753, +]; + +// The number of bits needed to represent the modulus. +const MODULUS_BITS: u32 = 255; + +const GENERATOR: Scalar = Scalar{ ls: [ + 0x0000_000e_ffff_fff1, + 0x17e3_63d3_0018_9c0f, + 0xff9c_5787_6f84_57b0, + 0x3513_3220_8fc5_a8c4, +]}; + +/// INV = -(q^{-1} mod 2^64) mod 2^64 +const INV: u64 = 0xffff_fffe_ffff_ffff; + +/// R = 2^256 mod q +const R: Scalar = Scalar{ ls: [ + 0x0000_0001_ffff_fffe, + 0x5884_b7fa_0003_4802, + 0x998c_4fef_ecbc_4ff5, + 0x1824_b159_acc5_056f, +]}; + +/// R^2 = 2^512 mod q +const R2: Scalar = Scalar{ ls: [ + 0xc999_e990_f3f2_9c6d, + 0x2b6c_edcb_8792_5c23, + 0x05d3_1496_7254_398f, + 0x0748_d9d9_9f59_ff11, +]}; + +/// R^3 = 2^768 mod q +const R3: Scalar = Scalar{ ls: [ + 0xc62c_1807_439b_73af, + 0x1b3e_0d18_8cf0_6990, + 0x73d1_3c71_c7b5_f418, + 0x6e2a_5bb9_c8db_33e9, +]}; + +// 2^S * t = MODULUS - 1 with t odd +const ls: u32 = 32; + +const ROOT_OF_UNITY: Scalar = Scalar{ ls: [ + 0xb9b5_8d8c_5f0e_466a, + 0x5b1b_4c80_1819_d7ec, + 0x0af5_3ae3_52a3_1e64, + 0x5bf3_adda_19e9_b27b, +]}; + +impl Scalar { + + pub fn zero() -> Scalar { + Scalar{ ls: [0, 0, 0, 0]} + } + + pub fn one() -> Scalar { + R + } + + // TODO to make this constant time the u64 should be compared with ct_eq, but is not existing in Sway (yet) + pub fn eq(self, other: Self) -> bool { + (self.ls[0] == other.ls[0]) + && (self.ls[1] == other.ls[1]) + && (self.ls[2] == other.ls[2]) + && (self.ls[3] == other.ls[3]) + } + + pub fn sub(self, rhs: Self) -> Self { + let (d0, borrow) = sbb(self.ls[0], rhs.ls[0], 0); + let (d1, borrow) = sbb(self.ls[1], rhs.ls[1], borrow); + let (d2, borrow) = sbb(self.ls[2], rhs.ls[2], borrow); + let (d3, borrow) = sbb(self.ls[3], rhs.ls[3], borrow); + + // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise + // borrow = 0x000.. .ls00. Thus, we use it as a mask to conditionally add the modulus. + let (d0, carry) = adc(d0, MODULUS_SCALAR.ls[0] & borrow, 0); + let (d1, carry) = adc(d1, MODULUS_SCALAR.ls[1] & borrow, carry); + let (d2, carry) = adc(d2, MODULUS_SCALAR.ls[2] & borrow, carry); + let (d3, _) = adc(d3, MODULUS_SCALAR.ls[3] & borrow, carry); + + Scalar{ ls: [d0, d1, d2, d3]} + } +} + +impl Scalar { + + /// Adds `rhs` to `self`, returning the result. + pub fn add(self, rhs: Self) -> Self { + let (d0, carry) = adc(self.ls[0], rhs.ls[0], 0); + let (d1, carry) = adc(self.ls[1], rhs.ls[1], carry); + let (d2, carry) = adc(self.ls[2], rhs.ls[2], carry); + let (d3, _) = adc(self.ls[3], rhs.ls[3], carry); + + // Attempt to subtract the modulus, to ensure the value + // is smaller than the modulus. + (Scalar{ls:[d0, d1, d2, d3]}).sub(MODULUS_SCALAR) + } +} + +impl ConditionallySelectable for Scalar { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + Scalar{ ls: [ + ~u64::conditional_select(a.ls[0], b.ls[0], choice), + ~u64::conditional_select(a.ls[1], b.ls[1], choice), + ~u64::conditional_select(a.ls[2], b.ls[2], choice), + ~u64::conditional_select(a.ls[3], b.ls[3], choice), + ]} + } +} + +impl Add for Scalar { + fn add(self, other: Self) -> Self { + self.add(other) + } +} \ No newline at end of file diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw index 3da42a9..f774116 100644 --- a/bls12_381/src/util.sw +++ b/bls12_381/src/util.sw @@ -2,6 +2,7 @@ library util; dep choice; use choice::*; +use std::{u128::*}; impl ConditionallySelectable for u64 { // TODO How can we do this in Sway in constant time? @@ -27,4 +28,48 @@ impl ConditionallySelectable for u64 { b } } +} + +// TODO rewrite without if branch +// If x >= y: x-y, else max::U128 - (y-x) +pub fn subtract_wrap(x: U128, y: U128) -> U128 { + if y > x { + ~U128::max() - (y - x - U128 { + lower: 1, upper: 0 + }) + } else { + x - y + } +} + +/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). +pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let borrow_128: U128 = ~U128::from(0, borrow); + + let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); + (res.lower, res.upper >> 63) //(result, borrow) +} + +//returns sum with carry of a and b +pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let carry_128: U128 = ~U128::from(0, carry); + + let sum = a_128 + b_128 + carry_128; + (sum.lower, sum.upper) +} + + +//returns the result and new carry of a + b*c + carry +pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + let c_128: U128 = ~U128::from(0, c); + let carry_128: U128 = ~U128::from(0, carry); + + let res: U128 = a_128 + (b_128 * c_128) + carry_128; + (res.lower, res.upper) } \ No newline at end of file diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 5a1e036..e88cd84 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,6 +1,6 @@ contract; -use bls12_381::{fp::*, fp2::*, fp6::*}; +use bls12_381::{fp::*, fp2::*, fp6::*, scalar::*}; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; @@ -15,7 +15,8 @@ abi BlsTestContract { #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; - #[storage(read, write)]fn add_fp6(a: Fp6, b: Fp6) -> Fp6; + #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; + // These can't be compiled yet.. // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6; // #[storage(read, write)]fn square_fp6(a: Fp6) -> Fp6; @@ -63,7 +64,7 @@ impl BlsTestContract for Contract { a.neg() } - #[storage(read, write)]fn add_fp6(a: Fp6, b: Fp6) -> Fp6 { + #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar { a + b } diff --git a/tests_bls12_381/tests/harness.rs b/tests_bls12_381/tests/harness.rs index 4c540a5..3c61e3f 100644 --- a/tests_bls12_381/tests/harness.rs +++ b/tests_bls12_381/tests/harness.rs @@ -1,3 +1,4 @@ // mod tests_fp; -mod tests_fp2; -// mod tests_fp6; \ No newline at end of file +// mod tests_fp2; +// mod tests_fp6; +mod tests_scalar; \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp6/mod.rs b/tests_bls12_381/tests/tests_fp6/mod.rs index 4ab52a4..0039855 100644 --- a/tests_bls12_381/tests/tests_fp6/mod.rs +++ b/tests_bls12_381/tests/tests_fp6/mod.rs @@ -24,29 +24,29 @@ async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { (instance, id) } +fn res_equals_fp(res: Fp, should_be: Fp) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + assert!(res.ls[4] == should_be.ls[4]); + assert!(res.ls[5] == should_be.ls[5]); + true +} -pub fn res_equals(res: Fp2, should_be: Fp2) -> bool { - - let c0_res = res.c_0; - let c1_res = res.c_1; - let c0_should_be = should_be.c_0; - let c1_should_be = should_be.c_1; - - assert!(c0_res.ls[0] == c0_should_be.ls[0]); - assert!(c0_res.ls[1] == c0_should_be.ls[1]); - assert!(c0_res.ls[2] == c0_should_be.ls[2]); - assert!(c0_res.ls[3] == c0_should_be.ls[3]); - assert!(c0_res.ls[4] == c0_should_be.ls[4]); - assert!(c0_res.ls[5] == c0_should_be.ls[5]); +fn res_equals_fp2(res: Fp2, c: Fp2) -> bool { + assert!(res_equals_fp(res.c_0, c.c_0)); + assert!(res_equals_fp(res.c_1, c.c_1)); + true +} - assert!(c1_res.ls[0] == c1_should_be.ls[0]); - assert!(c1_res.ls[1] == c1_should_be.ls[1]); - assert!(c1_res.ls[2] == c1_should_be.ls[2]); - assert!(c1_res.ls[3] == c1_should_be.ls[3]); - assert!(c1_res.ls[4] == c1_should_be.ls[4]); - assert!(c1_res.ls[5] == c1_should_be.ls[5]); +fn res_equals(res: Fp6, c: Fp6) -> bool { + assert!(res_equals_fp2(res.c_0, c.c_0)); + assert!(res_equals(res.c_1, c.c_1)); + assert!(res_equals(res.c_2, c.c_2)); true } + /* fn get_a() -> Fp6 { let a = Fp6 { diff --git a/tests_bls12_381/tests/tests_scalar/mod.rs b/tests_bls12_381/tests/tests_scalar/mod.rs new file mode 100644 index 0000000..4fedc9d --- /dev/null +++ b/tests_bls12_381/tests/tests_scalar/mod.rs @@ -0,0 +1,84 @@ +use fuels::{ + prelude::*, + tx::{ConsensusParameters, ContractId}, +}; + +abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); + +async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { + // Launch a local network and deploy the contract + let wallet = launch_provider_and_get_wallet().await; + + let id = Contract::deploy( + "./out/debug/tests_bls12_381.bin", + &wallet, + TxParameters::default(), + StorageConfiguration::with_storage_path(None) + ) + .await + .unwrap(); + + let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); + + (instance, id) +} + +fn scalar_equals(res: Scalar, should_be: Scalar) -> bool { + assert!(res.ls[0] == should_be.ls[0]); + assert!(res.ls[1] == should_be.ls[1]); + assert!(res.ls[2] == should_be.ls[2]); + assert!(res.ls[3] == should_be.ls[3]); + true +} + +#[tokio::test] +async fn test_addition() { + let a: Scalar = Scalar{ ls: [ + 0xffff_ffff_0000_0000, + 0x53bd_a402_fffe_5bfe, + 0x3339_d808_09a1_d805, + 0x73ed_a753_299d_7d48, + ].to_vec()}; + + let mut a_again = Scalar{ ls: [ + 0xffff_ffff_0000_0000, + 0x53bd_a402_fffe_5bfe, + 0x3339_d808_09a1_d805, + 0x73ed_a753_299d_7d48, + ].to_vec()}; + + let expected_res = Scalar{ ls:[ + 0xffff_fffe_ffff_ffff, + 0x53bd_a402_fffe_5bfe, + 0x3339_d808_09a1_d805, + 0x73ed_a753_299d_7d48, + ].to_vec()}; + + let (contract_instance, _id) = get_contract_instance().await; + + let res = contract_instance.add_scalar(a, a_again) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(scalar_equals(res, expected_res)); +} +// fn test_addition() { +// let mut tmp = LARGEST; +// tmp += &LARGEST; + +// assert_eq!( +// tmp, +// Scalar([ +// 0xffff_fffe_ffff_ffff, +// 0x53bd_a402_fffe_5bfe, +// 0x3339_d808_09a1_d805, +// 0x73ed_a753_299d_7d48, +// ]) +// ); + +// let mut tmp = LARGEST; +// tmp += &Scalar([1, 0, 0, 0]); + +// assert_eq!(tmp, Scalar::zero()); +// } \ No newline at end of file From 27e51f798d6952df16cc768d83e50e71d572a1e2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 4 Aug 2022 15:56:40 -0600 Subject: [PATCH 136/160] - Added functions to scalar.sw - Some functions added or moved to util.sw - Importing choice into the testing contract gives an Internal compiler error --- bls12_381/src/choice.sw | 31 ++- bls12_381/src/fp.sw | 29 +-- bls12_381/src/lib.sw | 3 +- bls12_381/src/scalar.sw | 237 +++++++++++++++++++++- bls12_381/src/util.sw | 18 ++ tests_bls12_381/src/main.sw | 12 ++ tests_bls12_381/tests/tests_scalar/mod.rs | 89 ++++++-- 7 files changed, 364 insertions(+), 55 deletions(-) diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 2714bf8..6f5b643 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -26,9 +26,21 @@ impl Choice { self.c } + pub fn unwrap_as_bool(self) -> bool { + self.c == 1u8 + } + pub fn from(input: u8) -> Choice { Choice{ c: input} } + + pub fn from_bool(b: bool) -> Choice { + if b { + Choice{ c: 1u8} + } else { + Choice{ c: 0u8} + } + } } @@ -54,12 +66,19 @@ impl CtOption { } } - pub fn new(value: T, is_some: bool) -> CtOption { - match is_some { - true => CtOption {value: value, is_some: Choice{ c: 1 },}, - false => CtOption {value: value, is_some: Choice{ c: 0 },}, - } - + pub fn new_from_bool(value: T, is_some: bool) -> CtOption { + match is_some { + true => CtOption {value: value, is_some: Choice{ c: 1 },}, + false => CtOption {value: value, is_some: Choice{ c: 0 },}, + } + } + + pub fn is_none(self) -> bool { + !self.is_some.unwrap_as_bool() + } + + pub fn unwrap(self) -> T { + self.value } } diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index bf93eba..90517b1 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -82,15 +82,6 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { } } - -//returns a*b mod(2^64) -pub fn multiply_wrap(a: u64, b: u64) -> u64 { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - - (a_128 * b_128).lower -} - impl Fp { pub fn zero() -> Fp { Fp{ls: [0, 0, 0, 0, 0, 0]} @@ -351,7 +342,7 @@ impl Fp { // // Algorithm 2, lines 4-5 // // This is a single step of the usual Montgomery reduction process. - // let k = multiply_wrap(t0, INV); + // let k = wrapping_mul(t0, INV); // let (_, carry) = mac(t0, k, MODULUS[0], 0); // let (r1, carry) = mac(t1, k, MODULUS[1], carry); // let (r2, carry) = mac(t2, k, MODULUS[2], carry); @@ -401,7 +392,7 @@ impl Fp { let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); let (t6, _) = adc(t6, 0, carry); - let k = multiply_wrap(t0, INV); + let k = wrapping_mul(t0, INV); let (_, carry) = mac(t0, k, MODULUS[0], 0); let (u1, carry) = mac(t1, k, MODULUS[1], carry); let (u2, carry) = mac(t2, k, MODULUS[2], carry); @@ -442,7 +433,7 @@ impl Fp { // let (t6, _) = adc(t6, 0, carry); // i += 1; // } - // let k = multiply_wrap(t0, INV); + // let k = wrapping_mul(t0, INV); // let (_, carry) = mac(t0, k, MODULUS[0], 0); // let (u1, carry) = mac(t1, k, MODULUS[1], carry); // let (u2, carry) = mac(t2, k, MODULUS[2], carry); @@ -478,7 +469,7 @@ impl Fp { 0x1a01_11ea_397f_e69a, ]); - ~CtOption::new(t, !self.is_zero()) + ~CtOption::new_from_bool(t, !self.is_zero()) } } @@ -507,7 +498,7 @@ impl Multiply for Fp { } pub fn montgomery_reduce(t: [u64;12]) -> Fp { - let k = multiply_wrap(t[0], INV); + let k = wrapping_mul(t[0], INV); let r0: (u64, u64) = mac(t[0], k, MODULUS[0], 0); let r1: (u64, u64) = mac(t[1], k, MODULUS[1], r0.1); @@ -517,7 +508,7 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r5: (u64, u64) = mac(t[5], k, MODULUS[5], r4.1); let r6_7: (u64, u64) = adc(t[6], 0, r5.1); - let k = multiply_wrap(r1.0, INV); + let k = wrapping_mul(r1.0, INV); let r0: (u64, u64) = mac(r1.0, k, MODULUS[0], 0); let r2: (u64, u64) = mac(r2.0, k, MODULUS[1], r0.1); let r3: (u64, u64) = mac(r3.0, k, MODULUS[2], r2.1); @@ -526,7 +517,7 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r6: (u64, u64) = mac(r6_7.0, k, MODULUS[5], r5.1); let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); - let k = multiply_wrap(r2.0, INV); + let k = wrapping_mul(r2.0, INV); let r0: (u64, u64) = mac(r2.0, k, MODULUS[0], 0); let r3: (u64, u64) = mac(r3.0, k, MODULUS[1], r0.1); let r4: (u64, u64) = mac(r4.0, k, MODULUS[2], r3.1); @@ -535,7 +526,7 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r7: (u64, u64) = mac(r7_8.0, k, MODULUS[5], r6.1); let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); - let k = multiply_wrap(r3.0, INV); + let k = wrapping_mul(r3.0, INV); let r0: (u64, u64) = mac(r3.0, k, MODULUS[0], 0); let r4: (u64, u64) = mac(r4.0, k, MODULUS[1], r0.1); let r5: (u64, u64) = mac(r5.0, k, MODULUS[2], r4.1); @@ -544,7 +535,7 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r8: (u64, u64) = mac(r8_9.0, k, MODULUS[5], r7.1); let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); - let k = multiply_wrap(r4.0, INV); + let k = wrapping_mul(r4.0, INV); let r0: (u64, u64) = mac(r4.0, k, MODULUS[0], 0); let r5: (u64, u64) = mac(r5.0, k, MODULUS[1], r0.1); let r6: (u64, u64) = mac(r6.0, k, MODULUS[2], r5.1); @@ -553,7 +544,7 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r9: (u64, u64) = mac(r9_10.0, k, MODULUS[5], r8.1); let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); - let k = multiply_wrap(r5.0, INV); + let k = wrapping_mul(r5.0, INV); let r0: (u64, u64) = mac(r5.0, k, MODULUS[0], 0); let r6: (u64, u64) = mac(r6.0, k, MODULUS[1], r0.1); let r7: (u64, u64) = mac(r7.0, k, MODULUS[2], r6.1); diff --git a/bls12_381/src/lib.sw b/bls12_381/src/lib.sw index 8ed37e4..35ac567 100644 --- a/bls12_381/src/lib.sw +++ b/bls12_381/src/lib.sw @@ -3,4 +3,5 @@ library bls12_381; dep fp; dep fp2; dep fp6; -dep scalar; \ No newline at end of file +dep scalar; +dep choice; \ No newline at end of file diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index 6e21a23..414f7c8 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -69,7 +69,7 @@ const R3: Scalar = Scalar{ ls: [ ]}; // 2^S * t = MODULUS - 1 with t odd -const ls: u32 = 32; +const S: u32 = 32; const ROOT_OF_UNITY: Scalar = Scalar{ ls: [ 0xb9b5_8d8c_5f0e_466a, @@ -78,6 +78,17 @@ const ROOT_OF_UNITY: Scalar = Scalar{ ls: [ 0x5bf3_adda_19e9_b27b, ]}; +impl ConditionallySelectable for Scalar { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + Scalar{ ls: [ + ~u64::conditional_select(a.ls[0], b.ls[0], choice), + ~u64::conditional_select(a.ls[1], b.ls[1], choice), + ~u64::conditional_select(a.ls[2], b.ls[2], choice), + ~u64::conditional_select(a.ls[3], b.ls[3], choice), + ]} + } +} + impl Scalar { pub fn zero() -> Scalar { @@ -88,6 +99,14 @@ impl Scalar { R } + fn ct(self, other: Self) -> Choice { + ~Choice::from_bool( + self.ls[0] == other.ls[0] + && self.ls[1] == other.ls[1] + && self.ls[2] == other.ls[2] + && self.ls[3] == other.ls[3]) + } + // TODO to make this constant time the u64 should be compared with ct_eq, but is not existing in Sway (yet) pub fn eq(self, other: Self) -> bool { (self.ls[0] == other.ls[0]) @@ -126,16 +145,114 @@ impl Scalar { // is smaller than the modulus. (Scalar{ls:[d0, d1, d2, d3]}).sub(MODULUS_SCALAR) } + + pub fn montgomery_reduce( + r0: u64, + r1: u64, + r2: u64, + r3: u64, + r4: u64, + r5: u64, + r6: u64, + r7: u64, + ) -> Self { + // The Montgomery reduction here is based on Algorithm 14.32 in + // Handbook of Applied Cryptography + // . + + let k = wrapping_mul(r0, INV); + let (_, carry) = mac(r0, k, MODULUS_SCALAR.ls[0], 0); + let (r1, carry) = mac(r1, k, MODULUS_SCALAR.ls[1], carry); + let (r2, carry) = mac(r2, k, MODULUS_SCALAR.ls[2], carry); + let (r3, carry) = mac(r3, k, MODULUS_SCALAR.ls[3], carry); + let (r4, carry2) = adc(r4, 0, carry); + + let k = wrapping_mul(r1, INV); + let (_, carry) = mac(r1, k, MODULUS_SCALAR.ls[0], 0); + let (r2, carry) = mac(r2, k, MODULUS_SCALAR.ls[1], carry); + let (r3, carry) = mac(r3, k, MODULUS_SCALAR.ls[2], carry); + let (r4, carry) = mac(r4, k, MODULUS_SCALAR.ls[3], carry); + let (r5, carry2) = adc(r5, carry2, carry); + + let k = wrapping_mul(r2, INV); + let (_, carry) = mac(r2, k, MODULUS_SCALAR.ls[0], 0); + let (r3, carry) = mac(r3, k, MODULUS_SCALAR.ls[1], carry); + let (r4, carry) = mac(r4, k, MODULUS_SCALAR.ls[2], carry); + let (r5, carry) = mac(r5, k, MODULUS_SCALAR.ls[3], carry); + let (r6, carry2) = adc(r6, carry2, carry); + + let k = wrapping_mul(r3, INV); + let (_, carry) = mac(r3, k, MODULUS_SCALAR.ls[0], 0); + let (r4, carry) = mac(r4, k, MODULUS_SCALAR.ls[1], carry); + let (r5, carry) = mac(r5, k, MODULUS_SCALAR.ls[2], carry); + let (r6, carry) = mac(r6, k, MODULUS_SCALAR.ls[3], carry); + let (r7, _) = adc(r7, carry2, carry); + + // Result may be within MODULUS of the correct value + (Scalar{ ls:[r4, r5, r6, r7]}).sub(MODULUS_SCALAR) + } } -impl ConditionallySelectable for Scalar { - fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { - Scalar{ ls: [ - ~u64::conditional_select(a.ls[0], b.ls[0], choice), - ~u64::conditional_select(a.ls[1], b.ls[1], choice), - ~u64::conditional_select(a.ls[2], b.ls[2], choice), - ~u64::conditional_select(a.ls[3], b.ls[3], choice), - ]} +impl Scalar { + pub fn mul(self, rhs: Self) -> Self { + // Schoolbook multiplication + + let (r0, carry) = mac(0, self.ls[0], rhs.ls[0], 0); + let (r1, carry) = mac(0, self.ls[0], rhs.ls[1], carry); + let (r2, carry) = mac(0, self.ls[0], rhs.ls[2], carry); + let (r3, r4) = mac(0, self.ls[0], rhs.ls[3], carry); + + let (r1, carry) = mac(r1, self.ls[1], rhs.ls[0], 0); + let (r2, carry) = mac(r2, self.ls[1], rhs.ls[1], carry); + let (r3, carry) = mac(r3, self.ls[1], rhs.ls[2], carry); + let (r4, r5) = mac(r4, self.ls[1], rhs.ls[3], carry); + + let (r2, carry) = mac(r2, self.ls[2], rhs.ls[0], 0); + let (r3, carry) = mac(r3, self.ls[2], rhs.ls[1], carry); + let (r4, carry) = mac(r4, self.ls[2], rhs.ls[2], carry); + let (r5, r6) = mac(r5, self.ls[2], rhs.ls[3], carry); + + let (r3, carry) = mac(r3, self.ls[3], rhs.ls[0], 0); + let (r4, carry) = mac(r4, self.ls[3], rhs.ls[1], carry); + let (r5, carry) = mac(r5, self.ls[3], rhs.ls[2], carry); + let (r6, r7) = mac(r6, self.ls[3], rhs.ls[3], carry); + + ~Scalar::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7) + } + + pub fn square(self) -> Scalar { + let (r1, carry) = mac(0, self.ls[0], self.ls[1], 0); + let (r2, carry) = mac(0, self.ls[0], self.ls[2], carry); + let (r3, r4) = mac(0, self.ls[0], self.ls[3], carry); + + let (r3, carry) = mac(r3, self.ls[1], self.ls[2], 0); + let (r4, r5) = mac(r4, self.ls[1], self.ls[3], carry); + + let (r5, r6) = mac(r5, self.ls[2], self.ls[3], 0); + + let r7 = r6 >> 63; + let r6 = (r6 << 1) | (r5 >> 63); + let r5 = (r5 << 1) | (r4 >> 63); + let r4 = (r4 << 1) | (r3 >> 63); + let r3 = (r3 << 1) | (r2 >> 63); + let r2 = (r2 << 1) | (r1 >> 63); + let r1 = r1 << 1; + + let (r0, carry) = mac(0, self.ls[0], self.ls[0], 0); + let (r1, carry) = adc(0, r1, carry); + let (r2, carry) = mac(r2, self.ls[1], self.ls[1], carry); + let (r3, carry) = adc(0, r3, carry); + let (r4, carry) = mac(r4, self.ls[2], self.ls[2], carry); + let (r5, carry) = adc(0, r5, carry); + let (r6, carry) = mac(r6, self.ls[3], self.ls[3], carry); + let (r7, _) = adc(0, r7, carry); + + ~Scalar::montgomery_reduce(r0, r1, r2, r3, r4, r5, r6, r7) + } + + pub fn double(self) -> Scalar { + // TODO: This can be achieved more efficiently with a bitshift. + self.add(self) } } @@ -143,4 +260,106 @@ impl Add for Scalar { fn add(self, other: Self) -> Self { self.add(other) } +} + +impl Multiply for Scalar { + fn multiply(self, other: Self) -> Self { + self.mul(other) + } +} + +impl Scalar { + + fn from(val: u64) -> Scalar { + Scalar{ ls: [val, 0, 0, 0]} * R2 + } +} + +impl Scalar { + + /// Exponentiates `self` by `by`, where `by` is a + /// little-endian order integer exponent. + /// + /// **This operation is variable time with respect + /// to the exponent.** If the exponent is fixed, + /// this operation is effectively constant time. + pub fn pow_vartime(self, by: [u64; 4]) -> Self { + let mut res = ~Self::one(); + let mut i = 4; + while i > 0 { + let e = by[i -1]; + let mut j = 65; + while j > 0 { + res = res.square(); + + if ((e >> (j-1)) & 1) == 1 { + res *= self; + // res.mul_assign(self); + } + j -= 1; + } + i -= 1; + } + res + } +} + +impl Scalar { + + /// Computes the square root of this element, if it exists. + pub fn sqrt(self) -> CtOption { + // Tonelli-Shank's algorithm for q mod 16 = 1 + // https://eprint.iacr.org/2012/685.pdf (page 12, algorithm 5) + + // w = self^((t - 1) // 2) + // = self^6104339283789297388802252303364915521546564123189034618274734669823 + let w = self.pow_vartime([ + 0x7fff_2dff_7fff_ffff, + 0x04d0_ec02_a9de_d201, + 0x94ce_bea4_199c_ec04, + 0x0000_0000_39f6_d3a9, + ]); + + let mut v = S; + let mut x = self * w; + let mut b = x * w; + + // Initialize z as the 2^S root of unity. + let mut z = ROOT_OF_UNITY; + + let mut max_v = S; + + while max_v > 0 { + let mut k = 1; + let mut tmp = b.square(); + let mut j_less_than_v: Choice = ~Choice::from(1u8); + + let mut j = 2; // j in 2..max_v + while j <= max_v { + let tmp_is_one = ~Choice::from_bool(tmp.eq(~Scalar::one())); + let squared = ~Scalar::conditional_select(tmp, z, tmp_is_one).square(); + tmp = ~Scalar::conditional_select(squared, tmp, tmp_is_one); + let new_z = ~Scalar::conditional_select(z, squared, tmp_is_one); + let j_less_than_v_bool = ~Choice::unwrap_as_bool(j_less_than_v) && j != v; + j_less_than_v = ~Choice::from_bool(j_less_than_v_bool); + k = ~u32::conditional_select(j, k, tmp_is_one); + z = ~Scalar::conditional_select(z, new_z, j_less_than_v); + + j += 1; + } + + let result = x * z; + x = ~Scalar::conditional_select(result, x, ~Choice::from_bool(b.eq(~Scalar::one()))); + z = z.square(); + b *= z; + v = k; + + max_v -= 1; + } + + ~CtOption::new( + x, + (x * x).ct(self), // Only return Some if it's the square root. + ) + } } \ No newline at end of file diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw index f774116..a4080d9 100644 --- a/bls12_381/src/util.sw +++ b/bls12_381/src/util.sw @@ -30,6 +30,16 @@ impl ConditionallySelectable for u64 { } } +impl ConditionallySelectable for u32 { + fn conditional_select(a: u32, b: u32, choice: Choice) -> u32 { + if (choice.unwrap_u8() == 0) { + a + } else { + b + } + } +} + // TODO rewrite without if branch // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { @@ -72,4 +82,12 @@ pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { let res: U128 = a_128 + (b_128 * c_128) + carry_128; (res.lower, res.upper) +} + +//returns a*b mod(2^64) +pub fn wrapping_mul(a: u64, b: u64) -> u64 { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + + (a_128 * b_128).lower } \ No newline at end of file diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index e88cd84..389b633 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,6 +1,7 @@ contract; use bls12_381::{fp::*, fp2::*, fp6::*, scalar::*}; +use bls12_381::choice::*; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; @@ -16,6 +17,13 @@ abi BlsTestContract { #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; + + // this returntype CtOption seems to cause the error: + /* +error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. +Please file an issue on the repository and include the code that triggered this error. +*/ + // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption; // These can't be compiled yet.. // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6; @@ -68,6 +76,10 @@ impl BlsTestContract for Contract { a + b } + // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { + // a.sqrt() + // } + // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6 { // a * b // } diff --git a/tests_bls12_381/tests/tests_scalar/mod.rs b/tests_bls12_381/tests/tests_scalar/mod.rs index 4fedc9d..4526912 100644 --- a/tests_bls12_381/tests/tests_scalar/mod.rs +++ b/tests_bls12_381/tests/tests_scalar/mod.rs @@ -40,7 +40,7 @@ async fn test_addition() { 0x73ed_a753_299d_7d48, ].to_vec()}; - let mut a_again = Scalar{ ls: [ + let a_2 = Scalar{ ls: [ 0xffff_ffff_0000_0000, 0x53bd_a402_fffe_5bfe, 0x3339_d808_09a1_d805, @@ -56,29 +56,78 @@ async fn test_addition() { let (contract_instance, _id) = get_contract_instance().await; - let res = contract_instance.add_scalar(a, a_again) + let res = contract_instance.add_scalar(a, a_2) .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(scalar_equals(res, expected_res)); + + let a_3 = Scalar{ ls: [ + 0xffff_ffff_0000_0000, + 0x53bd_a402_fffe_5bfe, + 0x3339_d808_09a1_d805, + 0x73ed_a753_299d_7d48, + ].to_vec()}; + + let one = Scalar{ ls: [1,0,0,0].to_vec() }; + let res_2 = contract_instance.add_scalar(a_3, one) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(scalar_equals(res_2, Scalar{ ls: [0,0,0,0].to_vec() })); + } -// fn test_addition() { -// let mut tmp = LARGEST; -// tmp += &LARGEST; - -// assert_eq!( -// tmp, -// Scalar([ -// 0xffff_fffe_ffff_ffff, -// 0x53bd_a402_fffe_5bfe, -// 0x3339_d808_09a1_d805, -// 0x73ed_a753_299d_7d48, -// ]) -// ); - -// let mut tmp = LARGEST; -// tmp += &Scalar([1, 0, 0, 0]); - -// assert_eq!(tmp, Scalar::zero()); + +/*BLOCKED +error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. +Please file an issue on the repository and include the code that triggered this error. +*/ +// #[tokio::test] +// async fn test_sqrt() { +// let zero = Scalar{ ls: [0,0,0,0].to_vec() }; +// let (contract_instance, _id) = get_contract_instance().await; +// let square_root = contract_instance.scalar_sqrt(zero) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// assert_eq!(square_root, Scalar{ ls: [0,0,0,0].to_vec() }); +// } + + +/*BLOCKED +error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. +Please file an issue on the repository and include the code that triggered this error. +*/ +// #[tokio::test] +// async fn test_sqrt() { +// let mut square = Scalar{ ls:[ +// 0x46cd_85a5_f273_077e, +// 0x1d30_c47d_d68f_c735, +// 0x77f6_56f6_0bec_a0eb, +// 0x494a_a01b_df32_468d, +// ].to_vec()}; + +// let mut none_count = 0; +// let (contract_instance, _id) = get_contract_instance().await; + + +// let j = 0; +// while j < 101 { +// let square_root = contract_instance.scalar_sqrt(square) +// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .call_params(CallParameters::new(None, None, Some(100_000_000))) +// .call().await.unwrap().value; +// // let square_root = square.sqrt(); +// if square_root.is_none() { +// none_count += 1; +// } else { +// assert_eq!(square_root.unwrap() * square_root.unwrap(), square); +// } +// square -= Scalar::one(); +// j += 1; +// } + +// assert_eq!(49, none_count); // } \ No newline at end of file From 78fbbd0a0a84064363bd8b5265806021f6a1ab79 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 4 Aug 2022 16:10:51 -0600 Subject: [PATCH 137/160] Causes error --- tests_bls12_381/src/main.sw | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 389b633..78e73b0 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -23,7 +23,7 @@ abi BlsTestContract { error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. Please file an issue on the repository and include the code that triggered this error. */ - // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption; + #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption; // These can't be compiled yet.. // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6; @@ -76,9 +76,9 @@ impl BlsTestContract for Contract { a + b } - // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { - // a.sqrt() - // } + #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { + a.sqrt() + } // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6 { // a * b From 6c7ef5139ae2d045a09f707b25cc3a0faca9f767 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 4 Aug 2022 17:33:42 -0600 Subject: [PATCH 138/160] Improved imports --- bls12_381/src/choice.sw | 2 +- bls12_381/src/fp.sw | 4 +- bls12_381/src/fp2.sw | 2 +- bls12_381/src/fp6.sw | 6 +- bls12_381/src/main.sw | 2 +- bls12_381/src/scalar.sw | 123 ++++++++++++++++++------------------ bls12_381/src/util.sw | 4 +- tests_bls12_381/src/main.sw | 9 ++- 8 files changed, 79 insertions(+), 73 deletions(-) diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 6f5b643..1d2d939 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -1,6 +1,6 @@ library choice; -use std::{option::*}; +use std::{option::Option}; /////////////// IMPORTANT /////////////// diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 90517b1..1337bf5 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -3,9 +3,9 @@ library fp; dep choice; dep util; -use choice::*; +use choice::{Choice, CtOption, ConditionallySelectable}; use util::*; -use std::{option::*, u128::*, vec::Vec}; +use std::{option::Option, u128::*, vec::Vec}; use core::ops::{Eq, Add, Subtract, Multiply}; // Little endian big integer with 6 limbs diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index f8d7855..f74a1e3 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -1,7 +1,7 @@ library fp2; dep fp; -use fp::*; +use fp::Fp; use core::ops::{Eq, Add, Subtract, Multiply}; pub struct Fp2 { diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 59354c1..d8e739c 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -4,9 +4,9 @@ dep fp2; dep fp; dep choice; -use fp::*; -use fp2::*; -use choice::*; +use fp::Fp; +use fp2::Fp2; +use choice::{Choice, CtOption}; use core::ops::{Add, Multiply}; diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index 022510d..f448a59 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -2,7 +2,7 @@ script; dep fp; -use ::fp::*; +use ::fp::Fp; use std::{assert::assert}; use std::logging::log; diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index 414f7c8..294d847 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -3,7 +3,7 @@ library scalar; dep choice; dep util; -use choice::*; +use choice::{Choice, CtOption, ConditionallySelectable}; use util::*; use core::ops::{Eq, Add, Subtract, Multiply}; @@ -283,23 +283,23 @@ impl Scalar { /// **This operation is variable time with respect /// to the exponent.** If the exponent is fixed, /// this operation is effectively constant time. - pub fn pow_vartime(self, by: [u64; 4]) -> Self { + pub fn pow_vartime(self, by: [u64; 4]) -> Scalar { let mut res = ~Self::one(); - let mut i = 4; - while i > 0 { - let e = by[i -1]; - let mut j = 65; - while j > 0 { - res = res.square(); - - if ((e >> (j-1)) & 1) == 1 { - res *= self; - // res.mul_assign(self); - } - j -= 1; - } - i -= 1; - } + // let mut i = 4; + // while i > 0 { + // let e = by[i -1]; + // let mut j = 65; + // while j > 0 { + // res = res.square(); + + // if ((e >> (j-1)) & 1) == 1 { + // res *= self; + // // res.mul_assign(self); + // } + // j -= 1; + // } + // i -= 1; + // } res } } @@ -313,53 +313,54 @@ impl Scalar { // w = self^((t - 1) // 2) // = self^6104339283789297388802252303364915521546564123189034618274734669823 - let w = self.pow_vartime([ + let w = ~Scalar::one();/*pow_vartime(self, [ 0x7fff_2dff_7fff_ffff, 0x04d0_ec02_a9de_d201, 0x94ce_bea4_199c_ec04, 0x0000_0000_39f6_d3a9, - ]); - - let mut v = S; - let mut x = self * w; - let mut b = x * w; - - // Initialize z as the 2^S root of unity. - let mut z = ROOT_OF_UNITY; - - let mut max_v = S; - - while max_v > 0 { - let mut k = 1; - let mut tmp = b.square(); - let mut j_less_than_v: Choice = ~Choice::from(1u8); - - let mut j = 2; // j in 2..max_v - while j <= max_v { - let tmp_is_one = ~Choice::from_bool(tmp.eq(~Scalar::one())); - let squared = ~Scalar::conditional_select(tmp, z, tmp_is_one).square(); - tmp = ~Scalar::conditional_select(squared, tmp, tmp_is_one); - let new_z = ~Scalar::conditional_select(z, squared, tmp_is_one); - let j_less_than_v_bool = ~Choice::unwrap_as_bool(j_less_than_v) && j != v; - j_less_than_v = ~Choice::from_bool(j_less_than_v_bool); - k = ~u32::conditional_select(j, k, tmp_is_one); - z = ~Scalar::conditional_select(z, new_z, j_less_than_v); - - j += 1; - } - - let result = x * z; - x = ~Scalar::conditional_select(result, x, ~Choice::from_bool(b.eq(~Scalar::one()))); - z = z.square(); - b *= z; - v = k; - - max_v -= 1; - } - - ~CtOption::new( - x, - (x * x).ct(self), // Only return Some if it's the square root. - ) + ]);*/ + + // let mut v = S; + // let mut x = self * w; + // let mut b = x * w; + + // // Initialize z as the 2^S root of unity. + // let mut z = ROOT_OF_UNITY; + + // let mut max_v = S; + + // while max_v > 0 { + // let mut k = 1; + // let mut tmp = b.square(); + // let mut j_less_than_v: Choice = ~Choice::from(1u8); + + // let mut j = 2; // j in 2..max_v + // while j <= max_v { + // let tmp_is_one = ~Choice::from_bool(tmp.eq(~Scalar::one())); + // let squared = ~Scalar::conditional_select(tmp, z, tmp_is_one).square(); + // tmp = ~Scalar::conditional_select(squared, tmp, tmp_is_one); + // let new_z = ~Scalar::conditional_select(z, squared, tmp_is_one); + // let j_less_than_v_bool = ~Choice::unwrap_as_bool(j_less_than_v) && j != v; + // j_less_than_v = ~Choice::from_bool(j_less_than_v_bool); + // k = ~u32::conditional_select(j, k, tmp_is_one); + // z = ~Scalar::conditional_select(z, new_z, j_less_than_v); + + // j += 1; + // } + + // let result = x * z; + // x = ~Scalar::conditional_select(result, x, ~Choice::from_bool(b.eq(~Scalar::one()))); + // z = z.square(); + // b *= z; + // v = k; + + // max_v -= 1; + // } + + // ~CtOption::new( + // x, + // (x * x).ct(self), // Only return Some if it's the square root. + // ) + ~CtOption::new(self, ~Choice::from(1)) } } \ No newline at end of file diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw index a4080d9..beb9d1f 100644 --- a/bls12_381/src/util.sw +++ b/bls12_381/src/util.sw @@ -1,8 +1,8 @@ library util; dep choice; -use choice::*; -use std::{u128::*}; +use choice::{Choice, CtOption, ConditionallySelectable}; +use std::{u128::U128}; impl ConditionallySelectable for u64 { // TODO How can we do this in Sway in constant time? diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 78e73b0..1150694 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,7 +1,12 @@ contract; -use bls12_381::{fp::*, fp2::*, fp6::*, scalar::*}; -use bls12_381::choice::*; +use bls12_381::{ + fp::Fp, + fp::from_raw_unchecked, + fp2::Fp2, + fp6::Fp6, + scalar::Scalar}; +use bls12_381::choice::CtOption; abi BlsTestContract { #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; From 8b61e5d9f8a468caa57b4d0196dbde0fe919d3c7 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 4 Aug 2022 18:03:56 -0600 Subject: [PATCH 139/160] Commented out functions that will give error --- bls12_381/src/scalar.sw | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index 294d847..ef16ee9 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -305,6 +305,18 @@ impl Scalar { } impl Scalar { +/* +functions +- pow_vartime +- sqrt + +will give Immediate18TooLarge + +(It originally gave the error +error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. +Please file an issue on the repository and include the code that triggered this error. +) +*/ /// Computes the square root of this element, if it exists. pub fn sqrt(self) -> CtOption { From cd49a8027d145decdc656cde5e25a8ea55c0592c Mon Sep 17 00:00:00 2001 From: Manish Date: Fri, 5 Aug 2022 14:48:20 +0530 Subject: [PATCH 140/160] frobenius_map in fp2 & fp6 --- bls12_381/src/fp2.sw | 16 ++++++++++++++-- bls12_381/src/fp6.sw | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index f74a1e3..a31e95b 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -59,7 +59,7 @@ impl Fp2 { } } */ -/* + pub fn mul(self, rhs: Fp2) -> Fp2 { // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) // computes the result as: @@ -111,7 +111,7 @@ impl Fp2 { // c1: c1 // } } -*/ + pub fn add(self, rhs: Fp2) -> Fp2 { Fp2 { c0: self.c0 + rhs.c0, @@ -146,6 +146,18 @@ impl Fp2 { } } + pub fn conjugate(self) -> Fp2 { + Fp2{ + c0: self.c0, + c1: (self.c1).neg(), + } + } + + /// Raises this element to p. + pub fn frobenius_map(self) -> Fp2 { + self.conjugate() + } + } impl Eq for Fp2 { diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index d8e739c..fd16b42 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -209,6 +209,41 @@ impl Fp6 { c2: s1 + s2 + s3 - s0 - s4, } }*/ + + pub fn frobenius_map(self) -> Fp6 { + let c0 = (self.c0).frobenius_map(); + let c1 = (self.c1).frobenius_map(); + let c2 = (self.c2).frobenius_map(); + + // c1 = c1 * (u + 1)^((p - 1) / 3) + + let c1 = c1 * Fp2 { + c0: ~Fp::zero(), + c1: ~Fp::from_raw_unchecked([ + 0xcd03_c9e4_8671_f071, + 0x5dab_2246_1fcd_a5d2, + 0x5870_42af_d385_1b95, + 0x8eb6_0ebe_01ba_cb9e, + 0x03f9_7d6e_83d0_50d2, + 0x18f0_2065_5463_8741, + ]), + }; + let c2 = c2 * Fp { + c0: ~Fp::from_raw_unchecked([ + 0x890d_c9e4_8675_45c3, + 0x2af3_2253_3285_a5d5, + 0x5088_0866_309b_7e2c, + 0xa20d_1b8c_7e88_1024, + 0x14e4_f04f_e2db_9068, + 0x14e5_6d3f_1564_853a, + ]), + c1: ~Fp::zero(), + }; + + fp6 { + c0, c1, c2 + } + } } impl Add for Fp6 { From 2c3e6e3362de42787ba13c356b0a78f60475206b Mon Sep 17 00:00:00 2001 From: man2706kum Date: Fri, 5 Aug 2022 12:06:57 +0000 Subject: [PATCH 141/160] error fixing --- bls12_381/src/fp2.sw | 19 +++++++++++++------ bls12_381/src/fp6.sw | 4 ++-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index a31e95b..cf7166d 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -155,7 +155,14 @@ impl Fp2 { /// Raises this element to p. pub fn frobenius_map(self) -> Fp2 { - self.conjugate() + //needs to be verified + // This is always just a conjugation. If you're curious why, here's + // an article about it: https://alicebob.cryptoland.net/the-frobenius-endomorphism-with-finite-fields/ + // self.conjugate() //showing error + Fp2{ + c0: self.c0, + c1: (self.c1).neg(), + } } } @@ -178,8 +185,8 @@ impl Subtract for Fp2 { } } -// impl Multiply for Fp2 { -// fn multiply(self, other: Self) -> Self { -// self.mul(other) -// } -// } \ No newline at end of file +impl Multiply for Fp2 { + fn multiply(self, other: Self) -> Self { + self.mul(other) + } +} \ No newline at end of file diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index fd16b42..343b5d8 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -228,7 +228,7 @@ impl Fp6 { 0x18f0_2065_5463_8741, ]), }; - let c2 = c2 * Fp { + let c2 = c2 * Fp2 { c0: ~Fp::from_raw_unchecked([ 0x890d_c9e4_8675_45c3, 0x2af3_2253_3285_a5d5, @@ -240,7 +240,7 @@ impl Fp6 { c1: ~Fp::zero(), }; - fp6 { + Fp6 { c0, c1, c2 } } From 19f1e853522334baba2dc0744d6ea8712fb26365 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 5 Aug 2022 08:56:47 -0600 Subject: [PATCH 142/160] import fix --- bls12_381/src/fp6.sw | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 343b5d8..9ec4b9d 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -4,7 +4,7 @@ dep fp2; dep fp; dep choice; -use fp::Fp; +use fp::{Fp, from_raw_unchecked}; use fp2::Fp2; use choice::{Choice, CtOption}; @@ -219,7 +219,7 @@ impl Fp6 { let c1 = c1 * Fp2 { c0: ~Fp::zero(), - c1: ~Fp::from_raw_unchecked([ + c1: from_raw_unchecked([ 0xcd03_c9e4_8671_f071, 0x5dab_2246_1fcd_a5d2, 0x5870_42af_d385_1b95, @@ -229,7 +229,7 @@ impl Fp6 { ]), }; let c2 = c2 * Fp2 { - c0: ~Fp::from_raw_unchecked([ + c0: from_raw_unchecked([ 0x890d_c9e4_8675_45c3, 0x2af3_2253_3285_a5d5, 0x5088_0866_309b_7e2c, From a6eb90ba93e3bc3e5f85a4e4c973e8df87ec0529 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 5 Aug 2022 10:47:10 -0600 Subject: [PATCH 143/160] Comment out the function that is not being able to compile yet (Internal compiler error:) --- tests_bls12_381/src/main.sw | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 1150694..cb76a5c 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -23,12 +23,8 @@ abi BlsTestContract { #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; - // this returntype CtOption seems to cause the error: - /* -error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. -Please file an issue on the repository and include the code that triggered this error. -*/ - #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption; +//This function gives an error + // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption; // These can't be compiled yet.. // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6; @@ -81,9 +77,9 @@ impl BlsTestContract for Contract { a + b } - #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { - a.sqrt() - } + // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { + // a.sqrt() + // } // #[storage(read, write)]fn mul_fp6(a: Fp6, b: Fp6) -> Fp6 { // a * b From fde03d26a970ef725fdad4c2f1e46685f8339cae Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 5 Aug 2022 12:10:09 -0600 Subject: [PATCH 144/160] Update fuels version in bls12-381 lib. --- bls12_381/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bls12_381/Cargo.toml b/bls12_381/Cargo.toml index 5f74e37..8f22ae3 100644 --- a/bls12_381/Cargo.toml +++ b/bls12_381/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "Apache-2.0" [dependencies] -fuels = { version = "0.17", features = ["fuel-core-lib"] } +fuels = { version = "0.19", features = ["fuel-core-lib"] } tokio = { version = "1.12", features = ["rt", "macros"] } [[test]] From 26f0b8ed6b7d3a86fc0e70fd3a699706f207ea5d Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 5 Aug 2022 18:30:30 -0600 Subject: [PATCH 145/160] - Renamed old bls and tests-bls folder for clarity. These will be removed soon. - Updated authors in tests-bls --- {bls => old-bls}/Cargo.toml | 0 {bls => old-bls}/Forc.toml | 0 {bls => old-bls}/src/consts.sw | 0 {bls => old-bls}/src/definitions.sw | 0 {bls => old-bls}/src/ec1.sw | 0 {bls => old-bls}/src/fields.sw | 0 {bls => old-bls}/src/lib.sw | 0 {bls => old-bls}/src/main.sw | 0 {bls => old-bls}/src/test_helpers.sw | 0 .../src/tests/tests_temp_fe_mont_mul.sw | 0 .../src/tests/tests_vect_subfunctions.sw | 0 {bls => old-bls}/src/vect.sw | 23 ++++++++++++------- {tests-bls => old-tests-bls}/.gitignore | 0 {tests-bls => old-tests-bls}/Cargo.toml | 0 {tests-bls => old-tests-bls}/Forc.toml | 0 {tests-bls => old-tests-bls}/src/main.sw | 0 {tests-bls => old-tests-bls}/tests/harness.rs | 4 ++-- .../tests/tests_add_fp/mod.rs | 0 .../tests/tests_l_shift/mod.rs | 0 .../tests/tests_mul_by_x_fp/mod.rs | 0 .../tests/tests_rshift_mod_384/mod.rs | 0 .../tests/tests_small_functions/mod.rs | 0 .../tests/tests_sub_fp/mod.rs | 0 .../tests/tests_temp_mul/mod.rs | 0 .../tests/tests_temp_mul_mont_n/mod.rs | 0 .../tests/tests_vect_fp2/mod.rs | 0 .../tests/tests_vect_subfunctions/mod.rs | 0 test_contract/src/main.sw | 8 +++---- tests_bls12_381/Cargo.toml | 2 +- tests_bls12_381/Forc.toml | 2 +- 30 files changed, 23 insertions(+), 16 deletions(-) rename {bls => old-bls}/Cargo.toml (100%) rename {bls => old-bls}/Forc.toml (100%) rename {bls => old-bls}/src/consts.sw (100%) rename {bls => old-bls}/src/definitions.sw (100%) rename {bls => old-bls}/src/ec1.sw (100%) rename {bls => old-bls}/src/fields.sw (100%) rename {bls => old-bls}/src/lib.sw (100%) rename {bls => old-bls}/src/main.sw (100%) rename {bls => old-bls}/src/test_helpers.sw (100%) rename {bls => old-bls}/src/tests/tests_temp_fe_mont_mul.sw (100%) rename {bls => old-bls}/src/tests/tests_vect_subfunctions.sw (100%) rename {bls => old-bls}/src/vect.sw (97%) rename {tests-bls => old-tests-bls}/.gitignore (100%) rename {tests-bls => old-tests-bls}/Cargo.toml (100%) rename {tests-bls => old-tests-bls}/Forc.toml (100%) rename {tests-bls => old-tests-bls}/src/main.sw (100%) rename {tests-bls => old-tests-bls}/tests/harness.rs (71%) rename {tests-bls => old-tests-bls}/tests/tests_add_fp/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_l_shift/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_mul_by_x_fp/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_rshift_mod_384/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_small_functions/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_sub_fp/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_temp_mul/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_temp_mul_mont_n/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_vect_fp2/mod.rs (100%) rename {tests-bls => old-tests-bls}/tests/tests_vect_subfunctions/mod.rs (100%) diff --git a/bls/Cargo.toml b/old-bls/Cargo.toml similarity index 100% rename from bls/Cargo.toml rename to old-bls/Cargo.toml diff --git a/bls/Forc.toml b/old-bls/Forc.toml similarity index 100% rename from bls/Forc.toml rename to old-bls/Forc.toml diff --git a/bls/src/consts.sw b/old-bls/src/consts.sw similarity index 100% rename from bls/src/consts.sw rename to old-bls/src/consts.sw diff --git a/bls/src/definitions.sw b/old-bls/src/definitions.sw similarity index 100% rename from bls/src/definitions.sw rename to old-bls/src/definitions.sw diff --git a/bls/src/ec1.sw b/old-bls/src/ec1.sw similarity index 100% rename from bls/src/ec1.sw rename to old-bls/src/ec1.sw diff --git a/bls/src/fields.sw b/old-bls/src/fields.sw similarity index 100% rename from bls/src/fields.sw rename to old-bls/src/fields.sw diff --git a/bls/src/lib.sw b/old-bls/src/lib.sw similarity index 100% rename from bls/src/lib.sw rename to old-bls/src/lib.sw diff --git a/bls/src/main.sw b/old-bls/src/main.sw similarity index 100% rename from bls/src/main.sw rename to old-bls/src/main.sw diff --git a/bls/src/test_helpers.sw b/old-bls/src/test_helpers.sw similarity index 100% rename from bls/src/test_helpers.sw rename to old-bls/src/test_helpers.sw diff --git a/bls/src/tests/tests_temp_fe_mont_mul.sw b/old-bls/src/tests/tests_temp_fe_mont_mul.sw similarity index 100% rename from bls/src/tests/tests_temp_fe_mont_mul.sw rename to old-bls/src/tests/tests_temp_fe_mont_mul.sw diff --git a/bls/src/tests/tests_vect_subfunctions.sw b/old-bls/src/tests/tests_vect_subfunctions.sw similarity index 100% rename from bls/src/tests/tests_vect_subfunctions.sw rename to old-bls/src/tests/tests_vect_subfunctions.sw diff --git a/bls/src/vect.sw b/old-bls/src/vect.sw similarity index 97% rename from bls/src/vect.sw rename to old-bls/src/vect.sw index 397097d..3894339 100644 --- a/bls/src/vect.sw +++ b/old-bls/src/vect.sw @@ -282,16 +282,23 @@ pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { // To mont form let a_mont = fe_to_mont(a); - let b_mont = fe_to_mont(b); - // Mult - let res = temp_fe_mont_mul(a_mont, b_mont); - // Transform back - let res = fe_to_norm(res); - let res_vec = vec384{ - ls: [unpack_or_0(res.get(0)),unpack_or_0(res.get(1)),unpack_or_0(res.get(2)),unpack_or_0(res.get(3)),unpack_or_0(res.get(4)),unpack_or_0(res.get(5))] + let res_vec = vec384{ + ls: [unpack_or_0(a_mont.get(0)),unpack_or_0(a_mont.get(1)), + unpack_or_0(a_mont.get(2)),unpack_or_0(a_mont.get(3)), + unpack_or_0(a_mont.get(4)),unpack_or_0(a_mont.get(5))] }; - + // a_mont; res_vec + // let b_mont = fe_to_mont(b); + // // Mult + // let res = temp_fe_mont_mul(a_mont, b_mont); + // // Transform back + // let res = fe_to_norm(res); + // let res_vec = vec384{ + // ls: [unpack_or_0(res.get(0)),unpack_or_0(res.get(1)),unpack_or_0(res.get(2)),unpack_or_0(res.get(3)),unpack_or_0(res.get(4)),unpack_or_0(res.get(5))] + // }; + + // res_vec } // Same functionality as mul_temp diff --git a/tests-bls/.gitignore b/old-tests-bls/.gitignore similarity index 100% rename from tests-bls/.gitignore rename to old-tests-bls/.gitignore diff --git a/tests-bls/Cargo.toml b/old-tests-bls/Cargo.toml similarity index 100% rename from tests-bls/Cargo.toml rename to old-tests-bls/Cargo.toml diff --git a/tests-bls/Forc.toml b/old-tests-bls/Forc.toml similarity index 100% rename from tests-bls/Forc.toml rename to old-tests-bls/Forc.toml diff --git a/tests-bls/src/main.sw b/old-tests-bls/src/main.sw similarity index 100% rename from tests-bls/src/main.sw rename to old-tests-bls/src/main.sw diff --git a/tests-bls/tests/harness.rs b/old-tests-bls/tests/harness.rs similarity index 71% rename from tests-bls/tests/harness.rs rename to old-tests-bls/tests/harness.rs index 16a61ad..b28eeeb 100644 --- a/tests-bls/tests/harness.rs +++ b/old-tests-bls/tests/harness.rs @@ -1,4 +1,4 @@ -mod tests_add_fp; +// mod tests_add_fp; // mod tests_mul_by_x_fp; // mod tests_sub_fp; // mod tests_l_shift; @@ -6,4 +6,4 @@ mod tests_add_fp; // mod tests_temp_mul; // mod tests_vect_subfunctions; // mod tests_vect_fp2; -// mod tests_temp_mul_mont_n; gives error OutOfGas +mod tests_temp_mul_mont_n; diff --git a/tests-bls/tests/tests_add_fp/mod.rs b/old-tests-bls/tests/tests_add_fp/mod.rs similarity index 100% rename from tests-bls/tests/tests_add_fp/mod.rs rename to old-tests-bls/tests/tests_add_fp/mod.rs diff --git a/tests-bls/tests/tests_l_shift/mod.rs b/old-tests-bls/tests/tests_l_shift/mod.rs similarity index 100% rename from tests-bls/tests/tests_l_shift/mod.rs rename to old-tests-bls/tests/tests_l_shift/mod.rs diff --git a/tests-bls/tests/tests_mul_by_x_fp/mod.rs b/old-tests-bls/tests/tests_mul_by_x_fp/mod.rs similarity index 100% rename from tests-bls/tests/tests_mul_by_x_fp/mod.rs rename to old-tests-bls/tests/tests_mul_by_x_fp/mod.rs diff --git a/tests-bls/tests/tests_rshift_mod_384/mod.rs b/old-tests-bls/tests/tests_rshift_mod_384/mod.rs similarity index 100% rename from tests-bls/tests/tests_rshift_mod_384/mod.rs rename to old-tests-bls/tests/tests_rshift_mod_384/mod.rs diff --git a/tests-bls/tests/tests_small_functions/mod.rs b/old-tests-bls/tests/tests_small_functions/mod.rs similarity index 100% rename from tests-bls/tests/tests_small_functions/mod.rs rename to old-tests-bls/tests/tests_small_functions/mod.rs diff --git a/tests-bls/tests/tests_sub_fp/mod.rs b/old-tests-bls/tests/tests_sub_fp/mod.rs similarity index 100% rename from tests-bls/tests/tests_sub_fp/mod.rs rename to old-tests-bls/tests/tests_sub_fp/mod.rs diff --git a/tests-bls/tests/tests_temp_mul/mod.rs b/old-tests-bls/tests/tests_temp_mul/mod.rs similarity index 100% rename from tests-bls/tests/tests_temp_mul/mod.rs rename to old-tests-bls/tests/tests_temp_mul/mod.rs diff --git a/tests-bls/tests/tests_temp_mul_mont_n/mod.rs b/old-tests-bls/tests/tests_temp_mul_mont_n/mod.rs similarity index 100% rename from tests-bls/tests/tests_temp_mul_mont_n/mod.rs rename to old-tests-bls/tests/tests_temp_mul_mont_n/mod.rs diff --git a/tests-bls/tests/tests_vect_fp2/mod.rs b/old-tests-bls/tests/tests_vect_fp2/mod.rs similarity index 100% rename from tests-bls/tests/tests_vect_fp2/mod.rs rename to old-tests-bls/tests/tests_vect_fp2/mod.rs diff --git a/tests-bls/tests/tests_vect_subfunctions/mod.rs b/old-tests-bls/tests/tests_vect_subfunctions/mod.rs similarity index 100% rename from tests-bls/tests/tests_vect_subfunctions/mod.rs rename to old-tests-bls/tests/tests_vect_subfunctions/mod.rs diff --git a/test_contract/src/main.sw b/test_contract/src/main.sw index b32ea31..35496a2 100644 --- a/test_contract/src/main.sw +++ b/test_contract/src/main.sw @@ -22,7 +22,7 @@ abi EdContract { #[storage()]fn scalar_mult(a: Element, x: u32) -> Element; #[storage()]fn shift_right_by51(a: U128) -> u64; - #[storage()]fn inverse(a: Element) -> Element; + // #[storage()]fn inverse(a: Element) -> Element; } @@ -76,7 +76,7 @@ impl EdContract for Contract { shift_right_by51(a) } - #[storage()]fn inverse(a: Element) -> Element { - inverse(a) - } + // #[storage()]fn inverse(a: Element) -> Element { + // inverse(a) + // } } \ No newline at end of file diff --git a/tests_bls12_381/Cargo.toml b/tests_bls12_381/Cargo.toml index 3a1a75e..0269fc5 100644 --- a/tests_bls12_381/Cargo.toml +++ b/tests_bls12_381/Cargo.toml @@ -1,7 +1,7 @@ [project] name = "tests_bls12_381" version = "0.1.0" -authors = ["Elena Fuentes Bongenaar"] +authors = ["Hashcloak"] edition = "2021" license = "Apache-2.0" diff --git a/tests_bls12_381/Forc.toml b/tests_bls12_381/Forc.toml index 2271d6f..d092598 100644 --- a/tests_bls12_381/Forc.toml +++ b/tests_bls12_381/Forc.toml @@ -1,5 +1,5 @@ [project] -authors = ["Elena Fuentes Bongenaar"] +authors = ["Hashcloak"] entry = "main.sw" license = "Apache-2.0" name = "tests_bls12_381" From 1596b9012e9a74d02a9d78b8128e97b4ed35f424 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 8 Aug 2022 18:58:57 -0600 Subject: [PATCH 146/160] - Added comment where error Immediate18TooLarge pops up - Converted tests_fp and tests_fp2 to use a local node with custom gas limit - What functions & tests work - Fp2 mult gives result 0 atm --- bls12_381/src/fp.sw | 10 +- bls12_381/src/fp2.sw | 15 +- bls12_381/src/fp6.sw | 2 + tests_bls12_381/src/main.sw | 36 ++-- tests_bls12_381/tests/tests_fp/mod.rs | 195 +++++++++++--------- tests_bls12_381/tests/tests_fp2/mod.rs | 245 ++++++++++++++----------- 6 files changed, 282 insertions(+), 221 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 1337bf5..0a02c7e 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -171,7 +171,7 @@ impl Fp { // is smaller than the modulus. (Fp{ls:[d0, d1, d2, d3, d4, d5]}).subtract_p() } -/* + pub fn mul(self, rhs: Fp) -> Fp { let self0 = self.ls[0]; let self1 = self.ls[1]; @@ -232,7 +232,7 @@ impl Fp { let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) } - +/*TODO test pub fn square(self) -> Fp { let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); @@ -282,7 +282,7 @@ impl Fp { let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) } - */ + */ } impl Fp { @@ -490,7 +490,7 @@ impl Subtract for Fp { self.sub(other) } } -/* + impl Multiply for Fp { fn multiply(self, other: Self) -> Self { self.mul(other) @@ -554,4 +554,4 @@ pub fn montgomery_reduce(t: [u64;12]) -> Fp { let r11_12 = adc(t[11], r10_11.1, r10.1); (Fp { ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0]}).subtract_p() -}*/ \ No newline at end of file +} \ No newline at end of file diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index cf7166d..d44abbc 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -34,8 +34,9 @@ impl Fp2 { fn eq(self, other: Self) -> bool { self.c0 == other.c0 && self.c1 == other.c1 } + /* -// //TODO test + // not tested, gives Immediate18TooLarge error pub fn square(self) -> Fp2 { // Complex squaring: // @@ -58,7 +59,7 @@ impl Fp2 { c1: c * self.c1, } } - */ + */ pub fn mul(self, rhs: Fp2) -> Fp2 { // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) @@ -185,8 +186,8 @@ impl Subtract for Fp2 { } } -impl Multiply for Fp2 { - fn multiply(self, other: Self) -> Self { - self.mul(other) - } -} \ No newline at end of file +// impl Multiply for Fp2 { +// fn multiply(self, other: Self) -> Self { +// self.mul(other) +// } +// } \ No newline at end of file diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 9ec4b9d..9d75552 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -210,6 +210,7 @@ impl Fp6 { } }*/ +/* pub fn frobenius_map(self) -> Fp6 { let c0 = (self.c0).frobenius_map(); let c1 = (self.c1).frobenius_map(); @@ -244,6 +245,7 @@ impl Fp6 { c0, c1, c2 } } + */ } impl Add for Fp6 { diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index cb76a5c..5a29255 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -9,17 +9,26 @@ use bls12_381::{ use bls12_381::choice::CtOption; abi BlsTestContract { + // Works #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; + + // works but takes a long time // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; + + // not tested, gives Immediate18TooLarge error // #[storage(read, write)]fn square_fp(a: Fp) -> Fp; - #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp; - // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; - // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; + // Works #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; + + // not tested, gives Immediate18TooLarge error + // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; + + // Gives wrong output atm + #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; @@ -49,18 +58,6 @@ impl BlsTestContract for Contract { // a.square() // } - #[storage(read, write)]fn fp_from_raw_unchecked(v: [u64; 6]) -> Fp { - from_raw_unchecked(v) - } - - // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { - // a.square() - // } - - // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { - // a * b - // } - #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { a + b } @@ -77,6 +74,15 @@ impl BlsTestContract for Contract { a + b } + // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { + // a.square() + // } + + #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { + a * b + } + + // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { // a.sqrt() // } diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index dc17120..89364a2 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -3,28 +3,43 @@ use fuels::{ tx::{ConsensusParameters, ContractId}, }; -// Load abi from json +use helpers::get_contract_instance; + abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); +//TODO move this to a separate helpers file. How to achieve this in Rust/Cargo? async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_wallet().await; + let mut wallet = LocalWallet::new_random(None); + let num_assets = 1; + let coins_per_asset = 100; + let amount_per_coin = 100000; + + let (coins, asset_ids) = setup_multiple_assets_coins( + wallet.address(), + num_assets, + coins_per_asset, + amount_per_coin, + ); + + // Custom gas limit + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); + + let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; + + let provider = Provider::new(client); + wallet.set_provider(provider.clone()); let id = Contract::deploy( "./out/debug/tests_bls12_381.bin", &wallet, TxParameters::default(), - StorageConfiguration::with_storage_path(None) - ) - .await - .unwrap(); + StorageConfiguration::default(), + ).await.unwrap(); let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); - (instance, id) } - pub fn res_equals(res: Fp, should_be: Fp) -> bool { assert!(res.ls[0] == should_be.ls[0]); assert!(res.ls[1] == should_be.ls[1]); @@ -35,7 +50,7 @@ pub fn res_equals(res: Fp, should_be: Fp) -> bool { true } -#[tokio::test] +#[tokio::test] //works async fn test_add_fp() { let small = Fp{ ls: [1, 2, 3, 4, 5, 6].to_vec() @@ -57,7 +72,7 @@ async fn test_add_fp() { assert!(res_equals(res, expected_res)); } -#[tokio::test] +#[tokio::test] //works async fn test_sub_fp() { let a = Fp { ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194].to_vec() @@ -78,78 +93,86 @@ async fn test_sub_fp() { assert!(res_equals(res, expected_res)); } -// // WORKS, but smart to comment out when wanting to test other things -// #[tokio::test] -// async fn test_mul_fp() { -// let a = Fp{ ls:[ -// 0x0397_a383_2017_0cd4, -// 0x734c_1b2c_9e76_1d30, -// 0x5ed2_55ad_9a48_beb5, -// 0x095a_3c6b_22a7_fcfc, -// 0x2294_ce75_d4e2_6a27, -// 0x1333_8bd8_7001_1ebb, -// ].to_vec()}; -// let b = Fp{ ls:[ -// 0xb9c3_c7c5_b119_6af7, -// 0x2580_e208_6ce3_35c1, -// 0xf49a_ed3d_8a57_ef42, -// 0x41f2_81e4_9846_e878, -// 0xe076_2346_c384_52ce, -// 0x0652_e893_26e5_7dc0, -// ].to_vec()}; -// let c = Fp{ ls:[ -// 0xf96e_f3d7_11ab_5355, -// 0xe8d4_59ea_00f1_48dd, -// 0x53f7_354a_5f00_fa78, -// 0x9e34_a4f3_125c_5f83, -// 0x3fbe_0c47_ca74_c19e, -// 0x01b0_6a8b_bd4a_dfe4, -// ].to_vec()}; -// let (_instance, _id) = get_contract_instance().await; - -// let res = _instance.mul_fp(a, b) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// assert!(res_equals(res, c)); -// } - -// // WORKS, but smart to comment out when wanting to test other things -// #[tokio::test] -// async fn test_square_fp() { -// let a: Fp = Fp { -// ls: [0xd215_d276_8e83_191b,//15138237129114720539 -// 0x5085_d80f_8fb2_8261,//5802281256283701857 -// 0xce9a_032d_df39_3a56,//14887215013780077142 -// 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 -// 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 -// 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 -// }; - -// // let a_again: Fp = Fp { -// // ls: [0xd215_d276_8e83_191b, -// // 0x5085_d80f_8fb2_8261,//5802281256283701857 -// // 0xce9a_032d_df39_3a56,//14887215013780077142 -// // 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 -// // 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 -// // 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 -// // }; - -// let expected_res: Fp = Fp { -// ls: [0x33d9_c42a_3cb3_e235, -// 0xdad1_1a09_4c4c_d455, -// 0xa2f1_44bd_729a_aeba, -// 0xd415_0932_be9f_feac, -// 0xe27b_c7c4_7d44_ee50, -// 0x14b6_a78d_3ec7_a560].to_vec() -// }; - -// let (_instance, _id) = get_contract_instance().await; - -// let res = _instance.square_fp(a) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// //fails :( -// assert!(res_equals(res, expected_res)); -// } +/* +#[tokio::test] //works, but takes a long time! +async fn test_mul_fp() { + let a = Fp{ ls:[ + 0x0397_a383_2017_0cd4, + 0x734c_1b2c_9e76_1d30, + 0x5ed2_55ad_9a48_beb5, + 0x095a_3c6b_22a7_fcfc, + 0x2294_ce75_d4e2_6a27, + 0x1333_8bd8_7001_1ebb, + ].to_vec()}; + let b = Fp{ ls:[ + 0xb9c3_c7c5_b119_6af7, + 0x2580_e208_6ce3_35c1, + 0xf49a_ed3d_8a57_ef42, + 0x41f2_81e4_9846_e878, + 0xe076_2346_c384_52ce, + 0x0652_e893_26e5_7dc0, + ].to_vec()}; + let c = Fp{ ls:[ + 0xf96e_f3d7_11ab_5355, + 0xe8d4_59ea_00f1_48dd, + 0x53f7_354a_5f00_fa78, + 0x9e34_a4f3_125c_5f83, + 0x3fbe_0c47_ca74_c19e, + 0x01b0_6a8b_bd4a_dfe4, + ].to_vec()}; + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.mul_fp(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert!(res_equals(res, c)); +} +*/ +/* +#[tokio::test] //Immediate18TooLarge +async fn test_square_fp() { + let a: Fp = Fp { + ls: [0xd215_d276_8e83_191b,//15138237129114720539 + 0x5085_d80f_8fb2_8261,//5802281256283701857 + 0xce9a_032d_df39_3a56,//14887215013780077142 + 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 + }; + + // let a_again: Fp = Fp { + // ls: [0xd215_d276_8e83_191b, + // 0x5085_d80f_8fb2_8261,//5802281256283701857 + // 0xce9a_032d_df39_3a56,//14887215013780077142 + // 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 + // 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 + // 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 + // }; + + let expected_res: Fp = Fp { + ls: [0x33d9_c42a_3cb3_e235, + 0xdad1_1a09_4c4c_d455, + 0xa2f1_44bd_729a_aeba, + 0xd415_0932_be9f_feac, + 0xe27b_c7c4_7d44_ee50, + 0x14b6_a78d_3ec7_a560].to_vec() + }; + + let (_instance, _id) = get_contract_instance().await; + + let res = _instance.square_fp(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + //Unclear whether this works because of Immediate18TooLarge error + println!("{}", res.ls[0]); + println!("{}", res.ls[1]); + println!("{}", res.ls[2]); + println!("{}", res.ls[2]); + println!("{}", res.ls[4]); + println!("{}", res.ls[5]); + assert!(res_equals(res, expected_res)); +} +*/ \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index fa0cf06..b016314 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -3,24 +3,37 @@ use fuels::{ tx::{ConsensusParameters, ContractId}, }; -// Load abi from json abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_wallet().await; + let mut wallet = LocalWallet::new_random(None); + let num_assets = 1; + let coins_per_asset = 100; + let amount_per_coin = 100000; + + let (coins, asset_ids) = setup_multiple_assets_coins( + wallet.address(), + num_assets, + coins_per_asset, + amount_per_coin, + ); + + // Custom gas limit + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); + + let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; + + let provider = Provider::new(client); + wallet.set_provider(provider.clone()); let id = Contract::deploy( "./out/debug/tests_bls12_381.bin", &wallet, TxParameters::default(), - StorageConfiguration::with_storage_path(None) - ) - .await - .unwrap(); + StorageConfiguration::default(), + ).await.unwrap(); let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); - (instance, id) } @@ -226,106 +239,122 @@ async fn test_neg_fp2() { assert!(res_equals(res.c_1, b.c_1)); } -// BLOCKED thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262256, span: Span { src (ptr): 0x600012cb7b50, path: None, start: 0, end: 0, as_str(): "" } }' -// #[tokio::test] -// fn test_multiplication() { -// let a = Fp2 { -// c0: fp_from_raw_unchecked([ -// 0xc9a2_1831_63ee_70d4, -// 0xbc37_70a7_196b_5c91, -// 0xa247_f8c1_304c_5f44, -// 0xb01f_c2a3_726c_80b5, -// 0xe1d2_93e5_bbd9_19c9, -// 0x04b7_8e80_020e_f2ca, -// ]), -// c1: fp_from_raw_unchecked([ -// 0x952e_a446_0462_618f, -// 0x238d_5edd_f025_c62f, -// 0xf6c9_4b01_2ea9_2e72, -// 0x03ce_24ea_c1c9_3808, -// 0x0559_50f9_45da_483c, -// 0x010a_768d_0df4_eabc, -// ]), -// }; -// let b = Fp2 { -// c0: fp_from_raw_unchecked([ -// 0xa1e0_9175_a4d2_c1fe, -// 0x8b33_acfc_204e_ff12, -// 0xe244_15a1_1b45_6e42, -// 0x61d9_96b1_b6ee_1936, -// 0x1164_dbe8_667c_853c, -// 0x0788_557a_cc7d_9c79, -// ]), -// c1: fp_from_raw_unchecked([ -// 0xda6a_87cc_6f48_fa36, -// 0x0fc7_b488_277c_1903, -// 0x9445_ac4a_dc44_8187, -// 0x0261_6d5b_c909_9209, -// 0xdbed_4677_2db5_8d48, -// 0x11b9_4d50_76c7_b7b1, -// ]), -// }; -// let c = Fp2 { -// c0: fp_from_raw_unchecked([ -// 0xf597_483e_27b4_e0f7, -// 0x610f_badf_811d_ae5f, -// 0x8432_af91_7714_327a, -// 0x6a9a_9603_cf88_f09e, -// 0xf05a_7bf8_bad0_eb01, -// 0x0954_9131_c003_ffae, -// ]), -// c1: fp_from_raw_unchecked([ -// 0x963b_02d0_f93d_37cd, -// 0xc95c_e1cd_b30a_73d4, -// 0x3087_25fa_3126_f9b8, -// 0x56da_3c16_7fab_0d50, -// 0x6b50_86b5_f4b6_d6af, -// 0x09c3_9f06_2f18_e9f2, -// ]), -// }; -// assert_eq!(mul_fp2(a, b), c); -// } +// Fails! TODO: fix mult +#[tokio::test] +async fn test_multiplication() { + let a = Fp2 { + c_0: Fp{ ls:[ + 0xc9a2_1831_63ee_70d4, + 0xbc37_70a7_196b_5c91, + 0xa247_f8c1_304c_5f44, + 0xb01f_c2a3_726c_80b5, + 0xe1d2_93e5_bbd9_19c9, + 0x04b7_8e80_020e_f2ca, + ].to_vec()}, + c_1: Fp{ ls:[ + 0x952e_a446_0462_618f, + 0x238d_5edd_f025_c62f, + 0xf6c9_4b01_2ea9_2e72, + 0x03ce_24ea_c1c9_3808, + 0x0559_50f9_45da_483c, + 0x010a_768d_0df4_eabc, + ].to_vec()}, + }; + let b = Fp2 { + c_0: Fp{ ls:[ + 0xa1e0_9175_a4d2_c1fe, + 0x8b33_acfc_204e_ff12, + 0xe244_15a1_1b45_6e42, + 0x61d9_96b1_b6ee_1936, + 0x1164_dbe8_667c_853c, + 0x0788_557a_cc7d_9c79, + ].to_vec()}, + c_1: Fp{ ls:[ + 0xda6a_87cc_6f48_fa36, + 0x0fc7_b488_277c_1903, + 0x9445_ac4a_dc44_8187, + 0x0261_6d5b_c909_9209, + 0xdbed_4677_2db5_8d48, + 0x11b9_4d50_76c7_b7b1, + ].to_vec()}, + }; + let c = Fp2 { + c_0: Fp{ ls:[ + 0xf597_483e_27b4_e0f7, + 0x610f_badf_811d_ae5f, + 0x8432_af91_7714_327a, + 0x6a9a_9603_cf88_f09e, + 0xf05a_7bf8_bad0_eb01, + 0x0954_9131_c003_ffae, + ].to_vec()}, + c_1: Fp{ ls:[ + 0x963b_02d0_f93d_37cd, + 0xc95c_e1cd_b30a_73d4, + 0x3087_25fa_3126_f9b8, + 0x56da_3c16_7fab_0d50, + 0x6b50_86b5_f4b6_d6af, + 0x09c3_9f06_2f18_e9f2, + ].to_vec()}, + }; -// BLOCKED Gives error: thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Immediate18TooLarge { val: 262151, span: Span { src (ptr): 0x600013668f70, path: None, start: 0, end: 0, as_str(): "" } }', sway-core/src/asm_lang/virtual_ops.rs:866:18 -// #[test] -// fn test_squaring() { -// let a = Fp2 { -// c0: fp_from_raw_unchecked([ -// 0xc9a2_1831_63ee_70d4, -// 0xbc37_70a7_196b_5c91, -// 0xa247_f8c1_304c_5f44, -// 0xb01f_c2a3_726c_80b5, -// 0xe1d2_93e5_bbd9_19c9, -// 0x04b7_8e80_020e_f2ca, -// ]), -// c1: fp_from_raw_unchecked([ -// 0x952e_a446_0462_618f, -// 0x238d_5edd_f025_c62f, -// 0xf6c9_4b01_2ea9_2e72, -// 0x03ce_24ea_c1c9_3808, -// 0x0559_50f9_45da_483c, -// 0x010a_768d_0df4_eabc, -// ]), -// }; -// let b = Fp2 { -// c0: fp_from_raw_unchecked([ -// 0xa1e0_9175_a4d2_c1fe, -// 0x8b33_acfc_204e_ff12, -// 0xe244_15a1_1b45_6e42, -// 0x61d9_96b1_b6ee_1936, -// 0x1164_dbe8_667c_853c, -// 0x0788_557a_cc7d_9c79, -// ]), -// c1: fp_from_raw_unchecked([ -// 0xda6a_87cc_6f48_fa36, -// 0x0fc7_b488_277c_1903, -// 0x9445_ac4a_dc44_8187, -// 0x0261_6d5b_c909_9209, -// 0xdbed_4677_2db5_8d48, -// 0x11b9_4d50_76c7_b7b1, -// ]), -// }; + let (contract_instance, _id) = get_contract_instance().await; + + let res = contract_instance.mul_fp2(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + //Fails! Result is 0 + assert_eq!(res, c); +} + +/* +#[tokio::test] //Immediate18TooLarge +async fn test_squaring() { + let a = Fp2 { + c_0: Fp{ ls:[ + 0xc9a2_1831_63ee_70d4, + 0xbc37_70a7_196b_5c91, + 0xa247_f8c1_304c_5f44, + 0xb01f_c2a3_726c_80b5, + 0xe1d2_93e5_bbd9_19c9, + 0x04b7_8e80_020e_f2ca, + ].to_vec()}, + c_1: Fp{ ls:[ + 0x952e_a446_0462_618f, + 0x238d_5edd_f025_c62f, + 0xf6c9_4b01_2ea9_2e72, + 0x03ce_24ea_c1c9_3808, + 0x0559_50f9_45da_483c, + 0x010a_768d_0df4_eabc, + ].to_vec()}, + }; + let b = Fp2 { + c_0: Fp{ ls:[ + 0xa1e0_9175_a4d2_c1fe, + 0x8b33_acfc_204e_ff12, + 0xe244_15a1_1b45_6e42, + 0x61d9_96b1_b6ee_1936, + 0x1164_dbe8_667c_853c, + 0x0788_557a_cc7d_9c79, + ].to_vec()}, + c_1: Fp{ ls:[ + 0xda6a_87cc_6f48_fa36, + 0x0fc7_b488_277c_1903, + 0x9445_ac4a_dc44_8187, + 0x0261_6d5b_c909_9209, + 0xdbed_4677_2db5_8d48, + 0x11b9_4d50_76c7_b7b1, + ].to_vec()}, + }; + let (contract_instance, _id) = get_contract_instance().await; -// assert_eq!(a.square_fp2(), b); -// } \ No newline at end of file + let res = contract_instance.square_fp2(a) // results to 0 :o + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert_eq!(res, b); +} +*/ \ No newline at end of file From 6c7b47933b8b9822c20e35caeb7d24985ff209c2 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 9 Aug 2022 11:10:17 -0600 Subject: [PATCH 147/160] - Fp2 multiplication fixed - Script is updated for debugging fp2 mult --- bls12_381/src/fp.sw | 43 +++++----- bls12_381/src/fp2.sw | 10 +-- bls12_381/src/main.sw | 104 ++++++++++++++++++++----- tests_bls12_381/tests/tests_fp2/mod.rs | 3 - 4 files changed, 112 insertions(+), 48 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 0a02c7e..2414010 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -359,22 +359,21 @@ impl Fp { // (Fp([u0, u1, u2, u3, u4, u5])).subtract_p() // } -// This will be tested when fp2 multiplication is tested. This is not working atm because of Immediate18TooLarge error -//fold unpacked for the case that T = 2 + // Tested and works pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { - let u0 = 0; - let u1 = 0; - let u2 = 0; - let u3 = 0; - let u4 = 0; - let u5 = 0; + let mut u1 = 0; + let mut u2 = 0; + let mut u3 = 0; + let mut u4 = 0; + let mut u5 = 0; + let mut u6 = 0; let mut j = 0; while j < 6 { - let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); + let (t0, t1, t2, t3, t4, t5, t6) = (u1, u2, u3, u4, u5, u6, 0); let mut i = 0; - + let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); @@ -394,19 +393,23 @@ impl Fp { let k = wrapping_mul(t0, INV); let (_, carry) = mac(t0, k, MODULUS[0], 0); - let (u1, carry) = mac(t1, k, MODULUS[1], carry); - let (u2, carry) = mac(t2, k, MODULUS[2], carry); - let (u3, carry) = mac(t3, k, MODULUS[3], carry); - let (u4, carry) = mac(t4, k, MODULUS[4], carry); - let (u5, carry) = mac(t5, k, MODULUS[5], carry); - let (u6, _) = adc(t6, 0, carry); - + let (u1_temp, carry) = mac(t1, k, MODULUS[1], carry); + let (u2_temp, carry) = mac(t2, k, MODULUS[2], carry); + let (u3_temp, carry) = mac(t3, k, MODULUS[3], carry); + let (u4_temp, carry) = mac(t4, k, MODULUS[4], carry); + let (u5_temp, carry) = mac(t5, k, MODULUS[5], carry); + let (u6_temp, _) = adc(t6, 0, carry); + // assigning directly to u1..u6 didn't work. + u1 = u1_temp; + u2 = u2_temp; + u3 = u3_temp; + u4 = u4_temp; + u5 = u5_temp; + u6 = u6_temp; j += 1; } - // Because we represent F_p elements in non-redundant form, we need a final - // conditional subtraction to ensure the output is in range. - (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() + (Fp{ ls: [u1, u2, u3, u4, u5, u6]}).subtract_p() } // //TODO: Testing not done diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index d44abbc..3d008e3 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -186,8 +186,8 @@ impl Subtract for Fp2 { } } -// impl Multiply for Fp2 { -// fn multiply(self, other: Self) -> Self { -// self.mul(other) -// } -// } \ No newline at end of file +impl Multiply for Fp2 { + fn multiply(self, other: Self) -> Self { + self.mul(other) + } +} \ No newline at end of file diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index f448a59..1380878 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -1,8 +1,10 @@ script; dep fp; +dep fp2; use ::fp::Fp; +use ::fp2::Fp2; use std::{assert::assert}; use std::logging::log; @@ -10,7 +12,8 @@ use std::logging::log; // Logging in a library is easier when testing with a script. When testing through a contract that's not possible fn main () { - assert(test_square_fp()); + // assert(test_square_fp()); + assert(test_mul_fp2()); } pub fn res_equals(a: Fp, b: Fp) -> bool { @@ -23,26 +26,87 @@ pub fn res_equals(a: Fp, b: Fp) -> bool { true } -fn test_square_fp() -> bool { - let a: Fp = Fp { - ls: [0xd215_d276_8e83_191b, - 0x5085_d80f_8fb2_8261, - 0xce9a_032d_df39_3a56, - 0x3e9c_4fff_2ca0_c4bb, - 0x6436_b6f7_f4d9_5dfb, - 0x1060_6628_ad4a_4d90] - }; +// fn test_square_fp() -> bool { +// let a: Fp = Fp { +// ls: [0xd215_d276_8e83_191b, +// 0x5085_d80f_8fb2_8261, +// 0xce9a_032d_df39_3a56, +// 0x3e9c_4fff_2ca0_c4bb, +// 0x6436_b6f7_f4d9_5dfb, +// 0x1060_6628_ad4a_4d90] +// }; - let expected_res: Fp = Fp { - ls: [0x33d9_c42a_3cb3_e235, - 0xdad1_1a09_4c4c_d455, - 0xa2f1_44bd_729a_aeba, - 0xd415_0932_be9f_feac, - 0xe27b_c7c4_7d44_ee50, - 0x14b6_a78d_3ec7_a560] - }; +// let expected_res: Fp = Fp { +// ls: [0x33d9_c42a_3cb3_e235, +// 0xdad1_1a09_4c4c_d455, +// 0xa2f1_44bd_729a_aeba, +// 0xd415_0932_be9f_feac, +// 0xe27b_c7c4_7d44_ee50, +// 0x14b6_a78d_3ec7_a560] +// }; + +// let res = a.square(); +// res_equals(res, expected_res); +// true +// } - let res = a.square(); - res_equals(res, expected_res); +fn test_mul_fp2() -> bool { + let a = Fp2 { + c0: Fp{ ls: [ + 0xc9a2_1831_63ee_70d4, + 0xbc37_70a7_196b_5c91, + 0xa247_f8c1_304c_5f44, + 0xb01f_c2a3_726c_80b5, + 0xe1d2_93e5_bbd9_19c9, + 0x04b7_8e80_020e_f2ca, + ]}, + c1: Fp{ ls: [ + 0x952e_a446_0462_618f, + 0x238d_5edd_f025_c62f, + 0xf6c9_4b01_2ea9_2e72, + 0x03ce_24ea_c1c9_3808, + 0x0559_50f9_45da_483c, + 0x010a_768d_0df4_eabc, + ]}, + }; + let b = Fp2 { + c0: Fp{ ls: [ + 0xa1e0_9175_a4d2_c1fe, + 0x8b33_acfc_204e_ff12, + 0xe244_15a1_1b45_6e42, + 0x61d9_96b1_b6ee_1936, + 0x1164_dbe8_667c_853c, + 0x0788_557a_cc7d_9c79, + ]}, + c1: Fp{ ls: [ + 0xda6a_87cc_6f48_fa36, + 0x0fc7_b488_277c_1903, + 0x9445_ac4a_dc44_8187, + 0x0261_6d5b_c909_9209, + 0xdbed_4677_2db5_8d48, + 0x11b9_4d50_76c7_b7b1, + ]}, + }; + let c = Fp2 { + c0: Fp{ ls: [ + 0xf597_483e_27b4_e0f7, + 0x610f_badf_811d_ae5f, + 0x8432_af91_7714_327a, + 0x6a9a_9603_cf88_f09e, + 0xf05a_7bf8_bad0_eb01, + 0x0954_9131_c003_ffae, + ]}, + c1: Fp{ ls: [ + 0x963b_02d0_f93d_37cd, + 0xc95c_e1cd_b30a_73d4, + 0x3087_25fa_3126_f9b8, + 0x56da_3c16_7fab_0d50, + 0x6b50_86b5_f4b6_d6af, + 0x09c3_9f06_2f18_e9f2, + ]}, + }; + let res = a.mul(b); + res_equals(res.c0, c.c0); + res_equals(res.c1, c.c1); true } \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index b016314..c41358d 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -239,8 +239,6 @@ async fn test_neg_fp2() { assert!(res_equals(res.c_1, b.c_1)); } - -// Fails! TODO: fix mult #[tokio::test] async fn test_multiplication() { let a = Fp2 { @@ -305,7 +303,6 @@ async fn test_multiplication() { .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - //Fails! Result is 0 assert_eq!(res, c); } From 919fc75ea6079df234520b624a28fcc3e15c376e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Tue, 9 Aug 2022 18:47:09 -0600 Subject: [PATCH 148/160] - Fixes in g1.sw - Added test for double in g1 to main.sw (but doesn't seem to terminate) - Added sum_of_products_6. (Can't be tested yet) - Removed unnecessary comments --- bls12_381/src/fp.sw | 144 +++++++++++++++++++++++++----------------- bls12_381/src/fp2.sw | 45 ------------- bls12_381/src/fp6.sw | 7 +- bls12_381/src/g1.sw | 45 +++++++++---- bls12_381/src/main.sw | 17 ++++- 5 files changed, 137 insertions(+), 121 deletions(-) diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 2414010..8d5c74f 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -359,37 +359,44 @@ impl Fp { // (Fp([u0, u1, u2, u3, u4, u5])).subtract_p() // } - // Tested and works - pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { + pub fn sum_of_products_6(a: [Fp; 6], b: [Fp; 6]) -> Fp { let mut u1 = 0; let mut u2 = 0; let mut u3 = 0; let mut u4 = 0; let mut u5 = 0; let mut u6 = 0; + let mut j = 0; while j < 6 { - let (t0, t1, t2, t3, t4, t5, t6) = (u1, u2, u3, u4, u5, u6, 0); - + let mut t0 = u1; + let mut t1 = u2; + let mut t2 = u3; + let mut t3 = u4; + let mut t4 = u5; + let mut t5 = u6; + let mut t6 = 0; + let mut i = 0; - - let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - let (t6, _) = adc(t6, 0, carry); - - i = 1; - let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - let (t6, _) = adc(t6, 0, carry); + while i < 6 { + let (t0_temp, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + let (t1_temp, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + let (t2_temp, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + let (t3_temp, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + let (t4_temp, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + let (t5_temp, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + let (t6_temp, _) = adc(t6, 0, carry); + // assigning directly to t0..t6 didn't work. + t0 = t0_temp; + t1 = t1_temp; + t2 = t2_temp; + t3 = t3_temp; + t4 = t4_temp; + t5 = t5_temp; + t6 = t6_temp; + i += 1; + } let k = wrapping_mul(t0, INV); let (_, carry) = mac(t0, k, MODULUS[0], 0); @@ -412,47 +419,65 @@ impl Fp { (Fp{ ls: [u1, u2, u3, u4, u5, u6]}).subtract_p() } - // //TODO: Testing not done - // pub fn sum_of_products_6(a: [Fp; 6], b: [Fp; 6]) -> Fp { - // let u0 = 0; - // let u1 = 0; - // let u2 = 0; - // let u3 = 0; - // let u4 = 0; - // let u5 = 0; - // let mut j = 0; - - // while j < 6 { - // let (t0, t1, t2, t3, t4, t5, t6) = (u0, u1, u2, u3, u4, u5, 0); - - // let mut i = 0; - // while i < 6 { - // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - // let (t6, _) = adc(t6, 0, carry); - // i += 1; - // } - // let k = wrapping_mul(t0, INV); - // let (_, carry) = mac(t0, k, MODULUS[0], 0); - // let (u1, carry) = mac(t1, k, MODULUS[1], carry); - // let (u2, carry) = mac(t2, k, MODULUS[2], carry); - // let (u3, carry) = mac(t3, k, MODULUS[3], carry); - // let (u4, carry) = mac(t4, k, MODULUS[4], carry); - // let (u5, carry) = mac(t5, k, MODULUS[5], carry); - // let (u6, _) = adc(t6, 0, carry); + pub fn sum_of_products_2(a: [Fp; 2], b: [Fp; 2]) -> Fp { + let mut u1 = 0; + let mut u2 = 0; + let mut u3 = 0; + let mut u4 = 0; + let mut u5 = 0; + let mut u6 = 0; + + let mut j = 0; + + while j < 6 { + let mut t0 = u1; + let mut t1 = u2; + let mut t2 = u3; + let mut t3 = u4; + let mut t4 = u5; + let mut t5 = u6; + let mut t6 = 0; - // j += 1; - // } + let mut i = 0; + while i < 2 { + let (t0_temp, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); + let (t1_temp, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); + let (t2_temp, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); + let (t3_temp, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); + let (t4_temp, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); + let (t5_temp, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); + let (t6_temp, _) = adc(t6, 0, carry); + // assigning directly to t0..t6 didn't work. + t0 = t0_temp; + t1 = t1_temp; + t2 = t2_temp; + t3 = t3_temp; + t4 = t4_temp; + t5 = t5_temp; + t6 = t6_temp; + i += 1; + } - // // Because we represent F_p elements in non-redundant form, we need a final - // // conditional subtraction to ensure the output is in range. - // (Fp{ ls: [u0, u1, u2, u3, u4, u5]}).subtract_p() - // } + let k = wrapping_mul(t0, INV); + let (_, carry) = mac(t0, k, MODULUS[0], 0); + let (u1_temp, carry) = mac(t1, k, MODULUS[1], carry); + let (u2_temp, carry) = mac(t2, k, MODULUS[2], carry); + let (u3_temp, carry) = mac(t3, k, MODULUS[3], carry); + let (u4_temp, carry) = mac(t4, k, MODULUS[4], carry); + let (u5_temp, carry) = mac(t5, k, MODULUS[5], carry); + let (u6_temp, _) = adc(t6, 0, carry); + // assigning directly to u1..u6 didn't work. + u1 = u1_temp; + u2 = u2_temp; + u3 = u3_temp; + u4 = u4_temp; + u5 = u5_temp; + u6 = u6_temp; + j += 1; + } + (Fp{ ls: [u1, u2, u3, u4, u5, u6]}).subtract_p() + } } impl Fp { @@ -476,6 +501,7 @@ impl Fp { } } +// Eq in Sway requires bool return type impl Eq for Fp { fn eq(self, other: Self) -> bool { self.eq(other) diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index 3d008e3..00e91a1 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -62,55 +62,10 @@ impl Fp2 { */ pub fn mul(self, rhs: Fp2) -> Fp2 { - // F_{p^2} x F_{p^2} multiplication implemented with operand scanning (schoolbook) - // computes the result as: - // - // a·b = (a_0 b_0 + a_1 b_1 β) + (a_0 b_1 + a_1 b_0)i - // - // In BLS12-381's F_{p^2}, our β is -1, so the resulting F_{p^2} element is: - // - // c_0 = a_0 b_0 - a_1 b_1 - // c_1 = a_0 b_1 + a_1 b_0 - // - // Each of these is a "sum of products", which we can compute efficiently. - Fp2 { c0: ~Fp::sum_of_products_2([self.c0, self.c1.neg()], [rhs.c0, rhs.c1]), c1: ~Fp::sum_of_products_2([self.c0, self.c1], [rhs.c1, rhs.c0]), } - //-------------------------------------------- - // From zcash impl - // fn mul_assign(&mut self, other: &Self) { - // let mut aa = self.c0; - // aa.mul_assign(&other.c0); - // let mut bb = self.c1; - // bb.mul_assign(&other.c1); - // let mut o = other.c0; - // o.add_assign(&other.c1); - // self.c1.add_assign(&self.c0); - // self.c1.mul_assign(&o); - // self.c1.sub_assign(&aa); - // self.c1.sub_assign(&bb); - // self.c0 = aa; - // self.c0.sub_assign(&bb); - //------------------------------------ - // let mut aa = self.c0; - // let mut aa = aa.mul(rhs.c0); - // let mut bb = self.c1; - // let mut bb = bb.mul(rhs.c1); - // let mut o = rhs.c0; - // let mut o = o.add(rhs.c1); - // let mut c1 = self.c1.add(self.c0); - // let mut c1 = self.c1.mul(o); - // let mut c1 = self.c1.sub(aa); - // let mut c1 = self.c1.sub(bb); - // let mut c0 = aa; - // let mut c1 = self.c0.sub(bb); - - // Fp2{ - // c0: c0, - // c1: c1 - // } } pub fn add(self, rhs: Fp2) -> Fp2 { diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 9d75552..a647474 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -117,7 +117,9 @@ impl Fp6 { // c2: ~Fp2::conditional_select(a.c2, b.c2, choice), // } // } -/* Can't compile if this is uncommented atm... + +/* + // not tested, gives Immediate18TooLarge error fn mul_interleaved(self, b: Self) -> Self { // The intuition for this algorithm is that we can look at F_p^6 as a direct // extension of F_p^2, and express the overall operations down to the base field @@ -193,7 +195,8 @@ impl Fp6 { }, } } - + */ +/* pub fn square(self) -> Fp6 { let s0 = self.c0.square(); let ab = self.c0 * self.c1; diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index 9ef828b..2500734 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -1,5 +1,12 @@ library g1; +dep fp; +dep choice; + +use ::fp::{Fp, from_raw_unchecked}; +use choice::{Choice, CtOption, ConditionallySelectable}; + + // Comment from zkcrypto /// This is an element of $\mathbb{G}_1$ represented in the affine coordinate space. /// It is ideal to keep elements in this representation to reduce memory usage and @@ -8,15 +15,15 @@ library g1; /// Values of `G1Affine` are guaranteed to be in the $q$-order subgroup unless an /// "unchecked" API was misused. pub struct G1Affine { - pub x: Fp, - pub y: Fp, + x: Fp, + y: Fp, infinity: Choice, } pub struct G1Projective { - pub x: Fp, - pub y: Fp, - pub z: Fp, + x: Fp, + y: Fp, + z: Fp, } fn mul_by_3b(a: Fp) -> Fp { @@ -44,15 +51,15 @@ impl G1Affine { /// Returns the identity of the group: the point at infinity. pub fn identity() -> G1Affine { G1Affine { - x: Fp::zero(), - y: Fp::one(), - infinity: Choice::from(1u8), + x: ~Fp::zero(), + y: ~Fp::one(), + infinity: ~Choice::from(1u8), } } pub fn generator() -> G1Affine { G1Affine { - x: ~Fp::from_raw_unchecked([ + x: from_raw_unchecked([ 0x5cb3_8790_fd53_0c16, 0x7817_fc67_9976_fff5, 0x154f_95c7_143b_a1c1, @@ -60,7 +67,7 @@ impl G1Affine { 0xedce_6ecc_21db_f440, 0x1201_7741_9e0b_fb75, ]), - y: ~Fp::from_raw_unchecked([ + y: from_raw_unchecked([ 0xbaac_93d5_0ce7_2271, 0x8c22_631a_7918_fd8e, 0xdd59_5f13_5707_25ce, @@ -94,11 +101,15 @@ impl G1Projective { } } + pub fn is_identity(self) -> Choice { + ~Choice::from_bool(self.z.is_zero()) + } + /// Returns a fixed generator of the group. See [`notes::design`](notes/design/index.html#fixed-generators) /// for how this generator is chosen. pub fn generator() -> G1Projective { G1Projective { - x: ~Fp::from_raw_unchecked([ + x: from_raw_unchecked([ 0x5cb3_8790_fd53_0c16, 0x7817_fc67_9976_fff5, 0x154f_95c7_143b_a1c1, @@ -106,7 +117,7 @@ impl G1Projective { 0xedce_6ecc_21db_f440, 0x1201_7741_9e0b_fb75, ]), - y: ~Fp::from_raw_unchecked([ + y: from_raw_unchecked([ 0xbaac_93d5_0ce7_2271, 0x8c22_631a_7918_fd8e, 0xdd59_5f13_5707_25ce, @@ -117,7 +128,12 @@ impl G1Projective { z: ~Fp::one(), } } +} + +impl G1Projective { + /* + // Not able to test this yet, doesn't terminate /// Computes the doubling of this point. pub fn double(self) -> G1Projective { // Algorithm 9, https://eprint.iacr.org/2015/1060.pdf @@ -147,9 +163,10 @@ impl G1Projective { z: z3, }; - ~G1Projective::conditional_select(tmp, G1Projective::identity(), self.is_identity()) + ~G1Projective::conditional_select(tmp, ~G1Projective::identity(), self.is_identity()) } - + */ +/* /// Adds this point to another point. pub fn add(self, rhs: G1Projective) -> G1Projective { // Algorithm 7, https://eprint.iacr.org/2015/1060.pdf diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index 1380878..c2b536a 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -2,20 +2,35 @@ script; dep fp; dep fp2; +dep g1; use ::fp::Fp; use ::fp2::Fp2; +use ::g1::G1Projective; use std::{assert::assert}; use std::logging::log; +use ::g1::G1Affine; + //this is a temporary file for test purposes. // Logging in a library is easier when testing with a script. When testing through a contract that's not possible fn main () { // assert(test_square_fp()); - assert(test_mul_fp2()); + // log(1010101); + // assert(test_mul_fp2()); + test_double_identity(); + +} + +// This doesn't terminate (or does it maybe give the Immediate18TooLarge after forever?) +fn test_double_identity() -> bool { + let p_id = ~G1Projective::identity(); + let doubled = p_id.double(); + true } + pub fn res_equals(a: Fp, b: Fp) -> bool { assert(a.ls[0] == b.ls[0]); assert(a.ls[1] == b.ls[1]); From 0b9cc5d0cf19dafbf0fd91ff4cbe8cb6f3d2204a Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 10 Aug 2022 14:14:20 -0600 Subject: [PATCH 149/160] - Added ConstantTimeEq and impl for Fp - Updated uses of eq to ct_eq for Fp - Tests in script expanded. This is still meant as a temporary way to debug stuff. --- bls12_381/src/choice.sw | 49 ++++++++++++++++++++++++++- bls12_381/src/fp.sw | 24 +++++++++---- bls12_381/src/g1.sw | 2 -- bls12_381/src/main.sw | 44 ++++++++++++++++++++---- tests_bls12_381/tests/tests_fp/mod.rs | 1 - 5 files changed, 103 insertions(+), 17 deletions(-) diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 1d2d939..a3ecb7a 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -1,6 +1,7 @@ library choice; -use std::{option::Option}; +use std::{option::Option, u128::*}; +use core::ops::BitwiseAnd; /////////////// IMPORTANT /////////////// @@ -43,6 +44,21 @@ impl Choice { } } +impl BitwiseAnd for u8 { + fn binary_and(self, other: Self) -> Self { + asm(r1: self, r2: other, r3) { + and r3 r1 r2; + r3: u8 + } + } +} + +impl BitwiseAnd for Choice { + fn binary_and(self, other: Self) -> Self { + ~Choice::from(self.c & other.c) + } +} + /// The `CtOption` type represents an optional value similar to the /// [`Option`](core::option::Option) type but is intended for @@ -95,4 +111,35 @@ impl CtOption { // This should have constant time implementations, but not sure atm how to do this in Sway pub trait ConditionallySelectable { fn conditional_select(a: Self, b: Self, choice: Choice) -> Self; +} + +// From https://github.com/dalek-cryptography/subtle/blob/main/src/lib.rs +pub trait ConstantTimeEq { + fn ct_eq(self, other: Self) -> Choice; +} + +pub fn add_wrap_64(a: u64, b :u64) -> u64 { + let a_128: U128 = ~U128::from(0, a); + let b_128: U128 = ~U128::from(0, b); + (a_128 + b_128).lower +} + +pub fn wrapping_neg(a: u64) -> u64 { + add_wrap_64(~u64::max() - a, 1) +} + +impl ConstantTimeEq for u64 { + fn ct_eq(self, other: u64) -> Choice { + // comments from reference impl + // x == 0 if and only if self == other + let x: u64 = self ^ other; + + // If x == 0, then x and -x are both equal to zero; + // otherwise, one or both will have its high bit set. + let y: u64 = (x | wrapping_neg(x)) >> 63; + + // Result is the opposite of the high bit (now shifted to low). + let res: u8 = y ^ (1u64); + ~Choice::from(res) + } } \ No newline at end of file diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 8d5c74f..556d4e2 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -3,7 +3,8 @@ library fp; dep choice; dep util; -use choice::{Choice, CtOption, ConditionallySelectable}; +//This import is needed because of importing ConstantTimeEq for u64 (since it's a trait for a primitive type) +use choice::*; use util::*; use std::{option::Option, u128::*, vec::Vec}; use core::ops::{Eq, Add, Subtract, Multiply}; @@ -82,6 +83,17 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { } } +impl ConstantTimeEq for Fp { + fn ct_eq(self, other: Fp) -> Choice { + ~u64::ct_eq(self.ls[0], other.ls[0]) + .binary_and(~u64::ct_eq(self.ls[1], other.ls[1])) + .binary_and(~u64::ct_eq(self.ls[2], other.ls[2])) + .binary_and(~u64::ct_eq(self.ls[3], other.ls[3])) + .binary_and(~u64::ct_eq(self.ls[4], other.ls[4])) + .binary_and(~u64::ct_eq(self.ls[5], other.ls[5])) + } +} + impl Fp { pub fn zero() -> Fp { Fp{ls: [0, 0, 0, 0, 0, 0]} @@ -156,7 +168,7 @@ pub fn from_raw_unchecked(v: [u64; 6]) -> Fp { impl Fp { pub fn is_zero(self) -> bool { - self.eq(~Fp::zero()) + self.ct_eq(~Fp::zero()).unwrap_as_bool() } fn add(self, rhs: Fp) -> Fp { @@ -504,7 +516,7 @@ impl Fp { // Eq in Sway requires bool return type impl Eq for Fp { fn eq(self, other: Self) -> bool { - self.eq(other) + self.ct_eq(other).unwrap_as_bool() } } @@ -521,9 +533,9 @@ impl Subtract for Fp { } impl Multiply for Fp { - fn multiply(self, other: Self) -> Self { - self.mul(other) - } + fn multiply(self, other: Self) -> Self { + self.mul(other) + } } pub fn montgomery_reduce(t: [u64;12]) -> Fp { diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index 2500734..9ee0303 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -105,8 +105,6 @@ impl G1Projective { ~Choice::from_bool(self.z.is_zero()) } - /// Returns a fixed generator of the group. See [`notes::design`](notes/design/index.html#fixed-generators) - /// for how this generator is chosen. pub fn generator() -> G1Projective { G1Projective { x: from_raw_unchecked([ diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index c2b536a..291c518 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -3,10 +3,12 @@ script; dep fp; dep fp2; dep g1; +dep choice; use ::fp::Fp; use ::fp2::Fp2; use ::g1::G1Projective; +use ::choice::*; use std::{assert::assert}; use std::logging::log; use ::g1::G1Affine; @@ -17,19 +19,47 @@ use ::g1::G1Affine; fn main () { // assert(test_square_fp()); - // log(1010101); // assert(test_mul_fp2()); - test_double_identity(); + // test_double_identity(); + // assert(test_wrap_neg()); + // assert(test_ct_eq()); + // assert(test_is_zero()); + assert(test_is_eq()); +} +pub fn test_is_zero() -> bool { + ~Fp::is_zero(~Fp::zero()) } -// This doesn't terminate (or does it maybe give the Immediate18TooLarge after forever?) -fn test_double_identity() -> bool { - let p_id = ~G1Projective::identity(); - let doubled = p_id.double(); - true +pub fn test_is_eq() -> bool { + let a = Fp{ ls: [ + 0xf597_483e_27b4_e0f7, + 0x610f_badf_811d_ae5f, + 0x8432_af91_7714_327a, + 0x6a9a_9603_cf88_f09e, + 0xf05a_7bf8_bad0_eb01, + 0x0954_9131_c003_ffae, + ]}; + (a == a) && (~Fp::zero() == ~Fp::zero()) } +pub fn test_wrap_neg() -> bool { + let x: u64 = 100; + let res = wrapping_neg(x); + res == 18446744073709551516 +} + +pub fn test_ct_eq() -> bool { + ~u64::ct_eq(100, (100)).unwrap_as_bool() +} + +// This doesn't terminate (or does it maybe give the Immediate18TooLarge after forever?) +// fn test_double_identity() -> bool { +// let p_id = ~G1Projective::identity(); +// let doubled = p_id.double(); +// true +// } + pub fn res_equals(a: Fp, b: Fp) -> bool { assert(a.ls[0] == b.ls[0]); diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index 89364a2..a3f1b41 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -3,7 +3,6 @@ use fuels::{ tx::{ConsensusParameters, ContractId}, }; -use helpers::get_contract_instance; abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); From d9ca8df2a7ec0f1bc55bbe223424e2a790e6a016 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 10 Aug 2022 15:54:29 -0600 Subject: [PATCH 150/160] - Fixed implementation for conditional_select - ct_eq, is_zero for Fp2 and Fp6 - Adjustments for other functions that can now use Choice instead of bool --- bls12_381/src/choice.sw | 3 ++- bls12_381/src/fp.sw | 6 +++--- bls12_381/src/fp2.sw | 24 +++++++++++++++++++++++- bls12_381/src/fp6.sw | 29 +++++++++++++++++++---------- bls12_381/src/g1.sw | 2 +- bls12_381/src/main.sw | 13 +++++++++++-- bls12_381/src/util.sw | 40 +++++++++++++++++----------------------- 7 files changed, 76 insertions(+), 41 deletions(-) diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index a3ecb7a..37c2d4d 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -110,6 +110,7 @@ impl CtOption { // This should have constant time implementations, but not sure atm how to do this in Sway pub trait ConditionallySelectable { + // Select a if choice == 1 or select b if choice == 0, in constant time. fn conditional_select(a: Self, b: Self, choice: Choice) -> Self; } @@ -118,7 +119,7 @@ pub trait ConstantTimeEq { fn ct_eq(self, other: Self) -> Choice; } -pub fn add_wrap_64(a: u64, b :u64) -> u64 { +fn add_wrap_64(a: u64, b :u64) -> u64 { let a_128: U128 = ~U128::from(0, a); let b_128: U128 = ~U128::from(0, b); (a_128 + b_128).lower diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 556d4e2..8491eee 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -167,8 +167,8 @@ pub fn from_raw_unchecked(v: [u64; 6]) -> Fp { } impl Fp { - pub fn is_zero(self) -> bool { - self.ct_eq(~Fp::zero()).unwrap_as_bool() + pub fn is_zero(self) -> Choice { + self.ct_eq(~Fp::zero()) } fn add(self, rhs: Fp) -> Fp { @@ -509,7 +509,7 @@ impl Fp { 0x1a01_11ea_397f_e69a, ]); - ~CtOption::new_from_bool(t, !self.is_zero()) + ~CtOption::new_from_bool(t, !self.is_zero().unwrap_as_bool()) } } diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index 00e91a1..fc601b5 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -1,14 +1,32 @@ library fp2; dep fp; +dep choice; + use fp::Fp; use core::ops::{Eq, Add, Subtract, Multiply}; +use choice::*; pub struct Fp2 { c0: Fp, c1: Fp, } +impl ConstantTimeEq for Fp2 { + fn ct_eq(self, other: Self) -> Choice { + self.c0.ct_eq(other.c0) & self.c1.ct_eq(other.c1) + } +} + +impl ConditionallySelectable for Fp2 { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + Fp2 { + c0: ~Fp::conditional_select(a.c0, b.c0, choice), + c1: ~Fp::conditional_select(a.c1, b.c1, choice), + } + } +} + impl Fp2 { fn from(f: Fp) -> Fp2 { Fp2 { @@ -31,8 +49,12 @@ impl Fp2 { } } + pub fn is_zero(self) -> Choice { + self.c0.is_zero().binary_and(self.c1.is_zero()) + } + fn eq(self, other: Self) -> bool { - self.c0 == other.c0 && self.c1 == other.c1 + self.ct_eq(other).unwrap_as_bool() } /* diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index a647474..fb6994a 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -6,7 +6,7 @@ dep choice; use fp::{Fp, from_raw_unchecked}; use fp2::Fp2; -use choice::{Choice, CtOption}; +use choice::{Choice, CtOption, ConstantTimeEq}; use core::ops::{Add, Multiply}; @@ -16,6 +16,11 @@ pub struct Fp6 { c2: Fp2, } +impl ConstantTimeEq for Fp6 { + fn ct_eq(self, other: Self) -> Choice { + self.c0.ct_eq(other.c0) & self.c1.ct_eq(other.c1) & self.c2.ct_eq(other.c2) + } +} impl Fp6 { fn from(f: Fp) -> Fp6 { @@ -48,7 +53,12 @@ impl Fp6 { c1: ~Fp2::zero(), c2: ~Fp2::zero(), } - }/* + } + + pub fn is_zero(self) -> Choice { + self.c0.is_zero().binary_and(self.c1.is_zero()).binary_and(self.c2.is_zero()) + } + /* //TODO test (but zkcrypto doesnt have a dedicated test, so will be tested implicitly) pub fn mul_by_1(self, c1: Fp2) -> Fp6 { @@ -109,14 +119,13 @@ impl Fp6 { } } - // // Is not tested - // fn conditional_select(a: Fp6, b: Fp6, choice: Choice) -> Fp6 { - // Fp6 { - // c0: ~Fp2::conditional_select(a.c0, b.c0, choice), - // c1: ~Fp2::conditional_select(a.c1, b.c1, choice), - // c2: ~Fp2::conditional_select(a.c2, b.c2, choice), - // } - // } + fn conditional_select(a: Fp6, b: Fp6, choice: Choice) -> Fp6 { + Fp6 { + c0: ~Fp2::conditional_select(a.c0, b.c0, choice), + c1: ~Fp2::conditional_select(a.c1, b.c1, choice), + c2: ~Fp2::conditional_select(a.c2, b.c2, choice), + } + } /* // not tested, gives Immediate18TooLarge error diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index 9ee0303..44d518e 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -102,7 +102,7 @@ impl G1Projective { } pub fn is_identity(self) -> Choice { - ~Choice::from_bool(self.z.is_zero()) + self.z.is_zero() } pub fn generator() -> G1Projective { diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index 291c518..e36dbb5 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -4,6 +4,7 @@ dep fp; dep fp2; dep g1; dep choice; +dep util; use ::fp::Fp; use ::fp2::Fp2; @@ -12,6 +13,7 @@ use ::choice::*; use std::{assert::assert}; use std::logging::log; use ::g1::G1Affine; +use ::util::*; //this is a temporary file for test purposes. @@ -24,11 +26,18 @@ fn main () { // assert(test_wrap_neg()); // assert(test_ct_eq()); // assert(test_is_zero()); - assert(test_is_eq()); + // assert(test_is_eq()); + assert(test_conditional_select()); +} + +pub fn test_conditional_select() -> bool { + let first_check = ~u64::conditional_select(10, 100, ~Choice::from(1)) == 10; + let second_check = ~u64::conditional_select(10, 100, ~Choice::from(0)) == 100; + first_check && second_check } pub fn test_is_zero() -> bool { - ~Fp::is_zero(~Fp::zero()) + ~Fp::is_zero(~Fp::zero()).unwrap_as_bool() } pub fn test_is_eq() -> bool { diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw index beb9d1f..dca9f48 100644 --- a/bls12_381/src/util.sw +++ b/bls12_381/src/util.sw @@ -1,42 +1,36 @@ library util; dep choice; -use choice::{Choice, CtOption, ConditionallySelectable}; + +use choice::{Choice, CtOption, ConditionallySelectable, wrapping_neg}; use std::{u128::U128}; +use core::ops::{BitwiseXor}; + impl ConditionallySelectable for u64 { - // TODO How can we do this in Sway in constant time? fn conditional_select(a: u64, b: u64, choice: Choice) -> u64 { - // From original impl: - // if choice = 0, mask = (-0) = 0000...0000 // if choice = 1, mask = (-1) = 1111...1111 + let choice_64: u64 = choice.unwrap_u8(); + let mask = wrapping_neg(choice_64); + b ^ (mask & (a ^ b)) + } +} - // let mask = -(choice.unwrap_u8() as to_signed_int!($t)) as $t; - // a ^ (mask & (a ^ b)) - -// Apparently this doesn't work in Sway? - // match choice { - // Choice(0) => a, - // Choice(1) => b, - // } - - // TODO improve. - if (choice.unwrap_u8() == 0) { - a - } else { - b +impl BitwiseXor for u32 { + fn binary_xor(self, other: Self) -> Self { + asm(r1: self, r2: other, r3) { + xor r3 r1 r2; + r3: u32 } } } impl ConditionallySelectable for u32 { fn conditional_select(a: u32, b: u32, choice: Choice) -> u32 { - if (choice.unwrap_u8() == 0) { - a - } else { - b - } + let choice_32: u32 = choice.unwrap_u8(); + let mask = wrapping_neg(choice_32); + b ^ (mask & (a ^ b)) } } From 885e1ee916f7a6f2ad2680bf7119b6ce8b4a943e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 10 Aug 2022 17:07:17 -0600 Subject: [PATCH 151/160] Trying to create the From trait --- bls12_381/Forc.toml | 2 +- bls12_381/src/choice.sw | 20 ++++++++++++++++++-- bls12_381/src/main.sw | 6 ++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/bls12_381/Forc.toml b/bls12_381/Forc.toml index ae041b9..6ddd920 100644 --- a/bls12_381/Forc.toml +++ b/bls12_381/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["Hashcloak"] -entry = "lib.sw" +entry = "main.sw" license = "Apache-2.0" name = "bls12_381" diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 37c2d4d..2c1d6c8 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -1,7 +1,8 @@ library choice; -use std::{option::Option, u128::*}; -use core::ops::BitwiseAnd; +use core::num::*; +use std::{option::Option, u128::U128}; +use core::ops::{BitwiseAnd, BitwiseOr}; /////////////// IMPORTANT /////////////// @@ -22,6 +23,21 @@ use core::ops::BitwiseAnd; pub struct Choice { c: u8 } +pub trait From { + fn from(input: u8) -> Self; + fn into(self) -> u8; +} + +impl From for Choice { + fn from(input: u8) -> Self { + Choice { c: input } + } + + fn into(self) -> u8 { + self.c + } +} + impl Choice { pub fn unwrap_u8(self) -> u8 { self.c diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index e36dbb5..dbcecbb 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -28,6 +28,12 @@ fn main () { // assert(test_is_zero()); // assert(test_is_eq()); assert(test_conditional_select()); + assert(test_g1()); +} + +pub fn test_g1() -> bool { + let a = ~G1Affine::identity(); + true } pub fn test_conditional_select() -> bool { From 1d3801c6770f75b146f5209257c00f0b6c243cff Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 10 Aug 2022 18:46:38 -0600 Subject: [PATCH 152/160] - Added not and conditional_select for Choice - Added bitwise_or and conditional_select for u8 - Added ct_eq for G1Affine --- bls12_381/src/choice.sw | 90 +++++++++++++++++++++++++++++------------ bls12_381/src/g1.sw | 45 +++++++++++++++------ bls12_381/src/main.sw | 9 ++++- 3 files changed, 104 insertions(+), 40 deletions(-) diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 2c1d6c8..9e86460 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -1,34 +1,31 @@ library choice; + use core::num::*; use std::{option::Option, u128::U128}; -use core::ops::{BitwiseAnd, BitwiseOr}; +use core::ops::{Eq, BitwiseAnd, BitwiseOr, BitwiseXor}; /////////////// IMPORTANT /////////////// // All of this is coming from the dalek cryptograhpy project // see https://github.com/dalek-cryptography/subtle/blob/main/src/lib.rs -// The intention is that these implementations will provide constant time functionality. -// However, it's not clear how to achieve this in Sway. -// So we use the traits and names, but have to fill out the correct implementations when we know have -// and Sway supports this. - /////////////// IMPORTANT /////////////// /// The `Choice` struct represents a choice for use in conditional assignment. /// /// It is a wrapper around a `u8`, which should have the value either `1` (true) /// or `0` (false). - pub struct Choice { c: u8 } -pub trait From { +// Can't use name "From" because of collision with trait in U128 (even though not importing u128::*). +// This seems to be a bug in Sway, see discussion in Discord https://discord.com/channels/732892373507375164/734213700835082330/1007067117029433405 +pub trait from { fn from(input: u8) -> Self; fn into(self) -> u8; } -impl From for Choice { +impl from for Choice { fn from(input: u8) -> Self { Choice { c: input } } @@ -38,6 +35,14 @@ impl From for Choice { } } +// If equals 1u8 => false, if 0u8 => true +pub fn opposite_choice_value(a: u8) -> bool { + asm(r1: a, r2) { + eq r2 r1 zero; + r2: bool + } +} + impl Choice { pub fn unwrap_u8(self) -> u8 { self.c @@ -46,11 +51,6 @@ impl Choice { pub fn unwrap_as_bool(self) -> bool { self.c == 1u8 } - - pub fn from(input: u8) -> Choice { - Choice{ c: input} - } - pub fn from_bool(b: bool) -> Choice { if b { Choice{ c: 1u8} @@ -60,6 +60,34 @@ impl Choice { } } +impl Choice { + pub fn not(self) -> Choice { + ~Choice::from_bool(opposite_choice_value(self.c)) + } +} + +impl BitwiseXor for u8 { + fn binary_xor(self, other: Self) -> Self { + asm(r1: self, r2: other, r3) { + xor r3 r1 r2; + r3: u8 + } + } +} + +impl ConditionallySelectable for u8 { + fn conditional_select(a: u8, b: u8, choice: Choice) -> u32 { + let mask = wrapping_neg(choice.unwrap_u8()); + b.binary_xor(mask & (a.binary_xor(b))) + } +} + +impl ConditionallySelectable for Choice { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + ~Choice::from(~u8::conditional_select(a.c, b.c, choice)) + } +} + impl BitwiseAnd for u8 { fn binary_and(self, other: Self) -> Self { asm(r1: self, r2: other, r3) { @@ -75,6 +103,21 @@ impl BitwiseAnd for Choice { } } +impl BitwiseOr for u8 { + fn binary_or(self, other: Self) -> Self { + asm(r1: self, r2: other, r3) { + or r3 r1 r2; + r3: u8 + } + } +} + +impl BitwiseOr for Choice { + fn binary_or(self, other: Self) -> Self { + ~Choice::from(self.c | other.c) + } +} + /// The `CtOption` type represents an optional value similar to the /// [`Option`](core::option::Option) type but is intended for @@ -112,19 +155,16 @@ impl CtOption { pub fn unwrap(self) -> T { self.value } -} -// impl From> for Option { -// fn from(source: CtOption) -> Option { -// if source.is_some().unwrap_u8() == 1u8 { -// Option::Some(source.value) -// } else { -// None -// } -// } -// } +//It seems there is no type retriction possible on generics + // pub fn unwrap_or(self, def: T) -> T + // where + // T: ConditionallySelectable, + // { + // T::conditional_select(&def, &self.value, self.is_some) + // } +} -// This should have constant time implementations, but not sure atm how to do this in Sway pub trait ConditionallySelectable { // Select a if choice == 1 or select b if choice == 0, in constant time. fn conditional_select(a: Self, b: Self, choice: Choice) -> Self; diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index 44d518e..c392e93 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -4,7 +4,8 @@ dep fp; dep choice; use ::fp::{Fp, from_raw_unchecked}; -use choice::{Choice, CtOption, ConditionallySelectable}; +use choice::{Choice, CtOption, ConditionallySelectable, ConstantTimeEq}; +use core::ops::Eq; // Comment from zkcrypto @@ -32,20 +33,38 @@ fn mul_by_3b(a: Fp) -> Fp { a + a + a // 12 } -// TODO: trying to get this to work, seems like a good starting point -// fn from(p: G1Projective) -> G1Affine { -// let zinv = p.z.invert().unwrap_or(~Fp::zero()); -// let x = p.x * zinv; -// let y = p.y * zinv; +impl ConstantTimeEq for G1Affine { + fn ct_eq(self, other: Self) -> Choice { + // The only cases in which two points are equal are + // 1. infinity is set on both + // 2. infinity is not set on both, and their coordinates are equal + + (self.infinity & other.infinity) + .binary_or( + (self.infinity.not()) + .binary_and(other.infinity.not()) + .binary_and(self.x.ct_eq(other.x)) + .binary_and(self.y.ct_eq(other.y)) + ) + } +} + -// let tmp = G1Affine { -// x, -// y, -// infinity: Choice::from(0u8), -// }; +impl ConditionallySelectable for G1Affine { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + G1Affine { + x: ~Fp::conditional_select(a.x, b.x, choice), + y: ~Fp::conditional_select(a.y, b.y, choice), + infinity: ~Choice::conditional_select(a.infinity, b.infinity, choice), + } + } +} -// G1Affine::conditional_select(&tmp, &G1Affine::identity(), zinv.is_zero()) -// } +impl Eq for G1Affine { + fn eq(self, other: Self) -> bool { + self.ct_eq(other).unwrap_as_bool() + } +} impl G1Affine { /// Returns the identity of the group: the point at infinity. diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index dbcecbb..1412b1a 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -27,13 +27,18 @@ fn main () { // assert(test_ct_eq()); // assert(test_is_zero()); // assert(test_is_eq()); - assert(test_conditional_select()); + // assert(test_conditional_select()); assert(test_g1()); + // assert(test_opposite_choice_value()); +} + +pub fn test_opposite_choice_value() -> bool { + !opposite_choice_value(1u8) && opposite_choice_value(0u8) } pub fn test_g1() -> bool { let a = ~G1Affine::identity(); - true + a.eq(a) } pub fn test_conditional_select() -> bool { From 2bfe21b7bdc87e97dc47f29ebfef46125f4ff215 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 11 Aug 2022 17:44:08 -0600 Subject: [PATCH 153/160] - fp6: added conditional_select and several trait implementations - g1: added several functions, but compilation is really slow - trait from in choice.sw can use capital letter because it doesn't shadow a trait from U128 anymore - Removed outdated comments - script in main.sw is updated with some new tests. Again, this is temporary and can be stripped down, but it is handy for debugging and testing some sub functions --- bls12_381/src/choice.sw | 19 ++-- bls12_381/src/fp.sw | 74 +------------ bls12_381/src/fp6.sw | 33 +++++- bls12_381/src/g1.sw | 212 +++++++++++++++++++++++++++++++++--- bls12_381/src/main.sw | 67 ++++++++++-- tests_bls12_381/src/main.sw | 1 - 6 files changed, 299 insertions(+), 107 deletions(-) diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 9e86460..0795769 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -20,12 +20,12 @@ pub struct Choice { c: u8 } // Can't use name "From" because of collision with trait in U128 (even though not importing u128::*). // This seems to be a bug in Sway, see discussion in Discord https://discord.com/channels/732892373507375164/734213700835082330/1007067117029433405 -pub trait from { +pub trait From { fn from(input: u8) -> Self; fn into(self) -> u8; } -impl from for Choice { +impl From for Choice { fn from(input: u8) -> Self { Choice { c: input } } @@ -148,21 +148,22 @@ impl CtOption { } } + //To reference `is_some` this would have to go in a separate Impl pub fn is_none(self) -> bool { !self.is_some.unwrap_as_bool() } + pub fn is_some(self) -> bool { + self.is_some.unwrap_as_bool() + } + pub fn unwrap(self) -> T { self.value } -//It seems there is no type retriction possible on generics - // pub fn unwrap_or(self, def: T) -> T - // where - // T: ConditionallySelectable, - // { - // T::conditional_select(&def, &self.value, self.is_some) - // } + // unwrap_or can't be implemented here.. + // There is no type restriction possible on generics in Sway + // See https://discord.com/channels/732892373507375164/734213700835082330/1007097764242522273 } pub trait ConditionallySelectable { diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index 8491eee..d14a999 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -6,7 +6,7 @@ dep util; //This import is needed because of importing ConstantTimeEq for u64 (since it's a trait for a primitive type) use choice::*; use util::*; -use std::{option::Option, u128::*, vec::Vec}; +use std::{option::Option, u128::U128, vec::Vec}; use core::ops::{Eq, Add, Subtract, Multiply}; // Little endian big integer with 6 limbs @@ -244,7 +244,7 @@ impl Fp { let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) } -/*TODO test + pub fn square(self) -> Fp { let (t1, carry) = mac(0, self.ls[0], self.ls[1], 0); let (t2, carry) = mac(0, self.ls[0], self.ls[2], carry); @@ -294,7 +294,7 @@ impl Fp { let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) } - */ + } impl Fp { @@ -303,74 +303,12 @@ impl Fp { } -//TODO implement this from zkcrypto +// TODO implement when performing many squares is possible pub fn pow_vartime(self, by: [u64; 6]) -> Self { ~Fp::zero() } -//TODO implement this one for T=6 when sum_of_products_2 is working correctly. -// (sum_of_products_2 can be tested through testing fp2 multiplication, but this is not running atm because of Immediate18TooLarge) - - /// Returns `c = a.zip(b).fold(0, |acc, (a_i, b_i)| acc + a_i * b_i)`. - /// - /// Implements Algorithm 2 from Patrick Longa's - /// [ePrint 2022-367](https://eprint.iacr.org/2022/367) §3. - // pub fn sum_of_products(a: [Fp; T], b: [Fp; T]) -> Fp { //Elena T = 6 or T = 2 - // // For a single `a x b` multiplication, operand scanning (schoolbook) takes each - // // limb of `a` in turn, and multiplies it by all of the limbs of `b` to compute - // // the result as a double-width intermediate representation, which is then fully - // // reduced at the end. Here however we have pairs of multiplications (a_i, b_i), - // // the results of which are summed. - // // - // // The intuition for this algorithm is two-fold: - // // - We can interleave the operand scanning for each pair, by processing the jth - // // limb of each `a_i` together. As these have the same offset within the overall - // // operand scanning flow, their results can be summed directly. - // // - We can interleave the multiplication and reduction steps, resulting in a - // // single bitshift by the limb size after each iteration. This means we only - // // need to store a single extra limb overall, instead of keeping around all the - // // intermediate results and eventually having twice as many limbs. - - // // Algorithm 2, line 2 - // let (u0, u1, u2, u3, u4, u5) = // Elena range and fold dont seem to exist in Sway - // (0..6).fold((0, 0, 0, 0, 0, 0), |(u0, u1, u2, u3, u4, u5), j| { - // // Algorithm 2, line 3 - // // For each pair in the overall sum of products: - // let (t0, t1, t2, t3, t4, t5, t6) = (0..T).fold( - // (u0, u1, u2, u3, u4, u5, 0), - // |(t0, t1, t2, t3, t4, t5, t6), i| { - // // Compute digit_j x row and accumulate into `u`. - // let (t0, carry) = mac(t0, a[i].ls[j], b[i].ls[0], 0); - // let (t1, carry) = mac(t1, a[i].ls[j], b[i].ls[1], carry); - // let (t2, carry) = mac(t2, a[i].ls[j], b[i].ls[2], carry); - // let (t3, carry) = mac(t3, a[i].ls[j], b[i].ls[3], carry); - // let (t4, carry) = mac(t4, a[i].ls[j], b[i].ls[4], carry); - // let (t5, carry) = mac(t5, a[i].ls[j], b[i].ls[5], carry); - // let (t6, _) = adc(t6, 0, carry); - - // (t0, t1, t2, t3, t4, t5, t6) - // }, - // ); - - // // Algorithm 2, lines 4-5 - // // This is a single step of the usual Montgomery reduction process. - // let k = wrapping_mul(t0, INV); - // let (_, carry) = mac(t0, k, MODULUS[0], 0); - // let (r1, carry) = mac(t1, k, MODULUS[1], carry); - // let (r2, carry) = mac(t2, k, MODULUS[2], carry); - // let (r3, carry) = mac(t3, k, MODULUS[3], carry); - // let (r4, carry) = mac(t4, k, MODULUS[4], carry); - // let (r5, carry) = mac(t5, k, MODULUS[5], carry); - // let (r6, _) = adc(t6, 0, carry); - - // (r1, r2, r3, r4, r5, r6) - // }); - - // // Because we represent F_p elements in non-redundant form, we need a final - // // conditional subtraction to ensure the output is in range. - // (Fp([u0, u1, u2, u3, u4, u5])).subtract_p() - // } - + // In Rust this is implemented as sum_of_products for T, but this is not possible in Sway pub fn sum_of_products_6(a: [Fp; 6], b: [Fp; 6]) -> Fp { let mut u1 = 0; let mut u2 = 0; @@ -494,7 +432,7 @@ impl Fp { impl Fp { -//TODO pow_vartime has to be implemented + CtOption is not constant time +//TODO pow_vartime has to be implemented /// Computes the multiplicative inverse of this field /// element, returning None in the case that this element /// is zero. diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index fb6994a..12a54af 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -6,9 +6,8 @@ dep choice; use fp::{Fp, from_raw_unchecked}; use fp2::Fp2; -use choice::{Choice, CtOption, ConstantTimeEq}; - -use core::ops::{Add, Multiply}; +use choice::{Choice, CtOption, ConstantTimeEq, ConditionallySelectable}; +use core::ops::{Eq, Add, Subtract, Multiply}; pub struct Fp6 { c0: Fp2, @@ -22,8 +21,22 @@ impl ConstantTimeEq for Fp6 { } } +impl ConditionallySelectable for Fp6 { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + Fp6 { + c0: ~Fp2::conditional_select(a.c0, b.c0, choice), + c1: ~Fp2::conditional_select(a.c1, b.c1, choice), + c2: ~Fp2::conditional_select(a.c2, b.c2, choice), + } + } +} + impl Fp6 { - fn from(f: Fp) -> Fp6 { + fn eq(self, other: Self) -> bool { + self.ct_eq(other).unwrap_as_bool() + } + + fn from(f: Fp) -> Fp6 {//is it possibly to have multiple functions with same name and different arguments? Fp6 { c0: ~Fp2::from(f), c1: ~Fp2::zero(), @@ -260,12 +273,24 @@ impl Fp6 { */ } +impl Eq for Fp6 { + fn eq(self, other: Self) -> bool { + self.eq(other) + } +} + impl Add for Fp6 { fn add(self, other: Self) -> Self { self.add(other) } } +impl Subtract for Fp6 { + fn subtract(self, other: Self) -> Self { + self.sub(other) + } +} + // impl Multiply for Fp6 { // fn multiply(self, other: Self) -> Self { // self.mul_interleaved(other) diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index c392e93..17d1162 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -5,7 +5,7 @@ dep choice; use ::fp::{Fp, from_raw_unchecked}; use choice::{Choice, CtOption, ConditionallySelectable, ConstantTimeEq}; -use core::ops::Eq; +use core::ops::{Eq, Add}; // Comment from zkcrypto @@ -21,11 +21,14 @@ pub struct G1Affine { infinity: Choice, } -pub struct G1Projective { - x: Fp, - y: Fp, - z: Fp, -} +pub const B: Fp = from_raw_unchecked([ + 0xaa27_0000_000c_fff3, + 0x53cc_0032_fc34_000a, + 0x478f_e97a_6b0a_807f, + 0xb1d3_7ebe_e6ba_24d7, + 0x8ec9_733b_bf78_ab2f, + 0x09d6_4551_3d83_de7e, +]); fn mul_by_3b(a: Fp) -> Fp { let a = a + a; // 2 @@ -35,6 +38,7 @@ fn mul_by_3b(a: Fp) -> Fp { impl ConstantTimeEq for G1Affine { fn ct_eq(self, other: Self) -> Choice { + // Comment from zkcrypto // The only cases in which two points are equal are // 1. infinity is set on both // 2. infinity is not set on both, and their coordinates are equal @@ -49,6 +53,25 @@ impl ConstantTimeEq for G1Affine { } } +pub trait From_Proj { + fn from(p: G1Projective) -> Self; +} + +fn unwrap_or(input: CtOption, default: Fp) -> Fp { + match input.is_some() { + true => input.unwrap(), + false => default, + } +} + +//TODO +// - needs fp invert, which is not working yet +// - will use already created fn `unwrap_or` since adding unwrap_or to trait CtOption can't work yet +// impl From_Proj for G1Affine { +// fn from(p: G1Projective) -> Self { +// .. +// } +// } impl ConditionallySelectable for G1Affine { fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { @@ -76,6 +99,29 @@ impl G1Affine { } } + pub fn is_identity(self) -> Choice { + self.infinity + } + + // TODO TEST WHEN POSSIBLE: Uses mul_by_x on G1Projective which uses double, which can't compile + // pub fn is_torsion_free(self) -> Choice { + // Comment from zkcrypto + // // Algorithm from Section 6 of https://eprint.iacr.org/2021/1130 + // // Updated proof of correctness in https://eprint.iacr.org/2022/352 + // // + // // Check that endomorphism_p(P) == -[x^2] P + + // let minus_x_squared_times_p = from(self).mul_by_x().mul_by_x().neg(); + // let endomorphism_p = endomorphism(self); + // minus_x_squared_times_p.ct_eq(from(endomorphism_p)) + // } + + //Errors to Immediate18TooLarge + // pub fn is_on_curve(self) -> Choice { + // // y^2 - x^3 ?= 4 + // (self.y.square() - (self.x.square() * self.x)).ct_eq(B) | self.infinity + // } + pub fn generator() -> G1Affine { G1Affine { x: from_raw_unchecked([ @@ -97,20 +143,46 @@ impl G1Affine { infinity: ~Choice::from(0u8), } } -} - -impl ConditionallySelectable for G1Projective { - fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { - G1Projective { - x: ~Fp::conditional_select(a.x, b.x, choice), - y: ~Fp::conditional_select(a.y, b.y, choice), - z: ~Fp::conditional_select(a.z, b.z, choice), + fn neg(self) -> G1Affine {//will be tested with subtraction (TODO) + G1Affine { + x: self.x, + y: ~Fp::conditional_select(self.y.neg(), ~Fp::one(), self.infinity), + infinity: self.infinity, } } } +// Comment from zkcrypto +/// A nontrivial third root of unity in Fp +pub const BETA: Fp = from_raw_unchecked([ + 0x30f1_361b_798a_64e8, + 0xf3b8_ddab_7ece_5a2a, + 0x16a8_ca3a_c615_77f7, + 0xc26a_2ff8_74fd_029b, + 0x3636_b766_6070_1c6e, + 0x051b_a4ab_241b_6160, +]); + +fn endomorphism(p: G1Affine) -> G1Affine { + // Comment from zkcrypto + // Endomorphism of the points on the curve. + // endomorphism_p(x,y) = (BETA * x, y) + // where BETA is a non-trivial cubic root of unity in Fq. + let mut res = p; + res.x *= BETA; + res +} + +pub struct G1Projective { + x: Fp, + y: Fp, + z: Fp, +} + + impl G1Projective { + // Comment from zkcrypto /// Returns the identity of the group: the point at infinity. pub fn identity() -> G1Projective { G1Projective { @@ -124,6 +196,22 @@ impl G1Projective { self.z.is_zero() } + pub fn neg(self) -> G1Projective { //will be tested with subtraction (TODO) + G1Projective { + x: self.x, + y: self.y.neg(), + z: self.z, + } + } + + //Errors to Immediate18TooLarge + // pub fn is_on_curve(self) -> Choice { + // // Y^2 Z = X^3 + b Z^3 + + // (self.y.square() * self.z).ct_eq(self.x.square() * self.x + self.z.square() * self.z * B) + // | self.z.is_zero() + // } + pub fn generator() -> G1Projective { G1Projective { x: from_raw_unchecked([ @@ -147,6 +235,16 @@ impl G1Projective { } } +impl ConditionallySelectable for G1Projective { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + G1Projective { + x: ~Fp::conditional_select(a.x, b.x, choice), + y: ~Fp::conditional_select(a.y, b.y, choice), + z: ~Fp::conditional_select(a.z, b.z, choice), + } + } +} + impl G1Projective { /* @@ -183,9 +281,9 @@ impl G1Projective { ~G1Projective::conditional_select(tmp, ~G1Projective::identity(), self.is_identity()) } */ -/* - /// Adds this point to another point. + pub fn add(self, rhs: G1Projective) -> G1Projective { + // Comment from zkcrypto // Algorithm 7, https://eprint.iacr.org/2015/1060.pdf let t0 = self.x * rhs.x; @@ -228,5 +326,85 @@ impl G1Projective { z: z3, } } -*/ + +//TODO TEST + pub fn add_mixed(self, rhs: G1Affine) -> G1Projective { + // Comment from zkcrypto + // Algorithm 8, https://eprint.iacr.org/2015/1060.pdf + + let t0 = self.x * rhs.x; + let t1 = self.y * rhs.y; + let t3 = rhs.x + rhs.y; + let t4 = self.x + self.y; + let t3 = t3 * t4; + let t4 = t0 + t1; + let t3 = t3 - t4; + let t4 = rhs.y * self.z; + let t4 = t4 + self.y; + let y3 = rhs.x * self.z; + let y3 = y3 + self.x; + let x3 = t0 + t0; + let t0 = x3 + t0; + let t2 = mul_by_3b(self.z); + let z3 = t1 + t2; + let t1 = t1 - t2; + let y3 = mul_by_3b(y3); + let x3 = t4 * y3; + let t2 = t3 * t1; + let x3 = t2 - x3; + let y3 = y3 * t0; + let t1 = t1 * z3; + let y3 = t1 + y3; + let t0 = t0 * t3; + let z3 = z3 * t4; + let z3 = z3 + t0; + + let tmp = G1Projective { + x: x3, + y: y3, + z: z3, + }; + + ~G1Projective::conditional_select(tmp, self, rhs.is_identity()) + } +} + +pub trait From_Aff { + fn from(p: G1Affine) -> Self; +} + +impl From_Aff for G1Projective { + fn from(p: G1Affine) -> Self { + G1Projective { + x: p.x, + y: p.y, + z: ~Fp::conditional_select(~Fp::one(), ~Fp::zero(), p.infinity), + } + } +} + +impl ConstantTimeEq for G1Projective { + fn ct_eq(self, other: Self) -> Choice { + // Comments from zkcrypto + // Is (xz, yz, z) equal to (x'z', y'z', z') when converted to affine? + + let x1 = self.x * other.z; + let x2 = other.x * self.z; + + let y1 = self.y * other.z; + let y2 = other.y * self.z; + + let self_is_zero = self.z.is_zero(); + let other_is_zero = other.z.is_zero(); + + self_is_zero.binary_and(other_is_zero) // Both point at infinity + .binary_or(((~Choice::not(self_is_zero)).binary_and(~Choice::not(other_is_zero)).binary_and(x1.ct_eq(x2).binary_and(y1.ct_eq(y2))))) + // Neither point at infinity, coordinates are the same + } +} + +impl Eq for G1Projective { + fn eq(self, other: Self) -> bool { + self.ct_eq(other).unwrap_as_bool() + } } \ No newline at end of file diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index 1412b1a..081a466 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -2,17 +2,17 @@ script; dep fp; dep fp2; -dep g1; +// dep g1; //compiles but takes a really long time dep choice; dep util; -use ::fp::Fp; +use ::fp::{Fp, from_raw_unchecked}; use ::fp2::Fp2; -use ::g1::G1Projective; +// use ::g1::G1Projective; use ::choice::*; use std::{assert::assert}; use std::logging::log; -use ::g1::G1Affine; +// use ::g1::G1Affine; use ::util::*; @@ -28,18 +28,69 @@ fn main () { // assert(test_is_zero()); // assert(test_is_eq()); // assert(test_conditional_select()); - assert(test_g1()); - // assert(test_opposite_choice_value()); + // assert(test_g1_equality()); + assert(test_opposite_choice_value()); + // assert(test_add_g1()); } pub fn test_opposite_choice_value() -> bool { !opposite_choice_value(1u8) && opposite_choice_value(0u8) } -pub fn test_g1() -> bool { +/*G1 compilation takes forever atm +fn test_add_g1() -> bool { + let a = G1Projective { + x: from_raw_unchecked([ + 0x29e1_e987_ef68_f2d0, + 0xc5f3_ec53_1db0_3233, + 0xacd6_c4b6_ca19_730f, + 0x18ad_9e82_7bc2_bab7, + 0x46e3_b2c5_785c_c7a9, + 0x07e5_71d4_2d22_ddd6, + ]), + y: from_raw_unchecked([ + 0x94d1_17a7_e5a5_39e7, + 0x8e17_ef67_3d4b_5d22, + 0x9d74_6aaf_508a_33ea, + 0x8c6d_883d_2516_c9a2, + 0x0bc3_b8d5_fb04_47f7, + 0x07bf_a4c7_210f_4f44, + ]), + z: ~Fp::one() + }; + + let first = a.add(a); + // let second = ~G1Projective::identity(); + // res_equals(first.x, second.x); + // res_equals(first.y, second.y); + // res_equals(first.z, second.z); + true +} + +pub fn test_g1_equality() -> bool { + let p = G1Affine { + x: from_raw_unchecked([ + 0x5cb3_8790_fd53_0c16, + 0x7817_fc67_9976_fff5, + 0x154f_95c7_143b_a1c1, + 0xf0ae_6acd_f3d0_e747, + 0xedce_6ecc_21db_f440, + 0x1201_7741_9e0b_fb75, + ]), + y: from_raw_unchecked([ + 0xbaac_93d5_0ce7_2271, + 0x8c22_631a_7918_fd8e, + 0xdd59_5f13_5707_25ce, + 0x51ac_5829_5040_5194, + 0x0e1c_8c3f_ad00_59c0, + 0x0bbc_3efc_5008_a26a, + ]), + infinity: ~Choice::from(0u8), + }; let a = ~G1Affine::identity(); - a.eq(a) + a.eq(a) && p.eq(p) && !a.eq(p) } +*/ pub fn test_conditional_select() -> bool { let first_check = ~u64::conditional_select(10, 100, ~Choice::from(1)) == 10; diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 5a29255..33925ff 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -27,7 +27,6 @@ abi BlsTestContract { // not tested, gives Immediate18TooLarge error // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; - // Gives wrong output atm #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; From af824c2acdb8faf18e4686ffab60b0e2811ea22e Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 12 Aug 2022 16:51:20 -0600 Subject: [PATCH 154/160] - Started with Fp12 - Added lexicographically_largest in fp and fp2 - Added functions in scalar and g1 - Moved subtract_wrap - main.sw script is continuously updated for debugging and testing - meant as a scratchpad --- bls12_381/Forc.toml | 2 +- bls12_381/src/choice.sw | 1 + bls12_381/src/f12.sw | 103 +++++++++ bls12_381/src/fp.sw | 47 +++-- bls12_381/src/fp2.sw | 13 ++ bls12_381/src/g1.sw | 12 ++ bls12_381/src/main.sw | 246 ++++++++++++---------- bls12_381/src/scalar.sw | 66 ++++-- bls12_381/src/util.sw | 17 +- tests_bls12_381/src/main.sw | 85 ++++---- tests_bls12_381/tests/tests_fp/mod.rs | 80 ++++++- tests_bls12_381/tests/tests_scalar/mod.rs | 6 +- 12 files changed, 490 insertions(+), 188 deletions(-) create mode 100644 bls12_381/src/f12.sw diff --git a/bls12_381/Forc.toml b/bls12_381/Forc.toml index 6ddd920..ae041b9 100644 --- a/bls12_381/Forc.toml +++ b/bls12_381/Forc.toml @@ -1,6 +1,6 @@ [project] authors = ["Hashcloak"] -entry = "main.sw" +entry = "lib.sw" license = "Apache-2.0" name = "bls12_381" diff --git a/bls12_381/src/choice.sw b/bls12_381/src/choice.sw index 0795769..54b889a 100644 --- a/bls12_381/src/choice.sw +++ b/bls12_381/src/choice.sw @@ -51,6 +51,7 @@ impl Choice { pub fn unwrap_as_bool(self) -> bool { self.c == 1u8 } + pub fn from_bool(b: bool) -> Choice { if b { Choice{ c: 1u8} diff --git a/bls12_381/src/f12.sw b/bls12_381/src/f12.sw new file mode 100644 index 0000000..956c467 --- /dev/null +++ b/bls12_381/src/f12.sw @@ -0,0 +1,103 @@ +library fp12; + +dep fp6; + +use fp6::Fp6; +use choice::{ConstantTimeEq}; +use core::ops::{Eq, Add, Subtract, Multiply}; + +pub struct Fp12 { + c0: Fp6, + c1: Fp6, +} + +impl ConditionallySelectable for Fp12 { + fn conditional_select(a: Self, b: Self, choice: Choice) -> Self { + Fp12 { + c0: ~Fp6::conditional_select(a.c0, b.c0, choice), + c1: ~Fp6::conditional_select(a.c1, b.c1, choice), + } + } +} + +impl ConstantTimeEq for Fp12 { + fn ct_eq(self, other: Self) -> Choice { + self.c0.ct_eq(other.c0) & self.c1.ct_eq(other.c1) + } +} + +impl Fp12 { + fn eq(self, other: Self) -> bool { + self.ct_eq(other).unwrap_as_bool() + } + + pub fn zero() -> Self { + Fp12 { + c0: ~Fp6::zero(), + c1: ~Fp6::zero(), + } + } + + pub fn one() -> Self { + Fp12 { + c0: ~Fp6::one(), + c1: ~Fp6::zero(), + } + } + + fn from(f: Fp) -> Fp12 { + Fp12 { + c0: ~Fp6::from(f), + c1: ~Fp6::zero(), + } + } + + fn from(f: Fp2) -> Fp12 { + Fp12 { + c0: ~Fp6::from(f), + c1: ~Fp6::zero(), + } + } + + fn from(f: Fp6) -> Fp12 { + Fp12 { + c0: f, + c1: ~Fp6::zero(), + } + } + + pub fn is_zero(self) -> Choice { + self.c0.is_zero().binary_and(self.c1.is_zero()) + } + + fn neg(self) -> Self { + Fp12 { + c0: self.c0.neg(), + c1: self.c1.neg(), + } + } +} + +impl Eq for Fp12 { + fn eq(self, other: Self) -> bool { + self.eq(other) + } +} + +impl Add for Fp12 { + fn add(self, rhs: Fp12) -> Self { + Fp12 { + c0: self.c0 + rhs.c0, + c1: self.c1 + rhs.c1, + } + } +} + +impl Subtract for Fp12 { + fn sub(self, rhs: Fp12) -> Self { + Fp12 { + c0: self.c0 - rhs.c0, + c1: self.c1 - rhs.c1, + } + } +} \ No newline at end of file diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index d14a999..e53f7a1 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -73,16 +73,6 @@ fn not(input: u64) -> u64 { ~u64::max() - input } -// TODO rewrite without if branch -// If x >= y: x-y, else max::U64 - (y-x) -pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { - if y > x { - ~u64::max() - (y - x - 1) - } else { - x - y - } -} - impl ConstantTimeEq for Fp { fn ct_eq(self, other: Fp) -> Choice { ~u64::ct_eq(self.ls[0], other.ls[0]) @@ -146,9 +136,9 @@ impl Fp { let(r4, borrow) = sbb(self.ls[4], MODULUS[4], borrow); let(r5, borrow) = sbb(self.ls[5], MODULUS[5], borrow); - // If underflow occurred on the final limb, borrow = 1, otherwise - // borrow = 0. We convert it into a mask. - let mut mask = borrow * ~u64::max(); + // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise + // borrow = 0x000...000. Thus, we use it as a mask! + let mut mask = borrow; let r0 = (self.ls[0] & mask) | (r0 & not(mask)); let r1 = (self.ls[1] & mask) | (r1 & not(mask)); let r2 = (self.ls[2] & mask) | (r2 & not(mask)); @@ -428,6 +418,37 @@ impl Fp { (Fp{ ls: [u1, u2, u3, u4, u5, u6]}).subtract_p() } + + /// Returns whether or not this element is strictly lexicographically + /// larger than its negation. + pub fn lexicographically_largest(self) -> Choice { + // This can be determined by checking to see if the element is + // larger than (p - 1) // 2. If we subtract by ((p - 1) // 2) + 1 + // and there is no underflow, then the element must be larger than + // (p - 1) // 2. + + // First, because self is in Montgomery form we need to reduce it + let tmp = montgomery_reduce( + [self.ls[0], self.ls[1], self.ls[2], self.ls[3], self.ls[4], self.ls[5], 0, 0, 0, 0, 0, 0,] + ); + + let (_, borrow) = sbb(tmp.ls[0], 0xdcff_7fff_ffff_d556, 0); + let (_, borrow) = sbb(tmp.ls[1], 0x0f55_ffff_58a9_ffff, borrow); + let (_, borrow) = sbb(tmp.ls[2], 0xb398_6950_7b58_7b12, borrow); + let (_, borrow) = sbb(tmp.ls[3], 0xb23b_a5c2_79c2_895f, borrow); + let (_, borrow) = sbb(tmp.ls[4], 0x258d_d3db_21a5_d66b, borrow); + let (_, borrow) = sbb(tmp.ls[5], 0x0d00_88f5_1cbf_f34d, borrow); + + // If the element was smaller, the subtraction will underflow + // producing a borrow value of 0xffff...ffff, otherwise it will + // be zero. We create a Choice representing true if there was + // overflow (and so this element is not lexicographically larger + // than its negation) and then negate it. + + let borrow_u8: u8 = borrow; + ~Choice::from(borrow_u8 & 1).not() + } + } impl Fp { diff --git a/bls12_381/src/fp2.sw b/bls12_381/src/fp2.sw index fc601b5..9ad2ebd 100644 --- a/bls12_381/src/fp2.sw +++ b/bls12_381/src/fp2.sw @@ -124,6 +124,19 @@ impl Fp2 { } } + /// Returns whether or not this element is strictly lexicographically + /// larger than its negation. + pub fn lexicographically_largest(self) -> Choice { + // If this element's c1 coefficient is lexicographically largest + // then it is lexicographically largest. Otherwise, in the event + // the c1 coefficient is zero and the c0 coefficient is + // lexicographically largest, then this element is lexicographically + // largest. + + self.c1.lexicographically_largest() + .binary_or(self.c1.is_zero().binary_and(self.c0.lexicographically_largest())) + } + pub fn conjugate(self) -> Fp2 { Fp2{ c0: self.c0, diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index 17d1162..bae9d78 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -407,4 +407,16 @@ impl Eq for G1Projective { fn eq(self, other: Self) -> bool { self.ct_eq(other).unwrap_as_bool() } +} + +impl Add for G1Projective { + fn add(self, other: Self) -> Self { + self.add(other) + } +} + +impl Sub for G1Projective { + fn subtract(self, other: Self) -> Self { + self + (other.neg()) + } } \ No newline at end of file diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index 081a466..d97ada0 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -1,20 +1,21 @@ script; -dep fp; -dep fp2; +// dep fp; +// dep fp2; // dep g1; //compiles but takes a really long time -dep choice; -dep util; +// dep choice; +// dep util; +dep scalar; -use ::fp::{Fp, from_raw_unchecked}; -use ::fp2::Fp2; +// use ::fp::{Fp, from_raw_unchecked}; +// use ::fp2::Fp2; // use ::g1::G1Projective; -use ::choice::*; +// use ::choice::*; use std::{assert::assert}; -use std::logging::log; +// use std::logging::log; // use ::g1::G1Affine; -use ::util::*; - +// use ::util::*; +use ::scalar::*; //this is a temporary file for test purposes. // Logging in a library is easier when testing with a script. When testing through a contract that's not possible @@ -29,14 +30,41 @@ fn main () { // assert(test_is_eq()); // assert(test_conditional_select()); // assert(test_g1_equality()); - assert(test_opposite_choice_value()); + // assert(test_opposite_choice_value()); // assert(test_add_g1()); + assert(test_scalar_equality()); + assert(test_scalar_neg()); +} + +pub fn test_scalar_neg() -> bool { + let largest = Scalar { ls: [ + 0xffff_ffff_0000_0000, + 0x53bd_a402_fffe_5bfe, + 0x3339_d808_09a1_d805, + 0x73ed_a753_299d_7d48, + ]}; + let neg_largest = largest.neg(); + assert(neg_largest == Scalar { ls: [1, 0, 0, 0]}); + + let zero = Scalar { ls: [0,0,0,0]}; + let neg_zero = zero.neg(); + assert(neg_zero == Scalar { ls: [0,0,0,0]} ); + + let neg_one = (Scalar { ls: [1,0,0,0]}).neg(); + assert(neg_one == largest); + + true } -pub fn test_opposite_choice_value() -> bool { - !opposite_choice_value(1u8) && opposite_choice_value(0u8) +pub fn test_scalar_equality() -> bool { + assert(R2 == R2); + true } +// pub fn test_opposite_choice_value() -> bool { +// !opposite_choice_value(1u8) && opposite_choice_value(0u8) +// }x + /*G1 compilation takes forever atm fn test_add_g1() -> bool { let a = G1Projective { @@ -92,37 +120,37 @@ pub fn test_g1_equality() -> bool { } */ -pub fn test_conditional_select() -> bool { - let first_check = ~u64::conditional_select(10, 100, ~Choice::from(1)) == 10; - let second_check = ~u64::conditional_select(10, 100, ~Choice::from(0)) == 100; - first_check && second_check -} +// pub fn test_conditional_select() -> bool { +// let first_check = ~u64::conditional_select(10, 100, ~Choice::from(1)) == 10; +// let second_check = ~u64::conditional_select(10, 100, ~Choice::from(0)) == 100; +// first_check && second_check +// } -pub fn test_is_zero() -> bool { - ~Fp::is_zero(~Fp::zero()).unwrap_as_bool() -} +// pub fn test_is_zero() -> bool { +// ~Fp::is_zero(~Fp::zero()).unwrap_as_bool() +// } -pub fn test_is_eq() -> bool { - let a = Fp{ ls: [ - 0xf597_483e_27b4_e0f7, - 0x610f_badf_811d_ae5f, - 0x8432_af91_7714_327a, - 0x6a9a_9603_cf88_f09e, - 0xf05a_7bf8_bad0_eb01, - 0x0954_9131_c003_ffae, - ]}; - (a == a) && (~Fp::zero() == ~Fp::zero()) -} +// pub fn test_is_eq() -> bool { +// let a = Fp{ ls: [ +// 0xf597_483e_27b4_e0f7, +// 0x610f_badf_811d_ae5f, +// 0x8432_af91_7714_327a, +// 0x6a9a_9603_cf88_f09e, +// 0xf05a_7bf8_bad0_eb01, +// 0x0954_9131_c003_ffae, +// ]}; +// (a == a) && (~Fp::zero() == ~Fp::zero()) +// } -pub fn test_wrap_neg() -> bool { - let x: u64 = 100; - let res = wrapping_neg(x); - res == 18446744073709551516 -} +// pub fn test_wrap_neg() -> bool { +// let x: u64 = 100; +// let res = wrapping_neg(x); +// res == 18446744073709551516 +// } -pub fn test_ct_eq() -> bool { - ~u64::ct_eq(100, (100)).unwrap_as_bool() -} +// pub fn test_ct_eq() -> bool { +// ~u64::ct_eq(100, (100)).unwrap_as_bool() +// } // This doesn't terminate (or does it maybe give the Immediate18TooLarge after forever?) // fn test_double_identity() -> bool { @@ -132,15 +160,15 @@ pub fn test_ct_eq() -> bool { // } -pub fn res_equals(a: Fp, b: Fp) -> bool { - assert(a.ls[0] == b.ls[0]); - assert(a.ls[1] == b.ls[1]); - assert(a.ls[2] == b.ls[2]); - assert(a.ls[3] == b.ls[3]); - assert(a.ls[4] == b.ls[4]); - assert(a.ls[5] == b.ls[5]); - true -} +// pub fn res_equals(a: Fp, b: Fp) -> bool { +// assert(a.ls[0] == b.ls[0]); +// assert(a.ls[1] == b.ls[1]); +// assert(a.ls[2] == b.ls[2]); +// assert(a.ls[3] == b.ls[3]); +// assert(a.ls[4] == b.ls[4]); +// assert(a.ls[5] == b.ls[5]); +// true +// } // fn test_square_fp() -> bool { // let a: Fp = Fp { @@ -166,63 +194,63 @@ pub fn res_equals(a: Fp, b: Fp) -> bool { // true // } -fn test_mul_fp2() -> bool { - let a = Fp2 { - c0: Fp{ ls: [ - 0xc9a2_1831_63ee_70d4, - 0xbc37_70a7_196b_5c91, - 0xa247_f8c1_304c_5f44, - 0xb01f_c2a3_726c_80b5, - 0xe1d2_93e5_bbd9_19c9, - 0x04b7_8e80_020e_f2ca, - ]}, - c1: Fp{ ls: [ - 0x952e_a446_0462_618f, - 0x238d_5edd_f025_c62f, - 0xf6c9_4b01_2ea9_2e72, - 0x03ce_24ea_c1c9_3808, - 0x0559_50f9_45da_483c, - 0x010a_768d_0df4_eabc, - ]}, - }; - let b = Fp2 { - c0: Fp{ ls: [ - 0xa1e0_9175_a4d2_c1fe, - 0x8b33_acfc_204e_ff12, - 0xe244_15a1_1b45_6e42, - 0x61d9_96b1_b6ee_1936, - 0x1164_dbe8_667c_853c, - 0x0788_557a_cc7d_9c79, - ]}, - c1: Fp{ ls: [ - 0xda6a_87cc_6f48_fa36, - 0x0fc7_b488_277c_1903, - 0x9445_ac4a_dc44_8187, - 0x0261_6d5b_c909_9209, - 0xdbed_4677_2db5_8d48, - 0x11b9_4d50_76c7_b7b1, - ]}, - }; - let c = Fp2 { - c0: Fp{ ls: [ - 0xf597_483e_27b4_e0f7, - 0x610f_badf_811d_ae5f, - 0x8432_af91_7714_327a, - 0x6a9a_9603_cf88_f09e, - 0xf05a_7bf8_bad0_eb01, - 0x0954_9131_c003_ffae, - ]}, - c1: Fp{ ls: [ - 0x963b_02d0_f93d_37cd, - 0xc95c_e1cd_b30a_73d4, - 0x3087_25fa_3126_f9b8, - 0x56da_3c16_7fab_0d50, - 0x6b50_86b5_f4b6_d6af, - 0x09c3_9f06_2f18_e9f2, - ]}, - }; - let res = a.mul(b); - res_equals(res.c0, c.c0); - res_equals(res.c1, c.c1); - true -} \ No newline at end of file +// fn test_mul_fp2() -> bool { +// let a = Fp2 { +// c0: Fp{ ls: [ +// 0xc9a2_1831_63ee_70d4, +// 0xbc37_70a7_196b_5c91, +// 0xa247_f8c1_304c_5f44, +// 0xb01f_c2a3_726c_80b5, +// 0xe1d2_93e5_bbd9_19c9, +// 0x04b7_8e80_020e_f2ca, +// ]}, +// c1: Fp{ ls: [ +// 0x952e_a446_0462_618f, +// 0x238d_5edd_f025_c62f, +// 0xf6c9_4b01_2ea9_2e72, +// 0x03ce_24ea_c1c9_3808, +// 0x0559_50f9_45da_483c, +// 0x010a_768d_0df4_eabc, +// ]}, +// }; +// let b = Fp2 { +// c0: Fp{ ls: [ +// 0xa1e0_9175_a4d2_c1fe, +// 0x8b33_acfc_204e_ff12, +// 0xe244_15a1_1b45_6e42, +// 0x61d9_96b1_b6ee_1936, +// 0x1164_dbe8_667c_853c, +// 0x0788_557a_cc7d_9c79, +// ]}, +// c1: Fp{ ls: [ +// 0xda6a_87cc_6f48_fa36, +// 0x0fc7_b488_277c_1903, +// 0x9445_ac4a_dc44_8187, +// 0x0261_6d5b_c909_9209, +// 0xdbed_4677_2db5_8d48, +// 0x11b9_4d50_76c7_b7b1, +// ]}, +// }; +// let c = Fp2 { +// c0: Fp{ ls: [ +// 0xf597_483e_27b4_e0f7, +// 0x610f_badf_811d_ae5f, +// 0x8432_af91_7714_327a, +// 0x6a9a_9603_cf88_f09e, +// 0xf05a_7bf8_bad0_eb01, +// 0x0954_9131_c003_ffae, +// ]}, +// c1: Fp{ ls: [ +// 0x963b_02d0_f93d_37cd, +// 0xc95c_e1cd_b30a_73d4, +// 0x3087_25fa_3126_f9b8, +// 0x56da_3c16_7fab_0d50, +// 0x6b50_86b5_f4b6_d6af, +// 0x09c3_9f06_2f18_e9f2, +// ]}, +// }; +// let res = a.mul(b); +// res_equals(res.c0, c.c0); +// res_equals(res.c1, c.c1); +// true +// } \ No newline at end of file diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index ef16ee9..0509278 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -3,7 +3,8 @@ library scalar; dep choice; dep util; -use choice::{Choice, CtOption, ConditionallySelectable}; +//This import is needed because of importing ConstantTimeEq for u64 (since it's a trait for a primitive type) +use choice::*; use util::*; use core::ops::{Eq, Add, Subtract, Multiply}; @@ -53,7 +54,7 @@ const R: Scalar = Scalar{ ls: [ ]}; /// R^2 = 2^512 mod q -const R2: Scalar = Scalar{ ls: [ +pub const R2: Scalar = Scalar{ ls: [ 0xc999_e990_f3f2_9c6d, 0x2b6c_edcb_8792_5c23, 0x05d3_1496_7254_398f, @@ -89,6 +90,15 @@ impl ConditionallySelectable for Scalar { } } +impl ConstantTimeEq for Scalar { + fn ct_eq(self, other: Self) -> Choice { + ~u64::ct_eq(self.ls[0], other.ls[0]) + .binary_and(~u64::ct_eq(self.ls[1], other.ls[1])) + .binary_and(~u64::ct_eq(self.ls[2], other.ls[2])) + .binary_and(~u64::ct_eq(self.ls[3], other.ls[3])) + } +} + impl Scalar { pub fn zero() -> Scalar { @@ -99,22 +109,6 @@ impl Scalar { R } - fn ct(self, other: Self) -> Choice { - ~Choice::from_bool( - self.ls[0] == other.ls[0] - && self.ls[1] == other.ls[1] - && self.ls[2] == other.ls[2] - && self.ls[3] == other.ls[3]) - } - - // TODO to make this constant time the u64 should be compared with ct_eq, but is not existing in Sway (yet) - pub fn eq(self, other: Self) -> bool { - (self.ls[0] == other.ls[0]) - && (self.ls[1] == other.ls[1]) - && (self.ls[2] == other.ls[2]) - && (self.ls[3] == other.ls[3]) - } - pub fn sub(self, rhs: Self) -> Self { let (d0, borrow) = sbb(self.ls[0], rhs.ls[0], 0); let (d1, borrow) = sbb(self.ls[1], rhs.ls[1], borrow); @@ -130,6 +124,24 @@ impl Scalar { Scalar{ ls: [d0, d1, d2, d3]} } + +//E: This was tested through script and work. Didn't add test to contract because contract testing is slow and this will be tested implicitly as well + pub fn neg(self) -> Self { + // Subtract `self` from `MODULUS` to negate. Ignore the final + // borrow because it cannot underflow; self is guaranteed to + // be in the field. + let (d0, borrow) = sbb(MODULUS_SCALAR.ls[0], self.ls[0], 0); + let (d1, borrow) = sbb(MODULUS_SCALAR.ls[1], self.ls[1], borrow); + let (d2, borrow) = sbb(MODULUS_SCALAR.ls[2], self.ls[2], borrow); + let (d3, _) = sbb(MODULUS_SCALAR.ls[3], self.ls[3], borrow); + + // `tmp` could be `MODULUS` if `self` was zero. Create a mask that is + // zero if `self` was zero, and `u64::max_value()` if self was nonzero. + let temp: u64 = if ((self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3]) == 0) { 1 } else { 0 }; + let mask = subtract_wrap_64(temp, 1); + + Scalar{ ls: [d0 & mask, d1 & mask, d2 & mask, d3 & mask]} + } } impl Scalar { @@ -268,6 +280,12 @@ impl Multiply for Scalar { } } +impl Eq for Scalar { + fn eq(self, other: Self) -> bool { + self.ct_eq(other).unwrap_as_bool() + } +} + impl Scalar { fn from(val: u64) -> Scalar { @@ -375,4 +393,16 @@ Please file an issue on the repository and include the code that triggered this // ) ~CtOption::new(self, ~Choice::from(1)) } +} + +impl Subtract for Scalar { + fn subtract(self, other: Self) -> Self { + self.sub(other) + } +} + +impl Multiply for Scalar { + fn multiply(self, other: Self) -> Self { + self.mul(other) + } } \ No newline at end of file diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw index dca9f48..57c3bde 100644 --- a/bls12_381/src/util.sw +++ b/bls12_381/src/util.sw @@ -5,6 +5,7 @@ dep choice; use choice::{Choice, CtOption, ConditionallySelectable, wrapping_neg}; use std::{u128::U128}; use core::ops::{BitwiseXor}; +use core::num::*; impl ConditionallySelectable for u64 { @@ -46,14 +47,24 @@ pub fn subtract_wrap(x: U128, y: U128) -> U128 { } } -/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). +// TODO rewrite without if branch +// If x >= y: x-y, else max::U64 - (y-x) +pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { + if y > x { + ~u64::max() - (y - x - 1) + } else { + x - y + } +} + +/// Compute a - (b + borrow), returning the result and the new borrow. pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { let a_128: U128 = ~U128::from(0, a); let b_128: U128 = ~U128::from(0, b); - let borrow_128: U128 = ~U128::from(0, borrow); + let borrow_128: U128 = ~U128::from(0, borrow >> 63); let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); - (res.lower, res.upper >> 63) //(result, borrow) + (res.lower, res.upper) //(result, borrow) } //returns sum with carry of a and b diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 33925ff..53fc3d7 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,17 +1,20 @@ contract; -use bls12_381::{ - fp::Fp, - fp::from_raw_unchecked, - fp2::Fp2, - fp6::Fp6, - scalar::Scalar}; -use bls12_381::choice::CtOption; +use bls12_381::fp::Fp; + +// use bls12_381::{ +// fp::Fp, +// fp::from_raw_unchecked, +// fp2::Fp2, +// fp6::Fp6, +// scalar::Scalar}; +use bls12_381::choice::{CtOption, Choice}; abi BlsTestContract { // Works - #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; - #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; + // #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; + // #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice; // works but takes a long time // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; @@ -20,16 +23,16 @@ abi BlsTestContract { // #[storage(read, write)]fn square_fp(a: Fp) -> Fp; // Works - #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; - #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; - #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; + // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; + // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; + // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; - // not tested, gives Immediate18TooLarge error - // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; + // // not tested, gives Immediate18TooLarge error + // // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; - #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; + // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; - #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; + // #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar; //This function gives an error // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption; @@ -41,12 +44,16 @@ abi BlsTestContract { } impl BlsTestContract for Contract { - #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp { - a + b - } + // #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp { + // a + b + // } + + // #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { + // a - b + // } - #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { - a - b + #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice { + a.lexicographically_largest() } // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { @@ -57,29 +64,29 @@ impl BlsTestContract for Contract { // a.square() // } - #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { - a + b - } - - #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 { - a - b - } + // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { + // a + b + // } - #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2 { - a.neg() - } + // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2 { + // a - b + // } - #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar { - a + b - } + // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2 { + // a.neg() + // } - // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { - // a.square() + // #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar { + // a + b // } - #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { - a * b - } + // // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { + // // a.square() + // // } + + // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { + // a * b + // } // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index a3f1b41..c078552 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -21,7 +21,7 @@ async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { ); // Custom gas limit - let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(10_000_000_000_000); let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; @@ -48,7 +48,7 @@ pub fn res_equals(res: Fp, should_be: Fp) -> bool { assert!(res.ls[5] == should_be.ls[5]); true } - +/* #[tokio::test] //works async fn test_add_fp() { let small = Fp{ @@ -70,7 +70,9 @@ async fn test_add_fp() { assert!(res_equals(res, expected_res)); } +*/ +/* #[tokio::test] //works async fn test_sub_fp() { let a = Fp { @@ -91,7 +93,7 @@ async fn test_sub_fp() { .call().await.unwrap().value; assert!(res_equals(res, expected_res)); } - +*/ /* #[tokio::test] //works, but takes a long time! async fn test_mul_fp() { @@ -174,4 +176,74 @@ async fn test_square_fp() { println!("{}", res.ls[5]); assert!(res_equals(res, expected_res)); } -*/ \ No newline at end of file +*/ + +#[tokio::test] +async fn lexicographically_largest_fp() { + let zero = Fp{ ls: [0,0,0,0,0,0].to_vec()}; + let one = Fp{ ls: [ //=R + 0x7609_0000_0002_fffd, + 0xebf4_000b_c40c_0002, + 0x5f48_9857_53c7_58ba, + 0x77ce_5853_7052_5745, + 0x5c07_1a97_a256_ec6d, + 0x15f6_5ec3_fa80_e493, + ].to_vec()}; + let first = Fp{ ls: [ + 0xa1fa_ffff_fffe_5557, + 0x995b_fff9_76a3_fffe, + 0x03f4_1d24_d174_ceb4, + 0xf654_7998_c199_5dbd, + 0x778a_468f_507a_6034, + 0x0205_5993_1f7f_8103 + ].to_vec()}; + let second = Fp{ ls: [ + 0x1804_0000_0001_5554, + 0x8550_0005_3ab0_0001, + 0x633c_b57c_253c_276f, + 0x6e22_d1ec_31eb_b502, + 0xd391_6126_f2d1_4ca2, + 0x17fb_b857_1a00_6596, + ].to_vec()}; + let third = Fp{ ls: [ + 0x43f5_ffff_fffc_aaae, + 0x32b7_fff2_ed47_fffd, + 0x07e8_3a49_a2e9_9d69, + 0xeca8_f331_8332_bb7a, + 0xef14_8d1e_a0f4_c069, + 0x040a_b326_3eff_0206, + ].to_vec()}; + + let (contract_instance, _id) = get_contract_instance().await; + + let res_zero = contract_instance.lexicographically_largest_fp(zero) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + let res_one = contract_instance.lexicographically_largest_fp(one) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + let res_first = contract_instance.lexicographically_largest_fp(first) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + let res_second = contract_instance.lexicographically_largest_fp(second) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + let res_third = contract_instance.lexicographically_largest_fp(third) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + assert!(res_zero.c == 0); + assert!(res_one.c == 0); + assert!(res_first.c == 0); + assert!(res_second.c == 1); + assert!(res_third.c == 1); +} \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_scalar/mod.rs b/tests_bls12_381/tests/tests_scalar/mod.rs index 4526912..412315b 100644 --- a/tests_bls12_381/tests/tests_scalar/mod.rs +++ b/tests_bls12_381/tests/tests_scalar/mod.rs @@ -83,6 +83,8 @@ async fn test_addition() { /*BLOCKED error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. Please file an issue on the repository and include the code that triggered this error. + +Eventually, this gave Braqzen the error Immediate18TooLarge */ // #[tokio::test] // async fn test_sqrt() { @@ -99,6 +101,8 @@ Please file an issue on the repository and include the code that triggered this /*BLOCKED error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. Please file an issue on the repository and include the code that triggered this error. + +Eventually, this gave Braqzen the error Immediate18TooLarge */ // #[tokio::test] // async fn test_sqrt() { @@ -130,4 +134,4 @@ Please file an issue on the repository and include the code that triggered this // } // assert_eq!(49, none_count); -// } \ No newline at end of file +// } From 1a117ae41380e75785872c761f8cd90af13f7fbd Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Fri, 12 Aug 2022 18:13:12 -0600 Subject: [PATCH 155/160] - Added test lexicographically_largest_fp2 (subset of test from zkcrypto impl). This runs into the error: Err` value: ValidationError(TransactionGasLimit - Added mul_by_nonresidue for fp6 which will be tested indirectly. --- bls12_381/src/fp6.sw | 14 +++++ tests_bls12_381/src/main.sw | 8 ++- tests_bls12_381/tests/tests_fp2/mod.rs | 73 +++++++++++++++++++++++--- 3 files changed, 86 insertions(+), 9 deletions(-) diff --git a/bls12_381/src/fp6.sw b/bls12_381/src/fp6.sw index 12a54af..21333ab 100644 --- a/bls12_381/src/fp6.sw +++ b/bls12_381/src/fp6.sw @@ -107,6 +107,20 @@ impl Fp6 { } } */ + + pub fn mul_by_nonresidue(self) -> Self { + // Given a + bv + cv^2, this produces + // av + bv^2 + cv^3 + // but because v^3 = u + 1, we have + // c(u + 1) + av + v^2 + + Fp6 { + c0: self.c2.mul_by_nonresidue(), + c1: self.c0, + c2: self.c1, + } + } + //TODO: Testing. Has no dedicated tests in zkcrypto pub fn add(self, rhs: Fp6) -> Fp6 { Fp6 { diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 53fc3d7..35afc9f 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,6 +1,6 @@ contract; -use bls12_381::fp::Fp; +use bls12_381::{fp::Fp, fp2::Fp2}; // use bls12_381::{ // fp::Fp, @@ -26,6 +26,7 @@ abi BlsTestContract { // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; + #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice; // // not tested, gives Immediate18TooLarge error // // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; @@ -76,6 +77,10 @@ impl BlsTestContract for Contract { // a.neg() // } + #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice { + a.lexicographically_largest() + } + // #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar { // a + b // } @@ -88,7 +93,6 @@ impl BlsTestContract for Contract { // a * b // } - // #[storage(read, write)]fn scalar_sqrt(a: Scalar) -> CtOption { // a.sqrt() // } diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index c41358d..cbc6ca5 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -47,7 +47,7 @@ pub fn res_equals(res: Fp, should_be: Fp) -> bool { assert!(res.ls[5] == should_be.ls[5]); true } - +/* #[tokio::test] async fn test_add_fp2() { @@ -116,7 +116,8 @@ async fn test_add_fp2() { assert!(res_equals(res.c_0, c.c_0)); assert!(res_equals(res.c_1, c.c_1)); } - +*/ +/* #[tokio::test] async fn test_sub_fp2() { @@ -185,8 +186,8 @@ async fn test_sub_fp2() { assert!(res_equals(res.c_0, c.c_0)); assert!(res_equals(res.c_1, c.c_1)); } - - +*/ +/* #[tokio::test] async fn test_neg_fp2() { @@ -238,7 +239,8 @@ async fn test_neg_fp2() { assert!(res_equals(res.c_0, b.c_0)); assert!(res_equals(res.c_1, b.c_1)); } - +*/ +/* #[tokio::test] async fn test_multiplication() { let a = Fp2 { @@ -305,7 +307,7 @@ async fn test_multiplication() { assert_eq!(res, c); } - +*/ /* #[tokio::test] //Immediate18TooLarge async fn test_squaring() { @@ -354,4 +356,61 @@ async fn test_squaring() { assert_eq!(res, b); } -*/ \ No newline at end of file +*/ + +#[tokio::test]//stripped down version from zkcrypto impl +async fn lexicographically_largest_fp2() { + let zero = Fp2 { + c_0 : Fp{ ls: [0,0,0,0,0,0].to_vec()}, + c_1 : Fp{ ls: [0,0,0,0,0,0].to_vec()}, + }; + let one = Fp2 { + c_0: Fp{ ls: [ //=R + 0x7609_0000_0002_fffd, + 0xebf4_000b_c40c_0002, + 0x5f48_9857_53c7_58ba, + 0x77ce_5853_7052_5745, + 0x5c07_1a97_a256_ec6d, + 0x15f6_5ec3_fa80_e493, + ].to_vec()}, + c_1 : Fp{ ls: [0,0,0,0,0,0].to_vec()} + }; + + let first = Fp2 { + c_0: Fp{ ls: [ + 0x1128_ecad_6754_9455, + 0x9e7a_1cff_3a4e_a1a8, + 0xeb20_8d51_e08b_cf27, + 0xe98a_d408_11f5_fc2b, + 0x736c_3a59_232d_511d, + 0x10ac_d42d_29cf_cbb6, + ].to_vec()}, + c_1 : Fp{ ls: [ + 0xd328_e37c_c2f5_8d41, + 0x948d_f085_8a60_5869, + 0x6032_f9d5_6f93_a573, + 0x2be4_83ef_3fff_dc87, + 0x30ef_61f8_8f48_3c2a, + 0x1333_f55a_3572_5be0].to_vec()} + }; + let (contract_instance, _id) = get_contract_instance().await; + + let res_zero = contract_instance.lexicographically_largest_fp2(zero) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + let res_one = contract_instance.lexicographically_largest_fp2(one) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + let res_first = contract_instance.lexicographically_largest_fp2(first) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) + .call().await.unwrap().value; + + assert!(res_zero.c == 0); + assert!(res_one.c == 0); + assert!(res_first.c == 1); +} From f37ba7f2c7371e5cc861430653820115752bf81f Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Wed, 31 Aug 2022 10:57:48 -0600 Subject: [PATCH 156/160] Running forc test in tests_bls12_381 gives Immediate18TooLarge. --- tests_bls12_381/src/main.sw | 52 +++++++++++++-------------- tests_bls12_381/tests/harness.rs | 4 +-- tests_bls12_381/tests/tests_fp/mod.rs | 20 +++++------ 3 files changed, 36 insertions(+), 40 deletions(-) diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 35afc9f..312b8ba 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -1,6 +1,6 @@ contract; -use bls12_381::{fp::Fp, fp2::Fp2}; +use bls12_381::{fp::Fp}; // use bls12_381::{ // fp::Fp, @@ -12,24 +12,24 @@ use bls12_381::choice::{CtOption, Choice}; abi BlsTestContract { // Works - // #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; - // #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice; // works but takes a long time - // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; + #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; - // not tested, gives Immediate18TooLarge error - // #[storage(read, write)]fn square_fp(a: Fp) -> Fp; + // works if ran by itself + #[storage(read, write)]fn square_fp(a: Fp) -> Fp; // Works // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2; // #[storage(read, write)]fn sub_fp2(a: Fp2, b: Fp2) -> Fp2; // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; - #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice; + // #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice; // // not tested, gives Immediate18TooLarge error - // // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; + // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; @@ -45,25 +45,25 @@ abi BlsTestContract { } impl BlsTestContract for Contract { - // #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp { - // a + b - // } + #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp { + a + b + } - // #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { - // a - b - // } + #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { + a - b + } #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice { a.lexicographically_largest() } - // #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { - // a * b - // } + #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { + a * b + } - // #[storage(read, write)]fn square_fp(a: Fp) -> Fp { - // a.square() - // } + #[storage(read, write)]fn square_fp(a: Fp) -> Fp { + a.square() + } // #[storage(read, write)]fn add_fp2(a: Fp2, b: Fp2) -> Fp2 { // a + b @@ -77,17 +77,17 @@ impl BlsTestContract for Contract { // a.neg() // } - #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice { - a.lexicographically_largest() - } + // #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice { + // a.lexicographically_largest() + // } // #[storage(read, write)]fn add_scalar(a: Scalar, b: Scalar) -> Scalar { // a + b // } - // // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { - // // a.square() - // // } + // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2 { + // a.square() + // } // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2 { // a * b diff --git a/tests_bls12_381/tests/harness.rs b/tests_bls12_381/tests/harness.rs index 3c61e3f..ed4b844 100644 --- a/tests_bls12_381/tests/harness.rs +++ b/tests_bls12_381/tests/harness.rs @@ -1,4 +1,4 @@ -// mod tests_fp; +mod tests_fp; // mod tests_fp2; // mod tests_fp6; -mod tests_scalar; \ No newline at end of file +// mod tests_scalar; \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index c078552..31e830b 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -3,7 +3,6 @@ use fuels::{ tx::{ConsensusParameters, ContractId}, }; - abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); //TODO move this to a separate helpers file. How to achieve this in Rust/Cargo? @@ -48,7 +47,7 @@ pub fn res_equals(res: Fp, should_be: Fp) -> bool { assert!(res.ls[5] == should_be.ls[5]); true } -/* + #[tokio::test] //works async fn test_add_fp() { let small = Fp{ @@ -70,9 +69,8 @@ async fn test_add_fp() { assert!(res_equals(res, expected_res)); } -*/ -/* + #[tokio::test] //works async fn test_sub_fp() { let a = Fp { @@ -93,8 +91,8 @@ async fn test_sub_fp() { .call().await.unwrap().value; assert!(res_equals(res, expected_res)); } -*/ -/* + + #[tokio::test] //works, but takes a long time! async fn test_mul_fp() { let a = Fp{ ls:[ @@ -129,9 +127,9 @@ async fn test_mul_fp() { .call().await.unwrap().value; assert!(res_equals(res, c)); } -*/ -/* -#[tokio::test] //Immediate18TooLarge + + +#[tokio::test] async fn test_square_fp() { let a: Fp = Fp { ls: [0xd215_d276_8e83_191b,//15138237129114720539 @@ -167,7 +165,6 @@ async fn test_square_fp() { .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - //Unclear whether this works because of Immediate18TooLarge error println!("{}", res.ls[0]); println!("{}", res.ls[1]); println!("{}", res.ls[2]); @@ -176,7 +173,6 @@ async fn test_square_fp() { println!("{}", res.ls[5]); assert!(res_equals(res, expected_res)); } -*/ #[tokio::test] async fn lexicographically_largest_fp() { @@ -246,4 +242,4 @@ async fn lexicographically_largest_fp() { assert!(res_first.c == 0); assert!(res_second.c == 1); assert!(res_third.c == 1); -} \ No newline at end of file +} From 08ef32f6b84f7a3a22e2d8ac007bb3967c4f67a0 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Mon, 19 Sep 2022 15:21:32 +0200 Subject: [PATCH 157/160] - Updated fuels - Adjusted some of the contract testing to new version - Added a few comments according to the performance of this new version --- bls12_381/Cargo.toml | 2 +- bls12_381/src/fp.sw | 14 ++++- bls12_381/src/g1.sw | 8 +-- bls12_381/src/main.sw | 64 ++++++++++---------- bls12_381/src/scalar.sw | 6 +- tests_bls12_381/Cargo.toml | 3 +- tests_bls12_381/src/main.sw | 10 ++-- tests_bls12_381/tests/tests_fp/mod.rs | 23 ++++---- tests_bls12_381/tests/tests_fp2/mod.rs | 31 +++++++--- tests_bls12_381/tests/tests_fp6/mod.rs | 71 +++++++++++++++-------- tests_bls12_381/tests/tests_scalar/mod.rs | 58 +++++++++++------- 11 files changed, 180 insertions(+), 110 deletions(-) diff --git a/bls12_381/Cargo.toml b/bls12_381/Cargo.toml index 8f22ae3..19f18a3 100644 --- a/bls12_381/Cargo.toml +++ b/bls12_381/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" license = "Apache-2.0" [dependencies] -fuels = { version = "0.19", features = ["fuel-core-lib"] } +fuels = { version = "0.23", features = ["fuel-core-lib"] } tokio = { version = "1.12", features = ["rt", "macros"] } [[test]] diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index e53f7a1..d69cbc2 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -292,9 +292,19 @@ impl Fp { (rhs.neg()).add(self) } - -// TODO implement when performing many squares is possible +// TODO implement when performing *many* squares is possible pub fn pow_vartime(self, by: [u64; 6]) -> Self { + // let mut res = Self::one(); + // for e in by.iter().rev() { + // for i in (0..64).rev() { + // res = res.square(); + + // if ((*e >> i) & 1) == 1 { + // res *= self; + // } + // } + // } + // res ~Fp::zero() } diff --git a/bls12_381/src/g1.sw b/bls12_381/src/g1.sw index bae9d78..63e8118 100644 --- a/bls12_381/src/g1.sw +++ b/bls12_381/src/g1.sw @@ -3,9 +3,9 @@ library g1; dep fp; dep choice; -use ::fp::{Fp, from_raw_unchecked}; +use fp::{Fp, from_raw_unchecked}; use choice::{Choice, CtOption, ConditionallySelectable, ConstantTimeEq}; -use core::ops::{Eq, Add}; +use core::ops::{Eq, Add, Subtract}; // Comment from zkcrypto @@ -247,7 +247,6 @@ impl ConditionallySelectable for G1Projective { impl G1Projective { -/* // Not able to test this yet, doesn't terminate /// Computes the doubling of this point. pub fn double(self) -> G1Projective { @@ -280,7 +279,6 @@ impl G1Projective { ~G1Projective::conditional_select(tmp, ~G1Projective::identity(), self.is_identity()) } - */ pub fn add(self, rhs: G1Projective) -> G1Projective { // Comment from zkcrypto @@ -415,7 +413,7 @@ impl Add for G1Projective { } } -impl Sub for G1Projective { +impl Subtract for G1Projective { fn subtract(self, other: Self) -> Self { self + (other.neg()) } diff --git a/bls12_381/src/main.sw b/bls12_381/src/main.sw index d97ada0..0a1ebc1 100644 --- a/bls12_381/src/main.sw +++ b/bls12_381/src/main.sw @@ -2,20 +2,20 @@ script; // dep fp; // dep fp2; -// dep g1; //compiles but takes a really long time +dep g1; //compiles but takes a really long time // dep choice; // dep util; -dep scalar; +// dep scalar; // use ::fp::{Fp, from_raw_unchecked}; // use ::fp2::Fp2; -// use ::g1::G1Projective; +use ::g1::G1Projective; // use ::choice::*; use std::{assert::assert}; // use std::logging::log; // use ::g1::G1Affine; // use ::util::*; -use ::scalar::*; +// use ::scalar::*; //this is a temporary file for test purposes. // Logging in a library is easier when testing with a script. When testing through a contract that's not possible @@ -32,34 +32,36 @@ fn main () { // assert(test_g1_equality()); // assert(test_opposite_choice_value()); // assert(test_add_g1()); - assert(test_scalar_equality()); - assert(test_scalar_neg()); + // assert(test_scalar_equality()); + // assert(test_scalar_neg()); + + assert(test_double_identity()); } -pub fn test_scalar_neg() -> bool { - let largest = Scalar { ls: [ - 0xffff_ffff_0000_0000, - 0x53bd_a402_fffe_5bfe, - 0x3339_d808_09a1_d805, - 0x73ed_a753_299d_7d48, - ]}; - let neg_largest = largest.neg(); - assert(neg_largest == Scalar { ls: [1, 0, 0, 0]}); +// pub fn test_scalar_neg() -> bool { +// let largest = Scalar { ls: [ +// 0xffff_ffff_0000_0000, +// 0x53bd_a402_fffe_5bfe, +// 0x3339_d808_09a1_d805, +// 0x73ed_a753_299d_7d48, +// ]}; +// let neg_largest = largest.neg(); +// assert(neg_largest == Scalar { ls: [1, 0, 0, 0]}); - let zero = Scalar { ls: [0,0,0,0]}; - let neg_zero = zero.neg(); - assert(neg_zero == Scalar { ls: [0,0,0,0]} ); +// let zero = Scalar { ls: [0,0,0,0]}; +// let neg_zero = zero.neg(); +// assert(neg_zero == Scalar { ls: [0,0,0,0]} ); - let neg_one = (Scalar { ls: [1,0,0,0]}).neg(); - assert(neg_one == largest); +// let neg_one = (Scalar { ls: [1,0,0,0]}).neg(); +// assert(neg_one == largest); - true -} +// true +// } -pub fn test_scalar_equality() -> bool { - assert(R2 == R2); - true -} +// pub fn test_scalar_equality() -> bool { +// assert(R2 == R2); +// true +// } // pub fn test_opposite_choice_value() -> bool { // !opposite_choice_value(1u8) && opposite_choice_value(0u8) @@ -153,11 +155,11 @@ pub fn test_g1_equality() -> bool { // } // This doesn't terminate (or does it maybe give the Immediate18TooLarge after forever?) -// fn test_double_identity() -> bool { -// let p_id = ~G1Projective::identity(); -// let doubled = p_id.double(); -// true -// } +fn test_double_identity() -> bool { + let p_id = ~G1Projective::identity(); + let doubled = p_id.double(); + true +} // pub fn res_equals(a: Fp, b: Fp) -> bool { diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index 0509278..0f89627 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -301,7 +301,7 @@ impl Scalar { /// **This operation is variable time with respect /// to the exponent.** If the exponent is fixed, /// this operation is effectively constant time. - pub fn pow_vartime(self, by: [u64; 4]) -> Scalar { + pub fn pow_vartime(self, by: [u64; 4]) -> Scalar {//TODO fix let mut res = ~Self::one(); // let mut i = 4; // while i > 0 { @@ -333,6 +333,10 @@ will give Immediate18TooLarge (It originally gave the error error: Internal compiler error: Verification failed: Function anon_11103 return type must match its RET instructions. Please file an issue on the repository and include the code that triggered this error. + +Sept 12: new error = +error: Internal compiler error: Verification failed: Function one_1 return type must match its RET instructions. +Please file an issue on the repository and include the code that triggered this error. ) */ diff --git a/tests_bls12_381/Cargo.toml b/tests_bls12_381/Cargo.toml index 0269fc5..7e9e44b 100644 --- a/tests_bls12_381/Cargo.toml +++ b/tests_bls12_381/Cargo.toml @@ -5,9 +5,8 @@ authors = ["Hashcloak"] edition = "2021" license = "Apache-2.0" -# change to 0.19 [dependencies] -fuels = { version = "0.19", features = ["fuel-core-lib"] } +fuels = { version = "0.23", features = ["fuel-core-lib"] } tokio = { version = "1.12", features = ["rt", "macros"] } [[test]] diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index 312b8ba..ce8a00e 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -14,7 +14,7 @@ abi BlsTestContract { // Works #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; - #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice; + // #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice; // works but takes a long time #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp; @@ -28,7 +28,7 @@ abi BlsTestContract { // #[storage(read, write)]fn neg_fp2(a: Fp2) -> Fp2; // #[storage(read, write)]fn lexicographically_largest_fp2(a: Fp2) -> Choice; - // // not tested, gives Immediate18TooLarge error + // // not tested, still gives Immediate18TooLarge error // #[storage(read, write)]fn square_fp2(a: Fp2) -> Fp2; // #[storage(read, write)]fn mul_fp2(a: Fp2, b: Fp2) -> Fp2; @@ -53,9 +53,9 @@ impl BlsTestContract for Contract { a - b } - #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice { - a.lexicographically_largest() - } + // #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice { + // a.lexicographically_largest() + // } #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { a * b diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index 31e830b..67956c7 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -7,7 +7,7 @@ abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); //TODO move this to a separate helpers file. How to achieve this in Rust/Cargo? async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { - let mut wallet = LocalWallet::new_random(None); + let mut wallet = WalletUnlocked::new_random(None); let num_assets = 1; let coins_per_asset = 100; let amount_per_coin = 100000; @@ -63,7 +63,7 @@ async fn test_add_fp() { let (contract_instance, _id) = get_contract_instance().await; let res = contract_instance.add_fp(small, random) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; @@ -86,13 +86,12 @@ async fn test_sub_fp() { let (_instance, _id) = get_contract_instance().await; let res = _instance.sub_fp(a, b) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(res_equals(res, expected_res)); } - #[tokio::test] //works, but takes a long time! async fn test_mul_fp() { let a = Fp{ ls:[ @@ -122,7 +121,7 @@ async fn test_mul_fp() { let (_instance, _id) = get_contract_instance().await; let res = _instance.mul_fp(a, b) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; assert!(res_equals(res, c)); @@ -161,7 +160,7 @@ async fn test_square_fp() { let (_instance, _id) = get_contract_instance().await; let res = _instance.square_fp(a) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; @@ -174,6 +173,7 @@ async fn test_square_fp() { assert!(res_equals(res, expected_res)); } +/* #[tokio::test] async fn lexicographically_largest_fp() { let zero = Fp{ ls: [0,0,0,0,0,0].to_vec()}; @@ -213,27 +213,27 @@ async fn lexicographically_largest_fp() { let (contract_instance, _id) = get_contract_instance().await; let res_zero = contract_instance.lexicographically_largest_fp(zero) - .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None)) .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) .call().await.unwrap().value; let res_one = contract_instance.lexicographically_largest_fp(one) - .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None)) .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) .call().await.unwrap().value; let res_first = contract_instance.lexicographically_largest_fp(first) - .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None)) .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) .call().await.unwrap().value; let res_second = contract_instance.lexicographically_largest_fp(second) - .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None)) .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) .call().await.unwrap().value; let res_third = contract_instance.lexicographically_largest_fp(third) - .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(10_000_000_000_000), None)) .call_params(CallParameters::new(None, None, Some(10_000_000_000_000))) .call().await.unwrap().value; @@ -243,3 +243,4 @@ async fn lexicographically_largest_fp() { assert!(res_second.c == 1); assert!(res_third.c == 1); } +*/ \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp2/mod.rs b/tests_bls12_381/tests/tests_fp2/mod.rs index cbc6ca5..857610a 100644 --- a/tests_bls12_381/tests/tests_fp2/mod.rs +++ b/tests_bls12_381/tests/tests_fp2/mod.rs @@ -6,7 +6,7 @@ use fuels::{ abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { - let mut wallet = LocalWallet::new_random(None); + let mut wallet = WalletUnlocked::new_random(None); let num_assets = 1; let coins_per_asset = 100; let amount_per_coin = 100000; @@ -308,8 +308,9 @@ async fn test_multiplication() { assert_eq!(res, c); } */ -/* -#[tokio::test] //Immediate18TooLarge + + +#[tokio::test] //still gives Immediate18TooLarge :( (12 sept) async fn test_squaring() { let a = Fp2 { c_0: Fp{ ls:[ @@ -349,15 +350,30 @@ async fn test_squaring() { }; let (contract_instance, _id) = get_contract_instance().await; - let res = contract_instance.square_fp2(a) // results to 0 :o - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + let res = contract_instance.square_fp2(a) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - assert_eq!(res, b); + println!("{}", res.c_0.ls[0]); + println!("{}", res.c_0.ls[1]); + println!("{}", res.c_0.ls[2]); + println!("{}", res.c_0.ls[2]); + println!("{}", res.c_0.ls[4]); + println!("{}", res.c_0.ls[5]); + + println!("{}", res.c_1.ls[0]); + println!("{}", res.c_1.ls[1]); + println!("{}", res.c_1.ls[2]); + println!("{}", res.c_1.ls[2]); + println!("{}", res.c_1.ls[4]); + println!("{}", res.c_1.ls[5]); + + assert_eq!(res.c_0, b.c_0); + assert_eq!(res.c_1, b.c_1); } -*/ +/* #[tokio::test]//stripped down version from zkcrypto impl async fn lexicographically_largest_fp2() { let zero = Fp2 { @@ -414,3 +430,4 @@ async fn lexicographically_largest_fp2() { assert!(res_one.c == 0); assert!(res_first.c == 1); } +*/ \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_fp6/mod.rs b/tests_bls12_381/tests/tests_fp6/mod.rs index 0039855..836fc51 100644 --- a/tests_bls12_381/tests/tests_fp6/mod.rs +++ b/tests_bls12_381/tests/tests_fp6/mod.rs @@ -3,27 +3,41 @@ use fuels::{ tx::{ConsensusParameters, ContractId}, }; -// Load abi from json abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_wallet().await; + let mut wallet = WalletUnlocked::new_random(None); + let num_assets = 1; + let coins_per_asset = 100; + let amount_per_coin = 100000; + + let (coins, asset_ids) = setup_multiple_assets_coins( + wallet.address(), + num_assets, + coins_per_asset, + amount_per_coin, + ); + + // Custom gas limit + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); + + let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; + + let provider = Provider::new(client); + wallet.set_provider(provider.clone()); let id = Contract::deploy( "./out/debug/tests_bls12_381.bin", &wallet, TxParameters::default(), - StorageConfiguration::with_storage_path(None) - ) - .await - .unwrap(); + StorageConfiguration::default(), + ).await.unwrap(); let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); - (instance, id) } + fn res_equals_fp(res: Fp, should_be: Fp) -> bool { assert!(res.ls[0] == should_be.ls[0]); assert!(res.ls[1] == should_be.ls[1]); @@ -47,7 +61,6 @@ fn res_equals(res: Fp6, c: Fp6) -> bool { true } -/* fn get_a() -> Fp6 { let a = Fp6 { c_0: Fp2 { @@ -169,10 +182,11 @@ fn get_b() -> Fp6 { b } -*/ +/* #[tokio::test] -async fn test_fp6() { +async fn test_fp6() { let (contract_instance, _id) = get_contract_instance().await; + let a = Fp6 { c_0: Fp2 { c_0: Fp{ls: [ @@ -229,22 +243,29 @@ async fn test_fp6() { ].to_vec()}, }, }; + + let res = contract_instance.add_fp2(a, b) + .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + + assert!(true); -} +} */ -// #[tokio::test] -// async fn test_square_fp6() { -// let (contract_instance, _id) = get_contract_instance().await; +#[tokio::test] +async fn test_square_fp6() { + let (contract_instance, _id) = get_contract_instance().await; -// let res_square = contract_instance.square_fp6(get_a()) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; + let res_square = contract_instance.square_fp6(get_a()) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; -// let res_expected = contract_instance.mul_fp6(get_a(), get_a()) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; + let res_expected = contract_instance.mul_fp6(get_a(), get_a()) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; -// // assert!();TODO -// } \ No newline at end of file + assert!(res_equals(res_square,res_expected )); +} \ No newline at end of file diff --git a/tests_bls12_381/tests/tests_scalar/mod.rs b/tests_bls12_381/tests/tests_scalar/mod.rs index 412315b..1f33afd 100644 --- a/tests_bls12_381/tests/tests_scalar/mod.rs +++ b/tests_bls12_381/tests/tests_scalar/mod.rs @@ -6,20 +6,34 @@ use fuels::{ abigen!(BlsTestContract, "out/debug/tests_bls12_381-abi.json"); async fn get_contract_instance() -> (BlsTestContract, Bech32ContractId) { - // Launch a local network and deploy the contract - let wallet = launch_provider_and_get_wallet().await; + let mut wallet = WalletUnlocked::new_random(None); + let num_assets = 1; + let coins_per_asset = 100; + let amount_per_coin = 100000; + + let (coins, asset_ids) = setup_multiple_assets_coins( + wallet.address(), + num_assets, + coins_per_asset, + amount_per_coin, + ); + + // Custom gas limit + let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(10_000_000_000_000); + + let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; + + let provider = Provider::new(client); + wallet.set_provider(provider.clone()); let id = Contract::deploy( "./out/debug/tests_bls12_381.bin", &wallet, TxParameters::default(), - StorageConfiguration::with_storage_path(None) - ) - .await - .unwrap(); + StorageConfiguration::default(), + ).await.unwrap(); let instance = BlsTestContractBuilder::new(id.to_string(), wallet).build(); - (instance, id) } @@ -57,7 +71,7 @@ async fn test_addition() { let (contract_instance, _id) = get_contract_instance().await; let res = contract_instance.add_scalar(a, a_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; @@ -72,7 +86,7 @@ async fn test_addition() { let one = Scalar{ ls: [1,0,0,0].to_vec() }; let res_2 = contract_instance.add_scalar(a_3, one) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; @@ -85,17 +99,21 @@ error: Internal compiler error: Verification failed: Function anon_11103 return Please file an issue on the repository and include the code that triggered this error. Eventually, this gave Braqzen the error Immediate18TooLarge + +update sept 12: +error: Internal compiler error: Verification failed: Function one_1 return type must match its RET instructions. +Please file an issue on the repository and include the code that triggered this error. */ -// #[tokio::test] -// async fn test_sqrt() { -// let zero = Scalar{ ls: [0,0,0,0].to_vec() }; -// let (contract_instance, _id) = get_contract_instance().await; -// let square_root = contract_instance.scalar_sqrt(zero) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// assert_eq!(square_root, Scalar{ ls: [0,0,0,0].to_vec() }); -// } +#[tokio::test] +async fn test_sqrt() { + let zero = Scalar{ ls: [0,0,0,0].to_vec() }; + let (contract_instance, _id) = get_contract_instance().await; + let square_root = contract_instance.scalar_sqrt(zero) + .tx_params(TxParameters::new(None, Some(100_000_000), None)) + .call_params(CallParameters::new(None, None, Some(100_000_000))) + .call().await.unwrap().value; + assert_eq!(square_root, Scalar{ ls: [0,0,0,0].to_vec() }); +} /*BLOCKED @@ -120,7 +138,7 @@ Eventually, this gave Braqzen the error Immediate18TooLarge // let j = 0; // while j < 101 { // let square_root = contract_instance.scalar_sqrt(square) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) +// .tx_params(TxParameters::new(None, Some(100_000_000), None)) // .call_params(CallParameters::new(None, None, Some(100_000_000))) // .call().await.unwrap().value; // // let square_root = square.sqrt(); From 2d538fca0506a0cb1ba383b3f856876e20e11768 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 22 Sep 2022 09:46:46 +0200 Subject: [PATCH 158/160] Rewrote some if branches and with that removed some TODOs. There's some assembly in here because Sway doesn't support underflow natively. This is usually leveraged to avoid writing if else. --- README.md | 7 ++ bls12_381/src/fp.sw | 145 +++++++++++++++++++--------------------- bls12_381/src/scalar.sw | 11 +-- bls12_381/src/util.sw | 29 +++++++- 4 files changed, 109 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index a1c05b8..8b63b9f 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,10 @@ This starts a Fuel node with a volatile database that will be cleared when shut cd tests-bls forc test ``` + +## Running a script +Also to run a script a Fuel Node has to be spun up. + +``` +forc run --unsigned --pretty-print +``` \ No newline at end of file diff --git a/bls12_381/src/fp.sw b/bls12_381/src/fp.sw index d69cbc2..32fd532 100644 --- a/bls12_381/src/fp.sw +++ b/bls12_381/src/fp.sw @@ -10,7 +10,7 @@ use std::{option::Option, u128::U128, vec::Vec}; use core::ops::{Eq, Add, Subtract, Multiply}; // Little endian big integer with 6 limbs -// in Montgomery form (!) +// in Montgomery form pub struct Fp{ls: [u64;6]} /// p = 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 @@ -93,34 +93,23 @@ impl Fp { R } - // TODO to make this constant time the u64 should be compared with ct_eq, but is not existing in Sway (yet) - pub fn eq(self, other: Self) -> bool { - (self.ls[0] == other.ls[0]) - && (self.ls[1] == other.ls[1]) - && (self.ls[2] == other.ls[2]) - && (self.ls[3] == other.ls[3]) - && (self.ls[4] == other.ls[4]) - && (self.ls[5] == other.ls[5]) - } - + // -a mod p pub fn neg(self) -> Fp { - let(d0, borrow) = sbb(MODULUS[0], self.ls[0], 0); - let(d1, borrow) = sbb(MODULUS[1], self.ls[1], borrow); - let(d2, borrow) = sbb(MODULUS[2], self.ls[2], borrow); - let(d3, borrow) = sbb(MODULUS[3], self.ls[3], borrow); - let(d4, borrow) = sbb(MODULUS[4], self.ls[4], borrow); - let(d5, _) = sbb(MODULUS[5], self.ls[5], borrow); - - // We need a mask that's 0 when a==p and 2^65-1 otherwise - // TODO improve this - let mut a_is_p = 0; - if (self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3] | self.ls[4] | self.ls[5] == 0) { - a_is_p = 1; //don't know is there's a native conversion - } else { - a_is_p = 0; - } - - let mask = subtract_wrap_64(a_is_p, 1); + let (d0, borrow) = sbb(MODULUS[0], self.ls[0], 0); + let (d1, borrow) = sbb(MODULUS[1], self.ls[1], borrow); + let (d2, borrow) = sbb(MODULUS[2], self.ls[2], borrow); + let (d3, borrow) = sbb(MODULUS[3], self.ls[3], borrow); + let (d4, borrow) = sbb(MODULUS[4], self.ls[4], borrow); + let (d5, _) = sbb(MODULUS[5], self.ls[5], borrow); + + // The mask should be 0 when a==p and 2^65-1 otherwise + // limbs = 0 when self = 0 + let limbs = (self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3] | self.ls[4] | self.ls[5]); + // p mod p = 0, so this checks whether self is p + // a_is_p = 0 when self = 0, otherwise a_is_p = 1 + let a_is_p: u64 = is_zero_u64(limbs); + // mask = a_is_p - 1. This will give either 1-1 (=0) or 0-1 (wrap around to 2^64-1) + let mask = subtract_1_wrap(a_is_p); Fp { ls: [d0 & mask, d1 & mask, d2 & mask, d3 & mask, d4 & mask, d5 & mask] @@ -129,15 +118,14 @@ impl Fp { // If a >= p, return a-p, else return a pub fn subtract_p(self) -> Fp { - let(r0, borrow) = sbb(self.ls[0], MODULUS[0], 0); - let(r1, borrow) = sbb(self.ls[1], MODULUS[1], borrow); - let(r2, borrow) = sbb(self.ls[2], MODULUS[2], borrow); - let(r3, borrow) = sbb(self.ls[3], MODULUS[3], borrow); - let(r4, borrow) = sbb(self.ls[4], MODULUS[4], borrow); - let(r5, borrow) = sbb(self.ls[5], MODULUS[5], borrow); - - // If underflow occurred on the final limb, borrow = 0xfff...fff, otherwise - // borrow = 0x000...000. Thus, we use it as a mask! + let (r0, borrow) = sbb(self.ls[0], MODULUS[0], 0); + let (r1, borrow) = sbb(self.ls[1], MODULUS[1], borrow); + let (r2, borrow) = sbb(self.ls[2], MODULUS[2], borrow); + let (r3, borrow) = sbb(self.ls[3], MODULUS[3], borrow); + let (r4, borrow) = sbb(self.ls[4], MODULUS[4], borrow); + let (r5, borrow) = sbb(self.ls[5], MODULUS[5], borrow); + + // The final borrow is 0xfff...fff if there was underflow. Otherwise 0. let mut mask = borrow; let r0 = (self.ls[0] & mask) | (r0 & not(mask)); let r1 = (self.ls[1] & mask) | (r1 & not(mask)); @@ -189,47 +177,47 @@ impl Fp { let rhs4 = rhs.ls[4]; let rhs5 = rhs.ls[5]; - let(t0, carry) = mac(0, self0, rhs0, 0); - let(t1, carry) = mac(0, self0, rhs1, carry); - let(t2, carry) = mac(0, self0, rhs2, carry); - let(t3, carry) = mac(0, self0, rhs3, carry); - let(t4, carry) = mac(0, self0, rhs4, carry); - let(t5, t6) = mac(0, self0, rhs5, carry); - - let(t1, carry) = mac(t1, self1, rhs0, 0); - let(t2, carry) = mac(t2, self1, rhs1, carry); - let(t3, carry) = mac(t3, self1, rhs2, carry); - let(t4, carry) = mac(t4, self1, rhs3, carry); - let(t5, carry) = mac(t5, self1, rhs4, carry); - let(t6, t7) = mac(t6, self1, rhs5, carry); - - let(t2, carry) = mac(t2, self2, rhs0, 0); - let(t3, carry) = mac(t3, self2, rhs1, carry); - let(t4, carry) = mac(t4, self2, rhs2, carry); - let(t5, carry) = mac(t5, self2, rhs3, carry); - let(t6, carry) = mac(t6, self2, rhs4, carry); - let(t7, t8) = mac(t7, self2, rhs5, carry); - - let(t3, carry) = mac(t3, self3, rhs0, 0); - let(t4, carry) = mac(t4, self3, rhs1, carry); - let(t5, carry) = mac(t5, self3, rhs2, carry); - let(t6, carry) = mac(t6, self3, rhs3, carry); - let(t7, carry) = mac(t7, self3, rhs4, carry); - let(t8, t9) = mac(t8, self3, rhs5, carry); - - let(t4, carry) = mac(t4, self4, rhs0, 0); - let(t5, carry) = mac(t5, self4, rhs1, carry); - let(t6, carry) = mac(t6, self4, rhs2, carry); - let(t7, carry) = mac(t7, self4, rhs3, carry); - let(t8, carry) = mac(t8, self4, rhs4, carry); - let(t9, t10) = mac(t9, self4, rhs5, carry); - - let(t5, carry) = mac(t5, self5, rhs0, 0); - let(t6, carry) = mac(t6, self5, rhs1, carry); - let(t7, carry) = mac(t7, self5, rhs2, carry); - let(t8, carry) = mac(t8, self5, rhs3, carry); - let(t9, carry) = mac(t9, self5, rhs4, carry); - let(t10, t11) = mac(t10, self5, rhs5, carry); + let (t0, carry) = mac(0, self0, rhs0, 0); + let (t1, carry) = mac(0, self0, rhs1, carry); + let (t2, carry) = mac(0, self0, rhs2, carry); + let (t3, carry) = mac(0, self0, rhs3, carry); + let (t4, carry) = mac(0, self0, rhs4, carry); + let (t5, t6) = mac(0, self0, rhs5, carry); + + let (t1, carry) = mac(t1, self1, rhs0, 0); + let (t2, carry) = mac(t2, self1, rhs1, carry); + let (t3, carry) = mac(t3, self1, rhs2, carry); + let (t4, carry) = mac(t4, self1, rhs3, carry); + let (t5, carry) = mac(t5, self1, rhs4, carry); + let (t6, t7) = mac(t6, self1, rhs5, carry); + + let (t2, carry) = mac(t2, self2, rhs0, 0); + let (t3, carry) = mac(t3, self2, rhs1, carry); + let (t4, carry) = mac(t4, self2, rhs2, carry); + let (t5, carry) = mac(t5, self2, rhs3, carry); + let (t6, carry) = mac(t6, self2, rhs4, carry); + let (t7, t8) = mac(t7, self2, rhs5, carry); + + let (t3, carry) = mac(t3, self3, rhs0, 0); + let (t4, carry) = mac(t4, self3, rhs1, carry); + let (t5, carry) = mac(t5, self3, rhs2, carry); + let (t6, carry) = mac(t6, self3, rhs3, carry); + let (t7, carry) = mac(t7, self3, rhs4, carry); + let (t8, t9) = mac(t8, self3, rhs5, carry); + + let (t4, carry) = mac(t4, self4, rhs0, 0); + let (t5, carry) = mac(t5, self4, rhs1, carry); + let (t6, carry) = mac(t6, self4, rhs2, carry); + let (t7, carry) = mac(t7, self4, rhs3, carry); + let (t8, carry) = mac(t8, self4, rhs4, carry); + let (t9, t10) = mac(t9, self4, rhs5, carry); + + let (t5, carry) = mac(t5, self5, rhs0, 0); + let (t6, carry) = mac(t6, self5, rhs1, carry); + let (t7, carry) = mac(t7, self5, rhs2, carry); + let (t8, carry) = mac(t8, self5, rhs3, carry); + let (t9, carry) = mac(t9, self5, rhs4, carry); + let (t10, t11) = mac(t10, self5, rhs5, carry); let res: [u64;12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; montgomery_reduce(res) @@ -309,6 +297,7 @@ impl Fp { } // In Rust this is implemented as sum_of_products for T, but this is not possible in Sway + // Since specifically T=2 and T=6 is used, we implement both of them separately pub fn sum_of_products_6(a: [Fp; 6], b: [Fp; 6]) -> Fp { let mut u1 = 0; let mut u2 = 0; diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index 0f89627..a3ebce8 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -135,10 +135,13 @@ impl Scalar { let (d2, borrow) = sbb(MODULUS_SCALAR.ls[2], self.ls[2], borrow); let (d3, _) = sbb(MODULUS_SCALAR.ls[3], self.ls[3], borrow); - // `tmp` could be `MODULUS` if `self` was zero. Create a mask that is - // zero if `self` was zero, and `u64::max_value()` if self was nonzero. - let temp: u64 = if ((self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3]) == 0) { 1 } else { 0 }; - let mask = subtract_wrap_64(temp, 1); + // The mask should be 0 when a==p and 2^65-1 otherwise + // limbs = 0 when self = 0 + let limbs = self.ls[0] | self.ls[1] | self.ls[2] | self.ls[3]; + // p mod p = 0, so this checks whether self is p + let scalar_is_0_mod_p = is_zero_u64(limbs); + // mask = a_is_p - 1. This will give either 1-1 (=0) or 0-1 (wrap around to 2^64-1) + let mask = subtract_1_wrap(scalar_is_0_mod_p); Scalar{ ls: [d0 & mask, d1 & mask, d2 & mask, d3 & mask]} } diff --git a/bls12_381/src/util.sw b/bls12_381/src/util.sw index 57c3bde..5c43af2 100644 --- a/bls12_381/src/util.sw +++ b/bls12_381/src/util.sw @@ -6,6 +6,7 @@ use choice::{Choice, CtOption, ConditionallySelectable, wrapping_neg}; use std::{u128::U128}; use core::ops::{BitwiseXor}; use core::num::*; +use std::flags::{disable_panic_on_overflow, enable_panic_on_overflow}; impl ConditionallySelectable for u64 { @@ -35,7 +36,17 @@ impl ConditionallySelectable for u32 { } } -// TODO rewrite without if branch +// If input == 0u64, return 1. Otherwise return 0. +// Done in assembly, because natively comparison becomes a bool. +pub fn is_zero_u64(input: u64) -> u64 { + asm(r1: input, r2) { + eq r2 r1 zero; + r2: u64 + } +} + +// TODO rewrite without if branch. This one is used with variable a and b +// See resources below // If x >= y: x-y, else max::U128 - (y-x) pub fn subtract_wrap(x: U128, y: U128) -> U128 { if y > x { @@ -48,6 +59,9 @@ pub fn subtract_wrap(x: U128, y: U128) -> U128 { } // TODO rewrite without if branch +// In practice this is only being called with fixed values, so we can make it more specific. +// 1 -1 +// 0 -1 // If x >= y: x-y, else max::U64 - (y-x) pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { if y > x { @@ -57,6 +71,19 @@ pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { } } +// +pub fn subtract_1_wrap(x: u64) -> u64 { + disable_panic_on_overflow(); + let res = asm(underflow, r1: x, r2, r3) { + subi r2 r1 i1; // x - 1 + move underflow of; // move the underflow to a variable + or r3 r2 underflow; // if 1-1 then this is 0 | 0 = 0, if 0-1 this is 0 | u64::max + r3 + }; + enable_panic_on_overflow(); + res +} + /// Compute a - (b + borrow), returning the result and the new borrow. pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { let a_128: U128 = ~U128::from(0, a); From e63759edcf34cb3195d2ab3de50e16a88bfaecf5 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 22 Sep 2022 12:39:43 +0200 Subject: [PATCH 159/160] For Fp we can run add, sub, mul and sqrt at the same time. Adding the test for lexicographically_largest_fp will still give an error. --- bls12_381/src/scalar.sw | 6 +++--- tests_bls12_381/src/main.sw | 9 +++++---- tests_bls12_381/tests/tests_fp/mod.rs | 19 ++----------------- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/bls12_381/src/scalar.sw b/bls12_381/src/scalar.sw index a3ebce8..0fc3d93 100644 --- a/bls12_381/src/scalar.sw +++ b/bls12_381/src/scalar.sw @@ -125,7 +125,7 @@ impl Scalar { Scalar{ ls: [d0, d1, d2, d3]} } -//E: This was tested through script and work. Didn't add test to contract because contract testing is slow and this will be tested implicitly as well +//E: This was tested through script and works. Didn't add test to contract because contract testing is slow and this will be tested implicitly as well pub fn neg(self) -> Self { // Subtract `self` from `MODULUS` to negate. Ignore the final // borrow because it cannot underflow; self is guaranteed to @@ -266,7 +266,7 @@ impl Scalar { } pub fn double(self) -> Scalar { - // TODO: This can be achieved more efficiently with a bitshift. + // zkcrypto comment: TODO: This can be achieved more efficiently with a bitshift. self.add(self) } } @@ -304,7 +304,7 @@ impl Scalar { /// **This operation is variable time with respect /// to the exponent.** If the exponent is fixed, /// this operation is effectively constant time. - pub fn pow_vartime(self, by: [u64; 4]) -> Scalar {//TODO fix + pub fn pow_vartime(self, by: [u64; 4]) -> Scalar {//TODO implement when possible, this gives an error when called from sqrt let mut res = ~Self::one(); // let mut i = 4; // while i > 0 { diff --git a/tests_bls12_381/src/main.sw b/tests_bls12_381/src/main.sw index ce8a00e..0b1fba8 100644 --- a/tests_bls12_381/src/main.sw +++ b/tests_bls12_381/src/main.sw @@ -14,6 +14,7 @@ abi BlsTestContract { // Works #[storage(read, write)]fn add_fp(a: Fp, b: Fp) -> Fp; #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp; + // Running this one will give Immediate18TooLarge // #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice; // works but takes a long time @@ -52,10 +53,10 @@ impl BlsTestContract for Contract { #[storage(read, write)]fn sub_fp(a: Fp, b: Fp) -> Fp { a - b } - - // #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice { - // a.lexicographically_largest() - // } +/* + #[storage(read, write)]fn lexicographically_largest_fp(a: Fp) -> Choice { + a.lexicographically_largest() + }*/ #[storage(read, write)]fn mul_fp(a: Fp, b: Fp) -> Fp { a * b diff --git a/tests_bls12_381/tests/tests_fp/mod.rs b/tests_bls12_381/tests/tests_fp/mod.rs index 67956c7..064055e 100644 --- a/tests_bls12_381/tests/tests_fp/mod.rs +++ b/tests_bls12_381/tests/tests_fp/mod.rs @@ -127,8 +127,7 @@ async fn test_mul_fp() { assert!(res_equals(res, c)); } - -#[tokio::test] +#[tokio::test] //works, but takes a long time async fn test_square_fp() { let a: Fp = Fp { ls: [0xd215_d276_8e83_191b,//15138237129114720539 @@ -139,15 +138,6 @@ async fn test_square_fp() { 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 }; - // let a_again: Fp = Fp { - // ls: [0xd215_d276_8e83_191b, - // 0x5085_d80f_8fb2_8261,//5802281256283701857 - // 0xce9a_032d_df39_3a56,//14887215013780077142 - // 0x3e9c_4fff_2ca0_c4bb,//4511568884102382779 - // 0x6436_b6f7_f4d9_5dfb,//7221160228616232443 - // 0x1060_6628_ad4a_4d90].to_vec()//1180055427263122832 - // }; - let expected_res: Fp = Fp { ls: [0x33d9_c42a_3cb3_e235, 0xdad1_1a09_4c4c_d455, @@ -164,16 +154,11 @@ async fn test_square_fp() { .call_params(CallParameters::new(None, None, Some(100_000_000))) .call().await.unwrap().value; - println!("{}", res.ls[0]); - println!("{}", res.ls[1]); - println!("{}", res.ls[2]); - println!("{}", res.ls[2]); - println!("{}", res.ls[4]); - println!("{}", res.ls[5]); assert!(res_equals(res, expected_res)); } /* +Running this one will give Immediate18TooLarge #[tokio::test] async fn lexicographically_largest_fp() { let zero = Fp{ ls: [0,0,0,0,0,0].to_vec()}; From 79c36f513e6e47e9ec7176d7da0e246e517da754 Mon Sep 17 00:00:00 2001 From: Elena Fuentes Bongenaar Date: Thu, 22 Sep 2022 14:29:18 +0200 Subject: [PATCH 160/160] Old code removed. --- old-bls/Cargo.toml | 16 - old-bls/Forc.toml | 7 - old-bls/src/consts.sw | 14 - old-bls/src/definitions.sw | 29 - old-bls/src/ec1.sw | 77 -- old-bls/src/fields.sw | 136 --- old-bls/src/lib.sw | 4 - old-bls/src/main.sw | 55 - old-bls/src/test_helpers.sw | 41 - old-bls/src/tests/tests_temp_fe_mont_mul.sw | 175 ---- old-bls/src/tests/tests_vect_subfunctions.sw | 563 ---------- old-bls/src/vect.sw | 985 ------------------ old-tests-bls/.gitignore | 2 - old-tests-bls/Cargo.toml | 16 - old-tests-bls/Forc.toml | 8 - old-tests-bls/src/main.sw | 185 ---- old-tests-bls/tests/harness.rs | 9 - old-tests-bls/tests/tests_add_fp/mod.rs | 157 --- old-tests-bls/tests/tests_l_shift/mod.rs | 56 - old-tests-bls/tests/tests_mul_by_x_fp/mod.rs | 96 -- .../tests/tests_rshift_mod_384/mod.rs | 42 - .../tests/tests_small_functions/mod.rs | 219 ---- old-tests-bls/tests/tests_sub_fp/mod.rs | 124 --- old-tests-bls/tests/tests_temp_mul/mod.rs | 101 -- .../tests/tests_temp_mul_mont_n/mod.rs | 101 -- old-tests-bls/tests/tests_vect_fp2/mod.rs | 104 -- .../tests/tests_vect_subfunctions/mod.rs | 70 -- 27 files changed, 3392 deletions(-) delete mode 100644 old-bls/Cargo.toml delete mode 100644 old-bls/Forc.toml delete mode 100644 old-bls/src/consts.sw delete mode 100644 old-bls/src/definitions.sw delete mode 100644 old-bls/src/ec1.sw delete mode 100644 old-bls/src/fields.sw delete mode 100644 old-bls/src/lib.sw delete mode 100644 old-bls/src/main.sw delete mode 100644 old-bls/src/test_helpers.sw delete mode 100644 old-bls/src/tests/tests_temp_fe_mont_mul.sw delete mode 100644 old-bls/src/tests/tests_vect_subfunctions.sw delete mode 100644 old-bls/src/vect.sw delete mode 100644 old-tests-bls/.gitignore delete mode 100644 old-tests-bls/Cargo.toml delete mode 100644 old-tests-bls/Forc.toml delete mode 100644 old-tests-bls/src/main.sw delete mode 100644 old-tests-bls/tests/harness.rs delete mode 100644 old-tests-bls/tests/tests_add_fp/mod.rs delete mode 100644 old-tests-bls/tests/tests_l_shift/mod.rs delete mode 100644 old-tests-bls/tests/tests_mul_by_x_fp/mod.rs delete mode 100644 old-tests-bls/tests/tests_rshift_mod_384/mod.rs delete mode 100644 old-tests-bls/tests/tests_small_functions/mod.rs delete mode 100644 old-tests-bls/tests/tests_sub_fp/mod.rs delete mode 100644 old-tests-bls/tests/tests_temp_mul/mod.rs delete mode 100644 old-tests-bls/tests/tests_temp_mul_mont_n/mod.rs delete mode 100644 old-tests-bls/tests/tests_vect_fp2/mod.rs delete mode 100644 old-tests-bls/tests/tests_vect_subfunctions/mod.rs diff --git a/old-bls/Cargo.toml b/old-bls/Cargo.toml deleted file mode 100644 index 2b4e1f1..0000000 --- a/old-bls/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "bls" -version = "0.1.0" -authors = ["HashCloak"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.15" -fuels-abigen-macro = "0.15" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/old-bls/Forc.toml b/old-bls/Forc.toml deleted file mode 100644 index 1d4bc7e..0000000 --- a/old-bls/Forc.toml +++ /dev/null @@ -1,7 +0,0 @@ -[project] -authors = ["HashCloak"] -entry = "lib.sw" -license = "Apache-2.0" -name = "bls" - -[dependencies] diff --git a/old-bls/src/consts.sw b/old-bls/src/consts.sw deleted file mode 100644 index 16808a7..0000000 --- a/old-bls/src/consts.sw +++ /dev/null @@ -1,14 +0,0 @@ -library consts; - -pub const NLIMBS_384 = 6; - -/* - R = 2**384 % p - = 3380320199399472671518931668520476396067793891014375699959770179129436917079669831430077592723774664465579537268733 -*/ -pub const ONE_MONT_P: [u64; -6] = [0x760900000002fffd, 0xebf4000bc40c0002, 0x5f48985753c758ba, 0x77ce585370525745, 0x5c071a97a256ec6d, 0x15f65ec3fa80e493, ]; - -// -1/P -// -p^(-1) mod 2^64 -pub const P0: u64 = 0x89f3fffcfffcfffd; diff --git a/old-bls/src/definitions.sw b/old-bls/src/definitions.sw deleted file mode 100644 index cb81d90..0000000 --- a/old-bls/src/definitions.sw +++ /dev/null @@ -1,29 +0,0 @@ -library definitions; - -pub struct fp { - ls: [u64; - 6], -} - -pub struct p1 { - x: fp, - y: fp, - z: fp, -} -pub struct p1_affine { - x: fp, - y: fp, -} - -pub struct BLS12_381_G1 { - value: p1_affine, -} - -pub struct POINTonE1 { - x: [u64; - 6], - y: [u64; - 6], - z: [u64; - 6], -} diff --git a/old-bls/src/ec1.sw b/old-bls/src/ec1.sw deleted file mode 100644 index f3c5bad..0000000 --- a/old-bls/src/ec1.sw +++ /dev/null @@ -1,77 +0,0 @@ -library ec1; - -dep fields; -dep consts; - -use ::fields::*; -use ::consts::*; - -/* - y^2 = x^3 + B - -B = (4 << 384) % P -= 1514052131932888505822357196874193114600527104240479143842906308145652716846165732392247483508051665748635331395571 - -According to Zcash impl this is equal to 4 - */ -const B_E1: vec384 = {ls: [0xaa270000000cfff3, 0x53cc0032fc34000a, 0x478fe97a6b0a807f, 0xb1d37ebee6ba24d7, 0x8ec9733bbf78ab2f, 0x09d645513d83de7e]}; - -const BLS12_381_G1: POINTonE1 = { /* generator point [in Montgomery] */ - /* - (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905 - a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P - = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 - */ - x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75], - /* - (0x08b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af6 - 00db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1 << 384) % P - = 1806233535529883172442092828064561001318757138177058380995827434860385074092408792531060859215838632649768391090801 - */ - y: [0xbaac93d50ce72271, 0x8c22631a7918fd8e, 0xdd595f13570725ce, 0x51ac582950405194, 0xe1c8c3fad0059c0, 0xbbc3efc5008a26a], - z: ONE_MONT_P -}; - -const BLS12_381_NEG_G1: POINTonE1 = { /* negative generator [in Montgomery] */ - /* - (0x17f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905 - a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb << 384) % P - = 2771334866125919199105806127325991204049638301394587550983394276622338185155646768704112188431188468948617777056790 - */ - x: [0x5cb38790fd530c16, 0x7817fc679976fff5, 0x154f95c7143ba1c1, 0xf0ae6acdf3d0e747, 0xedce6ecc21dbf440, 0x120177419e0bfb75], - /* - (0x114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c9 - 6655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca << 384) % P - = 2196176019691784220975696997671343155238125681761949504336230701263646576398429071911626769913177031388125881468986 - */ - y: [0xff526c2af318883a, 0x92899ce4383b0270, 0x89d7738d9fa9d055, 0x12caf35ba344c12a, 0x3cff1b76964b5317, 0xe44d2ede9774430], - z: ONE_MONT_P -}; - -// TODO TEST -// TODO: why is mul by b equal to *4? -// value of b is 4 << 384 mod p -pub fn mul_by_b_onE1(in: vec384) -> vec384 { - lshift_fp(in, 2) -} - -// TODO TEST -pub fn mul_by_4b_onE1(in: vec384) -> vec384 { - lshift_fp(in, 4) -} - -// TODO TEST -pub fn POINTonE1_cneg(p: POINTonE1, cbit: u64) -> vec384 { - cneg_fp(p.y, cbit) -} - -// TODO TEST -pub fn blst_p1_cneg(a: POINTonE1, cbit: u32) -> vec384 { - POINTonE1_cneg(a, is_zero(cbit) ^1) -} - -pub fn POINTonE1_from_Jacobian(in: POINTonE1) -> POINTonE1 { - //TODO - POINTonE1 { x: ONE_MONT_P, y: ONE_MONT_P, z: ONE_MONT_P } -} - diff --git a/old-bls/src/fields.sw b/old-bls/src/fields.sw deleted file mode 100644 index 50ebf54..0000000 --- a/old-bls/src/fields.sw +++ /dev/null @@ -1,136 +0,0 @@ -library fields; - -dep vect; -dep consts; - -use vect::*; -use consts::*; -use std::u128::*; - -/* -Reference implementation -https://github.com/supranational/blst -*/ - -// Fp - -pub fn add_fp(a: vec384, b: vec384) -> vec384 { - add_mod_384(a, b, BLS12_381_P) -} - -pub fn sub_fp(a: vec384, b: vec384) -> vec384 { - sub_mod_384(a, b, BLS12_381_P) -} - -pub fn mul_by_3_fp(a: vec384) -> vec384 { - mul_by_3_mod_384(a, BLS12_381_P) -} - -pub fn mul_by_8_fp(a: vec384) -> vec384 { - mul_by_8_mod_384(a, BLS12_381_P) -} - -pub fn lshift_fp(a: vec384, count: u64) -> vec384 { - lshift_mod_384(a, count, BLS12_381_P) -} - -//TODO TEST -pub fn rshift_fp(a: vec384, count: u64) -> vec384 { - rshift_mod_384(a, count, BLS12_381_P) -} - -//TODO TEST -pub fn div_by_2_fp(a: vec384) -> vec384 { - div_by_2_mod_384(a, BLS12_381_P) -} - -//TODO TEST -pub fn mul_fp(a: vec384, b: vec384) -> vec384 { - mul_mont_384(a, b, BLS12_381_P, P0) -} - -//TODO TEST -pub fn sqr_fp(a: vec384) -> vec384 { - sqr_mont_384(a, BLS12_381_P, P0) -} - -//TODO TEST -// conditional negation -pub fn cneg_fp(a: vec384, flag: u64) -> vec384 { - cneg_mod_384(a, flag, BLS12_381_P) -} - -//TODO TEST -pub fn from_fp(a: vec384) -> vec384 { - from_mont_384(a, BLS12_381_P, P0) -} - -//TODO TEST -pub fn redc_fp(a: vec768) -> vec384 { - redc_mont_384(a, BLS12_381_P, P0) -} - -// Fp2 - -pub fn add_fp2(a: vec384x, b: vec384x) -> vec384x { - let res_r = add_mod_384(a.r, b.r, BLS12_381_P); - let res_i = add_mod_384(a.i, b.i, BLS12_381_P); - vec384x { - r: res_r, - i: res_i, - } -} - -pub fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { - let res_r = sub_mod_384(a.r, b.r, BLS12_381_P); - let res_i = sub_mod_384(a.i, b.i, BLS12_381_P); - vec384x { - r: res_r, - i: res_i, - } -} - -//TODO TEST -pub fn mul_by_3_fp2(a: vec384x) -> vec384x { - mul_by_3_mod_384x(a, BLS12_381_P) -} - -//TODO TEST -pub fn mul_by_8_fp2(a: vec384x) -> vec384x { - mul_by_8_mod_384x(a, BLS12_381_P) -} - -//TODO TEST -pub fn lshift_fp2(a: vec384x, count: u64) -> vec384x { - let res_r = lshift_mod_384(a.r, count, BLS12_381_P); - let res_i = lshift_mod_384(a.i, count, BLS12_381_P); - vec384x { - r: res_r, - i: res_i, - } -} - -//TODO TEST -pub fn mul_fp2(a: vec384x, b: vec384x) -> vec384x { - mul_mont_384x(a, b, BLS12_381_P, P0) -} - -//TODO TEST -pub fn sqr_fp2(a: vec384x) -> vec384x { - sqr_mont_384x(a, BLS12_381_P, P0) -} - -//TODO TEST -pub fn cneg_fp2(a: vec384x, flag: u64) -> vec384x { - let res_r = cneg_mod_384(a.r, flag, BLS12_381_P); - let res_i = cneg_mod_384(a.i, flag, BLS12_381_P); - vec384x { - r: res_r, - i: res_i, - } -} - -pub fn reciprocal_fp(inp: vec384x) -> vec384x { - //TODO - ZERO_X -} diff --git a/old-bls/src/lib.sw b/old-bls/src/lib.sw deleted file mode 100644 index c69d70c..0000000 --- a/old-bls/src/lib.sw +++ /dev/null @@ -1,4 +0,0 @@ -library bls; - -dep fields; -dep vect; diff --git a/old-bls/src/main.sw b/old-bls/src/main.sw deleted file mode 100644 index 28dc79e..0000000 --- a/old-bls/src/main.sw +++ /dev/null @@ -1,55 +0,0 @@ -script; - -dep vect; -dep fields; -dep test_helpers; -dep consts; -dep tests/tests_vect_subfunctions; -dep tests/tests_temp_fe_mont_mul; - -use std::{assert::assert, option::*, u128::*, vec::Vec}; -use ::fields::*; -use ::vect::*; -use ::consts::*; -use ::test_helpers::*; -use std::logging::log; - -use ::tests_vect_subfunctions::vect_subfunctions_tests; -use ::tests_temp_fe_mont_mul::tests_temp_fe_mont_mul; - -fn main() { - // assert(fp_tests()); - // assert(fp2_tests()); - // assert(test_multiply_wrap()); - assert(test_mac()); - // assert(vect_subfunctions_tests()); - // assert(tests_small_functions()); - - // assert(tests_temp_mul()); - // assert(tests_temp_fe_mont_mul()); -} - -fn test_mac() -> bool { - let a = 13282407956253574712; - let b = 7557322358563246340; - let c = 14991082624209354397; - - let res = mac(a, b, c, 0); - assert(res.0 == 15211181400380206508); - assert(res.1 == 6141595689857899799); - - let carry = 1234555432334; - let res2 = mac(a, b, c, carry); - assert(res2.0 == 15211182634935638842); - assert(res2.1 == 6141595689857899799); - - true -} - -fn test_multiply_wrap() -> bool { - let a: u64 = 562706585515371056; - let b: u64 = 2854579515609623853; - let res: u64 = multiply_wrap(a, b); - assert(res == 2259604989141998192); - true -} diff --git a/old-bls/src/test_helpers.sw b/old-bls/src/test_helpers.sw deleted file mode 100644 index 0d25a7a..0000000 --- a/old-bls/src/test_helpers.sw +++ /dev/null @@ -1,41 +0,0 @@ -library test_helpers; - -dep vect; - -use vect::*; -use std::{assert::assert, logging::log, vec::Vec}; - -pub fn print_vec384(a: vec384) { - log(a.ls[0]); - log(a.ls[1]); - log(a.ls[2]); - log(a.ls[3]); - log(a.ls[4]); - log(a.ls[5]); -} - -pub fn equals_vec384(a: vec384, b: vec384) { - assert(a.ls[0] == b.ls[0]); - assert(a.ls[1] == b.ls[1]); - assert(a.ls[2] == b.ls[2]); - assert(a.ls[3] == b.ls[3]); - assert(a.ls[4] == b.ls[4]); - assert(a.ls[5] == b.ls[5]); -} - -pub fn equals_vec(a: Vec, b: Vec, n: u64) -> bool { - let mut i = 0; - while i < n { - assert(unpack_or_0(a.get(i)) == unpack_or_0(a.get(i))); - i += 1; - } - true -} -pub fn print_vec(a: Vec) { - let mut i = 0; - let l = a.len(); - while i < l { - log(unpack_or_0(a.get(i))); - i += 1; - } -} diff --git a/old-bls/src/tests/tests_temp_fe_mont_mul.sw b/old-bls/src/tests/tests_temp_fe_mont_mul.sw deleted file mode 100644 index e7554ec..0000000 --- a/old-bls/src/tests/tests_temp_fe_mont_mul.sw +++ /dev/null @@ -1,175 +0,0 @@ -library tests_temp_fe_mont_mul; - -use ::vect::*; -use std::{assert::assert, vec::Vec}; -use ::test_helpers::*; -use std::logging::log; - -// COMMENT: this runs out of gas in contract testing as well -// Keeping this for now, because it hasn't been converted yet - -pub fn tests_temp_fe_mont_mul() -> bool { - // assert(test_temp_mul_random_by_random()); - // assert(test_temp_mul_mont_n()); - true -} -/* -fn test_temp_mul_mont_n() -> bool { - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new(); - r1_vec.push(6071868568151433008); - r1_vec.push(12105094901188801210); - r1_vec.push(2389211775905699303); - r1_vec.push(7838417195104481535); - r1_vec.push(5826366508043997497); - r1_vec.push(13436617433956842131); - //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new(); - r2_vec.push(16964885827015180015); - r2_vec.push(12035734743809705289); - r2_vec.push(10517060043363161601); - r2_vec.push(1119606639881808286); - r2_vec.push(2211903887497377980); - r2_vec.push(395875676649998273); - - //Sway can't handle this. Error: - /* - { - "Panic": { - "id": "0000000000000000000000000000000000000000000000000000000000000000", - "is": 10352, - "pc": 169804, - "reason": { - "instruction": { - "imm06": 0, - "imm12": 0, - "imm18": 0, - "imm24": 0, - "op": 96, - "ra": 0, - "rb": 0, - "rc": 0, - "rd": 0 - }, - "reason": "OutOfGas" - } - } - }, - { - "ScriptResult": { - "gas_used": 100000000, - "result": "Panic" - } - } - */ - let res = temp_mul_mont_n(r1_vec, r2_vec); - print_vec(res); - true -} - -fn test_temp_mul_random_by_random() -> bool { - let mut p_vec = ~Vec::new(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new(); - r1_vec.push(6071868568151433008); - r1_vec.push(12105094901188801210); - r1_vec.push(2389211775905699303); - r1_vec.push(7838417195104481535); - r1_vec.push(5826366508043997497); - r1_vec.push(13436617433956842131); - //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new(); - r2_vec.push(16964885827015180015); - r2_vec.push(12035734743809705289); - r2_vec.push(10517060043363161601); - r2_vec.push(1119606639881808286); - r2_vec.push(2211903887497377980); - r2_vec.push(395875676649998273); - - // let a_mont = fe_to_mont(r1_vec); - // print_vec(a_mont); - /* -17993655965713306301 -15604842006860479165 -10837926002905938402 -13429498400065700031 -1823694494885156540 -933350646299434799 - */ - - // let b_mont = fe_to_mont(r2_vec); - // print_vec(b_mont); - /* -5720430457560562798 -2568557665684583703 -15870134958983808442 -14065062413899436375 -12262047246709729804 -1303068506660090079 - */ - - // let res = temp_fe_mont_mul(a_mont, b_mont); - // print_vec(res); - /* -8042921339150017446 -4899742317194411181 -11922910400151252689 -7736564210120511729 -10892349319971706476 -542573957820843489 - */ - - /* - This is what res has as a value at this point, but running all the operations gives the error - out of gas, so just run with this known value. All intermediate steps are correct with - the ncc ref implementation - */ - let mut intermediate_res_vec = ~Vec::new(); - intermediate_res_vec.push(8042921339150017446); - intermediate_res_vec.push(4899742317194411181); - intermediate_res_vec.push(11922910400151252689); - intermediate_res_vec.push(7736564210120511729); - intermediate_res_vec.push(10892349319971706476); - intermediate_res_vec.push(542573957820843489); - // let res_norm = fe_to_norm(res); - let res_norm = fe_to_norm(intermediate_res_vec); - // print_vec(res_norm); - /* -16494539950903960225 + -6909894500484332639 * 2^64 + -10854278113294925999 * 2^128 + -10279541547892741855 * 2^192 + -12499445441687670930 * 2^256 + -440910865060157199 *2^320 - -941779891765169534644661530249600716619032215997678548055171344032200486581648291416343986992810576160191745532577 -which is a*b mod p -*/ - true -} - -/* -Note: from the reference impl, you can see it's being tested as follows: - - - let a_big = rnd_big_mod_n(); - let b_big = rnd_big_mod_n(); - fe_to_mont(&mut a_mont, &big_to_6u64(&a_big)); - fe_to_mont(&mut b_mont, &big_to_6u64(&b_big)); - - let expected = (&a_big * &b_big) % &(*N_BIG); - fe_mont_mul(&mut actual_mont, &a_mont, &b_mont); - - fe_to_norm(&mut actual_norm, &actual_mont); - assert_eq!(big_to_6u64(&expected), actual_norm); - -So there is a conversion to and from the mont form -*/ -*/ \ No newline at end of file diff --git a/old-bls/src/tests/tests_vect_subfunctions.sw b/old-bls/src/tests/tests_vect_subfunctions.sw deleted file mode 100644 index 16d31ca..0000000 --- a/old-bls/src/tests/tests_vect_subfunctions.sw +++ /dev/null @@ -1,563 +0,0 @@ -library tests_vect_subfunctions; - -use ::fields::*; -use ::vect::*; -use ::test_helpers::*; -use std::logging::log; -use std::{assert::assert, vec::Vec}; -use ::consts::*; - -// COMMENT: these tests can't be converted to contract testing yet because they don't support Vec yet - -pub fn vect_subfunctions_tests() -> bool { - // NOTE: Don't run all at the same time, because will run out of gas - - // add_mod_n tests. They have the same test values as add_fp - // which should be correct, but of course add_mod_n should do more - // assert(test_add_zero_to_zero_addn()); - // assert(test_add_zero_to_random_addn()); - // assert(test_add_random_to_small_addn()); - - // assert(test_mul_mont_n_by_zero()); - // assert(test_mul_mont_n_zero_by_one()); - // assert(test_mul_mont_n_one_by_one()); - // assert(test_mul_mont_n_random_by_one()); - // assert(test_mul_mont_n_random_by_random()); - assert(test_mont_mul_partial()); - - // these tests are the same as for sub_fp and work. But they should support more values of n, thus more tests have to be added - // assert(test_sub_zero_from_zero_subn()); - // assert(test_sub_zero_from_random_subn()); - // assert(test_sub_random_from_zero_subn()); - // assert(test_sub_random_from_small_subn()); - // assert(test_sub_2_randoms_subn()); - // assert(test_sub_2_randoms_reverse_subn()); - - // assert(tests_redc_mont()); - true -} - -fn get_test_vectors() -> (Vec, Vec) { - let mut zero_vec = ~Vec::new(); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - - let mut p_vec = ~Vec::new(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - (zero_vec, p_vec) -} - -fn test_mul_mont_n_by_zero() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = mul_mont_n(zero_vec, zero_vec, p_vec, P0, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn get_one_vec() -> Vec { - let mut one_vec = ~Vec::new(); - one_vec.push(1); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec.push(0); - one_vec -} - -fn test_mul_mont_n_zero_by_one() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - let one_vec = get_one_vec(); - - let res = mul_mont_n(zero_vec, one_vec, p_vec, P0, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_mul_mont_n_one_by_one() -> bool { - let(_, p_vec) = get_test_vectors(); - let one_vec = get_one_vec(); - - let res = mul_mont_n(one_vec, one_vec, p_vec, P0, 6); - equals_vec(res, one_vec, 6); - //print_vec(res); - // print_vec(one_vec); - true -} - -fn test_mul_mont_n_random_by_one() -> bool { - let(_, p_vec) = get_test_vectors(); - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r_vec = ~Vec::new(); - r_vec.push(0x54439c4ae7869f30); //6071868568151433008 - r_vec.push(0xa7fdefad55c032ba); //12105094901188801210 - r_vec.push(0x21282f739c0a15e7); //2389211775905699303 - r_vec.push(0x6cc7a6e8c38430ff); //7838417195104481535 - r_vec.push(0x50db69783b321139); //5826366508043997497 - r_vec.push(0xba78745dadd17a93); //13436617433956842131 - let one_vec = get_one_vec(); - - let res = mul_mont_n(r_vec, one_vec, p_vec, P0, 6); - // print_vec(res); - /* - - */ - // let b = equals_vec(res, r_vec, 6); - // log(b); - let mut i = 0; - while i < 6 { - assert(unpack_or_0(res.get(i)) == unpack_or_0(r_vec.get(i))); - i += 1; - } - true -} - -fn test_mul_mont_n_random_by_random() -> bool { - let(_, p_vec) = get_test_vectors(); - //28700440645560700010247999350858186656965165501286811298915027297835050275063552879691348405696442872566701753802544 - let mut r1_vec = ~Vec::new(); - r1_vec.push(6071868568151433008); - r1_vec.push(12105094901188801210); - r1_vec.push(2389211775905699303); - r1_vec.push(7838417195104481535); - r1_vec.push(5826366508043997497); - r1_vec.push(13436617433956842131); - //845585313160814446158446407435059620350609671735802091463220815564059525214346533476776130630310896229502998576879 - let mut r2_vec = ~Vec::new(); - r2_vec.push(16964885827015180015); - r2_vec.push(12035734743809705289); - r2_vec.push(10517060043363161601); - r2_vec.push(1119606639881808286); - r2_vec.push(2211903887497377980); - r2_vec.push(395875676649998273); - - //1128153310087946582770541547041113021655162062067663357733024411531633319713239944238808860915038256082620363451095 - //[4793585148327242455, 2837967030551533581, 1626660158106644623, - //15384342728939744618, 1826521055323312182, 528164867630647501] - - // mult by p0 - //241244430210532575562827373868655963084727802841779217074318408842127082994632785925923353131362216879147315212775676243090892648326992525470904388378004276874316175983655739522130737118499414971959740231422333803704862166384557102941841719958128272 - // mod p - //1233002344306172478209354248697859329250780126726480993298462574958424022710616415994206080732967265541051783400711 - //[1734233419737550087, 7827676449723675145, 5835727259298429301, 3992373620040751347, 13994230039556723943, 577251792061825638] - let mut res_vec = ~Vec::new(); - res_vec.push(0x42863c4b7ea22ad7); //4793585148327242455 - res_vec.push(0x27627bfa644b580d); //2837967030551533581 - res_vec.push(0x16930ecb9e3a308f); //1626660158106644623 - res_vec.push(0xd5802a33c5512d6a); //15384342728939744618 - res_vec.push(0x19591b38f5515036); //1826521055323312182 - res_vec.push(0x7546b2615f748cd); //528164867630647501 - let res = mul_mont_n(r1_vec, r2_vec, p_vec, P0, 6); - print_vec(res); - /* -10466566815393401694 -14579313370948138685 -11816151785009594293 -7246864926219872143 -15908820384664990112 -328568623818015453 - -blst impl -3517150968681791168 -13347192682519393737 -4541454005160136609 -16590274403525876995 -17086414653262144931 -16572945458942657492 - */ - // equals_vec(res, res_vec, 6); - - true -} - -fn test_mont_mul_partial() -> bool { - let(_, p_vec) = get_test_vectors(); - - let mut intermediate_res_vec = ~Vec::new(); - intermediate_res_vec.push(8042921339150017446); - intermediate_res_vec.push(4899742317194411181); - intermediate_res_vec.push(11922910400151252689); - intermediate_res_vec.push(7736564210120511729); - intermediate_res_vec.push(10892349319971706476); - intermediate_res_vec.push(542573957820843489); - - let mut ONE: Vec = ~Vec::new(); - ONE.push(0x1); - ONE.push(0); - ONE.push(0); - ONE.push(0); - ONE.push(0); - ONE.push(0); - - let res = mul_mont_n(intermediate_res_vec, ONE, p_vec, P0, 6); - print_vec(res); - - /* -Should be -16494539950903960225 -6909894500484332639 -10854278113294925999 -10279541547892741855 -12499445441687670930 -440910865060157199 - -//Current output is: -4899742317194411181 -11922910400151252689 -7736564210120511729 -10892349319971706476 -542573957820843489 -0 -This is almost the input vector... -*/ - true -} - -fn test_add_zero_to_zero_addn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = add_mod_n(zero_vec, zero_vec, p_vec, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_add_zero_to_random_addn() -> bool { - let mut random_vec = ~Vec::new(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - let(zero_vec, p_vec) = get_test_vectors(); - - let res = add_mod_n(random_vec, zero_vec, p_vec, 6); - equals_vec(res, random_vec, 6); - true -} - -fn test_add_random_to_small_addn() -> bool { - let mut small_vec = ~Vec::new(); - small_vec.push(0x1); - small_vec.push(0x2); - small_vec.push(0x3); - small_vec.push(0x4); - small_vec.push(0x5); - small_vec.push(0x6); - let mut random_vec = ~Vec::new(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - let mut res_vec = ~Vec::new(); - res_vec.push(4478030004447473543); - res_vec.push(2814704111667093004); - res_vec.push(15884408734010272161); - res_vec.push(17001047363111187582); - res_vec.push(932823543034528552); - res_vec.push(1051481384684610851); - - let(_, p_vec) = get_test_vectors(); - - let res = add_mod_n(small_vec, random_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - true -} - -fn test_sub_zero_from_zero_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let res = sub_mod_n(zero_vec, zero_vec, p_vec, 6); - equals_vec(res, zero_vec, 6); - true -} - -fn test_sub_zero_from_random_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let mut random_vec = ~Vec::new(); - random_vec.push(0x3e2528903ca1ef86); - random_vec.push(0x270fd67a03bf9e0a); - random_vec.push(0xdc70c19599cb699e); - random_vec.push(0xebefda8057d5747a); - random_vec.push(0xcf20e11f0b1c323); - random_vec.push(0xe979cbf960fe51d); - - let res = sub_mod_n(random_vec, zero_vec, p_vec, 6); - equals_vec(res, random_vec, 6); - true -} - -fn test_sub_random_from_zero_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - - let mut random_vec = ~Vec::new(); - random_vec.push(13059245463466299169); - random_vec.push(17774603101077980186); - random_vec.push(889990675562875390); - random_vec.push(12771390643166271294); - random_vec.push(5370893444473505192); - random_vec.push(599972797727911687); - - let res = sub_mod_n(zero_vec, random_vec, p_vec, 6); - // p-r (is the same as 0-r mod p) - let mut res_vec = ~Vec::new(); - res_vec.push(343185552611564426); - res_vec.push(2882282484148780005); - res_vec.push(6545683898001206309); - res_vec.push(12914691390957992833); - res_vec.push(41210333997197102); - res_vec.push(1273825819919628179); - equals_vec(res, res_vec, 6); - true -} - -fn test_sub_random_from_small_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - // 1 + 2 *2^64 + 3*2^128 + 4 * 2^192 + 5 * 2^256 + 6 * 2^320 - //12815922215525460494949090683203893664759190466124902882004963575055114655935967659265637031608321 - let mut small_vec = ~Vec::new(); - small_vec.push(1); - small_vec.push(2); - small_vec.push(3); - small_vec.push(4); - small_vec.push(5); - small_vec.push(6); - - //1281534117852017820269267861584320258656990227317793864009951923807317297699607442944495077621627898376663719366433 - let mut r_vec = ~Vec::new(); - r_vec.push(13059245463466299169); - r_vec.push(17774603101077980186); - r_vec.push(889990675562875390); - r_vec.push(12771390643166271294); - r_vec.push(5370893444473505192); - r_vec.push(599972797727911687); - - let mut res_vec = ~Vec::new(); - res_vec.push(343185552611564427); - res_vec.push(2882282484148780007); - res_vec.push(6545683898001206312); - res_vec.push(12914691390957992837); - res_vec.push(41210333997197107); - res_vec.push(1273825819919628185); - - //result should be 2720875437369649585964444179677044392848983275825107686081296678441617234796193996553307207443355424926867584801675 - let res = sub_mod_n(small_vec, r_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn get_r1_r2_vecs() -> (Vec, Vec) { - //a = 1636725880549280067486622211868244649555599468607198938781220718077581339058902572863029175226410795172800087248680 - //[10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194] - let mut r1_vec = ~Vec::new(); - r1_vec.push(10587454305359941416); - r1_vec.push(4615625447881587853); - r1_vec.push(9368308553698906485); - r1_vec.push(9494054596162055604); - r1_vec.push(377309137954328098); - r1_vec.push(766262085408033194); - - //b = 633982047616931537296775994873240773075794315607478597677958352919546237170580686209956468014669319291596219488262 - //[13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174] - let mut r2_vec = ~Vec::new(); - r2_vec.push(13403040667047958534); - r2_vec.push(405585388298286396); - r2_vec.push(7295341050629342949); - r2_vec.push(1749456428444609784); - r2_vec.push(1856600841951774635); - r2_vec.push(296809876162753174); - - (r1_vec, r2_vec) -} - -fn test_sub_2_randoms_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - let(r1_vec, r2_vec) = get_r1_r2_vecs(); - - //res = - //1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - //[15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019] - let mut res_vec = ~Vec::new(); - res_vec.push(15631157712021534498); - res_vec.push(4210040059583301456); - res_vec.push(2072967503069563536); - res_vec.push(7744598167717445820); - res_vec.push(16967452369712105079); - res_vec.push(469452209245280019); - - let res = sub_mod_n(r1_vec, r2_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn test_sub_2_randoms_reverse_subn() -> bool { - let(zero_vec, p_vec) = get_test_vectors(); - let(r1_vec, r2_vec) = get_r1_r2_vecs(); - - //res = - //-1002743832932348530189846216995003876479805152999720341103262365158035101888321886653072707211741475881203867760418 - // => mod p - //2999665722289318863227943608740900280077077666939287544228795770965996548602515977789614921917274188156690404799369 - //[16218017377765880713, 16446845525643458734, 5362707070494518163, 17941483866406818307, 6891395482468148831, 1404346408402259846] - let mut res_vec = ~Vec::new(); - res_vec.push(16218017377765880713); - res_vec.push(16446845525643458734); - res_vec.push(5362707070494518163); - res_vec.push(17941483866406818307); - res_vec.push(6891395482468148831); - res_vec.push(1404346408402259846); - - let res = sub_mod_n(r2_vec, r1_vec, p_vec, 6); - equals_vec(res, res_vec, 6); - - true -} - -fn tests_redc_mont() -> bool { - assert(test_redc_mont_n_small()); - // assert(test_redc_mont_n_p()); - // assert(test_redc_mont_n_random()); - // assert(test_redc_mont_n_random_large()); - - true -} -fn test_redc_mont_n_small() -> bool { - let mut a_vec: Vec = ~Vec::new(); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(10); - let mut res_vec: Vec = ~Vec::new(); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(0); - res_vec.push(10); - let test_vec = get_test_vectors(); - let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); - equals_vec(res, res_vec, 6); - true -} - -fn test_redc_mont_n_p() -> bool { - let mut p_vec = ~Vec::new(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - p_vec.push(0); - p_vec.push(0); - p_vec.push(0); - p_vec.push(0); - p_vec.push(0); - p_vec.push(0); - let test_vec = get_test_vectors(); - let res = redc_mont_n(p_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); - //equals_vec(res, get_test_vectors().0, 6); - print_vec(res); - true -} - -fn test_redc_mont_n_random() -> bool { - /* - a_vec = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 - = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] - (using GP Pari) - a_vec mod P = 3696765165377537992548071770426871989328256175267415194498929704185983294358703155983657203868185085593368583538232 - = [1730705806359781376, 10719928016004921607, 6631139461101160670, 14991082624209354397, 7557322358563246340, 13282407956253574712] - */ - let mut a_vec = ~Vec::new(); - - a_vec.push(13282407956253574712); - a_vec.push(7557322358563246340); - a_vec.push(14991082624209354397); - a_vec.push(6631139461101160670); - a_vec.push(10719928016004921607); - a_vec.push(1730705806359781376); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - let mut result = ~Vec::new(); - result.push(13282407956253574712); - result.push(7557322358563246340); - result.push(14991082624209354397); - result.push(6631139461101160670); - result.push(10719928016004921607); - result.push(1730705806359781376); - - let test_vec = get_test_vectors(); - let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); - print_vec(res); - //equals_vec(res, result, 6); - true -} - -fn test_redc_mont_n_random_large() -> bool { - /* - a = random({2^384}) = 21380795309672530537064108666460268360580493838230277925224860893329212391422460281305468429766194371347271041959862 - = [10009796384580774444, 9837491998535547791, 12861376030615125811, 15982738825684268908, 17984324540840297179, 13142370077570254774] - - a mod p = 1368747533564193569975159537780747577796079738535238498564570212709054138968270959092030284121116051157799679160927 - = [640803296343075113, 1223717179891587930, 13558174375960666486, 15697854105282963640, 6933616983254254301, 1470447218309591647] - - - - */ - let mut a_vec = ~Vec::new(); - a_vec.push(13142370077570254774); - a_vec.push(17984324540840297179); - a_vec.push(15982738825684268908); - a_vec.push(12861376030615125811); - a_vec.push(9837491998535547791); - a_vec.push(10009796384580774444); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - a_vec.push(0); - - let mut result = ~Vec::new(); - result.push(1470447218309591647); - result.push(6933616983254254301); - result.push(15697854105282963640); - result.push(13558174375960666486); - result.push(1223717179891587930); - result.push(640803296343075113); - - let test_vec = get_test_vectors(); - let res = redc_mont_n(a_vec, test_vec.1, 0x89f3fffcfffcfffd, 6); - //equals_vec(res, result, 6); - print_vec(res); - true -} diff --git a/old-bls/src/vect.sw b/old-bls/src/vect.sw deleted file mode 100644 index 3894339..0000000 --- a/old-bls/src/vect.sw +++ /dev/null @@ -1,985 +0,0 @@ -library vect; - -dep consts; - -use std::{option::*, u128::*, vec::Vec}; -use consts::*; - -// Stores field element with max 384 bits -// element in fp -pub struct vec384 { - ls: [u64; - 6], -} - -pub struct vec768 { - ls: [u64; - 12], -} - -// element in fp2 -pub struct vec384x { - r: vec384, //"real" part - i: vec384, //"imaginary" part -} - -//TODO: remove these. Only for developing (as placeholder return values) and testing atm -pub const ZERO: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0] -}; -pub const ZERO_X: vec384x = vec384x { - r: ZERO, i: ZERO -}; - -/* - z = -0xd201000000010000 - (z-1)^2 * (z^4 - z^2 + 1)/3 + z - 4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787 - (381 bits) -*/ -pub const BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a] -}; -/// INV = -(P^{-1} mod 2^64) mod 2^64 -pub const INV: u64 = 0x89f3fffcfffcfffd; - -// START FUNCTIONS - -pub fn unpack_or_0(x: Option) -> u64 { - match x { - Option::Some(val) => val, Option::None => 0, - } -} - -pub fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { - let mut limbx: u64 = 0; - let mut carry: u64 = 0; - let mut tmp = ~Vec::new(); - - let mut i = 0; - while i < n { - // sum with carry of a and b. Returns result and new carry - let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), carry); - tmp.insert(i, limb); - carry = temp_carry; - i += 1; - } - - let mut ret = ~Vec::new(); - let mut borrow: u64 = 0; - i = 0; - while i < n { - // sum with borrow of a and b. Returns result and new borrow - let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(tmp.get(i)), unpack_or_0(p.get(i)), borrow); - ret.insert(i, limb); - borrow = temp_borrow; - i += 1; - } - - let mask: u64 = borrow * ~u64::max(); - let mut res = ~Vec::new(); - i = 0; - while i < n { - let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp.get(i)) & mask); - res.insert(i, value); - i += 1; - } - res -} - - -/* -WIP - -This is following the blst implementation. - -It's unclear why the output that the blst gives would be the correct one. - -For example: temp_fe_mont_mul implements montgomery mult following ncc impl does give the right "montgomery output", -which has conversions before and after to perform a complete multiplication. -But this intermediate value doesn't correspond to what the blst impl outputs. -*/ -pub fn mul_mont_n(a: Vec, b: Vec, p: Vec, n0: u64, n: u64) -> Vec { - let mut mx: U128 = ~U128::from(0, unpack_or_0(b.get(0))); - let mut hi: U128 = ~U128::from(0, 0); - let mut tmp: Vec = ~Vec::new(); - let mut tmp2: Vec = ~Vec::new(); - let mut tmp3: Vec = ~Vec::new(); - let mut i = 0; - - while i < n { - let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); - let limbx = mx * ai + hi; - tmp.insert(i, limbx.lower); - hi = ~U128::from(0, limbx.upper); - i += 1; - } - tmp.insert(i, hi.lower); - - let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp.get(0)))).lower; - let mut mx: U128 = ~U128::from(0, mx_temp); - let mut carry: u64 = 0; - let mut j = 0; - let mut limbx: U128 = ~U128::from(0, 0); - while true { - let p0: U128 = ~U128::from(0, unpack_or_0(p.get(0))); - let tmp0: U128 = ~U128::from(0, unpack_or_0(tmp.get(0))); - limbx = (mx * p0) + tmp0; - hi = ~U128::from(0, limbx.upper); - i = 1; - - //just to be sure copying this over - let mut k = 0; - while k < 12 { - tmp2.push(unpack_or_0(tmp.get(k))); - k += 1; - } - - while i < n { - let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - limbx = (mx * pi + hi) + tmpi; - tmp2.insert(i - 1, limbx.lower); - hi = ~U128::from(0, limbx.upper); - i += 1; - } - limbx = ~U128::from(0, unpack_or_0(tmp.get(i))) + (hi + ~U128::from(0, carry)); - tmp2.insert(i - 1, limbx.lower); - - carry = limbx.upper; - j += 1; - if j == n { - break; - } - mx = ~U128::from(0, unpack_or_0(b.get(j))); - hi = ~U128::from(0, 0); - i = 0; - - //just to be sure copying this over - k = 0; - while k < 12 { - tmp3.push(unpack_or_0(tmp2.get(k))); - k += 1; - } - - while i < n { - let ai: U128 = ~U128::from(0, unpack_or_0(a.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); - limbx = (mx * ai + hi) + tmpi; - tmp3.insert(i, limbx.lower); - hi = ~U128::from(0, limbx.upper); - i += 1; - } - let mut mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(tmp3.get(0)))).lower; - let mut mx: U128 = ~U128::from(0, mx_temp); - - limbx = hi + ~U128::from(0, carry); - tmp3.insert(i, limbx.lower); - carry = limbx.upper; - } - - let mut borrow: u64 = 0; - i = 0; - let mut ret: Vec = ~Vec::new(); - while i < n { - let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp3.get(i))); - let pi_w_borrow = pi + ~U128::from(0, borrow); - // Prevent underflow. When U256 arithmetic is available we can create sbb_256 - let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmpi { - (tmpi - pi_w_borrow, 0) - } else { - (~U128::max() - (pi_w_borrow - tmpi - ~U128::from(0, 1)), 1) - }; - limbx = sub_res; - ret.insert(i, limbx.lower); - borrow = b_res & 0x1; - i += 1; - } - - /*ret: -9944055374826099202 -9712768888634044113 -300889636556430029 -3653011359556993965 -13577214253059692810 -16572945456062011749 -0..0 - */ - - /*tmp3: -4899742317194411181 -11922910400151252689 -7736564210120511729 -10892349319971706476 -542573957820843489 -0 -0 -4899742317194411181 -11922910400151252689 -7736564210120511729 -10892349319971706476 -542573957820843489 - */ - - let mask: u64 = if carry >= borrow { - carry - borrow - } else { - ~u64::max() - (borrow - carry - 1) - }; - - i = 0; - let mut res: Vec = ~Vec::new(); - while i < n { - let value = (unpack_or_0(ret.get(i)) & not(mask)) | (unpack_or_0(tmp3.get(i)) & mask); - res.insert(i, value); - i += 1; - } - res -} - -// TEMP MONTGOMERY MULT FROM NCC impl -// Repo: https://github.com/nccgroup/pairing -// Blogpost: https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ -fn zero_vec() -> Vec { - let mut temp: Vec = ~Vec::new(); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp.push(0); - temp -} - -/* -The mul_mont_n is not working yet, so this would be a temporary solution but using montgomery mult. -*/ -//pub fn temp_mul_mont_n(a: Vec, b: Vec) -> Vec { -pub fn temp_mul_mont_n(a_vec: vec384, b_vec: vec384) -> vec384 { - let mut a: Vec = ~Vec::new(); - a.push(a_vec.ls[0]); - a.push(a_vec.ls[1]); - a.push(a_vec.ls[2]); - a.push(a_vec.ls[3]); - a.push(a_vec.ls[4]); - a.push(a_vec.ls[5]); - - let mut b: Vec = ~Vec::new(); - b.push(b_vec.ls[0]); - b.push(b_vec.ls[1]); - b.push(b_vec.ls[2]); - b.push(b_vec.ls[3]); - b.push(b_vec.ls[4]); - b.push(b_vec.ls[5]); - - - // To mont form - let a_mont = fe_to_mont(a); - let res_vec = vec384{ - ls: [unpack_or_0(a_mont.get(0)),unpack_or_0(a_mont.get(1)), - unpack_or_0(a_mont.get(2)),unpack_or_0(a_mont.get(3)), - unpack_or_0(a_mont.get(4)),unpack_or_0(a_mont.get(5))] - }; - // a_mont; - res_vec - // let b_mont = fe_to_mont(b); - // // Mult - // let res = temp_fe_mont_mul(a_mont, b_mont); - // // Transform back - // let res = fe_to_norm(res); - // let res_vec = vec384{ - // ls: [unpack_or_0(res.get(0)),unpack_or_0(res.get(1)),unpack_or_0(res.get(2)),unpack_or_0(res.get(3)),unpack_or_0(res.get(4)),unpack_or_0(res.get(5))] - // }; - - // res_vec -} - -// Same functionality as mul_temp -// Effectively a_mont = (a_norm * R) mod N -pub fn fe_to_mont(a: Vec) -> Vec { - let mut BLS12_381_RR: Vec = ~Vec::new(); - BLS12_381_RR.push(0xf4df1f341c341746); - BLS12_381_RR.push(0x0a76e6a609d104f1); - BLS12_381_RR.push(0x8de5476c4c95b6d5); - BLS12_381_RR.push(0x67eb88a9939d83c0); - BLS12_381_RR.push(0x9a793e85b519952d); - BLS12_381_RR.push(0x11988fe592cae3aa); - temp_fe_mont_mul(a, BLS12_381_RR) -} - -// Effectively a_norm = (a_mont * R^{-1}) mod N -pub fn fe_to_norm(a: Vec) -> Vec { - let mut ONE: Vec = ~Vec::new(); - ONE.push(0x1); - ONE.push(0); - ONE.push(0); - ONE.push(0); - ONE.push(0); - ONE.push(0); - temp_fe_mont_mul(a, ONE) -} - -// temporary mont mult impl from https://research.nccgroup.com/2021/06/09/optimizing-pairing-based-cryptography-montgomery-arithmetic-in-rust/ -// with repo https://github.com/nccgroup/pairing -pub fn temp_fe_mont_mul(a: Vec, b: Vec) -> Vec { - let mut temp: Vec = zero_vec(); - let mut i = 0; - let mut j = 0; - let mut carry = 0u64; - while i < 6 { - carry = 0; - j = 0; - while j < 6 { - let aj: U128 = ~U128::from(0, unpack_or_0(a.get(j))); - let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); - let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); - let carry_128 = ~U128::from(0, carry); - let hilo: U128 = aj * bi + temp_ij + carry_128; - temp.remove(i + j); - temp.insert(i + j, hilo.lower); - carry = hilo.upper; - j += 1; - } - let mut t = unpack_or_0(temp.get(i + 6)); - temp.remove(i + 6); - temp.insert(i + 6, t + carry); - - let m: u64 = multiply_wrap(unpack_or_0(temp.get(i)), P0); - let m_128 = ~U128::from(0, m); - - carry = 0; - j = 0; - while j < 6 { - let nj: U128 = ~U128::from(0, BLS12_381_P.ls[j]); - let temp_ij = ~U128::from(0, unpack_or_0(temp.get(i + j))); - let carry_128 = ~U128::from(0, carry); - let hilo: U128 = m_128 * nj + temp_ij + carry_128; - temp.remove(i + j); - temp.insert(i + j, hilo.lower); - carry = hilo.upper; - j += 1; - } - t = unpack_or_0(temp.get(i + 6)); - temp.remove(i + 6); - temp.insert(i + 6, t + carry); - i += 1; - } - - let mut dec: Vec = zero_vec(); - let mut borrow = 0u64; - j = 0; - while j < 6 { - let(diff, borrow_t0) = sbb(unpack_or_0(temp.get(j + 6)), BLS12_381_P.ls[j], borrow); - dec.insert(j, diff); - borrow = borrow_t0; - j += 1; - } - - /*temp: -0..0 -16494539950903960225 -6909894500484332639 -10854278113294925999 -10279541547892741855 -12499445441687670930 -440910865060157199 - */ - - /*dec: -3092108934826096630 -4699752988967124064 -3418603539730844299 -3040203587478029344 -7087341663216968635 -17013856321122168949 -0..0 - */ - - let mask: u64 = if borrow == 1 { - ~u64::max() - } else { - 0 - }; - let mut result: Vec = zero_vec(); - j = 0; - while j < 6 { - let entry = (unpack_or_0(temp.get(j + 6)) & mask) | (not(mask) & unpack_or_0(dec.get(j))); - result.insert(j, entry); - j += 1; - } - result -} - -// from https://github.com/zkcrypto/bls12_381 -pub fn montgomery_reduction(t: [u64; -12]) -> vec384 { - let k = multiply_wrap(t[0], INV); - - let r0: (u64, u64) = mac(t[0], k, BLS12_381_P.ls[0], 0); - let r1: (u64, u64) = mac(t[1], k, BLS12_381_P.ls[1], r0.1); - let r2: (u64, u64) = mac(t[2], k, BLS12_381_P.ls[2], r1.1); - let r3: (u64, u64) = mac(t[3], k, BLS12_381_P.ls[3], r2.1); - let r4: (u64, u64) = mac(t[4], k, BLS12_381_P.ls[4], r3.1); - let r5: (u64, u64) = mac(t[5], k, BLS12_381_P.ls[5], r4.1); - let r6_7: (u64, u64) = adc(t[6], 0, r5.1); - - let k = multiply_wrap(r1.0, INV); - let r0: (u64, u64) = mac(r1.0, k, BLS12_381_P.ls[0], 0); - let r2: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[1], r0.1); - let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[2], r2.1); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[3], r3.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[4], r4.1); - let r6: (u64, u64) = mac(r6_7.0, k, BLS12_381_P.ls[5], r5.1); - let r7_8: (u64, u64) = adc(t[7], r6_7.1, r6.1); - - let k = multiply_wrap(r2.0, INV); - let r0: (u64, u64) = mac(r2.0, k, BLS12_381_P.ls[0], 0); - let r3: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[1], r0.1); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[2], r3.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[3], r4.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[4], r5.1); - let r7: (u64, u64) = mac(r7_8.0, k, BLS12_381_P.ls[5], r6.1); - let r8_9: (u64, u64) = adc(t[8], r7_8.1, r7.1); - - let k = multiply_wrap(r3.0, INV); - let r0: (u64, u64) = mac(r3.0, k, BLS12_381_P.ls[0], 0); - let r4: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[1], r0.1); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[2], r4.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[3], r5.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[4], r6.1); - let r8: (u64, u64) = mac(r8_9.0, k, BLS12_381_P.ls[5], r7.1); - let r9_10: (u64, u64) = adc(t[9], r8_9.1, r8.1); - - let k = multiply_wrap(r4.0, INV); - let r0: (u64, u64) = mac(r4.0, k, BLS12_381_P.ls[0], 0); - let r5: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[1], r0.1); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[2], r5.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[3], r6.1); - let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[4], r7.1); - let r9: (u64, u64) = mac(r9_10.0, k, BLS12_381_P.ls[5], r8.1); - let r10_11: (u64, u64) = adc(t[10], r9_10.1, r9.1); - - let k = multiply_wrap(r5.0, INV); - let r0: (u64, u64) = mac(r5.0, k, BLS12_381_P.ls[0], 0); - let r6: (u64, u64) = mac(r6.0, k, BLS12_381_P.ls[1], r0.1); - let r7: (u64, u64) = mac(r7.0, k, BLS12_381_P.ls[2], r6.1); - let r8: (u64, u64) = mac(r8.0, k, BLS12_381_P.ls[3], r7.1); - let r9: (u64, u64) = mac(r9.0, k, BLS12_381_P.ls[4], r8.1); - let r10: (u64, u64) = mac(r10_11.0, k, BLS12_381_P.ls[5], r9.1); - let r11_12 = adc(t[11], r10_11.1, r10.1); - - subtract_p(vec384 { - ls: [r6.0, r7.0, r8.0, r9.0, r10.0, r11_12.0] - }, - BLS12_381_P) -} - -pub fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { - let mut a_temp: Vec = ~Vec::new(); - a_temp.push(a.ls[0]); - a_temp.push(a.ls[1]); - a_temp.push(a.ls[2]); - a_temp.push(a.ls[3]); - a_temp.push(a.ls[4]); - a_temp.push(a.ls[5]); - - let mut b_temp: Vec = ~Vec::new(); - b_temp.push(b.ls[0]); - b_temp.push(b.ls[1]); - b_temp.push(b.ls[2]); - b_temp.push(b.ls[3]); - b_temp.push(b.ls[4]); - b_temp.push(b.ls[5]); - - let mut p_temp: Vec = ~Vec::new(); - p_temp.push(p.ls[0]); - p_temp.push(p.ls[1]); - p_temp.push(p.ls[2]); - p_temp.push(p.ls[3]); - p_temp.push(p.ls[4]); - p_temp.push(p.ls[5]); - - // mul_temp and temp_fe_mont_mul give the same result - - // mul_temp(a_temp, b_temp, p_temp, n) - let temp_vec = temp_fe_mont_mul(a_temp, b_temp); - vec384 { - ls: [unpack_or_0(temp_vec.get(0)), - unpack_or_0(temp_vec.get(1)), - unpack_or_0(temp_vec.get(2)), - unpack_or_0(temp_vec.get(3)), - unpack_or_0(temp_vec.get(4)), - unpack_or_0(temp_vec.get(5)) - ] - } -} -// Same functionality as fe_to_mont -// TEMP NAIVE MULT IMPL -// Naive multiplication implementation following zkcrypto. -// Can be used as stand-in until we figure our how to make mul_mont_n work or the NCC mult with conversions before and after is feasible -pub fn mul_temp(a: Vec, b: Vec, p: Vec, n: u64) -> vec384 { - let a0 = unpack_or_0(a.get(0)); - let a1 = unpack_or_0(a.get(1)); - let a2 = unpack_or_0(a.get(2)); - let a3 = unpack_or_0(a.get(3)); - let a4 = unpack_or_0(a.get(4)); - let a5 = unpack_or_0(a.get(5)); - - let b0 = unpack_or_0(b.get(0)); - let b1 = unpack_or_0(b.get(1)); - let b2 = unpack_or_0(b.get(2)); - let b3 = unpack_or_0(b.get(3)); - let b4 = unpack_or_0(b.get(4)); - let b5 = unpack_or_0(b.get(5)); - - let(t0, carry) = mac(0, a0, b0, 0); - let(t1, carry) = mac(0, a0, b1, carry); - let(t2, carry) = mac(0, a0, b2, carry); - let(t3, carry) = mac(0, a0, b3, carry); - let(t4, carry) = mac(0, a0, b4, carry); - let(t5, t6) = mac(0, a0, b5, carry); - - let(t1, carry) = mac(t1, a1, b0, 0); - let(t2, carry) = mac(t2, a1, b1, carry); - let(t3, carry) = mac(t3, a1, b2, carry); - let(t4, carry) = mac(t4, a1, b3, carry); - let(t5, carry) = mac(t5, a1, b4, carry); - let(t6, t7) = mac(t6, a1, b5, carry); - - let(t2, carry) = mac(t2, a2, b0, 0); - let(t3, carry) = mac(t3, a2, b1, carry); - let(t4, carry) = mac(t4, a2, b2, carry); - let(t5, carry) = mac(t5, a2, b3, carry); - let(t6, carry) = mac(t6, a2, b4, carry); - let(t7, t8) = mac(t7, a2, b5, carry); - - let(t3, carry) = mac(t3, a3, b0, 0); - let(t4, carry) = mac(t4, a3, b1, carry); - let(t5, carry) = mac(t5, a3, b2, carry); - let(t6, carry) = mac(t6, a3, b3, carry); - let(t7, carry) = mac(t7, a3, b4, carry); - let(t8, t9) = mac(t8, a3, b5, carry); - - let(t4, carry) = mac(t4, a4, b0, 0); - let(t5, carry) = mac(t5, a4, b1, carry); - let(t6, carry) = mac(t6, a4, b2, carry); - let(t7, carry) = mac(t7, a4, b3, carry); - let(t8, carry) = mac(t8, a4, b4, carry); - let(t9, t10) = mac(t9, a4, b5, carry); - - let(t5, carry) = mac(t5, a5, b0, 0); - let(t6, carry) = mac(t6, a5, b1, carry); - let(t7, carry) = mac(t7, a5, b2, carry); - let(t8, carry) = mac(t8, a5, b3, carry); - let(t9, carry) = mac(t9, a5, b4, carry); - let(t10, t11) = mac(t10, a5, b5, carry); - - let res: [u64; - 12] = [t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11]; - montgomery_reduction(res) -} - -pub fn sub_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { - let mut limbx: u64 = 0; - let mut borrow: u64 = 0; - let mut i = 0; - let mut ret = ~Vec::new(); - - while i < n { - let(limb, temp_borrow): (u64, u64) = sbb(unpack_or_0(a.get(i)), unpack_or_0(b.get(i)), borrow); - ret.insert(i, limb); - borrow = temp_borrow; - i += 1; - } - - let mask: u64 = borrow * ~u64::max(); - let mut res = ~Vec::new(); - let mut carry: u64 = 0; - while i < n { - let(limb, temp_carry): (u64, u64) = adc(unpack_or_0(ret.get(i)), unpack_or_0(p.get(i)) & mask, carry); - res.insert(i, limb); - carry = temp_carry; - i += 1; - } - res -} - -// TODO -pub fn mul_mont_384(a: vec384, b: vec384, p: vec384, n0: u64) -> vec384 { - ZERO -} - -pub fn sqr_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { - //TODO - ZERO -} - -pub fn redc_mont_n(a: Vec, p: Vec, n0: u64, n: u64) -> Vec { - let mut j = 0; - let mut i = 1; - let mut b: Vec = a; - //let mut limbx: U128 = ~U128::from(0,0); - let mut tmp: Vec = ~Vec::new(); - while j < n { - let mx_temp: u64 = (~U128::from(0, n0) * ~U128::from(0, unpack_or_0(b.get(0)))).lower; - let mx: U128 = ~U128::from(0, mx_temp); - let mut limbx = mx * ~U128::from(0, unpack_or_0(p.get(0))) + ~U128::from(0, unpack_or_0(b.get(0))); - let mut hi: U128 = ~U128::from(0, limbx.upper); - i = 1; - while i < n { - let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); - let bi: U128 = ~U128::from(0, unpack_or_0(b.get(i))); - limbx = (mx * pi + hi) + bi; - tmp.insert(i - 1, limbx.lower); - hi = ~U128::from(0, limbx.upper); - i += 1; - } - tmp.insert(i - 1, hi.lower); - b = tmp; - j += 1; - } - - let mut tmp2: Vec = ~Vec::new(); - let mut carry = 0; - i = 0; - while i < n { - let ani: U128 = ~U128::from(0, unpack_or_0(a.get(n + i))); - let tmpi: U128 = ~U128::from(0, unpack_or_0(tmp.get(i))); - let carryi: U128 = ~U128::from(0, carry); - let limbx = ani + (tmpi + carryi); - tmp2.insert(i, limbx.lower); - carry = limbx.upper; - i += 1; - } - - let mut borrow = 0; - let mut res: Vec = ~Vec::new(); - i = 0; - while i < n { - let tmp2i: U128 = ~U128::from(0, unpack_or_0(tmp2.get(i))); - let pi: U128 = ~U128::from(0, unpack_or_0(p.get(i))); - let borrow_i: U128 = ~U128::from(0, borrow); - let pi_w_borrow = pi + borrow_i; - // Prevent underflow. When U256 arithmetic is available we can create sbb_256 - let(sub_res, b_res): (U128, u64) = if pi_w_borrow < tmp2i { - (tmp2i - pi_w_borrow, 0) - } else { - (~U128::max() - (pi_w_borrow - tmp2i - ~U128::from(0, 1)), 1) - }; - let mut limbx = sub_res; - //borrow = b_res; - borrow = limbx.upper & 0x1; - res.insert(i, limbx.lower); - i += 1; - } - //arithmetic overflow is happning - //let mut mask = carry - borrow; - //let mask: u64 = borrow * ~u64::max(); - let mut mask = if carry >= borrow { - carry - borrow - } else { - ~u64::max() - (borrow - carry - 1) - }; - let mut result: Vec = ~Vec::new(); - i = 0; - while i < n { - let result_i = (unpack_or_0(res.get(i)) & not(mask)) | (unpack_or_0(tmp2.get(i)) & mask); - result.insert(i, result_i); - i += 1; - } - - result -} - -pub fn redc_mont_384(a: vec768, p: vec384, n0: u64) -> vec384 { - //TODO - ZERO -} - -pub fn from_mont_384(a: vec384, p: vec384, n0: u64) -> vec384 { - //TODO - ZERO -} - -// Original impl: -// static inline bool_t is_zero(limb_t l) -// { return (~l & (l - 1)) >> (LIMB_T_BITS - 1); } -//TODO -pub fn is_zero(l: u64) -> u64 { - // (~l & (l-1)) >> 63 - 0 -} - -pub fn vec_is_zero(a: Vec, num: u64) -> u64 { - //TODO - 0 -} - -// TODO rewrite without if branch -// If x >= y: x-y, else max::U128 - (y-x) -pub fn subtract_wrap(x: U128, y: U128) -> U128 { - if y > x { - ~U128::max() - (y - x - U128 { - lower: 1, upper: 0 - }) - } else { - x - y - } -} - -// TODO rewrite without if branch -// If x >= y: x-y, else max::U64 - (y-x) -pub fn subtract_wrap_64(x: u64, y: u64) -> u64 { - if y > x { - ~u64::max() - (y - x - 1) - } else { - x - y - } -} - -/// Compute a - (b + borrow), returning the result and the new borrow (0 or 1). -pub fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - let borrow_128: U128 = ~U128::from(0, borrow); - - let res: U128 = subtract_wrap(a_128, b_128 + borrow_128); - (res.lower, res.upper >> 63) //(result, borrow) -} - -pub fn not(input: u64) -> u64 { - ~u64::max() - input -} - -// from https://github.com/zkcrypto/bls12_381 -// If a >= p, return a-p, else return a -pub fn subtract_p(a: vec384, p: vec384) -> vec384 { - let(r0, borrow) = sbb(a.ls[0], p.ls[0], 0); - let(r1, borrow) = sbb(a.ls[1], p.ls[1], borrow); - let(r2, borrow) = sbb(a.ls[2], p.ls[2], borrow); - let(r3, borrow) = sbb(a.ls[3], p.ls[3], borrow); - let(r4, borrow) = sbb(a.ls[4], p.ls[4], borrow); - let(r5, borrow) = sbb(a.ls[5], p.ls[5], borrow); - - // If underflow occurred on the final limb, borrow = 1, otherwise - // borrow = 0. We convert it into a mask. - let mut mask = borrow * ~u64::max(); - let r0 = (a.ls[0] & mask) | (r0 & not(mask)); - let r1 = (a.ls[1] & mask) | (r1 & not(mask)); - let r2 = (a.ls[2] & mask) | (r2 & not(mask)); - let r3 = (a.ls[3] & mask) | (r3 & not(mask)); - let r4 = (a.ls[4] & mask) | (r4 & not(mask)); - let r5 = (a.ls[5] & mask) | (r5 & not(mask)); - - vec384 { - ls: [r0, - r1, r2, r3, r4, r5] - } -} - -//TODO this function is also in edwards25519/src/field_element.sw (called add64). Where do we want to place these overlapping functions? -//returns sum with carry of a and b -pub fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - let carry_128: U128 = ~U128::from(0, carry); - - let sum: u64 = (a_128 + b_128 + carry_128).lower; - let carry_res = ((a & b) | ((a | b) & not(sum))) >> 63; - - (sum, carry_res) -} - -// from https://github.com/zkcrypto/bls12_381 -pub fn add_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { - let(d0, carry) = adc(a.ls[0], b.ls[0], 0); - let(d1, carry) = adc(a.ls[1], b.ls[1], carry); - let(d2, carry) = adc(a.ls[2], b.ls[2], carry); - let(d3, carry) = adc(a.ls[3], b.ls[3], carry); - let(d4, carry) = adc(a.ls[4], b.ls[4], carry); - let(d5, _) = adc(a.ls[5], b.ls[5], carry); - - //subtract p if needed - subtract_p(vec384 { - ls: [d0, d1, d2, d3, d4, d5] - }, - p) -} - -// from https://github.com/zkcrypto/bls12_381 -pub fn neg(a: vec384, p: vec384) -> vec384 { - let(d0, borrow) = sbb(p.ls[0], a.ls[0], 0); - let(d1, borrow) = sbb(p.ls[1], a.ls[1], borrow); - let(d2, borrow) = sbb(p.ls[2], a.ls[2], borrow); - let(d3, borrow) = sbb(p.ls[3], a.ls[3], borrow); - let(d4, borrow) = sbb(p.ls[4], a.ls[4], borrow); - let(d5, _) = sbb(p.ls[5], a.ls[5], borrow); - - // We need a mask that's 0 when a==p and 2^65-1 otherwise - // TODO improve this - let mut a_is_p = 0; - if (a.ls[0] | a.ls[1] | a.ls[2] | a.ls[3] | a.ls[4] | a.ls[5]) == 0 { - a_is_p = 1; //don't know is there's a native conversion - } else { - a_is_p = 0; - } - - let mask = subtract_wrap_64(a_is_p, 1); - - vec384 { - ls: [d0 & mask, - d1 & mask, d2 & mask, d3 & mask, d4 & mask, d5 & mask, ] - } -} - -pub fn sub_mod_384(a: vec384, b: vec384, p: vec384) -> vec384 { - add_mod_384(a, neg(b, p), p) -} - -//returns the result and new carry of a + b*c + carry -pub fn mac(a: u64, b: u64, c: u64, carry: u64) -> (u64, u64) { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - let c_128: U128 = ~U128::from(0, c); - let carry_128: U128 = ~U128::from(0, carry); - - let res: U128 = a_128 + (b_128 * c_128) + carry_128; - (res.lower, res.upper) -} - -//returns a*b mod(2^64) -pub fn multiply_wrap(a: u64, b: u64) -> u64 { - let a_128: U128 = ~U128::from(0, a); - let b_128: U128 = ~U128::from(0, b); - - (a_128 * b_128).lower -} - -pub fn mul_by_8_mod_384(a: vec384, p: vec384) -> vec384 { - lshift_mod_384(a, 3, p) -} - -pub fn mul_by_3_mod_384(a: vec384, p: vec384) -> vec384 { - let temp = add_mod_384(a, a, p); - add_mod_384(temp, a, p) -} - -pub fn cneg_mod_384(a: vec384, flag: u64, p: vec384) -> vec384 { - //TODO - ZERO -} - -pub fn lshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { - let mut i = 0; - let mut a_temp: vec384 = a; - while i < n { - a_temp = add_mod_384(a_temp, a_temp, p); - i += 1; - } - a_temp -} - -pub fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { - let mut limbx: U128 = ~U128::from(0, 0); - let mut mask = 0; - let mut carry = 0; - let mut limb = 0; - let mut next = 0; - let mut i = 0; - let mut m = n; - //let mut res_vec: (u64, u64, u64, u64, u64, u64) = (0,0,0,0,0,0); - let mut res_vec: Vec = ~Vec::new(); - while m > 0 { - - if a.ls[0] & 1 > 0 { - mask = 1<<64 - 1; - } else { - mask = 0; - } - //mask = 0 - (a.ls[0] & 1); - //launder(mask)?? - carry = 0; - i = 0; - while i < 6 { - limbx = ~U128::from(0,a.ls[i]) + (~U128::from(0,(p.ls[i] & mask)) + ~U128::from(0,carry)); - //res_vec.i = limbx; - res_vec.insert(i, limbx.lower); - carry = limbx.upper; - i += 1; - } - //next = res_vec.0; - next = unpack_or_0(res_vec.get(0)); - i = 0; - while i < 5 { - limb = next >> 1; - //next = res_vec.(i+1); - next = unpack_or_0(res_vec.get(i+1)); - //res_vec.i = limb | next << 31; - res_vec.remove(i); - res_vec.insert(i,limb | next << 31); - i += 1; - } - //res_vec.i = next >> 1 | carry << 31; - res_vec.remove(i); - res_vec.insert(i,next >> 1 | carry << 31); - m -= 1; - } - vec384 { - //ls: [res_vec.0, res_vec.1, res_vec.2, res_vec.3, res_vec.4, res_vec.5], - ls: [unpack_or_0(res_vec.get(0)), unpack_or_0(res_vec.get(1)), unpack_or_0(res_vec.get(2)), unpack_or_0(res_vec.get(3)), unpack_or_0(res_vec.get(4)), unpack_or_0(res_vec.get(5))], - } - // ZERO -} - -pub fn div_by_2_mod_384(a: vec384, p: vec384) -> vec384 { - //TODO - ZERO -} - -pub fn mul_by_8_mod_384x(a: vec384x, p: vec384) -> vec384x { - //TODO - ZERO_X -} - -pub fn mul_by_3_mod_384x(a: vec384x, p: vec384) -> vec384x { - //TODO - ZERO_X -} - -fn to_vec(v: vec384) -> Vec { - let mut res = ~Vec::new(); - let mut i = 0; - while i < 6 { - res.push(v.ls[i]); - i += 1; - } - res -} - -// TODO -pub fn mul_mont_384x(a: vec384x, b: vec384x, p: vec384, n0: u64) -> vec384x { - let a0_vec = to_vec(a.r); - let a1_vec = to_vec(a.i); - let b0_vec = to_vec(b.r); - let b1_vec = to_vec(b.i); - let p_vec = to_vec(p); - - let mut aa = add_mod_n(a0_vec, a1_vec, p_vec, NLIMBS_384); - let mut bb = add_mod_n(b0_vec, b1_vec, p_vec, NLIMBS_384); - // let bb_temp = mul_mont_n(bb, aa, p_vec, n0, NLIMBS_384); - // aa = mul_mont_n(a0_vec, b0_vec, p_vec, n0, NLIMBS_384); - - ZERO_X -} - -pub fn sqr_mont_384x(a: vec384x, p: vec384, n0: u64) -> vec384x { - //TODO. Has a non-assembly impl in blst in src/vect.c - ZERO_X -} diff --git a/old-tests-bls/.gitignore b/old-tests-bls/.gitignore deleted file mode 100644 index 77d3844..0000000 --- a/old-tests-bls/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -out -target diff --git a/old-tests-bls/Cargo.toml b/old-tests-bls/Cargo.toml deleted file mode 100644 index 1ea4990..0000000 --- a/old-tests-bls/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[project] -name = "tests-bls" -version = "0.1.0" -authors = ["Hashcloak"] -edition = "2021" -license = "Apache-2.0" - -[dependencies] -fuels = "0.19" -fuels-abigen-macro = "0.16.1" -tokio = { version = "1.12", features = ["rt", "macros"] } - -[[test]] -harness = true -name = "integration_tests" -path = "tests/harness.rs" diff --git a/old-tests-bls/Forc.toml b/old-tests-bls/Forc.toml deleted file mode 100644 index af7d324..0000000 --- a/old-tests-bls/Forc.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -authors = ["Hashcloak"] -entry = "main.sw" -license = "Apache-2.0" -name = "tests-bls" - -[dependencies] -bls = { path = "../bls" } diff --git a/old-tests-bls/src/main.sw b/old-tests-bls/src/main.sw deleted file mode 100644 index bb11425..0000000 --- a/old-tests-bls/src/main.sw +++ /dev/null @@ -1,185 +0,0 @@ -contract; - -use bls::{fields::*, vect::*}; -use std::u128::*; - -abi BlsContract { - //Small helper functions - #[storage()]fn not(input: u64) -> u64; - #[storage()]fn subtract_wrap(x: U128, y: U128) -> U128; - #[storage()]fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64); - #[storage()]fn adc(a: u64, b: u64, carry: u64) -> (u64, u64); - #[storage()]fn subtract_p(a: vec384, p: vec384) -> vec384; - #[storage()]fn neg(a: vec384, p: vec384) -> vec384; - - // Vec can't be used yet here WIP in Sway https://github.com/FuelLabs/fuels-rs/issues/353 - // #[storage()]fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec; - - //Fp - #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn mul_by_3_fp(a: vec384) -> vec384; - #[storage()]fn mul_by_8_fp(a: vec384) -> vec384; - #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384; - #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384; - #[storage()]fn div_by_2_fp(a: vec384) -> vec384; - #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384; - #[storage()]fn sqr_fp(a: vec384) -> vec384; - #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384; - #[storage()]fn from_fp(a: vec384) -> vec384; - // #[storage()]fn redc_fp(a: vec384) -> vec384; - - // Temp mul functions - #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384; - #[storage()]fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384; - #[storage()]fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384; - - - // // Fp2 - #[storage()]fn add_fp2(a: vec384x, b: vec384x) -> vec384x; - #[storage()]fn sub_fp2(a: vec384x, b: vec384x) -> vec384x; - // #[storage()]fn mul_by_3_fp2(a: vec384) -> vec384; - // #[storage()]fn mul_by_8_fp2(a: vec384) -> vec384; - // #[storage()]fn lshift_fp2(a: vec384, count: u64) -> vec384; - // #[storage()]fn rshift_fp2(a: vec384, count: u64) -> vec384; - // #[storage()]fn div_by_2_f2(a: vec384) -> vec384; - // #[storage()]fn mul_fp2(a: vec384, b: vec384) -> vec384; - // #[storage()]fn sqr_fp2(a: vec384) -> vec384; - // #[storage()]fn cneg_fp2(a: vec384, flag: u64) -> vec384; -} - -impl BlsContract for Contract { - - //Small helper functions - #[storage()]fn not(input: u64) -> u64 { - not(input) - } - - #[storage()]fn subtract_wrap(x: U128, y: U128) -> U128 { - subtract_wrap(x, y) - } - - #[storage()]fn sbb(a: u64, b: u64, borrow: u64) -> (u64, u64) { - sbb(a, b, borrow) - } - - #[storage()]fn adc(a: u64, b: u64, carry: u64) -> (u64, u64) { - adc(a, b, carry) - } - - #[storage()]fn subtract_p(a: vec384, p: vec384) -> vec384 { - subtract_p(a, p) - } - - #[storage()]fn neg(a: vec384, p: vec384) -> vec384 { - neg(a, p) - } - -// Vec can't be used yet here WIP in Sway https://github.com/FuelLabs/fuels-rs/issues/353 - // #[storage()]fn add_mod_n(a: Vec, b: Vec, p: Vec, n: u64) -> Vec { - // add_mod_n(a, b, p, n) - // } - - // Fp - #[storage()]fn add_fp(a: vec384, b: vec384) -> vec384 { - add_fp(a, b) - } - - #[storage()]fn sub_fp(a: vec384, b: vec384) -> vec384 { - sub_fp(a, b) - } - - #[storage()]fn mul_by_3_fp(a: vec384) -> vec384 { - mul_by_3_fp(a) - } - - #[storage()]fn mul_by_8_fp(a: vec384) -> vec384 { - mul_by_8_fp(a) - } - - #[storage()]fn lshift_fp(a: vec384, count: u64) -> vec384 { - lshift_fp(a, count) - } - - #[storage()]fn rshift_fp(a: vec384, count: u64) -> vec384 { - rshift_fp(a, count) - } - - #[storage()]fn div_by_2_fp(a: vec384) -> vec384 { - div_by_2_fp(a) - } - - #[storage()]fn mul_fp(a: vec384, b: vec384) -> vec384 { - mul_fp(a, b) - } - - #[storage()]fn sqr_fp(a: vec384) -> vec384 { - sqr_fp(a) - } - - #[storage()]fn cneg_fp(a: vec384, flag: u64) -> vec384 { - cneg_fp(a, flag) - } - - #[storage()]fn from_fp(a: vec384) -> vec384 { - from_fp(a) - } - - // Temp mul functions - #[storage()]fn temp_mul_mont_n(a: vec384, b: vec384) -> vec384 { - temp_mul_mont_n(a, b) - } - - #[storage()]fn rshift_mod_384(a: vec384, n: u64, p: vec384) -> vec384 { - rshift_mod_384(a, n, p) - } - - #[storage()]fn mul_temp_wrapper(a: vec384, b:vec384, p: vec384, n: u64) -> vec384 { - mul_temp_wrapper(a, b, p, n) - } - - // #[storage()]fn redc_fp(a: vec384) -> vec384 { - // redc_fp(a) - // } - - // // Fp2 - #[storage()]fn add_fp2(a: vec384x, b: vec384x) -> vec384x { - add_fp2(a, b) - } - - #[storage()]fn sub_fp2(a: vec384x, b: vec384x) -> vec384x { - sub_fp2(a, b) - } - - // #[storage()]fn mul_by_3_fp2(a: vec384) -> vec384 { - // mul_by_3_fp2(a) - // } - - // #[storage()]fn mul_by_8_fp2(a: vec384) -> vec384 { - // mul_by_8_fp2(a) - // } - - // #[storage()]fn lshift_fp2(a: vec384, count: u64) -> vec384 { - // lshift_fp2(a, count) - // } - - // #[storage()]fn rshift_fp2(a: vec384, count: u64) -> vec384 { - // rshift_fp2(a, count) - // } - - // #[storage()]fn div_by_2_fp2(a: vec384) -> vec384 { - // div_by_2_fp2(a) - // } - - // #[storage()]fn mul_fp2(a: vec384, b: vec384) -> vec384 { - // mul_fp2(a, b) - // } - - // #[storage()]fn sqr_fp2(a: vec384) -> vec384 { - // sqr_fp2(a) - // } - - // #[storage()]fn cneg_fp2(a: vec384, flag: u64) -> vec384 { - // cneg_fp2(a, flag) - // } -} \ No newline at end of file diff --git a/old-tests-bls/tests/harness.rs b/old-tests-bls/tests/harness.rs deleted file mode 100644 index b28eeeb..0000000 --- a/old-tests-bls/tests/harness.rs +++ /dev/null @@ -1,9 +0,0 @@ -// mod tests_add_fp; -// mod tests_mul_by_x_fp; -// mod tests_sub_fp; -// mod tests_l_shift; -// mod tests_rshift_mod_384; -// mod tests_temp_mul; -// mod tests_vect_subfunctions; -// mod tests_vect_fp2; -mod tests_temp_mul_mont_n; diff --git a/old-tests-bls/tests/tests_add_fp/mod.rs b/old-tests-bls/tests/tests_add_fp/mod.rs deleted file mode 100644 index db40a88..0000000 --- a/old-tests-bls/tests/tests_add_fp/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -use fuels::{ - prelude::*, - tx::{ConsensusParameters, ContractId}, -}; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, Bech32ContractId) { - // Create the wallet. - let mut wallet = LocalWallet::new_random(None); - let num_assets = 1; - let coins_per_asset = 100; - let amount_per_coin = 100000; - - let (coins, asset_ids) = setup_multiple_assets_coins( - wallet.address(), - num_assets, - coins_per_asset, - amount_per_coin, - ); - - // configure the gas limit - let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(1000000000); - - // Here's the important part. This will be running a `fuel-core` that will live through this test. - // The configured coins are the same as before, I'm just passing them to it. - let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; - - // Important. Make sure the random wallet you created above uses this provider you created just now. - let provider = Provider::new(client); - wallet.set_provider(provider.clone()); - - let id = Contract::deploy( - "./out/debug/tests-bls.bin", - &wallet, - TxParameters::default(), - StorageConfiguration::default(), // <--- new stuff from 0.18 - ) - .await - .unwrap(); - let instance = BlsContractBuilder::new(id.to_string(), wallet).build(); // <-- notice the `.build()` coming from `0.18` here - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_add_zero_to_zero() { - let ZERO_1: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let ZERO_2: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let ZERO_3: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(ZERO_1, ZERO_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, ZERO_3)); -} - -#[tokio::test] -async fn test_add_zero_to_random() { - let random = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let zero = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let expected_res = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(random, zero) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_add_random_to_small() { - let small = vec384{ - ls: [1, 2, 3, 4, 5, 6].to_vec() - }; - let random = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let expected_res = vec384{ - ls: [4478030004447473543, 2814704111667093004, 15884408734010272161, 17001047363111187582, 932823543034528552, 1051481384684610851].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(small, random) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_add_larger_than_p() { - let a = vec384{ - ls: [13402431016077863508,2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() - }; - let b = vec384{ - ls: [100,0,0,0,0,0].to_vec() - }; - let expected_res = vec384{ - ls: [13, 0,0,0,0,0].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(a, b) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_add_2_randoms() { - let random_1 = vec384{ - ls: [4510245898505151773,8849327944066866226, 11451510199254766964, 782624411996506985, 9666712539018543006, 17492304704872943].to_vec() - }; - let random_2 = vec384{ - ls: [8877477209635348035,16708328088811667500, 14014037299927741552, 1795070958963053268, 10606788931721547929, 841903545056265961].to_vec() - }; - let expected_res = vec384{ - ls: [13387723108140499808, 7110911959168982110, 7018803425472956901, 2577695370959560254, 1826757397030539319, 859395849761138905].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp(random_1, random_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} diff --git a/old-tests-bls/tests/tests_l_shift/mod.rs b/old-tests-bls/tests/tests_l_shift/mod.rs deleted file mode 100644 index 928b4b2..0000000 --- a/old-tests-bls/tests/tests_l_shift/mod.rs +++ /dev/null @@ -1,56 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_1_lshift_p() { - let r = vec384 { - ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() - }; - let expected_res = vec384{ - ls: [7671746853223046722, 17102462128446408757, 1779981351125750781, 7096037212622990972, 10741786888947010385, 1199945595455823374].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.lshift_fp(r,1) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_250_lshift_p() { - let a = vec384 { - ls: [13749239540608708580, 16959468157877110068, 1567469580365175571, 14160078721051372203, 9626163454156242266, 1779547015017246937].to_vec() - }; - let expected_res = vec384{ - ls: [13113011510218319406, 16706544215516829647, 7984223107370075095, 1162337285386263785, 307447685117845313, 411984953494678179].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.lshift_fp(a, 250) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_mul_by_x_fp/mod.rs b/old-tests-bls/tests/tests_mul_by_x_fp/mod.rs deleted file mode 100644 index c3fb249..0000000 --- a/old-tests-bls/tests/tests_mul_by_x_fp/mod.rs +++ /dev/null @@ -1,96 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_mul_by_3_fp_zero() { - let zero: vec384 = vec384 { - ls:[0,0,0,0,0,0].to_vec() - }; - - let expected_res = vec384{ - ls:[0,0,0,0,0,0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_by_3_fp(zero) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_mul_by_3_fp() { - let a = vec384 { - ls: [5598198260030196614, 9227139175563025534, 12721729458998794199, 15322498199590564519, 14360971206699872851, 1550139647308650475].to_vec() - }; - - let expected_res = vec384{ - ls: [8436476821644414268, 4814390429945107835, 4847095156158667582, 13042074604232716920, 13811961989448662348, 902821706630871694].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_by_3_fp(a) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_mul_by_8_fp_zero() { - let zero: vec384 = vec384 { - ls:[0,0,0,0,0,0].to_vec() - }; - - let expected_res = vec384{ - ls:[0,0,0,0,0,0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_by_8_fp(zero) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - - -#[tokio::test] -async fn tests_mul_by_8_fp() { - let a = vec384 { - ls: [4748578380656466952, 10419428663092908236, 18363049814497995794, 10615108747081361673, 10405771956295193853, 1009856344616347211].to_vec() - }; - let expected_res = vec384{ - ls: [2825647054649832852, 727886963836225123, 6481235779470329860, 623285913863388498, 6257528315350086799, 583656286340618227].to_vec() - }; - - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_by_8_fp(a) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_rshift_mod_384/mod.rs b/old-tests-bls/tests/tests_rshift_mod_384/mod.rs deleted file mode 100644 index 02eb77b..0000000 --- a/old-tests-bls/tests/tests_rshift_mod_384/mod.rs +++ /dev/null @@ -1,42 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(100_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_1_rshift_mod_384() { - let r_vec: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let p: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let expected_res = vec384{ - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.rshift_mod_384(r_vec,1, p) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_small_functions/mod.rs b/old-tests-bls/tests/tests_small_functions/mod.rs deleted file mode 100644 index 31675b2..0000000 --- a/old-tests-bls/tests/tests_small_functions/mod.rs +++ /dev/null @@ -1,219 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_not() { - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.not(18417751708719972248) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res == 28992364989579367); -} - -#[tokio::test] -async fn tests_subtract_wrap() { - let (_instance, _id) = get_contract_instance().await; - - let res1 = _instance.subtract_wrap(U128{upper: 0, lower: 100}, U128{upper: 0, lower: 80}) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res1.lower == 20); - assert!(res1.upper == 0); - - let res2 = _instance.subtract_wrap(U128{upper: 0, lower: 100}, U128{upper: 0, lower: 230}) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res2.lower == 18446744073709551486); - assert!(res2.upper == 18446744073709551615); -} - -#[tokio::test] -async fn tests_sbb() { - let (_instance, _id) = get_contract_instance().await; - - let res1 = _instance.sbb(0,0,0) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - let res2 = _instance.sbb(0,1,0) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - let res3 = _instance.sbb(0,1,1) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - let a = 435983458; - let res4 = _instance.sbb(a,0,1) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - assert!(res1.0 == 0); - assert!(res1.1 == 0); - - assert!(res2.0 == u64::MAX); - assert!(res2.1 == 1); - - assert!(res3.0 == u64::MAX - 1); - assert!(res3.1 == 1); - - assert!(res4.0 == a-1); - assert!(res4.1 == 0); -} - -#[tokio::test] -async fn test_adc_random() { - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.adc(9837491998535547791, 10009796384580774444, 0) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res.0 == 1400544309406770619); - assert!(res.1 == 1); -} - -#[tokio::test] -async fn test_adc_random_with_carry() { - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.adc(9837491998535547791, 10009796384580774444, 1) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res.0 == 1400544309406770620); - assert!(res.1 == 1); -} - -#[tokio::test] -async fn test_subtract_p_smaller() { - let BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - let a_smaller_than_p = vec384 { - ls: [13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() - }; - let expected_res = vec384 { - ls: [13402431016077863508, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() - }; - - let res = _instance.subtract_p(a_smaller_than_p, BLS12_381_P) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_subtract_p_larger() { - let BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - let a_larger_than_p = vec384 { // p+ 200 - ls: [13402431016077863795, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() - }; - let expected_res = vec384 { - ls: [200, 0, 0, 0, 0, 0].to_vec() - }; - - let res = _instance.subtract_p(a_larger_than_p, BLS12_381_P) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_neg_p() { - let BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - let p: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let zero: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - - let res = _instance.neg(p, BLS12_381_P) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - assert!(res_equals(res, zero)); -} - -#[tokio::test] -async fn test_neg_1() { - let BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - let one: vec384 = vec384 { - ls: [1, 0, 0, 0, 0, 0].to_vec() - }; - let expected_res = vec384 { // p-1 - ls: [13402431016077863594, 2210141511517208575, 7435674573564081700, 7239337960414712511, 5412103778470702295, 1873798617647539866].to_vec() - }; - - let res = _instance.neg(one, BLS12_381_P) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_neg_random() { - let BLS12_381_P: vec384 = vec384 { - ls: [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - let r = vec384 { - ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() - }; - let expected_res = vec384 { // p-r - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179].to_vec() - }; - - let res = _instance.neg(r, BLS12_381_P) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - - assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_sub_fp/mod.rs b/old-tests-bls/tests/tests_sub_fp/mod.rs deleted file mode 100644 index 7569ac2..0000000 --- a/old-tests-bls/tests/tests_sub_fp/mod.rs +++ /dev/null @@ -1,124 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_sub_zero_from_zero() { - let zero_1: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let zero_2: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let zero_3: vec384 = vec384 { - ls: [0, 0, 0, 0, 0, 0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.sub_fp(zero_1, zero_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, zero_3)); -} - -#[tokio::test] -async fn test_sub_zero_from_random() { - let random = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let expected_res = vec384{ - ls: [0x3e2528903ca1ef86, 0x270fd67a03bf9e0a, 0xdc70c19599cb699e, 0xebefda8057d5747a, 0xcf20e11f0b1c323, 0xe979cbf960fe51d].to_vec() - }; - let zero_4: vec384 = vec384 { - ls:[0,0,0,0,0,0].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.sub_fp(random, zero_4) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_sub_random_from_zero() { - let r = vec384 { - ls: [13059245463466299169, - 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() - }; - let zero_4: vec384 = vec384 { - ls:[0,0,0,0,0,0].to_vec() - }; - let expected_res = vec384{ - ls: [343185552611564426, 2882282484148780005, 6545683898001206309, 12914691390957992833, 41210333997197102, 1273825819919628179].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.sub_fp(zero_4,r) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_sub_random_from_small() { - let small = vec384 { - ls: [1, 2, 3, 4, 5, 6].to_vec() - }; - let r = vec384 { - ls: [13059245463466299169, 17774603101077980186, 889990675562875390, 12771390643166271294, 5370893444473505192, 599972797727911687].to_vec() - }; - let expected_res = vec384{ - ls: [343185552611564427, 2882282484148780007, 6545683898001206312, 12914691390957992837, 41210333997197107, 1273825819919628185].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.sub_fp(small, r) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} - -#[tokio::test] -async fn test_sub_2_random() { - let a = vec384 { - ls: [10587454305359941416, 4615625447881587853, 9368308553698906485, 9494054596162055604, 377309137954328098, 766262085408033194].to_vec() - }; - - let b = vec384 { - ls: [13403040667047958534, 405585388298286396, 7295341050629342949, 1749456428444609784, 1856600841951774635, 296809876162753174].to_vec() - }; - let expected_res = vec384{ - ls: [15631157712021534498, 4210040059583301456, 2072967503069563536, 7744598167717445820, 16967452369712105079, 469452209245280019].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.sub_fp(a, b) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_temp_mul/mod.rs b/old-tests-bls/tests/tests_temp_mul/mod.rs deleted file mode 100644 index 9ef87ff..0000000 --- a/old-tests-bls/tests/tests_temp_mul/mod.rs +++ /dev/null @@ -1,101 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -#[tokio::test] -async fn test_temp_mul_random_by_random() { - let p_vec: vec384 = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a].to_vec() - }; - let r1_vec: vec384 = vec384 { - ls: [6071868568151433008, - 12105094901188801210, - 2389211775905699303, - 7838417195104481535, - 5826366508043997497, - 13436617433956842131].to_vec() - }; - let r2_vec: vec384 = vec384 { - ls: [16964885827015180015, - 12035734743809705289, - 10517060043363161601, - 1119606639881808286, - 2211903887497377980, - 395875676649998273].to_vec() - }; - // this is the expected result according to the zkcrypto impl. This is multiplication on montgomery forms - let expected_res: vec384 = vec384 { - ls: [16484308011771146774, 12795119582497094196, 7495239071060242083, - 6228288009955243706, 334445847756758381, 1343304342180463133].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_temp_wrapper(r1_vec, r2_vec, p_vec, 6) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); - - //zkcrypto impl gives this res as well. So it's not a "standard" mul - //[16484308011771146774, 12795119582497094196, 7495239071060242083, - // 6228288009955243706, 334445847756758381, 1343304342180463133] -} - -#[tokio::test] -async fn test_mul_temp_by_2() { - let p_vec: vec384 = vec384 { - ls: [0xb9feffffffffaaab, - 0x1eabfffeb153ffff, - 0x6730d2a0f6b0f624, - 0x64774b84f38512bf, - 0x4b1ba7b6434bacd7, - 0x1a0111ea397fe69a].to_vec() - }; - - //2367106380816923637832389518823092703674202766714323478820851269126356623723913304989534316437425836090100832620729 - let r1_vec: vec384 = vec384 { - ls: [9172416622910853305, 14987574562624449790, - 13213778230238218784, 15872153713916140599, - 9712154313263354644, 1108202597211161767].to_vec() - }; - let vec_2: vec384 = vec384 { - ls: [2,0,0,0,0,0].to_vec() - }; - - // this is the expected result according to the zkcrypto impl. This is multiplication on montgomery forms - let expected_res: vec384 = vec384 { - ls: [11360606136736300744, 10320420748134520786, 17912563010296520217, - 16145629554006184624, 12933232110729028586, 1518885514198738558].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.mul_temp_wrapper(r1_vec, vec_2, p_vec, 6) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_temp_mul_mont_n/mod.rs b/old-tests-bls/tests/tests_temp_mul_mont_n/mod.rs deleted file mode 100644 index 46df062..0000000 --- a/old-tests-bls/tests/tests_temp_mul_mont_n/mod.rs +++ /dev/null @@ -1,101 +0,0 @@ -use fuels::{ - prelude::*, - tx::{ConsensusParameters, ContractId}, -}; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, Bech32ContractId) { - // Create the wallet. - let mut wallet = LocalWallet::new_random(None); - let num_assets = 1; - let coins_per_asset = 100; - let amount_per_coin = 100000; - - let (coins, asset_ids) = setup_multiple_assets_coins( - wallet.address(), - num_assets, - coins_per_asset, - amount_per_coin, - ); - - // configure the gas limit - let consensus_parameters_config = ConsensusParameters::DEFAULT.with_max_gas_per_tx(10_000_000_000_000); - - // Here's the important part. This will be running a `fuel-core` that will live through this test. - // The configured coins are the same as before, I'm just passing them to it. - let (client, addr) = setup_test_client(coins, None, Some(consensus_parameters_config)).await; - - // Important. Make sure the random wallet you created above uses this provider you created just now. - let provider = Provider::new(client); - wallet.set_provider(provider.clone()); - - let id = Contract::deploy( - "./out/debug/tests-bls.bin", - &wallet, - TxParameters::default(), - StorageConfiguration::default(), // <--- new stuff from 0.18 - ) - .await - .unwrap(); - let instance = BlsContractBuilder::new(id.to_string(), wallet).build(); // <-- notice the `.build()` coming from `0.18` here - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -//runs with gas limit 10_000_000_000_000 -// I would think this does a "normal" mult... but it doesnt. However, our zkcrypto functions are being tested against -// zkcrypto tests so thats OK. With this test at least we know how to increase the gas limit. And that a very high limit is probably needed. -#[tokio::test] -async fn test_temp_mul_random_by_random() { -// 15893342109957185315274996980159955840696869464618597139081654135225976620298280402004730099734930472282685911264653 -// [7601317525063134605, 14737835108041207235, 7856501253924799053, 9728524752340033442, 8018744563895365642, 7440748395322036726] - - - //let p_vec: [u64;6] = [0xb9feffffffffaaab, 0x1eabfffeb153ffff, 0x6730d2a0f6b0f624, 0x64774b84f38512bf, 0x4b1ba7b6434bacd7, 0x1a0111ea397fe69a]; - let r1_vec = vec384 { - ls: [7601317525063134605, 14737835108041207235, 7856501253924799053, 9728524752340033442, 8018744563895365642, 7440748395322036726].to_vec() - }; - -// 6426056301875987760035045131419826427959545715777668602170085103660258490882518289245959835486066380634045485171465 -// [2100109755352105737, 8370746840931066636, 11596494770511871063, 3039720716978434317, 16449625404618362957, 3008471584241360315] - let r2_vec = vec384{ - ls: [2100109755352105737, 8370746840931066636, 11596494770511871063, 3039720716978434317, 16449625404618362957, 3008471584241360315].to_vec() - }; - - //662295453570983325530111016671619871152537908715293912221215151084869461019373230933077596861385628632414151952313 - //[8398368441850316729, 11909455072033861112, 10407834670867800778, 5873847235982413757, 1304857104357117827, 310065296480341730] - let expected_res = vec384 { - ls: [8398368441850316729, 11909455072033861112, 10407834670867800778, 5873847235982413757, 1304857104357117827, 310065296480341730].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.temp_mul_mont_n(r1_vec, r2_vec) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - println!("{}", res.ls[0]); - println!("{}", res.ls[1]); - println!("{}", res.ls[2]); - println!("{}", res.ls[2]); - println!("{}", res.ls[4]); - println!("{}", res.ls[5]); - /*-> different outcome -9333873115146394089 -4782551559207793765 -10050393911427975672 -10050393911427975672 -1218813032832674028 -1486933856237831752 - */ - // assert!(res_equals(res, expected_res)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_vect_fp2/mod.rs b/old-tests-bls/tests/tests_vect_fp2/mod.rs deleted file mode 100644 index 3714e00..0000000 --- a/old-tests-bls/tests/tests_vect_fp2/mod.rs +++ /dev/null @@ -1,104 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(100_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -fn get_a1() -> vec384x { - let r_1 = vec384 { - ls: [14795151457364307190, 6622185142386025417, - 17709159039044576520, 1719961663313476946, - 4148264363906786574, 980769587779429096].to_vec() - }; - //1854013830343626212433083622699305309002946726548085159596712876339371488002438401231777242990713512722976854546804 - let i_1 = vec384 { - ls: [8306319196692453748, 10328470218072223240, - 3451314819045096133, 17542580433704256157, - 9684937745078445131, 867989271079206780].to_vec() - }; - let a_1 = vec384x { - r: r_1, - i: i_1, - }; - a_1 -} - - -fn get_a2() -> vec384x { - let r2_vec = vec384{ - ls: [16448140995118783999, 9520526689676604696, - 7916863578364318753, 8691145487628551970, - 16531338352426028355, 1893914179705411585].to_vec() - }; - - let i2_vec = vec384{ - ls: [1139524850979729662, 10226030227531743340, - 16078343496594203218, 16066350528929326807, - 17232578759082026236, 1990003151713484304].to_vec() - }; - - let a_2 = vec384x { - r: r2_vec, - i: i2_vec, - }; - a_2 -} - -#[tokio::test] -async fn tests_add_fp2() { - let a_1 = get_a1(); - let a_2 = get_a2(); - - let expected_r = vec384 { - ls: [17840861436405227594, 13932570320545421538, 18190348043844813573, 3171769190527316405, 15267498937862112634, 1000885149837300815].to_vec() - }; - let expected_i = vec384 { - ls: [14490157105303871431, 18344358934086758004, 12093983742075217651, 7922848928509318837, 3058668651980217457, 984193805145151219].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.add_fp2(a_1, a_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res.r, expected_r)); - assert!(res_equals(res.i, expected_i)); -} - -#[tokio::test] -async fn tests_sub_fp2() { - let a_1 = get_a1(); - let a_2 = get_a2(); - - let expected_r = vec384 { - ls: [11749441478323386786, 17758544037936180912, 17227970034244339466, 268154136099637487, 11475773863661012130, 960654025721557376].to_vec() - }; - let expected_i = vec384 { - ls: [2122481288081036065, 2312581502057688476, 13255389969724526231, 8715567865189641860, 16311206838176672806, 751784737013262341].to_vec() - }; - let (_instance, _id) = get_contract_instance().await; - - let res = _instance.sub_fp2(a_1, a_2) - .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) - .call_params(CallParameters::new(None, None, Some(100_000_000))) - .call().await.unwrap().value; - assert!(res_equals(res.r, expected_r)); - assert!(res_equals(res.i, expected_i)); -} \ No newline at end of file diff --git a/old-tests-bls/tests/tests_vect_subfunctions/mod.rs b/old-tests-bls/tests/tests_vect_subfunctions/mod.rs deleted file mode 100644 index 2acb2f9..0000000 --- a/old-tests-bls/tests/tests_vect_subfunctions/mod.rs +++ /dev/null @@ -1,70 +0,0 @@ -use fuels::{prelude::*, tx::ContractId}; -use fuels_abigen_macro::abigen; - -abigen!(BlsContract, "out/debug/tests-bls-abi.json"); - -async fn get_contract_instance() -> (BlsContract, ContractId) { - let mut wallets = launch_provider_and_get_wallets(WalletsConfig::new_single(Some(1), Some(1_000_000))).await; - let wallet = wallets.pop().unwrap(); - let id = Contract::deploy("./out/debug/tests-bls.bin", &wallet, TxParameters::default()).await.unwrap(); - let instance = BlsContract::new(id.to_string(), wallet); - (instance, id) -} - -pub fn res_equals(res: vec384, should_be: vec384) -> bool { - assert!(res.ls[0] == should_be.ls[0]); - assert!(res.ls[1] == should_be.ls[1]); - assert!(res.ls[2] == should_be.ls[2]); - assert!(res.ls[3] == should_be.ls[3]); - assert!(res.ls[4] == should_be.ls[4]); - assert!(res.ls[5] == should_be.ls[5]); - true -} - -fn get_test_vectors() -> (Vec, Vec) { - let mut zero_vec = Vec::new(); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - zero_vec.push(0); - - let mut p_vec = Vec::new(); - p_vec.push(0xb9feffffffffaaab); - p_vec.push(0x1eabfffeb153ffff); - p_vec.push(0x6730d2a0f6b0f624); - p_vec.push(0x64774b84f38512bf); - p_vec.push(0x4b1ba7b6434bacd7); - p_vec.push(0x1a0111ea397fe69a); - - (zero_vec, p_vec) -} - -// TODO This can't run yet, because in the contract we can't use Vec -// #[tokio::test] -// async fn test_add_zero_to_zero_addn() { -// let (_instance, _id) = get_contract_instance().await; -// let mut zero_vec = Vec::new(); -// zero_vec.push(0); -// zero_vec.push(0); -// zero_vec.push(0); -// zero_vec.push(0); -// zero_vec.push(0); -// zero_vec.push(0); -// let(zero_vec1, p_vec) = get_test_vectors(); - -// let mut expected_res = Vec::new(); -// expected_res.push(0); -// expected_res.push(0); -// expected_res.push(0); -// expected_res.push(0); -// expected_res.push(0); -// expected_res.push(0); - -// let res = _instance.add_mod_n(zero_vec, zero_vec1, p_vec, 6) -// .tx_params(TxParameters::new(None, Some(100_000_000), None, None)) -// .call_params(CallParameters::new(None, None, Some(100_000_000))) -// .call().await.unwrap().value; -// assert!(res_equals(res, expected_res)); -// } \ No newline at end of file