Skip to content

Replace serde_cbor with minicbor#784

Closed
Ferryx349 wants to merge 1 commit into
citadel-tech:masterfrom
Ferryx349:b2
Closed

Replace serde_cbor with minicbor#784
Ferryx349 wants to merge 1 commit into
citadel-tech:masterfrom
Ferryx349:b2

Conversation

@Ferryx349
Copy link
Copy Markdown

@Ferryx349 Ferryx349 commented Feb 27, 2026

Fixes- #782
Migrated from serde_cbor to minicbor_serde to maintain serde-based serialization across the codebase.
Included minicbor explicitly for implementing a custom to_writer adapter.

Ref.- https://docs.rs/minicbor-serde/latest/minicbor_serde/

Summary by CodeRabbit

  • Chores
    • Switched CBOR implementation to minicbor across the codebase and updated Cargo manifest.
    • Standardized CBOR encoding/decoding and error types/conversions everywhere.
    • Broadened CBOR support for many public data types (messages, wallet, registry) with explicit tags and helpers.
    • No deliberate changes to user-facing behavior or external APIs; functionality and UX remain unchanged.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR replaces direct serde_cbor usage with minicbor across the codebase, adding minicbor to Cargo.toml, introducing minicbor-based CBOR helpers in src/utill.rs and migrating serialization/deserialization, derives, and error types to use minicbor::Encode/Decode and minicbor::decode/encode paths.

Changes

