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
354 changes: 329 additions & 25 deletions Cargo.lock

Large diffs are not rendered by default.

573 changes: 479 additions & 94 deletions Cargo.lock.msrv

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion crates/cashu/src/nuts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub use nut05::{
MeltMethodSettings, MeltQuoteCustomRequest, MeltQuoteCustomResponse, MeltRequest,
QuoteState as MeltQuoteState, Settings as NUT05Settings,
};
pub use nut06::{ContactInfo, MintInfo, MintVersion, Nuts};
pub use nut06::{ContactInfo, MintInfo, MintVersion, Nuts, OhttpSettings};
pub use nut07::{CheckStateRequest, CheckStateResponse, ProofState, State};
pub use nut09::{RestoreRequest, RestoreResponse};
pub use nut10::{
Expand Down
48 changes: 48 additions & 0 deletions crates/cashu/src/nuts/nut06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ pub struct Nuts {
#[serde(rename = "22")]
#[serde(skip_serializing_if = "Option::is_none")]
pub nut22: Option<BlindAuthSettings>,
/// NUT26 Settings
#[serde(rename = "26")]
#[serde(skip_serializing_if = "Option::is_none")]
pub nut26: Option<OhttpSettings>,
/// NUT29 Settings
#[serde(default)]
#[serde(rename = "29")]
Expand Down Expand Up @@ -454,6 +458,14 @@ impl Nuts {
}
}

/// Nut26 OHTTP settings
pub fn nut26(self, ohttp_settings: OhttpSettings) -> Self {
Self {
nut26: Some(ohttp_settings),
..self
}
}

/// Nut29 settings
pub fn nut29(self, settings: nut29::Settings) -> Self {
Self {
Expand Down Expand Up @@ -485,6 +497,42 @@ impl Nuts {
}
}

/// NUT-26 OHTTP Settings
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct OhttpSettings {
/// Ohttp is supported
pub supported: bool,
/// OHTTP gateway URL
#[serde(skip_serializing_if = "Option::is_none")]
pub gateway_url: Option<String>,
}

impl OhttpSettings {
/// Create new [`OhttpSettings`]
pub fn new(supported: bool, gateway_url: Option<String>) -> Self {
Self {
supported,
gateway_url,
}
}
}

impl MintInfo {
/// Check if mint supports OHTTP
pub fn supports_ohttp(&self) -> bool {
self.nuts
.nut26
.as_ref()
.map(|s| s.supported)
.unwrap_or_default()
}

/// Get OHTTP configuration if supported
pub fn ohttp_config(&self) -> Option<&OhttpSettings> {
self.nuts.nut26.as_ref()
}
}

/// Check state Settings
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Hash, Serialize, Deserialize)]
pub struct SupportedSettings {
Expand Down
1 change: 1 addition & 0 deletions crates/cdk-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ sqlcipher = ["cdk-sqlite/sqlcipher"]
redb = ["dep:cdk-redb"]
tor = ["cdk/tor"]
npubcash = ["cdk/npubcash"]
ohttp = ["cdk/ohttp"]

[dependencies]
anyhow.workspace = true
Expand Down
97 changes: 95 additions & 2 deletions crates/cdk-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,12 +571,105 @@ cdk-cli burn
cdk-cli restore <MINT_URL>
```


## License

Code is under the [MIT License](../../LICENSE)

## Contribution
## Contributing

All contributions are welcome.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, shall be licensed as above, without any additional terms or conditions.
### Basic Commands

Check wallet balance:
```bash
cdk-cli balance
```

Send tokens:
```bash
cdk-cli send --amount 100
```

Receive tokens:
```bash
cdk-cli receive <TOKEN>
```

### OHTTP Support

The CLI supports OHTTP (Oblivious HTTP) for enhanced privacy when communicating with mints. OHTTP is enabled by default and automatically used when:

1. The mint supports OHTTP (advertised in mint info)
2. You provide an OHTTP relay URL using `--ohttp-relay`

#### OHTTP Usage

To use OHTTP, simply provide a relay URL. The CLI will automatically detect if the mint supports OHTTP and configure the connection appropriately:

```bash
# Use OHTTP relay - CLI auto-detects OHTTP support and gateway URL from mint
cdk-cli --ohttp-relay https://relay.example.com balance
cdk-cli --ohttp-relay https://relay.example.com send --amount 100
cdk-cli --ohttp-relay https://relay.example.com receive <TOKEN>
```

#### How OHTTP Works in CDK-CLI

1. **Automatic Detection**: When `--ohttp-relay` is provided, the CLI checks if the mint supports OHTTP
2. **Gateway Discovery**: The gateway URL is automatically discovered from the mint's OHTTP configuration, or falls back to using the mint URL directly
3. **Transport Setup**: An OHTTP transport layer is created with the mint URL, relay, and gateway
4. **Privacy Protection**: Requests are routed through the relay, providing privacy from both the relay and the gateway

#### OHTTP Arguments

- `--ohttp-relay <URL>`: OHTTP relay URL for routing requests through a privacy relay

#### Example OHTTP Usage

```bash
# Standard OHTTP usage with relay
cdk-cli --ohttp-relay https://ohttp-relay.example.com balance

# All commands work with OHTTP
cdk-cli --ohttp-relay https://relay.example.com send --amount 100
cdk-cli --ohttp-relay https://relay.example.com receive <TOKEN>
cdk-cli --ohttp-relay https://relay.example.com mint --amount 1000
```

#### OHTTP vs Regular Proxy

OHTTP provides significantly better privacy compared to regular HTTP proxies:

- **Regular proxy:** `cdk-cli --proxy https://proxy.example.com balance`
- Proxy can see all request content and your IP
- **OHTTP relay:** `cdk-cli --ohttp-relay https://relay.example.com balance`
- Relay cannot see request content (cryptographically protected)
- Gateway cannot see your real IP address
- Provides true metadata protection

#### Important Notes

- OHTTP requires the mint to explicitly support it
- If you specify `--ohttp-relay` but the mint doesn't support OHTTP, you'll see a warning and fall back to regular HTTP
- Gateway URL is automatically determined from the mint's OHTTP configuration
- When OHTTP is used, WebSocket subscriptions are automatically disabled in favor of HTTP polling

## Building

### Features

- `ohttp`: Enables OHTTP support for enhanced privacy
- `sqlcipher`: Enables SQLCipher support for encrypted databases
- `redb`: Enables redb as an alternative database backend

### Examples

```bash
# Build with all features
cargo build --features "ohttp,sqlcipher,redb"

# Build with just OHTTP
cargo build --features ohttp
```
4 changes: 4 additions & 0 deletions crates/cdk-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ struct Cli {
#[cfg(all(feature = "tor", not(target_arch = "wasm32")))]
#[arg(long = "tor", value_enum, default_value_t = TorToggle::On)]
transport: TorToggle,
/// OHTTP Relay URL for proxying requests (advanced usage)
#[cfg(feature = "ohttp")]
#[arg(long)]
ohttp_relay: Option<Url>,
/// Subcommand to run
#[command(subcommand)]
command: Commands,
Expand Down
32 changes: 32 additions & 0 deletions crates/cdk-ffi/src/types/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,30 @@ impl TryFrom<BlindAuthSettings> for cdk::nuts::BlindAuthSettings {
}
}

/// FFI-compatible OhttpSettings (NUT-26)
#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record)]
pub struct OhttpSettings {
/// OHTTP is supported
pub supported: bool,
/// OHTTP gateway URL
pub gateway_url: Option<String>,
}

impl From<cdk::nuts::OhttpSettings> for OhttpSettings {
fn from(settings: cdk::nuts::OhttpSettings) -> Self {
Self {
supported: settings.supported,
gateway_url: settings.gateway_url,
}
}
}

impl From<OhttpSettings> for cdk::nuts::OhttpSettings {
fn from(settings: OhttpSettings) -> Self {
Self::new(settings.supported, settings.gateway_url)
}
}

/// FFI-compatible Nut29Settings (NUT-29)
#[derive(Debug, Clone, Serialize, Deserialize, uniffi::Record, Default)]
pub struct Nut29Settings {
Expand Down Expand Up @@ -495,6 +519,8 @@ pub struct Nuts {
pub nut21: Option<ClearAuthSettings>,
/// NUT22 Settings - Blind authentication
pub nut22: Option<BlindAuthSettings>,
/// NUT26 Settings - OHTTP
pub nut26: Option<OhttpSettings>,
/// NUT29 Settings - Batch minting
pub nut29: Nut29Settings,
/// Supported currency units for minting
Expand Down Expand Up @@ -529,6 +555,7 @@ impl From<cdk::nuts::Nuts> for Nuts {
nut20_supported: nuts.nut20.supported,
nut21: nuts.nut21.map(Into::into),
nut22: nuts.nut22.map(Into::into),
nut26: nuts.nut26.map(Into::into),
nut29: nuts.nut29.into(),
mint_units,
melt_units,
Expand Down Expand Up @@ -572,6 +599,7 @@ impl TryFrom<Nuts> for cdk::nuts::Nuts {
},
nut21: n.nut21.map(|s| s.try_into()).transpose()?,
nut22: n.nut22.map(|s| s.try_into()).transpose()?,
nut26: n.nut26.map(Into::into),
nut29: n.nut29.into(),
})
}
Expand Down Expand Up @@ -747,6 +775,7 @@ mod tests {
),
)],
}),
nut26: None,
nut29: Default::default(),
}
}
Expand Down Expand Up @@ -887,6 +916,7 @@ mod tests {
nut20: cdk::nuts::nut06::SupportedSettings { supported: false },
nut21: None,
nut22: None,
nut26: None,
nut29: Default::default(),
};

