Skip to content

Commit 1876a06

Browse files
committed
add channel <-> channel monitor consistency check
1 parent dcad93c commit 1876a06

File tree

5 files changed

+187
-13
lines changed

5 files changed

+187
-13
lines changed

lightning/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ _externalize_tests = ["inventory", "_test_utils"]
2222
# Allow signing of local transactions that may have been revoked or will be revoked, for functional testing (e.g. justice tx handling).
2323
# This is unsafe to use in production because it may result in the counterparty publishing taking our funds.
2424
unsafe_revoked_tx_signing = []
25+
safe_channels = []
2526

2627
std = []
2728

lightning/src/chain/chainmonitor.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,9 +1417,10 @@ where
14171417
let logger = WithChannelMonitor::from(&self.logger, &monitor, None);
14181418
log_trace!(
14191419
logger,
1420-
"Updating ChannelMonitor to id {} for channel {}",
1420+
"Updating ChannelMonitor to id {} for channel {} with updates {:#?}",
14211421
update.update_id,
1422-
log_funding_info!(monitor)
1422+
log_funding_info!(monitor),
1423+
update.updates
14231424
);
14241425

14251426
// We hold a `pending_monitor_updates` lock through `update_monitor` to ensure we

lightning/src/chain/channelmonitor.rs

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use crate::ln::chan_utils::{
5050
self, ChannelTransactionParameters, CommitmentTransaction, CounterpartyCommitmentSecrets,
5151
HTLCClaim, HTLCOutputInCommitment, HolderCommitmentTransaction,
5252
};
53-
use crate::ln::channel::INITIAL_COMMITMENT_NUMBER;
53+
use crate::ln::channel::{read_check_data, INITIAL_COMMITMENT_NUMBER};
5454
use crate::ln::channel_keys::{
5555
DelayedPaymentBasepoint, DelayedPaymentKey, HtlcBasepoint, HtlcKey, RevocationBasepoint,
5656
RevocationKey,
@@ -111,6 +111,9 @@ pub struct ChannelMonitorUpdate {
111111
/// Will be `None` for `ChannelMonitorUpdate`s constructed on LDK versions prior to 0.0.121 and
112112
/// always `Some` otherwise.
113113
pub channel_id: Option<ChannelId>,
114+
115+
/// The encoded channel data associated with this ChannelMonitor, if any.
116+
pub encoded_channel: Option<Vec<u8>>,
114117
}
115118

116119
impl ChannelMonitorUpdate {
@@ -159,6 +162,7 @@ impl Writeable for ChannelMonitorUpdate {
159162
write_tlv_fields!(w, {
160163
// 1 was previously used to store `counterparty_node_id`
161164
(3, self.channel_id, option),
165+
(5, self.encoded_channel, option)
162166
});
163167
Ok(())
164168
}
@@ -176,11 +180,13 @@ impl Readable for ChannelMonitorUpdate {
176180
}
177181
}
178182
let mut channel_id = None;
183+
let mut encoded_channel = None;
179184
read_tlv_fields!(r, {
180185
// 1 was previously used to store `counterparty_node_id`
181186
(3, channel_id, option),
187+
(5, encoded_channel, option)
182188
});
183-
Ok(Self { update_id, updates, channel_id })
189+
Ok(Self { update_id, updates, channel_id, encoded_channel })
184190
}
185191
}
186192

@@ -1402,6 +1408,8 @@ pub(crate) struct ChannelMonitorImpl<Signer: EcdsaChannelSigner> {
14021408
/// make deciding whether to do so simple, here we track whether this monitor was last written
14031409
/// prior to 0.1.
14041410
written_by_0_1_or_later: bool,
1411+
1412+
encoded_channel: Option<Vec<u8>>,
14051413
}
14061414

14071415
// Returns a `&FundingScope` for the one we are currently observing/handling commitment transactions
@@ -1521,6 +1529,9 @@ const MIN_SERIALIZATION_VERSION: u8 = 1;
15211529
pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
15221530
channel_monitor: &ChannelMonitorImpl<Signer>, _is_stub: bool, writer: &mut W,
15231531
) -> Result<(), Error> {
1532+
if let Some(ref encoded_channel) = channel_monitor.encoded_channel {
1533+
channel_monitor.check_encoded_channel_consistency(encoded_channel);
1534+
}
15241535
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
15251536

15261537
channel_monitor.latest_update_id.write(writer)?;
@@ -1755,6 +1766,7 @@ pub(crate) fn write_chanmon_internal<Signer: EcdsaChannelSigner, W: Writer>(
17551766
(34, channel_monitor.alternative_funding_confirmed, option),
17561767
(35, channel_monitor.is_manual_broadcast, required),
17571768
(37, channel_monitor.funding_seen_onchain, required),
1769+
(39, channel_monitor.encoded_channel, option),
17581770
});
17591771

17601772
Ok(())
@@ -1994,6 +2006,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
19942006
alternative_funding_confirmed: None,
19952007

19962008
written_by_0_1_or_later: true,
2009+
encoded_channel: None,
19972010
})
19982011
}
19992012

@@ -2114,6 +2127,17 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
21142127
inner.update_monitor(updates, broadcaster, fee_estimator, &logger)
21152128
}
21162129

