fix(platform-wallet): derive the shield fee reserve from the versioned fee - #4366
Conversation
…d fee The fixed 1e9-credit input-0 reserve was ~6x the actual charged fee (metered storage/processing + compute, ~1.65e8 at current constants), and the preflight promoted that slop into authoritative capacity numbers: accounts fragmented into sub-1e9 addresses reported can_shield=false regardless of aggregate balance, Max understated real capacity by ~8.3e8 credits, and a Max shield left its residue below the viability threshold, permanently unshieldable. Replace the constant with shield_fee_reserve_credits(platform_version) = 2 x compute_minimum_shielded_fee(SHIELD_NUM_ACTIONS), threaded through plan_shield_inputs like the other versioned planner limits. The reserve only has to cover the execution-side metered fee taken from input 0's post-reallocation residue (the structure gate is satisfied by the claimed fee reserve_shield_fee_on_input_0 loads, which is already versioned-exact), so one extra fee of metering headroom suffices, and the value now tracks fee-constant bumps instead of freezing. The headroom test now also bounds the reserve from above (<= 4x fee) so an oversized reserve can't silently reintroduce the capacity loss. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
|
🕓 Ready for review — next in queue (commit 0ba8231) |
1e691aa
into
codex/fix-platform-to-shielded-max
Issue being fixed or feature implemented
Targets #4360's branch. The preflight/planner introduced there computes
can_shield,max_shieldable_credits, and the input-0 viability threshold from the fixedSHIELDED_SHIELD_FEE_RESERVE_CREDITS = 1_000_000_000reserve. That value is ~6× the fee the network actually charges a Type 15 shield (metered note/nullifier storage/processing +compute_shielded_verification_fee(2)≈ 1.65e8 credits at current constants), which turns internal slop into wrong host-visible capacity:can_shield == falsewith zero capacity, regardless of aggregate balance. Platform payment accounts accumulate many small per-payment addresses, so this shape is the norm, and the loss is unbounded.reserve − actual fee≈ 8.3e8 credits — below the 1e9 viability threshold — so every account that shields Max converges to a permanently unshieldable transparent residue.The reserve's only real job is covering the execution-side fee that drive deducts from input 0's post-reallocation residue (
DeductFromInput(0)). The structure gate (Σ claims ≥ amount + fee) is satisfied by the claimed feereserve_shield_fee_on_input_0loads, which is already versioned-exact — an oversized unclaimed reserve contributes nothing there.What was done?
shield_fee_reserve_credits(platform_version)=2 × compute_minimum_shielded_fee(SHIELD_NUM_ACTIONS)inoperations.rs, next to the action-count constant it depends on. The 2× keeps one full fee of headroom for the GroveDB metering the client cannot reproduce, and the value now tracks fee-constant bumps instead of freezing (at current constants: 325,702,400 credits, ~0.0033 DASH).plan_shield_inputsas a parameter, like the versionedmin_input_amount/max_address_inputsthe planner already takes fromsdk.version().ShieldedShieldPreflight.fee_reserve_creditsand the FFI struct field now carry the versioned value; no FFI/Swift/Kotlin shape changes.LATEST_PLATFORM_VERSION, keeping every scenario parametric; the real-account regression test now guards its own shape (leading address must stay below the reserve).≤ 4× fee) so an oversized reserve can't silently reintroduce the capacity loss, and refreshed the stale~1.2e8fee comment (pre-bump value; it's ~1.63e8 at current constants).How Has This Been Tested?
cargo test -p platform-wallet --features shielded --lib— 775 passed, including the 12 planner tests, 4 reserve tests, and the fetch-error mapping test.cargo clippy -p platform-wallet -p platform-wallet-ffi --all-targets --all-featuresand no-featurecargo checkfor both crates — clean.cargo fmt --all.Breaking Changes
None on-wire. The
SHIELDED_SHIELD_FEE_RESERVE_CREDITSexport (added on this branch, unreleased) is replaced by theshield_fee_reserve_creditsfunction; hosts should keep readingfee_reserve_creditsfrom the preflight, which is unchanged in shape.Checklist:
🤖 Generated with Claude Code