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

Commit 00be64a

Browse files
committed
Enable payjoin expiration
1 parent 8e23b93 commit 00be64a

File tree

3 files changed

+52
-16
lines changed

3 files changed

+52
-16
lines changed

mutiny-core/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,17 +1096,19 @@ impl<S: MutinyStorage> MutinyWallet<S> {
10961096
.process_res(ohttp_response.as_ref(), context)
10971097
.map_err(|e| anyhow!("parse error {}", e))
10981098
.unwrap();
1099-
self.node_manager
1099+
let session = self
1100+
.node_manager
11001101
.storage
11011102
.persist_payjoin(enrolled.clone())
11021103
.unwrap();
11031104
let pj_uri = enrolled.fallback_target();
11041105
log_debug!(self.logger, "{pj_uri}");
11051106
let wallet = self.node_manager.wallet.clone();
11061107
let stop = self.node_manager.stop.clone();
1108+
let storage = Arc::new(self.node_manager.storage.clone());
11071109
// run await payjoin task in the background as it'll keep polling the relay
11081110
utils::spawn(async move {
1109-
let pj_txid = NodeManager::receive_payjoin(wallet, stop, enrolled)
1111+
let pj_txid = NodeManager::receive_payjoin(wallet, stop, storage, session)
11101112
.await
11111113
.unwrap();
11121114
log::info!("Received payjoin txid: {}", pj_txid);

mutiny-core/src/nodemanager.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -582,8 +582,11 @@ impl<S: MutinyStorage> NodeManager<S> {
582582
for payjoin in all {
583583
let wallet = nm.wallet.clone();
584584
let stop = nm.stop.clone();
585+
let storage = Arc::new(nm.storage.clone());
585586
utils::spawn(async move {
586-
let pj_txid = Self::receive_payjoin(wallet, stop, payjoin).await.unwrap();
587+
let pj_txid = Self::receive_payjoin(wallet, stop, storage, payjoin)
588+
.await
589+
.unwrap();
587590
log::info!("Received payjoin txid: {}", pj_txid);
588591
});
589592
}
@@ -754,14 +757,15 @@ impl<S: MutinyStorage> NodeManager<S> {
754757
pub async fn receive_payjoin(
755758
wallet: Arc<OnChainWallet<S>>,
756759
stop: Arc<AtomicBool>,
757-
mut enrolled: payjoin::receive::v2::Enrolled,
760+
storage: Arc<S>,
761+
mut session: crate::payjoin::Session,
758762
) -> Result<Txid, MutinyError> {
759763
let http_client = reqwest::Client::builder()
760764
//.danger_accept_invalid_certs(true) ? is tls unchecked :O
761765
.build()
762766
.unwrap();
763767
let proposal: payjoin::receive::v2::UncheckedProposal =
764-
Self::poll_for_fallback_psbt(stop, &http_client, &mut enrolled)
768+
Self::poll_for_fallback_psbt(stop, storage, &http_client, &mut session)
765769
.await
766770
.unwrap();
767771
let payjoin_proposal = wallet.process_payjoin_proposal(proposal).unwrap();
@@ -786,17 +790,23 @@ impl<S: MutinyStorage> NodeManager<S> {
786790

787791
async fn poll_for_fallback_psbt(
788792
stop: Arc<AtomicBool>,
793+
storage: Arc<S>,
789794
client: &reqwest::Client,
790-
enroller: &mut payjoin::receive::v2::Enrolled,
795+
session: &mut crate::payjoin::Session,
791796
) -> Result<payjoin::receive::v2::UncheckedProposal, ()> {
792797
loop {
793798
if stop.load(Ordering::Relaxed) {
794799
return Err(()); // stopped
795800
}
796-
let (req, context) = enroller.extract_req().unwrap();
801+
if session.expiry < utils::now() {
802+
let _ = storage.delete_payjoin(&session.enrolled.pubkey());
803+
return Err(()); // expired
804+
}
805+
let (req, context) = session.enrolled.extract_req().unwrap();
797806
let ohttp_response = client.post(req.url).body(req.body).send().await.unwrap();
798807
let ohttp_response = ohttp_response.bytes().await.unwrap();
799-
let proposal = enroller
808+
let proposal = session
809+
.enrolled
800810
.process_res(ohttp_response.as_ref(), context)
801811
.map_err(|e| anyhow!("parse error {}", e))
802812
.unwrap();

mutiny-core/src/payjoin.rs

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,27 @@
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

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+
}
720
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>;
21+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Session>, MutinyError>;
22+
fn get_payjoins(&self) -> Result<Vec<Session>, MutinyError>;
23+
fn persist_payjoin(&self, session: Enrolled) -> Result<Session, MutinyError>;
24+
fn delete_payjoin(&self, id: &[u8; 33]) -> Result<(), MutinyError>;
1125
}
1226

1327
const PAYJOIN_KEY_PREFIX: &str = "payjoin/";
@@ -17,17 +31,27 @@ fn get_payjoin_key(id: &[u8; 33]) -> String {
1731
}
1832

1933
impl<S: MutinyStorage> PayjoinStorage for S {
20-
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Enrolled>, MutinyError> {
34+
fn get_payjoin(&self, id: &[u8; 33]) -> Result<Option<Session>, MutinyError> {
2135
let sessions = self.get_data(get_payjoin_key(id))?;
2236
Ok(sessions)
2337
}
2438

25-
fn get_payjoins(&self) -> Result<Vec<Enrolled>, MutinyError> {
26-
let map: HashMap<String, Enrolled> = self.scan(PAYJOIN_KEY_PREFIX, None)?;
39+
fn get_payjoins(&self) -> Result<Vec<Session>, MutinyError> {
40+
let map: HashMap<String, Session> = self.scan(PAYJOIN_KEY_PREFIX, None)?;
2741
Ok(map.values().map(|v| v.to_owned()).collect())
2842
}
2943

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

0 commit comments

Comments
 (0)