Skip to content

Commit f4fff42

Browse files
committed
Use channel ID over funding outpoint to track monitors in ChannelManager
As motivated by the previous commit, we do some of the same work here at the `ChannelManager` level instead. Unfortunately, we still need to track the funding outpoint to support downgrades by writing the in flight monitor updates as two separate TLVs, one using the channel IDs, and the other using the funding outpoints. Once we are willing to stop supporting downgrades past this version, we can fully drop it.
1 parent 01b1738 commit f4fff42

File tree

3 files changed

+64
-53
lines changed

3 files changed

+64
-53
lines changed

lightning/src/ln/channelmanager.rs

+60-49
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,8 @@ pub(super) struct PeerState<SP: Deref> where SP::Target: SignerProvider {
13091309
/// for broadcast messages, where ordering isn't as strict).
13101310
pub(super) pending_msg_events: Vec<MessageSendEvent>,
13111311
/// Map from Channel IDs to pending [`ChannelMonitorUpdate`]s which have been passed to the
1312-
/// user but which have not yet completed.
1312+
/// user but which have not yet completed. We still keep the funding outpoint around to backfill
1313+
/// the legacy TLV field to support downgrading.
13131314
///
13141315
/// Note that the channel may no longer exist. For example if the channel was closed but we
13151316
/// later needed to claim an HTLC which is pending on-chain, we may generate a monitor update
@@ -1321,7 +1322,7 @@ pub(super) struct PeerState<SP: Deref> where SP::Target: SignerProvider {
13211322
/// where we complete one [`ChannelMonitorUpdate`] (but there are more pending as background
13221323
/// events) but we conclude all pending [`ChannelMonitorUpdate`]s have completed and its safe
13231324
/// to run post-completion actions.
1324-
in_flight_monitor_updates: BTreeMap<OutPoint, Vec<ChannelMonitorUpdate>>,
1325+
in_flight_monitor_updates: BTreeMap<(OutPoint, ChannelId), Vec<ChannelMonitorUpdate>>,
13251326
/// Map from a specific channel to some action(s) that should be taken when all pending
13261327
/// [`ChannelMonitorUpdate`]s for the channel complete updating.
13271328
///
@@ -3284,7 +3285,7 @@ macro_rules! handle_new_monitor_update {
32843285
$chan_id: expr, $counterparty_node_id: expr, $in_flight_updates: ident, $update_idx: ident,
32853286
_internal_outer, $completed: expr
32863287
) => { {
3287-
$in_flight_updates = $peer_state.in_flight_monitor_updates.entry($funding_txo)
3288+
$in_flight_updates = $peer_state.in_flight_monitor_updates.entry(($funding_txo, $chan_id))
32883289
.or_insert_with(Vec::new);
32893290
// During startup, we push monitor updates as background events through to here in
32903291
// order to replay updates that were in-flight when we shut down. Thus, we have to
@@ -4010,7 +4011,7 @@ where
40104011
let per_peer_state = self.per_peer_state.read().unwrap();
40114012
if let Some(peer_state_mtx) = per_peer_state.get(&shutdown_res.counterparty_node_id) {
40124013
let mut peer_state = peer_state_mtx.lock().unwrap();
4013-
if peer_state.in_flight_monitor_updates.get(&funding_txo).map(|l| l.is_empty()).unwrap_or(true) {
4014+
if peer_state.in_flight_monitor_updates.get(&(funding_txo, shutdown_res.channel_id)).map(|l| l.is_empty()).unwrap_or(true) {
40144015
let update_actions = peer_state.monitor_update_blocked_actions
40154016
.remove(&shutdown_res.channel_id).unwrap_or(Vec::new());
40164017

@@ -7574,7 +7575,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
75747575
let peer_state = &mut *peer_state_lock;
75757576

75767577
let remaining_in_flight =
7577-
if let Some(pending) = peer_state.in_flight_monitor_updates.get_mut(funding_txo) {
7578+
if let Some(pending) = peer_state.in_flight_monitor_updates.get_mut(&(*funding_txo, *channel_id)) {
75787579
pending.retain(|upd| upd.update_id > highest_applied_update_id);
75797580
pending.len()
75807581
} else { 0 };
@@ -12986,12 +12987,22 @@ where
1298612987
pending_claiming_payments = None;
1298712988
}
1298812989

12989-
let mut in_flight_monitor_updates: Option<HashMap<(&PublicKey, &OutPoint), &Vec<ChannelMonitorUpdate>>> = None;
12990+
let mut legacy_in_flight_monitor_updates: Option<HashMap<(&PublicKey, &OutPoint), &Vec<ChannelMonitorUpdate>>> = None;
12991+
let mut in_flight_monitor_updates: Option<HashMap<(&PublicKey, &ChannelId), &Vec<ChannelMonitorUpdate>>> = None;
1299012992
for ((counterparty_id, _), peer_state) in per_peer_state.iter().zip(peer_states.iter()) {
12991-
for (funding_outpoint, updates) in peer_state.in_flight_monitor_updates.iter() {
12993+
for ((funding_txo, channel_id), updates) in peer_state.in_flight_monitor_updates.iter() {
1299212994
if !updates.is_empty() {
12993-
if in_flight_monitor_updates.is_none() { in_flight_monitor_updates = Some(new_hash_map()); }
12994-
in_flight_monitor_updates.as_mut().unwrap().insert((counterparty_id, funding_outpoint), updates);
12995+
if legacy_in_flight_monitor_updates.is_none() {
12996+
legacy_in_flight_monitor_updates = Some(new_hash_map());
12997+
}
12998+
legacy_in_flight_monitor_updates.as_mut().unwrap()
12999+
.insert((counterparty_id, funding_txo), updates);
13000+
13001+
if in_flight_monitor_updates.is_none() {
13002+
in_flight_monitor_updates = Some(new_hash_map());
13003+
}
13004+
in_flight_monitor_updates.as_mut().unwrap()
13005+
.insert((counterparty_id, channel_id), updates);
1299513006
}
1299613007
}
1299713008
}
@@ -13006,11 +13017,12 @@ where
1300613017
(7, self.fake_scid_rand_bytes, required),
1300713018
(8, if events_not_backwards_compatible { Some(&*events) } else { None }, option),
1300813019
(9, htlc_purposes, required_vec),
13009-
(10, in_flight_monitor_updates, option),
13020+
(10, legacy_in_flight_monitor_updates, option),
1301013021
(11, self.probing_cookie_secret, required),
1301113022
(13, htlc_onion_fields, optional_vec),
1301213023
(14, decode_update_add_htlcs_opt, option),
1301313024
(15, self.inbound_payment_id_secret, required),
13025+
(17, in_flight_monitor_updates, required),
1301413026
});
1301513027

1301613028
Ok(())
@@ -13146,8 +13158,7 @@ where
1314613158
/// runtime settings which were stored when the ChannelManager was serialized.
1314713159
pub default_config: UserConfig,
1314813160

13149-
/// A map from channel funding outpoints to ChannelMonitors for those channels (ie
13150-
/// value.context.get_funding_txo() should be the key).
13161+
/// A map from channel IDs to ChannelMonitors for those channels.
1315113162
///
1315213163
/// If a monitor is inconsistent with the channel state during deserialization the channel will
1315313164
/// be force-closed using the data in the ChannelMonitor and the channel will be dropped. This
@@ -13158,7 +13169,7 @@ where
1315813169
/// this struct.
1315913170
///
1316013171
/// This is not exported to bindings users because we have no HashMap bindings
13161-
pub channel_monitors: HashMap<OutPoint, &'a ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>>,
13172+
pub channel_monitors: HashMap<ChannelId, &'a ChannelMonitor<<SP::Target as SignerProvider>::EcdsaSigner>>,
1316213173
}
1316313174

1316413175
impl<'a, M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref>
@@ -13187,7 +13198,7 @@ where
1318713198
entropy_source, node_signer, signer_provider, fee_estimator, chain_monitor,
1318813199
tx_broadcaster, router, message_router, logger, default_config,
1318913200
channel_monitors: hash_map_from_iter(
13190-
channel_monitors.drain(..).map(|monitor| { (monitor.get_funding_txo().0, monitor) })
13201+
channel_monitors.drain(..).map(|monitor| { (monitor.channel_id(), monitor) })
1319113202
),
1319213203
}
1319313204
}
@@ -13250,22 +13261,21 @@ where
1325013261

1325113262
let mut failed_htlcs = Vec::new();
1325213263
let channel_count: u64 = Readable::read(reader)?;
13253-
let mut funding_txo_set = hash_set_with_capacity(cmp::min(channel_count as usize, 128));
13264+
let mut channel_id_set = hash_set_with_capacity(cmp::min(channel_count as usize, 128));
1325413265
let mut per_peer_state = hash_map_with_capacity(cmp::min(channel_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex<PeerState<SP>>)>()));
1325513266
let mut outpoint_to_peer = hash_map_with_capacity(cmp::min(channel_count as usize, 128));
1325613267
let mut short_to_chan_info = hash_map_with_capacity(cmp::min(channel_count as usize, 128));
1325713268
let mut channel_closures = VecDeque::new();
1325813269
let mut close_background_events = Vec::new();
13259-
let mut funding_txo_to_channel_id = hash_map_with_capacity(channel_count as usize);
1326013270
for _ in 0..channel_count {
1326113271
let mut channel: FundedChannel<SP> = FundedChannel::read(reader, (
1326213272
&args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config)
1326313273
))?;
1326413274
let logger = WithChannelContext::from(&args.logger, &channel.context, None);
13275+
let channel_id = channel.context.channel_id();
13276+
channel_id_set.insert(channel_id.clone());
1326513277
let funding_txo = channel.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
13266-
funding_txo_to_channel_id.insert(funding_txo, channel.context.channel_id());
13267-
funding_txo_set.insert(funding_txo.clone());
13268-
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
13278+
if let Some(ref mut monitor) = args.channel_monitors.get_mut(&channel_id) {
1326913279
if channel.get_cur_holder_commitment_transaction_number() > monitor.get_cur_holder_commitment_number() ||
1327013280
channel.get_revoked_counterparty_commitment_transaction_number() > monitor.get_min_seen_secret() ||
1327113281
channel.get_cur_counterparty_commitment_transaction_number() > monitor.get_cur_counterparty_commitment_number() ||
@@ -13348,9 +13358,7 @@ where
1334813358
if let Some(short_channel_id) = channel.context.get_short_channel_id() {
1334913359
short_to_chan_info.insert(short_channel_id, (channel.context.get_counterparty_node_id(), channel.context.channel_id()));
1335013360
}
13351-
if let Some(funding_txo) = channel.context.get_funding_txo() {
13352-
outpoint_to_peer.insert(funding_txo, channel.context.get_counterparty_node_id());
13353-
}
13361+
outpoint_to_peer.insert(funding_txo, channel.context.get_counterparty_node_id());
1335413362
per_peer_state.entry(channel.context.get_counterparty_node_id())
1335513363
.or_insert_with(|| Mutex::new(empty_peer_state()))
1335613364
.get_mut().unwrap()
@@ -13380,8 +13388,8 @@ where
1338013388
}
1338113389
}
1338213390

13383-
for (funding_txo, monitor) in args.channel_monitors.iter() {
13384-
if !funding_txo_set.contains(funding_txo) {
13391+
for (channel_id, monitor) in args.channel_monitors.iter() {
13392+
if !channel_id_set.contains(channel_id) {
1338513393
let mut should_queue_fc_update = false;
1338613394
if let Some(counterparty_node_id) = monitor.get_counterparty_node_id() {
1338713395
// If the ChannelMonitor had any updates, we may need to update it further and
@@ -13419,10 +13427,11 @@ where
1341913427
updates: vec![ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast: true }],
1342013428
channel_id: Some(monitor.channel_id()),
1342113429
};
13430+
let funding_txo = monitor.get_funding_txo().0;
1342213431
if let Some(counterparty_node_id) = monitor.get_counterparty_node_id() {
1342313432
let update = BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
1342413433
counterparty_node_id,
13425-
funding_txo: *funding_txo,
13434+
funding_txo,
1342613435
channel_id,
1342713436
update: monitor_update,
1342813437
};
@@ -13435,7 +13444,7 @@ where
1343513444
// generate a `ChannelMonitorUpdate` for it aside from this
1343613445
// `ChannelForceClosed` one.
1343713446
monitor_update.update_id = u64::MAX;
13438-
close_background_events.push(BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup((*funding_txo, channel_id, monitor_update)));
13447+
close_background_events.push(BackgroundEvent::ClosedMonitorUpdateRegeneratedOnStartup((funding_txo, channel_id, monitor_update)));
1343913448
}
1344013449
}
1344113450
}
@@ -13535,7 +13544,10 @@ where
1353513544
let mut pending_claiming_payments = Some(new_hash_map());
1353613545
let mut monitor_update_blocked_actions_per_peer: Option<Vec<(_, BTreeMap<_, Vec<_>>)>> = Some(Vec::new());
1353713546
let mut events_override = None;
13538-
let mut in_flight_monitor_updates: Option<HashMap<(PublicKey, OutPoint), Vec<ChannelMonitorUpdate>>> = None;
13547+
let mut _legacy_in_flight_monitor_updates: Option<HashMap<(PublicKey, OutPoint), Vec<ChannelMonitorUpdate>>> = None;
13548+
// We use this one over the legacy since they represent the same data, just with a different
13549+
// key. We still need to read the legacy one as it's an even TLV.
13550+
let mut in_flight_monitor_updates: Option<HashMap<(PublicKey, ChannelId), Vec<ChannelMonitorUpdate>>> = None;
1353913551
let mut decode_update_add_htlcs: Option<HashMap<u64, Vec<msgs::UpdateAddHTLC>>> = None;
1354013552
let mut inbound_payment_id_secret = None;
1354113553
read_tlv_fields!(reader, {
@@ -13548,11 +13560,12 @@ where
1354813560
(7, fake_scid_rand_bytes, option),
1354913561
(8, events_override, option),
1355013562
(9, claimable_htlc_purposes, optional_vec),
13551-
(10, in_flight_monitor_updates, option),
13563+
(10, _legacy_in_flight_monitor_updates, option),
1355213564
(11, probing_cookie_secret, option),
1355313565
(13, claimable_htlc_onion_fields, optional_vec),
1355413566
(14, decode_update_add_htlcs, option),
1355513567
(15, inbound_payment_id_secret, option),
13568+
(17, in_flight_monitor_updates, required),
1355613569
});
1355713570
let mut decode_update_add_htlcs = decode_update_add_htlcs.unwrap_or_else(|| new_hash_map());
1355813571
if fake_scid_rand_bytes.is_none() {
@@ -13599,19 +13612,20 @@ where
1359913612
// Because the actual handling of the in-flight updates is the same, it's macro'ized here:
1360013613
let mut pending_background_events = Vec::new();
1360113614
macro_rules! handle_in_flight_updates {
13602-
($counterparty_node_id: expr, $chan_in_flight_upds: expr, $funding_txo: expr,
13603-
$monitor: expr, $peer_state: expr, $logger: expr, $channel_info_log: expr
13615+
($counterparty_node_id: expr, $chan_in_flight_upds: expr, $monitor: expr,
13616+
$peer_state: expr, $logger: expr, $channel_info_log: expr
1360413617
) => { {
1360513618
let mut max_in_flight_update_id = 0;
1360613619
$chan_in_flight_upds.retain(|upd| upd.update_id > $monitor.get_latest_update_id());
13620+
let funding_txo = $monitor.get_funding_txo().0;
1360713621
for update in $chan_in_flight_upds.iter() {
1360813622
log_trace!($logger, "Replaying ChannelMonitorUpdate {} for {}channel {}",
1360913623
update.update_id, $channel_info_log, &$monitor.channel_id());
1361013624
max_in_flight_update_id = cmp::max(max_in_flight_update_id, update.update_id);
1361113625
pending_background_events.push(
1361213626
BackgroundEvent::MonitorUpdateRegeneratedOnStartup {
1361313627
counterparty_node_id: $counterparty_node_id,
13614-
funding_txo: $funding_txo,
13628+
funding_txo: funding_txo.clone(),
1361513629
channel_id: $monitor.channel_id(),
1361613630
update: update.clone(),
1361713631
});
@@ -13630,7 +13644,7 @@ where
1363013644
.and_modify(|v| *v = cmp::max(max_in_flight_update_id, *v))
1363113645
.or_insert(max_in_flight_update_id);
1363213646
}
13633-
if $peer_state.in_flight_monitor_updates.insert($funding_txo, $chan_in_flight_upds).is_some() {
13647+
if $peer_state.in_flight_monitor_updates.insert((funding_txo, $monitor.channel_id()), $chan_in_flight_upds).is_some() {
1363413648
log_error!($logger, "Duplicate in-flight monitor update set for the same channel!");
1363513649
return Err(DecodeError::InvalidValue);
1363613650
}
@@ -13641,28 +13655,27 @@ where
1364113655
for (counterparty_id, peer_state_mtx) in per_peer_state.iter_mut() {
1364213656
let mut peer_state_lock = peer_state_mtx.lock().unwrap();
1364313657
let peer_state = &mut *peer_state_lock;
13644-
for phase in peer_state.channel_by_id.values() {
13658+
for (channel_id, phase) in &peer_state.channel_by_id {
1364513659
if let Some(chan) = phase.as_funded() {
1364613660
let logger = WithChannelContext::from(&args.logger, &chan.context, None);
1364713661

1364813662
// Channels that were persisted have to be funded, otherwise they should have been
1364913663
// discarded.
13650-
let funding_txo = chan.context.get_funding_txo().ok_or(DecodeError::InvalidValue)?;
13651-
let monitor = args.channel_monitors.get(&funding_txo)
13664+
let monitor = args.channel_monitors.get(channel_id)
1365213665
.expect("We already checked for monitor presence when loading channels");
1365313666
let mut max_in_flight_update_id = monitor.get_latest_update_id();
1365413667
if let Some(in_flight_upds) = &mut in_flight_monitor_updates {
13655-
if let Some(mut chan_in_flight_upds) = in_flight_upds.remove(&(*counterparty_id, funding_txo)) {
13668+
if let Some(mut chan_in_flight_upds) = in_flight_upds.remove(&(*counterparty_id, *channel_id)) {
1365613669
max_in_flight_update_id = cmp::max(max_in_flight_update_id,
1365713670
handle_in_flight_updates!(*counterparty_id, chan_in_flight_upds,
13658-
funding_txo, monitor, peer_state, logger, ""));
13671+
monitor, peer_state, logger, ""));
1365913672
}
1366013673
}
1366113674
if chan.get_latest_unblocked_monitor_update_id() > max_in_flight_update_id {
1366213675
// If the channel is ahead of the monitor, return DangerousValue:
1366313676
log_error!(logger, "A ChannelMonitor is stale compared to the current ChannelManager! This indicates a potentially-critical violation of the chain::Watch API!");
1366413677
log_error!(logger, " The ChannelMonitor for channel {} is at update_id {} with update_id through {} in-flight",
13665-
chan.context.channel_id(), monitor.get_latest_update_id(), max_in_flight_update_id);
13678+
channel_id, monitor.get_latest_update_id(), max_in_flight_update_id);
1366613679
log_error!(logger, " but the ChannelManager is at update_id {}.", chan.get_latest_unblocked_monitor_update_id());
1366713680
log_error!(logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
1366813681
log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");
@@ -13680,23 +13693,21 @@ where
1368013693
}
1368113694

1368213695
if let Some(in_flight_upds) = in_flight_monitor_updates {
13683-
for ((counterparty_id, funding_txo), mut chan_in_flight_updates) in in_flight_upds {
13684-
let channel_id = funding_txo_to_channel_id.get(&funding_txo).copied();
13685-
let logger = WithContext::from(&args.logger, Some(counterparty_id), channel_id, None);
13686-
if let Some(monitor) = args.channel_monitors.get(&funding_txo) {
13696+
for ((counterparty_id, channel_id), mut chan_in_flight_updates) in in_flight_upds {
13697+
let logger = WithContext::from(&args.logger, Some(counterparty_id), Some(channel_id), None);
13698+
if let Some(monitor) = args.channel_monitors.get(&channel_id) {
1368713699
// Now that we've removed all the in-flight monitor updates for channels that are
1368813700
// still open, we need to replay any monitor updates that are for closed channels,
1368913701
// creating the neccessary peer_state entries as we go.
1369013702
let peer_state_mutex = per_peer_state.entry(counterparty_id).or_insert_with(|| {
1369113703
Mutex::new(empty_peer_state())
1369213704
});
1369313705
let mut peer_state = peer_state_mutex.lock().unwrap();
13694-
handle_in_flight_updates!(counterparty_id, chan_in_flight_updates,
13695-
funding_txo, monitor, peer_state, logger, "closed ");
13706+
handle_in_flight_updates!(counterparty_id, chan_in_flight_updates, monitor,
13707+
peer_state, logger, "closed ");
1369613708
} else {
1369713709
log_error!(logger, "A ChannelMonitor is missing even though we have in-flight updates for it! This indicates a potentially-critical violation of the chain::Watch API!");
13698-
log_error!(logger, " The ChannelMonitor for channel {} is missing.", if let Some(channel_id) =
13699-
channel_id { channel_id.to_string() } else { format!("with outpoint {}", funding_txo) } );
13710+
log_error!(logger, " The ChannelMonitor for channel {} is missing.", channel_id.to_string());
1370013711
log_error!(logger, " The chain::Watch API *requires* that monitors are persisted durably before returning,");
1370113712
log_error!(logger, " client applications must ensure that ChannelMonitor data is always available and the latest to avoid funds loss!");
1370213713
log_error!(logger, " Without the latest ChannelMonitor we cannot continue without risking funds.");
@@ -13748,7 +13759,7 @@ where
1374813759
.or_insert(update.update_id);
1374913760
}
1375013761
let in_flight_updates = per_peer_state.in_flight_monitor_updates
13751-
.entry(*funding_txo)
13762+
.entry((*funding_txo, *channel_id))
1375213763
.or_insert_with(Vec::new);
1375313764
debug_assert!(!in_flight_updates.iter().any(|upd| upd == update));
1375413765
in_flight_updates.push(update.clone());
@@ -13873,7 +13884,7 @@ where
1387313884
.filter_map(|(htlc_source, (htlc, preimage_opt))| {
1387413885
if let HTLCSource::PreviousHopData(prev_hop) = &htlc_source {
1387513886
if let Some(payment_preimage) = preimage_opt {
13876-
let inbound_edge_monitor = args.channel_monitors.get(&prev_hop.outpoint);
13887+
let inbound_edge_monitor = args.channel_monitors.get(&prev_hop.channel_id);
1387713888
// Note that for channels which have gone to chain,
1387813889
// `get_all_current_outbound_htlcs` is never pruned and always returns
1387913890
// a constant set until the monitor is removed/archived. Thus, we
@@ -14361,7 +14372,7 @@ where
1436114372
);
1436214373
}
1436314374
}
14364-
if let Some(previous_hop_monitor) = args.channel_monitors.get(&claimable_htlc.prev_hop.outpoint) {
14375+
if let Some(previous_hop_monitor) = args.channel_monitors.get(&claimable_htlc.prev_hop.channel_id) {
1436514376
// Note that this is unsafe as we no longer require the
1436614377
// `ChannelMonitor`s to be re-persisted prior to this
1436714378
// `ChannelManager` being persisted after we get started running.

0 commit comments

Comments
 (0)