Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ pem = "1.0.2"
proptest = "1.0.0"
reqwest = { version = "0.12.4", default-features = false, features = [
"rustls-tls",
"blocking",
] }
ring = "0.16.11"
schemars = "0.8"
Expand All @@ -72,7 +73,7 @@ tempfile = "3.3.0"
thiserror = "1.0.24"
time = "0.3.9"
tokio = "1.35"
url = { version="2.1.0", features=["serde"] }
url = { version = "2.1.0", features = ["serde"] }
walkdir = "2.3.2"

[profile.release]
Expand Down
4 changes: 4 additions & 0 deletions src/dfx-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ edition.workspace = true
repository.workspace = true
license.workspace = true
rust-version.workspace = true
build = "src/build.rs"

[build-dependencies]
reqwest.workspace = true

[dependencies]
aes-gcm.workspace = true
Expand Down
35 changes: 35 additions & 0 deletions src/dfx-core/src/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::{env, fs::File, io::Write, path::Path};

const CANISTER_IDS_URL: &str = "https://raw.githubusercontent.com/dfinity/ic/1402bf35308ec9bd87356c26f7c430f49b49423a/rs/nns/canister_ids.json";
fn define_well_known_canisters() {
let well_known_canisters = reqwest::blocking::get(CANISTER_IDS_URL)
.unwrap()
.error_for_status()
.unwrap()
.text()
.unwrap();

let out_dir = env::var("OUT_DIR").unwrap();
let loader_path = Path::new(&out_dir).join("well_known_canisters.rs");
let mut f = File::create(loader_path).unwrap();
f.write_all(
format!(
"
const WELL_KNOWN_CANISTERS: &str = r#\"
{}
\"#;
pub fn map_wellknown_canisters() -> CanisterIds {{
serde_json::from_str(WELL_KNOWN_CANISTERS).unwrap_or(CanisterIds::new())
}}
",
well_known_canisters.replace("mainnet", "ic")
)
.as_bytes(),
)
.unwrap()
}

fn main() {
define_well_known_canisters();
}
14 changes: 14 additions & 0 deletions src/dfx-core/src/config/model/canister_id_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use std::time::{Duration, SystemTime};
use time::format_description::well_known::Rfc3339;
use time::OffsetDateTime;

include!(concat!(env!("OUT_DIR"), "/well_known_canisters.rs"));

pub type CanisterName = String;
pub type NetworkName = String;
pub type CanisterIdString = String;
Expand Down Expand Up @@ -94,6 +96,8 @@ pub struct CanisterIdStore {
// which does not include remote canister ids
ids: CanisterIds,

well_known_ids: CanisterIds,

// Only canisters that will time out at some point have their timestamp of acquisition saved
acquisition_timestamps: CanisterTimestamps,

Expand Down Expand Up @@ -166,6 +170,7 @@ impl CanisterIdStore {
acquisition_timestamps,
remote_ids,
pull_ids,
well_known_ids: map_wellknown_canisters(),
};

if let NetworkTypeDescriptor::Playground {
Expand All @@ -189,6 +194,7 @@ impl CanisterIdStore {
self.remote_ids
.as_ref()
.and_then(|remote_ids| self.get_name_in(canister_id, remote_ids))
.or_else(|| self.get_name_in(canister_id, &self.well_known_ids))
.or_else(|| self.get_name_in_project(canister_id))
.or_else(|| self.get_name_in_pull_ids(canister_id))
}
Expand Down Expand Up @@ -246,6 +252,7 @@ impl CanisterIdStore {
.as_ref()
.and_then(|remote_ids| self.find_in(canister_name, remote_ids))
.or_else(|| self.find_in(canister_name, &self.ids))
.or_else(|| self.find_in(canister_name, &self.well_known_ids))
.or_else(|| self.pull_ids.get(canister_name).copied())
}
pub fn get_name_id_map(&self) -> BTreeMap<String, String> {
Expand Down Expand Up @@ -293,6 +300,13 @@ impl CanisterIdStore {
.and_then(|s| CanisterId::from_text(s).ok())
}

pub fn is_well_known(&self, canister_id: &CanisterId) -> bool {
let canister_str = canister_id.to_string();
self.well_known_ids
.values()
.any(|val| val.values().any(|k| &canister_str == k))
}

pub fn get(&self, canister_name: &str) -> Result<CanisterId, CanisterIdStoreError> {
self.find(canister_name).ok_or_else(|| {
let network = if self.network_descriptor.name == "local" {
Expand Down
17 changes: 14 additions & 3 deletions src/dfx/src/commands/canister/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ use crate::commands::canister::call::get_effective_canister_id;
use crate::lib::environment::Environment;
use crate::lib::error::DfxResult;
use crate::lib::operations::canister::get_canister_id_and_candid_path;
use crate::lib::root_key::fetch_root_key_if_needed;
use crate::lib::sign::sign_transport::SignTransport;
use crate::lib::sign::signed_message::SignedMessageV1;
use crate::util::clap::argument_from_cli::ArgumentFromCliPositionalOpt;
use crate::util::{blob_from_arguments, get_candid_type};
use crate::util::{blob_from_arguments, fetch_remote_did_file, get_candid_type};
use anyhow::{anyhow, bail, Context};
use candid::Principal;
use candid_parser::utils::CandidSource;
Expand Down Expand Up @@ -75,6 +76,9 @@ pub async fn exec(
opts: CanisterSignOpts,
call_sender: &CallSender,
) -> DfxResult {
let agent = env.get_agent();
fetch_root_key_if_needed(env).await?;

let log = env.get_logger();
if *call_sender != CallSender::SelectedId {
bail!("`sign` currently doesn't support proxying through the wallet canister, please use `dfx canister sign --no-wallet ...`.");
Expand All @@ -85,8 +89,15 @@ pub async fn exec(
let (canister_id, maybe_candid_path) =
get_canister_id_and_candid_path(env, opts.canister_name.as_str())?;

let method_type =
maybe_candid_path.and_then(|path| get_candid_type(CandidSource::File(&path), method_name));
let method_type = match maybe_candid_path
.and_then(|path| get_candid_type(CandidSource::File(&path), method_name))
{
Some(mt) => Some(mt),
None => fetch_remote_did_file(agent, canister_id)
.await
.and_then(|did| get_candid_type(CandidSource::Text(&did), method_name)),
};

let is_query_method = method_type.as_ref().map(|(_, f)| f.is_query());

let (argument_from_cli, argument_type) = opts.argument_from_cli.get_argument_and_type()?;
Expand Down
10 changes: 9 additions & 1 deletion src/dfx/src/lib/operations/canister/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,13 +357,21 @@ pub fn get_canister_id_and_candid_path(
) -> DfxResult<(CanisterId, Option<PathBuf>)> {
let canister_id_store = env.get_canister_id_store()?;
let (canister_name, canister_id) = if let Ok(id) = Principal::from_text(canister) {
if canister_id_store.is_well_known(&id) {
return Ok((id, None));
}

if let Some(canister_name) = canister_id_store.get_name(canister) {
(canister_name.to_string(), id)
} else {
return Ok((id, None));
}
} else {
(canister.to_string(), canister_id_store.get(canister)?)
let canister_id = canister_id_store.get(canister)?;
if canister_id_store.is_well_known(&canister_id) {
return Ok((canister_id, None));
}
(canister.to_string(), canister_id)
};
let config = env.get_config_or_anyhow()?;
let candid_path = match CanisterInfo::load(&config, &canister_name, Some(canister_id)) {
Expand Down
Loading