X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fpayment_tests.rs;h=46d5d22b49a07112f680086c3e701d902088fcd1;hb=637fb88037fa329363e4b6462e9ad01f25cb4e41;hp=f685c375f38913c6fbedc9ce40a064d7e7373598;hpb=081ce7c843713a42803097a6d2dcf3631778beda;p=rust-lightning diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index f685c375..46d5d22b 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -14,11 +14,12 @@ use chain::{ChannelMonitorUpdateErr, Confirm, Listen, Watch}; use chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor, LATENCY_GRACE_PERIOD_BLOCKS}; use chain::transaction::OutPoint; -use ln::{PaymentPreimage, PaymentHash}; -use ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, ChannelManagerReadArgs, PaymentId, PaymentSendFailure}; -use ln::features::InitFeatures; +use chain::keysinterface::KeysInterface; +use ln::channelmanager::{BREAKDOWN_TIMEOUT, ChannelManager, ChannelManagerReadArgs, MPP_TIMEOUT_TICKS, PaymentId, PaymentSendFailure}; +use ln::features::{InitFeatures, InvoiceFeatures}; use ln::msgs; -use ln::msgs::{ChannelMessageHandler, ErrorAction}; +use ln::msgs::ChannelMessageHandler; +use routing::router::{PaymentParameters, get_route}; use util::events::{ClosureReason, Event, MessageSendEvent, MessageSendEventsProvider}; use util::test_utils; use util::errors::APIError; @@ -26,9 +27,8 @@ use util::enforcing_trait_impls::EnforcingSigner; use util::ser::{ReadableArgs, Writeable}; use io; -use bitcoin::hashes::sha256::Hash as Sha256; -use bitcoin::hashes::Hash; use bitcoin::{Block, BlockHeader, BlockHash}; +use bitcoin::network::constants::Network; use prelude::*; @@ -70,7 +70,7 @@ fn retry_single_path_payment() { check_added_monitors!(nodes[1], 1); nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[1], htlc_updates.commitment_signed, false); - expect_payment_failed!(nodes[0], payment_hash, false); + expect_payment_failed_conditions!(nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain()); // Rebalance the channel so the retry succeeds. send_payment(&nodes[2], &vec!(&nodes[1])[..], 3_000_000); @@ -173,7 +173,7 @@ fn mpp_retry() { check_added_monitors!(nodes[2], 1); nodes[0].node.handle_update_fail_htlc(&nodes[2].node.get_our_node_id(), &htlc_updates.update_fail_htlcs[0]); commitment_signed_dance!(nodes[0], nodes[2], htlc_updates.commitment_signed, false); - expect_payment_failed!(nodes[0], payment_hash, false); + expect_payment_failed_conditions!(nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain()); // Rebalance the channel so the second half of the payment can succeed. send_payment(&nodes[3], &vec!(&nodes[2])[..], 1_500_000); @@ -199,6 +199,78 @@ fn mpp_retry() { claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); } +fn do_mpp_receive_timeout(send_partial_mpp: bool) { + let chanmon_cfgs = create_chanmon_cfgs(4); + let node_cfgs = create_node_cfgs(4, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]); + let nodes = create_network(4, &node_cfgs, &node_chanmgrs); + + let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; + let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; + let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; + let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known()).0.contents.short_channel_id; + + let (mut route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[3], 100_000); + let path = route.paths[0].clone(); + route.paths.push(path); + route.paths[0][0].pubkey = nodes[1].node.get_our_node_id(); + route.paths[0][0].short_channel_id = chan_1_id; + route.paths[0][1].short_channel_id = chan_3_id; + route.paths[1][0].pubkey = nodes[2].node.get_our_node_id(); + route.paths[1][0].short_channel_id = chan_2_id; + route.paths[1][1].short_channel_id = chan_4_id; + + // Initiate the MPP payment. + let _ = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + check_added_monitors!(nodes[0], 2); // one monitor per path + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 2); + + // Pass half of the payment along the first path. + pass_along_path(&nodes[0], &[&nodes[1], &nodes[3]], 200_000, payment_hash, Some(payment_secret), events.remove(0), false, None); + + if send_partial_mpp { + // Time out the partial MPP + for _ in 0..MPP_TIMEOUT_TICKS { + nodes[3].node.timer_tick_occurred(); + } + + // Failed HTLC from node 3 -> 1 + expect_pending_htlcs_forwardable!(nodes[3]); + let htlc_fail_updates_3_1 = get_htlc_update_msgs!(nodes[3], nodes[1].node.get_our_node_id()); + assert_eq!(htlc_fail_updates_3_1.update_fail_htlcs.len(), 1); + nodes[1].node.handle_update_fail_htlc(&nodes[3].node.get_our_node_id(), &htlc_fail_updates_3_1.update_fail_htlcs[0]); + check_added_monitors!(nodes[3], 1); + commitment_signed_dance!(nodes[1], nodes[3], htlc_fail_updates_3_1.commitment_signed, false); + + // Failed HTLC from node 1 -> 0 + expect_pending_htlcs_forwardable!(nodes[1]); + let htlc_fail_updates_1_0 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); + assert_eq!(htlc_fail_updates_1_0.update_fail_htlcs.len(), 1); + nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_fail_updates_1_0.update_fail_htlcs[0]); + check_added_monitors!(nodes[1], 1); + commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates_1_0.commitment_signed, false); + + expect_payment_failed_conditions!(nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain().expected_htlc_error_data(23, &[][..])); + } else { + // Pass half of the payment along the second path. + pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 200_000, payment_hash, Some(payment_secret), events.remove(0), true, None); + + // Even after MPP_TIMEOUT_TICKS we should not timeout the MPP if we have all the parts + for _ in 0..MPP_TIMEOUT_TICKS { + nodes[3].node.timer_tick_occurred(); + } + + claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage); + } +} + +#[test] +fn mpp_receive_timeout() { + do_mpp_receive_timeout(true); + do_mpp_receive_timeout(false); +} + #[test] fn retry_expired_payment() { let chanmon_cfgs = create_chanmon_cfgs(3); @@ -377,12 +449,12 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { assert_eq!(as_broadcasted_txn[0], as_commitment_tx); nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known()}); + nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known(), remote_network_address: None }); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); // Now nodes[1] should send a channel reestablish, which nodes[0] will respond to with an // error, as the channel has hit the chain. - nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known()}); + nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known(), remote_network_address: None }); let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id()); nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish); let as_err = nodes[0].node.get_and_clear_pending_msg_events(); @@ -423,9 +495,11 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { let bs_htlc_claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); assert_eq!(bs_htlc_claim_txn.len(), 1); check_spends!(bs_htlc_claim_txn[0], as_commitment_tx); - expect_payment_forwarded!(nodes[1], None, false); + expect_payment_forwarded!(nodes[1], nodes[0], None, false); - mine_transaction(&nodes[0], &as_commitment_tx); + if !confirm_before_reload { + mine_transaction(&nodes[0], &as_commitment_tx); + } mine_transaction(&nodes[0], &bs_htlc_claim_txn[0]); expect_payment_sent!(nodes[0], payment_preimage_1); connect_blocks(&nodes[0], TEST_FINAL_CLTV*4 + 20); @@ -440,7 +514,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { confirm_transaction(&nodes[0], &as_htlc_timeout_txn[0]); } nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear(); - expect_payment_failed!(nodes[0], payment_hash, false); + expect_payment_failed_conditions!(nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain()); // Finally, retry the payment (which was reloaded from the ChannelMonitor when nodes[0] was // reloaded) via a route over the new channel, which work without issue and eventually be @@ -517,6 +591,10 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co check_added_monitors!(nodes[1], 1); check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed); let claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0); + assert_eq!(claim_txn.len(), 3); + check_spends!(claim_txn[0], node_txn[1]); + check_spends!(claim_txn[1], funding_tx); + check_spends!(claim_txn[2], claim_txn[1]); header.prev_blockhash = nodes[0].best_block_hash(); connect_block(&nodes[0], &Block { header, txdata: vec![node_txn[1].clone()]}); @@ -526,7 +604,7 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co } header.prev_blockhash = nodes[0].best_block_hash(); - let claim_block = Block { header, txdata: if payment_timeout { timeout_txn } else { claim_txn } }; + let claim_block = Block { header, txdata: if payment_timeout { timeout_txn } else { vec![claim_txn[0].clone()] } }; if payment_timeout { assert!(confirm_commitment_tx); // Otherwise we're spending below our CSV! @@ -664,7 +742,7 @@ fn test_fulfill_restart_failure() { check_added_monitors!(nodes[1], 1); let htlc_fulfill_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); - expect_payment_sent!(nodes[0], payment_preimage); + expect_payment_sent_without_paths!(nodes[0], payment_preimage); // Now reload nodes[1]... persister = test_utils::TestPersister::new(); @@ -707,4 +785,38 @@ fn test_fulfill_restart_failure() { commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates.commitment_signed, false); // nodes[0] shouldn't generate any events here, while it just got a payment failure completion // it had already considered the payment fulfilled, and now they just got free money. + assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); +} + +#[test] +fn get_ldk_payment_preimage() { + // Ensure that `ChannelManager::get_payment_preimage` can successfully be used to claim a payment. + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); + let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); + create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); + + let amt_msat = 60_000; + let expiry_secs = 60 * 60; + let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(amt_msat), expiry_secs).unwrap(); + + let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()) + .with_features(InvoiceFeatures::known()); + let scorer = test_utils::TestScorer::with_penalty(0); + let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet); + let random_seed_bytes = keys_manager.get_secure_random_bytes(); + let route = get_route( + &nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), + Some(&nodes[0].node.list_usable_channels().iter().collect::>()), + amt_msat, TEST_FINAL_CLTV, nodes[0].logger, &scorer, &random_seed_bytes).unwrap(); + let _payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + check_added_monitors!(nodes[0], 1); + + // Make sure to use `get_payment_preimage` + let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap(); + let mut events = nodes[0].node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + pass_along_path(&nodes[0], &[&nodes[1]], amt_msat, payment_hash, Some(payment_secret), events.pop().unwrap(), true, Some(payment_preimage)); + claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, payment_preimage); }