Skip to content

fix(sdk): prevent sized_integer_types config downgrade that breaks document#3071

Open
shumkov wants to merge 12 commits intov3.1-devfrom
fix/config-update-validation
Open

fix(sdk): prevent sized_integer_types config downgrade that breaks document#3071
shumkov wants to merge 12 commits intov3.1-devfrom
fix/config-update-validation

Conversation

@shumkov
Copy link
Collaborator

@shumkov shumkov commented Feb 8, 2026

Issue being fixed or feature implemented

Changing DataContractConfig from V1 (sized_integer_types=true) to V0 (sized_integer_types=false) breaks deserialization of existing documents that were serialized with sized integer types (version byte 1/2). When the config is downgraded, all integer property types become I64, but the binary data still contains sized integers (U8/U16/U32/U64), causing deserialization failures.

This was the root cause of document deserialization failures observed on testnet where the JS SDK hardcodes protocol v1, which auto-downgrades config V1 to V0.

What was done?

Part 1: Validation — prevent future breakage

  • Added validate_update_v1 that blocks sized_integer_types from being changed from true to false, as this direction is dangerous. The reverse
    (falsetrue) remains allowed since version byte 0 documents use from_bytes_v0 which forces all integers to I64 regardless of config.
  • validate_update_v1 delegates to validate_update_v0 for all existing checks, then adds the sized_integer_types guard.
  • Wired via DPP_VALIDATION_VERSIONS_V3 (validate_config_update: 1) in platform version v12.

Part 2: Deserialization fallback — mitigate already-broken contracts in state

  • Added clone_with_sized_integer_types() on DocumentTypeRef that reconstructs sized integer types from the schema's min/max constraints.
  • Added fallback logic in from_bytes and from_bytes_in_consensus for version bytes 1 and 2: if deserialization fails, reconstruct the document
    type with sized types from schema and retry.
  • Made find_integer_type_for_subschema_value visible within crate::data_contract to support the fallback.

How Has This Been Tested?

Validation tests (6) in validate_update::v1::tests:

  • V1→V0 config change rejected
  • V1(sized=true)→V1(sized=false) rejected
  • V0→V1 allowed (safe direction)
  • V0→V0 allowed (no change)
  • V1→V1 same allowed
  • All v0 checks still work through delegation

Deserialization fallback tests (3) in document::v0::serialize::tests:

  • Config downgrade fallback works (serialize with V1 config, deserialize with V0 doc type — succeeds via fallback)
  • Normal round-trip deserialization still works without fallback
  • Version byte 0 documents remain unaffected

Breaking Changes

None. This is a purely additive change — existing valid contract updates continue to work. Only the previously-unvalidated dangerous config downgrade (sized_integer_types true→false) is now blocked for new protocol version.

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

Summary by CodeRabbit

Release Notes

  • New Features

    • Enforced minimum data contract configuration version requirements based on platform capabilities.
    • Prevention of deprecated configuration state transitions during contract updates.
  • Chores

    • Updated platform version to 3.1.0 with enhanced validation framework.
    • Expanded contract state transition validation layers across create and update operations.

@github-actions github-actions bot added this to the v3.1.0 milestone Feb 8, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 8, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Introduces V1 validation layers for data contract configuration, creation, and update state transitions that enforce minimum supported config versions derived from platform versioning. Includes new DPP and DRIVE_ABCI validation version constants (V3 and V8), updates platform version V12 to reference these, and restructures validation dispatch to conditionally route to V0 or V1 handlers.

Changes

