Skip to content

feat(platform)!: decision proposals open masternode yes/no polls (PV15) - #5684

Merged
QuantumExplorer merged 7 commits into
v5.1-devfrom
claude/decision-proposals
Oct 30, 2026
Merged

QuantumExplorer merged 7 commits into
v5.1-devfrom
claude/decision-proposals

Conversation

@QuantumExplorer

@QuantumExplorer QuantumExplorer commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Basic explanation

What this does: It lets anyone open a decision proposal from protocol version 15. A proposal is a yes/no question put to the masternodes. It is a proposal document of a new system contract, DecisionProposals. Creating it opens a masternode yes/no vote poll with the rule the proposal states. The proposer pays 0.5 Dash, which funds the votes. When the poll closes, its result is recorded. Nothing acts on it: proposals are signaling only.

Value:

This is steps 2 and 3 of #5679, in one PR as the owner chose on 2026-10-30, with the two open limits settled the same day: a threshold of at least a simple majority, and at least one week of voting.

Risks:

  • Consensus impact: the contract, the fee schedule and every changed validation and conversion path are selected only by protocol version 15's tables, which have not shipped. Protocol 14 and earlier behave exactly as before. The table under "In-place changes to shipped generations" lists every shipped table touched and why it cannot change consensus.
  • Mempool and block can disagree on the end date: check_tx judges a proposal's end date against the last block's time, and the block judges it against its own. A proposal ending exactly one week after the last block can pass check_tx and then be refused (paid) in a later block. Clients should leave a margin; the SDK step will.
  • New consensus errors: 11100, 11101 and 41300, appended at the end of their enums.

Issue being fixed or feature implemented

Steps 2 (contract, limits, fee) and 3 (opening on create) of #5679. The poll format they build on is #5680; the client queries that read a proposal's result are #5651.

What was done?

A system contract holds the proposals

DecisionProposals is SystemDataContract 11 (3iNyoNwjCTkb7XS3RHyWUtLx7pgC6AFAEQNNDHzxqngF, owner all zeros). Chains born at 15 register it at genesis (create_genesis_state 1, behind >= 15), and transition_to_version_15 inserts it with no storage flags, as genesis stores system contracts. Its one document type, proposal, cannot be deleted. Its rule never changes; its text may be edited for a short window, and every version is kept:

{
  "title": "Raise the limit?",                      // 1-128 characters, at most 512 bytes
  "description": "Yes raises it, no keeps it.",     // 1-4096 characters, at most 4096 bytes
  "url": "https://example.org/discussion",          // optional, a URI, at most 512 bytes
  "passPercent": 50,                                // 50-80: passes when yes > 50% of yes + no
  "minimumTurnoutPercent": 10,                      // 0-50: yes + no must reach 10% of the network, rounded up
  "endDate": 1767225600000                          // ms; one to four weeks after the block
}

Indexes: byEndDate, byOwner and byCreatedAt.

