Skip to content

feat(platform)!: document history system contract with per-doctype opt-in#4171

Merged
QuantumExplorer merged 7 commits into
v4.1-devfrom
claude/document-history-contract
Jul 22, 2026
Merged

feat(platform)!: document history system contract with per-doctype opt-in#4171
QuantumExplorer merged 7 commits into
v4.1-devfrom
claude/document-history-contract

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Jul 20, 2026

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

PR #4145 enabled DPNS username transfers and sales at protocol version 13, but they leave no queryable trace: the domain document is updated in place, overwriting the previous owner, the sale price, and when it happened. More generally, no document type on Platform has any transfer/sale/listing history — even though tokens already solved this exact problem with the TokenHistory system contract and per-token keepsHistory rules.

This PR ports that architecture to documents: a document-history system contract that any document type can subscribe to, with DPNS domain as the first subscriber.

What was done?

New document-history system contract (packages/document-history-contract, SystemDataContract::DocumentHistory = 8) with three document types — transfer, purchase (records seller and the explicit price paid) and priceUpdate. All are creationRestrictionMode: 2 (only the protocol can write them), immutable, and non-deletable. Indices support per-document provenance (dataContractId, documentId, $createdAt), per-contract feeds, per-identity history (buyer/seller/sender/recipient) and price analytics. documentTypeName is recorded as a data field but deliberately not indexed: document type names may be 64 chars while indexed strings cap at 63.

Per-doctype subscription flags in DPP — keepsTransferHistory, keepsPurchaseHistory, keepsPricingHistory — mirroring TokenKeepsHistoryRules. Parsed from the document type schema (default false), whitelisted in the v1 document meta-schema only (they are v13-introduced, so the v11→v12 migration allowlist is untouched, same as documentsCountable), and immutable on contract update like documentsKeepHistory.

History writes in ops conversion — the v1 transfer/purchase arms and a new v1 update-price arm check the source doctype's flags and emit a DocumentOperationType::DocumentHistory op. At apply time drive builds the history document via the new DocumentEvent (rs-dpp), with a deterministic ID derived from the source document, acting identity, and identity contract nonce — every validator produces identical history documents. The acting party (sender / buyer / seller respectively) owns and pays for the record.

DPNS v2 subscribes domain to all three flags (SYSTEM_DATA_CONTRACT_VERSIONS_V2, consumed by PLATFORM_V13), so as of PV13: username transfers record sender→recipient, listings record the asking price, and sales record buyer, seller, and price paid — all queryable through the standard document query path with proofs.

Upgrade and genesistransition_to_version_13 inserts the document-history contract and re-stores DPNS v2 on the first block after upgrade; genesis registers both for new networks. No migration of existing documents is required — the history contract starts empty and the DPNS change is contract-definition-only.

Also fixes a latent copy-paste bug: dpns_contract::load_definitions/load_documents_schemas gated on the withdrawals version field instead of dpns.

How Has This Been Tested?

New drive-abci execution tests (all in batch/tests/document/dpns.rs unless noted):

  • test_dpns_username_transfer now also asserts a transfer history document exists, owned by the sender, pointing at the recipient, timestamped.
  • test_dpns_username_sale now also asserts the priceUpdate record (seller, 0.1 DASH asking price) and the purchase record (buyer-owned, seller identity, explicit price paid) — and that no transfer record exists for a sale.
  • PV12 variants assert nothing is recorded before activation.
  • test_document_transfer_without_history_subscription_records_nothing — a transferable doctype without the flags (crypto card game) records nothing at PV13, proving flag-gating rather than version-gating.
  • test_document_history_contract_direct_writes_rejected — user document creation on the history contract fails with DocumentCreationNotAllowedError.
  • test_transition_to_version_13_inserts_document_history_contract_and_updates_dpns (protocol upgrade tests) — a PV12-born chain upgrading to 13 gains the history contract and a stored DPNS v2 whose domain doctype reports all three flags.

Full runs: all 3789 dpp tests, all 102 drive-abci document batch tests (includes NFT update-price/purchase flows with pinned fee constants — the new v1 update-price arm is behavior-identical for unsubscribed doctypes), all 14 protocol-upgrade tests, cargo check --workspace --all-targets, clippy clean on all touched crates, cargo check -p drive --no-default-features --features verify.

Breaking Changes

