Skip to content

Commit b4a4b03

Browse files
authored
Make _danger-local-https feature additive (payjoin#430)
2 parents f7cb8b7 + fdcc566 commit b4a4b03

File tree

5 files changed

+68
-41
lines changed

5 files changed

+68
-41
lines changed

payjoin-cli/src/app/v2.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -360,14 +360,14 @@ async fn unwrap_ohttp_keys_or_else_fetch(config: &AppConfig) -> Result<payjoin::
360360
let ohttp_relay = config.ohttp_relay.clone();
361361
let payjoin_directory = config.pj_directory.clone();
362362
#[cfg(feature = "_danger-local-https")]
363-
let cert_der = crate::app::read_local_cert()?;
364-
Ok(payjoin::io::fetch_ohttp_keys(
365-
ohttp_relay,
366-
payjoin_directory,
367-
#[cfg(feature = "_danger-local-https")]
368-
cert_der,
369-
)
370-
.await?)
363+
let ohttp_keys = {
364+
let cert_der = crate::app::read_local_cert()?;
365+
payjoin::io::fetch_ohttp_keys_with_cert(ohttp_relay, payjoin_directory, cert_der)
366+
.await?
367+
};
368+
#[cfg(not(feature = "_danger-local-https"))]
369+
let ohttp_keys = payjoin::io::fetch_ohttp_keys(ohttp_relay, payjoin_directory).await?;
370+
Ok(ohttp_keys)
371371
}
372372
}
373373