The type is mutable and keeps history (documentsKeepHistory). passPercent, minimumTurnoutPercent and endDate are listed under immutable. title, description and url are conditional immutable entries (#5217) that freeze once

{ "greaterThan": [{ "subtract": ["$updatedAt", "$createdAt"] },
                  { "min": [86400000, { "divide": [{ "subtract": ["endDate", "$createdAt"] }, 5] }] }] }

holds, that is a day after creation, or a fifth of the run if that is shorter. With a one-week minimum run a fifth is at least 1.4 days, so the day applies today; the fifth takes over if the minimum is ever lowered. An edit after the window, or of the rule at any time, is refused (DocumentImmutablePropertyChangedError, 40128).

The poll stores the rule as it always has: a supermajority of passPercent / 100 and a share minimum of minimumTurnoutPercent / 100 rounded up.

Creating a proposal opens its poll

Before (protocol 15, #5680): nothing called Drive::open_yes_no_vote_poll, so no yes/no poll could exist.

After: a proposal create

  1. states the decision proposal fund as its prefunded voting balance, ("proposal", 50_000_000_000). The transition builders fill it in for a proposal (prefunded_voting_balance_for_document), as they do for a contested document;
  2. passes document create structure validation 2, which refuses any other fund (DecisionProposalFundMismatchError, 11100), a rule outside the limits (InvalidDecisionProposalRuleError, 11101) and an end date outside one to four weeks after the block (DecisionProposalEndDateOutOfRangeError, 41300). These run in check_tx too, so the mempool refuses what a block would;
  3. is converted by the create conversion 1 into: the fund credited to the poll's prefunded balance, the same amount removed from the proposer, the document, and a new DriveOperation::VotePollOperation(OpenYesNoVotePoll { vote_poll, end_date }) that opens the poll.

The poll is read from the proposal by one rs-dpp function, DecisionProposalVotePoll::from_proposal, which consensus and clients share. Its purpose is DecisionProposal { document_id } and its rule is the proposal's.

The opener gained a fee-estimate path, since check_tx and block fee validation convert the create with estimated costs. When estimating, it reads no state and takes the poll as new: a proposal's document id is never reused.

Limits

Rule Limit Where
Pass threshold 50 to 80 percent (passPercent) new, the contract schema; every poll also needs n/d >= 1/2 (min_yes_no_vote_poll_supermajority_percent: 50, new, YesNoVotePoll::validate_parameters v0)
Minimum turnout 0 to 50 percent of the network (minimumTurnoutPercent), rounded up the contract schema; existing poll cap of 50%
End date at most four weeks after the block existed
at least one week after the block (min_yes_no_vote_poll_duration_ms) new, YesNoVotePoll::end_date_window v0, shared by validation and the opener

Fund

VoteResolutionFundFees gained decision_proposal_fund_required_amount: 0 (unread) in the schedules before 15, and 0.5 Dash in the new VOTE_RESOLUTION_FUND_FEES_VERSION3, which the new FEE_VERSION4 carries for protocol 15. Platform states store only a fee schedule's number, so no stored format changes. What the votes leave of the fund goes to processing fees when the poll closes, as for DPNS contests.

How Has This Been Tested?

New tests:

  • drive-abci, end to end (masternode_vote/yes_no_tests/decision_proposal_tests.rs, 6 tests):
    • a proposal create opens the poll with its rule, writes its end date entry, funds it with exactly 0.5 Dash, takes 0.5 Dash plus fees from the proposer and stores the proposal; check_tx admits it at both levels;
    • no fund, 0.5 Dash minus or plus 1 credit, and the right amount under another name are each refused, in check_tx too, and open nothing;
    • a passPercent of 49 or 81, a minimumTurnoutPercent of 51 and either one missing are refused; 50/50 and 80/0 pass;
    • the proposer edits the title, description and url within the day, cannot change the end date even then, cannot edit after the day, and both versions stay readable in the document's history; the poll keeps its rule;
    • a proposer holding the fund but only half the fees is refused before anything is written (the fund counts in the balance the batch needs);
    • an end date one week minus 1 ms or four weeks plus 1 ms away is refused with the window in the error; exactly one week and exactly four weeks pass; check_tx refuses one far too soon;
    • the same question from two owners opens two polls;
    • full lifecycle: two evonodes vote yes and a masternode no; the close records a pass (8 to 1, 5 required), the remaining fund goes to processing fees, the end date entry goes, the proposal stays, and getYesNoVotePollState proves the result.
  • rs-dpp: reading a proposal into its poll (passPercent / 100, a share minimum rounded up), passing strictly above the percent (a tie fails at 50), each rule refusal, not active before 15, the contract and type names pinned to the contract crate's, the builders stating the fund, the edit window's condition at a day and at a fifth of a two-day run, the simple-majority floor (128/255 passes, 127/255 fails) and the end date window, including its cap at i64::MAX.
  • rs-drive: the opener refuses end dates outside one to four weeks, and opens at exactly each bound.
  • Contract registration:
    • a chain registers the contract at genesis only from protocol 15;
    • transition_to_version_15 inserts it;
    • a chain upgraded from 14 to 15 stores the same contract bytes and trees as one born at 15;
    • the upgrade dispatcher's rollback and retry cover it;
    • Drive's contract cache and the trusted context provider serve it only from 15;
    • the contract crate pins its id and schema and refuses to load below 15;
    • the JS package's unit spec passes (23 tests).

Updated tests: the opener and yes/no vote tests now end their polls two weeks after the opening block, inside the new window. should_close_a_contested_poll_and_a_yes_no_poll_that_end_at_the_same_time runs on a mainnet configuration, whose two-week DPNS contest ends inside that window (a test network's 90 minutes would not). One more contract in a protocol 15 genesis adds a sibling to the contracts tree, which moves some exact fee and root pins at protocol 15. Each one is re-pinned with a comment, after checking that it returns to its old value when the contract is moved to a later genesis branch:

  • the document deletion, replacement, DPNS, DPNS v3 and commit-reveal lookup fees;
  • the token burn and direct-selling fees;
  • the shielded nullifier batch guard's fees and roots;
  • the moderation restore fee.

Runs (targeted, as usual): dpp (with decision-proposals-contract, discriminants included) 37, drive 38, drive-abci decision proposals, masternode votes, create validation and document creation 221, contract create and update, fee claims, moderation, genesis and the protocol upgrade 491, the batch document and token modules (all pass after the re-pins), rs-sdk-trusted-context-provider 47. wasm-sdk (wasm32) and dash-sdk build. should_page_with_a_cursor_only_where_the_query_fixes_the_derived_property failed once under parallel load and passes alone on this branch and on the registration-only commit: its replies take their creation time from the wall clock. Other fee or root pins at protocol 15 outside the modules run here may move the same way; CI will show them. Formatted with cargo fmt --all; clippy-clean on platform-version, dpp, drive, drive-abci, data-contracts and decision-proposals-contract with tests, and wasm-dpp for wasm32 (the data-contracts unused-parameter warning without contract features predates this PR).

In-place changes to shipped generations

Shipped generation Change Why consensus cannot change
SYSTEM_LIMITS_V1 to V4 Gained min_yes_no_vote_poll_duration_ms and min_yes_no_vote_poll_supermajority_percent. Read only by YesNoVotePoll::validate_parameters and end_date_window, which are None (not active) before 15.
VOTE_RESOLUTION_FUND_FEES_VERSION1 (and V2 through it), and the pre-1.4 From Gained decision_proposal_fund_required_amount: 0. Read only for a decision proposal, whose contract does not exist before 15. Platform states store only the fee schedule's number.
SYSTEM_DATA_CONTRACT_VERSIONS_V1 to V3 Gained decision_proposals: 0. 0 names no schema: the contract refuses to load, and the cache answers "absent" below 15.
VOTING_VERSION_V1, V2 Gained decision_proposal_vote_poll: None. Not active.
DocumentCreateTransitionAction transformer A create of the decision proposals contract's proposal keeps its stated fund for validation instead of resolving it as a contested index. That contract does not exist before 15, so no create reaches the branch.
prefunded_voting_balance_for_document v0 States the decision proposal fund for a proposal. Only transition builders call it, never validation; and the contract does not exist before 15.
DocumentCreateTransitionActionV0 Gained decision_proposal: None for every other create. An in-memory action, never serialized.

Breaking Changes

Protocol 15 is unreleased, so nothing breaks on a live network.

  • Rust: Drive::open_yes_no_vote_poll_operations takes estimated_costs_only_with_layer_info. DriveOperation gained VotePollOperation. VoteResolutionFundFees, SystemLimits, SystemDataContractVersions and DPPVotingVersions gained fields. SystemDataContract::ALL has 12 entries.
  • Protocol 15 devnets: a yes/no poll may no longer end within a week of opening or pass below a simple majority. No feature opened one before this PR.

Checklist:

  • I have performed a self-review of my own code
  • My Rust, FFI, WASM, Swift or Kotlin changes follow the coding conventions
  • 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
  • If I added or changed GroveDB structure, I described it in the area's structure.rs, regenerated grovedb-structure.json, and checked the structure viewer link posted on this pull request
  • If I added or changed a system contract's document schemas, I checked the contract viewer link posted on this pull request

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

PR Hygiene · 5cc4fa4

  • Bots — thepastaclaw not yet — /skip-bots proceeds without the ones not yet reported
  • Self-review — post /self-reviewed
  • Build running
  • Approvals
    • files with no dedicated owner — you own it
    • github (.github/package-filters/js-packages-direct.yml, .github/package-filters/js-packages-no-workflows.yml, .github/package-filters/js-packages.yml and 6 more) — ktechmidas or shumkov
    • system-contracts — you own it
    • dpp — you own it
    • rs-drive-abci — you own it
    • rs-drive — you own it
    • rust-sdk-ffi (packages/rs-sdk-ffi/Cargo.toml) — lklimek or shumkov
    • rust-sdk (packages/rs-sdk/Cargo.toml) — lklimek or shumkov
    • js-wasm-sdk (packages/wasm-sdk/Cargo.toml) — shumkov

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

QuantumExplorer and others added 6 commits October 30, 2026 13:52
…docs

The @dashevo/decision-proposals-contract workspace (package.json, system
ids, README and a unit spec of the proposal schema), the contract in the
root, Docker, codecov and CI package lists the moderation charters
contract is in, its row in the book's system contracts table, the 0.5
Dash decision proposal fund in the book's contest funds table, and a
protocol guide for decision proposals.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…text provider at protocol 15

Behind the decision-proposals-contract feature (and all-system-contracts),
the provider loads the decision proposals system contract from protocol
version 15 on and reports it absent below, like the app-connect and
moderation charters contracts from 14.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…he upgrade to 15

The contract is in a genesis state born at 15 and not at 14, is inserted
by transition_to_version_15, is stored byte for byte as a chain born at
15 stores it (no storage flags, same trees), and its registration rolls
back and retries to the same root through the upgrade dispatcher.

It is one more sibling in the genesis contracts tree from protocol 15,
which reshapes that tree and moves the byte-billed contract reads of the
fee pins at the latest version: deletion and replacement -47_280, DPNS
domain creates +95_920 each, the commit/reveal fixture's contract
-45_920, token burn and direct purchase -48_640, the sponsored shielded
token payments +45_920, and the single-entry shielded GroveDB root pins.
Confirmed by gating the genesis registration off, which restores every
old value.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…inimum; restore fee pin at 15

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

coderabbitai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 110 files, which is 10 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

Check out review usage here.

Run configuration
Commits

Reviewing files that changed from the base of the PR and between e269d6f and 5cc4fa4.

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: 110
  • .codecov.yml
  • .github/package-filters/js-packages-direct.yml
  • .github/package-filters/js-packages-no-workflows.yml
  • .github/package-filters/js-packages.yml
  • .github/package-filters/rs-packages-direct.yml
  • .github/package-filters/rs-packages-no-workflows.yml
  • .github/package-filters/rs-packages.yml
  • .github/package-filters/test-suite-triggers.yml
  • .github/workflows/tests-rs-workspace.yml
  • .github/workflows/tests.yml
  • .pnp.cjs
  • Cargo.toml
  • Dockerfile
  • book/src/architecture/overview.md
  • book/src/error-handling/error-codes.md
  • book/src/fees/overview.md
  • docs/protocol/decision-proposals.md
  • package.json
  • packages/data-contracts/Cargo.toml
  • packages/data-contracts/src/error.rs
  • packages/data-contracts/src/lib.rs
  • packages/decision-proposals-contract/.mocharc.yml
  • packages/decision-proposals-contract/Cargo.toml
  • packages/decision-proposals-contract/LICENSE
  • packages/decision-proposals-contract/README.md
  • packages/decision-proposals-contract/eslint.config.mjs
  • packages/decision-proposals-contract/lib/systemIds.js
  • packages/decision-proposals-contract/package.json
  • packages/decision-proposals-contract/schema/v1/decision-proposals-contract-documents.json
  • packages/decision-proposals-contract/src/error.rs
  • packages/decision-proposals-contract/src/lib.rs
  • packages/decision-proposals-contract/src/v1/mod.rs
  • packages/decision-proposals-contract/test/bootstrap.js
  • packages/decision-proposals-contract/test/unit/decisionProposalsContract.spec.js
  • packages/rs-dpp/Cargo.toml
  • packages/rs-dpp/src/data_contract/document_type/methods/versioned_methods.rs
  • packages/rs-dpp/src/decision_proposal/mod.rs
  • packages/rs-dpp/src/errors/consensus/basic/basic_error.rs
  • packages/rs-dpp/src/errors/consensus/basic/decision_proposal/decision_proposal_fund_mismatch_error.rs
  • packages/rs-dpp/src/errors/consensus/basic/decision_proposal/invalid_decision_proposal_rule_error.rs
  • packages/rs-dpp/src/errors/consensus/basic/decision_proposal/mod.rs
  • packages/rs-dpp/src/errors/consensus/basic/mod.rs
  • packages/rs-dpp/src/errors/consensus/codes.rs
  • packages/rs-dpp/src/errors/consensus/state/decision_proposal/decision_proposal_end_date_out_of_range_error.rs
  • packages/rs-dpp/src/errors/consensus/state/decision_proposal/mod.rs
  • packages/rs-dpp/src/errors/consensus/state/mod.rs
  • packages/rs-dpp/src/errors/consensus/state/state_error.rs
  • packages/rs-dpp/src/lib.rs
  • packages/rs-dpp/src/system_data_contracts.rs
  • packages/rs-dpp/src/voting/vote_polls/yes_no_vote_poll/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/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/action_validation/document/document_create_transition_action/advanced_structure_v1/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_create_transition_action/advanced_structure_v2/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_create_transition_action/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/state/v0/accepted_token_pool_nullifiers.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/commit_reveal_lookup.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/deletion.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/dpns_v3.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/replacement.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/burn/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/shielded/nullifier_batch_guard.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/contract_user_moderation/tests/restore_constraints.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/yes_no_tests.rs
  • packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/masternode_vote/yes_no_tests/decision_proposal_tests.rs
  • packages/rs-drive/src/cache/system_contracts.rs
  • packages/rs-drive/src/drive/document/index_uniqueness/mod.rs
  • packages/rs-drive/src/drive/votes/insert/yes_no/open_yes_no_vote_poll/mod.rs
  • packages/rs-drive/src/drive/votes/insert/yes_no/open_yes_no_vote_poll/v0/mod.rs
  • packages/rs-drive/src/state_transition_action/action_convert_to_operations/batch/document/document_create_transition/v1.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/mod.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/mod.rs
  • packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs
  • packages/rs-drive/src/state_transition_action/batch/tests.rs
  • packages/rs-drive/src/state_transition_action/batch/v0/mod.rs
  • packages/rs-drive/src/util/batch/drive_op_batch/mod.rs
  • packages/rs-drive/src/util/batch/drive_op_batch/vote_poll.rs
  • packages/rs-drive/src/util/test_helpers/mod.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/mod.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v1.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v2.rs
  • packages/rs-platform-version/src/version/dpp_versions/dpp_voting_versions/v3.rs
  • packages/rs-platform-version/src/version/drive_abci_versions/drive_abci_validation_versions/v11.rs
  • packages/rs-platform-version/src/version/feature_initial_protocol_versions.rs
  • packages/rs-platform-version/src/version/fee/mod.rs
  • packages/rs-platform-version/src/version/fee/v4.rs
  • packages/rs-platform-version/src/version/fee/vote_resolution_fund_fees/mod.rs
  • packages/rs-platform-version/src/version/fee/vote_resolution_fund_fees/v1.rs
  • packages/rs-platform-version/src/version/fee/vote_resolution_fund_fees/v3.rs
  • packages/rs-platform-version/src/version/mocks/v2_test.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/system_data_contract_versions/v3.rs
  • packages/rs-platform-version/src/version/system_data_contract_versions/v4.rs
  • packages/rs-platform-version/src/version/system_limits/mod.rs
  • packages/rs-platform-version/src/version/system_limits/v1.rs
  • packages/rs-platform-version/src/version/system_limits/v2.rs
  • packages/rs-platform-version/src/version/system_limits/v3.rs
  • packages/rs-platform-version/src/version/system_limits/v4.rs
  • packages/rs-platform-version/src/version/v15.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
  • packages/wasm-dpp/src/errors/consensus/consensus_error.rs
  • packages/wasm-sdk/Cargo.toml

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@github-actions github-actions Bot added this to the v5.1.0 milestone Oct 30, 2026
@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

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

@github-actions github-actions Bot added the waiting-bots Waiting for the review bots to report on this head label Oct 30, 2026
@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

📖 Book Preview built successfully.

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

Updated at 2026-10-30T17:26:32.592Z

@github-actions

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

📜 System contracts

This pull request adds or changes system contract document schemas. The contract viewer diagrams each one, and a comparison marks what is added, changed and removed, with the update rule each change meets.

Compared e269d6ff8e with 5cc4fa41f8. Updated at 2026-10-30T17:26:18.583Z

@thepastaclaw

thepastaclaw commented Oct 30, 2026 •

Copy link
Copy Markdown
Collaborator

🔍 Review in progress — actively reviewing now (commit 5cc4fa4) · triage: critical
███████████░░░░░░░░░ 54% · taking longer than usual · running for 25 min
✅ triage → ⏳ Phase 2 (3/5 lanes) → ⏳ Phase 1 (1/2 lanes) → ▫️ verify 2 → ▫️ fresh Phase 2 → ▫️ fresh verify → ▫️ publish
Estimated from recent reviews of this tier · updated 17:52 UTC · live progress

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Final validation — Phase 1 + Phase 2

The decision-proposal feature is generally wired through the correct protocol-versioned layers, but the proposal fund is omitted from principal-balance accounting, allowing underfunded proposals to pass fee validation and fail during execution. The poll-opening conversion also loses batch context, so valid batches with proposals sharing an end date can emit duplicate GroveDB tree inserts; additional activation and mempool-time issues remain. CI is still incomplete, with Rust tests queued and several build jobs in progress.

🔴 1 blocking | 🟡 4 suggestion(s) | 💬 1 nitpick(s)

Review provenance

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

  • Triage: critical by gpt-6.1-sol (effort low) — This is a large, intricate change that modifies consensus-critical protocol-version dispatch, document validation, voting and poll opening, fee-funded balance movement, system-contract persistence, and ABCI state transitions, including files such as packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_create_transition_action/
  • Phase 1 reviewers: muse-spark-1.3-contributor — general (completed, effort xhigh); agent phase1-reviewer, muse-spark-1.3-contributor — rust-quality (completed, effort xhigh); agent phase1-reviewer
  • Phase 1 model: muse-spark-1.3-contributor — not quota-gated; passed over gemini-3.8-flash-high (antigravity quota lookup failed), glm-5.3-flash (not used above high effort; tier asks max)
  • Single stage: Phase 1 and Phase 2 reviewed this head side by side, with no blocker gate between them (triage tier)
  • Fresh verifier: gpt-6.1-sol — final-verifier; agent sol-verifier
  • Phase 2 reviewers: gpt-6.1-sol — general (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — architecture-layering (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — platform-versioning (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — rust-quality (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — security-auditor (completed, effort xhigh); agent phase2-reviewer, gpt-6.1-sol — tenderdash-consensus-security (completed, effort xhigh); agent phase2-reviewer
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs`:
- [BLOCKING] packages/rs-drive/src/state_transition_action/batch/batched_transition/document_transition/document_create_transition_action/v0/transformer.rs:103-105: Count the decision-proposal fund in principal-balance accounting
  This branch removes a decision proposal's stated fund from `prefunded_voting_balance` and stores it only in `DecisionProposalCreate.stated_fund`. However, `BatchTransitionActionV0::all_conflicting_index_collateral_voting_funds` still sums only `prefunded_voting_balance`, so `all_used_balances()` and the resulting `ExecutionEvent::Paid.removed_balance` omit the 0.5 Dash identity debit emitted later by `document_create_transition/v1`. Fee validation therefore checks only the processing fee: an identity with enough credits for fees but less than the fund plus fees can pass validation, then fail when `RemoveFromIdentityBalance` executes. Include `decision_proposal.stated_fund` in the shared balance aggregate using checked addition, and add fee-estimation/execution parity coverage for an underfunded proposal.

In `packages/rs-drive/src/util/batch/drive_op_batch/vote_poll.rs`:
- [SUGGESTION] packages/rs-drive/src/util/batch/drive_op_batch/vote_poll.rs:43-50: Preserve pending batch operations when opening proposal polls
  `VotePollOperationType::into_low_level_drive_operations` creates a fresh operation vector and passes `None` for `previous_batch_operations`. The opener's protocol-15 end-date deduplication explicitly relies on that context to recognize an end-date tree queued by an earlier poll or contest. Consequently, two valid proposal creates with the same `endDate` independently queue the same tree insert; the batch can then be rejected by GroveDB for duplicate writes. The same omission loses the storage flags and deletion-cancellation behavior documented by `open_yes_no_vote_poll_operations`. Pass the accumulated batch context through the conversion pipeline or aggregate poll openings in a batch-aware converter.

In `packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_create_transition_action/advanced_structure_v2/mod.rs`:
- [SUGGESTION] packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/action_validation/document/document_create_transition_action/advanced_structure_v2/mod.rs:80-84: Prevent minimum-duration proposals from becoming invalid after mempool admission
  The lower end-date bound is computed from `block_info.time_ms`. During `check_tx`, the caller supplies the last committed block's time, while block execution validates against the candidate block's later time. A proposal whose `endDate` is exactly one week after the committed timestamp can therefore pass mempool validation and fail the same structure check when included in the next block. Because this check occurs after identity processing, the transaction can become a paid consensus failure rather than simply being excluded. Use a conservative mempool margin or a stable reference time that guarantees a transaction accepted by `check_tx` remains valid at inclusion.

In `packages/rs-sdk-trusted-context-provider/src/provider.rs`:
- [SUGGESTION] packages/rs-sdk-trusted-context-provider/src/provider.rs:1209-1213: Apply the protocol activation check before returning cached contracts
  The protocol-15 guard is reached only after the generic `known_contracts` lookup at lines 1041-1045. If a decision-proposals contract is preloaded through `with_known_contracts`, `add_known_contract`, `add_known_contracts`, or `register_data_contract`, a lookup at protocol 14 returns the cached contract immediately and bypasses this guard. That contradicts the provider's stated behavior that the contract is absent below protocol 15. Apply the activation filter before the generic cache lookup or make cached entries protocol-version aware, and add a regression test that preloads the contract before querying it at protocol 14.

In `packages/rs-platform-version/src/version/system_limits/mod.rs`:
- [SUGGESTION] packages/rs-platform-version/src/version/system_limits/mod.rs:267-270: Update the stale minimum-duration reader reference
  The field comment says the limit is read by `YesNoVotePoll::validate_end_date`, but that function does not exist. The actual reader is `YesNoVotePoll::end_date_window`, which is also used by the Drive poll opener. Update the reference so future changes to the duration window find the correct implementation.

In `packages/rs-dpp/src/voting/vote_polls/yes_no_vote_poll/mod.rs`:
- [NITPICK] packages/rs-dpp/src/voting/vote_polls/yes_no_vote_poll/mod.rs:394-398: Document the empty end-date window at extreme timestamps
  When `opening_time_ms` exceeds `i64::MAX`, `earliest` can remain above `i64::MAX` while `latest` is clamped to `i64::MAX`, producing an inverted `RangeInclusive`. This is safe for current block times because callers reject every date in that range, but it contradicts the documentation promising that both returned bounds are allowed. Document the empty-window behavior or explicitly handle this edge case.

@github-actions

Copy link
Copy Markdown
Contributor

Your move: thepastaclaw requested changes on this head; dismiss the review or push a fix; thepastaclaw left review threads unresolved; resolve them.
Full checklist in the description.

@github-actions github-actions Bot added waiting-self-review Waiting for the author to post /self-reviewed and removed waiting-bots Waiting for the review bots to report on this head labels Oct 30, 2026
…s and their text stays editable for a day

- The rule is `passPercent` (50 to 80: yes must be strictly more than that
  share of yes plus no) and `minimumTurnoutPercent` (0 to 50 of the
  network's voting power, rounded up), replacing the supermajority fraction
  and the two kinds of minimum. The poll stores p/100 and a share minimum
  rounded up, as before.
- `title`, `description` and `url` may be edited for min(1 day, run / 5)
  after creation (conditional `immutable` entries); the rule never changes;
  every version is kept (`documentsKeepHistory`).
- The decision proposal fund counts in the balance a batch uses
  (`all_conflicting_index_collateral_voting_funds`), so an owner who cannot
  pay both the fund and the fees is refused before anything is written.
- Review notes: the minimum-duration limit names `end_date_window`, the
  window documents when it is empty, and the poll-opening conversion says why
  it needs no earlier batch operations.
- Re-pinned the shielded nullifier guard's settled hashes and root (the
  genesis contract changed) and the valid-payment characterization (the
  create action gained `decision_proposal`).

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

github-actions Bot commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

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

@github-actions github-actions Bot added waiting-bots Waiting for the review bots to report on this head and removed waiting-self-review Waiting for the author to post /self-reviewed labels Oct 30, 2026
@QuantumExplorer

Copy link
Copy Markdown
Member Author

Reviewed

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

Labels

waiting-bots Waiting for the review bots to report on this head

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants