From db960772abfead018e4f6da55ae259c6b3d574ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bene=C5=A1?= Date: Wed, 10 Jul 2024 15:50:14 +0200 Subject: [PATCH] feat: typing return values of embedded_curve_ops (#7413) --- .../aztec/src/keys/point_to_symmetric_key.nr | 4 ++-- .../contracts/avm_test_contract/src/main.nr | 2 +- .../src/types/token_note.nr | 19 +++--------------- .../noir_stdlib/src/embedded_curve_ops.nr | 20 +++++++++---------- noir/noir-repo/noir_stdlib/src/hash/mod.nr | 5 ++--- .../embedded_curve_ops/src/main.nr | 6 +++--- .../regression_5045/src/main.nr | 2 +- .../execution_success/schnorr/src/main.nr | 8 ++++---- .../simple_shield/src/main.nr | 7 +++---- .../embedded_curve_ops/src/main.nr | 10 +++++----- 10 files changed, 34 insertions(+), 49 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr index 6515b2bca38..caa3173443f 100644 --- a/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr +++ b/noir-projects/aztec-nr/aztec/src/keys/point_to_symmetric_key.nr @@ -7,9 +7,9 @@ use std::{hash::sha256, embedded_curve_ops::multi_scalar_mul}; // TODO(#5726): This function is called deriveAESSecret in TS. I don't like point_to_symmetric_key name much since // point is not the only input of the function. Unify naming with TS once we have a better name. pub fn point_to_symmetric_key(secret: Scalar, point: Point) -> [u8; 32] { - let shared_secret_fields = multi_scalar_mul([point], [secret]); + let shared_secret: Point = multi_scalar_mul([point], [secret]); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/6061): make the func return Point struct directly - let shared_secret = pub_key_to_bytes(Point::new(shared_secret_fields[0], shared_secret_fields[1], false)); + let shared_secret = pub_key_to_bytes(shared_secret); let mut shared_secret_bytes_with_separator = [0 as u8; 65]; shared_secret_bytes_with_separator = arr_copy_slice(shared_secret, shared_secret_bytes_with_separator, 0); shared_secret_bytes_with_separator[64] = GENERATOR_INDEX__SYMMETRIC_KEY; diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index cb7aef45b53..eeb04aa75c8 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -145,7 +145,7 @@ contract AvmTest { } #[aztec(public)] - fn variable_base_msm() -> [Field; 3] { + fn variable_base_msm() -> Point { let g = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; let scalar = Scalar { lo: 3, hi: 0 }; let scalar2 = Scalar { lo: 20, hi: 0 }; diff --git a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr index 0be1dc18f52..30ef7add279 100644 --- a/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr +++ b/noir-projects/noir-contracts/contracts/private_token_contract/src/types/token_note.nr @@ -92,7 +92,7 @@ impl NoteInterface for TokenNote { lo: random_lo, hi: random_hi, }] - )[0] + ).x } } @@ -238,15 +238,7 @@ impl PrivatelyRefundable for TokenNote { ); // 5. At last we represent the points as Points and return them. - (Point { - x: incomplete_fee_payer_point[0], - y: incomplete_fee_payer_point[1], - is_infinite: incomplete_fee_payer_point[2] == 1 - }, Point { - x: incomplete_user_point[0], - y: incomplete_user_point[1], - is_infinite: incomplete_user_point[2] == 1 - }) + (incomplete_fee_payer_point, incomplete_user_point) } fn complete_refund(incomplete_fee_payer_point: Point, incomplete_user_point: Point, transaction_fee: Field) -> (Field, Field) { @@ -254,18 +246,13 @@ impl PrivatelyRefundable for TokenNote { let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); // 2. We compute the fee point as `G ^ transaction_fee` - let fee_point_raw = multi_scalar_mul( + let fee_point = multi_scalar_mul( [G1], [Scalar { lo: transaction_fee_lo, hi: transaction_fee_hi, }] ); - let fee_point = Point { - x: fee_point_raw[0], - y: fee_point_raw[1], - is_infinite: fee_point_raw[2] == 1 - }; // 3. Now we leverage homomorphism to privately add the fee to fee payer point and subtract it from // the sponsored user point in public. diff --git a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr index c791ac88404..916943b737c 100644 --- a/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr +++ b/noir/noir-repo/noir_stdlib/src/embedded_curve_ops.nr @@ -61,8 +61,7 @@ impl EmbeddedCurveScalar { } pub fn derive_public_key(self) -> EmbeddedCurvePoint { - let public_key = fixed_base_scalar_mul(self.lo, self.hi); - EmbeddedCurvePoint { x: public_key[0], y: public_key[1], is_infinite: false } + fixed_base_scalar_mul(self) } #[field(bn254)] @@ -84,24 +83,25 @@ impl Eq for EmbeddedCurveScalar { // // The embedded curve being used is decided by the // underlying proof system. -#[foreign(multi_scalar_mul)] // docs:start:multi_scalar_mul pub fn multi_scalar_mul( points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N] -) -> [Field; 3] +) -> EmbeddedCurvePoint // docs:end:multi_scalar_mul -{} +{ + let point_array = multi_scalar_mul_array_return(points, scalars); + EmbeddedCurvePoint { x: point_array[0], y: point_array[1], is_infinite: point_array[2] as bool } +} + +#[foreign(multi_scalar_mul)] +fn multi_scalar_mul_array_return(points: [EmbeddedCurvePoint; N], scalars: [EmbeddedCurveScalar; N]) -> [Field; 3] {} // docs:start:fixed_base_scalar_mul -pub fn fixed_base_scalar_mul( - scalar_low: Field, - scalar_high: Field -) -> [Field; 3] +pub fn fixed_base_scalar_mul(scalar: EmbeddedCurveScalar) -> EmbeddedCurvePoint // docs:end:fixed_base_scalar_mul { let g1 = EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; - let scalar = EmbeddedCurveScalar { lo: scalar_low, hi: scalar_high }; multi_scalar_mul([g1], [scalar]) } diff --git a/noir/noir-repo/noir_stdlib/src/hash/mod.nr b/noir/noir-repo/noir_stdlib/src/hash/mod.nr index 65f3b9419ff..dc82ff08efe 100644 --- a/noir/noir-repo/noir_stdlib/src/hash/mod.nr +++ b/noir/noir-repo/noir_stdlib/src/hash/mod.nr @@ -43,8 +43,7 @@ fn pedersen_commitment_with_separator_noir(input: [Field; N], separa points[i] = EmbeddedCurveScalar::from_field(input[i]); } let generators = derive_generators("DEFAULT_DOMAIN_SEPARATOR".as_bytes(), separator); - let values = multi_scalar_mul(generators, points); - EmbeddedCurvePoint { x: values[0], y: values[1], is_infinite: values[2] as bool } + multi_scalar_mul(generators, points) } #[no_predicates] @@ -80,7 +79,7 @@ fn pedersen_hash_with_separator_noir(input: [Field; N], separator: u multi_scalar_mul( [length_generator[0], v1], [EmbeddedCurveScalar { lo: N as Field, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] - )[0] + ).x } #[foreign(pedersen_hash)] diff --git a/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr b/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr index 4eeda39c6aa..5372f73df23 100644 --- a/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/embedded_curve_ops/src/main.nr @@ -4,8 +4,8 @@ fn main(priv_key: Field, pub_x: pub Field, pub_y: pub Field) { let scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: priv_key, hi: 0 }; // Test that multi_scalar_mul correctly derives the public key let res = std::embedded_curve_ops::multi_scalar_mul([g1], [scalar]); - assert(res[0] == pub_x); - assert(res[1] == pub_y); + assert(res.x == pub_x); + assert(res.y == pub_y); // Test that double function calling embedded_curve_add works as expected let pub_point = std::embedded_curve_ops::EmbeddedCurvePoint { x: pub_x, y: pub_y, is_infinite: false }; @@ -18,5 +18,5 @@ fn main(priv_key: Field, pub_x: pub Field, pub_y: pub Field) { let res = std::embedded_curve_ops::multi_scalar_mul([g1, g1], [scalar, scalar]); // The results should be double the g1 point because the scalars are 1 and we pass in g1 twice - assert(double.x == res[0]); + assert(double.x == res.x); } diff --git a/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr b/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr index cf39b2f97e4..d1bc4f663fd 100644 --- a/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/regression_5045/src/main.nr @@ -15,6 +15,6 @@ fn main(is_active: bool) { [a, bad], [EmbeddedCurveScalar { lo: 1, hi: 0 }, EmbeddedCurveScalar { lo: 1, hi: 0 }] ); - assert(e[0] != d.x); + assert(e.x != d.x); } } diff --git a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr index 5bc0ca9fefb..cf22fd371d1 100644 --- a/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/schnorr/src/main.nr @@ -50,7 +50,7 @@ pub fn verify_signature_noir(public_key: embedded_curve_ops::EmbeddedCurvePoi let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); // compare the _hashes_ rather than field elements modulo r - let pedersen_hash = std::hash::pedersen_hash([r[0], public_key.x, public_key.y]); + let pedersen_hash = std::hash::pedersen_hash([r.x, public_key.x, public_key.y]); let mut hash_input = [0; M]; let pde = pedersen_hash.to_be_bytes(32); @@ -62,7 +62,7 @@ pub fn verify_signature_noir(public_key: embedded_curve_ops::EmbeddedCurvePoi } let result = std::hash::blake2s(hash_input); - is_ok = (r[2] == 0); + is_ok = !r.is_infinite; for i in 0..32 { if result[i] != signature[32 + i] { is_ok = false; @@ -101,7 +101,7 @@ pub fn assert_valid_signature(public_key: embedded_curve_ops::EmbeddedCurvePo let g1 = embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; let r = embedded_curve_ops::multi_scalar_mul([g1, public_key], [sig_s, sig_e]); // compare the _hashes_ rather than field elements modulo r - let pedersen_hash = std::hash::pedersen_hash([r[0], public_key.x, public_key.y]); + let pedersen_hash = std::hash::pedersen_hash([r.x, public_key.x, public_key.y]); let mut hash_input = [0; M]; let pde = pedersen_hash.to_be_bytes(32); @@ -113,7 +113,7 @@ pub fn assert_valid_signature(public_key: embedded_curve_ops::EmbeddedCurvePo } let result = std::hash::blake2s(hash_input); - assert(r[2] == 0); + assert(!r.is_infinite); for i in 0..32 { assert(result[i] == signature[32 + i]); } diff --git a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr index d84288b9fd6..66ac0a2b313 100644 --- a/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr +++ b/noir/noir-repo/test_programs/execution_success/simple_shield/src/main.nr @@ -10,12 +10,11 @@ fn main( to_pubkey_x: Field, to_pubkey_y: Field ) -> pub [Field; 2] { + let priv_key_as_scalar = std::embedded_curve_ops::EmbeddedCurveScalar::new(priv_key, 0); // Compute public key from private key to show ownership - let pubkey = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key, 0); - let pubkey_x = pubkey[0]; - let pubkey_y = pubkey[1]; + let pubkey = std::embedded_curve_ops::fixed_base_scalar_mul(priv_key_as_scalar); // Compute input note commitment - let note_commitment = std::hash::pedersen_commitment([pubkey_x, pubkey_y]); + let note_commitment = std::hash::pedersen_commitment([pubkey.x, pubkey.y]); // Compute input note nullifier let nullifier = std::hash::pedersen_commitment([note_commitment.x, index, priv_key]); // Compute output note nullifier diff --git a/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr b/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr index 225e86397fd..0c2c333fa62 100644 --- a/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr +++ b/noir/noir-repo/test_programs/noir_test_success/embedded_curve_ops/src/main.nr @@ -10,28 +10,28 @@ use std::embedded_curve_ops::{EmbeddedCurvePoint, EmbeddedCurveScalar, multi_sca let s1 = EmbeddedCurveScalar { lo: 1, hi: 0 }; let a = multi_scalar_mul([g1], [s1]); - assert(a[2] == 0); + assert(!a.is_infinite); assert(g1 + zero == g1); assert(g1 - g1 == zero); assert(g1 - zero == g1); assert(zero + zero == zero); assert( multi_scalar_mul([g1], [s1]) - == [1, 17631683881184975370165255887551781615748388533673675138860, 0] + == EmbeddedCurvePoint { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false } ); - assert(multi_scalar_mul([g1, g1], [s1, s1]) == [g2.x, g2.y, 0]); + assert(multi_scalar_mul([g1, g1], [s1, s1]) == g2); assert( multi_scalar_mul( [g1, zero], [EmbeddedCurveScalar { lo: 2, hi: 0 }, EmbeddedCurveScalar { lo: 42, hi: 25 }] ) - == [g2.x, g2.y, 0] + == g2 ); assert( multi_scalar_mul( [g1, g1, zero], [s1, s1, EmbeddedCurveScalar { lo: 42, hi: 25 }] ) - == [g2.x, g2.y, 0] + == g2 ); }