Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diagnostic data for supporting users. #900

Merged
merged 5 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libs/sdk-bindings/src/breez_sdk.udl
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,9 @@ interface BlockingBreezServices {
[Throws=SdkError]
string execute_dev_command(string command);

[Throws=SdkError]
string generate_diagnostic_data();

[Throws=SdkError]
void sync();

Expand Down
4 changes: 4 additions & 0 deletions libs/sdk-bindings/src/uniffi_binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@ impl BlockingBreezServices {
rt().block_on(self.breez_services.execute_dev_command(command))
}

pub fn generate_diagnostic_data(&self) -> SdkResult<String> {
rt().block_on(self.breez_services.generate_diagnostic_data())
}

pub fn sync(&self) -> SdkResult<()> {
rt().block_on(self.breez_services.sync())
}
Expand Down
6 changes: 6 additions & 0 deletions libs/sdk-core/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,12 @@ pub fn execute_command(command: String) -> Result<String> {
.map_err(anyhow::Error::new::<SdkError>)
}

/// See [BreezServices::generate_diagnostic_data]
pub fn generate_diagnostic_data() -> Result<String> {
block_on(async { get_breez_services().await?.generate_diagnostic_data().await })
.map_err(anyhow::Error::new::<SdkError>)
}

/* Binding Related Logic */

struct BindingEventListener;
Expand Down
34 changes: 34 additions & 0 deletions libs/sdk-core/src/breez_services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,6 +1042,14 @@ impl BreezServices {
Ok(self.node_api.execute_command(command).await?)
}

// Collects various user data from the node and the sdk storage.
// This is used for debugging and support purposes only.
pub async fn generate_diagnostic_data(&self) -> SdkResult<String> {
let node_data = self.node_api.generate_diagnostic_data().await?;
let sdk_data = self.generate_sdk_diagnostic_data().await?;
Ok(format!("Node Data\n{node_data}\n\nSDK Data\n{sdk_data}"))
}

/// This method sync the local state with the remote node state.
/// The synced items are as follows:
/// * node state - General information about the node and its liquidity status
Expand Down Expand Up @@ -1850,6 +1858,32 @@ impl BreezServices {
err: format!("Failed to register for tx confirmation notifications: {err}"),
})
}

async fn generate_sdk_diagnostic_data(&self) -> SdkResult<String> {
let state: String = serde_json::to_string_pretty(&self.persister.get_node_state()?)?;
let payments = serde_json::to_string_pretty(
&self
.persister
.list_payments(ListPaymentsRequest::default())?,
)?;
let channels = serde_json::to_string_pretty(&self.persister.list_channels()?)?;
let settings = serde_json::to_string_pretty(&self.persister.list_settings()?)?;
let reverse_swaps = serde_json::to_string_pretty(&self.persister.list_reverse_swaps()?)?;
let swaps = serde_json::to_string_pretty(&self.persister.list_swaps()?)?;
let lsp_id = serde_json::to_string_pretty(&self.persister.get_lsp_id()?)?;

let res = format!(
"\
***Node State***\n{state}\n\n \
***Payments***\n{payments}\n\n \
***Channels***\n{channels}\n\n \
***Settings***\n{settings}\n\n \
***Reverse Swaps***\n{reverse_swaps}\n\n \
***LSP ID***\n{lsp_id}\n\n \
***Swaps***\n{swaps}\n\n"
);
Ok(res)
}
}

struct GlobalSdkLogger {
Expand Down
5 changes: 5 additions & 0 deletions libs/sdk-core/src/bridge_generated.io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,11 @@ pub extern "C" fn wire_execute_command(port_: i64, command: *mut wire_uint_8_lis
wire_execute_command_impl(port_, command)
}

#[no_mangle]
pub extern "C" fn wire_generate_diagnostic_data(port_: i64) {
wire_generate_diagnostic_data_impl(port_)
}

// Section: allocate functions

#[no_mangle]
Expand Down
10 changes: 10 additions & 0 deletions libs/sdk-core/src/bridge_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,16 @@ fn wire_execute_command_impl(port_: MessagePort, command: impl Wire2Api<String>
},
)
}
fn wire_generate_diagnostic_data_impl(port_: MessagePort) {
FLUTTER_RUST_BRIDGE_HANDLER.wrap::<_, _, _, String, _>(
WrapInfo {
debug_name: "generate_diagnostic_data",
port: Some(port_),
mode: FfiCallMode::Normal,
},
move || move |task_callback| generate_diagnostic_data(),
)
}
// Section: wrapper structs

