Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ dfx cycles convert --amount 100

Use `BTreeMap` instead of `HashMap` for headers to guarantee deterministic ordering.

- Module hash: 47927c343a5217f1687d2d60ac7d1cd32b35100f9e24a5c488828857146419e9
Sets the `ic_env` cookie for html files, which contains the root key and the canister environment variables that are prefixed with `PUBLIC_`.
Please note that this version of the frontend canister is only compatible with PocketIC **v10** and above.

- Module hash: 2c5ab2cdebe93356e319b36c33abcb49c2162b97353476bb5894540e6e616f13
- https://github.com/dfinity/sdk/pull/4392
- https://github.com/dfinity/sdk/pull/4387

# 0.29.2

Expand Down
14 changes: 7 additions & 7 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ candid_parser = "0.2.1"
dfx-core = { path = "src/dfx-core", version = "0.2.0" }
ic-agent = "0.44.0"
ic-asset = { path = "src/canisters/frontend/ic-asset", version = "0.25.0" }
ic-cdk = "0.18.4"
ic-cdk = "0.19.0-beta.2"
ic-identity-hsm = "0.44.0"
ic-utils = "0.44.0"
ic-management-canister-types = "0.4.1"
Expand Down
1 change: 1 addition & 0 deletions src/canisters/frontend/ic-certified-assets/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Changed `CreateAssetArguments.headers` to use `BTreeMap<String, String>` instead of `HashMap<String, String>`
- Changed `AssetProperties.headers` to use `BTreeMap<String, String>` instead of `HashMap<String, String>`
- Changed `SetAssetPropertiesArguments.headers` to use `BTreeMap<String, String>` instead of `HashMap<String, String>`
- **BREAKING**: Sets the `ic_env` cookie for html files, which contains the root key and the canister environment variables that are prefixed with `PUBLIC_`. Please note that this version of the `ic-certified-assets` is only compatible with PocketIC **v10** and above.

#### Migration guide

Expand Down
60 changes: 60 additions & 0 deletions src/canisters/frontend/ic-certified-assets/src/canister_env.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::collections::HashMap;

use ic_cdk::api::{env_var_count, env_var_name, env_var_value, root_key};

use crate::url::url_encode;

const PUBLIC_ENV_VAR_NAME_PREFIX: &str = "PUBLIC_";

const IC_ROOT_KEY_VALUE_KEY: &str = "ic_root_key";
const COOKIE_VALUES_SEPARATOR: &str = "&";

pub struct CanisterEnv {
pub ic_root_key: Vec<u8>,
/// We can expect a maximum of 20 entries, each with a maximum of 128 characters
/// for both the key and the value. Total size: 20 * 128 * 2 = 4096 bytes
///
/// Numbers from https://github.com/dfinity/ic/blob/34bd4301f941cdfa1596a0eecf9f58ad6407293c/rs/config/src/execution_environment.rs#L175-L183
pub icp_public_env_vars: HashMap<String, String>,
}

impl CanisterEnv {
pub fn load() -> Self {
Self {
ic_root_key: root_key(),
icp_public_env_vars: load_icp_public_env_vars(),
}
}

pub fn to_cookie_value(&self) -> String {
let hex_root_key = hex::encode(&self.ic_root_key);
let root_key_value = format!("{IC_ROOT_KEY_VALUE_KEY}={hex_root_key}");

let mut values = vec![root_key_value];

let icp_public_env_vars = self
.icp_public_env_vars
.iter()
.map(|(k, v)| format!("{}={}", k, v))
.collect::<Vec<String>>();
values.extend(icp_public_env_vars);

let cookie_value = values.join(COOKIE_VALUES_SEPARATOR);

url_encode(&cookie_value)
}
}

fn load_icp_public_env_vars() -> HashMap<String, String> {
let mut public_env_vars = HashMap::new();
let env_var_count = env_var_count();

for i in 0..env_var_count {
let name = env_var_name(i);
if name.starts_with(PUBLIC_ENV_VAR_NAME_PREFIX) {
let value = env_var_value(&name);
public_env_vars.insert(name, value);
}
}
public_env_vars
}
10 changes: 10 additions & 0 deletions src/canisters/frontend/ic-certified-assets/src/cookies.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use std::collections::BTreeMap;

const SET_COOKIE_HEADER_NAME: &str = "Set-Cookie";
const IC_ENV_COOKIE_NAME: &str = "ic_env";

pub fn add_ic_env_cookie(headers: &mut BTreeMap<String, String>, encoded_canister_env: &String) {
let cookie_value = format!("{IC_ENV_COOKIE_NAME}={encoded_canister_env}; SameSite=Lax");

headers.insert(SET_COOKIE_HEADER_NAME.to_string(), cookie_value);
}
13 changes: 10 additions & 3 deletions src/canisters/frontend/ic-certified-assets/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! This module declares canister methods expected by the assets canister client.
pub mod asset_certification;
mod canister_env;
mod cookies;
pub mod evidence;
pub mod state_machine;
pub mod types;
mod url_decode;
mod url;

#[cfg(test)]
mod tests;
Expand All @@ -14,6 +16,7 @@ use crate::{
CallbackFunc, HttpRequest, HttpResponse, StreamingCallbackHttpResponse,
StreamingCallbackToken,
},
canister_env::CanisterEnv,
state_machine::{AssetDetails, CertifiedTree, EncodedAsset, State},
types::*,
};
Expand Down Expand Up @@ -191,8 +194,10 @@ pub fn clear() {
}

pub fn commit_batch(arg: CommitBatchArguments) {
let canister_env = CanisterEnv::load();

with_state_mut(|s| {
if let Err(msg) = s.commit_batch(arg, time()) {
if let Err(msg) = s.commit_batch(arg, time(), &canister_env) {
trap(&msg);
}
certified_data_set(s.root_hash());
Expand All @@ -216,8 +221,10 @@ pub fn compute_evidence(arg: ComputeEvidenceArguments) -> Option<ic_certified_as
}

pub fn commit_proposed_batch(arg: CommitProposedBatchArguments) {
let canister_env = CanisterEnv::load();

with_state_mut(|s| {
if let Err(msg) = s.commit_proposed_batch(arg, time()) {
if let Err(msg) = s.commit_proposed_batch(arg, time(), &canister_env) {
trap(&msg);
}
certified_data_set(s.root_hash());
Expand Down
Loading
Loading