Skip to content

ci: cargo deny workflow#775

Open
hulxv wants to merge 2 commits into
citadel-tech:masterfrom
hulxv:ci/cargo-deny
Open

ci: cargo deny workflow#775
hulxv wants to merge 2 commits into
citadel-tech:masterfrom
hulxv:ci/cargo-deny

Conversation

@hulxv
Copy link
Copy Markdown
Collaborator

@hulxv hulxv commented Feb 19, 2026

Close #761

Summary by CodeRabbit

  • Chores
    • Added an automated security-audit workflow that runs on pushes, pull requests, manual trigger, and a weekly schedule.
    • Included a comprehensive, ready-to-edit configuration template for dependency and license scanning with guidance and sensible defaults.
    • Updated a dependency declaration to use a package-name override and a newer version to improve supply-chain resolution.

Copilot AI review requested due to automatic review settings February 19, 2026 13:41
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds cargo-deny as a CI workflow to audit dependencies for vulnerabilities and license compliance, addressing issue #761. The goal is to help identify vulnerable dependencies and maintain security best practices by adding automated dependency auditing to the continuous integration pipeline.

Changes:

  • Added a new GitHub Actions workflow file for running cargo-deny security audits
  • Added a cargo-deny configuration file (deny.toml) to control the audit behavior

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/audit.yaml New GitHub Actions workflow to run cargo-deny checks in CI
deny.toml Configuration file for cargo-deny specifying rules for advisories, licenses, bans, and sources

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/audit.yaml
Comment thread deny.toml Outdated
@hulxv hulxv force-pushed the ci/cargo-deny branch 2 times, most recently from 2ae7415 to 28d9313 Compare February 19, 2026 13:51
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 19, 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

Adds a GitHub Actions "Security Audit" workflow to run cargo-deny on pushes/PRs to master, weekly Cron, and manual triggers; adds a comprehensive deny.toml cargo-deny configuration template; and updates the serde_cbor dependency in Cargo.toml to { package = "serde_cbor_2", version = "0.13" }.

Changes

Cohort / File(s) Summary
GitHub Actions Audit Workflow
\.github/workflows/audit.yaml
New workflow "Security Audit" triggered on push/PR to master, weekly Cron (Sunday 00:00), and workflow_dispatch; defines a cargo-deny job that checks out the repo and runs EmbarkStudios/cargo-deny-action@v2 with argument check all.
Cargo‑Deny Configuration
deny.toml
Added a full deny.toml template containing commented defaults and examples for graph, output, advisories, licenses, bans, and sources sections.
Dependency update
Cargo.toml
Updated serde_cbor dependency from "0.11.2" to an explicit package override: { package = "serde_cbor_2", version = "0.13" }.

Sequence Diagram(s)

sequenceDiagram
  participant Dev as Developer
  participant GH as GitHub Actions
  participant Repo as Repository
  participant Action as EmbarkStudios/cargo-deny-action
  participant Tool as cargo-deny

  Dev->>GH: Push / PR / Manual trigger / Cron
  GH->>Repo: checkout repository
  GH->>Action: execute with "check all"
  Action->>Tool: run cargo-deny using `deny.toml`
  Tool->>Action: return audit results
  Action->>GH: report status and logs
  GH->>Dev: surface status / logs
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 I hop through TOML, sniffing every crate,
I chase misplaced versions before it's too late,
I tap the CI drum with a careful paw,
Guarding the tree with an anxious awe,
Carrots and checks — secure and elate.

🚥 Pre-merge checks | ✅ 4 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The changes include a cargo-deny workflow and configuration file directly supporting issue #761, but the Cargo.toml serde_cbor dependency change appears unrelated to the cargo-deny CI setup objective. Clarify whether the serde_cbor version change is necessary for cargo-deny compliance, or move it to a separate PR focused on dependency updates.
Description check ❓ Inconclusive The PR lacks detailed explanation beyond referencing issue #761, making it difficult to understand the rationale for included changes such as the serde_cbor dependency modification. Expand the PR description to explain all included changes and their relationship to the linked issue.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'ci: cargo deny workflow' directly and clearly summarizes the primary change—adding a cargo-deny security audit workflow to CI. It is concise and specific.
Linked Issues check ✅ Passed The PR implements issue #761's requirement to add cargo-deny to CI through a new GitHub Actions workflow and configuration file, enabling dependency vulnerability auditing as specified.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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
📝 Coding Plan for PR comments
  • Generate coding plan

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.

@hulxv hulxv force-pushed the ci/cargo-deny branch 2 times, most recently from cf0d52a to 17e081d Compare February 19, 2026 14:04
@codecov
Copy link
Copy Markdown

codecov Bot commented Feb 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.19%. Comparing base (776b75d) to head (fed44ac).
⚠️ Report is 130 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master     #775       +/-   ##
===========================================
+ Coverage   68.87%   83.19%   +14.32%     
===========================================
  Files          35       52       +17     
  Lines        4932    15153    +10221     
===========================================
+ Hits         3397    12607     +9210     
- Misses       1535     2546     +1011     

☔ 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.

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: 4

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

Inline comments:
In `@deny.toml`:
- Around line 42-45: The deny.toml currently sets the audit metadata flag
all-features = false which skips feature-gated dependencies from being audited;
change the setting to all-features = true so Deny collects metadata with
--all-features and includes feature-gated/optional dependencies in vulnerability
scans (update the all-features key value from false to true).
- Around line 220-231: The lint settings currently set unknown-registry = "warn"
and unknown-git = "warn", which permits unknown sources to pass CI; change these
to "deny" to enforce stricter supply-chain security so builds fail on unapproved
registries or git repos, and verify allow-registry and allow-git contain the
intended approved entries (symbols: unknown-registry, unknown-git,
allow-registry, allow-git).
- Around line 136-138: The commented example in the registries array has a
missing closing quote in the URL string; update the registries example (the
registries = [...] line) so the commented URL is properly quoted (e.g., ensure
"https://sekretz.com/registry" is enclosed in both opening and closing quotes)
and keep it commented as shown.
- Around line 88-107: Add "CC0-1.0" to the allow list in deny.toml so cargo-deny
won’t fail for the bitcoin v0.32 dependency; locate the allow = [...] array (the
explicit allow list near the top of the file) and insert "CC0-1.0" alongside
"MIT" and "Apache-2.0" entries, keeping the existing formatting and commas.

ℹ️ 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 8c0e3a3.

📒 Files selected for processing (2)
  • .github/workflows/audit.yaml
  • deny.toml

Comment thread deny.toml Outdated
Comment thread deny.toml
Comment thread deny.toml
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 @.github/workflows/audit.yaml:
- Around line 14-25: The cargo-deny job should be hardened by pinning the used
actions to immutable commit SHAs and restricting job token permissions: replace
uses: actions/checkout@v4 and uses: EmbarkStudios/cargo-deny-action@v2 with
their corresponding commit SHA references, and add a permissions block under the
cargo-deny job (e.g., permissions: contents: read) to limit the GITHUB_TOKEN
scope to the minimum required for these steps; update the job definition named
cargo-deny and the two step entries (Checkout repository and Run cargo-deny)
accordingly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c0e3a3 and e210064.

📒 Files selected for processing (2)
  • .github/workflows/audit.yaml
  • deny.toml

