X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fpayment_tests.rs;h=a65da368709a77aa84147b86dc11e55ae367a558;hb=263d76eb3da4fed149a5a2ec7fbcde701acdffcd;hp=83eb84334a0720671f83cfc419134598ce73a189;hpb=166e0c88e46565d5f65fac83fbb606bbb3414fc3;p=rust-lightning diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index 83eb8433..a65da368 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -367,7 +367,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let persister: test_utils::TestPersister; let new_chain_monitor: test_utils::TestChainMonitor; - let nodes_0_deserialized: ChannelManager; + let nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2; @@ -425,7 +425,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { let (_, nodes_0_deserialized_tmp) = { let mut channel_monitors = HashMap::new(); channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor); - <(BlockHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs { default_config: test_default_channel_config(), keys_manager, fee_estimator: node_cfgs[0].fee_estimator, @@ -485,6 +485,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &htlc_fulfill_updates.update_fulfill_htlcs[0]); check_added_monitors!(nodes[1], 1); commitment_signed_dance!(nodes[1], nodes[2], htlc_fulfill_updates.commitment_signed, false); + expect_payment_forwarded!(nodes[1], nodes[0], nodes[2], None, false, false); if confirm_before_reload { let best_block = nodes[0].blocks.lock().unwrap().last().unwrap().clone(); @@ -501,7 +502,6 @@ 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], nodes[0], nodes[2], None, false, false); if !confirm_before_reload { mine_transaction(&nodes[0], &as_commitment_tx); @@ -576,13 +576,13 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { let first_persister: test_utils::TestPersister; let first_new_chain_monitor: test_utils::TestChainMonitor; - let first_nodes_0_deserialized: ChannelManager; + let first_nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>; let second_persister: test_utils::TestPersister; let second_new_chain_monitor: test_utils::TestChainMonitor; - let second_nodes_0_deserialized: ChannelManager; + let second_nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>; let third_persister: test_utils::TestPersister; let third_new_chain_monitor: test_utils::TestChainMonitor; - let third_nodes_0_deserialized: ChannelManager; + let third_nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>; let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); @@ -633,7 +633,7 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { let mut nodes_0_read = &nodes_0_serialized[..]; let (_, nodes_0_deserialized_tmp) = { - <(BlockHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { + <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_0_read, ChannelManagerReadArgs { default_config: test_default_channel_config(), keys_manager, fee_estimator: node_cfgs[0].fee_estimator, @@ -801,7 +801,7 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let persister: test_utils::TestPersister; let new_chain_monitor: test_utils::TestChainMonitor; - let nodes_0_deserialized: ChannelManager; + let nodes_0_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()); @@ -917,7 +917,7 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co let (_, nodes_0_deserialized_tmp) = { let mut channel_monitors = HashMap::new(); channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor); - <(BlockHash, ChannelManager)> + <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)> ::read(&mut io::Cursor::new(&chan_manager_serialized.0[..]), ChannelManagerReadArgs { default_config: Default::default(), keys_manager, @@ -974,7 +974,7 @@ fn test_fulfill_restart_failure() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let persister: test_utils::TestPersister; let new_chain_monitor: test_utils::TestChainMonitor; - let nodes_1_deserialized: ChannelManager; + let nodes_1_deserialized: ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>; let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2; @@ -1008,7 +1008,7 @@ fn test_fulfill_restart_failure() { let (_, nodes_1_deserialized_tmp) = { let mut channel_monitors = HashMap::new(); channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor); - <(BlockHash, ChannelManager)> + <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)> ::read(&mut io::Cursor::new(&chan_manager_serialized.0[..]), ChannelManagerReadArgs { default_config: Default::default(), keys_manager, @@ -1326,3 +1326,62 @@ fn claimed_send_payment_idempotent() { pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, second_payment_hash, second_payment_secret); claim_payment(&nodes[0], &[&nodes[1]], second_payment_preimage); } + +#[test] +fn abandoned_send_payment_idempotent() { + // Tests that `send_payment` (and friends) allow duplicate PaymentIds immediately after + // abandon_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 nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2; + + let (route, second_payment_hash, second_payment_preimage, second_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100_000); + let (_, first_payment_hash, _, payment_id) = send_along_route(&nodes[0], route.clone(), &[&nodes[1]], 100_000); + + macro_rules! check_send_rejected { + () => { + // If we try to resend a new payment with a different payment_hash but with the same + // payment_id, it should be rejected. + let send_result = nodes[0].node.send_payment(&route, second_payment_hash, &Some(second_payment_secret), payment_id); + match send_result { + Err(PaymentSendFailure::ParameterError(APIError::RouteError { err: "Payment already in progress" })) => {}, + _ => panic!("Unexpected send result: {:?}", send_result), + } + + // Further, if we try to send a spontaneous payment with the same payment_id it should + // also be rejected. + let send_result = nodes[0].node.send_spontaneous_payment(&route, None, payment_id); + match send_result { + Err(PaymentSendFailure::ParameterError(APIError::RouteError { err: "Payment already in progress" })) => {}, + _ => panic!("Unexpected send result: {:?}", send_result), + } + } + } + + check_send_rejected!(); + + nodes[1].node.fail_htlc_backwards(&first_payment_hash); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(nodes[1], [HTLCDestination::FailedPayment { payment_hash: first_payment_hash }]); + + pass_failed_payment_back_no_abandon(&nodes[0], &[&[&nodes[1]]], false, first_payment_hash); + check_send_rejected!(); + + // Until we abandon the payment, no matter how many timer ticks pass, we still cannot reuse the + // PaymentId. + for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS { + nodes[0].node.timer_tick_occurred(); + } + check_send_rejected!(); + + nodes[0].node.abandon_payment(payment_id); + get_event!(nodes[0], Event::PaymentFailed); + + // However, we can reuse the PaymentId immediately after we `abandon_payment`. + nodes[0].node.send_payment(&route, second_payment_hash, &Some(second_payment_secret), payment_id).unwrap(); + check_added_monitors!(nodes[0], 1); + pass_along_route(&nodes[0], &[&[&nodes[1]]], 100_000, second_payment_hash, second_payment_secret); + claim_payment(&nodes[0], &[&nodes[1]], second_payment_preimage); +}