Expand Down Expand Up @@ -919,6 +949,7 @@ mod tests {
nut20_supported: false,
nut21: None,
nut22: None,
nut26: None,
nut29: Default::default(),
mint_units: vec![],
melt_units: vec![],
Expand Down Expand Up @@ -1080,6 +1111,7 @@ mod tests {
path: "/v1/unknown-custom-endpoint".to_string(),
}],
}),
nut26: None,
nut29: Nut29Settings::default(),
mint_units: vec![],
melt_units: vec![],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ fn create_ldk_settings(
ldk_node: Some(ldk_config),
fake_wallet: None,
onchain: None,
ohttp_gateway: None,
..Default::default()
}
}
Expand Down
3 changes: 3 additions & 0 deletions crates/cdk-integration-tests/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ pub fn create_fake_wallet_settings(
mint_management_rpc: None,
auth: None,
prometheus: Some(Default::default()),
ohttp_gateway: None,
..Default::default()
}
}
Expand Down Expand Up @@ -285,6 +286,7 @@ pub fn create_cln_settings(
mint_management_rpc: None,
auth: None,
prometheus: Some(Default::default()),
ohttp_gateway: None,
..Default::default()
}
}
Expand Down Expand Up @@ -338,6 +340,7 @@ pub fn create_lnd_settings(
mint_management_rpc: None,
auth: None,
prometheus: Some(Default::default()),
ohttp_gateway: None,
..Default::default()
}
}
Expand Down
2 changes: 2 additions & 0 deletions crates/cdk-mintd/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ cdk-axum.workspace = true
cdk-signatory.workspace = true
cdk-mint-rpc = { workspace = true, optional = true }
cdk-payment-processor = { workspace = true, optional = true }
ohttp-gateway = { path = "../ohttp-gateway" }
config.workspace = true
cdk-prometheus = { workspace = true, optional = true , features = ["system-metrics"]}
clap.workspace = true
Expand All @@ -67,6 +68,7 @@ tower-http = { workspace = true, features = ["compression-full", "decompression-
tower.workspace = true
lightning-invoice.workspace = true
home.workspace = true
url.workspace = true

[lints]
workspace = true
Expand Down
4 changes: 4 additions & 0 deletions crates/cdk-mintd/example.config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ melt_ttl = 120
enabled = false
# address = "127.0.0.1"
# port = 8086
#

# [ohttp_gateway]
# enabled = false

#[prometheus]
#enabled = true
Expand Down
10 changes: 10 additions & 0 deletions crates/cdk-mintd/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,7 @@ pub struct Settings {
#[cfg(feature = "prometheus")]
#[serde(default, skip_serializing_if = "Option::is_none")]
pub prometheus: Option<Prometheus>,
pub ohttp_gateway: Option<OhttpGateway>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
Expand Down Expand Up @@ -1067,6 +1068,15 @@ fn default_max_outputs() -> usize {
1000
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct OhttpGateway {
/// Whether OHTTP Gateway is enabled
#[serde(default)]
pub enabled: bool,
/// OHTTP gateway URL (if different from mint URL)
pub gateway_url: Option<String>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct MintInfo {
/// name of the mint and should be recognizable
Expand Down
Loading
Loading