Comment thread .github/workflows/audit.yaml
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`:
- Line 22: Update the wallet recovery logic and add tests to guard against
serde_cbor_2 formatting changes: replace the fragile string check
format!("{e:?}").contains("code: TrailingData") in src/utill.rs (around the
wallet recovery path) with a robust match against the CBOR error type or variant
provided by serde_cbor_2 (e.g., inspect the error kind/variant instead of Debug
text) so detection does not depend on Debug formatting; then add regression
tests that simulate the trailing-data scenario for wallet deserialization (unit
tests near utill.rs or integration tests) to assert recovery still triggers with
serde_cbor_2, and run/verify that behavior with the updated dependency in
Cargo.toml.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f35454b2-7e01-45d6-9d57-2f3475a46ae2

📥 Commits

Reviewing files that changed from the base of the PR and between e210064 and 40f82fb.

📒 Files selected for processing (1)
  • Cargo.toml

Comment thread Cargo.toml
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_cbor = "0.11.2"
serde_cbor = { package = "serde_cbor_2", version = "0.13" }
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

❓ Verification inconclusive

Script executed:

#!/bin/bash
set -euo pipefail

echo "== Cargo.toml context (lines around 22) =="
sed -n '15,30p' Cargo.toml

echo -e "\n== serde_cbor usage in runtime paths =="
rg -n 'serde_cbor::(Error|from_slice|to_writer|ser::to_vec)' src/ --no-heading -A2 -B2 || echo "No matches found"

echo -e "\n== TrailingData string matching =="
rg -n 'TrailingData|format!\("\{e:\?\}"\)|contains.*code.*TrailingData' src/ --no-heading -A3 -B1 || echo "No matches found"

echo -e "\n== All serde_cbor references =="
rg -n 'serde_cbor' src/ --no-heading -A1 || echo "No matches found"

echo -e "\n== Wallet-related test files =="
fd -t f 'test|spec' tests/ 2>/dev/null | head -20 || echo "No tests dir found"

echo -e "\n== utill.rs around the claimed lines 724-750 =="
wc -l src/utill.rs
if [ $(wc -l < src/utill.rs) -ge 750 ]; then
  sed -n '720,760p' src/utill.rs
else
  echo "File is smaller than 750 lines; showing full file"
  wc -l src/utill.rs
fi

echo -e "\n== Check for Cargo.lock =="
if [ -f Cargo.lock ]; then
  grep -A2 'name = "serde_cbor' Cargo.lock | head -20
fi

Repository: citadel-tech/coinswap


Repository: citadel-tech/coinswap
Exit code: 0

stdout:

== Cargo.toml context (lines around 22) ==
keywords = ["bitcoin", "HTLC", "coinswap"]  

[dependencies]
bip39 =  { version = "2.1.0", features = ["rand"] }
bitcoin =  "0.32"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_cbor = { package = "serde_cbor_2", version = "0.13" }
log = "^0.4"
dirs = "3.0.1"
socks = "0.3.4"
clap = { version = "4.5", features = ["derive"] }
bitcoind = "0.36"
log4rs = "1.3.0"
secp256k1 = {git = "https://github.com/jlest01/rust-secp256k1.git", branch = "musig2-module", features = ["rand", "global-context"]}
minreq = { version = "2.12.0", features = ["https"] }

== serde_cbor usage in runtime paths ==
src/watch_tower/watcher_error.rs-21-    RPCError(bitcoind::bitcoincore_rpc::Error),
src/watch_tower/watcher_error.rs-22-    /// Serialization/deserialization error for CBOR.
src/watch_tower/watcher_error.rs:23:    SerdeCbor(serde_cbor::Error),
src/watch_tower/watcher_error.rs-24-    /// WebSocket error from tungstenite
src/watch_tower/watcher_error.rs-25-    WebSocket(tungstenite::Error),
--
src/watch_tower/watcher_error.rs-50-}
src/watch_tower/watcher_error.rs-51-
src/watch_tower/watcher_error.rs:52:impl From<serde_cbor::Error> for WatcherError {
src/watch_tower/watcher_error.rs:53:    fn from(value: serde_cbor::Error) -> Self {
src/watch_tower/watcher_error.rs-54-        Self::SerdeCbor(value)
src/watch_tower/watcher_error.rs-55-    }
--
src/watch_tower/registry_storage.rs-64-            match std::fs::read(&path) {
src/watch_tower/registry_storage.rs-65-                Ok(bytes) => Arc::new(Mutex::new(
src/watch_tower/registry_storage.rs:66:                    serde_cbor::from_slice(&bytes).unwrap_or_default(),
src/watch_tower/registry_storage.rs-67-                )),
src/watch_tower/registry_storage.rs-68-                Err(e) => {
--
src/wallet/storage.rs-129-
src/wallet/storage.rs-130-                // Write encrypted wallet data to disk.
src/wallet/storage.rs:131:                serde_cbor::to_writer(writer, &encrypted)?;
src/wallet/storage.rs-132-            }
src/wallet/storage.rs-133-            None => {
src/wallet/storage.rs-134-                // No encryption: serialize and write the wallet directly.
src/wallet/storage.rs:135:                serde_cbor::to_writer(writer, &self)?;
src/wallet/storage.rs-136-            }
src/wallet/storage.rs-137-        }
--
src/utill.rs-208-) -> Result<(), NetError> {
src/utill.rs-209-    let mut writer = BufWriter::new(socket_writer);
src/utill.rs:210:    let msg_bytes = serde_cbor::ser::to_vec(message)?;
src/utill.rs-211-    let msg_len = (msg_bytes.len() as u32).to_be_bytes();
src/utill.rs-212-    let mut to_send = Vec::with_capacity(msg_bytes.len() + msg_len.len());
--
src/utill.rs-483-    General(String),
src/utill.rs-484-    /// Cbor error
src/utill.rs:485:    Serde(serde_cbor::Error),
src/utill.rs-486-}
src/utill.rs-487-
--
src/utill.rs-492-}
src/utill.rs-493-
src/utill.rs:494:impl From<serde_cbor::Error> for TorError {
src/utill.rs:495:    fn from(value: serde_cbor::Error) -> Self {
src/utill.rs-496-        TorError::Serde(value)
src/utill.rs-497-    }
--
src/utill.rs-713-    fs::write(
src/utill.rs-714-        &tor_config_path,
src/utill.rs:715:        serde_cbor::ser::to_vec(&[private_key, hostname.clone()])?,
src/utill.rs-716-    )?;
src/utill.rs-717-
--
src/utill.rs-722-
src/utill.rs-723-/// Deserialize any generic type from a CBOR file. The type should impl [serde::de::Deserialize].
src/utill.rs:724:pub fn deserialize_from_cbor<T>(mut reader: Vec<u8>) -> Result<T, serde_cbor::Error>
src/utill.rs-725-where
src/utill.rs-726-    T: serde::de::DeserializeOwned,
src/utill.rs-727-{
src/utill.rs:728:    match serde_cbor::from_slice::<T>(&reader) {
src/utill.rs-729-        Ok(store) => Ok(store),
src/utill.rs-730-        Err(e) => {
--
src/utill.rs-735-                loop {
src/utill.rs-736-                    reader.pop();
src/utill.rs:737:                    match serde_cbor::from_slice::<T>(&reader) {
src/utill.rs-738-                        Ok(store) => break Ok(store),
src/utill.rs-739-                        Err(_) => continue,
--
src/utill.rs-1001-            let (mut socket, _) = listener.accept().unwrap();
src/utill.rs-1002-            let msg_bytes = read_message(&mut socket).unwrap();
src/utill.rs:1003:            let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes).unwrap();
src/utill.rs-1004-
src/utill.rs-1005-            if let MakerToTakerMessage::MakerHello(hello) = msg {
--
src/wallet/error.rs-19-    ///
src/wallet/error.rs-20-    /// This is used for encoding/decoding data structures.
src/wallet/error.rs:21:    Cbor(serde_cbor::Error),
src/wallet/error.rs-22-
src/wallet/error.rs-23-    /// Represents an error during JSON serialization or deserialization.
--
src/wallet/error.rs-115-    }
src/wallet/error.rs-116-}
src/wallet/error.rs:117:impl From<serde_cbor::Error> for WalletError {
src/wallet/error.rs:118:    fn from(value: serde_cbor::Error) -> Self {
src/wallet/error.rs-119-        Self::Cbor(value)
src/wallet/error.rs-120-    }
--
src/security.rs-26-pub enum EncryptError {
src/security.rs-27-    /// Error occurred during CBOR serialization of the input struct.
src/security.rs:28:    Serialization(serde_cbor::Error),
src/security.rs-29-    /// Error occurred during AES-GCM encryption.
src/security.rs-30-    ///
--
src/security.rs-34-}
src/security.rs-35-
src/security.rs:36:impl From<serde_cbor::Error> for EncryptError {
src/security.rs:37:    fn from(err: serde_cbor::Error) -> Self {
src/security.rs-38-        EncryptError::Serialization(err)
src/security.rs-39-    }
--
src/security.rs-90-
src/security.rs-91-impl SerdeFormat for SerdeCbor {
src/security.rs:92:    type Error = serde_cbor::Error;
src/security.rs-93-    fn from_slice<T: DeserializeOwned>(input: &[u8]) -> Result<T, Self::Error> {
src/security.rs-94-        utill::deserialize_from_cbor::<T>(input.to_vec())
--
src/security.rs-222-///
src/security.rs-223-/// This function applies the following transformation pipeline:
src/security.rs:224:/// `Struct -> serde_cbor::ser::to_vec(Struct) -> AES-GCM(encrypted_bytes) = encrypted_payload -> EncryptedData { encrypted_payload, nonce }`
src/security.rs-225-///
src/security.rs-226-///
--
src/security.rs-236-) -> Result<EncryptedData, EncryptError> {
src/security.rs-237-    // Serialize wallet data to bytes.
src/security.rs:238:    let packed_store = serde_cbor::ser::to_vec(&plain_struct)?;
src/security.rs-239-
src/security.rs-240-    // Extract nonce and key for AES-GCM.
--
src/security.rs-268-    encrypted_struct: EncryptedData,
src/security.rs-269-    enc_material: &KeyMaterial,
src/security.rs:270:) -> Result<T, serde_cbor::Error> {
src/security.rs-271-    // Deserialize the outer EncryptedWalletStore wrapper.
src/security.rs-272-
--
src/taker/routines.rs-45-    )?;
src/taker/routines.rs-46-    let msg_bytes = read_message(socket)?;
src/taker/routines.rs:47:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-48-
src/taker/routines.rs-49-    // Check that protocol version is always 1.
--
src/taker/routines.rs-108-
src/taker/routines.rs-109-    let msg_bytes = read_message(socket)?;
src/taker/routines.rs:110:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-111-    let contract_sigs_for_sender = match msg {
src/taker/routines.rs-112-        MakerToTakerMessage::RespContractSigsForSender(m) => {
--
src/taker/routines.rs-163-
src/taker/routines.rs-164-    let msg_bytes = read_message(socket)?;
src/taker/routines.rs:165:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-166-    let contract_sigs_for_recvr = match msg {
src/taker/routines.rs-167-        MakerToTakerMessage::RespContractSigsForRecvr(m) => {
--
src/taker/routines.rs-245-    // Recv ContractSigsAsRecvrAndSender.
src/taker/routines.rs-246-    let msg_bytes = read_message(socket)?;
src/taker/routines.rs:247:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-248-    let contract_sigs_as_recvr_and_sender = match msg {
src/taker/routines.rs-249-        MakerToTakerMessage::ReqContractSigsAsRecvrAndSender(m) => {
--
src/taker/routines.rs-383-
src/taker/routines.rs-384-    let msg_bytes = read_message(socket)?;
src/taker/routines.rs:385:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-386-    let privkey_handover = match msg {
src/taker/routines.rs-387-        MakerToTakerMessage::RespPrivKeyHandover(m) => {
--
src/taker/offers.rs-742-
src/taker/offers.rs-743-        let msg_bytes = read_message(&mut socket)?;
src/taker/offers.rs:744:        let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/offers.rs-745-        let offer = match msg {
src/taker/offers.rs-746-            MakerToTakerMessage::RespOffer(offer) => offer,
--
src/taker/offers.rs-776-        let response_bytes = read_message(&mut socket)?;
src/taker/offers.rs-777-
src/taker/offers.rs:778:        let response: messages2::MakerToTakerMessage = serde_cbor::from_slice(&response_bytes)?;
src/taker/offers.rs-779-
src/taker/offers.rs-780-        let taproot_offer = match response {
--
src/taker/error.rs-49-}
src/taker/error.rs-50-
src/taker/error.rs:51:impl From<serde_cbor::Error> for TakerError {
src/taker/error.rs:52:    fn from(value: serde_cbor::Error) -> Self {
src/taker/error.rs-53-        Self::Deserialize(value.to_string())
src/taker/error.rs-54-    }
--
src/error.rs-22-    /// Error related to CBOR (Concise Binary Object Representation) serialization or deserialization.
src/error.rs-23-    ///
src/error.rs:24:    /// This variant wraps a [`serde_cbor::Error`] to provide details about the issue.
src/error.rs:25:    Cbor(serde_cbor::Error),
src/error.rs-26-
src/error.rs-27-    /// Error indicating an invalid CLI application network.
--
src/error.rs-47-}
src/error.rs-48-
src/error.rs:49:impl From<serde_cbor::Error> for NetError {
src/error.rs:50:    fn from(value: serde_cbor::Error) -> Self {
src/error.rs-51-        Self::Cbor(value)
src/error.rs-52-    }
--
src/maker/server.rs-373-            }
src/maker/server.rs-374-        }
src/maker/server.rs:375:        let taker_msg = serde_cbor::from_slice::<TakerToMakerMessage>(&bytes)?;
src/maker/server.rs-376-
src/maker/server.rs-377-        log::info!("[{}] <=== {}", maker.config.network_port, taker_msg);
--
src/taker/api2.rs-829-        // Read response
src/taker/api2.rs-830-        let response_bytes = read_message(&mut socket)?;
src/taker/api2.rs:831:        let response: MakerToTakerMessage = serde_cbor::from_slice(&response_bytes)?;
src/taker/api2.rs-832-        log::info!("<=== {} | {maker_addr}", response);
src/taker/api2.rs-833-
--
src/maker/server2.rs-436-            ip
src/maker/server2.rs-437-        );
src/maker/server2.rs:438:        let message = match serde_cbor::from_slice::<TakerToMakerMessage>(&message_bytes) {
src/maker/server2.rs-439-            Ok(msg) => {
src/maker/server2.rs-440-                log::info!("[{}] <=== {}", maker.config.network_port, msg);
--
src/maker/error.rs-60-}
src/maker/error.rs-61-
src/maker/error.rs:62:impl From<serde_cbor::Error> for MakerError {
src/maker/error.rs:63:    fn from(value: serde_cbor::Error) -> Self {
src/maker/error.rs-64-        Self::Net(NetError::Cbor(value))
src/maker/error.rs-65-    }
--
src/maker/rpc/server.rs-29-fn handle_request<M: MakerRpc>(maker: &Arc<M>, socket: &mut TcpStream) -> Result<(), MakerError> {
src/maker/rpc/server.rs-30-    let msg_bytes = read_message(socket)?;
src/maker/rpc/server.rs:31:    let rpc_request: RpcMsgReq = serde_cbor::from_slice(&msg_bytes)?;
src/maker/rpc/server.rs-32-    log::info!("RPC request received: {rpc_request:?}");
src/maker/rpc/server.rs-33-
--
src/wallet/ffi.rs-116-        // If it succeeds, the wallet is encrypted
src/wallet/ffi.rs-117-        // If it fails, the wallet is plaintext
src/wallet/ffi.rs:118:        match serde_cbor::from_slice::<crate::security::EncryptedData>(&content) {
src/wallet/ffi.rs-119-            Ok(_) => Ok(true),   // Successfully parsed as EncryptedData = encrypted
src/wallet/ffi.rs-120-            Err(_) => Ok(false), // Failed to parse as EncryptedData = plaintext

== TrailingData string matching ==
src/utill.rs-730-        Err(e) => {
src/utill.rs:731:            let err_string = format!("{e:?}");
src/utill.rs:732:            if err_string.contains("code: TrailingData") {
src/utill.rs-733-                // Defensive error handling - monitor logs to confirm wallet files stay clean.
src/utill.rs-734-                log::info!("Wallet file has trailing data, trying to restore");
src/utill.rs-735-                loop {
--
src/maker/rpc/server.rs-182-                    if let Err(e) =
src/maker/rpc/server.rs:183:                        send_message(&mut stream, &RpcMsgResp::ServerError(format!("{e:?}")))
src/maker/rpc/server.rs-184-                    {
src/maker/rpc/server.rs-185-                        log::error!("Error sending RPC response {e:?}");
src/maker/rpc/server.rs-186-                    };

== All serde_cbor references ==
src/watch_tower/watcher_error.rs:23:    SerdeCbor(serde_cbor::Error),
src/watch_tower/watcher_error.rs-24-    /// WebSocket error from tungstenite
--
src/watch_tower/watcher_error.rs:52:impl From<serde_cbor::Error> for WatcherError {
src/watch_tower/watcher_error.rs:53:    fn from(value: serde_cbor::Error) -> Self {
src/watch_tower/watcher_error.rs-54-        Self::SerdeCbor(value)
--
src/watch_tower/registry_storage.rs:66:                    serde_cbor::from_slice(&bytes).unwrap_or_default(),
src/watch_tower/registry_storage.rs-67-                )),
--
src/watch_tower/registry_storage.rs:82:            match serde_cbor::to_vec(&RegistryData::default()) {
src/watch_tower/registry_storage.rs-83-                Ok(bytes) => {
--
src/watch_tower/registry_storage.rs:115:        let bytes = match serde_cbor::to_vec(&*data) {
src/watch_tower/registry_storage.rs-116-            Ok(bytes) => bytes,
--
src/wallet/storage.rs:131:                serde_cbor::to_writer(writer, &encrypted)?;
src/wallet/storage.rs-132-            }
--
src/wallet/storage.rs:135:                serde_cbor::to_writer(writer, &self)?;
src/wallet/storage.rs-136-            }
--
src/wallet/error.rs:21:    Cbor(serde_cbor::Error),
src/wallet/error.rs-22-
--
src/wallet/error.rs:117:impl From<serde_cbor::Error> for WalletError {
src/wallet/error.rs:118:    fn from(value: serde_cbor::Error) -> Self {
src/wallet/error.rs-119-        Self::Cbor(value)
--
src/wallet/ffi.rs:118:        match serde_cbor::from_slice::<crate::security::EncryptedData>(&content) {
src/wallet/ffi.rs-119-            Ok(_) => Ok(true),   // Successfully parsed as EncryptedData = encrypted
--
src/utill.rs:210:    let msg_bytes = serde_cbor::ser::to_vec(message)?;
src/utill.rs-211-    let msg_len = (msg_bytes.len() as u32).to_be_bytes();
--
src/utill.rs:485:    Serde(serde_cbor::Error),
src/utill.rs-486-}
--
src/utill.rs:494:impl From<serde_cbor::Error> for TorError {
src/utill.rs:495:    fn from(value: serde_cbor::Error) -> Self {
src/utill.rs-496-        TorError::Serde(value)
--
src/utill.rs:684:            let data: [&str; 2] = serde_cbor::de::from_slice(&tor_metadata)?;
src/utill.rs-685-
--
src/utill.rs:715:        serde_cbor::ser::to_vec(&[private_key, hostname.clone()])?,
src/utill.rs-716-    )?;
--
src/utill.rs:724:pub fn deserialize_from_cbor<T>(mut reader: Vec<u8>) -> Result<T, serde_cbor::Error>
src/utill.rs-725-where
--
src/utill.rs:728:    match serde_cbor::from_slice::<T>(&reader) {
src/utill.rs-729-        Ok(store) => Ok(store),
--
src/utill.rs:737:                    match serde_cbor::from_slice::<T>(&reader) {
src/utill.rs-738-                        Ok(store) => break Ok(store),
--
src/utill.rs:1003:            let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes).unwrap();
src/utill.rs-1004-
--
src/taker/routines.rs:47:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-48-
--
src/taker/routines.rs:110:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-111-    let contract_sigs_for_sender = match msg {
--
src/taker/routines.rs:165:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-166-    let contract_sigs_for_recvr = match msg {
--
src/taker/routines.rs:247:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-248-    let contract_sigs_as_recvr_and_sender = match msg {
--
src/taker/routines.rs:385:    let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/routines.rs-386-    let privkey_handover = match msg {
--
src/taker/offers.rs:744:        let msg: MakerToTakerMessage = serde_cbor::from_slice(&msg_bytes)?;
src/taker/offers.rs-745-        let offer = match msg {
--
src/taker/offers.rs:778:        let response: messages2::MakerToTakerMessage = serde_cbor::from_slice(&response_bytes)?;
src/taker/offers.rs-779-
--
src/taker/error.rs:51:impl From<serde_cbor::Error> for TakerError {
src/taker/error.rs:52:    fn from(value: serde_cbor::Error) -> Self {
src/taker/error.rs-53-        Self::Deserialize(value.to_string())
--
src/security.rs:28:    Serialization(serde_cbor::Error),
src/security.rs-29-    /// Error occurred during AES-GCM encryption.
--
src/security.rs:36:impl From<serde_cbor::Error> for EncryptError {
src/security.rs:37:    fn from(err: serde_cbor::Error) -> Self {
src/security.rs-38-        EncryptError::Serialization(err)
--
src/security.rs:57:/// Due to potential trailing bytes left by `serde_cbor`, the CBOR variant delegates
src/security.rs-58-/// parsing to [`utill::deserialize_from_cbor`] that strips extra data before deserialization.
--
src/security.rs:86:/// `serde_cbor` may leave trailing data behind, which can cause
src/security.rs-87-/// parsing errors.
--
src/security.rs:92:    type Error = serde_cbor::Error;
src/security.rs-93-    fn from_slice<T: DeserializeOwned>(input: &[u8]) -> Result<T, Self::Error> {
--
src/security.rs:224:/// `Struct -> serde_cbor::ser::to_vec(Struct) -> AES-GCM(encrypted_bytes) = encrypted_payload -> EncryptedData { encrypted_payload, nonce }`
src/security.rs-225-///
--
src/security.rs:238:    let packed_store = serde_cbor::ser::to_vec(&plain_struct)?;
src/security.rs-239-
--
src/security.rs:270:) -> Result<T, serde_cbor::Error> {
src/security.rs-271-    // Deserialize the outer EncryptedWalletStore wrapper.
--
src/taker/api2.rs:831:        let response: MakerToTakerMessage = serde_cbor::from_slice(&response_bytes)?;
src/taker/api2.rs-832-        log::info!("<=== {} | {maker_addr}", response);
--
src/error.rs:24:    /// This variant wraps a [`serde_cbor::Error`] to provide details about the issue.
src/error.rs:25:    Cbor(serde_cbor::Error),
src/error.rs-26-
--
src/error.rs:49:impl From<serde_cbor::Error> for NetError {
src/error.rs:50:    fn from(value: serde_cbor::Error) -> Self {
src/error.rs-51-        Self::Cbor(value)
--
src/maker/server.rs:375:        let taker_msg = serde_cbor::from_slice::<TakerToMakerMessage>(&bytes)?;
src/maker/server.rs-376-
--
src/maker/server2.rs:438:        let message = match serde_cbor::from_slice::<TakerToMakerMessage>(&message_bytes) {
src/maker/server2.rs-439-            Ok(msg) => {
--
src/maker/rpc/server.rs:31:    let rpc_request: RpcMsgReq = serde_cbor::from_slice(&msg_bytes)?;
src/maker/rpc/server.rs-32-    log::info!("RPC request received: {rpc_request:?}");
--
src/maker/error.rs:62:impl From<serde_cbor::Error> for MakerError {
src/maker/error.rs:63:    fn from(value: serde_cbor::Error) -> Self {
src/maker/error.rs-64-        Self::Net(NetError::Cbor(value))

== Wallet-related test files ==
tests/liquidity_test.rs

== utill.rs around the claimed lines 724-750 ==
1152 src/utill.rs
    Ok(hostname)
}

/// Deserialize any generic type from a CBOR file. The type should impl [serde::de::Deserialize].
pub fn deserialize_from_cbor<T>(mut reader: Vec<u8>) -> Result<T, serde_cbor::Error>
where
    T: serde::de::DeserializeOwned,
{
    match serde_cbor::from_slice::<T>(&reader) {
        Ok(store) => Ok(store),
        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 serde_cbor::from_slice::<T>(&reader) {
                        Ok(store) => break Ok(store),
                        Err(_) => continue,
                    }
                }
            } else {
                Err(e)
            }
        }
    }
}

/// Interactive Selection by User for Utxos
pub fn interactive_select(
    mut choices: Vec<(ListUnspentResultEntry, UTXOSpendInfo)>,
    required_amount: Amount,
) -> Result<Vec<(ListUnspentResultEntry, UTXOSpendInfo)>, WalletError> {
    if choices.is_empty() {
        return Err(WalletError::General("No UTXOs available".to_string()));
    }

    let total_available: Amount = choices.iter().map(|(utxo, _)| utxo.amount).sum();
    if total_available < required_amount {
        return Err(WalletError::General(format!(

== Check for Cargo.lock ==

Script executed:

#!/bin/bash
set -euo pipefail

echo "== Searching for serde_cbor_2 references in repo =="
rg -n 'serde_cbor_2' . --type-list 2>/dev/null | head -30 || echo "No additional refs found"

echo -e "\n== Check for wallet tests and CBOR deserialization tests =="
find tests -name "*.rs" -type f 2>/dev/null | while read f; do
  echo "--- $f ---"
  wc -l "$f"
done

echo -e "\n== Look for wallet fixture or deserialization tests =="
rg -n 'deserialize.*cbor|wallet.*fixture|TrailingData|deserialize_from_cbor' tests/ --type rust -A3 -B1 2>/dev/null || echo "No test coverage found"

echo -e "\n== Cargo.toml context for dependencies and versions =="
cat Cargo.toml | head -40

Repository: citadel-tech/coinswap


Repository: citadel-tech/coinswap
Exit code: 0

stdout:

== Searching for serde_cbor_2 references in repo ==
No additional refs found

== Check for wallet tests and CBOR deserialization tests ==
--- tests/abort1.rs ---
255 tests/abort1.rs
--- tests/abort2_case1.rs ---
340 tests/abort2_case1.rs
--- tests/abort2_case2.rs ---
290 tests/abort2_case2.rs
--- tests/abort2_case3.rs ---
304 tests/abort2_case3.rs
--- tests/abort3_case1.rs ---
313 tests/abort3_case1.rs
--- tests/abort3_case2.rs ---
291 tests/abort3_case2.rs
--- tests/abort3_case3.rs ---
262 tests/abort3_case3.rs
--- tests/fidelity.rs ---
489 tests/fidelity.rs
--- tests/fidelity_renewal.rs ---
336 tests/fidelity_renewal.rs
--- tests/fidelity_timelock_violation.rs ---
127 tests/fidelity_timelock_violation.rs
--- tests/funding_dynamic_splits.rs ---
152 tests/funding_dynamic_splits.rs
--- tests/liquidity_test.rs ---
145 tests/liquidity_test.rs
--- tests/malice1.rs ---
260 tests/malice1.rs
--- tests/malice2.rs ---
267 tests/malice2.rs
--- tests/multi-taker.rs ---
223 tests/multi-taker.rs
--- tests/standard_swap.rs ---
279 tests/standard_swap.rs
--- tests/taker_cli.rs ---
180 tests/taker_cli.rs
--- tests/taproot_hashlock_recovery.rs ---
252 tests/taproot_hashlock_recovery.rs
--- tests/taproot_maker_abort1.rs ---
188 tests/taproot_maker_abort1.rs
--- tests/taproot_maker_abort2.rs ---
231 tests/taproot_maker_abort2.rs
--- tests/taproot_maker_abort3.rs ---
204 tests/taproot_maker_abort3.rs
--- tests/taproot_multi_maker.rs ---
200 tests/taproot_multi_maker.rs
--- tests/taproot_multi_taker.rs ---
223 tests/taproot_multi_taker.rs
--- tests/taproot_swap.rs ---
204 tests/taproot_swap.rs
--- tests/taproot_taker_abort1.rs ---
192 tests/taproot_taker_abort1.rs
--- tests/taproot_taker_abort2.rs ---
218 tests/taproot_taker_abort2.rs
--- tests/taproot_taker_abort3.rs ---
237 tests/taproot_taker_abort3.rs
--- tests/taproot_timelock_recovery.rs ---
256 tests/taproot_timelock_recovery.rs
--- tests/test_framework/mod.rs ---
866 tests/test_framework/mod.rs
--- tests/utxo_behavior.rs ---
701 tests/utxo_behavior.rs
--- tests/wallet_backup.rs ---
144 tests/wallet_backup.rs

== Look for wallet fixture or deserialization tests ==
No test coverage found

== Cargo.toml context for dependencies and versions ==
[package]
name = "coinswap"
version = "0.2.0"
authors = ["Developers at Citadel-Tech"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

description = "Functioning, minimal-viable binaries and libraries to perform a trustless, p2p Maxwell-Belcher Coinswap Protocol"
license = "MIT OR Apache-2.0"          
documentation = "https://docs.rs/coinswap"
homepage = "https://github.com/citadel-tech/coinswap" 
repository = "https://github.com/citadel-tech/coinswap" 
categories = ["Bitcoin", "Atomic Swap", "HTLC"]   
keywords = ["bitcoin", "HTLC", "coinswap"]  

[dependencies]
bip39 =  { version = "2.1.0", features = ["rand"] }
bitcoin =  "0.32"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_cbor = { package = "serde_cbor_2", version = "0.13" }
log = "^0.4"
dirs = "3.0.1"
socks = "0.3.4"
clap = { version = "4.5", features = ["derive"] }
bitcoind = "0.36"
log4rs = "1.3.0"
secp256k1 = {git = "https://github.com/jlest01/rust-secp256k1.git", branch = "musig2-module", features = ["rand", "global-context"]}
minreq = { version = "2.12.0", features = ["https"] }
pbkdf2 = { version = "0.12", features = ["simple"] }
aes-gcm = "0.10.3"
sha2 = "0.10.9"
rust-coinselect = "0.1.6"
crossterm = "0.29.0"
zmq = "0.10.0"
tungstenite = { version = "0.28.0", features = ["native-tls"]}
nostr = "0.44.2"
crossbeam-channel = "0.5.15"


serde_cbor_2 rust crate


serde_cbor_2 is a Rust crate that provides CBOR (Concise Binary Object Representation) serialization/deserialization via Serde, intended as a drop-in replacement for serde_cbor. (docs.rs)

Add it to Cargo.toml:

[dependencies]
serde_cbor_2 = "0.13"

(Docs.rs shows serde_cbor_2 0.13.0 as the latest.) (docs.rs)

Drop-in replacement pattern (keep importing serde_cbor in code):

[dependencies]
serde_cbor = { version = "0.12", package = "serde_cbor_2" }

(docs.rs)

Docs / repo:

  • Documentation is on docs.rs. (docs.rs)
  • Repository is kanidm/cbor on GitHub. (github.com)

Citations:


Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check git history or comments near Cargo.toml change =="
git log --oneline -n 20 -- Cargo.toml 2>/dev/null || echo "Git log not available"

echo -e "\n== Search for comments about serde_cbor_2 in codebase =="
rg -n 'serde_cbor_2|serde.cbor.*2|cbor.*fork|cbor.*compatible' . --type rust --type toml -B2 -A2 2>/dev/null || echo "No explanatory comments found"

echo -e "\n== Check if there's a comment in Cargo.toml itself =="
cat Cargo.toml | grep -A5 -B5 'serde_cbor'

echo -e "\n== Look for error format testing or TrailingData handling docs =="
rg -n 'TrailingData|trailing.*data' src/ --type rust -B3 -A3 2>/dev/null

Repository: citadel-tech/coinswap


Repository: citadel-tech/coinswap
Exit code: 0

stdout:

== Check git history or comments near Cargo.toml change ==
a8f8fe7 replace serde_cbor with serde_cbor_2 (close `#782`)