Cohort / File(s) Summary
Manifest
Cargo.toml
Removed serde_cbor; added minicbor = { version = "0.24.4", features = ["derive", "alloc", "std"] }.
CBOR utilities & wrapper
src/utill.rs
Introduced minicbor-backed CBOR utilities (serialize/deserialize helpers, to_vec/from_slice, cbor module), updated function signatures and Tor hostname CBOR handling, adjusted TorError variants and From impls to minicbor error types.
Global error types
src/error.rs, src/security.rs, src/wallet/error.rs, src/maker/error.rs, src/taker/error.rs, src/watch_tower/watcher_error.rs
Replaced serde_cbor error types with minicbor::decode::Error; added mapping for minicbor::encode::Error where relevant (often as String/Encode variant); updated From impls and enum variants.
CLI / RPC / RPC messages
src/bin/maker-cli.rs, src/maker/rpc/server.rs, src/maker/rpc/messages.rs
Switched RPC request/response (de)serialization to minicbor::decode/Encode; added minicbor::Encode/Decode derives and CBOR field/variant tags for RpcMsgReq and RpcMsgResp; added CBOR helpers (json bytes, PathBuf).
Maker & RPC handling
src/maker/server.rs, src/maker/server2.rs
Replaced serde_cbor deserialization with minicbor::decode for incoming Maker messages; minimal control-flow change.
Taker: offers & routines & API
src/taker/offers.rs, src/taker/routines.rs, src/taker/api2.rs
Converted public/internal message and address types to derive minicbor Encode/Decode with per-field tags; replaced from_slice calls with minicbor::decode across fetch/handshake/routine flows.
Protocol messages
src/protocol/messages.rs, src/protocol/messages2.rs
Massive switch of many protocol structs/enums to minicbor::Encode/Decode with per-field/variant CBOR indices and many custom encode/decode helpers for keys, amounts, txs, signatures, scripts. Serialization behavior changed extensively (no public signature changes).
Security / encryption APIs
src/security.rs
Updated EncryptedData to derive minicbor Encode/Decode and tagged fields; encrypt/decrypt functions switched to minicbor-based serialization and error types; EncryptError variant types adjusted.
Wallet: storage, backup, fidelity, swapcoin, ffi
src/wallet/storage.rs, src/wallet/backup.rs, src/wallet/fidelity.rs, src/wallet/swapcoin.rs, src/wallet/ffi.rs
Added minicbor Encode/Decode derives, field tags and custom encode/decode hooks; replaced file write/read paths to use minicbor::to_vec/decode; updated wallet CBOR encoding helpers and file write flow.
Watch tower: registry & helpers
src/watch_tower/registry_storage.rs
Replaced serde_cbor with minicbor for registry persistence; implemented manual Encode/Decode for RegistryData, added helper (de)serializers, fallback/default handling and updated I/O flows.
Misc deserialization call sites
src/bin/..., src/* (various small files listed in diff)
Many calls changed from serde_cbor::from_slice / serde_cbor::to_vec / serde_cbor::to_writer to minicbor::decode / minicbor::to_vec or the new utill::cbor helpers; several files updated only for error-type adjustments.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • mojoX911

Poem

🐰 I swapped the cobby berry pie,

Minicbor hopped in — bright and spry,
Tags in rows and bytes in tune,
Hopping packets 'neath the moon,
🥕 CBOR carrots for all who try.

🚥 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 PR title 'Replace serde_cbor with minicbor' directly and clearly summarizes the main change across the codebase: migrating from the serde_cbor dependency to minicbor for CBOR serialization.
Docstring Coverage ✅ Passed Docstring coverage is 80.52% 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 unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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

@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: 3

🤖 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/utill.rs`:
- Around line 1153-1158: The module-level documentation for the cbor module is
currently outside the module; move that comment block into the cbor module and
convert the leading triple-slash comments to inner-line doc comments (use //!).
Locate the cbor module declaration (mod cbor { ... } or the module's file) and
place the documentation immediately inside the module body (or at the top of the
module file) as //! comments so it becomes true module-level documentation.

In `@src/watch_tower/watcher_error.rs`:
- Line 23: The enum variant SerdeCbor in watcher_error.rs is backend-specific;
rename it to a backend-agnostic name like CborError (wrapping the same
crate::utill::cbor::Error) and update all references. Replace occurrences of
SerdeCbor with CborError in the enum definition and adjust any pattern matches,
From/Into impls, Display/Debug/error conversions, and tests that construct or
match that variant so compilation and behavior remain unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 95a726e and d67aa77.

📒 Files selected for processing (18)
  • Cargo.toml
  • src/bin/maker-cli.rs
  • src/error.rs
  • src/maker/error.rs
  • src/maker/rpc/server.rs
  • src/maker/server.rs
  • src/maker/server2.rs
  • src/security.rs
  • src/taker/api2.rs
  • src/taker/error.rs
  • src/taker/offers.rs
  • src/taker/routines.rs
  • src/utill.rs
  • src/wallet/error.rs
  • src/wallet/ffi.rs
  • src/wallet/storage.rs
  • src/watch_tower/registry_storage.rs
  • src/watch_tower/watcher_error.rs

Comment thread src/utill.rs Outdated
Comment thread src/watch_tower/registry_storage.rs Outdated
Comment thread src/watch_tower/watcher_error.rs Outdated
Copy link
Copy Markdown

@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/security.rs (1)

270-287: ⚠️ Potential issue | 🟠 Major

decrypt_struct returns Result but panics on decryption failure.

Line 283 uses .expect(...), which crashes on wrong passphrase instead of returning an error. The return type at line 270 only represents CBOR errors, not AES-GCM decryption failures. This mirrors the asymmetry with encrypt_struct (line 236), which properly returns EncryptError for both encryption and serialization failures.

Suggested fix
+#[derive(Debug)]
+pub enum DecryptError {
+    Decryption,
+    Deserialization(crate::utill::cbor::Error),
+}
+
+impl From<aes_gcm::Error> for DecryptError {
+    fn from(_: aes_gcm::Error) -> Self {
+        DecryptError::Decryption
+    }
+}
+
+impl From<crate::utill::cbor::Error> for DecryptError {
+    fn from(err: crate::utill::cbor::Error) -> Self {
+        DecryptError::Deserialization(err)
+    }
+}
+
 pub fn decrypt_struct<T: DeserializeOwned>(
     encrypted_struct: EncryptedData,
     enc_material: &KeyMaterial,
-) -> Result<T, crate::utill::cbor::Error> {
+) -> Result<T, DecryptError> {
@@
-    let plaintext_cbor = cipher
-        .decrypt(&nonce, encrypted_struct.encrypted_payload.as_ref())
-        .expect("Error decrypting wallet, wrong passphrase?");
+    let plaintext_cbor = cipher
+        .decrypt(&nonce, encrypted_struct.encrypted_payload.as_ref())
+        .map_err(DecryptError::from)?;
@@
-    utill::deserialize_from_cbor::<T>(plaintext_cbor)
+    utill::deserialize_from_cbor::<T>(plaintext_cbor).map_err(DecryptError::from)
 }
🤖 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/utill.rs`:
- Around line 1195-1208: The mapping of serialization errors in to_writer
currently uses Debug formatting which can lose structured context; change the
map_err call in to_writer so it preserves a more useful error message (e.g., use
Display "{}" formatting of the error instead of "{:?}" or extend the Error enum
to include a variant for writer/serialization errors) so that errors from
minicbor_serde::Serializer and the WriteWrapper adapter are reported with
clearer text or their original error type (reference symbols: to_writer,
WriteWrapper, minicbor_serde::Serializer, Error::Custom).

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d67aa77 and 10ea2e0.

📒 Files selected for processing (18)
  • Cargo.toml
  • src/bin/maker-cli.rs
  • src/error.rs
  • src/maker/error.rs
  • src/maker/rpc/server.rs
  • src/maker/server.rs
  • src/maker/server2.rs
  • src/security.rs
  • src/taker/api2.rs
  • src/taker/error.rs
  • src/taker/offers.rs
  • src/taker/routines.rs
  • src/utill.rs
  • src/wallet/error.rs
  • src/wallet/ffi.rs
  • src/wallet/storage.rs
  • src/watch_tower/registry_storage.rs
  • src/watch_tower/watcher_error.rs

Comment thread src/utill.rs Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 28, 2026

Codecov Report

❌ Patch coverage is 48.68421% with 39 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.97%. Comparing base (776b75d) to head (b8f02e2).
⚠️ Report is 120 commits behind head on master.

Files with missing lines Patch % Lines
src/utill.rs 41.86% 25 Missing ⚠️
src/watch_tower/registry_storage.rs 57.14% 3 Missing ⚠️
src/watch_tower/watcher_error.rs 0.00% 3 Missing ⚠️
src/bin/maker-cli.rs 0.00% 1 Missing ⚠️
src/error.rs 0.00% 1 Missing ⚠️
src/maker/error.rs 0.00% 1 Missing ⚠️
src/maker/rpc/server.rs 0.00% 1 Missing ⚠️
src/security.rs 66.66% 1 Missing ⚠️
src/taker/error.rs 0.00% 1 Missing ⚠️
src/wallet/error.rs 0.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@             Coverage Diff             @@
##           master     #784       +/-   ##
===========================================
+ Coverage   68.87%   80.97%   +12.10%     
===========================================
  Files          35       52       +17     
  Lines        4932    15063    +10131     
===========================================
+ Hits         3397    12198     +8801     
- Misses       1535     2865     +1330     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread src/utill.rs Outdated
assert_eq!(returned_pubkey.to_string(), tweaked_pubkey.to_string());
}
}
pub mod cbor {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What is the purpose of these wrappers? from_slice and to_vec are already in minicbor_serde

https://docs.rs/minicbor-serde/0.6.2/minicbor_serde/#functions

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@hulxv Thanks for review, I have added the wrappers to isolate the serialization backend and prevent direct dependency on minicbor_serde across the codebase. This makes future backend swaps less invasive and centralizes error handling.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Happy to adjust based on feedback

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This makes future backend swaps less invasive and centralizes error handling.

I see that now. I am not sure if that's a good decision. It's not normal that we need to switch the library many times.

What do you think? @stark-3k @mojoX911

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

That makes sense. Will it work if I simplify this by removing the wrappers around to_vec and from_slice by using minicbor_serde directly, keeping only the necessary to_writer adapter?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nope we don't need this wrapper. I don't see its doing anything that we can't call inline.

This should not be a module.

Also as per minicbor-serde docs, we should be using minicbor-derive to get a more compact message format.

In contrast to minicbor-derive, this serde-based implementation makes no attempt to be particularly clever with regards to forward and backward compatibility, nor does it use integers instead of strings for struct field names or enum constructors. If those features are important, consider using minicbor-derive instead.

Comment thread src/utill.rs Outdated
Comment thread src/utill.rs Outdated
Copy link
Copy Markdown

@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 (2)
src/utill.rs (1)

728-741: ⚠️ Potential issue | 🔴 Critical

Trailing-data recovery loop can spin forever on irrecoverable input.

Line [735] starts an unbounded loop, and Line [736] keeps calling pop() even after the buffer is empty. If decode never succeeds, this becomes non-terminating.

🔧 Proposed fix
         Err(e) => {
             let err_string = format!("{e:?}");
             if err_string.contains("code: TrailingData") {
                 // Defensive error handling - monitor logs to confirm wallet files stay clean.
                 log::info!("Wallet file has trailing data, trying to restore");
-                loop {
-                    reader.pop();
-                    match crate::utill::cbor::from_slice::<T>(&reader) {
-                        Ok(store) => break Ok(store),
-                        Err(_) => continue,
-                    }
-                }
+                while !reader.is_empty() {
+                    reader.pop();
+                    if let Ok(store) = crate::utill::cbor::from_slice::<T>(&reader) {
+                        return Ok(store);
+                    }
+                }
+                Err(e)
             } else {
                 Err(e)
             }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/utill.rs` around lines 728 - 741, The recovery loop for TrailingData can
spin forever because it repeatedly calls reader.pop() without checking
emptiness; update the block handling
crate::utill::cbor::from_slice::<T>(&reader) so that inside the loop you first
check whether reader is empty (or whether pop returned Some) and if so return
the original Err(e) (or a new descriptive error) instead of continuing,
otherwise pop() and retry decoding; ensure you preserve the original error
context when bailing and reference the reader.pop() call and the
cbor::from_slice::<T> retry logic in your fix.
src/security.rs (1)

270-287: ⚠️ Potential issue | 🔴 Critical

Stop panicking in decrypt_struct; return decrypt failures as errors.

Line [283] uses expect(...), so a wrong passphrase/corrupted payload can crash the process even though the function returns Result. Also, Line [270] only exposes CBOR errors, so AES-GCM failures are not representable.

🔧 Proposed fix
+#[derive(Debug)]
+pub enum DecryptError {
+    Decryption,
+    Deserialization(crate::utill::cbor::Error),
+}
+
 pub fn decrypt_struct<T: DeserializeOwned>(
     encrypted_struct: EncryptedData,
     enc_material: &KeyMaterial,
-) -> Result<T, crate::utill::cbor::Error> {
+) -> Result<T, DecryptError> {
@@
     let plaintext_cbor = cipher
         .decrypt(&nonce, encrypted_struct.encrypted_payload.as_ref())
-        .expect("Error decrypting wallet, wrong passphrase?");
+        .map_err(|_| DecryptError::Decryption)?;
@@
-    utill::deserialize_from_cbor::<T>(plaintext_cbor)
+    utill::deserialize_from_cbor::<T>(plaintext_cbor)
+        .map_err(DecryptError::Deserialization)
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/security.rs` around lines 270 - 287, decrypt_struct currently panics on
AES-GCM failures via expect; change it to return decryption errors instead of
panicking by updating decrypt_struct's return type to a combined error (e.g., a
new SecurityError enum or an existing error type) that can represent both
aes_gcm::Error and crate::utill::cbor::Error, replace the expect call on
cipher.decrypt(...) with a match or map_err to convert aes_gcm::Error into that
combined error, then propagate that error to the caller before calling
utill::deserialize_from_cbor::<T>(...), ensuring
encrypted_struct.encrypted_payload, cipher.decrypt and
utill::deserialize_from_cbor are referenced when implementing the mapping or
From conversions.
🤖 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/utill.rs`:
- Around line 697-698: Replace the runtime panics caused by assert_eq!(hostname,
*hostname_data) and assert_eq!(private_key, *private_key_data) with a typed
error return (TorError) so production won't abort when persisted metadata and
live Tor response diverge; inside the function that compares hostname,
hostname_data, private_key, and private_key_data, perform equality checks and if
they differ return an appropriate TorError variant (e.g.,
TorError::MetadataMismatch or TorError::InvalidMetadata) including contextual
info (which field mismatched) instead of calling assert_eq!, and update the
function signature to propagate the TorError (Result<..., TorError>) where
necessary.

---

Outside diff comments:
In `@src/security.rs`:
- Around line 270-287: decrypt_struct currently panics on AES-GCM failures via
expect; change it to return decryption errors instead of panicking by updating
decrypt_struct's return type to a combined error (e.g., a new SecurityError enum
or an existing error type) that can represent both aes_gcm::Error and
crate::utill::cbor::Error, replace the expect call on cipher.decrypt(...) with a
match or map_err to convert aes_gcm::Error into that combined error, then
propagate that error to the caller before calling
utill::deserialize_from_cbor::<T>(...), ensuring
encrypted_struct.encrypted_payload, cipher.decrypt and
utill::deserialize_from_cbor are referenced when implementing the mapping or
From conversions.

In `@src/utill.rs`:
- Around line 728-741: The recovery loop for TrailingData can spin forever
because it repeatedly calls reader.pop() without checking emptiness; update the
block handling crate::utill::cbor::from_slice::<T>(&reader) so that inside the
loop you first check whether reader is empty (or whether pop returned Some) and
if so return the original Err(e) (or a new descriptive error) instead of
continuing, otherwise pop() and retry decoding; ensure you preserve the original
error context when bailing and reference the reader.pop() call and the
cbor::from_slice::<T> retry logic in your fix.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 10ea2e0 and c12e219.

📒 Files selected for processing (18)
  • Cargo.toml
  • src/bin/maker-cli.rs
  • src/error.rs
  • src/maker/error.rs
  • src/maker/rpc/server.rs
  • src/maker/server.rs
  • src/maker/server2.rs
  • src/security.rs
  • src/taker/api2.rs
  • src/taker/error.rs
  • src/taker/offers.rs
  • src/taker/routines.rs
  • src/utill.rs
  • src/wallet/error.rs
  • src/wallet/ffi.rs
  • src/wallet/storage.rs
  • src/watch_tower/registry_storage.rs
  • src/watch_tower/watcher_error.rs

Comment thread src/utill.rs Outdated
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Cargo.toml`:
- Around line 39-40: Confirm whether the project currently uses serde_cbor's
packed/integer-key encoding before replacing it with minicbor-serde: search for
usages of serde_cbor (e.g., serde_cbor::to_vec, serde_cbor::from_slice,
serde_cbor::ser::Serializer with packed/config options) and for all
serialization/deserialization codepaths that handle wallet files and network
messages; if any code paths use packed/integer keys, revert the dependency
change or add a migration/version field and conversion logic for wallet files
and a version/negotiation or compatibility layer for network messages so that
minicbor/minicbor-serde (which assumes string-key encoding for Serde-derived
types) can interoperate; otherwise, proceed with swapping to minicbor and
minicbor-serde.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c12e219 and b8f02e2.

📒 Files selected for processing (18)
  • Cargo.toml
  • src/bin/maker-cli.rs
  • src/error.rs
  • src/maker/error.rs
  • src/maker/rpc/server.rs
  • src/maker/server.rs
  • src/maker/server2.rs
  • src/security.rs
  • src/taker/api2.rs
  • src/taker/error.rs
  • src/taker/offers.rs
  • src/taker/routines.rs
  • src/utill.rs
  • src/wallet/error.rs
  • src/wallet/ffi.rs
  • src/wallet/storage.rs
  • src/watch_tower/registry_storage.rs
  • src/watch_tower/watcher_error.rs

Comment thread Cargo.toml Outdated
@Ferryx349
Copy link
Copy Markdown
Author

@coderrabit

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents

Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Cargo.toml`:
- Around line 39-40: Confirm whether the project currently uses serde_cbor's
packed/integer-key encoding before replacing it with minicbor-serde: search for
usages of serde_cbor (e.g., serde_cbor::to_vec, serde_cbor::from_slice,
serde_cbor::ser::Serializer with packed/config options) and for all
serialization/deserialization codepaths that handle wallet files and network
messages; if any code paths use packed/integer keys, revert the dependency
change or add a migration/version field and conversion logic for wallet files
and a version/negotiation or compatibility layer for network messages so that
minicbor/minicbor-serde (which assumes string-key encoding for Serde-derived
types) can interoperate; otherwise, proceed with swapping to minicbor and
minicbor-serde.

ℹ️ Review info

I have thoroughly verified the codebase and found that coinswap did not use any packed or integer-key representations.

Comment thread src/utill.rs Outdated
assert_eq!(returned_pubkey.to_string(), tweaked_pubkey.to_string());
}
}
pub mod cbor {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nope we don't need this wrapper. I don't see its doing anything that we can't call inline.

This should not be a module.

Also as per minicbor-serde docs, we should be using minicbor-derive to get a more compact message format.

In contrast to minicbor-derive, this serde-based implementation makes no attempt to be particularly clever with regards to forward and backward compatibility, nor does it use integers instead of strings for struct field names or enum constructors. If those features are important, consider using minicbor-derive instead.

Copy link
Copy Markdown

@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: 5

♻️ Duplicate comments (1)
src/watch_tower/registry_storage.rs (1)

83-95: ⚠️ Potential issue | 🔴 Critical

Do not swallow container decode failures in RegistryData::decode.

Current if let Ok(Some(...)) patterns discard decode errors and can turn invalid/corrupt payloads into empty in-memory state. That bypasses the intended error fallback path in FileRegistry::load and risks silent state loss.

💡 Suggested fix
-        if let Ok(Some(n)) = d.map() {
-            for _ in 0..n {
-                let k = decode_outpoint(d, &mut ())?;
-                let v: WatchRequest = serde_json::from_slice(d.bytes()?)
-                    .map_err(|_| minicbor::decode::Error::message("invalid wrap"))?;
-                watches.insert(k, v);
-            }
-        }
+        let n = d
+            .map()?
+            .ok_or_else(|| minicbor::decode::Error::message("indefinite map not supported"))?;
+        for _ in 0..n {
+            let k = decode_outpoint(d, &mut ())?;
+            let v: WatchRequest = serde_json::from_slice(d.bytes()?)
+                .map_err(|_| minicbor::decode::Error::message("invalid wrap"))?;
+            watches.insert(k, v);
+        }

         let mut fidelity = HashSet::new();
-        if let Ok(Some(n)) = d.array() {
-            for _ in 0..n {
-                let f: Fidelity = serde_json::from_slice(d.bytes()?)
-                    .map_err(|_| minicbor::decode::Error::message("invalid wrap"))?;
-                fidelity.insert(f);
-            }
-        }
+        let n = d
+            .array()?
+            .ok_or_else(|| minicbor::decode::Error::message("indefinite array not supported"))?;
+        for _ in 0..n {
+            let f: Fidelity = serde_json::from_slice(d.bytes()?)
+                .map_err(|_| minicbor::decode::Error::message("invalid wrap"))?;
+            fidelity.insert(f);
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/watch_tower/registry_storage.rs` around lines 83 - 95,
RegistryData::decode currently uses if let Ok(Some(...)) on d.map() and
d.array(), which silently ignores Err cases and treats corrupt payloads as
empty; update RegistryData::decode to explicitly propagate decode errors instead
of swallowing them by matching the Result from d.map() and d.array() (or using ?
where applicable), so any Err returned by the decoder is returned from
RegistryData::decode (preserving intent in FileRegistry::load). Ensure decoding
of entries (calls to decode_outpoint, serde_json::from_slice for WatchRequest
and Fidelity, and insertion into watches and fidelity) only runs when the
container count is Ok(Some(n)); return an appropriate minicbor::decode::Error
for Err cases rather than falling through.
🤖 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/bin/maker-cli.rs`:
- Around line 141-142: Replace the panic-causing expect when decoding RPC
responses so decode errors are returned as a MakerError instead of aborting:
change the decode call in maker-cli.rs (where response: RpcMsgResp is created)
to propagate errors (use map_err or ? to convert minicbor::decode's error into
an appropriate MakerError variant like MakerError::RpcDecode or add that variant
if missing) and return Result from the surrounding function so callers receive
the error path rather than panicking.

In `@src/maker/rpc/messages.rs`:
- Around line 209-222: The encoder encode_path_buf currently uses
x.to_str().unwrap_or("") which silently drops non-UTF8 paths; change
encode_path_buf to fail explicitly when to_str() is None by returning an
appropriate minicbor encode error instead of encoding an empty string (so
callers get a serialization error). Update encode_path_buf to check x.to_str(),
and on None return Err(minicbor::encode::Error::custom(...) or similar) with a
clear message; leave decode_path_buf unchanged (it can continue decoding a
String into PathBuf) so round-trip will surface non-UTF8 path errors during
encoding.

In `@src/protocol/messages2.rs`:
- Around line 338-349: The function decode_opt_public_key currently swallows
parsing failures by mapping FromStr::from_str(&s) errors to Ok(None); change it
so parse failures return Err(minicbor::decode::Error) instead of Ok(None): after
decoding the string in decode_opt_public_key, attempt to parse with
std::str::FromStr::from_str(&s) and map any parse error into a
minicbor::decode::Error (with a descriptive message like "invalid opt public
key"), then return that Err; keep the existing handling for Null values and only
return Ok(Some(pubkey)) on successful parse.

In `@src/wallet/swapcoin.rs`:
- Around line 1165-1174: The optional decoders (decode_opt_secret_key and
decode_opt_signature) currently swallow parse failures by calling .ok(), turning
malformed non-null inputs into None; change them to mirror decode_secret_key by
returning an Err on invalid data: when the type is not Null, read the bytes with
d.bytes()? and attempt to create the item with SecretKey::from_slice(...) (or
Signature::from_slice(...)) and convert any failure into a
minicbor::decode::Error (propagate with ? or map the failure to an appropriate
decode error) instead of returning Ok(None), so malformed payloads fail decoding
rather than silently coercing to None.

In `@src/watch_tower/registry_storage.rs`:
- Around line 61-67: The two uses of serde_json::to_vec(...).unwrap() in the
registry serialization (the v_bytes and f_bytes conversions inside the loops in
registry_storage.rs) must not panic; instead map the serde_json error into and
return an encode error so persistence can fail gracefully. Replace the unwraps
with error-aware conversions (e.g., serde_json::to_vec(v).map_err(|err| /*
convert into the same error type returned by e.bytes / the function */ )?) and
propagate that error out of the serialization function so e.bytes is only called
on a successful byte vector; do the same for the f_bytes path.

