Skip to content

Commit 71f7be1

Browse files
author
Antoine Riard
committed
Cancel the outbound feerate update if above what we can afford
1 parent ad819ea commit 71f7be1

File tree

2 files changed

+72
-7
lines changed

2 files changed

+72
-7
lines changed

lightning/src/ln/channel.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2942,7 +2942,7 @@ impl<Signer: Sign> Channel<Signer> {
29422942
/// Adds a pending update to this channel. See the doc for send_htlc for
29432943
/// further details on the optionness of the return value.
29442944
/// You MUST call send_commitment prior to any other calls on this Channel
2945-
fn send_update_fee(&mut self, feerate_per_kw: u32) -> Option<msgs::UpdateFee> {
2945+
fn send_update_fee<L: Deref>(&mut self, feerate_per_kw: u32, logger: &L) -> Option<msgs::UpdateFee> where L::Target: Logger {
29462946
if !self.is_outbound() {
29472947
panic!("Cannot send fee from inbound channel");
29482948
}
@@ -2953,6 +2953,16 @@ impl<Signer: Sign> Channel<Signer> {
29532953
panic!("Cannot update fee while peer is disconnected/we're awaiting a monitor update (ChannelManager should have caught this)");
29542954
}
29552955

2956+
// Before to propose a feerate update, check that we can actually afford the new fee compare to the holder balance.
2957+
if let Some(reserve) = self.counterparty_selected_channel_reserve_satoshis {
2958+
let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
2959+
let total_fee = feerate_per_kw as u64 * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
2960+
if self.value_to_self_msat / 1000 - total_fee < reserve {
2961+
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
2962+
return None;
2963+
}
2964+
}
2965+
29562966
if (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32 | ChannelState::MonitorUpdateFailed as u32)) != 0 {
29572967
self.holding_cell_update_fee = Some(feerate_per_kw);
29582968
return None;
@@ -2968,7 +2978,7 @@ impl<Signer: Sign> Channel<Signer> {
29682978
}
29692979

29702980
pub fn send_update_fee_and_commit<L: Deref>(&mut self, feerate_per_kw: u32, logger: &L) -> Result<Option<(msgs::UpdateFee, msgs::CommitmentSigned, ChannelMonitorUpdate)>, ChannelError> where L::Target: Logger {
2971-
match self.send_update_fee(feerate_per_kw) {
2981+
match self.send_update_fee(feerate_per_kw, logger) {
29722982
Some(update_fee) => {
29732983
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check(logger)?;
29742984
Ok(Some((update_fee, commitment_signed, monitor_update)))

lightning/src/ln/functional_tests.rs

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
2222
use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, MppId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA};
2323
use ln::channel::{Channel, ChannelError};
2424
use ln::{chan_utils, onion_utils};
25-
use ln::chan_utils::HTLC_SUCCESS_TX_WEIGHT;
25+
use ln::chan_utils::{HTLC_SUCCESS_TX_WEIGHT, HTLCOutputInCommitment};
2626
use routing::router::{Route, RouteHop, RouteHint, RouteHintHop, get_route, get_keysend_route};
2727
use routing::network_graph::{NetworkUpdate, RoutingFees};
2828
use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
@@ -591,6 +591,7 @@ fn test_update_fee_that_funder_cannot_afford() {
591591
let channel_value = 1888;
592592
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, channel_value, 700000, InitFeatures::known(), InitFeatures::known());
593593
let channel_id = chan.2;
594+
let secp_ctx = Secp256k1::new();
594595

595596
let feerate = 260;
596597
{
@@ -625,16 +626,70 @@ fn test_update_fee_that_funder_cannot_afford() {
625626
*feerate_lock = feerate + 2;
626627
}
627628
nodes[0].node.timer_tick_occurred();
628-
check_added_monitors!(nodes[0], 1);
629+
nodes[0].logger.assert_log("lightning::ln::channel".to_string(), format!("Cannot afford to send new feerate at {}", feerate + 2), 1);
630+
check_added_monitors!(nodes[0], 0);
629631

630-
let update2_msg = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
632+
const INITIAL_COMMITMENT_NUMBER: u64 = 281474976710654;
631633

632-
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), &update2_msg.update_fee.unwrap());
634+
// Get the EnforcingSigner for each channel, which will be used to (1) get the keys
635+
// needed to sign the new commitment tx and (2) sign the new commitment tx.
636+
let (local_revocation_basepoint, local_htlc_basepoint, local_funding) = {
637+
let chan_lock = nodes[0].node.channel_state.lock().unwrap();
638+
let local_chan = chan_lock.by_id.get(&chan.2).unwrap();
639+
let chan_signer = local_chan.get_signer();
640+
let pubkeys = chan_signer.pubkeys();
641+
(pubkeys.revocation_basepoint, pubkeys.htlc_basepoint,
642+
pubkeys.funding_pubkey)
643+
};
644+
let (remote_delayed_payment_basepoint, remote_htlc_basepoint,remote_point, remote_funding) = {
645+
let chan_lock = nodes[1].node.channel_state.lock().unwrap();
646+
let remote_chan = chan_lock.by_id.get(&chan.2).unwrap();
647+
let chan_signer = remote_chan.get_signer();
648+
let pubkeys = chan_signer.pubkeys();
649+
(pubkeys.delayed_payment_basepoint, pubkeys.htlc_basepoint,
650+
chan_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - 1, &secp_ctx),
651+
pubkeys.funding_pubkey)
652+
};
653+
654+
// Assemble the set of keys we can use for signatures for our commitment_signed message.
655+
let commit_tx_keys = chan_utils::TxCreationKeys::derive_new(&secp_ctx, &remote_point, &remote_delayed_payment_basepoint,
656+
&remote_htlc_basepoint, &local_revocation_basepoint, &local_htlc_basepoint).unwrap();
657+
658+
let res = {
659+
let local_chan_lock = nodes[0].node.channel_state.lock().unwrap();
660+
let local_chan = local_chan_lock.by_id.get(&chan.2).unwrap();
661+
let local_chan_signer = local_chan.get_signer();
662+
let mut htlcs: Vec<(HTLCOutputInCommitment, ())> = vec![];
663+
let commitment_tx = CommitmentTransaction::new_with_auxiliary_htlc_data(
664+
INITIAL_COMMITMENT_NUMBER - 1,
665+
700,
666+
999,
667+
false, local_funding, remote_funding,
668+
commit_tx_keys.clone(),
669+
feerate + 2,
670+
&mut htlcs,
671+
&local_chan.channel_transaction_parameters.as_counterparty_broadcastable()
672+
);
673+
local_chan_signer.sign_counterparty_commitment(&commitment_tx, &secp_ctx).unwrap()
674+
};
675+
676+
let commit_signed_msg = msgs::CommitmentSigned {
677+
channel_id: chan.2,
678+
signature: res.0,
679+
htlc_signatures: res.1
680+
};
681+
682+
let update_fee = msgs::UpdateFee {
683+
channel_id: chan.2,
684+
feerate_per_kw: feerate + 2,
685+
};
686+
687+
nodes[1].node.handle_update_fee(&nodes[0].node.get_our_node_id(), &update_fee);
633688

634689
//While producing the commitment_signed response after handling a received update_fee request the
635690
//check to see if the funder, who sent the update_fee request, can afford the new fee (funder_balance >= fee+channel_reserve)
636691
//Should produce and error.
637-
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &update2_msg.commitment_signed);
692+
nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &commit_signed_msg);
638693
nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Funding remote cannot afford proposed new fee".to_string(), 1);
639694
check_added_monitors!(nodes[1], 1);
640695
check_closed_broadcast!(nodes[1], true);

0 commit comments

Comments
 (0)