Skip to content

Commit

Permalink
f Add PayjoinScheduler
Browse files Browse the repository at this point in the history
  • Loading branch information
jbesraa committed Feb 28, 2024
1 parent e726227 commit 538e42c
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 132 deletions.
12 changes: 12 additions & 0 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::logger::{log_error, FilesystemLogger, Logger};
use crate::message_handler::NodeCustomMessageHandler;
use crate::payment_store::PaymentStore;
use crate::peer_store::PeerStore;
use crate::pj::{PayjoinExecuter, PayjoinScheduler, PendingChannels};
use crate::sweep::OutputSweeper;
use crate::tx_broadcaster::TransactionBroadcaster;
use crate::types::{
Expand Down Expand Up @@ -943,6 +944,15 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
},
};

let payjoin_executer = Arc::new(PayjoinExecuter::new(
Arc::clone(&wallet),
Arc::clone(&logger),
Arc::clone(&peer_manager),
Arc::clone(&channel_manager),
));

let pending_channels = Arc::new(Mutex::new(PendingChannels::new()));

let (stop_sender, stop_receiver) = tokio::sync::watch::channel(());

Ok(Node {
Expand All @@ -958,6 +968,8 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
channel_manager,
chain_monitor,
output_sweeper,
payjoin_executer,
pending_channels,
peer_manager,
keys_manager,
network_graph,
Expand Down
6 changes: 6 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ pub(crate) const WALLET_SYNC_INTERVAL_MINIMUM_SECS: u64 = 10;
// The length in bytes of our wallets' keys seed.
pub(crate) const WALLET_KEYS_SEED_LEN: usize = 64;

// Port used by the Payjoin HTTP server.
pub(crate) const DEFAULT_PAYJOIN_HTTP_SERVER_PORT: u16 = 3227;

#[derive(Debug, Clone)]
/// Represents the configuration of an [`Node`] instance.
///
Expand Down Expand Up @@ -104,6 +107,8 @@ pub struct Config {
///
/// Any messages below this level will be excluded from the logs.
pub log_level: LogLevel,
/// Payjoin server port
pub payjoin_server_port: u16,
}

impl Default for Config {
Expand All @@ -120,6 +125,7 @@ impl Default for Config {
trusted_peers_0conf: Vec::new(),
probing_liquidity_limit_multiplier: DEFAULT_PROBING_LIQUIDITY_LIMIT_MULTIPLIER,
log_level: DEFAULT_LOG_LEVEL,
payjoin_server_port: DEFAULT_PAYJOIN_HTTP_SERVER_PORT,
}
}
}
Expand Down
66 changes: 53 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,18 @@ mod wallet;
pub use bip39;
pub use bitcoin;
pub use lightning;
use lightning::routing::gossip::NodeId;
pub use lightning_invoice;

pub use balance::{BalanceDetails, LightningBalance, PendingSweepBalance};
pub use config::{default_config, Config};
pub use error::Error as NodeError;
use error::Error;

use ::payjoin::Uri;
use payjoin::Uri;
pub use event::Event;
use pj::{PayjoinExecuter, PayjoinScheduler, PendingChannels};
use tokio::sync::mpsc;
pub use types::ChannelConfig;

pub use io::utils::generate_entropy_mnemonic;
Expand Down Expand Up @@ -172,6 +175,8 @@ use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime};
use std::{default::Default, str::FromStr};

use crate::pj::{PayjoinRequest, PayjoinResponse, ScheduledChannel};

#[cfg(feature = "uniffi")]
uniffi::include_scaffolding!("ldk_node");

Expand All @@ -191,6 +196,8 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
channel_manager: Arc<ChannelManager<K>>,
chain_monitor: Arc<ChainMonitor<K>>,
output_sweeper: Arc<Sweeper<K>>,
pending_channels: Arc<Mutex<PendingChannels>>,
payjoin_executer: Arc<PayjoinExecuter<K>>,
peer_manager: Arc<PeerManager<K>>,
keys_manager: Arc<KeysManager>,
network_graph: Arc<NetworkGraph>,
Expand Down Expand Up @@ -470,21 +477,29 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
use tokio::net::TcpListener;

// Start the HTTP server for payjoin
let wallet = Arc::clone(&self.wallet);
let (payjoin_queue_sender, mut payjoin_queue_receiver) = mpsc::channel::<PayjoinRequest>(1);
let executor = Arc::clone(&self.payjoin_executer);
// listen for payjoin_queue_receiver
runtime.spawn(async move {
loop {
let payjoin_request = payjoin_queue_receiver.recv().await.unwrap();
Self::create_channel_from_pj(payjoin_request, executor.clone()).await;
}
});

let pj_port = self.config.payjoin_server_port;
runtime.spawn(async move {
let addr = SocketAddr::from(([127, 0, 0, 1], PAYJOIN_HTTP_SERVER_PORT));
let addr = SocketAddr::from(([127, 0, 0, 1], pj_port));
let listener = TcpListener::bind(addr).await.unwrap();
dbg!("Started HTTP server on http://{}", addr);
// let our_pubkey= wallet.get_new_address().unwrap().script_pubkey().into_bytes();
let create_channel_request = pj::CreateChannelRequest::init(wallet);
let pj_scheduler = pj::PayjoinScheduler::new(payjoin_queue_sender);
loop {
let (stream, _) = listener.accept().await.unwrap();
let io = TokioIo::new(stream);
let clone_ccr = create_channel_request.clone();
let clone_pj_scheduler = pj_scheduler.clone();
tokio::task::spawn(async move {
if let Err(err) = http1::Builder::new()
.serve_connection(io, clone_ccr)
.await
if let Err(err) =
http1::Builder::new().serve_connection(io, clone_pj_scheduler).await
{
println!("Failed to serve connection: {:?}", err);
}
Expand Down Expand Up @@ -705,11 +720,36 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
self.runtime.read().unwrap().is_some()
}

/// Request Payjoin Payment
pub fn payjoin_uri(&self) -> Result<String, Error> {
async fn create_channel_from_pj(
pj_req: PayjoinRequest, _payjoin_executer: Arc<PayjoinExecuter<K>>,
) {
let psbt = pj_req.clone().original_psbt();
let pj_response = PayjoinResponse::new(psbt);
// Send OpenChannel message
// Wait for AcceptChannel message
// Send FundingCreated message
// Wait for FundingSigned message
// Build PayjoinResponse
// Send PayjoinResponse to queue
pj_req.clone().queue(pj_response);
}

/// Request a new channel to be opened with a remote peer.
pub fn payjoin_channel(
&self, channel_amount_sats: u64, push_msat: Option<u64>, announce_channel: bool,
node_id: PublicKey,
) -> Result<String, Error> {
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
self.pending_channels.lock().unwrap().push(ScheduledChannel::new(
channel_amount_sats,
push_msat,
user_channel_id,
announce_channel,
node_id,
));
let address = self.wallet.get_new_address()?;
let amount = Amount::from_sat(1000);
let pj = "https://0.0.0.0:3227/payjoin";
let amount = Amount::from_sat(channel_amount_sats);
let pj = format!("https://0.0.0.0:{}/payjoin", self.config.payjoin_server_port);
let pj_uri_string = format!("{}?amount={}&pj={}", address.to_qr_uri(), amount.to_btc(), pj);
assert!(Uri::from_str(&pj_uri_string).is_ok());
Ok(pj_uri_string)
Expand Down

0 comments on commit 538e42c

Please sign in to comment.