Skip to content

Commit

Permalink
Merge pull request #1189 from MutinyWallet/pref-private-gateways
Browse files Browse the repository at this point in the history
Prefer gateways that support private payments
  • Loading branch information
TonyGiorgio authored Jun 12, 2024
2 parents 2ba3942 + 1f5b765 commit dc03da6
Showing 1 changed file with 52 additions and 17 deletions.
69 changes: 52 additions & 17 deletions mutiny-core/src/federation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use fedimint_ln_client::{
LightningOperationMetaVariant, LnPayState, LnReceiveState,
};
use fedimint_ln_common::lightning_invoice::{Bolt11InvoiceDescription, Description, RoutingFees};
use fedimint_ln_common::{LightningCommonInit, LightningGateway};
use fedimint_ln_common::{LightningCommonInit, LightningGateway, LightningGatewayAnnouncement};
use fedimint_mint_client::MintClientInit;
use fedimint_wallet_client::{
WalletClientInit, WalletClientModule, WalletCommonInit, WalletOperationMeta, WithdrawState,
Expand Down Expand Up @@ -1034,10 +1034,10 @@ fn sats_round_up(amount: &Amount) -> u64 {

// Get a preferred gateway from a federation
fn get_gateway_preference(
gateways: Vec<fedimint_ln_common::LightningGatewayAnnouncement>,
gateways: Vec<LightningGatewayAnnouncement>,
federation_id: FederationId,
) -> Option<fedimint_ln_common::bitcoin::secp256k1::PublicKey> {
let mut active_choice: Option<fedimint_ln_common::bitcoin::secp256k1::PublicKey> = None;
let mut active_choice: Option<LightningGatewayAnnouncement> = None;

let signet_gateway_id =
fedimint_ln_common::bitcoin::secp256k1::PublicKey::from_str(SIGNET_GATEWAY)
Expand All @@ -1063,26 +1063,25 @@ fn get_gateway_preference(

// if vetted, set up as current active choice
if g.vetted {
active_choice = Some(g_id);
continue;
active_choice = Some(g.clone());
break;
}

// if not vetted, make sure fee is high enough
if active_choice.is_none() {
let fees = g.info.fees;
if fees.base_msat >= 1_000 && fees.proportional_millionths >= 100 {
active_choice = Some(g_id);
continue;
let fees = g.info.fees;
if fees.base_msat >= 1_000 && fees.proportional_millionths >= 100 {
// only select gateways that support private payments, unless we don't have a gateway
if g.info.supports_private_payments || active_choice.is_none() {
active_choice = Some(g.clone());
}
}
}

// fallback to any gateway if none fit our criteria
if active_choice.is_none() {
active_choice = gateways.first().map(|g| g.info.gateway_id);
match active_choice {
None => gateways.first().map(|g| g.info.gateway_id),
Some(g) => Some(g.info.gateway_id),
}

active_choice
}

// A federation private key will be derived from
Expand Down Expand Up @@ -1907,7 +1906,6 @@ fn fedimint_mnemonic_generation() {
fn gateway_preference() {
use fedimint_core::util::SafeUrl;
use fedimint_ln_common::bitcoin::secp256k1::PublicKey;
use fedimint_ln_common::LightningGatewayAnnouncement;

use super::*;

Expand All @@ -1923,6 +1921,11 @@ fn gateway_preference() {
let unvetted_gateway_high_fee_pubkey =
PublicKey::from_str(UNVETTED_GATEWAY_KEY_HIGH_FEE).unwrap();

const UNVETTED_GATEWAY_KEY_HIGH_FEE_NO_PRIVATE: &str =
"033d8656219478701227199cbd6f670335c8d408a92ae88b962c49d4dc0e83e025";
let unvetted_gateway_high_fee_no_private_pubkey =
PublicKey::from_str(UNVETTED_GATEWAY_KEY_HIGH_FEE_NO_PRIVATE).unwrap();

const UNVETTED_GATEWAY_KEY_LOW_FEE: &str =
"02e6642fd69bd211f93f7f1f36ca51a26a5290eb2dd1b0d8279a87bb0d480c8443";
let unvetted_gateway_low_fee_pubkey =
Expand Down Expand Up @@ -1997,8 +2000,8 @@ fn gateway_preference() {
api: SafeUrl::parse("http://localhost:8080").unwrap(),
route_hints: vec![],
fees: RoutingFees {
base_msat: 200,
proportional_millionths: 20,
base_msat: 1_000,
proportional_millionths: 100,
},
gateway_id: unvetted_gateway_high_fee_pubkey,
supports_private_payments: true,
Expand All @@ -2007,6 +2010,25 @@ fn gateway_preference() {
ttl: Duration::from_secs(3600),
};

let unvetted_gateway_high_fee_no_private = LightningGatewayAnnouncement {
info: LightningGateway {
mint_channel_id: 12345,
gateway_redeem_key: random_key,
node_pub_key: unvetted_gateway_high_fee_no_private_pubkey,
lightning_alias: "Unvetted Gateway".to_string(),
api: SafeUrl::parse("http://localhost:8080").unwrap(),
route_hints: vec![],
fees: RoutingFees {
base_msat: 1_000,
proportional_millionths: 100,
},
gateway_id: unvetted_gateway_high_fee_no_private_pubkey,
supports_private_payments: false,
},
vetted: false,
ttl: Duration::from_secs(3600),
};

let unvetted_gateway_low_fee = LightningGatewayAnnouncement {
info: LightningGateway {
mint_channel_id: 12345,
Expand All @@ -2031,6 +2053,7 @@ fn gateway_preference() {
mainnet_gateway.clone(),
vetted_gateway.clone(),
unvetted_gateway_low_fee.clone(),
unvetted_gateway_high_fee_no_private.clone(),
unvetted_gateway_high_fee.clone(),
];

Expand All @@ -2056,6 +2079,7 @@ fn gateway_preference() {
// Test that the method returns the first vetted gateway if none of the gateways match the federation ID
let gateways = vec![
unvetted_gateway_low_fee.clone(),
unvetted_gateway_high_fee_no_private.clone(),
unvetted_gateway_high_fee.clone(),
vetted_gateway.clone(),
];
Expand All @@ -2064,6 +2088,17 @@ fn gateway_preference() {
Some(vetted_gateway_pubkey)
);

// Test that the method returns the private high fee gateway if none of the gateways match the federation ID and no vetted gateways
let gateways = vec![
unvetted_gateway_low_fee.clone(),
unvetted_gateway_high_fee_no_private.clone(),
unvetted_gateway_high_fee.clone(),
];
assert_eq!(
get_gateway_preference(gateways, random_federation_id),
Some(unvetted_gateway_high_fee_pubkey)
);

// Test that the method returns the first when given a non-matching federation ID and gateway ID,
// and no unvetted gateways with a high enough fee
let gateways = vec![
Expand Down

0 comments on commit dc03da6

Please sign in to comment.