Skip to content

Commit c1c9b11

Browse files
authored
Merge pull request #577 from valentinewallace/fix-onchain-fee-check-htlcs
Incl tx fee when calcing inbound+outbound HTLC limits on channels
2 parents 9be497c + 17ccab4 commit c1c9b11

File tree

4 files changed

+506
-132
lines changed

4 files changed

+506
-132
lines changed

fuzz/src/chanmon_consistency.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
408408

409409
loop {
410410
macro_rules! send_payment {
411-
($source: expr, $dest: expr) => { {
411+
($source: expr, $dest: expr, $amt: expr) => { {
412412
let payment_hash = Sha256::hash(&[payment_id; 1]);
413413
payment_id = payment_id.wrapping_add(1);
414414
if let Err(_) = $source.send_payment(&Route {
@@ -417,15 +417,15 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
417417
node_features: NodeFeatures::empty(),
418418
short_channel_id: $dest.1,
419419
channel_features: ChannelFeatures::empty(),
420-
fee_msat: 5000000,
420+
fee_msat: $amt,
421421
cltv_expiry_delta: 200,
422422
}]],
423423
}, PaymentHash(payment_hash.into_inner()), &None) {
424424
// Probably ran out of funds
425425
test_return!();
426426
}
427427
} };
428-
($source: expr, $middle: expr, $dest: expr) => { {
428+
($source: expr, $middle: expr, $dest: expr, $amt: expr) => { {
429429
let payment_hash = Sha256::hash(&[payment_id; 1]);
430430
payment_id = payment_id.wrapping_add(1);
431431
if let Err(_) = $source.send_payment(&Route {
@@ -441,7 +441,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
441441
node_features: NodeFeatures::empty(),
442442
short_channel_id: $dest.1,
443443
channel_features: ChannelFeatures::empty(),
444-
fee_msat: 5000000,
444+
fee_msat: $amt,
445445
cltv_expiry_delta: 200,
446446
}]],
447447
}, PaymentHash(payment_hash.into_inner()), &None) {
@@ -644,12 +644,12 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
644644
});
645645
for event in events.drain(..) {
646646
match event {
647-
events::Event::PaymentReceived { payment_hash, payment_secret, .. } => {
647+
events::Event::PaymentReceived { payment_hash, payment_secret, amt } => {
648648
if claim_set.insert(payment_hash.0) {
649649
if $fail {
650650
assert!(nodes[$node].fail_htlc_backwards(&payment_hash, &payment_secret));
651651
} else {
652-
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &payment_secret, 5_000_000));
652+
assert!(nodes[$node].claim_funds(PaymentPreimage(payment_hash.0), &payment_secret, amt));
653653
}
654654
}
655655
},
@@ -691,12 +691,12 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
691691
nodes[2].channel_monitor_updated(&chan_2_funding, *id);
692692
}
693693
},
694-
0x09 => send_payment!(nodes[0], (&nodes[1], chan_a)),
695-
0x0a => send_payment!(nodes[1], (&nodes[0], chan_a)),
696-
0x0b => send_payment!(nodes[1], (&nodes[2], chan_b)),
697-
0x0c => send_payment!(nodes[2], (&nodes[1], chan_b)),
698-
0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)),
699-
0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)),
694+
0x09 => send_payment!(nodes[0], (&nodes[1], chan_a), 5_000_000),
695+
0x0a => send_payment!(nodes[1], (&nodes[0], chan_a), 5_000_000),
696+
0x0b => send_payment!(nodes[1], (&nodes[2], chan_b), 5_000_000),
697+
0x0c => send_payment!(nodes[2], (&nodes[1], chan_b), 5_000_000),
698+
0x0d => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 5_000_000),
699+
0x0e => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 5_000_000),
700700
0x0f => {
701701
if !chan_a_disconnected {
702702
nodes[0].peer_disconnected(&nodes[1].get_our_node_id(), false);
@@ -781,6 +781,24 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
781781
},
782782
0x22 => send_payment_with_secret!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b)),
783783
0x23 => send_payment_with_secret!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a)),
784+
0x25 => send_payment!(nodes[0], (&nodes[1], chan_a), 10),
785+
0x26 => send_payment!(nodes[1], (&nodes[0], chan_a), 10),
786+
0x27 => send_payment!(nodes[1], (&nodes[2], chan_b), 10),
787+
0x28 => send_payment!(nodes[2], (&nodes[1], chan_b), 10),
788+
0x29 => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 10),
789+
0x2a => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 10),
790+
0x2b => send_payment!(nodes[0], (&nodes[1], chan_a), 1_000),
791+
0x2c => send_payment!(nodes[1], (&nodes[0], chan_a), 1_000),
792+
0x2d => send_payment!(nodes[1], (&nodes[2], chan_b), 1_000),
793+
0x2e => send_payment!(nodes[2], (&nodes[1], chan_b), 1_000),
794+
0x2f => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 1_000),
795+
0x30 => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 1_000),
796+
0x31 => send_payment!(nodes[0], (&nodes[1], chan_a), 100_000),
797+
0x32 => send_payment!(nodes[1], (&nodes[0], chan_a), 100_000),
798+
0x33 => send_payment!(nodes[1], (&nodes[2], chan_b), 100_000),
799+
0x34 => send_payment!(nodes[2], (&nodes[1], chan_b), 100_000),
800+
0x35 => send_payment!(nodes[0], (&nodes[1], chan_a), (&nodes[2], chan_b), 100_000),
801+
0x36 => send_payment!(nodes[2], (&nodes[1], chan_b), (&nodes[0], chan_a), 100_000),
784802
// 0x24 defined above
785803
_ => test_return!(),
786804
}

