diff --git a/Cargo.lock b/Cargo.lock index 86335ed3..9a9dbd1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,6 +226,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "ldk-lsp-client" +version = "0.1.0" +source = "git+https://github.com/johncantrell97/ldk-lsp-client?rev=a7313e645c46a79c3ff91dab228a9f98790263c6#a7313e645c46a79c3ff91dab228a9f98790263c6" +dependencies = [ + "bitcoin", + "lightning", + "lightning-invoice", + "lightning-net-tokio", + "serde", + "serde_json", +] + [[package]] name = "ldk-sample" version = "0.1.0" @@ -236,6 +249,7 @@ dependencies = [ "bitcoin-bech32", "chrono", "hex", + "ldk-lsp-client", "libc", "lightning", "lightning-background-processor", @@ -258,17 +272,16 @@ checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "lightning" version = "0.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e009e1c0c21f66378b491bb40f548682138c63e09db6f3a05af59f8804bb9f4a" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bitcoin", + "musig2", ] [[package]] name = "lightning-background-processor" version = "0.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721b05b9848a09d5b943915449b5ffb31e24708007763640cf9d79b124a17e19" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bitcoin", "lightning", @@ -278,8 +291,7 @@ dependencies = [ [[package]] name = "lightning-block-sync" version = "0.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c60cf241b3c219ee865aad91eab85a879b23c1756a335a5a311790ad6c1c3d2" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bitcoin", "chunked_transfer", @@ -290,8 +302,7 @@ dependencies = [ [[package]] name = "lightning-invoice" version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4e44b0e2822c8811470137d2339fdfe67a699b3248bb1606d1d02eb6a1e9f0a" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bech32 0.9.1", "bitcoin", @@ -304,8 +315,7 @@ dependencies = [ [[package]] name = "lightning-net-tokio" version = "0.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4561ec5d4df2dd410a8b80955791fcfb007ef9210395db6e914b9527397b868c" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bitcoin", "lightning", @@ -315,8 +325,7 @@ dependencies = [ [[package]] name = "lightning-persister" version = "0.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c52ed57ec33fb945f464b7e91b5df49f49fec649e1b44909f3ce517e96b0449a" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bitcoin", "libc", @@ -327,8 +336,7 @@ dependencies = [ [[package]] name = "lightning-rapid-gossip-sync" version = "0.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd84d74a9b3892db22a60ac11dfc12e76b257b3174db6743e818ecc24834f3be" +source = "git+https://github.com/lightningdevkit/rust-lightning.git?rev=498f2331459d8031031ef151a44c90d700aa8c7e#498f2331459d8031031ef151a44c90d700aa8c7e" dependencies = [ "bitcoin", "lightning", @@ -380,6 +388,14 @@ dependencies = [ "winapi", ] +[[package]] +name = "musig2" +version = "0.1.0" +source = "git+https://github.com/arik-so/rust-musig2?rev=27797d7#27797d78cf64e8974e38d7f31ebb11e455015a9e" +dependencies = [ + "bitcoin", +] + [[package]] name = "ntapi" version = "0.3.7" @@ -521,6 +537,20 @@ name = "serde" version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.152" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "serde_json" diff --git a/Cargo.toml b/Cargo.toml index aa842bf0..f8481a55 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,13 +8,14 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -lightning = { version = "0.0.115", features = ["max_level_trace"] } -lightning-block-sync = { version = "0.0.115", features = [ "rpc-client" ] } -lightning-invoice = { version = "0.23" } -lightning-net-tokio = { version = "0.0.115" } -lightning-persister = { version = "0.0.115" } -lightning-background-processor = { version = "0.0.115", features = [ "futures" ] } -lightning-rapid-gossip-sync = { version = "0.0.115" } +lightning = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e", features = ["max_level_trace"] } +lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e", features = [ "rpc-client" ] } +lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e" } +lightning-net-tokio = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e" } +lightning-persister = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e" } +lightning-background-processor = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e", features = [ "futures" ] } +lightning-rapid-gossip-sync = { git = "https://github.com/lightningdevkit/rust-lightning.git", rev = "498f2331459d8031031ef151a44c90d700aa8c7e" } +ldk-lsp-client = { git = "https://github.com/johncantrell97/ldk-lsp-client", rev = "a7313e645c46a79c3ff91dab228a9f98790263c6" } base64 = "0.13.0" bitcoin = "0.29.0" diff --git a/src/cli.rs b/src/cli.rs index cba62559..a3e6d3c8 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,3 +1,4 @@ +use crate::SampleLiquidityManager; use crate::disk; use crate::hex_utils; use crate::{ @@ -8,7 +9,8 @@ use bitcoin::hashes::sha256::Hash as Sha256; use bitcoin::hashes::Hash; use bitcoin::network::constants::Network; use bitcoin::secp256k1::PublicKey; -use lightning::chain::keysinterface::{EntropySource, KeysManager}; +use ldk_lsp_client::LiquidityManager; +use lightning::sign::{EntropySource, KeysManager}; use lightning::ln::channelmanager::{PaymentId, RecipientOnionFields, Retry}; use lightning::ln::msgs::NetAddress; use lightning::ln::{PaymentHash, PaymentPreimage}; @@ -63,7 +65,7 @@ pub(crate) async fn poll_for_user_input( keys_manager: Arc, network_graph: Arc, onion_messenger: Arc, inbound_payments: PaymentInfoStorage, outbound_payments: PaymentInfoStorage, ldk_data_dir: String, network: Network, - logger: Arc, + logger: Arc, liquidity_manager: Arc, ) { println!( "LDK startup successful. Enter \"help\" to view available commands. Press Ctrl-D to quit." @@ -87,6 +89,45 @@ pub(crate) async fn poll_for_user_input( if let Some(word) = words.next() { match word { "help" => help(), + "getjitchannelinvoice" => { + let peer_pubkey_and_ip_addr = words.next(); + + if peer_pubkey_and_ip_addr.is_none() { + println!("ERROR: getjitchannelinvoice has 1 required argument: `getjitchannelinvoice pubkey@host:port [payment_amount_msat]`"); + continue; + } + let peer_pubkey_and_ip_addr = peer_pubkey_and_ip_addr.unwrap(); + let (pubkey, peer_addr) = + match parse_peer_info(peer_pubkey_and_ip_addr.to_string()) { + Ok(info) => info, + Err(e) => { + println!("{:?}", e.into_inner().unwrap()); + continue; + } + }; + + if connect_peer_if_necessary(pubkey, peer_addr, peer_manager.clone()) + .await + .is_err() + { + continue; + }; + + let mut payment_amount_msat = None; + + if let Some(n) = words.next() { + let n: Result = n.parse(); + if n.is_err() { + println!("ERROR: payment_amount_msat must be a number"); + continue; + } + payment_amount_msat = Some(n.unwrap()); + } + + if let Err(e) = liquidity_manager.create_invoice(pubkey, payment_amount_msat, None, 0) { + println!("{:?}", e); + } + } "openchannel" => { let peer_pubkey_and_ip_addr = words.next(); let channel_value_sat = words.next(); diff --git a/src/disk.rs b/src/disk.rs index 0c308513..7a9c5390 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -2,7 +2,7 @@ use crate::{cli, NetworkGraph}; use bitcoin::secp256k1::PublicKey; use bitcoin::Network; use chrono::Utc; -use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters}; +use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringDecayParameters}; use lightning::util::logger::{Logger, Record}; use lightning::util::ser::{ReadableArgs, Writer}; use std::collections::HashMap; @@ -86,9 +86,9 @@ pub(crate) fn read_network( pub(crate) fn read_scorer( path: &Path, graph: Arc, logger: Arc, ) -> ProbabilisticScorer, Arc> { - let params = ProbabilisticScoringParameters::default(); + let params = ProbabilisticScoringDecayParameters::default(); if let Ok(file) = File::open(path) { - let args = (params.clone(), Arc::clone(&graph), Arc::clone(&logger)); + let args = (params, Arc::clone(&graph), Arc::clone(&logger)); if let Ok(scorer) = ProbabilisticScorer::read(&mut BufReader::new(file), args) { return scorer; } diff --git a/src/main.rs b/src/main.rs index 5a3389e8..d8d8fc3d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,26 +10,30 @@ use crate::bitcoind_client::BitcoindClient; use crate::disk::FilesystemLogger; use bitcoin::blockdata::transaction::Transaction; use bitcoin::consensus::encode; +use bitcoin::hashes::{sha256, Hash}; use bitcoin::network::constants::Network; use bitcoin::BlockHash; +use bitcoin::secp256k1::Secp256k1; use bitcoin_bech32::WitnessProgram; -use lightning::chain; -use lightning::chain::keysinterface::{ +use lightning_invoice::{InvoiceBuilder, Currency, Sha256}; +use lightning::{chain, log_error}; +use lightning::sign::{ EntropySource, InMemorySigner, KeysManager, SpendableOutputDescriptor, }; +use lightning::routing::scoring::ProbabilisticScoringFeeParameters; use lightning::chain::{chainmonitor, ChannelMonitorUpdateStatus}; use lightning::chain::{Filter, Watch}; use lightning::events::{Event, PaymentFailureReason, PaymentPurpose}; -use lightning::ln::channelmanager; +use lightning::ln::channelmanager::{self, MIN_FINAL_CLTV_EXPIRY_DELTA}; use lightning::ln::channelmanager::{ ChainParameters, ChannelManagerReadArgs, SimpleArcChannelManager, }; -use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler, SimpleArcPeerManager}; +use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler, PeerManager as LDKPeerManager, APeerManager}; use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use lightning::onion_message::SimpleArcOnionMessenger; -use lightning::routing::gossip; +use lightning::routing::gossip::{self, RoutingFees}; use lightning::routing::gossip::{NodeId, P2PGossipSync}; -use lightning::routing::router::DefaultRouter; +use lightning::routing::router::{DefaultRouter, RouteHintHop, RouteHint}; use lightning::util::config::UserConfig; use lightning::util::persist::KVStorePersister; use lightning::util::ser::ReadableArgs; @@ -54,6 +58,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::time::{Duration, SystemTime}; +use ldk_lsp_client::{LiquidityManager, LiquidityProviderConfig, RawOpeningFeeParams, JITChannelEvent, JITChannelsConfig}; +use ldk_lsp_client::events::Event as LSPEvent; + pub(crate) const PENDING_SPENDABLE_OUTPUT_DIR: &'static str = "pending_spendable_outputs"; pub(crate) enum HTLCStatus { @@ -91,7 +98,11 @@ type ChainMonitor = chainmonitor::ChainMonitor< Arc, >; -pub(crate) type PeerManager = SimpleArcPeerManager< +pub(crate) type SimpleArcLiquidityManager = LiquidityManager, SD, Arc, Arc>>, Arc, Arc>>,Arc>,Arc>,Arc>; + +pub(crate) type SimpleArcPeerManagerWithCustomMessageHandler = LDKPeerManager>, Arc>>, Arc, Arc>>, Arc>, Arc, Arc>, Arc>; + +pub(crate) type PeerManager = SimpleArcPeerManagerWithCustomMessageHandler< SocketDescriptor, ChainMonitor, BitcoindClient, @@ -100,6 +111,8 @@ pub(crate) type PeerManager = SimpleArcPeerManager< FilesystemLogger, >; +pub(crate) type SampleLiquidityManager = SimpleArcLiquidityManager; + pub(crate) type ChannelManager = SimpleArcChannelManager; @@ -107,11 +120,172 @@ pub(crate) type NetworkGraph = gossip::NetworkGraph>; type OnionMessenger = SimpleArcOnionMessenger; +async fn handle_lsp_event( + network: Network, + event: LSPEvent, + channel_manager: &Arc, + keys_manager: &Arc, + liquidity_manager: &Arc, +) { + match event { + LSPEvent::LSPS2(event) => { + match event { + JITChannelEvent::GetInfo { + request_id, + counterparty_node_id, + version, + token + } => { + // determine based on counterparty_node_id + token + // what fees and restrictions you want to offer + let opening_fee_params_menu = vec![ + RawOpeningFeeParams { + min_fee_msat: 0, + proportional: 0, + valid_until: "2023-06-23T08:47:30.511Z".to_string(), + min_lifetime: 1008, + max_client_to_self_delay: 2016, + } + ]; + + // maybe these should be derived from the fees? + // if not, we will need to somehow store them such that we can + // be sure the payment_size_msat provided in buy request is within + // these bounds + // + // comment open on PR + let min_payment_size_msat = 1_000_000; + let max_payment_size_msat = 100_000_000_000; + + if let Err(e) = liquidity_manager.opening_fee_params_generated( + counterparty_node_id, + request_id, + opening_fee_params_menu, + min_payment_size_msat, + max_payment_size_msat) { + println!("Failed to handle generated opening fee params: {:?}", e); + } + }, + JITChannelEvent::GetInfoResponse { + channel_id, + counterparty_node_id, + opening_fee_params_menu, + min_payment_size_msat, + max_payment_size_msat, + user_channel_id, + } => { + // determine which fee params you want to use + // here we just take the first one + if let Err(e) = liquidity_manager.opening_fee_params_selected( + counterparty_node_id, + channel_id, + opening_fee_params_menu[0].clone() + ) { + println!("Failed to select opening fee parameters: {:?}", e); + } + }, + JITChannelEvent::BuyRequest { + request_id, + counterparty_node_id, + version, + opening_fee_params, + payment_size_msat, + } => { + + // use channel manager to get an scid? + let scid = channel_manager.get_intercept_scid(); + // pick a cltv_expiry_delta? + let cltv_expiry_delta = 144; + + let client_trusts_lsp = false; + + if let Err(e) = liquidity_manager.invoice_parameters_generated( + counterparty_node_id, + request_id, + scid, + cltv_expiry_delta, + client_trusts_lsp + ) { + println!("Failed to provide invoice parameters: {:?}", e); + } + }, + JITChannelEvent::InvoiceGenerationReady { + counterparty_node_id, + scid, + cltv_expiry_delta , + payment_size_msat, + .. + } => { + + // how long until we consider a payment invalid + // really we don't care? but probably should be based on the valid_until params we agreed upon with lsp + let invoice_expiry_delta_secs = 60*60*24*3; + let (payment_hash, payment_secret) = channel_manager.create_inbound_payment(None, invoice_expiry_delta_secs, None).unwrap(); + + let lsp_route_hint = RouteHint(vec![RouteHintHop { + src_node_id: counterparty_node_id, + short_channel_id: scid, + fees: RoutingFees { base_msat: 0, proportional_millionths: 0}, + cltv_expiry_delta: cltv_expiry_delta.try_into().unwrap(), + htlc_minimum_msat: None, + htlc_maximum_msat: None + }]); + + let mut invoice = InvoiceBuilder::new(network.into()) + .description("Coins pls!".into()) + .payment_hash(sha256::Hash::from_slice(&payment_hash.0).unwrap()) + .payment_secret(payment_secret) + .current_timestamp() + .min_final_cltv_expiry_delta(MIN_FINAL_CLTV_EXPIRY_DELTA.into()) + .private_route(lsp_route_hint); + + if let Some(payment_size_msat) = payment_size_msat { + invoice = invoice.amount_milli_satoshis(payment_size_msat) + }; + + let invoice = invoice.build_signed(|hash| { + Secp256k1::new().sign_ecdsa_recoverable(hash, &keys_manager.get_node_secret_key()) + }) + .unwrap(); + + println!("JIT Channel Invoice: {}", invoice); + + }, + JITChannelEvent::FailInterceptedHTLC { + intercept_id + } => { + channel_manager.fail_intercepted_htlc(intercept_id); + }, + JITChannelEvent::ForwardInterceptedHTLC { + intercept_id, + next_hop_channel_id, + next_node_id, + amt_to_forward_msat, + } => { + println!("forwarding intercepted htlc"); + + if let Err(e) = channel_manager.forward_intercepted_htlc(intercept_id, &next_hop_channel_id, next_node_id, amt_to_forward_msat) { + println!("failed to forward intercepted htlc: {:?}", e); + } + }, + JITChannelEvent::OpenChannel { + user_channel_id, + their_network_key, + channel_value_satoshis, + } => { + channel_manager.create_channel(their_network_key, channel_value_satoshis, 0, user_channel_id, None); + } + } + } + } +} + async fn handle_ldk_events( channel_manager: &Arc, bitcoind_client: &BitcoindClient, network_graph: &NetworkGraph, keys_manager: &KeysManager, inbound_payments: &PaymentInfoStorage, outbound_payments: &PaymentInfoStorage, persister: &Arc, network: Network, event: Event, + liquidity_manager: &Arc, ) { match event { Event::FundingGenerationReady { @@ -240,8 +414,16 @@ async fn handle_ldk_events( } } } - Event::OpenChannelRequest { .. } => { - // Unreachable, we don't set manually_accept_inbound_channels + Event::OpenChannelRequest { + temporary_channel_id, + counterparty_node_id, + .. + } => { + // if counterparty_node_id is our LSP then: + if let Err(e) = channel_manager.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &counterparty_node_id, 0) { + println!("Failed to accept inbound channel: {:?}", e); + } + // else accept_inbound_channel } Event::PaymentPathSuccessful { .. } => {} Event::PaymentPathFailed { .. } => {} @@ -364,10 +546,12 @@ async fn handle_ldk_events( } Event::ChannelReady { ref channel_id, - user_channel_id: _, + user_channel_id, ref counterparty_node_id, channel_type: _, } => { + liquidity_manager.channel_ready(user_channel_id, channel_id, counterparty_node_id); + println!( "\nEVENT: Channel {} with peer {} is ready to be used!", hex_utils::hex_str(channel_id), @@ -389,7 +573,9 @@ async fn handle_ldk_events( // A "real" node should probably "lock" the UTXOs spent in funding transactions until // the funding transaction either confirms, or this event is generated. } - Event::HTLCIntercepted { .. } => {} + Event::HTLCIntercepted { requested_next_hop_scid, intercept_id, payment_hash, inbound_amount_msat, expected_outbound_amount_msat } => { + liquidity_manager.htlc_intercepted(requested_next_hop_scid, intercept_id, inbound_amount_msat, expected_outbound_amount_msat); + } } } @@ -519,11 +705,15 @@ async fn start_ldk() { logger.clone(), keys_manager.get_secure_random_bytes(), scorer.clone(), + ProbabilisticScoringFeeParameters::default() )); // Step 11: Initialize the ChannelManager let mut user_config = UserConfig::default(); user_config.channel_handshake_limits.force_announced_channel_preference = false; + user_config.accept_intercept_htlcs = true; + user_config.manually_accept_inbound_channels = true; + let mut restarting_node = true; let (channel_manager_blockhash, channel_manager) = { if let Ok(mut f) = fs::File::open(format!("{}/manager", ldk_data_dir.clone())) { @@ -633,20 +823,33 @@ async fn start_ldk() { let mut ephemeral_bytes = [0; 32]; let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); rand::thread_rng().fill_bytes(&mut ephemeral_bytes); + + // this needs to be the same every time, probably should derive this from an existing secret (hash(node_secret?)) + let promise_secret = keys_manager.get_secure_random_bytes(); + let liquidity_provider_config = LiquidityProviderConfig { + jit_channels: Some(JITChannelsConfig { + promise_secret + }) + }; + + let liquidity_manager = Arc::new(LiquidityManager::new(keys_manager.clone(), Some(liquidity_provider_config))); + let lightning_msg_handler = MessageHandler { chan_handler: channel_manager.clone(), route_handler: gossip_sync.clone(), onion_message_handler: onion_messenger.clone(), + custom_message_handler: liquidity_manager.clone(), }; let peer_manager: Arc = Arc::new(PeerManager::new( lightning_msg_handler, current_time.try_into().unwrap(), &ephemeral_bytes, logger.clone(), - IgnoringMessageHandler {}, Arc::clone(&keys_manager), )); + liquidity_manager.set_peer_manager(peer_manager.clone()); + // ## Running LDK // Step 16: Initialize networking @@ -701,6 +904,7 @@ async fn start_ldk() { let inbound_payments_event_listener = Arc::clone(&inbound_payments); let outbound_payments_event_listener = Arc::clone(&outbound_payments); let persister_event_listener = Arc::clone(&persister); + let liquidity_manager_listener = Arc::clone(&liquidity_manager); let network = args.network; let event_handler = move |event: Event| { let channel_manager_event_listener = Arc::clone(&channel_manager_event_listener); @@ -710,6 +914,7 @@ async fn start_ldk() { let inbound_payments_event_listener = Arc::clone(&inbound_payments_event_listener); let outbound_payments_event_listener = Arc::clone(&outbound_payments_event_listener); let persister_event_listener = Arc::clone(&persister_event_listener); + let liquidity_manager_listener = Arc::clone(&liquidity_manager_listener); async move { handle_ldk_events( &channel_manager_event_listener, @@ -721,6 +926,7 @@ async fn start_ldk() { &persister_event_listener, network, event, + &liquidity_manager_listener ) .await; } @@ -816,6 +1022,20 @@ async fn start_ldk() { } }); + let liquidity_manager_events = liquidity_manager.clone(); + let channel_manager_lsp_events = Arc::clone(&channel_manager); + let keys_manager_lsp_events = Arc::clone(&keys_manager); + tokio::spawn(async move { + let mut interval = tokio::time::interval(Duration::from_secs(1)); + loop { + interval.tick().await; + let events = liquidity_manager_events.get_and_clear_pending_events(); + for event in events { + handle_lsp_event(network, event, &channel_manager_lsp_events, &keys_manager_lsp_events, &liquidity_manager_events).await; + } + } + }); + tokio::spawn(sweep::periodic_sweep( ldk_data_dir.clone(), Arc::clone(&keys_manager), @@ -836,6 +1056,7 @@ async fn start_ldk() { ldk_data_dir, network, Arc::clone(&logger), + Arc::clone(&liquidity_manager), ) .await; diff --git a/src/sweep.rs b/src/sweep.rs index 2a168a7d..59262cfe 100644 --- a/src/sweep.rs +++ b/src/sweep.rs @@ -5,7 +5,7 @@ use std::time::Duration; use std::{fs, io}; use lightning::chain::chaininterface::{BroadcasterInterface, ConfirmationTarget, FeeEstimator}; -use lightning::chain::keysinterface::{EntropySource, KeysManager, SpendableOutputDescriptor}; +use lightning::sign::{EntropySource, KeysManager, SpendableOutputDescriptor}; use lightning::util::logger::Logger; use lightning::util::persist::KVStorePersister; use lightning::util::ser::{Readable, WithoutLength}; @@ -111,6 +111,7 @@ pub(crate) async fn periodic_sweep( Vec::new(), destination_address.script_pubkey(), tx_feerate, + None, &Secp256k1::new(), ) { // Note that, most likely, we've already sweeped this set of outputs