Cohort / File(s) Summary
Data Contract Config Validation
packages/rs-dpp/src/data_contract/config/methods/validate_update/mod.rs, packages/rs-dpp/src/data_contract/config/methods/validate_update/v1/mod.rs
New V1 validation module that delegates to V0 checks then enforces minimum config version based on platform version; includes comprehensive test scenarios for version transitions.
Platform Version Constants
packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs, packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/v3.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/v8.rs
Introduces DPP_VALIDATION_VERSIONS_V3 and DRIVE_ABCI_VALIDATION_VERSIONS_V8 constants with complete validation configuration; exposes v3 and v8 modules.
Platform V12 Updates
packages/rs-platform-version/src/version/v12.rs
Upgrades PLATFORM_V12 to reference DPP_VALIDATION_VERSIONS_V3 and DRIVE_ABCI_VALIDATION_VERSIONS_V8; extends DPPVersion initialization with new fields (state_transitions, contract_versions, document_versions, etc.).
Contract Version Constraints
packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v3.rs
Updates contract config feature version bounds to enforce min_version 1, disallowing V0 configs.
Data Contract Create Validation
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/mod.rs, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v1/mod.rs, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs
Adds DataContractCreateStateTransitionBasicStructureValidationV1 trait with V1 validation that runs V0 checks then enforces minimum config version; updates dispatch logic and tests.
Data Contract Update Validation
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/mod.rs, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/v1/mod.rs, packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs
Adds DataContractUpdateStateTransitionBasicStructureValidationV1 trait with identical V1 pattern; updates validation dispatch and test fixtures.
Data Contract Validation Helpers
packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs
Replaces V0-specific owner_id mutation accessor with public setter; updates test fixtures to use active platform protocol version; generalizes document type mutation to support both V0 and V1.
WASM Integration
packages/wasm-dpp/src/data_contract/data_contract.rs
Changes from PlatformVersion::first() to PlatformVersion::latest() when constructing DataContractConfig.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Validator as Validator<br/>(V0 or V1)
    participant PlatformVersion
    participant ConfigMinVersion

    Client->>Validator: validate_update(contract, new_config, version)
    alt Version 1
        Validator->>Validator: validate_basic_structure_v0()
        alt V0 Validation Fails
            Validator-->>Client: Return Error
        else V0 Validation Passes
            Validator->>PlatformVersion: Get dpp.contract_versions.config.min_version
            PlatformVersion-->>Validator: min_version (e.g., 1)
            Validator->>ConfigMinVersion: Compare new_config.version() vs min_version
            alt Config Version < Min Version
                Validator-->>Client: Return DataContractConfigUpdateError
            else Config Version >= Min Version
                Validator->>Validator: Check sized_integer_types transition
                alt Disabling sized_integer_types (V1→V0)
                    Validator-->>Client: Return DataContractConfigUpdateError
                else Valid Transition
                    Validator-->>Client: Return Success
                end
            end
        end
    else Version 0
        Validator->>Validator: validate_basic_structure_v0()
        Validator-->>Client: Return Result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Poem

🐰 Hops through versions, one and naught,
Config rules are tightly wrought,
Min versions checked with careful care,
Validating contracts everywhere!

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (176 files):