lightning/src/ln/channel.rs

Lines changed: 167 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub struct ChannelValueStat {
4444
pub pending_inbound_htlcs_amount_msat: u64,
4545
pub holding_cell_outbound_amount_msat: u64,
4646
pub their_max_htlc_value_in_flight_msat: u64, // outgoing
47+
pub their_dust_limit_msat: u64,
4748
}
4849

4950
enum InboundHTLCRemovalReason {
@@ -1687,8 +1688,83 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
16871688
cmp::min(self.value_to_self_msat as i64 - self.get_outbound_pending_htlc_stats().1 as i64, 0) as u64)
16881689
}
16891690

1690-
pub fn update_add_htlc(&mut self, msg: &msgs::UpdateAddHTLC, pending_forward_state: PendingHTLCStatus) -> Result<(), ChannelError> {
1691-
if (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32) {
1691+
// Get the fee cost of a commitment tx with a given number of HTLC outputs.
1692+
// Note that num_htlcs should not include dust HTLCs.
1693+
fn commit_tx_fee_msat(&self, num_htlcs: usize) -> u64 {
1694+
// Note that we need to divide before multiplying to round properly,
1695+
// since the lowest denomination of bitcoin on-chain is the satoshi.
1696+
(COMMITMENT_TX_BASE_WEIGHT + num_htlcs as u64 * COMMITMENT_TX_WEIGHT_PER_HTLC) * self.feerate_per_kw / 1000 * 1000
1697+
}
1698+
1699+
// Get the commitment tx fee for the local (i.e our) next commitment transaction
1700+
// based on the number of pending HTLCs that are on track to be in our next
1701+
// commitment tx. `addl_htcs` is an optional parameter allowing the caller
1702+
// to add a number of additional HTLCs to the calculation. Note that dust
1703+
// HTLCs are excluded.
1704+
fn next_local_commit_tx_fee_msat(&self, addl_htlcs: usize) -> u64 {
1705+
assert!(self.channel_outbound);
1706+
1707+
let mut their_acked_htlcs = self.pending_inbound_htlcs.len();
1708+
for ref htlc in self.pending_outbound_htlcs.iter() {
1709+
if htlc.amount_msat / 1000 <= self.our_dust_limit_satoshis {
1710+
continue
1711+
}
1712+
match htlc.state {
1713+
OutboundHTLCState::Committed => their_acked_htlcs += 1,
1714+
OutboundHTLCState::RemoteRemoved {..} => their_acked_htlcs += 1,
1715+
OutboundHTLCState::LocalAnnounced {..} => their_acked_htlcs += 1,
1716+
_ => {},
1717+
}
1718+
}
1719+
1720+
for htlc in self.holding_cell_htlc_updates.iter() {
1721+
match htlc {
1722+
&HTLCUpdateAwaitingACK::AddHTLC { .. } => their_acked_htlcs += 1,
1723+
_ => {},
1724+
}
1725+
}
1726+
1727+
self.commit_tx_fee_msat(their_acked_htlcs + addl_htlcs)
1728+
}
1729+
1730+
// Get the commitment tx fee for the remote's next commitment transaction
1731+
// based on the number of pending HTLCs that are on track to be in their
1732+
// next commitment tx. `addl_htcs` is an optional parameter allowing the caller
1733+
// to add a number of additional HTLCs to the calculation. Note that dust HTLCs
1734+
// are excluded.
1735+
fn next_remote_commit_tx_fee_msat(&self, addl_htlcs: usize) -> u64 {
1736+
assert!(!self.channel_outbound);
1737+
1738+
// When calculating the set of HTLCs which will be included in their next
1739+
// commitment_signed, all inbound HTLCs are included (as all states imply it will be
1740+
// included) and only committed outbound HTLCs, see below.
1741+
let mut their_acked_htlcs = self.pending_inbound_htlcs.len();
1742+
for ref htlc in self.pending_outbound_htlcs.iter() {
1743+
if htlc.amount_msat / 1000 <= self.their_dust_limit_satoshis {
1744+
continue
1745+
}
1746+
// We only include outbound HTLCs if it will not be included in their next
1747+
// commitment_signed, i.e. if they've responded to us with an RAA after announcement.
1748+
match htlc.state {
1749+
OutboundHTLCState::Committed => their_acked_htlcs += 1,
1750+
OutboundHTLCState::RemoteRemoved {..} => their_acked_htlcs += 1,
1751+
_ => {},
1752+
}
1753+
}
1754+
1755+
self.commit_tx_fee_msat(their_acked_htlcs + addl_htlcs)
1756+
}
1757+
1758+
pub fn update_add_htlc<F>(&mut self, msg: &msgs::UpdateAddHTLC, mut pending_forward_status: PendingHTLCStatus, create_pending_htlc_status: F) -> Result<(), ChannelError>
1759+
where F: for<'a> Fn(&'a Self, PendingHTLCStatus, u16) -> PendingHTLCStatus {
1760+
// We can't accept HTLCs sent after we've sent a shutdown.
1761+
let local_sent_shutdown = (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::LocalShutdownSent as u32)) != (ChannelState::ChannelFunded as u32);
1762+
if local_sent_shutdown {
1763+
pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|20);
1764+
}
1765+
// If the remote has sent a shutdown prior to adding this HTLC, then they are in violation of the spec.
1766+
let remote_sent_shutdown = (self.channel_state & (ChannelState::ChannelFunded as u32 | ChannelState::RemoteShutdownSent as u32)) != (ChannelState::ChannelFunded as u32);
1767+
if remote_sent_shutdown {
16921768
return Err(ChannelError::Close("Got add HTLC message when channel was not in an operational state"));
16931769
}
16941770
if self.channel_state & (ChannelState::PeerDisconnected as u32) == ChannelState::PeerDisconnected as u32 {
@@ -1732,9 +1808,55 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17321808
removed_outbound_total_msat += htlc.amount_msat;
17331809
}
17341810
}
1735-
if htlc_inbound_value_msat + msg.amount_msat + self.value_to_self_msat > (self.channel_value_satoshis - Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis)) * 1000 + removed_outbound_total_msat {
1736-
return Err(ChannelError::Close("Remote HTLC add would put them under their reserve value"));
1811+
1812+
let pending_value_to_self_msat =
1813+
self.value_to_self_msat + htlc_inbound_value_msat - removed_outbound_total_msat;
1814+
let pending_remote_value_msat =
1815+
self.channel_value_satoshis * 1000 - pending_value_to_self_msat;
1816+
if pending_remote_value_msat < msg.amount_msat {
1817+
return Err(ChannelError::Close("Remote HTLC add would overdraw remaining funds"));
1818+
}
1819+
1820+
// Check that the remote can afford to pay for this HTLC on-chain at the current
1821+
// feerate_per_kw, while maintaining their channel reserve (as required by the spec).
1822+
let remote_commit_tx_fee_msat = if self.channel_outbound { 0 } else {
1823+
// +1 for this HTLC.
1824+
self.next_remote_commit_tx_fee_msat(1)
1825+
};
1826+
if pending_remote_value_msat - msg.amount_msat < remote_commit_tx_fee_msat {
1827+
return Err(ChannelError::Close("Remote HTLC add would not leave enough to pay for fees"));
1828+
};
1829+
1830+
let chan_reserve_msat =
1831+
Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis) * 1000;
1832+
if pending_remote_value_msat - msg.amount_msat - remote_commit_tx_fee_msat < chan_reserve_msat {
1833+
return Err(ChannelError::Close("Remote HTLC add would put them under remote reserve value"));
1834+
}
1835+
1836+
if !self.channel_outbound {
1837+
// `+1` for this HTLC, `2 *` and `+1` fee spike buffer we keep for the remote. This deviates from the
1838+
// spec because in the spec, the fee spike buffer requirement doesn't exist on the receiver's side,
1839+
// only on the sender's.
1840+
// Note that when we eventually remove support for fee updates and switch to anchor output fees,
1841+
// we will drop the `2 *`, since we no longer be as sensitive to fee spikes. But, keep the extra +1
1842+
// as we should still be able to afford adding this HTLC plus one more future HTLC, regardless of
1843+
// being sensitive to fee spikes.
1844+
let remote_fee_cost_incl_stuck_buffer_msat = 2 * self.next_remote_commit_tx_fee_msat(1 + 1);
1845+
if pending_remote_value_msat - msg.amount_msat - chan_reserve_msat < remote_fee_cost_incl_stuck_buffer_msat {
1846+
// Note that if the pending_forward_status is not updated here, then it's because we're already failing
1847+
// the HTLC, i.e. its status is already set to failing.
1848+
pending_forward_status = create_pending_htlc_status(self, pending_forward_status, 0x1000|7);
1849+
}
1850+
} else {
1851+
// Check that they won't violate our local required channel reserve by adding this HTLC.
1852+
1853+
// +1 for this HTLC.
1854+
let local_commit_tx_fee_msat = self.next_local_commit_tx_fee_msat(1);
1855+
if self.value_to_self_msat < self.local_channel_reserve_satoshis * 1000 + local_commit_tx_fee_msat {
1856+
return Err(ChannelError::Close("Cannot receive value that would put us under local channel reserve value"));
1857+
}
17371858
}
1859+
17381860
if self.next_remote_htlc_id != msg.htlc_id {
17391861
return Err(ChannelError::Close("Remote skipped HTLC ID"));
17401862
}
@@ -1743,7 +1865,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17431865
}
17441866

