Skip to content

Commit 16d0f2f

Browse files
committed
Make DataLossProtect fields required and remove wrappers
The fields provided by `DataLossProtect` have been mandatory since lightning/bolts@6656b70, regardless of whether `option_dataloss_protect` or `option_remote_key` feature bits are set. We move the fields out of `DataLossProtect` to make encoding definitions more succinct with `impl_writeable_msg!` and to reduce boilerplate. This paves the way for completely removing `OptionalField` in subsequent commits.
1 parent 0e8da58 commit 16d0f2f

File tree

2 files changed

+44
-119
lines changed

2 files changed

+44
-119
lines changed

lightning/src/ln/channel.rs

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use bitcoin::secp256k1;
2525
use crate::ln::{PaymentPreimage, PaymentHash};
2626
use crate::ln::features::{ChannelTypeFeatures, InitFeatures};
2727
use crate::ln::msgs;
28-
use crate::ln::msgs::{DecodeError, OptionalField, DataLossProtect};
28+
use crate::ln::msgs::{DecodeError, OptionalField};
2929
use crate::ln::script::{self, ShutdownScript};
3030
use crate::ln::channelmanager::{self, CounterpartyForwardingInfo, PendingHTLCStatus, HTLCSource, SentHTLCId, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
3131
use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, htlc_success_tx_weight, htlc_timeout_tx_weight, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, ClosingTransaction};
@@ -4043,32 +4043,27 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
40434043
}
40444044

