From ba1e028f4f6cf182acc81fd0889c9eee62651de4 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 10 Jul 2024 09:18:23 +0000 Subject: [PATCH 1/6] fix: using different generators in private refund --- noir-projects/aztec-nr/aztec/src/generators.nr | 3 +++ noir-projects/aztec-nr/aztec/src/lib.nr | 1 + .../contracts/avm_test_contract/src/main.nr | 10 ++++------ .../private_token_contract/src/types/token_note.nr | 5 ++--- 4 files changed, 10 insertions(+), 9 deletions(-) create mode 100644 noir-projects/aztec-nr/aztec/src/generators.nr diff --git a/noir-projects/aztec-nr/aztec/src/generators.nr b/noir-projects/aztec-nr/aztec/src/generators.nr new file mode 100644 index 000000000000..6a4840cff607 --- /dev/null +++ b/noir-projects/aztec-nr/aztec/src/generators.nr @@ -0,0 +1,3 @@ +use dep::protocol_types::point::Point; + +global G1 = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; diff --git a/noir-projects/aztec-nr/aztec/src/lib.nr b/noir-projects/aztec-nr/aztec/src/lib.nr index d4b1abf35e71..af7f03c1f516 100644 --- a/noir-projects/aztec-nr/aztec/src/lib.nr +++ b/noir-projects/aztec-nr/aztec/src/lib.nr @@ -1,5 +1,6 @@ mod context; mod deploy; +mod generators; mod hash; mod history; mod initializer; 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 eeb04aa75c8d..e257cd79bcdb 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 @@ -32,6 +32,7 @@ contract AvmTest { use dep::aztec::oracle::get_contract_instance::{get_contract_instance_avm, get_contract_instance_internal_avm}; use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; use dep::aztec::context::gas::GasOpts; + use dep::aztec::generators::G1; use dep::compressed_string::CompressedString; #[aztec(storage)] @@ -137,19 +138,16 @@ contract AvmTest { #[aztec(public)] fn elliptic_curve_add_and_double() -> Point { - let g = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; - - let doubled = g + g; - let added = g + doubled; + let doubled = G1 + G1; + let added = G1 + doubled; added } #[aztec(public)] 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 }; - let triple_g = multi_scalar_mul([g, g], [scalar, scalar2]); + let triple_g = multi_scalar_mul([G1, G1], [scalar, scalar2]); triple_g } 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 30ef7add279a..0ca85a31f6c0 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 @@ -2,7 +2,8 @@ use dep::aztec::{ prelude::{AztecAddress, NoteHeader, NoteInterface, PrivateContext}, protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, point::Point, scalar::Scalar, hash::poseidon2_hash}, note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, - keys::getters::get_nsk_app, note::note_getter_options::PropertySelector + keys::getters::get_nsk_app, note::note_getter_options::PropertySelector, + generators::G1, }; use dep::std::field::bn254::decompose; use dep::std::embedded_curve_ops::multi_scalar_mul; @@ -32,8 +33,6 @@ trait PrivatelyRefundable { global TOKEN_NOTE_LEN: Field = 3; // 3 plus a header. global TOKEN_NOTE_BYTES_LEN: Field = 3 * 32 + 64; -// Grumpkin generator point. -global G1 = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; #[aztec(note)] struct TokenNote { From bdd0410499d1812936188bcdf8cd8c12d3dd9650 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 10 Jul 2024 09:39:38 +0000 Subject: [PATCH 2/6] computing generators --- noir-projects/aztec-nr/aztec/src/generators.nr | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/generators.nr b/noir-projects/aztec-nr/aztec/src/generators.nr index 6a4840cff607..da39f1279f8d 100644 --- a/noir-projects/aztec-nr/aztec/src/generators.nr +++ b/noir-projects/aztec-nr/aztec/src/generators.nr @@ -1,3 +1,19 @@ use dep::protocol_types::point::Point; -global G1 = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; +global Ga1 = Point { x: 0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1, y: 0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6, is_infinite: false }; +global Ga2 = Point { x: 0x2825c79cc6a5cbbeef7d6a8f1b6a12b312aa338440aefeb4396148c89147c049, y: 0x129bfd1da54b7062d6b544e7e36b90736350f6fba01228c41c72099509f5701e, is_infinite: false }; +global Ga3 = Point { x: 0x0edb1e293c3ce91bfc04e3ceaa50d2c541fa9d091c72eb403efb1cfa2cb3357f, y: 0x1341d675fa030ece3113ad53ca34fd13b19b6e9762046734f414824c4d6ade35, is_infinite: false }; + +mod test { + use crate::generators::{Ga1, Ga2, Ga3}; + use dep::protocol_types::point::Point; + use std::hash::derive_generators; + + #[test] +fn test_generators() { + let generators: [Point; 3] = derive_generators("aztec_nr_generators".as_bytes(), 0); + assert_eq(generators[0], Ga1); + assert_eq(generators[1], Ga2); + assert_eq(generators[2], Ga3); + } +} From 556f05ba7a2836892cc013d9c68b4ab7683a5f91 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 10 Jul 2024 10:23:05 +0000 Subject: [PATCH 3/6] fixes --- .../aztec-nr/aztec/src/generators.nr | 1 + .../contracts/avm_test_contract/src/main.nr | 8 +- .../src/types/token_note.nr | 95 ++++++++++--------- 3 files changed, 55 insertions(+), 49 deletions(-) diff --git a/noir-projects/aztec-nr/aztec/src/generators.nr b/noir-projects/aztec-nr/aztec/src/generators.nr index da39f1279f8d..3836e17269f3 100644 --- a/noir-projects/aztec-nr/aztec/src/generators.nr +++ b/noir-projects/aztec-nr/aztec/src/generators.nr @@ -1,5 +1,6 @@ use dep::protocol_types::point::Point; +// A set of generators generated with derive_generators function from noir::std global Ga1 = Point { x: 0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1, y: 0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6, is_infinite: false }; global Ga2 = Point { x: 0x2825c79cc6a5cbbeef7d6a8f1b6a12b312aa338440aefeb4396148c89147c049, y: 0x129bfd1da54b7062d6b544e7e36b90736350f6fba01228c41c72099509f5701e, is_infinite: false }; global Ga3 = Point { x: 0x0edb1e293c3ce91bfc04e3ceaa50d2c541fa9d091c72eb403efb1cfa2cb3357f, y: 0x1341d675fa030ece3113ad53ca34fd13b19b6e9762046734f414824c4d6ade35, is_infinite: false }; 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 e257cd79bcdb..68037136a750 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 @@ -32,7 +32,7 @@ contract AvmTest { use dep::aztec::oracle::get_contract_instance::{get_contract_instance_avm, get_contract_instance_internal_avm}; use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; use dep::aztec::context::gas::GasOpts; - use dep::aztec::generators::G1; + use dep::aztec::generators::Ga1; use dep::compressed_string::CompressedString; #[aztec(storage)] @@ -138,8 +138,8 @@ contract AvmTest { #[aztec(public)] fn elliptic_curve_add_and_double() -> Point { - let doubled = G1 + G1; - let added = G1 + doubled; + let doubled = Ga1 + Ga1; + let added = Ga1 + doubled; added } @@ -147,7 +147,7 @@ contract AvmTest { fn variable_base_msm() -> Point { let scalar = Scalar { lo: 3, hi: 0 }; let scalar2 = Scalar { lo: 20, hi: 0 }; - let triple_g = multi_scalar_mul([G1, G1], [scalar, scalar2]); + let triple_g = multi_scalar_mul([Ga1, Ga1], [scalar, scalar2]); triple_g } 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 0ca85a31f6c0..d5bf549e10ce 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 @@ -3,7 +3,7 @@ use dep::aztec::{ protocol_types::{constants::GENERATOR_INDEX__NOTE_NULLIFIER, point::Point, scalar::Scalar, hash::poseidon2_hash}, note::utils::compute_note_hash_for_consumption, oracle::unsafe_rand::unsafe_rand, keys::getters::get_nsk_app, note::note_getter_options::PropertySelector, - generators::G1, + generators::{Ga1 as G_amt, Ga2 as G_npk, Ga3 as G_rnd} }; use dep::std::field::bn254::decompose; use dep::std::embedded_curve_ops::multi_scalar_mul; @@ -74,11 +74,11 @@ impl NoteInterface for TokenNote { fn compute_note_content_hash(self) -> Field { let (npk_lo, npk_hi) = decompose(self.npk_m_hash); let (random_lo, random_hi) = decompose(self.randomness); - // We compute the note content hash as an x-coordinate of `G ^ (amount + npk_m_hash + randomness)` instead + // We compute the note content hash as an x-coordinate of `G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness` instead // of using pedersen or poseidon2 because it allows us to privately add and subtract from amount in public // by leveraging homomorphism. multi_scalar_mul( - [G1, G1, G1], + [G_amt, G_npk, G_rnd], [Scalar { lo: self.amount.to_integer(), hi: 0 @@ -130,51 +130,53 @@ impl OwnedNote for TokenNote { * This is because the compute_note_content_hash function above defines the content hash to be * the x-coordinate of a point defined as: * - * amount * G + npk * G + randomness * G - * = (amount + npk + randomness) * G + * G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness * - * where G is a generator point. Interesting point here is that we actually need to convert + * where G_amt, G_npk and G_rnd are generator points. Interesting point here is that we actually need to convert * - amount - * - npk + * - npk_m_hash * - randomness * from grumpkin Field elements * (which have a modulus of 21888242871839275222246405745257275088548364400416034343698204186575808495617) * into a grumpkin scalar * (which have a modulus of 21888242871839275222246405745257275088696311157297823662689037894645226208583) * - * The intuition for this is that the Field elements define the domain of the x,y coordinates for points on the curves, - * but the number of points on the curve is actually greater than the size of that domain. + * The intuition for this is that the Field elements define the domain of the x, y coordinates for points on + * the curves, but the number of points on the curve is actually greater than the size of that domain. * - * (Consider, e.g. if the curve were defined over a field of 10 elements, and each x coord had two corresponding y for +/-) + * (Consider, e.g. if the curve were defined over a field of 10 elements, and each x coord had two corresponding + * y for +/-) * * For a bit more info, see * https://hackmd.io/@aztec-network/ByzgNxBfd#2-Grumpkin---A-curve-on-top-of-BN-254-for-SNARK-efficient-group-operations * * - * Anyway, if we have a secret scalar n := amount + npk + randomness, and then we reveal a point n * G, there is no efficient way to - * deduce what n is. This is the discrete log problem. + * Anyway, if we have a secret scalar s, and then we reveal a point s * G (G being a generator), there is no efficient + * way to deduce what s is. This is the discrete log problem. * * However we can still perform addition/subtraction on points! That is why we generate those two points, which are: - * incomplete_fee_payer_point := (fee_payer_npk + fee_payer_randomness) * G - * incomplete_user_point := (user_npk + funded_amount + user_randomness) * G + * incomplete_fee_payer_point := G_npk * fee_payer_npk + G_amt * fee_payer_randomness + * incomplete_user_point := G_npk * user_npk + G_amt * funded_amount + G_rnd * user_randomness * - * where `funded_amount` is the total amount in tokens that the sponsored user initially supplied, from which the transaction fee will be subtracted. + * where `funded_amount` is the total amount in tokens that the sponsored user initially supplied, from which + * the transaction fee will be subtracted. * - * So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction fee as just + * So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction + * fee as just: * - * fee_point := transaction_fee * G + * fee_point := G_amt * transaction_fee * * Then we arrive at the final points via addition/subtraction of that transaction fee point: * - * fee_payer_point := incomplete_fee_payer_point + fee_point - * = (fee_payer_npk + fee_payer_randomness) * G + transaction_fee * G - * = (fee_payer_npk + fee_payer_randomness + transaction_fee) * G + * fee_payer_point := incomplete_fee_payer_point + fee_point = + * = (G_npk * fee_payer_npk + G_rnd * fee_payer_randomness) + G_amt * transaction_fee = + * = G_amt * transaction_fee + G_npk * fee_payer_npk + G_rnd * fee_payer_randomness * - * user_point := incomplete_user_point - fee_point - * = (user_npk + funded_amount + user_randomness) * G - transaction_fee * G - * = (user_npk + user_randomness + (funded_amount - transaction_fee)) * G + * user_point := incomplete_user_point - fee_point = + * = (G_amt * funded_amount + G_npk * user_npk + G_rnd + user_randomness) - G_amt * transaction_fee = + * = G_amt * (funded_amount - transaction_fee) + G_npk * user_npk + G_rnd + user_randomness * - * When we return the x-coordinate of those points, it identically matches the note_content_hash of (and therefore *is*) notes like: + * The x-coordinate of points above identically matches the note_content_hash of (and therefore *is*) notes like: * { * amount: (funded_amount - transaction_fee), * npk_m_hash: user_npk, @@ -183,26 +185,29 @@ impl OwnedNote for TokenNote { * * Why do we need different randomness for the user and the fee payer notes? * --> This is because if the randomness values were the same we could fingerprint the user by doing the following: - * 1) randomness_influence = incomplete_fee_payer_point - G * fee_payer_npk = - * = (fee_payer_npk + randomness) * G - G * fee_payer_npk = randomness * G - * 2) user_fingerprint = incomplete_user_point - G * funded_amount - randomness_influence = - * = (user_npk + funded_amount + randomness) * G - funded_amount * G - randomness * G = - * = user_npk * G + * 1) randomness_influence = incomplete_fee_payer_point - G_npk * fee_payer_npk = + * = (G_npk * fee_payer_npk + G_rnd * randomness) - G_npk * fee_payer_npk = + * = G_rnd * randomness + * 2) user_fingerprint = incomplete_user_point - G_amt * funded_amount - randomness_influence = + * = (G_npk * user_npk + G_amt * funded_amount + G_rnd * randomness) - G_amt * funded_amount + * - G_rnd * randomness = + * = G_npk * user_npk * 3) Then the second time the user would use this fee paying contract we would recover the same fingerprint and * link that the 2 transactions were made by the same user. Given that it's expected that only a limited set - * of fee paying contracts will be used and they will be known searching for fingerprints by trying different + * of fee paying contracts will be used and they will be known, searching for fingerprints by trying different * fee payer npk values of these known contracts is a feasible attack. */ impl PrivatelyRefundable for TokenNote { fn generate_refund_points(fee_payer_npk_m_hash: Field, user_npk_m_hash: Field, funded_amount: Field, user_randomness: Field, fee_payer_randomness: Field) -> (Point, Point) { - // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox function we - // first need to convert the fields to high and low limbs. + // 1. To be able to multiply generators with randomness and npk_m_hash using barretneberg's (BB) blackbox + // function we first need to convert the fields to high and low limbs. let (fee_payer_randomness_lo, fee_payer_randomness_hi) = decompose(fee_payer_randomness); let (fee_payer_npk_m_hash_lo, fee_payer_npk_m_hash_hi) = decompose(fee_payer_npk_m_hash); - // 2. Now that we have correct representationsn of fee payer and randomness we can compute `G ^ (fee_payer_npk + randomness)` + // 2. Now that we have correct representationsn of fee payer and randomness we can compute + // `G_npk * fee_payer_npk + G_rnd * randomness`. let incomplete_fee_payer_point = multi_scalar_mul( - [G1, G1], + [G_npk, G_rnd], [Scalar { lo: fee_payer_npk_m_hash_lo, hi: fee_payer_npk_m_hash_hi @@ -215,28 +220,28 @@ impl PrivatelyRefundable for TokenNote { // 3. We do the necessary conversion for values relevant for the sponsored user point. let (user_randomness_lo, user_randomness_hi) = decompose(user_randomness); - // TODO(#7324): representing user with their npk_m_hash here does not work with key rotation - let (user_lo, user_hi) = decompose(user_npk_m_hash); + // TODO(#7324), TODO(#7323): using npk_m_hash here is vulnerable in 2 ways described in the linked issues. + let (user_npk_lo, user_npk_hi) = decompose(user_npk_m_hash); let (funded_amount_lo, funded_amount_hi) = decompose(funded_amount); - // 4. We compute `G ^ (user_npk_m_hash + funded_amount + randomness)` + // 4. We compute `G_amt * funded_amount + G_npk * user_npk_m_hash + G_rnd * randomness`. let incomplete_user_point = multi_scalar_mul( - [G1, G1, G1], + [G_amt, G_npk, G_rnd], [Scalar { - lo: user_lo, - hi: user_hi - }, - Scalar { lo: funded_amount_lo, hi: funded_amount_hi }, + Scalar { + lo: user_npk_lo, + hi: user_npk_hi + }, Scalar { lo: user_randomness_lo, hi: user_randomness_hi }] ); - // 5. At last we represent the points as Points and return them. + // 5. At last we return the points. (incomplete_fee_payer_point, incomplete_user_point) } @@ -244,9 +249,9 @@ impl PrivatelyRefundable for TokenNote { // 1. We convert the transaction fee to high and low limbs to be able to use BB API. let (transaction_fee_lo, transaction_fee_hi) = decompose(transaction_fee); - // 2. We compute the fee point as `G ^ transaction_fee` + // 2. We compute the fee point as `G_amt * transaction_fee` let fee_point = multi_scalar_mul( - [G1], + [G_amt], [Scalar { lo: transaction_fee_lo, hi: transaction_fee_hi, From 642dd474e78a7527590ded9b72513262e7b520a9 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 10 Jul 2024 10:24:57 +0000 Subject: [PATCH 4/6] more autism --- .../contracts/private_token_contract/src/types/token_note.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d5bf549e10ce..99c61356e142 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 @@ -125,7 +125,7 @@ impl OwnedNote for TokenNote { * these are going to be eventually turned into notes: * one for the user, and one for the fee payer. * - * So you can think of these (x,y) points as "partial notes": they encode part of the internals of the notes. + * So you can think of these (x, y) points as "partial notes": they encode part of the internals of the notes. * * This is because the compute_note_content_hash function above defines the content hash to be * the x-coordinate of a point defined as: From d17250d33063fc01f9f983f45e1a5898fac34b17 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 10 Jul 2024 10:31:14 +0000 Subject: [PATCH 5/6] WIP --- noir-projects/aztec-nr/aztec/src/generators.nr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/noir-projects/aztec-nr/aztec/src/generators.nr b/noir-projects/aztec-nr/aztec/src/generators.nr index 3836e17269f3..02eae3307fb2 100644 --- a/noir-projects/aztec-nr/aztec/src/generators.nr +++ b/noir-projects/aztec-nr/aztec/src/generators.nr @@ -1,6 +1,6 @@ use dep::protocol_types::point::Point; -// A set of generators generated with derive_generators function from noir::std +// A set of generators generated with `derive_generators(...)` function from noir::std global Ga1 = Point { x: 0x30426e64aee30e998c13c8ceecda3a77807dbead52bc2f3bf0eae851b4b710c1, y: 0x113156a068f603023240c96b4da5474667db3b8711c521c748212a15bc034ea6, is_infinite: false }; global Ga2 = Point { x: 0x2825c79cc6a5cbbeef7d6a8f1b6a12b312aa338440aefeb4396148c89147c049, y: 0x129bfd1da54b7062d6b544e7e36b90736350f6fba01228c41c72099509f5701e, is_infinite: false }; global Ga3 = Point { x: 0x0edb1e293c3ce91bfc04e3ceaa50d2c541fa9d091c72eb403efb1cfa2cb3357f, y: 0x1341d675fa030ece3113ad53ca34fd13b19b6e9762046734f414824c4d6ade35, is_infinite: false }; From c5e6ed971aac93eeb52a2eee9695aa10ee8adce2 Mon Sep 17 00:00:00 2001 From: benesjan Date: Wed, 10 Jul 2024 10:35:26 +0000 Subject: [PATCH 6/6] reverting unhelpful change --- .../contracts/avm_test_contract/src/main.nr | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 68037136a750..eeb04aa75c8d 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 @@ -32,7 +32,6 @@ contract AvmTest { use dep::aztec::oracle::get_contract_instance::{get_contract_instance_avm, get_contract_instance_internal_avm}; use dep::aztec::protocol_types::abis::function_selector::FunctionSelector; use dep::aztec::context::gas::GasOpts; - use dep::aztec::generators::Ga1; use dep::compressed_string::CompressedString; #[aztec(storage)] @@ -138,16 +137,19 @@ contract AvmTest { #[aztec(public)] fn elliptic_curve_add_and_double() -> Point { - let doubled = Ga1 + Ga1; - let added = Ga1 + doubled; + let g = Point { x: 1, y: 17631683881184975370165255887551781615748388533673675138860, is_infinite: false }; + + let doubled = g + g; + let added = g + doubled; added } #[aztec(public)] 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 }; - let triple_g = multi_scalar_mul([Ga1, Ga1], [scalar, scalar2]); + let triple_g = multi_scalar_mul([g, g], [scalar, scalar2]); triple_g }