2130+
/// Gets the encoded channel data, if any, associated with this ChannelMonitor.
2131+
pub fn get_encoded_channel(&self) -> Option<Vec<u8>> {
2132+
self.inner.lock().unwrap().encoded_channel.clone()
2133+
}
2134+
2135+
/// Updates the encoded channel data associated with this ChannelMonitor. To clear the encoded channel data (for
2136+
/// example after shut down of a channel), pass an empty vector.
2137+
pub fn update_encoded_channel(&self, encoded: Vec<u8>) {
2138+
self.inner.lock().unwrap().update_encoded_channel(encoded);
2139+
}
2140+
21172141
/// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
21182142
/// ChannelMonitor.
21192143
///
@@ -2719,6 +2743,51 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
27192743
}
27202744

27212745
impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
2746+
fn check_encoded_channel_consistency(&self, encoded: &[u8]) {
2747+
let encoded_channel_reader = &mut &encoded[..];
2748+
let check_res = read_check_data(encoded_channel_reader);
2749+
if let Ok(check_data) = check_res {
2750+
debug_assert!(
2751+
check_data.cur_holder_commitment_transaction_number
2752+
== self.get_cur_holder_commitment_number(),
2753+
"cur_holder_commitment_transaction_number - channel: {} vs monitor: {}",
2754+
check_data.cur_holder_commitment_transaction_number,
2755+
self.get_cur_holder_commitment_number()
2756+
);
2757+
debug_assert!(
2758+
check_data.revoked_counterparty_commitment_transaction_number
2759+
== self.get_min_seen_secret(),
2760+
"revoked_counterparty_commitment_transaction_number - channel: {} vs monitor: {}",
2761+
check_data.revoked_counterparty_commitment_transaction_number,
2762+
self.get_min_seen_secret()
2763+
);
2764+
debug_assert!(
2765+
check_data.cur_counterparty_commitment_transaction_number
2766+
== self.get_cur_counterparty_commitment_number(),
2767+
"cur_counterparty_commitment_transaction_number - channel: {} vs monitor: {}",
2768+
check_data.cur_counterparty_commitment_transaction_number,
2769+
self.get_cur_counterparty_commitment_number()
2770+
);
2771+
debug_assert!(
2772+
check_data.latest_monitor_update_id == self.get_latest_update_id(),
2773+
"latest_monitor_update_id - channel: {} vs monitor: {}",
2774+
check_data.latest_monitor_update_id,
2775+
self.get_latest_update_id()
2776+
);
2777+
} else {
2778+
debug_assert!(false, "Failed to read check data from encoded channel");
2779+
}
2780+
}
2781+
2782+
fn update_encoded_channel(&mut self, encoded: Vec<u8>) {
2783+
if encoded.len() > 0 {
2784+
self.check_encoded_channel_consistency(&encoded);
2785+
self.encoded_channel = Some(encoded);
2786+
} else {
2787+
self.encoded_channel = None;
2788+
}
2789+
}
2790+
27222791
/// Helper for get_claimable_balances which does the work for an individual HTLC, generating up
27232792
/// to one `Balance` for the HTLC.
27242793
#[rustfmt::skip]
@@ -3475,6 +3544,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
34753544
return Err("Previous secret did not match new one");
34763545
}
34773546

3547+
println!("Channel monitor current commitment secret index: {}", self.commitment_secrets.get_min_seen_secret());
3548+
34783549
// Prune HTLCs from the previous counterparty commitment tx so we don't generate failure/fulfill
34793550
// events for now-revoked/fulfilled HTLCs.
34803551
let mut removed_fulfilled_htlcs = false;
@@ -4405,9 +4476,20 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
44054476
}
44064477
}
44074478

4408-
if ret.is_ok() && self.no_further_updates_allowed() && is_pre_close_update {
4409-
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
4410-
Err(())
4479+
// Assume that if the updates contains no encoded channel, that the channel remained unchanged. We
4480+
// therefore do not update the monitor.
4481+
if let Some(encoded_channel) = updates.encoded_channel.as_ref() {
4482+
self.update_encoded_channel(encoded_channel.clone());
4483+
}
4484+
4485+
if ret.is_ok() {
4486+
if self.no_further_updates_allowed() && is_pre_close_update {
4487+
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
4488+
Err(())
4489+
} else {
4490+
4491+
Ok(())
4492+
}
44114493
} else { ret }
44124494
}
44134495

@@ -6645,6 +6727,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66456727
let mut alternative_funding_confirmed = None;
66466728
let mut is_manual_broadcast = RequiredWrapper(None);
66476729
let mut funding_seen_onchain = RequiredWrapper(None);
6730+
let mut encoded_channel = None;
66486731
read_tlv_fields!(reader, {
66496732
(1, funding_spend_confirmed, option),
66506733
(3, htlcs_resolved_on_chain, optional_vec),
@@ -6667,6 +6750,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
66676750
(34, alternative_funding_confirmed, option),
66686751
(35, is_manual_broadcast, (default_value, false)),
66696752
(37, funding_seen_onchain, (default_value, true)),
6753+
(39, encoded_channel, option),
66706754
});
66716755
// Note that `payment_preimages_with_info` was added (and is always written) in LDK 0.1, so
66726756
// we can use it to determine if this monitor was last written by LDK 0.1 or later.
@@ -6844,6 +6928,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
68446928
alternative_funding_confirmed,
68456929

68466930
written_by_0_1_or_later,
6931+
encoded_channel,
68476932
});
68486933

68496934
if counterparty_node_id.is_none() {

0 commit comments

Comments
 (0)