-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Loading status checks…
Merge pull request #2 from bitfinity-network/EPROD-969_inspect_message
[EPROD-969] Inspect message check and docs
Showing
13 changed files
with
504 additions
and
74 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,30 @@ | ||
# canister-upgrader | ||
|
||
## Introduction | ||
|
||
The upgrader canister allows the creation of polls to approve upgrade of other canisters. | ||
This is achieved by allowing registered voters to approve or reject upgrades identified by unique hashes. | ||
|
||
## Poll types | ||
|
||
Thee different types of polls can be created: | ||
1. `ProjectHash`: a poll to approve a specific project hash | ||
1. `AddPermission`: a poll to grant permissions to a Principal | ||
1. `RemovePermission`: a poll to remove permissions from a Principal | ||
|
||
For each new poll, the creator has to provide the following informations: | ||
- `description`: The description of the poll, | ||
- `poll_type`: The type of poll as discussed above, | ||
- `start_timestamp_secs`: The timestamp in seconds of when the poll opens | ||
- `end_timestamp_secs`: The timestamp in seconds of when the poll closes | ||
|
||
## User Permissions | ||
|
||
The access to the canister features is restricted by a set of permissions that allow selected Pricipals to operate on the canister. | ||
The available permissions are: | ||
|
||
- `Admin`: this permission grants admin rights to the principal. An admin can directy grant or remove permissions to other principals | ||
- `CreateProject`: Allows calling the endpoints to create a project (e.g. evm, bridge, etc.) | ||
- `CreatePoll`: Allows calling the endpoints to create a poll | ||
- `VotePoll`: Allows calling the endpoints to vote in a poll | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// required by the inspect_message macro | ||
#[allow(unused_imports)] | ||
use ic_exports::ic_cdk::{self, api}; | ||
use ic_exports::ic_kit::ic; | ||
|
||
use crate::canister::UpgraderCanister; | ||
use crate::state::UpgraderCanisterState; | ||
|
||
/// NOTE: inspect is disabled for non-wasm targets because without it we are getting a weird compilation error | ||
/// in CI: | ||
/// > multiple definition of `canister_inspect_message' | ||
#[cfg(target_family = "wasm")] | ||
#[ic_exports::ic_cdk_macros::inspect_message] | ||
fn inspect_messages() { | ||
crate::canister::STATE.with(|state| inspect_message_impl(state)) | ||
} | ||
|
||
#[allow(dead_code)] | ||
fn inspect_message_impl(state: &UpgraderCanisterState) { | ||
// If inspect message is disabled, accept the message | ||
if state.settings.borrow().is_inspect_message_disabled() { | ||
api::call::accept_message(); | ||
return; | ||
} | ||
|
||
let permissions = state.permissions.borrow(); | ||
let method = api::call::method_name(); | ||
|
||
let check_result = match method.as_str() { | ||
method if method.starts_with("admin_") => permissions.check_admin(&ic::caller()), | ||
"project_create" => UpgraderCanister::project_create_inspect(&permissions, &ic::caller()), | ||
"poll_create" => UpgraderCanister::poll_create_inspect(&permissions, &ic::caller()), | ||
"poll_vote" => UpgraderCanister::poll_vote_inspect(&permissions, &ic::caller()), | ||
_ => Ok(()), | ||
}; | ||
|
||
if let Err(e) = check_result { | ||
ic::trap(&format!("Call rejected by inspect check: {e:?}")); | ||
} else { | ||
api::call::accept_message(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
use std::borrow::Cow; | ||
|
||
use candid::{CandidType, Deserialize}; | ||
use ic_stable_structures::stable_structures::Memory; | ||
use ic_stable_structures::{Bound, CellStructure, MemoryManager, StableCell, Storable}; | ||
use serde::Serialize; | ||
use upgrader_canister_did::codec; | ||
|
||
use crate::constant::SETTINGS_MAP_MEMORY_ID; | ||
|
||
pub struct Settings<M: Memory> { | ||
settings: StableCell<SettingsData, M>, | ||
} | ||
|
||
impl<M: Memory> Settings<M> { | ||
/// Create new settings | ||
pub fn new(memory_manager: &dyn MemoryManager<M, u8>) -> Self { | ||
let settings = StableCell::new( | ||
memory_manager.get(SETTINGS_MAP_MEMORY_ID), | ||
Default::default(), | ||
) | ||
.expect("failed to initialize settings in stable memory"); | ||
|
||
Self { settings } | ||
} | ||
|
||
/// Disable the inspect message | ||
pub fn disable_inspect_message(&mut self, disable: bool) { | ||
self.update(|s| { | ||
s.disable_inspect_message = disable; | ||
}); | ||
} | ||
|
||
/// Returns true if the inspect message is disabled | ||
pub fn is_inspect_message_disabled(&self) -> bool { | ||
self.read(|s| s.disable_inspect_message) | ||
} | ||
|
||
fn read<F, T>(&self, f: F) -> T | ||
where | ||
for<'a> F: FnOnce(&'a SettingsData) -> T, | ||
{ | ||
f(self.settings.get()) | ||
} | ||
|
||
fn update<F, T>(&mut self, f: F) -> T | ||
where | ||
for<'a> F: FnOnce(&'a mut SettingsData) -> T, | ||
{ | ||
let cell = &mut self.settings; | ||
let mut new_settings = cell.get().clone(); | ||
let result = f(&mut new_settings); | ||
cell.set(new_settings).expect("failed to set evm settings"); | ||
result | ||
} | ||
} | ||
|
||
#[derive(Debug, Default, Deserialize, CandidType, Clone, PartialEq, Eq, Serialize)] | ||
pub struct SettingsData { | ||
disable_inspect_message: bool, | ||
} | ||
|
||
impl Storable for SettingsData { | ||
fn to_bytes(&self) -> std::borrow::Cow<[u8]> { | ||
codec::encode(self).into() | ||
} | ||
|
||
fn from_bytes(bytes: Cow<[u8]>) -> Self { | ||
codec::decode(&bytes) | ||
} | ||
|
||
const BOUND: Bound = Bound::Unbounded; | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_storable_settings_data() { | ||
let settings = SettingsData::default(); | ||
|
||
let serialized = settings.to_bytes(); | ||
let deserialized = SettingsData::from_bytes(serialized); | ||
|
||
assert_eq!(settings, deserialized); | ||
} | ||
|
||
/// Test inspect message is not disabled by default | ||
#[test] | ||
fn test_default_inspect_message_disabled() { | ||
let settings = SettingsData::default(); | ||
assert!(!settings.disable_inspect_message); | ||
} | ||
|
||
/// Test disabling the inspect message | ||
#[test] | ||
fn test_disable_inspect_message() { | ||
let mut settings = Settings::new(&ic_stable_structures::default_ic_memory_manager()); | ||
assert!(!settings.is_inspect_message_disabled()); | ||
settings.disable_inspect_message(true); | ||
assert!(settings.is_inspect_message_disabled()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters