Skip to content

fix for giftwrap with pow creation#161

Merged
grunch merged 3 commits intomainfrom
fix-pow
Apr 15, 2026
Merged

fix for giftwrap with pow creation#161
grunch merged 3 commits intomainfrom
fix-pow

Conversation

@arkanoider
Copy link
Copy Markdown
Collaborator

@arkanoider arkanoider commented Apr 15, 2026

Summary

fixed wrong creation of giftwrap with pow, we need to create giftwrap event Id with pow not rumor.

Summary by CodeRabbit

  • Improvements

    • Gift Wraps now use ephemeral keys and enforce proof-of-work on the outer envelope for stronger message integrity and privacy.
  • Chores

    • Configuration directory path updated: MCLI now uses ~/.mcli instead of ~/.mcliUserA.
  • Tests

    • Added unit tests validating Gift Wrap kind, proof-of-work difficulty, and rejection of invalid inputs.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 15, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9ff2f7c3-156c-4098-b932-dd423975a6a6

📥 Commits

Reviewing files that changed from the base of the PR and between d5c9aae and 3c05591.

📒 Files selected for processing (1)
  • src/util/messaging.rs

Walkthrough

Refactors NIP-59 Gift Wrap creation in src/util/messaging.rs by extracting a helper that builds a PoW-mined Gift Wrap from a signed Seal (using ephemeral keys + NIP-44 encryption) and updates rumor/Seal creation flow; also changes get_mcli_path() in src/util/misc.rs to use ~/.mcli.

Changes

Cohort / File(s) Summary
Gift Wrap / Messaging
src/util/messaging.rs
Removed PoW from inner rumor creation. Added gift_wrap_from_seal_with_pow(receiver, seal, extra_tags, pow) to validate Seal, generate ephemeral keypair, encrypt the seal JSON via NIP-44, merge tags (append p tag), tweak created_at, mine PoW on the outer Gift Wrap, and sign the outer event; updated create_gift_wrap_event() to create rumor → sign Seal → delegate to new helper. Added unit tests for Gift Wrap kind, PoW satisfaction, and Seal-type validation.
Path config / Misc
src/util/misc.rs
Changed get_mcli_path() to use ~/.mcli (directory creation and checks updated accordingly).

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant RumorBuilder
    participant Signer
    participant GiftWrapHelper
    participant NIP44
    participant PoWMiner
    participant Recipient

    User->>RumorBuilder: build rumor (no .pow)
    RumorBuilder->>Signer: sign rumor -> produces Seal (signed event)
    Signer->>GiftWrapHelper: call with receiver, Seal, extra_tags, pow
    GiftWrapHelper->>GiftWrapHelper: validate event is Seal
    GiftWrapHelper->>GiftWrapHelper: generate ephemeral keypair
    GiftWrapHelper->>NIP44: encrypt Seal JSON for Recipient with ephemeral pubkey
    NIP44-->>GiftWrapHelper: encrypted payload
    GiftWrapHelper->>GiftWrapHelper: merge extra_tags + append p tag, tweak created_at
    GiftWrapHelper->>PoWMiner: mine PoW on outer Gift Wrap (pow difficulty)
    PoWMiner-->>GiftWrapHelper: mined event with nonce
    GiftWrapHelper->>GiftWrapHelper: sign Gift Wrap with ephemeral keys
    GiftWrapHelper-->>User: return outer Gift Wrap event (signed, encrypted)
    User->>Recipient: deliver Gift Wrap
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇
I stitched a seal with nimble paws,
Ephemeral keys obeyed my laws.
I baked the pow, I wrapped the gift,
Encrypted tight — a tiny lift.
Hop, unwrap — the secret's safe and swift! 🎁✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix for giftwrap with pow creation' directly reflects the main change: fixing how GiftWrap events are created when using proof-of-work by applying PoW to the outer GiftWrap (kind 1059) instead of the inner rumor.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-pow

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/util/misc.rs (1)

13-23: ⚠️ Potential issue | 🟠 Major

Add backward-compatible migration/fallback for the directory rename.

Line 13 switches storage to ~/.mcli, but there is no migration from the previous directory. Since src/db.rs (Line 14) immediately derives mcli.db from this path, existing users can silently start using a new empty DB location.

Consider checking the legacy directory first and migrating (or reusing) it before creating ~/.mcli.