// Section: static checks
Expand Down
21 changes: 21 additions & 0 deletions libs/sdk-core/src/greenlight/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,27 @@ impl NodeAPI for Greenlight {
Ok(hex_vec)
}

async fn generate_diagnostic_data(&self) -> NodeResult<String> {
let all_commands = vec![
NodeCommand::GetInfo.to_string(),
NodeCommand::ListPeerChannels.to_string(),
NodeCommand::ListFunds.to_string(),
NodeCommand::ListPayments.to_string(),
NodeCommand::ListInvoices.to_string(),
];

let mut result = String::new();
for command in all_commands {
let command_name = command.clone();
let res = self
.execute_command(command)
.await
.unwrap_or_else(|e| e.to_string());
result += &format!("***{command_name}:***\n\n {res}\n\n");
}
Ok(result)
}

async fn execute_command(&self, command: String) -> NodeResult<String> {
let node_cmd =
NodeCommand::from_str(&command).map_err(|_| anyhow!("Command not found: {command}"))?;
Expand Down
4 changes: 2 additions & 2 deletions libs/sdk-core/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ impl OpeningFeeParamsMenu {
}

/// Lightning channel
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
pub struct Channel {
pub funding_txid: String,
pub short_channel_id: Option<String>,
Expand All @@ -1259,7 +1259,7 @@ pub struct Channel {
pub htlcs: Vec<Htlc>,
}

#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
pub struct Htlc {
pub expiry: u32,
pub payment_hash: Vec<u8>,
Expand Down
17 changes: 9 additions & 8 deletions libs/sdk-core/src/node_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ use tonic::Streaming;

use crate::{
bitcoin::util::bip32::{ChildNumber, ExtendedPrivKey},
invoice::InvoiceError, lightning_invoice::RawBolt11Invoice, persist::error::PersistError, CustomMessage, MaxChannelAmount,
NodeCredentials, Payment, PaymentResponse, Peer, PrepareRedeemOnchainFundsRequest,
PrepareRedeemOnchainFundsResponse, RouteHint, RouteHintHop, SyncResponse, TlvEntry,
invoice::InvoiceError,
lightning_invoice::RawBolt11Invoice,
persist::error::PersistError,
CustomMessage, MaxChannelAmount, NodeCredentials, Payment, PaymentResponse, Peer,
PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse, RouteHint, RouteHintHop,
SyncResponse, TlvEntry,
};

pub type NodeResult<T, E = NodeError> = Result<T, E>;
Expand Down Expand Up @@ -65,18 +68,15 @@ pub struct CreateInvoiceRequest {

pub struct FetchBolt11Result {
pub bolt11: String,
pub payer_amount_msat: Option<u64>
pub payer_amount_msat: Option<u64>,
}

/// Trait covering functions affecting the LN node
#[tonic::async_trait]
pub trait NodeAPI: Send + Sync {
fn node_credentials(&self) -> NodeResult<Option<NodeCredentials>>;
async fn configure_node(&self, close_to_address: Option<String>) -> NodeResult<()>;
async fn create_invoice(
&self,
request: CreateInvoiceRequest,
) -> NodeResult<String>;
async fn create_invoice(&self, request: CreateInvoiceRequest) -> NodeResult<String>;
/// Fetches an existing BOLT11 invoice from the node
async fn fetch_bolt11(&self, payment_hash: Vec<u8>) -> NodeResult<Option<FetchBolt11Result>>;
async fn pull_changed(
Expand Down Expand Up @@ -128,6 +128,7 @@ pub trait NodeAPI: Send + Sync {
) -> NodeResult<Streaming<gl_client::signer::model::greenlight::LogEntry>>;
async fn static_backup(&self) -> NodeResult<Vec<String>>;
async fn execute_command(&self, command: String) -> NodeResult<String>;
async fn generate_diagnostic_data(&self) -> NodeResult<String>;
async fn sign_message(&self, message: &str) -> NodeResult<String>;
async fn check_message(&self, message: &str, pubkey: &str, signature: &str)
-> NodeResult<bool>;
Expand Down
3 changes: 3 additions & 0 deletions libs/sdk-core/src/persist/settings.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use serde::Serialize;

use super::{db::SqliteStorage, error::PersistResult};

#[allow(dead_code)]
#[derive(Serialize)]
pub struct SettingItem {
key: String,
value: String,
Expand Down
52 changes: 33 additions & 19 deletions libs/sdk-core/src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ use chrono::{SecondsFormat, Utc};
use gl_client::signer::model::greenlight::amount::Unit;
use gl_client::signer::model::greenlight::Amount;
use gl_client::signer::model::greenlight::PayStatus;
use rand::distributions::uniform::{SampleRange, SampleUniform};
use rand::distributions::{Alphanumeric, DistString, Standard};
use rand::rngs::OsRng;
use rand::{random, Rng};
use rand::distributions::uniform::{SampleRange, SampleUniform};
use tokio::sync::{mpsc, Mutex};
use tokio::time::sleep;
use tokio_stream::Stream;
Expand All @@ -34,14 +34,22 @@ use crate::invoice::{InvoiceError, InvoiceResult};
use crate::lightning::ln::PaymentSecret;
use crate::lightning_invoice::{Currency, InvoiceBuilder, RawBolt11Invoice};
use crate::lsp::LspInformation;
use crate::models::{FiatAPI, LspAPI, NodeState, Payment, ReverseSwapServiceAPI, Swap, SwapperAPI, SyncResponse, TlvEntry};
use crate::models::{
FiatAPI, LspAPI, NodeState, Payment, ReverseSwapServiceAPI, Swap, SwapperAPI, SyncResponse,
TlvEntry,
};
use crate::moonpay::MoonPayApi;
use crate::node_api::{CreateInvoiceRequest, FetchBolt11Result, NodeAPI, NodeError, NodeResult};
use crate::swap_in::error::SwapResult;
use crate::swap_in::swap::create_submarine_swap_script;
use crate::{parse_invoice, Config, CustomMessage, LNInvoice, MaxChannelAmount, NodeCredentials, OpeningFeeParams, OpeningFeeParamsMenu, PaymentResponse, Peer, PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse, ReceivePaymentRequest, RouteHint, RouteHintHop, SwapInfo, ReverseSwapPairInfo};
use crate::swap_out::boltzswap::{BoltzApiCreateReverseSwapResponse, BoltzApiReverseSwapStatus};
use crate::swap_out::error::{ReverseSwapError, ReverseSwapResult};
use crate::{
parse_invoice, Config, CustomMessage, LNInvoice, MaxChannelAmount, NodeCredentials,
OpeningFeeParams, OpeningFeeParamsMenu, PaymentResponse, Peer,
PrepareRedeemOnchainFundsRequest, PrepareRedeemOnchainFundsResponse, ReceivePaymentRequest,
ReverseSwapPairInfo, RouteHint, RouteHintHop, SwapInfo,
};

pub const MOCK_REVERSE_SWAP_MIN: u64 = 50_000;
pub const MOCK_REVERSE_SWAP_MAX: u64 = 1_000_000;
Expand Down Expand Up @@ -152,13 +160,13 @@ pub struct MockReverseSwapperAPI {}
impl ReverseSwapServiceAPI for MockReverseSwapperAPI {
async fn fetch_reverse_swap_fees(&self) -> ReverseSwapResult<ReverseSwapPairInfo> {
Ok(ReverseSwapPairInfo {
min: MOCK_REVERSE_SWAP_MIN,
max: MOCK_REVERSE_SWAP_MAX,
fees_hash: rand_string(5),
fees_percentage: 0.5,
fees_lockup: 3_000 + rand_int_in_range(1..1_000),
fees_claim: 3_000 + rand_int_in_range(1..1_000),
total_fees: None,
min: MOCK_REVERSE_SWAP_MIN,
max: MOCK_REVERSE_SWAP_MAX,
fees_hash: rand_string(5),
fees_percentage: 0.5,
fees_lockup: 3_000 + rand_int_in_range(1..1_000),
fees_claim: 3_000 + rand_int_in_range(1..1_000),
total_fees: None,
})
}

Expand All @@ -168,7 +176,7 @@ impl ReverseSwapServiceAPI for MockReverseSwapperAPI {
_preimage_hash_hex: String,
_claim_pubkey: String,
_pair_hash: String,
_routing_node: String
_routing_node: String,
) -> ReverseSwapResult<BoltzApiCreateReverseSwapResponse> {
Err(ReverseSwapError::Generic(anyhow!("Not implemented")))
}
Expand Down Expand Up @@ -331,11 +339,13 @@ impl NodeAPI for MockNodeAPI {
Ok(())
}

async fn create_invoice(
&self,
request: CreateInvoiceRequest,
) -> NodeResult<String> {
let invoice = create_invoice(request.description, request.amount_msat, vec![], request.preimage);
async fn create_invoice(&self, request: CreateInvoiceRequest) -> NodeResult<String> {
let invoice = create_invoice(
request.description,
request.amount_msat,
vec![],
request.preimage,
);
Ok(invoice.bolt11)
}

Expand Down Expand Up @@ -446,6 +456,10 @@ impl NodeAPI for MockNodeAPI {
Err(NodeError::Generic(anyhow!("Not implemented")))
}

async fn generate_diagnostic_data(&self) -> NodeResult<String> {
Ok("".to_string())
}

async fn max_sendable_amount(
&self,
_payee_node_id: Option<Vec<u8>>,
Expand Down Expand Up @@ -727,9 +741,9 @@ pub fn rand_vec_u8(len: usize) -> Vec<u8> {
}

pub fn rand_int_in_range<T, R>(range: R) -> T
where
T: SampleUniform,
R: SampleRange<T>
where
T: SampleUniform,
R: SampleRange<T>,
{
rand::thread_rng().gen_range(range)
}
Expand Down
3 changes: 3 additions & 0 deletions libs/sdk-flutter/ios/Classes/bridge_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,8 @@ void wire_recommended_fees(int64_t port_);

void wire_execute_command(int64_t port_, struct wire_uint_8_list *command);

void wire_generate_diagnostic_data(int64_t port_);

bool *new_box_autoadd_bool_0(bool value);

struct wire_BuyBitcoinRequest *new_box_autoadd_buy_bitcoin_request_0(void);
Expand Down Expand Up @@ -549,6 +551,7 @@ static int64_t dummy_method_to_enforce_bundling(void) {
dummy_var ^= ((int64_t) (void*) wire_in_progress_onchain_payments);
dummy_var ^= ((int64_t) (void*) wire_recommended_fees);
dummy_var ^= ((int64_t) (void*) wire_execute_command);
dummy_var ^= ((int64_t) (void*) wire_generate_diagnostic_data);
dummy_var ^= ((int64_t) (void*) new_box_autoadd_bool_0);
dummy_var ^= ((int64_t) (void*) new_box_autoadd_buy_bitcoin_request_0);
dummy_var ^= ((int64_t) (void*) new_box_autoadd_check_message_request_0);
Expand Down
6 changes: 6 additions & 0 deletions libs/sdk-flutter/lib/breez_sdk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,12 @@ class BreezSDK {
return await _lnToolkit.executeCommand(command: command);
}

/// Generate diagnostic data.
/// Mainly used to debugging.
Future<String> generateDiagnosticData() async {
return await _lnToolkit.generateDiagnosticData();
}

/* Helper Methods */

/// Validate if given address is a valid BTC address
Expand Down
Loading
Loading