Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

circuits: valid-commitments: Allow relayer fees below max_match_fee #867

Merged
merged 2 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions circuit-types/src/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ where
pub keys: PublicKeyChain,
/// The match fee authorized by the wallet owner that the relayer may take
/// on a match
pub match_fee: FixedPoint,
#[serde(alias = "match_fee")]
pub max_match_fee: FixedPoint,
/// The public key of the cluster that this wallet has been delegated to for
/// matches
///
Expand All @@ -82,7 +83,7 @@ where
.unwrap(),
orders: (0..MAX_ORDERS).map(|_| Order::default()).collect_vec().try_into().unwrap(),
keys: PublicKeyChain::default(),
match_fee: FixedPoint::from_integer(0),
max_match_fee: FixedPoint::from_integer(0),
managing_cluster: EncryptionKey::default(),
blinder: Scalar::zero(),
}
Expand Down
2 changes: 1 addition & 1 deletion circuits/benches/valid_wallet_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ where
balances: create_default_arr(),
orders: create_default_arr(),
keys: PUBLIC_KEYS.clone(),
match_fee: FixedPoint::from_integer(0),
max_match_fee: FixedPoint::from_integer(0),
managing_cluster: enc,
blinder: Scalar::zero(),
};
Expand Down
4 changes: 2 additions & 2 deletions circuits/integration/mpc_circuits/match_settle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ fn run_match_settle_with_amounts(

let wallet0 = w0.allocate(PARTY0, fabric);
let wallet1 = w1.allocate(PARTY0, fabric);
let relayer_fee0 = w0.match_fee.allocate(PARTY0, fabric);
let relayer_fee1 = w1.match_fee.allocate(PARTY0, fabric);
let relayer_fee0 = w0.max_match_fee.allocate(PARTY0, fabric);
let relayer_fee1 = w1.max_match_fee.allocate(PARTY0, fabric);
let party0_pre_shares = pre_public_shares1.allocate(PARTY0, fabric);
let party1_pre_shares = pre_public_shares2.allocate(PARTY0, fabric);

Expand Down
2 changes: 1 addition & 1 deletion circuits/src/zk_circuits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ pub mod test_helpers {
balances: INITIAL_BALANCES.clone(),
orders: INITIAL_ORDERS.clone(),
keys: PUBLIC_KEYS.clone(),
match_fee: FixedPoint::from_f64_round_down(0.002), // 20 bps
max_match_fee: FixedPoint::from_f64_round_down(0.002), // 20 bps
managing_cluster: DecryptionKey::random_pair(&mut thread_rng()).1,
blinder: Scalar::from(42u64)
};
Expand Down
4 changes: 2 additions & 2 deletions circuits/src/zk_circuits/proof_linking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,12 +654,12 @@ mod test {
let mut new_public_shares1 = public_share.clone();

let party0_fees = compute_fee_obligation(
wallet.match_fee,
wallet.max_match_fee,
match_witness.order0.side,
&match_witness.match_res,
);
let party1_fees = compute_fee_obligation(
wallet.match_fee,
wallet.max_match_fee,
match_witness.order1.side,
&match_witness.match_res,
);
Expand Down
39 changes: 30 additions & 9 deletions circuits/src/zk_circuits/valid_commitments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::{
VALID_REBLIND_COMMITMENTS_LINK,
},
zk_gadgets::{
comparators::{EqGadget, EqVecGadget, EqZeroGadget},
comparators::{EqGadget, EqVecGadget, EqZeroGadget, GreaterThanEqGadget},
wallet_operations::{OrderGadget, WalletGadget},
},
SingleProverCircuit,
Expand All @@ -30,7 +30,7 @@ use circuit_types::{
r#match::OrderSettlementIndices,
traits::{BaseType, CircuitBaseType, CircuitVarType},
wallet::{WalletShare, WalletVar},
PlonkCircuit,
PlonkCircuit, FEE_BITS,
};
use constants::{Scalar, ScalarField, MAX_BALANCES, MAX_ORDERS};
use mpc_plonk::errors::PlonkError;
Expand Down Expand Up @@ -81,7 +81,13 @@ where

// The advertised relayer take rate in the witness should equal the authorized
// take rate in the wallet
EqGadget::constrain_eq(&witness.relayer_fee, &base_wallet.match_fee, cs)?;
let relayer_fee_repr = witness.relayer_fee.repr;
let max_match_fee_repr = base_wallet.max_match_fee.repr;
GreaterThanEqGadget::<FEE_BITS>::constrain_greater_than_eq(
max_match_fee_repr,
relayer_fee_repr,
cs,
)?;

// Verify that the wallets are the same other than a possibly augmented balance
// of zero for the received mint of the order. This augmented balance
Expand Down Expand Up @@ -183,7 +189,7 @@ where
EqGadget::constrain_eq(&base_wallet.keys, &augmented_wallet.keys, cs)?;

// Match fee, managing cluster, and blinder should be equal
EqGadget::constrain_eq(&base_wallet.match_fee, &augmented_wallet.match_fee, cs)?;
EqGadget::constrain_eq(&base_wallet.max_match_fee, &augmented_wallet.max_match_fee, cs)?;
EqGadget::constrain_eq(
&base_wallet.managing_cluster,
&augmented_wallet.managing_cluster,
Expand Down Expand Up @@ -502,7 +508,7 @@ pub mod test_helpers {
public_secret_shares: public_share.clone(),
augmented_public_shares,
order,
relayer_fee: wallet.match_fee,
relayer_fee: wallet.max_match_fee,
balance_send,
balance_receive,
};
Expand Down Expand Up @@ -556,7 +562,7 @@ pub mod test_helpers {
mod test {
use circuit_types::{
balance::{Balance, BalanceShare},
fixed_point::FixedPointShare,
fixed_point::{FixedPoint, FixedPointShare},
order::{OrderShare, OrderSide},
traits::{SecretShareType, SingleProverCircuit},
Address,
Expand Down Expand Up @@ -659,6 +665,21 @@ mod test {
assert!(check_constraint_satisfaction::<SizedCommitments>(&witness, &statement))
}

/// Test the case in which a prover charges a lower fee than the wallet's
/// configured maximum
#[test]
fn test_valid_commitments__valid_augmentation__lower_fee() {
let wallet = UNAUGMENTED_WALLET.clone();
let (mut witness, statement) = create_witness_and_statement(&wallet);

// Prover charges a lower fee than the wallet's configured maximum
let max_fee = witness.relayer_fee.to_f64();
let new_fee = FixedPoint::from_f64_round_down(max_fee / 2.);
witness.relayer_fee = new_fee;

assert!(check_constraint_satisfaction::<SizedCommitments>(&witness, &statement))
}

// ------------------------
// | Invalid Augmentation |
// ------------------------
Expand Down Expand Up @@ -754,20 +775,20 @@ mod test {

// Modify the match fee in the wallet
let mut rng = thread_rng();
witness.augmented_public_shares.match_fee =
witness.augmented_public_shares.max_match_fee =
FixedPointShare { repr: Scalar::random(&mut rng) };
assert!(!check_constraint_satisfaction::<SizedCommitments>(&witness, &statement));
}

/// Tests the case in which the prover provides an incorrect relayer fee in
/// the witness
#[test]
fn test_invalid_commitments__wrong_relayer_fee() {
fn test_invalid_commitments__higher_fee() {
let wallet = INITIAL_WALLET.clone();
let (mut witness, statement) = create_witness_and_statement(&wallet);

// Modify the relayer fee in the witness
witness.relayer_fee = witness.relayer_fee + Scalar::one();
witness.relayer_fee.repr += Scalar::one(); // one above the configured maximum
assert!(!check_constraint_satisfaction::<SizedCommitments>(&witness, &statement));
}

Expand Down
4 changes: 2 additions & 2 deletions circuits/src/zk_circuits/valid_fee_redemption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ where
EqGadget::constrain_eq(&old_wallet.orders, &new_wallet.orders, cs)?;

// The match fee and managing cluster key should remain the same
EqGadget::constrain_eq(&old_wallet.match_fee, &new_wallet.match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.max_match_fee, &new_wallet.max_match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.managing_cluster, &new_wallet.managing_cluster, cs)?;

// The match key should remain the same, the root key may rotate, and the nonce
Expand Down Expand Up @@ -705,7 +705,7 @@ mod test {

// Modify the match fee
let mut statement = original_statement.clone();
statement.new_wallet_public_shares.match_fee.repr += Scalar::one();
statement.new_wallet_public_shares.max_match_fee.repr += Scalar::one();

assert!(!check_constraints_satisfied(&witness, &statement));

Expand Down
12 changes: 6 additions & 6 deletions circuits/src/zk_circuits/valid_match_settle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,8 +288,8 @@ pub mod test_helpers {
let (_, party1_public_shares) = create_wallet_shares(&wallet2);

// Compute the fee obligations of both parties
let party0_fees = compute_fee_obligation(wallet1.match_fee, o1.side, &match_res);
let party1_fees = compute_fee_obligation(wallet2.match_fee, o2.side, &match_res);
let party0_fees = compute_fee_obligation(wallet1.max_match_fee, o1.side, &match_res);
let party1_fees = compute_fee_obligation(wallet2.max_match_fee, o2.side, &match_res);

// Update the wallets
let mut party0_modified_shares = party0_public_shares.clone();
Expand Down Expand Up @@ -318,14 +318,14 @@ pub mod test_helpers {
order0: o1,
balance0: wallet1.balances[party0_indices.balance_send].clone(),
balance_receive0: wallet1.balances[party0_indices.balance_receive].clone(),
relayer_fee0: wallet1.match_fee,
relayer_fee0: wallet1.max_match_fee,
price0: price,
party0_fees,
amount0,
order1: o2,
balance1: wallet2.balances[party1_indices.balance_send].clone(),
balance_receive1: wallet2.balances[party1_indices.balance_receive].clone(),
relayer_fee1: wallet2.match_fee,
relayer_fee1: wallet2.max_match_fee,
price1: price,
party1_fees,
amount1,
Expand Down Expand Up @@ -354,7 +354,7 @@ pub mod test_helpers {
{
let mut wallet = Wallet {
keys: INITIAL_WALLET.keys.clone(),
match_fee: INITIAL_WALLET.match_fee,
max_match_fee: INITIAL_WALLET.max_match_fee,
managing_cluster: INITIAL_WALLET.managing_cluster,
..Default::default()
};
Expand Down Expand Up @@ -866,7 +866,7 @@ mod tests {

// Modify the match fee
let mut statement = original_statement.clone();
statement.party0_modified_shares.match_fee.repr += Scalar::one();
statement.party0_modified_shares.max_match_fee.repr += Scalar::one();

assert!(!check_constraint_satisfaction::<SizedValidMatchSettle>(
&witness.clone(),
Expand Down
6 changes: 5 additions & 1 deletion circuits/src/zk_circuits/valid_match_settle/multi_prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,11 @@ where
&post_update_shares.managing_cluster,
cs,
)?;
EqGadget::constrain_eq(&pre_update_shares.match_fee, &post_update_shares.match_fee, cs)?;
EqGadget::constrain_eq(
&pre_update_shares.max_match_fee,
&post_update_shares.max_match_fee,
cs,
)?;
EqGadget::constrain_eq(&pre_update_shares.keys, &post_update_shares.keys, cs)?;
EqGadget::constrain_eq(&pre_update_shares.blinder, &post_update_shares.blinder, cs)
}
Expand Down
6 changes: 5 additions & 1 deletion circuits/src/zk_circuits/valid_match_settle/single_prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,11 @@ where
&post_update_shares.managing_cluster,
cs,
)?;
EqGadget::constrain_eq(&pre_update_shares.match_fee, &post_update_shares.match_fee, cs)?;
EqGadget::constrain_eq(
&pre_update_shares.max_match_fee,
&post_update_shares.max_match_fee,
cs,
)?;
EqGadget::constrain_eq(&pre_update_shares.keys, &post_update_shares.keys, cs)?;
EqGadget::constrain_eq(&pre_update_shares.blinder, &post_update_shares.blinder, cs)
}
Expand Down
4 changes: 2 additions & 2 deletions circuits/src/zk_circuits/valid_offline_fee_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ where

// The keys, match fee, and managing cluster should be the same
EqGadget::constrain_eq(&old_wallet.keys, &new_wallet.keys, cs)?;
EqGadget::constrain_eq(&old_wallet.match_fee, &new_wallet.match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.max_match_fee, &new_wallet.max_match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.managing_cluster, &new_wallet.managing_cluster, cs)?;

// Check the balance updates
Expand Down Expand Up @@ -731,7 +731,7 @@ mod test {

// Modify the match fee
let mut statement = original_statement.clone();
statement.updated_wallet_public_shares.match_fee.repr += Scalar::one();
statement.updated_wallet_public_shares.max_match_fee.repr += Scalar::one();

assert!(!check_constraints_satisfied(&statement, &witness));

Expand Down
8 changes: 4 additions & 4 deletions circuits/src/zk_circuits/valid_relayer_fee_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ where

// The keys, match fee and managing cluster key should remain the same
EqGadget::constrain_eq(&old_wallet.keys, &new_wallet.keys, cs)?;
EqGadget::constrain_eq(&old_wallet.match_fee, &new_wallet.match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.max_match_fee, &new_wallet.max_match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.managing_cluster, &new_wallet.managing_cluster, cs)?;

// The balances should remain the same except for the balance that pays the fee
Expand Down Expand Up @@ -242,7 +242,7 @@ where
EqGadget::constrain_eq(&old_wallet.orders, &new_wallet.orders, cs)?;

// The match fee and managing cluster key should remain the same
EqGadget::constrain_eq(&old_wallet.match_fee, &new_wallet.match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.max_match_fee, &new_wallet.max_match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.managing_cluster, &new_wallet.managing_cluster, cs)?;

// The match key must be the same as the old wallet, but the root key may
Expand Down Expand Up @@ -822,7 +822,7 @@ mod test {

// Modify the match fee
let mut statement = original_statement.clone();
statement.sender_updated_public_shares.match_fee.repr += Scalar::one();
statement.sender_updated_public_shares.max_match_fee.repr += Scalar::one();
assert!(!check_constraints_satisfied(&statement, &witness));

// Modify the managing cluster
Expand Down Expand Up @@ -904,7 +904,7 @@ mod test {

// Modify the match fee
let mut statement = original_statement.clone();
statement.recipient_updated_public_shares.match_fee.repr += Scalar::one();
statement.recipient_updated_public_shares.max_match_fee.repr += Scalar::one();
assert!(!check_constraints_satisfied(&statement, &witness));

// Modify the managing cluster
Expand Down
4 changes: 2 additions & 2 deletions circuits/src/zk_circuits/valid_wallet_create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ where
)?;

// Verify that the match fee is a valid fee take
FeeGadget::constrain_valid_fee(wallet.match_fee, cs)?;
FeeGadget::constrain_valid_fee(wallet.max_match_fee, cs)?;

// Verify that the orders and balances are zero'd
Self::verify_zero_wallet(wallet, cs)
Expand Down Expand Up @@ -309,7 +309,7 @@ pub mod tests {
fn test_invalid_match_fee() {
let mut wallet = create_empty_wallet();
let fee_repr = Scalar::from(2u8).pow(FEE_BITS as u64); // max fee plus one
wallet.match_fee = FixedPoint { repr: fee_repr };
wallet.max_match_fee = FixedPoint { repr: fee_repr };

let (witness, statement) = create_witness_statement_from_wallet(&wallet);
assert!(!check_constraint_satisfaction::<SizedWalletCreate>(&witness, &statement));
Expand Down
4 changes: 2 additions & 2 deletions circuits/src/zk_circuits/valid_wallet_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ where
// Note that the keys are allowed to change to enable key rotation. The actual
// wallet transition is authorized by a signature from the old root key
// (checked on-chain) so rotation is protected outside of the circuit
EqGadget::constrain_eq(&old_wallet.match_fee, &new_wallet.match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.max_match_fee, &new_wallet.max_match_fee, cs)?;
EqGadget::constrain_eq(&old_wallet.managing_cluster, &new_wallet.managing_cluster, cs)
}

Expand Down Expand Up @@ -1420,7 +1420,7 @@ mod test {
let old_wallet = INITIAL_WALLET.clone();
let mut new_wallet = INITIAL_WALLET.clone();

new_wallet.match_fee = new_wallet.match_fee + Scalar::one();
new_wallet.max_match_fee = new_wallet.max_match_fee + Scalar::one();

assert!(!constraints_satisfied_on_wallets(
&old_wallet,
Expand Down
2 changes: 1 addition & 1 deletion common/src/types/wallet/match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ impl Wallet {
order_id: &OrderIdentifier,
) -> Result<(), String> {
// Subtract the matched volume from the order
let match_fee = self.match_fee;
let match_fee = self.max_match_fee;
let order = self.get_order_mut(order_id).unwrap();
order.amount =
order.amount.checked_sub(match_res.base_amount).expect("order volume underflow");
Expand Down
2 changes: 1 addition & 1 deletion common/src/types/wallet/mocks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn mock_empty_wallet() -> Wallet {
secret_keys: PrivateKeyChain { sk_root, sk_match, symmetric_key },
},
blinder: Scalar::random(&mut rng),
match_fee: FixedPoint::from_integer(0),
max_match_fee: FixedPoint::from_integer(0),
managing_cluster: managing_cluster_key,
private_shares: SizedWalletShare::from_scalars(&mut iter::repeat_with(|| {
Scalar::random(&mut rng)
Expand Down
Loading
Loading