From 77f82eebaf7384ce5cf2e7235ab58c2ef06bfae5 Mon Sep 17 00:00:00 2001 From: Andre Popovitch Date: Fri, 10 Jan 2025 00:33:37 -0600 Subject: [PATCH] Add topics list --- .../api/src/ic_sns_governance.pb.v1.rs | 8 ++ rs/sns/governance/api/src/lib.rs | 1 + rs/sns/governance/api/src/topics.rs | 89 ++++++++++++++ rs/sns/governance/canister/canister.rs | 37 ++++-- rs/sns/governance/canister/governance.did | 75 +++++++++++- .../governance/canister/governance_test.did | 75 +++++++++++- .../ic_sns_governance/pb/v1/governance.proto | 9 +- .../src/gen/ic_sns_governance.pb.v1.rs | 9 +- rs/sns/governance/src/governance.rs | 3 + rs/sns/governance/src/lib.rs | 1 + rs/sns/governance/src/pb/conversions.rs | 13 ++ rs/sns/governance/src/proposal.rs | 1 + rs/sns/governance/src/topics.rs | 115 ++++++++++++++++++ rs/sns/governance/src/types.rs | 5 + 14 files changed, 420 insertions(+), 21 deletions(-) create mode 100644 rs/sns/governance/api/src/topics.rs create mode 100644 rs/sns/governance/src/topics.rs diff --git a/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs b/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs index 09f66dafdbeb..a6eb3659aa03 100644 --- a/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs +++ b/rs/sns/governance/api/src/ic_sns_governance.pb.v1.rs @@ -1,3 +1,4 @@ +use crate::topics; use std::collections::BTreeMap; /// A principal with a particular set of permissions over a neuron. @@ -80,6 +81,9 @@ pub struct Neuron { /// The neuron's followees, specified as a map of proposal functions IDs to followees neuron IDs. /// The map's keys are represented by integers as Protobuf does not support enum keys in maps. pub followees: BTreeMap, + /// The neuron's followees on topics, specified as a map of topic IDs to followees neuron IDs. + /// The map's keys are represented by integers as Protobuf does not support enum keys in maps. + pub topic_followees: BTreeMap, /// The accumulated unstaked maturity of the neuron, measured in "e8s equivalent", i.e., in equivalent of /// 10E-8 of a governance token. /// @@ -208,6 +212,8 @@ pub struct NervousSystemFunction { } /// Nested message and enum types in `NervousSystemFunction`. pub mod nervous_system_function { + use super::*; + #[derive(Default, candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub struct GenericNervousSystemFunction { /// The id of the target canister that will be called to execute the proposal. @@ -224,6 +230,8 @@ pub mod nervous_system_function { /// The signature of the method must be equivalent to the following: /// (proposal_data: ProposalData) -> Result pub validator_method_name: Option, + /// The topic this function belongs to + pub topic: Option, } #[derive(candid::CandidType, candid::Deserialize, Debug, Clone, PartialEq)] pub enum FunctionType { diff --git a/rs/sns/governance/api/src/lib.rs b/rs/sns/governance/api/src/lib.rs index 4b2634f4717d..48d036c9ec2c 100644 --- a/rs/sns/governance/api/src/lib.rs +++ b/rs/sns/governance/api/src/lib.rs @@ -1,4 +1,5 @@ pub mod pb; +pub mod topics; /// Formats the 32 bytes of a hash as a hexadecimal string. Corresponds to 64 ascii symbols. pub fn format_full_hash(hash: &[u8]) -> String { diff --git a/rs/sns/governance/api/src/topics.rs b/rs/sns/governance/api/src/topics.rs new file mode 100644 index 000000000000..6c2b80c54927 --- /dev/null +++ b/rs/sns/governance/api/src/topics.rs @@ -0,0 +1,89 @@ +/// Functions are categorized into topics. +/// (As a reminder, a function is either a built-in proposal type, or a generic function that has been added via an +/// AddGenericNervousSystemFunction proposal) +#[derive(Debug, candid::CandidType, candid::Deserialize, Ord, PartialOrd, Eq, Clone, PartialEq)] +pub enum Topic { + NonCriticalProposals, + DaoCommunitySettings, + SnsFrameworkManagement, + DappCanisterManagement, + ApplicationBusinessLogic, + Governance, + TreasuryAssetManagement, + CriticalDappOperations, +} + +mod topic_ids { + pub const NON_CRITICAL_PROPOSALS: u64 = 0; + pub const DAO_COMMUNITY_SETTINGS: u64 = 1; + pub const SNS_FRAMEWORK_MANAGEMENT: u64 = 2; + pub const DAPP_CANISTER_MANAGEMENT: u64 = 3; + pub const APPLICATION_BUSINESS_LOGIC: u64 = 4; + pub const GOVERNANCE: u64 = 5; + pub const TREASURY_ASSET_MANAGEMENT: u64 = 6; + pub const CRITICAL_DAPP_OPERATIONS: u64 = 7; +} + +impl From for u64 { + fn from(topic: Topic) -> Self { + match topic { + Topic::NonCriticalProposals => topic_ids::NON_CRITICAL_PROPOSALS, + Topic::DaoCommunitySettings => topic_ids::DAO_COMMUNITY_SETTINGS, + Topic::SnsFrameworkManagement => topic_ids::SNS_FRAMEWORK_MANAGEMENT, + Topic::DappCanisterManagement => topic_ids::DAPP_CANISTER_MANAGEMENT, + Topic::ApplicationBusinessLogic => topic_ids::APPLICATION_BUSINESS_LOGIC, + Topic::Governance => topic_ids::GOVERNANCE, + Topic::TreasuryAssetManagement => topic_ids::TREASURY_ASSET_MANAGEMENT, + Topic::CriticalDappOperations => topic_ids::CRITICAL_DAPP_OPERATIONS, + } + } +} + +impl TryFrom for Topic { + type Error = (); + + fn try_from(value: u64) -> Result { + match value { + topic_ids::NON_CRITICAL_PROPOSALS => Ok(Topic::NonCriticalProposals), + topic_ids::DAO_COMMUNITY_SETTINGS => Ok(Topic::DaoCommunitySettings), + topic_ids::SNS_FRAMEWORK_MANAGEMENT => Ok(Topic::SnsFrameworkManagement), + topic_ids::DAPP_CANISTER_MANAGEMENT => Ok(Topic::DappCanisterManagement), + topic_ids::APPLICATION_BUSINESS_LOGIC => Ok(Topic::ApplicationBusinessLogic), + topic_ids::GOVERNANCE => Ok(Topic::Governance), + topic_ids::TREASURY_ASSET_MANAGEMENT => Ok(Topic::TreasuryAssetManagement), + topic_ids::CRITICAL_DAPP_OPERATIONS => Ok(Topic::CriticalDappOperations), + _ => Err(()), + } + } +} + +/// Each topic has some information associated with it. This information is for the benefit of the user but has +/// no effect on the behavior of the SNS. +#[derive(Debug, candid::CandidType, candid::Deserialize, Clone, PartialEq)] +pub struct TopicInfo { + pub topic: Topic, + pub name: String, + pub description: String, + pub content: C, + pub nested_topics: Vec>, + pub critical: bool, +} + +#[derive(Debug, candid::CandidType, candid::Deserialize, Clone, PartialEq)] +pub struct BuiltInFunctions { + pub built_in_functions: Vec, +} + +#[derive(Debug, candid::CandidType, candid::Deserialize, Clone, PartialEq)] +pub struct BuiltInAndGenericFunctions { + pub built_in_functions: Vec, + pub generic_functions: Vec, +} + +#[derive(Debug, candid::CandidType, candid::Deserialize, Clone, PartialEq)] +pub struct ListTopicsRequest {} + +#[derive(Debug, candid::CandidType, candid::Deserialize, Clone, PartialEq)] +pub struct ListTopicsResponse { + pub topics: Option>>, +} diff --git a/rs/sns/governance/canister/canister.rs b/rs/sns/governance/canister/canister.rs index 3a0b80b66ad6..df8edd4c8845 100644 --- a/rs/sns/governance/canister/canister.rs +++ b/rs/sns/governance/canister/canister.rs @@ -27,24 +27,27 @@ use ic_sns_governance::{ types::{Environment, HeapGrowthPotential}, upgrade_journal::serve_journal, }; -use ic_sns_governance_api::pb::v1::{ - get_running_sns_version_response::UpgradeInProgress, governance::Version, - ClaimSwapNeuronsRequest, ClaimSwapNeuronsResponse, FailStuckUpgradeInProgressRequest, - FailStuckUpgradeInProgressResponse, GetMaturityModulationRequest, - GetMaturityModulationResponse, GetMetadataRequest, GetMetadataResponse, GetMode, - GetModeResponse, GetNeuron, GetNeuronResponse, GetProposal, GetProposalResponse, - GetRunningSnsVersionRequest, GetRunningSnsVersionResponse, - GetSnsInitializationParametersRequest, GetSnsInitializationParametersResponse, - GetUpgradeJournalRequest, GetUpgradeJournalResponse, ListNervousSystemFunctionsResponse, - ListNeurons, ListNeuronsResponse, ListProposals, ListProposalsResponse, ManageNeuron, - ManageNeuronResponse, NervousSystemParameters, RewardEvent, SetMode, SetModeResponse, -}; #[cfg(feature = "test")] use ic_sns_governance_api::pb::v1::{ AddMaturityRequest, AddMaturityResponse, AdvanceTargetVersionRequest, AdvanceTargetVersionResponse, GovernanceError, MintTokensRequest, MintTokensResponse, Neuron, RefreshCachedUpgradeStepsRequest, RefreshCachedUpgradeStepsResponse, }; +use ic_sns_governance_api::{ + pb::v1::{ + get_running_sns_version_response::UpgradeInProgress, governance::Version, + ClaimSwapNeuronsRequest, ClaimSwapNeuronsResponse, FailStuckUpgradeInProgressRequest, + FailStuckUpgradeInProgressResponse, GetMaturityModulationRequest, + GetMaturityModulationResponse, GetMetadataRequest, GetMetadataResponse, GetMode, + GetModeResponse, GetNeuron, GetNeuronResponse, GetProposal, GetProposalResponse, + GetRunningSnsVersionRequest, GetRunningSnsVersionResponse, + GetSnsInitializationParametersRequest, GetSnsInitializationParametersResponse, + GetUpgradeJournalRequest, GetUpgradeJournalResponse, ListNervousSystemFunctionsResponse, + ListNeurons, ListNeuronsResponse, ListProposals, ListProposalsResponse, ManageNeuron, + ManageNeuronResponse, NervousSystemParameters, RewardEvent, SetMode, SetModeResponse, + }, + topics::{ListTopicsRequest, ListTopicsResponse}, +}; use prost::Message; use rand::{RngCore, SeedableRng}; use rand_chacha::ChaCha20Rng; @@ -383,9 +386,10 @@ async fn manage_neuron(request: ManageNeuron) -> ManageNeuronResponse { fn update_neuron(neuron: Neuron) -> Option { log!(INFO, "update_neuron"); let governance = governance_mut(); + let neuron = sns_gov_pb::Neuron::from(neuron); measure_span(governance.profiling_information, "update_neuron", || { governance - .update_neuron(sns_gov_pb::Neuron::from(neuron)) + .update_neuron(neuron) .map_err(GovernanceError::from) .err() }) @@ -450,6 +454,13 @@ fn list_nervous_system_functions() -> ListNervousSystemFunctionsResponse { ListNervousSystemFunctionsResponse::from(governance().list_nervous_system_functions()) } +/// Returns the current list of topics. +#[query] +fn list_topics(_: ListTopicsRequest) -> ListTopicsResponse { + log!(INFO, "list_topics"); + unimplemented!() +} + /// Returns the latest reward event. #[query] fn get_latest_reward_event() -> RewardEvent { diff --git a/rs/sns/governance/canister/governance.did b/rs/sns/governance/canister/governance.did index b379d8687ebd..367d43ae75a4 100644 --- a/rs/sns/governance/canister/governance.did +++ b/rs/sns/governance/canister/governance.did @@ -225,6 +225,7 @@ type GenericNervousSystemFunction = record { target_canister_id : opt principal; validator_method_name : opt text; target_method_name : opt text; + topic: opt Topic; }; type GetMaturityModulationResponse = record { @@ -278,9 +279,44 @@ type CachedUpgradeSteps = record { response_timestamp_seconds : opt nat64; }; +type NeuronInit = record { + id : opt NeuronId; + staked_maturity_e8s_equivalent : opt nat64; + permissions : vec NeuronPermission; + maturity_e8s_equivalent : nat64; + cached_neuron_stake_e8s : nat64; + created_timestamp_seconds : nat64; + source_nns_neuron_id : opt nat64; + auto_stake_maturity : opt bool; + aging_since_timestamp_seconds : nat64; + dissolve_state : opt DissolveState; + voting_power_percentage_multiplier : nat64; + vesting_period_seconds : opt nat64; + disburse_maturity_in_progress : vec DisburseMaturityInProgress; + followees : vec record { nat64; Followees }; + topic_followees : vec record { nat64; Followees }; + neuron_fees_e8s : nat64; +}; + +type NervousSystemFunctionInit = record { + id : nat64; + name : text; + description : opt text; + function_type : opt variant { + NativeNervousSystemFunction : record {}; + GenericNervousSystemFunction : record { + validator_canister_id : opt principal; + target_canister_id : opt principal; + validator_method_name : opt text; + target_method_name : opt text; + topic: opt nat64; + }; + }; +}; + type Governance = record { root_canister_id : opt principal; - id_to_nervous_system_functions : vec record { nat64; NervousSystemFunction }; + id_to_nervous_system_functions : vec record { nat64; NervousSystemFunctionInit }; metrics : opt GovernanceCachedMetrics; maturity_modulation : opt MaturityModulation; mode : int32; @@ -293,10 +329,10 @@ type Governance = record { pending_version : opt PendingVersion; swap_canister_id : opt principal; ledger_canister_id : opt principal; - proposals : vec record { nat64; ProposalData }; + proposals : vec record { nat64; ProposalData }; // this would also change but I haven't done it yet in_flight_commands : vec record { text; NeuronInFlightCommand }; sns_metadata : opt ManageSnsMetadata; - neurons : vec record { text; Neuron }; + neurons : vec record { text; NeuronInit }; genesis_timestamp_seconds : nat64; target_version : opt Version; timers : opt Timers; @@ -483,6 +519,17 @@ type NervousSystemParameters = record { max_number_of_principals_per_neuron : opt nat64; }; +type Topic = variant { + NonCriticalProposals; + DaoCommunitySettings; + SnsFrameworkManagement; + DappCanisterManagement; + ApplicationBusinessLogic; + Governance; + TreasuryAssetManagement; + CriticalDappOperations; +}; + type Neuron = record { id : opt NeuronId; staked_maturity_e8s_equivalent : opt nat64; @@ -498,6 +545,7 @@ type Neuron = record { vesting_period_seconds : opt nat64; disburse_maturity_in_progress : vec DisburseMaturityInProgress; followees : vec record { nat64; Followees }; + topic_followees : vec record { Topic; Followees }; neuron_fees_e8s : nat64; }; @@ -822,6 +870,26 @@ type GetUpgradeJournalResponse = record { upgrade_journal_entry_count: opt nat64; }; +type ListTopicsRequest = record {}; + +type BuiltInAndGenericFunctions = record { + built_in_functions : vec nat64; + generic_functions : vec nat64; +}; + +type TopicInfo = record { + topic : Topic; + name : text; + description : text; + content : BuiltInAndGenericFunctions; + nested_topics : vec TopicInfo; + critical : bool; +}; + +type ListTopicsResponse = record { + topics: opt vec TopicInfo; +}; + service : (Governance) -> { claim_swap_neurons : (ClaimSwapNeuronsRequest) -> (ClaimSwapNeuronsResponse); fail_stuck_upgrade_in_progress : (record {}) -> (record {}); @@ -840,6 +908,7 @@ service : (Governance) -> { list_nervous_system_functions : () -> (ListNervousSystemFunctionsResponse) query; list_neurons : (ListNeurons) -> (ListNeuronsResponse) query; list_proposals : (ListProposals) -> (ListProposalsResponse) query; + list_topics : (ListTopicsRequest) -> (ListTopicsResponse) query; manage_neuron : (ManageNeuron) -> (ManageNeuronResponse); set_mode : (SetMode) -> (record {}); reset_timers : (record {}) -> (record {}); diff --git a/rs/sns/governance/canister/governance_test.did b/rs/sns/governance/canister/governance_test.did index 4ba441aabdac..09c680eaf0e0 100644 --- a/rs/sns/governance/canister/governance_test.did +++ b/rs/sns/governance/canister/governance_test.did @@ -234,6 +234,7 @@ type GenericNervousSystemFunction = record { target_canister_id : opt principal; validator_method_name : opt text; target_method_name : opt text; + topic: opt Topic; }; type GetMaturityModulationResponse = record { @@ -287,9 +288,44 @@ type CachedUpgradeSteps = record { response_timestamp_seconds : opt nat64; }; +type NeuronInit = record { + id : opt NeuronId; + staked_maturity_e8s_equivalent : opt nat64; + permissions : vec NeuronPermission; + maturity_e8s_equivalent : nat64; + cached_neuron_stake_e8s : nat64; + created_timestamp_seconds : nat64; + source_nns_neuron_id : opt nat64; + auto_stake_maturity : opt bool; + aging_since_timestamp_seconds : nat64; + dissolve_state : opt DissolveState; + voting_power_percentage_multiplier : nat64; + vesting_period_seconds : opt nat64; + disburse_maturity_in_progress : vec DisburseMaturityInProgress; + followees : vec record { nat64; Followees }; + topic_followees : vec record { nat64; Followees }; + neuron_fees_e8s : nat64; +}; + +type NervousSystemFunctionInit = record { + id : nat64; + name : text; + description : opt text; + function_type : opt variant { + NativeNervousSystemFunction : record {}; + GenericNervousSystemFunction : record { + validator_canister_id : opt principal; + target_canister_id : opt principal; + validator_method_name : opt text; + target_method_name : opt text; + topic: opt nat64; + }; + }; +}; + type Governance = record { root_canister_id : opt principal; - id_to_nervous_system_functions : vec record { nat64; NervousSystemFunction }; + id_to_nervous_system_functions : vec record { nat64; NervousSystemFunctionInit }; metrics : opt GovernanceCachedMetrics; maturity_modulation : opt MaturityModulation; mode : int32; @@ -302,10 +338,10 @@ type Governance = record { pending_version : opt PendingVersion; swap_canister_id : opt principal; ledger_canister_id : opt principal; - proposals : vec record { nat64; ProposalData }; + proposals : vec record { nat64; ProposalData }; // this would also change but I haven't done it yet in_flight_commands : vec record { text; NeuronInFlightCommand }; sns_metadata : opt ManageSnsMetadata; - neurons : vec record { text; Neuron }; + neurons : vec record { text; NeuronInit }; genesis_timestamp_seconds : nat64; target_version : opt Version; timers : opt Timers; @@ -497,6 +533,17 @@ type NervousSystemParameters = record { max_number_of_principals_per_neuron : opt nat64; }; +type Topic = variant { + NonCriticalProposals; + DaoCommunitySettings; + SnsFrameworkManagement; + DappCanisterManagement; + ApplicationBusinessLogic; + Governance; + TreasuryAssetManagement; + CriticalDappOperations; +}; + type Neuron = record { id : opt NeuronId; staked_maturity_e8s_equivalent : opt nat64; @@ -512,6 +559,7 @@ type Neuron = record { vesting_period_seconds : opt nat64; disburse_maturity_in_progress : vec DisburseMaturityInProgress; followees : vec record { nat64; Followees }; + topic_followees : vec record { Topic; Followees }; neuron_fees_e8s : nat64; }; @@ -839,6 +887,26 @@ type GetUpgradeJournalResponse = record { type AdvanceTargetVersionRequest = record { target_version : opt Version; }; type AdvanceTargetVersionResponse = record {}; +type ListTopicsRequest = record {}; + +type BuiltInAndGenericFunctions = record { + built_in_functions : vec nat64; + generic_functions : vec nat64; +}; + +type TopicInfo = record { + topic : Topic; + name : text; + description : text; + content : BuiltInAndGenericFunctions; + nested_topics : vec TopicInfo; + critical : bool; +}; + +type ListTopicsResponse = record { + topics: opt vec TopicInfo; +}; + service : (Governance) -> { add_maturity : (AddMaturityRequest) -> (AddMaturityResponse); claim_swap_neurons : (ClaimSwapNeuronsRequest) -> (ClaimSwapNeuronsResponse); @@ -858,6 +926,7 @@ service : (Governance) -> { list_nervous_system_functions : () -> (ListNervousSystemFunctionsResponse) query; list_neurons : (ListNeurons) -> (ListNeuronsResponse) query; list_proposals : (ListProposals) -> (ListProposalsResponse) query; + list_topics : (ListTopicsRequest) -> (ListTopicsResponse) query; manage_neuron : (ManageNeuron) -> (ManageNeuronResponse); mint_tokens : (MintTokensRequest) -> (record {}); set_mode : (SetMode) -> (record {}); diff --git a/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto b/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto index f26318098b26..d973bfb88e75 100644 --- a/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto +++ b/rs/sns/governance/proto/ic_sns_governance/pb/v1/governance.proto @@ -18,7 +18,7 @@ enum NeuronPermissionType { NEURON_PERMISSION_TYPE_CONFIGURE_DISSOLVE_STATE = 1; // The principal has permission to add additional principals to modify the neuron. - // The nervous system parameter `NervousSystemParameters::neuron_grantable_permissions` + // The nervous system para meter `NervousSystemParameters::neuron_grantable_permissions` // determines the maximum set of privileges that a principal can grant to another principal in // the given SNS. NEURON_PERMISSION_TYPE_MANAGE_PRINCIPALS = 2; @@ -168,6 +168,10 @@ message Neuron { // The map's keys are represented by integers as Protobuf does not support enum keys in maps. map followees = 11; + // The neuron's followees on topics, specified as a map of topic IDs to followees neuron IDs. + // The map's keys are represented by integers as Protobuf does not support enum keys in maps. + map topic_followees = 19; + // The accumulated unstaked maturity of the neuron, measured in "e8s equivalent", i.e., in equivalent of // 10E-8 of a governance token. // @@ -275,6 +279,9 @@ message NervousSystemFunction { // The signature of the method must be equivalent to the following: // (proposal_data: ProposalData) -> Result optional string validator_method_name = 5; + + // The topic this function belongs to + optional uint64 topic = 6; } oneof function_type { diff --git a/rs/sns/governance/src/gen/ic_sns_governance.pb.v1.rs b/rs/sns/governance/src/gen/ic_sns_governance.pb.v1.rs index 543f636048e6..2c8e9484aab1 100644 --- a/rs/sns/governance/src/gen/ic_sns_governance.pb.v1.rs +++ b/rs/sns/governance/src/gen/ic_sns_governance.pb.v1.rs @@ -118,6 +118,10 @@ pub struct Neuron { /// The map's keys are represented by integers as Protobuf does not support enum keys in maps. #[prost(btree_map = "uint64, message", tag = "11")] pub followees: ::prost::alloc::collections::BTreeMap, + /// The neuron's followees on topics, specified as a map of topic IDs to followees neuron IDs. + /// The map's keys are represented by integers as Protobuf does not support enum keys in maps. + #[prost(btree_map = "uint64, message", tag = "19")] + pub topic_followees: ::prost::alloc::collections::BTreeMap, /// The accumulated unstaked maturity of the neuron, measured in "e8s equivalent", i.e., in equivalent of /// 10E-8 of a governance token. /// @@ -310,6 +314,9 @@ pub mod nervous_system_function { /// (proposal_data: ProposalData) -> Result #[prost(string, optional, tag = "5")] pub validator_method_name: ::core::option::Option<::prost::alloc::string::String>, + /// The topic this function belongs to + #[prost(uint64, optional, tag = "6")] + pub topic: ::core::option::Option, } #[derive( candid::CandidType, @@ -3802,7 +3809,7 @@ pub enum NeuronPermissionType { /// start dissolving, stop dissolving, and increasing the dissolve delay for the neuron. ConfigureDissolveState = 1, /// The principal has permission to add additional principals to modify the neuron. - /// The nervous system parameter `NervousSystemParameters::neuron_grantable_permissions` + /// The nervous system para meter `NervousSystemParameters::neuron_grantable_permissions` /// determines the maximum set of privileges that a principal can grant to another principal in /// the given SNS. ManagePrincipals = 2, diff --git a/rs/sns/governance/src/governance.rs b/rs/sns/governance/src/governance.rs index 2f254ed42af0..65dc5ef91458 100644 --- a/rs/sns/governance/src/governance.rs +++ b/rs/sns/governance/src/governance.rs @@ -1373,6 +1373,7 @@ impl Governance { created_timestamp_seconds: creation_timestamp_seconds, aging_since_timestamp_seconds: parent_neuron.aging_since_timestamp_seconds, followees: parent_neuron.followees.clone(), + topic_followees: parent_neuron.topic_followees.clone(), maturity_e8s_equivalent: 0, dissolve_state: parent_neuron.dissolve_state, voting_power_percentage_multiplier: parent_neuron.voting_power_percentage_multiplier, @@ -4009,6 +4010,7 @@ impl Governance { created_timestamp_seconds: now, aging_since_timestamp_seconds: now, followees: self.default_followees_or_panic().followees, + topic_followees: BTreeMap::new(), maturity_e8s_equivalent: 0, dissolve_state: Some(DissolveState::DissolveDelaySeconds(0)), // A neuron created through the `claim_or_refresh` ManageNeuron command will @@ -4175,6 +4177,7 @@ impl Governance { created_timestamp_seconds: now, aging_since_timestamp_seconds: now, followees: neuron_recipe.construct_followees(), + topic_followees: neuron_recipe.construct_topic_followees(), maturity_e8s_equivalent: 0, dissolve_state: Some(DissolveState::DissolveDelaySeconds( neuron_recipe.get_dissolve_delay_seconds_or_panic(), diff --git a/rs/sns/governance/src/lib.rs b/rs/sns/governance/src/lib.rs index 837b1c00a7b6..bd1a1490a43b 100644 --- a/rs/sns/governance/src/lib.rs +++ b/rs/sns/governance/src/lib.rs @@ -12,6 +12,7 @@ pub mod proposal; mod request_impls; pub mod reward; pub mod sns_upgrade; +pub mod topics; mod treasury; pub mod types; pub mod upgrade_journal; diff --git a/rs/sns/governance/src/pb/conversions.rs b/rs/sns/governance/src/pb/conversions.rs index 7a14fbd1ad9e..9d2f8e85490d 100644 --- a/rs/sns/governance/src/pb/conversions.rs +++ b/rs/sns/governance/src/pb/conversions.rs @@ -1,5 +1,6 @@ use crate::pb::v1 as pb; use ic_sns_governance_api::pb::v1 as pb_api; +use ic_sns_governance_api::topics; impl From for pb_api::NeuronPermission { fn from(item: pb::NeuronPermission) -> Self { @@ -90,6 +91,11 @@ impl From for pb_api::Neuron { .into_iter() .map(|(k, v)| (k, v.into())) .collect(), + topic_followees: item + .topic_followees + .into_iter() + .map(|(k, v)| (topics::Topic::try_from(k).unwrap(), v.into())) // TODO: DO NOT MERGE: Let's handle this error in a better way + .collect(), maturity_e8s_equivalent: item.maturity_e8s_equivalent, voting_power_percentage_multiplier: item.voting_power_percentage_multiplier, source_nns_neuron_id: item.source_nns_neuron_id, @@ -119,6 +125,11 @@ impl From for pb::Neuron { .into_iter() .map(|(k, v)| (k, v.into())) .collect(), + topic_followees: item + .topic_followees + .into_iter() + .map(|(k, v)| (u64::from(k), v.into())) + .collect(), maturity_e8s_equivalent: item.maturity_e8s_equivalent, voting_power_percentage_multiplier: item.voting_power_percentage_multiplier, source_nns_neuron_id: item.source_nns_neuron_id, @@ -201,6 +212,7 @@ impl From { fn from(item: pb::nervous_system_function::GenericNervousSystemFunction) -> Self { Self { + topic: item.topic.and_then(|x| topics::Topic::try_from(x).ok()), target_canister_id: item.target_canister_id, target_method_name: item.target_method_name, validator_canister_id: item.validator_canister_id, @@ -213,6 +225,7 @@ impl From { fn from(item: pb_api::nervous_system_function::GenericNervousSystemFunction) -> Self { Self { + topic: item.topic.map(|x| u64::from(x)), target_canister_id: item.target_canister_id, target_method_name: item.target_method_name, validator_canister_id: item.validator_canister_id, diff --git a/rs/sns/governance/src/proposal.rs b/rs/sns/governance/src/proposal.rs index 6aaae38eddce..07e3887786b8 100644 --- a/rs/sns/governance/src/proposal.rs +++ b/rs/sns/governance/src/proposal.rs @@ -1288,6 +1288,7 @@ impl TryFrom<&NervousSystemFunction> for ValidGenericNervousSystemFunction { target_method_name, validator_canister_id, validator_method_name, + topic: _, // TODO: probably should do something with this })) => { // Validate the target_canister_id field. let target_canister_id = diff --git a/rs/sns/governance/src/topics.rs b/rs/sns/governance/src/topics.rs new file mode 100644 index 000000000000..bbdc67181a50 --- /dev/null +++ b/rs/sns/governance/src/topics.rs @@ -0,0 +1,115 @@ +use ic_sns_governance_api::topics::{BuiltInFunctions, Topic, TopicInfo}; + +/// Returns an exhaustive list of topic descriptions, each corresponding to a topic. +/// Topics may be nested within other topics, and each topic may have a list of built-in functions that are categorized within that topic. +pub fn topic_descriptions() -> Vec> { + use crate::types::native_action_ids::{ + ADD_GENERIC_NERVOUS_SYSTEM_FUNCTION, ADVANCE_SNS_TARGET_VERSION, DEREGISTER_DAPP_CANISTERS, + MANAGE_DAPP_CANISTER_SETTINGS, MANAGE_LEDGER_PARAMETERS, MANAGE_NERVOUS_SYSTEM_PARAMETERS, + MANAGE_SNS_METADATA, MINT_SNS_TOKENS, MOTION, REGISTER_DAPP_CANISTERS, + REMOVE_GENERIC_NERVOUS_SYSTEM_FUNCTION, TRANSFER_SNS_TREASURY_FUNDS, + UPGRADE_SNS_CONTROLLED_CANISTER, UPGRADE_SNS_TO_NEXT_VERSION, + }; + + vec![ + TopicInfo:: { + topic: Topic::NonCriticalProposals, + name: "Non-critical proposals".to_string(), + description: "All proposals that are not considered \"critical\".".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![], + }, + nested_topics: vec![ + TopicInfo:: { + topic: Topic::DaoCommunitySettings, + name: "DAO community settings".to_string(), + description: "Proposals to set the direction of the DAO by tokenomics & branding, such as the name and description, token name etc".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![ + MANAGE_NERVOUS_SYSTEM_PARAMETERS, + MANAGE_LEDGER_PARAMETERS, + MANAGE_SNS_METADATA, + ], + }, + nested_topics: vec![], + critical: false, + }, + TopicInfo:: { + topic: Topic::SnsFrameworkManagement, + name: "SNS framework management".to_string(), + description: "Proposals to upgrade and manage the SNS DAO framework.".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![ + UPGRADE_SNS_TO_NEXT_VERSION, + ADVANCE_SNS_TARGET_VERSION, + ], + }, + nested_topics: vec![], + critical: false, + }, + TopicInfo:: { + topic: Topic::DappCanisterManagement, + name: "Dapp canister management".to_string(), + description: "Proposals to upgrade the registered dapp canisters and dapp upgrades via built-in or custom logic and updates to frontend assets.".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![ + UPGRADE_SNS_CONTROLLED_CANISTER, + REGISTER_DAPP_CANISTERS, + MANAGE_DAPP_CANISTER_SETTINGS, + ], + }, + nested_topics: vec![], + critical: false, + }, + TopicInfo:: { + topic: Topic::ApplicationBusinessLogic, + name: "Application Business Logic".to_string(), + description: "Proposals that are custom to what the governed dapp requires.".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![], + }, + nested_topics: vec![], + critical: false, + }, + TopicInfo:: { + topic: Topic::Governance, + name: "Governance".to_string(), + description: "Proposals that represent community polls or other forms of community opinion but don’t have any immediate effect in terms of code changes.".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![MOTION], + }, + nested_topics: vec![], + critical: false, + } + ], + critical: false, + }, + TopicInfo:: { + topic: Topic::TreasuryAssetManagement, + name: "Treasury & asset management".to_string(), + description: "Proposals to move and manage assets that are DAO-owned, including tokens in the treasury, tokens in liquidity pools, or DAO-owned neurons.".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![ + TRANSFER_SNS_TREASURY_FUNDS, + MINT_SNS_TOKENS, + ], + }, + nested_topics: vec![], + critical: true, + }, + TopicInfo:: { + topic: Topic::CriticalDappOperations, + name: "Critical Dapp Operations".to_string(), + description: "Proposals to execute critical operations on dapps, such as adding or removing dapps from the SNS, or executing custom logic on dapps.".to_string(), + content: BuiltInFunctions { + built_in_functions: vec![ + DEREGISTER_DAPP_CANISTERS, + ADD_GENERIC_NERVOUS_SYSTEM_FUNCTION, + REMOVE_GENERIC_NERVOUS_SYSTEM_FUNCTION, + ], + }, + nested_topics: vec![], + critical: true, + }, + ] +} diff --git a/rs/sns/governance/src/types.rs b/rs/sns/governance/src/types.rs index 343afd39b6d6..73cd0aeebcbe 100644 --- a/rs/sns/governance/src/types.rs +++ b/rs/sns/governance/src/types.rs @@ -2301,6 +2301,11 @@ impl NeuronRecipe { } } + /// Adds self.topic_followee entries + pub(crate) fn construct_topic_followees(&self) -> BTreeMap { + BTreeMap::new() + } + pub(crate) fn construct_auto_staking_maturity(&self) -> Option { if self.is_neurons_fund_neuron() { Some(true)