Skip to content

Commit d4dfbde

Browse files
committed
Review: check for reserve, etc.
1 parent c5a9932 commit d4dfbde

File tree

2 files changed

+46
-28
lines changed

2 files changed

+46
-28
lines changed

lightning/src/ln/channel.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2525
use bitcoin::secp256k1::{PublicKey,SecretKey};
2626
use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
2727
use bitcoin::{secp256k1, sighash};
28-
#[cfg(splicing)]
29-
use bitcoin::TxIn;
3028

3129
use crate::ln::types::ChannelId;
3230
use crate::types::payment::{PaymentPreimage, PaymentHash};
@@ -1188,11 +1186,12 @@ impl UnfundedChannelContext {
11881186
#[derive(Clone)]
11891187
pub(crate) struct PendingSpliceInfoPre {
11901188
pub our_funding_contribution: i64,
1191-
pub funding_feerate_perkw: u32,
1192-
pub locktime: u32,
1193-
/// The funding inputs we will be contributing to the splice.
1194-
/// TODO(splice): will be changed to TransactionU16LenLimited
1195-
pub our_funding_inputs: Vec<(TxIn, Transaction)>,
1189+
// TODO(splicing): Enable below fields
1190+
// pub funding_feerate_perkw: u32,
1191+
// pub locktime: u32,
1192+
// /// The funding inputs we will be contributing to the splice.
1193+
// /// TODO(splice): will be changed to TransactionU16LenLimited
1194+
// pub our_funding_inputs: Vec<(TxIn, Transaction)>,
11961195
}
11971196

11981197
#[cfg(splicing)]
@@ -3654,6 +3653,28 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36543653
(context.holder_selected_channel_reserve_satoshis, context.counterparty_selected_channel_reserve_satoshis)
36553654
}
36563655

