Skip to content
Open
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
1 change: 1 addition & 0 deletions bindings/ldk_node.udl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace ldk_node {

dictionary Config {
string storage_dir_path = "/tmp/ldk_node/";
string? log_dir_path = null;
Network network = "Bitcoin";
NetAddress? listening_address = null;
u32 default_cltv_expiry_delta = 144;
Expand Down
39 changes: 29 additions & 10 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ use crate::types::{
use crate::wallet::Wallet;
use crate::LogLevel;
use crate::{
Config, Node, BDK_CLIENT_CONCURRENCY, BDK_CLIENT_STOP_GAP, DEFAULT_ESPLORA_SERVER_URL,
WALLET_KEYS_SEED_LEN,
Config, Node, OnionMessageHandler, BDK_CLIENT_CONCURRENCY, BDK_CLIENT_STOP_GAP,
DEFAULT_ESPLORA_SERVER_URL, WALLET_KEYS_SEED_LEN,
};

use lightning::chain::keysinterface::EntropySource;
Expand All @@ -42,6 +42,7 @@ use bip39::Mnemonic;

use bitcoin::BlockHash;

use std::collections::VecDeque;
use std::convert::TryInto;
use std::default::Default;
use std::fmt;
Expand Down Expand Up @@ -202,6 +203,12 @@ impl NodeBuilder {
self
}

/// Sets the log dir path if logs need to live separate from the storage directory path.
pub fn set_log_dir_path(&mut self, log_dir_path: String) -> &mut Self {
self.config.log_dir_path = Some(log_dir_path);
self
}

/// Sets the Bitcoin network used.
pub fn set_network(&mut self, network: Network) -> &mut Self {
self.config.network = network;
Expand Down Expand Up @@ -329,6 +336,11 @@ impl ArcedNodeBuilder {
self.inner.write().unwrap().set_storage_dir_path(storage_dir_path);
}

/// Sets the log dir path if logs need to live separate from the storage directory path.
pub fn set_log_dir_path(&self, log_dir_path: String) {
self.inner.write().unwrap().set_log_dir_path(log_dir_path);
}

/// Sets the Bitcoin network used.
pub fn set_network(&self, network: Network) {
self.inner.write().unwrap().set_network(network);
Expand Down Expand Up @@ -377,12 +389,14 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
let bdk_data_dir = format!("{}/bdk", config.storage_dir_path);
fs::create_dir_all(bdk_data_dir.clone()).map_err(|_| BuildError::StoragePathAccessFailed)?;

let log_dir = match &config.log_dir_path {
Some(log_dir) => String::from(log_dir),
None => config.storage_dir_path.clone() + "/logs",
};

// Initialize the Logger
let log_file_path = format!(
"{}/logs/ldk_node_{}.log",
config.storage_dir_path,
chrono::offset::Local::now().format("%Y_%m_%d")
);
let log_file_path =
format!("{}/ldk_node_{}.log", log_dir, chrono::offset::Local::now().format("%Y_%m_%d"));
let logger = Arc::new(
FilesystemLogger::new(log_file_path.clone(), config.log_level)
.map_err(|_| BuildError::LoggerSetupFailed)?,
Expand Down Expand Up @@ -595,12 +609,15 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
chain_monitor.watch_channel(funding_outpoint, channel_monitor);
}

let onion_message_handler =
Arc::new(OnionMessageHandler { messages: Mutex::new(VecDeque::new()) });

// Initialize the PeerManager
let onion_messenger: Arc<OnionMessenger> = Arc::new(OnionMessenger::new(
Arc::clone(&keys_manager),
Arc::clone(&keys_manager),
Arc::clone(&logger),
IgnoringMessageHandler {},
Arc::clone(&onion_message_handler),
));
let ephemeral_bytes: [u8; 32] = keys_manager.get_secure_random_bytes();

Expand Down Expand Up @@ -646,13 +663,13 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
chan_handler: Arc::clone(&channel_manager),
route_handler: Arc::clone(&p2p_gossip_sync)
as Arc<dyn RoutingMessageHandler + Sync + Send>,
onion_message_handler: onion_messenger,
onion_message_handler: onion_messenger.clone(),
},
GossipSync::Rapid(_) => MessageHandler {
chan_handler: Arc::clone(&channel_manager),
route_handler: Arc::new(IgnoringMessageHandler {})
as Arc<dyn RoutingMessageHandler + Sync + Send>,
onion_message_handler: onion_messenger,
onion_message_handler: onion_messenger.clone(),
},
GossipSync::None => {
unreachable!("We must always have a gossip sync!");
Expand Down Expand Up @@ -722,5 +739,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
scorer,
peer_store,
payment_store,
onion_messenger,
custom_handler: onion_message_handler,
})
}
103 changes: 91 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
//! [`connect_open_channel`]: Node::connect_open_channel
//! [`send_payment`]: Node::send_payment
//!
#![cfg_attr(not(feature = "uniffi"), deny(missing_docs))]
#![cfg_attr(not(feature = "uniffi"),)]
#![deny(rustdoc::broken_intra_doc_links)]
#![deny(rustdoc::private_intra_doc_links)]
#![allow(bare_trait_objects)]
Expand Down Expand Up @@ -101,6 +101,8 @@ use error::Error;
pub use event::Event;
pub use types::NetAddress;

use types::OnionMessenger;

pub use io::utils::generate_entropy_mnemonic;

#[cfg(feature = "uniffi")]
Expand All @@ -126,11 +128,17 @@ use logger::{log_error, log_info, log_trace, FilesystemLogger, Logger};

use lightning::chain::keysinterface::EntropySource;
use lightning::chain::Confirm;
use lightning::io::Read;
use lightning::ln::channelmanager::{self, PaymentId, RecipientOnionFields, Retry};
use lightning::ln::msgs::DecodeError;
use lightning::ln::{PaymentHash, PaymentPreimage};
use lightning::onion_message::{
CustomOnionMessageContents, CustomOnionMessageHandler, Destination, OnionMessageContents,
};

use lightning::util::config::{ChannelConfig, ChannelHandshakeConfig, UserConfig};
pub use lightning::util::logger::Level as LogLevel;
use lightning::util::ser::{Writeable, Writer};

use lightning_background_processor::process_events_async;

Expand All @@ -148,8 +156,10 @@ use bitcoin::{Address, Txid};

use rand::Rng;

use std::collections::VecDeque;
use std::default::Default;
use std::net::ToSocketAddrs;
use std::ops::Deref;
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime};

Expand Down Expand Up @@ -193,26 +203,77 @@ const WALLET_SYNC_INTERVAL_MINIMUM_SECS: u64 = 10;
// The length in bytes of our wallets' keys seed.
const WALLET_KEYS_SEED_LEN: usize = 64;

#[derive(Clone, Debug)]
pub struct UserOnionMessageContents {
tlv_type: u64,
data: Vec<u8>,
}

impl CustomOnionMessageContents for UserOnionMessageContents {
fn tlv_type(&self) -> u64 {
self.tlv_type
}
}

impl Writeable for UserOnionMessageContents {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), std::io::Error> {
w.write_all(&self.data)
}
}

