Skip to content

Commit 3b02a56

Browse files
Ensure build_commitment_tx and next_local/remote_tx_fee agree on the fee
... when possible. Sometimes they'll inevitably count different HTLCs, so we skip those cases.
1 parent 87fa298 commit 3b02a56

File tree

1 file changed

+165
-8
lines changed

1 file changed

+165
-8
lines changed

lightning/src/ln/channel.rs

Lines changed: 165 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ use std;
4242
use std::default::Default;
4343
use std::{cmp,mem,fmt};
4444
use std::ops::Deref;
45+
#[cfg(any(test, feature = "fuzztarget"))]
46+
use std::sync::Mutex;
4547
use bitcoin::hashes::hex::ToHex;
4648

4749
#[cfg(test)]
@@ -386,6 +388,15 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
386388
commitment_secrets: CounterpartyCommitmentSecrets,
387389

388390
network_sync: UpdateStatus,
391+
392+
// We save these values so we can make sure `next_local_commit_tx_fee_msat` and
393+
// `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
394+
// be, by comparing the cached values to the fee of the tranaction generated by
395+
// `build_commitment_transaction`.
396+
#[cfg(any(test, feature = "fuzztarget"))]
397+
next_local_commitment_tx_fee_cached: Mutex<Option<u64>>,
398+
#[cfg(any(test, feature = "fuzztarget"))]
399+
next_remote_commitment_tx_fee_cached: Mutex<Option<u64>>,
389400
}
390401

391402
pub const OUR_MAX_HTLCS: u16 = 50; //TODO
@@ -557,6 +568,11 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
557568
commitment_secrets: CounterpartyCommitmentSecrets::new(),
558569

559570
network_sync: UpdateStatus::Fresh,
571+
572+
#[cfg(any(test, feature = "fuzztarget"))]
573+
next_local_commitment_tx_fee_cached: Mutex::new(None),
574+
#[cfg(any(test, feature = "fuzztarget"))]
575+
next_remote_commitment_tx_fee_cached: Mutex::new(None),
560576
})
561577
}
562578

@@ -790,6 +806,11 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
790806
commitment_secrets: CounterpartyCommitmentSecrets::new(),
791807

792808
network_sync: UpdateStatus::Fresh,
809+
810+
#[cfg(any(test, feature = "fuzztarget"))]
811+
next_local_commitment_tx_fee_cached: Mutex::new(None),
812+
#[cfg(any(test, feature = "fuzztarget"))]
813+
next_remote_commitment_tx_fee_cached: Mutex::new(None),
793814
};
794815

795816
Ok(chan)
@@ -867,7 +888,21 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
867888
InboundHTLCState::AwaitingRemoteRevokeToAnnounce(_) => (!generated_by_local, "AwaitingRemoteRevokeToAnnounce"),
868889
InboundHTLCState::AwaitingAnnouncedRemoteRevoke(_) => (true, "AwaitingAnnouncedRemoteRevoke"),
869890
InboundHTLCState::Committed => (true, "Committed"),
870-
InboundHTLCState::LocalRemoved(_) => (!generated_by_local, "LocalRemoved"),
891+
InboundHTLCState::LocalRemoved(_) => {
892+
#[cfg(any(test, feature = "fuzztarget"))]
893+
{
894+
// Remote commitment transactions generated by us won't include our locally removed
895+
// HTLCs, even though we include them when deciding whether to accept/send new HTLCs and
896+
// setting these cached values. Therefore, set these values to None here so we don't
897+
// assert that the transaction generated in this function has the same fee as the cached
898+
// fee. Similar reasoning applies to LocalAnnounced and RemoveRemoved HTLCs below.
899+
if !local && generated_by_local {
900+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
901+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
902+
}
903+
}
904+
(!generated_by_local, "LocalRemoved")
905+
},
871906
};
872907