Consensus-breaking at protocol version 13 activation (extends the PV13 changes from #4145): nodes without this change would neither register the document-history contract nor write history documents, diverging in app hash from nodes that do. No behavior change for protocol versions ≤ 12. The seller-balance economics pinned in #4145's tests are unchanged — the buyer pays for the purchase history record.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added a Document History system contract recording transfer, purchase, and price-update events.
    • Document types can independently enable history for transfers, purchases, and pricing changes.
    • Added protocol version 13 support, including automatic contract activation and migration.
    • DPNS domain transfers and sales now update ownership records and generate applicable history entries.
    • Added schema validation for history records and expanded document meta-schema support.
  • Documentation

    • Added documentation describing history record types, immutability, and protocol-managed creation.
  • Tests

    • Added coverage for valid history records, invalid data, transfers, sales, and protocol compatibility.

@github-actions github-actions Bot added this to the v4.1.0 milestone Jul 20, 2026
@thepastaclaw

thepastaclaw commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

🕓 Ready for review — next in queue (commit 0753175)
Queue position: 1/72 · 2 reviews active
ETA: start ~19:45 UTC · complete ~20:13 UTC (median 28m across 30 recent reviews; 2 slots)
Queued 1d 6h ago · Last checked: 2026-07-22 19:40 UTC

@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@QuantumExplorer, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e6ac9f0-8e7a-44ed-80b8-e07ffbce6f4c

📥 Commits

Reviewing files that changed from the base of the PR and between 31b4f83 and 0753175.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (21)
  • Cargo.toml
  • package.json
  • packages/data-contracts/Cargo.toml
  • packages/data-contracts/src/error.rs
  • packages/data-contracts/src/lib.rs
  • packages/document-history-contract/.mocharc.yml
  • packages/document-history-contract/Cargo.toml
  • packages/document-history-contract/LICENSE
  • packages/document-history-contract/README.md
  • packages/document-history-contract/eslint.config.mjs
  • packages/document-history-contract/lib/systemIds.js
  • packages/document-history-contract/package.json
  • packages/document-history-contract/schema/v1/document-history-contract-documents.json
  • packages/document-history-contract/src/error.rs
  • packages/document-history-contract/src/lib.rs
  • packages/document-history-contract/src/v1/mod.rs
  • packages/document-history-contract/test/bootstrap.js
  • packages/document-history-contract/test/unit/documentHistoryContract.spec.js
  • packages/dpns-contract/schema/v2/dpns-contract-documents.json
  • packages/dpns-contract/src/lib.rs
  • packages/dpns-contract/src/v2/mod.rs
📝 Walkthrough

Walkthrough

Adds the DocumentHistory system contract, per-event retention settings, protocol 13 version wiring, DPNS v2 support, Drive history operations, and integration tests for transfer, purchase, pricing, migration, and rejection behavior.

Changes

Document-history contract package

Layer / File(s) Summary
Contract package and schemas
Cargo.toml, package.json, packages/document-history-contract/...
Adds the Rust and JavaScript package, contract identifiers, versioned loaders, transfer/purchase/price-update schemas, test setup, and schema validation tests.

System contract registration and availability

Layer / File(s) Summary
System contract wiring
packages/data-contracts/..., packages/rs-dpp/Cargo.toml, packages/rs-dpp/src/system_data_contracts.rs, packages/rs-drive/src/cache/..., packages/rs-drive-abci/..., packages/rs-sdk*/*
Registers SystemDataContract::DocumentHistory, adds feature propagation, loads the cached contract with protocol activation at 13, and inserts it during genesis or protocol upgrade paths.

History configuration and document model

Layer / File(s) Summary
History flags, schemas, and events
packages/rs-dpp/schema/meta_schemas/document/v2/..., packages/rs-dpp/src/data_contract/document_type/..., packages/rs-dpp/src/document/...
Adds transfer, purchase, and pricing retention flags to document schemas and versioned document types, exposes accessors and immutable update validation, and defines DocumentEvent historical document construction.

DPNS and protocol 13 support

Layer / File(s) Summary
Versioned protocol configuration
packages/dpns-contract/..., packages/rs-platform-version/..., packages/rs-drive-abci/.../data_triggers/...
Adds DPNS v2 schema loading, protocol 13 drive and validation versions, system-contract version mappings, and version 1 data-trigger bindings.

History operation execution

Layer / File(s) Summary
Transition-to-storage flow and validation
packages/rs-drive/src/drive/document/insert/..., packages/rs-drive/src/state_transition_action/..., packages/rs-drive/src/util/batch/..., packages/rs-drive-abci/.../tests/document/dpns.rs
Emits history operations for configured transfer, purchase, and price-update transitions, rewrites DPNS ownership records, inserts immutable history documents, and tests protocol gating, subscriptions, direct-write rejection, and existing replace/delete rejection.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DocumentTransition
  participant DocumentEvent
  participant Drive
  participant DocumentHistoryContract
  DocumentTransition->>DocumentEvent: create event payload
  DocumentEvent->>DocumentHistoryContract: resolve event document type
  DocumentEvent-->>Drive: build historical document
  Drive->>DocumentHistoryContract: insert history document
Loading

Possibly related PRs

Suggested labels: ready for final review

Suggested reviewers: shumkov, lklimek

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: a new platform document-history system contract with per-doctype opt-in.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/document-history-contract

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/rs-dpp/src/document/document_event.rs (1)

53-59: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Redundant Ok(...?) — clippy::needless_question_mark.

document_type_for_name already returns the exact Result<DocumentTypeRef, ProtocolError> this function returns, so wrapping it in Ok(...?) triggers clippy's needless_question_mark lint.

As per coding guidelines, packages/**/*.rs should "follow rustfmt defaults, keep code clippy-clean."

♻️ Proposed fix
     pub fn associated_document_type<'a>(
         &self,
         document_history_contract: &'a DataContract,
     ) -> Result<DocumentTypeRef<'a>, ProtocolError> {
