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::{OffChainPayment, 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;
39use tonic::Streaming;
40
41use crate::bitcoin::bech32::{u5, ToBase32};
42use crate::bitcoin::blockdata::constants::WITNESS_SCALE_FACTOR;
43use crate::bitcoin::hashes::Hash;
44use crate::bitcoin::secp256k1::ecdsa::{RecoverableSignature, RecoveryId};
45use crate::bitcoin::secp256k1::PublicKey;
46use crate::bitcoin::secp256k1::Secp256k1;
47use crate::bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey};
48use crate::bitcoin::{
49 Address, OutPoint, Script, Sequence, Transaction, TxIn, TxOut, Txid, Witness,
50};
51use crate::lightning::util::message_signing::verify;
52use crate::lightning_invoice::{RawBolt11Invoice, SignedRawBolt11Invoice};
53use crate::node_api::{CreateInvoiceRequest, FetchBolt11Result, NodeAPI, NodeError, NodeResult};
54use crate::persist::cache::NodeStateStorage;
55use crate::persist::db::SqliteStorage;
56use crate::persist::send_pays::{SendPay, SendPayStatus};
57use crate::{models::*, LspInformation};
58use crate::{NodeConfig, PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse};
59
60const MAX_PAYMENT_AMOUNT_MSAT: u64 = 4294967000;
61const MAX_INBOUND_LIQUIDITY_MSAT: u64 = 4000000000;
62const TRAMPOLINE_BASE_FEE_MSAT: u64 = 4000;
63const TRAMPOLINE_FEE_PPM: u64 = 5000;
64const PAYMENT_STATE_PENDING: u8 = 1;
65const PAYMENT_STATE_COMPLETE: u8 = 2;
66const PAYMENT_STATE_FAILED: u8 = 4;
67
68pub(crate) struct Greenlight {
69 sdk_config: Config,
70 signer: Mutex<Arc<Signer>>,
71 device: Device,
72 gl_client: Mutex<Option<node::Client>>,
73 node_client: Mutex<Option<ClnClient>>,
74 persister: Arc<SqliteStorage>,
75 inprogress_payments: AtomicU16,
76}
77
78#[derive(Serialize, Deserialize)]
79struct InvoiceLabel {
80 pub unix_milli: u128,
81 pub payer_amount_msat: Option<u64>,
82}
83
84#[derive(Serialize, Deserialize)]
85struct PaymentLabel {
86 pub unix_nano: u128,
87 pub trampoline: bool,
88 pub client_label: Option<String>,
89 pub amount_msat: u64,
90}
91
92impl Greenlight {
93 pub async fn connect(
100 config: Config,
101 seed: Vec<u8>,
102 restore_only: Option<bool>,
103 persister: Arc<SqliteStorage>,
104 ) -> NodeResult<Self> {
105 let temp_signer = Arc::new(Signer::new(
107 seed.clone(),
108 config.network.into(),
109 Nobody::new(),
110 )?);
111 let encryption_key = Self::derive_bip32_key(
112 config.network,
113 &temp_signer,
114 vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
115 )?
116 .to_priv()
117 .to_bytes();
118 let encryption_key_slice = encryption_key.as_slice();
119
120 let register_credentials = match config.node_config.clone() {
121 NodeConfig::Greenlight { config } => config,
122 };
123
124 let mut parsed_credentials =
126 Self::get_node_credentials(config.network, &temp_signer, persister.clone())?
127 .ok_or(NodeError::credentials("No credentials found"));
128 if parsed_credentials.is_err() {
129 info!("No credentials found, trying to recover existing node");
130 parsed_credentials = match Self::recover(config.network, seed.clone()).await {
131 Ok(creds) => Ok(creds),
132 Err(_) => {
133 match restore_only.unwrap_or(false) {
134 false => {
135 info!("Failed to recover node, registering new one");
137 let credentials = Self::register(
138 config.clone().network,
139 seed.clone(),
140 register_credentials.partner_credentials,
141 register_credentials.invite_code,
142 )
143 .await?;
144 Ok(credentials)
145 }
146 true => {
147 return Err(NodeError::RestoreOnly("Node does not exist".to_string()));
148 }
149 }
150 }
151 }
152 }
153
154 match parsed_credentials {
156 Ok(creds) => {
157 let temp_scheduler = Scheduler::new(config.network.into(), creds.clone()).await?;
158 debug!("upgrading credentials");
159 let creds = creds.upgrade(&temp_scheduler, &temp_signer).await?;
160 debug!("upgrading credentials succeeded");
161 let encrypted_creds = sym_encrypt(encryption_key_slice, &creds.to_bytes());
162 match encrypted_creds {
163 Some(c) => {
164 persister.set_gl_credentials(c)?;
165 Greenlight::new(config, seed, creds.clone(), persister)
166 }
167 None => Err(NodeError::generic("Failed to encrypt credentials")),
168 }
169 }
170 Err(_) => Err(NodeError::credentials("Failed to get gl credentials")),
171 }
172 }
173
174 fn new(
175 sdk_config: Config,
176 seed: Vec<u8>,
177 device: Device,
178 persister: Arc<SqliteStorage>,
179 ) -> NodeResult<Greenlight> {
180 let greenlight_network = sdk_config.network.into();
181 let signer = Signer::new(seed.clone(), greenlight_network, device.clone())?;
182 Ok(Greenlight {
183 sdk_config,
184 signer: Mutex::new(Arc::new(signer)),
185 device,
186 gl_client: Mutex::new(None),
187 node_client: Mutex::new(None),
188 persister,
189 inprogress_payments: AtomicU16::new(0),
190 })
191 }
192
193 async fn get_signer(&self) -> Arc<Signer> {
194 Arc::clone(&*self.signer.lock().await)
195 }
196
197 fn derive_bip32_key(
198 network: Network,
199 signer: &Arc<Signer>,
200 path: Vec<ChildNumber>,
201 ) -> NodeResult<ExtendedPrivKey> {
202 Ok(
203 ExtendedPrivKey::new_master(network.into(), &signer.bip32_ext_key())?
204 .derive_priv(&Secp256k1::new(), &path)?,
205 )
206 }
207
208 fn legacy_derive_bip32_key(
209 network: Network,
210 signer: &Arc<Signer>,
211 path: Vec<ChildNumber>,
212 ) -> NodeResult<ExtendedPrivKey> {
213 Ok(
214 ExtendedPrivKey::new_master(network.into(), &signer.legacy_bip32_ext_key())?
215 .derive_priv(&Secp256k1::new(), &path)?,
216 )
217 }
218
219 async fn register(
220 network: Network,
221 seed: Vec<u8>,
222 register_credentials: Option<GreenlightCredentials>,
223 invite_code: Option<String>,
224 ) -> Result<Device> {
225 if invite_code.is_some() && register_credentials.is_some() {
226 return Err(anyhow!("Cannot specify both invite code and credentials"));
227 }
228 let greenlight_network = network.into();
229 let creds = match register_credentials {
230 Some(creds) => {
231 debug!("registering with credentials");
232 Nobody {
233 cert: creds.developer_cert,
234 key: creds.developer_key,
235 ..Default::default()
236 }
237 }
238 None => Nobody::new(),
239 };
240
241 let signer = Signer::new(seed, greenlight_network, creds.clone())?;
242 let scheduler = Scheduler::new(greenlight_network, creds).await?;
243
244 let register_res: scheduler::RegistrationResponse =
245 scheduler.register(&signer, invite_code).await?;
246
247 Ok(Device::from_bytes(register_res.creds))
248 }
249
250 async fn recover(network: Network, seed: Vec<u8>) -> Result<Device> {
251 let greenlight_network = network.into();
252 let credentials = Nobody::new();
253 let signer = Signer::new(seed, greenlight_network, credentials.clone())?;
254 let scheduler = Scheduler::new(greenlight_network, credentials).await?;
255 let recover_res: scheduler::RecoveryResponse = scheduler.recover(&signer).await?;
256
257 Ok(Device::from_bytes(recover_res.creds))
258 }
259
260 async fn get_client(&self) -> NodeResult<node::Client> {
261 let mut gl_client = self.gl_client.lock().await;
262 if gl_client.is_none() {
263 let scheduler = Scheduler::new(self.sdk_config.network.into(), self.device.clone())
264 .await
265 .map_err(|e| NodeError::ServiceConnectivity(e.to_string()))?;
266 *gl_client = Some(scheduler.node().await?);
267 }
268 Ok(gl_client.clone().unwrap())
269 }
270
271 pub(crate) async fn get_node_client(&self) -> NodeResult<node::ClnClient> {
272 let mut node_client = self.node_client.lock().await;
273 if node_client.is_none() {
274 let scheduler = Scheduler::new(self.sdk_config.network.into(), self.device.clone())
275 .await
276 .map_err(|e| NodeError::ServiceConnectivity(e.to_string()))?;
277 *node_client = Some(scheduler.node().await?);
278 }
279 Ok(node_client.clone().unwrap())
280 }
281
282 fn get_node_credentials(
283 network: Network,
284 signer: &Arc<Signer>,
285 persister: Arc<SqliteStorage>,
286 ) -> NodeResult<Option<Device>> {
287 let encryption_key = Self::derive_bip32_key(
289 network,
290 signer,
291 vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
292 )?
293 .to_priv()
294 .to_bytes();
295 let encryption_key_slice = encryption_key.as_slice();
296
297 let legacy_encryption_key = Self::legacy_derive_bip32_key(
298 network,
299 signer,
300 vec![ChildNumber::from_hardened_idx(140)?, ChildNumber::from(0)],
301 )?
302 .to_priv()
303 .to_bytes();
304 let legacy_encryption_key_slice = legacy_encryption_key.as_slice();
305
306 match persister.get_gl_credentials()? {
307 Some(encrypted_creds) => {
308 let mut decrypted_credentials =
309 sym_decrypt(encryption_key_slice, encrypted_creds.as_slice());
310 if decrypted_credentials.is_none() {
311 info!("Failed to decrypt credentials, trying legacy key");
312 decrypted_credentials =
313 sym_decrypt(legacy_encryption_key_slice, encrypted_creds.as_slice());
314 }
315 match decrypted_credentials {
316 Some(decrypted_creds) => {
317 let credentials = Device::from_bytes(decrypted_creds.as_slice());
318 if credentials.cert.is_empty() {
319 Err(NodeError::credentials("Unable to parse credentials"))
320 } else {
321 Ok(Some(credentials))
322 }
323 }
324 None => Err(NodeError::credentials(
325 "Failed to decrypt credentials, seed doesn't match existing node",
326 )),
327 }
328 }
329 None => Ok(None),
330 }
331 }
332
333 async fn fetch_outgoing_payment_with_retry(
334 client: node::ClnClient,
335 payment_hash: Vec<u8>,
336 ) -> Result<cln::ListpaysPays> {
337 let mut response = cln::ListpaysResponse::default();
338 let mut retry = 0;
339 let max_retries = 20;
340
341 while response.pays.is_empty() && retry < max_retries {
342 let req = cln::ListpaysRequest {
343 payment_hash: Some(payment_hash.clone()),
344 status: Some(cln::listpays_request::ListpaysStatus::Complete.into()),
345 ..cln::ListpaysRequest::default()
346 };
347 let mut client = client.clone();
348 response = with_connection_retry!(client.list_pays(req.clone()))
349 .await?
350 .into_inner();
351 if response.pays.is_empty() {
352 debug!("fetch outgoing payment failed, retrying in 100ms...");
353 sleep(Duration::from_millis(100)).await;
354 }
355 retry += 1;
356 }
357
358 debug!("list_pays: {:?}", response.pays);
360 let pays: Vec<ListpaysPays> = response
361 .pays
362 .into_iter()
363 .filter(|pay| pay.status() == cln::listpays_pays::ListpaysPaysStatus::Complete)
364 .collect();
365
366 if pays.is_empty() {
367 return Err(anyhow!("Payment not found"));
368 }
369 Ok(pays[0].clone())
370 }
371
372 async fn fetch_channels_and_balance_with_retry(
373 cln_client: node::ClnClient,
374 persister: Arc<SqliteStorage>,
375 match_local_balance: bool,
376 ) -> NodeResult<(
377 Vec<cln::ListpeerchannelsChannels>,
378 Vec<cln::ListpeerchannelsChannels>,
379 Vec<String>,
380 u64,
381 )> {
382 let (mut all_channels, mut opened_channels, mut connected_peers, mut channels_balance) =
383 Greenlight::fetch_channels_and_balance(cln_client.clone()).await?;
384 if match_local_balance {
385 let node_state = persister.get_node_state()?;
386 if let Some(state) = node_state {
387 let mut retry_count = 0;
388 while state.channels_balance_msat != channels_balance && retry_count < 10 {
389 warn!("balance matching local state is required and not yet satisfied, retrying in 100ms...");
390 sleep(Duration::from_millis(100)).await;
391 (
392 all_channels,
393 opened_channels,
394 connected_peers,
395 channels_balance,
396 ) = Greenlight::fetch_channels_and_balance(cln_client.clone()).await?;
397 retry_count += 1;
398 }
399 }
400 }
401 Ok((
402 all_channels,
403 opened_channels,
404 connected_peers,
405 channels_balance,
406 ))
407 }
408
409 async fn fetch_channels_and_balance(
410 mut client: node::ClnClient,
411 ) -> NodeResult<(
412 Vec<cln::ListpeerchannelsChannels>,
413 Vec<cln::ListpeerchannelsChannels>,
414 Vec<String>,
415 u64,
416 )> {
417 let req = cln::ListpeerchannelsRequest::default();
419 let peerchannels = with_connection_retry!(client.list_peer_channels(req.clone()))
420 .await?
421 .into_inner();
422
423 let connected_peers: Vec<String> = peerchannels
425 .channels
426 .iter()
427 .filter(|channel| channel.peer_connected())
428 .filter_map(|channel| channel.peer_id.clone())
429 .map(hex::encode)
430 .collect::<HashSet<_>>()
431 .into_iter()
432 .collect();
433
434 let opened_channels: Vec<cln::ListpeerchannelsChannels> = peerchannels
436 .channels
437 .iter()
438 .filter(|c| c.state() == ChanneldNormal)
439 .cloned()
440 .collect();
441
442 let channels_balance = opened_channels
444 .iter()
445 .map(|c| Channel::from(c.clone()))
446 .map(|c| c.spendable_msat)
447 .sum::<u64>();
448 Ok((
449 peerchannels.channels,
450 opened_channels,
451 connected_peers,
452 channels_balance,
453 ))
454 }
455
456 async fn list_funds(&self) -> Result<cln::ListfundsResponse> {
457 let mut client = self.get_node_client().await?;
458 let req = cln::ListfundsRequest::default();
459 let funds: cln::ListfundsResponse = with_connection_retry!(client.list_funds(req.clone()))
460 .await?
461 .into_inner();
462 Ok(funds)
463 }
464
465 async fn on_chain_balance(&self, funds: &cln::ListfundsResponse) -> Result<u64> {
466 let on_chain_balance = funds.outputs.iter().fold(0, |a, b| {
467 if b.reserved {
468 return a;
469 }
470 a + b.amount_msat.clone().unwrap_or_default().msat
471 });
472 Ok(on_chain_balance)
473 }
474
475 async fn pending_onchain_balance(
476 &self,
477 peer_channels: &[cln::ListpeerchannelsChannels],
478 ) -> Result<u64> {
479 let pending_onchain_balance = peer_channels.iter().fold(0, |a, b| match b.state() {
480 ChanneldShuttingDown | ClosingdSigexchange | ClosingdComplete | AwaitingUnilateral
481 | FundingSpendSeen => a + b.to_us_msat.clone().unwrap_or_default().msat,
482
483 Onchain => {
488 if b.closer() == cln::ChannelSide::Local
489 && b.status
490 .last()
491 .is_some_and(|status| status.contains("DELAYED_OUTPUT_TO_US"))
492 {
493 a + b.to_us_msat.clone().unwrap_or_default().msat
494 } else {
495 a
496 }
497 }
498 _ => a,
499 });
500 info!("pending_onchain_balance is {}", pending_onchain_balance);
501 Ok(pending_onchain_balance)
502 }
503
504 async fn utxos(&self, funds: cln::ListfundsResponse) -> Result<Vec<UnspentTransactionOutput>> {
506 let utxos: Vec<UnspentTransactionOutput> = funds
507 .outputs
508 .iter()
509 .map(|output| UnspentTransactionOutput {
510 txid: output.txid.clone(),
511 outnum: output.output,
512 amount_millisatoshi: output
513 .amount_msat
514 .as_ref()
515 .map(|a| a.msat)
516 .unwrap_or_default(),
517 address: output.address.clone().unwrap_or_default(),
518 reserved: output.reserved,
519 })
520 .collect();
521 Ok(utxos)
522 }
523
524 async fn build_payment_path(
525 &self,
526 route: &Vec<GetrouteRoute>,
527 first_edge: PaymentPathEdge,
528 ) -> NodeResult<PaymentPath> {
529 let client = self.get_node_client().await?;
530 let mut hops = vec![first_edge];
531
532 for hop in route {
533 let req = ListchannelsRequest {
534 short_channel_id: Some(hop.channel.clone()),
535 source: None,
536 destination: None,
537 };
538 let mut client = client.clone();
539 let hopchannels = with_connection_retry!(client.list_channels(req.clone()))
540 .await?
541 .into_inner()
542 .channels;
543
544 let first_channel = hopchannels.first().ok_or(NodeError::RouteNotFound(format!(
545 "Channel not found {}",
546 hop.channel.clone()
547 )))?;
548
549 info!("found channel in route: {:?}", first_channel);
550 hops.push(PaymentPathEdge {
551 base_fee_msat: first_channel.base_fee_millisatoshi as u64,
552 fee_per_millionth: first_channel.fee_per_millionth as u64,
553 node_id: hop.id.clone(),
554 short_channel_id: hop.channel.clone(),
555 channel_delay: first_channel.delay as u64,
556 });
557 }
558 Ok(PaymentPath { edges: hops })
559 }
560
561 async fn max_sendable_amount_from_peer(
562 &self,
563 via_peer_id: Vec<u8>,
564 via_peer_channels: Vec<ListpeerchannelsChannels>,
565 payee_node_id: Option<Vec<u8>>,
566 max_hops: u32,
567 last_hop_hint: Option<&RouteHintHop>,
568 ) -> NodeResult<Vec<MaxChannelAmount>> {
569 let mut client = self.get_node_client().await?;
570
571 let (last_node, max_hops) = match last_hop_hint {
575 Some(hop) => (hex::decode(&hop.src_node_id)?, max_hops - 1),
576 None => match payee_node_id.clone() {
577 Some(node_id) => (node_id, max_hops),
578 None => {
579 return Err(NodeError::RouteNotFound(
580 "No payee node id or last hop hints provided, cannot calculate max amount"
581 .to_string(),
582 ));
583 }
584 },
585 };
586
587 info!(
589 "calling get_route for peer {} to node {}, max_hops: {}",
590 hex::encode(via_peer_id.clone()),
591 hex::encode(last_node.clone()),
592 max_hops - 1
593 );
594 let req = GetrouteRequest {
595 id: last_node.clone(),
596 amount_msat: Some(Amount { msat: 0 }),
597 riskfactor: 0,
598 cltv: None,
599 fromid: Some(via_peer_id.clone()),
600 fuzzpercent: Some(0),
601 exclude: vec![],
602 maxhops: Some(max_hops - 1),
604 };
605 let route_result = with_connection_retry!(client.get_route(req.clone())).await;
606
607 if let Err(e) = route_result {
609 error!(
610 "Failed to get route for peer {}: {}",
611 hex::encode(via_peer_id.clone()),
612 e
613 );
614 return Ok(vec![]);
615 }
616
617 let route_response = route_result?.into_inner();
618 info!(
619 "max_sendable_amount: route response = {:?}",
620 route_response
621 .route
622 .iter()
623 .map(|r| format!(
624 "{{node_id: {}, channel: {}}}",
625 hex::encode(&r.id),
626 r.channel
627 ))
628 .collect::<Vec<_>>()
629 );
630
631 let opened_channels: Vec<cln::ListpeerchannelsChannels> = via_peer_channels
633 .iter()
634 .filter(|c| c.state() == ChanneldNormal)
635 .cloned()
636 .collect();
637
638 let mut max_per_channel = vec![];
639 for c in opened_channels {
640 let chan_id = c
641 .clone()
642 .channel_id
643 .ok_or(NodeError::generic("Empty channel id"))?;
644
645 let first_edge = PaymentPathEdge {
647 base_fee_msat: 0,
648 fee_per_millionth: 0,
649 node_id: via_peer_id.clone(),
650 short_channel_id: c.clone().short_channel_id.unwrap_or_default(),
651 channel_delay: 0,
652 };
653
654 let mut payment_path = self
656 .build_payment_path(&route_response.route, first_edge)
657 .await?;
658
659 if let Some(hint) = last_hop_hint {
661 payment_path.edges.extend(vec![PaymentPathEdge {
662 base_fee_msat: hint.fees_base_msat as u64,
663 fee_per_millionth: hint.fees_proportional_millionths as u64,
664 node_id: payee_node_id.clone().unwrap_or_default(),
665 short_channel_id: hint.short_channel_id.clone(),
666 channel_delay: hint.cltv_expiry_delta,
667 }])
668 }
669
670 info!(
671 "max_sendable_amount: route_hops = {:?}",
672 payment_path
673 .edges
674 .iter()
675 .map(|e| format!(
676 "{{node_id: {}, channel: {}}}",
677 hex::encode(&e.node_id),
678 e.short_channel_id
679 ))
680 .collect::<Vec<_>>()
681 );
682
683 let max_payment_amount =
685 payment_path.final_hop_amount(c.clone().spendable_msat.unwrap_or_default().msat);
686 max_per_channel.push(MaxChannelAmount {
687 channel_id: hex::encode(chan_id),
688 amount_msat: max_payment_amount,
689 path: payment_path,
690 });
691 }
692
693 Ok(max_per_channel)
694 }
695
696 async fn get_open_peer_channels_pb(
698 &self,
699 ) -> NodeResult<HashMap<Vec<u8>, cln::ListpeerchannelsChannels>> {
700 let mut client = self.get_node_client().await?;
701 let req = cln::ListpeerchannelsRequest::default();
703 let peer_channels = with_connection_retry!(client.list_peer_channels(req.clone()))
704 .await?
705 .into_inner();
706
707 let open_peer_channels: HashMap<Vec<u8>, cln::ListpeerchannelsChannels> = peer_channels
708 .channels
709 .into_iter()
710 .filter(|c| {
711 c.state == Some(cln::ChannelState::ChanneldNormal as i32) && c.peer_id.is_some()
712 })
713 .map(|c| (c.peer_id.clone().unwrap(), c))
714 .collect();
715 Ok(open_peer_channels)
716 }
717
718 async fn with_keep_alive<T, F>(&self, f: F) -> T
719 where
720 F: Future<Output = T>,
721 {
722 _ = self.inprogress_payments.fetch_add(1, Ordering::Relaxed);
723 let res = f.await;
724 _ = self.inprogress_payments.fetch_sub(1, Ordering::Relaxed);
725 res
726 }
727
728 async fn pull_transactions(
731 &self,
732 sync_state: &SyncState,
733 htlc_list: Vec<Htlc>,
734 ) -> NodeResult<(SyncState, Vec<Payment>)> {
735 let (receive_payments_res, send_payments_res) = join!(
736 self.pull_receive_payments(&sync_state.list_invoices_index),
737 self.pull_send_payments(&sync_state.send_pays_index, htlc_list),
738 );
739
740 let (receive_payments, list_invoices_index) = receive_payments_res?;
741 let (send_payments, send_pays_index) = send_payments_res?;
742 let mut new_state = sync_state.clone();
743 new_state.list_invoices_index = list_invoices_index;
744 new_state.send_pays_index = send_pays_index;
745
746 let mut payments: Vec<Payment> = Vec::new();
747 payments.extend(receive_payments);
748 payments.extend(send_payments);
749
750 Ok((new_state, payments))
751 }
752
753 async fn pull_receive_payments(
754 &self,
755 state: &SyncIndex,
756 ) -> NodeResult<(Vec<Payment>, SyncIndex)> {
757 let mut client = self.get_node_client().await?;
758
759 let req = cln::ListinvoicesRequest {
760 index: Some(ListinvoicesIndex::Created.into()),
761 start: Some(state.created),
762 ..Default::default()
763 };
764 let mut clone = client.clone();
765 let created_invoices = with_connection_retry!(clone.list_invoices(req.clone()))
766 .await?
767 .into_inner();
768 let req = cln::ListinvoicesRequest {
769 index: Some(ListinvoicesIndex::Updated.into()),
770 start: Some(state.updated),
771 ..Default::default()
772 };
773
774 let updated_invoices = with_connection_retry!(client.list_invoices(req.clone()))
775 .await?
776 .into_inner();
777 let mut new_state = state.clone();
778 if let Some(last) = created_invoices.invoices.last() {
779 new_state.created = last.created_index()
780 }
781 if let Some(last) = updated_invoices.invoices.last() {
782 new_state.updated = last.updated_index()
783 }
784
785 let received_payments: NodeResult<Vec<Payment>> = created_invoices
786 .invoices
787 .into_iter()
788 .chain(updated_invoices.invoices.into_iter())
789 .filter(|i| i.status() == ListinvoicesInvoicesStatus::Paid)
790 .map(TryInto::try_into)
791 .collect();
792
793 Ok((received_payments?, new_state))
794 }
795
796 async fn pull_send_payments(
797 &self,
798 state: &SyncIndex,
799 htlc_list: Vec<Htlc>,
800 ) -> NodeResult<(Vec<Payment>, SyncIndex)> {
801 let mut client = self.get_node_client().await?;
802 let req = cln::ListsendpaysRequest {
803 index: Some(ListsendpaysIndex::Created.into()),
804 start: Some(state.created),
805 ..Default::default()
806 };
807 let mut clone = client.clone();
808 let created_send_pays = with_connection_retry!(clone.list_send_pays(req.clone()))
809 .await?
810 .into_inner();
811 let req = cln::ListsendpaysRequest {
812 index: Some(ListsendpaysIndex::Updated.into()),
813 start: Some(state.updated),
814 ..Default::default()
815 };
816 let updated_send_pays = with_connection_retry!(client.list_send_pays(req.clone()))
817 .await?
818 .into_inner();
819
820 let mut new_state = state.clone();
821 if let Some(last) = created_send_pays.payments.last() {
822 new_state.created = last.created_index()
823 }
824 if let Some(last) = updated_send_pays.payments.last() {
825 new_state.updated = last.updated_index()
826 }
827
828 let hash_groups: HashMap<_, _> = created_send_pays
829 .payments
830 .iter()
831 .chain(updated_send_pays.payments.iter())
832 .map(|p| {
833 let mut key = hex::encode(&p.payment_hash);
834 key.push('|');
835 key.push_str(&p.groupid.to_string());
836 (key, (p.payment_hash.clone(), p.groupid.to_string()))
837 })
838 .collect();
839 let hash_group_values: Vec<_> = hash_groups.values().cloned().collect();
840
841 self.persister.insert_send_pays(
842 &created_send_pays
843 .payments
844 .into_iter()
845 .map(TryInto::try_into)
846 .collect::<Result<Vec<_>, _>>()?,
847 )?;
848 self.persister.insert_send_pays(
849 &updated_send_pays
850 .payments
851 .into_iter()
852 .map(TryInto::try_into)
853 .collect::<Result<Vec<_>, _>>()?,
854 )?;
855
856 let send_pays = self.persister.list_send_pays(&hash_group_values)?;
860
861 let mut outbound_payments: HashMap<String, SendPayAgg> = HashMap::new();
865 for send_pay in send_pays {
866 let mut key = hex::encode(&send_pay.payment_hash);
867 key.push('|');
868 key.push_str(&send_pay.groupid);
869 let payment = outbound_payments.entry(key).or_insert(SendPayAgg {
870 state: 0,
871 created_at: send_pay.created_at,
872 payment_hash: send_pay.payment_hash,
873 bolt11: None,
874 destination: None,
875 label: None,
876 description: None,
877 preimage: None,
878 amount_sent: 0,
879 amount: Some(0),
880 num_nonfailed_parts: 0,
881 });
882 if payment.bolt11.is_none() {
883 payment.bolt11 = send_pay.bolt11;
884 }
885 if payment.destination.is_none() {
886 payment.destination = send_pay.destination;
887 }
888 if payment.description.is_none() {
889 payment.description = send_pay.description;
890 }
891 if payment.label.is_none() {
892 payment.label = send_pay.label;
893 }
894 if payment.preimage.is_none() {
895 payment.preimage = send_pay.payment_preimage;
896 }
897 if send_pay.created_at < payment.created_at {
898 payment.created_at = send_pay.created_at;
899 }
900
901 match send_pay.status {
902 SendPayStatus::Pending => {
903 add_amount_sent(payment, send_pay.amount_sent_msat, send_pay.amount_msat);
904 payment.num_nonfailed_parts += 1;
905 payment.state |= PAYMENT_STATE_PENDING;
906 }
907 SendPayStatus::Failed => {
908 payment.state |= PAYMENT_STATE_FAILED;
909 }
910 SendPayStatus::Complete => {
911 add_amount_sent(payment, send_pay.amount_sent_msat, send_pay.amount_msat);
912 payment.num_nonfailed_parts += 1;
913 payment.state |= PAYMENT_STATE_COMPLETE;
914 }
915 }
916 }
917
918 let outbound_payments: Vec<Payment> = outbound_payments
919 .into_values()
920 .map(TryInto::try_into)
921 .collect::<Result<Vec<_>, _>>()?;
922 let outbound_payments = update_payment_expirations(outbound_payments, htlc_list)?;
923 Ok((outbound_payments, new_state))
924 }
925
926 async fn wait_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<()> {
927 let deadline =
928 Instant::now()
929 .checked_add(Duration::from_secs(20))
930 .ok_or(NodeError::generic(
931 "Failed to set channel establishment deadline",
932 ))?;
933
934 while Instant::now().le(&deadline) && !self.poll_channel_reestablished(path).await? {
935 tokio::time::sleep(Duration::from_millis(50)).await
936 }
937
938 Ok(())
939 }
940
941 async fn poll_channel_reestablished(&self, path: &PaymentPath) -> NodeResult<bool> {
942 let edge = match path.edges.first() {
943 Some(edge) => edge,
944 None => return Err(NodeError::generic("Channel not found")),
945 };
946 let mut client = self.get_node_client().await?;
947 let req = cln::ListpeerchannelsRequest {
948 id: Some(edge.node_id.clone()),
949 };
950 let res = with_connection_retry!(client.list_peer_channels(req.clone()))
951 .await?
952 .into_inner();
953 let channel = match res.channels.iter().find(|c| {
954 match (
955 c.alias.as_ref().and_then(|a| a.local.as_ref()),
956 c.short_channel_id.as_ref(),
957 ) {
958 (Some(alias), Some(short_channel_id)) => {
959 *alias == edge.short_channel_id || *short_channel_id == edge.short_channel_id
960 }
961 (Some(alias), None) => *alias == edge.short_channel_id,
962 (None, Some(short_channel_id)) => *short_channel_id == edge.short_channel_id,
963 (None, None) => false,
964 }
965 }) {
966 Some(channel) => channel,
967 None => return Err(NodeError::generic("Channel not found")),
968 };
969
970 if let Some(peer_connected) = channel.peer_connected {
971 if !peer_connected {
972 return Ok(false);
973 }
974 }
975
976 if !channel
977 .status
978 .iter()
979 .any(|s| s.contains("Channel ready") || s.contains("Reconnected, and reestablished"))
980 {
981 return Ok(false);
982 }
983
984 Ok(true)
985 }
986}
987
988fn add_amount_sent(
989 agg: &mut SendPayAgg,
990 send_pay_amount_sent_msat: Option<u64>,
991 send_pay_amount_msat: Option<u64>,
992) {
993 if let Some(amount_sent_msat) = send_pay_amount_sent_msat {
994 agg.amount_sent += amount_sent_msat;
995 }
996
997 let amount_msat = match send_pay_amount_msat {
998 Some(amount_msat) => amount_msat,
999 None => {
1000 agg.amount = None;
1001 return;
1002 }
1003 };
1004
1005 if let Some(amount) = agg.amount {
1006 agg.amount = Some(amount + amount_msat);
1007 }
1008}
1009
1010#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1011struct SyncIndex {
1012 pub created: u64,
1013 pub updated: u64,
1014}
1015
1016#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1017struct SyncState {
1018 pub send_pays_index: SyncIndex,
1019 pub list_invoices_index: SyncIndex,
1020}
1021
1022#[tonic::async_trait]
1023impl NodeAPI for Greenlight {
1024 async fn node_credentials(&self) -> NodeResult<Option<NodeCredentials>> {
1025 Ok(Self::get_node_credentials(
1026 self.sdk_config.network,
1027 &self.get_signer().await,
1028 self.persister.clone(),
1029 )?
1030 .map(|credentials| NodeCredentials::Greenlight {
1031 credentials: GreenlightDeviceCredentials {
1032 device: credentials.to_bytes(),
1033 },
1034 }))
1035 }
1036
1037 async fn configure_node(&self, close_to_address: Option<String>) -> NodeResult<()> {
1038 match close_to_address {
1039 Some(close_to_addr) => {
1040 let mut client = self.get_client().await?;
1041 let req = gl_client::pb::GlConfig { close_to_addr };
1042 with_connection_retry!(client.configure(req.clone()))
1043 .await
1044 .map_err(|e| NodeError::Generic(format!("Unable to set node config: {}", e)))?;
1045 }
1046 None => {
1047 let mut client = self.get_node_client().await?;
1048 let req = cln::DeldatastoreRequest {
1049 key: vec!["glconf".to_string(), "request".to_string()],
1050 generation: None,
1051 };
1052 with_connection_retry!(client.del_datastore(req.clone()))
1053 .await
1054 .map_err(|e| {
1055 NodeError::Generic(format!("Unable to delete node config: {}", e))
1056 })?;
1057 }
1058 }
1059 Ok(())
1060 }
1061
1062 async fn create_invoice(&self, request: CreateInvoiceRequest) -> NodeResult<String> {
1063 let mut client = self.get_node_client().await?;
1064 let label = serde_json::to_string(&InvoiceLabel {
1065 unix_milli: SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis(),
1066 payer_amount_msat: request.payer_amount_msat,
1067 })?;
1068 let cln_request = cln::InvoiceRequest {
1069 amount_msat: Some(cln::AmountOrAny {
1070 value: Some(cln::amount_or_any::Value::Amount(cln::Amount {
1071 msat: request.amount_msat,
1072 })),
1073 }),
1074 label,
1075 description: request.description,
1076 preimage: request.preimage,
1077 deschashonly: request.use_description_hash,
1078 expiry: request.expiry.map(|e| e as u64),
1079 fallbacks: vec![],
1080 cltv: request.cltv,
1081 };
1082
1083 let res = with_connection_retry!(client.invoice(cln_request.clone()))
1084 .await?
1085 .into_inner();
1086 Ok(res.bolt11)
1087 }
1088
1089 async fn delete_invoice(&self, bolt11: String) -> NodeResult<()> {
1090 let mut client = self.get_node_client().await?;
1091 let invoice_request = cln::ListinvoicesRequest {
1092 invstring: Some(bolt11),
1093 ..Default::default()
1094 };
1095 let invoice_result = with_connection_retry!(client.list_invoices(invoice_request.clone()))
1096 .await?
1097 .into_inner();
1098 let invoice_result = invoice_result.invoices.first();
1099 let result = match invoice_result {
1100 Some(result) => result,
1101 None => return Ok(()),
1102 };
1103
1104 let status = match result.status() {
1105 ListinvoicesInvoicesStatus::Unpaid => DelinvoiceStatus::Unpaid,
1106 ListinvoicesInvoicesStatus::Paid => return Err(NodeError::InvoiceAlreadyPaid),
1107 ListinvoicesInvoicesStatus::Expired => DelinvoiceStatus::Expired,
1108 };
1109 with_connection_retry!(client.del_invoice(DelinvoiceRequest {
1110 label: result.label.clone(),
1111 status: status.into(),
1112 desconly: Some(false),
1113 }))
1114 .await?;
1115 Ok(())
1116 }
1117
1118 async fn fetch_bolt11(&self, payment_hash: Vec<u8>) -> NodeResult<Option<FetchBolt11Result>> {
1119 let mut client = self.get_node_client().await?;
1120 let request = cln::ListinvoicesRequest {
1121 payment_hash: Some(payment_hash),
1122 ..Default::default()
1123 };
1124
1125 let result = with_connection_retry!(client.list_invoices(request.clone()))
1126 .await?
1127 .into_inner()
1128 .invoices
1129 .first()
1130 .cloned()
1131 .and_then(|invoice| {
1132 invoice.bolt11.map(|bolt11| FetchBolt11Result {
1133 bolt11,
1134 payer_amount_msat: serde_json::from_str::<InvoiceLabel>(&invoice.label)
1135 .map(|label| label.payer_amount_msat)
1136 .ok()
1137 .flatten(),
1138 })
1139 });
1140
1141 Ok(result)
1142 }
1143
1144 async fn pull_changed(
1146 &self,
1147 sync_state: Option<Value>,
1148 match_local_balance: bool,
1149 ) -> NodeResult<SyncResponse> {
1150 let sync_state: SyncState = match sync_state {
1151 Some(sync_state) => serde_json::from_value(sync_state)?,
1152 None => SyncState::default(),
1153 };
1154
1155 let client = self.get_node_client().await?;
1156
1157 let mut client_clone1 = client.clone();
1159 let node_info_future =
1160 with_connection_retry!(client_clone1.getinfo(cln::GetinfoRequest::default()));
1161
1162 let funds_future = self.list_funds();
1164
1165 let mut client_clone2 = client.clone();
1167 let closed_channels_future = with_connection_retry!(
1168 client_clone2.list_closed_channels(cln::ListclosedchannelsRequest { id: None })
1169 );
1170
1171 let balance_future = Greenlight::fetch_channels_and_balance_with_retry(
1174 client.clone(),
1175 self.persister.clone(),
1176 match_local_balance,
1177 );
1178
1179 let (node_info_res, funds_res, closed_channels_res, balance_res) = tokio::join!(
1180 node_info_future,
1181 funds_future,
1182 closed_channels_future,
1183 balance_future
1184 );
1185
1186 let node_info = node_info_res?.into_inner();
1187 let funds = funds_res?;
1188 let closed_channels = closed_channels_res?.into_inner().closedchannels;
1189 let (all_channels, opened_channels, connected_peers, channels_balance) = balance_res?;
1190 let forgotten_closed_channels: NodeResult<Vec<Channel>> = closed_channels
1191 .into_iter()
1192 .filter(|cc| {
1193 all_channels
1194 .iter()
1195 .all(|ac| ac.funding_txid != Some(cc.funding_txid.clone()))
1196 })
1197 .map(TryInto::try_into)
1198 .collect();
1199 info!("forgotten_closed_channels {:?}", forgotten_closed_channels);
1200
1201 let mut all_channel_models: Vec<Channel> =
1202 all_channels.clone().into_iter().map(|c| c.into()).collect();
1203 all_channel_models.extend(forgotten_closed_channels?);
1204
1205 let onchain_balance = self.on_chain_balance(&funds).await?;
1207 let pending_onchain_balance = self.pending_onchain_balance(&all_channels).await?;
1208 let utxos: Vec<UnspentTransactionOutput> = self.utxos(funds).await?;
1209
1210 let mut max_payable: u64 = 0;
1212 let mut max_receivable_single_channel: u64 = 0;
1213 let mut total_inbound_liquidity_msats: u64 = 0;
1214 opened_channels.iter().try_for_each(|c| -> Result<()> {
1215 max_payable += c
1216 .spendable_msat
1217 .as_ref()
1218 .map(|a| a.msat)
1219 .unwrap_or_default();
1220 let receivable_amount = c
1221 .receivable_msat
1222 .as_ref()
1223 .map(|a| a.msat)
1224 .unwrap_or_default();
1225 total_inbound_liquidity_msats += receivable_amount;
1226 if receivable_amount > max_receivable_single_channel {
1227 max_receivable_single_channel = receivable_amount;
1228 }
1229 Ok(())
1230 })?;
1231
1232 let max_allowed_to_receive_msats =
1233 MAX_INBOUND_LIQUIDITY_MSAT.saturating_sub(channels_balance);
1234 let node_pubkey = hex::encode(node_info.id);
1235 let node_state = NodeState {
1237 id: node_pubkey.clone(),
1238 block_height: node_info.blockheight,
1239 channels_balance_msat: channels_balance,
1240 onchain_balance_msat: onchain_balance,
1241 pending_onchain_balance_msat: pending_onchain_balance,
1242 utxos,
1243 max_payable_msat: max_payable,
1244 max_receivable_msat: max_allowed_to_receive_msats,
1245 max_single_payment_amount_msat: MAX_PAYMENT_AMOUNT_MSAT,
1246 max_chan_reserve_msats: channels_balance - min(max_payable, channels_balance),
1247 connected_peers,
1248 max_receivable_single_payment_amount_msat: max_receivable_single_channel,
1249 total_inbound_liquidity_msats,
1250 };
1251 let mut htlc_list: Vec<Htlc> = Vec::new();
1252 for channel in all_channel_models.clone() {
1253 htlc_list.extend(channel.htlcs);
1254 }
1255
1256 let (new_sync_state, payments) = self.pull_transactions(&sync_state, htlc_list).await?;
1257
1258 Ok(SyncResponse {
1259 sync_state: serde_json::to_value(new_sync_state)?,
1260 node_state,
1261 payments,
1262 channels: all_channel_models,
1263 })
1264 }
1265
1266 async fn send_pay(&self, bolt11: String, max_hops: u32) -> NodeResult<PaymentResponse> {
1267 let invoice = parse_invoice(&bolt11)?;
1268 let last_hop = invoice.routing_hints.first().and_then(|rh| rh.hops.first());
1269 let mut client = self.get_node_client().await?;
1270
1271 validate_network(invoice.clone(), self.sdk_config.network)?;
1273
1274 let mut max_amount_per_channel = self
1276 .max_sendable_amount(Some(hex::decode(invoice.payee_pubkey)?), max_hops, last_hop)
1277 .await?;
1278 info!("send_pay: routes: {:?}", max_amount_per_channel);
1279
1280 let total_msat: u64 = max_amount_per_channel.iter().map(|m| m.amount_msat).sum();
1282
1283 max_amount_per_channel.sort_by_key(|m| Reverse(m.amount_msat));
1286
1287 let amount_to_pay_msat = match invoice.amount_msat {
1288 Some(amount) => Ok(amount),
1289 None => Err(NodeError::generic("Invoice has no amount")),
1290 }?;
1291
1292 if amount_to_pay_msat > total_msat {
1293 return Err(NodeError::RouteNotFound(format!(
1294 "Amount too high, max amount is {} msat",
1295 total_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<Streaming<gl_client::signer::model::greenlight::IncomingPayment>> {
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(stream)
1764 }
1765
1766 async fn stream_log_messages(
1767 &self,
1768 ) -> NodeResult<Streaming<gl_client::signer::model::greenlight::LogEntry>> {
1769 let mut client = self.get_client().await?;
1770 let req = gl_client::signer::model::greenlight::StreamLogRequest {};
1771 let stream = with_connection_retry!(client.stream_log(req.clone()))
1772 .await?
1773 .into_inner();
1774 Ok(stream)
1775 }
1776
1777 async fn static_backup(&self) -> NodeResult<Vec<String>> {
1778 let mut client = self.get_node_client().await?;
1779 let req = cln::StaticbackupRequest {};
1780 let res = with_connection_retry!(client.static_backup(req.clone()))
1781 .await?
1782 .into_inner();
1783 let hex_vec: Vec<String> = res.scb.into_iter().map(hex::encode).collect();
1784 Ok(hex_vec)
1785 }
1786
1787 async fn generate_diagnostic_data(&self) -> NodeResult<Value> {
1788 let all_commands = vec![
1789 NodeCommand::GetInfo.to_string(),
1790 NodeCommand::ListPeerChannels.to_string(),
1791 NodeCommand::ListFunds.to_string(),
1792 NodeCommand::ListPayments.to_string(),
1793 NodeCommand::ListInvoices.to_string(),
1794 ];
1795
1796 let mut result = Map::new();
1797 for command in all_commands {
1798 let command_name = command.clone();
1799 let res = self
1800 .execute_command(command)
1801 .await
1802 .unwrap_or_else(|e| json!({ "error": e.to_string() }));
1803 result.insert(command_name, res);
1804 }
1805 Ok(Value::Object(result))
1806 }
1807
1808 async fn execute_command(&self, command: String) -> NodeResult<Value> {
1809 let node_cmd =
1810 NodeCommand::from_str(&command).map_err(|_| anyhow!("Command not found: {command}"))?;
1811
1812 let mut client = self.get_node_client().await?;
1813 match node_cmd {
1814 NodeCommand::ListPeers => {
1815 let req = cln::ListpeersRequest::default();
1816 let resp = with_connection_retry!(client.list_peers(req.clone()))
1817 .await?
1818 .into_inner();
1819
1820 Ok(crate::serializer::value::to_value(&resp)?)
1821 }
1822 NodeCommand::ListPeerChannels => {
1823 let req = cln::ListpeerchannelsRequest::default();
1824 let resp = with_connection_retry!(client.list_peer_channels(req.clone()))
1825 .await?
1826 .into_inner();
1827 Ok(crate::serializer::value::to_value(&resp)?)
1828 }
1829 NodeCommand::ListFunds => {
1830 let req = cln::ListfundsRequest::default();
1831 let resp = with_connection_retry!(client.list_funds(req.clone()))
1832 .await?
1833 .into_inner();
1834 Ok(crate::serializer::value::to_value(&resp)?)
1835 }
1836 NodeCommand::ListPayments => {
1837 let req = cln::ListpaysRequest::default();
1838 let resp = with_connection_retry!(client.list_pays(req.clone()))
1839 .await?
1840 .into_inner();
1841 Ok(crate::serializer::value::to_value(&resp)?)
1842 }
1843 NodeCommand::ListInvoices => {
1844 let req = cln::ListinvoicesRequest::default();
1845 let resp = with_connection_retry!(client.list_invoices(req.clone()))
1846 .await?
1847 .into_inner();
1848
1849 Ok(crate::serializer::value::to_value(&resp)?)
1850 }
1851 NodeCommand::CloseAllChannels => {
1852 let req = cln::ListpeersRequest::default();
1853 let resp = with_connection_retry!(client.list_peers(req.clone()))
1854 .await?
1855 .into_inner();
1856 for p in resp.peers {
1857 self.close_peer_channels(hex::encode(p.id)).await?;
1858 }
1859
1860 Ok(Value::String("All channels were closed".to_string()))
1861 }
1862 NodeCommand::GetInfo => {
1863 let req = cln::GetinfoRequest::default();
1864 let resp = with_connection_retry!(client.getinfo(req.clone()))
1865 .await?
1866 .into_inner();
1867 Ok(crate::serializer::value::to_value(&resp)?)
1868 }
1869 NodeCommand::Stop => {
1870 let req = cln::StopRequest::default();
1871 let resp = with_connection_retry!(client.stop(req.clone()))
1872 .await?
1873 .into_inner();
1874 Ok(crate::serializer::value::to_value(&resp)?)
1875 }
1876 }
1877 }
1878
1879 async fn max_sendable_amount<'a>(
1880 &self,
1881 payee_node_id: Option<Vec<u8>>,
1882 max_hops: u32,
1883 last_hop_hint: Option<&'a RouteHintHop>,
1884 ) -> NodeResult<Vec<MaxChannelAmount>> {
1885 let mut client = self.get_node_client().await?;
1886
1887 let mut peers = HashMap::new();
1888 let req = cln::ListpeerchannelsRequest::default();
1889 with_connection_retry!(client.list_peer_channels(req.clone()))
1890 .await?
1891 .into_inner()
1892 .channels
1893 .into_iter()
1894 .for_each(|channel| {
1895 peers
1896 .entry(channel.peer_id().to_vec())
1897 .or_insert(Vec::new())
1898 .push(channel)
1899 });
1900
1901 let mut max_channel_amounts = vec![];
1902 for (peer, channels) in peers {
1903 let max_amounts_for_peer = self
1904 .max_sendable_amount_from_peer(
1905 peer,
1906 channels,
1907 payee_node_id.clone(),
1908 max_hops,
1909 last_hop_hint,
1910 )
1911 .await?;
1912 max_channel_amounts.extend_from_slice(max_amounts_for_peer.as_slice());
1913 }
1914 Ok(max_channel_amounts)
1915 }
1916
1917 async fn derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey> {
1918 Self::derive_bip32_key(self.sdk_config.network, &self.get_signer().await, path)
1919 }
1920
1921 async fn legacy_derive_bip32_key(&self, path: Vec<ChildNumber>) -> NodeResult<ExtendedPrivKey> {
1922 Self::legacy_derive_bip32_key(self.sdk_config.network, &self.get_signer().await, path)
1923 }
1924
1925 async fn stream_custom_messages(
1926 &self,
1927 ) -> NodeResult<Pin<Box<dyn Stream<Item = Result<CustomMessage>> + Send>>> {
1928 let stream = {
1929 let mut client = match self.get_client().await {
1930 Ok(c) => Ok(c),
1931 Err(e) => Err(anyhow!("{}", e)),
1932 }?;
1933 let req = gl_client::signer::model::greenlight::StreamCustommsgRequest {};
1934 match with_connection_retry!(client.stream_custommsg(req.clone())).await {
1935 Ok(s) => Ok(s),
1936 Err(e) => Err(anyhow!("{}", e)),
1937 }?
1938 .into_inner()
1939 };
1940
1941 Ok(Box::pin(stream.filter_map(|msg| {
1942 let msg = match msg {
1943 Ok(msg) => msg,
1944 Err(e) => return Some(Err(anyhow!("failed to receive message: {}", e))),
1945 };
1946
1947 if msg.payload.len() < 2 {
1948 debug!(
1949 "received too short custom message payload: {:?}",
1950 &msg.payload
1951 );
1952 return None;
1953 }
1954
1955 let msg_type = u16::from_be_bytes([msg.payload[0], msg.payload[1]]);
1956
1957 Some(Ok(CustomMessage {
1958 peer_id: msg.peer_id,
1959 message_type: msg_type,
1960 payload: msg.payload[2..].to_vec(),
1961 }))
1962 })))
1963 }
1964
1965 async fn send_custom_message(&self, message: CustomMessage) -> NodeResult<()> {
1966 let mut client = self.get_node_client().await?;
1967
1968 let mut msg = message.message_type.to_be_bytes().to_vec();
1969 msg.extend(message.payload);
1970 let req = cln::SendcustommsgRequest {
1971 msg,
1972 node_id: message.peer_id,
1973 };
1974 let resp = with_connection_retry!(client.send_custom_msg(req.clone()))
1975 .await?
1976 .into_inner();
1977 debug!("send_custom_message returned status {:?}", resp.status);
1978 Ok(())
1979 }
1980
1981 async fn get_routing_hints(
1983 &self,
1984 lsp_info: &LspInformation,
1985 ) -> NodeResult<(Vec<RouteHint>, bool)> {
1986 let mut client = self.get_node_client().await?;
1987
1988 let open_peer_channels = self.get_open_peer_channels_pb().await?;
1989 let (open_peer_channels_private, open_peer_channels_public): (
1990 HashMap<Vec<u8>, ListpeerchannelsChannels>,
1991 HashMap<Vec<u8>, ListpeerchannelsChannels>,
1992 ) = open_peer_channels
1993 .into_iter()
1994 .partition(|(_, c)| c.private.unwrap_or_default());
1995 let has_public_channel = !open_peer_channels_public.is_empty();
1996
1997 let mut hints: Vec<RouteHint> = vec![];
1998
1999 let pubkey = self
2001 .persister
2002 .get_node_state()?
2003 .map(|n| n.id)
2004 .ok_or(NodeError::generic("Node info not found"))?;
2005 let req = cln::ListchannelsRequest {
2006 destination: Some(hex::decode(pubkey)?),
2007 ..Default::default()
2008 };
2009 let channels: HashMap<Vec<u8>, cln::ListchannelsChannels> =
2010 with_connection_retry!(client.list_channels(req.clone()))
2011 .await?
2012 .into_inner()
2013 .channels
2014 .into_iter()
2015 .map(|c| (c.source.clone(), c))
2016 .collect();
2017
2018 for (peer_id, peer_channel) in open_peer_channels_private {
2020 let peer_id_str = hex::encode(&peer_id);
2021 let optional_channel_id = peer_channel
2022 .alias
2023 .and_then(|a| a.remote)
2024 .or(peer_channel.short_channel_id);
2025
2026 if let Some(channel_id) = optional_channel_id {
2027 let maybe_policy = match channels.get(&peer_id) {
2029 Some(channel) => Some((
2030 channel.base_fee_millisatoshi,
2031 channel.fee_per_millionth,
2032 channel.delay,
2033 )),
2034 None if peer_id_str == lsp_info.pubkey => Some((
2035 lsp_info.base_fee_msat as u32,
2036 (lsp_info.fee_rate * 1000000.0) as u32,
2037 lsp_info.time_lock_delta,
2038 )),
2039 _ => None,
2040 };
2041 match maybe_policy {
2042 Some((fees_base_msat, fees_proportional_millionths, cltv_delta)) => {
2043 debug!(
2044 "For peer {}: remote base {} proportional {} cltv_delta {}",
2045 peer_id_str, fees_base_msat, fees_proportional_millionths, cltv_delta,
2046 );
2047 let hint = RouteHint {
2048 hops: vec![RouteHintHop {
2049 src_node_id: peer_id_str,
2050 short_channel_id: channel_id,
2051 fees_base_msat,
2052 fees_proportional_millionths,
2053 cltv_expiry_delta: cltv_delta as u64,
2054 htlc_minimum_msat: Some(
2055 peer_channel
2056 .minimum_htlc_in_msat
2057 .clone()
2058 .unwrap_or_default()
2059 .msat,
2060 ),
2061 htlc_maximum_msat: None,
2062 }],
2063 };
2064 info!("Generating hint hop as routing hint: {:?}", hint);
2065 hints.push(hint);
2066 }
2067 _ => debug!("No source channel found for peer: {:?}", peer_id_str),
2068 };
2069 }
2070 }
2071 Ok((hints, has_public_channel))
2072 }
2073
2074 async fn get_open_peers(&self) -> NodeResult<HashSet<Vec<u8>>> {
2075 let open_peer_channels = self.get_open_peer_channels_pb().await?;
2076 let open_peers: HashSet<Vec<u8>> = open_peer_channels.into_keys().collect();
2077 Ok(open_peers)
2078 }
2079}
2080
2081#[derive(Clone, PartialEq, Eq, Debug, EnumString, Display, Deserialize, Serialize)]
2082enum NodeCommand {
2083 #[strum(serialize = "closeallchannels")]
2085 CloseAllChannels,
2086
2087 #[strum(serialize = "getinfo")]
2089 GetInfo,
2090
2091 #[strum(serialize = "listfunds")]
2093 ListFunds,
2094
2095 #[strum(serialize = "listinvoices")]
2097 ListInvoices,
2098
2099 #[strum(serialize = "listpayments")]
2101 ListPayments,
2102
2103 #[strum(serialize = "listpeers")]
2105 ListPeers,
2106
2107 #[strum(serialize = "listpeerchannels")]
2109 ListPeerChannels,
2110
2111 #[strum(serialize = "stop")]
2117 Stop,
2118}
2119
2120struct SendPayAgg {
2121 state: u8,
2122 created_at: u64,
2123 payment_hash: Vec<u8>,
2124 bolt11: Option<String>,
2125 destination: Option<Vec<u8>>,
2126 label: Option<String>,
2127 description: Option<String>,
2128 preimage: Option<Vec<u8>>,
2129 amount_sent: u64,
2130 amount: Option<u64>,
2131 num_nonfailed_parts: u64,
2132}
2133
2134fn update_payment_expirations(
2135 payments: Vec<Payment>,
2136 htlc_list: Vec<Htlc>,
2137) -> NodeResult<Vec<Payment>> {
2138 if htlc_list.is_empty() {
2139 return Ok(payments);
2140 }
2141
2142 let mut payments_res: Vec<Payment> = Vec::new();
2143 for mut payment in payments {
2144 if payment.status == PaymentStatus::Pending {
2145 let new_data = payment.clone().details;
2146 if let PaymentDetails::Ln { data } = new_data {
2147 for htlc in &htlc_list {
2148 let payment_hash = hex::encode(htlc.clone().payment_hash);
2149 if payment_hash == data.payment_hash
2150 && data.pending_expiration_block < Some(htlc.expiry)
2151 {
2152 payment.details.add_pending_expiration_block(htlc.clone())
2153 }
2154 }
2155 }
2156 }
2157 payments_res.push(payment);
2158 }
2159 info!("pending htlc payments {:?}", payments_res);
2160 Ok(payments_res)
2161}
2162
2163impl TryFrom<ListsendpaysPayments> for SendPay {
2164 type Error = NodeError;
2165
2166 fn try_from(value: ListsendpaysPayments) -> std::result::Result<Self, Self::Error> {
2167 Ok(SendPay {
2168 created_index: value
2169 .created_index
2170 .ok_or(NodeError::generic("missing created index"))?,
2171 updated_index: value.updated_index,
2172 groupid: value.groupid.to_string(),
2173 partid: value.partid,
2174 payment_hash: value.payment_hash,
2175 status: value.status.try_into()?,
2176 amount_msat: value.amount_msat.map(|a| a.msat),
2177 destination: value.destination,
2178 created_at: value.created_at,
2179 amount_sent_msat: value.amount_sent_msat.map(|a| a.msat),
2180 label: value.label,
2181 bolt11: value.bolt11,
2182 description: value.description,
2183 bolt12: value.bolt12,
2184 payment_preimage: value.payment_preimage,
2185 erroronion: value.erroronion,
2186 })
2187 }
2188}
2189
2190impl TryFrom<i32> for SendPayStatus {
2191 type Error = NodeError;
2192
2193 fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
2194 match value {
2195 0 => Ok(Self::Pending),
2196 1 => Ok(Self::Failed),
2197 2 => Ok(Self::Complete),
2198 _ => Err(NodeError::generic("invalid send_pay status")),
2199 }
2200 }
2201}
2202
2203impl TryFrom<SendPayAgg> for Payment {
2204 type Error = NodeError;
2205
2206 fn try_from(value: SendPayAgg) -> std::result::Result<Self, Self::Error> {
2207 let ln_invoice = value
2208 .bolt11
2209 .as_ref()
2210 .ok_or(InvoiceError::generic("No bolt11 invoice"))
2211 .and_then(|b| parse_invoice(b));
2212
2213 let (payment_amount, client_label) =
2216 serde_json::from_str::<PaymentLabel>(&value.label.clone().unwrap_or_default())
2217 .ok()
2218 .and_then(|label| {
2219 label
2220 .trampoline
2221 .then_some((label.amount_msat, label.client_label))
2222 })
2223 .unwrap_or((value.amount.unwrap_or_default(), value.label));
2224 let fee_msat = value.amount_sent.saturating_sub(payment_amount);
2225 let status = if value.state & PAYMENT_STATE_COMPLETE > 0 {
2226 PaymentStatus::Complete
2227 } else if value.state & PAYMENT_STATE_PENDING > 0 {
2228 PaymentStatus::Pending
2229 } else {
2230 PaymentStatus::Failed
2231 };
2232 Ok(Self {
2233 id: hex::encode(&value.payment_hash),
2234 payment_type: PaymentType::Sent,
2235 payment_time: value.created_at as i64,
2236 amount_msat: match status {
2237 PaymentStatus::Complete => payment_amount,
2238 _ => ln_invoice
2239 .as_ref()
2240 .map_or(0, |i| i.amount_msat.unwrap_or_default()),
2241 },
2242 fee_msat,
2243 status,
2244 error: None,
2245 description: ln_invoice
2246 .as_ref()
2247 .map(|i| i.description.clone())
2248 .unwrap_or_default(),
2249 details: PaymentDetails::Ln {
2250 data: LnPaymentDetails {
2251 payment_hash: hex::encode(&value.payment_hash),
2252 label: client_label.unwrap_or_default(),
2253 destination_pubkey: ln_invoice.map_or(
2254 value.destination.map(hex::encode).unwrap_or_default(),
2255 |i| i.payee_pubkey,
2256 ),
2257 payment_preimage: value.preimage.map(hex::encode).unwrap_or_default(),
2258 keysend: value.bolt11.is_none(),
2259 bolt11: value.bolt11.unwrap_or_default(),
2260 open_channel_bolt11: None,
2261 lnurl_success_action: None,
2262 lnurl_pay_domain: None,
2263 lnurl_pay_comment: None,
2264 ln_address: None,
2265 lnurl_metadata: None,
2266 lnurl_withdraw_endpoint: None,
2267 swap_info: None,
2268 reverse_swap_info: None,
2269 pending_expiration_block: None,
2270 },
2271 },
2272 metadata: None,
2273 })
2274 }
2275}
2276
2277impl TryFrom<OffChainPayment> for Payment {
2279 type Error = NodeError;
2280
2281 fn try_from(p: OffChainPayment) -> std::result::Result<Self, Self::Error> {
2282 let ln_invoice = parse_invoice(&p.bolt11)?;
2283 Ok(Payment {
2284 id: hex::encode(p.payment_hash.clone()),
2285 payment_type: PaymentType::Received,
2286 payment_time: SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64,
2287 amount_msat: amount_to_msat(&p.amount.unwrap_or_default()),
2288 fee_msat: 0,
2289 status: PaymentStatus::Complete,
2290 error: None,
2291 description: ln_invoice.description,
2292 details: PaymentDetails::Ln {
2293 data: LnPaymentDetails {
2294 payment_hash: hex::encode(p.payment_hash),
2295 label: p.label,
2296 destination_pubkey: ln_invoice.payee_pubkey,
2297 payment_preimage: hex::encode(p.preimage),
2298 keysend: false,
2299 bolt11: p.bolt11,
2300 lnurl_success_action: None, lnurl_pay_domain: None, lnurl_pay_comment: None, lnurl_metadata: None, ln_address: None,
2305 lnurl_withdraw_endpoint: None,
2306 swap_info: None,
2307 reverse_swap_info: None,
2308 pending_expiration_block: None,
2309 open_channel_bolt11: None,
2310 },
2311 },
2312 metadata: None,
2313 })
2314 }
2315}
2316
2317impl TryFrom<cln::ListinvoicesInvoices> for Payment {
2319 type Error = NodeError;
2320
2321 fn try_from(invoice: cln::ListinvoicesInvoices) -> std::result::Result<Self, Self::Error> {
2322 let ln_invoice = invoice
2323 .bolt11
2324 .as_ref()
2325 .ok_or(InvoiceError::generic("No bolt11 invoice"))
2326 .and_then(|b| parse_invoice(b))?;
2327 Ok(Payment {
2328 id: hex::encode(invoice.payment_hash.clone()),
2329 payment_type: PaymentType::Received,
2330 payment_time: invoice.paid_at.map(|i| i as i64).unwrap_or_default(),
2331 amount_msat: invoice
2332 .amount_received_msat
2333 .or(invoice.amount_msat)
2334 .map(|a| a.msat)
2335 .unwrap_or_default(),
2336 fee_msat: 0,
2337 status: PaymentStatus::Complete,
2338 error: None,
2339 description: ln_invoice.description,
2340 details: PaymentDetails::Ln {
2341 data: LnPaymentDetails {
2342 payment_hash: hex::encode(invoice.payment_hash),
2343 label: invoice.label,
2344 destination_pubkey: ln_invoice.payee_pubkey,
2345 payment_preimage: invoice
2346 .payment_preimage
2347 .map(hex::encode)
2348 .unwrap_or_default(),
2349 keysend: false,
2350 bolt11: invoice.bolt11.unwrap_or_default(),
2351 lnurl_success_action: None, lnurl_pay_domain: None, lnurl_pay_comment: None, lnurl_metadata: None, ln_address: None,
2356 lnurl_withdraw_endpoint: None,
2357 swap_info: None,
2358 reverse_swap_info: None,
2359 pending_expiration_block: None,
2360 open_channel_bolt11: None,
2361 },
2362 },
2363 metadata: None,
2364 })
2365 }
2366}
2367
2368impl From<ListpaysPaysStatus> for PaymentStatus {
2369 fn from(value: ListpaysPaysStatus) -> Self {
2370 match value {
2371 ListpaysPaysStatus::Pending => PaymentStatus::Pending,
2372 ListpaysPaysStatus::Complete => PaymentStatus::Complete,
2373 ListpaysPaysStatus::Failed => PaymentStatus::Failed,
2374 }
2375 }
2376}
2377
2378impl TryFrom<cln::ListpaysPays> for Payment {
2379 type Error = NodeError;
2380
2381 fn try_from(payment: cln::ListpaysPays) -> NodeResult<Self, Self::Error> {
2382 let ln_invoice = payment
2383 .bolt11
2384 .as_ref()
2385 .ok_or(InvoiceError::generic("No bolt11 invoice"))
2386 .and_then(|b| parse_invoice(b));
2387 let payment_amount_sent = payment
2388 .amount_sent_msat
2389 .clone()
2390 .map(|a| a.msat)
2391 .unwrap_or_default();
2392
2393 let (payment_amount, client_label) = serde_json::from_str::<PaymentLabel>(payment.label())
2396 .ok()
2397 .and_then(|label| {
2398 label
2399 .trampoline
2400 .then_some((label.amount_msat, label.client_label))
2401 })
2402 .unwrap_or((
2403 payment
2404 .amount_msat
2405 .clone()
2406 .map(|a| a.msat)
2407 .unwrap_or_default(),
2408 payment.label.clone(),
2409 ));
2410 let status = payment.status().into();
2411
2412 Ok(Payment {
2413 id: hex::encode(payment.payment_hash.clone()),
2414 payment_type: PaymentType::Sent,
2415 payment_time: payment.completed_at.unwrap_or(payment.created_at) as i64,
2416 amount_msat: match status {
2417 PaymentStatus::Complete => payment_amount,
2418 _ => ln_invoice
2419 .as_ref()
2420 .map_or(0, |i| i.amount_msat.unwrap_or_default()),
2421 },
2422 fee_msat: payment_amount_sent.saturating_sub(payment_amount),
2423 status,
2424 error: None,
2425 description: ln_invoice
2426 .as_ref()
2427 .map(|i| i.description.clone())
2428 .unwrap_or_default(),
2429 details: PaymentDetails::Ln {
2430 data: LnPaymentDetails {
2431 payment_hash: hex::encode(payment.payment_hash),
2432 label: client_label.unwrap_or_default(),
2433 destination_pubkey: ln_invoice.map_or(
2434 payment.destination.map(hex::encode).unwrap_or_default(),
2435 |i| i.payee_pubkey,
2436 ),
2437 payment_preimage: payment.preimage.map(hex::encode).unwrap_or_default(),
2438 keysend: payment.bolt11.is_none(),
2439 bolt11: payment.bolt11.unwrap_or_default(),
2440 lnurl_success_action: None,
2441 lnurl_pay_domain: None,
2442 lnurl_pay_comment: None,
2443 lnurl_metadata: None,
2444 ln_address: None,
2445 lnurl_withdraw_endpoint: None,
2446 swap_info: None,
2447 reverse_swap_info: None,
2448 pending_expiration_block: None,
2449 open_channel_bolt11: None,
2450 },
2451 },
2452 metadata: None,
2453 })
2454 }
2455}
2456
2457impl TryFrom<cln::PayResponse> for PaymentResponse {
2458 type Error = NodeError;
2459
2460 fn try_from(payment: cln::PayResponse) -> std::result::Result<Self, Self::Error> {
2461 let payment_amount = payment.amount_msat.unwrap_or_default().msat;
2462 let payment_amount_sent = payment.amount_sent_msat.unwrap_or_default().msat;
2463
2464 Ok(PaymentResponse {
2465 payment_time: payment.created_at as i64,
2466 amount_msat: payment_amount,
2467 fee_msat: payment_amount_sent - payment_amount,
2468 payment_hash: hex::encode(payment.payment_hash),
2469 payment_preimage: hex::encode(payment.payment_preimage),
2470 })
2471 }
2472}
2473
2474impl TryFrom<cln::KeysendResponse> for PaymentResponse {
2475 type Error = NodeError;
2476
2477 fn try_from(payment: cln::KeysendResponse) -> std::result::Result<Self, Self::Error> {
2478 let payment_amount = payment.amount_msat.unwrap_or_default().msat;
2479 let payment_amount_sent = payment.amount_sent_msat.unwrap_or_default().msat;
2480
2481 Ok(PaymentResponse {
2482 payment_time: payment.created_at as i64,
2483 amount_msat: payment_amount,
2484 fee_msat: payment_amount_sent - payment_amount,
2485 payment_hash: hex::encode(payment.payment_hash),
2486 payment_preimage: hex::encode(payment.payment_preimage),
2487 })
2488 }
2489}
2490
2491fn amount_to_msat(amount: &gl_client::pb::greenlight::Amount) -> u64 {
2492 match amount.unit {
2493 Some(amount::Unit::Millisatoshi(val)) => val,
2494 Some(amount::Unit::Satoshi(val)) => val * 1000,
2495 Some(amount::Unit::Bitcoin(val)) => val * 100000000,
2496 Some(_) => 0,
2497 None => 0,
2498 }
2499}
2500
2501impl From<cln::ListpeerchannelsChannels> for Channel {
2503 fn from(c: cln::ListpeerchannelsChannels) -> Self {
2504 let state = match c.state() {
2505 Openingd | ChanneldAwaitingLockin | DualopendOpenInit | DualopendAwaitingLockin => {
2506 ChannelState::PendingOpen
2507 }
2508 ChanneldNormal => ChannelState::Opened,
2509 _ => ChannelState::PendingClose,
2510 };
2511
2512 let (alias_remote, alias_local) = match c.alias {
2513 Some(a) => (a.remote, a.local),
2514 None => (None, None),
2515 };
2516
2517 Channel {
2518 short_channel_id: c.short_channel_id,
2519 state,
2520 funding_txid: c.funding_txid.map(hex::encode).unwrap_or_default(),
2521 spendable_msat: c.spendable_msat.unwrap_or_default().msat,
2522 local_balance_msat: c.to_us_msat.unwrap_or_default().msat,
2523 receivable_msat: c.receivable_msat.unwrap_or_default().msat,
2524 closed_at: None,
2525 funding_outnum: c.funding_outnum,
2526 alias_remote,
2527 alias_local,
2528 closing_txid: None,
2529 htlcs: c
2530 .htlcs
2531 .into_iter()
2532 .map(|c| Htlc::from(c.expiry.unwrap_or(0), c.payment_hash.unwrap_or_default()))
2533 .collect(),
2534 }
2535 }
2536}
2537
2538fn convert_to_send_pay_route(
2539 route: PaymentPath,
2540 to_pay_msat: u64,
2541 final_cltv_delta: u64,
2542) -> (Vec<SendpayRoute>, u64) {
2543 let mut sendpay_route = vec![];
2544 let mut to_forward = to_pay_msat;
2545 let mut cltv_delay = 0;
2546 let hops_arr = route.edges.as_slice();
2547
2548 let reverse_hops: Vec<&PaymentPathEdge> = hops_arr.iter().rev().collect();
2549
2550 for (reverse_index, hop) in reverse_hops.iter().enumerate() {
2553 (to_forward, cltv_delay) = match reverse_index == 0 {
2555 true => (to_forward, final_cltv_delta),
2557
2558 false => (
2560 reverse_hops[reverse_index - 1].amount_from_forward(to_forward),
2561 cltv_delay + reverse_hops[reverse_index - 1].channel_delay,
2562 ),
2563 };
2564
2565 sendpay_route.insert(
2566 0,
2567 SendpayRoute {
2568 amount_msat: Some(gl_client::pb::cln::Amount { msat: to_forward }),
2569 id: hop.node_id.clone(),
2570 delay: cltv_delay as u32,
2571 channel: hop.short_channel_id.clone(),
2572 },
2573 );
2574 }
2575
2576 (sendpay_route, to_forward)
2577}
2578
2579impl TryFrom<ListclosedchannelsClosedchannels> for Channel {
2580 type Error = NodeError;
2581
2582 fn try_from(
2583 c: cln::ListclosedchannelsClosedchannels,
2584 ) -> std::result::Result<Self, Self::Error> {
2585 let (alias_remote, alias_local) = match c.alias {
2586 Some(a) => (a.remote, a.local),
2587 None => (None, None),
2588 };
2589
2590 let local_balance_msat = c
2593 .final_to_us_msat
2594 .ok_or(anyhow!("final_to_us_msat is missing"))?
2595 .msat;
2596 Ok(Channel {
2597 short_channel_id: c.short_channel_id,
2598 state: ChannelState::Closed,
2599 funding_txid: hex::encode(c.funding_txid),
2600 spendable_msat: local_balance_msat,
2601 local_balance_msat,
2602 receivable_msat: 0,
2603 closed_at: None,
2604 funding_outnum: Some(c.funding_outnum),
2605 alias_remote,
2606 alias_local,
2607 closing_txid: None,
2608 htlcs: Vec::new(),
2609 })
2610 }
2611}
2612
2613#[cfg(test)]
2614mod tests {
2615 use anyhow::Result;
2616 use gl_client::pb::cln::listpeerchannels_channels::{
2617 ListpeerchannelsChannelsState, ListpeerchannelsChannelsState::*,
2618 };
2619 use gl_client::pb::cln::Amount;
2620 use gl_client::pb::{self, cln};
2621
2622 use crate::greenlight::node_api::convert_to_send_pay_route;
2623 use crate::{models, PaymentPath, PaymentPathEdge};
2624
2625 #[test]
2626 fn test_convert_route() -> Result<()> {
2627 let path = PaymentPath {
2628 edges: vec![
2629 PaymentPathEdge {
2630 node_id: vec![1],
2631 short_channel_id: "807189x2048x0".into(),
2632 channel_delay: 34,
2633 base_fee_msat: 1000,
2634 fee_per_millionth: 10,
2635 },
2636 PaymentPathEdge {
2637 node_id: vec![2],
2638 short_channel_id: "811871x2726x1".into(),
2639 channel_delay: 34,
2640 base_fee_msat: 0,
2641 fee_per_millionth: 0,
2642 },
2643 PaymentPathEdge {
2644 node_id: vec![3],
2645 short_channel_id: "16000000x0x18087".into(),
2646 channel_delay: 40,
2647 base_fee_msat: 1000,
2648 fee_per_millionth: 1,
2649 },
2650 ],
2651 };
2652
2653 let (r, sent) = convert_to_send_pay_route(path, 50000000, 144);
2654 assert_eq!(
2655 r,
2656 vec![
2657 pb::cln::SendpayRoute {
2658 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50001050 }),
2659 id: vec![1],
2660 delay: 218,
2661 channel: "807189x2048x0".into(),
2662 },
2663 pb::cln::SendpayRoute {
2664 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50001050 }),
2665 id: vec![2],
2666 delay: 184,
2667 channel: "811871x2726x1".into(),
2668 },
2669 pb::cln::SendpayRoute {
2670 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50000000 }),
2671 id: vec![3],
2672 delay: 144,
2673 channel: "16000000x0x18087".into(),
2674 }
2675 ]
2676 );
2677 assert_eq!(sent, 50001050);
2678
2679 let path = PaymentPath {
2680 edges: vec![
2681 PaymentPathEdge {
2682 node_id: vec![1],
2683 short_channel_id: "807189x2048x0".into(),
2684 channel_delay: 34,
2685 base_fee_msat: 1000,
2686 fee_per_millionth: 10,
2687 },
2688 PaymentPathEdge {
2689 node_id: vec![2],
2690 short_channel_id: "811871x2726x1".into(),
2691 channel_delay: 34,
2692 base_fee_msat: 0,
2693 fee_per_millionth: 0,
2694 },
2695 PaymentPathEdge {
2696 node_id: vec![3],
2697 short_channel_id: "16000000x0x18087".into(),
2698 channel_delay: 40,
2699 base_fee_msat: 0,
2700 fee_per_millionth: 2000,
2701 },
2702 ],
2703 };
2704 let (r, sent) = convert_to_send_pay_route(path, 50000000, 144);
2705 assert_eq!(
2706 r,
2707 vec![
2708 pb::cln::SendpayRoute {
2709 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50100000 }),
2710 id: vec![1],
2711 delay: 218,
2712 channel: "807189x2048x0".into(),
2713 },
2714 pb::cln::SendpayRoute {
2715 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50100000 }),
2716 id: vec![2],
2717 delay: 184,
2718 channel: "811871x2726x1".into(),
2719 },
2720 pb::cln::SendpayRoute {
2721 amount_msat: Some(gl_client::pb::cln::Amount { msat: 50000000 }),
2722 id: vec![3],
2723 delay: 144,
2724 channel: "16000000x0x18087".into(),
2725 }
2726 ]
2727 );
2728 assert_eq!(sent, 50100000);
2729
2730 Ok(())
2731 }
2732
2733 #[test]
2734 fn test_channel_states() -> Result<()> {
2735 for s in &[Openingd, ChanneldAwaitingLockin] {
2736 let c: models::Channel = cln_channel(s).into();
2737 assert_eq!(c.state, models::ChannelState::PendingOpen);
2738 }
2739
2740 let s = ChanneldNormal;
2741 let c: models::Channel = cln_channel(&s).into();
2742 assert_eq!(c.state, models::ChannelState::Opened);
2743
2744 for s in &[
2745 ChanneldShuttingDown,
2746 ClosingdSigexchange,
2747 ClosingdComplete,
2748 AwaitingUnilateral,
2749 FundingSpendSeen,
2750 ] {
2751 let c: models::Channel = cln_channel(s).into();
2752 assert_eq!(c.state, models::ChannelState::PendingClose);
2753 }
2754
2755 let c: models::Channel = cln_channel(&Onchain).into();
2756 assert_eq!(c.state, models::ChannelState::PendingClose);
2757
2758 Ok(())
2759 }
2760
2761 fn cln_channel(state: &ListpeerchannelsChannelsState) -> cln::ListpeerchannelsChannels {
2762 cln::ListpeerchannelsChannels {
2763 state: Some((*state).into()),
2764 scratch_txid: None,
2765 feerate: None,
2766 owner: None,
2767 short_channel_id: None,
2768 channel_id: None,
2769 funding_txid: None,
2770 funding_outnum: None,
2771 initial_feerate: None,
2772 last_feerate: None,
2773 next_feerate: None,
2774 next_fee_step: None,
2775 inflight: vec![],
2776 close_to: None,
2777 private: Some(true),
2778 opener: Some(0),
2779 closer: None,
2780 funding: None,
2781 to_us_msat: None,
2782 min_to_us_msat: None,
2783 max_to_us_msat: None,
2784 total_msat: Some(Amount { msat: 1_000 }),
2785 fee_base_msat: None,
2786 fee_proportional_millionths: None,
2787 dust_limit_msat: Some(Amount { msat: 10 }),
2788 max_total_htlc_in_msat: None,
2789 their_reserve_msat: None,
2790 our_reserve_msat: None,
2791 spendable_msat: Some(Amount { msat: 20_000 }),
2792 receivable_msat: Some(Amount { msat: 960_000 }),
2793 minimum_htlc_in_msat: None,
2794 minimum_htlc_out_msat: None,
2795 maximum_htlc_out_msat: None,
2796 their_to_self_delay: Some(144),
2797 our_to_self_delay: Some(144),
2798 max_accepted_htlcs: None,
2799 alias: None,
2800 status: vec![],
2801 in_payments_offered: None,
2802 in_offered_msat: None,
2803 in_payments_fulfilled: None,
2804 in_fulfilled_msat: None,
2805 out_payments_offered: None,
2806 out_offered_msat: None,
2807 out_payments_fulfilled: None,
2808 out_fulfilled_msat: None,
2809 htlcs: vec![],
2810 close_to_addr: None,
2811 peer_id: None,
2812 peer_connected: None,
2813 updates: None,
2814 ignore_fee_limits: None,
2815 lost_state: None,
2816 last_stable_connection: None,
2817 }
2818 }
2819}