fuzz: retain channel ids in payment paths
What changed, and why it matters
This commit changes internal fuzz-testing code only. It adds extra bookkeeping so that simulated payment paths remember both a short channel ID and a channel ID. The commit message explicitly says the new fields are not used yet and that this is mechanical preparation for future work. There is no change to production code, no user-facing behavior change, and no security fix or vulnerability introduced in the diff itself.
No security action needed. Treat as normal test-infrastructure refactoring. Monitor follow-up commits that actually interpret the retained channel IDs and paths for any force-close-related logic.
Security signals we found
No security-relevant code change in production paths
Change is confined to fuzz test harness
Commit message describes change as preparatory and explicitly notes new fields are not interpreted yet
Evidence from the diff
In fuzz/src/chanmon_consistency.rs, PaymentHop gains a channel_id field and PendingPayment gains a paths field. Helper methods are updated to carry Vec
Changed components
fuzz/src/chanmon_consistency.rsInspect captured patch +51 / −18
diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs
index 5d493d5..3363c99 100644
--- a/fuzz/src/chanmon_consistency.rs
+++ b/fuzz/src/chanmon_consistency.rs
@@ -1945,6 +1945,7 @@ impl PeerLink {
#[derive(Clone, Copy)]
struct PaymentHop {
+ channel_id: ChannelId,
amount_msat: u64,
short_channel_id: u64,
}
@@ -1955,6 +1956,7 @@ struct PendingPayment {
payment_id: PaymentId,
payment_hash: PaymentHash,
first_persisted_manager_generation: u64,
+ paths: Vec<PaymentPath>,
min_final_cltv_expiry: u32,
}
@@ -1970,14 +1972,17 @@ impl NodePayments {
fn add_pending(
&mut self, payment_id: PaymentId, payment_hash: PaymentHash,
- first_persisted_manager_generation: u64, min_final_cltv_expiry: u32,
+ first_persisted_manager_generation: u64, paths: Vec<PaymentPath>,
+ min_final_cltv_expiry: u32,
) {
assert!(!self.pending.iter().any(|pending| pending.payment_id == payment_id));
assert!(!self.resolved.contains_key(&payment_id));
+ assert!(!paths.is_empty(), "tracked payment must have at least one path");
self.pending.push(PendingPayment {
payment_id,
payment_hash,
first_persisted_manager_generation,
+ paths,
min_final_cltv_expiry,
});
}
@@ -2154,13 +2159,15 @@ impl PaymentTracker {
fn record_send_result(
&mut self, source_idx: usize, source: &HarnessNode<'_>, payment_id: PaymentId,
- payment_hash: PaymentHash, min_final_cltv_expiry: u32, has_pending_work: bool,
+ payment_hash: PaymentHash, payment_paths: Vec<PaymentPath>, min_final_cltv_expiry: u32,
+ has_pending_work: bool,
) {
let node_payments = &mut self.nodes[source_idx];
node_payments.add_pending(
payment_id,
payment_hash,
source.next_manager_persistence_generation(),
+ payment_paths,
min_final_cltv_expiry,
);
if !has_pending_work {
@@ -2187,8 +2194,11 @@ impl PaymentTracker {
)
})
.unwrap_or((0, 0, 0));
- let payment_paths =
- vec![vec![PaymentHop { amount_msat: amt, short_channel_id: dest_scid }]];
+ let payment_paths = vec![vec![PaymentHop {
+ channel_id: dest_chan_id,
+ amount_msat: amt,
+ short_channel_id: dest_scid,
+ }]];
let route_params = RouteParameters::from_payment_params_and_value(
PaymentParameters::from_node_id(source.get_our_node_id(), TEST_FINAL_CLTV),
amt,
@@ -2214,6 +2224,7 @@ impl PaymentTracker {
source,
id,
hash,
+ payment_paths,
min_final_cltv_expiry,
has_pending_work,
);
@@ -2248,8 +2259,12 @@ impl PaymentTracker {
.unwrap_or(0);
let first_hop_fee = 50_000;
let payment_paths = vec![vec![
- PaymentHop { amount_msat: amt + first_hop_fee, short_channel_id: middle_scid },
- PaymentHop { amount_msat: amt, short_channel_id: dest_scid },
+ PaymentHop {
+ channel_id: middle_chan_id,
+ amount_msat: amt + first_hop_fee,
+ short_channel_id: middle_scid,
+ },
+ PaymentHop { channel_id: dest_chan_id, amount_msat: amt, short_channel_id: dest_scid },
]];
let route_params = RouteParameters::from_payment_params_and_value(
PaymentParameters::from_node_id(source.get_our_node_id(), TEST_FINAL_CLTV),
@@ -2277,6 +2292,7 @@ impl PaymentTracker {
source,
id,
hash,
+ payment_paths,
min_final_cltv_expiry,
has_pending_work,
);
@@ -2308,24 +2324,29 @@ impl PaymentTracker {
let dest_scids: Vec<_> = dest_chan_ids
.iter()
.map(|chan_id| {
- dest_chans
+ let scid = dest_chans
.iter()
.find(|chan| chan.channel_id == *chan_id)
.and_then(|chan| chan.short_channel_id)
- .unwrap()
+ .unwrap();
+ (*chan_id, scid)
})
.collect();
let payment_paths: Vec<PaymentPath> = dest_scids
.iter()
.enumerate()
- .map(|(i, dest_scid)| {
+ .map(|(i, (chan_id, dest_scid))| {
let path_amt = if i == num_paths - 1 {
amt - amt_per_path * (num_paths as u64 - 1)
} else {
amt_per_path
};
- vec![PaymentHop { amount_msat: path_amt, short_channel_id: *dest_scid }]
+ vec![PaymentHop {
+ channel_id: *chan_id,
+ amount_msat: path_amt,
+ short_channel_id: *dest_scid,
+ }]
})
.collect();
@@ -2347,6 +2368,7 @@ impl PaymentTracker {
source,
id,
hash,
+ payment_paths,
min_final_cltv_expiry,
has_pending_work,
);
@@ -2375,11 +2397,12 @@ impl PaymentTracker {
let middle_scids: Vec<_> = middle_chan_ids
.iter()
.map(|chan_id| {
- middle_chans
+ let scid = middle_chans
.iter()
.find(|chan| chan.channel_id == *chan_id)
.and_then(|chan| chan.short_channel_id)
- .unwrap()
+ .unwrap();
+ (*chan_id, scid)
})
.collect();
@@ -2387,18 +2410,19 @@ impl PaymentTracker {
let dest_scids: Vec<_> = dest_chan_ids
.iter()
.map(|chan_id| {
- dest_chans
+ let scid = dest_chans
.iter()
.find(|chan| chan.channel_id == *chan_id)
.and_then(|chan| chan.short_channel_id)
- .unwrap()
+ .unwrap();
+ (*chan_id, scid)
})
.collect();
let payment_paths: Vec<PaymentPath> = (0..num_paths)
.map(|i| {
- let middle_scid = middle_scids[i % middle_scids.len()];
- let dest_scid = dest_scids[i % dest_scids.len()];
+ let (middle_chan_id, middle_scid) = middle_scids[i % middle_scids.len()];
+ let (dest_chan_id, dest_scid) = dest_scids[i % dest_scids.len()];
let path_amt = if i == num_paths - 1 {
amt - amt_per_path * (num_paths as u64 - 1)
} else {
@@ -2410,8 +2434,16 @@ impl PaymentTracker {
fee_per_path
};
vec![
- PaymentHop { amount_msat: path_amt + path_fee, short_channel_id: middle_scid },
- PaymentHop { amount_msat: path_amt, short_channel_id: dest_scid },
+ PaymentHop {
+ channel_id: middle_chan_id,
+ amount_msat: path_amt + path_fee,
+ short_channel_id: middle_scid,
+ },
+ PaymentHop {
+ channel_id: dest_chan_id,
+ amount_msat: path_amt,
+ short_channel_id: dest_scid,
+ },
]
})
.collect();
@@ -2434,6 +2466,7 @@ impl PaymentTracker {
source,
id,
hash,
+ payment_paths,
min_final_cltv_expiry,
has_pending_work,
);
Why this scored 13/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.