---

Duplicate comments:
In `@src/watch_tower/registry_storage.rs`:
- Around line 83-95: RegistryData::decode currently uses if let Ok(Some(...)) on
d.map() and d.array(), which silently ignores Err cases and treats corrupt
payloads as empty; update RegistryData::decode to explicitly propagate decode
errors instead of swallowing them by matching the Result from d.map() and
d.array() (or using ? where applicable), so any Err returned by the decoder is
returned from RegistryData::decode (preserving intent in FileRegistry::load).
Ensure decoding of entries (calls to decode_outpoint, serde_json::from_slice for
WatchRequest and Fidelity, and insertion into watches and fidelity) only runs
when the container count is Ok(Some(n)); return an appropriate
minicbor::decode::Error for Err cases rather than falling through.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8f02e2 and 5c05e8f.

📒 Files selected for processing (24)
  • Cargo.toml
  • src/bin/maker-cli.rs
  • src/error.rs
  • src/maker/error.rs
  • src/maker/rpc/messages.rs
  • src/maker/rpc/server.rs
  • src/maker/server.rs
  • src/maker/server2.rs
  • src/protocol/messages.rs
  • src/protocol/messages2.rs
  • src/security.rs
  • src/taker/api2.rs
  • src/taker/error.rs
  • src/taker/offers.rs
  • src/taker/routines.rs
  • src/utill.rs
  • src/wallet/backup.rs
  • src/wallet/error.rs
  • src/wallet/ffi.rs
  • src/wallet/fidelity.rs
  • src/wallet/storage.rs
  • src/wallet/swapcoin.rs
  • src/watch_tower/registry_storage.rs
  • src/watch_tower/watcher_error.rs

