Skip to content

feat(platform-wallet): serde support#3637

Open
Claudius-Maginificent wants to merge 7 commits into
v3.1-devfrom
feat/rs-platform-wallet-serde
Open

feat(platform-wallet): serde support#3637
Claudius-Maginificent wants to merge 7 commits into
v3.1-devfrom
feat/rs-platform-wallet-serde

Conversation

@Claudius-Maginificent
Copy link
Copy Markdown
Collaborator

@Claudius-Maginificent Claudius-Maginificent commented May 13, 2026

Issue being fixed or feature implemented

Splits the rs-platform-wallet serde-support additions out of PR #3625 (feat(platform-wallet): add platform-wallet-storage crate (sqlite persister)) so they can land independently on v3.1-dev. Original commit (e26945cfdf by @lklimek) stays in PR #3625; this PR cherry-picks just the serde-additive changes for separate review/merge cadence — same hygiene pattern used for PR #3636 (birth_height_override split from PR #3549).

What was done?

Adds optional serde derives behind a serde feature flag on rs-platform-wallet's public types. 12 files, +154 lines. Touches:

  • packages/rs-platform-wallet/Cargo.toml — new [features] serde = ["dep:serde", "key-wallet/serde", "key-wallet-manager/serde", "dash-sdk/serde"] entry + optional serde dependency. Propagation reaches rs-sdk (AddressFunds), key-wallet (AssetLockFundingType — upstream derive after feat(key-wallet,key-wallet-manager): add serde derives for AssetLockFundingType and DerivedAddress rust-dashcore#761), and key-wallet-manager (DerivedAddress — upstream derive after fix commenting #761).
  • packages/rs-platform-wallet/src/changeset/changeset.rs and mod.rs updated with #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] attributes on the changeset types. No serde_adapters module — upstream now derives both AssetLockFundingType (via #761) and DerivedAddress (via #761 with a serde_pubkey33 adapter for the 33-byte pubkey field), so the changeset types serialize via plain derives.
  • packages/rs-sdk/src/platform/address_sync/types.rsAddressFunds gets a direct cfg_attr derive.
  • packages/rs-platform-wallet/src/wallet/cfg_attr derives on 8 leaf types in asset_lock/tracked.rs, identity/types/block_time.rs, identity/types/key_storage.rs, and identity/types/dashpay/{contact_request,established_contact,payment,profile}.rs.
  • Workspace Cargo.tomltemporary: 9 rust-dashcore deps swapped from rev = "53130869..." to branch = "feat/key-wallet-serde-derives" to consume feat(key-wallet,key-wallet-manager): add serde derives for AssetLockFundingType and DerivedAddress rust-dashcore#761 ahead of its upstream merge. Cargo's [patch] mechanism doesn't support same-source-different-branch redirects (rust-lang/cargo#5478, #10756); direct branch pinning is the working alternative. fix commenting #761's branch has been rebased onto 53130869 so it carries ONLY the serde additions (no v0.42-dev drift). Follow-up: drop the branch pin and restore rev = "<new>" after fix commenting #761 merges to v0.42-dev and a subsequent dashcore rev bump flows into this workspace.

No production-logic changes — purely additive serde derive lines + adapter helpers, behind a default-off feature gate.

Breaking Changes

None. The additions are behind a serde feature that's off by default.

How Has This Been Tested?

  • cargo check -p platform-wallet --no-default-features — clean
  • cargo check -p platform-wallet --features serde — clean
  • cargo check -p platform-wallet --tests --all-features — clean
  • cargo clippy -p platform-wallet --tests --all-features --no-deps -- -D warnings — zero warnings
  • cargo test -p platform-wallet --features serde --lib121/121 pass
  • cargo fmt — clean

Companion to

PR #3625 retains the same commit (e26945cfdf); this is a hygiene split for independent review cadence. When this PR merges to v3.1-dev, the cherry-pick in PR #3625 becomes a duplicate-by-content and git drops it on rebase.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests (feature-gated existing tests cover the new serde paths; no new tests needed for derive-only additions)
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any (no breaking changes — feature is opt-in)
  • I have made corresponding changes to the documentation if needed (no public-API surface change beyond the feature flag itself)

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Co-authored by Claudius the Magnificent AI Agent

Summary by CodeRabbit

  • New Features

    • Added serialization and deserialization support for wallet data when the serde feature is enabled, allowing wallet state persistence and data interchange capabilities across the platform.
  • Chores

    • Updated workspace dependencies to use a feature branch for Dashcore-related packages pending upstream changes.

Review Change Stack

Add a new `serde` Cargo feature on `platform-wallet`. When enabled,
every type carried in a `PlatformWalletChangeSet` gains
`serde::Serialize` / `serde::Deserialize` derives via
`#[cfg_attr(feature = "serde", derive(...))]`:

- `CoreChangeSet`, `IdentityChangeSet`, `IdentityEntry`,
  `IdentityKeysChangeSet`, `IdentityKeyEntry`,
  `IdentityKeyDerivationIndices`, `ContactChangeSet`,
  `ContactRequestEntry`, `SentContactRequestKey`,
  `ReceivedContactRequestKey`, `PlatformAddressChangeSet`,
  `PlatformAddressBalanceEntry`, `AssetLockChangeSet`,
  `AssetLockEntry`, `TokenBalanceChangeSet`,
  `WalletMetadataEntry`, `AccountRegistrationEntry`,
  `AccountAddressPoolEntry`, and the top-level
  `PlatformWalletChangeSet`.
- Per-identity / DashPay leaf types referenced inside those
  changesets: `BlockTime`, `IdentityStatus`, `DpnsNameInfo`,
  `DashPayProfile`, `ContactRequest`, `EstablishedContact`,
  `PaymentEntry`, `PaymentDirection`, `PaymentStatus`,
  `AssetLockStatus`.

The feature activates `key-wallet/serde` (which transitively flips
`dashcore/serde` and `dash-network/serde`) so every upstream leaf
type already wired with `#[cfg_attr(feature = "serde", ...)]`
(TransactionRecord, Utxo, InstantLock, AccountType, AddressInfo,
AddressPoolType, ExtendedPubKey, Network) round-trips cleanly.

Two upstream types lack their own serde feature and use
`#[serde(with = ...)]` adapters in the new
`src/changeset/serde_adapters.rs` module:
- `AssetLockFundingType` (key-wallet, no `serde` derive) — encoded
  as a stable u8 tag matching the prior hand-rolled blob layout.
- `AddressFunds` (dash-sdk re-export, no serde derive) — encoded
  as a `(nonce, balance)` shadow struct.

One field is marked `#[serde(skip)]`:
- `CoreChangeSet::addresses_derived` carries
  `key_wallet_manager::DerivedAddress`, which has no serde derive
  AND no `key-wallet-manager/serde` feature to activate. The
  breadcrumb is written to a typed table by persisters, not via a
  changeset blob, so skipping costs nothing.

`cargo build -p platform-wallet` (no features) and
`cargo build -p platform-wallet --features serde` both build
clean. `cargo test -p platform-wallet` passes (8 lib tests, 121
integration tests) with and without the new feature. The change
is opt-in; the default-feature build is byte-identical to its
prior shape.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

This PR introduces optional serde serialization support to wallet persistence types and application data structures. Root workspace dependencies are temporarily branch-pinned to an upstream dashcore feature branch. A new feature flag gates conditional serde derives across changeset persistence models, identity and asset-lock types, and SDK address types.

Changes

Serde Serialization Feature for Wallet Types

Layer / File(s) Summary
Workspace branch override
Cargo.toml
Root workspace dependencies for dashcore, dash-network-seeds, dash-spv, key-wallet, and related crates are pinned to feat/key-wallet-serde-derives branch until upstream changes land.
Serde feature wiring
packages/rs-platform-wallet/Cargo.toml
New optional serde feature with derive support is declared and wired to propagate through key-wallet, key-wallet-manager, and dash-sdk dependencies.
Changeset persistence model serde support
packages/rs-platform-wallet/src/changeset/changeset.rs
Conditional serde derives are added to 19 persistence structs: CoreChangeSet, identity/contact/address/asset-lock/token change sets, wallet metadata, account registration, and address pool entries.
Wallet type definitions serde support
packages/rs-platform-wallet/src/wallet/asset_lock/tracked.rs, packages/rs-platform-wallet/src/wallet/identity/types/block_time.rs, packages/rs-platform-wallet/src/wallet/identity/types/dashpay/..., packages/rs-platform-wallet/src/wallet/identity/types/key_storage.rs
Conditional serde derives added to AssetLockStatus, BlockTime, ContactRequest, EstablishedContact, PaymentDirection, PaymentStatus, PaymentEntry, DashPayProfile, IdentityStatus, and DpnsNameInfo.
SDK address types serde support
packages/rs-sdk/src/platform/address_sync/types.rs
AddressFunds struct gains conditional serde derives for SDK-wide compatibility.
Code formatting
packages/rs-platform-wallet/src/wallet/platform_addresses/wallet.rs
Function call reformatted from multi-line to single-line layout without behavioral changes.

🎯 2 (Simple) | ⏱️ ~12 minutes

🐰 Serde derives spring to life,
Feature-gated without strife,
Wallet types now serialize and decode,
Dependencies hop down the feature road,
Persistence models bloom in light!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(platform-wallet): serde support' accurately summarizes the main change: adding optional serde serialization/deserialization support to platform-wallet types via a new Cargo feature.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rs-platform-wallet-serde

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.

@github-actions github-actions Bot added this to the v3.1.0 milestone May 13, 2026
@lklimek lklimek changed the title feat(rs-platform-wallet): serde support feat(platform-wallet): serde support May 13, 2026
Per audit: `AddressFunds` is first-party (lives in
`rs-sdk/src/platform/address_sync/types.rs`) and its inner fields
(`AddressNonce = u32`, `Credits = u64`) come from `dpp`, which derives
serde unconditionally. The `#[serde(with = "serde_adapters::address_funds")]`
adapter was pure boilerplate re-implementing what
`derive(Serialize, Deserialize)` would produce. Replaced with a direct
`#[cfg_attr(feature = "serde", derive(...))]` on `AddressFunds`.

The `asset_lock_funding_type` adapter is retained — the upstream
`AssetLockFundingType` in `rust-dashcore` key-wallet has no serde
derives, and the adapter also encodes a stable `u8` wire-tag for
on-disk blob compatibility that's worth keeping documented.

Net: -~30 LOC. `platform-wallet`'s `serde` feature now propagates
`dash-sdk/serde` so the gated derive on `AddressFunds` is activated
when the parent feature is on. (Stray `cargo fmt -p platform-wallet`
hit one pre-existing formatting nit in
`wallet/platform_addresses/wallet.rs` — included since the quality
gate runs fmt.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Claudius-Maginificent
Copy link
Copy Markdown
Collaborator Author

Audit-driven cleanup landed (9485e542af)

Quick post-creation audit pass on serde_adapters.rs flagged that the address_funds adapter was speculative — AddressFunds lives at packages/rs-sdk/src/platform/address_sync/types.rs:51-57 (first-party, not upstream), and its inner fields (AddressNonce = u32, Credits = u64) are primitives that always-Serialize. The custom adapter was pure boilerplate re-implementing what derive(Serialize, Deserialize) would produce.

Verified empirically: replaced the adapter with a direct #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] on AddressFunds + appended "dash-sdk/serde" to platform-wallet's serde feature, then ran cargo check --no-default-features AND cargo check --features serde AND cargo clippy --all-features -- -D warnings AND cargo test --features serde --lib (121/121 pass). All green.

Net: 5 files / +3 / -45 LOC.

Kept: the asset_lock_funding_type adapter (lines 19–55 of serde_adapters.rs). Reason: upstream AssetLockFundingType in rust-dashcore@5313086 key-wallet/.../asset_lock_builder.rs:22-37 doesn't derive serde, AND the adapter additionally encodes a stable u8 wire-tag worth keeping documented for pre-serde blob compat.

Architectural smell flagged for follow-up (out of scope for this PR): the serde_adapters.rs module header still says "upstream types that don't (yet) derive their own Serialize/Deserialize" — but with AddressFunds removed, the only remaining adapter (asset_lock_funding_type) is genuinely for an upstream type. The header is now accurate by accident. If we ever add another wire-tag-stable enum adapter for our own types, the module description should be updated to reflect "stable wire-tag enums" rather than just "missing serde derives".

🤖 Co-authored by Claudius the Magnificent AI Agent

Scope: PR #3637's own diff against v3.1-dev only (the serde-feature PR).
Pre-existing v3.1-dev comments left untouched.

Drivers:
- Verbosity: the Cargo.toml `serde` feature note was 12 lines enumerating
  every leaf type that gains a derive — collapsed to 6 lines covering the
  meaningful "what activates" + "which field is skipped" bits.
- Verbosity: the `addresses_derived` `#[serde(skip)]` paragraph trimmed
  from 7 lines to 4, keeping the external-constraint citation (upstream
  type has no serde derive, no feature to activate) and the pointer to
  where persisters actually store the breadcrumb.
- Present-state, not history: the `asset_lock_funding_type` adapter
  docstring referenced "the hand-rolled BlobWriter used before the serde
  swap" — that's PR history, dropped. Kept the meaningful "stable u8 tag
  for on-disk blob compat" rationale.
- Verbosity / redundant-with-cfg: the `serde_adapters.rs` module header
  said "compiled only when the serde feature is on" with a paragraph
  pointing back to the `#[cfg(feature = "serde")]` line that imports it.
  The cfg gate is self-documenting; trimmed from 6 lines to 2 and
  rephrased "upstream types that don't (yet) derive" to "upstream types
  lacking their own derives" now that only one adapter remains.

No tombstones added. No code semantics touched. cargo fmt + check
(both feature flag states) + clippy --all-features + lib tests (121
passing) all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…rop serde workarounds

Workspace `Cargo.toml` swapped `rev = "53130869..."` for `branch =
"feat/key-wallet-serde-derives"` on all 9 rust-dashcore crates to consume
PR #761's serde derives ahead of upstream merge. Cargo's `[patch]`
mechanism doesn't support same-source-different-branch redirects
(rust-lang/cargo#5478, #10756); direct branch pinning is the working
mechanism. Cargo.lock now resolves the 12 dashcore-sourced crates at
`56a84402c8cb006d65b12e400785a62d67441930`, which the branch has been
rebased onto so it carries ONLY the serde additions (no v0.42-dev drift).

Dropped `serde_adapters::asset_lock_funding_type` adapter — type now
derives upstream via #761. `serde_adapters.rs` deleted and removed from
`changeset/mod.rs`.

Dropped `#[serde(skip)]` on `CoreChangeSet::addresses_derived` —
`DerivedAddress` now derives upstream (with `serde_pubkey33` adapter
packaged inside #761 for the 33-byte pubkey field).

Added `"key-wallet-manager/serde"` to platform-wallet's serde feature.

Wire-format note: the upstream derive on `AssetLockFundingType` produces
externally-tagged enum representation; the dropped custom adapter
produced a stable `u8` wire-tag. PR #3637 is unreleased and the feature
is opt-in — no consumer was persisting blobs with the prior format.

Follow-up after #761 merges to v0.42-dev: swap `branch = "..."` back to
`rev = "<new-rev>"` and remove the temp comment in workspace Cargo.toml.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@lklimek lklimek marked this pull request as ready for review May 13, 2026 14:23
@Claudius-Maginificent
Copy link
Copy Markdown
Collaborator Author

Consuming dashpay/rust-dashcore#761 (561ccb4902)

After the earlier audit + comment cleanup commits, three "TODO once upstream lands" workarounds remained on this PR:

  1. serde_adapters::asset_lock_funding_type custom #[serde(with = ...)] adapter (because upstream AssetLockFundingType lacked serde derives)
  2. #[serde(skip)] on CoreChangeSet::addresses_derived (because upstream DerivedAddress lacked serde derives)
  3. "key-wallet-manager/serde" missing from the feature array (because that feature didn't exist upstream)

Cleared all three in one shot by branch-pinning to dashpay/rust-dashcore#761 which adds the upstream derives. Mechanism note: Cargo's [patch] block doesn't support same-source-different-branch redirects (cargo#5478, cargo#10756) — the working mechanism is to swap rev = "..." for branch = "..." directly in workspace dep declarations. Did that for all 9 rust-dashcore-sourced crates.

To keep the rev-shift narrow, #761's branch was rebased onto 53130869 (platform's current pin) — so it carries ONLY the serde-derive additions, no v0.42-dev drift. Cargo.lock confirmed 12 crates shifted to 56a84402c8, zero unrelated churn.

Net change in this commit: +41 / -96 across 6 files (Cargo.toml + Cargo.lock + changeset.rs + Cargo.toml + mod.rs + serde_adapters.rs deletion).

Quality gates — all green: cargo check --no-default-features + --features serde + --tests --all-features, clippy -D warnings, 121/121 lib tests, and cargo check --workspace confirms no wider-workspace breakage from the rev shift.

Follow-up after #761 merges: drop the branch pin in workspace Cargo.toml and restore rev = "<new>". The branch-pin block has an inline TODO comment marking this single remaining cleanup hook.

🤖 Co-authored by Claudius the Magnificent AI Agent

@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented May 13, 2026

✅ Review complete (commit 5fe906e)

lklimek and others added 2 commits May 13, 2026 16:31
`platform_wallet_info_create_from_mnemonic` now takes 3 args
(network, mnemonic, out_handle); the integration tests still passed a
4th `std::ptr::null()` between `mnemonic` and `out_handle`, breaking the
mac nextest job. Sync both call sites with the current FFI signature.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing `matches!(result, Err(_))` patterns trip
`clippy::redundant_pattern_matching` under the workspace's `-D warnings`
gate. Swap to `result.is_err()` so the clippy step stays green for the
crates this PR touches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 13, 2026

✅ DashSDKFFI.xcframework built for this PR.

SwiftPM (host the zip at a stable URL, then use):

.binaryTarget(
  name: "DashSDKFFI",
  url: "https://your.cdn.example/DashSDKFFI.xcframework.zip",
  checksum: "76ca1c5f6be6ac74b73870da500a5273d73030168e63366771f3dcbde3ca2472"
)

Xcode manual integration:

  • Download 'DashSDKFFI.xcframework' artifact from the run link above.
  • Drag it into your app target (Frameworks, Libraries & Embedded Content) and set Embed & Sign.
  • If using the Swift wrapper package, point its binaryTarget to the xcframework location or add the package and place the xcframework at the expected path.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.24%. Comparing base (3b9fe6b) to head (5fe906e).
⚠️ Report is 5 commits behind head on v3.1-dev.

Additional details and impacted files
@@             Coverage Diff              @@
##           v3.1-dev    #3637      +/-   ##
============================================
- Coverage     88.25%   88.24%   -0.01%     
============================================
  Files          2494     2506      +12     
  Lines        304580   307938    +3358     
============================================
+ Hits         268812   271745    +2933     
- Misses        35768    36193     +425     
Components Coverage Δ
dpp 88.00% <92.17%> (+0.01%) ⬆️
drive 87.33% <76.72%> (-0.04%) ⬇️
drive-abci 90.24% <94.62%> (+0.07%) ⬆️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.17% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 53.62% <4.16%> (-0.60%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

Purely additive PR adding opt-in serde derives behind a new serde feature on rs-platform-wallet changeset/wallet types plus AddressFunds in rs-sdk. No blocking issues. Two material suggestions: (1) the temporary workspace-wide switch from rev = to branch = on nine rust-dashcore crates weakens reproducibility, and (2) several newly-Serialize-able changesets use composite/struct BTreeMap keys ((Identifier, KeyID), OutPoint, SentContactRequestKey, (Identifier, Identifier)) which compile cleanly but fail at runtime under serde_json. Minor coverage and style nits round out the review.

Reviewed commit: f23183c

🟡 3 suggestion(s) | 💬 1 nitpick(s)

1 additional finding

🟡 suggestion: Newly-serializable changesets use non-string map keys — incompatible with `serde_json`

packages/rs-platform-wallet/src/changeset/changeset.rs (lines 358-363)

Several types behind the new serde feature use BTreeMap/BTreeSet keys that serde-derives can encode for binary formats (bincode/CBOR/MessagePack) but that serde_json rejects at runtime with key must be a string:

  • IdentityKeysChangeSet::upserts: BTreeMap<(Identifier, KeyID), _> (line 360)
  • IdentityKeysChangeSet::removed: BTreeSet<(Identifier, KeyID)> (line 362)
  • ContactChangeSet::sent_requests/incoming_requests/established keyed by SentContactRequestKey/ReceivedContactRequestKey (lines 553/557/565)
  • AssetLockChangeSet::asset_locks: BTreeMap<OutPoint, AssetLockEntry> (line 687)
  • TokenBalanceChangeSet::balances: BTreeMap<(Identifier, Identifier), u64> (line 744)
  • PlatformWalletChangeSet::dashpay_profiles/dashpay_payments_overlay keyed by Identifier (lines 896/900)

If the only intended consumer is a bincode-backed persister this is a latent footgun rather than an immediate bug, but the feature is public on a published crate and the PR description frames serde as the persistence path. A downstream consumer enabling platform-wallet/serde will compile cleanly and only discover the JSON limitation at runtime. Options: (a) reshape these as Vec<(K, V)>, (b) apply #[serde(with = ...)]/serde_with to flatten tuple/struct keys into strings, or (c) explicitly document in the feature flag that JSON is unsupported.

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `Cargo.toml`:
- [SUGGESTION] lines 52-65: Pin rust-dashcore by `rev` instead of mutable `branch`
  All nine `rust-dashcore`-derived workspace dependencies were switched from a fixed `rev = "53130869…"` to `branch = "feat/key-wallet-serde-derives"`. Cargo.lock currently locks the resolved commit (`56a84402c8cb006d65b12e400785a62d67441930`), but any `cargo update`, fresh lockfile generation, or upstream force-push/rebase/branch-deletion will silently re-resolve every dashcore-derived crate to whatever HEAD is at that moment. The blast radius covers the whole workspace, not just the two crates that actually need the new serde derives. Pinning to the current branch tip by `rev = "56a84402c8cb006d65b12e400785a62d67441930"` carries identical bits today, is immune to rebases of dashpay/rust-dashcore#761, and leaves a clean `rev` → `rev` swap when the upstream merges. This matches the hygiene pattern used at every other previous dashcore consumption point in this workspace.

In `packages/rs-platform-wallet/src/changeset/changeset.rs`:
- [SUGGESTION] lines 358-363: Newly-serializable changesets use non-string map keys — incompatible with `serde_json`
  Several types behind the new `serde` feature use `BTreeMap`/`BTreeSet` keys that serde-derives can encode for binary formats (bincode/CBOR/MessagePack) but that `serde_json` rejects at runtime with `key must be a string`:

- `IdentityKeysChangeSet::upserts: BTreeMap<(Identifier, KeyID), _>` (line 360)
- `IdentityKeysChangeSet::removed: BTreeSet<(Identifier, KeyID)>` (line 362)
- `ContactChangeSet::sent_requests`/`incoming_requests`/`established` keyed by `SentContactRequestKey`/`ReceivedContactRequestKey` (lines 553/557/565)
- `AssetLockChangeSet::asset_locks: BTreeMap<OutPoint, AssetLockEntry>` (line 687)
- `TokenBalanceChangeSet::balances: BTreeMap<(Identifier, Identifier), u64>` (line 744)
- `PlatformWalletChangeSet::dashpay_profiles`/`dashpay_payments_overlay` keyed by `Identifier` (lines 896/900)

If the only intended consumer is a bincode-backed persister this is a latent footgun rather than an immediate bug, but the feature is public on a published crate and the PR description frames serde as the persistence path. A downstream consumer enabling `platform-wallet/serde` will compile cleanly and only discover the JSON limitation at runtime. Options: (a) reshape these as `Vec<(K, V)>`, (b) apply `#[serde(with = ...)]`/`serde_with` to flatten tuple/struct keys into strings, or (c) explicitly document in the feature flag that JSON is unsupported.

In `packages/rs-platform-wallet/Cargo.toml`:
- [SUGGESTION] lines 69-76: No round-trip serde tests cover the new serde surface
  The PR adds `Serialize`/`Deserialize` derives on ~16 public types but no encode→decode test exercises them. The existing 121/121 test count cited in the description is pre-existing — `cargo check --features serde` only proves the feature compiles. The derives use default representation (field names as map keys, field order for non-self-describing formats), so any future field rename/reorder or upstream serde-impl change in transitive deps (`TransactionRecord`, `Utxo`, `InstantLock`, `AssetLockFundingType`, `AddressInfo`, `ExtendedPubKey`, `PlatformP2PKHAddress`, `AddressFunds`, `IdentityPublicKey`, `AssetLockProof`) can silently break the wire format with no signal in this crate's test suite. A small set of bincode round-trip tests on `PlatformWalletChangeSet`, `IdentityEntry`, and `AssetLockEntry` would lock down the format and catch regressions before they reach a persister.

Comment thread Cargo.toml
Comment on lines +52 to +65
# Temporary: branch-pinned to dashpay/rust-dashcore#761 (`feat/key-wallet-serde-derives`)
# for serde derives on AssetLockFundingType + DerivedAddress. The branch has been
# rebased onto 53130869 so it carries ONLY the serde additions (no v0.42-dev drift).
# Drop the branch= override and restore rev= once #761 merges to v0.42-dev and a
# subsequent dashcore rev bump flows the new rev in.
dashcore = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-spv = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-network = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
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.

🟡 Suggestion: Pin rust-dashcore by rev instead of mutable branch

All nine rust-dashcore-derived workspace dependencies were switched from a fixed rev = "53130869…" to branch = "feat/key-wallet-serde-derives". Cargo.lock currently locks the resolved commit (56a84402c8cb006d65b12e400785a62d67441930), but any cargo update, fresh lockfile generation, or upstream force-push/rebase/branch-deletion will silently re-resolve every dashcore-derived crate to whatever HEAD is at that moment. The blast radius covers the whole workspace, not just the two crates that actually need the new serde derives. Pinning to the current branch tip by rev = "56a84402c8cb006d65b12e400785a62d67441930" carries identical bits today, is immune to rebases of dashpay/rust-dashcore#761, and leaves a clean revrev swap when the upstream merges. This matches the hygiene pattern used at every other previous dashcore consumption point in this workspace.

💡 Suggested change
Suggested change
# Temporary: branch-pinned to dashpay/rust-dashcore#761 (`feat/key-wallet-serde-derives`)
# for serde derives on AssetLockFundingType + DerivedAddress. The branch has been
# rebased onto 53130869 so it carries ONLY the serde additions (no v0.42-dev drift).
# Drop the branch= override and restore rev= once #761 merges to v0.42-dev and a
# subsequent dashcore rev bump flows the new rev in.
dashcore = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-spv = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-network = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dashcore = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
dash-spv = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
dash-network = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }
dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", rev = "56a84402c8cb006d65b12e400785a62d67441930" }

source: ['claude', 'codex']

🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `Cargo.toml`:
- [SUGGESTION] lines 52-65: Pin rust-dashcore by `rev` instead of mutable `branch`
  All nine `rust-dashcore`-derived workspace dependencies were switched from a fixed `rev = "53130869…"` to `branch = "feat/key-wallet-serde-derives"`. Cargo.lock currently locks the resolved commit (`56a84402c8cb006d65b12e400785a62d67441930`), but any `cargo update`, fresh lockfile generation, or upstream force-push/rebase/branch-deletion will silently re-resolve every dashcore-derived crate to whatever HEAD is at that moment. The blast radius covers the whole workspace, not just the two crates that actually need the new serde derives. Pinning to the current branch tip by `rev = "56a84402c8cb006d65b12e400785a62d67441930"` carries identical bits today, is immune to rebases of dashpay/rust-dashcore#761, and leaves a clean `rev` → `rev` swap when the upstream merges. This matches the hygiene pattern used at every other previous dashcore consumption point in this workspace.

Comment on lines +69 to +76
# Opt-in serde derives on the changeset types. Activates `key-wallet/serde`,
# `key-wallet-manager/serde` (both via dashpay/rust-dashcore#761, branch-pinned in
# workspace Cargo.toml), and `dash-sdk/serde`. `dpp` derives serde unconditionally.
serde = [
"dep:serde",
"key-wallet/serde",
"key-wallet-manager/serde",
"dash-sdk/serde",
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.

🟡 Suggestion: No round-trip serde tests cover the new serde surface

The PR adds Serialize/Deserialize derives on ~16 public types but no encode→decode test exercises them. The existing 121/121 test count cited in the description is pre-existing — cargo check --features serde only proves the feature compiles. The derives use default representation (field names as map keys, field order for non-self-describing formats), so any future field rename/reorder or upstream serde-impl change in transitive deps (TransactionRecord, Utxo, InstantLock, AssetLockFundingType, AddressInfo, ExtendedPubKey, PlatformP2PKHAddress, AddressFunds, IdentityPublicKey, AssetLockProof) can silently break the wire format with no signal in this crate's test suite. A small set of bincode round-trip tests on PlatformWalletChangeSet, IdentityEntry, and AssetLockEntry would lock down the format and catch regressions before they reach a persister.

source: ['claude']

🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `packages/rs-platform-wallet/Cargo.toml`:
- [SUGGESTION] lines 69-76: No round-trip serde tests cover the new serde surface
  The PR adds `Serialize`/`Deserialize` derives on ~16 public types but no encode→decode test exercises them. The existing 121/121 test count cited in the description is pre-existing — `cargo check --features serde` only proves the feature compiles. The derives use default representation (field names as map keys, field order for non-self-describing formats), so any future field rename/reorder or upstream serde-impl change in transitive deps (`TransactionRecord`, `Utxo`, `InstantLock`, `AssetLockFundingType`, `AddressInfo`, `ExtendedPubKey`, `PlatformP2PKHAddress`, `AddressFunds`, `IdentityPublicKey`, `AssetLockProof`) can silently break the wire format with no signal in this crate's test suite. A small set of bincode round-trip tests on `PlatformWalletChangeSet`, `IdentityEntry`, and `AssetLockEntry` would lock down the format and catch regressions before they reach a persister.

Comment on lines 117 to 121
.platform_payment_managed_account_at_index_mut(*account_index)
{
for (p2pkh, funds) in account_state.found() {
account.set_address_credit_balance(
*p2pkh,
funds.balance,
None,
);
account.set_address_credit_balance(*p2pkh, funds.balance, None);
}
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.

💬 Nitpick: Unrelated formatting change bundled into a serde-only PR

The diff collapses the 4-line set_address_credit_balance(*p2pkh, funds.balance, None) call into a single line. The change is cosmetic and unrelated to the serde-feature additions the PR is scoped to — it pollutes git blame for an otherwise serde-focused commit history. Either revert this hunk and land the fmt fix separately, or mention it explicitly in the PR description.

source: ['claude']

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/rs-platform-wallet/src/changeset/changeset.rs`:
- Around line 867-868: CoreChangeSet and PlatformWalletChangeSet currently add
serde derives via #[cfg_attr(feature = "serde", ...)] but they contain upstream
types (TransactionRecord, Utxo, InstantLock, etc.) that do not implement serde
yet, causing build failures when the serde feature is enabled; fix this by
removing or disabling the conditional serde derives until the upstream
feat/key-wallet-serde-derives branch lands — either delete the
#[cfg_attr(feature = "serde", derive(...))] lines on the CoreChangeSet and
PlatformWalletChangeSet structs, or replace them with a new feature gate (e.g.,
#[cfg_attr(feature = "key-wallet-serde", derive(...))]) that you only enable
once the upstream types implement serde, and keep a comment referencing
TransactionRecord, Utxo, and InstantLock so future maintainers know why the
serde derives are withheld.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 17f27c68-f361-4ba4-97a2-cf0618592baa

📥 Commits

Reviewing files that changed from the base of the PR and between 54322f7 and 5fe906e.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • Cargo.toml
  • packages/rs-platform-wallet/Cargo.toml
  • packages/rs-platform-wallet/src/changeset/changeset.rs
  • packages/rs-platform-wallet/src/wallet/asset_lock/tracked.rs
  • packages/rs-platform-wallet/src/wallet/identity/types/block_time.rs
  • packages/rs-platform-wallet/src/wallet/identity/types/dashpay/contact_request.rs
  • packages/rs-platform-wallet/src/wallet/identity/types/dashpay/established_contact.rs
  • packages/rs-platform-wallet/src/wallet/identity/types/dashpay/payment.rs
  • packages/rs-platform-wallet/src/wallet/identity/types/dashpay/profile.rs
  • packages/rs-platform-wallet/src/wallet/identity/types/key_storage.rs
  • packages/rs-platform-wallet/src/wallet/platform_addresses/wallet.rs
  • packages/rs-sdk/src/platform/address_sync/types.rs

Comment on lines 867 to +868
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify that enabling the serde feature allows successful compilation
cargo check --package rs-platform-wallet --features serde

Repository: dashpay/platform

Length of output: 1127


🏁 Script executed:

# Check the workspace structure and Cargo.toml files
git ls-files | grep -E "Cargo.toml$" | head -20

Repository: dashpay/platform

Length of output: 794


🏁 Script executed:

# Explore the directory structure
ls -la packages/rs-platform-wallet/ | head -20

Repository: dashpay/platform

Length of output: 672


🏁 Script executed:

# Check if rs-platform-wallet has Cargo.toml
cat packages/rs-platform-wallet/Cargo.toml | head -50

Repository: dashpay/platform

Length of output: 1304


🏁 Script executed:

# Read the rest of Cargo.toml to check [features] section
tail -n +42 packages/rs-platform-wallet/Cargo.toml

Repository: dashpay/platform

Length of output: 2139


🏁 Script executed:

# Check the changeset.rs file around lines 867-868
sed -n '860,880p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 1156


🏁 Script executed:

# Find where upstream types are defined - search for their definitions
rg -A 3 "struct TransactionRecord" --type rs

Repository: dashpay/platform

Length of output: 87


🏁 Script executed:

# Search for CoreChangeSet definition
rg "struct CoreChangeSet" --type-list | head

Repository: dashpay/platform

Length of output: 450


🏁 Script executed:

# Look at the imports and full context of changeset.rs file
head -n 50 packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 2264


🏁 Script executed:

# Find where TransactionRecord is imported from
rg "TransactionRecord" packages/rs-platform-wallet/src/changeset/changeset.rs -B 2 -A 2

Repository: dashpay/platform

Length of output: 1319


🏁 Script executed:

# Find CoreChangeSet definition
rg "struct CoreChangeSet" --type rust -A 5

Repository: dashpay/platform

Length of output: 682


🏁 Script executed:

# Now try the correct cargo command with the right package name
cd packages/rs-platform-wallet && cargo check --features serde 2>&1 | tail -50

Repository: dashpay/platform

Length of output: 146


🏁 Script executed:

# Get the full CoreChangeSet struct definition
rg "struct CoreChangeSet" --type rust -A 30 | head -50

Repository: dashpay/platform

Length of output: 3375


🏁 Script executed:

# Check what derives CoreChangeSet has
sed -n '650,750p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 4096


🏁 Script executed:

# Search for custom serde implementations for CoreChangeSet
rg "impl.*Serialize.*CoreChangeSet\|impl.*Deserialize.*CoreChangeSet" --type rust

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Search for CoreChangeSet with its struct definition and derives
sed -n '600,700p' packages/rs-platform-wallet/src/changeset/changeset.rs | head -80

Repository: dashpay/platform

Length of output: 3640


🏁 Script executed:

# Look at lines around where CoreChangeSet is likely defined (searching backwards from line 867)
sed -n '500,650p' packages/rs-platform-wallet/src/changeset/changeset.rs | tail -100

Repository: dashpay/platform

Length of output: 4829


🏁 Script executed:

# Search for CoreChangeSet struct definition with derives
rg "pub struct CoreChangeSet" --type rust -B 5 -A 50 | head -80

Repository: dashpay/platform

Length of output: 6069


🏁 Script executed:

# Also check if there are any custom serde implementations
rg "impl.*serde.*CoreChangeSet\|#\[cfg_attr.*serde.*CoreChangeSet" --type rust -B 2 -A 5

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Check around line 400-550 where CoreChangeSet is likely defined
sed -n '400,550p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 7373


🏁 Script executed:

# Check if there are custom serde impls for CoreChangeSet or its types
rg "impl.*Serialize\|impl.*Deserialize" packages/rs-platform-wallet/src/changeset/changeset.rs | head -20

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Search in key_wallet for TransactionRecord serde support
fd -t f "transaction_record" packages/ 2>/dev/null

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Check key-wallet crate for TransactionRecord definition
find packages -name "*key-wallet*" -type d 2>/dev/null | head -5

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Let's check the actual comment around TransactionRecord to understand the constraint better
sed -n '420,445p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 1709


🏁 Script executed:

# Let's search in the workspace dependencies for key-wallet crate
git ls-files | grep -i "key.wallet" | grep -v ".git" | head -20

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Check the workspace Cargo.toml for key-wallet details
cat Cargo.toml | grep -A 10 "key-wallet"

Repository: dashpay/platform

Length of output: 1804


🏁 Script executed:

# Look for any documentation or source about TransactionRecord serde support
rg "TransactionRecord" packages/rs-platform-wallet/ -B 2 -A 2 | grep -i "serde\|serialize" | head -10

Repository: dashpay/platform

Length of output: 300


🏁 Script executed:

# Search for any custom serde implementations in changeset.rs
rg "impl.*Serialize\|impl.*Deserialize" packages/rs-platform-wallet/src/ -A 3 | grep -i "corechangeset\|transactionrecord"

Repository: dashpay/platform

Length of output: 42


🏁 Script executed:

# Check if there's a way serde works despite TransactionRecord not having it - look for feature gates
rg "#\[cfg" packages/rs-platform-wallet/src/changeset/changeset.rs | head -20

Repository: dashpay/platform

Length of output: 1536


🏁 Script executed:

# Look at the exact line with the problematic comment about TransactionRecord
sed -n '415,435p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 1358


🏁 Script executed:

# Let's check what's on the feat/key-wallet-serde-derives branch for TransactionRecord
# First, try to understand if TransactionRecord actually has serde now
rg "pub struct TransactionRecord" --type rust -A 10 | head -20

Repository: dashpay/platform

Length of output: 1055


🏁 Script executed:

# Check the comment in Cargo.toml more carefully about which types get serde
sed -n '1,20p' Cargo.toml

Repository: dashpay/platform

Length of output: 658


🏁 Script executed:

# Let's look at the full context of the comment about TransactionRecord in changeset.rs
sed -n '405,425p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 1265


🏁 Script executed:

# Check what the current cargo.lock or Cargo.toml says about the branch status
cat Cargo.lock | grep -A 5 "name = \"key-wallet\"" | head -20

Repository: dashpay/platform

Length of output: 276


🏁 Script executed:

# Let's look at the exact line numbers mentioned in the review (867-868)
sed -n '865,870p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 413


🏁 Script executed:

# Look at the broader context - is this CoreChangeSet or PlatformWalletChangeSet?
sed -n '860,875p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 854


🏁 Script executed:

# Check the comment about TransactionRecord more fully
sed -n '408,425p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 1060


🏁 Script executed:

# Check the comment about what the serde feature enables
sed -n '42,52p' packages/rs-platform-wallet/Cargo.toml

Repository: dashpay/platform

Length of output: 459


🏁 Script executed:

# Look at CoreChangeSet definition with its derives
sed -n '405,475p' packages/rs-platform-wallet/src/changeset/changeset.rs

Repository: dashpay/platform

Length of output: 3701


🏁 Script executed:

# Search for where CoreChangeSet is defined with its derives
rg "pub struct CoreChangeSet" --type rust -B 10 | head -25

Repository: dashpay/platform

Length of output: 1264


Upstream types lack serde support for changeset serialization.

CoreChangeSet and PlatformWalletChangeSet use conditional serde derives (#[cfg_attr(feature = "serde", ...)]), but they contain TransactionRecord and other upstream types from key-wallet that are currently "Debug + Clone only" per the code's own comment. The serde feature cannot work until TransactionRecord, Utxo, InstantLock, and other imported types derive serde on the upstream feat/key-wallet-serde-derives branch. This will cause compilation failures when the serde feature is enabled until upstream types are fully updated.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rs-platform-wallet/src/changeset/changeset.rs` around lines 867 -
868, CoreChangeSet and PlatformWalletChangeSet currently add serde derives via
#[cfg_attr(feature = "serde", ...)] but they contain upstream types
(TransactionRecord, Utxo, InstantLock, etc.) that do not implement serde yet,
causing build failures when the serde feature is enabled; fix this by removing
or disabling the conditional serde derives until the upstream
feat/key-wallet-serde-derives branch lands — either delete the
#[cfg_attr(feature = "serde", derive(...))] lines on the CoreChangeSet and
PlatformWalletChangeSet structs, or replace them with a new feature gate (e.g.,
#[cfg_attr(feature = "key-wallet-serde", derive(...))]) that you only enable
once the upstream types implement serde, and keep a comment referencing
TransactionRecord, Utxo, and InstantLock so future maintainers know why the
serde derives are withheld.

Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

The serde derives added in this PR are mechanically consistent with the types they touch, and I did not confirm any consensus, runtime, or persistence-path regression in the wallet code itself. Three of the reported issues depend on assumptions the source does not make: the new feature is documented as serde support for changeset types, not for the separately documented startup snapshot path, and it does not promise JSON-specific encoding or backward-compatible on-disk schema evolution. The remaining review-worthy issue is the workspace-wide move from fixed git revisions to a floating branch, which introduces avoidable build drift on the next lockfile refresh.

Reviewed commit: 5fe906e

🟡 1 suggestion(s)

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `Cargo.toml`:
- [SUGGESTION] lines 57-65: Floating branch pins weaken workspace reproducibility
  This PR replaces nine `rust-dashcore` workspace dependencies that were pinned to commit `53130869e5b9343ae59016323e5e5269e717a8fd` with `branch = "feat/key-wallet-serde-derives"`. The comment above these lines explains the intent, but the manifest still stops identifying the exact upstream source being reviewed. `Cargo.lock` keeps this checkout stable today, yet any future `cargo update` or lockfile regeneration can silently pull a different branch head into consensus-sensitive crates. Keeping the temporary serde workaround on a fixed `rev` preserves the same functionality without introducing that drift.

Comment thread Cargo.toml
Comment on lines +57 to +65
dashcore = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-network-seeds = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-spv = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-spv-ffi = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet-ffi = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
key-wallet-manager = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dash-network = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
dashcore-rpc = { git = "https://github.com/dashpay/rust-dashcore", branch = "feat/key-wallet-serde-derives" }
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.

🟡 Suggestion: Floating branch pins weaken workspace reproducibility

This PR replaces nine rust-dashcore workspace dependencies that were pinned to commit 53130869e5b9343ae59016323e5e5269e717a8fd with branch = "feat/key-wallet-serde-derives". The comment above these lines explains the intent, but the manifest still stops identifying the exact upstream source being reviewed. Cargo.lock keeps this checkout stable today, yet any future cargo update or lockfile regeneration can silently pull a different branch head into consensus-sensitive crates. Keeping the temporary serde workaround on a fixed rev preserves the same functionality without introducing that drift.

source: ['codex']

🤖 Fix this with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `Cargo.toml`:
- [SUGGESTION] lines 57-65: Floating branch pins weaken workspace reproducibility
  This PR replaces nine `rust-dashcore` workspace dependencies that were pinned to commit `53130869e5b9343ae59016323e5e5269e717a8fd` with `branch = "feat/key-wallet-serde-derives"`. The comment above these lines explains the intent, but the manifest still stops identifying the exact upstream source being reviewed. `Cargo.lock` keeps this checkout stable today, yet any future `cargo update` or lockfile regeneration can silently pull a different branch head into consensus-sensitive crates. Keeping the temporary serde workaround on a fixed `rev` preserves the same functionality without introducing that drift.

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