1use std::cmp::{min, Reverse};
2use std::collections::{HashMap, HashSet};
3use std::iter::Iterator;
4use std::pin::Pin;
5use std::str::FromStr;
6use std::sync::atomic::{AtomicU16, Ordering};
7use std::sync::Arc;
8use std::time::{Duration, SystemTime, UNIX_EPOCH};
9
10use anyhow::{anyhow, Result};
11use ecies::symmetric::{sym_decrypt, sym_encrypt};
12use futures::{Future, Stream};
13use gl_client::credentials::{Device, Nobody};
14use gl_client::node;
15use gl_client::node::ClnClient;
16use gl_client::pb::cln::delinvoice_request::DelinvoiceStatus;
17use gl_client::pb::cln::listinvoices_invoices::ListinvoicesInvoicesStatus;
18use gl_client::pb::cln::listinvoices_request::ListinvoicesIndex;
19use gl_client::pb::cln::listpays_pays::ListpaysPaysStatus;
20use gl_client::pb::cln::listpeerchannels_channels::ListpeerchannelsChannelsState::*;
21use gl_client::pb::cln::listsendpays_request::ListsendpaysIndex;
22use gl_client::pb::cln::{
23 self, Amount, DelinvoiceRequest, GetrouteRequest, GetrouteRoute, ListchannelsRequest,
24 ListclosedchannelsClosedchannels, ListpaysPays, ListpeerchannelsChannels, ListsendpaysPayments,
25 PreapproveinvoiceRequest, SendpayRequest, SendpayRoute, WaitsendpayRequest,
26};
27use gl_client::pb::{incoming_payment, TrampolinePayRequest};
28use gl_client::scheduler::Scheduler;
29use gl_client::signer::model::greenlight::{amount, scheduler};
30use gl_client::signer::Signer;
31use sdk_common::prelude::*;
32use serde::{Deserialize, Serialize};
33use serde_json::{json, Map, Value};
34use strum_macros::{Display, EnumString};
35use tokio::join;
36use tokio::sync::{mpsc, watch, Mutex};
37use tokio::time::{sleep, Instant, MissedTickBehavior};
38use tokio_stream::StreamExt;
39
40use crate::bitcoin::bech32::{u5, ToBase32};
41use crate::bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
42use crate::bitcoin::hashes::Hash;
43use crate::bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
44use crate::bitcoin::secp256k1::PublicKey;
45use crate::bitcoin::secp256k1::Secp256k1;
46use crate::bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey};
47use crate::bitcoin::{
48 Address, OutPoint, Script, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
49};
50use crate::lightning::util::message_signing::verify;
51use crate::lightning_invoice::{RawBolt11Invoice, SignedRawBolt11Invoice};
52use crate::node_api::{
53 CreateInvoiceRequest, FetchBolt11Result, IncomingPayment, NodeAPI, NodeError, NodeResult,
54};
55use crate::persist::cache::NodeStateStorage;
56use crate::persist::db::SqliteStorage;
57use crate::persist::send_pays::{SendPay, SendPayStatus};
58use crate::{models::*, LspInformation};
59use crate::{NodeConfig, PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse};
60
61const MAX_PAYMENT_AMOUNT_MSAT: u64 = 4294967000;
62const MAX_INBOUND_LIQUIDITY_MSAT: u64 = 4000000000;
63const TRAMPOLINE_BASE_FEE_MSAT: u64 = 4000;
64const TRAMPOLINE_FEE_PPM: u64 = 5000;
65const PAYMENT_STATE_PENDING: u8 = 1;
66const PAYMENT_STATE_COMPLETE: u8 = 2;
67const PAYMENT_STATE_FAILED: u8 = 4;
68
69pub(crate) struct Greenlight {
70 sdk_config: Config,
71 signer: Mutex<Arc<Signer>>,
72 device: Device,
73 gl_client: Mutex<Option<node::Client>>,
74 node_client: Mutex<Option<ClnClient>>,
75 persister: Arc<SqliteStorage>,
76 inprogress_payments: AtomicU16,
77}
78
79#[derive(Serialize, Deserialize)]
80struct InvoiceLabel {
81 pub unix_milli: u128,
82 pub payer_amount_msat: Option<u64>,
83}
84
85#[derive(Serialize, Deserialize)]
86struct PaymentLabel {
87 pub unix_nano: u128,
88 pub trampoline: bool,
89 pub client_label: Option<String>,
90 pub amount_msat: u64,
91}
92
93impl Greenlight {
94 pub async fn connect(
101 config: Config,
102 seed: Vec<u8>,
103 restore_only: Option<bool>,
104 persister: Arc<SqliteStorage>,
105 ) -> NodeResult<Self> {
106 let temp_signer = Arc::new(Signer::new(
108 seed.clone(),
109 config.network.into(),
110 Nobody::new(),
111 )?);
112 let encryption_key = Self::derive_bip32_key(
113 config.network,
114 &temp_signer,
115 vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
116 )?
117 .to_priv()
118 .to_bytes();
119 let encryption_key_slice = encryption_key.as_slice();
120
121 let register_credentials = match config.node_config.clone() {
122 NodeConfig::Greenlight { config } => config,
123 };
124
125 let mut parsed_credentials =
127 Self::get_node_credentials(config.network, &temp_signer, persister.clone())?
128 .ok_or(NodeError::credentials("No credentials found"));
129 if parsed_credentials.is_err() {
130 info!("No credentials found, trying to recover existing node");
131 parsed_credentials = match Self::recover(config.network, seed.clone()).await {
132 Ok(creds) => Ok(creds),
133 Err(_) => {
134 match restore_only.unwrap_or(false) {
135 false => {
136 info!("Failed to recover node, registering new one");
138 let credentials = Self::register(
139 config.clone().network,
140 seed.clone(),
141 register_credentials.partner_credentials,
142 register_credentials.invite_code,
143 )
144 .await?;
145 Ok(credentials)
146 }
147 true => {
148 return Err(NodeError::RestoreOnly("Node does not exist".to_string()));
149 }
150 }
151 }
152 }
153 }
154
155 match parsed_credentials {
157 Ok(creds) => {
158 let temp_scheduler = Scheduler::new(config.network.into(), creds.clone()).await?;
159 debug!("upgrading credentials");
160 let creds = creds.upgrade(&temp_scheduler, &temp_signer).await?;
161 debug!("upgrading credentials succeeded");
162 let encrypted_creds = sym_encrypt(encryption_key_slice, &creds.to_bytes());
163 match encrypted_creds {
164 Some(c) => {
165 persister.set_gl_credentials(c)?;
166 Greenlight::new(config, seed, creds.clone(), persister)
167 }
168 None => Err(NodeError::generic("Failed to encrypt credentials")),
169 }
170 }
171 Err(_) => Err(NodeError::credentials("Failed to get gl credentials")),
172 }
173 }
174
175 fn new(
176 sdk_config: Config,
177 seed: Vec<u8>,
178 device: Device,
179 persister: Arc<SqliteStorage>,
180 ) -> NodeResult<Greenlight> {
181 let greenlight_network = sdk_config.network.into();
182 let signer = Signer::new(seed.clone(), greenlight_network, device.clone())?;
183 Ok(Greenlight {
184 sdk_config,
185 signer: Mutex::new(Arc::new(signer)),
186 device,
187 gl_client: Mutex::new(None),
188 node_client: Mutex::new(None),
189 persister,
190 inprogress_payments: AtomicU16::new(0),
191 })
192 }
193
194 async fn get_signer(&self) -> Arc<Signer> {
195 Arc::clone(&*self.signer.lock().await)
196 }
197
198 fn derive_bip32_key(
199 network: Network,
200 signer: &Arc<Signer>,
201 path: Vec<ChildNumber>,
202 ) -> NodeResult<ExtendedPrivKey> {
203 Ok(
204 ExtendedPrivKey::new_master(network.into(), &signer.bip32_ext_key())?
205 .derive_priv(&Secp256k1::new(), &path)?,
206 )
207 }
208
209 fn legacy_derive_bip32_key(
210 network: Network,
211 signer: &Arc<Signer>,
212 path: Vec<ChildNumber>,
213 ) -> NodeResult<ExtendedPrivKey> {
214 Ok(
215 ExtendedPrivKey::new_master(network.into(), &signer.legacy_bip32_ext_key())?
216 .derive_priv(&Secp256k1::new(), &path)?,
217 )
218 }
219
220 async fn register(
221 network: Network,
222 seed: Vec<u8>,
223 register_credentials: Option<GreenlightCredentials>,
224 invite_code: Option<String>,
225 ) -> Result<Device> {
226 if invite_code.is_some() && register_credentials.is_some() {
227 return Err(anyhow!("Cannot specify both invite code and credentials"));
228 }
229 let greenlight_network = network.into();
230 let creds = match register_credentials {
231 Some(creds) => {
232 debug!("registering with credentials");
233 Nobody {
234 cert: creds.developer_cert,
235 key: creds.developer_key,
236 ..Default::default()
237 }
238 }
239 None => Nobody::new(),
240 };
241
242 let signer = Signer::new(seed, greenlight_network, creds.clone())?;
243 let scheduler = Scheduler::new(greenlight_network, creds).await?;
244
245 let register_res: scheduler::RegistrationResponse =
246 scheduler.register(&signer, invite_code).await?;
247
248 Ok(Device::from_bytes(register_res.creds))
249 }
250
251 async fn recover(network: Network, seed: Vec<u8>) -> Result<Device> {
252 let greenlight_network = network.into();
253 let credentials = Nobody::new();
254 let signer = Signer::new(seed, greenlight_network, credentials.clone())?;
255 let scheduler = Scheduler::new(greenlight_network, credentials).await?;
256 let recover_res: scheduler::RecoveryResponse = scheduler.recover(&signer).await?;
257
258 Ok(Device::from_bytes(recover_res.creds))
259 }
260
261 async fn get_client(&self) -> NodeResult<node::Client> {
262 let mut gl_client = self.gl_client.lock().await;
263 if gl_client.is_none() {
264 let scheduler = Scheduler::new(self.sdk_config.network.into(), self.device.clone())
265 .await
266 .map_err(|e| NodeError::ServiceConnectivity(e.to_string()))?;
267 *gl_client = Some(scheduler.node().await?);
268 }
269 Ok(gl_client.clone().unwrap())
270 }
271
272 pub(crate) async fn get_node_client(&self) -> NodeResult<node::ClnClient> {
273 let mut node_client = self.node_client.lock().await;
274 if node_client.is_none() {
275 let scheduler = Scheduler::new(self.sdk_config.network.into(), self.device.clone())
276 .await
277 .map_err(|e| NodeError::ServiceConnectivity(e.to_string()))?;
278 *node_client = Some(scheduler.node().await?);
279 }
280 Ok(node_client.clone().unwrap())
281 }
282
283 fn get_node_credentials(
284 network: Network,
285 signer: &Arc<Signer>,
286 persister: Arc<SqliteStorage>,
287 ) -> NodeResult<Option<Device>> {
288 let encryption_key = Self::derive_bip32_key(
290 network,
291 signer,
292 vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
293 )?
294 .to_priv()
295 .to_bytes();
296 let encryption_key_slice = encryption_key.as_slice();
297
298 let legacy_encryption_key = Self::legacy_derive_bip32_key(
299 network,
300 signer,
301 vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
302 )?
303 .to_priv()
304 .to_bytes();
305 let legacy_encryption_key_slice = legacy_encryption_key.as_slice();
306
307 match persister.get_gl_credentials()? {
308 Some(encrypted_creds) => {
309 let mut decrypted_credentials =
310 sym_decrypt(encryption_key_slice, encrypted_creds.as_slice());
311 if decrypted_credentials.is_none() {
312 info!("Failed to decrypt credentials, trying legacy key");
313 decrypted_credentials =
314 sym_decrypt(legacy_encryption_key_slice, encrypted_creds.as_slice());
315 }
316 match decrypted_credentials {
317 Some(decrypted_creds) => {
318 let credentials = Device::from_bytes(decrypted_creds.as_slice());
319 if credentials.cert.is_empty() {
320 Err(NodeError::credentials("Unable to parse credentials"))
321 } else {
322 Ok(Some(credentials))
323 }
324 }
325 None => Err(NodeError::credentials(
326 "Failed to decrypt credentials, seed doesn't match existing node",
327 )),
328 }
329 }
330 None => Ok(None),
331 }
332 }
333
334 async fn fetch_outgoing_payment_with_retry(
335 client: node::ClnClient,
336 payment_hash: Vec<u8>,
337 ) -> Result<cln::ListpaysPays> {
338 let mut response = cln::ListpaysResponse::default();
339 let mut retry = 0;
340 let max_retries = 20;
341
342 while response.pays.is_empty() && retry < max_retries {
343 let req = cln::ListpaysRequest {
344 payment_hash: Some(payment_hash.clone()),
345 status: Some(cln::listpays_request::ListpaysStatus::Complete.into()),
346 ..cln::ListpaysRequest::default()
347 };
348 let mut client = client.clone();
349 response = with_connection_retry!(client.list_pays(req.clone()))
350 .await?
351 .into_inner();
352 if response.pays.is_empty() {
353 debug!("fetch outgoing payment failed, retrying in 100ms...");
354 sleep(Duration::from_millis(100)).await;
355 }
356 retry += 1;
357 }
358
359 debug!("list_pays: {:?}", response.pays);
361 let pays: Vec<ListpaysPays> = response
362 .pays
363 .into_iter()
364 .filter(|pay| pay.status() == cln::listpays_pays::ListpaysPaysStatus::Complete)
365 .collect();
366
367 if pays.is_empty() {
368 return Err(anyhow!("Payment not found"));
369 }
370 Ok(pays[0].clone())
371 }
372
373 async fn fetch_channels_and_balance_with_retry(
374 cln_client: node::ClnClient,
375 persister: Arc<SqliteStorage>,
376 match_local_balance: bool,
377 ) -> NodeResult<(
378 Vec<cln::ListpeerchannelsChannels>,
379 Vec<cln::ListpeerchannelsChannels>,
380 Vec<String>,
381 u64,
382 )> {
383 let (mut all_channels, mut opened_channels, mut connected_peers, mut channels_balance) =
384 Greenlight::fetch_channels_and_balance(cln_client.clone()).await?;
385 if match_local_balance {
386 let node_state = persister.get_node_state()?;
387 if let Some(state) = node_state {
388 let mut retry_count = 0;
389 while state.channels_balance_msat != channels_balance && retry_count < 10 {
390 warn!("balance matching local state is required and not yet satisfied, retrying in 100ms...");
391 sleep(Duration::from_millis(100)).await;
392 (
393 all_channels,
394 opened_channels,
395 connected_peers,
396 channels_balance,
397 ) = Greenlight::fetch_channels_and_balance(cln_client.clone()).await?;
398 retry_count += 1;
399 }
400 }
401 }
402 Ok((
403 all_channels,
404 opened_channels,
405 connected_peers,
406 channels_balance,
407 ))
408 }
409
410 async fn fetch_channels_and_balance(
411 mut client: node::ClnClient,
412 ) -> NodeResult<(
413 Vec<cln::ListpeerchannelsChannels>,
414 Vec<cln::ListpeerchannelsChannels>,
415 Vec<String>,
416 u64,
417 )> {
418 let req = cln::ListpeerchannelsRequest::default();
420 let peerchannels = with_connection_retry!(client.list_peer_channels(req.clone()))
421 .await?
422 .into_inner();
423
424 let connected_peers: Vec<String> = peerchannels
426 .channels
427 .iter()
428 .filter(|channel| channel.peer_connected())
429 .filter_map(|channel| channel.peer_id.clone())
430 .map(hex::encode)
431 .collect::<HashSet<_>>()
432 .into_iter()
433 .collect();
434
435 let opened_channels: Vec<cln::ListpeerchannelsChannels> = peerchannels
437 .channels
438 .iter()
439 .filter(|c| c.state() == ChanneldNormal)
440 .cloned()
441 .collect();
442
443 let channels_balance = opened_channels
445 .iter()
446 .map(|c| Channel::from(c.clone()))
447 .map(|c| c.spendable_msat)
448 .sum::<u64>();
449 Ok((
450 peerchannels.channels,
451 opened_channels,
452 connected_peers,
453 channels_balance,
454 ))
455 }
456
457 async fn list_funds(&self) -> Result<cln::ListfundsResponse> {
458 let mut client = self.get_node_client().await?;
459 let req = cln::ListfundsRequest::default();
460 let funds: cln::ListfundsResponse = with_connection_retry!(client.list_funds(req.clone()))
461 .await?
462 .into_inner();
463 Ok(funds)
464 }
465
466 async fn on_chain_balance(&self, funds: &cln::ListfundsResponse) -> Result<u64> {
467 let on_chain_balance = funds.outputs.iter().fold(0, |a, b| {
468 if b.reserved {
469 return a;
470 }
471 a + b.amount_msat.clone().unwrap_or_default().msat
472 });
473 Ok(on_chain_balance)
474 }
475
476 async fn pending_onchain_balance(
477 &self,
478 peer_channels: &[cln::ListpeerchannelsChannels],
479 ) -> Result<u64> {
480 let pending_onchain_balance = peer_channels.iter().fold(0, |a, b| match b.state() {
481 ChanneldShuttingDown | ClosingdSigexchange | ClosingdComplete | AwaitingUnilateral
482 | FundingSpendSeen => a + b.to_us_msat.clone().unwrap_or_default().msat,
483
484 Onchain => {
489 if b.closer() == cln::ChannelSide::Local
490 && b.status
491 .last()
492 .is_some_and(|status| status.contains("DELAYED_OUTPUT_TO_US"))
493 {
494 a + b.to_us_msat.clone().unwrap_or_default().msat
495 } else {
496 a
497 }
498 }
499 _ => a,
500 });
501 info!("pending_onchain_balance is {}", pending_onchain_balance);
502 Ok(pending_onchain_balance)
503 }
504
505 async fn utxos(&self, funds: cln::ListfundsResponse) -> Result<Vec<UnspentTransactionOutput>> {
507 let utxos: Vec<UnspentTransactionOutput> = funds
508 .outputs
509 .iter()
510 .map(|output| UnspentTransactionOutput {
511 txid: output.txid.clone(),
512 outnum: output.output,
513 amount_millisatoshi: output
514 .amount_msat
515 .as_ref()
516 .map(|a| a.msat)
517 .unwrap_or_default(),
518 address: output.address.clone().unwrap_or_default(),
519 reserved: output.reserved,
520 })
521 .collect();
522 Ok(utxos)
523 }
524
525 async fn build_payment_path(
526 &self,
527 route: &Vec<GetrouteRoute>,
528 first_edge: PaymentPathEdge,
529 ) -> NodeResult<PaymentPath> {
530 let client = self.get_node_client().await?;
531 let mut hops = vec![first_edge];
532
533 for hop in route {
534 let req = ListchannelsRequest {
535 short_channel_id: Some(hop.channel.clone()),
536 source: None,
537 destination: None,
538 };
539 let mut client = client.clone();
540 let hopchannels = with_connection_retry!(client.list_channels(req.clone()))
541 .await?
542 .into_inner()
543 .channels;
544
545 let first_channel = hopchannels.first().ok_or(NodeError::RouteNotFound(format!(
546 "Channel not found {}",
547 hop.channel.clone()
548 )))?;
549
550 info!("found channel in route: {:?}", first_channel);
551 hops.push(PaymentPathEdge {
552 base_fee_msat: first_channel.base_fee_millisatoshi as u64,
553 fee_per_millionth: first_channel.fee_per_millionth as u64,
554 node_id: hop.id.clone(),
555 short_channel_id: hop.channel.clone(),
556 channel_delay: first_channel.delay as u64,
557 });
558 }
559 Ok(PaymentPath { edges: hops })
560 }
561
562 async fn max_sendable_amount_from_peer(
563 &self,
564 via_peer_id: Vec<u8>,
565 via_peer_channels: Vec<ListpeerchannelsChannels>,
566 payee_node_id: Option<Vec<u8>>,
567 max_hops: u32,
568 last_hop_hint: Option<&RouteHintHop>,
569 ) -> NodeResult<Vec<MaxChannelAmount>> {
570 let mut client = self.get_node_client().await?;
571
572 let (last_node, max_hops) = match last_hop_hint {
576 Some(hop) => (hex::decode(&hop.src_node_id)?, max_hops - 1),
577 None => match payee_node_id.clone() {
578 Some(node_id) => (node_id, max_hops),
579 None => {
580 return Err(NodeError::RouteNotFound(
581 "No payee node id or last hop hints provided, cannot calculate max amount"
582 .to_string(),
583 ));
584 }
585 },
586 };
587
588 info!(
590 "calling get_route for peer {} to node {}, max_hops: {}",
591 hex::encode(via_peer_id.clone()),
592 hex::encode(last_node.clone()),
593 max_hops - 1
594 );
595 let req = GetrouteRequest {
596 id: last_node.clone(),
597 amount_msat: Some(Amount { msat: 0 }),
598 riskfactor: 0,
599 cltv: None,
600 fromid: Some(via_peer_id.clone()),
601 fuzzpercent: Some(0),
602 exclude: vec![],
603 maxhops: Some(max_hops - 1),
605 };
606 let route_result = with_connection_retry!(client.get_route(req.clone())).await;
607
608 if let Err(e) = route_result {
610 error!(
611 "Failed to get route for peer {}: {}",
612 hex::encode(via_peer_id.clone()),
613 e
614 );
615 return Ok(vec![]);
616 }
617
618 let route_response = route_result?.into_inner();
619 info!(
620 "max_sendable_amount: route response = {:?}",
621 route_response
622 .route
623 .iter()
624 .map(|r| format!(
625 "{{node_id: {}, channel: {}}}",
626 hex::encode(&r.id),
627 r.channel
628 ))
629 .collect::<Vec<_>>()
630 );
631
632 let opened_channels: Vec<cln::ListpeerchannelsChannels> = via_peer_channels
634 .iter()
635 .filter(|c| c.state() == ChanneldNormal)
636 .cloned()
637 .collect();
638
639 let mut max_per_channel = vec![];
640 for c in opened_channels {
641 let chan_id = c
642 .clone()
643 .channel_id
644 .ok_or(NodeError::generic("Empty channel id"))?;
645
646 let first_edge = PaymentPathEdge {
648 base_fee_msat: 0,
649 fee_per_millionth: 0,
650 node_id: via_peer_id.clone(),
651 short_channel_id: c.clone().short_channel_id.unwrap_or_default(),
652 channel_delay: 0,
653 };
654
655 let mut payment_path = self
657 .build_payment_path(&route_response.route, first_edge)
658 .await?;
659
660 if let Some(hint) = last_hop_hint {
662 payment_path.edges.extend(vec![PaymentPathEdge {
663 base_fee_msat: hint.fees_base_msat as u64,
664 fee_per_millionth: hint.fees_proportional_millionths as u64,
665 node_id: payee_node_id.clone().unwrap_or_default(),
666 short_channel_id: hint.short_channel_id.clone(),
667 channel_delay: hint.cltv_expiry_delta,
668 }])
669 }
670
671 info!(
672 "max_sendable_amount: route_hops = {:?}",
673 payment_path
674 .edges
675 .iter()
676 .map(|e| format!(
677 "{{node_id: {}, channel: {}}}",
678 hex::encode(&e.node_id),
679 e.short_channel_id
680 ))
681 .collect::<Vec<_>>()
682 );
683
684 let max_payment_amount =
686 payment_path.final_hop_amount(c.clone().spendable_msat.unwrap_or_default().msat);
687 max_per_channel.push(MaxChannelAmount {
688 channel_id: hex::encode(chan_id),
689 amount_msat: max_payment_amount,
690 path: payment_path,
691 });
692 }
693
694 Ok(max_per_channel)
695 }
696
697 async fn get_open_peer_channels_pb(
699 &self,
700 ) -> NodeResult<HashMap<Vec<u8>, cln::ListpeerchannelsChannels>> {
701 let mut client = self.get_node_client().await?;
702 let req = cln::ListpeerchannelsRequest::default();
704 let peer_channels = with_connection_retry!(client.list_peer_channels(req.clone()))
705 .await?
706 .into_inner();
707
708 let open_peer_channels: HashMap<Vec<u8>, cln::ListpeerchannelsChannels> = peer_channels
709 .channels
710 .into_iter()
711 .filter(|c| {
712 c.state == Some(cln::ChannelState::ChanneldNormal as i32) && c.peer_id.is_some()
713 })
714 .map(|c| (c.peer_id.clone().unwrap(), c))
715 .collect();
716 Ok(open_peer_channels)
717 }
718
719 async fn with_keep_alive<T, F>(&self, f: F) -> T
720 where
721 F: Future<Output = T>,
722 {
723 _ = self.inprogress_payments.fetch_add(1, Ordering::Relaxed);
724 let res = f.await;
725 _ = self.inprogress_payments.fetch_sub(1, Ordering::Relaxed);
726 res
727 }
728
729 async fn pull_transactions(
732 &self,
733 sync_state: &SyncState,
734 htlc_list: Vec<Htlc>,
735 ) -> NodeResult<(SyncState, Vec<Payment>)> {
736 let (receive_payments_res, send_payments_res) = join!(
737 self.pull_receive_payments(&sync_state.list_invoices_index),
738 self.pull_send_payments(&sync_state.send_pays_index, htlc_list),
739 );
740
741 let (receive_payments, list_invoices_index) = receive_payments_res?;
742 let (send_payments, send_pays_index) = send_payments_res?;
743 let mut new_state = sync_state.clone();
744 new_state.list_invoices_index = list_invoices_index;
745 new_state.send_pays_index = send_pays_index;
746
747 let mut payments: Vec<Payment> = Vec::new();
748 payments.extend(receive_payments);
749 payments.extend(send_payments);
750
751 Ok((new_state, payments))
752 }
753
754 async fn pull_receive_payments(
755 &self,
756 state: &SyncIndex,
757 ) -> NodeResult<(Vec<Payment>, SyncIndex)> {
758 let mut client = self.get_node_client().await?;
759
760 let req = cln::ListinvoicesRequest {
761 index: Some(ListinvoicesIndex::Created.into()),
762 start: Some(state.created),
763 ..Default::default()
764 };
765 let mut clone = client.clone();
766 let created_invoices = with_connection_retry!(clone.list_invoices(req.clone()))
767 .await?
768 .into_inner();
769 let req = cln::ListinvoicesRequest {
770 index: Some(ListinvoicesIndex::Updated.into()),
771 start: Some(state.updated),
772 ..Default::default()
773 };
774
775 let updated_invoices = with_connection_retry!(client.list_invoices(req.clone()))
776 .await?
777 .into_inner();
778 let mut new_state = state.clone();
779 if let Some(last) = created_invoices.invoices.last() {
780 new_state.created = last.created_index()
781 }
782 if let Some(last) = updated_invoices.invoices.last() {
783 new_state.updated = last.updated_index()
784 }
785
786 let received_payments: NodeResult<Vec<Payment>> = created_invoices
787 .invoices
788 .into_iter()
789 .chain(updated_invoices.invoices.into_iter())
790 .filter(|i| i.status() == ListinvoicesInvoicesStatus::Paid)
791 .map(TryInto::try_into)
792 .collect();
793
794 Ok((received_payments?, new_state))
795 }
796
797 async fn pull_send_payments(
798 &self,
799 state: &SyncIndex,
800 htlc_list: Vec<Htlc>,
801 ) -> NodeResult<(Vec<Payment>, SyncIndex)> {
802 let mut client = self.get_node_client().await?;
803 let req = cln::ListsendpaysRequest {
804 index: Some(ListsendpaysIndex::Created.into()),
805 start: Some(state.created),
806 ..Default::default()
807 };
808 let mut clone = client.clone();
809 let created_send_pays = with_connection_retry!(clone.list_send_pays(req.clone()))
810 .await?
811 .into_inner();
812 let req = cln::ListsendpaysRequest {
813 index: Some(ListsendpaysIndex::Updated.into()),
814 start: Some(state.updated),
815 ..Default::default()
816 };
817 let updated_send_pays = with_connection_retry!(client.list_send_pays(req.clone()))
818 .await?
819 .into_inner();
820
821 let mut new_state = state.clone();
822 if let Some(last) = created_send_pays.payments.last() {
823 new_state.created = last.created_index()
824 }
825 if let Some(last) = updated_send_pays.payments.last() {
826 new_state.updated = last.updated_index()
827 }
828
829 let hash_groups: HashMap<_, _> = created_send_pays
830 .payments
831 .iter()
832 .chain(updated_send_pays.payments.iter())
833 .map(|p| {
834 let mut key = hex::encode(&p.payment_hash);
835 key.push('|');
836 key.push_str(&p.groupid.to_string());
837 (key, (p.payment_hash.clone(), p.groupid.to_string()))
838 })
839 .collect();
840 let hash_group_values: Vec<_> = hash_groups.values().cloned().collect();
841
842 self.persister.insert_send_pays(
843 &created_send_pays
844 .payments
845 .into_iter()
846 .map(TryInto::try_into)
847 .collect::<Result<Vec<_>, _>>()?,
848 )?;
849 self.persister.insert_send_pays(
850 &updated_send_pays
851 .payments
852 .into_iter()
853 .map(TryInto::try_into)
854 .collect::<Result<Vec<_>, _>>()?,
855 )?;
856
857 let send_pays = self.persister.list_send_pays(&hash_group_values)?;
861
862 let mut outbound_payments: HashMap<String, SendPayAgg> = HashMap::new();
866 for send_pay in send_pays {
867 let mut key = hex::encode(&send_pay.payment_hash);
868 key.push('|');
869 key.push_str(&send_pay.groupid);
870 let payment = outbound_payments.entry(key).or_insert(SendPayAgg {
871 state: 0,
872 created_at: send_pay.created_at,
873 payment_hash: send_pay.payment_hash,
874 bolt11: None,
875 destination: None,
876 label: None,
877 description: None,
878 preimage: None,
879 amount_sent: 0,
880 amount: Some(0),
881 num_nonfailed_parts: 0,
882 });
883 if payment.bolt11.is_none() {
884 payment.bolt11 = send_pay.bolt11;
885 }
886 if payment.destination.is_none() {
887 payment.destination = send_pay.destination;
888 }
889 if payment.description.is_none() {
890 payment.description = send_pay.description;
891 }
892 if payment.label.is_none() {
893 payment.label = send_pay.label;
894 }
895 if payment.preimage.is_none() {
896 payment.preimage = send_pay.payment_preimage;
897 }
898 if send_pay.created_at < payment.created_at {
899 payment.created_at = send_pay.created_at;
900 }
901
902 match send_pay.status {
903 SendPayStatus::Pending => {
904 add_amount_sent(payment, send_pay.amount_sent_msat, send_pay.amount_msat);
905 payment.num_nonfailed_parts += 1;
906 payment.state |= PAYMENT_STATE_PENDING;
907 }
908 SendPayStatus::Failed => {
909 payment.state |= PAYMENT_STATE_FAILED;
910 }
911 SendPayStatus::Complete => {
912 add_amount_sent(payment, send_pay.amount_sent_msat, send_pay.amount_msat);
913 payment.num_nonfailed_parts += 1;
914 payment.state |= PAYMENT_STATE_COMPLETE;
915 }
916 }
917 }
918
919 let outbound_payments: Vec<Payment> = outbound_payments
920 .into_values()
921 .map(TryInto::try_into)
922 .collect::<Result<Vec<_>, _>>()?;
923 let outbound_payments = update_payment_expirations(outbound_payments, htlc_list)?;
924 Ok((outbound_payments, new_state))
925 }
926
927 async fn wait_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<()> {
928 let deadline =
929 Instant::now()
930 .checked_add(Duration::from_secs(20))
931 .ok_or(NodeError::generic(
932 "Failed to set channel establishment deadline",
933 ))?;
934
935 while Instant::now().le(&deadline) && !self.poll_channel_reestablished(path).await? {
936 tokio::time::sleep(Duration::from_millis(50)).await
937 }
938
939 Ok(())
940 }
941
942 async fn poll_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<bool> {
943 let edge = match path.edges.first() {
944 Some(edge) => edge,
945 None => return Err(NodeError::generic("Channel not found")),
946 };
947 let mut client = self.get_node_client().await?;
948 let req = cln::ListpeerchannelsRequest {
949 id: Some(edge.node_id.clone()),
950 };
951 let res = with_connection_retry!(client.list_peer_channels(req.clone()))
952 .await?
953 .into_inner();
954 let channel = match res.channels.iter().find(|c| {
955 match (
956 c.alias.as_ref().and_then(|a| a.local.as_ref()),
957 c.short_channel_id.as_ref(),
958 ) {
959 (Some(alias), Some(short_channel_id)) => {
960 *alias == edge.short_channel_id || *short_channel_id == edge.short_channel_id
961 }
962 (Some(alias), None) => *alias == edge.short_channel_id,
963 (None, Some(short_channel_id)) => *short_channel_id == edge.short_channel_id,
964 (None, None) => false,
965 }
966 }) {
967 Some(channel) => channel,
968 None => return Err(NodeError::generic("Channel not found")),
969 };
970
971 if let Some(peer_connected) = channel.peer_connected {
972 if !peer_connected {
973 return Ok(false);
974 }
975 }
976
977 if !channel
978 .status
979 .iter()
980 .any(|s| s.contains("Channel ready") || s.contains("Reconnected, and reestablished"))
981 {
982 return Ok(false);
983 }
984
985 Ok(true)
986 }
987}
988
989fn add_amount_sent(
990 agg: &mut SendPayAgg,
991 send_pay_amount_sent_msat: Option<u64>,
992 send_pay_amount_msat: Option<u64>,
993) {
994 if let Some(amount_sent_msat) = send_pay_amount_sent_msat {
995 agg.amount_sent += amount_sent_msat;
996 }
997
998 let amount_msat = match send_pay_amount_msat {
999 Some(amount_msat) => amount_msat,
1000 None => {
1001 agg.amount = None;
1002 return;
1003 }
1004 };
1005
1006 if let Some(amount) = agg.amount {
1007 agg.amount = Some(amount + amount_msat);
1008 }
1009}
1010
1011#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1012struct SyncIndex {
1013 pub created: u64,
1014 pub updated: u64,
1015}
1016
1017#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1018struct SyncState {
1019 pub send_pays_index: SyncIndex,
1020 pub list_invoices_index: SyncIndex,
1021}
1022
1023#[tonic::async_trait]
1024impl NodeAPI for Greenlight {
1025 async fn node_credentials(&self) -> NodeResult<Option<NodeCredentials>> {
1026 Ok(Self::get_node_credentials(
1027 self.sdk_config.network,
1028 &self.get_signer().await,
1029 self.persister.clone(),
1030 )?
1031 .map(|credentials| NodeCredentials::Greenlight {
1032 credentials: GreenlightDeviceCredentials {
1033 device: credentials.to_bytes(),
1034 },
1035 }))
1036 }
1037
1038 async fn configure_node(&self, close_to_address: Option<String>) -> NodeResult<()> {
1039 match close_to_address {
1040 Some(close_to_addr) => {
1041 let mut client = self.get_client().await?;
1042 let req = gl_client::pb::GlConfig { close_to_addr };
1043 with_connection_retry!(client.configure(req.clone()))
1044 .await
1045 .map_err(|e| NodeError::Generic(format!("Unable to set node config: {e}")))?;
1046 }
1047 None => {
1048 let mut client = self.get_node_client().await?;
1049 let req = cln::DeldatastoreRequest {
1050 key: vec!["glconf".to_string(), "request".to_string()],
1051 generation: None,
1052 };
1053 with_connection_retry!(client.del_datastore(req.clone()))
1054 .await
1055 .map_err(|e| {
1056 NodeError::Generic(format!("Unable to delete node config: {e}"))
1057 })?;
1058 }
1059 }
1060 Ok(())
1061 }
1062
1063 async fn create_invoice(&self, request: CreateInvoiceRequest) -> NodeResult<String> {
1064 let mut client = self.get_node_client().await?;
1065 let label = serde_json::to_string(&InvoiceLabel {
1066 unix_milli: SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis(),
1067 payer_amount_msat: request.payer_amount_msat,
1068 })?;
1069 let cln_request = cln::InvoiceRequest {
1070 amount_msat: Some(cln::AmountOrAny {
1071 value: Some(cln::amount_or_any::Value::Amount(cln::Amount {
1072 msat: request.amount_msat,
1073 })),
1074 }),
1075 label,
1076 description: request.description,
1077 preimage: request.preimage,
1078 deschashonly: request.use_description_hash,
1079 expiry: request.expiry.map(|e| e as u64),
1080 fallbacks: vec![],
1081 cltv: request.cltv,
1082 };
1083
1084 let res = with_connection_retry!(client.invoice(cln_request.clone()))
1085 .await?
1086 .into_inner();
1087 Ok(res.bolt11)
1088 }
1089
1090 async fn delete_invoice(&self, bolt11: String) -> NodeResult<()> {
1091 let mut client = self.get_node_client().await?;
1092 let invoice_request = cln::ListinvoicesRequest {
1093 invstring: Some(bolt11),
1094 ..Default::default()
1095 };
1096 let invoice_result = with_connection_retry!(client.list_invoices(invoice_request.clone()))
1097 .await?
1098 .into_inner();
1099 let invoice_result = invoice_result.invoices.first();
1100 let result = match invoice_result {
1101 Some(result) => result,
1102 None => return Ok(()),
1103 };
1104
1105 let status = match result.status() {
1106 ListinvoicesInvoicesStatus::Unpaid => DelinvoiceStatus::Unpaid,
1107 ListinvoicesInvoicesStatus::Paid => return Err(NodeError::InvoiceAlreadyPaid),
1108 ListinvoicesInvoicesStatus::Expired => DelinvoiceStatus::Expired,
1109 };
1110 with_connection_retry!(client.del_invoice(DelinvoiceRequest {
1111 label: result.label.clone(),
1112 status: status.into(),
1113 desconly: Some(false),
1114 }))
1115 .await?;
1116 Ok(())
1117 }
1118
1119 async fn fetch_bolt11(&self, payment_hash: Vec<u8>) -> NodeResult<Option<FetchBolt11Result>> {
1120 let mut client = self.get_node_client().await?;
1121 let request = cln::ListinvoicesRequest {
1122 payment_hash: Some(payment_hash),
1123 ..Default::default()
1124 };
1125
1126 let result = with_connection_retry!(client.list_invoices(request.clone()))
1127 .await?
1128 .into_inner()
1129 .invoices
1130 .first()
1131 .cloned()
1132 .and_then(|invoice| {
1133 invoice.bolt11.map(|bolt11| FetchBolt11Result {
1134 bolt11,
1135 payer_amount_msat: serde_json::from_str::<InvoiceLabel>(&invoice.label)
1136 .map(|label| label.payer_amount_msat)
1137 .ok()
1138 .flatten(),
1139 })
1140 });
1141
1142 Ok(result)
1143 }
1144
1145 async fn pull_changed(
1147 &self,
1148 sync_state: Option<Value>,
1149 match_local_balance: bool,
1150 ) -> NodeResult<SyncResponse> {
1151 let sync_state: SyncState = match sync_state {
1152 Some(sync_state) => serde_json::from_value(sync_state)?,
1153 None => SyncState::default(),
1154 };
1155
1156 let client = self.get_node_client().await?;
1157
1158 let mut client_clone1 = client.clone();
1160 let node_info_future =
1161 with_connection_retry!(client_clone1.getinfo(cln::GetinfoRequest::default()));
1162
1163 let funds_future = self.list_funds();
1165
1166 let mut client_clone2 = client.clone();
1168 let closed_channels_future = with_connection_retry!(
1169 client_clone2.list_closed_channels(cln::ListclosedchannelsRequest { id: None })
1170 );
1171
1172 let balance_future = Greenlight::fetch_channels_and_balance_with_retry(
1175 client.clone(),
1176 self.persister.clone(),
1177 match_local_balance,
1178 );
1179
1180 let (node_info_res, funds_res, closed_channels_res, balance_res) = tokio::join!(
1181 node_info_future,
1182 funds_future,
1183 closed_channels_future,
1184 balance_future
1185 );
1186
1187 let node_info = node_info_res?.into_inner();
1188 let funds = funds_res?;
1189 let closed_channels = closed_channels_res?.into_inner().closedchannels;
1190 let (all_channels, opened_channels, connected_peers, channels_balance) = balance_res?;
1191 let forgotten_closed_channels: NodeResult<Vec<Channel>> = closed_channels
1192 .into_iter()
1193 .filter(|cc| {
1194 all_channels
1195 .iter()
1196 .all(|ac| ac.funding_txid != Some(cc.funding_txid.clone()))
1197 })
1198 .map(TryInto::try_into)
1199 .collect();
1200 info!("forgotten_closed_channels {:?}", forgotten_closed_channels);
1201
1202 let mut all_channel_models: Vec<Channel> =
1203 all_channels.clone().into_iter().map(|c| c.into()).collect();
1204 all_channel_models.extend(forgotten_closed_channels?);
1205
1206 let onchain_balance = self.on_chain_balance(&funds).await?;
1208 let pending_onchain_balance = self.pending_onchain_balance(&all_channels).await?;
1209 let utxos: Vec<UnspentTransactionOutput> = self.utxos(funds).await?;
1210
1211 let mut max_payable: u64 = 0;
1213 let mut max_receivable_single_channel: u64 = 0;
1214 let mut total_inbound_liquidity_msats: u64 = 0;
1215 opened_channels.iter().try_for_each(|c| -> Result<()> {
1216 max_payable += c
1217 .spendable_msat
1218 .as_ref()
1219 .map(|a| a.msat)
1220 .unwrap_or_default();
1221 let receivable_amount = c
1222 .receivable_msat
1223 .as_ref()
1224 .map(|a| a.msat)
1225 .unwrap_or_default();
1226 total_inbound_liquidity_msats += receivable_amount;
1227 if receivable_amount > max_receivable_single_channel {
1228 max_receivable_single_channel = receivable_amount;
1229 }
1230 Ok(())
1231 })?;
1232
1233 let max_allowed_to_receive_msats =
1234 MAX_INBOUND_LIQUIDITY_MSAT.saturating_sub(channels_balance);
1235 let node_pubkey = hex::encode(node_info.id);
1236 let node_state = NodeState {
1238 id: node_pubkey.clone(),
1239 block_height: node_info.blockheight,
1240 channels_balance_msat: channels_balance,
1241 onchain_balance_msat: onchain_balance,
1242 pending_onchain_balance_msat: pending_onchain_balance,
1243 utxos,
1244 max_payable_msat: max_payable,
1245 max_receivable_msat: max_allowed_to_receive_msats,
1246 max_single_payment_amount_msat: MAX_PAYMENT_AMOUNT_MSAT,
1247 max_chan_reserve_msats: channels_balance - min(max_payable, channels_balance),
1248 connected_peers,
1249 max_receivable_single_payment_amount_msat: max_receivable_single_channel,
1250 total_inbound_liquidity_msats,
1251 };
1252 let mut htlc_list: Vec<Htlc> = Vec::new();
1253 for channel in all_channel_models.clone() {
1254 htlc_list.extend(channel.htlcs);
1255 }
1256
1257 let (new_sync_state, payments) = self.pull_transactions(&sync_state, htlc_list).await?;
1258
1259 Ok(SyncResponse {
1260 sync_state: serde_json::to_value(new_sync_state)?,
1261 node_state,
1262 payments,
1263 channels: all_channel_models,
1264 })
1265 }
1266
1267 async fn send_pay(&self, bolt11: String, max_hops: u32) -> NodeResult<PaymentResponse> {
1268 let invoice = parse_invoice(&bolt11)?;
1269 let last_hop = invoice.routing_hints.first().and_then(|rh| rh.hops.first());
1270 let mut client = self.get_node_client().await?;
1271
1272 validate_network(invoice.clone(), self.sdk_config.network)?;
1274
1275 let mut max_amount_per_channel = self
1277 .max_sendable_amount(Some(hex::decode(invoice.payee_pubkey)?), max_hops, last_hop)
1278 .await?;
1279 info!("send_pay: routes: {:?}", max_amount_per_channel);
1280
1281 let total_msat: u64 = max_amount_per_channel.iter().map(|m| m.amount_msat).sum();
1283
1284 max_amount_per_channel.sort_by_key(|m| Reverse(m.amount_msat));
1287
1288 let amount_to_pay_msat = match invoice.amount_msat {
1289 Some(amount) => Ok(amount),
1290 None => Err(NodeError::generic("Invoice has no amount")),
1291 }?;
1292
1293 if amount_to_pay_msat > total_msat {
1294 return Err(NodeError::RouteNotFound(format!(
1295 "Amount too high, max amount is {total_msat} msat"
1296 )));
1297 }
1298
1299 client
1301 .pre_approve_invoice(PreapproveinvoiceRequest {
1302 bolt11: Some(bolt11.clone()),
1303 })
1304 .await?;
1305
1306 let mut part_id = 1;
1308 let mut amount_sent_msat = 0;
1310 let mut amount_received_msat = 0;
1312 let group_id = rand::random::<u64>();
1314
1315 for max in max_amount_per_channel {
1318 let left_to_pay_msat = amount_to_pay_msat - amount_received_msat;
1320 let to_pay_msat = std::cmp::min(left_to_pay_msat, max.amount_msat);
1322
1323 let (route, sent_msat) = convert_to_send_pay_route(
1326 max.path.clone(),
1327 to_pay_msat,
1328 invoice.min_final_cltv_expiry_delta,
1329 );
1330 info!(
1331 "send_pay route to pay: {:?}, received_amount = {}",
1332 route, to_pay_msat
1333 );
1334 self.wait_channel_reestablished(&max.path).await?;
1335 let req = SendpayRequest {
1337 route,
1338 payment_hash: hex::decode(invoice.payment_hash.clone())?,
1339 label: None,
1340 amount_msat: Some(Amount {
1341 msat: amount_to_pay_msat,
1342 }),
1343 bolt11: Some(bolt11.clone()),
1344 payment_secret: Some(invoice.payment_secret.clone()),
1345 partid: Some(part_id),
1346 localinvreqid: None,
1347 groupid: Some(group_id),
1348 };
1349 let mut client = client.clone();
1350 with_connection_retry!(client.send_pay(req.clone())).await?;
1351 part_id += 1;
1352 amount_sent_msat += sent_msat;
1353 amount_received_msat += to_pay_msat;
1354 if amount_received_msat == amount_to_pay_msat {
1355 break;
1356 }
1357 }
1358
1359 let req = WaitsendpayRequest {
1362 payment_hash: hex::decode(invoice.payment_hash.clone())?,
1363 partid: Some(1),
1364 timeout: Some(self.sdk_config.payment_timeout_sec),
1365 groupid: Some(group_id),
1366 };
1367 let response = self
1368 .with_keep_alive(with_connection_retry!(client.wait_send_pay(req.clone())))
1369 .await?
1370 .into_inner();
1371 Ok(PaymentResponse {
1372 payment_time: response.completed_at.unwrap_or(response.created_at as f64) as i64,
1373 amount_msat: amount_received_msat,
1374 fee_msat: amount_sent_msat - amount_received_msat,
1375 payment_hash: invoice.payment_hash,
1376 payment_preimage: hex::encode(response.payment_preimage.unwrap_or_default()),
1377 })
1378 }
1379
1380 async fn send_payment(
1381 &self,
1382 bolt11: String,
1383 amount_msat: Option<u64>,
1384 label: Option<String>,
1385 ) -> NodeResult<Payment> {
1386 let mut description = None;
1387 if !bolt11.is_empty() {
1388 let invoice = parse_invoice(&bolt11)?;
1389 validate_network(invoice.clone(), self.sdk_config.network)?;
1390 description = invoice.description;
1391 }
1392
1393 let mut client = self.get_node_client().await?;
1394 let request = cln::PayRequest {
1395 bolt11,
1396 amount_msat: amount_msat.map(|amt| cln::Amount { msat: amt }),
1397 maxfeepercent: Some(self.sdk_config.maxfee_percent),
1398 retry_for: Some(self.sdk_config.payment_timeout_sec),
1399 label,
1400 maxdelay: None,
1401 riskfactor: None,
1402 localinvreqid: None,
1403 exclude: vec![],
1404 maxfee: None,
1405 description,
1406 exemptfee: Some(cln::Amount {
1407 msat: self.sdk_config.exemptfee_msat,
1408 }),
1409 };
1410 let result: cln::PayResponse = self
1411 .with_keep_alive(with_connection_retry!(client.pay(request.clone())))
1412 .await?
1413 .into_inner();
1414
1415 let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
1418 payment.try_into()
1419 }
1420
1421 async fn send_trampoline_payment(
1422 &self,
1423 bolt11: String,
1424 amount_msat: u64,
1425 label: Option<String>,
1426 trampoline_node_id: Vec<u8>,
1427 ) -> NodeResult<Payment> {
1428 let invoice = parse_invoice(&bolt11)?;
1429 validate_network(invoice.clone(), self.sdk_config.network)?;
1430 let label = serde_json::to_string(&PaymentLabel {
1431 trampoline: true,
1432 client_label: label,
1433 unix_nano: SystemTime::now().duration_since(UNIX_EPOCH)?.as_nanos(),
1434 amount_msat,
1435 })?;
1436 let fee_msat =
1437 (amount_msat.saturating_mul(TRAMPOLINE_FEE_PPM) / 1_000_000) + TRAMPOLINE_BASE_FEE_MSAT;
1438 let fee_percent = ((fee_msat as f64 / amount_msat as f64) * 100.) as f32;
1439 debug!("using fee msat {} fee percent {}", fee_msat, fee_percent);
1440 let mut client = self.get_client().await?;
1441 let request = TrampolinePayRequest {
1442 bolt11,
1443 trampoline_node_id,
1444 amount_msat,
1445 label,
1446 maxdelay: u32::default(),
1447 description: String::default(),
1448 maxfeepercent: fee_percent,
1449 };
1450 let result = self
1451 .with_keep_alive(with_connection_retry!(
1452 client.trampoline_pay(request.clone())
1453 ))
1454 .await?
1455 .into_inner();
1456
1457 let client = self.get_node_client().await?;
1458
1459 let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
1465 payment.try_into()
1466 }
1467
1468 async fn send_spontaneous_payment(
1469 &self,
1470 node_id: String,
1471 amount_msat: u64,
1472 extra_tlvs: Option<Vec<TlvEntry>>,
1473 label: Option<String>,
1474 ) -> NodeResult<Payment> {
1475 let mut client: node::ClnClient = self.get_node_client().await?;
1476 let request = cln::KeysendRequest {
1477 destination: hex::decode(node_id)?,
1478 amount_msat: Some(cln::Amount { msat: amount_msat }),
1479 label: label.or(Some(format!(
1480 "breez-{}",
1481 SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis()
1482 ))),
1483 extratlvs: extra_tlvs.map(|tlvs| cln::TlvStream {
1484 entries: tlvs
1485 .into_iter()
1486 .map(|tlv| cln::TlvEntry {
1487 r#type: tlv.field_number,
1488 value: tlv.value,
1489 })
1490 .collect(),
1491 }),
1492 routehints: None,
1493 maxfeepercent: Some(self.sdk_config.maxfee_percent),
1494 exemptfee: None,
1495 retry_for: Some(self.sdk_config.payment_timeout_sec),
1496 maxdelay: None,
1497 };
1498
1499 let result = self
1501 .with_keep_alive(client.key_send(request))
1502 .await?
1503 .into_inner();
1504
1505 let payment = Self::fetch_outgoing_payment_with_retry(client, result.payment_hash).await?;
1508 payment.try_into()
1509 }
1510
1511 async fn node_id(&self) -> NodeResult<String> {
1512 Ok(hex::encode(self.get_signer().await.node_id()))
1513 }
1514
1515 async fn redeem_onchain_funds(
1516 &self,
1517 to_address: String,
1518 sat_per_vbyte: u32,
1519 ) -> NodeResult<Vec<u8>> {
1520 let mut client = self.get_node_client().await?;
1521
1522 let request = cln::WithdrawRequest {
1523 feerate: Some(cln::Feerate {
1524 style: Some(cln::feerate::Style::Perkw(sat_per_vbyte * 250)),
1525 }),
1526 satoshi: Some(cln::AmountOrAll {
1527 value: Some(cln::amount_or_all::Value::All(true)),
1528 }),
1529 destination: to_address,
1530 minconf: None,
1531 utxos: vec![],
1532 };
1533
1534 Ok(with_connection_retry!(client.withdraw(request.clone()))
1535 .await?
1536 .into_inner()
1537 .txid)
1538 }
1539
1540 async fn prepare_redeem_onchain_funds(
1541 &self,
1542 req: PrepareRedeemOnchainFundsRequest,
1543 ) -> NodeResult<PrepareRedeemOnchainFundsResponse> {
1544 let funds = self.list_funds().await?;
1545 let utxos = self.utxos(funds).await?;
1546
1547 let mut amount_msat: u64 = 0;
1548 let txins: Vec<TxIn> = utxos
1549 .iter()
1550 .map(|utxo| {
1551 amount_msat += utxo.amount_millisatoshi;
1552 TxIn {
1553 previous_output: OutPoint {
1554 txid: Txid::from_slice(&utxo.txid).unwrap(),
1555 vout: 0,
1556 },
1557 script_sig: Script::new(),
1558 sequence: Sequence(0),
1559 witness: Witness::default(),
1560 }
1561 })
1562 .collect();
1563
1564 let amount_sat = amount_msat / 1_000;
1565 let btc_address = Address::from_str(&req.to_address)?;
1566 let tx_out: Vec<TxOut> = vec![TxOut {
1567 value: amount_sat,
1568 script_pubkey: btc_address.payload.script_pubkey(),
1569 }];
1570 let tx = Transaction {
1571 version: 2,
1572 lock_time: crate::bitcoin::PackedLockTime(0),
1573 input: txins.clone(),
1574 output: tx_out,
1575 };
1576
1577 let witness_input_size: u64 = 110;
1578 let tx_weight = tx.strippedsize() as u64 * WITNESS_SCALE_FACTOR as u64
1579 + witness_input_size * txins.len() as u64;
1580 let fee: u64 = tx_weight * req.sat_per_vbyte as u64 / WITNESS_SCALE_FACTOR as u64;
1581 if fee >= amount_sat {
1582 return Err(NodeError::InsufficientFunds(
1583 "Insufficient funds to pay fees".to_string(),
1584 ));
1585 }
1586
1587 return Ok(PrepareRedeemOnchainFundsResponse {
1588 tx_weight,
1589 tx_fee_sat: fee,
1590 });
1591 }
1592
1593 async fn start_signer(&self, shutdown: mpsc::Receiver<()>) {
1595 match self.get_signer().await.run_forever(shutdown).await {
1596 Ok(_) => info!("signer exited gracefully"),
1597 Err(e) => error!("signer exited with error: {e}"),
1598 }
1599 }
1600
1601 async fn start_keep_alive(&self, mut shutdown: watch::Receiver<()>) {
1602 info!("keep alive started");
1603 let mut interval = tokio::time::interval(Duration::from_secs(15));
1604 interval.set_missed_tick_behavior(MissedTickBehavior::Skip);
1605 loop {
1606 tokio::select! {
1607 _ = shutdown.changed() => {
1608 info!("keep alive exited");
1609 break;
1610 }
1611 _ = interval.tick() => {
1612 let inprogress_payments = self.inprogress_payments.load(Ordering::Relaxed);
1613 if inprogress_payments == 0 {
1614 continue
1615 }
1616 let client_res = self.get_node_client().await;
1617 match client_res {
1618 Ok(mut client) => {
1619 let res = client.getinfo(cln::GetinfoRequest {}).await;
1620 match res {
1621 Ok(_) => {
1622 info!("keep alive ping sent, in progress payments: {inprogress_payments}");
1623 }
1624 Err(e) => {
1625 error!("keep alive ping failed: {e}");
1626 }
1627 }
1628 }
1629 Err(e) => {
1630 error!("keep alive ping failed to create client: {e}");
1631 }
1632 }
1633 }
1634 }
1635 }
1636 }
1637
1638 async fn connect_peer(&self, id: String, addr: String) -> NodeResult<()> {
1639 let mut client = self.get_node_client().await?;
1640 let connect_req = cln::ConnectRequest {
1641 id: format!("{id}@{addr}"),
1642 host: None,
1643 port: None,
1644 };
1645 with_connection_retry!(client.connect_peer(connect_req.clone())).await?;
1646 Ok(())
1647 }
1648
1649 async fn sign_message(&self, message: &str) -> NodeResult<String> {
1650 let (sig, recovery_id) = self
1651 .get_signer()
1652 .await
1653 .sign_message(message.as_bytes().to_vec())?;
1654 let mut complete_signature = vec![31 + recovery_id];
1655 complete_signature.extend_from_slice(&sig);
1656 Ok(zbase32::encode_full_bytes(&complete_signature))
1657 }
1658
1659 async fn check_message(
1660 &self,
1661 message: &str,
1662 pubkey: &str,
1663 signature: &str,
1664 ) -> NodeResult<bool> {
1665 let pk = PublicKey::from_str(pubkey)?;
1666 Ok(verify(message.as_bytes(), signature, &pk))
1667 }
1668
1669 async fn sign_invoice(&self, invoice: RawBolt11Invoice) -> NodeResult<String> {
1670 let hrp_bytes = invoice.hrp.to_string().as_bytes().to_vec();
1671 let data_bytes = invoice.data.to_base32();
1672
1673 let msg_type: u16 = 8;
1675 let data_len: u16 = data_bytes.len().try_into()?;
1676 let mut data_len_bytes = data_len.to_be_bytes().to_vec();
1677 let mut data_buf = data_bytes.iter().copied().map(u5::to_u8).collect();
1678
1679 let hrp_len: u16 = hrp_bytes.len().try_into()?;
1680 let mut hrp_len_bytes = hrp_len.to_be_bytes().to_vec();
1681 let mut hrp_buf = hrp_bytes.to_vec();
1682
1683 let mut buf = msg_type.to_be_bytes().to_vec();
1684 buf.append(&mut data_len_bytes);
1685 buf.append(&mut data_buf);
1686 buf.append(&mut hrp_len_bytes);
1687 buf.append(&mut hrp_buf);
1688 let raw_result = self.get_signer().await.sign_invoice(buf)?;
1690 info!(
1691 "recover id: {:?} raw = {:?}",
1692 raw_result, raw_result[64] as i32
1693 );
1694 let rid = RecoveryId::from_i32(raw_result[64] as i32).expect("recovery ID");
1696 let sig = &raw_result[0..64];
1697 let recoverable_sig = RecoverableSignature::from_compact(sig, rid)?;
1698
1699 let signed_invoice: Result<SignedRawBolt11Invoice> = invoice.sign(|_| Ok(recoverable_sig));
1700 Ok(signed_invoice?.to_string())
1701 }
1702
1703 async fn close_peer_channels(&self, node_id: String) -> NodeResult<Vec<String>> {
1704 let mut client = self.get_node_client().await?;
1705 let req = cln::ListpeerchannelsRequest {
1706 id: Some(hex::decode(node_id)?),
1707 };
1708 let closed_channels = with_connection_retry!(client.list_peer_channels(req.clone()))
1709 .await?
1710 .into_inner();
1711 let mut tx_ids = vec![];
1712 for channel in closed_channels.channels {
1713 let mut should_close = false;
1714 if let Some(state) = channel.state {
1715 match cln::ChannelState::from_i32(state) {
1716 Some(cln::ChannelState::Openingd) => should_close = true,
1717 Some(cln::ChannelState::ChanneldAwaitingLockin) => should_close = true,
1718 Some(cln::ChannelState::ChanneldNormal) => should_close = true,
1719 Some(cln::ChannelState::ChanneldShuttingDown) => should_close = true,
1720 Some(cln::ChannelState::FundingSpendSeen) => should_close = true,
1721 Some(cln::ChannelState::DualopendOpenInit) => should_close = true,
1722 Some(cln::ChannelState::DualopendAwaitingLockin) => should_close = true,
1723 Some(_) => should_close = false,
1724 None => should_close = false,
1725 }
1726 }
1727
1728 if should_close {
1729 let chan_id = channel.channel_id.ok_or(anyhow!("Empty channel id"))?;
1730 let req = cln::CloseRequest {
1731 id: hex::encode(chan_id),
1732 unilateraltimeout: None,
1733 destination: None,
1734 fee_negotiation_step: None,
1735 wrong_funding: None,
1736 force_lease_closed: None,
1737 feerange: vec![],
1738 };
1739 let response = with_connection_retry!(client.close(req.clone())).await;
1740 match response {
1741 Ok(res) => {
1742 tx_ids.push(hex::encode(
1743 res.into_inner()
1744 .txid
1745 .ok_or(anyhow!("Empty txid in close response"))?,
1746 ));
1747 }
1748 Err(e) => Err(anyhow!("Empty closing channel: {e}"))?,
1749 };
1750 }
1751 }
1752 Ok(tx_ids)
1753 }
1754
1755 async fn stream_incoming_payments(
1756 &self,
1757 ) -> NodeResult<Pin<Box<dyn Stream<Item = IncomingPayment> + Send>>> {
1758 let mut client = self.get_client().await?;
1759 let req = gl_client::signer::model::greenlight::StreamIncomingFilter {};
1760 let stream = with_connection_retry!(client.stream_incoming(req.clone()))
1761 .await?
1762 .into_inner();
1763 Ok(Box::pin(stream.filter_map(|msg| match msg {
1764 Ok(msg) => match msg.details {
1765 Some(incoming_payment::Details::Offchain(p)) => Some(IncomingPayment {
1766 label: p.label,
1767 payment_hash: p.payment_hash,
1768 preimage: p.preimage,
1769 amount_msat: amount_to_msat(&p.amount.unwrap_or_default()),
1770 bolt11: p.bolt11,
1771 }),
1772 _ => None,
1773 },
1774 Err(e) => {
1775 debug!("failed to receive message: {e}");
1776 None
1777 }
1778 })))
1779 }
1780
1781 async fn stream_log_messages(&self) -> NodeResult<Pin<Box<dyn Stream<Item = String> + Send>>> {
1782 let mut client = self.get_client().await?;
1783 let req = gl_client::signer::model::greenlight::StreamLogRequest {};
1784 let stream = with_connection_retry!(client.stream_log(req.clone()))
1785 .await?
1786 .into_inner();
1787 Ok(Box::pin(stream.filter_map(|msg| match msg {
1788 Ok(msg) => Some(msg.line),
1789 Err(e) => {
1790 debug!("failed to receive log message: {e}");
1791 None
1792 }
1793 })))
1794 }
1795
1796 async fn static_backup(&self) -> NodeResult<Vec<String>> {
1797 let mut client = self.get_node_client().await?;
1798 let req = cln::StaticbackupRequest {};
1799 let res = with_connection_retry!(client.static_backup(req.clone()))
1800 .await?
1801 .into_inner();
1802 let hex_vec: Vec<String> = res.scb.into_iter().map(hex::encode).collect();
1803 Ok(hex_vec)
1804 }
1805
1806 async fn generate_diagnostic_data(&self) -> NodeResult<Value> {
1807 let all_commands = vec![
1808 NodeCommand::GetInfo.to_string(),
1809 NodeCommand::ListPeerChannels.to_string(),
1810 NodeCommand::ListFunds.to_string(),
1811 NodeCommand::ListPayments.to_string(),
1812 NodeCommand::ListInvoices.to_string(),
1813 ];
1814
1815 let mut result = Map::new();
1816 for command in all_commands {
1817 let command_name = command.clone();
1818 let res = self
1819 .execute_command(command)
1820 .await
1821 .unwrap_or_else(|e| json!({ "error": e.to_string() }));
1822 result.insert(command_name, res);
1823 }
1824 Ok(Value::Object(result))
1825 }
1826
1827 async fn execute_command(&self, command: String) -> NodeResult<Value> {
1828 let node_cmd =
1829 NodeCommand::from_str(&command).map_err(|_| anyhow!("Command not found: {command}"))?;
1830
1831 let mut client = self.get_node_client().await?;
1832 match node_cmd {
1833 NodeCommand::ListPeers => {
1834 let req = cln::ListpeersRequest::default();
1835 let resp = with_connection_retry!(client.list_peers(req.clone()))
1836 .await?
1837 .into_inner();
1838
1839 Ok(crate::serializer::value::to_value(&resp)?)
1840 }
1841 NodeCommand::ListPeerChannels => {
1842 let req = cln::ListpeerchannelsRequest::default();
1843 let resp = with_connection_retry!(client.list_peer_channels(req.clone()))
1844 .await?
1845 .into_inner();
1846 Ok(crate::serializer::value::to_value(&resp)?)
1847 }
1848 NodeCommand::ListFunds => {
1849 let req = cln::ListfundsRequest::default();
1850 let resp = with_connection_retry!(client.list_funds(req.clone()))
1851 .await?
1852 .into_inner();
1853 Ok(crate::serializer::value::to_value(&resp)?)
1854 }
1855 NodeCommand::ListPayments => {
1856 let req = cln::ListpaysRequest::default();
1857 let resp = with_connection_retry!(client.list_pays(req.clone()))
1858 .await?
1859 .into_inner();
1860 Ok(crate::serializer::value::to_value(&resp)?)
1861 }
1862 NodeCommand::ListInvoices => {
1863 let req = cln::ListinvoicesRequest::default();
1864 let resp = with_connection_retry!(client.list_invoices(req.clone()))
1865 .await?
1866 .into_inner();
1867
1868 Ok(crate::serializer::value::to_value(&resp)?)
1869 }
1870 NodeCommand::CloseAllChannels => {
1871 let req = cln::ListpeersRequest::default();
1872 let resp = with_connection_retry!(client.list_peers(req.clone()))
1873 .await?
1874 .into_inner();
1875 for p in resp.peers {
1876 self.close_peer_channels(hex::encode(p.id)).await?;
1877 }
1878
1879 Ok(Value::String("All channels were closed".to_string()))
1880 }
1881 NodeCommand::GetInfo => {
1882 let req = cln::GetinfoRequest::default();
1883 let resp = with_connection_retry!(client.getinfo(req.clone()))
1884 .await?
1885 .into_inner();
1886 Ok(crate::serializer::value::to_value(&resp)?)
1887 }
1888 NodeCommand::Stop => {
1889 let req = cln::StopRequest::default();
1890 let resp = with_connection_retry!(client.stop(req.clone()))
1891 .await?
1892 .into_inner();
1893 Ok(crate::serializer::value::to_value(&resp)?)
1894 }
1895 }
1896 }
1897
1898 async fn max_sendable_amount<'a>(
1899 &self,
1900 payee_node_id: Option<Vec<u8>>,
1901 max_hops: u32,
1902 last_hop_hint: Option<&'a RouteHintHop>,
1903 ) -> NodeResult<Vec<MaxChannelAmount>> {
1904 let mut client = self.get_node_client().await?;
1905
1906 let mut peers = HashMap::new();
1907 let req = cln::ListpeerchannelsRequest::default();
1908 with_connection_retry!(client.list_peer_channels(req.clone()))
1909 .await?
1910 .into_inner()
1911 .channels
1912 .into_iter()
1913 .for_each(|channel| {
1914 peers
1915 .entry(channel.peer_id().to_vec())
1916 .or_insert(Vec::new())
1917 .push(channel)
1918 });
1919
1920 let mut max_channel_amounts = vec![];
1921 for (peer, channels) in peers {
1922 let max_amounts_for_peer = self
1923 .max_sendable_amount_from_peer(
1924 peer,
1925 channels,
1926 payee_node_id.clone(),
1927 max_hops,
1928 last_hop_hint,
1929 )
1930 .await?;
1931 max_channel_amounts.extend_from_slice(max_amounts_for_peer.as_slice());
1932 }
1933 Ok(max_channel_amounts)
1934 }
1935
1936 async fn derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey> {
1937 Self::derive_bip32_key(self.sdk_config.network, &self.get_signer().await, path)
1938 }
1939
1940 async fn legacy_derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey> {
1941 Self::legacy_derive_bip32_key(self.sdk_config.network, &self.get_signer().await, path)
1942 }
1943
1944 async fn stream_custom_messages(
1945 &self,
1946 ) -> NodeResult<Pin<Box<dyn Stream<Item = Result<CustomMessage>> + Send>>> {
1947 let stream = {
1948 let mut client = self.get_client().await?;
1949 let req = gl_client::signer::model::greenlight::StreamCustommsgRequest {};
1950 with_connection_retry!(client.stream_custommsg(req.clone()))
1951 .await?
1952 .into_inner()
1953 };
1954
1955 Ok(Box::pin(stream.filter_map(|msg| {
1956 let msg = match msg {
1957 Ok(msg) => msg,
1958 Err(e) => return Some(Err(anyhow!("failed to receive message: {e}"))),
1959 };
1960
1961 if msg.payload.len() < 2 {
1962 debug!(
1963 "received too short custom message payload: {:?}",
1964 &msg.payload
1965 );
1966 return None;
1967 }
1968
1969 let msg_type = u16::from_be_bytes([msg.payload[0], msg.payload[1]]);
1970
1971 Some(Ok(CustomMessage {
1972 peer_id: msg.peer_id,
1973 message_type: msg_type,
1974 payload: msg.payload[2..].to_vec(),
1975 }))
1976 })))
1977 }
1978
1979 async fn send_custom_message(&self, message: CustomMessage) -> NodeResult<()> {
1980 let mut client = self.get_node_client().await?;
1981
1982 let mut msg = message.message_type.to_be_bytes().to_vec();
1983 msg.extend(message.payload);
1984 let req = cln::SendcustommsgRequest {
1985 msg,
1986 node_id: message.peer_id,
1987 };
1988 let resp = with_connection_retry!(client.send_custom_msg(req.clone()))
1989 .await?
1990 .into_inner();
1991 debug!("send_custom_message returned status {:?}", resp.status);
1992 Ok(())
1993 }
1994
1995 async fn get_routing_hints(
1997 &self,
1998 lsp_info: &LspInformation,
1999 ) -> NodeResult<(Vec<RouteHint>, bool)> {
2000 let mut client = self.get_node_client().await?;
2001
2002 let open_peer_channels = self.get_open_peer_channels_pb().await?;
2003 let (open_peer_channels_private, open_peer_channels_public): (
2004 HashMap<Vec<u8>, ListpeerchannelsChannels>,
2005 HashMap<Vec<u8>, ListpeerchannelsChannels>,
2006 ) = open_peer_channels
2007 .into_iter()
2008 .partition(|(_, c)| c.private.unwrap_or_default());
2009 let has_public_channel = !open_peer_channels_public.is_empty();
2010
2011 let mut hints: Vec<RouteHint> = vec![];
2012
2013 let pubkey = self
2015 .persister
2016 .get_node_state()?
2017 .map(|n| n.id)
2018 .ok_or(NodeError::generic("Node info not found"))?;
2019 let req = cln::ListchannelsRequest {
2020 destination: Some(hex::decode(pubkey)?),
2021 ..Default::default()
2022 };
2023 let channels: HashMap<Vec<u8>, cln::ListchannelsChannels> =
2024 with_connection_retry!(client.list_channels(req.clone()))
2025 .await?
2026 .into_inner()
2027 .channels
2028 .into_iter()
2029 .map(|c| (c.source.clone(), c))
2030 .collect();
2031
2032 for (peer_id, peer_channel) in open_peer_channels_private {
2034 let peer_id_str = hex::encode(&peer_id);
2035 let optional_channel_id = peer_channel
2036 .alias
2037 .and_then(|a| a.remote)
2038 .or(peer_channel.short_channel_id);
2039
2040 if let Some(channel_id) = optional_channel_id {
2041 let maybe_policy = match channels.get(&peer_id) {
2043 Some(channel) => Some((
2044 channel.base_fee_millisatoshi,
2045 channel.fee_per_millionth,
2046 channel.delay,
2047 )),
2048 None if peer_id_str == lsp_info.pubkey => Some((
2049 lsp_info.base_fee_msat as u32,
2050 (lsp_info.fee_rate * 1000000.0) as u32,
2051 lsp_info.time_lock_delta,
2052 )),
2053 _ => None,
2054 };
2055 match maybe_policy {
2056 Some((fees_base_msat, fees_proportional_millionths, cltv_delta)) => {
2057 debug!(
2058 "For peer {}: remote base {} proportional {} cltv_delta {}",
2059 peer_id_str, fees_base_msat, fees_proportional_millionths, cltv_delta,
2060 );
2061 let hint = RouteHint {
2062 hops: vec![RouteHintHop {
2063 src_node_id: peer_id_str,
2064 short_channel_id: channel_id,
2065 fees_base_msat,
2066 fees_proportional_millionths,
2067 cltv_expiry_delta: cltv_delta as u64,
2068 htlc_minimum_msat: Some(
2069 peer_channel
2070 .minimum_htlc_in_msat
2071 .clone()
2072 .unwrap_or_default()
2073 .msat,
2074 ),
2075 htlc_maximum_msat: None,
2076 }],
2077 };
2078 info!("Generating hint hop as routing hint: {:?}", hint);
2079 hints.push(hint);
2080 }
2081 _ => debug!("No source channel found for peer: {:?}", peer_id_str),
2082 };
2083 }
2084 }
2085 Ok((hints, has_public_channel))
2086 }
2087
2088 async fn get_open_peers(&self) -> NodeResult<HashSet<Vec<u8>>> {
2089 let open_peer_channels = self.get_open_peer_channels_pb().await?;
2090 let open_peers: HashSet<Vec<u8>> = open_peer_channels.into_keys().collect();
2091 Ok(open_peers)
2092 }
2093}
2094
2095#[derive(Clone, PartialEq, Eq, Debug, EnumString, Display, Deserialize, Serialize)]
2096enum NodeCommand {
2097 #[strum(serialize = "closeallchannels")]
2099 CloseAllChannels,
2100
2101 #[strum(serialize = "getinfo")]
2103 GetInfo,
2104
2105 #[strum(serialize = "listfunds")]
2107 ListFunds,
2108
2109 #[strum(serialize = "listinvoices")]
2111 ListInvoices,
2112
2113 #[strum(serialize = "listpayments")]
2115 ListPayments,
2116
2117 #[strum(serialize = "listpeers")]
2119 ListPeers,
2120
2121 #[strum(serialize = "listpeerchannels")]
2123 ListPeerChannels,
2124
2125 #[strum(serialize = "stop")]
2131 Stop,
2132}
2133
2134struct SendPayAgg {
2135 state: u8,
2136 created_at: u64,
2137 payment_hash: Vec<u8>,
2138 bolt11: Option<String>,
2139 destination: Option<Vec<u8>>,
2140 label: Option<String>,
2141 description: Option<String>,
2142 preimage: Option<Vec<u8>>,
2143 amount_sent: u64,
2144 amount: Option<u64>,
2145 num_nonfailed_parts: u64,
2146}
2147
2148fn update_payment_expirations(
2149 payments: Vec<Payment>,
2150 htlc_list: Vec<Htlc>,
2151) -> NodeResult<Vec<Payment>> {
2152 if htlc_list.is_empty() {
2153 return Ok(payments);
2154 }
2155
2156 let mut payments_res: Vec<Payment> = Vec::new();
2157 for mut payment in payments {
2158 if payment.status == PaymentStatus::Pending {
2159 let new_data = payment.clone().details;
2160 if let PaymentDetails::Ln { data } = new_data {
2161 for htlc in &htlc_list {
2162 let payment_hash = hex::encode(htlc.clone().payment_hash);
2163 if payment_hash == data.payment_hash
2164 && data.pending_expiration_block < Some(htlc.expiry)
2165 {
2166 payment.details.add_pending_expiration_block(htlc.clone())
2167 }
2168 }
2169 }
2170 }
2171 payments_res.push(payment);
2172 }
2173 info!("pending htlc payments {:?}", payments_res);
2174 Ok(payments_res)
2175}
2176
2177impl TryFrom<ListsendpaysPayments> for SendPay {
2178 type Error = NodeError;
2179
2180 fn try_from(value: ListsendpaysPayments) -> std::result::Result<Self, Self::Error> {
2181 Ok(SendPay {
2182 created_index: value
2183 .created_index
2184 .ok_or(NodeError::generic("missing created index"))?,
2185 updated_index: value.updated_index,
2186 groupid: value.groupid.to_string(),
2187 partid: value.partid,
2188 payment_hash: value.payment_hash,
2189 status: value.status.try_into()?,
2190 amount_msat: value.amount_msat.map(|a| a.msat),
2191 destination: value.destination,
2192 created_at: value.created_at,
2193 amount_sent_msat: value.amount_sent_msat.map(|a| a.msat),
2194 label: value.label,
2195 bolt11: value.bolt11,
2196 description: value.description,
2197 bolt12: value.bolt12,
2198 payment_preimage: value.payment_preimage,
2199 erroronion: value.erroronion,
2200 })
2201 }
2202}
2203
2204impl TryFrom<i32> for SendPayStatus {
2205 type Error = NodeError;
2206
2207 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
2208 match value {
2209 0 => Ok(Self::Pending),
2210 1 => Ok(Self::Failed),
2211 2 => Ok(Self::Complete),
2212 _ => Err(NodeError::generic("invalid send_pay status")),
2213 }
2214 }
2215}
2216
2217impl TryFrom<SendPayAgg> for Payment {
2218 type Error = NodeError;
2219
2220 fn try_from(value: SendPayAgg) -> std::result::Result<Self, Self::Error> {
2221 let ln_invoice = value
2222 .bolt11
2223 .as_ref()
2224 .ok_or(InvoiceError::generic("No bolt11 invoice"))
2225 .and_then(|b| parse_invoice(b));
2226
2227 let (payment_amount, client_label) =
2230 serde_json::from_str::<PaymentLabel>(&value.label.clone().unwrap_or_default())
2231 .ok()
2232 .and_then(|label| {
2233 label
2234 .trampoline
2235 .then_some((label.amount_msat, label.client_label))
2236 })
2237 .unwrap_or((value.amount.unwrap_or_default(), value.label));
2238 let fee_msat = value.amount_sent.saturating_sub(payment_amount);
2239 let status = if value.state & PAYMENT_STATE_COMPLETE > 0 {
2240 PaymentStatus::Complete
2241 } else if value.state & PAYMENT_STATE_PENDING > 0 {
2242 PaymentStatus::Pending
2243 } else {
2244 PaymentStatus::Failed
2245 };
2246 Ok(Self {
2247 id: hex::encode(&value.payment_hash),
2248 payment_type: PaymentType::Sent,
2249 payment_time: value.created_at as i64,
2250 amount_msat: match status {
2251 PaymentStatus::Complete => payment_amount,
2252 _ => ln_invoice
2253 .as_ref()
2254 .map_or(0, |i| i.amount_msat.unwrap_or_default()),
2255 },
2256 fee_msat,
2257 status,
2258 error: None,
2259 description: ln_invoice
2260 .as_ref()
2261 .map(|i| i.description.clone())
2262 .unwrap_or_default(),
2263 details: PaymentDetails::Ln {
2264 data: LnPaymentDetails {
2265 payment_hash: hex::encode(&value.payment_hash),
2266 label: client_label.unwrap_or_default(),
2267 destination_pubkey: ln_invoice.map_or(
2268 value.destination.map(hex::encode).unwrap_or_default(),
2269 |i| i.payee_pubkey,
2270 ),
2271 payment_preimage: value.preimage.map(hex::encode).unwrap_or_default(),
2272 keysend: value.bolt11.is_none(),
2273 bolt11: value.bolt11.unwrap_or_default(),
2274 open_channel_bolt11: None,
2275 lnurl_success_action: None,
2276 lnurl_pay_domain: None,
2277 lnurl_pay_comment: None,
2278 ln_address: None,
2279 lnurl_metadata: None,
2280 lnurl_withdraw_endpoint: None,
2281 swap_info: None,
2282 reverse_swap_info: None,
2283 pending_expiration_block: None,
2284 },
2285 },
2286 metadata: None,
2287 })
2288 }
2289}
2290
2291impl TryFrom<cln::ListinvoicesInvoices> for Payment {
2293 type Error = NodeError;
2294
2295 fn try_from(invoice: cln::ListinvoicesInvoices) -> std::result::Result<Self, Self::Error> {
2296 let ln_invoice = invoice
2297 .bolt11
2298 .as_ref()
2299 .ok_or(InvoiceError::generic("No bolt11 invoice"))
2300 .and_then(|b| parse_invoice(b))?;
2301 Ok(Payment {
2302 id: hex::encode(invoice.payment_hash.clone()),
2303 payment_type: PaymentType::Received,
2304 payment_time: invoice.paid_at.map(|i| i as i64).unwrap_or_default(),
2305 amount_msat: invoice
2306 .amount_received_msat
2307 .or(invoice.amount_msat)
2308 .map(|a| a.msat)
2309 .unwrap_or_default(),
2310 fee_msat: 0,
2311 status: PaymentStatus::Complete,
2312 error: None,
2313 description: ln_invoice.description,
2314 details: PaymentDetails::Ln {
2315 data: LnPaymentDetails {
2316 payment_hash: hex::encode(invoice.payment_hash),
2317 label: invoice.label,
2318 destination_pubkey: ln_invoice.payee_pubkey,
2319 payment_preimage: invoice
2320 .payment_preimage
2321 .map(hex::encode)
2322 .unwrap_or_default(),
2323 keysend: false,
2324 bolt11: invoice.bolt11.unwrap_or_default(),
2325 lnurl_success_action: None, lnurl_pay_domain: None, lnurl_pay_comment: None, lnurl_metadata: None, ln_address: None,
2330 lnurl_withdraw_endpoint: None,
2331 swap_info: None,
2332 reverse_swap_info: None,
2333 pending_expiration_block: None,
2334 open_channel_bolt11: None,
2335 },
2336 },
2337 metadata: None,
2338 })
2339 }
2340}
2341
2342impl From<ListpaysPaysStatus> for PaymentStatus {
2343 fn from(value: ListpaysPaysStatus) -> Self {
2344 match value {
2345 ListpaysPaysStatus::Pending => PaymentStatus::Pending,
2346 ListpaysPaysStatus::Complete => PaymentStatus::Complete,
2347 ListpaysPaysStatus::Failed => PaymentStatus::Failed,
2348 }
2349 }
2350}
2351
2352impl TryFrom<cln::ListpaysPays> for Payment {
2353 type Error = NodeError;
2354
2355 fn try_from(payment: cln::ListpaysPays) -> NodeResult<Self, Self::Error> {
2356 let ln_invoice = payment
2357 .bolt11
2358 .as_ref()
2359 .ok_or(InvoiceError::generic("No bolt11 invoice"))
2360 .and_then(|b| parse_invoice(b));
2361 let payment_amount_sent = payment
2362 .amount_sent_msat
2363 .clone()
2364 .map(|a| a.msat)
2365 .unwrap_or_default();
2366
2367 let (payment_amount, client_label) = serde_json::from_str::<PaymentLabel>(payment.label())
2370 .ok()
2371 .and_then(|label| {
2372 label
2373 .trampoline
2374 .then_some((label.amount_msat, label.client_label))
2375 })
2376 .unwrap_or((
2377 payment
2378 .amount_msat
2379 .clone()
2380 .map(|a| a.msat)
2381 .unwrap_or_default(),
2382 payment.label.clone(),
2383 ));
2384 let status = payment.status().into();
2385
2386 Ok(Payment {
2387 id: hex::encode(payment.payment_hash.clone()),
2388 payment_type: PaymentType::Sent,
2389 payment_time: payment.completed_at.unwrap_or(payment.created_at) as i64,
2390 amount_msat: match status {
2391 PaymentStatus::Complete => payment_amount,
2392 _ => ln_invoice
2393 .as_ref()
2394 .map_or(0, |i| i.amount_msat.unwrap_or_default()),
2395 },
2396 fee_msat: payment_amount_sent.saturating_sub(payment_amount),
2397 status,
2398 error: None,
2399 description: ln_invoice
2400 .as_ref()
2401 .map(|i| i.description.clone())
2402 .unwrap_or_default(),
2403 details: PaymentDetails::Ln {
2404 data: LnPaymentDetails {
2405 payment_hash: hex::encode(payment.payment_hash),
2406 label: client_label.unwrap_or_default(),
2407 destination_pubkey: ln_invoice.map_or(
2408 payment.destination.map(hex::encode).unwrap_or_default(),
2409 |i| i.payee_pubkey,
2410 ),
2411 payment_preimage: payment.preimage.map(hex::encode).unwrap_or_default(),
2412 keysend: payment.bolt11.is_none(),
2413 bolt11: payment.bolt11.unwrap_or_default(),
2414 lnurl_success_action: None,
2415 lnurl_pay_domain: None,
2416 lnurl_pay_comment: None,
2417 lnurl_metadata: None,
2418 ln_address: None,
2419 lnurl_withdraw_endpoint: None,
2420 swap_info: None,
2421 reverse_swap_info: None,
2422 pending_expiration_block: None,
2423 open_channel_bolt11: None,
2424 },
2425 },
2426 metadata: None,
2427 })
2428 }
2429}
2430
2431impl TryFrom<cln::PayResponse> for PaymentResponse {
2432 type Error = NodeError;
2433
2434 fn try_from(payment: cln::PayResponse) -> std::result::Result<Self, Self::Error> {
2435 let payment_amount = payment.amount_msat.unwrap_or_default().msat;
2436 let payment_amount_sent = payment.amount_sent_msat.unwrap_or_default().msat;
2437
2438 Ok(PaymentResponse {
2439 payment_time: payment.created_at as i64,
2440 amount_msat: payment_amount,
2441 fee_msat: payment_amount_sent - payment_amount,
2442 payment_hash: hex::encode(payment.payment_hash),
2443 payment_preimage: hex::encode(payment.payment_preimage),
2444 })
2445 }
2446}
2447
2448impl TryFrom<cln::KeysendResponse> for PaymentResponse {
2449 type Error = NodeError;
2450
2451 fn try_from(payment: cln::KeysendResponse) -> std::result::Result<Self, Self::Error> {
2452 let payment_amount = payment.amount_msat.unwrap_or_default().msat;
2453 let payment_amount_sent = payment.amount_sent_msat.unwrap_or_default().msat;
2454
2455 Ok(PaymentResponse {
2456 payment_time: payment.created_at as i64,
2457 amount_msat: payment_amount,
2458 fee_msat: payment_amount_sent - payment_amount,
2459 payment_hash: hex::encode(payment.payment_hash),
2460 payment_preimage: hex::encode(payment.payment_preimage),
2461 })
2462 }
2463}
2464
2465fn amount_to_msat(amount: &gl_client::pb::greenlight::Amount) -> u64 {
2466 match amount.unit {
2467 Some(amount::Unit::Millisatoshi(val)) => val,
2468 Some(amount::Unit::Satoshi(val)) => val * 1000,
2469 Some(amount::Unit::Bitcoin(val)) => val * 100000000,
2470 Some(_) => 0,
2471 None => 0,
2472 }
2473}
2474
2475impl From<cln::ListpeerchannelsChannels> for Channel {
2477 fn from(c: cln::ListpeerchannelsChannels) -> Self {
2478 let state = match c.state() {
2479 Openingd | ChanneldAwaitingLockin | DualopendOpenInit | DualopendAwaitingLockin => {
2480 ChannelState::PendingOpen
2481 }
2482 ChanneldNormal => ChannelState::Opened,
2483 _ => ChannelState::PendingClose,
2484 };
2485
2486 let (alias_remote, alias_local) = match c.alias {
2487 Some(a) => (a.remote, a.local),
2488 None => (None, None),
2489 };
2490
2491 Channel {
2492 short_channel_id: c.short_channel_id,
2493 state,
2494 funding_txid: c.funding_txid.map(hex::encode).unwrap_or_default(),
2495 spendable_msat: c.spendable_msat.unwrap_or_default().msat,
2496 local_balance_msat: c.to_us_msat.unwrap_or_default().msat,
2497 receivable_msat: c.receivable_msat.unwrap_or_default().msat,
2498 closed_at: None,
2499 funding_outnum: c.funding_outnum,
2500 alias_remote,
2501 alias_local,
2502 closing_txid: None,
2503 htlcs: c
2504 .htlcs
2505 .into_iter()
2506 .map(|c| Htlc::from(c.expiry.unwrap_or(0), c.payment_hash.unwrap_or_default()))
2507 .collect(),
2508 }
2509 }
2510}
2511
2512fn convert_to_send_pay_route(
2513 route: PaymentPath,
2514 to_pay_msat: u64,
2515 final_cltv_delta: u64,
2516) -> (Vec<SendpayRoute>, u64) {
2517 let mut sendpay_route = vec![];
2518 let mut to_forward = to_pay_msat;
2519 let mut cltv_delay = 0;
2520 let hops_arr = route.edges.as_slice();
2521
2522 let reverse_hops: Vec<&PaymentPathEdge> = hops_arr.iter().rev().collect();
2523
2524 for (reverse_index, hop) in reverse_hops.iter().enumerate() {
2527 (to_forward, cltv_delay) = match reverse_index == 0 {
2529 true => (to_forward, final_cltv_delta),
2531
2532 false => (
2534 reverse_hops[reverse_index - 1].amount_from_forward(to_forward),
2535 cltv_delay + reverse_hops[reverse_index - 1].channel_delay,
2536 ),
2537 };
2538
2539 sendpay_route.insert(
2540 0,
2541 SendpayRoute {
2542 amount_msat: Some(gl_client::pb::cln::Amount { msat: to_forward }),
2543 id: hop.node_id.clone(),
2544 delay: cltv_delay as u32,
2545 channel: hop.short_channel_id.clone(),
2546 },
2547 );
2548 }
2549
2550 (sendpay_route, to_forward)
2551}
2552
2553impl TryFrom<ListclosedchannelsClosedchannels> for Channel {
2554 type Error = NodeError;
2555
2556 fn try_from(
2557 c: cln::ListclosedchannelsClosedchannels,
2558 ) -> std::result::Result<Self, Self::Error> {
2559 let (alias_remote, alias_local) = match c.alias {
2560 Some(a) => (a.remote, a.local),
2561 None => (None, None),
2562 };
2563
2564 let local_balance_msat = c
2567 .final_to_us_msat
2568 .ok_or(anyhow!("final_to_us_msat is missing"))?
2569 .msat;
2570 Ok(Channel {
2571 short_channel_id: c.short_channel_id,
2572 state: ChannelState::Closed,
2573 funding_txid: hex::encode(c.funding_txid),
2574 spendable_msat: local_balance_msat,
2575 local_balance_msat,
2576 receivable_msat: 0,
2577 closed_at: None,
2578 funding_outnum: Some(c.funding_outnum),
2579 alias_remote,
2580 alias_local,
2581 closing_txid: None,
2582 htlcs: Vec::new(),
2583 })
2584 }
2585}
2586
2587#[cfg(test)]
2588mod tests {
2589 use anyhow::Result;
2590 use gl_client::pb::cln::listpeerchannels_channels::{
2591 ListpeerchannelsChannelsState, ListpeerchannelsChannelsState::*,
2592 };
2593 use gl_client::pb::cln::Amount;
2594 use gl_client::pb::{self, cln};
2595
2596 use crate::greenlight::node_api::convert_to_send_pay_route;
2597 use crate::{models, PaymentPath, PaymentPathEdge};
2598
2599 #[test]
2600 fn test_convert_route() -> Result<()> {
2601 let path = PaymentPath {
2602 edges: vec![
2603 PaymentPathEdge {
2604 node_id: vec![1],
2605 short_channel_id: "807189x2048x0".into(),
2606 channel_delay: 34,
2607 base_fee_msat: 1000,
2608 fee_per_millionth: 10,
2609 },
2610 PaymentPathEdge {
2611 node_id: vec![2],
2612 short_channel_id: "811871x2726x1".into(),
2613 channel_delay: 34,
2614 base_fee_msat: 0,
2615 fee_per_millionth: 0,
2616 },
2617 PaymentPathEdge {
2618 node_id: vec![3],
2619 short_channel_id: "16000000x0x18087".into(),
2620 channel_delay: 40,
2621 base_fee_msat: 1000,
2622 fee_per_millionth: 1,
2623 },
2624 ],
2625 };
2626
2627 let (r, sent) = convert_to_send_pay_route(path, 50000000, 144);
2628 assert_eq!(
2629 r,
2630 vec![
2631 pb::cln::SendpayRoute {
2632 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50001050 }),
2633 id: vec![1],
2634 delay: 218,
2635 channel: "807189x2048x0".into(),
2636 },
2637 pb::cln::SendpayRoute {
2638 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50001050 }),
2639 id: vec![2],
2640 delay: 184,
2641 channel: "811871x2726x1".into(),
2642 },
2643 pb::cln::SendpayRoute {
2644 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50000000 }),
2645 id: vec![3],
2646 delay: 144,
2647 channel: "16000000x0x18087".into(),
2648 }
2649 ]
2650 );
2651 assert_eq!(sent, 50001050);
2652
2653 let path = PaymentPath {
2654 edges: vec![
2655 PaymentPathEdge {
2656 node_id: vec![1],
2657 short_channel_id: "807189x2048x0".into(),
2658 channel_delay: 34,
2659 base_fee_msat: 1000,
2660 fee_per_millionth: 10,
2661 },
2662 PaymentPathEdge {
2663 node_id: vec![2],
2664 short_channel_id: "811871x2726x1".into(),
2665 channel_delay: 34,
2666 base_fee_msat: 0,
2667 fee_per_millionth: 0,
2668 },
2669 PaymentPathEdge {
2670 node_id: vec![3],
2671 short_channel_id: "16000000x0x18087".into(),
2672 channel_delay: 40,
2673 base_fee_msat: 0,
2674 fee_per_millionth: 2000,
2675 },
2676 ],
2677 };
2678 let (r, sent) = convert_to_send_pay_route(path, 50000000, 144);
2679 assert_eq!(
2680 r,
2681 vec![
2682 pb::cln::SendpayRoute {
2683 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50100000 }),
2684 id: vec![1],
2685 delay: 218,
2686 channel: "807189x2048x0".into(),
2687 },
2688 pb::cln::SendpayRoute {
2689 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50100000 }),
2690 id: vec![2],
2691 delay: 184,
2692 channel: "811871x2726x1".into(),
2693 },
2694 pb::cln::SendpayRoute {
2695 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50000000 }),
2696 id: vec![3],
2697 delay: 144,
2698 channel: "16000000x0x18087".into(),
2699 }
2700 ]
2701 );
2702 assert_eq!(sent, 50100000);
2703
2704 Ok(())
2705 }
2706
2707 #[test]
2708 fn test_channel_states() -> Result<()> {
2709 for s in &[Openingd, ChanneldAwaitingLockin] {
2710 let c: models::Channel = cln_channel(s).into();
2711 assert_eq!(c.state, models::ChannelState::PendingOpen);
2712 }
2713
2714 let s = ChanneldNormal;
2715 let c: models::Channel = cln_channel(&s).into();
2716 assert_eq!(c.state, models::ChannelState::Opened);
2717
2718 for s in &[
2719 ChanneldShuttingDown,
2720 ClosingdSigexchange,
2721 ClosingdComplete,
2722 AwaitingUnilateral,
2723 FundingSpendSeen,
2724 ] {
2725 let c: models::Channel = cln_channel(s).into();
2726 assert_eq!(c.state, models::ChannelState::PendingClose);
2727 }
2728
2729 let c: models::Channel = cln_channel(&Onchain).into();
2730 assert_eq!(c.state, models::ChannelState::PendingClose);
2731
2732 Ok(())
2733 }
2734
2735 fn cln_channel(state: &ListpeerchannelsChannelsState) -> cln::ListpeerchannelsChannels {
2736 cln::ListpeerchannelsChannels {
2737 state: Some((*state).into()),
2738 scratch_txid: None,
2739 feerate: None,
2740 owner: None,
2741 short_channel_id: None,
2742 channel_id: None,
2743 funding_txid: None,
2744 funding_outnum: None,
2745 initial_feerate: None,
2746 last_feerate: None,
2747 next_feerate: None,
2748 next_fee_step: None,
2749 inflight: vec![],
2750 close_to: None,
2751 private: Some(true),
2752 opener: Some(0),
2753 closer: None,
2754 funding: None,
2755 to_us_msat: None,
2756 min_to_us_msat: None,
2757 max_to_us_msat: None,
2758 total_msat: Some(Amount { msat: 1_000 }),
2759 fee_base_msat: None,
2760 fee_proportional_millionths: None,
2761 dust_limit_msat: Some(Amount { msat: 10 }),
2762 max_total_htlc_in_msat: None,
2763 their_reserve_msat: None,
2764 our_reserve_msat: None,
2765 spendable_msat: Some(Amount { msat: 20_000 }),
2766 receivable_msat: Some(Amount { msat: 960_000 }),
2767 minimum_htlc_in_msat: None,
2768 minimum_htlc_out_msat: None,
2769 maximum_htlc_out_msat: None,
2770 their_to_self_delay: Some(144),
2771 our_to_self_delay: Some(144),
2772 max_accepted_htlcs: None,
2773 alias: None,
2774 status: vec![],
2775 in_payments_offered: None,
2776 in_offered_msat: None,
2777 in_payments_fulfilled: None,
2778 in_fulfilled_msat: None,
2779 out_payments_offered: None,
2780 out_offered_msat: None,
2781 out_payments_fulfilled: None,
2782 out_fulfilled_msat: None,
2783 htlcs: vec![],
2784 close_to_addr: None,
2785 peer_id: None,
2786 peer_connected: None,
2787 updates: None,
2788 ignore_fee_limits: None,
2789 lost_state: None,
2790 last_stable_connection: None,
2791 }
2792 }
2793}