873908
if include {
@@ -890,9 +925,27 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
890925

891926
for ref htlc in self.pending_outbound_htlcs.iter() {
892927
let (include, state_name) = match htlc.state {
893-
OutboundHTLCState::LocalAnnounced(_) => (generated_by_local, "LocalAnnounced"),
928+
OutboundHTLCState::LocalAnnounced(_) => {
929+
#[cfg(any(test, feature = "fuzztarget"))]
930+
{
931+
if local && !generated_by_local {
932+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
933+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
934+
}
935+
}
936+
(generated_by_local, "LocalAnnounced")
937+
},
894938
OutboundHTLCState::Committed => (true, "Committed"),
895-
OutboundHTLCState::RemoteRemoved(_) => (generated_by_local, "RemoteRemoved"),
939+
OutboundHTLCState::RemoteRemoved(_) => {
940+
#[cfg(any(test, feature = "fuzztarget"))]
941+
{
942+
if local && !generated_by_local {
943+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
944+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
945+
}
946+
}
947+
(generated_by_local, "RemoteRemoved")
948+
},
896949
OutboundHTLCState::AwaitingRemoteRevokeToRemove(_) => (generated_by_local, "AwaitingRemoteRevokeToRemove"),
897950
OutboundHTLCState::AwaitingRemovedRemoteRevoke(_) => (false, "AwaitingRemovedRemoteRevoke"),
898951
};
@@ -1261,6 +1314,12 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
12611314
}
12621315
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
12631316

1317+
#[cfg(any(test, feature = "fuzztarget"))]
1318+
{
1319+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
1320+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
1321+
}
1322+
12641323
// ChannelManager may generate duplicate claims/fails due to HTLC update events from
12651324
// on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop
12661325
// these, but for now we just have to treat them as normal.
@@ -1312,6 +1371,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
13121371
return Ok(None);
13131372
}
13141373

1374+
13151375
{
13161376
let htlc = &mut self.pending_inbound_htlcs[pending_idx];
13171377
htlc.state = InboundHTLCState::LocalRemoved(InboundHTLCRemovalReason::FailRelay(err_packet.clone()));
@@ -1740,7 +1800,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17401800
}
17411801
}
17421802

1743-
self.commit_tx_fee_msat(included_htlcs + addl_htlcs)
1803+
let num_htlcs = included_htlcs + addl_htlcs;
1804+
let res = self.commit_tx_fee_msat(num_htlcs);
1805+
#[cfg(any(test, feature = "fuzztarget"))]
1806+
{
1807+
if fee_spike_buffer_htlc.is_none() {
1808+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = Some(res);
1809+
} else {
1810+
let fee = self.commit_tx_fee_msat(num_htlcs - 1);
1811+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = Some(fee);
1812+
}
1813+
}
1814+
res
17441815
}
17451816

17461817
// Get the commitment tx fee for the remote's next commitment transaction based on the number of
@@ -1785,10 +1856,38 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17851856
}
17861857
}
17871858

1788-
self.commit_tx_fee_msat(included_htlcs + addl_htlcs)
1859+
let num_htlcs = included_htlcs + addl_htlcs;
1860+
let res = self.commit_tx_fee_msat(num_htlcs);
1861+
#[cfg(any(test, feature = "fuzztarget"))]
1862+
{
1863+
if fee_spike_buffer_htlc.is_none() {
1864+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = Some(res);
1865+
} else {
1866+
let fee = self.commit_tx_fee_msat(num_htlcs - 1);
1867+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = Some(fee);
1868+
}
1869+
}
1870+
res
1871+
}
1872+
1873+
1874+
pub fn update_add_htlc<F, L: Deref>(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_status: PendingHTLCStatus, create_pending_htlc_status: F, logger: &L) -> Result<(), ChannelError>
1875+
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, L::Target: Logger {
1876+
match self.update_add_htlc_internal(msg, pending_forward_status, create_pending_htlc_status, logger) {
1877+
Ok(()) => return Ok(()),
1878+
Err(e) => {
1879+
#[cfg(any(test, feature = "fuzztarget"))]
1880+
{
1881+
// If we errored, one of these fields still might've been set, so re-set them to None.
1882+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
1883+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
1884+
}
1885+
return Err(e);
1886+
},
1887+
}
17891888
}
17901889

1791-
pub fn update_add_htlc<F, L: Deref>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_status: PendingHTLCStatus, create_pending_htlc_status: F, logger: &L) -> Result<(), ChannelError>
1890+
fn update_add_htlc_internal<F, L: Deref>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_status: PendingHTLCStatus, create_pending_htlc_status: F, logger: &L) -> Result<(), ChannelError>
17921891
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, L::Target: Logger {
17931892
// We can't accept HTLCs sent after we've sent a shutdown.
17941893
let local_sent_shutdown = (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::LocalShutdownSent as u32)) != (ChannelState::ChannelFunded as u32);
@@ -2019,15 +2118,23 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
20192118
(commitment_tx.1, htlcs_cloned, commitment_tx.0, commitment_txid)
20202119
};
20212120

2121+
let total_fee = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
20222122
//If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
20232123
if update_fee {
2024-
let total_fee = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
2025-
20262124
let counterparty_reserve_we_require = Channel::<ChanSigner>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
20272125
if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + counterparty_reserve_we_require {
20282126
return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())));
20292127
}
20302128
}
2129+
#[cfg(any(test, feature = "fuzztarget"))]
2130+
{
2131+
if self.is_outbound() {
2132+
let projected_fee = self.next_local_commitment_tx_fee_cached.lock().unwrap().take();
2133+
if let Some(fee) = projected_fee {
2134+
assert_eq!(total_fee, fee / 1000);
2135+
}
2136+
}
2137+
}
20312138