40454045
if msg.next_remote_commitment_number > 0 {
4046-
match msg.data_loss_protect {
4047-
OptionalField::Present(ref data_loss) => {
4048-
let expected_point = self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.secp_ctx);
4049-
let given_secret = SecretKey::from_slice(&data_loss.your_last_per_commitment_secret)
4050-
.map_err(|_| ChannelError::Close("Peer sent a garbage channel_reestablish with unparseable secret key".to_owned()))?;
4051-
if expected_point != PublicKey::from_secret_key(&self.secp_ctx, &given_secret) {
4052-
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned()));
4046+
let expected_point = self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.secp_ctx);
4047+
let given_secret = SecretKey::from_slice(&msg.your_last_per_commitment_secret)
4048+
.map_err(|_| ChannelError::Close("Peer sent a garbage channel_reestablish with unparseable secret key".to_owned()))?;
4049+
if expected_point != PublicKey::from_secret_key(&self.secp_ctx, &given_secret) {
4050+
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned()));
4051+
}
4052+
if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number {
4053+
macro_rules! log_and_panic {
4054+
($err_msg: expr) => {
4055+
log_error!(logger, $err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
4056+
panic!($err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
40534057
}
4054-
if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number {
4055-
macro_rules! log_and_panic {
4056-
($err_msg: expr) => {
4057-
log_error!(logger, $err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
4058-
panic!($err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
4059-
}
4060-
}
4061-
log_and_panic!("We have fallen behind - we have received proof that if we broadcast our counterparty is going to claim all our funds.\n\
4062-
This implies you have restarted with lost ChannelMonitor and ChannelManager state, the first of which is a violation of the LDK chain::Watch requirements.\n\
4063-
More specifically, this means you have a bug in your implementation that can cause loss of funds, or you are running with an old backup, which is unsafe.\n\
4064-
If you have restored from an old backup and wish to force-close channels and return to operation, you should start up, call\n\
4065-
ChannelManager::force_close_without_broadcasting_txn on channel {} with counterparty {} or\n\
4066-
ChannelManager::force_close_all_channels_without_broadcasting_txn, then reconnect to peer(s).\n\
4067-
Note that due to a long-standing bug in lnd you may have to reach out to peers running lnd-based nodes to ask them to manually force-close channels\n\
4068-
See https://github.com/lightningdevkit/rust-lightning/issues/1565 for more info.");
4069-
}
4070-
},
4071-
OptionalField::Absent => {}
4058+
}
4059+
log_and_panic!("We have fallen behind - we have received proof that if we broadcast our counterparty is going to claim all our funds.\n\
4060+
This implies you have restarted with lost ChannelMonitor and ChannelManager state, the first of which is a violation of the LDK chain::Watch requirements.\n\
4061+
More specifically, this means you have a bug in your implementation that can cause loss of funds, or you are running with an old backup, which is unsafe.\n\
4062+
If you have restored from an old backup and wish to force-close channels and return to operation, you should start up, call\n\
4063+
ChannelManager::force_close_without_broadcasting_txn on channel {} with counterparty {} or\n\
4064+
ChannelManager::force_close_all_channels_without_broadcasting_txn, then reconnect to peer(s).\n\
4065+
Note that due to a long-standing bug in lnd you may have to reach out to peers running lnd-based nodes to ask them to manually force-close channels\n\
4066+
See https://github.com/lightningdevkit/rust-lightning/issues/1565 for more info.");
40724067
}
40734068
}
40744069

@@ -5651,19 +5646,13 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
56515646
// valid, and valid in fuzzing mode's arbitrary validity criteria:
56525647
let mut pk = [2; 33]; pk[1] = 0xff;
56535648
let dummy_pubkey = PublicKey::from_slice(&pk).unwrap();
5654-
let data_loss_protect = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER {
5649+
let remote_last_secret = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER {
56555650
let remote_last_secret = self.commitment_secrets.get_secret(self.cur_counterparty_commitment_transaction_number + 2).unwrap();
56565651
log_trace!(logger, "Enough info to generate a Data Loss Protect with per_commitment_secret {} for channel {}", log_bytes!(remote_last_secret), log_bytes!(self.channel_id()));
5657-
OptionalField::Present(DataLossProtect {
5658-
your_last_per_commitment_secret: remote_last_secret,
5659-
my_current_per_commitment_point: dummy_pubkey
5660-
})
5652+
remote_last_secret
56615653
} else {
56625654
log_info!(logger, "Sending a data_loss_protect with no previous remote per_commitment_secret for channel {}", log_bytes!(self.channel_id()));
5663-
OptionalField::Present(DataLossProtect {
5664-
your_last_per_commitment_secret: [0;32],
5665-
my_current_per_commitment_point: dummy_pubkey,
5666-
})
5655+
[0;32]
56675656
};
56685657
msgs::ChannelReestablish {
56695658
channel_id: self.channel_id(),
@@ -5685,7 +5674,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
56855674
// dropped this channel on disconnect as it hasn't yet reached FundingSent so we can't
56865675
// overflow here.
56875676
next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_counterparty_commitment_transaction_number - 1,
5688-
data_loss_protect,
5677+
your_last_per_commitment_secret: remote_last_secret,
5678+
my_current_per_commitment_point: dummy_pubkey,
56895679
}
56905680
}
56915681

@@ -7016,7 +7006,7 @@ mod tests {
70167006
use crate::ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
70177007
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
70187008
use crate::ln::features::ChannelTypeFeatures;
7019-
use crate::ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate, MAX_VALUE_MSAT};
7009+
use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
70207010
use crate::ln::script::ShutdownScript;
70217011
use crate::ln::chan_utils;
70227012
use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
@@ -7317,25 +7307,15 @@ mod tests {
73177307
let msg = node_b_chan.get_channel_reestablish(&&logger);
73187308
assert_eq!(msg.next_local_commitment_number, 1); // now called next_commitment_number
73197309
assert_eq!(msg.next_remote_commitment_number, 0); // now called next_revocation_number
7320-
match msg.data_loss_protect {
7321-
OptionalField::Present(DataLossProtect { your_last_per_commitment_secret, .. }) => {
7322-
assert_eq!(your_last_per_commitment_secret, [0; 32]);
7323-
},
7324-
_ => panic!()
7325-
}
7310+
assert_eq!(msg.your_last_per_commitment_secret, [0; 32]);
73267311

73277312
// Check that the commitment point in Node A's channel_reestablish message
73287313
// is sane.
73297314
node_a_chan.remove_uncommitted_htlcs_and_mark_paused(&&logger);
73307315
let msg = node_a_chan.get_channel_reestablish(&&logger);
73317316
assert_eq!(msg.next_local_commitment_number, 1); // now called next_commitment_number
73327317
assert_eq!(msg.next_remote_commitment_number, 0); // now called next_revocation_number
7333-
match msg.data_loss_protect {
7334-
OptionalField::Present(DataLossProtect { your_last_per_commitment_secret, .. }) => {
7335-
assert_eq!(your_last_per_commitment_secret, [0; 32]);
7336-
},
7337-
_ => panic!()
7338-
}
7318+
assert_eq!(msg.your_last_per_commitment_secret, [0; 32]);
73397319
}
73407320

73417321
#[test]

lightning/src/ln/msgs.rs

Lines changed: 15 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -458,20 +458,6 @@ pub struct UpdateFee {
458458
pub feerate_per_kw: u32,
459459
}
460460

461-
#[derive(Clone, Debug, PartialEq, Eq)]
462-
/// Proof that the sender knows the per-commitment secret of the previous commitment transaction.
463-
///
464-
/// This is used to convince the recipient that the channel is at a certain commitment
465-
/// number even if they lost that data due to a local failure. Of course, the peer may lie
466-
/// and even later commitments may have been revoked.
467-
pub struct DataLossProtect {
468-
/// Proof that the sender knows the per-commitment secret of a specific commitment transaction
469-
/// belonging to the recipient
470-
pub your_last_per_commitment_secret: [u8; 32],
471-
/// The sender's per-commitment point for their current commitment transaction
472-
pub my_current_per_commitment_point: PublicKey,
473-
}
474-
475461
/// A [`channel_reestablish`] message to be sent to or received from a peer.
476462
///
477463
/// [`channel_reestablish`]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#message-retransmission
@@ -483,8 +469,11 @@ pub struct ChannelReestablish {
483469
pub next_local_commitment_number: u64,
484470
/// The next commitment number for the recipient
485471
pub next_remote_commitment_number: u64,
486-
/// Optionally, a field proving that next_remote_commitment_number-1 has been revoked
487-
pub data_loss_protect: OptionalField<DataLossProtect>,
472+
/// Proof that the sender knows the per-commitment secret of a specific commitment transaction
473+
/// belonging to the recipient
474+
pub your_last_per_commitment_secret: [u8; 32],
475+
/// The sender's per-commitment point for their current commitment transaction
476+
pub my_current_per_commitment_point: PublicKey,
488477
}
489478

490479
/// An [`announcement_signatures`] message to be sent to or received from a peer.
@@ -1362,42 +1351,13 @@ impl_writeable_msg!(AnnouncementSignatures, {
13621351
bitcoin_signature
13631352
}, {});
13641353

1365-
impl Writeable for ChannelReestablish {
1366-
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
1367-
self.channel_id.write(w)?;
1368-
self.next_local_commitment_number.write(w)?;
1369-
self.next_remote_commitment_number.write(w)?;
1370-
match self.data_loss_protect {
1371-
OptionalField::Present(ref data_loss_protect) => {
1372-
(*data_loss_protect).your_last_per_commitment_secret.write(w)?;
1373-
(*data_loss_protect).my_current_per_commitment_point.write(w)?;
1374-
},
1375-
OptionalField::Absent => {}
1376-
}
1377-
Ok(())
1378-
}
1379-
}
1380-
1381-
impl Readable for ChannelReestablish{
1382-
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1383-
Ok(Self {
1384-
channel_id: Readable::read(r)?,
1385-
next_local_commitment_number: Readable::read(r)?,
1386-
next_remote_commitment_number: Readable::read(r)?,
1387-
data_loss_protect: {
1388-
match <[u8; 32] as Readable>::read(r) {
1389-
Ok(your_last_per_commitment_secret) =>
1390-
OptionalField::Present(DataLossProtect {
1391-
your_last_per_commitment_secret,
1392-
my_current_per_commitment_point: Readable::read(r)?,
1393-
}),
1394-
Err(DecodeError::ShortRead) => OptionalField::Absent,
1395-
Err(e) => return Err(e)
1396-
}
1397-
}
1398-
})
1399-
}
1400-
}
1354+
impl_writeable_msg!(ChannelReestablish, {
1355+
channel_id,
1356+
next_local_commitment_number,
1357+
next_remote_commitment_number,
1358+
your_last_per_commitment_secret,
1359+
my_current_per_commitment_point,
1360+
}, {});
14011361

14021362
impl_writeable_msg!(ClosingSigned,
14031363
{ channel_id, fee_satoshis, signature },
@@ -2162,23 +2122,7 @@ mod tests {
21622122
use core::convert::TryFrom;
21632123

21642124
#[test]
2165-
fn encoding_channel_reestablish_no_secret() {
2166-
let cr = msgs::ChannelReestablish {
2167-
channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0],
2168-
next_local_commitment_number: 3,
2169-
next_remote_commitment_number: 4,
2170-
data_loss_protect: OptionalField::Absent,
2171-
};
2172-
2173-
let encoded_value = cr.encode();
2174-
assert_eq!(
2175-
encoded_value,
2176-
vec![4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 4]
2177-
);
2178-
}
2179-
2180-
#[test]
2181-
fn encoding_channel_reestablish_with_secret() {
2125+
fn encoding_channel_reestablish() {
21822126
let public_key = {
21832127
let secp_ctx = Secp256k1::new();
21842128
PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&hex::decode("0101010101010101010101010101010101010101010101010101010101010101").unwrap()[..]).unwrap())
@@ -2188,7 +2132,8 @@ mod tests {
21882132
channel_id: [4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0],
21892133
next_local_commitment_number: 3,
21902134
next_remote_commitment_number: 4,
2191-
data_loss_protect: OptionalField::Present(msgs::DataLossProtect { your_last_per_commitment_secret: [9;32], my_current_per_commitment_point: public_key}),
2135+
your_last_per_commitment_secret: [9;32],
2136+
my_current_per_commitment_point: public_key,
21922137
};
21932138

21942139
let encoded_value = cr.encode();

0 commit comments

Comments
 (0)