Skip to content

Develop branch merge to main#480

Merged
arkanoider merged 15 commits into
mainfrom
develop
Apr 30, 2025
Merged

Develop branch merge to main#480
arkanoider merged 15 commits into
mainfrom
develop

Conversation

@arkanoider

@arkanoider arkanoider commented Apr 30, 2025

Copy link
Copy Markdown
Collaborator

@grunch

opening this pr to fix a point to start working on from here with main trunk

Summary by CodeRabbit

  • New Features
    • Added notifications to inform users about the reputation of their trading counterparties.
    • Enhanced dispute management with improved notifications and additional dispute information.
    • Orders now include an explicit expiration date, with logic to handle maximum and default durations.
  • Bug Fixes
    • Improved error handling and messaging throughout the app for more precise feedback.
    • Fixed issues with event and message delivery logic in disputes, order updates, and cancellations.
  • Refactor
    • Standardized and clarified error handling across the app, replacing generic errors with more descriptive, custom error types.
    • Streamlined logic for dispute actions, order publishing, and event tagging.
    • Updated event sending calls to use references to avoid ownership issues.
    • Replaced generic error results with specific custom error types for better error propagation.
    • Consistently used new tag construction methods for event creation.
  • Documentation
    • Added comprehensive documentation to key functions for improved clarity.
  • Chores
    • Updated and cleaned up dependencies.
    • Removed unused imports and redundant code.
    • Improved logging consistency and replaced debug prints with structured logs.

grunch and others added 14 commits February 28, 2025 11:00
* add feature to check correctly if order is full privacy or normal

* 📝 Add docstrings to `feature-full-privacy-mode-checks`

Docstrings generation was requested by @arkanoider.

* #454 (comment)

The following files were modified:

* `src/app/order.rs`
* `src/util.rs`

---------

Co-authored-by: arkanoider <github.913zc@simplelogin.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: arkanoider <113362043+arkanoider@users.noreply.github.com>
Now in orers event 38383 the network that comes out is the correct one
* remove of anyhow dependency start

* removed anyhow dependecy

* remove patch from cargo.toml

* Update mostro-core version

---------

Co-authored-by: Francisco Calderón <fjcalderon@gmail.com>
* Feature: dispute fix for new logic

* fix for coop cancel case

* Add logic for info message about dispute for solver

* first working dispute info message for admin after taking disputes

* added fields to dispute info message for solver

* removed some probably useless and refactored a bit admin-take-dispute function

* clippy suggestion

* other cosmetics to admin take file

* some other cosmetics on admin-take-dispute file

* fix on admin-take

* Update admin_take_dispute.rs

* fixed a wrong search of order id in admin take file@

* Fix: added correct check to add solver from admin cli

* fix: wrong check on admin cancel

* Fix initiator pubkey: now is the trade key of initiator not identity

* quick fix for full privacy orders

* new logic with mixed full privacy - regular reputation mode

* Update cargo toml to compile with version 0.6.32 of mostro-core - this is in preparation for migrating to nostr-sdk 0.40

* rollback sdk to 0.38 version to merge disputes - we will come back to 0.40 when we will fix signature issue

* Update mostro-core dependency

---------

Co-authored-by: Francisco Calderón <fjcalderon@gmail.com>
* testing sdk 40

* fix for sdk 40

* cleaned cargo.toml

* Bump mostro core version

---------

Co-authored-by: Francisco Calderón <fjcalderon@gmail.com>
* feature: align to nip69 order status in nostr event

* Improved in progress nip69 logic

* refined event states of the order with nip69 request

* add another check to avoid multiple events with in-progress state
* add optional field for users in full privacy inside solver message

* To be tested - privacy range child order fix

* fix cargo.toml

* bumped mostro-core version to 6.35
* new user or privacy order send same user info with zeros

* fix days field and removed some println! macro with nicer tracing messages

* bumped mostro-core version to 6.36 and added requested fix to compile
* add previous state in database for solver message

