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

Commit 4a681f2

Browse files
committed
Enable payjoin expiration
1 parent 6c58885 commit 4a681f2

File tree

2 files changed

+53
-21
lines changed

2 files changed

+53
-21
lines changed

mutiny-core/src/nodemanager.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,11 @@ impl<S: MutinyStorage> NodeManager<S> {
809809
for payjoin in all {
810810
let wallet = nm.wallet.clone();
811811
let stop = nm.stop.clone();
812+
let storage = Arc::new(nm.storage.clone());
812813
utils::spawn(async move {
813-
let pj_txid = Self::receive_payjoin(wallet, stop, payjoin).await.unwrap();
814+
let pj_txid = Self::receive_payjoin(wallet, stop, storage, payjoin)
815+
.await
816+
.unwrap();
814817
log::info!("Received payjoin txid: {}", pj_txid);
815818
});
816819
}
@@ -1057,14 +1060,17 @@ impl<S: MutinyStorage> NodeManager<S> {
10571060
.process_res(ohttp_response.as_ref(), context)
10581061
.map_err(|e| anyhow!("parse error {}", e))
10591062
.unwrap();
1060-
self.storage.persist_payjoin(enrolled.clone()).unwrap();
1063+
let session = self.storage.persist_payjoin(enrolled.clone()).unwrap();
10611064
let pj_uri = enrolled.fallback_target();
10621065
log_debug!(self.logger, "{pj_uri}");
10631066
// run await payjoin task in the background as it'll keep polling the relay
10641067
let wallet = self.wallet.clone();
10651068
let stop = self.stop.clone();
1069+
let storage = Arc::new(self.storage.clone());
10661070
utils::spawn(async move {
1067-
let pj_txid = Self::receive_payjoin(wallet, stop, enrolled).await.unwrap();
1071+
let pj_txid = Self::receive_payjoin(wallet, stop, storage, session)
1072+
.await
1073+
.unwrap();
10681074
log::info!("Received payjoin txid: {}", pj_txid);
10691075
});
10701076
Some(pj_uri)
@@ -1155,14 +1161,15 @@ impl<S: MutinyStorage> NodeManager<S> {
11551161
pub async fn receive_payjoin(
11561162
wallet: Arc<OnChainWallet<S>>,
11571163
stop: Arc<AtomicBool>,
1158-
mut enrolled: payjoin::receive::v2::Enrolled,
1164+
storage: Arc<S>,
1165+
mut session: crate::payjoin::Session,
11591166
) -> Result<Txid, MutinyError> {
11601167
let http_client = reqwest::Client::builder()
11611168
//.danger_accept_invalid_certs(true) ? is tls unchecked :O
11621169
.build()
11631170
.unwrap();
11641171
let proposal: payjoin::receive::v2::UncheckedProposal =
1165-
Self::poll_for_fallback_psbt(stop, &http_client, &mut enrolled)
1172+
Self::poll_for_fallback_psbt(stop, storage, &http_client, &mut session)
11661173
.await
11671174
.unwrap();
11681175
let payjoin_proposal = wallet.process_payjoin_proposal(proposal).unwrap();
@@ -1187,17 +1194,23 @@ impl<S: MutinyStorage> NodeManager<S> {
11871194

11881195
async fn poll_for_fallback_psbt(
11891196
stop: Arc<AtomicBool>,
1197+
storage: Arc<S>,
11901198
client: &reqwest::Client,
1191-
enroller: &mut payjoin::receive::v2::Enrolled,
1199+
session: &mut crate::payjoin::Session,
11921200
) -> Result<payjoin::receive::v2::UncheckedProposal, ()> {
11931201
loop {
11941202
if stop.load(Ordering::Relaxed) {
11951203
return Err(()); // stopped
11961204
}
1197-
let (req, context) = enroller.extract_req().unwrap();
1205+
if session.expiry < utils::now() {
1206+
let _ = storage.delete_payjoin(&session.enrolled.pubkey());
1207+
return Err(()); // expired
1208+
}
1209+
let (req, context) = session.enrolled.extract_req().unwrap();
11981210
let ohttp_response = client.post(req.url).body(req.body).send().await.unwrap();
11991211
let ohttp_response = ohttp_response.bytes().await.unwrap();
1200-
let proposal = enroller
1212+
let proposal = session
1213+
.enrolled
12011214
.process_res(ohttp_response.as_ref(), context)
12021215
.map_err(|e| anyhow!("parse error {}", e))
12031216
.unwrap();

mutiny-core/src/payjoin.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
11
use crate::error::MutinyError;
22
use crate::storage::MutinyStorage;
33
use bitcoin::hashes::hex::ToHex;
4+
use core::time::Duration;
45
use payjoin::receive::v2::Enrolled;
6+
use serde::{Deserialize, Serialize};
57
use std::collections::HashMap;
68

7-
// #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8-
// pub struct Session {
9-
// pub id: [u8; 16],
10-
// pub enrolled: Enrolled,
11-
// }
9+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10+
pub struct Session {
11+
pub enrolled: Enrolled,
12+
pub expiry: Duration,
13+
}
14+
15+
impl Session {
16+
pub fn pubkey(&self) -> [u8; 33] {
17+
self.enrolled.pubkey()
18+
}
19+
}
1220

1321
pub trait PayjoinStorage {
14-
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError>;
15-
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError>;
16-
fn persist_payjoin(&self, session: Enrolled) -> Result<(), MutinyError>;
22+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Session>, MutinyError>;
23+
fn get_payjoins(&self) -> Result<Vec<Session>, MutinyError>;
24+
fn persist_payjoin(&self, session: Enrolled) -> Result<Session, MutinyError>;
25+
fn delete_payjoin(&self, id: &[u8; 33]) -> Result<(), MutinyError>;
1726
}
1827

1928
const PAYJOIN_KEY_PREFIX: &str = "payjoin/";
@@ -23,17 +32,27 @@ fn get_payjoin_key(id: &[u8; 33]) -> String {
2332
}
2433

2534
impl<S: MutinyStorage> PayjoinStorage for S {
26-
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError> {
35+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Session>, MutinyError> {
2736
let sessions = self.get_data(get_payjoin_key(id))?;
2837
Ok(sessions)
2938
}
3039

31-
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError> {
32-
let map: HashMap<String, Enrolled> = self.scan(PAYJOIN_KEY_PREFIX, None)?;
40+
fn get_payjoins(&self) -> Result<Vec<Session>, MutinyError> {
41+
let map: HashMap<String, Session> = self.scan(PAYJOIN_KEY_PREFIX, None)?;
3342
Ok(map.values().map(|v| v.to_owned()).collect())
3443
}
3544

36-
fn persist_payjoin(&self, session: Enrolled) -> Result<(), MutinyError> {
37-
self.set_data(get_payjoin_key(&session.pubkey()), session, None)
45+
fn persist_payjoin(&self, enrolled: Enrolled) -> Result<Session, MutinyError> {
46+
let in_24_hours = crate::utils::now() + Duration::from_secs(60 * 60 * 24);
47+
let session = Session {
48+
enrolled,
49+
expiry: in_24_hours,
50+
};
51+
self.set_data(get_payjoin_key(&session.pubkey()), session.clone(), None)
52+
.map(|_| session)
53+
}
54+
55+
fn delete_payjoin(&self, id: &[u8; 33]) -> Result<(), MutinyError> {
56+
self.delete(&[get_payjoin_key(id)])
3857
}
3958
}

0 commit comments

Comments
 (0)