Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,724 changes: 1,096 additions & 628 deletions Cargo-minimal.lock

Large diffs are not rendered by default.

1,724 changes: 1,096 additions & 628 deletions Cargo-recent.lock

Large diffs are not rendered by default.

30 changes: 0 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,36 +103,6 @@ Seeking review of the code that verifies there is no overpayment. Contributions

The `payjoin` library and `payjoin-cli` should always compile with any combination of features on Rust **1.85.0**.

To build and test with the MSRV you will need to pin the below dependency versions:

### `payjoin`

```shell
cargo update -p cc --precise 1.0.105
cargo update -p regex --precise 1.9.6
cargo update -p reqwest --precise 0.12.4
cargo update -p url --precise 2.5.0
cargo update -p tokio --precise 1.38.1
cargo update -p tokio-util --precise 0.7.11
cargo update -p which --precise 4.4.0
cargo update -p zstd-sys --precise 2.0.8+zstd.1.5.5
```

### `payjoin-cli`

```shell
cargo update -p cc --precise 1.0.105
cargo update -p clap_lex --precise 0.3.0
cargo update -p regex --precise 1.9.6
cargo update -p reqwest --precise 0.12.4
cargo update -p [email protected] --precise 0.3.20
cargo update -p tokio --precise 1.38.1
cargo update -p tokio-util --precise 0.7.11
cargo update -p url --precise 2.5.0
cargo update -p which --precise 4.4.0
cargo update -p zstd-sys --precise 2.0.8+zstd.1.5.5
```

## Contributing

See [`CONTRIBUTING.md`](.github/CONTRIBUTING.md)
Expand Down
44 changes: 22 additions & 22 deletions payjoin-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,38 @@ path = "src/main.rs"
[features]
default = ["v2"]
native-certs = ["reqwest/rustls-tls-native-roots"]
_manual-tls = ["rcgen", "reqwest/rustls-tls", "rustls", "hyper-rustls", "payjoin/_manual-tls", "tokio-rustls"]
_manual-tls = ["rcgen", "reqwest/rustls-tls", "hyper-rustls", "payjoin/_manual-tls", "tokio-rustls"]
v1 = ["payjoin/v1","hyper", "hyper-util", "http-body-util"]
v2 = ["payjoin/v2", "payjoin/io"]

[dependencies]
anyhow = "1.0.70"
async-trait = "0.1"
clap = { version = "~4.0.32", features = ["derive"] }
config = "0.13.3"
anyhow = "1.0.99"
async-trait = "0.1.89"
clap = { version = "4.5.45", features = ["derive"] }
config = "0.15.14"
corepc-types = "0.8.0"
env_logger = "0.9.0"
futures = "0.3"
http-body-util = { version = "0.1", optional = true }
hyper = { version = "1", features = ["http1", "server"], optional = true }
hyper-rustls = { version = "0.26", optional = true }
hyper-util = { version = "0.1", optional = true }
log = "0.4.7"
env_logger = "0.11.8"
futures = "0.3.31"
http-body-util = { version = "0.1.3", optional = true }
hyper = { version = "1.6.0", features = ["http1", "server"], optional = true }
hyper-rustls = { version = "0.27.7", default-features=false, features = ["ring"], optional = true }
hyper-util = { version = "0.1.16", optional = true }
log = "0.4.27"
payjoin = { version = "0.24.0", default-features = false }
r2d2 = "0.8.10"
r2d2_sqlite = "0.22.0"
rcgen = { version = "0.11.1", optional = true }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
serde_json = "1.0"
rcgen = { version = "0.14.3", optional = true }
reqwest = { version = "0.12.23", default-features = false, features = ["json", "rustls-tls"] }
rusqlite = { version = "0.29.0", features = ["bundled"] }
rustls = { version = "0.22.4", optional = true }
serde = { version = "1.0.160", features = ["derive"] }
tokio = { version = "1.38.1", features = ["full"] }
tokio-rustls = { version = "0.25", features = ["ring"], default-features = false, optional = true }
url = { version = "2.3.1", features = ["serde"] }
dirs = "5.0.1"
serde_json = "1.0.142"
serde = { version = "1.0.219", features = ["derive"] }
sled = "0.34.7"
tokio = { version = "1.47.1", features = ["full"] }
tokio-rustls = { version = "0.26.2", features = ["ring"], default-features = false, optional = true }
url = { version = "2.5.4", features = ["serde"] }
dirs = "6.0.0"