⚔️ .pnp.cjs (content)
⚔️ CHANGELOG.md (content)
⚔️ Cargo.lock (content)
⚔️ Cargo.toml (content)
⚔️ package.json (content)
⚔️ packages/bench-suite/package.json (content)
⚔️ packages/dapi-grpc/build.rs (content)
⚔️ packages/dapi-grpc/package.json (content)
⚔️ packages/dapi-grpc/src/lib.rs (content)
⚔️ packages/dapi/package.json (content)
⚔️ packages/dash-spv/package.json (content)
⚔️ packages/dashmate/configs/defaults/getBaseConfigFactory.js (content)
⚔️ packages/dashmate/configs/getConfigFileMigrationsFactory.js (content)
⚔️ packages/dashmate/docs/config/tenderdash.md (content)
⚔️ packages/dashmate/package.json (content)
⚔️ packages/dashmate/src/config/configJsonSchema.js (content)
⚔️ packages/dashmate/src/doctor/analyse/analyseConfigFactory.js (content)
⚔️ packages/dashmate/src/listr/tasks/doctor/collectSamplesTaskFactory.js (content)
⚔️ packages/dashmate/src/listr/tasks/ssl/letsencrypt/obtainLetsEncryptCertificateTaskFactory.js (content)
⚔️ packages/dashmate/templates/platform/drive/tenderdash/config.toml.dot (content)
⚔️ packages/dashpay-contract/package.json (content)
⚔️ packages/dpns-contract/package.json (content)
⚔️ packages/feature-flags-contract/package.json (content)
⚔️ packages/js-dapi-client/package.json (content)
⚔️ packages/js-dash-sdk/package.json (content)
⚔️ packages/js-evo-sdk/package.json (content)
⚔️ packages/js-evo-sdk/src/addresses/facade.ts (content)
⚔️ packages/js-evo-sdk/src/contracts/facade.ts (content)
⚔️ packages/js-evo-sdk/src/documents/facade.ts (content)
⚔️ packages/js-evo-sdk/src/dpns/facade.ts (content)
⚔️ packages/js-evo-sdk/src/epoch/facade.ts (content)
⚔️ packages/js-evo-sdk/src/group/facade.ts (content)
⚔️ packages/js-evo-sdk/src/identities/facade.ts (content)
⚔️ packages/js-evo-sdk/src/protocol/facade.ts (content)
⚔️ packages/js-evo-sdk/src/sdk.ts (content)
⚔️ packages/js-evo-sdk/src/system/facade.ts (content)
⚔️ packages/js-evo-sdk/src/tokens/facade.ts (content)
⚔️ packages/js-evo-sdk/src/voting/facade.ts (content)
⚔️ packages/js-evo-sdk/src/wallet/functions.ts (content)
⚔️ packages/js-evo-sdk/tests/karma/options.cjs (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/addresses.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/contracts.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/documents.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/dpns.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/epoch.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/group.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/identities.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/protocol.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/system.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/tokens.spec.ts (content)
⚔️ packages/js-evo-sdk/tests/unit/facades/voting.spec.ts (content)
⚔️ packages/js-grpc-common/package.json (content)
⚔️ packages/keyword-search-contract/package.json (content)
⚔️ packages/masternode-reward-shares-contract/package.json (content)
⚔️ packages/platform-test-suite/package.json (content)
⚔️ packages/rs-context-provider/src/provider.rs (content)
⚔️ packages/rs-dapi-client/src/address_list.rs (content)
⚔️ packages/rs-dapi-client/src/dapi_client.rs (content)
⚔️ packages/rs-dapi-client/src/transport/grpc.rs (content)
⚔️ packages/rs-dpp/src/data_contract/config/methods/validate_update/mod.rs (content)
⚔️ packages/rs-dpp/src/data_contract/methods/validate_update/v0/mod.rs (content)
⚔️ packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/block_based.rs (content)
⚔️ packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/mod.rs (content)
⚔️ packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs (content)
⚔️ packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/basic_structure/mod.rs (content)
⚔️ packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs (content)
⚔️ packages/rs-drive-abci/src/logging/destination.rs (content)
⚔️ packages/rs-drive-abci/src/logging/mod.rs (content)
⚔️ packages/rs-drive-abci/tests/strategy_tests/test_cases/address_tests.rs (content)
⚔️ packages/rs-drive-abci/tests/strategy_tests/test_cases/identity_and_document_tests.rs (content)
⚔️ packages/rs-drive-proof-verifier/src/error.rs (content)
⚔️ packages/rs-drive-proof-verifier/src/proof.rs (content)
⚔️ packages/rs-drive-proof-verifier/src/unproved.rs (content)
⚔️ packages/rs-platform-version/Cargo.toml (content)
⚔️ packages/rs-platform-version/src/version/dpp_versions/dpp_contract_versions/v3.rs (content)
⚔️ packages/rs-platform-version/src/version/dpp_versions/dpp_validation_versions/mod.rs (content)
⚔️ packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/mod.rs (content)
⚔️ packages/rs-platform-version/src/version/v12.rs (content)
⚔️ packages/rs-sdk-trusted-context-provider/src/provider.rs (content)
⚔️ packages/rs-sdk/src/mock/provider.rs (content)
⚔️ packages/rs-sdk/src/mock/sdk.rs (content)
⚔️ packages/rs-sdk/src/platform/documents/document_query.rs (content)
⚔️ packages/rs-sdk/src/platform/fetch.rs (content)
⚔️ packages/rs-sdk/src/platform/fetch_many.rs (content)
⚔️ packages/rs-sdk/src/sdk.rs (content)
⚔️ packages/rs-sdk/tests/fetch/common.rs (content)
⚔️ packages/rs-sdk/tests/fetch/mod.rs (content)
⚔️ packages/rs-sdk/tests/vectors/test_sync_address_balances/msg_GetAddressesTrunkStateRequest_c49aeef007d9b94685bb7a38fa0daa7f11dfff63969ad07d74a36a45514c3d33.json (content)
⚔️ packages/simple-signer/Cargo.toml (content)
⚔️ packages/strategy-tests/src/lib.rs (content)
⚔️ packages/token-history-contract/package.json (content)
⚔️ packages/wallet-lib/package.json (content)
⚔️ packages/wallet-utils-contract/package.json (content)
⚔️ packages/wasm-dpp/package.json (content)
⚔️ packages/wasm-dpp/src/data_contract/data_contract.rs (content)
⚔️ packages/wasm-dpp2/package.json (content)
⚔️ packages/wasm-dpp2/src/asset_lock_proof/chain.rs (content)
⚔️ packages/wasm-dpp2/src/asset_lock_proof/instant/instant_asset_lock_proof.rs (content)
⚔️ packages/wasm-dpp2/src/block.rs (content)
⚔️ packages/wasm-dpp2/src/core/pro_tx_hash.rs (content)
⚔️ packages/wasm-dpp2/src/data_contract/contract_bounds.rs (content)
⚔️ packages/wasm-dpp2/src/data_contract/mod.rs (content)
⚔️ packages/wasm-dpp2/src/data_contract/transitions/create.rs (content)
⚔️ packages/wasm-dpp2/src/data_contract/transitions/update.rs (content)
⚔️ packages/wasm-dpp2/src/epoch/extended_epoch_info.rs (content)
⚔️ packages/wasm-dpp2/src/epoch/finalized_epoch_info.rs (content)
⚔️ packages/wasm-dpp2/src/group/action.rs (content)
⚔️ packages/wasm-dpp2/src/group/action_event.rs (content)
⚔️ packages/wasm-dpp2/src/group/token_event.rs (content)
⚔️ packages/wasm-dpp2/src/identifier.rs (content)
⚔️ packages/wasm-dpp2/src/identity/model.rs (content)
⚔️ packages/wasm-dpp2/src/identity/partial_identity.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/create_transition.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/credit_withdrawal_transition.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/identity_credit_transfer_transition.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/masternode_vote_transition.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/public_key_in_creation.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/top_up_transition.rs (content)
⚔️ packages/wasm-dpp2/src/identity/transitions/update_transition.rs (content)
⚔️ packages/wasm-dpp2/src/lib.rs (content)
⚔️ packages/wasm-dpp2/src/platform_address/address.rs (content)
⚔️ packages/wasm-dpp2/src/serialization/conversions.rs (content)
⚔️ packages/wasm-dpp2/src/state_transitions/base/state_transition.rs (content)
⚔️ packages/wasm-dpp2/src/state_transitions/batch/token_pricing_schedule.rs (content)
⚔️ packages/wasm-dpp2/src/state_transitions/mod.rs (content)
⚔️ packages/wasm-dpp2/src/tokens/info.rs (content)
⚔️ packages/wasm-dpp2/src/tokens/status.rs (content)
⚔️ packages/wasm-dpp2/src/version.rs (content)
⚔️ packages/wasm-dpp2/src/voting/contender.rs (content)
⚔️ packages/wasm-dpp2/src/voting/resource_vote.rs (content)
⚔️ packages/wasm-dpp2/src/voting/resource_vote_choice.rs (content)
⚔️ packages/wasm-dpp2/src/voting/vote.rs (content)
⚔️ packages/wasm-dpp2/src/voting/vote_poll.rs (content)
⚔️ packages/wasm-dpp2/src/voting/winner_info.rs (content)
⚔️ packages/wasm-dpp2/tests/unit/DataContract.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/DataContractCreateStateTransition.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/DataContractUpdateStateTransition.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/Document.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/IdentityCreateTransition.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/PlatformAddress.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/PlatformAddressInput.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/PlatformAddressOutput.spec.ts (content)
⚔️ packages/wasm-dpp2/tests/unit/PlatformAddressSigner.spec.ts (content)
⚔️ packages/wasm-drive-verify/package.json (content)
⚔️ packages/wasm-sdk/package.json (content)
⚔️ packages/wasm-sdk/src/context_provider.rs (content)
⚔️ packages/wasm-sdk/src/dpns.rs (content)
⚔️ packages/wasm-sdk/src/queries/document.rs (content)
⚔️ packages/wasm-sdk/src/queries/identity.rs (content)
⚔️ packages/wasm-sdk/src/queries/token.rs (content)
⚔️ packages/wasm-sdk/src/sdk.rs (content)
⚔️ packages/wasm-sdk/src/state_transitions/broadcast.rs (content)
⚔️ packages/wasm-sdk/src/state_transitions/token.rs (content)
⚔️ packages/wasm-sdk/tests/functional/addresses.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/contracts.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/dpns.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/epochs-blocks.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/fixtures/requiredTestData.ts (content)
⚔️ packages/wasm-sdk/tests/functional/groups.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/identities.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/protocol.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/status.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/system.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/token-pricing.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/tokens.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/transitions/contracts.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/transitions/documents.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/transitions/dpns.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/transitions/identity.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/transitions/tokens.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/utilities.spec.ts (content)
⚔️ packages/wasm-sdk/tests/functional/voting.spec.ts (content)
⚔️ packages/wasm-sdk/tests/unit/builder.spec.ts (content)
⚔️ packages/wasm-sdk/tests/unit/data-contract.spec.ts (content)
⚔️ packages/withdrawals-contract/package.json (content)
⚔️ yarn.lock (content)

These conflicts must be resolved before merging into v3.1-dev.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: preventing a config downgrade (sized_integer_types from V1 to V0) that breaks document deserialization.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/config-update-validation

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 and usage tips.

@shumkov shumkov self-assigned this Feb 8, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/rs-dpp/src/data_contract/document_type/mod.rs`:
- Around line 116-129: The recalc currently looks up property names directly in
the top-level schema, so dotted keys in flattened_properties (e.g.
"parent.child") never find their nested subschema; update
recalculate_integer_types_from_schema in DocumentType to handle
flattened_properties by resolving dotted keys into the nested schema before
calling recalculate_integer_types_from_schema(&mut properties, &schema): for
each key in flattened_properties split on '.' and walk the JSON Schema by
repeatedly entering "properties"[segment] (and following "items"/"properties"
for arrays/objects as needed) to locate the appropriate nested subschema, then
pass that subschema into the existing recalc routine; reference the
DocumentType::recalculate_integer_types_from_schema method and the calls that
currently pass v0.flattened_properties / v1.flattened_properties to locate and
change the behavior.
🧹 Nitpick comments (2)
packages/rs-dpp/src/data_contract/config/methods/validate_update/v1/mod.rs (1)

8-8: #[inline(always)] is unnecessary here.

This is a validation method called during contract updates, not a hot-path function. The compiler will make a good inlining decision on its own for a function this size. #[inline(always)] is typically reserved for tiny, performance-critical helpers.

packages/rs-dpp/src/document/v0/serialize.rs (1)

1509-1553: Consider extracting the fallback pattern into a helper to reduce duplication.

The identical fallback logic is repeated four times across from_bytes and from_bytes_in_consensus for version bytes 1 and 2. A helper closure or function parameterized on the deserialization function (from_bytes_v1/from_bytes_v2) could reduce the duplication. Not blocking — the current code is clear and each site has a helpful comment.

Also applies to: 1612-1669

shumkov and others added 4 commits February 8, 2026 18:50
…type recalculation

The recalculate function was using top-level schema lookups for
flattened_properties, so dotted keys like "parent.child" would never
match their nested subschema. Added resolve_schema_for_dotted_key
that walks through nested "properties" objects to find the correct
schema definition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The test was calling setConfig without sizedIntegerTypes, which defaults
to false. Since the contract was created with the platform default
(sizedIntegerTypes: true), this triggered the new validation that blocks
disabling sized integer types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…_integer_types

wasm-dpp uses PlatformVersion::first() which forces all configs to V0
during deserialization. This means SDKs always send ConfigV0 even when
platform stores ConfigV1 with sized_integer_types=true. The validation
now only rejects explicit V1(sized=false) configs, not V0 configs which
simply lack the concept of sized_integer_types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… sized_integer_types

setConfig used PlatformVersion::first() which forced config deserialization
to V0, silently dropping the sized_integer_types field. This caused contract
updates to fail validation when the existing contract had sized_integer_types
enabled. Now uses latest() so V1 configs are properly parsed.

Also reverts the V0 special-case workaround in validate_update_v1, restoring
the simple sized_integer_types true->false rejection for all config variants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
shumkov and others added 2 commits February 10, 2026 21:16
…pe deserialization

The clone_with_sized_integer_types fallback attempted to recover from
config downgrades at deserialization time. This approach is unnecessary
now that config updates are properly validated upstream.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comment on lines +25 to +33
if self.sized_integer_types() && !new_config.sized_integer_types() {
return SimpleConsensusValidationResult::new_with_error(
DataContractConfigUpdateError::new(
contract_id,
"contract can not disable sized integer types once enabled, as this would break deserialization of existing documents",
)
.into(),
);
}
Copy link
Member

Choose a reason for hiding this comment

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

Are we sure you can go V0 to V1?, Also I would include in V1 a verification that the DataContractConfig is V1, makes no sense to register or update to V0 anymore.

Copy link
Collaborator Author

@shumkov shumkov Feb 12, 2026

Choose a reason for hiding this comment

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

Yes, you can upgrade from v0 to v1. Agree, we shouldn't allow v0.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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 (2)
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_update/mod.rs (1)

54-57: ⚠️ Potential issue | 🟡 Minor

Minor: known_versions in VersionNotActive arm not updated to include 1.

The Some(version) arm on Line 51 was updated to vec![0, 1], but the None arm still reports vec![0]. For consistent error messaging, this should also reflect the newly supported version.

Proposed fix
             None => Err(Error::Execution(ExecutionError::VersionNotActive {
                 method: "data contract update transition: validate_basic_structure".to_string(),
-                known_versions: vec![0],
+                known_versions: vec![0, 1],
             })),
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs (1)

106-109: ⚠️ Potential issue | 🟡 Minor

known_versions in VersionNotActive arm is stale.

Line 108 still lists known_versions: vec![0] but version 1 is now also supported (Line 103). This should be vec![0, 1] for consistency with the UnknownVersionMismatch arm.

Proposed fix
             None => Err(Error::Execution(ExecutionError::VersionNotActive {
                 method: "data contract create transition: validate_basic_structure".to_string(),
-                known_versions: vec![0],
+                known_versions: vec![0, 1],
             })),
🧹 Nitpick comments (3)
packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/basic_structure/v1/mod.rs (1)

36-48: Semantically misleading error type for creation context.

DataContractConfigUpdateError is used here to reject a create transition, not an update. While the error message text is clear, the error type name may confuse consumers who filter or handle errors by variant. Consider whether a more general error type (or a new one) would be more appropriate.

packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs (1)

314-317: Misleading comment for protocol version 8 test.

The comment says "required since protocol version 12" but this test explicitly targets protocol version 8, where V0 config is still valid. The config is being set to V1 here likely to satisfy some other constraint introduced by this PR, but the comment is confusing in this context. Consider clarifying why V1 config is being set here despite testing against an older protocol version.

packages/rs-dpp/src/data_contract/config/methods/validate_update/v1/mod.rs (1)

23-39: Consider the ordering: min_version check may mask the more specific sized_integer_types error.

When a V1(sized=true) config attempts to downgrade to V0, both the min_version check (line 27) and the sized_integer_types check (line 46) would trigger. Currently, the user gets the generic "config version X is not supported" error rather than the more descriptive "contract can not disable sized integer types once enabled" message. This is functionally correct but could make the V1→V0 downgrade scenario less informative for the developer.

If the more descriptive error is preferred for that scenario, consider swapping the check order (sized_integer_types check before min_version). Otherwise this is fine as-is since both rejections are correct.

shumkov and others added 3 commits February 16, 2026 21:36
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- qs: ^6.14.1 -> ^6.14.2 (fixes arrayLimit bypass DoS)
- tar: 7.5.7 -> 7.5.9 (fixes deprecation warning)
- webpack: 5.94.0 -> 5.105.2 (fixes buildHttp SSRF bypasses)

Co-Authored-By: Claude Opus 4.6 <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