Skip to content
Draft
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
7 changes: 7 additions & 0 deletions Cargo-minimal.lock
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ dependencies = [
"winnow 0.7.15",
]

[[package]]
name = "asmap"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "996e3818c450a9497e2f1aff7306d1c56b4198a07880222ee0aa85b6c42ac81f"

[[package]]
name = "asn1-rs"
version = "0.7.1"
Expand Down Expand Up @@ -2784,6 +2790,7 @@ name = "payjoin-cli"
version = "0.2.0"
dependencies = [
"anyhow",
"asmap",
"async-trait",
"bitcoind-async-client",
"clap 4.6.0",
Expand Down
19 changes: 13 additions & 6 deletions Cargo-recent.lock
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ dependencies = [
"winnow",
]

[[package]]
name = "asmap"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "996e3818c450a9497e2f1aff7306d1c56b4198a07880222ee0aa85b6c42ac81f"

[[package]]
name = "asn1-rs"
version = "0.7.1"
Expand Down Expand Up @@ -1950,7 +1956,7 @@ dependencies = [
"tokio",
"tokio-rustls 0.26.2",
"tower-service",
"webpki-roots 1.0.2",
"webpki-roots 1.0.7",
]

[[package]]
Expand Down Expand Up @@ -2752,6 +2758,7 @@ name = "payjoin-cli"
version = "0.2.0"
dependencies = [
"anyhow",
"asmap",
"async-trait",
"bitcoind-async-client",
"clap 4.5.46",
Expand Down Expand Up @@ -3404,7 +3411,7 @@ dependencies = [
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"webpki-roots 1.0.2",
"webpki-roots 1.0.7",
]

[[package]]
Expand Down Expand Up @@ -4332,7 +4339,7 @@ dependencies = [
"time",
"tokio",
"tokio-rustls 0.26.2",
"webpki-roots 1.0.2",
"webpki-roots 1.0.7",
"x509-parser 0.18.0",
]

Expand Down Expand Up @@ -5094,14 +5101,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
"webpki-roots 1.0.2",
"webpki-roots 1.0.7",
]

[[package]]
name = "webpki-roots"
version = "1.0.2"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
dependencies = [
"rustls-pki-types",
]
Expand Down
6 changes: 4 additions & 2 deletions payjoin-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ path = "src/main.rs"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["v2"]
asmap = ["dep:asmap"]
native-certs = ["reqwest/rustls-tls-native-roots"]
_manual-tls = ["reqwest/rustls-tls", "payjoin/_manual-tls", "tokio-rustls"]
_manual-tls = ["reqwest/rustls-tls", "payjoin/_manual-tls"]
v1 = ["payjoin/v1", "hyper", "hyper-util", "http-body-util"]
v2 = ["payjoin/v2", "payjoin/io"]

[dependencies]
anyhow = "1.0.99"
asmap = { version = "0.1.0", optional = true }
async-trait = "0.1.89"
bitcoind-async-client = "0.10.2"
clap = { version = "4.5.45", features = ["derive"] }
Expand All @@ -48,7 +50,7 @@ serde_json = "1.0.149"
tokio = { version = "1.47.1", features = ["full"] }
tokio-rustls = { version = "0.26.2", features = [
"ring",
], default-features = false, optional = true }
], default-features = false }
tracing = "0.1.41"
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }

Expand Down
28 changes: 26 additions & 2 deletions payjoin-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ rpchost = "http://localhost:18443/wallet/sender"

# For v2, our config also requires a payjoin directory server and OHTTP relay
[v2]
pj_directory = "https://payjo.in"
pj_directories = ["https://payjo.in"]
ohttp_relays = ["https://pj.benalleng.com", "https://pj.bobspacebkk.com", "https://ohttp.achow101.com"]
```

Expand All @@ -90,7 +90,7 @@ rpchost = "http://localhost:18443/wallet/receiver"

# For v2, our config also requires a payjoin directory server and OHTTP relay
[v2]
pj_directory = "https://payjo.in"
pj_directories = ["https://payjo.in"]
ohttp_relays = ["https://pj.benalleng.com", "https://pj.bobspacebkk.com", "https://ohttp.achow101.com"]
```

Expand Down Expand Up @@ -138,6 +138,30 @@ See the
[example.config.toml](https://github.com/payjoin/rust-payjoin/blob/fde867b93ede767c9a50913432a73782a94ef40b/payjoin-cli/example.config.toml)
for inspiration.

`payjoin-cli` also supports optional AS-aware filtering for BIP77 relay
selection:

```toml
[v2]
pj_directories = ["https://payjo.in", "https://backup.example"]
ohttp_relays = ["https://relay-1.example", "https://relay-2.example"]

[v2.asmap]
asmap_file = "./ip_asn.dat"
user_public_ips = ["198.51.100.10"]
user_asns = [64512]
```

Build `payjoin-cli` with `--features asmap` to enable the `[v2.asmap]`
configuration block.

When enabled, directories and relays that resolve into the same ASN as the
configured user identity are excluded, mixed-ASN hostnames are rejected, and
relay ordering becomes deterministic from the receiver key embedded in the
BIP77 URI. This mitigates some AS-level correlation risks, but it does not
eliminate traffic analysis when sender and receiver already share the same
network.

### Asynchronous Operation

Sender and receiver state is saved to a database in the directory from which `payjoin-cli` is run, called `payjoin.sqlite`. Once a send or receive session is started, it may resume using the `resume` argument if prior payjoin sessions have not yet complete.
Expand Down
12 changes: 11 additions & 1 deletion payjoin-cli/example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,19 @@ rpcpassword = "password"

# Version 2 Configuration
# [v2]
# pj_directory = "https://payjo.in"
# pj_directories = ["https://payjo.in"]
# ohttp_relays = ["https://pj.benalleng.com", "https://pj.bobspacebkk.com", "https://ohttp.achow101.com", "https://example.com"]
# # Optional: The HPKE keys which need to be fetched ahead of time from the pj_endpoint
# # for the payjoin packets to be encrypted.
# # These can now be fetched and no longer need to be configured.
# ohttp_keys = "./path/to/ohttp_keys"
#
# # Optional AS-aware relay and directory filtering.
# # When enabled, payjoin-cli will reject directories/relays that share an
# # ASN with the configured user identity, and will deterministically order
# # relay selection from the remaining candidates.
# # Requires building payjoin-cli with `--features asmap`.
# [v2.asmap]
# asmap_file = "./ip_asn.dat"
# user_public_ips = ["198.51.100.10", "2001:db8::10"]
# user_asns = [64512]
Loading