* bumped mostro-core version to 6.36
I think that could be modifies in a more generic UserInfo.
 (#473)

* added logic to send infos to maker when an order is taken

* Add takers info message for maker

* fix cargo.toml

* set peer pubkey to empty string when notifying taker reputation to maker

* moved user info message to the right point of the order flow

* fix cargo.toml

* changed message struct from UserDisputeInfo to UserInfo

* fix: get master keys for user infos

* Bumped mostro-core to version 6.38
@coderabbitai

coderabbitai Bot commented Apr 30, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request introduces a comprehensive refactor and enhancement of error handling, dependency management, and control flow across the codebase. The generic anyhow error handling is replaced with a custom MostroError type, resulting in signature changes for many functions and improved error propagation. Several utility functions are added or refactored, such as for order expiration, dispute retrieval, and reputation notification. Database access functions and event publishing routines are updated for more explicit error management. The PR also updates dependencies in Cargo.toml, modifies database schema migrations, and improves documentation and code clarity in key modules.

Changes

File(s) Change Summary
Cargo.toml Updated dependencies: nostr-sdk (0.38.0→0.40.0), mostro-core (0.6.28→0.6.38), removed anyhow.
migrations/20230928145530_disputes.sql Added non-nullable column order_previous_status to disputes table.
src/app.rs Removed unused anyhow::Result import; updated signature verification and error handling; updated handle_message_action to pass my_keys to admin dispute action.
src/app/add_invoice.rs Renamed check_order_status to pay_new_invoice; restructured control flow; added taker reputation notification; improved error handling and messaging.
src/app/admin_add_solver.rs, src/app/rate_user.rs, src/app/take_buy.rs, src/app/take_sell.rs, src/lightning/mod.rs Removed unused anyhow::Result imports.
src/app/admin_cancel.rs, src/app/admin_settle.rs Replaced event.rumor.pubkey with event.sender in logic; inverted cooperative cancel/dispute checks; updated tag/event construction and sending.
src/app/admin_take_dispute.rs Refactored with helper for solver info; updated function signatures; improved message construction and sending; used mostro_keys parameter.
src/app/dispute.rs Refactored control flow; simplified counterpart info logic; added notify_dispute_to_users; updated tag/event creation.
src/app/fiat_sent.rs Changed Peer construction to explicit struct initialization.
src/app/order.rs Added detailed doc comment to order_action function.
src/app/release.rs Improved privacy order handling in event creation; conditionally includes user data in tags; minor event sending change.
src/bitcoin_price.rs Replaced anyhow::Result with MostroError; improved error mapping and propagation in price updates and retrieval.
src/cli.rs Changed settings_init to return Result<PathBuf, MostroError>; updated error handling.
src/cli/settings.rs Replaced anyhow::Error with MostroError in all TryFrom implementations and init_default_dir; explicit error mapping for env/file ops.
src/db.rs Replaced anyhow::Result with Result<T, MostroError> in all functions; explicit error mapping for SQL/IO/validation errors.
src/flow.rs Added call to notify_taker_reputation in hold_invoice_paid flow.
src/main.rs Cleaned up imports; changed Nostr subscription to use a single filter.
src/messages.rs Changed hold_invoice_description to return Result<String, MostroError>.
src/nip33.rs Refactored tag/event creation; added conditional tag creation based on order status; improved reputation tag handling.
src/scheduler.rs Changed error handling to use MostroError; updated event sending and logging.
src/util.rs Added/rewrote functions for expiration, tag generation, event publishing, dispute retrieval, and taker reputation notification; improved error handling and documentation.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant DB
    participant Nostr
    participant LN

    User->>App: Sends message (e.g., add invoice, dispute)
    App->>DB: Query/update order/dispute/user
    App->>LN: (If needed) Interact with Lightning node
    App->>Nostr: Publish event or send DM (with tags)
    App->>App: Notify taker reputation (if applicable)
    App->>User: Respond/acknowledge via Nostr
Loading

Possibly related PRs

  • MostroP2P/mostro#390: Refactors dispute handling and message action processing, overlapping with changes to src/app.rs and src/app/dispute.rs.
  • MostroP2P/mostro#479: Modifies the notify_taker_reputation function and its usage, directly related to new notification features in this PR.
  • MostroP2P/mostro#459: Removes the anyhow dependency and updates error handling to use MostroError, matching the error handling refactor in this PR.

Poem

In fields of code where errors once did roam,
The rabbits hopped, refactoring their home.
"No more anyhow!" they cheerfully decree,
"MostroError shall set our errors free!"
With tags and disputes, and reputation bright,
They nibble bugs away by morning light.
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@grunch grunch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🔭 Outside diff range comments (4)
src/app.rs (1)

316-334: 🛠️ Refactor suggestion

Signature is skipped when sender == rumor pubkey – verify anyway
Current logic only verifies sig when sender ≠ rumor. An attacker controlling the relay could still forge a GiftWrap with sender == rumor but an invalid signature. Verifying whenever Some(sig) is present (regardless of pubkey equality) closes that gap with negligible cost:

-if let Some(sig) = sig {
-    // Verify signature only if sender and rumor pubkey are different
-    if !sender_matches_rumor
-        && !Message::verify_signature(message_json, event.rumor.pubkey, sig)
-    {
+if let Some(sig) = sig {
+    if !Message::verify_signature(message_json, event.rumor.pubkey, sig) {
src/cli/settings.rs (1)

173-222: 🛠️ Refactor suggestion

Robustness: surface FS errors when default dir already exists
File::create_new(...) will error if settings.toml exists, which is correct, but the surrounding if create_dir(...).is_ok() swallows directory creation failures (e.g., permissions). If the directory wasn’t created, subsequent file operations will also fail, but with a less helpful message. Suggest early-returning on Err:

-        if std::fs::create_dir(settings_dir_default.clone()).is_ok() {
+        std::fs::create_dir(&settings_dir_default)
+            .map_err(|e| MostroInternalErr(ServiceError::IOError(e.to_string())))?;

This preserves the explicit IO error context.

src/app/admin_take_dispute.rs (1)

218-233: ⚠️ Potential issue

map_err usage produces type mismatch

map_err expects a closure (FnOnce(E) -> F) but MostroInternalErr is a variant, not a function.
Use an explicit closure so the compiler can construct the MostroError:

-        order.get_buyer_pubkey().map_err(MostroInternalErr)?,
+        order
+            .get_buyer_pubkey()
+            .map_err(|_| MostroInternalErr(ServiceError::InvalidPubkey))?,

Apply the same change for the seller branch below.

src/db.rs (1)

404-419: 🛠️ Refactor suggestion

is_user_present returns a User but the name suggests a boolean

Calling code will assume an existence-check returning bool, yet we return the whole User, and sqlx::fetch_one will raise an error for “not found”. Either:

  1. Keep the current return type but rename the function (e.g. get_user_by_pubkey)
  2. Keep the name and change to Result<Option<User>, MostroError> using fetch_optional.

Returning Option<User> is usually the most ergonomic for callers.

🧹 Nitpick comments (18)
src/app/admin_cancel.rs (2)

35-45: Avoid extra heap allocation when checking solver-assignment

event.sender is already a PublicKey; converting it to String forces an allocation for every call.
is_assigned_solver can accept &PublicKey (or &str derived on demand) to eliminate the allocation.

-match is_assigned_solver(pool, &event.sender.to_string(), order.id).await {
+match is_assigned_solver(pool, &event.sender, order.id).await {

If the helper currently expects a string slice, consider adding an overload or changing its signature; the public key’s hex can be produced inside the helper only when strictly necessary.


86-99: Minor: Tags::from_list call could be expressed with into()

Very small nit – Tags::from_list(vec![ … ]) allocates a temporary Vec. The API also accepts an iterator (impl IntoIterator). You can save one allocation:

-let tags: Tags = Tags::from_list(vec![
+let tags = Tags::from_list([

No functional difference, just a micro-optimisation.

src/bitcoin_price.rs (2)

36-40: Store rates with uppercase currency codes for case-insensitive lookup

get_price("usd") currently fails unless the caller uses the exact case found in the API (usually upper-case). Normalising keys once avoids surprises and additional allocations during every lookup.

-*prices_write = yadio_response.btc;
+*prices_write = yadio_response
+    .btc
+    .into_iter()
+    .map(|(k, v)| (k.to_uppercase(), v))
+    .collect();

Remember to apply the same normalisation in get_price.


43-51: Provide case-insensitive lookup and clearer error

Following the previous suggestion, you can avoid forcing callers to worry about case:

-let prices_read = BITCOIN_PRICES.read() ...?;
-prices_read.get(currency).cloned()
+let prices_read = BITCOIN_PRICES.read() ...?;
+prices_read.get(&currency.to_uppercase()).cloned()

Optionally introduce a dedicated ServiceError::CurrencyNotFound for better diagnostics rather than re-using NoAPIResponse.

src/app/add_invoice.rs (1)

16-36: Persist changes without cloning & reuse existing order instance

order.clone().update(pool) allocates a full copy just to persist one field. You already mutated payment_attempts; simply call order.update(pool) (if the trait takes &self). If an owned value is required, move the original.

-order
-    .clone()
-    .update(pool)
+order.update(pool)

Avoiding the clone removes an extra heap allocation and keeps intent clear.

src/app.rs (2)

282-286: Log the actual unwrap error for easier troubleshooting
tracing::warn!("Error unwrapping gift"); hides the concrete failure reason captured in the Err(e) branch. Exposing the e will greatly shorten incident-resolution time.

-                        Err(_) => {
-                            tracing::warn!("Error unwrapping gift");
+                        Err(e) => {
+                            tracing::warn!("Error unwrapping gift: {e}");

309-315: Avoid serialise-then-deserialise churn
message.clone().as_json() is performed here and again later in check_trade_index. Consider caching the JSON string once and passing a reference to downstream helpers to shave a few µs and an extra allocation per event.

src/app/dispute.rs (3)

31-47: Hard-coded custom tag keys – consider constants
"s", "y", and "z" appear multiple times across modules. Extracting them into const values (or an enum) will avoid typos and ease future schema changes.


83-89: Return type of get_counterpart_info is no longer self-describing
Changing the function to return only a bool loses clarity at the call-site (is_buyer_dispute). A small enum conveys intent without needing comments:

enum DisputeRole { Buyer, Seller }

fn get_counterpart_info(...) -> Result<DisputeRole, CantDoReason> { ... }

This also prevents accidental misuse of the truth-value.


209-227: get_*_pubkey() called twice – reuse references
The nested match clones and dereferences several times. A minor tidy-up:

let (initiator_pubkey, counterpart_pubkey) = if is_buyer_dispute {
    (order.get_buyer_pubkey()?, order.get_seller_pubkey()?)
} else {
    (order.get_seller_pubkey()?, order.get_buyer_pubkey()?)
};

reduces cloning and indirection.

src/app/admin_take_dispute.rs (1)

216-236: Reduce duplication when sending DMs to both parties

The two send_dm calls differ only by the destination key. Iterating over a slice of keys improves readability and reduces copy-paste risk.

src/nip33.rs (1)

166-167: Hard-coded 12-hour extension violates settings

The expiration tag is extended by a fixed 12h, ignoring mostro_settings.expiration_hours.
Using the configured value keeps behaviour consistent with users’ expectations.

src/util.rs (3)

175-188: Potential overflow when computing expires_at_max

Timestamp::now().as_u64() + Duration::days(...).num_seconds() can overflow i64 on very long uptimes or large max_expiration_days.
Use saturating_add or check the sum with checked_add.


224-240: Zero-value reputation tag leaks into first-time orders

When no user record is found, get_tags_for_new_order injects a rating tag with zeros, which may mislead takers.
Skip the rating tag instead:

-                order_to_tags(new_order_db, Some((0.0, 0, 0)))
+                order_to_tags(new_order_db, None)

526-529: Swallowing send errors hides relay outages

send_event(&event).await.is_err() only logs a warning.
Consider retrying or propagating the error so callers can react.

src/db.rs (3)

42-56: Error message does not correspond to the failure path

In this block we’re handling a migration failure, but the log says “Failed to create database connection”, which is misleading and will complicate troubleshooting.

-    "Failed to create database connection"
+    "Failed to run database migrations"

A precise log message is vital for operators triaging startup problems.


421-447: Lack of duplicate-key handling in add_new_user

Attempting to insert an already-existing pubkey will bubble up a raw SQLite error. If this situation is expected (e.g. idempotent user creation on first contact), consider:

.matching(|e| e.sqlite_error_code() == Some(sqlite3::ErrorCode::ConstraintViolation))
.then(|| MostroCantDo(CantDoReason::UserAlreadyExists))

or switch to INSERT OR IGNORE / INSERT … ON CONFLICT. This gives the caller a domain-specific error instead of a generic DB failure.


455-461: Public-key validation logic scattered & duplicated

The 64-hex-char check appears in several functions (update_user_trade_index, rating updates, pending-order checks). Extract it into a single validate_pubkey(&str) -> Result<(), MostroError> helper to avoid divergence and ensure future format changes propagate consistently.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d5df4c1 and 5fb8de6.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (26)
  • Cargo.toml (3 hunks)
  • migrations/20230928145530_disputes.sql (1 hunks)
  • src/app.rs (5 hunks)
  • src/app/add_invoice.rs (4 hunks)
  • src/app/admin_add_solver.rs (1 hunks)
  • src/app/admin_cancel.rs (4 hunks)
  • src/app/admin_settle.rs (4 hunks)
  • src/app/admin_take_dispute.rs (5 hunks)
  • src/app/dispute.rs (6 hunks)
  • src/app/fiat_sent.rs (2 hunks)
  • src/app/order.rs (1 hunks)
  • src/app/rate_user.rs (0 hunks)
  • src/app/release.rs (3 hunks)
  • src/app/take_buy.rs (0 hunks)
  • src/app/take_sell.rs (0 hunks)
  • src/bitcoin_price.rs (2 hunks)
  • src/cli.rs (2 hunks)
  • src/cli/settings.rs (8 hunks)
  • src/db.rs (33 hunks)
  • src/flow.rs (2 hunks)
  • src/lightning/mod.rs (0 hunks)
  • src/main.rs (2 hunks)
  • src/messages.rs (1 hunks)
  • src/nip33.rs (5 hunks)
  • src/scheduler.rs (6 hunks)
  • src/util.rs (12 hunks)
💤 Files with no reviewable changes (4)
  • src/lightning/mod.rs
  • src/app/take_buy.rs
  • src/app/take_sell.rs
  • src/app/rate_user.rs
🧰 Additional context used
🧬 Code Graph Analysis (8)
src/main.rs (1)
src/db.rs (1)
  • find_held_invoices (354-367)
src/flow.rs (1)
src/util.rs (2)
  • enqueue_order_msg (837-854)
  • notify_taker_reputation (949-1025)
src/cli.rs (1)
src/cli/settings.rs (1)
  • init_default_dir (173-222)
src/scheduler.rs (3)
src/db.rs (1)
  • connect (22-75)
src/app.rs (1)
  • e (355-355)
src/util.rs (1)
  • get_keys (458-468)
src/app/add_invoice.rs (1)
src/util.rs (6)
  • enqueue_order_msg (837-854)
  • get_order (910-923)
  • notify_taker_reputation (949-1025)
  • show_hold_invoice (568-646)
  • update_order_event (506-539)
  • validate_invoice (925-947)
src/bitcoin_price.rs (2)
src/util.rs (1)
  • reqwest (48-51)
src/app.rs (1)
  • e (355-355)
src/app/release.rs (2)
src/nip33.rs (2)
  • new_event (26-40)
  • order_to_tags (115-192)
src/db.rs (1)
  • is_user_present (404-419)
src/db.rs (1)
src/app.rs (1)
  • e (355-355)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: tests
🔇 Additional comments (37)
Cargo.toml (3)

19-19: Dependency version update for nostr-sdk looks good.

The version upgrade from 0.38.0 to 0.40.0 appears appropriate as part of the broader refactoring to use custom error types instead of anyhow.


40-40: Verify compatibility with this significant mostro-core version upgrade.

The mostro-core version has been updated from 0.6.28 to 0.6.38, which is a substantial jump of 10 minor versions.

Please ensure all tests pass with this updated dependency version. This upgrade likely introduces new functionality and possibly API changes that should be verified.


51-51: LGTM - Dev dependency formatting change.

This appears to be a minor formatting change in the dev dependencies section.

src/app/fiat_sent.rs (2)

56-59: Improved explicitness in Peer initialization.

Direct struct initialization makes the code more explicit about which fields are being set, improving readability and maintainability compared to using the Peer::new() constructor.


72-75: Consistent Peer initialization approach.

This change follows the same pattern as the earlier peer initialization, maintaining consistency in the codebase.

src/main.rs (3)

17-17: Improved import structure with crate-relative path.

Using crate::db::find_held_invoices makes the import hierarchy clearer and aligns with Rust best practices.


19-19: Consistent import pattern.

Using crate::lightning::LndConnector maintains consistency with the import style in the rest of the file.


93-93: Simplified client subscription call.

Changed from passing vec![subscription] to directly passing subscription, which is a cleaner approach if the API now supports accepting a single filter directly.

src/messages.rs (2)

1-1: Appropriate error handling import.

Replacing the generic anyhow::Result with the domain-specific MostroError aligns with the broader refactoring effort to use more explicit error types throughout the codebase.


7-7: Improved error type specificity.

Changing the return type from Result<String> to Result<String, MostroError> makes the error handling more explicit, following Rust best practices of clearly communicating possible error conditions.

src/app/admin_add_solver.rs (1)

38-39: Security check update aligns with codebase standardization

The change from checking event.rumor.pubkey to event.sender for authentication is consistent with the broader refactoring across admin modules. This establishes event.sender as the authoritative source for public key verification in admin actions.

migrations/20230928145530_disputes.sql (1)

5-5:

Details

❓ Verification inconclusive

Migration adds required column but lacks default value for existing records

The addition of the non-nullable order_previous_status column will enhance dispute tracking by storing the previous order status. However, this migration might fail on databases with existing records since it doesn't specify a default value for existing rows.

Consider validating this migration against a database with existing records or modifying it to include a default value:

-  order_previous_status varchar(10) not null,
+  order_previous_status varchar(10) not null DEFAULT 'unknown',

🏁 Script executed:

#!/bin/bash
# Check if there are existing disputes records that would be affected
echo "Checking for existing disputes records"
sqlite3 mostro.db "SELECT COUNT(*) FROM disputes;"

Length of output: 237


Ensure non-nullable column won’t break on existing data

In migrations/20230928145530_disputes.sql at line 5, you’ve added:

order_previous_status varchar(10) NOT NULL,

If the disputes table already contains rows, this migration will fail because there’s no value for existing records. Please verify and update the migration by either:

  • Adding a default value:
    - order_previous_status varchar(10) NOT NULL,
    + order_previous_status varchar(10) NOT NULL DEFAULT 'unknown',
  • Or backfilling before enforcing NOT NULL, for example:
    ALTER TABLE disputes ADD COLUMN order_previous_status varchar(10);
    UPDATE disputes SET order_previous_status = 'unknown' WHERE order_previous_status IS NULL;
    ALTER TABLE disputes ALTER COLUMN order_previous_status SET NOT NULL;

Request you to confirm whether there are existing dispute records in your environments and adjust the migration accordingly.

src/flow.rs (2)

1-1: Import updated to support new reputation notification functionality

The import statement has been updated to include the new notify_taker_reputation function that will be used later in the file.


108-112: Enhanced user experience with reputation notifications

Adding reputation notifications for takers provides valuable transparency about counterparty reliability, which helps users make more informed decisions. This implementation correctly calls the new utility function after sending messages to both parties.

src/app/order.rs (1)

50-89: Excellent documentation improvement

The added documentation for order_action thoroughly explains the function's purpose, behavior, parameters, error conditions, and includes a helpful usage example. This significantly improves code maintainability and developer onboarding.

src/cli.rs (3)

5-5: Import change aligns with error handling refactoring

The import of MostroError from mostro_core::error replaces the previously used anyhow::Result, supporting the codebase-wide shift to custom error types.


32-32: Function return signature updated for consistent error handling

The return type has been changed from anyhow::Result<PathBuf> to Result<PathBuf, MostroError>, making the error type explicit and consistent with the rest of the codebase.


35-39: Updated error propagation with explicit Ok wrapping

The function now wraps the result of init_default_dir with Ok(...) and uses the ? operator to propagate errors properly, matching the new return type signature.

src/app/admin_settle.rs (4)

34-34: Fixed solver verification to use correct event sender field

Changed from using event.rumor.pubkey to event.sender for solver verification, ensuring consistent access to the sender's public key throughout the codebase.


49-61: Improved control flow for cooperative cancellation

The logic for handling cooperative cancellation has been restructured to enqueue a message and return early if the order status is CooperativelyCanceled. This improves readability and makes the control flow more explicit.


86-87: Updated tag creation method

Changed from Tags::new to Tags::from_list for creating Tags, consistent with tag construction changes elsewhere in the codebase.


107-107: Changed event passing to use reference

Now passing a reference to the event (&event) rather than moving it, which is more efficient and aligns with similar changes across other modules.

src/scheduler.rs (5)

12-13: Added custom error imports to replace anyhow

Imported MostroError and ServiceError from mostro_core::error to support the codebase-wide shift from general anyhow error handling to custom error types.


127-127: Changed event sending to use references

Now passing references to events (&event) in client.send_event calls rather than moving them, which is more efficient and consistent with the pattern used elsewhere in the codebase.

Also applies to: 157-157, 214-214


235-235: Updated function return type for consistent error handling

Changed the return type of job_cancel_orders from anyhow::Result<()> to Result<(), MostroError>, aligning with the broader project-wide removal of anyhow in favor of MostroError.


238-253: Improved error handling with specific error types

Updated error handling in the database connection and key retrieval code to use specific MostroError variants with contextual information, rather than generic anyhow errors.


402-406: Enhanced logging with tracing instead of println

Replaced println! with tracing::info! for logging expired orders, which is a better practice for structured logging in a production application.

src/app/release.rs (3)

5-5: Added imports for Nostr event handling

Imported new_event and order_to_tags from the nip33 module to support the refactored create_order_event function.


117-117: Changed event sending to use reference

Now passing a reference to the event (&event) in the client.send_event call rather than moving it, which aligns with similar changes across the codebase.


406-428: Enhanced order event creation with privacy awareness

Significantly improved the create_order_event function to respect privacy settings:

  1. Now checks if the order is a full privacy order for both buyer and seller
  2. For non-private orders, fetches user reputation data and passes it to tag generation
  3. For private orders, omits reputation data in tags
  4. Adds validation to ensure tags are generated before creating an event
  5. Returns a specific error if tag creation fails

This approach properly respects user privacy settings while still providing reputation information when appropriate.

src/app/admin_cancel.rs (2)

48-60: Early-return branch never persists any state change

When the order is already CooperativelyCanceled you enqueue CooperativeCancelAccepted and immediately return, but no DB or event update is performed.
Is that intentional? If the goal is merely to acknowledge the request it’s fine, otherwise you may want to call update_order_event (or at least persist CooperativeCancelAccepted) before returning.


136-139: Inconsistent use of event.sender vs event.rumor.pubkey

Above, the solver (and DM recipients inside enqueue_order_msg) are identified with event.sender, yet for the admin DM you fall back to event.rumor.pubkey.

Please double-check that this is the intended recipient. If the new convention is “always trust sender”, the line below should be updated:

-send_dm(event.rumor.pubkey, sender_keys, message.clone(), None)
+send_dm(event.sender,        sender_keys, message.clone(), None)

Mixing the two may DM the wrong key in multi-proxy scenarios.

src/app/add_invoice.rs (1)

27-35: Potentially wrong notification recipient

enqueue_order_msg sends InvoiceUpdated to order.get_buyer_pubkey(), yet the buyer is the one who just updated the invoice. Shouldn’t the seller be informed instead?

Please verify the business rule; if notification should go to the counter-party, switch to order.get_seller_pubkey().

-        order.get_buyer_pubkey().map_err(MostroInternalErr)?,
+        order.get_seller_pubkey().map_err(MostroInternalErr)?,
src/app.rs (2)

234-236: Admin-take dispute call correctly forwards my_keys now – nice catch
Passing my_keys keeps the handler signature consistent with the recent refactor, preventing compile-time breakage.


298-306: Good move: deserialize directly into Message to avoid double parsing
The switch to (Message, Option<Signature>) removes the previous Value → Message detour and saves one allocation / traversal.

src/app/dispute.rs (1)

109-145: Queue operations ignore failures – bubble them up or log
enqueue_order_msg(...).await; returns () today, but if it ever evolves to Result, silent failures would break UX. Even now, the await may panic in case of channel closure. Consider:

if let Err(e) = enqueue_order_msg(...).await {
    tracing::error!("Unable to enqueue dispute notification: {e}");
}

or change the helper signature to propagate errors.

src/nip33.rs (1)

94-107: Boolean logic may skip events for valid states

create_status_tags sets create_event using is_sell_order().is_ok() / is_buy_order().is_ok().
Those calls return true even when the order is not of the expected kind but the check merely succeeded.
Use order.is_sell_order()? (or compare order.kind) to avoid false negatives.

Comment thread src/bitcoin_price.rs
Comment thread src/app/add_invoice.rs
Comment thread src/app/admin_take_dispute.rs
Comment thread src/app/admin_take_dispute.rs
Comment thread src/nip33.rs
Comment thread src/db.rs
Comment thread src/db.rs
Comment thread src/db.rs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/app/admin_take_dispute.rs (1)

117-121: Inconsistent public key access pattern

There's an inconsistency in how the public key is accessed. Line 119 uses direct field access my_keys.public_key while line 122 uses the method call my_keys.public_key().

According to previous discussions, both approaches work since the Keys struct has a public public_key field. For consistency, consider using the same approach throughout the codebase:

-            my_keys.public_key.to_string(),
+            my_keys.public_key().to_string(),

or:

-        if ev_pubkey.to_string() == my_keys.public_key().to_string()
+        if ev_pubkey.to_string() == my_keys.public_key.to_string()
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fb8de6 and 8588983.

📒 Files selected for processing (4)
  • src/app/add_invoice.rs (4 hunks)
  • src/app/admin_take_dispute.rs (5 hunks)
  • src/db.rs (33 hunks)
  • src/nip33.rs (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: tests
🔇 Additional comments (25)
src/app/add_invoice.rs (6)

16-36: Function name change clarifies purpose

The function has been renamed from check_order_status to pay_new_invoice, which better reflects its actual purpose. The implementation also consistently uses the MostroError type for better error handling.


48-48: Improved control flow with separate status check

Extracting the order status into a variable before processing makes the code more readable and maintainable.


60-69: Better status handling with explicit match

The match statement provides clearer handling for different order statuses, making the control flow easier to understand.


71-73: Added reputation notification improves user experience

Notifying the taker about the counterparty's reputation is a good enhancement that helps users make informed decisions.


81-90: Improved error handling for order event updates

This change properly handles errors from update_order_event by using a match statement with explicit error handling. The early return on error prevents proceeding with inconsistent order data.

This implementation addresses a previous review comment about ensuring DB consistency when update_order_event fails - now the operation is properly aborted on error.


92-111: Use of updated order data in messaging

Using the updated order data from active_order for subsequent messaging ensures consistency throughout the operation.

src/app/admin_take_dispute.rs (7)

20-108: Good extraction of dispute info preparation logic

The new helper function prepare_solver_info_message encapsulates the complex logic of constructing a SolverDisputeInfo object. It properly handles privacy modes, retrieves master pubkeys, and conditionally fetches user presence data.

The conditional logic for determining which party is the initiator and counterpart is well-structured, and the proper error handling throughout the function ensures robustness.


149-169: Improved dispute and order retrieval with better error handling

Using the utility function get_dispute and retrieving the order directly by ID simplifies the code and provides consistent error handling.


173-174: Updated dispute solver attribution

Now using event.sender instead of rumor.pubkey for setting the solver's public key, which correctly attributes the dispute to the event sender.


185-186: Use of dedicated helper for solver info message

Using the extracted helper function prepare_solver_info_message makes the code more modular and readable.


206-215: Improved message structure with solver peer info

Using Payload::Peer with the solver's public key provides a cleaner interface for communicating solver information to users.


217-238: Use of passed mostro_keys parameter

Using the passed mostro_keys parameter instead of fetching keys internally reduces duplication and improves consistency.


277-278: Proper reference passing for event sending

Using &event instead of passing by value ensures efficient event passing to the send_event method.

src/nip33.rs (7)

35-35: Consistent tag list building

Using Tags::from_list instead of Tags::new maintains consistency in tag construction throughout the codebase.


50-68: Fixed rating tag creation with proper JSON formatting

The updated function now correctly handles missing reputation data by returning an empty JSON object "{}" instead of a sentinel string. It also properly handles the case where the reputation timestamp is zero.

This change addresses a previous review comment about returning valid JSON when reputation data is missing, which prevents downstream JSON parsing errors.


93-107: Well-structured status tag mapping function

The new helper function create_status_tags encapsulates the logic for mapping order statuses to NIP69-compatible statuses and determining whether to create event tags. This improves code organization and reusability.


115-118: Improved function signature with Result and Optional return

Changing the return type to Result<Option<Tags>, MostroError> properly handles both errors and the case when no tags should be created.


119-129: Proper handling of Lightning network data

Using LN_STATUS.get() to retrieve the current Lightning network status ensures accurate network information in the tags.


179-191: Conditional reputation tag insertion

Conditionally inserting the reputation tag at a specific index only when data is available improves the handling of optional data.


203-203: Consistent tag list construction

Using Tags::from_list for info tags maintains consistency with the tag creation pattern used elsewhere in the file.

src/db.rs (5)

23-37: Improved database file creation with OpenOptions

The code now uses OpenOptions with create_new(true) instead of std::fs::File::create_new, making it compatible with stable Rust while maintaining the same functionality.

This change addresses a previous review comment about using stable Rust APIs instead of nightly-only features.


55-57: Consistent error handling pattern

The consistent use of MostroInternalErr(ServiceError::DbAccessError(e.to_string())) for database errors improves error specificity and consistency.


135-146: Standardized error handling in database queries

All database query functions now consistently return Result<_, MostroError> with appropriate error mapping, which aligns with the broader codebase changes to remove anyhow in favor of custom error types.


570-572: Added cross-field consistency check for ratings

The added check ensures that min_rating <= last_rating <= max_rating, which preserves important data integrity constraints.

This change addresses a previous review comment about ensuring cross-field consistency in rating data, preventing contradictory data such as having min_rating > last_rating.


597-601: Improved logging for solver assignment

Using tracing::info! instead of debug prints provides better visibility into solver assignments for troubleshooting and monitoring.

@arkanoider arkanoider merged commit 3684988 into main Apr 30, 2025
2 checks passed
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.

4 participants