Skip to content

Commit

Permalink
tests: add api for interacting with ldk node
Browse files Browse the repository at this point in the history
  • Loading branch information
orbitalturtle committed Sep 7, 2023
1 parent f9d5849 commit 14e43a6
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 9 deletions.
32 changes: 23 additions & 9 deletions tests/common/ldk_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod config;
mod convert;
mod disk;
mod hex_utils;
pub mod node_api;
mod peer_utils;
mod sweep;

Expand Down Expand Up @@ -521,7 +522,7 @@ async fn handle_ldk_events(
}
}

pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) -> node_api::Node {
let (ldk_data_dir, _ldk_dir_binding, ldk_log_dir) = config::setup_data_and_log_dirs(test_name);

// ## Setup
Expand All @@ -541,8 +542,7 @@ pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
{
Ok(client) => Arc::new(client),
Err(e) => {
println!("Failed to connect to bitcoind client: {}", e);
return;
panic!("Failed to connect to bitcoind client: {}", e);
}
};

Expand All @@ -556,11 +556,10 @@ pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
bitcoin::Network::Signet => "signet",
}
{
println!(
panic!(
"Chain argument ({}) didn't match bitcoind chain ({})",
args.network, bitcoind_chain
);
return;
}

// Step 2: Initialize the FeeEstimator
Expand Down Expand Up @@ -605,11 +604,10 @@ pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
f.sync_all().expect("Failed to sync node keys seed to disk");
}
Err(e) => {
println!(
panic!(
"ERROR: Unable to create keys seed file {}: {}",
keys_seed_path, e
);
return;
}
}
key
Expand Down Expand Up @@ -691,7 +689,7 @@ pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
fee_estimator.clone(),
chain_monitor.clone(),
broadcaster.clone(),
router,
router.clone(),
logger.clone(),
user_config,
channel_monitor_mut_references,
Expand All @@ -711,7 +709,7 @@ pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
fee_estimator.clone(),
chain_monitor.clone(),
broadcaster.clone(),
router,
router.clone(),
logger.clone(),
keys_manager.clone(),
keys_manager.clone(),
Expand Down Expand Up @@ -1023,4 +1021,20 @@ pub(crate) async fn start_ldk(args: config::LdkUserInfo, test_name: &str) {
Arc::clone(&bitcoind_client),
Arc::clone(&channel_manager),
));

return node_api::Node {
logger,
bitcoind_client,
persister,
chain_monitor,
keys_manager,
network_graph,
router,
scorer,
channel_manager,
gossip_sync,
onion_messenger,
peer_manager,
listening_port: args.ldk_peer_listening_port,
};
}
168 changes: 168 additions & 0 deletions tests/common/ldk_node/node_api.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
use crate::common::ldk_node::disk::FilesystemLogger;
use crate::common::ldk_node::{
BitcoindClient, ChainMonitor, ChannelManager, NetworkGraph, OnionMessenger, PeerManager,
};

use bitcoin::secp256k1::PublicKey;
use lightning::onion_message::{
CustomOnionMessageContents, Destination, OnionMessageContents, OnionMessagePath,
};
use lightning::routing::router::DefaultRouter;
use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters};
use lightning::sign::KeysManager;
use lightning::util::ser::{Writeable, Writer};
use lightning_persister::FilesystemPersister;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::{Arc, Mutex};
use std::time::Duration;

pub(crate) type Router = DefaultRouter<
Arc<NetworkGraph>,
Arc<FilesystemLogger>,
Arc<Mutex<Scorer>>,
ProbabilisticScoringFeeParameters,
Scorer,
>;
pub(crate) type Scorer = ProbabilisticScorer<Arc<NetworkGraph>, Arc<FilesystemLogger>>;

pub(crate) type P2PGossipSyncType = lightning::routing::gossip::P2PGossipSync<
Arc<NetworkGraph>,
Arc<BitcoindClient>,
Arc<FilesystemLogger>,
>;

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)
}
}

pub struct Node {
pub(crate) logger: Arc<FilesystemLogger>,
pub(crate) bitcoind_client: Arc<BitcoindClient>,
pub(crate) persister: Arc<FilesystemPersister>,
pub(crate) chain_monitor: Arc<ChainMonitor>,
pub(crate) keys_manager: Arc<KeysManager>,
pub(crate) network_graph: Arc<NetworkGraph>,
pub(crate) router: Arc<Router>,
pub(crate) scorer: Arc<Mutex<Scorer>>,
pub(crate) channel_manager: Arc<ChannelManager>,
pub(crate) gossip_sync: Arc<P2PGossipSyncType>,
pub(crate) onion_messenger: Arc<OnionMessenger>,
pub(crate) peer_manager: Arc<PeerManager>,

// Config values
pub(crate) listening_port: u16,
}

impl Node {
// get_node_info retrieves node_id and listening address.
pub fn get_node_info(&self) -> (PublicKey, SocketAddr) {
let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), self.listening_port);
(self.channel_manager.get_our_node_id(), socket)
}

pub async fn connect_to_peer(
&self,
pubkey: PublicKey,
peer_addr: SocketAddr,
) -> Result<(), ()> {
// If we're already connected to peer, then we're good to go.
for (node_pubkey, _) in self.peer_manager.get_peer_node_ids() {
if node_pubkey == pubkey {
return Ok(());
}
}
let res = match self.do_connect_peer(pubkey, peer_addr).await {
Ok(_) => {
println!("SUCCESS: connected to peer {}", pubkey);
Ok(())
}
Err(e) => {
println!("ERROR: failed to connect to peer: {e:?}");
Err(())
}
};
res
}

pub async fn do_connect_peer(
&self,
pubkey: PublicKey,
peer_addr: SocketAddr,
) -> Result<(), ()> {
match lightning_net_tokio::connect_outbound(
Arc::clone(&self.peer_manager),
pubkey,
peer_addr,
)
.await
{
Some(connection_closed_future) => {
let mut connection_closed_future = Box::pin(connection_closed_future);
loop {
tokio::select! {
_ = &mut connection_closed_future => return Err(()),
_ = tokio::time::sleep(Duration::from_millis(10)) => {},
};
if self
.peer_manager
.get_peer_node_ids()
.iter()
.find(|(id, _)| *id == pubkey)
.is_some()
{
return Ok(());
}
}
}
None => Err(()),
}
}

pub async fn send_onion_message(
&self,
mut intermediate_nodes: Vec<PublicKey>,
tlv_type: u64,
data: Vec<u8>,
) -> Result<(), ()> {
if intermediate_nodes.len() == 0 {
println!("Need to provide pubkey to send onion message");
return Err(());
}
if tlv_type <= 64 {
println!("Need an integral message type above 64");
return Err(());
}
let destination = Destination::Node(intermediate_nodes.pop().unwrap());
let message_path = OnionMessagePath {
intermediate_nodes,
destination,
};
match self.onion_messenger.send_onion_message(
message_path,
OnionMessageContents::Custom(UserOnionMessageContents { tlv_type, data }),
None,
) {
Ok(()) => {
println!("SUCCESS: forwarded onion message to first hop");
Ok(())
}
Err(e) => {
println!("ERROR: failed to send onion message: {:?}", e);
Ok(())
}
}
}
}

0 comments on commit 14e43a6

Please sign in to comment.