feat(nns): Reduce maximum dissolve delay to 2 years and clamp all neurons#9688
feat(nns): Reduce maximum dissolve delay to 2 years and clamp all neurons#9688jasonz-dfinity merged 3 commits intomasterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR reduces the NNS Governance maximum neuron dissolve delay from 8 years to 2 years behind the Mission 70 flag, and adds an upgrade-time migration that clamps all existing neurons to the new maximum while recording a per-neuron pre-clamp snapshot for potential recovery.
Changes:
- Introduce
max_dissolve_delay_seconds()(2y when Mission 70 is enabled, otherwise 8y) and update logic/tests to use it. - Add post-upgrade clamping of all neurons’ dissolve states, storing pre-clamp snapshots in new persisted governance state.
- Extend protobuf + heap governance plumbing to persist
NeuronDissolveStateSnapshot, and add/adjust unit tests accordingly.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| rs/nns/governance/src/governance.rs | Adds dynamic max dissolve delay function/constants; clamps all neurons on upgrade and stores snapshots. |
| rs/nns/governance/src/governance/create_neuron.rs | Validates requested dissolve delay against the dynamic maximum and updates error formatting. |
| rs/nns/governance/src/neuron/dissolve_state_and_age.rs | Replaces static cap with dynamic max and adds clamp_dissolve_delay helper. |
| rs/nns/governance/src/neuron/types.rs | Updates voting power dissolve-delay bonus denominator to dynamic max; adds clamping on AbridgedNeuron. |
| rs/nns/governance/src/storage/neurons.rs | Adds stable-store iteration to clamp dissolve delay for all neurons and return snapshots. |
| rs/nns/governance/src/neuron_store.rs | Exposes a NeuronStore wrapper method to clamp all neurons and return snapshots. |
| rs/nns/governance/src/heap_governance_data.rs | Persists the new snapshot map through heap governance split/reassemble. |
| rs/nns/governance/proto/ic_nns_governance/pb/v1/governance.proto | Adds NeuronDissolveStateSnapshot and governance map field. |
| rs/nns/governance/src/gen/ic_nns_governance.pb.v1.rs | Regenerated Rust protobuf bindings for the new messages/fields. |
| rs/nns/governance/tests/governance.rs | Updates tests to use the dynamic maximum and adjust expectations under Mission 70. |
| rs/nns/governance/tests/merge_neurons.rs | Updates proptest ranges to use max_dissolve_delay_seconds(). |
| rs/nns/governance/src/voting.rs | Updates tally expectations in tests to account for Mission 70 dissolve-delay bonus changes. |
| rs/nns/governance/src/neuron/types/tests.rs | Updates dissolve-delay-related tests to use the dynamic maximum. |
| rs/nns/governance/src/storage/neurons/neurons_tests.rs | Updates eight-year-gang tests to use the pre-mission constant. |
| rs/nns/governance/src/neuron_store/neuron_store_tests.rs | Adds unit tests for clamping all neurons + snapshot correctness. |
| rs/nns/governance/src/neuron_store/metrics/tests.rs | Updates metrics tests to be compatible with the dynamic max. |
| rs/nns/governance/src/governance/tests/mod.rs | Updates tests using max dissolve delay to reference the pre-mission constant. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5541d50 to
6650a84
Compare
There was a problem hiding this comment.
This pull request changes code owned by the Governance team. Therefore, make sure that
you have considered the following (for Governance-owned code):
-
Update
unreleased_changelog.md(if there are behavior changes, even if they are
non-breaking). -
Are there BREAKING changes?
-
Is a data migration needed?
-
Security review?
How to Satisfy This Automatic Review
-
Go to the bottom of the pull request page.
-
Look for where it says this bot is requesting changes.
-
Click the three dots to the right.
-
Select "Dismiss review".
-
In the text entry box, respond to each of the numbered items in the previous
section, declare one of the following:
-
Done.
-
$REASON_WHY_NO_NEED. E.g. for
unreleased_changelog.md, "No
canister behavior changes.", or for item 2, "Existing APIs
behave as before.".
Brief Guide to "Externally Visible" Changes
"Externally visible behavior change" is very often due to some NEW canister API.
Changes to EXISTING APIs are more likely to be "breaking".
If these changes are breaking, make sure that clients know how to migrate, how to
maintain their continuity of operations.
If your changes are behind a feature flag, then, do NOT add entrie(s) to
unreleased_changelog.md in this PR! But rather, add entrie(s) later, in the PR
that enables these changes in production.
Reference(s)
For a more comprehensive checklist, see here.
GOVERNANCE_CHECKLIST_REMINDER_DEDUP
…on test The max dissolve delay reduction from 8 years to 2 years changed voting power calculations, but the hardcoded expected values were not updated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # rs/nns/governance/src/governance.rs
N/A behind feature flag
Why
As part of Mission 70, we want to reduce the maximum dissolve delay from 8 years to 2 years. To maintain the invariant that all neuron dissolve delays are at or below the maximum, existing neurons must be clamped.
https://dfinity.atlassian.net/browse/NNS1-4313
What
MAX_DISSOLVE_DELAY_SECONDSconstant with amax_dissolve_delay_seconds()function that returns 2 years when the mission-70 flag is enabled, 8 years otherwisepost_upgrade, guarded by the flagneuron_id_to_pre_clamp_dissolve_stateGovernance field for recovery purposes (the snapshot doubles as an idempotency guard)NeuronDissolveStateSnapshotprotobuf message and plumb it through heap governance dataTesting
Unit tests added for
clamp_dissolve_delayandclamp_dissolve_delay_for_all_neurons_or_panic. Existing tests updated to use the dynamic max.