Skip to content

Commit 1bf995a

Browse files
joostjagerclaude
andcommitted
chanmon_consistency: skip channels without SCID in MPP sends
send_mpp_payment and send_mpp_hop_payment used list_channels() and unwrapped short_channel_id, which panics for channels that have been force-closed or are not yet fully open. Filter out channels without an SCID and send over the remaining ones, recomputing path count and amounts accordingly. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a24f086 commit 1bf995a

1 file changed

Lines changed: 26 additions & 28 deletions

File tree

fuzz/src/chanmon_consistency.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -713,24 +713,25 @@ fn send_mpp_payment(
713713
source: &ChanMan, dest: &ChanMan, dest_chan_ids: &[ChannelId], amt: u64,
714714
payment_secret: PaymentSecret, payment_hash: PaymentHash, payment_id: PaymentId,
715715
) -> bool {
716-
let num_paths = dest_chan_ids.len();
716+
let mut paths = Vec::new();
717+
718+
let dest_chans = dest.list_channels();
719+
let dest_scids: Vec<_> = dest_chan_ids
720+
.iter()
721+
.filter_map(|chan_id| {
722+
dest_chans
723+
.iter()
724+
.find(|chan| chan.channel_id == *chan_id)
725+
.and_then(|chan| chan.short_channel_id)
726+
})
727+
.collect();
728+
let num_paths = dest_scids.len();
717729
if num_paths == 0 {
718730
return false;
719731
}
720-
721732
let amt_per_path = amt / num_paths as u64;
722-
let mut paths = Vec::with_capacity(num_paths);
723-
724-
let dest_chans = dest.list_channels();
725-
let dest_scids = dest_chan_ids.iter().map(|chan_id| {
726-
dest_chans
727-
.iter()
728-
.find(|chan| chan.channel_id == *chan_id)
729-
.and_then(|chan| chan.short_channel_id)
730-
.unwrap()
731-
});
732733

733-
for (i, dest_scid) in dest_scids.enumerate() {
734+
for (i, dest_scid) in dest_scids.into_iter().enumerate() {
734735
let path_amt = if i == num_paths - 1 {
735736
amt - amt_per_path * (num_paths as u64 - 1)
736737
} else {
@@ -772,41 +773,38 @@ fn send_mpp_hop_payment(
772773
dest_chan_ids: &[ChannelId], amt: u64, payment_secret: PaymentSecret,
773774
payment_hash: PaymentHash, payment_id: PaymentId,
774775
) -> bool {
775-
// Create paths by pairing middle_scids with dest_scids
776-
let num_paths = middle_chan_ids.len().max(dest_chan_ids.len());
777-
if num_paths == 0 {
778-
return false;
779-
}
780-
781-
let first_hop_fee = 50_000;
782-
let amt_per_path = amt / num_paths as u64;
783-
let fee_per_path = first_hop_fee / num_paths as u64;
784-
let mut paths = Vec::with_capacity(num_paths);
785-
786776
let middle_chans = middle.list_channels();
787777
let middle_scids: Vec<_> = middle_chan_ids
788778
.iter()
789-
.map(|chan_id| {
779+
.filter_map(|chan_id| {
790780
middle_chans
791781
.iter()
792782
.find(|chan| chan.channel_id == *chan_id)
793783
.and_then(|chan| chan.short_channel_id)
794-
.unwrap()
795784
})
796785
.collect();
797786

798787
let dest_chans = dest.list_channels();
799788
let dest_scids: Vec<_> = dest_chan_ids
800789
.iter()
801-
.map(|chan_id| {
790+
.filter_map(|chan_id| {
802791
dest_chans
803792
.iter()
804793
.find(|chan| chan.channel_id == *chan_id)
805794
.and_then(|chan| chan.short_channel_id)
806-
.unwrap()
807795
})
808796
.collect();
809797

798+
let num_paths = middle_scids.len().max(dest_scids.len());
799+
if middle_scids.is_empty() || dest_scids.is_empty() {
800+
return false;
801+
}
802+
803+
let first_hop_fee = 50_000;
804+
let amt_per_path = amt / num_paths as u64;
805+
let fee_per_path = first_hop_fee / num_paths as u64;
806+
let mut paths = Vec::with_capacity(num_paths);
807+
810808
for i in 0..num_paths {
811809
let middle_scid = middle_scids[i % middle_scids.len()];
812810
let dest_scid = dest_scids[i % dest_scids.len()];

0 commit comments

Comments
 (0)