//! serialization ordering between ChannelManager/ChannelMonitors and ensuring we can still retry
//! payments thereafter.
-use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen, Watch};
+use crate::chain::{ChannelMonitorUpdateStatus, Confirm, Listen};
use crate::chain::channelmonitor::{ANTI_REORG_DELAY, HTLC_FAIL_BACK_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS};
use crate::sign::EntropySource;
-use crate::chain::transaction::OutPoint;
use crate::events::{ClosureReason, Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PathFailure, PaymentFailureReason, PaymentPurpose};
use crate::ln::channel::{EXPIRE_PREV_CONFIG_TICKS, commit_tx_fee_msat, get_holder_selected_channel_reserve_satoshis, ANCHOR_OUTPUT_VALUE_SATOSHI};
use crate::ln::channelmanager::{BREAKDOWN_TIMEOUT, MPP_TIMEOUT_TICKS, MIN_CLTV_EXPIRY_DELTA, PaymentId, PaymentSendFailure, RecentPaymentDetails, RecipientOnionFields, HTLCForwardInfo, PendingHTLCRouting, PendingAddHTLCInfo};
use crate::ln::features::{Bolt11InvoiceFeatures, ChannelTypeFeatures};
-use crate::ln::{msgs, ChannelId, PaymentHash, PaymentSecret, PaymentPreimage};
+use crate::ln::msgs;
+use crate::ln::types::{ChannelId, PaymentHash, PaymentSecret, PaymentPreimage};
use crate::ln::msgs::ChannelMessageHandler;
use crate::ln::onion_utils;
use crate::ln::outbound_payment::{IDEMPOTENCY_TIMEOUT_TICKS, Retry};
use bitcoin::hashes::Hash;
use bitcoin::hashes::sha256::Hash as Sha256;
-use bitcoin::network::constants::Network;
+use bitcoin::network::Network;
use bitcoin::secp256k1::{Secp256k1, SecretKey};
use crate::prelude::*;
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
pass_along_path(&nodes[0], &[&nodes[2], &nodes[3]], 2_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+ );
}
#[test]
nodes[3].node.timer_tick_occurred();
}
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+ );
}
}
let ev = remove_first_msg_event_to_node(&nodes[2].node.get_our_node_id(), &mut events);
pass_along_path(&nodes[0], expected_route[1], recv_value, payment_hash.clone(),
Some(payment_secret), ev.clone(), true, Some(payment_preimage));
- claim_payment_along_route(&nodes[0], expected_route, false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], expected_route, payment_preimage)
+ );
}
#[test]
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000, payment_hash, Some(payment_secret), events.pop().unwrap(), true, None);
- do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+ do_claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+ );
expect_payment_sent!(nodes[0], payment_preimage, Some(new_route.paths[0].hops[0].fee_msat));
}
do_test_completed_payment_not_retryable_on_reload(false);
}
-
-fn do_test_dup_htlc_onchain_fails_on_reload(persist_manager_post_event: bool, confirm_commitment_tx: bool, payment_timeout: bool) {
+fn do_test_dup_htlc_onchain_doesnt_fail_on_reload(persist_manager_post_event: bool, confirm_commitment_tx: bool, payment_timeout: bool) {
// When a Channel is closed, any outbound HTLCs which were relayed through it are simply
- // dropped when the Channel is. From there, the ChannelManager relies on the ChannelMonitor
- // having a copy of the relevant fail-/claim-back data and processes the HTLC fail/claim when
- // the ChannelMonitor tells it to.
+ // dropped. From there, the ChannelManager relies on the ChannelMonitor having a copy of the
+ // relevant fail-/claim-back data and processes the HTLC fail/claim when the ChannelMonitor tells
+ // it to.
//
- // If, due to an on-chain event, an HTLC is failed/claimed, we should avoid providing the
- // ChannelManager the HTLC event until after the monitor is re-persisted. This should prevent a
- // duplicate HTLC fail/claim (e.g. via a PaymentPathFailed event).
+ // If, due to an on-chain event, an HTLC is failed/claimed, we provide the
+ // ChannelManager with the HTLC event without waiting for ChannelMonitor persistence.
+ // This might generate duplicate HTLC fail/claim (e.g. via a PaymentPathFailed event) on reload.
let chanmon_cfgs = create_chanmon_cfgs(2);
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
let persister;
let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
let (_, _, chan_id, funding_tx) = create_announced_chan_between_nodes(&nodes, 0, 1);
+ let error_message = "Channel force-closed";
// Route a payment, but force-close the channel before the HTLC fulfill message arrives at
// nodes[0].
let (payment_preimage, payment_hash, ..) = route_payment(&nodes[0], &[&nodes[1]], 10_000_000);
- nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id()).unwrap();
+ nodes[0].node.force_close_broadcasting_latest_txn(&nodes[0].node.list_channels()[0].channel_id, &nodes[1].node.get_our_node_id(), error_message.to_string()).unwrap();
check_closed_broadcast!(nodes[0], true);
check_added_monitors!(nodes[0], 1);
check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed, [nodes[1].node.get_our_node_id()], 100000);
// Now connect the HTLC claim transaction with the ChainMonitor-generated ChannelMonitor update
// returning InProgress. This should cause the claim event to never make its way to the
// ChannelManager.
- chanmon_cfgs[0].persister.chain_sync_monitor_persistences.lock().unwrap().clear();
chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::InProgress);
if payment_timeout {
connect_block(&nodes[0], &claim_block);
}
- let funding_txo = OutPoint { txid: funding_tx.txid(), index: 0 };
- let mon_updates: Vec<_> = chanmon_cfgs[0].persister.chain_sync_monitor_persistences.lock().unwrap()
- .get_mut(&funding_txo).unwrap().drain().collect();
- // If we are using chain::Confirm instead of chain::Listen, we will get the same update twice.
- // If we're testing connection idempotency we may get substantially more.
- assert!(mon_updates.len() >= 1);
- assert!(nodes[0].chain_monitor.release_pending_monitor_events().is_empty());
- assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
+ // Note that we skip persisting ChannelMonitors. We should still be generating the payment sent
+ // event without ChannelMonitor persistence. If we reset to a previous state on reload, the block
+ // should be replayed and we'll regenerate the event.
// If we persist the ChannelManager here, we should get the PaymentSent event after
// deserialization.
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 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();
- }
if payment_timeout {
expect_payment_failed!(nodes[0], payment_hash, false);
} else {
}
#[test]
-fn test_dup_htlc_onchain_fails_on_reload() {
- do_test_dup_htlc_onchain_fails_on_reload(true, true, true);
- do_test_dup_htlc_onchain_fails_on_reload(true, true, false);
- do_test_dup_htlc_onchain_fails_on_reload(true, false, false);
- do_test_dup_htlc_onchain_fails_on_reload(false, true, true);
- do_test_dup_htlc_onchain_fails_on_reload(false, true, false);
- do_test_dup_htlc_onchain_fails_on_reload(false, false, false);
+fn test_dup_htlc_onchain_doesnt_fail_on_reload() {
+ do_test_dup_htlc_onchain_doesnt_fail_on_reload(true, true, true);
+ do_test_dup_htlc_onchain_doesnt_fail_on_reload(true, true, false);
+ do_test_dup_htlc_onchain_doesnt_fail_on_reload(true, false, false);
+ do_test_dup_htlc_onchain_doesnt_fail_on_reload(false, true, true);
+ do_test_dup_htlc_onchain_doesnt_fail_on_reload(false, true, false);
+ do_test_dup_htlc_onchain_doesnt_fail_on_reload(false, false, false);
}
#[test]
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);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], payment_preimage)
+ );
}
#[test]
// 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);
+ do_claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], first_payment_preimage)
+ );
for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS {
nodes[0].node.timer_tick_occurred();
let payment_preimage = nodes[2].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
expect_payment_claimable!(&nodes[2], payment_hash, payment_secret, amt_msat, Some(payment_preimage), nodes[2].node.get_our_node_id());
- do_claim_payment_along_route(&nodes[0], &vec!(&vec!(&nodes[1], &nodes[2])[..]), false, payment_preimage);
+ do_claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+ );
let events = nodes[0].node.get_and_clear_pending_events();
assert_eq!(events.len(), 2);
match events[0] {
assert_eq!(skimmed_fee_msat * num_mpp_parts as u64, counterparty_skimmed_fee_msat);
assert_eq!(nodes[2].node.get_our_node_id(), receiver_node_id.unwrap());
match purpose {
- crate::events::PaymentPurpose::InvoicePayment { payment_preimage: ev_payment_preimage,
- payment_secret: ev_payment_secret, .. } =>
- {
+ crate::events::PaymentPurpose::Bolt11InvoicePayment {
+ payment_preimage: ev_payment_preimage,
+ payment_secret: ev_payment_secret,
+ ..
+ } => {
assert_eq!(payment_preimage, ev_payment_preimage.unwrap());
assert_eq!(payment_secret, *ev_payment_secret);
},
let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 1);
pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, Some(payment_secret), msg_events.pop().unwrap(), true, None);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+ );
} else if test == AutoRetry::Spontaneous {
nodes[0].node.send_spontaneous_payment_with_retry(Some(payment_preimage),
RecipientOnionFields::spontaneous_empty(), PaymentId(payment_hash.0), route_params,
let mut msg_events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(msg_events.len(), 1);
pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], amt_msat, payment_hash, None, msg_events.pop().unwrap(), true, Some(payment_preimage));
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+ );
} else if test == AutoRetry::FailAttempts {
// Ensure ChannelManager will not retry a payment if it has run out of payment attempts.
nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
// height.
connect_blocks(&nodes[3], final_cltv - HTLC_FAIL_BACK_BUFFER - nodes[3].best_block_info().1
- if fail_payment { 0 } else { 2 });
+ let error_message = "Channel force-closed";
if fail_payment {
// We fail the HTLC on the A->B->D path first as it expires 4 blocks earlier. We go ahead
// and expire both immediately, though, by connecting another 4 blocks.
expect_pending_htlcs_forwardable_and_htlc_handling_failed!(&nodes[3], [reason]);
pass_failed_payment_back(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_hash, PaymentFailureReason::RecipientRejected);
} else {
- nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id()).unwrap();
+ nodes[1].node.force_close_broadcasting_latest_txn(&chan_bd, &nodes[3].node.get_our_node_id(), error_message.to_string()).unwrap();
check_closed_event!(&nodes[1], 1, ClosureReason::HolderForceClosed, false,
[nodes[3].node.get_our_node_id()], 1000000);
check_closed_broadcast(&nodes[1], 1, true);
match (known_tlvs, even_tlvs) {
(true, _) => {
nodes[1].node.claim_funds_with_known_custom_tlvs(our_payment_preimage);
- let expected_total_fee_msat = pass_claimed_payment_along_route(ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage));
+ let expected_total_fee_msat = pass_claimed_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage)
+ .with_custom_tlvs(custom_tlvs)
+ );
expect_payment_sent!(&nodes[0], our_payment_preimage, Some(expected_total_fee_msat));
},
(false, false) => {
- claim_payment(&nodes[0], &[&nodes[1]], our_payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1]]], our_payment_preimage)
+ .with_custom_tlvs(custom_tlvs)
+ );
},
(false, true) => {
nodes[1].node.claim_funds(our_payment_preimage);
check_added_monitors!(nodes[0], 1);
let mut events = nodes[0].node.get_and_clear_pending_msg_events();
assert_eq!(events.len(), 1);
- let payment_claimable = pass_along_path(&nodes[0], &[&nodes[1], &nodes[2]], 1_000_000,
- payment_hash, Some(payment_secret), events.pop().unwrap(), true, None).unwrap();
- match payment_claimable {
- Event::PaymentClaimable { onion_fields, .. } => {
- assert_eq!(&onion_fields.unwrap().custom_tlvs()[..], &custom_tlvs[..]);
- },
- _ => panic!("Unexpected event"),
- };
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage);
+ let path = &[&nodes[1], &nodes[2]];
+ let args = PassAlongPathArgs::new(&nodes[0], path, 1_000_000, payment_hash, events.pop().unwrap())
+ .with_payment_secret(payment_secret)
+ .with_custom_tlvs(custom_tlvs.clone());
+ do_pass_along_path(args);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[2]]], payment_preimage)
+ .with_custom_tlvs(custom_tlvs)
+ );
}
#[test]
_ => panic!("Unexpected event"),
}
- do_claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]],
- false, our_payment_preimage);
+ do_claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], our_payment_preimage)
+ .with_custom_tlvs(expected_tlvs)
+ );
expect_payment_sent(&nodes[0], our_payment_preimage, Some(Some(2000)), true, true);
} else {
// Expect fail back
} else {
expect_pending_htlcs_forwardable!(nodes[3]);
expect_payment_claimable!(nodes[3], payment_hash, payment_secret, amt_msat);
- claim_payment_along_route(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage);
+ claim_payment_along_route(
+ ClaimAlongRouteArgs::new(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], payment_preimage)
+ );
}
}
let payment_hash = PaymentHash(Sha256::hash(&keysend_preimage.0).to_byte_array());
let (onion_routing_packet, first_hop_msat, cltv_expiry) = onion_utils::create_payment_onion(
- &secp_ctx, &route.paths[0], &session_priv, amt_msat, recipient_onion.clone(),
+ &secp_ctx, &route.paths[0], &session_priv, amt_msat, &recipient_onion,
nodes[0].best_block_info().1, &payment_hash, &Some(keysend_preimage), prng_seed
).unwrap();