feat(platform)!: a document batch proof carries the owner's credit balance - #4887
QuantumExplorer wants to merge 5 commits into
Conversation
…lance A document batch's waitForStateTransitionResult proof proved only the document, so a wallet had to query the balance again after every write (the post-DPNS refresh in #4799). The prover now merges the owner's balance into the document proof, for stored and indexOnly types, and the verifier reads the document and the balance as subsets of that proof from one root hash. `StateTransitionProofResult::VerifiedDocuments` carries the balance next to the documents; the execution-proved tag is unchanged, the balance is a snapshot at the proof's block. A wait that asks for no proof reports the same balance unverified in the new `owner_balance` field of the response: rs-dapi reads it from Drive for a document batch, with the metadata of that read. rs-sdk exposes it through `wait_for_document_and_owner_balance` and `put_to_platform_and_wait_for_response_with_owner_balance`; wasm-dpp2, wasm-drive-verify, wasm-sdk and js-dapi-client hand it out as well. Old clients verify the document strictly and reject the merged proof, so proved document writes against a 4.2 node need 4.2 clients. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Understand this PR’s impact Explore downstream dependencies and potential security impact with Blast Radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: dashpay/platform/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (17)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe change adds owner balances to document-batch proofs from protocol version 14 and adds optional unproved balance responses for wait requests. It updates Drive proof processing, DAPI and generated protobuf bindings, SDK and WASM APIs, tests, and documentation. ChangesOwner balance propagation
Priority: ➖ Normal Estimated code review effort: 5 (Critical) | ~90 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant SDK
participant DAPI
participant Drive
participant ProofResult
SDK->>DAPI: wait with prove or requestUserBalance
DAPI->>Drive: fetch proof or unproved owner balance
Drive-->>DAPI: return proof or balance
DAPI-->>SDK: return transition result
SDK-->>ProofResult: expose optional owner balance
Suggested reviewers: Merge Risk: ⚪ Minimal · up to No actionable compatibility defect remains; the change is mergeable after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 78.38% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 74 functions across 37 files. (9 skipped: 3 unsupported, 6 too large.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
📖 Book Preview built successfully. Download the preview from the workflow artifacts. Updated at 2026-09-21T19:01:51.773Z |
|
PR Hygiene: the checklist is in the description. |
|
|
Regenerated the dapi-grpc clients from the merged proto: the python client conflicted only in its serialized descriptor. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…tegy harness The harness verified a batch's document strictly, which rejects the merged proof that now also carries the owner's balance. Verify the document as a subset and check the owner's balance from the same proof against the stored one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Review fix-ups for the document batch owner-balance proof: - The merged document+balance proof is prove_state_transition v1 and verify_state_transition_was_executed_with_proof v1, selected only by PV14's drive tables; v0 keeps the document-only proof, so the client break aligns with the activation rather than the binary upgrade. `VerifiedDocuments` carries `Option<Credits>`: `None` for a proof made at an earlier version. - The verifier verifies the prover's merged query strictly once instead of parsing the proof twice as subsets; a proof without the balance is rejected by that one verification, and the negative tests pin the error kind while showing the document part verifies on its own. - rs-dapi reports the unproved balance only from a Drive state at or past the block that executed the transition. - wasm-sdk reports an unproved success as SUCCESS whether or not a balance came back. - The new PutDocument method is provided, not required. - Keeps-history and contested creates are proven and verified in tests. - wasm-dpp2 imports the JSON normaliser at the top of the file. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The unproved balance is no longer a loose field on the wait response: `WaitForStateTransitionResultRequestV0.request_user_balance` asks for it, and the answer is the `unproved_with_owner_balance` member of the result oneof (an `UnprovedResultWithOwnerBalance` with the balance), so a response is exactly one of an error, a proof, or the unproved balance. It works for any transition with an owner. rs-dapi reads the balance from Drive only when asked and only from a state at or past the block that executed the transition. The Rust SDK keeps proving, so it never sets the flag (a document batch's proof carries the balance from protocol version 14); the wasm SDK's raw wait sets it whenever it does not prove; js-dapi-client takes a `requestUserBalance` option. Generated clients regenerated. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Issue being fixed or feature implemented
A state transition's
waitForStateTransitionResultanswer gave the new credit balance back only for identity-money transitions (top-up, withdrawal, credit transfer, fee claim). A document batch proved only the document, so a wallet had to query the balance again after every write: the post-DPNS balance refresh that #4799 adds exists for that reason. This makes the batch proof, and the unproved wait, report the owner's balance.What was done?
prove_state_transition(new version 1, selected by PV14's drive tables) merges the owner's balance query into the document path query, for stored and indexOnly document types; version 0 keeps the document-only proof. The verifier (new version 1) rebuilds the merged query and verifies it strictly once; version 0 verifies the document alone.StateTransitionProofResult::VerifiedDocumentsbecomesVerifiedDocuments(documents, Option<Credits>):Somefrom PV14,Nonefor a proof made at an earlier version. TheExecutionProved/AffectedStatetag is unchanged: the document binds the execution, the balance is a snapshot at the proof's block and may already include later transitions of the same identity.WaitForStateTransitionResultRequestV0gainsbool request_user_balance = 3; the response'sresultoneof gainsUnprovedResultWithOwnerBalance unproved_with_owner_balance = 4(owner_balanceasuint64,JS_STRING), so a response is exactly one of an error, a proof, or the unproved balance. rs-dapi answers with it only when the flag is set and no proof was requested, for any transition with an owner, from an unprovedgetIdentityBalanceread of Drive whose state is at or past the block that executed the transition, and sets the responsemetadatafrom that read; a failed or stale read is logged and skipped like a failed proof fetch. A proved wait carries the balance inside the proof. Generated clients regenerated. The legacy JS DAPI inpackages/dapiis untouched.wait_for_document_and_owner_balanceand the providedPutDocument::put_to_platform_and_wait_for_response_with_owner_balanceare additive and return(Document, Option<Credits>); the typedDocument*Resultenums keep their shape; the SDK keeps proving and never sets the request flag. wasm-dpp2VerifiedDocuments.ownerBalance(BigInt orundefined; a number in JSON while exact, a decimal string pastMAX_SAFE_INTEGER,nullwhen absent), wasm-drive-verifyownerBalance, wasm-sdkStateTransitionResult.ownerBalance(its raw wait sets the flag whenever it does not prove, and reports an unproved success as SUCCESS), js-dapi-clientgetOwnerBalance()with arequestUserBalanceoption.How Has This Been Tested?
verify_batch_document_create_happy_pathandverify_batch_document_delete_happy_pathnow prove throughprove_state_transitionand assert the balance; newverify_batch_document_proof_without_owner_balance_is_rejectedpins that a document-only proof verifies the document alone but not the batch at version 1.document::owner_balance_prooftests execute a dashpay profile create, replace and delete, a keeps-history create and replace, and a contested (prefunded) DPNS create, and check each proof's balance against the stored balance; a proof made for another owner's batch is rejected while its document part verifies on its own.test_executed_index_only_create_and_delete_proofsasserts the balance for indexOnly entries. The strategy-test harness verifies the balance from prover version 1 on.transition_owner_idunit tests (document batch, credit transfer, undecodable bytes). rs-dpp: JSON shape test for the two-field variant with a balance pastMAX_SAFE_INTEGERand for theNonecase. js-dapi-client: wait-factory spec coversrequestUserBalanceandgetOwnerBalance(). wasm-dpp2ProofResult.spec.tsupdated (not run locally: needs a wasm build).cargo clippy --tests -D warningsover dpp, drive, drive-proof-verifier, dash-sdk, rs-dapi and drive-abci;cargo fmt --check; wasm-dpp2, wasm-drive-verify and wasm-sdk compile onwasm32-unknown-unknown. Not run: platform-test-suite e2e, Swift and Kotlin builds.Breaking Changes
StateTransitionProofResult::VerifiedDocumentshas a second field (Option<Credits>); every consumer matching it changes. JSON shape becomes{"VerifiedDocuments": [documents, balance-or-null]}.WaitForStateTransitionResultResponseV0.resultgains a third member; a client that treats "no error, no proof" as success keeps working.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
PR Hygiene ·
3a7b703/skip-botsproceeds without the ones not yet reported/self-reviewedonce the bots are donerust-dapi(packages/rs-dapi/src/services/platform_service/wait_for_state_transition_result.rs) — lklimek or shumkovdpp— you own itrs-drive-abci— you own itrs-drive— you own itrust-sdk(packages/rs-sdk/src/platform/documents/transitions/create.rs,packages/rs-sdk/src/platform/documents/transitions/delete.rs,packages/rs-sdk/src/platform/documents/transitions/purchase.rsand 7 more) — lklimek or shumkovjs-wasm-sdk(packages/wasm-sdk/src/queries/system.rs) — shumkovWhen every box is checked the
PR Hygienecheck passes and this can merge.Summary by CodeRabbit
New Features
Compatibility