From 307303a935cabb2987883c015fb1117d87885401 Mon Sep 17 00:00:00 2001 From: Hamish Peebles Date: Thu, 12 Oct 2023 14:53:00 +0100 Subject: [PATCH] Store whether submitting proposals is enabled or not in the Registry (#4564) --- Cargo.lock | 1 + backend/canister_installer/src/lib.rs | 2 ++ backend/canisters/proposals_bot/CHANGELOG.md | 4 ++++ .../proposals_bot/api/src/lifecycle/init.rs | 1 + .../canisters/proposals_bot/impl/Cargo.toml | 1 + .../canisters/proposals_bot/impl/src/lib.rs | 8 +++++-- .../proposals_bot/impl/src/lifecycle/init.rs | 2 +- .../impl/src/lifecycle/post_upgrade.rs | 20 +++++++++++++++++- .../stake_neuron_for_submitting_proposals.rs | 9 ++++++++ backend/canisters/registry/CHANGELOG.md | 1 + backend/canisters/registry/api/src/lib.rs | 2 ++ .../registry/api/src/lifecycle/init.rs | 1 + .../c2c_set_submitting_proposals_enabled.rs | 14 +++++++++++++ .../canisters/registry/api/src/updates/mod.rs | 1 + .../canisters/registry/c2c_client/src/lib.rs | 1 + backend/canisters/registry/impl/src/guards.rs | 8 +++++++ .../impl/src/jobs/check_for_new_snses.rs | 1 + backend/canisters/registry/impl/src/lib.rs | 15 +++++++++++++ .../registry/impl/src/lifecycle/init.rs | 1 + .../impl/src/model/nervous_systems.rs | 19 +++++++++++++++++ .../c2c_set_submitting_proposals_enabled.rs | 21 +++++++++++++++++++ .../registry/impl/src/updates/mod.rs | 1 + backend/integration_tests/src/setup.rs | 2 ++ 23 files changed, 132 insertions(+), 4 deletions(-) create mode 100644 backend/canisters/registry/api/src/updates/c2c_set_submitting_proposals_enabled.rs create mode 100644 backend/canisters/registry/impl/src/updates/c2c_set_submitting_proposals_enabled.rs diff --git a/Cargo.lock b/Cargo.lock index 956c3ac148..b03efef23d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4957,6 +4957,7 @@ dependencies = [ "canister_tracing_macros", "community_canister", "community_canister_c2c_client", + "fire_and_forget_handler", "group_canister", "group_canister_c2c_client", "group_index_canister", diff --git a/backend/canister_installer/src/lib.rs b/backend/canister_installer/src/lib.rs index 316de7b244..2dae961523 100644 --- a/backend/canister_installer/src/lib.rs +++ b/backend/canister_installer/src/lib.rs @@ -106,6 +106,7 @@ async fn install_service_canisters_impl( service_owner_principals: vec![principal], user_index_canister_id: canister_ids.user_index, group_index_canister_id: canister_ids.group_index, + registry_canister_id: canister_ids.registry, nns_governance_canister_id: canister_ids.nns_governance, sns_wasm_canister_id: canister_ids.nns_sns_wasm, cycles_dispenser_canister_id: canister_ids.cycles_dispenser, @@ -153,6 +154,7 @@ async fn install_service_canisters_impl( let registry_canister_wasm = get_canister_wasm(CanisterName::Registry, version); let registry_init_args = registry_canister::init::Args { governance_principals: vec![principal], + proposals_bot_canister_id: canister_ids.proposals_bot, nns_ledger_canister_id: canister_ids.nns_ledger, nns_governance_canister_id: canister_ids.nns_governance, nns_root_canister_id: canister_ids.nns_root, diff --git a/backend/canisters/proposals_bot/CHANGELOG.md b/backend/canisters/proposals_bot/CHANGELOG.md index 5e62357f28..e71c6fefa3 100644 --- a/backend/canisters/proposals_bot/CHANGELOG.md +++ b/backend/canisters/proposals_bot/CHANGELOG.md @@ -5,6 +5,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [unreleased] +### Added + +- Store whether submitting proposals is enabled or not in the Registry ([#4564](https://github.com/open-chat-labs/open-chat/pull/4564)) + ### Changed - Retry submitting proposal if looking up user fails ([#4543](https://github.com/open-chat-labs/open-chat/pull/4543)) diff --git a/backend/canisters/proposals_bot/api/src/lifecycle/init.rs b/backend/canisters/proposals_bot/api/src/lifecycle/init.rs index 5495177271..ef1cb4638b 100644 --- a/backend/canisters/proposals_bot/api/src/lifecycle/init.rs +++ b/backend/canisters/proposals_bot/api/src/lifecycle/init.rs @@ -7,6 +7,7 @@ pub struct Args { pub service_owner_principals: Vec, pub user_index_canister_id: CanisterId, pub group_index_canister_id: CanisterId, + pub registry_canister_id: CanisterId, pub nns_governance_canister_id: CanisterId, pub sns_wasm_canister_id: CanisterId, pub cycles_dispenser_canister_id: CanisterId, diff --git a/backend/canisters/proposals_bot/impl/Cargo.toml b/backend/canisters/proposals_bot/impl/Cargo.toml index c48f90f0b5..8bcdeb0d61 100644 --- a/backend/canisters/proposals_bot/impl/Cargo.toml +++ b/backend/canisters/proposals_bot/impl/Cargo.toml @@ -18,6 +18,7 @@ canister_timer_jobs = { path = "../../../libraries/canister_timer_jobs" } canister_tracing_macros = { path = "../../../libraries/canister_tracing_macros" } community_canister = { path = "../../community/api" } community_canister_c2c_client = { path = "../../community/c2c_client" } +fire_and_forget_handler = { path = "../../../libraries/fire_and_forget_handler" } group_canister = { path = "../../group/api" } group_canister_c2c_client = { path = "../../group/c2c_client" } group_index_canister = { path = "../../group_index/api" } diff --git a/backend/canisters/proposals_bot/impl/src/lib.rs b/backend/canisters/proposals_bot/impl/src/lib.rs index ef85c15ab8..a3401c7dee 100644 --- a/backend/canisters/proposals_bot/impl/src/lib.rs +++ b/backend/canisters/proposals_bot/impl/src/lib.rs @@ -3,6 +3,7 @@ use crate::timer_job_types::TimerJob; use candid::{CandidType, Principal}; use canister_state_macros::canister_state; use canister_timer_jobs::TimerJobs; +use fire_and_forget_handler::FireAndForgetHandler; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::cell::RefCell; @@ -79,6 +80,8 @@ struct Data { pub timer_jobs: TimerJobs, #[serde(default)] pub registry_synced_up_to: TimestampMillis, + #[serde(default)] + pub fire_and_forget_handler: FireAndForgetHandler, pub test_mode: bool, } @@ -91,9 +94,9 @@ impl Data { governance_principals: HashSet, user_index_canister_id: CanisterId, group_index_canister_id: CanisterId, + registry_canister_id: CanisterId, cycles_dispenser_canister_id: CanisterId, nns_governance_canister_id: CanisterId, - registry_canister_id: CanisterId, test_mode: bool, ) -> Data { Data { @@ -101,12 +104,13 @@ impl Data { governance_principals, user_index_canister_id, group_index_canister_id, + registry_canister_id, cycles_dispenser_canister_id, nns_governance_canister_id, - registry_canister_id, finished_proposals_to_process: VecDeque::new(), timer_jobs: TimerJobs::default(), registry_synced_up_to: 0, + fire_and_forget_handler: FireAndForgetHandler::default(), test_mode, } } diff --git a/backend/canisters/proposals_bot/impl/src/lifecycle/init.rs b/backend/canisters/proposals_bot/impl/src/lifecycle/init.rs index 23e12bcf40..cea3396cf4 100644 --- a/backend/canisters/proposals_bot/impl/src/lifecycle/init.rs +++ b/backend/canisters/proposals_bot/impl/src/lifecycle/init.rs @@ -18,9 +18,9 @@ fn init(args: Args) { args.service_owner_principals.into_iter().collect(), args.user_index_canister_id, args.group_index_canister_id, + args.registry_canister_id, args.cycles_dispenser_canister_id, args.nns_governance_canister_id, - args.sns_wasm_canister_id, args.test_mode, ); diff --git a/backend/canisters/proposals_bot/impl/src/lifecycle/post_upgrade.rs b/backend/canisters/proposals_bot/impl/src/lifecycle/post_upgrade.rs index db208a44c7..b37313eb44 100644 --- a/backend/canisters/proposals_bot/impl/src/lifecycle/post_upgrade.rs +++ b/backend/canisters/proposals_bot/impl/src/lifecycle/post_upgrade.rs @@ -1,12 +1,14 @@ use crate::lifecycle::{init_env, init_state, UPGRADE_BUFFER_SIZE}; use crate::memory::get_upgrades_memory; -use crate::Data; +use crate::{mutate_state, Data}; use canister_logger::LogEntry; use canister_tracing_macros::trace; use ic_cdk_macros::post_upgrade; use ic_stable_structures::reader::{BufferedReader, Reader}; use proposals_bot_canister::post_upgrade::Args; +use std::time::Duration; use tracing::info; +use types::CanisterId; use utils::cycles::init_cycles_dispenser_client; #[post_upgrade] @@ -25,4 +27,20 @@ fn post_upgrade(args: Args) { init_state(env, data, args.wasm_version); info!(version = %args.wasm_version, "Post-upgrade complete"); + + // TODO Remove this after next upgrade + ic_cdk_timers::set_timer(Duration::ZERO, enable_submitting_oc_proposals); +} + +fn enable_submitting_oc_proposals() { + mutate_state(|state| { + state.data.fire_and_forget_handler.send( + state.data.registry_canister_id, + "c2c_set_submitting_proposals_enabled_msgpack".to_string(), + msgpack::serialize_then_unwrap(registry_canister::c2c_set_submitting_proposals_enabled::Args { + governance_canister_id: CanisterId::from_text("2jvtu-yqaaa-aaaaq-aaama-cai").unwrap(), + enabled: true, + }), + ); + }); } diff --git a/backend/canisters/proposals_bot/impl/src/updates/stake_neuron_for_submitting_proposals.rs b/backend/canisters/proposals_bot/impl/src/updates/stake_neuron_for_submitting_proposals.rs index eb9e2fe23f..7de9ebadbc 100644 --- a/backend/canisters/proposals_bot/impl/src/updates/stake_neuron_for_submitting_proposals.rs +++ b/backend/canisters/proposals_bot/impl/src/updates/stake_neuron_for_submitting_proposals.rs @@ -43,6 +43,15 @@ async fn stake_neuron_for_submitting_proposals(args: Args) -> Response { .data .nervous_systems .set_neuron_id_for_submitting_proposals(&args.governance_canister_id, neuron_id); + + state.data.fire_and_forget_handler.send( + state.data.registry_canister_id, + "c2c_set_submitting_proposals_enabled_msgpack".to_string(), + msgpack::serialize_then_unwrap(registry_canister::c2c_set_submitting_proposals_enabled::Args { + governance_canister_id: args.governance_canister_id, + enabled: true, + }), + ); }); Success(neuron_id) } diff --git a/backend/canisters/registry/CHANGELOG.md b/backend/canisters/registry/CHANGELOG.md index baf77675e2..6087b339d4 100644 --- a/backend/canisters/registry/CHANGELOG.md +++ b/backend/canisters/registry/CHANGELOG.md @@ -8,6 +8,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Added `c2c_nervous_systems` ([#4557](https://github.com/open-chat-labs/open-chat/pull/4557)) +- Store whether submitting proposals is enabled or not in the Registry ([#4564](https://github.com/open-chat-labs/open-chat/pull/4564)) ### Changed diff --git a/backend/canisters/registry/api/src/lib.rs b/backend/canisters/registry/api/src/lib.rs index 879dd192a4..30501c40cc 100644 --- a/backend/canisters/registry/api/src/lib.rs +++ b/backend/canisters/registry/api/src/lib.rs @@ -46,6 +46,8 @@ pub struct NervousSystemDetails { pub min_dissolve_delay_to_vote: Milliseconds, pub proposal_rejection_fee: u64, pub is_nns: bool, + #[serde(default)] + pub submitting_proposals_enabled: bool, pub added: TimestampMillis, pub last_updated: TimestampMillis, } diff --git a/backend/canisters/registry/api/src/lifecycle/init.rs b/backend/canisters/registry/api/src/lifecycle/init.rs index 0886409bfb..bc25982126 100644 --- a/backend/canisters/registry/api/src/lifecycle/init.rs +++ b/backend/canisters/registry/api/src/lifecycle/init.rs @@ -5,6 +5,7 @@ use types::{BuildVersion, CanisterId}; #[derive(CandidType, Serialize, Deserialize, Debug)] pub struct Args { pub governance_principals: Vec, + pub proposals_bot_canister_id: CanisterId, pub nns_ledger_canister_id: CanisterId, pub nns_governance_canister_id: CanisterId, pub nns_root_canister_id: CanisterId, diff --git a/backend/canisters/registry/api/src/updates/c2c_set_submitting_proposals_enabled.rs b/backend/canisters/registry/api/src/updates/c2c_set_submitting_proposals_enabled.rs new file mode 100644 index 0000000000..40f2bcd42b --- /dev/null +++ b/backend/canisters/registry/api/src/updates/c2c_set_submitting_proposals_enabled.rs @@ -0,0 +1,14 @@ +use candid::CandidType; +use serde::{Deserialize, Serialize}; +use types::CanisterId; + +#[derive(CandidType, Serialize, Deserialize, Debug)] +pub struct Args { + pub governance_canister_id: CanisterId, + pub enabled: bool, +} + +#[derive(CandidType, Serialize, Deserialize, Debug)] +pub enum Response { + Success, +} diff --git a/backend/canisters/registry/api/src/updates/mod.rs b/backend/canisters/registry/api/src/updates/mod.rs index 05a1d25eef..fd5a550c0b 100644 --- a/backend/canisters/registry/api/src/updates/mod.rs +++ b/backend/canisters/registry/api/src/updates/mod.rs @@ -1,2 +1,3 @@ pub mod add_token; +pub mod c2c_set_submitting_proposals_enabled; pub mod update_token; diff --git a/backend/canisters/registry/c2c_client/src/lib.rs b/backend/canisters/registry/c2c_client/src/lib.rs index db36cfcec5..ad520a593c 100644 --- a/backend/canisters/registry/c2c_client/src/lib.rs +++ b/backend/canisters/registry/c2c_client/src/lib.rs @@ -5,3 +5,4 @@ use registry_canister::*; generate_c2c_call!(c2c_nervous_systems); // Updates +generate_c2c_call!(c2c_set_submitting_proposals_enabled); diff --git a/backend/canisters/registry/impl/src/guards.rs b/backend/canisters/registry/impl/src/guards.rs index 2581a3d0e6..3638334749 100644 --- a/backend/canisters/registry/impl/src/guards.rs +++ b/backend/canisters/registry/impl/src/guards.rs @@ -7,3 +7,11 @@ pub fn caller_is_governance_principal() -> Result<(), String> { Err("Caller is not a governance principal".to_string()) } } + +pub fn caller_is_proposals_bot() -> Result<(), String> { + if read_state(|state| state.is_caller_proposals_bot()) { + Ok(()) + } else { + Err("Caller is not the proposals bot".to_string()) + } +} diff --git a/backend/canisters/registry/impl/src/jobs/check_for_new_snses.rs b/backend/canisters/registry/impl/src/jobs/check_for_new_snses.rs index e173b6e0f2..0754571b76 100644 --- a/backend/canisters/registry/impl/src/jobs/check_for_new_snses.rs +++ b/backend/canisters/registry/impl/src/jobs/check_for_new_snses.rs @@ -112,6 +112,7 @@ fn build_nervous_system_details( min_neuron_stake: parameters.neuron_minimum_stake_e8s?, proposal_rejection_fee: parameters.reject_cost_e8s?, is_nns: false, + submitting_proposals_enabled: false, added: now, last_updated: now, }) diff --git a/backend/canisters/registry/impl/src/lib.rs b/backend/canisters/registry/impl/src/lib.rs index 09036d9fa3..3cd638b7a4 100644 --- a/backend/canisters/registry/impl/src/lib.rs +++ b/backend/canisters/registry/impl/src/lib.rs @@ -40,6 +40,10 @@ impl RuntimeState { self.data.governance_principals.contains(&caller) } + pub fn is_caller_proposals_bot(&self) -> bool { + self.env.caller() == self.data.proposals_bot_canister_id + } + pub fn metrics(&self) -> Metrics { Metrics { memory_used: utils::memory::used(), @@ -52,6 +56,7 @@ impl RuntimeState { nervous_systems: self.data.nervous_systems.get_all().iter().map(|ns| ns.into()).collect(), failed_sns_launches: self.data.failed_sns_launches.iter().copied().collect(), canister_ids: CanisterIds { + proposals_bot: self.data.proposals_bot_canister_id, sns_wasm: self.data.sns_wasm_canister_id, cycles_dispenser: self.data.cycles_dispenser_canister_id, }, @@ -62,6 +67,8 @@ impl RuntimeState { #[derive(Serialize, Deserialize)] struct Data { governance_principals: HashSet, + #[serde(default = "proposals_bot_canister_id")] + proposals_bot_canister_id: CanisterId, sns_wasm_canister_id: CanisterId, cycles_dispenser_canister_id: CanisterId, tokens: Tokens, @@ -71,15 +78,21 @@ struct Data { test_mode: bool, } +fn proposals_bot_canister_id() -> CanisterId { + CanisterId::from_text("iywa7-ayaaa-aaaaf-aemga-cai").unwrap() +} + impl Data { pub fn new( governance_principals: HashSet, + proposals_bot_canister_id: CanisterId, sns_wasm_canister_id: CanisterId, cycles_dispenser_canister_id: CanisterId, test_mode: bool, ) -> Data { Data { governance_principals, + proposals_bot_canister_id, sns_wasm_canister_id, cycles_dispenser_canister_id, tokens: Tokens::default(), @@ -113,6 +126,7 @@ impl Data { min_neuron_stake: 100_000_000, proposal_rejection_fee: 1_000_000_000, is_nns: true, + submitting_proposals_enabled: false, added: now, last_updated: now, }, @@ -154,6 +168,7 @@ pub struct Metrics { #[derive(Serialize)] pub struct CanisterIds { + pub proposals_bot: CanisterId, pub sns_wasm: CanisterId, pub cycles_dispenser: CanisterId, } diff --git a/backend/canisters/registry/impl/src/lifecycle/init.rs b/backend/canisters/registry/impl/src/lifecycle/init.rs index 0bcf5bfd4d..cb9fdfbee0 100644 --- a/backend/canisters/registry/impl/src/lifecycle/init.rs +++ b/backend/canisters/registry/impl/src/lifecycle/init.rs @@ -16,6 +16,7 @@ fn init(args: Args) { let env = init_env(); let mut data = Data::new( args.governance_principals.into_iter().collect(), + args.proposals_bot_canister_id, args.sns_wasm_canister_id, args.cycles_dispenser_canister_id, args.test_mode, diff --git a/backend/canisters/registry/impl/src/model/nervous_systems.rs b/backend/canisters/registry/impl/src/model/nervous_systems.rs index 438cbc6f43..fa8cecad9a 100644 --- a/backend/canisters/registry/impl/src/model/nervous_systems.rs +++ b/backend/canisters/registry/impl/src/model/nervous_systems.rs @@ -30,6 +30,23 @@ impl NervousSystems { pub fn last_updated(&self) -> TimestampMillis { self.last_updated } + + pub fn set_submitting_proposals_enabled( + &mut self, + governance_canister_id: CanisterId, + enabled: bool, + now: TimestampMillis, + ) { + if let Some(ns) = self + .nervous_systems + .iter_mut() + .find(|ns| ns.governance_canister_id == governance_canister_id) + { + ns.submitting_proposals_enabled = enabled; + ns.last_updated = now; + self.last_updated = now; + } + } } #[derive(Serialize)] @@ -48,6 +65,7 @@ pub struct NervousSystemMetrics { min_dissolve_delay_to_vote: Milliseconds, proposal_rejection_fee: u64, is_nns: bool, + submitting_proposals_enabled: bool, added: TimestampMillis, last_updated: TimestampMillis, } @@ -69,6 +87,7 @@ impl From<&NervousSystemDetails> for NervousSystemMetrics { min_dissolve_delay_to_vote: value.min_dissolve_delay_to_vote, proposal_rejection_fee: value.proposal_rejection_fee, is_nns: value.is_nns, + submitting_proposals_enabled: value.submitting_proposals_enabled, added: value.added, last_updated: value.last_updated, } diff --git a/backend/canisters/registry/impl/src/updates/c2c_set_submitting_proposals_enabled.rs b/backend/canisters/registry/impl/src/updates/c2c_set_submitting_proposals_enabled.rs new file mode 100644 index 0000000000..f6a44bbb41 --- /dev/null +++ b/backend/canisters/registry/impl/src/updates/c2c_set_submitting_proposals_enabled.rs @@ -0,0 +1,21 @@ +use crate::guards::caller_is_proposals_bot; +use crate::{mutate_state, RuntimeState}; +use canister_api_macros::update_msgpack; +use canister_tracing_macros::trace; +use registry_canister::c2c_set_submitting_proposals_enabled::{Response::*, *}; + +#[update_msgpack(guard = "caller_is_proposals_bot")] +#[trace] +fn c2c_set_submitting_proposals_enabled(args: Args) -> Response { + mutate_state(|state| c2c_set_submitting_proposals_enabled_impl(args, state)) +} + +fn c2c_set_submitting_proposals_enabled_impl(args: Args, state: &mut RuntimeState) -> Response { + let now = state.env.now(); + state + .data + .nervous_systems + .set_submitting_proposals_enabled(args.governance_canister_id, args.enabled, now); + + Success +} diff --git a/backend/canisters/registry/impl/src/updates/mod.rs b/backend/canisters/registry/impl/src/updates/mod.rs index 0eb3eba881..f6ed6f2ddf 100644 --- a/backend/canisters/registry/impl/src/updates/mod.rs +++ b/backend/canisters/registry/impl/src/updates/mod.rs @@ -1,3 +1,4 @@ pub mod add_token; +pub mod c2c_set_submitting_proposals_enabled; pub mod update_token; pub mod wallet_receive; diff --git a/backend/integration_tests/src/setup.rs b/backend/integration_tests/src/setup.rs index 55a59ef0ae..f7add6f298 100644 --- a/backend/integration_tests/src/setup.rs +++ b/backend/integration_tests/src/setup.rs @@ -142,6 +142,7 @@ fn install_canisters(env: &mut StateMachine, controller: Principal) -> CanisterI service_owner_principals: vec![controller], user_index_canister_id, group_index_canister_id, + registry_canister_id, nns_governance_canister_id, sns_wasm_canister_id, cycles_dispenser_canister_id, @@ -207,6 +208,7 @@ fn install_canisters(env: &mut StateMachine, controller: Principal) -> CanisterI let registry_init_args = registry_canister::init::Args { governance_principals: vec![controller], + proposals_bot_canister_id, nns_ledger_canister_id, nns_root_canister_id, nns_governance_canister_id,