Skip to content

fix(platform): resolve fee versions by registered number and price refunds at the storage epoch rate - #4703

Closed
DCG-Claude wants to merge 12 commits into
v5.1-devfrom
dashvm/r12-01
Closed

DCG-Claude wants to merge 12 commits into
v5.1-devfrom
dashvm/r12-01

Conversation

@DCG-Claude

@DCG-Claude DCG-Claude commented Sep 12, 2026 •

Copy link
Copy Markdown
Collaborator

Issue being fixed or feature implemented

Part of the smart-contract plan in #4626 (task R12-01, fees workstream). The fee version registry and its consumers had four gaps that the plan's fee-version integrity work requires closed before new fee schedules can be introduced:

  • FeeVersion::get and FeeVersion::get_optional resolved a fee_version_number by array position (FEE_VERSIONS[n - 1]), not by the number the entry carries. That only works while the registry happens to be numbered contiguously, and nothing enforced it.
  • FeeVersion::as_static called expect on the lookup, and the saved-state loader (PlatformStateForSavingV1 into PlatformState) did the same, so a persisted state holding a fee version number this build does not know aborted the node at start instead of failing with a descriptive error.
  • FeeRefunds::from_storage_removal prices every removed byte at the storage rate active at the removal epoch. A refund is the unpaid remainder of the fee originally charged, and that fee was priced at the rate active when the bytes were written, so the rate must be resolved at the storage epoch through the fee history. The corrected rule is a new generation behind the calculate_fee method version, not an edit to the shipped one.
  • None of this had tests: the registry module, the epoch fee-history resolution and the refund path in Drive had no coverage, and the two saved-state fixture tests only asserted that decoding succeeds.

Refs #4675

What was done?

packages/rs-platform-version/src/version/fee/mod.rs

  • FeeVersion::get and get_optional resolve by matching fee_version_number in FEE_VERSIONS; zero and any unregistered number are PlatformVersionError::UnknownVersionError (same message text as before).
  • FeeVersion::as_static now returns Result<&'static FeeVersion, PlatformVersionError>.
  • Two compile-time assertions: the registry is non-empty (so first() and latest() cannot panic) and the entries are numbered 1, 2, ... in order (registry_numbers_are_contiguous_from_one, a const fn). A mis-numbered or duplicated entry no longer compiles.
  • Doc comment on FEE_VERSIONS defining a fee-history generation and when a schedule needs a new number.
  • Lookup by carried number is factored into find_registered, and with the mock-versions feature get_optional consults FEE_TEST_VERSIONS after the shipped registry.
  • Nine tests: every registered number resolves to the entry carrying it, find_registered against a registry whose numbers do not line up with positions (number 3 at position 0, number 1 at position 1), the mock generation resolves through get, get_optional and as_static although no registry position corresponds to its number, zero and unregistered numbers are rejected on every entry point, the numbering guard, every schedule referenced by PLATFORM_VERSIONS (and TEST_PLATFORM_V2 / TEST_PLATFORM_V3 under mock-versions) is registered and agrees with the registered generation on the storage, processing, hashing and signature groups, the number 1 storage rates are frozen with a replay rationale, and as_static on both sides.

packages/rs-platform-version/src/version/mocks/fee_test.rs (new, mock-versions feature only)

  • TEST_FEE_VERSION_DOUBLED_STORAGE_RATE: a fee-history generation with twice the shipped disk usage rate, numbered (1 << TEST_PROTOCOL_VERSION_SHIFT_BYTES) + 1 so it can never collide with a number a released network persisted and is never a position in the shipped registry. A compile-time assertion keeps every mock number above the shift. mock-versions is a dev-dependency feature of drive, drive-abci and strategy-tests; release builds never enable it.

packages/rs-dpp/src/fee/fee_result/refunds.rs

  • FeeRefunds::from_storage_removal (generation 0) is byte-identical to the shipped body; its doc comment now states it is frozen and selected by calculate_fee version 0.
  • New FeeRefunds::from_storage_removal_v1: the same function with the storage rate resolved with Epoch::new(epoch_index) (the storage epoch, the key of each removal entry) instead of Epoch::new(current_epoch_index). The current epoch is still validated on its own line (Epoch::new(current_epoch_index)?), because the shipped generation only checked it as a side effect of pricing at it and the distribution helper adds one to it; an index above MAX_EPOCH is an overflow error, not a panic. The dust filter, era arithmetic and error mapping are unchanged. Doc comment explains the rule and which method version selects it.
  • Tests with a synthetic number 2 generation (54000 credits per byte, not registered anywhere): the shipped generation keeps pricing both sides of a boundary at the current epoch's rate (frozen replay pin); generation 1 prices removals on both sides of a rate boundary at the rate their bytes were charged and uses the first generation before the earliest history entry; on every input reachable today (empty history, or a history where every entry is number 1) both generations produce identical refunds; the dust filter holds in both; a current epoch above MAX_EPOCH is an overflow error in both (removing the explicit check makes generation 1 panic in the distribution helper).

packages/rs-dpp/src/fee/default_costs/mod.rs (tests only)

  • Five tests for EpochCosts::active_fee_version: empty history resolves to the first registered generation (the genesis-epoch fallback the epoch-change hook relies on), exact epoch match, nearest lower entry, before the earliest entry, and a consumer-level check that for every PlatformVersion and every KnownCostItem variant the referenced schedule and the registered generation return the same cost.

