Skip to content

Commit 88ab6e7

Browse files
grunchclaude
andcommitted
refactor: migrate gift-wrap to mostro-core 0.10 dual identity/trade keys
mostro-core 0.10 reshapes wrap_message / unwrap_message to match the Mostro key-management spec: the long-lived identity key signs the seal (kind 13) while the per-trade key authors the rumor (kind 1) and produces the inner tuple signature. Thread both keys through the CLI's send_dm / send_plain_text_dm / publish_gift_wrap pipeline and update every call site: - User order flows (new_order, take_order, add_invoice, orders_info, rate_user, send_msg, send_dm) pass ctx.identity_keys + the per-order trade keys. - Account-scoped requests (restore, last_trade_index) and admin flows (take_dispute, admin_send_dm, adm_send_dm) don't rotate trade keys, so they pass the same key for both — the full-privacy-mode wrap documented in the mostro-core NIP-59 transport spec. - Kind-14 NIP-17 direct messages (to_user = true) are signed with trade_keys directly; identity doesn't apply because there's no seal. Also refreshes the local wrap/unwrap unit tests to cover the identity/trade split and adds a full-privacy-mode assertion. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e30a1d5 commit 88ab6e7

16 files changed

Lines changed: 124 additions & 32 deletions

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ reqwest = { version = "0.12.23", default-features = false, features = [
4646
"json",
4747
"rustls-tls",
4848
] }
49-
mostro-core = "0.9.1"
49+
mostro-core = "0.10.0"
5050
lnurl-rs = { version = "0.9.0", default-features = false, features = ["ureq"] }
5151
pretty_env_logger = "0.5.0"
5252
sqlx = { version = "0.8.6", features = ["sqlite", "runtime-tokio-rustls"] }

src/cli/add_invoice.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ pub async fn execute_add_invoice(order_id: &Uuid, invoice: &str, ctx: &Context)
7575
// Send the DM
7676
let sent_message = send_dm(
7777
&ctx.client,
78+
&ctx.identity_keys,
7879
&order_trade_keys,
7980
&ctx.mostro_pubkey,
8081
message_json,

src/cli/adm_send_dm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub async fn execute_adm_send_dm(receiver: PublicKey, ctx: &Context, message: &s
2929
println!("{table}");
3030
println!("💡 Sending admin gift wrap message...\n");
3131

32-
send_plain_text_dm(&ctx.client, admin_keys, &receiver, message).await?;
32+
send_plain_text_dm(&ctx.client, admin_keys, admin_keys, &receiver, message).await?;
3333

3434
println!(
3535
"✅ Admin gift wrap message sent successfully to {}",

src/cli/last_trade_index.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ pub async fn execute_last_trade_index(
2424
.map_err(|_| anyhow::anyhow!("Failed to serialize message"))?;
2525

2626
// LastTradeIndex is account-scoped: the answer depends on which user
27-
// is asking, and Mostro looks that up by the sender pubkey. Sign with
28-
// `identity_keys` so the request resolves to the account, not to a
29-
// (possibly unregistered) trade key.
27+
// is asking, and Mostro looks that up by the sender pubkey. Sign both
28+
// seal and rumor with `identity_keys` so the request resolves to the
29+
// account, not to a (possibly unregistered) trade key.
3030
let sent_message = send_dm(
3131
&ctx.client,
3232
identity_keys,
33+
identity_keys,
3334
&mostro_key,
3435
message_json,
3536
None,

src/cli/new_order.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ pub async fn execute_new_order(
183183
// Send the DM
184184
let sent_message = send_dm(
185185
&ctx.client,
186+
&ctx.identity_keys,
186187
&ctx.trade_keys,
187188
&ctx.mostro_pubkey,
188189
message_json,

src/cli/orders_info.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ pub async fn execute_orders_info(order_ids: &[Uuid], ctx: &Context) -> Result<()
4444
// Send the DM
4545
let sent_message = send_dm(
4646
&ctx.client,
47+
&ctx.identity_keys,
4748
&ctx.trade_keys,
4849
&ctx.mostro_pubkey,
4950
message_json,

src/cli/rate_user.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ pub async fn execute_rate_user(order_id: &Uuid, rating: &u8, ctx: &Context) -> R
6060

6161
let sent_message = send_dm(
6262
&ctx.client,
63+
&ctx.identity_keys,
6364
&trade_keys,
6465
&ctx.mostro_pubkey,
6566
rate_message,

src/cli/restore.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ pub async fn execute_restore(
2222
// Restore is account-scoped: Mostro indexes users by their identity
2323
// pubkey, so the whole exchange (send, wait, decrypt) runs on
2424
// `identity_keys` — an unregistered trade key would look like an
25-
// unknown user and recovery would silently return nothing.
25+
// unknown user and recovery would silently return nothing. With the
26+
// mostro-core 0.10 dual-key split we pass `identity_keys` as both
27+
// the seal signer and the rumor author.
2628
let sent_message = send_dm(
2729
&ctx.client,
2830
identity_keys,
31+
identity_keys,
2932
&mostro_key,
3033
message_json,
3134
None,

src/cli/send_dm.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,16 @@ pub async fn execute_send_dm(
5353
return Err(anyhow::anyhow!("order {} not found", order_id));
5454
};
5555

56-
send_dm(&ctx.client, &trade_keys, &receiver, message, None, false).await?;
56+
send_dm(
57+
&ctx.client,
58+
&ctx.identity_keys,
59+
&trade_keys,
60+
&receiver,
61+
message,
62+
None,
63+
false,
64+
)
65+
.await?;
5766

5867
println!("✅ Direct message sent successfully!");
5968

0 commit comments

Comments
 (0)