Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/icp-canister-interfaces/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ publish.workspace = true
[dependencies]
bigdecimal = { workspace = true }
candid = { workspace = true }
ic-management-canister-types = { workspace = true }
serde = { workspace = true }
4 changes: 2 additions & 2 deletions crates/icp-canister-interfaces/src/cycles_ledger.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use candid::{CandidType, Nat, Principal};
use serde::Deserialize;

use crate::management_canister::CanisterSettingsArg;
use ic_management_canister_types::CanisterSettings;

/// 100m cycles
pub const CYCLES_LEDGER_BLOCK_FEE: u128 = 100_000_000;
Expand All @@ -20,7 +20,7 @@ pub enum SubnetSelectionArg {
#[derive(Clone, Debug, CandidType, Deserialize)]
pub struct CreationArgs {
pub subnet_selection: Option<SubnetSelectionArg>,
pub settings: Option<CanisterSettingsArg>,
pub settings: Option<CanisterSettings>,
}

#[derive(Clone, Debug, CandidType, Deserialize)]
Expand Down
1 change: 0 additions & 1 deletion crates/icp-canister-interfaces/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pub mod cycles_minting_canister;
pub mod governance;
pub mod icp_ledger;
pub mod internet_identity;
pub mod management_canister;
pub mod nns_migration;
pub mod nns_root;
pub mod proxy;
Expand Down
33 changes: 0 additions & 33 deletions crates/icp-canister-interfaces/src/management_canister.rs

This file was deleted.

44 changes: 15 additions & 29 deletions crates/icp-cli/src/commands/canister/call.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::{Context as _, anyhow, bail};
use candid::types::{Type, TypeInner};
use candid::{Encode, IDLArgs, Nat, Principal, TypeEnv, types::Function};
use candid::{IDLArgs, Principal, TypeEnv, types::Function};
use candid_parser::assist;
use candid_parser::parse_idl_args;
use candid_parser::utils::CandidSource;
Expand All @@ -12,12 +12,14 @@ use icp::fs;
use icp::manifest::InitArgsFormat;
use icp::parsers::CyclesAmount;
use icp::prelude::*;
use icp_canister_interfaces::proxy::{ProxyArgs, ProxyResult};
use serde::Serialize;
use std::io::{self, Write};
use tracing::{error, warn};

use crate::{commands::args, operations::misc::fetch_canister_metadata};
use crate::{
commands::args, operations::misc::fetch_canister_metadata,
operations::proxy::update_or_proxy_raw,
};

/// How to interpret and display the call response blob.
#[derive(Debug, Clone, Copy, Default, ValueEnum)]
Expand Down Expand Up @@ -206,30 +208,7 @@ pub(crate) async fn exec(ctx: &Context, args: &CallArgs) -> Result<(), anyhow::E
.context("failed to serialize candid arguments with specific types")?,
};

