Skip to content

Commit

Permalink
feat(nns): Validate manage network economics. (#3859)
Browse files Browse the repository at this point in the history
# Reference(s)

Closes [NNS1-3498].

[NNS1-3498]: https://dfinity.atlassian.net/browse/NNS1-3498
  • Loading branch information
daniel-wong-dfinity-org authored Feb 12, 2025
1 parent 8a3737f commit 2008d47
Show file tree
Hide file tree
Showing 6 changed files with 799 additions and 32 deletions.
96 changes: 78 additions & 18 deletions rs/nns/governance/src/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use crate::{
reassemble_governance_proto, split_governance_proto, HeapGovernanceData, XdrConversionRate,
},
migrations::maybe_run_migrations,
network_economics::InheritFrom,
neuron::{DissolveStateAndAge, Neuron, NeuronBuilder, Visibility},
neuron_data_validation::{NeuronDataValidationSummary, NeuronDataValidator},
neuron_store::{
Expand Down Expand Up @@ -4356,8 +4355,7 @@ impl Governance {
}
}
Action::ManageNetworkEconomics(network_economics) => {
self.perform_manage_network_economics(network_economics);
self.set_proposal_execution_status(pid, Ok(()));
self.perform_manage_network_economics(pid, network_economics);
}
// A motion is not executed, just recorded for posterity.
Action::Motion(_) => {
Expand Down Expand Up @@ -4522,20 +4520,40 @@ impl Governance {
);
}

fn perform_manage_network_economics(&mut self, new_network_economics: NetworkEconomics) {
let Some(original_network_economics) = &self.heap_data.economics else {
// This wouldn't happen in production, but if it does, we try to do
// the best we can, because doing nothing seems more catastrophic.
println!(
"{}ERROR: NetworkEconomics was not set. Setting to proposed NetworkEconomics:\n{:#?}",
LOG_PREFIX, new_network_economics,
);
self.heap_data.economics = Some(new_network_economics);
return;
};
fn perform_manage_network_economics(
&mut self,
proposal_id: u64,
proposed_network_economics: NetworkEconomics,
) {
let result = self.perform_manage_network_economics_impl(proposed_network_economics);
self.set_proposal_execution_status(proposal_id, result);
}

/// Only call this from perform_manage_network_economics.
fn perform_manage_network_economics_impl(
&mut self,
proposed_network_economics: NetworkEconomics,
) -> Result<(), GovernanceError> {
let new_network_economics = self
.economics()
.apply_changes_and_validate(&proposed_network_economics)
.map_err(|defects| {
GovernanceError::new_with_message(
ErrorType::InvalidProposal,
format!(
"The resulting NetworkEconomics is invalid for the following reason(s):\
\n - {}",
defects.join("\n - "),
),
)
})?;

self.heap_data.economics =
Some(new_network_economics.inherit_from(original_network_economics));
println!(
"{}INFO: Committing new NetworkEconomics:\n{:#?}",
LOG_PREFIX, new_network_economics,
);
self.heap_data.economics = Some(new_network_economics);
Ok(())
}

async fn perform_install_code(&mut self, proposal_id: u64, install_code: InstallCode) {
Expand Down Expand Up @@ -4883,6 +4901,45 @@ impl Governance {
Ok(())
}

/// This verifies the following:
///
/// 1. When the changes are applied, the resulting NetworkEconomics is
/// valid. See NetworkEconomics::validate.
///
/// Since self.heap_data.economics can be different when a proposal is
/// executed (compared to when it is created), this should be performed both
/// at proposal creation time AND execution time.
///
/// Note that it is not considered "invalid" when the "modified" result is
/// the same as the original (i.e. setting F to V even though the current
/// value of F is ALREADY V). This is because such a proposal is not
/// actually harmful to the system; just maybe confusing to users.
fn validate_manage_network_economics(
&self,
// (Note that this is the value associated with ManageNetworkEconomics,
// not the resulting NetworkEconomics.)
proposed_network_economics: &NetworkEconomics,
) -> Result<(), GovernanceError> {
// It maybe does not make sense to be able to set transaction_fee_e8s
// via proposal. What we probably want instead is to fetch this value
// from ledger.

self.economics()
.apply_changes_and_validate(proposed_network_economics)
.map_err(|defects| {
let message = format!(
"The resulting settings would not be valid for the \
following reason(s):\n\
- {}",
defects.join("\n - "),
);

GovernanceError::new_with_message(ErrorType::InvalidProposal, message)
})?;

Ok(())
}

pub(crate) fn economics(&self) -> &NetworkEconomics {
self.heap_data
.economics
Expand Down Expand Up @@ -4960,8 +5017,11 @@ impl Governance {
Action::ManageNeuron(manage_neuron) => {
self.validate_manage_neuron_proposal(manage_neuron)
}
Action::ManageNetworkEconomics(_)
| Action::ApproveGenesisKyc(_)
Action::ManageNetworkEconomics(network_economics) => {
self.validate_manage_network_economics(network_economics)
}

Action::ApproveGenesisKyc(_)
| Action::AddOrRemoveNodeProvider(_)
| Action::RewardNodeProvider(_)
| Action::RewardNodeProviders(_)
Expand Down
14 changes: 12 additions & 2 deletions rs/nns/governance/src/governance_proto_builder.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::pb::v1::{
Governance as GovernancePb, NetworkEconomics as NetworkEconomicsPb, Neuron as NeuronPb,
ProposalData as ProposalPb, RewardEvent as RewardEventPb,
NeuronsFundEconomics, ProposalData as ProposalPb, RewardEvent as RewardEventPb,
VotingPowerEconomics,
};

pub struct GovernanceProtoBuilder {
Expand All @@ -16,13 +17,22 @@ impl Default for GovernanceProtoBuilder {
impl GovernanceProtoBuilder {
/// Minimaly valid Governance proto.
pub fn new() -> Self {
let governance_proto = GovernancePb {
let mut governance_proto = GovernancePb {
wait_for_quiet_threshold_seconds: 1,
short_voting_period_seconds: 30,
neuron_management_voting_period_seconds: Some(30),
economics: Some(NetworkEconomicsPb::default()),
..Default::default()
};

// Make economics valid. Ideally, we'd use
// NetworkEconomics::with_default_values(), but many tests rely on
// NetworkEconomics::default() (not the same!).
let economics = governance_proto.economics.as_mut().unwrap();
economics.max_proposals_to_keep_per_topic = 100;
economics.neurons_fund_economics = Some(NeuronsFundEconomics::with_default_values());
economics.voting_power_economics = Some(VotingPowerEconomics::with_default_values());

Self { governance_proto }
}

Expand Down
Loading

0 comments on commit 2008d47

Please sign in to comment.