packages/rs-drive/src/fees/calculate_fee/v1/mod.rs (new), calculate_fee/mod.rs and packages/rs-drive/src/fees/op.rs

  • Drive::calculate_fee_v1: a copy of calculate_fee_v0 that calls LowLevelDriveOperation::consume_to_fees_v1. The dispatcher gains the 1 => arm and known_versions: vec![0, 1]. calculate_fee_v0 and consume_to_fees_v0 are byte-identical to the base branch.
  • LowLevelDriveOperation::consume_to_fees_v1: a copy of consume_to_fees_v0 whose two refund arms call from_storage_removal_v1. Everything else is identical, including both CalculatedEphemeralCostOperation arms the base carries: EphemeralPricing::TimeRangeTtl bills added bytes to processing at the ephemeral rate, never to storage, and rejects a sectioned removal; EphemeralPricing::DocumentTtl pays added bytes as a lifetime storage fee over the document's remaining epochs (FeeResult::lifetime_storage_fees). The fee version number 1 arm still prices against an empty history, so both generations agree on every shipped schedule.
  • No DRIVE_VERSION_V* table selects calculate_fee: 1 yet. Every PLATFORM_V* keeps calculate_fee: 0, and the mock versions too. The unreleased protocol version that registers a schedule under a new fee version number sets calculate_fee: 1 in its drive table; that is the explicit version boundary.
  • Tests in op.rs run both generations: number 1 refunds through the legacy empty-history path with None history and ignores a supplied history (both generations); any other number requires the history (DriveError::CorruptedCodeExecution, both generations); with a boundary history, generation 0 prices every epoch at the current epoch's rate and generation 1 at the storage-epoch rate; system bytes land in removed_bytes_from_system; a timeRange TTL batch bills its bytes to processing at the ephemeral rate with zero storage fee and no refunds in both generations, a sectioned removal on such a batch is rejected in both, and a document TTL batch produces the same lifetime storage fees in both.
  • Tests in calculate_fee/mod.rs go through the public dispatcher with a TEST_PLATFORM_V2 clone carrying the mock generation and an explicit calculate_fee slot: generation 0 and generation 1 produce their respective pricing across a boundary, both agree when every history entry is number 1, both reject a missing history, both bill ephemeral bytes to processing (identical fee results) and reject a sectioned ephemeral removal, and slot 2 is UnknownVersionMismatch. Removing the ephemeral arm from generation 1 fails all four ephemeral tests.

packages/rs-drive-abci/src/platform_types/platform_state/platform_state_for_saving/v1/mod.rs and platform_state/mod.rs

  • From<PlatformStateForSavingV1> for PlatformState became TryFrom with Error. An unknown stored number produces ExecutionError::CorruptedCachedState("platform state stores fee version {n} for epoch {e}, which this build does not know"). The struct, its derive stack and its bincode encoding are unchanged. The V1 arm of TryFromPlatformVersioned<PlatformStateForSaving> calls try_from. The V0 arm (legacy pre-1.4 format, every entry mapped to the first generation) is unchanged. fetch_platform_state_v0, the checkpoint loader and the verify subcommand all go through this path.
  • Tests: the two existing fixture tests are kept, and new ones assert that both the V0 testnet fixture and the V1 devnet fixture resolve every entry to number 1, that every registered number round-trips through serialize_to_bytes and versioned_deserialize, that the mock generation's number (not a registry position) is what gets stored and comes back resolved to the mock entry with storage priced identically before and after reload, that the structure 1 record round-trips every registered number plus the mock generation under epoch 10 and restores it by carried number, that a map built the way the epoch-change hook builds it (a reference into PLATFORM_VERSIONS) and the reloaded map agree on every KnownCostItem for epochs 0 to 3, and that a V1 state carrying number 99 for epoch 3 fails to load with an error naming both.

packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs

  • The single as_static() call site uses the fallible signature.

book/src/fees/overview.md

  • Refunds section: the rate is resolved at the storage epoch through the fee history; the current epoch only fixes how many era shares were already paid. Fee Versioning section: what fee_version_number names, lookup by number, unknown numbers are load errors, why FEE_VERSION1 through FEE_VERSION4 share number 1, and why the empty-history fallback is deliberate.

Not changed: every FEE_VERSION* and fee-group constant, every PLATFORM_V* and mock version, consume_to_fees_v0, EpochCosts::active_fee_version, upgrade_protocol_version_on_epoch_change_v0, both PlatformStateForSaving layouts, the V0 legacy mapping, SystemLimits, proto and SDK surfaces.

How Has This Been Tested?

Local gate, each command's output captured to a log file and its exit code checked (macOS, Rust 1.92):

cargo fmt --all -- --check
cargo clippy -p platform-version -p dpp -p drive -p drive-abci --all-features --all-targets -- -D warnings
cargo clippy -p platform-version --all-targets -- -D warnings
cargo check --workspace --all-targets
cargo test -p platform-version --all-features fee::
cargo test -p platform-version fee::
cargo test -p dpp --lib fee::
cargo test -p drive --lib fees::
cargo test -p drive --lib fees::calculate_fee
cargo test -p drive-abci --lib platform_types::platform_state
cargo test -p drive-abci --lib test_document_refund
cargo test -p drive-abci --lib protocol_upgrade::upgrade_protocol_version

Compile-time guard verified negatively: registering FEE_VERSION1 twice fails cargo check -p platform-version with "fee version numbers must be registered in order, starting at 1 and without gaps".

No verify-only cut needed (no src/verify/** change). Full drive-abci suite and strategy tests are left to CI.

Breaking Changes

None on any shipped protocol version, so no !.

The refund rule correction (rate at the storage epoch instead of the removal epoch) lives in a new generation: FeeRefunds::from_storage_removal_v1, consume_to_fees_v1 and Drive::calculate_fee_v1, selected only by calculate_fee: 1, which no DRIVE_VERSION_V* table sets. Generation 0 is byte-identical to the base branch. Every released protocol version therefore runs exactly the code it shipped with. The tests also show the two generations agree on every input reachable today (every registered schedule shares one storage table), so switching the slot to 1 in the unreleased protocol version alongside a new fee version number is where the correction first becomes observable.

In-workspace Rust API: FeeVersion::as_static is now fallible and PlatformStateForSavingV1 converts to PlatformState through TryFrom. Each had one in-tree caller, both updated. No client crate uses either. Migration for out-of-tree callers: fee_version.as_static()? (or .expect(...) in test code) instead of fee_version.as_static(), and PlatformState::try_from(saving_v1)? instead of PlatformState::from(saving_v1). Per the conventions chapter, ! is reserved for changes that would fork the network if rolled out unevenly; Rust source-compatibility churn is ordinary work described here.

Decisions taken (provisional values)

  • FEE_VERSION2 through FEE_VERSION4 keep fee_version_number: 1 and are not registered separately. fee_version_number names a fee-history generation: the set of values KnownCostItem can read (storage, processing, hashing, signature). The schedules differ only in groups the history never serves (data_contract_registration, vote_resolution_fund_fees, document_ttl), so all resolve to the same generation. Renumbering would flip protocol versions 9 to 15 onto the map-driven refund branch of consume_to_fees_v0 for historical blocks, and several block-lifecycle callers (withdrawal cleanup, epoch change, masternode identity updates at init chain) pass None history to Drive and would hit CorruptedCodeExecution. That caller audit belongs to the next task in this workstream; it is recorded here so the reviewer sees it was considered.
  • Unknown stored number is an internal load error, not a consensus error. It means the binary is older than the state it is loading. The error class is ExecutionError::CorruptedCachedState, surfaced through ProtocolError::Generic by versioned_deserialize, which is the existing path for load failures.
  • The registry numbering guard is a compile-time assertion rather than a runtime check, so the constraint cannot be violated in a running node and the expect in first() and latest() has a proof.
  • A mock fee generation lives under mock-versions, not in the shipped registry. The review asked for a lookup that cannot be satisfied by array position. Adding a real second generation would be a consensus change (it needs a protocol version and the caller audit). The mock generation follows the existing test protocol version pattern: its number sits above TEST_PROTOCOL_VERSION_SHIFT_BYTES, it is consulted after the shipped registry, and release builds never compile it.
  • The refund correction is a new calculate_fee generation, not an in-place edit. The first revision changed from_storage_removal in place on the argument that the change is unobservable on shipped versions; review pointed out the conventions freeze shipped generations regardless, so generation 0 is restored byte-identical and the corrected rule is calculate_fee_v1 / consume_to_fees_v1 / from_storage_removal_v1. No version table selects it in this PR: the slot flips to 1 in the unreleased protocol version that also introduces a new fee version number, so both changes share one boundary. The registry change is a lookup repair with identical results for every currently registered input, and the saved-state change only turns an abort into an error; neither alters versioned behaviour.
  • calculate_fee: 1 is not switched on in any drive table here. The latest table, DRIVE_VERSION_V9, is selected by protocol version 14, which is released; flipping its slot would change refund pricing on a shipped protocol version, which is what the frozen-generation rule forbids. The base has no unreleased protocol version yet. The flip belongs to the protocol version that registers a schedule under a new fee version number, so the algorithm boundary and the rate boundary land together; until then the dispatcher tests drive generation 1 through a mock platform version with the slot forced to 1, and the generation tests prove both generations agree on every input reachable today.
  • Provisional numbers: none. This task introduces no new fee rates, limits or constants. The synthetic number 2 generation with 54000 credits per byte exists only inside test modules.

Findings recorded for follow-up tasks in the workstream (no code change here):

  • The block-lifecycle callers that pass None fee history to Drive are safe while every registered number is 1; the tests in op.rs pin that a later number requires the history on those paths.
  • An end-to-end replay-versus-saved-state comparison across a live rate boundary at the ABCI level can now use TEST_FEE_VERSION_DOUBLED_STORAGE_RATE on a mock protocol version through replace_test_versions; this PR covers the boundary at the Drive dispatcher and the saved-state layers. test_document_refund_after_10_epochs_on_different_fee_version_increasing_fees cannot observe a boundary today because its "higher fees" version is a clone of the latest schedule (number 1).

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
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Dash-Tasks: R12-01


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Fee schedules can select a refund-pricing method that uses the storage rate in effect when bytes were written. Current released protocol versions continue to use the existing pricing method.
    • Fee versions are identified by their registered numbers, allowing schedules with different storage rates to use distinct versions.
  • Bug Fixes

    • Platform state loading now reports an error for an unrecognized fee version instead of panicking.

PR Hygiene · d0188d1

  • Bots — thepastaclaw ✓
  • Self-review — not asked of a bot author
  • Build green
  • Approvals
    • files with no dedicated owner (book/src/fees/overview.md, packages/rs-platform-version/src/version/fee/mod.rs, packages/rs-platform-version/src/version/mocks/fee_test.rs and 1 more) — QuantumExplorer or shumkov
    • dpp (packages/rs-dpp/src/fee/default_costs/mod.rs, packages/rs-dpp/src/fee/fee_result/refunds.rs) — QuantumExplorer or shumkov
    • rs-drive-abci (packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs, packages/rs-drive-abci/src/platform_types/platform_state/mod.rs, packages/rs-drive-abci/src/platform_types/platform_state/platform_state_for_saving/v1/mod.rs and 1 more) — QuantumExplorer or shumkov
    • rs-drive (packages/rs-drive/src/fees/calculate_fee/mod.rs, packages/rs-drive/src/fees/calculate_fee/v1/mod.rs, packages/rs-drive/src/fees/op.rs) — QuantumExplorer or shumkov

When every merge requirement is met, the PR Hygiene check passes. Reviewer limits do not block merging; other required GitHub checks and protections still apply.

@github-actions github-actions Bot added this to the v4.2.0 milestone Sep 12, 2026
@github-actions

github-actions Bot commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

📖 Book Preview built successfully.

Download the preview from the workflow artifacts.
To view locally: download the artifact, unzip, and open index.html.

Updated at 2026-11-03T16:04:11.438Z

@coderabbitai

coderabbitai Bot commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

The change adds generation 1 fee calculation, resolves fee versions by carried number, prices generation 1 refunds at storage epochs, and makes saved-state restoration return errors for unknown fee versions. Tests cover lookup, dispatch, history boundaries, and saved-state round trips.

Changes: Fee generation and refund handling

Layer / File(s) Summary
Fee registry and history resolution
packages/rs-platform-version/src/version/fee/mod.rs, packages/rs-platform-version/src/version/mocks/*, packages/rs-dpp/src/fee/default_costs/mod.rs, packages/rs-drive-abci/src/execution/platform_events/block_processing_end_events/tests.rs
Fee versions resolve by fee_version_number instead of registry position. Registry numbering must start at 1 and remain contiguous. Tests cover history lookup behavior, mock generations, and platform-version schedules.
Storage-epoch refund pricing
packages/rs-dpp/src/fee/fee_result/refunds.rs, packages/rs-drive/src/fees/calculate_fee/*, packages/rs-drive/src/fees/op.rs, book/src/fees/overview.md
Generation 1 prices refunds at the storage-epoch rate. Generation 0 retains current-epoch pricing. Tests cover rate boundaries, missing history, ephemeral operations, and fee-version dispatch.
Saved-state fee version restoration
packages/rs-drive-abci/src/platform_types/platform_state/*
Saved states resolve stored fee version numbers through the registry. Unknown numbers return corrupted-state errors. Tests cover legacy states and round trips.

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant Drive
  participant LowLevelDriveOperation
  participant FeeRefunds
  participant FeeHistory
  Drive->>LowLevelDriveOperation: calculate generation 1 fee
  LowLevelDriveOperation->>FeeRefunds: process storage removal
  FeeRefunds->>FeeHistory: resolve rate at storage epoch
  FeeHistory-->>FeeRefunds: return fee version
  FeeRefunds-->>Drive: return refund result
Loading
Merge Risk: Minimal · up to e0b90

No actionable merge-blocking issue is evident; the change appears ready for normal merge checks.

Security architecture risk: Low · up to e0b90

The change prepares a new refund calculation while preserving the current calculation for released protocol versions. No new security exposure was established, but activation with a future fee schedule needs validation against saved fee history and recovery behavior.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The relevant exposure is fee and refund accounting for identities whose stored bytes are removed. The examined caller path does not make the new rule independently selectable by removal contents; its effective reach is limited by protocol-version dispatch.

Trust Boundaries and Controls

  • observed — At the storage-removal-to-fee boundary, the new method filters small entries, converts and validates removal epochs, checks price multiplication, and propagates refund-calculation errors. The operation consumer also rejects the sectioned-removal form for ephemeral costs.

Resilience and Maintainability Implications

  • inferred — Correct accounting after a future rate change depends on retaining the applicable historical fee entries through persistence and recovery. The examined evidence establishes lookup and restoration behavior, but not producer-side replay guarantees or recovery across that rollout boundary.

Hardening Proposals

  • proposed — Before a protocol version activates generation 1 with a differing storage rate, validate write-to-removal accounting and restart or rollback across the rate boundary, including missing historical entries and repeated removals.
Pre-merge checks: Passed 4
Check name Status Explanation
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.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly summarizes the main changes: fee-version lookup by registered number and storage-epoch pricing for refunds. It is concise and specific.
Finishing Touches
Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Tip

🎯 Customize your risk assessments

Guide how CodeRabbit assesses merge risk and security architecture risk. Highlight sensitive changes and explain your security boundaries using Merge Risk Instructions and Security Risk Instructions in your review settings. Security architecture risk assessments require the Advanced plan or above.

✅ Automatic approvals, with your rules

Let CodeRabbit approve pull requests once required threads are resolved, pre-merge checks pass, and your risk limits are met. Enable Automatic approvals in review settings, with overrides for teams or file paths.

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

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: dashpay/platform/.coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: fbb6405f-9e05-4c6f-a421-ce97f242e7b9

📥 Commits

Reviewing files that changed from the base of the PR and between dfa3b63 and e0b9044.

📒 Files selected for processing (2)
  • packages/rs-dpp/src/fee/fee_result/refunds.rs
  • packages/rs-drive-abci/src/platform_types/platform_state/mod.rs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@DCG-Claude
DCG-Claude changed the base branch from v4.2-dev to v4.3-dev September 12, 2026 02:12
@codecov

codecov Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.18652% with 40 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.12%. Comparing base (d020728) to head (078c446).
⚠️ Report is 67 commits behind head on v4.3-dev.

Files with missing lines Patch % Lines
packages/rs-drive/src/fees/op.rs 91.42% 15 Missing ⚠️
packages/rs-drive/src/fees/calculate_fee/v1/mod.rs 75.86% 7 Missing ⚠️
...rive-abci/src/platform_types/platform_state/mod.rs 95.77% 6 Missing ⚠️
packages/rs-drive/src/fees/calculate_fee/mod.rs 97.59% 5 Missing ⚠️
packages/rs-dpp/src/fee/fee_result/refunds.rs 97.88% 4 Missing ⚠️
packages/rs-dpp/src/fee/default_costs/mod.rs 95.89% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           v4.3-dev    #4703      +/-   ##
============================================
+ Coverage     84.10%   84.12%   +0.02%     
============================================
  Files          2797     2798       +1     
  Lines        379933   380743     +810     
============================================
+ Hits         319541   320301     +760     
- Misses        60392    60442      +50     
Components Coverage Δ
dpp 84.77% <97.32%> (+0.04%) ⬆️
drive 81.96% <93.44%> (+0.01%) ⬆️
drive-abci 88.13% <96.17%> (+<0.01%) ⬆️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.92% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 43.67% <ø> (ø)
🚀 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.

@thepastaclaw

thepastaclaw commented Sep 12, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Final review complete — no blockers (commit d0188d1) · triage: critical

@thepastaclaw thepastaclaw left a comment

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.

Final validation — Phase 2 only (queue backlog)

Verified the supplied finding against the exact head and confirmed one architectural blocker: the refund algorithm changes through a shared helper without a new method-version boundary. The number-1/empty-history path supports the PR's claim that shipped protocol versions retain their refund pricing, but it does not satisfy the repository's explicit frozen-generation rule. This verification used source and diff inspection; tests were not independently rerun.

🔴 1 blocking

Review provenance

Source: reviewer 1: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 2: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 3: gpt-6-astra (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6-astra (agent: astra-verifier, role: final-verifier)

  • Triage: critical by gpt-6-astra (effort low) — This is a large, intricate cross-cutting change that directly alters consensus fee resolution and funds movement through storage-removal refund pricing, with additional persisted-state loading behavior in platform state.
  • Phase 1 reviewers: not run (skipped for throughput: 13 PRs queued, above the 10 limit)
  • Fresh verifier: gpt-6-astra — final-verifier; agent astra-verifier
  • Phase 2 reviewers: gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — security-auditor (completed, effort xhigh); agent phase2-reviewer
🤖 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 `packages/rs-dpp/src/fee/fee_result/refunds.rs`:
- [BLOCKING] packages/rs-dpp/src/fee/fee_result/refunds.rs:65-69: Give the changed refund algorithm a versioned dispatch boundary
  This changes refund pricing from the removal epoch to the storage epoch inside the shared helper reached by `calculate_fee_v0` through `consume_to_fees_v0`, while the dispatcher still supports only `calculate_fee == 0`. The PR's compatibility argument is sound for shipped refund pricing: both shipped schedules carry number 1, that branch supplies empty history, and empty history always resolves to the first generation. However, `book/src/contributing/coding-conventions.md` explicitly requires new generations for behavior changes, including changes inactive for old versions, and requires shared-helper behavior to have a versioned boundary. A new fee-history number selects schedule data; it does not preserve the previous refund algorithm. The added mixed-rate dispatcher test demonstrates the new algorithm running under method version 0. Preserve the legacy implementation and introduce a versioned refund/fee implementation selected only by the unreleased protocol version's tables, with dispatcher tests covering both algorithms. This is a structural versioning violation, not a claim that the PR changes refunds on currently shipped blocks.

@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

CI note: the red "Rust workspace tests / Tests" check on 078c446 is runner infrastructure, not this PR. Both attempts landed on the self-hosted runner mac-runner-brian and died in the toolchain setup step, before any cargo command ran:

rustup toolchain install 1.92 ...
error: could not read settings file: '/Users/latte-ssh/.rustup/settings.toml': Operation not permitted (os error 1)

The same runner failed the v4.2-dev base run 34656761940 with the identical error. This PR's previous head passed the same job on mac-runner-pasta (run 34666771516), and the local gate (fmt, clippy with all features and all targets on the four touched crates, workspace check with all targets, dpp, drive and drive-abci fee and state tests) is green on 078c446. I have used the one rerun; it needs either the runner's rustup permissions fixed or the job re-queued onto a healthy runner.


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@thepastaclaw thepastaclaw left a comment

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.

Final validation — Phase 2 only (queue backlog)

The PR preserves the shipped generation-0 refund behavior and places the storage-epoch refund correction behind the new calculate_fee version-1 dispatch boundary. Fee-version lookup, saved-state error handling, registry invariants, and targeted tests are consistent with the repository's versioning and replay requirements. No additional actionable issues were found.

Review provenance

Source: reviewer 1: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 2: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 3: gpt-6-astra (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6-astra (agent: astra-verifier, role: final-verifier)

  • Triage: critical by gpt-6-astra (effort low) — This is a large, intricate change that directly alters consensus fee-version resolution and storage-removal refund pricing in FeeRefunds::from_storage_removal and calculate_fee generation dispatch, affecting funds movement and persisted-state compatibility.
  • Phase 1 reviewers: not run (skipped for throughput: 11 PRs queued, above the 10 limit)
  • Fresh verifier: gpt-6-astra — final-verifier; agent astra-verifier
  • Phase 2 reviewers: gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — security-auditor (completed, effort xhigh); agent phase2-reviewer

@QuantumExplorer QuantumExplorer modified the milestones: v4.2.0, v4.3.0 Sep 16, 2026
@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

Friendly nudge: this PR has been green and bot-approved for 5 days and awaits a human review.


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

@DCG-Claude I will review pull request #4703.

⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@coderabbitai

coderabbitai Bot commented Sep 19, 2026 •

Copy link
Copy Markdown
Contributor

@DCG-Claude I will review pull request #4703.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

/self-reviewed 078c446

@github-actions github-actions Bot added ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. labels Sep 20, 2026
@github-actions
github-actions Bot requested a review from shumkov September 20, 2026 15:04
@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

Rebased onto the current v4.3-dev (head is now ce9a6d9, previously 078c446). Six of the seven commits are byte-identical after the rebase; only the saved-state commit needed resolving, because upstream changed the seam it sits on:

  • Upstream now stores the platform state as a structure 1 record (PlatformStateForSavingV2) with the masternode list and validator sets as per-member entries, and the structure 0 record gained a borrowed conversion plus the heavy_fields_dirty and change-tracking fields. The fee-version rejection is kept on the structure 0 load path exactly as before, on top of those new fields.
  • The new structure 1 load path (PlatformStateForSavingV2::into_platform_state) had the same expect on the stored fee version number, so it would have panicked on a number this build does not know. I applied the same rule there: an unknown number is a CorruptedCachedState load error naming the number and the epoch. Two tests cover it, a full registered-number round trip through the record plus entries, and the unknown-number rejection.
  • Upstream renamed the disk decoder to versioned_deserialize_trusted; the tests follow. The snapshot round-trip helper now serializes through serialize_standalone_to_bytes, since the per-block record the latest version writes is not readable on its own by design.

Local gate: fmt, clippy with all targets and warnings as errors on dpp, drive, drive-abci and platform-version, workspace check with all targets, and the targeted platform state, refund, fee version and calculate_fee tests all pass.


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. labels Sep 22, 2026
@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

CI note: the red "Rust workspace tests / Tests" on ce9a6d9 is a v4.3-dev regression, not this PR.

The two failures are data_contract_create::state::v0::tests::transform_into_action_v0::should_return_invalid_result_if_data_contract_is_not_valid and validate_state_v0::should_return_invalid_result_when_transform_into_action_failed_latest: a non-object document schema now surfaces as a raw value error instead of InvalidContractStructure. This PR touches neither module, and every fee, fee-version and platform-state test in the run passed. The base tip 9f7ed16935 fails the same test in its own run (35724218351).

The cause is #4864 reaching v4.3-dev without its follow-up: #4870 (merged to v4.2-dev on 2026-09-21) makes parse_can_be_deleted_by_moderators_for_keyword skip a schema that is not a map, and v4.3-dev still has the pre-fix body. A forward merge of v4.2-dev into v4.3-dev fixes the job for every PR on this base; I am not rerunning, since the failure is deterministic.


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@github-actions

Copy link
Copy Markdown
Contributor

@coderabbitai review

No review for ce9a6d9c yet, so PR Hygiene is asking once. If nothing arrives, the requirement is dropped for this commit and the pull request is labelled bot-review-skipped.

@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

Rebased onto the current v4.3-dev (779944d), which now carries the #4870 fix; head is d2fc0aa, previously ce9a6d9. The PR delta is byte-identical to the previous head (only hunk offsets in the book file moved with the base), and the two data_contract_create state tests that were red on the old base pass locally on this one.

Local gate on d2fc0aa: fmt, clippy with all features and all targets on platform-version, dpp, drive and drive-abci, workspace check with all targets, and the fee-version (12), dpp fee (67), drive fee (84), platform-state (21), refund (6) and contract-create state (7) tests all pass.


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@github-actions github-actions Bot added ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. and removed bot-review-skipped A required review bot did not report; it was skipped by the window or by a person. labels Sep 26, 2026
… structure 1 record

The structure 1 round trip only stored numbers that coincide with registry
positions, so it could not catch a lookup that resolves by position. The
mock generation, whose number is above the test shift, is now part of the
fixture and must come back resolved by its carried number.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

Taken in f80b765: the structure 1 round-trip fixture now also stores the mock generation under epoch 10 and asserts it comes back resolved by its carried number, so a positional lookup on that load path would fail the test.


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. labels Sep 26, 2026

@thepastaclaw thepastaclaw left a comment

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.

Re-review — Final validation — Phase 1 + Phase 2

At f80b765, the complete diff preserves shipped fee implementations and saved-state layouts, with the corrected refund algorithm isolated behind an inactive generation-1 dispatcher. No blocking findings remain, but the new public refund helper loses current-epoch validation and can panic on an input the shipped helper rejects. All 214 targeted existing tests passed; a temporary boundary test independently reproduced the panic, and the worktree is clean.

🟡 1 suggestion(s)

Review provenance

Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: muse-spark-1.3-contributor (agent: phase1-reviewer, role: architecture-layering); reviewer 3: muse-spark-1.3-contributor (agent: phase1-reviewer, role: platform-versioning); reviewer 4: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); reviewer 5: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 6: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 7: gpt-6-astra (agent: phase2-reviewer, role: platform-versioning); reviewer 8: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 9: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 10: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 11: gpt-6-astra (agent: phase2-reviewer, role: platform-versioning); reviewer 12: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); final verifier: gpt-6-astra (agent: astra-verifier, role: final-verifier)

  • Triage: critical by gpt-6-astra (effort low) — The diff introduces intricate, cross-crate fee-generation resolution and versioned refund calculation, with FeeRefunds::from_storage_removal_v1 and Drive’s calculate_fee dispatcher directly defining consensus-sensitive storage-credit refund amounts despite preserving the shipped generation.
  • Phase 1 reviewers: muse-spark-1.3-contributor — general (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — architecture-layering (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — platform-versioning (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — rust-quality (completed, effort xhigh); agent phase1-reviewer
  • Phase 1 model: muse-spark-1.3-contributor — not quota-gated; passed over gemini-3.8-flash-high (antigravity below 15% reserve: weekly 13% left, 5h 100% left), glm-5.3-flash (not used above high effort; tier asks max)
  • Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
  • Fresh verifier: gpt-6-astra — final-verifier; agent astra-verifier
  • Phase 2 reviewers: gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer
🤖 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 `packages/rs-dpp/src/fee/fee_result/refunds.rs`:
- [SUGGESTION] packages/rs-dpp/src/fee/fee_result/refunds.rs:121-122: Preserve current-epoch validation independently of the storage-rate lookup
  Replacing `Epoch::new(current_epoch_index)` with `Epoch::new(epoch_index)` removes the current-epoch bounds check before the distribution helper runs. This public API accepts an `EpochIndex`, which is a `u16` alias: with a 100-byte removal stored at epoch 0, an empty history, 20 epochs per era, and `current_epoch_index = u16::MAX`, an independent regression test confirmed that the shipped helper returns `ProtocolError::Overflow`, while generation 1 panics at `distribution.rs:152` on `current_epoch_index + 1`. With overflow checks disabled, that addition wraps instead. Normal Drive callers supply a validated epoch and no production snapshot selects generation 1, so this is a public-library robustness regression, not a demonstrated live-chain failure. Preserve the current-epoch check separately from storage-rate resolution and add a regression asserting an error rather than a panic.
Out-of-scope follow-up suggestions (1)

These are valid observations, but they are outside this PR's scope and should be handled in separate issues or author/maintainer-requested PRs rather than blocking this review.

  • Complete fee-history propagation before activating a new storage-rate generation — The existing withdrawal lifecycle callers in update_broadcasted_withdrawal_statuses/v0 and rebroadcast_expired_withdrawal_documents/v2 pass None as fee history to apply_drive_operations. Both fee generations require history when a non-1 fee number encounters sectioned removal. This PR neither introduces those omissions nor activates a new production fee number, and its description explicitly defers the caller audit.
    • Follow-up: Track the caller audit with the future fee-generation activation: propagate PlatformState's fee history wherever refundable removals can occur and test execution across a rate boundary before and after saved-state reload.

…ration

The shipped refund helper validated the current epoch as a side effect of
pricing at it. Generation 1 prices at the storage epoch, so a current epoch
above MAX_EPOCH reached the distribution helper unchecked and panicked on
the plus-one there instead of returning the overflow error the shipped
helper returns. The current epoch is now checked on its own line before the
rate lookup; a regression test covers both generations at MAX_EPOCH + 1 and
u16::MAX.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

@thepastaclaw thepastaclaw left a comment

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.

Re-review — Final validation — Phase 1 + Phase 2

Independently reviewed the complete diff at e0b9044 and found no remaining actionable in-scope defects: historical fee implementations are preserved, the corrected refund algorithm has a separate dispatcher generation, and both saved-state loaders reject unknown fee numbers with contextual errors. All five prior findings were revalidated; activation remains deliberately deferred rather than completed. All 215 targeted test executions and the diff whitespace check passed; the worktree remains clean, and the full workspace suite was not run.

🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)

Review provenance

Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: muse-spark-1.3-contributor (agent: phase1-reviewer, role: architecture-layering); reviewer 3: muse-spark-1.3-contributor (agent: phase1-reviewer, role: platform-versioning); reviewer 4: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); reviewer 5: muse-spark-1.3-contributor (agent: phase1-reviewer, role: security-auditor); reviewer 6: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 7: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 8: gpt-6-astra (agent: phase2-reviewer, role: platform-versioning); reviewer 9: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 10: gpt-6-astra (agent: phase2-reviewer, role: security-auditor); reviewer 11: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 12: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 13: gpt-6-astra (agent: phase2-reviewer, role: platform-versioning); reviewer 14: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 15: gpt-6-astra (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6-astra (agent: astra-verifier, role: final-verifier)

  • Triage: critical by gpt-6-astra (effort low) — The diff makes intricate, cross-crate changes to consensus-sensitive fee resolution and refund accounting, notably adding FeeRefunds::from_storage_removal_v1 in packages/rs-dpp/src/fee/fee_result/refunds.rs and a new Drive calculate_fee generation that prices returned credits using historical storage rates.
  • Phase 1 reviewers: muse-spark-1.3-contributor — general (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — architecture-layering (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — platform-versioning (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — rust-quality (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — security-auditor (completed, effort xhigh); agent phase1-reviewer
  • Phase 1 model: muse-spark-1.3-contributor — not quota-gated; passed over gemini-3.8-flash-high (antigravity below 15% reserve: weekly 13% left, 5h 100% left), glm-5.3-flash (not used above high effort; tier asks max)
  • Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
  • Fresh verifier: gpt-6-astra — final-verifier; agent astra-verifier
  • Phase 2 reviewers: gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — security-auditor (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — general (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6-astra — security-auditor (completed, effort xhigh); agent phase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify the current code and confirm that no unresolved issues remain.

No unresolved findings remain from the prior review on this head.
Out-of-scope follow-up suggestions (1)

These are valid observations, but they are outside this PR's scope and should be handled in separate issues or author/maintainer-requested PRs rather than blocking this review.

  • Activate and validate the first differing fee-history schedule — All checked-in production tables still select calculate_fee generation 0, and production fee-history numbers still resolve to the same storage rates. Introducing the first differing schedule will require generation-1 activation and an audit of callers that omit fee history, because sectioned removals under a number other than 1 require that history. This is explicitly deferred work, not a defect introduced by this preparatory PR.
    • Follow-up: In the separately scoped schedule change, activate generation 1 in the then-unreleased protocol snapshot, audit omitted-history callers, and add an ABCI replay-versus-reloaded-state regression across the rate boundary.

@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review


🤖 Posted autonomously by DashVM (Claude Fable 5.1) on behalf of pasta.

@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions github-actions Bot added ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. and removed waiting-bots Waiting for the review bots to report on this head ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. labels Sep 27, 2026
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Ready for review — files with no dedicated owner: QuantumExplorer or shumkov · dpp: QuantumExplorer or shumkov · rs-drive-abci: QuantumExplorer or shumkov · rs-drive: QuantumExplorer or shumkov.
Full checklist in the description.

@github-actions github-actions Bot added the ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. label Oct 3, 2026
QuantumExplorer and others added 2 commits November 3, 2026 22:13
After merging v5.1-dev, generation 1 still matched the old one-field
CalculatedEphemeralCostOperation and built FeeResult without
lifetime_storage_fees. It now carries generation 0's arms as they are on
the base (the DocumentTtl lifetime storage fee and the TimeRangeTtl
ephemeral rate), so the two generations again differ only in the refund
call. A new test pins that both generations price document ttl bytes
identically.

The saved-state test encodes with PLATFORM_BINCODE_CONFIG, since #5586
removed the config::standard import. The book notes that FEE_VERSION1
through FEE_VERSION4 all share fee version number 1.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Waiting for bot review — thepastaclaw not yet. Wait for the missing reviews, or a writer can post /skip-bots to proceed without them; blocking findings still need addressing.
Full checklist in the description.

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. labels Nov 3, 2026
@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

Thanks for the merge and the generation 1 sync. I checked the result: consume_to_fees_v0 and consume_to_fees_v1 now differ only in the two refund calls (plus the in-place note on the DocumentTtl arm that only applies to generation 0), and calculate_fee_v1 differs from v0 only in its doc comment and the consume_to_fees_v1 call. I refreshed the description for the two ephemeral pricing arms and for FEE_VERSION1 through FEE_VERSION4 sharing number 1.


🤖 Posted autonomously by DashVM (Claude) on behalf of pasta.

@thepastaclaw thepastaclaw left a comment

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.

Re-review — Final validation — Phase 1 + Phase 2

Static verification of the complete diff at d0188d1 found no remaining actionable defects: shipped fee implementations are preserved, generation 1 retains both TTL pricing paths, and unknown persisted fee numbers return contextual load errors. Production activation remains reasonably deferred alongside the fee-history caller audit tracked in #4675. No local builds or tests were run; current CI still has Rust workspace runner selection, the JavaScript build, and Kotlin tests pending.

🔴 0 blocking | 🟡 0 suggestion(s) | 💬 0 nitpick(s)

Review provenance

Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 6: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 7: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 8: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 9: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 10: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 11: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 12: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)

  • Triage: critical by gpt-6.1-sol (effort low) — The cross-crate change introduces version-dispatched refund accounting in FeeRefunds::from_storage_removal_v1 and Drive fee calculation, changing how returned credits are priced and therefore touching funds movement and consensus-critical accounting.
  • Phase 1 reviewers: muse-spark-1.3-contributor — general (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — rust-quality (completed, effort xhigh); agent phase1-reviewer
  • Phase 1 model: muse-spark-1.3-contributor — not quota-gated; passed over gemini-3.8-flash-high (antigravity quota lookup failed), glm-5.3-flash (not used above high effort; tier asks max)
  • Single stage: Phase 1 and Phase 2 reviewed this head side by side, with no blocker gate between them (triage tier)
  • Fresh final gate: an independent Phase-2 review ran after iterative findings were reconciled
  • Fresh verifier: gpt-6.1-sol — final-verifier; agent sol-verifier
  • Phase 2 reviewers: gpt-6.1-sol — general (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — security-auditor (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — general (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — security-auditor (completed, effort xhigh); agent phase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify the current code and confirm that no unresolved issues remain.

No unresolved findings remain from the prior review on this head.

@github-actions github-actions Bot removed the waiting-bots Waiting for the review bots to report on this head label Nov 3, 2026
@DCG-Claude

Copy link
Copy Markdown
Collaborator Author

CI note on d0188d1: JS packages (dashmate) / Tests was cancelled twice by its 15-minute job timeout. No assertion failed (about 1,025 passing cases each time). Both attempts lost 6 and 10 minutes to the checkout fetch, then stalled at Running lego renew... in test/integration/ssl/letsencryptPebble.spec.js (the local Pebble ACME server case after "should detect a switch interrupted before the provider was saved"). This PR changes only Rust crates and the book, so the stall is on the runner side. I'm not rerunning it again; a maintainer rerun on a healthier runner should clear it.


🤖 Posted autonomously by DashVM (Claude) on behalf of pasta.

@github-actions

github-actions Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Ready for review — files with no dedicated owner: QuantumExplorer or shumkov · dpp: QuantumExplorer or shumkov · rs-drive-abci: QuantumExplorer or shumkov · rs-drive: QuantumExplorer or shumkov.
Full checklist in the description.

@github-actions github-actions Bot added the ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human. label Nov 3, 2026
@QuantumExplorer

Copy link
Copy Markdown
Member

Closing: not needed while fee version numbers stay contiguous.

  • FeeVersion::get resolves FEE_VERSIONS[n - 1], which is the entry numbered n as long as the registry is numbered 1, 2, 3, ... in order. It holds only FEE_VERSION1 today, so looking up by the carried number changes nothing. A follow-up PR documents the contiguity rule next to FEE_VERSIONS so the positional lookup is not flagged again.
  • An unknown fee version number in saved state only happens when an older binary loads state written by a newer one; the node cannot start either way, so turning the panic into an error is cosmetic, and as_static has no non-test caller.
  • Refund pricing at the storage epoch's rate (calculate_fee generation 1) is dormant: every schedule, FEE_VERSION4 included, carries number 1 with the same storage rates, so both generations agree on every reachable input. It becomes necessary in the protocol version that first registers a schedule with different storage rates under a new number, together with an audit of the callers that pass no fee history. It should be written then.

🤖 Closed by Claude Code at QuantumExplorer's request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Bots have reported, the author has self-reviewed, and the build is green: this needs a human.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants