@@ -17330,19 +17330,14 @@ where
1733017330 peer_init_features: Vec<(PublicKey, InitFeatures)>,
1733117331 pending_events: VecDeque<(events::Event, Option<EventCompletionAction>)>,
1733217332 highest_seen_timestamp: u32,
17333- pending_outbound_payments_compat: HashMap<PaymentId, PendingOutboundPayment>,
17334- pending_outbound_payments_no_retry: Option<HashMap<PaymentId, HashSet<[u8; 32]>>>,
1733517333 pending_intercepted_htlcs: Option<HashMap<InterceptId, PendingAddHTLCInfo>>,
17336- pending_outbound_payments: Option< HashMap<PaymentId, PendingOutboundPayment> >,
17334+ pending_outbound_payments: HashMap<PaymentId, PendingOutboundPayment>,
1733717335 pending_claiming_payments: HashMap<PaymentHash, ClaimingPayment>,
1733817336 received_network_pubkey: Option<PublicKey>,
1733917337 monitor_update_blocked_actions_per_peer:
1734017338 Vec<(PublicKey, BTreeMap<ChannelId, Vec<MonitorUpdateCompletionAction>>)>,
1734117339 fake_scid_rand_bytes: Option<[u8; 32]>,
17342- events_override: Option<VecDeque<(events::Event, Option<EventCompletionAction>)>>,
1734317340 claimable_htlc_purposes: Option<Vec<events::PaymentPurpose>>,
17344- legacy_in_flight_monitor_updates:
17345- Option<HashMap<(PublicKey, OutPoint), Vec<ChannelMonitorUpdate>>>,
1734617341 probing_cookie_secret: Option<[u8; 32]>,
1734717342 claimable_htlc_onion_fields: Option<Vec<Option<RecipientOnionFields>>>,
1734817343 decode_update_add_htlcs: Option<HashMap<u64, Vec<msgs::UpdateAddHTLC>>>,
@@ -17539,6 +17534,48 @@ where
1753917534 (21, async_receive_offer_cache, (default_value, async_receive_offer_cache)),
1754017535 });
1754117536
17537+ // Merge legacy pending_outbound_payments fields into a single HashMap.
17538+ // Priority: pending_outbound_payments (TLV 3) > pending_outbound_payments_no_retry (TLV 1)
17539+ // > pending_outbound_payments_compat (non-TLV legacy)
17540+ let pending_outbound_payments = if let Some(payments) = pending_outbound_payments {
17541+ payments
17542+ } else if let Some(mut pending_outbound_payments_no_retry) = pending_outbound_payments_no_retry
17543+ {
17544+ let mut outbounds = new_hash_map();
17545+ for (id, session_privs) in pending_outbound_payments_no_retry.drain() {
17546+ outbounds.insert(id, PendingOutboundPayment::Legacy { session_privs });
17547+ }
17548+ outbounds
17549+ } else {
17550+ pending_outbound_payments_compat
17551+ };
17552+
17553+ // Merge legacy in-flight monitor updates (keyed by OutPoint) into the new format (keyed by
17554+ // ChannelId).
17555+ if let Some(legacy_in_flight_upds) = legacy_in_flight_monitor_updates {
17556+ // We should never serialize an empty map.
17557+ if legacy_in_flight_upds.is_empty() {
17558+ return Err(DecodeError::InvalidValue);
17559+ }
17560+ if in_flight_monitor_updates.is_none() {
17561+ let in_flight_upds = in_flight_monitor_updates.get_or_insert_with(new_hash_map);
17562+ for ((counterparty_node_id, funding_txo), updates) in legacy_in_flight_upds {
17563+ // All channels with legacy in flight monitor updates are v1 channels.
17564+ let channel_id = ChannelId::v1_from_funding_outpoint(funding_txo);
17565+ in_flight_upds.insert((counterparty_node_id, channel_id), updates);
17566+ }
17567+ } else if in_flight_monitor_updates.as_ref().unwrap().is_empty() {
17568+ // Both TLVs present - the new one takes precedence but must not be empty.
17569+ return Err(DecodeError::InvalidValue);
17570+ }
17571+ }
17572+
17573+ // Resolve events_override: if present, it replaces pending_events.
17574+ let mut pending_events = pending_events;
17575+ if let Some(events) = events_override {
17576+ pending_events = events;
17577+ }
17578+
1754217579 Ok(ChannelManagerData {
1754317580 chain_hash,
1754417581 best_block_height,
@@ -17549,8 +17586,6 @@ where
1754917586 peer_init_features,
1755017587 pending_events,
1755117588 highest_seen_timestamp,
17552- pending_outbound_payments_compat,
17553- pending_outbound_payments_no_retry,
1755417589 pending_intercepted_htlcs,
1755517590 pending_outbound_payments,
1755617591 // unwrap safety: pending_claiming_payments is guaranteed to be `Some` after read_tlv_fields
@@ -17560,9 +17595,7 @@ where
1756017595 monitor_update_blocked_actions_per_peer: monitor_update_blocked_actions_per_peer
1756117596 .unwrap(),
1756217597 fake_scid_rand_bytes,
17563- events_override,
1756417598 claimable_htlc_purposes,
17565- legacy_in_flight_monitor_updates,
1756617599 probing_cookie_secret,
1756717600 claimable_htlc_onion_fields,
1756817601 decode_update_add_htlcs,
@@ -17897,7 +17930,7 @@ where
1789717930 let mut claimable_htlcs_list = data.claimable_htlcs;
1789817931 let mut pending_intercepted_htlcs_legacy =
1789917932 data.pending_intercepted_htlcs.unwrap_or_else(new_hash_map);
17900- let mut pending_outbound_payments = data.pending_outbound_payments;
17933+ let pending_outbound_payments = data.pending_outbound_payments;
1790117934 let mut fake_scid_rand_bytes = data.fake_scid_rand_bytes;
1790217935 let mut probing_cookie_secret = data.probing_cookie_secret;
1790317936 let mut decode_update_add_htlcs_legacy =
@@ -18200,26 +18233,12 @@ where
1820018233 inbound_payment_id_secret = Some(args.entropy_source.get_secure_random_bytes());
1820118234 }
1820218235
18203- if let Some(events) = data.events_override {
18204- pending_events_read = events;
18205- }
18206-
1820718236 if !channel_closures.is_empty() {
1820818237 pending_events_read.append(&mut channel_closures);
1820918238 }
1821018239
18211- if pending_outbound_payments.is_none() && data.pending_outbound_payments_no_retry.is_none()
18212- {
18213- pending_outbound_payments = Some(data.pending_outbound_payments_compat);
18214- } else if pending_outbound_payments.is_none() {
18215- let mut outbounds = new_hash_map();
18216- for (id, session_privs) in data.pending_outbound_payments_no_retry.unwrap().drain() {
18217- outbounds.insert(id, PendingOutboundPayment::Legacy { session_privs });
18218- }
18219- pending_outbound_payments = Some(outbounds);
18220- }
1822118240 let pending_outbounds =
18222- OutboundPayments::new(pending_outbound_payments.unwrap() , args.logger.clone());
18241+ OutboundPayments::new(pending_outbound_payments, args.logger.clone());
1822318242
1822418243 if let Some(peer_storage_dir) = data.peer_storage_dir {
1822518244 for (peer_pubkey, peer_storage) in peer_storage_dir {
@@ -18229,28 +18248,6 @@ where
1822918248 }
1823018249 }
1823118250
18232- // Handle transitioning from the legacy TLV to the new one on upgrades.
18233- if let Some(legacy_in_flight_upds) = data.legacy_in_flight_monitor_updates {
18234- // We should never serialize an empty map.
18235- if legacy_in_flight_upds.is_empty() {
18236- return Err(DecodeError::InvalidValue);
18237- }
18238- if in_flight_monitor_updates.is_none() {
18239- let in_flight_upds =
18240- in_flight_monitor_updates.get_or_insert_with(|| new_hash_map());
18241- for ((counterparty_node_id, funding_txo), updates) in legacy_in_flight_upds {
18242- // All channels with legacy in flight monitor updates are v1 channels.
18243- let channel_id = ChannelId::v1_from_funding_outpoint(funding_txo);
18244- in_flight_upds.insert((counterparty_node_id, channel_id), updates);
18245- }
18246- } else {
18247- // We should never serialize an empty map.
18248- if in_flight_monitor_updates.as_ref().unwrap().is_empty() {
18249- return Err(DecodeError::InvalidValue);
18250- }
18251- }
18252- }
18253-
1825418251 // We have to replay (or skip, if they were completed after we wrote the `ChannelManager`)
1825518252 // each `ChannelMonitorUpdate` in `in_flight_monitor_updates`. After doing so, we have to
1825618253 // check that each channel we have isn't newer than the latest `ChannelMonitorUpdate`(s) we
0 commit comments