17451867
if self.channel_state & ChannelState::LocalShutdownSent as u32 != 0 {
1746-
if let PendingHTLCStatus::Forward(_) = pending_forward_state {
1868+
if let PendingHTLCStatus::Forward(_) = pending_forward_status {
17471869
panic!("ChannelManager shouldn't be trying to add a forwardable HTLC after we've started closing");
17481870
}
17491871
}
@@ -1755,7 +1877,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
17551877
amount_msat: msg.amount_msat,
17561878
payment_hash: msg.payment_hash,
17571879
cltv_expiry: msg.cltv_expiry,
1758-
state: InboundHTLCState::RemoteAnnounced(pending_forward_state),
1880+
state: InboundHTLCState::RemoteAnnounced(pending_forward_status),
17591881
});
17601882
Ok(())
17611883
}
@@ -3060,6 +3182,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
30603182
res
30613183
},
30623184
their_max_htlc_value_in_flight_msat: self.their_max_htlc_value_in_flight_msat,
3185+
their_dust_limit_msat: self.their_dust_limit_satoshis * 1000,
30633186
}
30643187
}
30653188

@@ -3570,40 +3693,67 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
35703693
return Err(ChannelError::Ignore("Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
35713694
}
35723695

3696+
if !self.channel_outbound {
3697+
// Check that we won't violate the remote channel reserve by adding this HTLC.
3698+
3699+
let remote_balance_msat = self.channel_value_satoshis * 1000 - self.value_to_self_msat;
3700+
let remote_chan_reserve_msat = Channel::<ChanSigner>::get_remote_channel_reserve_satoshis(self.channel_value_satoshis);
3701+
// 1 additional HTLC corresponding to this HTLC.
3702+
let remote_commit_tx_fee_msat = self.next_remote_commit_tx_fee_msat(1);
3703+
if remote_balance_msat < remote_chan_reserve_msat + remote_commit_tx_fee_msat {
3704+
return Err(ChannelError::Ignore("Cannot send value that would put them under remote channel reserve value"));
3705+
}
3706+
}
3707+
3708+
let pending_value_to_self_msat = self.value_to_self_msat - htlc_outbound_value_msat;
3709+
if pending_value_to_self_msat < amount_msat {
3710+
return Err(ChannelError::Ignore("Cannot send value that would overdraw remaining funds"));
3711+
}
3712+
3713+
// The `+1` is for the HTLC currently being added to the commitment tx and
3714+
// the `2 *` and `+1` are for the fee spike buffer.
3715+
let local_commit_tx_fee_msat = if self.channel_outbound {
3716+
2 * self.next_local_commit_tx_fee_msat(1 + 1)
3717+
} else { 0 };
3718+
if pending_value_to_self_msat - amount_msat < local_commit_tx_fee_msat {
3719+
return Err(ChannelError::Ignore("Cannot send value that would not leave enough to pay for fees"));
3720+
}
3721+
35733722
// Check self.local_channel_reserve_satoshis (the amount we must keep as
35743723
// reserve for the remote to have something to claim if we misbehave)
3575-
if self.value_to_self_msat < self.local_channel_reserve_satoshis * 1000 + amount_msat + htlc_outbound_value_msat {
3724+
let chan_reserve_msat = self.local_channel_reserve_satoshis * 1000;
3725+
if pending_value_to_self_msat - amount_msat - local_commit_tx_fee_msat < chan_reserve_msat {
35763726
return Err(ChannelError::Ignore("Cannot send value that would put us under local channel reserve value"));
35773727
}
35783728

35793729
// Now update local state:
35803730
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == (ChannelState::AwaitingRemoteRevoke as u32) {
35813731
self.holding_cell_htlc_updates.push(HTLCUpdateAwaitingACK::AddHTLC {
3582-
amount_msat: amount_msat,
3583-
payment_hash: payment_hash,
3584-
cltv_expiry: cltv_expiry,
3732+
amount_msat,
3733+
payment_hash,
3734+
cltv_expiry,
35853735
source,
3586-
onion_routing_packet: onion_routing_packet,
3736+
onion_routing_packet,
35873737
});
35883738
return Ok(None);
35893739
}
35903740

35913741
self.pending_outbound_htlcs.push(OutboundHTLCOutput {
35923742
htlc_id: self.next_local_htlc_id,
3593-
amount_msat: amount_msat,
3743+
amount_msat,
35943744
payment_hash: payment_hash.clone(),
3595-
cltv_expiry: cltv_expiry,
3745+
cltv_expiry,
35963746
state: OutboundHTLCState::LocalAnnounced(Box::new(onion_routing_packet.clone())),
35973747
source,
35983748
});
35993749

36003750
let res = msgs::UpdateAddHTLC {
36013751
channel_id: self.channel_id,
36023752
htlc_id: self.next_local_htlc_id,
3603-
amount_msat: amount_msat,
3604-
payment_hash: payment_hash,
3605-
cltv_expiry: cltv_expiry,
3606-
onion_routing_packet: onion_routing_packet,
3753+
amount_msat,
3754+
payment_hash,
3755+
cltv_expiry,
3756+
onion_routing_packet,
36073757
};
36083758
self.next_local_htlc_id += 1;
36093759

0 commit comments

Comments
 (0)