Skip to content

Commit

Permalink
last touches
Browse files Browse the repository at this point in the history
  • Loading branch information
benesjan committed Aug 2, 2024
1 parent e8af23b commit 10fe234
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 81 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ contract PrivateFPC {
// convince the FPC we are not cheating
context.push_nullifier(user_randomness);

// We use different randomness for fee payer to prevent a potential privay leak (see impl
// of PrivatelyRefundable for TokenNote for details).
// We use different randomness for fee payer to prevent a potential privay leak (see description
// of `setup_refund(...)` function in TokenWithRefunds for details.
let fee_payer_randomness = poseidon2_hash([user_randomness]);
// We emit fee payer randomness to ensure FPC admin can reconstruct their fee note
emit_randomness_as_unencrypted_log(&mut context, fee_payer_randomness);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,21 @@ contract TokenWithRefunds {
};
use crate::types::token_note::TokenNoteHidingPoint;

/// We need to use different randomness for the user and for the fee payer notes because if the randomness values
/// were the same we could fingerprint the user by doing the following:
/// 1) randomness_influence = 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 = user_point - randomness_influence =
/// = (G_npk * user_npk + G_rnd * randomness) - 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 fee payer npk values of these known contracts is a feasible attack.
///
/// fee_payer_point and user_point above are public information since there are args to the public
/// `complete_refund(...)` function.
#[aztec(private)]
fn setup_refund(
fee_payer: AztecAddress, // Address of the entity which will receive the fee note.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,82 +140,3 @@ impl OwnedNote for TokenNote {
self.amount
}
}

/**
* What is happening below?
*
* First in generate_refund_points, we create two points on the grumpkin curve;
* 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.
*
* This is because the compute_note_hiding_point function above defines the hiding point as:
*
* G_amt * amount + G_npk * npk_m_hash + G_rnd * randomness
*
* where G_amt, G_npk and G_rnd are generator points. Interesting point here is that we actually need to convert
* - amount
* - 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.
*
* (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 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 := G_npk * fee_payer_npk + G_rnd * fee_payer_randomness
* incomplete_user_point := G_npk * user_npk + G_rnd * user_randomness
*
* So we pass those points into the teardown function (here) and compute a third point corresponding to the transaction
* fee as just:
*
* fee_point := G_amt * transaction_fee
* refund_point := G_amt * (funded_amount - transaction_fee)
*
* where `funded_amount` is the total amount in tokens that the sponsored user initially supplied and the transaction
* fee is the final transaction fee whose value is made available in the public teardown function.
*
* Then we arrive at the final points via addition of the fee and refund points:
*
* 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 + refund_point =
* = (G_npk * user_npk + G_rnd + user_randomness) + G_amt * (funded_amount - transaction_fee) =
* = G_amt * (funded_amount - transaction_fee) + G_npk * user_npk + G_rnd * user_randomness
*
* The point above matches the note_hiding_point of (and therefore *is*) notes like:
* {
* amount: (funded_amount - transaction_fee),
* npk_m_hash: user_npk,
* randomness: user_randomness
* }
*
* 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_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 - randomness_influence =
* = (G_npk * user_npk + G_rnd * randomness) - 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
* fee payer npk values of these known contracts is a feasible attack.
*/

0 comments on commit 10fe234

Please sign in to comment.