Skip to content

Commit b0d37ed

Browse files
authored
Merge pull request #2253 from dunxen/2023-05-removeoptionalfield
Remove `OptionalField` and make `DataLossProtect` fields mandatory
2 parents 2cae6f0 + f0b3961 commit b0d37ed

File tree

7 files changed

+87
-205
lines changed

7 files changed

+87
-205
lines changed

lightning/src/ln/channel.rs

+35-55
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;
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};
@@ -1322,7 +1322,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
13221322

13231323
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
13241324
match &msg.shutdown_scriptpubkey {
1325-
&OptionalField::Present(ref script) => {
1325+
&Some(ref script) => {
13261326
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
13271327
if script.len() == 0 {
13281328
None
@@ -1334,7 +1334,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
13341334
}
13351335
},
13361336
// Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
1337-
&OptionalField::Absent => {
1337+
&None => {
13381338
return Err(ChannelError::Close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out".to_owned()));
13391339
}
13401340
}
@@ -2207,7 +2207,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
22072207

22082208
let counterparty_shutdown_scriptpubkey = if their_features.supports_upfront_shutdown_script() {
22092209
match &msg.shutdown_scriptpubkey {
2210-
&OptionalField::Present(ref script) => {
2210+
&Some(ref script) => {
22112211
// Peer is signaling upfront_shutdown and has opt-out with a 0-length script. We don't enforce anything
22122212
if script.len() == 0 {
22132213
None
@@ -2219,7 +2219,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
22192219
}
22202220
},
22212221
// Peer is signaling upfront shutdown but don't opt-out with correct mechanism (a.k.a 0-length script). Peer looks buggy, we fail the channel
2222-
&OptionalField::Absent => {
2222+
&None => {
22232223
return Err(ChannelError::Close("Peer is signaling upfront_shutdown but we don't get any script. Use 0-length script to opt-out".to_owned()));
22242224
}
22252225
}
@@ -4059,32 +4059,27 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
40594059
}
40604060

40614061
if msg.next_remote_commitment_number > 0 {
4062-
match msg.data_loss_protect {
4063-
OptionalField::Present(ref data_loss) => {
4064-
let expected_point = self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.secp_ctx);
4065-
let given_secret = SecretKey::from_slice(&data_loss.your_last_per_commitment_secret)
4066-
.map_err(|_| ChannelError::Close("Peer sent a garbage channel_reestablish with unparseable secret key".to_owned()))?;
4067-
if expected_point != PublicKey::from_secret_key(&self.secp_ctx, &given_secret) {
4068-
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned()));
4062+
let expected_point = self.holder_signer.get_per_commitment_point(INITIAL_COMMITMENT_NUMBER - msg.next_remote_commitment_number + 1, &self.secp_ctx);
4063+
let given_secret = SecretKey::from_slice(&msg.your_last_per_commitment_secret)
4064+
.map_err(|_| ChannelError::Close("Peer sent a garbage channel_reestablish with unparseable secret key".to_owned()))?;
4065+
if expected_point != PublicKey::from_secret_key(&self.secp_ctx, &given_secret) {
4066+
return Err(ChannelError::Close("Peer sent a garbage channel_reestablish with secret key not matching the commitment height provided".to_owned()));
4067+
}
4068+
if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number {
4069+
macro_rules! log_and_panic {
4070+
($err_msg: expr) => {
4071+
log_error!(logger, $err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
4072+
panic!($err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
40694073
}
4070-
if msg.next_remote_commitment_number > INITIAL_COMMITMENT_NUMBER - self.cur_holder_commitment_transaction_number {
4071-
macro_rules! log_and_panic {
4072-
($err_msg: expr) => {
4073-
log_error!(logger, $err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
4074-
panic!($err_msg, log_bytes!(self.channel_id), log_pubkey!(self.counterparty_node_id));
4075-
}
4076-
}
4077-
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\
4078-
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\
4079-
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\
4080-
If you have restored from an old backup and wish to force-close channels and return to operation, you should start up, call\n\
4081-
ChannelManager::force_close_without_broadcasting_txn on channel {} with counterparty {} or\n\
4082-
ChannelManager::force_close_all_channels_without_broadcasting_txn, then reconnect to peer(s).\n\
4083-
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\
4084-
See https://github.com/lightningdevkit/rust-lightning/issues/1565 for more info.");
4085-
}
4086-
},
4087-
OptionalField::Absent => {}
4074+
}
4075+
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\
4076+
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\
4077+
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\
4078+
If you have restored from an old backup and wish to force-close channels and return to operation, you should start up, call\n\
4079+
ChannelManager::force_close_without_broadcasting_txn on channel {} with counterparty {} or\n\
4080+
ChannelManager::force_close_all_channels_without_broadcasting_txn, then reconnect to peer(s).\n\
4081+
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\
4082+
See https://github.com/lightningdevkit/rust-lightning/issues/1565 for more info.");
40884083
}
40894084
}
40904085

@@ -5342,7 +5337,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
53425337
htlc_basepoint: keys.htlc_basepoint,
53435338
first_per_commitment_point,
53445339
channel_flags: if self.config.announced_channel {1} else {0},
5345-
shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
5340+
shutdown_scriptpubkey: Some(match &self.shutdown_scriptpubkey {
53465341
Some(script) => script.clone().into_inner(),
53475342
None => Builder::new().into_script(),
53485343
}),
@@ -5408,7 +5403,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
54085403
delayed_payment_basepoint: keys.delayed_payment_basepoint,
54095404
htlc_basepoint: keys.htlc_basepoint,
54105405
first_per_commitment_point,
5411-
shutdown_scriptpubkey: OptionalField::Present(match &self.shutdown_scriptpubkey {
5406+
shutdown_scriptpubkey: Some(match &self.shutdown_scriptpubkey {
54125407
Some(script) => script.clone().into_inner(),
54135408
None => Builder::new().into_script(),
54145409
}),
@@ -5670,19 +5665,13 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
56705665
// valid, and valid in fuzzing mode's arbitrary validity criteria:
56715666
let mut pk = [2; 33]; pk[1] = 0xff;
56725667
let dummy_pubkey = PublicKey::from_slice(&pk).unwrap();
5673-
let data_loss_protect = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER {
5668+
let remote_last_secret = if self.cur_counterparty_commitment_transaction_number + 1 < INITIAL_COMMITMENT_NUMBER {
56745669
let remote_last_secret = self.commitment_secrets.get_secret(self.cur_counterparty_commitment_transaction_number + 2).unwrap();
56755670
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()));
5676-
OptionalField::Present(DataLossProtect {
5677-
your_last_per_commitment_secret: remote_last_secret,
5678-
my_current_per_commitment_point: dummy_pubkey
5679-
})
5671+
remote_last_secret
56805672
} else {
56815673
log_info!(logger, "Sending a data_loss_protect with no previous remote per_commitment_secret for channel {}", log_bytes!(self.channel_id()));
5682-
OptionalField::Present(DataLossProtect {
5683-
your_last_per_commitment_secret: [0;32],
5684-
my_current_per_commitment_point: dummy_pubkey,
5685-
})
5674+
[0;32]
56865675
};
56875676
msgs::ChannelReestablish {
56885677
channel_id: self.channel_id(),
@@ -5704,7 +5693,8 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
57045693
// dropped this channel on disconnect as it hasn't yet reached FundingSent so we can't
57055694
// overflow here.
57065695
next_remote_commitment_number: INITIAL_COMMITMENT_NUMBER - self.cur_counterparty_commitment_transaction_number - 1,
5707-
data_loss_protect,
5696+
your_last_per_commitment_secret: remote_last_secret,
5697+
my_current_per_commitment_point: dummy_pubkey,
57085698
}
57095699
}
57105700

@@ -7038,7 +7028,7 @@ mod tests {
70387028
use crate::ln::channel::{Channel, InboundHTLCOutput, OutboundHTLCOutput, InboundHTLCState, OutboundHTLCState, HTLCCandidate, HTLCInitiator};
70397029
use crate::ln::channel::{MAX_FUNDING_SATOSHIS_NO_WUMBO, TOTAL_BITCOIN_SUPPLY_SATOSHIS, MIN_THEIR_CHAN_RESERVE_SATOSHIS};
70407030
use crate::ln::features::ChannelTypeFeatures;
7041-
use crate::ln::msgs::{ChannelUpdate, DataLossProtect, DecodeError, OptionalField, UnsignedChannelUpdate, MAX_VALUE_MSAT};
7031+
use crate::ln::msgs::{ChannelUpdate, DecodeError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
70427032
use crate::ln::script::ShutdownScript;
70437033
use crate::ln::chan_utils;
70447034
use crate::ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight};
@@ -7339,25 +7329,15 @@ mod tests {
73397329
let msg = node_b_chan.get_channel_reestablish(&&logger);
73407330
assert_eq!(msg.next_local_commitment_number, 1); // now called next_commitment_number
73417331
assert_eq!(msg.next_remote_commitment_number, 0); // now called next_revocation_number
7342-
match msg.data_loss_protect {
7343-
OptionalField::Present(DataLossProtect { your_last_per_commitment_secret, .. }) => {
7344-
assert_eq!(your_last_per_commitment_secret, [0; 32]);
7345-
},
7346-
_ => panic!()
7347-
}
7332+
assert_eq!(msg.your_last_per_commitment_secret, [0; 32]);
73487333

73497334
// Check that the commitment point in Node A's channel_reestablish message
73507335
// is sane.
73517336
node_a_chan.remove_uncommitted_htlcs_and_mark_paused(&&logger);
73527337
let msg = node_a_chan.get_channel_reestablish(&&logger);
73537338
assert_eq!(msg.next_local_commitment_number, 1); // now called next_commitment_number
73547339
assert_eq!(msg.next_remote_commitment_number, 0); // now called next_revocation_number
7355-
match msg.data_loss_protect {
7356-
OptionalField::Present(DataLossProtect { your_last_per_commitment_secret, .. }) => {
7357-
assert_eq!(your_last_per_commitment_secret, [0; 32]);
7358-
},
7359-
_ => panic!()
7360-
}
7340+
assert_eq!(msg.your_last_per_commitment_secret, [0; 32]);
73617341
}
73627342

73637343
#[test]

lightning/src/ln/channelmanager.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6698,7 +6698,7 @@ pub fn provided_init_features(_config: &UserConfig) -> InitFeatures {
66986698
// should also add the corresponding (optional) bit to the [`ChannelMessageHandler`] impl for
66996699
// [`ErroringMessageHandler`].
67006700
let mut features = InitFeatures::empty();
6701-
features.set_data_loss_protect_optional();
6701+
features.set_data_loss_protect_required();
67026702
features.set_upfront_shutdown_script_optional();
67036703
features.set_variable_length_onion_required();
67046704
features.set_static_remote_key_required();

lightning/src/ln/features.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,7 @@ mod tests {
856856
// Set a bunch of features we use, plus initial_routing_sync_required (which shouldn't get
857857
// converted as it's only relevant in an init context).
858858
init_features.set_initial_routing_sync_required();
859-
init_features.set_data_loss_protect_optional();
859+
init_features.set_data_loss_protect_required();
860860
init_features.set_variable_length_onion_required();
861861
init_features.set_static_remote_key_required();
862862
init_features.set_payment_secret_required();
@@ -876,15 +876,15 @@ mod tests {
876876
let node_features: NodeFeatures = init_features.to_context();
877877
{
878878
// Check that the flags are as expected:
879-
// - option_data_loss_protect
879+
// - option_data_loss_protect (req)
880880
// - var_onion_optin (req) | static_remote_key (req) | payment_secret(req)
881881
// - basic_mpp | wumbo
882882
// - opt_shutdown_anysegwit
883883
// - onion_messages
884884
// - option_channel_type | option_scid_alias
885885
// - option_zeroconf
886886
assert_eq!(node_features.flags.len(), 7);
887-
assert_eq!(node_features.flags[0], 0b00000010);
887+
assert_eq!(node_features.flags[0], 0b00000001);
888888
assert_eq!(node_features.flags[1], 0b01010001);
889889
assert_eq!(node_features.flags[2], 0b10001010);
890890
assert_eq!(node_features.flags[3], 0b00001000);

0 commit comments

Comments
 (0)