== Search for comments about serde_cbor_2 in codebase ==
./Cargo.toml-20-serde = { version = "1.0", features = ["derive"] }
./Cargo.toml-21-serde_json = "1.0"
./Cargo.toml:22:serde_cbor = { package = "serde_cbor_2", version = "0.13" }
./Cargo.toml-23-log = "^0.4"
./Cargo.toml-24-dirs = "3.0.1"

== Check if there's a comment in Cargo.toml itself ==
[dependencies]
bip39 =  { version = "2.1.0", features = ["rand"] }
bitcoin =  "0.32"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_cbor = { package = "serde_cbor_2", version = "0.13" }
log = "^0.4"
dirs = "3.0.1"
socks = "0.3.4"
clap = { version = "4.5", features = ["derive"] }
bitcoind = "0.36"

== Look for error format testing or TrailingData handling docs ==
src/security.rs-81-    }
src/security.rs-82-}
src/security.rs-83-/// CBOR implementation of `SerdeFormat`, using a utility wrapper
src/security.rs:84:/// that handles CBOR trailing data properly.
src/security.rs-85-///
src/security.rs:86:/// `serde_cbor` may leave trailing data behind, which can cause
src/security.rs-87-/// parsing errors.
src/security.rs-88-/// This wrapper [`utill::deserialize_from_cbor`] utility method to cleanly deserialize.
src/security.rs-89-pub struct SerdeCbor;
--
src/utill.rs-729-        Ok(store) => Ok(store),
src/utill.rs-730-        Err(e) => {
src/utill.rs-731-            let err_string = format!("{e:?}");
src/utill.rs:732:            if err_string.contains("code: TrailingData") {
src/utill.rs-733-                // Defensive error handling - monitor logs to confirm wallet files stay clean.
src/utill.rs:734:                log::info!("Wallet file has trailing data, trying to restore");
src/utill.rs-735-                loop {
src/utill.rs-736-                    reader.pop();
src/utill.rs-737-                    match serde_cbor::from_slice::<T>(&reader) {

Script executed:

#!/bin/bash
set -euo pipefail

echo "== Check for issue `#782` reference in code or git =="
git log --all --grep="782" --oneline 2>/dev/null || echo "Git grep not available"

echo -e "\n== Search for any test with trailing data or wallet recovery =="
rg -n 'trailing|TrailingData|pop.*reader|wallet.*recover' tests/ --type rust -B2 -A4 || echo "No tests found"

echo -e "\n== Check if serde_cbor_2 error type is documented in code =="
rg -n 'serde_cbor::Error|TrailingData' src/ --type rust -B1 -A3 2>/dev/null | head -60

echo -e "\n== Look for version info in Cargo.lock or documented compatibility =="
if [ -f Cargo.lock ]; then
  grep -A5 'serde_cbor' Cargo.lock | head -30
fi

echo -e "\n== Check if there's any documentation about the serde_cbor_2 swap =="
rg -n 'serde.cbor.*2|drop.in|compatible|replacement' . --type rust --type md --type toml -B2 -A2 2>/dev/null || echo "No docs found"

Repository: citadel-tech/coinswap


Repository: citadel-tech/coinswap
Exit code: 0

stdout:

== Check for issue `#782` reference in code or git ==
a8f8fe7 replace serde_cbor with serde_cbor_2 (close `#782`)

== Search for any test with trailing data or wallet recovery ==
No tests found

== Check if serde_cbor_2 error type is documented in code ==
src/watch_tower/watcher_error.rs-22-    /// Serialization/deserialization error for CBOR.
src/watch_tower/watcher_error.rs:23:    SerdeCbor(serde_cbor::Error),
src/watch_tower/watcher_error.rs-24-    /// WebSocket error from tungstenite
src/watch_tower/watcher_error.rs-25-    WebSocket(tungstenite::Error),
src/watch_tower/watcher_error.rs-26-    /// Nostr message parsing error
--
src/watch_tower/watcher_error.rs-51-
src/watch_tower/watcher_error.rs:52:impl From<serde_cbor::Error> for WatcherError {
src/watch_tower/watcher_error.rs:53:    fn from(value: serde_cbor::Error) -> Self {
src/watch_tower/watcher_error.rs-54-        Self::SerdeCbor(value)
src/watch_tower/watcher_error.rs-55-    }
src/watch_tower/watcher_error.rs-56-}
--
src/taker/error.rs-50-
src/taker/error.rs:51:impl From<serde_cbor::Error> for TakerError {
src/taker/error.rs:52:    fn from(value: serde_cbor::Error) -> Self {
src/taker/error.rs-53-        Self::Deserialize(value.to_string())
src/taker/error.rs-54-    }
src/taker/error.rs-55-}
--
src/wallet/error.rs-20-    /// This is used for encoding/decoding data structures.
src/wallet/error.rs:21:    Cbor(serde_cbor::Error),
src/wallet/error.rs-22-
src/wallet/error.rs-23-    /// Represents an error during JSON serialization or deserialization.
src/wallet/error.rs-24-    ///
--
src/wallet/error.rs-116-}
src/wallet/error.rs:117:impl From<serde_cbor::Error> for WalletError {
src/wallet/error.rs:118:    fn from(value: serde_cbor::Error) -> Self {
src/wallet/error.rs-119-        Self::Cbor(value)
src/wallet/error.rs-120-    }
src/wallet/error.rs-121-}
--
src/security.rs-27-    /// Error occurred during CBOR serialization of the input struct.
src/security.rs:28:    Serialization(serde_cbor::Error),
src/security.rs-29-    /// Error occurred during AES-GCM encryption.
src/security.rs-30-    ///
src/security.rs-31-    /// Note: This error type carries no additional information because
--
src/security.rs-35-
src/security.rs:36:impl From<serde_cbor::Error> for EncryptError {
src/security.rs:37:    fn from(err: serde_cbor::Error) -> Self {
src/security.rs-38-        EncryptError::Serialization(err)
src/security.rs-39-    }
src/security.rs-40-}
--
src/security.rs-91-impl SerdeFormat for SerdeCbor {
src/security.rs:92:    type Error = serde_cbor::Error;
src/security.rs-93-    fn from_slice<T: DeserializeOwned>(input: &[u8]) -> Result<T, Self::Error> {
src/security.rs-94-        utill::deserialize_from_cbor::<T>(input.to_vec())
src/security.rs-95-    }
--
src/security.rs-269-    enc_material: &KeyMaterial,
src/security.rs:270:) -> Result<T, serde_cbor::Error> {
src/security.rs-271-    // Deserialize the outer EncryptedWalletStore wrapper.
src/security.rs-272-
src/security.rs-273-    let nonce_vec = encrypted_struct.nonce;
--
src/error.rs-23-    ///
src/error.rs:24:    /// This variant wraps a [`serde_cbor::Error`] to provide details about the issue.

== Look for version info in Cargo.lock or documented compatibility ==

== Check if there's any documentation about the serde_cbor_2 swap ==
./src/wallet/ffi.rs:1://! FFI-compatible types for the Taker module.
./src/wallet/ffi.rs-2-//!
./src/wallet/ffi.rs:3://! This module provides Foreign Function Interface (FFI) compatible data structures
./src/wallet/ffi.rs-4-//! for exposing swap functionality and reporting to other languages.
./src/wallet/ffi.rs-5-
--
./Cargo.toml-20-serde = { version = "1.0", features = ["derive"] }
./Cargo.toml-21-serde_json = "1.0"
./Cargo.toml:22:serde_cbor = { package = "serde_cbor_2", version = "0.13" }
./Cargo.toml-23-log = "^0.4"
./Cargo.toml-24-dirs = "3.0.1"
--
./src/taker/api2.rs-1069-                log::error!("Dropping connection after sending SendersContract to Maker");
./src/taker/api2.rs-1070-                return Err(TakerError::General(
./src/taker/api2.rs:1071:                    "Taker dropping of after sending Senders Contract to Maker (test behavior) "
./src/taker/api2.rs-1072-                        .to_string(),
./src/taker/api2.rs-1073-                ));
--
./src/taker/api2.rs-1161-                            );
./src/taker/api2.rs-1162-                            return Err(TakerError::General(
./src/taker/api2.rs:1163:                                "Taker dropping of after receiving Senders Contract from Maker (test behavior) ".to_string(),));
./src/taker/api2.rs-1164-                        }
./src/taker/api2.rs-1165-                    }

serde_cbor_2 TrailingData error format compatibility


In serde_cbor_2, TrailingData (displayed as “trailing data”) means the deserializer successfully decoded one CBOR value, but there were still unread bytes left in the input—i.e., your input is not exactly one standalone CBOR item. [1]

Common causes:

  • You’re feeding a CBOR “sequence” (multiple CBOR values concatenated) to from_slice / from_reader (which expect one value).
  • Your transport/storage adds framing bytes (length prefixes, checksums, padding, etc.) after the CBOR payload.
  • You’re decoding from the middle of a buffer that contains more than one message.

What to do:

  • If you expect multiple CBOR values: use StreamDeserializer (iterator over consecutive CBOR values) instead of from_slice/from_reader. [2]
  • If you expect one value inside a larger buffer: use a Deserializer and then check byte_offset() to find where the decoded value ended (the docs show this pattern and how to get the “rest”). [2]

Format compatibility note:

  • serde_cbor_2 aims to be a drop-in replacement for serde_cbor and uses standard CBOR, but you must keep encoder/decoder settings aligned—e.g., if you enable packed encoding / legacy_enums(), the consumer must decode accordingly. Otherwise you can hit decode errors (including leftover bytes depending on framing). [2]

Sources
[1] https://docs.rs/serde_cbor_2/latest/src/serde_cbor_2/error.rs.html
[2] https://docs.rs/serde_cbor_2/latest/serde_cbor_2/


Verify error format compatibility and add wallet CBOR regression tests before merging.

The swap to serde_cbor_2 (v0.13) on line 22 is intentional (commit a8f8fe7 closed issue #782), but introduces a compatibility risk because the wallet recovery code at src/utill.rs:732 depends on CBOR error formatting stability. The code checks format!("{e:?}").contains("code: TrailingData") to detect and recover from trailing-data errors—if serde_cbor_2's Debug representation differs, this recovery will silently break for existing wallet files.

Confirm:

  1. Error format equivalence between serde_cbor and serde_cbor_2 for TrailingData errors
  2. Regression coverage for wallet deserialization with trailing-data scenarios (currently missing)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Cargo.toml` at line 22, Update the wallet recovery logic and add tests to
guard against serde_cbor_2 formatting changes: replace the fragile string check
format!("{e:?}").contains("code: TrailingData") in src/utill.rs (around the
wallet recovery path) with a robust match against the CBOR error type or variant
provided by serde_cbor_2 (e.g., inspect the error kind/variant instead of Debug
text) so detection does not depend on Debug formatting; then add regression
tests that simulate the trailing-data scenario for wallet deserialization (unit
tests near utill.rs or integration tests) to assert recovery still triggers with
serde_cbor_2, and run/verify that behavior with the updated dependency in
Cargo.toml.

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.

♻️ Duplicate comments (1)
Cargo.toml (1)

22-22: ⚠️ Potential issue | 🟠 Major

Harden trailing-data recovery before merging this crate swap.

At Line 22, moving to serde_cbor_2 is fine in principle, but current recovery in src/utill.rs depends on Debug string matching ("code: TrailingData"). That is brittle across crate/version changes and can silently disable wallet recovery behavior.

#!/bin/bash
set -euo pipefail

echo "== Find fragile TrailingData detection =="
rg -nP 'format!\("\{e:\?\}"\)\.contains\("code: TrailingData"\)' src/ -C2

echo -e "\n== Locate deserialization helper and call sites =="
rg -nP '\bdeserialize_from_cbor\s*\(' src/ tests/ -C2

echo -e "\n== Check for regression tests covering trailing-data recovery =="
rg -nP 'TrailingData|trailing data|deserialize_from_cbor' tests/ -C2 || true
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Cargo.toml` at line 22, The current trailing-data detection in src/utill.rs
(used by deserialize_from_cbor and its call sites) relies on matching the Debug
string "code: TrailingData", which is brittle across serde_cbor crate swaps;
replace the string-match with a proper error-type check: update the
deserialize_from_cbor error handling to match against the serde_cbor_2
trailing-data error variant (e.g., pattern-match the error enum or use the
crate's API like Error::TrailingData / an is_trailing_data/is_eof-like accessor)
instead of using format!(..).contains(...), update all call sites that expect
the old string, and add/adjust tests under tests/ to cover the trailing-data
recovery path so the behavior is verified after the serde_cbor -> serde_cbor_2
swap.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@Cargo.toml`:
- Line 22: The current trailing-data detection in src/utill.rs (used by
deserialize_from_cbor and its call sites) relies on matching the Debug string
"code: TrailingData", which is brittle across serde_cbor crate swaps; replace
the string-match with a proper error-type check: update the
deserialize_from_cbor error handling to match against the serde_cbor_2
trailing-data error variant (e.g., pattern-match the error enum or use the
crate's API like Error::TrailingData / an is_trailing_data/is_eof-like accessor)
instead of using format!(..).contains(...), update all call sites that expect
the old string, and add/adjust tests under tests/ to cover the trailing-data
recovery path so the behavior is verified after the serde_cbor -> serde_cbor_2
swap.

ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 8da40585-471c-47ac-8d4a-744f566ac083

📥 Commits

Reviewing files that changed from the base of the PR and between 40f82fb and a8f8fe7.

📒 Files selected for processing (1)
  • Cargo.toml

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 `@deny.toml`:
- Around line 221-232: The deny.toml currently sets unknown-git = "deny" while
allow-git = [] (and no allow-org entries), which will block the git-sourced
dependency secp256k1 referenced in Cargo.toml; to fix, add the git repository
URL ("https://github.com/jlest01/rust-secp256k1.git") to the allow-git list or
add the owning org/URL under the [sources.allow-org] configuration (so the
secp256k1 git dependency is permitted), ensuring the change is made in deny.toml
and references the existing unknown-git / allow-git / allow-org settings.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9cf9fa9a-a3f3-42e4-99dd-89ef13c9cc52

📥 Commits

Reviewing files that changed from the base of the PR and between a8f8fe7 and 5457b3d.

📒 Files selected for processing (3)
  • .github/workflows/audit.yaml
  • Cargo.toml
  • deny.toml

Comment thread deny.toml
Comment on lines +221 to +232
[sources]
# Lint level for what to happen when a crate from a crate registry that is not
# in the allow list is encountered
unknown-registry = "deny"
# Lint level for what to happen when a crate from a git repository that is not
# in the allow list is encountered
unknown-git = "deny"
# List of URLs for allowed crate registries. Defaults to the crates.io index
# if not specified. If it is specified but empty, no registries are allowed.
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
# List of URLs for allowed Git repositories
allow-git = []
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find Cargo.toml and deny.toml files
echo "== Finding relevant files =="
find . -name "Cargo.toml" -o -name "deny.toml" | head -20

echo -e "\n== Checking Cargo.toml for git dependencies =="
if [ -f "Cargo.toml" ]; then
  echo "Contents of Cargo.toml (git-related lines):"
  grep -n -E 'git\s*=' Cargo.toml || echo "No git dependencies found"
  echo -e "\nFull dependencies section:"
  sed -n '/^\[dependencies\]/,/^\[/p' Cargo.toml | head -40
else
  echo "Cargo.toml not found in root"
fi

echo -e "\n== Checking deny.toml sources section =="
if [ -f "deny.toml" ]; then
  echo "Lines 220-235 of deny.toml:"
  sed -n '220,235p' deny.toml
  echo -e "\nSearching for allow-git in deny.toml:"
  grep -n "allow-git" deny.toml
else
  echo "deny.toml not found in root"
fi

Repository: citadel-tech/coinswap

Length of output: 2117


🏁 Script executed:

#!/bin/bash

echo "== Full [sources.allow-org] section =="
grep -A 5 '\[sources.allow-org\]' deny.toml

echo -e "\n== Checking if github value exists in allow-org =="
awk '/\[sources.allow-org\]/,/^\[/' deny.toml | grep -E '^\s*github\s*='

Repository: citadel-tech/coinswap

Length of output: 358


Git dependency will fail: allow-git is empty but secp256k1 uses a git source.

The configuration sets unknown-git = "deny" with an empty allow-git = [] and empty github = [] in [sources.allow-org], but Cargo.toml declares a git dependency:

secp256k1 = {git = "https://github.com/jlest01/rust-secp256k1.git", branch = "musig2-module", ...}

This will cause cargo deny check sources to fail in CI.

🔧 Proposed fix to allow the git dependency
 # List of URLs for allowed Git repositories
-allow-git = []
+allow-git = ["https://github.com/jlest01/rust-secp256k1.git"]

Or use the allow-org section:

 [sources.allow-org]
 # github.com organizations to allow git sources for
-github = []
+github = ["jlest01"]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deny.toml` around lines 221 - 232, The deny.toml currently sets unknown-git =
"deny" while allow-git = [] (and no allow-org entries), which will block the
git-sourced dependency secp256k1 referenced in Cargo.toml; to fix, add the git
repository URL ("https://github.com/jlest01/rust-secp256k1.git") to the
allow-git list or add the owning org/URL under the [sources.allow-org]
configuration (so the secp256k1 git dependency is permitted), ensuring the
change is made in deny.toml and references the existing unknown-git / allow-git
/ allow-org settings.

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.

Add cargo deny to CI Replace unmaintained serde_cbor Update nostr-rs-relay to v0.9.0

2 participants