Skip to content

Commit

Permalink
Merge pull request #395 from getlipa/feature/enable-mpp-payments
Browse files Browse the repository at this point in the history
Enable MPP
  • Loading branch information
gcomte authored May 30, 2023
2 parents cbe9e5b + 279dd02 commit 3af9cb7
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 30 deletions.
3 changes: 2 additions & 1 deletion eel/src/invoice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ pub(crate) async fn create_invoice(
.amount_milli_satoshis(amount_msat)
.current_timestamp()
.expiry_time(Duration::from_secs(10 * 60))
.min_final_cltv_expiry_delta(144);
.min_final_cltv_expiry_delta(144)
.basic_mpp();
for private_route in private_routes {
builder = builder.private_route(private_route);
}
Expand Down
5 changes: 3 additions & 2 deletions eel/tests/persistence_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,10 @@ mod persistence_test {

let invoice = node
.create_invoice(payment_amount, "test".to_string(), String::new())
.unwrap();
.unwrap()
.to_string();

nigiri::pay_invoice(paying_node, &invoice.to_string()).unwrap();
nigiri::pay_invoice(paying_node, &invoice).unwrap();

assert_payment_received(node, initial_balance + payment_amount - lsp_fee);
}
Expand Down
14 changes: 8 additions & 6 deletions eel/tests/rapid_gossip_sync_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ mod rapid_gossip_sync_test {
// Pay from NigiriCln to 3L to create outbound liquidity
let invoice_cln = node
.create_invoice(HUNDRED_K_SATS, "test".to_string(), String::new())
.unwrap();
assert!(invoice_cln.to_string().starts_with("lnbc"));
.unwrap()
.to_string();
assert!(invoice_cln.starts_with("lnbc"));

nigiri::cln_pay_invoice(NodeInstance::NigiriCln, &invoice_cln.to_string()).unwrap();
nigiri::cln_pay_invoice(NodeInstance::NigiriCln, &invoice_cln).unwrap();

assert_eq!(
node.get_node_info().channels_info.local_balance_msat,
Expand Down Expand Up @@ -133,10 +134,11 @@ mod rapid_gossip_sync_test {
// Pay from NigiriLnd to 3L to create outbound liquidity (LspdLnd -> NigiriLnd)
let invoice_lnd = node
.create_invoice(HUNDRED_K_SATS, "test".to_string(), String::new())
.unwrap();
assert!(invoice_lnd.to_string().starts_with("lnbc"));
.unwrap()
.to_string();
assert!(invoice_lnd.starts_with("lnbc"));

nigiri::lnd_pay_invoice(NodeInstance::NigiriLnd, &invoice_lnd.to_string()).unwrap();
nigiri::lnd_pay_invoice(NodeInstance::NigiriLnd, &invoice_lnd).unwrap();

// wait for the RGS server to learn about the new channels (100 seconds isn't enough)
sleep(Duration::from_secs(150));
Expand Down
21 changes: 19 additions & 2 deletions eel/tests/receiving_payments_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ mod receiving_payments_test {
const TWO_K_SATS: u64 = 2_000_000;
const TEN_K_SATS: u64 = 10_000_000;
const TWENTY_K_SATS: u64 = 20_000_000;
const TWO_HUNDRED_K_SATS: u64 = 200_000_000;
const HALF_M_SATS: u64 = 500_000_000;
const ONE_M_SATS: u64 = 1_000_000_000;
const TWO_M_SATS: u64 = 2_000_000_000;

// The amount of sats the LSP provides to the user as inbound capacity.
// See https://github.com/getlipa/lipa-lightning-lib/blob/b821162df982799c497e083e9707aa421aee43a8/lspd/compose.yaml#LL63C44-L63C46
Expand Down Expand Up @@ -164,14 +167,28 @@ mod receiving_payments_test {

// Add 2M sats of inbound capacity - More than the max allowed receive amount
let node_id = node.get_node_info().node_pubkey.to_hex();
assert_eq!(nigiri::get_number_of_txs_in_mempool(), Ok::<u64, String>(2)); // 2 times jit channel open flow (zero-conf)
let _ = nigiri::lnd_node_open_channel(NodeInstance::LspdLnd, &node_id, false).unwrap(); // 1M sats
let _ = nigiri::lnd_node_open_channel(NodeInstance::LspdLnd, &node_id, false).unwrap(); // 1M sats
wait_for_eq!(nigiri::get_number_of_txs_in_mempool(), Ok::<u64, String>(4));
try_cmd_repeatedly!(nigiri::mine_blocks, N_RETRIES, HALF_SEC, 10);
wait_for!(node.get_node_info().channels_info.inbound_capacity_msat > 2_000_000_000);
wait_for!(node.get_node_info().channels_info.inbound_capacity_msat > TWO_M_SATS);

assert_high_inbound_capacity(&node);

// todo also test multipath payments
// test receiving MPP
let channels_info = node.get_node_info().channels_info;
let initial_balance = channels_info.local_balance_msat;
let payment_amount = channels_info.inbound_capacity_msat - TWO_HUNDRED_K_SATS; // todo use full inbound capacity as soon as the number is accurate

assert!(payment_amount > ONE_M_SATS); // Biggest channel is 1M sats; This payment involves transferring through more than 1 channel
let invoice = issue_invoice(&node, payment_amount);
wait_for!(nigiri::lnd_pay_invoice(NodeInstance::LspdLnd, &invoice).is_ok());

assert_eq!(
node.get_node_info().channels_info.local_balance_msat,
initial_balance + payment_amount
);
}
}

Expand Down
79 changes: 66 additions & 13 deletions eel/tests/sending_payments_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ mod sending_payments_test {
use crate::setup::{mocked_storage_node, setup_outbound_capacity};
use crate::setup_env::nigiri;
use crate::setup_env::nigiri::NodeInstance::{LspdLnd, NigiriCln, NigiriLnd};
use crate::wait_for_eq;
use crate::{wait_for, wait_for_eq};

const PAYMENT_AMOUNT: u64 = 1_000_000;
const SECONDS_IN_AN_HOUR: u64 = 3600;
const DESCRIPTION_SAMPLE: &str = "Luke, I Am Your Father";

const THOUSAND_SATS: u64 = 1_000_000;
const FIFE_K_SATS: u64 = 5_000_000;
const FOURTY_K_SATS: u64 = 40_000_000;
const NINE_HUNDRED_K_SATS: u64 = 900_000_000;
const ONE_M_SATS: u64 = 1_000_000_000;
const MORE_THAN_ONE_M_SATS: u64 = 1_500_000_000;

#[test]
#[file_serial(key, "/tmp/3l-int-tests-lock")]
Expand All @@ -25,15 +33,15 @@ mod sending_payments_test {
setup_outbound_capacity(&node);

// Test vanilla payment
let invoice = nigiri::issue_invoice(LspdLnd, "test", PAYMENT_AMOUNT, 3600).unwrap();
let invoice = nigiri::issue_invoice(LspdLnd, "test", FIFE_K_SATS, 3600).unwrap();

let initial_balance = nigiri::query_node_balance(LspdLnd).unwrap();

node.pay_invoice(invoice, String::new()).unwrap();

wait_for_eq!(
nigiri::query_node_balance(LspdLnd).unwrap() - initial_balance,
PAYMENT_AMOUNT
FIFE_K_SATS
);

// Test a regular payment but using an invoice that has no amount specified
Expand Down Expand Up @@ -61,12 +69,12 @@ mod sending_payments_test {

let initial_balance = nigiri::query_node_balance(LspdLnd).unwrap();

node.pay_open_invoice(invoice, PAYMENT_AMOUNT, String::new())
node.pay_open_invoice(invoice, FIFE_K_SATS, String::new())
.unwrap();

wait_for_eq!(
nigiri::query_node_balance(LspdLnd).unwrap() - initial_balance,
PAYMENT_AMOUNT
FIFE_K_SATS
);

// Test paying open invoices specifying 0 as the payment amount
Expand All @@ -89,11 +97,11 @@ mod sending_payments_test {
);

// Test paying open invoices using an invoice with a specified amount
let invoice = nigiri::issue_invoice(LspdLnd, "test", PAYMENT_AMOUNT, 3600).unwrap();
let invoice = nigiri::issue_invoice(LspdLnd, "test", FIFE_K_SATS, 3600).unwrap();

let initial_balance = nigiri::query_node_balance(LspdLnd).unwrap();

let payment_result = node.pay_open_invoice(invoice, PAYMENT_AMOUNT, String::new());
let payment_result = node.pay_open_invoice(invoice, FIFE_K_SATS, String::new());
assert!(matches!(
payment_result,
Err(perro::Error::InvalidInput { .. })
Expand All @@ -106,12 +114,57 @@ mod sending_payments_test {
nigiri::query_node_balance(LspdLnd).unwrap()
);

// todo also test multipath payments
}
// test sending mpp
let channels_info = node.get_node_info().channels_info;
assert_eq!(channels_info.num_usable_channels, 1);
assert_eq!(channels_info.local_balance_msat, FOURTY_K_SATS);
assert_eq!(channels_info.total_channel_capacities_msat, ONE_M_SATS);

const THOUSAND_SATS: u64 = 1_000_000;
const SECONDS_IN_AN_HOUR: u64 = 3600;
const DESCRIPTION_SAMPLE: &str = "Luke, I Am Your Father";
let invoice = node
.create_invoice(NINE_HUNDRED_K_SATS, "test".to_string(), String::new())
.unwrap()
.to_string();
assert!(invoice.starts_with("lnbc"));

nigiri::pay_invoice(LspdLnd, &invoice).unwrap();
assert_eq!(
node.get_node_info().channels_info.local_balance_msat,
NINE_HUNDRED_K_SATS + FOURTY_K_SATS
);

nigiri::initiate_channel_from_remote(node.get_node_info().node_pubkey, LspdLnd);

wait_for_eq!(node.get_node_info().channels_info.num_channels, 2);
wait_for_eq!(
node.get_node_info()
.channels_info
.total_channel_capacities_msat,
ONE_M_SATS * 2
);

let invoice = node
.create_invoice(NINE_HUNDRED_K_SATS, "test".to_string(), String::new())
.unwrap()
.to_string();
assert!(invoice.starts_with("lnbc"));

wait_for!(nigiri::pay_invoice(LspdLnd, &invoice).is_ok());
assert_eq!(
node.get_node_info().channels_info.local_balance_msat,
NINE_HUNDRED_K_SATS + NINE_HUNDRED_K_SATS + FOURTY_K_SATS
);

// Node has 2 channels of 1M SAT each. Paying 1.5M SAT requires sending through both of them
let initial_balance = nigiri::query_node_balance(LspdLnd).unwrap();
let invoice = nigiri::issue_invoice(LspdLnd, "MPP", MORE_THAN_ONE_M_SATS, 3600).unwrap();

node.pay_invoice(invoice, String::new()).unwrap();

wait_for_eq!(
nigiri::query_node_balance(LspdLnd).unwrap(),
initial_balance + MORE_THAN_ONE_M_SATS
);
}

fn invoice_decode_test(node: &LightningNode) {
// Test invoice from CLN
Expand Down
15 changes: 9 additions & 6 deletions eel/tests/setup/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ pub fn setup_outbound_capacity(node: &LightningNode) {

let invoice = node
.create_invoice(REBALANCE_AMOUNT, "test".to_string(), String::new())
.unwrap();
assert!(invoice.to_string().starts_with("lnbc"));
.unwrap()
.to_string();
assert!(invoice.starts_with("lnbc"));

nigiri::pay_invoice(LspdLnd, &invoice.to_string()).unwrap();
nigiri::pay_invoice(LspdLnd, &invoice).unwrap();

assert_eq!(
node.get_node_info().channels_info.local_balance_msat,
Expand All @@ -122,9 +123,11 @@ pub fn setup_outbound_capacity(node: &LightningNode) {
pub fn issue_invoice(node: &LightningNode, payment_amount: u64) -> String {
let invoice = node
.create_invoice(payment_amount, "test".to_string(), String::new())
.unwrap();
assert!(invoice.to_string().starts_with("lnbc"));
invoice.to_string()
.unwrap()
.to_string();
assert!(invoice.starts_with("lnbc"));

invoice
}

#[allow(dead_code)]
Expand Down
5 changes: 5 additions & 0 deletions eel/tests/setup_env/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,12 @@ pub mod nigiri {
}

pub fn initiate_channel_from_remote(node_pubkey: PublicKey, remote_node: NodeInstance) {
let txs_before = get_number_of_txs_in_mempool().unwrap();
lnd_node_open_channel(remote_node, &node_pubkey.to_hex(), false).unwrap();
wait_for_eq!(
nigiri::get_number_of_txs_in_mempool(),
Ok::<u64, String>(txs_before + 1)
);
try_cmd_repeatedly!(nigiri::mine_blocks, N_RETRIES, HALF_SEC, 10);

wait_for!(is_channel_confirmed(remote_node, &node_pubkey.to_hex()));
Expand Down

0 comments on commit 3af9cb7

Please sign in to comment.