3656+
/// Check that a proposed channel value meets the channel reserve requirements or violates them (below reserve)
3657+
#[cfg(any(dual_funding, splicing))]
3658+
pub fn check_channel_value_meets_reserve_requirements(&self, proposed_channel_value: u64) -> Result<(), ChannelError> {
3659+
let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
3660+
proposed_channel_value, self.holder_dust_limit_satoshis);
3661+
if proposed_channel_value < holder_selected_channel_reserve_satoshis {
3662+
return Err(ChannelError::Warn(format!(
3663+
"Proposed channel value below reserve mandated by holder, {} vs {}",
3664+
proposed_channel_value, holder_selected_channel_reserve_satoshis,
3665+
)));
3666+
}
3667+
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
3668+
proposed_channel_value, self.counterparty_dust_limit_satoshis);
3669+
if proposed_channel_value < counterparty_selected_channel_reserve_satoshis {
3670+
return Err(ChannelError::Warn(format!(
3671+
"Proposed channel value below reserve mandated by counterparty, {} vs {}",
3672+
proposed_channel_value, counterparty_selected_channel_reserve_satoshis,
3673+
)));
3674+
}
3675+
Ok(())
3676+
}
3677+
36573678
/// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
36583679
/// number of pending HTLCs that are on track to be in our next commitment tx.
36593680
///
@@ -4142,10 +4163,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41424163
pub fn get_splice_init(&self, our_funding_contribution_satoshis: i64, signer_provider: &SP,
41434164
funding_feerate_perkw: u32, locktime: u32,
41444165
) -> msgs::SpliceInit {
4145-
if !self.is_outbound() {
4146-
panic!("Tried to initiate a splice on an inbound channel!");
4147-
}
4148-
41494166
// At this point we are not committed to the new channel value yet, but the funding pubkey
41504167
// depends on the channel value, so we create here a new funding pubkey with the new
41514168
// channel value.
@@ -4175,10 +4192,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41754192
/// Get the splice_ack message that can be sent in response to splice initiation.
41764193
#[cfg(splicing)]
41774194
pub fn get_splice_ack(&mut self, our_funding_contribution_satoshis: i64) -> Result<msgs::SpliceAck, ChannelError> {
4178-
if self.is_outbound() {
4179-
panic!("Tried to accept a splice on an outound channel!");
4180-
}
4181-
41824195
// TODO(splicing): checks
41834196

41844197
// Note: at this point keys are already updated
@@ -7915,7 +7928,7 @@ impl<SP: Deref> Channel<SP> where
79157928
#[cfg(splicing)]
79167929
pub fn splice_init<ES: Deref, L: Deref>(
79177930
&mut self, our_funding_contribution_satoshis: i64,
7918-
_signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, logger: &L
7931+
_signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, _logger: &L
79197932
)
79207933
-> Result<msgs::SpliceAck, ChannelError>
79217934
where ES::Target: EntropySource, L::Target: Logger

lightning/src/ln/channelmanager.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4127,7 +4127,7 @@ where
41274127
#[cfg(splicing)]
41284128
pub fn splice_channel(
41294129
&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64,
4130-
our_funding_inputs: Vec<(TxIn, Transaction)>, funding_feerate_perkw: u32, locktime: u32,
4130+
_our_funding_inputs: Vec<(TxIn, Transaction)>, funding_feerate_perkw: u32, locktime: u32,
41314131
) -> Result<(), APIError> {
41324132
let per_peer_state = self.per_peer_state.read().unwrap();
41334133

@@ -4143,7 +4143,7 @@ where
41434143
if let ChannelPhase::Funded(chan) = chan_phase_entry.get_mut() {
41444144
let pre_channel_value = chan.context.get_value_satoshis();
41454145
// Sanity check: capacity cannot decrease below 0
4146-
if our_funding_contribution_satoshis < 0 && -our_funding_contribution_satoshis > (pre_channel_value as i64) {
4146+
if (pre_channel_value as i64).saturating_add(our_funding_contribution_satoshis) < 0 {
41474147
return Err(APIError::APIMisuseError {
41484148
err: format!(
41494149
"Post-splicing channel value cannot be negative. It was {} - {}",
@@ -4170,7 +4170,6 @@ where
41704170

41714171
chan.context.pending_splice_pre = Some(PendingSpliceInfoPre {
41724172
our_funding_contribution: our_funding_contribution_satoshis,
4173-
funding_feerate_perkw, locktime, our_funding_inputs,
41744173
});
41754174

41764175
let msg = chan.context.get_splice_init(our_funding_contribution_satoshis, &self.signer_provider, funding_feerate_perkw, locktime);
@@ -9407,7 +9406,7 @@ where
94079406
if let ChannelPhase::Funded(chan) = chan_entry.get_mut() {
94089407
let pre_channel_value = chan.context.get_value_satoshis();
94099408
// Sanity check: capacity cannot decrease below 0
9410-
if msg.funding_contribution_satoshis < 0 && -msg.funding_contribution_satoshis > (pre_channel_value as i64) {
9409+
if (pre_channel_value as i64).saturating_add(msg.funding_contribution_satoshis) < 0 {
94119410
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
94129411
"Post-splicing channel value cannot be negative. It was {} - {}", pre_channel_value, -msg.funding_contribution_satoshis,
94139412
), msg.channel_id));
@@ -9420,11 +9419,10 @@ where
94209419
}
94219420

94229421
let post_channel_value = PendingSpliceInfoPre::compute_post_value(pre_channel_value, msg.funding_contribution_satoshis, our_funding_contribution);
9423-
if post_channel_value < 1000 {
9424-
return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
9425-
"Post-splicing channel value must be at least 1000 satoshis. It was {}", post_channel_value,
9426-
), msg.channel_id));
9427-
}
9422+
9423+
// Check for reserve requirement, it will also be checked later at tx_complete
9424+
let _res = chan.context.check_channel_value_meets_reserve_requirements(post_channel_value)
9425+
.map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.channel_id))?;
94289426

94299427
// Check if a splice has been initiated already.
94309428
// Note: this could be handled more nicely, and support multiple outstanding splice's, the incoming splice_ack matters anyways.
@@ -9477,20 +9475,27 @@ where
94779475
let peer_state = &mut *peer_state_lock;
94789476

94799477
// Look for the channel
9480-
let _pending_splice = match peer_state.channel_by_id.entry(msg.channel_id) {
9478+
match peer_state.channel_by_id.entry(msg.channel_id) {
94819479
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
94829480
"Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}",
94839481
counterparty_node_id
94849482
), msg.channel_id)),
94859483
hash_map::Entry::Occupied(mut chan) => {
94869484
if let ChannelPhase::Funded(chan) = chan.get_mut() {
94879485
// check if splice is pending
9488-
if let Some(pending_splice) = &chan.context.pending_splice_pre {
9486+
let pending_splice = if let Some(pending_splice) = &chan.context.pending_splice_pre {
94899487
// Note: this is incomplete (their funding contribution is not set)
94909488
pending_splice.clone()
94919489
} else {
94929490
return Err(MsgHandleErrInternal::send_err_msg_no_close("Channel is not in pending splice".to_owned(), msg.channel_id));
9493-
}
9491+
};
9492+
9493+
let pre_channel_value = chan.context.get_value_satoshis();
9494+
let post_channel_value = PendingSpliceInfoPre::compute_post_value(pre_channel_value, pending_splice.our_funding_contribution, msg.funding_contribution_satoshis);
9495+
9496+
// Check for reserve requirement, it will also be checked later at tx_complete
9497+
let _res = chan.context.check_channel_value_meets_reserve_requirements(post_channel_value)
9498+
.map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.channel_id))?;
94949499
} else {
94959500
return Err(MsgHandleErrInternal::send_err_msg_no_close("Channel is not funded, cannot splice".to_owned(), msg.channel_id));
94969501
}

0 commit comments

Comments
 (0)