-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
23 changed files
with
2,105 additions
and
64 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
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
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,18 @@ | ||
[package] | ||
name = "ic_message" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
candid = { workspace = true } | ||
ciborium = { workspace = true } | ||
serde = { workspace = true } | ||
getrandom = { workspace = true } | ||
ic-cdk = { workspace = true } | ||
ic-stable-structures = { workspace = true } | ||
ic_cose_types = { workspace = true } |
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,4 @@ | ||
type ChainArgs = variant { Upgrade : UpgradeArgs; Init : InitArgs }; | ||
type InitArgs = record { managers : vec principal; name : text }; | ||
type UpgradeArgs = record { managers : opt vec principal; name : opt text }; | ||
service : (opt ChainArgs) -> {} |
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,70 @@ | ||
use candid::{CandidType, Principal}; | ||
use serde::Deserialize; | ||
use std::collections::BTreeSet; | ||
|
||
use crate::store; | ||
|
||
#[derive(Clone, Debug, CandidType, Deserialize)] | ||
pub enum ChainArgs { | ||
Init(InitArgs), | ||
Upgrade(UpgradeArgs), | ||
} | ||
|
||
#[derive(Clone, Debug, CandidType, Deserialize)] | ||
pub struct InitArgs { | ||
name: String, | ||
managers: BTreeSet<Principal>, | ||
} | ||
|
||
#[derive(Clone, Debug, CandidType, Deserialize)] | ||
pub struct UpgradeArgs { | ||
name: Option<String>, | ||
managers: Option<BTreeSet<Principal>>, | ||
} | ||
|
||
#[ic_cdk::init] | ||
fn init(args: Option<ChainArgs>) { | ||
match args { | ||
None => {} | ||
Some(ChainArgs::Init(args)) => { | ||
store::state::with_mut(|s| { | ||
s.name = args.name; | ||
s.managers = args.managers; | ||
}); | ||
} | ||
Some(ChainArgs::Upgrade(_)) => { | ||
ic_cdk::trap( | ||
"cannot initialize the canister with an Upgrade args. Please provide an Init args.", | ||
); | ||
} | ||
} | ||
} | ||
|
||
#[ic_cdk::pre_upgrade] | ||
fn pre_upgrade() { | ||
store::state::save(); | ||
} | ||
|
||
#[ic_cdk::post_upgrade] | ||
fn post_upgrade(args: Option<ChainArgs>) { | ||
store::state::load(); | ||
|
||
match args { | ||
Some(ChainArgs::Upgrade(args)) => { | ||
store::state::with_mut(|s| { | ||
if let Some(name) = args.name { | ||
s.name = name; | ||
} | ||
if let Some(managers) = args.managers { | ||
s.managers = managers; | ||
} | ||
}); | ||
} | ||
Some(ChainArgs::Init(_)) => { | ||
ic_cdk::trap( | ||
"cannot upgrade the canister with an Init args. Please provide an Upgrade args.", | ||
); | ||
} | ||
_ => {} | ||
} | ||
} |
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 @@ | ||
use ic_cose_types::ANONYMOUS; | ||
|
||
mod api_init; | ||
mod store; | ||
|
||
use crate::api_init::ChainArgs; | ||
|
||
fn is_controller() -> Result<(), String> { | ||
let caller = ic_cdk::caller(); | ||
if ic_cdk::api::is_controller(&caller) { | ||
Ok(()) | ||
} else { | ||
Err("user is not a controller".to_string()) | ||
} | ||
} | ||
|
||
fn is_authenticated() -> Result<(), String> { | ||
if ic_cdk::caller() == ANONYMOUS { | ||
Err("anonymous user is not allowed".to_string()) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
|
||
#[cfg(all( | ||
target_arch = "wasm32", | ||
target_vendor = "unknown", | ||
target_os = "unknown" | ||
))] | ||
/// A getrandom implementation that always fails | ||
pub fn always_fail(_buf: &mut [u8]) -> Result<(), getrandom::Error> { | ||
Err(getrandom::Error::UNSUPPORTED) | ||
} | ||
|
||
#[cfg(all( | ||
target_arch = "wasm32", | ||
target_vendor = "unknown", | ||
target_os = "unknown" | ||
))] | ||
getrandom::register_custom_getrandom!(always_fail); | ||
|
||
ic_cdk::export_candid!(); |
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,129 @@ | ||
use candid::Principal; | ||
use ciborium::{from_reader, from_reader_with_buffer, into_writer}; | ||
use ic_stable_structures::{ | ||
memory_manager::{MemoryId, MemoryManager, VirtualMemory}, | ||
storable::Bound, | ||
DefaultMemoryImpl, StableBTreeMap, StableCell, Storable, | ||
}; | ||
use serde::{Deserialize, Serialize}; | ||
use std::{borrow::Cow, cell::RefCell, collections::BTreeSet}; | ||
|
||
type Memory = VirtualMemory<DefaultMemoryImpl>; | ||
|
||
#[derive(Clone, Default, Deserialize, Serialize)] | ||
pub struct State { | ||
pub name: String, | ||
pub managers: BTreeSet<Principal>, | ||
} | ||
|
||
impl Storable for State { | ||
const BOUND: Bound = Bound::Unbounded; | ||
|
||
fn to_bytes(&self) -> Cow<[u8]> { | ||
let mut buf = vec![]; | ||
into_writer(self, &mut buf).expect("failed to encode State data"); | ||
Cow::Owned(buf) | ||
} | ||
|
||
fn from_bytes(bytes: Cow<'_, [u8]>) -> Self { | ||
from_reader(&bytes[..]).expect("failed to decode State data") | ||
} | ||
} | ||
|
||
#[derive(Clone, Deserialize, Serialize)] | ||
pub struct User { | ||
#[serde(rename = "n")] | ||
pub name: String, | ||
#[serde(rename = "i")] | ||
pub image: String, | ||
#[serde(rename = "p")] | ||
pub profile_canister: Principal, // profile canister | ||
#[serde(rename = "cn")] | ||
pub cose_namespace: Option<(Principal, String)>, // namespace in shared COSE service | ||
} | ||
|
||
impl Storable for User { | ||
const BOUND: Bound = Bound::Unbounded; | ||
|
||
fn to_bytes(&self) -> Cow<[u8]> { | ||
let mut buf = vec![]; | ||
into_writer(self, &mut buf).expect("failed to encode User data"); | ||
Cow::Owned(buf) | ||
} | ||
|
||
fn from_bytes(bytes: Cow<'_, [u8]>) -> Self { | ||
from_reader(&bytes[..]).expect("failed to decode User data") | ||
} | ||
} | ||
|
||
const STATE_MEMORY_ID: MemoryId = MemoryId::new(0); | ||
const NAME_MEMORY_ID: MemoryId = MemoryId::new(1); | ||
const USER_MEMORY_ID: MemoryId = MemoryId::new(2); | ||
|
||
thread_local! { | ||
static STATE: RefCell<State> = RefCell::new(State::default()); | ||
|
||
static MEMORY_MANAGER: RefCell<MemoryManager<DefaultMemoryImpl>> = | ||
RefCell::new(MemoryManager::init(DefaultMemoryImpl::default())); | ||
|
||
static STATE_STORE: RefCell<StableCell<Vec<u8>, Memory>> = RefCell::new( | ||
StableCell::init( | ||
MEMORY_MANAGER.with_borrow(|m| m.get(STATE_MEMORY_ID)), | ||
Vec::new() | ||
).expect("failed to init STATE store") | ||
); | ||
|
||
static NAME_STORE: RefCell<StableBTreeMap<String, Principal, Memory>> = RefCell::new( | ||
StableBTreeMap::init( | ||
MEMORY_MANAGER.with_borrow(|m| m.get(NAME_MEMORY_ID)), | ||
) | ||
); | ||
|
||
static USER_STORE: RefCell<StableBTreeMap<Principal, User, Memory>> = RefCell::new( | ||
StableBTreeMap::init( | ||
MEMORY_MANAGER.with_borrow(|m| m.get(USER_MEMORY_ID)), | ||
) | ||
); | ||
} | ||
|
||
pub mod state { | ||
use super::*; | ||
|
||
pub fn with<R>(f: impl FnOnce(&State) -> R) -> R { | ||
STATE.with(|r| f(&r.borrow())) | ||
} | ||
|
||
pub fn with_mut<R>(f: impl FnOnce(&mut State) -> R) -> R { | ||
STATE.with(|r| f(&mut r.borrow_mut())) | ||
} | ||
|
||
pub fn is_manager(caller: &Principal) -> Result<(), String> { | ||
STATE.with(|r| match r.borrow().managers.contains(caller) { | ||
true => Ok(()), | ||
false => Err("caller is not a manager".to_string()), | ||
}) | ||
} | ||
|
||
pub fn load() { | ||
let mut scratch = [0; 4096]; | ||
STATE_STORE.with(|r| { | ||
STATE.with(|h| { | ||
let v: State = from_reader_with_buffer(&r.borrow().get()[..], &mut scratch) | ||
.expect("failed to decode STATE_STORE data"); | ||
*h.borrow_mut() = v; | ||
}); | ||
}); | ||
} | ||
|
||
pub fn save() { | ||
STATE.with(|h| { | ||
STATE_STORE.with(|r| { | ||
let mut buf = vec![]; | ||
into_writer(&(*h.borrow()), &mut buf).expect("failed to encode STATE_STORE data"); | ||
r.borrow_mut() | ||
.set(buf) | ||
.expect("failed to set STATE_STORE data"); | ||
}); | ||
}); | ||
} | ||
} |
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,19 @@ | ||
[package] | ||
name = "ic_message_channel" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
|
||
[dependencies] | ||
candid = { workspace = true } | ||
ciborium = { workspace = true } | ||
serde = { workspace = true } | ||
serde_bytes = { workspace = true } | ||
getrandom = { workspace = true } | ||
ic-cdk = { workspace = true } | ||
ic-stable-structures = { workspace = true } | ||
ic_cose_types = { workspace = true } |
Oops, something went wrong.