let res = if let Some(proxy_cid) = args.proxy {
// Route the call through the proxy canister
let proxy_args = ProxyArgs {
canister_id: cid,
method: method.clone(),
args: arg_bytes,
cycles: Nat::from(args.cycles.get()),
};
let proxy_arg_bytes =
Encode!(&proxy_args).context("failed to encode proxy call arguments")?;

let proxy_res = agent
.update(&proxy_cid, "proxy")
.with_arg(proxy_arg_bytes)
.await?;

let proxy_result: (ProxyResult,) =
candid::decode_args(&proxy_res).context("failed to decode proxy canister response")?;

match proxy_result.0 {
ProxyResult::Ok(ok) => ok.result,
ProxyResult::Err(err) => bail!(err.format_error()),
}
} else if args.query {
let res = if args.query {
// Preemptive check: error if Candid shows this is an update method
if let Some((_, func)) = &declared_method
&& !func.is_query()
Expand All @@ -245,8 +224,15 @@ pub(crate) async fn exec(ctx: &Context, args: &CallArgs) -> Result<(), anyhow::E
.call()
.await?
} else {
// Direct update call to the target canister
agent.update(&cid, &method).with_arg(arg_bytes).await?
update_or_proxy_raw(
&agent,
cid,
&method,
arg_bytes,
args.proxy,
args.cycles.get(),
)
.await?
};

let mut term = Term::buffered_stdout();
Expand Down
15 changes: 10 additions & 5 deletions crates/icp-cli/src/commands/canister/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ use std::io::stdout;
use anyhow::anyhow;
use candid::{Nat, Principal};
use clap::{ArgGroup, Args, Parser};
use ic_management_canister_types::CanisterSettings as MgmtCanisterSettings;
use icp::context::Context;
use icp::parsers::{CyclesAmount, DurationAmount, MemoryAmount};
use icp::{Canister, context::CanisterSelection, prelude::*};
use icp_canister_interfaces::management_canister::CanisterSettingsArg;
use serde::Serialize;
use tracing::info;

Expand Down Expand Up @@ -112,8 +112,11 @@ pub(crate) struct CreateArgs {
}

impl CreateArgs {
pub(crate) fn canister_settings_with_default(&self, default: &Canister) -> CanisterSettingsArg {
CanisterSettingsArg {
pub(crate) fn canister_settings_with_default(
&self,
default: &Canister,
) -> MgmtCanisterSettings {
MgmtCanisterSettings {
freezing_threshold: self
.settings
.freezing_threshold
Expand Down Expand Up @@ -144,6 +147,7 @@ impl CreateArgs {
.compute_allocation
.or(default.settings.compute_allocation)
.map(Nat::from),
..Default::default()
}
}

Expand All @@ -155,8 +159,8 @@ impl CreateArgs {
}
}

pub(crate) fn canister_settings(&self) -> CanisterSettingsArg {
CanisterSettingsArg {
pub(crate) fn canister_settings(&self) -> MgmtCanisterSettings {
MgmtCanisterSettings {
freezing_threshold: self
.settings
.freezing_threshold
Expand All @@ -180,6 +184,7 @@ impl CreateArgs {
.clone()
.map(|m| Nat::from(m.get())),
compute_allocation: self.settings.compute_allocation.map(Nat::from),
..Default::default()
}
}
}
Expand Down
73 changes: 26 additions & 47 deletions crates/icp-cli/src/operations/create.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
use std::sync::Arc;

use candid::{Decode, Encode, Nat, Principal};
use ic_agent::{
Agent, AgentError,
agent::{Subnet, SubnetType},
};
use ic_management_canister_types::{
CanisterIdRecord, CanisterSettings, CreateCanisterArgs as MgmtCreateCanisterArgs,
};
use icp_canister_interfaces::{
cycles_ledger::{
CYCLES_LEDGER_PRINCIPAL, CreateCanisterArgs, CreateCanisterResponse, CreationArgs,
SubnetSelectionArg,
},
cycles_minting_canister::CYCLES_MINTING_CANISTER_PRINCIPAL,
management_canister::{
CanisterSettingsArg, MgmtCreateCanisterArgs, MgmtCreateCanisterResponse,
},
proxy::{ProxyArgs, ProxyResult},
};
use rand::seq::IndexedRandom;
use snafu::{OptionExt, ResultExt, Snafu};
use std::sync::Arc;
use tokio::sync::OnceCell;

use super::proxy::{UpdateOrProxyError, update_or_proxy};

#[derive(Debug, Snafu)]
pub enum CreateOperationError {
#[snafu(display("failed to encode candid: {source}"))]
Expand Down Expand Up @@ -51,11 +53,8 @@ pub enum CreateOperationError {
#[snafu(display("failed to resolve subnet: {message}"))]
SubnetResolution { message: String },

#[snafu(display("proxy call failed: {message}"))]
ProxyCall { message: String },

#[snafu(display("failed to decode proxy canister response: {source}"))]
ProxyDecode { source: candid::Error },
#[snafu(transparent)]
UpdateOrProxyCall { source: UpdateOrProxyError },
}

/// Determines how a new canister is created.
Expand Down Expand Up @@ -115,7 +114,7 @@ impl CreateOperation {
/// - `Err(CreateOperationError)` if an error occurred.
pub async fn create(
&self,
settings: &CanisterSettingsArg,
settings: &CanisterSettings,
) -> Result<Principal, CreateOperationError> {
if let CreateTarget::Proxy(proxy) = self.inner.target {
return self.create_proxy(settings, proxy).await;
Expand All @@ -141,7 +140,7 @@ impl CreateOperation {

async fn create_ledger(
&self,
settings: &CanisterSettingsArg,
settings: &CanisterSettings,
selected_subnet: Principal,
) -> Result<Principal, CreateOperationError> {
let creation_args = CreationArgs {
Expand Down Expand Up @@ -182,7 +181,7 @@ impl CreateOperation {

async fn create_mgmt(
&self,
settings: &CanisterSettingsArg,
settings: &CanisterSettings,
selected_subnet: &Subnet,
) -> Result<Principal, CreateOperationError> {
let arg = MgmtCreateCanisterArgs {
Expand All @@ -207,51 +206,31 @@ impl CreateOperation {
)
.await
.context(AgentSnafu)?;
let resp = Decode!(&resp, MgmtCreateCanisterResponse).context(CandidDecodeSnafu)?;
let resp: CanisterIdRecord = Decode!(&resp, CanisterIdRecord).context(CandidDecodeSnafu)?;
Ok(resp.canister_id)
}

async fn create_proxy(
&self,
settings: &CanisterSettingsArg,
settings: &CanisterSettings,
proxy: Principal,
) -> Result<Principal, CreateOperationError> {
let mgmt_arg = MgmtCreateCanisterArgs {
let args = MgmtCreateCanisterArgs {
settings: Some(settings.clone()),
sender_canister_version: None,
};
let mgmt_arg_bytes = Encode!(&mgmt_arg).context(CandidEncodeSnafu)?;

let proxy_args = ProxyArgs {
canister_id: Principal::management_canister(),
method: "create_canister".to_string(),
args: mgmt_arg_bytes,
cycles: Nat::from(self.inner.cycles),
};
let proxy_arg_bytes = Encode!(&proxy_args).context(CandidEncodeSnafu)?;

let proxy_res = self
.inner
.agent
.update(&proxy, "proxy")
.with_arg(proxy_arg_bytes)
.await
.context(AgentSnafu)?;

let proxy_result: (ProxyResult,) =
candid::decode_args(&proxy_res).context(ProxyDecodeSnafu)?;

match proxy_result.0 {
ProxyResult::Ok(ok) => {
let resp =
Decode!(&ok.result, MgmtCreateCanisterResponse).context(CandidDecodeSnafu)?;
Ok(resp.canister_id)
}
ProxyResult::Err(err) => ProxyCallSnafu {
message: err.format_error(),
}
.fail(),
}
let (result,): (CanisterIdRecord,) = update_or_proxy(
&self.inner.agent,
Principal::management_canister(),
"create_canister",
(args,),
Some(proxy),
self.inner.cycles,
)
.await?;

Ok(result.canister_id)
}

/// 1. If a subnet is explicitly provided, use it
Expand Down
1 change: 1 addition & 0 deletions crates/icp-cli/src/operations/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub(crate) mod candid_compat;
pub(crate) mod canister_migration;
pub(crate) mod create;
pub(crate) mod install;
pub(crate) mod proxy;
pub(crate) mod settings;
pub(crate) mod snapshot_transfer;
pub(crate) mod sync;
Expand Down
Loading
Loading