Include `maybe_announced` field in `RouteHop`
authorElias Rohrer <dev@tnull.de>
Tue, 12 Sep 2023 13:51:37 +0000 (15:51 +0200)
committerElias Rohrer <dev@tnull.de>
Mon, 18 Sep 2023 13:08:27 +0000 (15:08 +0200)
When sending preflight probes, we want to exclude last hops that are
possibly announced. To this end, we here include a new field in
`RouteHop` that will be `true` when we either def. know the hop to be
announced, or, if there exist public channels between the hop's
counterparties that this hop might refer to (i.e., be an alias for).

fuzz/src/chanmon_consistency.rs
lightning-background-processor/src/lib.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/onion_utils.rs
lightning/src/ln/outbound_payment.rs
lightning/src/ln/payment_tests.rs
lightning/src/routing/router.rs
lightning/src/routing/scoring.rs

index 4c79f0bee27f41e527bd40efdd51051e7dac15c9..b68310264280dbded23ca6000714cbee74902d6a 100644 (file)
@@ -375,6 +375,7 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
                        channel_features: dest.channel_features(),
                        fee_msat: amt,
                        cltv_expiry_delta: 200,
+                       maybe_announced_channel: true,
                }], blinded_tail: None }],
                route_params: None,
        }, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_id)) {
@@ -409,6 +410,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
                        channel_features: middle.channel_features(),
                        fee_msat: first_hop_fee,
                        cltv_expiry_delta: 100,
+                       maybe_announced_channel: true,
                }, RouteHop {
                        pubkey: dest.get_our_node_id(),
                        node_features: dest.node_features(),
@@ -416,6 +418,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
                        channel_features: dest.channel_features(),
                        fee_msat: amt,
                        cltv_expiry_delta: 200,
+                       maybe_announced_channel: true,
                }], blinded_tail: None }],
                route_params: None,
        }, payment_hash, RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_id)) {
index 353ed6738d686698a9dd88079587316019f738d2..b3d1f3755eb0f4b06a9696cee95fe6857a65506f 100644 (file)
@@ -1685,6 +1685,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 0,
                                cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA as u32,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None };
 
                        $nodes[0].scorer.lock().unwrap().expect(TestResult::PaymentFailure { path: path.clone(), short_channel_id: scored_scid });
index c0e33432611bd4aacc29f15b3affdea8fb1c7e98..b252a352c48df981c2a2d102ba188c9943942143 100644 (file)
@@ -1036,7 +1036,8 @@ fn fake_network_test() {
                short_channel_id: chan_2.0.contents.short_channel_id,
                channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
-               cltv_expiry_delta: chan_3.0.contents.cltv_expiry_delta as u32
+               cltv_expiry_delta: chan_3.0.contents.cltv_expiry_delta as u32,
+               maybe_announced_channel: true,
        });
        hops.push(RouteHop {
                pubkey: nodes[3].node.get_our_node_id(),
@@ -1044,7 +1045,8 @@ fn fake_network_test() {
                short_channel_id: chan_3.0.contents.short_channel_id,
                channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
-               cltv_expiry_delta: chan_4.1.contents.cltv_expiry_delta as u32
+               cltv_expiry_delta: chan_4.1.contents.cltv_expiry_delta as u32,
+               maybe_announced_channel: true,
        });
        hops.push(RouteHop {
                pubkey: nodes[1].node.get_our_node_id(),
@@ -1053,6 +1055,7 @@ fn fake_network_test() {
                channel_features: nodes[1].node.channel_features(),
                fee_msat: 1000000,
                cltv_expiry_delta: TEST_FINAL_CLTV,
+               maybe_announced_channel: true,
        });
        hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
        hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
@@ -1067,7 +1070,8 @@ fn fake_network_test() {
                short_channel_id: chan_4.0.contents.short_channel_id,
                channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
-               cltv_expiry_delta: chan_3.1.contents.cltv_expiry_delta as u32
+               cltv_expiry_delta: chan_3.1.contents.cltv_expiry_delta as u32,
+               maybe_announced_channel: true,
        });
        hops.push(RouteHop {
                pubkey: nodes[2].node.get_our_node_id(),
@@ -1075,7 +1079,8 @@ fn fake_network_test() {
                short_channel_id: chan_3.0.contents.short_channel_id,
                channel_features: ChannelFeatures::empty(),
                fee_msat: 0,
-               cltv_expiry_delta: chan_2.1.contents.cltv_expiry_delta as u32
+               cltv_expiry_delta: chan_2.1.contents.cltv_expiry_delta as u32,
+               maybe_announced_channel: true,
        });
        hops.push(RouteHop {
                pubkey: nodes[1].node.get_our_node_id(),
@@ -1084,6 +1089,7 @@ fn fake_network_test() {
                channel_features: nodes[1].node.channel_features(),
                fee_msat: 1000000,
                cltv_expiry_delta: TEST_FINAL_CLTV,
+               maybe_announced_channel: true,
        });
        hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
        hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
index 8fdbdefef6592766b52b9ad0cf142e55ad045990..9b6babe345b9f18d05479c735d3e218a309a2f30 100644 (file)
@@ -984,27 +984,27 @@ mod tests {
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
                                                channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops.
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops.
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
                                                channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops.
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops.
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
                                                channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops.
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops.
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("032c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991").unwrap()[..]).unwrap(),
                                                channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops.
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops.
                                        },
                                        RouteHop {
                                                pubkey: PublicKey::from_slice(&hex::decode("02edabbd16b41c8371b92ef2f04c1185b4f03b6dcd52ba9b78d9d7c89c8f221145").unwrap()[..]).unwrap(),
                                                channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0 // We fill in the payloads manually instead of generating them from RouteHops.
+                                               short_channel_id: 0, fee_msat: 0, cltv_expiry_delta: 0, maybe_announced_channel: true, // We fill in the payloads manually instead of generating them from RouteHops.
                                        },
                        ], blinded_tail: None }],
                        route_params: None,
