Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit 8e23b93

Browse files
committed
Persist payjoin sessions
1 parent 9759f1a commit 8e23b93

3 files changed

Lines changed: 56 additions & 1 deletion

File tree

mutiny-core/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
type_alias_bounds
99
)]
1010
extern crate core;
11+
extern crate payjoin as pj;
1112

1213
pub mod auth;
1314
mod chain;
@@ -30,6 +31,7 @@ mod node;
3031
pub mod nodemanager;
3132
pub mod nostr;
3233
mod onchain;
34+
mod payjoin;
3335
mod peermanager;
3436
pub mod scorer;
3537
pub mod storage;
@@ -44,6 +46,7 @@ use crate::event::{HTLCStatus, MillisatAmount, PaymentInfo};
4446
pub use crate::gossip::{GOSSIP_SYNC_TIME_KEY, NETWORK_GRAPH_KEY, PROB_SCORER_KEY};
4547
pub use crate::keymanager::generate_seed;
4648
pub use crate::ldkstorage::{CHANNEL_MANAGER_KEY, MONITORS_PREFIX_KEY};
49+
use crate::payjoin::PayjoinStorage;
4750
use crate::storage::{
4851
list_payment_info, MutinyStorage, DEVICE_ID_KEY, EXPECTED_NETWORK_KEY, NEED_FULL_SYNC_KEY,
4952
};
@@ -794,6 +797,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
794797
// when we restart, gen a new session id
795798
self.node_manager = Arc::new(nm_builder.build().await?);
796799
NodeManager::start_sync(self.node_manager.clone());
800+
NodeManager::resume_payjoins(self.node_manager.clone());
797801

798802
Ok(())
799803
}
@@ -1073,7 +1077,7 @@ impl<S: MutinyStorage> MutinyWallet<S> {
10731077
.await
10741078
.unwrap();
10751079

1076-
let mut enroller = payjoin::receive::v2::Enroller::from_relay_config(
1080+
let mut enroller = pj::receive::v2::Enroller::from_relay_config(
10771081
PAYJOIN_DIR,
10781082
&ohttp_config_base64,
10791083
OHTTP_RELAYS[0], // TODO pick ohttp relay at random
@@ -1092,6 +1096,10 @@ impl<S: MutinyStorage> MutinyWallet<S> {
10921096
.process_res(ohttp_response.as_ref(), context)
10931097
.map_err(|e| anyhow!("parse error {}", e))
10941098
.unwrap();
1099+
self.node_manager
1100+
.storage
1101+
.persist_payjoin(enrolled.clone())
1102+
.unwrap();
10951103
let pj_uri = enrolled.fallback_target();
10961104
log_debug!(self.logger, "{pj_uri}");
10971105
let wallet = self.node_manager.wallet.clone();

mutiny-core/src/nodemanager.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::event::HTLCStatus;
22
use crate::labels::LabelStorage;
33
use crate::logging::LOGGING_KEY;
4+
use crate::payjoin::PayjoinStorage;
45
use crate::utils::{sleep, spawn};
56
use crate::ActivityItem;
67
use crate::MutinyInvoice;
@@ -575,6 +576,19 @@ impl<S: MutinyStorage> NodeManager<S> {
575576
Ok(())
576577
}
577578

579+
/// Starts a background task to poll payjoin sessions to attempt receiving.
580+
pub(crate) fn resume_payjoins(nm: Arc<NodeManager<S>>) {
581+
let all = nm.storage.get_payjoins().unwrap_or_default();
582+
for payjoin in all {
583+
let wallet = nm.wallet.clone();
584+
let stop = nm.stop.clone();
585+
utils::spawn(async move {
586+
let pj_txid = Self::receive_payjoin(wallet, stop, payjoin).await.unwrap();
587+
log::info!("Received payjoin txid: {}", pj_txid);
588+
});
589+
}
590+
}
591+
578592
/// Creates a background process that will sync the wallet with the blockchain.
579593
/// This will also update the fee estimates every 10 minutes.
580594
pub fn start_sync(nm: Arc<NodeManager<S>>) {

mutiny-core/src/payjoin.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
use crate::error::MutinyError;
2+
use crate::storage::MutinyStorage;
3+
use bitcoin::hashes::hex::ToHex;
4+
use payjoin::receive::v2::Enrolled;
5+
use std::collections::HashMap;
6+
7+
pub trait PayjoinStorage {
8+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError>;
9+
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError>;
10+
fn persist_payjoin(&self, session: Enrolled) -> Result<(), MutinyError>;
11+
}
12+
13+
const PAYJOIN_KEY_PREFIX: &str = "payjoin/";
14+
15+
fn get_payjoin_key(id: &[u8; 33]) -> String {
16+
format!("{PAYJOIN_KEY_PREFIX}{}", id.to_hex())
17+
}
18+
19+
impl<S: MutinyStorage> PayjoinStorage for S {
20+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError> {
21+
let sessions = self.get_data(get_payjoin_key(id))?;
22+
Ok(sessions)
23+
}
24+
25+
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError> {
26+
let map: HashMap<String, Enrolled> = self.scan(PAYJOIN_KEY_PREFIX, None)?;
27+
Ok(map.values().map(|v| v.to_owned()).collect())
28+
}
29+
30+
fn persist_payjoin(&self, session: Enrolled) -> Result<(), MutinyError> {
31+
self.set_data(get_payjoin_key(&session.pubkey()), session, None)
32+
}
33+
}

0 commit comments

Comments
 (0)