-        Ok(document_history_contract
-            .document_type_for_name(self.associated_document_type_name())?)
+        document_history_contract.document_type_for_name(self.associated_document_type_name())
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rs-dpp/src/document/document_event.rs` around lines 53 - 59, Update
associated_document_type to return
document_history_contract.document_type_for_name(self.associated_document_type_name())
directly, removing the redundant Ok wrapper and question-mark operator while
preserving the existing Result<DocumentTypeRef, ProtocolError> behavior.

Source: Coding guidelines

packages/document-history-contract/test/unit/documentHistoryContract.spec.js (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer kebab-case filenames.

As per coding guidelines, JavaScript packages should prefer kebab-case filenames. Consider renaming this file to document-history-contract.spec.js.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/document-history-contract/test/unit/documentHistoryContract.spec.js`
at line 1, Rename the test file from its camelCase filename to the kebab-case
name document-history-contract.spec.js, updating any references to the existing
filename as needed.

Source: Coding guidelines

packages/document-history-contract/lib/systemIds.js (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer kebab-case filenames.

As per coding guidelines, JavaScript packages should prefer kebab-case filenames. Consider renaming this file to system-ids.js.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/document-history-contract/lib/systemIds.js` at line 1, Rename the
JavaScript file from systemIds.js to system-ids.js, and update all imports,
requires, and package references to use the new kebab-case filename while
preserving the module’s existing exports.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs`:
- Around line 112-117: Update the price extraction in the document update
transition to propagate missing or undecodable PRICE values instead of
converting them to a default zero. Replace the ok/flatten/default chain with the
surrounding error-return convention, ensuring the pricing-history record is not
persisted unless a valid Credits value is present.

---

Nitpick comments:
In `@packages/document-history-contract/lib/systemIds.js`:
- Line 1: Rename the JavaScript file from systemIds.js to system-ids.js, and
update all imports, requires, and package references to use the new kebab-case
filename while preserving the module’s existing exports.

In
`@packages/document-history-contract/test/unit/documentHistoryContract.spec.js`:
- Line 1: Rename the test file from its camelCase filename to the kebab-case
name document-history-contract.spec.js, updating any references to the existing
filename as needed.

In `@packages/rs-dpp/src/document/document_event.rs`:
- Around line 53-59: Update associated_document_type to return
document_history_contract.document_type_for_name(self.associated_document_type_name())
directly, removing the redundant Ok wrapper and question-mark operator while
preserving the existing Result<DocumentTypeRef, ProtocolError> behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c11fa015-59bf-4ad6-99a8-56c66e1d2b93

📥 Commits

Reviewing files that changed from the base of the PR and between c311c7e and 3140db0.

⛔ Files ignored due to path filters (2)
  • Cargo.lock is excluded by !**/*.lock
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (68)
  • Cargo.toml
  • package.json
  • packages/data-contracts/Cargo.toml
  • packages/data-contracts/src/error.rs
  • packages/data-contracts/src/lib.rs
  • packages/document-history-contract/.mocharc.yml
  • packages/document-history-contract/Cargo.toml
  • packages/document-history-contract/LICENSE
  • packages/document-history-contract/README.md
  • packages/document-history-contract/eslint.config.mjs
  • packages/document-history-contract/lib/systemIds.js
  • packages/document-history-contract/package.json
  • packages/document-history-contract/schema/v1/document-history-contract-documents.json
  • packages/document-history-contract/src/error.rs
  • packages/document-history-contract/src/lib.rs
  • packages/document-history-contract/src/v1/mod.rs
  • packages/document-history-contract/test/bootstrap.js
  • packages/document-history-contract/test/unit/documentHistoryContract.spec.js
  • packages/dpns-contract/schema/v2/dpns-contract-documents.json
  • packages/dpns-contract/src/lib.rs
  • packages/dpns-contract/src/v1/mod.rs
  • packages/dpns-contract/src/v2/mod.rs
  • packages/rs-dpp/Cargo.toml
  • packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json
  • packages/rs-dpp/src/data_contract/document_type/accessors/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/accessors/v0/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/methods/validate_update/v0/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/v0/accessors.rs
  • packages/rs-dpp/src/data_contract/document_type/v0/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/v0/random_document_type.rs
  • packages/rs-dpp/src/data_contract/document_type/v1/accessors.rs
  • packages/rs-dpp/src/data_contract/document_type/v1/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/v2/accessors.rs
  • packages/rs-dpp/src/data_contract/document_type/v2/mod.rs
  • packages/rs-dpp/src/document/document_event.rs
  • packages/rs-dpp/src/document/mod.rs
  • packages/rs-dpp/src/system_data_contracts.rs
  • packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs
  • packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/bindings/list/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/data_triggers/bindings/list/v1/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs
  • packages/rs-drive/src/cache/system_contracts.rs
  • packages/rs-drive/src/drive/document/insert/add_history_operations/mod.rs
  • packages/rs-drive/src/drive/document/insert/add_history_operations/v0/mod.rs
  • packages/rs-drive/src/drive/document/insert/mod.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_purchase_transition.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_transfer_transition.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/mod.rs
  • packages/rs-drive/src/util/batch/drive_op_batch/document.rs
  • packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs
  • packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v9.rs
  • packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/mod.rs
  • packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v1.rs
  • packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v2.rs
  • packages/rs-platform-version/src/version/drive_versions/drive_document_method_versions/v3.rs
  • packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/mod.rs
  • packages/rs-platform-version/src/version/drive_versions/drive_state_transition_method_versions/v3.rs
  • packages/rs-platform-version/src/version/drive_versions/mod.rs
  • packages/rs-platform-version/src/version/drive_versions/v8.rs
  • packages/rs-platform-version/src/version/system_data_contract_versions/mod.rs
  • packages/rs-platform-version/src/version/system_data_contract_versions/v1.rs
  • packages/rs-platform-version/src/version/system_data_contract_versions/v2.rs
  • packages/rs-platform-version/src/version/v13.rs

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preliminary review — Codex only

The document-history implementation follows the existing system-contract architecture, but three PV13 changes alter consensus-visible behavior under protocol version 12: schema validation accepts the new flags, shared genesis inserts the contract, and the system-contract cache exposes it before activation. The C/Swift trusted context provider also lacks the feature plumbing needed to resolve the new contract through contract-ID-based document APIs.

Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (failed), gpt-5.6-sol — security-auditor (failed), gpt-5.6-sol — rust-quality (failed), gpt-5.6-sol — ffi-engineer (failed), gpt-5.6-sol — general (failed), gpt-5.6-sol — security-auditor (failed), gpt-5.6-sol — rust-quality (unparseable_transport_capture), gpt-5.6-sol — ffi-engineer (unparseable_transport_capture), gpt-5.6-sol — ffi-engineer (failed), gpt-5.6-sol — general (completed), gpt-5.6-sol — security-auditor (completed), gpt-5.6-sol — rust-quality (completed), gpt-5.6-sol — ffi-engineer (completed)
  • Verifier: gpt-5.6-sol — verifier
  • Sonnet: not run (deferred by blocker gate)

🔴 3 blocking | 🟡 1 suggestion(s)

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json`:
- [BLOCKING] packages/rs-dpp/schema/meta_schemas/document/v1/document-meta.json:497-507: Gate the document-history schema fields to protocol version 13
  The three new properties are added directly to document meta-schema v1. Both PLATFORM_V12 and PLATFORM_V13 select CONTRACT_VERSIONS_V4, whose document_type_schema version is 1, so upgraded validators accept these properties while validating a protocol-version-12 data-contract create. The base revision rejects them because the same v1 schema has additionalProperties=false. During pre-activation deployment, the two binaries can therefore disagree on contract validity in process_proposal. Add a new document meta-schema version selected only by PLATFORM_V13, or introduce equivalent protocol-version gating that leaves PV12 validation unchanged.

In `packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs`:
- [BLOCKING] packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs:59-62: Preserve pre-v13 genesis state
  create_genesis_state_v1 is shared by protocol versions 12 and 13, but this entry registers DocumentHistory unconditionally. A network initialized or historically replayed at PV12 now stores state that the base revision did not, changing its deterministic application hash before the advertised PV13 activation. The upgrade test also starts from a PV12 genesis that already contains the contract, so it does not prove that transition_to_version_13 performs the insertion. Gate registration on protocol_version >= 13 or dispatch PV13 genesis through a new method version, and assert that the contract is absent before the upgrade transition.

In `packages/rs-drive/src/cache/system_contracts.rs`:
- [BLOCKING] packages/rs-drive/src/cache/system_contracts.rs:212-213: Keep the cached contract inactive until protocol version 13
  load_genesis_system_contracts preloads DocumentHistory with active_since_protocol_version set to 13, but find_by_id ignores that field and returns the contract at every protocol version. On an existing PV12 chain where the v13 migration has not inserted the contract into GroveDB, an upgraded node treats this ID as a free, present system contract while the base binary performs a billed lookup and reports it absent. validate_identity_public_key_contract_bounds_v1 uses this path for identity key contract bounds, so the nodes can produce different validation errors and operation costs for the same PV12 transition. Make cache lookup protocol-version-aware and exclude contracts whose activation version is greater than the active platform version.

In `packages/data-contracts/src/lib.rs`:
- [SUGGESTION] packages/data-contracts/src/lib.rs:48: Register DocumentHistory with the C/Swift trusted context provider
  The new SystemDataContract::DocumentHistory variant is not propagated through the rs-sdk and rs-sdk-trusted-context-provider feature lists, and TrustedHttpContextProvider::get_data_contract has no branch that loads it. rs-sdk-ffi enables the existing system-contract features and dash_sdk_create_trusted constructs this provider without a fallback, so dash_sdk_document_fetch_by_contract_id returns "Contract ... not found in trusted context" for the document-history ID. Add a document-history-contract feature through rs-sdk, rs-sdk-trusted-context-provider, and rs-sdk-ffi, include it in all-system-contracts, and load SystemDataContract::DocumentHistory alongside TokenHistory and KeywordSearch.

Comment on lines +497 to +507
"keepsTransferHistory": {
"type": "boolean",
"description": "True if transfers of these documents are recorded in the document history system contract, default is false"
},
"keepsPurchaseHistory": {
"type": "boolean",
"description": "True if purchases of these documents are recorded in the document history system contract, default is false"
},
"keepsPricingHistory": {
"type": "boolean",
"description": "True if price updates on these documents are recorded in the document history system contract, default is false"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: Gate the document-history schema fields to protocol version 13

The three new properties are added directly to document meta-schema v1. Both PLATFORM_V12 and PLATFORM_V13 select CONTRACT_VERSIONS_V4, whose document_type_schema version is 1, so upgraded validators accept these properties while validating a protocol-version-12 data-contract create. The base revision rejects them because the same v1 schema has additionalProperties=false. During pre-activation deployment, the two binaries can therefore disagree on contract validity in process_proposal. Add a new document meta-schema version selected only by PLATFORM_V13, or introduce equivalent protocol-version gating that leaves PV12 validation unchanged.

source: ['codex']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31b4f83 — the three keywords moved to a new document meta-schema v2, selected only by PV13 via CONTRACT_VERSIONS_V5 (document_type_schema: 2). Meta-schema v1 is reverted to its base-revision content, so PV12 contract validation is unchanged and both binaries agree in process_proposal pre-activation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in this update — Gate the document-history schema fields to protocol version 13 no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

Comment on lines +59 to +62
(
SystemDataContract::DocumentHistory,
system_data_contracts.load_document_history(),
),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: Preserve pre-v13 genesis state

create_genesis_state_v1 is shared by protocol versions 12 and 13, but this entry registers DocumentHistory unconditionally. A network initialized or historically replayed at PV12 now stores state that the base revision did not, changing its deterministic application hash before the advertised PV13 activation. The upgrade test also starts from a PV12 genesis that already contains the contract, so it does not prove that transition_to_version_13 performs the insertion. Gate registration on protocol_version >= 13 or dispatch PV13 genesis through a new method version, and assert that the contract is absent before the upgrade transition.

source: ['codex']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31b4f83 — genesis registers DocumentHistory only when protocol_version >= 13, so PV12 genesis/replay app hashes match the base revision. The upgrade test now asserts the contract is absent from the PV12 genesis before running transition_to_version_13, proving the transition performs the insertion. The DPNS PV12-rejection tests likewise now assert the contract does not exist at all pre-activation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in this update — Preserve pre-v13 genesis state no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

Comment on lines +212 to +213
} else if id == SystemDataContract::DocumentHistory.id() {
&self.document_history

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: Keep the cached contract inactive until protocol version 13

load_genesis_system_contracts preloads DocumentHistory with active_since_protocol_version set to 13, but find_by_id ignores that field and returns the contract at every protocol version. On an existing PV12 chain where the v13 migration has not inserted the contract into GroveDB, an upgraded node treats this ID as a free, present system contract while the base binary performs a billed lookup and reports it absent. validate_identity_public_key_contract_bounds_v1 uses this path for identity key contract bounds, so the nodes can produce different validation errors and operation costs for the same PV12 transition. Make cache lookup protocol-version-aware and exclude contracts whose activation version is greater than the active platform version.

source: ['codex']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31b4f83 — find_by_id now takes the current protocol version and returns None for contracts whose active_since_protocol_version is greater, so pre-activation lookups fall through to the billed grovedb fetch and report absent exactly like a non-upgraded node (same validation errors, same operation costs). This also retroactively hardens the TokenHistory/KeywordSearch entries (active since 9), with no behavior change at any released protocol version since the caller (get_system_or_user_contract_with_fee) postdates their activation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in this update — Keep the cached contract inactive until protocol version 13 no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

WalletUtils = 5,
TokenHistory = 6,
KeywordSearch = 7,
DocumentHistory = 8,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Suggestion: Register DocumentHistory with the C/Swift trusted context provider

The new SystemDataContract::DocumentHistory variant is not propagated through the rs-sdk and rs-sdk-trusted-context-provider feature lists, and TrustedHttpContextProvider::get_data_contract has no branch that loads it. rs-sdk-ffi enables the existing system-contract features and dash_sdk_create_trusted constructs this provider without a fallback, so dash_sdk_document_fetch_by_contract_id returns "Contract ... not found in trusted context" for the document-history ID. Add a document-history-contract feature through rs-sdk, rs-sdk-trusted-context-provider, and rs-sdk-ffi, include it in all-system-contracts, and load SystemDataContract::DocumentHistory alongside TokenHistory and KeywordSearch.

source: ['codex']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 31b4f83 — added a document-history-contract feature through rs-sdk, rs-sdk-trusted-context-provider (included in its all-system-contracts umbrella and enabled by rs-sdk-ffi's provider dependency), and a DocumentHistory branch in TrustedHttpContextProvider::get_data_contract alongside TokenHistory and KeywordSearch.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in this update — Register DocumentHistory with the C/Swift trusted context provider no longer present.

Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.

QuantumExplorer and others added 2 commits July 21, 2026 07:55
…t-in

Adds a document-history system contract recording transfer, purchase and
price-update events for document types that subscribe via three new
doctype configuration flags (keepsTransferHistory, keepsPurchaseHistory,
keepsPricingHistory), mirroring the token history architecture. DPNS v2
subscribes the domain document type, so username transfers, sales and
listings become queryable with proofs as of protocol version 13.

- new document-history-contract package: transfer/purchase/priceUpdate
  doctypes, creation-restricted (protocol writes only), immutable and
  permanent, indexed by document, contract, buyer, seller and price
- DocumentEvent in dpp builds deterministic history documents (id derived
  from source document, actor and nonce)
- transfer/purchase/update-price ops conversions emit a DocumentHistory
  op when the doctype subscribed; actor pays for the record
- transition_to_version_13 inserts the new contract and re-stores DPNS
  v2 on upgrade; genesis registers both for new networks
- documentTypeName is a data field, not an index member: doctype names
  may be 64 chars while indexed strings cap at 63
- new flags are immutable on contract update, mirroring
  documentsKeepHistory
- also fixes dpns_contract load fns gating on the withdrawals version
  field instead of dpns

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…version 13

Addresses PR review blockers — three ways an upgraded binary diverged
from the base binary under protocol version 12 before activation:

- document meta-schema v2 (CONTRACT_VERSIONS_V5, PV13 only) now carries
  the keeps*History keywords; meta-schema v1 is reverted so PV12
  contract validation is byte-identical to the base revision
- genesis registers the document history contract only at protocol
  version >= 13, preserving pre-13 genesis app hashes; the upgrade test
  now proves transition_to_version_13 performs the insertion by
  asserting the contract is absent beforehand
- the system-contract cache find_by_id is activation-aware: contracts
  whose active_since_protocol_version exceeds the current protocol
  version fall through to the billed grovedb lookup and report absent,
  matching non-upgraded nodes

Also per review: the pricing-history record now propagates a $price
decode error instead of silently recording a free listing, and the
DocumentHistory contract is plumbed through rs-sdk,
rs-sdk-trusted-context-provider and rs-sdk-ffi so contract-ID document
APIs resolve it in trusted mode.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuantumExplorer
QuantumExplorer force-pushed the claude/document-history-contract branch from 31b4f83 to dada3b9 Compare July 20, 2026 23:56

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/rs-sdk-trusted-context-provider/src/provider.rs (1)

654-662: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

Add document-history-contract to the outer cfg block.

The outer #[cfg(any(...))] macro guards the execution block for all system contracts. Since feature = "document-history-contract" is missing from this list, if a downstream crate compiles the provider with only this specific contract feature enabled (and without all-system-contracts or other contract features), the entire block will be skipped and DocumentHistory will not be resolved.

🐛 Proposed fix
         #[cfg(any(
             feature = "dpns-contract",
             feature = "dashpay-contract",
             feature = "withdrawals-contract",
             feature = "wallet-utils-contract",
             feature = "token-history-contract",
             feature = "keywords-contract",
+            feature = "document-history-contract",
             feature = "all-system-contracts"
         ))]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/rs-sdk-trusted-context-provider/src/provider.rs` around lines 654 -
662, Add feature = "document-history-contract" to the outer #[cfg(any(...))]
guard surrounding the system-contract execution block, preserving the existing
feature entries. Ensure DocumentHistory resolution remains compiled when only
this feature is enabled.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/rs-sdk-trusted-context-provider/src/provider.rs`:
- Around line 654-662: Add feature = "document-history-contract" to the outer
#[cfg(any(...))] guard surrounding the system-contract execution block,
preserving the existing feature entries. Ensure DocumentHistory resolution
remains compiled when only this feature is enabled.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 05613113-2e50-41c2-bd46-664717e369c2

📥 Commits

Reviewing files that changed from the base of the PR and between 3140db0 and 31b4f83.

📒 Files selected for processing (17)
  • packages/rs-dpp/schema/meta_schemas/document/v2/document-meta.json
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs
  • packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v1/mod.rs
  • packages/rs-dpp/src/validation/meta_validators/mod.rs
  • packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs
  • packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs
  • packages/rs-drive/src/cache/system_contracts.rs
  • packages/rs-drive/src/drive/contract/get_fetch/get_system_or_user_contract_with_fee/v0/mod.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/mod.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v5.rs
  • packages/rs-platform-version/src/version/v13.rs
  • packages/rs-sdk-ffi/Cargo.toml
  • packages/rs-sdk-trusted-context-provider/Cargo.toml
  • packages/rs-sdk-trusted-context-provider/src/provider.rs
  • packages/rs-sdk/Cargo.toml
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/rs-drive-abci/src/execution/platform_events/initialization/create_genesis_state/v1/mod.rs
  • packages/rs-platform-version/src/version/v13.rs
  • packages/rs-drive-abci/src/execution/platform_events/protocol_upgrade/perform_events_on_first_block_of_protocol_change/v0/mod.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_update_price_transition.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs

@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 89.11917% with 63 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.47%. Comparing base (033876f) to head (0753175).
⚠️ Report is 5 commits behind head on v4.1-dev.

Files with missing lines Patch % Lines
...ct/document_type/methods/validate_update/v0/mod.rs 25.00% 27 Missing ⚠️
packages/document-history-contract/src/lib.rs 44.44% 10 Missing ⚠️
...batch/document/document_update_price_transition.rs 86.56% 9 Missing ⚠️
...rive/document/insert/add_history_operations/mod.rs 86.84% 5 Missing ⚠️
...events_on_first_block_of_protocol_change/v0/mod.rs 95.69% 4 Missing ⚠️
packages/rs-drive/src/cache/system_contracts.rs 84.00% 4 Missing ⚠️
...ument_type/class_methods/try_from_schema/v0/mod.rs 96.00% 1 Missing ⚠️
...ument_type/class_methods/try_from_schema/v1/mod.rs 98.76% 1 Missing ⚠️
...e/document/insert/add_history_operations/v0/mod.rs 97.56% 1 Missing ⚠️
...rs-drive/src/util/batch/drive_op_batch/document.rs 94.73% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           v4.1-dev    #4171      +/-   ##
============================================
+ Coverage     87.45%   87.47%   +0.02%     
============================================
  Files          2648     2655       +7     
  Lines        334328   334968     +640     
============================================
+ Hits         292373   293018     +645     
+ Misses        41955    41950       -5     
Components Coverage Δ
dpp 88.44% <86.93%> (-0.01%) ⬇️
drive 86.19% <91.48%> (+0.05%) ⬆️
drive-abci 89.58% <96.00%> (+<0.01%) ⬆️
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.90% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 49.66% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…sis state

The PV13 genesis now registers the document history contract and stores
the larger DPNS v2 schema, which changes contracts-subtree node sizes
and therefore the byte-billed contract reads. Two version-pinned
baselines shift by the same 48,640 credits: the token burn group-action
confirmer processing fee and the direct-purchase buyer balance.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuantumExplorer

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Preliminary review — Codex only

Four previously reported activation and FFI-plumbing defects are fixed at the exact head, and the latest delta only updates internally consistent PV13 fee baselines. A consensus-blocking regression remains because historical schema parsers now interpret PV13-only history flags during PV1–PV11 validation and replay. The standalone trusted-context DocumentHistory feature also compiles while its lookup block is excluded.

Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.

Review provenance

  • Codex reviewers: gpt-5.6-sol — unknown role (failed), gpt-5.6-sol — unknown role (failed), gpt-5.6-sol — unknown role (failed), gpt-5.6-sol — unknown role (failed), gpt-5.6-sol — general (failed), gpt-5.6-sol — rust-quality (failed), gpt-5.6-sol — general (completed), gpt-5.6-sol — security-auditor (completed), gpt-5.6-sol — rust-quality (completed), gpt-5.6-sol — ffi-engineer (completed)
  • Verifier: gpt-5.6-sol — verifier
  • Sonnet: not run (deferred by blocker gate)

🔴 1 blocking | 🟡 1 suggestion(s)

1 additional finding(s) omitted (not in diff).

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs`:
- [BLOCKING] packages/rs-dpp/src/data_contract/document_type/class_methods/try_from_schema/v0/mod.rs:180-199: Keep PV13 history fields out of historical schema parsers
  The historical v0 parser now reads `keepsTransferHistory`, `keepsPurchaseHistory`, and `keepsPricingHistory` unconditionally, and the v1 parser does the same at lines 199–218. PLATFORM_V1 through PLATFORM_V11 select these parsers with document meta-schema v0, which permits unknown top-level properties; the base implementation therefore accepted and ignored these names. The new code rejects non-boolean values and lets boolean values affect the typed document configuration and immutable-update checks, changing historical consensus validation and potentially causing replay or mixed-binary disagreement. Parse these fields only when `document_type_schema >= 2`, leaving them false for earlier schema versions.

In `packages/rs-sdk-trusted-context-provider/src/provider.rs`:
- [SUGGESTION] packages/rs-sdk-trusted-context-provider/src/provider.rs:654-662: Include DocumentHistory in the outer feature gate
  The manifest exposes `document-history-contract` as an independent feature, and the inner dispatch branch handles it, but both this enclosing cfg and the matching import cfg at lines 13–21 omit the feature. Consequently, `cargo check -p rs-sdk-trusted-context-provider --no-default-features --features document-history-contract` succeeds while compiling out the entire system-contract lookup block, so DocumentHistory resolution falls through to the fallback provider or returns `None`. Add the feature to both outer cfg lists and cover isolated feature resolution. The shipped FFI configuration is unaffected because its other enabled contract features activate the enclosing block.

Comment on lines +180 to +199
// Are transfers of documents of this type recorded in the document
// history system contract?
let documents_keep_transfer_history: bool =
Value::inner_optional_bool_value(schema_map, KEEPS_TRANSFER_HISTORY)
.map_err(consensus_or_protocol_value_error)?
.unwrap_or_default();

// Are purchases of documents of this type recorded in the document
// history system contract?
let documents_keep_purchase_history: bool =
Value::inner_optional_bool_value(schema_map, KEEPS_PURCHASE_HISTORY)
.map_err(consensus_or_protocol_value_error)?
.unwrap_or_default();

// Are price updates on documents of this type recorded in the
// document history system contract?
let documents_keep_pricing_history: bool =
Value::inner_optional_bool_value(schema_map, KEEPS_PRICING_HISTORY)
.map_err(consensus_or_protocol_value_error)?
.unwrap_or_default();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Blocking: Keep PV13 history fields out of historical schema parsers

The historical v0 parser now reads keepsTransferHistory, keepsPurchaseHistory, and keepsPricingHistory unconditionally, and the v1 parser does the same at lines 199–218. PLATFORM_V1 through PLATFORM_V11 select these parsers with document meta-schema v0, which permits unknown top-level properties; the base implementation therefore accepted and ignored these names. The new code rejects non-boolean values and lets boolean values affect the typed document configuration and immutable-update checks, changing historical consensus validation and potentially causing replay or mixed-binary disagreement. Parse these fields only when document_type_schema >= 2, leaving them false for earlier schema versions.

source: ['codex']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8650436 — the v0 and v1 parsers now read the three flags only when document_type_schema >= 2, so PV1–PV11 (and PV12) parsing is byte-identical to the base implementation: unknown keys under these names stay accepted-and-ignored, non-boolean values can't fail replay, and boolean values can't retroactively flip the typed config or immutable-update checks. Pinned by three regression tests (non-boolean ignored at PV11, boolean ignored at PV11, boolean parsed at PV13).

Historical protocol versions used document meta-schema v0, which accepts
and ignores unknown top-level keys: a pre-v12 contract carrying e.g. a
non-boolean value under keepsTransferHistory validated fine on the base
implementation. Parsing the flags unconditionally would reject such
contracts on replay (and let boolean values flip the typed config and
immutable-update checks retroactively). The parsers now read the flags
only when document_type_schema >= 2, pinned by regression tests at
protocol versions 11 and 13.

Also adds the document-history-contract feature to the trusted context
provider's outer cfg gates so an isolated-feature build keeps the system
contract lookup block compiled in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuantumExplorer

Copy link
Copy Markdown
Member Author

Round-2 suggestion (trusted-context-provider outer cfg gate) also fixed in 8650436: document-history-contract added to both the import cfg and the enclosing lookup-block cfg, verified with an isolated cargo check -p rs-sdk-trusted-context-provider --no-default-features --features document-history-contract.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

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

…story

The history doctypes now carry aggregation trees, turning the contract
into a provable marketplace-stats source:

- purchase: doctype-averageable on price (O(1) provable all-time sale
  count, volume, and average), with byContract and byDocument indices
  range-averageable over $createdAt — provable sale count, volume and
  average price between any two dates, per contract or per document
- priceUpdate: doctype-countable, byContract/byDocument
  range-averageable over $createdAt — provable average asking price
  between dates (listing-event-weighted, documented on the doctype)
- transfer: doctype-countable, byContract range-countable — provable
  transfer counts per contract and time window

price drops its minimum bound so it infers as i64 (grovedb's sum
aggregator is i64; values are protocol-written consensus-validated
credit amounts). The genesis cache loads the contract pinned to its
activation version, since earlier document meta-schemas do not
recognize the index aggregation keywords.

Tests assert the provable count, sum, and (count, sum) average pairs
over the DPNS sale and transfer flows, including a wide date window,
an empty window, and the between-dates average asking price query.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@QuantumExplorer

Copy link
Copy Markdown
Member Author

Added in c94eb2e: the history doctypes now carry provable aggregation trees — purchase is doctype-averageable on price (O(1) provable all-time sale count / volume / average) with byContract/byDocument range-averageable over $createdAt (provable sale stats between any two dates, per contract or per document); priceUpdate gets the same range-averageable indices (provable average asking price between dates, listing-event-weighted — documented on the doctype); transfer is countable + range-countable per contract/time-window. Tests assert the numeric count/sum/(count,sum) results over the DPNS sale and transfer flows including wide-window, empty-window, and between-dates average queries.

The $comment was carried over verbatim from v1 and described v1's
activation (protocol v12, CONTRACT_VERSIONS_V4, frozen at the 3.1
release, changes go to v2+). v2 activates with protocol v13 via
CONTRACT_VERSIONS_V5, adds the keeps*History document type flags,
freezes when the release carrying protocol v13 ships, and future
changes must go to v3+.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@QuantumExplorer QuantumExplorer left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI PR Reviewed

@QuantumExplorer
QuantumExplorer merged commit f21519c into v4.1-dev Jul 22, 2026
73 of 75 checks passed
@QuantumExplorer
QuantumExplorer deleted the claude/document-history-contract branch July 22, 2026 06:04
QuantumExplorer added a commit that referenced this pull request Jul 23, 2026
Three more v4.1-dev breakages that only surface on full (dispatch or
version-change) CI runs:

- Docker image builds fail at cargo-chef prepare: #4171 made
  document-history-contract a dependency of data-contracts but the
  Dockerfile never copies the new crate. Add it everywhere
  token-history-contract appears. This also broke Test Suite and
  Dashmate E2E, which need the images.

- keyword-search-contract unit tests were copy-pasted from
  wallet-utils-contract and still tested its txMetadata document type,
  which this contract does not define; every case threw. Rewrite the
  suite against the real schema (contractKeywords, shortDescription,
  fullDescription). Two behaviors surfaced while doing so are asserted
  as such: wrong-length identifier fields throw at document creation
  (identifier conversion precedes schema validation), and fullDescription's
  schema maxLength (10000) sits above the system per-field cap (5120),
  so overlength strings yield a field-size error, not a maxLength error.

- document-history-contract asserted a minimum on purchase.price, but
  the schema deliberately leaves the integer unbounded so the property
  stays sum-aggregatable; consensus validates actual amounts. Assert
  the type check and the intentional absence of a schema minimum
  instead.

These suites were never exercised in CI before #4203 added the missing
package filters, and the contract-test jobs only run on full pipelines.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants