Skip to content

Commit 5964414

Browse files
committed
working POC
1 parent 01c12b7 commit 5964414

File tree

9 files changed

+564
-183
lines changed

9 files changed

+564
-183
lines changed

Cargo.toml

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,15 @@ panic = 'abort' # Abort on panic
2828
default = []
2929

3030
[dependencies]
31-
lightning = { version = "0.0.121", features = ["std"] }
32-
lightning-invoice = { version = "0.29.0" }
33-
lightning-net-tokio = { version = "0.0.121" }
34-
lightning-persister = { version = "0.0.121" }
35-
lightning-background-processor = { version = "0.0.121", features = ["futures"] }
36-
lightning-rapid-gossip-sync = { version = "0.0.121" }
37-
lightning-transaction-sync = { version = "0.0.121", features = ["esplora-async-https", "time"] }
38-
lightning-liquidity = { version = "0.1.0-alpha.1", features = ["std"] }
31+
# lightning = { version = "0.0.121", features = ["std"] }
32+
lightning = { path = "../rust-lightning/lightning", features = ["std"] }
33+
# lightning-invoice = { version = "0.29.0" }
34+
# lightning-net-tokio = { version = "0.0.121" }
35+
# lightning-persister = { version = "0.0.121" }
36+
# lightning-background-processor = { version = "0.0.121", features = ["futures"] }
37+
# lightning-rapid-gossip-sync = { version = "0.0.121" }
38+
# lightning-transaction-sync = { version = "0.0.121", features = ["esplora-async-https", "time"] }
39+
# lightning-liquidity = { version = "0.1.0-alpha.1", features = ["std"] }
3940

4041
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["std"] }
4142
#lightning-invoice = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main" }
@@ -46,14 +47,13 @@ lightning-liquidity = { version = "0.1.0-alpha.1", features = ["std"] }
4647
#lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["esplora-async"] }
4748
#lightning-liquidity = { git = "https://github.com/lightningdevkit/lightning-liquidity", branch="main", features = ["std"] }
4849

49-
#lightning = { path = "../rust-lightning/lightning", features = ["std"] }
50-
#lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
51-
#lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
52-
#lightning-persister = { path = "../rust-lightning/lightning-persister" }
53-
#lightning-background-processor = { path = "../rust-lightning/lightning-background-processor", features = ["futures"] }
54-
#lightning-rapid-gossip-sync = { path = "../rust-lightning/lightning-rapid-gossip-sync" }
55-
#lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync", features = ["esplora-async"] }
56-
#lightning-liquidity = { path = "../lightning-liquidity", features = ["std"] }
50+
lightning-invoice = { path = "../rust-lightning/lightning-invoice" }
51+
lightning-net-tokio = { path = "../rust-lightning/lightning-net-tokio" }
52+
lightning-persister = { path = "../rust-lightning/lightning-persister" }
53+
lightning-background-processor = { path = "../rust-lightning/lightning-background-processor", features = ["futures"] }
54+
lightning-rapid-gossip-sync = { path = "../rust-lightning/lightning-rapid-gossip-sync" }
55+
lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync", features = ["esplora-async"] }
56+
lightning-liquidity = { path = "../lightning-liquidity", features = ["std"] }
5757

5858
bdk = { version = "0.29.0", default-features = false, features = ["std", "async-interface", "use-esplora-async", "sqlite-bundled", "keys-bip39"]}
5959

@@ -83,7 +83,8 @@ prost = { version = "0.11.6", default-features = false}
8383
winapi = { version = "0.3", features = ["winbase"] }
8484

8585
[dev-dependencies]
86-
lightning = { version = "0.0.121", features = ["std", "_test_utils"] }
86+
lightning = { path = "../rust-lightning/lightning", features = ["std", "_test_utils"] }
87+
# lightning = { version = "0.0.121", features = ["std", "_test_utils"] }
8788
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", branch="main", features = ["std", "_test_utils"] }
8889
electrum-client = { version = "0.15.1", default-features = true }
8990
bitcoincore-rpc = { version = "0.17.0", default-features = false }