// An extremely basic message handler needed for our integration tests.
pub struct OnionMessageHandler {
pub messages: Mutex<VecDeque<UserOnionMessageContents>>,
}

impl CustomOnionMessageHandler for OnionMessageHandler {
type CustomMessage = UserOnionMessageContents;

fn handle_custom_message(&self, msg: Self::CustomMessage) {
println!("Received a new custom message!");
self.messages.lock().unwrap().push_back(msg);
}

fn read_custom_message<R: Read>(
&self, message_type: u64, buffer: &mut R,
) -> Result<Option<Self::CustomMessage>, DecodeError> {
unimplemented!();
}
}

impl Deref for OnionMessageHandler {
type Target = OnionMessageHandler;

fn deref(&self) -> &Self::Target {
&self
}
}

#[derive(Debug, Clone)]
/// Represents the configuration of an [`Node`] instance.
///
/// ### Defaults
///
/// | Parameter | Value |
/// |----------------------------------------|------------------|
/// | `storage_dir_path` | /tmp/ldk_node/ |
/// | `network` | Bitcoin |
/// | `listening_address` | None |
/// | `default_cltv_expiry_delta` | 144 |
/// | `onchain_wallet_sync_interval_secs` | 80 |
/// | `wallet_sync_interval_secs` | 30 |
/// | `fee_rate_cache_update_interval_secs` | 600 |
/// | `trusted_peers_0conf` | [] |
/// | `log_level` | Debug |
/// | Parameter | Value |
/// |----------------------------------------|--------------------|
/// | `storage_dir_path` | /tmp/ldk_node/ |
/// | `log_dir_path` | None |
/// | `network` | Bitcoin |
/// | `listening_address` | None |
/// | `default_cltv_expiry_delta` | 144 |
/// | `onchain_wallet_sync_interval_secs` | 80 |
/// | `wallet_sync_interval_secs` | 30 |
/// | `fee_rate_cache_update_interval_secs` | 600 |
/// | `trusted_peers_0conf` | [] |
/// | `log_level` | Debug |
///
pub struct Config {
/// The path where the underlying LDK and BDK persist their data.
pub storage_dir_path: String,
/// The path where logs are stored.
///
/// If set to `None`, logs can be found in the `logs` subdirectory in [`Config::storage_dir_path`].
pub log_dir_path: Option<String>,
/// The used Bitcoin network.
pub network: Network,
/// The IP address and TCP port the node will listen on.
Expand Down Expand Up @@ -247,6 +308,7 @@ impl Default for Config {
fn default() -> Self {
Self {
storage_dir_path: DEFAULT_STORAGE_DIR_PATH.to_string(),
log_dir_path: None,
network: DEFAULT_NETWORK,
listening_address: None,
default_cltv_expiry_delta: DEFAULT_CLTV_EXPIRY_DELTA,
Expand Down Expand Up @@ -281,6 +343,8 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
scorer: Arc<Mutex<Scorer>>,
peer_store: Arc<PeerStore<K, Arc<FilesystemLogger>>>,
payment_store: Arc<PaymentStore<K, Arc<FilesystemLogger>>>,
onion_messenger: Arc<OnionMessenger>,
pub custom_handler: Arc<OnionMessageHandler>,
}

impl<K: KVStore + Sync + Send + 'static> Node<K> {
Expand Down Expand Up @@ -807,6 +871,21 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
self.wallet.send_to_address(address, None)
}

/// Send an onion message to the following address.
pub fn send_onion_message(
&self, node_pks: Vec<PublicKey>, destination_pk: PublicKey, tlv_type: u64, data: Vec<u8>,
) {
match self.onion_messenger.send_onion_message(
&node_pks,
Destination::Node(destination_pk),
OnionMessageContents::Custom(UserOnionMessageContents { tlv_type, data }),
None,
) {
Ok(()) => println!("SUCCESS: forwarded onion message to first hop"),
Err(e) => println!("ERROR: failed to send onion message: {:?}", e),
}
}

/// Retrieve a list of known channels.
pub fn list_channels(&self) -> Vec<ChannelDetails> {
self.channel_manager.list_channels().into_iter().map(|c| c.into()).collect()
Expand Down
3 changes: 2 additions & 1 deletion src/types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::logger::FilesystemLogger;
use crate::wallet::{Wallet, WalletKeysManager};
use crate::OnionMessageHandler;

use lightning::chain::chainmonitor;
use lightning::chain::keysinterface::InMemorySigner;
Expand Down Expand Up @@ -84,7 +85,7 @@ pub(crate) type OnionMessenger = lightning::onion_message::OnionMessenger<
Arc<WalletKeysManager<bdk::database::SqliteDatabase, Arc<FilesystemLogger>>>,
Arc<WalletKeysManager<bdk::database::SqliteDatabase, Arc<FilesystemLogger>>>,
Arc<FilesystemLogger>,
IgnoringMessageHandler,
Arc<OnionMessageHandler>,
>;

/// The global identifier of a channel.
Expand Down