Skip to content

Commit 2b21745

Browse files
committed
f
1 parent e5f3a6b commit 2b21745

File tree

7 files changed

+152
-67
lines changed

7 files changed

+152
-67
lines changed

src/builder.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use crate::io::sqlite_store::SqliteStore;
1111
use crate::liquidity::LiquiditySource;
1212
use crate::logger::{log_error, log_info, FilesystemLogger, Logger};
1313
use crate::message_handler::NodeCustomMessageHandler;
14-
use crate::payment::payjoin::send::PayjoinSender;
1514
use crate::payjoin_receiver::PayjoinReceiver;
15+
use crate::payment::payjoin::send::PayjoinSender;
1616
use crate::payment::store::PaymentStore;
1717
use crate::peer_store::PeerStore;
1818
use crate::tx_broadcaster::TransactionBroadcaster;
@@ -269,15 +269,19 @@ impl NodeBuilder {
269269
pub fn set_payjoin_config(
270270
&mut self, payjoin_directory: String, payjoin_relay: String, ohttp_keys: Option<String>,
271271
) -> Result<&mut Self, BuildError> {
272-
let payjoin_relay = payjoin::Url::parse(&payjoin_relay).map_err(|_| BuildError::InvalidPayjoinConfig)?;
273-
let payjoin_directory = payjoin::Url::parse(&payjoin_directory).map_err(|_| BuildError::InvalidPayjoinConfig)?;
272+
let payjoin_relay =
273+
payjoin::Url::parse(&payjoin_relay).map_err(|_| BuildError::InvalidPayjoinConfig)?;
274+
let payjoin_directory = payjoin::Url::parse(&payjoin_directory)
275+
.map_err(|_| BuildError::InvalidPayjoinConfig)?;
274276
let ohttp_keys = if let Some(ohttp_keys) = ohttp_keys {
275277
let keys = match payjoin::OhttpKeys::decode(ohttp_keys.as_bytes()) {
276278
Ok(keys) => keys,
277279
Err(_) => return Err(BuildError::InvalidPayjoinConfig),
278280
};
279281
Some(keys)
280-
} else { None };
282+
} else {
283+
None
284+
};
281285
self.payjoin_config = Some(PayjoinConfig { payjoin_directory, payjoin_relay, ohttp_keys });
282286
Ok(self)
283287
}
@@ -491,8 +495,14 @@ impl ArcedNodeBuilder {
491495
}
492496

