Skip to content

feat(contract): report add-domains votes by proposal hash in state() - #4873

Draft
SimonRastikian wants to merge 15 commits into
2825-report-parameter-votes-tallyfrom
2825-report-add-domains-votes-tally
Draft

SimonRastikian wants to merge 15 commits into
2825-report-parameter-votes-tallyfrom
2825-report-add-domains-votes-tally

Conversation

@SimonRastikian

Copy link
Copy Markdown
Contributor

No description provided.

@SimonRastikian SimonRastikian self-assigned this Oct 21, 2026
@SimonRastikian
SimonRastikian added this pull request to stack #4871 October 21, 2026 00:01
@SimonRastikian
SimonRastikian marked this pull request as draft October 21, 2026 00:01
@github-actions

Copy link
Copy Markdown
Contributor

Pull request overview

Second PR in the #2825 stack (base: #4872). The state() view previously exposed add_domains_votes as a map from voter to the full Vec<DomainConfig> they proposed. It now reports the same votes as a tally keyed by ProposalHash (SHA-256 of the Borsh encoding of the domain list) with a BTreeSet<AuthenticatedParticipantId> of voters per proposal, mirroring the shape GovernanceThresholdParametersVotes adopted in #4872. Contract storage is untouched; the hashing happens only during DTO conversion, so no state migration is involved.

Changes:

  • impl ToProposalHash for Vec<DomainConfig> (Borsh + SHA-256) in the contract crate, and the DTO mapping now groups proposal_by_account entries by that hash.
  • Interface DTO AddDomainsVotes becomes a #[serde(transparent)] newtype around BTreeMap<ProposalHash, BTreeSet<AuthenticatedParticipantId>> with Default and Deref.
  • New unit test covering two voters on one proposal and a third on a different one; sandbox cleanup-after-resharing test and ABI snapshot updated; backup-cli sample state updated.

Reviewed changes

Per-file summary
File Description
crates/near-mpc-contract-interface/src/types/state.rs AddDomainsVotes DTO changed from { proposal_by_account } to a transparent BTreeMap<ProposalHash, BTreeSet<AuthenticatedParticipantId>> newtype
crates/contract/src/primitives/domain.rs Adds ToProposalHash impl for Vec<DomainConfig> (Borsh serializer, SHA-256 hasher)
crates/contract/src/dto_mapping.rs IntoInterfaceType<dtos::AddDomainsVotes> now buckets voters by domains.to_proposal_hash()
crates/contract/src/api/governance.rs New state__should_report_add_domains_votes_by_proposal_hash unit test
crates/contract/tests/sandbox/update_votes_cleanup_after_resharing.rs Assertions rewritten against the hash-keyed tally
crates/contract/tests/snapshots/abi__abi_has_not_changed.snap ABI: AddDomainsVotes definition removed, add_domains_votes is now an inline map of unique-item arrays
crates/backup-cli/assets/contract_state.json Sample state updated to the new empty-map shape

Correctness checks that passed on reading: the DTO grouping agrees with the contract's own vote counting, which compares Vec<DomainConfig> by structural equality (domain.rs:284-288); Borsh is deterministic, so equal proposals always land in the same bucket. Hashes are computed only inside state() (the mapping trait is pub(crate)), so near_sdk::env::sha256_array is never invoked outside the VM or testing_env!. The node does not read add_domains_votes, and no live doc under docs/ describes the old shape. The contract-side type ParticipantId is a re-export of the interface type, so the new test's dtos::AuthenticatedParticipantId(voters[i].1) type-checks.

I could not run CI status or cargo test from this environment, so the test/ABI snapshot are verified by inspection only.

Findings

Non-blocking (nits, follow-ups, suggestions):

  • crates/near-mpc-contract-interface/src/types/state.rs:192 — The doc comment says voters are grouped by the ProposalHash of the domain list, but nothing a consumer can reach says how that hash is derived (SHA-256 over the Borsh encoding of Vec<DomainConfig>); ToProposalHash/Borsh/Sha256 are all pub(crate) in the contract crate. Before this change an operator could read the proposed domains straight from state(); now they see opaque hex keys and cannot match them against the proposal they hold without re-implementing the recipe. feat(contract): report pending parameter votes by proposal hash in state() #4872 has the same gap for parameter votes. Suggest, somewhere in this stack: (a) spell out the derivation in the doc comment, and (b) expose a to_proposal_hash-style helper for the DTO proposal types in near-mpc-sdk, per AGENTS.md's "shared logic lives in the SDK" rule, so dashboards and the node can correlate tallies with proposals. This is also a breaking change to the state() JSON for any external tooling; worth a line in the release notes.
  • crates/contract/src/primitives/domain.rs:264 — Storage still keeps one full Vec<DomainConfig> per voter and vote() compares them structurally, while replace GovernanceThresholdParametersVotes with generic votes struct #2825's acceptance criteria ask for hash-based votes like the Votes<V> type now used for parameter votes. Clearly out of scope for a reporting-only PR, but a TODO(#2825) on the struct (or a linked follow-up issue) would make the intended end state discoverable.

✅ Approved

…-domains-votes-tally

# Conflicts:
#	crates/near-mpc-contract-interface/src/types/state.rs

This branch has not been deployed

No deployments
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.

1 participant