src/builder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::logger::{log_error, FilesystemLogger, Logger};
1212
use crate::message_handler::NodeCustomMessageHandler;
1313
use crate::payment_store::PaymentStore;
1414
use crate::peer_store::PeerStore;
15+
use crate::pj_new_crate::ChannelScheduler;
1516
use crate::pjoin::LDKPayjoinExecuter;
1617
use crate::sweep::OutputSweeper;
1718
use crate::tx_broadcaster::TransactionBroadcaster;
@@ -558,6 +559,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
558559
log_error!(logger, "Failed to set up wallet: {}", e);
559560
BuildError::WalletSetupFailed
560561
})?;
562+
let channel_scheduler = Arc::new(tokio::sync::Mutex::new(ChannelScheduler::new()));
561563

562564
let (blockchain, tx_sync, tx_broadcaster, fee_estimator) = match chain_data_source_config {
563565
Some(ChainDataSourceConfig::Esplora(server_url)) => {
@@ -568,6 +570,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
568570
let tx_broadcaster = Arc::new(TransactionBroadcaster::new(
569571
tx_sync.client().clone(),
570572
Arc::clone(&logger),
573+
Arc::clone(&channel_scheduler)
571574
));
572575
let fee_estimator = Arc::new(OnchainFeeEstimator::new(
573576
tx_sync.client().clone(),
@@ -586,6 +589,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
586589
let tx_broadcaster = Arc::new(TransactionBroadcaster::new(
587590
tx_sync.client().clone(),
588591
Arc::clone(&logger),
592+
Arc::clone(&channel_scheduler)
589593
));
590594
let fee_estimator = Arc::new(OnchainFeeEstimator::new(
591595
tx_sync.client().clone(),
@@ -952,6 +956,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
952956
Arc::clone(&logger),
953957
Arc::clone(&peer_manager),
954958
Arc::clone(&channel_manager),
959+
Arc::clone(&channel_scheduler)
955960
);
956961
let payjoin = Arc::new(LDKPayjoin::new(payjoin_executer));
957962

@@ -975,6 +980,7 @@ fn build_with_store_internal<K: KVStore + Sync + Send + 'static>(
975980
chain_monitor,
976981
output_sweeper,
977982
payjoin,
983+
channel_scheduler,
978984
peer_manager,
979985
keys_manager,
980986
network_graph,

src/event.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::pj_new_crate::{ChannelScheduler, FundingTxParams};
12
use crate::types::{Sweeper, Wallet};
23
use crate::{
34
hex_utils, ChannelManager, Config, Error, NetworkGraph, PeerInfo, PeerStore, UserChannelId,
@@ -292,7 +293,7 @@ impl Future for EventFuture {
292293
}
293294
}
294295

295-
pub(crate) struct EventHandler<K: KVStore + Sync + Send, L: Deref>
296+
pub(crate) struct EventHandler<K: KVStore + Sync + Send + 'static, L: Deref>
296297
where
297298
L::Target: Logger,
298299
{
@@ -302,6 +303,7 @@ where
302303
output_sweeper: Arc<Sweeper<K>>,
303304
network_graph: Arc<NetworkGraph>,
304305
payment_store: Arc<PaymentStore<K, L>>,
306+
channel_scheduler: Arc<tokio::sync::Mutex<ChannelScheduler>>,
305307
peer_store: Arc<PeerStore<K, L>>,
306308
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>,
307309
logger: L,
@@ -317,7 +319,7 @@ where
317319
channel_manager: Arc<ChannelManager<K>>, output_sweeper: Arc<Sweeper<K>>,
318320
network_graph: Arc<NetworkGraph>, payment_store: Arc<PaymentStore<K, L>>,
319321
peer_store: Arc<PeerStore<K, L>>, runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>,
320-
logger: L, config: Arc<Config>,
322+
logger: L, config: Arc<Config>, channel_scheduler: Arc<tokio::sync::Mutex<ChannelScheduler>>,
321323
) -> Self {
322324
Self {
323325
event_queue,
@@ -326,6 +328,7 @@ where
326328
output_sweeper,
327329
network_graph,
328330
payment_store,
331+
channel_scheduler,
329332
peer_store,
330333
logger,
331334
runtime,
@@ -340,8 +343,10 @@ where
340343
counterparty_node_id,
341344
channel_value_satoshis,
342345
output_script,
346+
user_channel_id,
343347
..
344348
} => {
349+
dbg!("Entered FundingGenerationReady event handler");
345350
// Construct the raw transaction with the output that is paid the amount of the
346351
// channel.
347352
let confirmation_target = ConfirmationTarget::NonAnchorChannelFee;
@@ -350,6 +355,22 @@ where
350355
let cur_height = self.channel_manager.current_best_block().height();
351356
let locktime = LockTime::from_height(cur_height).unwrap_or(LockTime::ZERO);
352357

358+
// payjoin scenario
359+
let mut channel_scheduler = self.channel_scheduler.lock().await;
360+
if channel_scheduler.channel(user_channel_id).is_some() {
361+
dbg!("Entered payjoin channel scheduler scenario");
362+
let funding_tx_params = FundingTxParams::new(
363+
output_script.clone().into_bytes(),
364+
confirmation_target,
365+
locktime,
366+
temporary_channel_id
367+
);
368+
channel_scheduler.add_funding_tx_params(user_channel_id, funding_tx_params);
369+
dbg!("payjoin channel scheduler scenario completed");
370+
return {};
371+
}
372+
dbg!("Didnt enter payjoin channel scheduler scenario");
373+
353374
// Sign the final funding transaction and broadcast it.
354375
match self.wallet.create_funding_transaction(
355376
output_script,

src/lib.rs

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub use error::Error as NodeError;
109109
use error::Error;
110110

111111
pub use event::Event;
112+
use pj_new_crate::ChannelScheduler;
112113
pub use types::{BestBlock, ChannelConfig};
113114
use payjoin::Uri;
114115
mod pjoin;
@@ -195,6 +196,7 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
195196
chain_monitor: Arc<ChainMonitor<K>>,
196197
output_sweeper: Arc<Sweeper<K>>,
197198
payjoin: Arc<LDKPayjoin<K>>,
199+
channel_scheduler: Arc<tokio::sync::Mutex<ChannelScheduler>>,
198200
peer_manager: Arc<PeerManager<K>>,
199201
keys_manager: Arc<KeysManager>,
200202
network_graph: Arc<NetworkGraph>,
@@ -667,6 +669,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
667669
Arc::clone(&self.runtime),
668670
Arc::clone(&self.logger),
669671
Arc::clone(&self.config),
672+
Arc::clone(&self.channel_scheduler),
670673
));
671674

672675
// Setup background processing
@@ -738,18 +741,33 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
738741

739742
/// Request a new channel to be opened with a remote peer.
740743
pub async fn schedule_payjoin_channel(
741-
&self, channel_amount_sats: u64, push_msat: Option<u64>, announce_channel: bool,
744+
&self,
745+
channel_amount_sats: u64,
746+
push_msat: Option<u64>,
747+
announce_channel: bool,
742748
node_id: PublicKey,
749+
address: SocketAddress,
743750
) -> Result<String, Error> {
751+
let user_channel_id: u128 = rand::thread_rng().gen::<u128>();
744752
let channel =
745-
ScheduledChannel::new(channel_amount_sats, push_msat, announce_channel, node_id);
746-
self.payjoin.schedule(channel).await;
753+
ScheduledChannel::new(channel_amount_sats, push_msat, announce_channel, node_id, user_channel_id, None, None);
754+
self.channel_scheduler.lock().await.schedule(channel);
755+
let announce_channel = true;
756+
self.connect_open_channel_payjoin(
757+
node_id,
758+
address,
759+
channel_amount_sats,
760+
None,
761+
None,
762+
announce_channel,
763+
user_channel_id
764+
)?; // this should be stopped after `ACCEPT_CHANNEL`
747765
let bip21 = self.payjoin_bip21(channel_amount_sats);
748766
bip21
749767
}
750768

751769
/// Generate a BIP21 URI for a payjoin request.
752-
pub fn payjoin_bip21(&self, amount_sats: u64) -> Result<String, Error> {
770+
fn payjoin_bip21(&self, amount_sats: u64) -> Result<String, Error> {
753771
let address = self.wallet.get_new_address()?;
754772
let amount = Amount::from_sat(amount_sats);
755773
let pj = format!("https://0.0.0.0:{}/payjoin", self.config.payjoin_server_port);
@@ -760,7 +778,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
760778

761779
/// List all scheduled payjoin channels.
762780
pub async fn list_scheduled_channels(&self) -> Result<Vec<ScheduledChannel>, Error> {
763-
Ok(self.payjoin.list_scheduled_channels().await)
781+
Ok(self.channel_scheduler.lock().await.channels.clone())
764782
}
765783

766784
/// Disconnects all peers, stops all running background tasks, and shuts down [`Node`].
@@ -973,6 +991,76 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
973991
Ok(())
974992
}
975993

994+
/// included `user_channel_id` in inputs
995+
pub fn connect_open_channel_payjoin(
996+
&self, node_id: PublicKey, address: SocketAddress, channel_amount_sats: u64,
997+
push_to_counterparty_msat: Option<u64>, channel_config: Option<Arc<ChannelConfig>>,
998+
announce_channel: bool, user_channel_id: u128,
999+
) -> Result<UserChannelId, Error> {
1000+
let rt_lock = self.runtime.read().unwrap();
1001+
if rt_lock.is_none() {
1002+
return Err(Error::NotRunning);
1003+
}
1004+
let runtime = rt_lock.as_ref().unwrap();
1005+
1006+
// let cur_balance = self.wallet.get_balance()?;
1007+
// if cur_balance.get_spendable() < channel_amount_sats {
1008+
// log_error!(self.logger, "Unable to create channel due to insufficient funds.");
1009+
// return Err(Error::InsufficientFunds);
1010+
// }
1011+
1012+
let peer_info = PeerInfo { node_id, address };
1013+
1014+
let con_node_id = peer_info.node_id;
1015+
let con_addr = peer_info.address.clone();
1016+
let con_logger = Arc::clone(&self.logger);
1017+
let con_pm = Arc::clone(&self.peer_manager);
1018+
1019+
// We need to use our main runtime here as a local runtime might not be around to poll
1020+
// connection futures going forward.
1021+
tokio::task::block_in_place(move || {
1022+
runtime.block_on(async move {
1023+
connect_peer_if_necessary(con_node_id, con_addr, con_pm, con_logger).await
1024+
})
1025+
})?;
1026+
1027+
let channel_config = (*(channel_config.unwrap_or_default())).clone().into();
1028+
let user_config = UserConfig {
1029+
channel_handshake_limits: Default::default(),
1030+
channel_handshake_config: ChannelHandshakeConfig {
1031+
announced_channel: announce_channel,
1032+
..Default::default()
1033+
},
1034+
channel_config,
1035+
..Default::default()
1036+
};
1037+
1038+
let push_msat = push_to_counterparty_msat.unwrap_or(0);
1039+
1040+
match self.channel_manager.create_channel(
1041+
peer_info.node_id,
1042+
channel_amount_sats,
1043+
push_msat,
1044+
user_channel_id,
1045+
None,
1046+
Some(user_config),
1047+
) {
1048+
Ok(_) => {
1049+
log_info!(
1050+
self.logger,
1051+
"Initiated channel creation with peer {}. ",
1052+
peer_info.node_id
1053+
);
1054+
self.peer_store.add_peer(peer_info)?;
1055+
Ok(UserChannelId(user_channel_id))
1056+
},
1057+
Err(e) => {
1058+
log_error!(self.logger, "Failed to initiate channel creation: {:?}", e);
1059+
Err(Error::ChannelCreationFailed)
1060+
},
1061+
}
1062+
}
1063+
9761064
/// Connect to a node and open a new channel. Disconnects and re-connects are handled automatically
9771065
///
9781066
/// Disconnects and reconnects are handled automatically.
@@ -1964,3 +2052,15 @@ async fn do_connect_peer<K: KVStore + Sync + Send + 'static>(
19642052
},
19652053
}
19662054
}
2055+
2056+
2057+
// 1. user schedule channel
2058+
// 1.1 qrcode created to scan
2059+
// 2. user scan qrcode
2060+
// 2.1 node receives payjoin request
2061+
// 2.2 http endpoint loops for x amount of time looking for PayjoinProposal
2062+
// 3. node scans if any scheduled channels waiting
2063+
// 3.1 node creates the requested channel
2064+
// 4. node wait for payjoin channel open requests in FundingGenerationReady state
2065+
// 4.1 node creates funding tx with payjoin incoming transaction
2066+
// 4.2 save in channel scheduler

0 commit comments

Comments
 (0)