Comment thread src/bin/maker-cli.rs Outdated
Comment thread src/maker/rpc/messages.rs
Comment thread src/protocol/messages2.rs Outdated
Comment thread src/wallet/swapcoin.rs
Comment thread src/watch_tower/registry_storage.rs Outdated
@Ferryx349
Copy link
Copy Markdown
Author

@mojoX911 @hulxv, I have implemented migration using minicbor-derive taking ref. from doc. Along with that I have followed two stratagies inline helper functions and manual implementation of traits for some structs where normal implentation using minicbor:Encode/Decode is not supported cleanly and might be proved a bit messy.

@Ferryx349
Copy link
Copy Markdown
Author

Let me know if this approach works, happy to adjust on feedback.

@Ferryx349 Ferryx349 force-pushed the b2 branch 3 times, most recently from e31d34e to 0a38af3 Compare March 2, 2026 08:42
Signed-off-by: ABHAY PANDEY <pandeyabhay967@gmail.com>
@Ferryx349
Copy link
Copy Markdown
Author

While resolving merge conflicts during rebase, by mistake I have removed few varients which resulted in CI. I have fixed and tests are passing locally now.

@hulxv
Copy link
Copy Markdown
Collaborator

hulxv commented Mar 4, 2026

That's too much for replacing a library. After searching, I found serde_cbor_2. It's a maintained fork of serde_cbor. That should be enough for our case, and it should be merged with #775. Thanks too much for your contributions.

@hulxv hulxv closed this Mar 4, 2026
@Ferryx349
Copy link
Copy Markdown
Author

Got it, that makes sense, using serde_cbor_2 seems like a much simpler solution for our case.
Working on this helped me to explore the codebase much better, so I really appreciate the feedback. Happy to help with other issues in future.
Thanks :)

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