index 127e73c20f8044be5749947fbce14560296974c6..0d6586e40f405386bab08737e8e05398ce1d5b51 100644 (file)
@@ -1853,6 +1853,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 0,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None }],
                        route_params: Some(route_params.clone()),
                };
@@ -2153,6 +2154,7 @@ mod tests {
                                                                channel_features: ChannelFeatures::empty(),
                                                                fee_msat: invoice.amount_msats(),
                                                                cltv_expiry_delta: 0,
+                                                               maybe_announced_channel: true,
                                                        }
                                                ],
                                                blinded_tail: None,
index d88730c22db058f6f39c0a0f140adc3fdc89dfb5..835ad67f1bc458638bf1061cfd56890070a916fa 100644 (file)
@@ -2201,6 +2201,7 @@ fn auto_retry_partial_failure() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: amt_msat / 2,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                        Path { hops: vec![RouteHop {
                                pubkey: nodes[1].node.get_our_node_id(),
@@ -2209,6 +2210,7 @@ fn auto_retry_partial_failure() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: amt_msat / 2,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                ],
                route_params: Some(route_params.clone()),
@@ -2222,6 +2224,7 @@ fn auto_retry_partial_failure() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: amt_msat / 4,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                        Path { hops: vec![RouteHop {
                                pubkey: nodes[1].node.get_our_node_id(),
@@ -2230,6 +2233,7 @@ fn auto_retry_partial_failure() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: amt_msat / 4,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                ],
                route_params: Some(route_params.clone()),
@@ -2243,6 +2247,7 @@ fn auto_retry_partial_failure() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: amt_msat / 4,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                ],
                route_params: Some(route_params.clone()),
@@ -2487,6 +2492,7 @@ fn retry_multi_path_single_failed_payment() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 10_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                        Path { hops: vec![RouteHop {
                                pubkey: nodes[1].node.get_our_node_id(),
@@ -2495,6 +2501,7 @@ fn retry_multi_path_single_failed_payment() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                ],
                route_params: Some(route_params.clone()),
@@ -2576,6 +2583,7 @@ fn immediate_retry_on_failure() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 100_000_001, // Our default max-HTLC-value is 10% of the channel value, which this is one more than
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                ],
                route_params: Some(RouteParameters::from_payment_params_and_value(
@@ -2662,6 +2670,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }, RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
                                node_features: nodes[2].node.node_features(),
@@ -2669,6 +2678,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                                channel_features: nodes[2].node.channel_features(),
                                fee_msat: 100_000_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                        Path { hops: vec![RouteHop {
                                pubkey: nodes[1].node.get_our_node_id(),
@@ -2677,6 +2687,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }, RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
                                node_features: nodes[2].node.node_features(),
@@ -2684,6 +2695,7 @@ fn no_extra_retries_on_back_to_back_fail() {
                                channel_features: nodes[2].node.channel_features(),
                                fee_msat: 100_000_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None }
                ],
                route_params: Some(RouteParameters::from_payment_params_and_value(
@@ -2862,6 +2874,7 @@ fn test_simple_partial_retry() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 0, // nodes[1] will fail the payment as we don't pay its fee
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }, RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
                                node_features: nodes[2].node.node_features(),
@@ -2869,6 +2882,7 @@ fn test_simple_partial_retry() {
                                channel_features: nodes[2].node.channel_features(),
                                fee_msat: 100_000_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                        Path { hops: vec![RouteHop {
                                pubkey: nodes[1].node.get_our_node_id(),
@@ -2877,6 +2891,7 @@ fn test_simple_partial_retry() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 100_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }, RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
                                node_features: nodes[2].node.node_features(),
@@ -2884,6 +2899,7 @@ fn test_simple_partial_retry() {
                                channel_features: nodes[2].node.channel_features(),
                                fee_msat: 100_000_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None }
                ],
                route_params: Some(RouteParameters::from_payment_params_and_value(
@@ -3026,6 +3042,7 @@ fn test_threaded_payment_retries() {
                                channel_features: nodes[1].node.channel_features(),
                                fee_msat: 0,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }, RouteHop {
                                pubkey: nodes[3].node.get_our_node_id(),
                                node_features: nodes[2].node.node_features(),
@@ -3033,6 +3050,7 @@ fn test_threaded_payment_retries() {
                                channel_features: nodes[2].node.channel_features(),
                                fee_msat: amt_msat / 1000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None },
                        Path { hops: vec![RouteHop {
                                pubkey: nodes[2].node.get_our_node_id(),
@@ -3041,6 +3059,7 @@ fn test_threaded_payment_retries() {
                                channel_features: nodes[2].node.channel_features(),
                                fee_msat: 100_000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }, RouteHop {
                                pubkey: nodes[3].node.get_our_node_id(),
                                node_features: nodes[3].node.node_features(),
@@ -3048,6 +3067,7 @@ fn test_threaded_payment_retries() {
                                channel_features: nodes[3].node.channel_features(),
                                fee_msat: amt_msat - amt_msat / 1000,
                                cltv_expiry_delta: 100,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None }
                ],
                route_params: Some(RouteParameters::from_payment_params_and_value(
index 9c5fe8e1f9bd3dab59033644591a4a59b49d173b..1758cbbf9c3eaae24151050f488c2524f43109da 100644 (file)
@@ -250,10 +250,20 @@ pub struct RouteHop {
        ///
        /// [`BlindedPath`]: crate::blinded_path::BlindedPath
        pub cltv_expiry_delta: u32,
+       /// Indicates whether this hop is possibly announced in the public network graph.
+       ///
+       /// Will be `true` if there is a possibility that the channel is publicly known, i.e., if we
+       /// either know for sure it's announced in the public graph, or if any public channels exist
+       /// for which the given `short_channel_id` could be an alias for. Will be `false` if we believe
+       /// the channel to be unannounced.
+       ///
+       /// Will be `true` for objects serialized with LDK version 0.0.116 and before.
+       pub maybe_announced_channel: bool,
 }
 
 impl_writeable_tlv_based!(RouteHop, {
        (0, pubkey, required),
+       (1, maybe_announced_channel, (default_value, true)),
        (2, node_features, required),
        (4, short_channel_id, required),
        (6, channel_features, required),
@@ -2472,9 +2482,27 @@ where L::Target: Logger {
        let mut paths = Vec::new();
        for payment_path in selected_route {
                let mut hops = Vec::with_capacity(payment_path.hops.len());
+               let mut prev_hop_node_id = our_node_id;
                for (hop, node_features) in payment_path.hops.iter()
                        .filter(|(h, _)| h.candidate.short_channel_id().is_some())
                {
+                       let maybe_announced_channel = if let CandidateRouteHop::PublicHop { .. } = hop.candidate {
+                               // If we sourced the hop from the graph we're sure the target node is announced.
+                               true
+                       } else if let CandidateRouteHop::FirstHop { details } = hop.candidate {
+                               // If this is a first hop we also know if it's announced.
+                               details.is_public
+                       } else {
+                               // If we sourced it any other way, we double-check the network graph to see if
+                               // there are announced channels between the endpoints. If so, the hop might be
+                               // referring to any of the announced channels, as its `short_channel_id` might be
+                               // an alias, in which case we don't take any chances here.
+                               network_graph.node(&hop.node_id).map_or(false, |hop_node|
+                                       hop_node.channels.iter().any(|scid| network_graph.channel(*scid)
+                                                       .map_or(false, |c| c.as_directed_from(&prev_hop_node_id).is_some()))
+                               )
+                       };
+
                        hops.push(RouteHop {
                                pubkey: PublicKey::from_slice(hop.node_id.as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &hop.node_id), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
                                node_features: node_features.clone(),
@@ -2482,7 +2510,10 @@ where L::Target: Logger {
                                channel_features: hop.candidate.features(),
                                fee_msat: hop.fee_msat,
                                cltv_expiry_delta: hop.candidate.cltv_expiry_delta(),
+                               maybe_announced_channel,
                        });
+
+                       prev_hop_node_id = hop.node_id;
                }
                let mut final_cltv_delta = final_cltv_expiry_delta;
                let blinded_tail = payment_path.hops.last().and_then(|(h, _)| {
@@ -5964,17 +5995,17 @@ mod tests {
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("027f31ebc5462c1fdce1b737ecff52d37d75dea43ce11c74d25aa297165faa2007").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 225, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                        ], blinded_tail: None }],
                        route_params: None,
@@ -5991,23 +6022,23 @@ mod tests {
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                        ], blinded_tail: None }, Path { hops: vec![
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("02eec7245d6b7d2ccb30380bfbe2a3648cd7a942653f5aa340edcea1f283686619").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 100, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                                RouteHop {
                                        pubkey: PublicKey::from_slice(&hex::decode("0324653eac434488002cc06bbfb7f10fe18991e35f9fe4302dbea6d2353dc0ab1c").unwrap()[..]).unwrap(),
                                        channel_features: ChannelFeatures::empty(), node_features: NodeFeatures::empty(),
-                                       short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0
+                                       short_channel_id: 0, fee_msat: 150, cltv_expiry_delta: 0, maybe_announced_channel: true,
                                },
                        ], blinded_tail: None }],
                        route_params: None,
@@ -6606,6 +6637,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 100,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: true,
                        }],
                        blinded_tail: Some(BlindedTail {
                                hops: blinded_path_1.blinded_hops,
@@ -6620,6 +6652,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 100,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: true,
                        }], blinded_tail: None }],
                        route_params: None,
                };
@@ -6659,6 +6692,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 100,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: false,
                        },
                        RouteHop {
                                pubkey: blinded_path.introduction_node_id,
@@ -6667,6 +6701,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 1,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: false,
                        }],
                        blinded_tail: Some(BlindedTail {
                                hops: blinded_path.blinded_hops,
@@ -6699,6 +6734,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 100,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: false,
                        },
                        RouteHop {
                                pubkey: blinded_path.introduction_node_id,
@@ -6707,6 +6743,7 @@ mod tests {
                                channel_features: ChannelFeatures::empty(),
                                fee_msat: 1,
                                cltv_expiry_delta: 0,
+                               maybe_announced_channel: false,
                        }
                        ],
                        blinded_tail: Some(BlindedTail {
index aaafbc35b6134f4edd839e13c4b3a4c7830759e2..c4f31db9471039581d028888725de76c999c7ac4 100644 (file)
@@ -2014,6 +2014,7 @@ mod tests {
                        channel_features: channelmanager::provided_channel_features(&config),
                        fee_msat,
                        cltv_expiry_delta: 18,
+                       maybe_announced_channel: true,
                }
        }