fix(platform): encrypt shielded outputs to the sender's outgoing viewing key#3839
Conversation
…ing key All shielded builders passed ovk: None to the Orchard builder, so every real output's out_ciphertext was keyed to random bytes. The wallet's try_recover_outgoing_note OVK scan could never open its own sends, and the outgoing-payments store never populated. Output-only builders (shield, shield-from-asset-lock) now take an explicit sender OVK; spend-side builders (transfer, unshield, withdrawal, identity-create) derive it from the full viewing key they already receive, covering recipient and change outputs. Dummy/padding outputs keep random keys. out_ciphertext is opaque to consensus, so this is a client-side fix only. platform-wallet passes the account OVK at shield call sites and adds a sender-side round-trip test: build a Shield transition, recover the recipient note via the scanner's OVK path, persist it as an outgoing payment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughExtend shielded transaction builders to support optional outgoing viewing key (OVK) encryption so senders can recover their complete send history from chain data. Thread ChangesOutgoing Viewing Key (OVK) Support for Shielded Output Recovery
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
…nath-458203 # Conflicts: # packages/rs-platform-wallet/src/wallet/shielded/sync.rs
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Reviewed |
|
✅ 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: "4f86b7c8c83bdad78e5a532b9d16b25b3f2ba0581bc6aae8d62a314267f7d9b6"
)Xcode manual integration:
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## v3.1-dev #3839 +/- ##
==========================================
Coverage 87.04% 87.05%
==========================================
Files 2677 2679 +2
Lines 329918 330173 +255
==========================================
+ Hits 287182 287427 +245
- Misses 42736 42746 +10
🚀 New features to boost your workflow:
|
Issue being fixed or feature implemented
Every shielded builder passed
ovk: Noneto the Orchard bundle builder, so each real output'sout_ciphertextwas encrypted to a per-output random cipher key. As a result,try_recover_outgoing_note— the wallet scanner's outgoing-payment recovery path — could never decrypt the wallet's own sends, and the outgoing-payments store (surfaced in the app as sent-payment history with memos) never populated, even though the sync path insync.rsalready tried every account's OVK and persisted hits.What was done?
rs-dpp builders (client-side only —
out_ciphertextis opaque to consensus validation, so no protocol impact):build_output_only_bundletakes a newsender_ovk: Option<OutgoingViewingKey>parameter, exposed as a new parameter onbuild_shield_transitionand bothbuild_shield_from_asset_lock_transitionvariants (these signatures carry no FVK to derive it from).build_spend_bundle— used by unshield, withdrawal, identity-create — and the inline transfer builder) derivefvk.to_ovk(Scope::External)internally, so transfer recipient outputs and change outputs are recoverable with no public-API change on the spend side.rs-platform-wallet wiring:
operations::shieldpasses the account'soutgoing_viewing_key.shielded_fund_from_asset_lockresolves the OVK from the bound account whose IVK recognizes the recipient address (falling back to the lowest bound account), on both the normal and the InstantLock→ChainLock retry broadcast paths.How Has This Been Tested?
output_built_with_sender_ovk_recovers_under_that_ovk_only: exactly one action recovers (note, recipient, memo) under the sender's OVK viatry_output_recovery_with_ovk, and a foreign OVK opens nothing.ovk_builder_roundtrip_tests::shield_built_note_ovk_recovers_and_persists_as_outgoingin rs-platform-wallet — the sender-side mirror ofshield_decrypt_tests: builds a real Shield transition with the wallet's OVK, reassembles each action into the scanner's wire form, assertstry_recover_outgoing_noterecovers exactly the recipient output with matching recipient/value/memo (this returnedNonebefore the fix), and persists it end-to-end viarecord_outgoing_note.cargo test -p dpp --all-features shielded→ 172 passed.cargo test -p platform-wallet --features shielded --release→ all green (lib: 218 passed).cargo fmt --allclean. drive-abci shielded-transfer tests use unchanged signatures and assert only ciphertext sizes, so they are unaffected.Breaking Changes
None at the protocol level.
build_shield_transitionandbuild_shield_from_asset_lock_transition(_with_signer)gained asender_ovkparameter (pre-release client API; all in-repo call sites updated).Checklist:
For repository code-owners and collaborators only
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Tests
Documentation