20322139
if msg.htlc_signatures.len() != num_htlcs {
20332140
return Err((None, ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), num_htlcs))));
@@ -2276,6 +2383,12 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
22762383
return Err(ChannelError::Close("Peer sent revoke_and_ack after we'd started exchanging closing_signeds".to_owned()));
22772384
}
22782385

2386+
#[cfg(any(test, feature = "fuzztarget"))]
2387+
{
2388+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
2389+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
2390+
}
2391+
22792392
if let Some(counterparty_prev_commitment_point) = self.counterparty_prev_commitment_point {
22802393
if PublicKey::from_secret_key(&self.secp_ctx, &secp_check!(SecretKey::from_slice(&msg.per_commitment_secret), "Peer provided an invalid per_commitment_secret".to_owned())) != counterparty_prev_commitment_point {
22812394
return Err(ChannelError::Close("Got a revoke commitment secret which didn't correspond to their current pubkey".to_owned()));
@@ -2757,6 +2870,12 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
27572870
return Err(ChannelError::Close("Peer sent a loose channel_reestablish not after reconnect".to_owned()));
27582871
}
27592872

2873+
#[cfg(any(test, feature = "fuzztarget"))]
2874+
{
2875+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
2876+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
2877+
}
2878+
27602879
if msg.next_local_commitment_number >= INITIAL_COMMITMENT_NUMBER || msg.next_remote_commitment_number >= INITIAL_COMMITMENT_NUMBER ||
27612880
msg.next_local_commitment_number == 0 {
27622881
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish".to_owned()));
@@ -3726,6 +3845,28 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
37263845
/// You MUST call send_commitment prior to any other calls on this Channel
37273846
/// If an Err is returned, it's a ChannelError::Ignore!
37283847
pub fn send_htlc(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError> {
3848+
match self.send_htlc_internal(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet) {
3849+
Ok(res) => return Ok(res),
3850+
Err(e) => {
3851+
#[cfg(any(test, feature = "fuzztarget"))]
3852+
{
3853+
// If we errored, one of these fields still might've been set, so re-set them to None.
3854+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
3855+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
3856+
}
3857+
return Err(e);
3858+
}
3859+
}
3860+
}
3861+
3862+
/// Adds a pending outbound HTLC to this channel, note that you probably want
3863+
/// send_htlc_and_commit instead cause you'll want both messages at once.
3864+
/// This returns an option instead of a pure UpdateAddHTLC as we may be in a state where we are
3865+
/// waiting on the remote peer to send us a revoke_and_ack during which time we cannot add new
3866+
/// HTLCs on the wire or we wouldn't be able to determine what they actually ACK'ed.
3867+
/// You MUST call send_commitment prior to any other calls on this Channel
3868+
/// If an Err is returned, it's a ChannelError::Ignore!
3869+
fn send_htlc_internal(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError> {
37293870
if (self.channel_state & (ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelFunded as u32) {
37303871
return Err(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned()));
37313872
}
@@ -3921,6 +4062,17 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
39214062
let counterparty_commitment_txid = counterparty_commitment_tx.0.trust().txid();
39224063
let (signature, htlc_signatures);
39234064

4065+
#[cfg(any(test, feature = "fuzztarget"))]
4066+
{
4067+
if !self.is_outbound() {
4068+
let projected_fee = self.next_remote_commitment_tx_fee_cached.lock().unwrap().take();
4069+
if let Some(fee) = projected_fee {
4070+
let actual_fee = self.commit_tx_fee_msat(counterparty_commitment_tx.1);
4071+
assert_eq!(actual_fee, fee);
4072+
}
4073+
}
4074+
}
4075+
39244076
{
39254077
let mut htlcs = Vec::with_capacity(counterparty_commitment_tx.2.len());
39264078
for &(ref htlc, _) in counterparty_commitment_tx.2.iter() {
@@ -4511,6 +4663,11 @@ impl<'a, ChanSigner: ChannelKeys, K: Deref> ReadableArgs<&'a K> for Channel<Chan
45114663
commitment_secrets,
45124664

45134665
network_sync: UpdateStatus::Fresh,
4666+
4667+
#[cfg(any(test, feature = "fuzztarget"))]
4668+
next_local_commitment_tx_fee_cached: Mutex::new(None),
4669+
#[cfg(any(test, feature = "fuzztarget"))]
4670+
next_remote_commitment_tx_fee_cached: Mutex::new(None),
45144671
})
45154672
}
45164673
}

0 commit comments

Comments
 (0)