Skip to content

Commit ba5ea8c

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 ba5ea8c

File tree

1 file changed

+148
-8
lines changed

1 file changed

+148
-8
lines changed

lightning/src/ln/channel.rs

Lines changed: 148 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
};
@@ -1740,7 +1793,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17401793
}
17411794
}
17421795

1743-
self.commit_tx_fee_msat(included_htlcs + addl_htlcs)
1796+
let num_htlcs = included_htlcs + addl_htlcs;
1797+
let res = self.commit_tx_fee_msat(num_htlcs);
1798+
#[cfg(any(test, feature = "fuzztarget"))]
1799+
{
1800+
if fee_spike_buffer_htlc.is_none() {
1801+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = Some(res);
1802+
} else {
1803+
let fee = self.commit_tx_fee_msat(num_htlcs - 1);
1804+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = Some(fee);
1805+
}
1806+
}
1807+
res
17441808
}
17451809

17461810
// Get the commitment tx fee for the remote's next commitment transaction based on the number of
@@ -1785,10 +1849,38 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17851849
}
17861850
}
17871851

1788-
self.commit_tx_fee_msat(included_htlcs + addl_htlcs)
1852+
let num_htlcs = included_htlcs + addl_htlcs;
1853+
let res = self.commit_tx_fee_msat(num_htlcs);
1854+
#[cfg(any(test, feature = "fuzztarget"))]
1855+
{
1856+
if fee_spike_buffer_htlc.is_none() {
1857+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = Some(res);
1858+
} else {
1859+
let fee = self.commit_tx_fee_msat(num_htlcs - 1);
1860+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = Some(fee);
1861+
}
1862+
}
1863+
res
17891864
}
17901865

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>
1866+
1867+
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>
1868+
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, L::Target: Logger {
1869+
match self.update_add_htlc_internal(msg, pending_forward_status, create_pending_htlc_status, logger) {
1870+
Ok(()) => return Ok(()),
1871+
Err(e) => {
1872+
#[cfg(any(test, feature = "fuzztarget"))]
1873+
{
1874+
// If we errored, one of these fields still might've been set, so re-set them to None.
1875+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
1876+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
1877+
}
1878+
return Err(e);
1879+
},
1880+
}
1881+
}
1882+
1883+
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>
17921884
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus, L::Target: Logger {
17931885
// We can't accept HTLCs sent after we've sent a shutdown.
17941886
let local_sent_shutdown = (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::LocalShutdownSent as u32)) != (ChannelState::ChannelFunded as u32);
@@ -2019,15 +2111,24 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
20192111
(commitment_tx.1, htlcs_cloned, commitment_tx.0, commitment_txid)
20202112
};
20212113

2114+
let total_fee = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
20222115
//If channel fee was updated by funder confirm funder can afford the new fee rate when applied to the current local commitment transaction
20232116
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-
20262117
let counterparty_reserve_we_require = Channel::<ChanSigner>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
20272118
if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee + counterparty_reserve_we_require {
20282119
return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())));
20292120
}
20302121
}
2122+
#[cfg(any(test, feature = "fuzztarget"))]
2123+
{
2124+
let projected_fee = match self.is_outbound() {
2125+
true => self.next_local_commitment_tx_fee_cached.lock().unwrap().take(),
2126+
false => self.next_remote_commitment_tx_fee_cached.lock().unwrap().take()
2127+
};
2128+
if let Some(fee) = projected_fee {
2129+
assert_eq!(total_fee, fee / 1000);
2130+
}
2131+
}
20312132

20322133
if msg.htlc_signatures.len() != num_htlcs {
20332134
return Err((None, ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), num_htlcs))));
@@ -3726,6 +3827,28 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
37263827
/// You MUST call send_commitment prior to any other calls on this Channel
37273828
/// If an Err is returned, it's a ChannelError::Ignore!
37283829
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> {
3830+
match self.send_htlc_internal(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet) {
3831+
Ok(res) => return Ok(res),
3832+
Err(e) => {
3833+
#[cfg(any(test, feature = "fuzztarget"))]
3834+
{
3835+
// If we errored, one of these fields still might've been set, so re-set them to None.
3836+
*self.next_local_commitment_tx_fee_cached.lock().unwrap() = None;
3837+
*self.next_remote_commitment_tx_fee_cached.lock().unwrap() = None;
3838+
}
3839+
return Err(e);
3840+
}
3841+
}
3842+
}
3843+
3844+
/// Adds a pending outbound HTLC to this channel, note that you probably want
3845+
/// send_htlc_and_commit instead cause you'll want both messages at once.
3846+
/// This returns an option instead of a pure UpdateAddHTLC as we may be in a state where we are
3847+
/// waiting on the remote peer to send us a revoke_and_ack during which time we cannot add new
3848+
/// HTLCs on the wire or we wouldn't be able to determine what they actually ACK'ed.
3849+
/// You MUST call send_commitment prior to any other calls on this Channel
3850+
/// If an Err is returned, it's a ChannelError::Ignore!
3851+
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> {
37293852
if (self.channel_state & (ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelFunded as u32) {
37303853
return Err(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned()));
37313854
}
@@ -3921,6 +4044,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
39214044
let counterparty_commitment_txid = counterparty_commitment_tx.0.trust().txid();
39224045
let (signature, htlc_signatures);
39234046

4047+
#[cfg(any(test, feature = "fuzztarget"))]
4048+
{
4049+
let projected_fee = match self.is_outbound() {
4050+
true => self.next_local_commitment_tx_fee_cached.lock().unwrap().take(),
4051+
false => self.next_remote_commitment_tx_fee_cached.lock().unwrap().take()
4052+
};
4053+
if let Some(fee) = projected_fee {
4054+
let actual_fee = self.commit_tx_fee_msat(counterparty_commitment_tx.1);
4055+
assert_eq!(actual_fee, fee);
4056+
}
4057+
}
4058+
39244059
{
39254060
let mut htlcs = Vec::with_capacity(counterparty_commitment_tx.2.len());
39264061
for &(ref htlc, _) in counterparty_commitment_tx.2.iter() {
@@ -4511,6 +4646,11 @@ impl<'a, ChanSigner: ChannelKeys, K: Deref> ReadableArgs<&'a K> for Channel<Chan
45114646
commitment_secrets,
45124647

45134648
network_sync: UpdateStatus::Fresh,
4649+
4650+
#[cfg(any(test, feature = "fuzztarget"))]
4651+
next_local_commitment_tx_fee_cached: Mutex::new(None),
4652+
#[cfg(any(test, feature = "fuzztarget"))]
4653+
next_remote_commitment_tx_fee_cached: Mutex::new(None),
45144654
})
45154655
}
45164656
}

0 commit comments

Comments
 (0)