Skip to content

Commit 7e2694f

Browse files
committed
Review: check for reserve, etc.
1 parent 5ecfa6f commit 7e2694f

File tree

2 files changed

+46
-28
lines changed

2 files changed

+46
-28
lines changed

lightning/src/ln/channel.rs

+29-16
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2323
use bitcoin::secp256k1::{PublicKey,SecretKey};
2424
use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
2525
use bitcoin::{secp256k1, sighash};
26-
#[cfg(splicing)]
27-
use bitcoin::TxIn;
2826

2927
use crate::ln::types::ChannelId;
3028
use crate::types::payment::{PaymentPreimage, PaymentHash};
@@ -1185,11 +1183,12 @@ impl UnfundedChannelContext {
11851183
#[derive(Clone)]
11861184
pub(crate) struct PendingSpliceInfoPre {
11871185
pub our_funding_contribution: i64,
1188-
pub funding_feerate_perkw: u32,
1189-
pub locktime: u32,
1190-
/// The funding inputs we will be contributing to the splice.
1191-
/// TODO(splice): will be changed to TransactionU16LenLimited
1192-
pub our_funding_inputs: Vec<(TxIn, Transaction)>,
1186+
// TODO(splicing): Enable below fields
1187+
// pub funding_feerate_perkw: u32,
1188+
// pub locktime: u32,
1189+
// /// The funding inputs we will be contributing to the splice.
1190+
// /// TODO(splice): will be changed to TransactionU16LenLimited
1191+
// pub our_funding_inputs: Vec<(TxIn, Transaction)>,
11931192
}
11941193

11951194
#[cfg(splicing)]
@@ -3425,6 +3424,28 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34253424
(context.holder_selected_channel_reserve_satoshis, context.counterparty_selected_channel_reserve_satoshis)
34263425
}
34273426

