X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fpayment_tests.rs;h=60310e9a3df33aa445af24c33fd574753d468e98;hb=46333affb9538fcaf00ffce86b78dc2cf80b8c79;hp=c22f4611c34438b80f3071de6635b9ae43410402;hpb=a257906743d528c32c862b053b652d4b728aa990;p=rust-lightning diff --git a/lightning/src/ln/payment_tests.rs b/lightning/src/ln/payment_tests.rs index c22f4611..60310e9a 100644 --- a/lightning/src/ln/payment_tests.rs +++ b/lightning/src/ln/payment_tests.rs @@ -12,28 +12,27 @@ //! payments thereafter. use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch}; -use crate::chain::channelmonitor::{ANTI_REORG_DELAY, ChannelMonitor, LATENCY_GRACE_PERIOD_BLOCKS}; +use crate::chain::channelmonitor::{ANTI_REORG_DELAY, LATENCY_GRACE_PERIOD_BLOCKS}; use crate::chain::transaction::OutPoint; use crate::chain::keysinterface::KeysInterface; use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS; -use crate::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChannelManager, ChannelManagerReadArgs, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure}; +use crate::ln::channelmanager::{self, BREAKDOWN_TIMEOUT, ChannelManager, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, IDEMPOTENCY_TIMEOUT_TICKS}; use crate::ln::msgs; use crate::ln::msgs::ChannelMessageHandler; use crate::routing::router::{PaymentParameters, get_route}; use crate::util::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider}; use crate::util::test_utils; use crate::util::errors::APIError; -use crate::util::enforcing_trait_impls::EnforcingSigner; -use crate::util::ser::{ReadableArgs, Writeable}; -use crate::io; +use crate::util::ser::Writeable; -use bitcoin::{Block, BlockHeader, BlockHash, TxMerkleNode}; +use bitcoin::{Block, BlockHeader, TxMerkleNode}; use bitcoin::hashes::Hash; use bitcoin::network::constants::Network; use crate::prelude::*; use crate::ln::functional_test_utils::*; +use crate::routing::gossip::NodeId; #[test] fn retry_single_path_payment() { @@ -53,7 +52,8 @@ fn retry_single_path_payment() { send_payment(&nodes[1], &vec!(&nodes[2])[..], 2_000_000); // Make sure the payment fails on the first hop. - let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + let payment_id = PaymentId(payment_hash.0); + nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), payment_id).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -138,7 +138,8 @@ fn mpp_retry() { route.paths[1][1].short_channel_id = chan_4_update.contents.short_channel_id; // Initiate the MPP payment. - let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + let payment_id = PaymentId(payment_hash.0); + nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), payment_id).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); @@ -222,7 +223,7 @@ fn do_mpp_receive_timeout(send_partial_mpp: bool) { route.paths[1][1].short_channel_id = chan_4_update.contents.short_channel_id; // Initiate the MPP payment. - let _ = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).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); @@ -290,7 +291,7 @@ fn retry_expired_payment() { send_payment(&nodes[1], &vec!(&nodes[2])[..], 2_000_000); // Make sure the payment fails on the first hop. - let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -314,7 +315,7 @@ fn retry_expired_payment() { connect_blocks(&nodes[0], 3); // Retry the payment and make sure it errors as expected. - if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, payment_id) { + if let Err(PaymentSendFailure::ParameterError(APIError::APIMisuseError { err })) = nodes[0].node.retry_payment(&route, PaymentId(payment_hash.0)) { assert!(err.contains("not found")); } else { panic!("Unexpected error"); @@ -341,7 +342,7 @@ fn no_pending_leak_on_initial_send_failure() { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); nodes[1].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); - unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)), + unwrap_send_err!(nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)), true, APIError::ChannelUnavailable { ref err }, assert_eq!(err, "Peer for first hop currently disconnected/pending monitor update!")); @@ -365,7 +366,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; @@ -378,7 +379,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // out and retry. let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 1_000_000); let (payment_preimage_1, payment_hash_1, _, payment_id_1) = send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000); - let payment_id = nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap(); + nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -407,39 +408,8 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { // The ChannelMonitor should always be the latest version, as we're required to persist it // during the `commitment_signed_dance!()`. - let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap(); - - persister = test_utils::TestPersister::new(); - let keys_manager = &chanmon_cfgs[0].keys_manager; - new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), nodes[0].logger, node_cfgs[0].fee_estimator, &persister, keys_manager); - nodes[0].chain_monitor = &new_chain_monitor; - let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; - let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read( - &mut chan_0_monitor_read, keys_manager).unwrap(); - assert!(chan_0_monitor_read.is_empty()); - - let mut nodes_0_read = &nodes_0_serialized[..]; - 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 { - default_config: test_default_channel_config(), - keys_manager, - fee_estimator: node_cfgs[0].fee_estimator, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster.clone(), - logger: nodes[0].logger, - channel_monitors, - }).unwrap() - }; - nodes_0_deserialized = nodes_0_deserialized_tmp; - assert!(nodes_0_read.is_empty()); - - assert_eq!(nodes[0].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor), - ChannelMonitorUpdateStatus::Completed); - nodes[0].node = &nodes_0_deserialized; - check_added_monitors!(nodes[0], 1); + let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); + reload_node!(nodes[0], test_default_channel_config(), &nodes_0_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and // force-close the channel. @@ -483,6 +453,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(); @@ -499,7 +470,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); @@ -543,7 +513,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) { } assert!(nodes[0].node.retry_payment(&new_route, payment_id_1).is_err()); // Shouldn't be allowed to retry a fulfilled payment - nodes[0].node.retry_payment(&new_route, payment_id).unwrap(); + nodes[0].node.retry_payment(&new_route, PaymentId(payment_hash.0)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -574,13 +544,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); @@ -601,64 +571,10 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // The ChannelMonitor should always be the latest version, as we're required to persist it // during the `commitment_signed_dance!()`. - let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap(); - - let mut chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - - macro_rules! reload_node { - ($chain_monitor: ident, $chan_manager: ident, $persister: ident) => { { - $persister = test_utils::TestPersister::new(); - let keys_manager = &chanmon_cfgs[0].keys_manager; - $chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), nodes[0].logger, node_cfgs[0].fee_estimator, &$persister, keys_manager); - nodes[0].chain_monitor = &$chain_monitor; - let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; - let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read( - &mut chan_0_monitor_read, keys_manager).unwrap(); - assert!(chan_0_monitor_read.is_empty()); - - let mut chan_1_monitor = None; - let mut channel_monitors = HashMap::new(); - channel_monitors.insert(chan_0_monitor.get_funding_txo().0, &mut chan_0_monitor); - - if !chan_1_monitor_serialized.0.is_empty() { - let mut chan_1_monitor_read = &chan_1_monitor_serialized.0[..]; - chan_1_monitor = Some(<(BlockHash, ChannelMonitor)>::read( - &mut chan_1_monitor_read, keys_manager).unwrap().1); - assert!(chan_1_monitor_read.is_empty()); - channel_monitors.insert(chan_1_monitor.as_ref().unwrap().get_funding_txo().0, chan_1_monitor.as_mut().unwrap()); - } + let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); - let mut nodes_0_read = &nodes_0_serialized[..]; - let (_, nodes_0_deserialized_tmp) = { - <(BlockHash, ChannelManager)>::read(&mut nodes_0_read, ChannelManagerReadArgs { - default_config: test_default_channel_config(), - keys_manager, - fee_estimator: node_cfgs[0].fee_estimator, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster.clone(), - logger: nodes[0].logger, - channel_monitors, - }).unwrap() - }; - $chan_manager = nodes_0_deserialized_tmp; - assert!(nodes_0_read.is_empty()); - - assert_eq!(nodes[0].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor), - ChannelMonitorUpdateStatus::Completed); - if !chan_1_monitor_serialized.0.is_empty() { - let funding_txo = chan_1_monitor.as_ref().unwrap().get_funding_txo().0; - assert_eq!(nodes[0].chain_monitor.watch_channel(funding_txo, chan_1_monitor.unwrap()), - ChannelMonitorUpdateStatus::Completed); - } - nodes[0].node = &$chan_manager; - check_added_monitors!(nodes[0], if !chan_1_monitor_serialized.0.is_empty() { 2 } else { 1 }); - - nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); - } } - } - - reload_node!(first_new_chain_monitor, first_nodes_0_deserialized, first_persister); + reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized], first_persister, first_new_chain_monitor, first_nodes_0_deserialized); + nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); // On reload, the ChannelManager should realize it is stale compared to the ChannelMonitor and // force-close the channel. @@ -742,16 +658,16 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { // We set mpp_parts_remain to avoid having abandon_payment called expect_payment_failed_conditions(&nodes[0], payment_hash, false, PaymentFailedConditions::new().mpp_parts_remain()); - chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap(); - chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id_3).write(&mut chan_1_monitor_serialized).unwrap(); + let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); + let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_3).encode(); nodes_0_serialized = nodes[0].node.encode(); assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_ok()); assert!(!nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - reload_node!(second_new_chain_monitor, second_nodes_0_deserialized, second_persister); + reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], second_persister, second_new_chain_monitor, second_nodes_0_deserialized); + nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + reconnect_nodes(&nodes[0], &nodes[1], (true, true), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); // Now resend the payment, delivering the HTLC and actually claiming it this time. This ensures @@ -764,14 +680,14 @@ fn do_test_completed_payment_not_retryable_on_reload(use_dust: bool) { assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err()); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); - chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap(); - chan_1_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id_3).write(&mut chan_1_monitor_serialized).unwrap(); + let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); + let chan_1_monitor_serialized = get_monitor!(nodes[0], chan_id_3).encode(); nodes_0_serialized = nodes[0].node.encode(); // Ensure that after reload we cannot retry the payment. - reload_node!(third_new_chain_monitor, third_nodes_0_deserialized, third_persister); + reload_node!(nodes[0], test_default_channel_config(), nodes_0_serialized, &[&chan_0_monitor_serialized, &chan_1_monitor_serialized], third_persister, third_new_chain_monitor, third_nodes_0_deserialized); + nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false); + reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); assert!(nodes[0].node.retry_payment(&new_route, payment_id).is_err()); @@ -799,7 +715,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()); @@ -877,16 +793,15 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co // If we persist the ChannelManager here, we should get the PaymentSent event after // deserialization. - let mut chan_manager_serialized = test_utils::TestVecWriter(Vec::new()); + let mut chan_manager_serialized = Vec::new(); if !persist_manager_post_event { - nodes[0].node.write(&mut chan_manager_serialized).unwrap(); + chan_manager_serialized = nodes[0].node.encode(); } // Now persist the ChannelMonitor and inform the ChainMonitor that we're done, generating the // payment sent event. chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::Completed); - let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[0], chan_id).write(&mut chan_0_monitor_serialized).unwrap(); + let chan_0_monitor_serialized = get_monitor!(nodes[0], chan_id).encode(); for update in mon_updates { nodes[0].chain_monitor.chain_monitor.channel_monitor_updated(funding_txo, update).unwrap(); } @@ -899,39 +814,11 @@ fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, co // If we persist the ChannelManager after we get the PaymentSent event, we shouldn't get it // twice. if persist_manager_post_event { - nodes[0].node.write(&mut chan_manager_serialized).unwrap(); + chan_manager_serialized = nodes[0].node.encode(); } // Now reload nodes[0]... - persister = test_utils::TestPersister::new(); - let keys_manager = &chanmon_cfgs[0].keys_manager; - new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[0].chain_source), nodes[0].tx_broadcaster.clone(), nodes[0].logger, node_cfgs[0].fee_estimator, &persister, keys_manager); - nodes[0].chain_monitor = &new_chain_monitor; - let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; - let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read( - &mut chan_0_monitor_read, keys_manager).unwrap(); - assert!(chan_0_monitor_read.is_empty()); - - 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 io::Cursor::new(&chan_manager_serialized.0[..]), ChannelManagerReadArgs { - default_config: Default::default(), - keys_manager, - fee_estimator: node_cfgs[0].fee_estimator, - chain_monitor: nodes[0].chain_monitor, - tx_broadcaster: nodes[0].tx_broadcaster.clone(), - logger: nodes[0].logger, - channel_monitors, - }).unwrap() - }; - nodes_0_deserialized = nodes_0_deserialized_tmp; - - assert_eq!(nodes[0].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor), - ChannelMonitorUpdateStatus::Completed); - check_added_monitors!(nodes[0], 1); - nodes[0].node = &nodes_0_deserialized; + reload_node!(nodes[0], &chan_manager_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_0_deserialized); if persist_manager_post_event { assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); @@ -972,7 +859,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; @@ -980,10 +867,8 @@ fn test_fulfill_restart_failure() { // The simplest way to get a failure after a fulfill is to reload nodes[1] from a state // pre-fulfill, which we do by serializing it here. - let mut chan_manager_serialized = test_utils::TestVecWriter(Vec::new()); - nodes[1].node.write(&mut chan_manager_serialized).unwrap(); - let mut chan_0_monitor_serialized = test_utils::TestVecWriter(Vec::new()); - get_monitor!(nodes[1], chan_id).write(&mut chan_0_monitor_serialized).unwrap(); + let chan_manager_serialized = nodes[1].node.encode(); + let chan_0_monitor_serialized = get_monitor!(nodes[1], chan_id).encode(); nodes[1].node.claim_funds(payment_preimage); check_added_monitors!(nodes[1], 1); @@ -994,35 +879,7 @@ fn test_fulfill_restart_failure() { expect_payment_sent_without_paths!(nodes[0], payment_preimage); // Now reload nodes[1]... - persister = test_utils::TestPersister::new(); - let keys_manager = &chanmon_cfgs[1].keys_manager; - new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[1].chain_source), nodes[1].tx_broadcaster.clone(), nodes[1].logger, node_cfgs[1].fee_estimator, &persister, keys_manager); - nodes[1].chain_monitor = &new_chain_monitor; - let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..]; - let (_, mut chan_0_monitor) = <(BlockHash, ChannelMonitor)>::read( - &mut chan_0_monitor_read, keys_manager).unwrap(); - assert!(chan_0_monitor_read.is_empty()); - - 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)> - ::read(&mut io::Cursor::new(&chan_manager_serialized.0[..]), ChannelManagerReadArgs { - default_config: Default::default(), - keys_manager, - fee_estimator: node_cfgs[1].fee_estimator, - chain_monitor: nodes[1].chain_monitor, - tx_broadcaster: nodes[1].tx_broadcaster.clone(), - logger: nodes[1].logger, - channel_monitors, - }).unwrap() - }; - nodes_1_deserialized = nodes_1_deserialized_tmp; - - assert_eq!(nodes[1].chain_monitor.watch_channel(chan_0_monitor.get_funding_txo().0, chan_0_monitor), - ChannelMonitorUpdateStatus::Completed); - check_added_monitors!(nodes[1], 1); - nodes[1].node = &nodes_1_deserialized; + reload_node!(nodes[1], &chan_manager_serialized, &[&chan_0_monitor_serialized], persister, new_chain_monitor, nodes_1_deserialized); nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); @@ -1060,7 +917,7 @@ fn get_ldk_payment_preimage() { &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(); + nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret), PaymentId(payment_hash.0)).unwrap(); check_added_monitors!(nodes[0], 1); // Make sure to use `get_payment_preimage` @@ -1253,3 +1110,263 @@ fn onchain_failed_probe_yields_event() { } assert!(found_probe_failed); } + +#[test] +fn claimed_send_payment_idempotent() { + // Tests that `send_payment` (and friends) are (reasonably) idempotent. + 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_preimage, _, _, 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::DuplicatePayment) => {}, + _ => 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::DuplicatePayment) => {}, + _ => panic!("Unexpected send result: {:?}", send_result), + } + } + } + + check_send_rejected!(); + + // Claim the payment backwards, but note that the PaymentSent event is still pending and has + // not been seen by the user. At this point, from the user perspective nothing has changed, so + // we must remain just as idempotent as we were before. + do_claim_payment_along_route(&nodes[0], &[&[&nodes[1]]], false, first_payment_preimage); + + for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS { + nodes[0].node.timer_tick_occurred(); + } + + check_send_rejected!(); + + // Once the user sees and handles the `PaymentSent` event, we expect them to no longer call + // `send_payment`, and our idempotency guarantees are off - they should have atomically marked + // the payment complete. However, they could have called `send_payment` while the event was + // being processed, leading to a race in our idempotency guarantees. Thus, even immediately + // after the event is handled a duplicate payment should sitll be rejected. + expect_payment_sent!(&nodes[0], first_payment_preimage, Some(0)); + check_send_rejected!(); + + // If relatively little time has passed, a duplicate payment should still fail. + nodes[0].node.timer_tick_occurred(); + check_send_rejected!(); + + // However, after some time has passed (at least more than the one timer tick above), a + // duplicate payment should go through, as ChannelManager should no longer have any remaining + // references to the old payment data. + for _ in 0..IDEMPOTENCY_TIMEOUT_TICKS { + nodes[0].node.timer_tick_occurred(); + } + + 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); +} + +#[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::DuplicatePayment) => {}, + _ => 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::DuplicatePayment) => {}, + _ => 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); +} + +#[test] +fn test_trivial_inflight_htlc_tracking(){ + // In this test, we test three scenarios: + // (1) Sending + claiming a payment successfully should return `None` when querying InFlightHtlcs + // (2) Sending a payment without claiming it should return the payment's value (500000) when querying InFlightHtlcs + // (3) After we claim the payment sent in (2), InFlightHtlcs should return `None` for the query. + let chanmon_cfgs = create_chanmon_cfgs(3); + let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); + let nodes = create_network(3, &node_cfgs, &node_chanmgrs); + + let (_, _, chan_1_id, _) = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()); + let (_, _, chan_2_id, _) = create_announced_chan_between_nodes(&nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()); + + // Send and claim the payment. Inflight HTLCs should be empty. + send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 500000); + { + let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); + + let node_0_channel_lock = nodes[0].node.channel_state.lock().unwrap(); + let node_1_channel_lock = nodes[1].node.channel_state.lock().unwrap(); + let channel_1 = node_0_channel_lock.by_id.get(&chan_1_id).unwrap(); + let channel_2 = node_1_channel_lock.by_id.get(&chan_2_id).unwrap(); + + let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), + channel_1.get_short_channel_id().unwrap() + ); + let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), + channel_2.get_short_channel_id().unwrap() + ); + + assert_eq!(chan_1_used_liquidity, None); + assert_eq!(chan_2_used_liquidity, None); + } + + // Send the payment, but do not claim it. Our inflight HTLCs should contain the pending payment. + let (payment_preimage, _, _) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 500000); + { + let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); + + let node_0_channel_lock = nodes[0].node.channel_state.lock().unwrap(); + let node_1_channel_lock = nodes[1].node.channel_state.lock().unwrap(); + let channel_1 = node_0_channel_lock.by_id.get(&chan_1_id).unwrap(); + let channel_2 = node_1_channel_lock.by_id.get(&chan_2_id).unwrap(); + + let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), + channel_1.get_short_channel_id().unwrap() + ); + let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), + channel_2.get_short_channel_id().unwrap() + ); + + // First hop accounts for expected 1000 msat fee + assert_eq!(chan_1_used_liquidity, Some(501000)); + assert_eq!(chan_2_used_liquidity, Some(500000)); + } + + // Now, let's claim the payment. This should result in the used liquidity to return `None`. + claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage); + { + let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); + + let node_0_channel_lock = nodes[0].node.channel_state.lock().unwrap(); + let node_1_channel_lock = nodes[1].node.channel_state.lock().unwrap(); + let channel_1 = node_0_channel_lock.by_id.get(&chan_1_id).unwrap(); + let channel_2 = node_1_channel_lock.by_id.get(&chan_2_id).unwrap(); + + let chan_1_used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), + channel_1.get_short_channel_id().unwrap() + ); + let chan_2_used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[2].node.get_our_node_id()), + channel_2.get_short_channel_id().unwrap() + ); + + assert_eq!(chan_1_used_liquidity, None); + assert_eq!(chan_2_used_liquidity, None); + } +} + +#[test] +fn test_holding_cell_inflight_htlcs() { + 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); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()).2; + + let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[0], nodes[1], 1000000); + let (_, payment_hash_2, payment_secret_2) = get_payment_preimage_hash!(nodes[1]); + + // Queue up two payments - one will be delivered right away, one immediately goes into the + // holding cell as nodes[0] is AwaitingRAA. + { + nodes[0].node.send_payment(&route, payment_hash_1, &Some(payment_secret_1), PaymentId(payment_hash_1.0)).unwrap(); + check_added_monitors!(nodes[0], 1); + nodes[0].node.send_payment(&route, payment_hash_2, &Some(payment_secret_2), PaymentId(payment_hash_2.0)).unwrap(); + check_added_monitors!(nodes[0], 0); + } + + let inflight_htlcs = node_chanmgrs[0].compute_inflight_htlcs(); + + { + let channel_lock = nodes[0].node.channel_state.lock().unwrap(); + let channel = channel_lock.by_id.get(&channel_id).unwrap(); + + let used_liquidity = inflight_htlcs.used_liquidity_msat( + &NodeId::from_pubkey(&nodes[0].node.get_our_node_id()) , + &NodeId::from_pubkey(&nodes[1].node.get_our_node_id()), + channel.get_short_channel_id().unwrap() + ); + + assert_eq!(used_liquidity, Some(2000000)); + } + + // Clear pending events so test doesn't throw a "Had excess message on node..." error + nodes[0].node.get_and_clear_pending_msg_events(); +}