Skip to content

Commit 3ec529d

Browse files
authored
Merge pull request #1201 from jkczyz/2021-12-idempotent-channelmanager
Ensure ChannelManager methods are idempotent
2 parents 9c6961e + c453d04 commit 3ec529d

File tree

3 files changed

+42
-10
lines changed

3 files changed

+42
-10
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2443,7 +2443,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
24432443
/// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs
24442444
/// or if no output was found which matches the parameters in [`Event::FundingGenerationReady`].
24452445
///
2446-
/// Panics if a funding transaction has already been provided for this channel.
2446+
/// Returns [`APIError::ChannelUnavailable`] if a funding transaction has already been provided
2447+
/// for the channel or if the channel has been closed as indicated by [`Event::ChannelClosed`].
24472448
///
24482449
/// May panic if the output found in the funding transaction is duplicative with some other
24492450
/// channel (note that this should be trivially prevented by using unique funding transaction
@@ -2458,6 +2459,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
24582459
/// create a new channel with a conflicting funding transaction.
24592460
///
24602461
/// [`Event::FundingGenerationReady`]: crate::util::events::Event::FundingGenerationReady
2462+
/// [`Event::ChannelClosed`]: crate::util::events::Event::ChannelClosed
24612463
pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_transaction: Transaction) -> Result<(), APIError> {
24622464
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
24632465

@@ -3353,19 +3355,21 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33533355
}
33543356
}
33553357

3356-
/// Provides a payment preimage in response to a PaymentReceived event, returning true and
3357-
/// generating message events for the net layer to claim the payment, if possible. Thus, you
3358-
/// should probably kick the net layer to go send messages if this returns true!
3358+
/// Provides a payment preimage in response to [`Event::PaymentReceived`], generating any
3359+
/// [`MessageSendEvent`]s needed to claim the payment.
33593360
///
33603361
/// Note that if you did not set an `amount_msat` when calling [`create_inbound_payment`] or
33613362
/// [`create_inbound_payment_for_hash`] you must check that the amount in the `PaymentReceived`
33623363
/// event matches your expectation. If you fail to do so and call this method, you may provide
33633364
/// the sender "proof-of-payment" when they did not fulfill the full expected payment.
33643365
///
3365-
/// May panic if called except in response to a PaymentReceived event.
3366+
/// Returns whether any HTLCs were claimed, and thus if any new [`MessageSendEvent`]s are now
3367+
/// pending for processing via [`get_and_clear_pending_msg_events`].
33663368
///
3369+
/// [`Event::PaymentReceived`]: crate::util::events::Event::PaymentReceived
33673370
/// [`create_inbound_payment`]: Self::create_inbound_payment
33683371
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
3372+
/// [`get_and_clear_pending_msg_events`]: MessageSendEventsProvider::get_and_clear_pending_msg_events
33693373
pub fn claim_funds(&self, payment_preimage: PaymentPreimage) -> bool {
33703374
let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner());
33713375

lightning/src/ln/functional_test_utils.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &
531531
let (temporary_channel_id, tx, funding_output) = create_funding_transaction(node_a, channel_value, 42);
532532
assert_eq!(temporary_channel_id, expected_temporary_channel_id);
533533

534-
node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
534+
assert!(node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone()).is_ok());
535535
check_added_monitors!(node_a, 0);
536536

537537
let funding_created_msg = get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id());
@@ -559,6 +559,11 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &
559559
assert_eq!(node_a.tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);
560560
node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
561561

562+
// Ensure that funding_transaction_generated is idempotent.
563+
assert!(node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone()).is_err());
564+
assert!(node_a.node.get_and_clear_pending_msg_events().is_empty());
565+
check_added_monitors!(node_a, 0);
566+
562567
tx
563568
}
564569

@@ -1067,6 +1072,9 @@ macro_rules! expect_pending_htlcs_forwardable {
10671072
($node: expr) => {{
10681073
expect_pending_htlcs_forwardable_ignore!($node);
10691074
$node.node.process_pending_htlc_forwards();
1075+
1076+
// Ensure process_pending_htlc_forwards is idempotent.
1077+
$node.node.process_pending_htlc_forwards();
10701078
}}
10711079
}
10721080

@@ -1080,6 +1088,9 @@ macro_rules! expect_pending_htlcs_forwardable_from_events {
10801088
};
10811089
if $ignore {
10821090
$node.node.process_pending_htlc_forwards();
1091+
1092+
// Ensure process_pending_htlc_forwards is idempotent.
1093+
$node.node.process_pending_htlc_forwards();
10831094
}
10841095
}}
10851096
}
@@ -1407,6 +1418,12 @@ pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>,
14071418
last_update_fulfill_dance!(origin_node, expected_route.first().unwrap());
14081419
}
14091420
}
1421+
1422+
// Ensure that claim_funds is idempotent.
1423+
assert!(!expected_paths[0].last().unwrap().node.claim_funds(our_payment_preimage));
1424+
assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events().is_empty());
1425+
check_added_monitors!(expected_paths[0].last().unwrap(), 0);
1426+
14101427
expected_total_fee_msat
14111428
}
14121429
pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_preimage: PaymentPreimage) {
@@ -1551,6 +1568,12 @@ pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe
15511568
}
15521569
}
15531570
}
1571+
1572+
// Ensure that fail_htlc_backwards is idempotent.
1573+
assert!(!expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
1574+
assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_events().is_empty());
1575+
assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events().is_empty());
1576+
check_added_monitors!(expected_paths[0].last().unwrap(), 0);
15541577
}
15551578

15561579
pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], our_payment_hash: PaymentHash) {

lightning/src/util/events.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,13 @@ impl_writeable_tlv_based_enum_upgradable!(ClosureReason,
153153
#[derive(Clone, Debug)]
154154
pub enum Event {
155155
/// Used to indicate that the client should generate a funding transaction with the given
156-
/// parameters and then call ChannelManager::funding_transaction_generated.
157-
/// Generated in ChannelManager message handling.
156+
/// parameters and then call [`ChannelManager::funding_transaction_generated`].
157+
/// Generated in [`ChannelManager`] message handling.
158158
/// Note that *all inputs* in the funding transaction must spend SegWit outputs or your
159159
/// counterparty can steal your funds!
160+
///
161+
/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
162+
/// [`ChannelManager::funding_transaction_generated`]: crate::ln::channelmanager::ChannelManager::funding_transaction_generated
160163
FundingGenerationReady {
161164
/// The random channel_id we picked which you'll need to pass into
162165
/// ChannelManager::funding_transaction_generated.
@@ -271,8 +274,10 @@ pub enum Event {
271274
#[cfg(test)]
272275
error_data: Option<Vec<u8>>,
273276
},
274-
/// Used to indicate that ChannelManager::process_pending_htlc_forwards should be called at a
275-
/// time in the future.
277+
/// Used to indicate that [`ChannelManager::process_pending_htlc_forwards`] should be called at
278+
/// a time in the future.
279+
///
280+
/// [`ChannelManager::process_pending_htlc_forwards`]: crate::ln::channelmanager::ChannelManager::process_pending_htlc_forwards
276281
PendingHTLCsForwardable {
277282
/// The minimum amount of time that should be waited prior to calling
278283
/// process_pending_htlc_forwards. To increase the effort required to correlate payments,

0 commit comments

Comments
 (0)