3427+
/// Check that a proposed channel value meets the channel reserve requirements or violates them (below reserve)
3428+
#[cfg(any(dual_funding, splicing))]
3429+
pub fn check_channel_value_meets_reserve_requirements(&self, proposed_channel_value: u64) -> Result<(), ChannelError> {
3430+
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
3431+
proposed_channel_value, self.holder_dust_limit_satoshis);
3432+
if proposed_channel_value < holder_selected_channel_reserve_satoshis {
3433+
return Err(ChannelError::Warn(format!(
3434+
"Proposed channel value below reserve mandated by holder, {} vs {}",
3435+
proposed_channel_value, holder_selected_channel_reserve_satoshis,
3436+
)));
3437+
}
3438+
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
3439+
proposed_channel_value, self.counterparty_dust_limit_satoshis);
3440+
if proposed_channel_value < counterparty_selected_channel_reserve_satoshis {
3441+
return Err(ChannelError::Warn(format!(
3442+
"Proposed channel value below reserve mandated by counterparty, {} vs {}",
3443+
proposed_channel_value, counterparty_selected_channel_reserve_satoshis,
3444+
)));
3445+
}
3446+
Ok(())
3447+
}
3448+
34283449
/// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
34293450
/// number of pending HTLCs that are on track to be in our next commitment tx.
34303451
///
@@ -3828,10 +3849,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38283849
pub fn get_splice_init(&self, our_funding_contribution_satoshis: i64, signer_provider: &SP,
38293850
funding_feerate_perkw: u32, locktime: u32,
38303851
) -> msgs::SpliceInit {
3831-
if !self.is_outbound() {
3832-
panic!("Tried to initiate a splice on an inbound channel!");
3833-
}
3834-
38353852
// At this point we are not committed to the new channel value yet, but the funding pubkey
38363853
// depends on the channel value, so we create here a new funding pubkey with the new
38373854
// channel value.
@@ -3861,10 +3878,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38613878
/// Get the splice_ack message that can be sent in response to splice initiation.
38623879
#[cfg(splicing)]
38633880
pub fn get_splice_ack(&mut self, our_funding_contribution_satoshis: i64) -> Result<msgs::SpliceAck, ChannelError> {
3864-
if self.is_outbound() {
3865-
panic!("Tried to accept a splice on an outound channel!");
3866-
}
3867-
38683881
// TODO(splicing): checks
38693882

38703883
// Note: at this point keys are already updated
@@ -7458,7 +7471,7 @@ impl<SP: Deref> Channel<SP> where
74587471
#[cfg(splicing)]
74597472
pub fn splice_init<ES: Deref, L: Deref>(
74607473
&mut self, our_funding_contribution_satoshis: i64,
7461-
_signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, logger: &L
7474+
_signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, _logger: &L
74627475
)
74637476
-> Result<msgs::SpliceAck, ChannelError>
74647477
where ES::Target: EntropySource, L::Target: Logger

lightning/src/ln/channelmanager.rs

+17-12
Original file line numberDiff line numberDiff line change
@@ -4115,7 +4115,7 @@ where
41154115
#[cfg(splicing)]
41164116
pub fn splice_channel(
41174117
&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64,
4118-
our_funding_inputs: Vec<(TxIn, Transaction)>, funding_feerate_perkw: u32, locktime: u32,
4118+
_our_funding_inputs: Vec<(TxIn, Transaction)>, funding_feerate_perkw: u32, locktime: u32,
41194119
) -> Result<(), APIError> {
41204120
let per_peer_state = self.per_peer_state.read().unwrap();
41214121

@@ -4131,7 +4131,7 @@ where
41314131
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
41324132
let pre_channel_value = chan.context.get_value_satoshis();
41334133
// Sanity check: capacity cannot decrease below 0
4134-
if our_funding_contribution_satoshis < 0 && -our_funding_contribution_satoshis > (pre_channel_value as i64) {
4134+
if (pre_channel_value as i64).saturating_add(our_funding_contribution_satoshis) < 0 {
41354135
return Err(APIError::APIMisuseError {
41364136
err: format!(
41374137
"Post-splicing channel value cannot be negative. It was {} - {}",
@@ -4158,7 +4158,6 @@ where
41584158

41594159
chan.context.pending_splice_pre = Some(PendingSpliceInfoPre {
41604160
our_funding_contribution: our_funding_contribution_satoshis,
4161-
funding_feerate_perkw, locktime, our_funding_inputs,
41624161
});
41634162

41644163
let msg = chan.context.get_splice_init(our_funding_contribution_satoshis, &self.signer_provider, funding_feerate_perkw, locktime);
@@ -9041,7 +9040,7 @@ where
90419040
if let ChannelPhase::Funded(chan) = chan_entry.get_mut() {
90429041
let pre_channel_value = chan.context.get_value_satoshis();
90439042
// Sanity check: capacity cannot decrease below 0
9044-
if msg.funding_contribution_satoshis < 0 && -msg.funding_contribution_satoshis > (pre_channel_value as i64) {
9043+
if (pre_channel_value as i64).saturating_add(msg.funding_contribution_satoshis) < 0 {
90459044
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
90469045
"Post-splicing channel value cannot be negative. It was {} - {}", pre_channel_value, -msg.funding_contribution_satoshis,
90479046
), msg.channel_id));
@@ -9054,11 +9053,10 @@ where
90549053
}
90559054

90569055
let post_channel_value = PendingSpliceInfoPre::compute_post_value(pre_channel_value, msg.funding_contribution_satoshis, our_funding_contribution);
9057-
if post_channel_value < 1000 {
9058-
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
9059-
"Post-splicing channel value must be at least 1000 satoshis. It was {}", post_channel_value,
9060-
), msg.channel_id));
9061-
}
9056+
9057+
// Check for reserve requirement, it will also be checked later at tx_complete
9058+
let _res = chan.context.check_channel_value_meets_reserve_requirements(post_channel_value)
9059+
.map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.channel_id))?;
90629060

90639061
// Check if a splice has been initiated already.
90649062
// Note: this could be handled more nicely, and support multiple outstanding splice's, the incoming splice_ack matters anyways.
@@ -9111,20 +9109,27 @@ where
91119109
let peer_state = &mut *peer_state_lock;
91129110

91139111
// Look for the channel
9114-
let _pending_splice = match peer_state.channel_by_id.entry(msg.channel_id) {
9112+
match peer_state.channel_by_id.entry(msg.channel_id) {
91159113
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
91169114
"Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}",
91179115
counterparty_node_id
91189116
), msg.channel_id)),
91199117
hash_map::Entry::Occupied(mut chan) => {
91209118
if let ChannelPhase::Funded(chan) = chan.get_mut() {
91219119
// check if splice is pending
9122-
if let Some(pending_splice) = &chan.context.pending_splice_pre {
9120+
let pending_splice = if let Some(pending_splice) = &chan.context.pending_splice_pre {
91239121
// Note: this is incomplete (their funding contribution is not set)
91249122
pending_splice.clone()
91259123
} else {
91269124
return Err(MsgHandleErrInternal::send_err_msg_no_close("Channel is not in pending splice".to_owned(), msg.channel_id));
9127-
}
9125+
};
9126+
9127+
let pre_channel_value = chan.context.get_value_satoshis();
9128+
let post_channel_value = PendingSpliceInfoPre::compute_post_value(pre_channel_value, pending_splice.our_funding_contribution, msg.funding_contribution_satoshis);
9129+
9130+
// Check for reserve requirement, it will also be checked later at tx_complete
9131+
let _res = chan.context.check_channel_value_meets_reserve_requirements(post_channel_value)
9132+
.map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.channel_id))?;
91289133
} else {
91299134
return Err(MsgHandleErrInternal::send_err_msg_no_close("Channel is not funded, cannot splice".to_owned(), msg.channel_id));
91309135
}

0 commit comments

Comments
 (0)