Suggested patch
 pub fn get_mcli_path() -> String {
     let home_dir = dirs::home_dir().expect("Couldn't get home directory");
-    let mcli_path = format!("{}/.mcli", home_dir.display());
+    let mcli_path = format!("{}/.mcli", home_dir.display());
+    let legacy_path = format!("{}/.mcliUserA", home_dir.display());
+
+    // Backward compatibility: if old dir exists and new dir does not, migrate.
+    if Path::new(&legacy_path).exists() && !Path::new(&mcli_path).exists() {
+        if let Err(e) = fs::rename(&legacy_path, &mcli_path) {
+            panic!("Couldn't migrate mostro-cli directory from legacy path: {}", e);
+        }
+    }
+
     if !Path::new(&mcli_path).exists() {
         match fs::create_dir(&mcli_path) {
             Ok(_) => println!("Directory {} created.", mcli_path),
             Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => {
                 // Directory was created by another thread/process, which is fine
             }
             Err(e) => panic!("Couldn't create mostro-cli directory in HOME: {}", e),
         }
     }

     mcli_path
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/util/misc.rs` around lines 13 - 23, The code unconditionally creates
~/.mcli without checking the old location, causing existing users to get a new
empty DB; update the logic around the mcli_path variable to first detect a
legacy directory (e.g., the previous dot directory used before the rename, such
as ~/.mostro-cli), and if that legacy path exists either set mcli_path to that
legacy path or atomically migrate it by calling fs::rename(legacy_path,
&mcli_path) and handle errors (AlreadyExists, NotFound) appropriately before
attempting fs::create_dir(&mcli_path); keep using Path::new, match on
fs::rename/fs::create_dir errors, and ensure callers that derive mcli.db from
mcli_path continue to work with the migrated/reused location.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/util/messaging.rs`:
- Around line 162-197: Update send_gift_wrap_dm_internal to create the
relay-visible Gift Wrap using gift_wrap_from_seal_with_pow instead of applying
PoW to the inner seal: locate send_gift_wrap_dm_internal and replace the current
flow that mines/signs the inner Seal with a call to
gift_wrap_from_seal_with_pow(receiver, &seal_event, extra_tags, pow), propagate
the pow argument (or determine appropriate pow) and handle its Result
(map/return the error) exactly like create_gift_wrap_event does, and remove any
leftover PoW/mining/ephemeral-key signing of the inner seal so only the outer
Gift Wrap is mined/signed.

---

Outside diff comments:
In `@src/util/misc.rs`:
- Around line 13-23: The code unconditionally creates ~/.mcli without checking
the old location, causing existing users to get a new empty DB; update the logic
around the mcli_path variable to first detect a legacy directory (e.g., the
previous dot directory used before the rename, such as ~/.mostro-cli), and if
that legacy path exists either set mcli_path to that legacy path or atomically
migrate it by calling fs::rename(legacy_path, &mcli_path) and handle errors
(AlreadyExists, NotFound) appropriately before attempting
fs::create_dir(&mcli_path); keep using Path::new, match on
fs::rename/fs::create_dir errors, and ensure callers that derive mcli.db from
mcli_path continue to work with the migrated/reused location.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 128212ca-dbff-4231-9229-c521036abf2b

📥 Commits

Reviewing files that changed from the base of the PR and between fa41ed8 and d5c9aae.

📒 Files selected for processing (2)
  • src/util/messaging.rs
  • src/util/misc.rs

Comment thread src/util/messaging.rs
@arkanoider arkanoider requested review from Catrya and grunch April 15, 2026 07:37
mostronatorcoder[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@mostronatorcoder mostronatorcoder Bot left a comment

Choose a reason for hiding this comment

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

The fix is moving in the right direction — applying PoW to the Gift Wrap (kind 1059) instead of the rumor is correct per NIP-59. However there are a few issues that need to be addressed before merging.

P1: Vague error message in gift_wrap_from_seal_with_pow

return Err(anyhow::anyhow!("Invalid kind"));

This gives no useful context when debugging. Please include the actual kind received:

return Err(anyhow::anyhow!(
    "Expected Seal (kind {}), got kind {}",
    nostr_sdk::Kind::Seal.as_u16(),
    seal.kind.as_u16()
));

P1: ~/.mcliUserA~/.mcli path change without migration or documentation

Changing the config directory path silently discards any existing data a user has in ~/.mcliUserA. If this was intentional (e.g. the old path was only used in tests), please document it explicitly in the PR description or add at least a warning in the code. If users might have real data there, a migration step is needed.

P2: No tests for gift_wrap_from_seal_with_pow

The original bug (PoW applied to the rumor instead of the wrap) had no test coverage, and the fix does not add any either. At minimum, a unit test verifying:

  • the output event has kind 1059 (GiftWrap)
  • the event ID satisfies the requested PoW difficulty
  • a non-Seal input is correctly rejected

would prevent regressions.

Info: review signer_keys resolution in create_gift_wrap_event

The function resolves signer_keys from optional identity_keys, which can differ from trade_keys. Please confirm explicitly that the Seal is always signed with the correct resolved key in all code paths after the refactor.

@arkanoider
Copy link
Copy Markdown
Collaborator Author

The fix is moving in the right direction — applying PoW to the Gift Wrap (kind 1059) instead of the rumor is correct per NIP-59. However there are a few issues that need to be addressed before merging.

P1: Vague error message in gift_wrap_from_seal_with_pow

return Err(anyhow::anyhow!("Invalid kind"));

This gives no useful context when debugging. Please include the actual kind received:

return Err(anyhow::anyhow!(
    "Expected Seal (kind {}), got kind {}",
    nostr_sdk::Kind::Seal.as_u16(),
    seal.kind.as_u16()
));

P1: ~/.mcliUserA~/.mcli path change without migration or documentation

Changing the config directory path silently discards any existing data a user has in ~/.mcliUserA. If this was intentional (e.g. the old path was only used in tests), please document it explicitly in the PR description or add at least a warning in the code. If users might have real data there, a migration step is needed.

P2: No tests for gift_wrap_from_seal_with_pow

The original bug (PoW applied to the rumor instead of the wrap) had no test coverage, and the fix does not add any either. At minimum, a unit test verifying:

  • the output event has kind 1059 (GiftWrap)
  • the event ID satisfies the requested PoW difficulty
  • a non-Seal input is correctly rejected

would prevent regressions.

Info: review signer_keys resolution in create_gift_wrap_event

The function resolves signer_keys from optional identity_keys, which can differ from trade_keys. Please confirm explicitly that the Seal is always signed with the correct resolved key in all code paths after the refactor.

This was caused by a wrong push, mcliUserA, consider .mcli the correct path.

@arkanoider
Copy link
Copy Markdown
Collaborator Author

The function resolves signer_keys from optional identity_keys, which can differ from trade_keys. Please confirm explicitly that the Seal is always signed with the correct resolved key in all code paths after the refactor.

Yes signer of seal per nip59 of nostr is always the identity keys

@arkanoider
Copy link
Copy Markdown
Collaborator Author

Mostronator review...

PR #161 — Aprobado ✅

Todo lo que pedí en la review anterior fue resuelto:

• Error descriptivo: el mensaje de error ya incluye el kind esperado y el recibido
• Tests completos: kind 1059, dificultad PoW y rechazo de non-Seal — los tres casos cubiertos
• CI 100% verde: build, test, clippy, MSRV, fmt
• Ambas rutas de producción (send_gift_wrap_dm_internal y create_gift_wrap_event) usan correctamente gift_wrap_from_seal_with_pow
• ~/.mcliUserA → ~/.mcli: seguro — el nombre anterior era claramente un artefacto de testing

La corrección de fondo es correcta: el PoW se aplica al Gift Wrap externo (kind 1059) como exige NIP-59, no al rumor. Pueden mergear.

Nota: la GitHub App no tiene permisos de approve en este repo, así que no pude hacer el approve formal desde GitHub. Alguien con acceso tendrá que hacerlo manualmente.

Copy link
Copy Markdown
Member

@Catrya Catrya left a comment

Choose a reason for hiding this comment

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

tACK

@grunch grunch merged commit 2be95d8 into main Apr 15, 2026
6 checks passed
@grunch grunch deleted the fix-pow branch April 15, 2026 18:10
@mostronatorcoder
Copy link
Copy Markdown

Review update from Mostronator: all previously requested changes have been addressed, and from a code review perspective this PR is approved. The PoW is now correctly applied to the outer Gift Wrap (kind 1059), tests were added, CI is green, and both production paths use gift_wrap_from_seal_with_pow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants