Repository navigation
feat(platform)!: destroy a frozen identity's escrowed listings with its funds (PV15) - #5532
QuantumExplorer wants to merge 56 commits into
Conversation
…ts funds (PV15) A frozen identity's open listings hold its tokens in escrow, out of the balance a TokenDestroyFrozenFunds burns. From protocol version 15 the destroy also reads the frozen identity's open listings of the token (order_escrow.fetch_frozen_listings, byOwner index, oldest first, at most max_frozen_listings_destroyed_per_transition = 16), destroys what they hold with the balance through TokenDestroyFrozenHolding (one supply decrement), deletes their ask documents and records the whole amount. Converter generation 1 (DRIVE_STATE_TRANSITION_METHOD_VERSIONS_V5) does this; v0's operations are unchanged. Offers hold credits and are left alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
📖 Book Preview built successfully. Download the preview from the workflow artifacts. Updated at 2026-10-27T00:05:26.708Z |
|
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
|
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Phase 1 + Phase 2
The PV15 gates and combined balance/escrow burn appear correct on inspection, but the listing deletions lose pending batch context, leaving empty index structures and withholding their storage refunds. Historical-path coverage and generation isolation also need improvement. This was static verification at head 2a7d869; current reported CI checks pass, but none reports a dedicated Rust test result.
🔴 1 blocking | 🟡 4 suggestion(s)
Review provenance
Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 6: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 7: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
criticalbygpt-6.1-sol(effort low) — This is a large, intricate change to consensus-critical token destruction, escrow removal, supply accounting, state-transition version dispatch, and persisted storage operations in files such as token_destroy_frozen_funds_transition.rs and the Drive batch operation code. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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 verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs`:
- [BLOCKING] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs:146-155: Preserve pending operations across the listing deletions
Each listing becomes a separate DeleteDocument, whose lowering in util/batch/drive_op_batch/document.rs passes None for previous_batch_operations. apply_drive_operations_v1 lowers all operations before applying the batch, so each deletion still sees the other listings in storage. With two listings at the same price, neither deletion prunes their shared depth bucket; byOwner ancestors also remain, and listings sharing a creation timestamp leave their shared timestamp buckets behind. The documents and escrow disappear, but empty index trees remain and the identities that paid for those trees do not receive their storage refunds. Both the pinned and current GroveDB implementations already support pending-operation-aware pruning. Build these deletions together in Drive's document-operation lowering and pass the accumulated low-level operations to each deletion, following AddDocumentAndDeleteConsumed, without changing historical protocol paths. Add a regression asserting shared-index cleanup and the associated refunds, not only document absence and token conservation.
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs:35-38: Add behavioral coverage for the pre-PV15 dispatcher path
Generation 0 now delegates to the shared helper, and both transformers call the new version-gated listing fetch. The existing destroy integration tests and the new marketplace tests use PlatformVersion::latest(), so they exercise generation 1; the action accessor tests do not exercise conversion. Comparison with the base revision shows the generation-0 operation sequence is currently preserved, but no behavioral test protects that claim. Add a dispatcher-level test pinned to PlatformVersion::get(14) that verifies nonce, burn, history and group-action operations, including perform_action=false. Also verify that the historical listing-fetch gate returns an empty result at zero cost without marketplace state. This supplies the historical regression evidence required by the book's in-place-change checklist.
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs:35-38: Keep the converter generations structurally separate
The version tables correctly select generation 1 only for PV15, and the false branch currently preserves generation 0's output. However, both generations execute the same listing-aware body through a destroy_listings flag. book/src/versioning/versioned-dispatch.md explicitly calls for separate generation implementations and identifies a shared helper with a flag as the pattern that separation replaces. Retain the balance-only implementation in generation 0 and put the listing-aware implementation in generation 1, selected by the existing table bump. This makes historical replay independent of later edits to PV15 operation ordering, history and group events. This is a structural replay-safety concern, not evidence of a current PV14 behavioral difference.
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs:64-68: Avoid cloning the owned action's listing vector
This helper owns self but clones every escrowed TokenOrder into a new vector. The following code only reads those orders and collects their id/remaining pairs, so the allocation and full-order copies are unnecessary on each listing-aware destroy. Borrow the listing slice until its final use, adjusting the loop accordingly, or move the vector out of the owned action. The borrow can end before public_note_owned consumes self.
In `packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:151-166: Share the new listing-fetch and billing sequence
The owned constructor's fetch, processing-fee update and optional market-contract lookup are repeated in the borrowed constructor at lines 318–333. These operations have identical semantics; only the frozen identity argument needs dereferencing. Keeping this new sequence in two places makes later changes to fee accounting or contract handling liable to diverge between transformation routes. Extract a helper used by both constructors that returns the listings, optional contract and read cost, or updates the FeeResult. This is a maintainability suggestion rather than a layer-ownership or current correctness violation.
…rozen-escrow fetch_frozen_listings joins the escrow methods as an OptionalFeatureVersion (None in V1, Some(0) in V3); DRIVE_VERSION_V10 keeps both sides' changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eration - New document operation DeleteDocuments: several documents of one type deleted in one conversion, each delete built against the ones before it, so index trees they share are removed and refunded. Generation 1 of the destroy-frozen-funds converter deletes the listings through it; separate DeleteDocuments each read the others as stored and left shared trees behind, unrefunded. - The converter's generation 0 is restored to its shipped implementation; generation 1 is its own function, and collects only the (id, remaining) pairs it needs instead of cloning the orders. - Both transformer routes read and bill the listings through one helper. - Tests: two listings sharing index buckets destroyed together leave the ask trees cancelling them one by one leaves and refund at least as much; dispatcher tests at protocol version 14 (nonce, burn, history, group proposal and completion) and 15; the listing read at 14 returns none at zero cost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
At head 086cbf0, four prior findings are fixed, but pending-operation context still stops at each DeleteDocuments operation, leaving shared index trees and their refunds behind when one batch destroys holdings of two tokens. Current reported CI checks pass, although they provide no dedicated Rust test or clippy results; this verification was static only.
🔴 1 blocking
Review provenance
Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 6: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 7: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
criticalbygpt-6.1-sol(effort low) — The intricate changes in token_destroy_frozen_funds_transition.rs and the TokenDestroyFrozenHolding batch operation alter consensus-critical destruction of balances, escrow holdings, and token supply, together with batch-aware listing deletion and storage refunds. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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 verifier:
gpt-6.1-sol— final-verifier; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/util/batch/drive_op_batch/document.rs`:
- [BLOCKING] packages/rs-drive/src/util/batch/drive_op_batch/document.rs:635-644: Preserve pending operations across the listing deletions
The grouped deletion fixes shared-tree pruning within one destroy, but this fresh vector excludes deletions from other operations in the same batch. A valid BatchTransition can destroy one frozen identity's holdings of two tokens from distinct contracts controlled by the signer: their contract nonces, token balances, supplies and escrows are distinct, so the nonce validation and repeated-token-write guard permit this. Conversion emits two DeleteDocuments operations, and apply_drive_operations_v1 lowers both before applying either. Their listings share the marketplace's byOwner/$ownerId index bucket. Each group sees the other token's subtree still in storage, so neither prunes the shared owner bucket; execution removes the listings but leaves empty index structure and withholds its storage refund. Your regression verifies the single-token case, not this enclosing-batch boundary. Thread relevant accumulated operations through document lowering, or coalesce compatible deletion groups in a PV15-only path. Both pinned and current GroveDB already support pending-aware pruning. Add a two-token, two-contract destroy-batch regression comparing remaining index paths and owner refunds with sequential destroys.
…rozen-escrow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…atch's earlier operations apply_drive_operations 2 (protocol version 15, unreleased, extended in place) builds every operation against the operations of its GroveDB batch built before it and appends its own (DriveOperation::append_low_level_drive_operations_after_ttl_drain). Every document insert, update and deletion, DeleteDocuments included, gets them as previous_batch_operations: one batch destroying a frozen identity's listings of two tokens removes the owner's shared byOwner bucket and refunds it, and an insert into a bucket an earlier deletion of the batch empties keeps the tree. Protocol version 14 and earlier keep generation 1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rozen-escrow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rozen-escrow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
Verified the complete diff at 5429998 and confirmed that all six prior findings are fixed. One blocking issue remains: pending-aware batch lowering fixes behavior that an existing non-ignored test still asserts is defective; two non-blocking gaps concern grouped-operation context and PV15 group-action coverage. Validation was static only; current CI checks pass, but none reports the native Drive test suite.
🔴 1 blocking | 🟡 2 suggestion(s)
Review provenance
Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 6: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 7: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); 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:
criticalbygpt-6.1-sol(effort low) — The large, intricate diff changes consensus-critical token destruction and escrow accounting in token_destroy_frozen_funds_transition.rs and shared pending-write batch semantics in apply_drive_operations/v2/mod.rs. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/util/batch/drive_op_batch/drive_methods/apply_drive_operations/v2/mod.rs`:
- [BLOCKING] packages/rs-drive/src/util/batch/drive_op_batch/drive_methods/apply_drive_operations/v2/mod.rs:134-138: Update the ranked-drain test that still asserts the pre-PV15 defect
Passing the enclosing batch's pending operations also fixes the ranked-index drain characterized by the non-ignored `a_batched_drain_leaves_a_phantom_group_that_verifies_and_proves` test in `packages/rs-drive/src/drive/contract/insert/insert_contract/v0/tests/batched_group_drain.rs:577`. Its helpers select `PlatformVersion::latest()` and call `apply_drive_operations`, so they now use this path. The second deletion sees the first pending deletion and prunes the empty `beta` group, but the assertion at lines 594–599 still requires both `alpha` and `beta` to remain. This leaves a failing test in the native Drive suite, outside the targeted filters listed in the PR description. Retain the old characterization under PV14 if historical coverage is needed, and update or enable the desired-behavior drain cases for PV15.
In `packages/rs-drive/src/util/batch/drive_op_batch/document.rs`:
- [SUGGESTION] packages/rs-drive/src/util/batch/drive_op_batch/document.rs:590-601: Preserve enclosing batch context through grouped document operations
The new append path preserves enclosing batch context for individual document operations but drops it for `MultipleDocumentOperationsForSameContractDocumentType`. That variant reaches this fallback, and its existing lowering starts a fresh accumulator at line 1011. Its inserts and updates therefore see only their group's predecessors. Expressing the replacement insert in `should_insert_into_a_tree_an_earlier_deletion_of_the_batch_empties` as a one-member grouped `AddOperation` exposes the gap: the earlier deletion schedules removal of shared index trees, while the grouped insert sees those trees in storage but cannot cancel their pending removal. The marketplace's current `DeleteDocuments` path is fixed, but the shared API's pending-context guarantee still depends on how equivalent writes are packaged. Pass the enclosing accumulator through grouped lowering and add the grouped equivalent of the delete-then-insert regression. This is a completeness gap in the shared batch abstraction, not a violation of layer ownership.
In `packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs:428-430: Exercise PV15 group actions with escrowed listings
The listing-aware dispatcher test constructs only an ungrouped, performing action. The new group-action dispatcher tests select PV14, and the existing latest-version group integration tests contain no listings. No test therefore protects generation 1's combination of a listing-inclusive group event and deferred execution: recording only the liquid balance in that event would pass the current tests. Add latest-version cases with nonempty listings for a non-closing proposal and a completing signature. Assert that the proposal records the balance-plus-escrow total without emitting holding destruction, document deletion or history, and that completion closes the group action and emits the listing destruction and total-valued history.
…erations see the batch - apply_drive_operations 2 builds the operations of a MultipleDocumentOperationsForSameContractDocumentType group against the enclosing batch's operations too, instead of a fresh accumulator. - batched_group_drain: the five drain specifications, #[ignore]d as a latent defect while the documents batch cap is 1, run and pass at the latest version; the phantom-group characterization applies its batch at protocol version 14 (generation 1). The module, case and SystemLimits docs say protocol version 15 removes the hazard and that the cap's other dependencies still stand. - Tests: a deletion and a grouped insert into the same bucket in one batch; the frozen-funds converter at the latest version in a group with listings (proposal records balance plus escrow, completion destroys and records the total). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The complete diff at the requested head has no blocking consensus, accounting, security, or historical-replay defects. Two non-blocking improvements remain: make the new batch append match exhaustive for the currently delegated variants, and add coverage for destroying partially filled listings. Available CI checks pass, although the supplied snapshot does not include native Rust test results.
🟡 2 suggestion(s)
Review provenance
Source: reviewer 1: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 6: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 7: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); 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:
criticalbygpt-6.1-sol(effort low) — This is a large consensus-critical change that alters protocol-versioned state-transition logic, token destruction and escrowed-fund movement, listing deletion, supply accounting, and persistent GroveDB operations. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/util/batch/drive_op_batch/document.rs`:
- [SUGGESTION] packages/rs-drive/src/util/batch/drive_op_batch/document.rs:654-665: Match remaining document operations explicitly instead of a wildcard
The new append path handles inserts, updates, deletions, and grouped writes with the enclosing batch as pending context, but the trailing wildcard delegates `AddContestedDocument`, `AddWithdrawalDocument`, and `DocumentHistory` to the standalone lowering path. That is the current intended behavior for those variants, but the wildcard removes exhaustiveness checking: a future `DocumentOperationType` variant would silently bypass the pending-aware path. Enumerate the three remaining variants explicitly so every new document operation requires an intentional pending-context decision.
In `packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/marketplace/mod.rs`:
- [SUGGESTION] packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/marketplace/mod.rs:2593-2602: Exercise destruction after a listing has been partially filled
The new frozen-listing tests create each order with `TokenOrder.amount` equal to `TokenOrder.remaining`, so they cannot distinguish burning the original listing amount from burning only the escrow still present. The implementation currently uses `remaining`, but both fields share the same type and a regression to `amount` would pass these tests. Add a partial-fill case before freezing—such as filling 1,000 tokens from a listing—and assert that destruction lowers supply and records history by the remaining amount, preserves the counterparty's purchased tokens, and removes the remaining escrow and document.
…rozen-escrow The frozen-listing helper signs the token's decimals, as listings now do. The batch-aware document lowering lists its remaining operation types explicitly instead of a wildcard, and a destroy of a partly filled listing takes what is left in escrow (new test). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
At c832240, the PV15 frozen-listing destruction path preserves historical dispatch and propagates pending operations through document application; all 11 prior findings are addressed in source. One non-blocking consistency gap remains in the alternate raw batch-conversion API. Current reported CI checks pass, but they do not establish native Drive or Drive-ABCI test success; this verification was static-only.
🟡 1 suggestion(s)
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 4: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 5: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 6: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); reviewer 7: gpt-6-astra (agent: phase2-reviewer, role: general); reviewer 8: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); reviewer 9: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 10: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 11: gpt-6-astra (agent: phase2-reviewer, role: security-auditor); reviewer 12: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 13: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 14: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 15: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 16: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
criticalbygpt-6.1-sol(effort low) — This large, intricate diff changes consensus-critical protocol-version dispatch, token supply destruction, escrowed funds movement, and persistent document/index deletion in functions such as token_destroy_frozen_funds_transition and apply_drive_operations. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— general (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer - Model comparison: every Phase-2 reviewer also ran on
gpt-6-astra; the verifier weighed both sets without knowing which model wrote which
🤖 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-drive/src/util/batch/drive_op_batch/drive_methods/apply_drive_operations/v2/mod.rs`:
- [SUGGESTION] packages/rs-drive/src/util/batch/drive_op_batch/drive_methods/apply_drive_operations/v2/mod.rs:134-141: Share pending-aware lowering with the raw batch converter
The application path now preserves enclosing batch context, but the public convert_drive_operations_to_grove_operations API still selects generation 1 at PV15, delegates to generation 0, and lowers each operation independently. In particular, each newly added DeleteDocuments operation starts a fresh accumulator in document.rs. Converting two such operations for one owner's asks of different tokens therefore still leaves their shared byOwner bucket behind: neither group sees the other's pending deletions. Existing RawConversion document tests establish that document batches are supported by this API. This is a non-blocking completeness gap in Drive's shared batch abstraction, not a misplaced-layer violation or a blocker for marketplace execution: the current production caller converts identity payouts, not documents. Add a PV15 raw-converter generation that uses the pending-aware accumulator, preserves the existing debt and ephemeral-operation refusals, and exercises the two-token cleanup case through both entry points.
… batch's earlier ones at protocol 15 convert_drive_operations_to_grove_operations 2, selected by DRIVE_VERSION_V10, is generation 1 (repeated counter moves refused, TTL preparation) with every operation appended through append_low_level_drive_operations_after_ttl_drain, as apply_drive_operations 2 does, so two deletions emptying a shared index tree remove it on this entry point too. Credits that repaid a debt and ephemeral operations are refused as before. New test: one owner's asks of two tokens deleted through the converter leave the trees deleting them separately leaves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rozen-escrow # Conflicts: # packages/rs-platform-version/src/version/system_limits/mod.rs
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The PV15 frozen-listing behavior is correctly version-gated, preserves historical PV14 behavior, and the pending-aware apply/raw conversion paths address the previously identified cleanup defects. Four in-scope suggestions remain: one fee-overflow handling inconsistency, one pending-operation gap for contested document writes, and two deviations from the required per-generation module layout. Available CI checks are successful.
🟡 4 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: 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:
criticalbygpt-6.1-sol(effort low) — This large, intricate diff changes consensus-critical protocol-versioned state-transition logic that destroys token funds, removes escrowed listings, adjusts supply, and mutates persistent GroveDB storage in files such as token_destroy_frozen_funds_transition.rs and apply_drive_operations/v2/mod.rs. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:360: Accumulate the listing-read fee with checked arithmetic
The newly billed listing query adds `read_cost` with `saturating_add`, so an overflow silently caps the processing fee instead of propagating the fee overflow error. This is the only marketplace read path using saturation; the analogous token order transformers use `FeeResult::checked_add_assign`, which preserves the fee-accounting invariant and avoids silently undercharging if the accumulated processing fee exceeds `u64::MAX`.
In `packages/rs-drive/src/util/batch/drive_op_batch/document.rs`:
- [SUGGESTION] packages/rs-drive/src/util/batch/drive_op_batch/document.rs:654-667: Preserve pending context for contested document writes
The PV15 append path passes the enclosing batch accumulator to ordinary document operations and grouped writes, but the explicit `AddContestedDocument` arm delegates to `into_low_level_drive_operations_after_ttl_drain`. That method creates a fresh accumulator and calls `add_contested_document_for_contract_operations` with `&mut None`, even though the contested-document API accepts `previous_batch_operations`. A contested document inserted after an earlier pending deletion can therefore lower against stale committed index state instead of the batch's pending writes. The same arm also leaves withdrawal and history operations on their standalone paths; these should be explicitly justified or extended if they are expected to participate in the pending-aware guarantee.
In `packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition.rs:102-123: Keep the PV15 converter generation in a dedicated version module
The dispatcher correctly selects generation 1 for protocol 15 and generation 0 remains behaviorally separate, but the new generation is still implemented as a private method in the same source module as the dispatcher and historical generation. The repository's versioning guidance requires every new generation to live in its own `vN/` directory with its tests. Moving the PV15 implementation into a dedicated version module would physically isolate replay behavior and prevent later edits to the active generation from silently changing the historical implementation.
In `packages/rs-drive/src/drive/tokens/order_escrow/fetch_order.rs`:
- [SUGGESTION] packages/rs-drive/src/drive/tokens/order_escrow/fetch_order.rs:97-128: Isolate the frozen-listing fetch implementation as a versioned module
The `None`/`Some(0)` protocol gate is correct, but `fetch_frozen_token_listings_v0` is implemented inline in `fetch_order.rs` rather than in a dedicated `v0/` module. The versioning guidance requires each versioned implementation to live in its own generation directory, which keeps historical replay code physically isolated and makes future behavior changes require an explicit new generation.
…operations; generation modules From protocol version 15, apply_drive_operations 2 builds a contested document insert and a withdrawal document insert against the batch's earlier operations, as it already did for other document writes; a document history entry stays standalone, with the reason recorded at its arm. The destroy's listing read adds its cost with checked fee arithmetic. The generation-1 destroy converter and the frozen-listing fetch move into their own version modules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
Static review of exact head 76c7c8b found no in-scope correctness, consensus, accounting, security, or architectural defects. Protocol 15 behavior is version-isolated, listing destruction and history calculations agree, and pending-aware document lowering covers the relevant batch paths. The supplied CI snapshot has no failed checks; the Kotlin SDK check was still in progress and does not appear to cover the changed Drive code.
🔴 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:
criticalbygpt-6.1-sol(effort low) — This is a large, intricate change to consensus-critical token destruction and storage operations that moves funds, alters token supply, deletes escrowed documents, and introduces protocol-versioned behavior in the transition and Drive layers. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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.
…erge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The current head correctly gates frozen-listing destruction and pending-aware document lowering behind protocol version 15, while preserving the protocol-14 generation and adding coverage for listings, groups, partial fills, refunds, and raw conversion. I found no blocking correctness, consensus, security, or fee-accounting defects. One non-blocking architectural suggestion remains: keep the version-dependent destroyed-amount calculation physically separated from the shared action module.
🟡 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: 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-astra (agent: phase2-reviewer, role: general); reviewer 9: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 10: gpt-6-astra (agent: phase2-reviewer, role: platform-versioning); reviewer 11: gpt-6-astra (agent: phase2-reviewer, role: rust-quality); reviewer 12: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 13: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 14: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 15: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 16: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
criticalbygpt-6.1-sol(effort low) — This large, intricate change modifies consensus-critical token destruction and escrowed-funds movement in the state-transition operation conversion and batch application paths, including protocol-version dispatch and persistent document/index deletion. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— general (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer - Model comparison: every Phase-2 reviewer also ran on
gpt-6-astra; the verifier weighed both sets without knowing which model wrote which
🤖 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-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/mod.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/mod.rs:103-125: Keep destroyed-amount history logic in versioned generation modules
The destroyed amount is consensus-visible because it is written into group-action events and token history documents. Although the method dispatches on the same platform-version slot as the converter, both generation-specific calculations remain inline in the shared action module, and the protocol-15 converter calls back into that helper. Move the v0 and v1 calculations into generation-owned modules, or make this helper dispatch to generation-owned implementations, so future edits to the active generation cannot accidentally alter shared replay-sensitive history construction.
…dule destroyed_amount dispatches to destroyed_amount_v0 (the frozen balance) and destroyed_amount_v1 (the balance and the listings' escrow, checked), each in its own version module, so an edit to the active generation cannot reach the recorded amount of an earlier one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rozen-escrow # Conflicts: # packages/rs-platform-version/src/version/v15.rs
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The PV15 frozen-listing destruction implementation is correctly version-gated and the previously reported consensus, accounting, batching, history, and test-coverage issues are fixed. Two non-blocking issues remain: the new optional fetch method should fail closed before protocol 15, and CheckTx currently performs bounded stateful listing reads before full authorization. The relevant CI checks are successful; the Kotlin SDK check was still queued.
🟡 2 suggestion(s)
Review provenance
Source: reviewer 1: muse-spark-1.3-contributor (agent: phase1-reviewer, role: general); reviewer 2: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 3: muse-spark-1.3-contributor (agent: phase1-reviewer, role: rust-quality); 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:
criticalbygpt-6.1-sol(effort low) — This large, intricate diff changes consensus-critical protocol-version dispatch and token destruction, escrowed-funds movement, supply accounting, and persistent marketplace document deletion in state-transition and batch-application code. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/drive/tokens/order_escrow/fetch_frozen_token_listings/mod.rs`:
- [SUGGESTION] packages/rs-drive/src/drive/tokens/order_escrow/fetch_frozen_token_listings/mod.rs:27-35: Return VersionNotActive for the pre-PV15 optional feature
`fetch_frozen_listings` is an optional versioned feature: its table entry is `None` before protocol 15 and `Some(0)` at protocol 15. The dispatcher currently turns the inactive `None` case into a successful empty result with zero cost, unlike the other token-market escrow dispatchers, which return `DriveError::VersionNotActive`. This makes an unsupported direct call appear to have succeeded and weakens the fail-closed version boundary. Keep the historical no-op in the pre-PV15 converter generation or a separate compatibility helper, but make this versioned method return `VersionNotActive` when its slot is `None`.
In `packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:344-360: Avoid stateful frozen-listing reads during CheckTx cost approximation
`read_frozen_listings` unconditionally calls `fetch_frozen_token_listings`, whose query passes `dry_run = false` and therefore reads and decodes up to 16 listing documents. Batch CheckTx transformation uses `approximate_without_state_for_costs = true`, while `TokenDestroyFrozenFunds` is not among the transitions that receive full state authorization during ordinary CheckTx. Consequently, a syntactically valid, correctly signed transition with a valid token contract and nonce can cause a bounded stateful listing query for arbitrary token and frozen-identity IDs before block validation rejects the unauthorized destroy. Because CheckTx admission does not charge the estimated fee or aggregate future mempool work, repeated funded nonces can amplify these RocksDB reads and document decodes. Pass the approximation mode into this helper and use a deterministic stateless worst-case cost estimate during CheckTx and recheck; resolve the actual listings only during validator execution, while preserving sufficient fee estimation for the maximum bounded read.
| fn read_frozen_listings( | ||
| drive: &Drive, | ||
| token_id: Identifier, | ||
| frozen_identity_id: Identifier, | ||
| block_info: &BlockInfo, | ||
| fee_result: &mut FeeResult, | ||
| transaction: TransactionArg, | ||
| platform_version: &PlatformVersion, | ||
| ) -> Result<(Vec<TokenOrder>, Option<Arc<DataContractFetchInfo>>), Error> { | ||
| let (listings, read_cost) = drive.fetch_frozen_token_listings( | ||
| token_id, | ||
| frozen_identity_id, | ||
| &block_info.epoch, | ||
| transaction, | ||
| platform_version, | ||
| )?; | ||
| fee_result.checked_add_assign(FeeResult::new_from_processing_fee(read_cost))?; |
There was a problem hiding this comment.
🟡 Suggestion: Avoid stateful frozen-listing reads during CheckTx cost approximation
read_frozen_listings unconditionally calls fetch_frozen_token_listings, whose query passes dry_run = false and therefore reads and decodes up to 16 listing documents. Batch CheckTx transformation uses approximate_without_state_for_costs = true, while TokenDestroyFrozenFunds is not among the transitions that receive full state authorization during ordinary CheckTx. Consequently, a syntactically valid, correctly signed transition with a valid token contract and nonce can cause a bounded stateful listing query for arbitrary token and frozen-identity IDs before block validation rejects the unauthorized destroy. Because CheckTx admission does not charge the estimated fee or aggregate future mempool work, repeated funded nonces can amplify these RocksDB reads and document decodes. Pass the approximation mode into this helper and use a deterministic stateless worst-case cost estimate during CheckTx and recheck; resolve the actual listings only during validator execution, while preserving sufficient fee estimation for the maximum bounded read.
source: gpt-6.1-sol (phase2-reviewer: security-auditor)
There was a problem hiding this comment.
Not changed here. The read is real, but it isn't specific to this transition:
TokenFillAsk,TokenFillBidandTokenCancelOrderread their order document in the same CheckTx transformation, for any order id a signed, funded batch names.- A grouped token transition reads its group action.
Each read is bounded. This one is a single byOwner index query of at most max_frozen_listings_destroyed_per_transition (16) documents.
Skipping it only when approximate_without_state_for_costs is set would also make CheckTx's fee estimate for a destroy leave out the deletes it actually performs. Replacing it with a stateless worst case of 16 deletes would overcharge every destroy's admission check.
If CheckTx should stop doing transformer state reads before authorization, that's a policy for every marketplace (and group) transformation, and should land as one change rather than for one transition. I've left this open for Sam to decide.
🤖 Addressed by Claude Code
There was a problem hiding this comment.
Still applies (re-reviewed at 8355a639): The current head still performs the indexed listing query with dry_run=false from the shared transformer, even when CheckTx is using approximate transformation and full destroy authorization is deferred. The bounded limit and analogous marketplace reads reduce the per-request cost but do not remove the new multi-document admission-time read amplification.
…ion 15 fetch_frozen_token_listings returns VersionNotActive when its slot is None, as the other escrow dispatchers do; the destroy transformer reads nothing before protocol version 15 itself, so a destroy there still burns the frozen balance alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The protocol-15 implementation is correctly version-gated and the listing, escrow, history, pending-operation, and regression-test changes address the previously identified correctness issues. One suggestion remains valid: the new frozen-listing lookup performs a real indexed query and decodes up to 16 documents during ordinary CheckTx before destroy authorization is evaluated; Kotlin and policy checks remain pending, while the book preview is green.
🟡 1 suggestion(s)
1 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
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:
criticalbygpt-6.1-sol(effort low) — This is a large, intricate consensus-critical change that alters protocol-versioned token destruction, escrowed funds movement, supply accounting, and document deletion across Drive state-transition operations. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:344-372: Avoid stateful frozen-listing reads during CheckTx cost approximation
(existing thread: https://github.com/dashpay/platform/pull/5532#discussion_r4372880155)
`read_frozen_listings` does not receive `approximate_without_state_for_costs` and always calls `fetch_frozen_token_listings`. The v0 query invokes `query_documents` with `dry_run = false`, so ordinary Batch CheckTx transformation can read the `byOwner` index and decode up to 16 `ask` documents before the later frozen-account and authorization checks reject the transition. A correctly signed, funded transition with a valid nonce can therefore name arbitrary token and frozen-identity IDs and repeatedly trigger bounded RocksDB and parsing work during mempool admission and recheck without being charged for that work. The limit of 16 bounds one request but does not remove amplification across transactions, and the analogous fill/cancel reads do not justify introducing this new multi-document scan. Thread the approximation mode through this helper and establish a deterministic stateless worst-case estimate or defer listing materialization to authoritative execution; if stateful marketplace reads are intentional during CheckTx, standardize and document that policy across all such transformations.
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The protocol-15 implementation preserves historical behavior, uses dedicated versioned generations, keeps escrow and history accounting consistent, and carries pending batch operations through both application and raw conversion paths. One in-scope performance/security concern remains: approximate CheckTx transformation performs a stateful query and decodes up to 16 attacker-selected listings before authorization is validated, allowing repeated mempool read amplification without admission-time charging.
🟡 1 suggestion(s)
1 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
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:
criticalbygpt-6.1-sol(effort low) — This is a large, intricate change to consensus-critical token destruction and escrow deletion logic that directly changes funds movement, supply accounting, storage operations, and protocol-versioned state-transition behavior. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:344-371: Avoid stateful frozen-listing reads during CheckTx cost approximation
(existing thread: https://github.com/dashpay/platform/pull/5532#discussion_r4372880155)
`read_frozen_listings` does not receive `approximate_without_state_for_costs` and unconditionally calls `fetch_frozen_token_listings`. The v0 query uses `dry_run = false`, traverses the `byOwner` index, and materializes up to 16 `TokenOrder` documents. Both transformer entry points already use approximation for the balance read, but this newly added multi-document read remains stateful and runs before the destroy action's full authorization and frozen-account state validation. A correctly signed transition with a valid nonce and token contract can therefore make nodes perform this bounded RocksDB and deserialization work for arbitrary token and identity IDs even when the destroy is later rejected; repeated funded nonce submissions can amplify the work without CheckTx charging or enforcing an equivalent aggregate budget. The fact that fill, cancel, and group transformations have similar reads supports a broader policy fix, but it does not remove the additional 16-document read introduced here. Thread the approximation mode into this helper and use a deterministic conservative/stateless estimate for the admission path, or land a tracked shared policy that gives these pre-authorization reads equivalent resource protection while retaining the actual query during authoritative block execution.
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The protocol-15 frozen-listing destruction implementation is correctly version-gated, preserves historical behavior, and the previously identified batch-lowering, history, escrow, and regression issues are fixed at the reviewed head. Two non-blocking concerns remain: CheckTx performs a stateful range query and decodes up to 16 listings before authorization, and the PR does not document the introduced public Rust API break. The supplied CI snapshot shows successful Kotlin SDK and book checks, with no Rust code-check result present.
🟡 2 suggestion(s)
1 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
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:
criticalbygpt-6.1-sol(effort low) — This is a large consensus-critical change to token destruction and escrowed funds movement, including protocol-version dispatch, state-transition serialization, and persistent document/storage operations. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-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-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_transition.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_transition.rs:172-175: Document the breaking public Drive API change
`TokenTransitionAction::associated_token_event` was a public method returning `TokenEvent`; it now requires `&PlatformVersion` and returns `Result<TokenEvent, Error>`, so external `drive` consumers no longer compile. The same PR also adds required public fields to `TokenDestroyFrozenFundsTransitionActionV0`, breaking external struct literals. The PR's Breaking Changes section describes only the protocol consensus change, while the repository's Unreleased changelog explicitly records other breaking Rust APIs. Add a breaking Rust API entry with the release/semver impact, or preserve source compatibility with an additive platform-version-aware method and compatibility wrapper.
In `packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:344-371: Avoid stateful frozen-listing reads during CheckTx cost approximation
(existing thread: https://github.com/dashpay/platform/pull/5532#discussion_r4372880155)
`transform_token_transition_v0` derives `approximate_for_costs` from `!validate_against_state` and passes it through the destroy transformer, but `read_frozen_listings` ignores it and always calls `fetch_frozen_token_listings`. That query uses `query_documents(..., false, ...)` and materializes up to 16 `TokenOrder` documents. Ordinary Batch CheckTx transformation does not run the destroy transition's full state authorization before this read, so a correctly signed, nonce-valid, funded transition targeting an existing token balance can cause a bounded index scan and document decode before the block later rejects an unauthorized or non-frozen target. The sibling marketplace reads do not eliminate this newly added amplification: they generally perform one primary-key lookup, whereas this path performs an owner-index range query with up to 16 decodes. Do not simply skip the read and understate the eventual delete cost; establish a shared CheckTx policy for marketplace and group reads, using a deterministic conservative estimate for the maximum bounded work while deferring materialization until stateful execution.
…rozen-escrow # Conflicts: # packages/rs-drive/src/util/batch/drive_op_batch/drive_methods/apply_drive_operations/v2/mod.rs # packages/rs-platform-version/src/version/drive_versions/v10.rs
thepastaclaw
left a comment
There was a problem hiding this comment.
Re-review — Final validation — Phase 1 + Phase 2
The protocol-15 frozen-listing destruction behavior is correctly version-gated, and the pending-aware batch lowering, history calculation, escrow handling, and regression coverage are in place. Two suggestions remain: the public Drive API breaking-changes section omits the new public DeleteDocuments enum variant, and CheckTx still performs a stateful multi-document listing scan before authorization is evaluated.
🟡 2 suggestion(s)
2 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
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-astra (agent: phase2-reviewer, role: general); reviewer 9: gpt-6-astra (agent: phase2-reviewer, role: architecture-layering); reviewer 10: gpt-6.1-sol (agent: phase2-reviewer, role: general); reviewer 11: gpt-6.1-sol (agent: phase2-reviewer, role: architecture-layering); reviewer 12: gpt-6.1-sol (agent: phase2-reviewer, role: platform-versioning); reviewer 13: gpt-6.1-sol (agent: phase2-reviewer, role: rust-quality); reviewer 14: gpt-6.1-sol (agent: phase2-reviewer, role: security-auditor); final verifier: gpt-6.1-sol (agent: sol-verifier, role: final-verifier)
- Triage:
criticalbygpt-6.1-sol(effort low) — This is a large, intricate change to consensus-critical token destruction, escrowed funds movement, supply accounting, document deletion, and protocol-versioned Drive state-transition behavior, including packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_destroy_frozen_funds_transition/v1/mod.rs and apply_drive_operations/v2/mod.rs. - Phase 1 reviewers:
muse-spark-1.3-contributor— general (completed, effort xhigh); agentphase1-reviewer,muse-spark-1.3-contributor— rust-quality (completed, effort xhigh); agentphase1-reviewer - Phase 1 model:
muse-spark-1.3-contributor— not quota-gated; passed overgemini-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; agentsol-verifier - Phase 2 reviewers:
gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— general (completed, effort xhigh); agentphase2-reviewer,gpt-6-astra— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— general (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— architecture-layering (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— platform-versioning (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— rust-quality (completed, effort xhigh); agentphase2-reviewer,gpt-6.1-sol— security-auditor (completed, effort xhigh); agentphase2-reviewer - Model comparison: every Phase-2 reviewer also ran on
gpt-6-astra; the verifier weighed both sets without knowing which model wrote which
🤖 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-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_transition.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/token/token_transition.rs:172-175: Document the breaking public Drive API change
(existing thread: https://github.com/dashpay/platform/pull/5532#discussion_r4380802922)
The PR description documents the changed `associated_token_event` signature and the new public fields on `TokenDestroyFrozenFundsTransitionActionV0`, but it does not mention the newly public and re-exported `DocumentOperationType::DeleteDocuments` variant. Adding a variant can break exhaustive matches in downstream `drive` consumers, so include it in the Rust API breaking-changes section and explain that downstream matches must be updated.
In `packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs`:
- [SUGGESTION] packages/rs-drive/src/state_transition_action/batch/batched_transition/token_transition/token_destroy_frozen_funds_transition_action/v0/transformer.rs:344-372: Avoid stateful frozen-listing reads during CheckTx cost approximation
(existing thread: https://github.com/dashpay/platform/pull/5532#discussion_r4372880155)
`read_frozen_listings` unconditionally calls `fetch_frozen_token_listings`, whose implementation performs a real indexed query and decodes up to 16 documents. Ordinary batch CheckTx transformation passes `approximate_without_state_for_costs = true`, while destroy authorization and frozen-account state validation occur later, so a correctly signed and funded transition can trigger this by-owner scan for arbitrary token and identity IDs before the transition is rejected. The read is bounded, but repeated valid nonces can amplify RocksDB traversal and document decoding without charging or committing the rejected transition. Thread the approximation mode through this helper and use a deterministic stateless layer-cost estimate during CheckTx/recheck, or establish a single tracked policy for pre-authorization marketplace reads while retaining exact listing resolution for authoritative execution.
Basic explanation
What this does: Closes a loophole the marketplace opened in freezing. A token issuer can freeze an account and then destroy the frozen funds. But tokens an account has listed for sale sit in escrow, not in its balance, so until now they escaped the destroy. From protocol version 15 destroying frozen funds also destroys what the frozen account's open listings hold, and deletes those listings.
Value: Freezing and destroying keep working as issuers expect: someone holding stolen or sanctioned tokens cannot shield them from destruction by listing them before the freeze lands.
Risks: Low-medium. A destroy at protocol version 15 reads the frozen account's listings (a small extra read, charged) and, when there are any, destroys at most 16 per transition, oldest first, so its work stays bounded. Before 15 nothing changes: the read and the new conversion are selected only by protocol version 15's tables, and the previous conversion's operations are byte-for-byte the same. The account's offers hold credits, not tokens, and are left alone.
Issue being fixed or feature implemented
The sixth PR of the token marketplace stack (PV15), on top of #5531 (history). A frozen account's listings cannot be filled (the listing PR refuses fills of a frozen maker), but nothing could remove the tokens they hold short of the account cancelling them itself.
What was done?
DriveTokenOrderEscrowMethodVersions.fetch_frozen_listings,Nonebefore 15,Some(0)inDRIVE_TOKEN_METHOD_VERSIONS_V3):Drive::fetch_frozen_token_listingsreads the frozen identity's openaskdocuments of the token through thebyOwnerindex ($ownerId,tokenId,$createdAt), oldest first, at mostSystemLimits::max_frozen_listings_destroyed_per_transition(16). WithNoneit reads nothing. The transformer always calls it and bills the read.TokenDestroyFrozenFundsTransitionActionV0carries the listings and, when there are any, the token market contract for deleting their documents.token_destroy_frozen_funds_transition1, in the newDRIVE_STATE_TRANSITION_METHOD_VERSIONS_V5thatDRIVE_VERSION_V10selects), its own implementation beside generation 0's: with listings, one new opTokenDestroyFrozenHoldingburns the balance, removes each listing's escrow and lowers the supply once by the total (so the repeated-write guard sees each key once); one new document opDeleteDocumentsdeletes the listings'askdocuments, each delete built against the ones before it so index trees the listings share (a price bucket, a$createdAtbucket, the owner's bucket) are removed and refunded to whoever paid for them; the history and group-action events record the total. Without listings it emits generation 0's operations.read_frozen_listings.apply_drive_operations2, the protocol 15 generation from feat(platform)!: token marketplace escrow trees and token market contract (PV15) #5526, extended in place as it is unreleased): every operation of a batch is built against the operations of its GroveDB batch built before it and appended to them (DriveOperation::append_low_level_drive_operations_after_ttl_drain). A document insert, update or deletion therefore sees the batch's earlier writes as pending: one batch destroying a frozen identity's listings of two tokens removes the owner's sharedbyOwnerbucket and refunds it, and an insert into a tree an earlier deletion of the batch empties keeps the tree. Grouped document operations (MultipleDocumentOperationsForSameContractDocumentType) are built the same way. This is the latent defectbatched_group_drainandSystemLimits::max_transitions_in_documents_batchdocument (unreachable through a transition while that cap is 1): its five specification cases,#[ignore]d until now, run and pass at the latest version, and the phantom-group characterization is pinned to protocol version 14. Protocol version 14 and earlier keep generation 1.max_frozen_listings_destroyed_per_transition= 16 in everySystemLimitstable; only 15's code reads it. More listings need one more destroy each 16.How Has This Been Tested?
cargo test -p drive-abci --lib -- batch::tests::token::marketplace::frozen:destroyedAmount10,000 recorded;cargo test -p drive-abci --lib -- destroy_frozen_funds batch::tests::token perform_events_on_first_block_of_protocol_change(every existing destroy test now goes through generation 1 with no listings).cargo test -p drive --lib -- verify::state_transition drive_op_batch state_transition_action::batch order_escrow;cargo test -p platform-version.Review round 1:
marketplace::frozen::should_remove_and_refund_the_index_trees_destroyed_listings_shared: two listings at one price in one block, which share index buckets: the 24asktrees and items they make shrink, after the destroy, to the same 3 that cancelling the two one by one leaves, and the frozen owner's refund is at least what those cancels refund (the destroy also shrinks the burned balance item). With the listings deleted as separateDeleteDocuments, 16 trees stayed and the refund was about half;DeleteDocumentsof both listings in order and the history of everything destroyed;fetch_order::tests: at protocol version 14, on a chain without marketplace state, the listing read returns none at zero cost.Review round 2,
apply_drive_operations::v2::tests::batch_document_writes:asktrees that deleting them in two batches leaves, with no tree keyed by the owner;cargo clippyon platform-version, drive, drive-abci.Review round 3:
batched_group_drain: the five drain specifications (two deletes in either order, under the shipped batching config, batched against sequential, a two-document move) run un-ignored at the latest version;a_batched_drain_leaves_a_phantom_group_that_verifies_and_provesapplies its batch at protocol version 14 and still finds the phantom;batch_document_writes::should_insert_through_a_group_into_a_tree_an_earlier_deletion_empties: a deletion and a grouped insert into the same bucket apply and leave the new document's trees alone (it failed with an insertion order error when grouped operations started a fresh accumulator);In-place changes to shipped generations
SystemLimitsV1 to V4 andDriveTokenOrderEscrowMethodVersionsinDRIVE_TOKEN_METHOD_VERSIONS_V1gain a field (max_frozen_listings_destroyed_per_transition,fetch_frozen_listings: None) that nothing before protocol version 15 reads.TokenDestroyFrozenFundsTransitionActionV0(in memory, never serialized) gains two fields, empty andNonebefore 15.Breaking Changes
Consensus, from protocol version 15:
TokenDestroyFrozenFundsalso destroys the frozen identity's escrowed listings and reads them first. Earlier protocol versions are unchanged.Rust API of the
drivecrate (source-breaking for code that builds or reads these actions itself):TokenTransitionAction::associated_token_eventtakes&PlatformVersionand returnsResult<TokenEvent, Error>, because the destroy event's amount now comes from a versioned calculation (the frozen balance alone before protocol version 15, plus the escrowed listings from 15). A caller passes the platform version and handles the error.TokenDestroyFrozenFundsTransitionActionV0gains the public fieldsescrowed_listings: Vec<TokenOrder>andtoken_market_contract: Option<Arc<DataContractFetchInfo>>. A struct literal sets them to an emptyVecandNonebefore protocol version 15; the transformer fills them from 15.DocumentOperationTypegains the public variantDeleteDocuments { document_ids, contract_info, document_type_info }, which deletes several documents of one type in one conversion (the destroy uses it for the listings'askdocuments). The enum is not#[non_exhaustive], so a downstream exhaustivematchon it needs a new arm.Checklist:
structure.rs, regeneratedgrovedb-structure.json, and checked the structure viewer link posted on this pull requestFor repository code-owners and collaborators only
🤖 Generated with Claude Code