Add simple, partially-tested, once-a-minute probing 2023-11-simple-prober
authorMatt Corallo <git@bluematt.me>
Wed, 15 Nov 2023 16:37:50 +0000 (16:37 +0000)
committerMatt Corallo <git@bluematt.me>
Wed, 15 Nov 2023 16:37:50 +0000 (16:37 +0000)
src/main.rs

index 6480805d92759eed4d90407ada06a3f6eb7f202f..1d6edb45006a70d53e8a3d466dd9968c3c8d1dfb 100644 (file)
@@ -12,6 +12,7 @@ use bitcoin::blockdata::transaction::Transaction;
 use bitcoin::consensus::encode;
 use bitcoin::network::constants::Network;
 use bitcoin::BlockHash;
+use bitcoin::secp256k1::PublicKey;
 use bitcoin_bech32::WitnessProgram;
 use disk::{INBOUND_PAYMENTS_FNAME, OUTBOUND_PAYMENTS_FNAME};
 use lightning::chain::{chainmonitor, ChannelMonitorUpdateStatus};
@@ -28,8 +29,9 @@ use lightning::ln::{ChannelId, PaymentHash, PaymentPreimage, PaymentSecret};
 use lightning::onion_message::{DefaultMessageRouter, SimpleArcOnionMessenger};
 use lightning::routing::gossip;
 use lightning::routing::gossip::{NodeId, P2PGossipSync};
-use lightning::routing::router::DefaultRouter;
+use lightning::routing::router::{DefaultRouter, RouteParameters, PaymentParameters, ScorerAccountingForInFlightHtlcs};
 use lightning::routing::scoring::ProbabilisticScoringFeeParameters;
+use lightning::routing::scoring::ProbabilisticScorer;
 use lightning::sign::{EntropySource, InMemorySigner, KeysManager, SpendableOutputDescriptor};
 use lightning::util::config::UserConfig;
 use lightning::util::persist::{self, KVStore, MonitorUpdatingPersister};
@@ -176,6 +178,48 @@ pub(crate) type BumpTxEventHandler = BumpTransactionEventHandler<
        Arc<FilesystemLogger>,
 >;
 
+fn send_rand_probe(
+       channel_manager: &ChannelManager, graph: &NetworkGraph,
+       logger: &disk::FilesystemLogger,
+       scorer: &RwLock<ProbabilisticScorer<Arc<NetworkGraph>, Arc<disk::FilesystemLogger>>>
+) {
+       let rcpt = {
+               let lck = graph.read_only();
+               if lck.nodes().is_empty() { return; }
+               let mut it = lck.nodes().unordered_iter().skip(::rand::random::<usize>() % lck.nodes().len());
+               it.next().unwrap().0.clone()
+       };
+       let amt = ::rand::random::<u64>() % 500_000_000;
+       if let Ok(pk) = bitcoin::secp256k1::PublicKey::from_slice(rcpt.as_slice()) {
+               send_probe(channel_manager, pk, graph, logger, amt, scorer);
+       }
+}
+
+fn send_probe(
+       channel_manager: &ChannelManager, recipient: PublicKey, graph: &NetworkGraph,
+       logger: &disk::FilesystemLogger, amt_msat: u64,
+       scorer: &RwLock<ProbabilisticScorer<Arc<NetworkGraph>, Arc<disk::FilesystemLogger>>>
+) {
+       let chans = channel_manager.list_usable_channels();
+       let chan_refs = chans.iter().map(|a| a).collect::<Vec<_>>();
+       let mut payment_params = PaymentParameters::from_node_id(recipient, 144);
+       payment_params.max_path_count = 1;
+       let in_flight_htlcs = channel_manager.compute_inflight_htlcs();
+       let scorer = scorer.read().unwrap();
+       let inflight_scorer = ScorerAccountingForInFlightHtlcs::new(&scorer, &in_flight_htlcs);
+       let score_params: ProbabilisticScoringFeeParameters = Default::default();
+       let route_res = lightning::routing::router::find_route(
+               &channel_manager.get_our_node_id(),
+               &RouteParameters::from_payment_params_and_value(payment_params, amt_msat),
+               &graph, Some(&chan_refs), logger, &inflight_scorer, &score_params, &[32; 32]
+       );
+       if let Ok(route) = route_res {
+               for path in route.paths {
+                       let _ = channel_manager.send_probe(path);
+               }
+       }
+}
+
 async fn handle_ldk_events(
        channel_manager: &Arc<ChannelManager>, bitcoind_client: &BitcoindClient,
        network_graph: &NetworkGraph, keys_manager: &KeysManager,
@@ -1015,6 +1059,19 @@ async fn start_ldk() {
                Arc::clone(&channel_manager),
        ));
 
+       // Regularly probe
+       let probing_cm = Arc::clone(&channel_manager);
+       let probing_graph = Arc::clone(&network_graph);
+       let probing_logger = Arc::clone(&logger);
+       let probing_scorer = Arc::clone(&scorer);
+       tokio::spawn(async move {
+               let mut interval = tokio::time::interval(Duration::from_secs(1));
+               loop {
+                       interval.tick().await;
+                       send_rand_probe(&*probing_cm, &*probing_graph, &*probing_logger, &*probing_scorer);
+               }
+       });
+
        // Start the CLI.
        let cli_channel_manager = Arc::clone(&channel_manager);
        let cli_persister = Arc::clone(&persister);