493497
/// Configures the [`Node`] instance to enable payjoin transactions.
494-
pub fn set_payjoin_config(&self, payjoin_directory: String, payjoin_relay: String, ohttp_keys: Option<String>) -> Result<(), BuildError> {
495-
self.inner.write().unwrap().set_payjoin_config(payjoin_directory, payjoin_relay, ohttp_keys).map(|_| ())
498+
pub fn set_payjoin_config(
499+
&self, payjoin_directory: String, payjoin_relay: String, ohttp_keys: Option<String>,
500+
) -> Result<(), BuildError> {
501+
self.inner
502+
.write()
503+
.unwrap()
504+
.set_payjoin_config(payjoin_directory, payjoin_relay, ohttp_keys)
505+
.map(|_| ())
496506
}
497507

498508
/// Configures the [`Node`] instance to source its gossip data from the given RapidGossipSync
@@ -1014,10 +1024,9 @@ fn build_with_store_internal(
10141024
if let Some(pj_config) = payjoin_config {
10151025
payjoin_sender = Some(Arc::new(PayjoinSender::new(
10161026
Arc::clone(&logger),
1027+
Arc::clone(&wallet),
10171028
pj_config.payjoin_relay.clone(),
10181029
)));
1019-
dbg!("directory", pj_config.payjoin_directory.clone());
1020-
dbg!("relay", pj_config.payjoin_relay.clone());
10211030
payjoin_receiver = Some(Arc::new(PayjoinReceiver::new(
10221031
Arc::clone(&logger),
10231032
Arc::clone(&wallet),

src/lib.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ pub use error::Error as NodeError;
111111
use error::Error;
112112

113113
pub use event::Event;
114-
use payment::payjoin::send::PayjoinSender;
115114
use payjoin_receiver::PayjoinReceiver;
115+
use payment::payjoin::send::PayjoinSender;
116116
pub use types::ChannelConfig;
117117

118118
pub use io::utils::generate_entropy_mnemonic;
@@ -374,6 +374,10 @@ impl Node {
374374
let archive_cmon = Arc::clone(&self.chain_monitor);
375375
let sync_sweeper = Arc::clone(&self.output_sweeper);
376376
let sync_logger = Arc::clone(&self.logger);
377+
let sync_payjoin = match &self.payjoin_sender {
378+
Some(sender) => Some(Arc::clone(sender)),
379+
None => None,
380+
};
377381
let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp);
378382
let sync_monitor_archival_height = Arc::clone(&self.latest_channel_monitor_archival_height);
379383
let mut stop_sync = self.stop_sender.subscribe();
@@ -393,12 +397,15 @@ impl Node {
393397
return;
394398
}
395399
_ = wallet_sync_interval.tick() => {
396-
let confirmables = vec![
397-
&*sync_cman as &(dyn Confirm + Sync + Send),
398-
&*sync_cmon as &(dyn Confirm + Sync + Send),
399-
&*sync_sweeper as &(dyn Confirm + Sync + Send),
400-
];
401-
let now = Instant::now();
400+
let mut confirmables = vec![
401+
&*sync_cman as &(dyn Confirm + Sync + Send),
402+
&*sync_cmon as &(dyn Confirm + Sync + Send),
403+
&*sync_sweeper as &(dyn Confirm + Sync + Send),
404+
];
405+
if let Some(sync_payjoin) = sync_payjoin.as_ref() {
406+
confirmables.push(sync_payjoin.as_ref() as &(dyn Confirm + Sync + Send));
407+
}
408+
let now = Instant::now();
402409
let timeout_fut = tokio::time::timeout(Duration::from_secs(LDK_WALLET_SYNC_TIMEOUT_SECS), tx_sync.sync(confirmables));
403410
match timeout_fut.await {
404411
Ok(res) => match res {
@@ -1348,11 +1355,15 @@ impl Node {
13481355
let fee_estimator = Arc::clone(&self.fee_estimator);
13491356
let sync_sweeper = Arc::clone(&self.output_sweeper);
13501357
let sync_logger = Arc::clone(&self.logger);
1351-
let confirmables = vec![
1358+
let sync_payjoin = &self.payjoin_sender.as_ref();
1359+
let mut confirmables = vec![
13521360
&*sync_cman as &(dyn Confirm + Sync + Send),
13531361
&*sync_cmon as &(dyn Confirm + Sync + Send),
13541362
&*sync_sweeper as &(dyn Confirm + Sync + Send),
13551363
];
1364+
if let Some(sync_payjoin) = sync_payjoin {
1365+
confirmables.push(sync_payjoin.as_ref() as &(dyn Confirm + Sync + Send));
1366+
}
13561367
let sync_wallet_timestamp = Arc::clone(&self.latest_wallet_sync_timestamp);
13571368
let sync_fee_rate_update_timestamp =
13581369
Arc::clone(&self.latest_fee_rate_cache_update_timestamp);

src/payment/payjoin/mod.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
//! Holds a payment handler allowing to send Payjoin payments.
22
3-
use lightning::chain::chaininterface::BroadcasterInterface;
3+
use lightning::chain::{chaininterface::BroadcasterInterface, Filter};
44

55
use crate::config::{PAYJOIN_REQUEST_TOTAL_DURATION, PAYJOIN_RETRY_INTERVAL};
66
use crate::logger::{log_error, log_info, FilesystemLogger, Logger};
7-
use crate::types::{ChannelManager, Broadcaster, EventQueue, Wallet};
7+
use crate::types::{Broadcaster, ChannelManager, EventQueue, Wallet};
88
use crate::Event;
99
use bitcoin::secp256k1::PublicKey;
1010
use lightning::ln::msgs::SocketAddress;
@@ -81,9 +81,8 @@ pub struct PayjoinPayment {
8181
impl PayjoinPayment {
8282
pub(crate) fn new(
8383
runtime: Arc<RwLock<Option<tokio::runtime::Runtime>>>, sender: Option<Arc<PayjoinSender>>,
84-
receiver: Option<Arc<PayjoinReceiver>>,
85-
config: Arc<Config>, event_queue: Arc<EventQueue>, logger: Arc<FilesystemLogger>,
86-
wallet: Arc<Wallet>, tx_broadcaster: Arc<Broadcaster>,
84+
receiver: Option<Arc<PayjoinReceiver>>, config: Arc<Config>, event_queue: Arc<EventQueue>,
85+
logger: Arc<FilesystemLogger>, wallet: Arc<Wallet>, tx_broadcaster: Arc<Broadcaster>,
8786
peer_store: Arc<PeerStore<Arc<FilesystemLogger>>>, channel_manager: Arc<ChannelManager>,
8887
connection_manager: Arc<ConnectionManager<Arc<FilesystemLogger>>>,
8988
) -> Self {
@@ -175,6 +174,11 @@ impl PayjoinPayment {
175174
let is_signed = wallet.sign_payjoin_proposal(payjoin_proposal_psbt, &mut original_psbt.clone()).unwrap();
176175
if is_signed {
177176
let tx = payjoin_proposal_psbt.clone().extract_tx();
177+
let inputs = tx.output.clone();
178+
let input = inputs.iter().find(|input| {
179+
wallet.is_mine(&input.script_pubkey).unwrap_or(false)
180+
}).unwrap().script_pubkey.clone();
181+
payjoin_sender.register_tx(&tx.txid(), &input);
178182
tx_broadcaster.broadcast_transactions(&[&tx]);
179183
let txid = tx.txid();
180184
let _ = event_queue.add_event(Event::PayjoinPaymentPending { txid });
@@ -352,4 +356,3 @@ impl PayjoinPayment {
352356
// fn register_output(&self, output: WatchOutput) {
353357
// }
354358
// }
355-

src/payment/payjoin/send.rs

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,41 @@
1+
#![allow(unused_variables)]
12
use crate::config::{PAYJOIN_REQUEST_TIMEOUT, PAYJOIN_RETRY_INTERVAL};
23
use crate::io::utils::ohttp_headers;
34
use crate::logger::FilesystemLogger;
5+
use crate::types::Wallet;
46

7+
use bitcoin::block::Header;
8+
use bitcoin::{BlockHash, Script, ScriptBuf, Txid};
9+
use lightning::chain::transaction::TransactionData;
10+
use lightning::chain::WatchedOutput;
511
use lightning::util::logger::Logger;
612
use lightning::{log_error, log_info};
713

814
use std::sync::Arc;
915

16+
enum PayjoinTransaction {
17+
PendingInitialBroadcast,
18+
PendingFirstConfirmation,
19+
PendingThresholdConfirmation,
20+
}
21+
1022
pub(crate) struct PayjoinSender {
1123
logger: Arc<FilesystemLogger>,
24+
wallet: Arc<Wallet>,
1225
payjoin_relay: payjoin::Url,
26+
transaction_queue: std::sync::Mutex<Vec<(Txid, ScriptBuf)>>,
1327
}
1428

1529
impl PayjoinSender {
16-
pub(crate) fn new(logger: Arc<FilesystemLogger>, payjoin_relay: payjoin::Url) -> Self {
17-
Self { logger, payjoin_relay }
30+
pub(crate) fn new(
31+
logger: Arc<FilesystemLogger>, wallet: Arc<Wallet>, payjoin_relay: payjoin::Url,
32+
) -> Self {
33+
Self {
34+
logger,
35+
wallet,
36+
payjoin_relay,
37+
transaction_queue: std::sync::Mutex::new(Vec::new()),
38+
}
1839
}
1940

2041
pub(crate) fn payjoin_relay(&self) -> &payjoin::Url {
@@ -74,3 +95,47 @@ impl PayjoinSender {
7495
}
7596
}
7697
}
98+
99+
impl lightning::chain::Filter for PayjoinSender {
100+
fn register_tx(&self, txid: &Txid, script_pubkey: &Script) {
101+
dbg!("Registering transaction {:?}", txid);
102+
self.transaction_queue.lock().unwrap().push((txid.clone(), script_pubkey.into()));
103+
}
104+
fn register_output(&self, output: WatchedOutput) {}
105+
}
106+
107+
impl lightning::chain::Confirm for PayjoinSender {
108+
fn transactions_confirmed(&self, header: &Header, txdata: &TransactionData, height: u32) {
109+
dbg!("Confirmed transaction {:?}", txdata);
110+
// let (index, tx) = txdata[0];
111+
// let txid = tx.txid();
112+
// let my_input =
113+
// tx.input.iter().find(|input| self.wallet.is_mine(&input.script_sig).unwrap_or(false));
114+
// if let Some(my_input) = my_input {
115+
// self.transaction_queue.push((txid, my_input.script_sig))
116+
// }
117+
}
118+
fn transaction_unconfirmed(&self, txid: &Txid) {
119+
dbg!("Unconfirmed transaction {:?}", txid);
120+
}
121+
fn best_block_updated(&self, header: &Header, height: u32) {
122+
dbg!("Best block updated {:?}", header);
123+
}
124+
fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
125+
// let state_lock = self.sweeper_state.lock().unwrap();
126+
// state_lock
127+
// .outputs
128+
// .iter()
129+
// .filter_map(|o| match o.status {
130+
// OutputSpendStatus::PendingThresholdConfirmations {
131+
// ref latest_spending_tx,
132+
// confirmation_height,
133+
// confirmation_hash,
134+
// ..
135+
// } => Some((latest_spending_tx.txid(), confirmation_height, Some(confirmation_hash))),
136+
// _ => None,
137+
// })
138+
// .collect::<Vec<_>>()
139+
vec![]
140+
}
141+
}

src/wallet.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature};
3535
use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, SecretKey, Signing};
3636
use bitcoin::{ScriptBuf, Transaction, TxOut, Txid};
3737

38+
use std::collections::{BTreeMap, HashMap};
3839
use std::ops::{Deref, DerefMut};
3940
use std::sync::{Arc, Mutex, RwLock};
40-
use std::collections::{BTreeMap, HashMap};
4141
use std::time::Duration;
4242

4343
enum WalletSyncStatus {

tests/integration_tests_payjoin.rs

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
mod common;
22

33
use common::{
4-
expect_payjoin_payment_pending_event, generate_blocks_and_wait,
5-
premine_and_distribute_funds, setup_bitcoind_and_electrsd, setup_two_payjoin_nodes,
6-
wait_for_tx,
4+
expect_payjoin_payment_pending_event, generate_blocks_and_wait, premine_and_distribute_funds,
5+
setup_bitcoind_and_electrsd, setup_two_payjoin_nodes, wait_for_tx,
76
};
87

98
use bitcoin::Amount;
@@ -41,34 +40,35 @@ fn send_receive_regular_payjoin_transaction() {
4140
assert!(node_b_balance.total_onchain_balance_sats < premine_amount_sat - 80000);
4241
}
4342

44-
// #[test]
45-
// fn send_payjoin_with_amount() {
46-
// let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
47-
// let (node_a_pj_receiver, node_b_pj_sender) = setup_two_payjoin_nodes(&electrsd, false);
48-
// let addr_b = node_b_pj_sender.onchain_payment().new_address().unwrap();
49-
// let addr_a = node_a_pj_receiver.onchain_payment().new_address().unwrap();
50-
// let premine_amount_sat = 100_000_00;
51-
// premine_and_distribute_funds(
52-
// &bitcoind.client,
53-
// &electrsd.client,
54-
// vec![addr_b, addr_a],
55-
// Amount::from_sat(premine_amount_sat),
56-
// );
57-
// node_a_pj_receiver.sync_wallets().unwrap();
58-
// node_b_pj_sender.sync_wallets().unwrap();
59-
// assert_eq!(node_b_pj_sender.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
60-
// assert_eq!(node_a_pj_receiver.list_balances().spendable_onchain_balance_sats, 100_000_00);
61-
// assert_eq!(node_a_pj_receiver.next_event(), None);
62-
// let payjoin_payment = node_a_pj_receiver.payjoin_payment();
63-
// let payjoin_uri = payjoin_payment.receive(Amount::from_sat(100_000_000)).unwrap();
64-
// let payjoin_uri = payjoin_uri.to_string();
65-
// dbg!(&payjoin_uri);
66-
// let sender_payjoin_payment = node_b_pj_sender.payjoin_payment();
67-
// assert!(sender_payjoin_payment.send_with_amount(payjoin_uri, 80_000).is_ok());
68-
// let txid = expect_payjoin_tx_sent_successfully_event!(node_b_pj_sender);
69-
// wait_for_tx(&electrsd.client, txid);
70-
// generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);
71-
// node_b_pj_sender.sync_wallets().unwrap();
72-
// let node_b_balance = node_b_pj_sender.list_balances();
73-
// assert!(node_b_balance.total_onchain_balance_sats < premine_amount_sat - 80000);
74-
// }
43+
#[ignore]
44+
#[test]
45+
fn send_payjoin_with_amount() {
46+
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
47+
let (node_a_pj_receiver, node_b_pj_sender) = setup_two_payjoin_nodes(&electrsd, false);
48+
let addr_b = node_b_pj_sender.onchain_payment().new_address().unwrap();
49+
let addr_a = node_a_pj_receiver.onchain_payment().new_address().unwrap();
50+
let premine_amount_sat = 100_000_00;
51+
premine_and_distribute_funds(
52+
&bitcoind.client,
53+
&electrsd.client,
54+
vec![addr_b, addr_a],
55+
Amount::from_sat(premine_amount_sat),
56+
);
57+
node_a_pj_receiver.sync_wallets().unwrap();
58+
node_b_pj_sender.sync_wallets().unwrap();
59+
assert_eq!(node_b_pj_sender.list_balances().spendable_onchain_balance_sats, premine_amount_sat);
60+
assert_eq!(node_a_pj_receiver.list_balances().spendable_onchain_balance_sats, 100_000_00);
61+
assert_eq!(node_a_pj_receiver.next_event(), None);
62+
let payjoin_payment = node_a_pj_receiver.payjoin_payment();
63+
let payjoin_uri = payjoin_payment.receive(Amount::from_sat(100_000_000)).unwrap();
64+
let payjoin_uri = payjoin_uri.to_string();
65+
dbg!(&payjoin_uri);
66+
let sender_payjoin_payment = node_b_pj_sender.payjoin_payment();
67+
assert!(sender_payjoin_payment.send_with_amount(payjoin_uri, 80_000).is_ok());
68+
let txid = expect_payjoin_payment_pending_event!(node_b_pj_sender);
69+
wait_for_tx(&electrsd.client, txid);
70+
generate_blocks_and_wait(&bitcoind.client, &electrsd.client, 6);
71+
node_b_pj_sender.sync_wallets().unwrap();
72+
let node_b_balance = node_b_pj_sender.list_balances();
73+
assert!(node_b_balance.total_onchain_balance_sats < premine_amount_sat - 80000);
74+
}

tests/integration_tests_payjoin_with_channel_opening.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
mod common;
22

33
use common::{
4-
expect_channel_pending_event, expect_channel_ready_event,
5-
expect_payjoin_payment_pending_event, generate_blocks_and_wait,
6-
premine_and_distribute_funds, setup_bitcoind_and_electrsd, setup_two_payjoin_nodes,
7-
wait_for_tx,
4+
expect_channel_pending_event, expect_channel_ready_event, expect_payjoin_payment_pending_event,
5+
generate_blocks_and_wait, premine_and_distribute_funds, setup_bitcoind_and_electrsd,
6+
setup_two_payjoin_nodes, wait_for_tx,
87
};
98

109
use bitcoin::Amount;
1110
use ldk_node::Event;
1211

12+
#[ignore]
1313
#[test]
1414
fn send_receive_payjoin_transaction_with_channel_opening() {
1515
let (bitcoind, electrsd) = setup_bitcoind_and_electrsd();
@@ -64,10 +64,7 @@ fn send_receive_payjoin_transaction_with_channel_opening() {
6464

6565
assert_eq!(node_a_pj_receiver.list_peers().get(0).unwrap().is_connected, true);
6666
assert_eq!(node_a_pj_receiver.list_peers().get(0).unwrap().is_persisted, true);
67-
assert_eq!(
68-
node_a_pj_receiver.list_peers().get(0).unwrap().node_id,
69-
node_b_pj_sender.node_id()
70-
);
67+
assert_eq!(node_a_pj_receiver.list_peers().get(0).unwrap().node_id, node_b_pj_sender.node_id());
7168

7269
let invoice_amount_1_msat = 2500_000;
7370
let invoice =

0 commit comments

Comments
 (0)