[dev-dependencies]
nix = "0.26.4"
nix = { version = "0.30.1", features = ["aio", "process", "signal"] }
payjoin-test-utils = { version = "0.0.1" }
tempfile = "3.20.0"
6 changes: 4 additions & 2 deletions payjoin-cli/src/app/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,10 @@ impl App {

#[cfg(feature = "_manual-tls")]
fn init_tls_acceptor(&self) -> Result<tokio_rustls::TlsAcceptor> {
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use rustls::ServerConfig;
use std::sync::Arc;

use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::TlsAcceptor;

let key_der = std::fs::read(
Expand Down
22 changes: 8 additions & 14 deletions payjoin-cli/tests/e2e.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,12 @@ mod e2e {

let cert = local_cert_key();
let cert_path = &temp_dir.path().join("localhost.crt");
tokio::fs::write(
cert_path,
cert.serialize_der().expect("must be able to serialize self signed certificate"),
)
.await
.expect("must be able to write self signed certificate");
tokio::fs::write(cert_path, cert.cert.der().to_vec())
.await
.expect("must be able to write self signed certificate");

let key_path = &temp_dir.path().join("localhost.key");
tokio::fs::write(key_path, cert.serialize_private_key_der())
tokio::fs::write(key_path, cert.signing_key.serialize_der())
.await
.expect("must be able to write self signed certificate");

Expand Down Expand Up @@ -450,15 +447,12 @@ mod e2e {
// Set up certificates for v1 receiver (needs local HTTPS server)
let cert = local_cert_key();
let cert_path = &temp_dir.path().join("localhost.crt");
tokio::fs::write(
cert_path,
cert.serialize_der().expect("must be able to serialize self signed certificate"),
)
.await
.expect("must be able to write self signed certificate");
tokio::fs::write(cert_path, cert.cert.der().to_vec())
.await
.expect("must be able to write self signed certificate");

let key_path = &temp_dir.path().join("localhost.key");
tokio::fs::write(key_path, cert.serialize_private_key_der())
tokio::fs::write(key_path, cert.signing_key.serialize_der())
.await
.expect("must be able to write self signed certificate");

Expand Down
31 changes: 15 additions & 16 deletions payjoin-directory/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,25 @@ resolver = "2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
_manual-tls = ["hyper-rustls", "rustls", "tokio-rustls"]
_manual-tls = ["hyper-rustls", "tokio-rustls"]

[dependencies]
anyhow = "1.0.71"
bitcoin = { version = "0.32.4", features = ["base64", "rand-std"] }
bhttp = { version = "=0.5.1", features = ["http"] }
futures = "0.3.17"
http-body-util = "0.1.2"
hyper = { version = "1", features = ["http1", "server"] }
hyper-rustls = { version = "0.26", optional = true }
hyper-util = { version = "0.1", features = ["tokio"] }
anyhow = "1.0.99"
bitcoin = { version = "0.32.7", features = ["base64", "rand-std"] }
bhttp = { version = "0.6.1", features = ["http"] }
futures = "0.3.31"
http-body-util = "0.1.3"
hyper = { version = "1.6.0", features = ["http1", "server"] }
hyper-rustls = { version = "0.27.7", default-features=false, features = ["webpki-roots", "http1", "ring"], optional=true }
hyper-util = { version = "0.1.16", features = ["tokio"] }
ohttp = { package = "bitcoin-ohttp", version = "0.6.0"}
payjoin = { version = "0.24.0", features = ["directory"], default-features = false }
redis = { version = "0.23.3", features = ["aio", "tokio-comp"] }
rustls = { version = "0.22.4", optional = true }
tokio = { version = "1.12.0", features = ["full"] }
tokio-rustls = { version = "0.25", features = ["ring"], default-features = false, optional = true }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
redis = { version = "0.32.5", features = ["aio", "tokio-comp"] }
tokio = { version = "1.23.31", features = ["full"] }
tokio-rustls = { version = "0.26.2", features = ["ring"], default-features = false, optional = true }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
prometheus = "0.13.4"

[dev-dependencies]
tempfile = "3.5.0"
tempfile = "3.20.0"
6 changes: 3 additions & 3 deletions payjoin-directory/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl DbPool {
}

async fn push(&self, mailbox_id: &ShortId, channel_type: &str, data: Vec<u8>) -> Result<()> {
let mut conn = self.client.get_async_connection().await?;
let mut conn = self.client.get_multiplexed_async_connection().await?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where'd you find this equivalence? https://docs.rs/redis/latest/redis/#connection-pooling?

Would be nice to have this kind of change documented in the commit log.

let key = channel_name(mailbox_id, channel_type);
() = conn.set(&key, data.clone()).await?;
() = conn.publish(&key, "updated").await?;
Expand All @@ -88,7 +88,7 @@ impl DbPool {
}

async fn peek(&self, mailbox_id: &ShortId, channel_type: &str) -> RedisResult<Vec<u8>> {
let mut conn = self.client.get_async_connection().await?;
let mut conn = self.client.get_multiplexed_async_connection().await?;
let key = channel_name(mailbox_id, channel_type);

// Attempt to fetch existing content for the given mailbox_id and channel_type
Expand All @@ -100,7 +100,7 @@ impl DbPool {
debug!("Failed to fetch content initially");

// Set up a temporary listener for changes
let mut pubsub_conn = self.client.get_async_connection().await?.into_pubsub();
let mut pubsub_conn = self.client.get_async_pubsub().await?;
let channel_name = channel_name(mailbox_id, channel_type);
pubsub_conn.subscribe(&channel_name).await?;

Expand Down
9 changes: 6 additions & 3 deletions payjoin-directory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ pub type BoxError = Box<dyn std::error::Error + Send + Sync>;

#[cfg(feature = "_manual-tls")]
fn init_tls_acceptor(cert_key: (Vec<u8>, Vec<u8>)) -> Result<tokio_rustls::TlsAcceptor> {
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
use rustls::ServerConfig;
use tokio_rustls::rustls::pki_types::{CertificateDer, PrivateKeyDer};
use tokio_rustls::rustls::ServerConfig;
use tokio_rustls::TlsAcceptor;
let (cert, key) = cert_key;
let cert = CertificateDer::from(cert);
Expand Down Expand Up @@ -193,7 +193,10 @@ impl Service {
let response = self.handle_v2(request).await?;

let (parts, body) = response.into_parts();
let mut bhttp_res = bhttp::Message::response(parts.status.as_u16());
let mut bhttp_res = bhttp::Message::response(
bhttp::StatusCode::try_from(parts.status.as_u16())
.map_err(|e| HandlerError::InternalServerError(e.into()))?,
);
for (name, value) in parts.headers.iter() {
bhttp_res.put_header(name.as_str(), value.to_str().unwrap_or_default());
}
Expand Down
14 changes: 7 additions & 7 deletions payjoin-ffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,20 @@ uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", rev = "b

[dependencies]
base64 = "0.22.1"
bitcoind = { version = "0.36.0", features = ["0_21_2"], optional = true }
bitcoind = { version = "0.36.1", features = ["0_21_2"], optional = true }
bitcoin-ffi = { git = "https://github.com/benalleng/bitcoin-ffi.git", rev = "8e3a23b" }
hex = "0.4.3"
lazy_static = "1.5.0"
ohttp = { package = "bitcoin-ohttp", version = "0.6.0" }
payjoin = { version = "0.24.0", features = ["v1", "v2", "io"] }
payjoin-test-utils = { version = "0.0.1", optional = true }
serde = { version = "1.0.200", features = ["derive"] }
serde_json = "1.0.128"
thiserror = "1.0.58"
tokio = { version = "1.38.0", features = ["full"], optional = true }
uniffi = { version = "0.29.1" }
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.142"
thiserror = "2.0.14"
tokio = { version = "1.47.1", features = ["full"], optional = true }
uniffi = { version = "0.29.4" }
uniffi-dart = { git = "https://github.com/Uniffi-Dart/uniffi-dart.git", rev = "b6186bc" }
url = "2.5.0"
url = "2.5.4"

[dev-dependencies]
bdk = { version = "0.29.0", features = ["all-keys", "use-esplora-ureq", "keys-bip39", "rpc"] }
Expand Down
2 changes: 1 addition & 1 deletion payjoin-ffi/contrib/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ set -e

RUST_VERSION=$(rustc --version | awk '{print $2}')

if [[ ! "$RUST_VERSION" =~ ^1\.63\. ]]; then
if [[ ! "$RUST_VERSION" =~ ^1\.85\. ]]; then
cargo test --package payjoin-ffi --verbose --features=_manual-tls,_test-utils
else
echo "Skipping payjoin-ffi tests for Rust version $RUST_VERSION (MSRV)"
Expand Down
26 changes: 13 additions & 13 deletions payjoin-test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ rust-version = "1.85"
license = "MIT"

[dependencies]
bitcoin = { version = "0.32.5", features = ["base64"] }
bitcoin = { version = "0.32.7", features = ["base64"] }
bitcoincore-rpc = "0.19.0"
bitcoind = { version = "0.36.0", features = ["0_21_2"] }
http = "1.1.0"
log = "0.4.7"
bitcoind = { version = "0.36.1", features = ["0_21_2"] }
http = "1.3.1"
log = "0.4.27"
ohttp = { package = "bitcoin-ohttp", version = "0.6.0" }
ohttp-relay = { version = "0.0.10", features = ["_test-util"] }
once_cell = "1.19.0"
ohttp-relay = { version = "0.0.11", features = ["_test-util"] }
once_cell = "1.21.3"
payjoin = { version = "0.24.0", features = ["io", "_manual-tls", "_test-utils"] }
payjoin-directory = { version = "0.0.3", features = ["_manual-tls"] }
rcgen = "0.11"
rustls = "0.22"
reqwest = { version = "0.12", default-features = false, features = ["rustls-tls"] }
rcgen = "0.14.3"
rustls = { version = "0.23.31", default-features=false, features = ["ring"] }
reqwest = { version = "0.12.23", default-features = false, features = ["rustls-tls"] }
testcontainers-modules = { version = "0.12.1", features = ["redis"]}
tokio = { version = "1.38.1", features = ["full"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
url = "2.2.2"
tokio = { version = "1.47.1", features = ["full"] }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
url = "2.5.4"
16 changes: 8 additions & 8 deletions payjoin-test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,31 +61,31 @@ impl TestServices {
pub async fn initialize() -> Result<Self, BoxSendSyncError> {
// TODO add a UUID, and cleanup guard to delete after on successful run
let cert = local_cert_key();
let cert_der = cert.serialize_der().expect("Failed to serialize cert");
let key_der = cert.serialize_private_key_der();
let cert_key = (cert_der.clone(), key_der.clone());
let cert_der = cert.cert.der().to_vec();
let key_der = cert.signing_key.serialize_der();
let cert_key = (cert_der.clone(), key_der);

let mut root_store = RootCertStore::empty();
root_store.add(CertificateDer::from(cert.serialize_der().unwrap())).unwrap();
root_store.add(CertificateDer::from(cert.cert.der().to_vec())).unwrap();

let redis = init_redis().await;
let db_host = format!("127.0.0.1:{}", redis.0);
let directory = init_directory(db_host, cert_key.clone()).await?;
let directory = init_directory(db_host, cert_key).await?;
let gateway_origin =
ohttp_relay::GatewayUri::from_str(&format!("https://localhost:{}", directory.0))?;
let ohttp_relay = ohttp_relay::listen_tcp_on_free_port(gateway_origin, root_store).await?;
let http_agent: Arc<Client> = Arc::new(http_agent(cert_der)?);

Ok(Self {
cert,
cert: cert.cert,
redis,
directory: (directory.0, Some(directory.1)),
ohttp_relay: (ohttp_relay.0, Some(ohttp_relay.1)),
http_agent,
})
}

pub fn cert(&self) -> Vec<u8> { self.cert.serialize_der().expect("Failed to serialize cert") }
pub fn cert(&self) -> Vec<u8> { self.cert.der().to_vec() }

pub fn directory_url(&self) -> Url {
Url::parse(&format!("https://localhost:{}", self.directory.0)).expect("invalid URL")
Expand Down Expand Up @@ -159,7 +159,7 @@ async fn bind_free_port() -> Result<tokio::net::TcpListener, std::io::Error> {
}

/// generate or get a DER encoded localhost cert and key.
pub fn local_cert_key() -> rcgen::Certificate {
pub fn local_cert_key() -> rcgen::CertifiedKey<rcgen::KeyPair> {
rcgen::generate_simple_self_signed(vec!["0.0.0.0".to_string(), "localhost".to_string()])
.expect("Failed to generate cert")
}
Expand Down
Loading
Loading