payjoin-cli/tests/e2e.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,9 +240,12 @@ mod e2e {
240240

241241
// fetch for setup here since ohttp_relay doesn't know the certificate for the directory
242242
// so payjoin-cli is set up with the mock_ohttp_relay which is the directory
243-
let ohttp_keys =
244-
payjoin::io::fetch_ohttp_keys(ohttp_relay.clone(), directory.clone(), cert.clone())
245-
.await?;
243+
let ohttp_keys = payjoin::io::fetch_ohttp_keys_with_cert(
244+
ohttp_relay.clone(),
245+
directory.clone(),
246+
cert.clone(),
247+
)
248+
.await?;
246249
let ohttp_keys_path = temp_dir.join("ohttp_keys");
247250
tokio::fs::write(&ohttp_keys_path, ohttp_keys.encode()?).await?;
248251

payjoin/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ send = []
2020
receive = ["bitcoin/rand"]
2121
base64 = ["bitcoin/base64"]
2222
v2 = ["bitcoin/rand", "bitcoin/serde", "hpke", "dep:http", "bhttp", "ohttp", "serde", "url/serde" ]
23-
io = ["reqwest/rustls-tls"]
24-
_danger-local-https = ["io", "reqwest/rustls-tls", "rustls"]
23+
#[doc = "Functions to fetch OHTTP keys via CONNECT proxy using reqwest. Enables `v2` since only `v2` uses OHTTP."]
24+
io = ["v2", "reqwest/rustls-tls"]
25+
_danger-local-https = ["reqwest/rustls-tls", "rustls"]
2526

2627
[dependencies]
2728
bitcoin = { version = "0.32.5", features = ["base64"] }

payjoin/src/io.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#[cfg(feature = "v2")]
1+
use reqwest::{Client, Proxy};
2+
23
use crate::{OhttpKeys, Url};
34

45
/// Fetch the ohttp keys from the specified payjoin directory via proxy.
@@ -9,22 +10,36 @@ use crate::{OhttpKeys, Url};
910
///
1011
/// * `payjoin_directory`: The payjoin directory from which to fetch the ohttp keys. This
1112
/// directory stores and forwards payjoin client payloads.
12-
///
13-
/// * `cert_der` (optional): The DER-encoded certificate to use for local HTTPS connections. This
14-
/// parameter is only available when the "_danger-local-https" feature is enabled.
15-
#[cfg(feature = "v2")]
1613
pub async fn fetch_ohttp_keys(
1714
ohttp_relay: Url,
1815
payjoin_directory: Url,
19-
#[cfg(feature = "_danger-local-https")] cert_der: Vec<u8>,
2016
) -> Result<OhttpKeys, Error> {
21-
use reqwest::{Client, Proxy};
22-
2317
let ohttp_keys_url = payjoin_directory.join("/ohttp-keys")?;
2418
let proxy = Proxy::all(ohttp_relay.as_str())?;
25-
#[cfg(not(feature = "_danger-local-https"))]
2619
let client = Client::builder().proxy(proxy).build()?;
27-
#[cfg(feature = "_danger-local-https")]
20+
let res = client.get(ohttp_keys_url).send().await?;
21+
let body = res.bytes().await?.to_vec();
22+
OhttpKeys::decode(&body).map_err(|e| Error(InternalError::InvalidOhttpKeys(e.to_string())))
23+
}
24+
25+
/// Fetch the ohttp keys from the specified payjoin directory via proxy.
26+
///
27+
/// * `ohttp_relay`: The http CONNNECT method proxy to request the ohttp keys from a payjoin
28+
/// directory. Proxying requests for ohttp keys ensures a client IP address is never revealed to
29+
/// the payjoin directory.
30+
///
31+
/// * `payjoin_directory`: The payjoin directory from which to fetch the ohttp keys. This
32+
/// directory stores and forwards payjoin client payloads.
33+
///
34+
/// * `cert_der`: The DER-encoded certificate to use for local HTTPS connections.
35+
#[cfg(feature = "_danger-local-https")]
36+
pub async fn fetch_ohttp_keys_with_cert(
37+
ohttp_relay: Url,
38+
payjoin_directory: Url,
39+
cert_der: Vec<u8>,
40+
) -> Result<OhttpKeys, Error> {
41+
let ohttp_keys_url = payjoin_directory.join("/ohttp-keys")?;
42+
let proxy = Proxy::all(ohttp_relay.as_str())?;
2843
let client = Client::builder()
2944
.danger_accept_invalid_certs(true)
3045
.use_rustls_tls()
@@ -46,7 +61,6 @@ enum InternalError {
4661
Io(std::io::Error),
4762
#[cfg(feature = "_danger-local-https")]
4863
Rustls(rustls::Error),
49-
#[cfg(feature = "v2")]
5064
InvalidOhttpKeys(String),
5165
}
5266

@@ -72,7 +86,6 @@ impl std::fmt::Display for Error {
7286
Reqwest(e) => e.fmt(f),
7387
ParseUrl(e) => e.fmt(f),
7488
Io(e) => e.fmt(f),
75-
#[cfg(feature = "v2")]
7689
InvalidOhttpKeys(e) => {
7790
write!(f, "Invalid ohttp keys returned from payjoin directory: {}", e)
7891
}
@@ -90,7 +103,6 @@ impl std::error::Error for Error {
90103
Reqwest(e) => Some(e),
91104
ParseUrl(e) => Some(e),
92105
Io(e) => Some(e),
93-
#[cfg(feature = "v2")]
94106
InvalidOhttpKeys(_) => None,
95107
#[cfg(feature = "_danger-local-https")]
96108
Rustls(e) => Some(e),

payjoin/tests/integration.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[cfg(all(feature = "send", feature = "receive"))]
1+
#[cfg(all(feature = "send", feature = "receive", feature = "_danger-local-https"))]
22
mod integration {
33
use std::collections::HashMap;
44
use std::env;
@@ -171,8 +171,7 @@ mod integration {
171171
}
172172
}
173173

174-
#[cfg(feature = "_danger-local-https")]
175-
#[cfg(feature = "v2")]
174+
#[cfg(all(feature = "io", feature = "v2"))]
176175
mod v2 {
177176
use std::sync::Arc;
178177
use std::time::Duration;
@@ -252,9 +251,12 @@ mod integration {
252251
let agent = Arc::new(http_agent(cert_der.clone())?);
253252
wait_for_service_ready(ohttp_relay.clone(), agent.clone()).await.unwrap();
254253
wait_for_service_ready(directory.clone(), agent.clone()).await.unwrap();
255-
let ohttp_keys =
256-
payjoin::io::fetch_ohttp_keys(ohttp_relay, directory.clone(), cert_der.clone())
257-
.await?;
254+
let ohttp_keys = payjoin::io::fetch_ohttp_keys_with_cert(
255+
ohttp_relay,
256+
directory.clone(),
257+
cert_der,
258+
)
259+
.await?;
258260

259261
// **********************
260262
// Inside the Receiver:
@@ -321,9 +323,12 @@ mod integration {
321323
let agent = Arc::new(http_agent(cert_der.clone())?);
322324
wait_for_service_ready(ohttp_relay.clone(), agent.clone()).await.unwrap();
323325
wait_for_service_ready(directory.clone(), agent.clone()).await.unwrap();
324-
let ohttp_keys =
325-
payjoin::io::fetch_ohttp_keys(ohttp_relay, directory.clone(), cert_der.clone())
326-
.await?;
326+
let ohttp_keys = payjoin::io::fetch_ohttp_keys_with_cert(
327+
ohttp_relay,
328+
directory.clone(),
329+
cert_der.clone(),
330+
)
331+
.await?;
327332
// **********************
328333
// Inside the Receiver:
329334
let address = receiver.get_new_address(None, None)?.assume_checked();
@@ -450,9 +455,12 @@ mod integration {
450455
let agent = Arc::new(http_agent(cert_der.clone())?);
451456
wait_for_service_ready(ohttp_relay.clone(), agent.clone()).await.unwrap();
452457
wait_for_service_ready(directory.clone(), agent.clone()).await.unwrap();
453-
let ohttp_keys =
454-
payjoin::io::fetch_ohttp_keys(ohttp_relay, directory.clone(), cert_der.clone())
455-
.await?;
458+
let ohttp_keys = payjoin::io::fetch_ohttp_keys_with_cert(
459+
ohttp_relay,
460+
directory.clone(),
461+
cert_der,
462+
)
463+
.await?;
456464
// **********************
457465
// Inside the Receiver:
458466
// make utxos with different script types
@@ -662,9 +670,12 @@ mod integration {
662670
let agent: Arc<Client> = Arc::new(http_agent(cert_der.clone())?);
663671
wait_for_service_ready(ohttp_relay.clone(), agent.clone()).await?;
664672
wait_for_service_ready(directory.clone(), agent.clone()).await?;
665-
let ohttp_keys =
666-
payjoin::io::fetch_ohttp_keys(ohttp_relay, directory.clone(), cert_der.clone())
667-
.await?;
673+
let ohttp_keys = payjoin::io::fetch_ohttp_keys_with_cert(
674+
ohttp_relay,
675+
directory.clone(),
676+
cert_der.clone(),
677+
)
678+
.await?;
668679
let address = receiver.get_new_address(None, None)?.assume_checked();
669680

670681
let mut session = initialize_session(address, directory, ohttp_keys.clone(), None);

0 commit comments

Comments
 (0)