Skip to content
Closed
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
14 changes: 11 additions & 3 deletions rs/ethereum/ledger-suite-orchestrator/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
load("@rules_rust//cargo:defs.bzl", "cargo_build_script")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understanding question: we use askama for other canisters, are they also not a problem for the reproducibility issue?

  1. ic-btc-checker
  2. ic-cketh-minter
  3. ic-ckbtc-kyt (this one we plan on deleting)

load("@rules_rust//rust:defs.bzl", "rust_doc", "rust_library", "rust_test")
load("//bazel:canisters.bzl", "rust_canister")
load("//bazel:defs.bzl", "rust_ic_test")
Expand Down Expand Up @@ -100,6 +101,15 @@ rust_test(
],
)

cargo_build_script(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@basvandijk : If I understand that failure correctly, this means that it doesn't solve the problem or there is another source of non-determinism?

//rs/ethereum/ledger-suite-orchestrator:_ledger_suite_orchestrator_canister.wasm.gz_finalize bazel-out/k8-opt/bin/rs/ethereum/ledger-suite-orchestrator/ledger_suite_orchestrator_canister.wasm.gz: 46b544a2e01428a5cf29384e2858f0bed73c98340b563a8d4157133a64ecb6b3
!= 5379b1dc3c8cea64d032c5d6ade6a4069a234aaadc945184fe6d122de69daf65

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? That this PR is insufficient?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mraszyk The description of the PR states

it's causing the Build Reproducibility check to fail in: https://github.com/dfinity/ic/actions/runs/15296835171/job/43032042139?pr=5194.

However, that PR seems to suffer from the same problem

https://github.com/dfinity/ic/actions/runs/15303873653/job/43056720920?pr=5348

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I think I was too soon turning this from draft into a PR. There seems to be another source of non-determinism.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the logs it seems that there is a non-determinism with the archive. This would definitely produce non-determinism in the ledger (because it embeds its wasm) and in the ledger suite orchestrator (which embeds among other also the archive wasm)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gregorydemay we're embedding other canisters into the ledger_suite_orchestrator_canister right? Are those other canisters also using askama? That could be one explanation while there's still non-determinism.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@basvandijk

we're embedding other canisters into the ledger_suite_orchestrator_canister right?

yes that's correct, they are defined here

Are those other canisters also using askama?

I don't think so, none of the canisters in the ledger suite have a dependency on askama

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@basvandijk To me the root cause of the non-determinism seen here could be explained by the archive

//rs/ledger_suite/icrc1/archive:_wasm_archive_canister_u256 bazel-out/k8-opt-ST-42b6d6ef7a37/bin/rs/ledger_suite/icrc1/archive/_wasm_archive_canister_u256.wasm: 4977a63fc611b224d47a4c0004139dda86f6ef69563870011ac6e3ddbbf99b17

since this would trigger non-determinism for ledger_u256 and the ledger suite orchestrator.
It's interesting that only the u256 variant seems to have that problem (and not the u64 variant)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right the archive canister is the source.

I think I jumped to conclusions too soon since we have been suffering from non-determinism from a very similar use of askama recently which we fixed using #5282. But maybe the symbol name generator of the rustc WASM backend is not sensitive to a changing metadata hash and so canisters remain reproducible while on x86_64 things blow up.

name = "build_script",
srcs = ["build.rs"],
build_script_env = {
"IN_BAZEL": "1",
},
data = ["templates/dashboard.html"],
)

[
rust_canister(
name = "ledger_suite_orchestrator_canister" + name_suffix,
Expand All @@ -109,9 +119,6 @@ rust_test(
"src/dashboard/tests.rs",
"src/main.rs",
],
compile_data = [
"templates/dashboard.html",
],
crate_name = "ic_ledger_suite_orchestrator_canister" + name_suffix,
opt = "z",
proc_macro_deps = [
Expand All @@ -120,6 +127,7 @@ rust_test(
service_file = "ledger_suite_orchestrator.did",
deps = [
# Keep sorted.
":build_script",
":ledger_suite_orchestrator" + name_suffix,
"//packages/ic-http-types",
"@crate_index//:askama",
Expand Down
83 changes: 61 additions & 22 deletions rs/ethereum/ledger-suite-orchestrator/build.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,68 @@
use std::env::{self};
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
let cargo_manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let compile_time_env_variables = [
"LEDGER_CANISTER_WASM_PATH",
"INDEX_CANISTER_WASM_PATH",
"LEDGER_ARCHIVE_NODE_CANISTER_WASM_PATH",
];
for env_var in compile_time_env_variables {
let archive_path = match env::var_os(env_var) {
Some(wasm_path) => PathBuf::from(wasm_path),
None => cargo_manifest_dir
// This is a hack.
// Cargo is called on CI via ci/src/rust_lint/lint.sh.
// The included WASMS binary for ledger, index and archive canisters are built by BAZEL tasks
// which would need here to be somehow spawned by Cargo. To avoid this, we just use a wasm binary that
// happens to be already checked-in in the repo.
.join("../../ledger_suite/icrc1/wasm/ic-icrc1-archive.wasm.gz")
.canonicalize()
.expect("failed to canonicalize a path"),
};
if env::var_os("IN_BAZEL").is_none() {
let cargo_manifest_dir = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
let compile_time_env_variables = [
"LEDGER_CANISTER_WASM_PATH",
"INDEX_CANISTER_WASM_PATH",
"LEDGER_ARCHIVE_NODE_CANISTER_WASM_PATH",
];
for env_var in compile_time_env_variables {
let archive_path = match env::var_os(env_var) {
Some(wasm_path) => PathBuf::from(wasm_path),
None => cargo_manifest_dir
// This is a hack.
// Cargo is called on CI via ci/src/rust_lint/lint.sh.
// The included WASMS binary for ledger, index and archive canisters are built by BAZEL tasks
// which would need here to be somehow spawned by Cargo. To avoid this, we just use a wasm binary that
// happens to be already checked-in in the repo.
.join("../../ledger_suite/icrc1/wasm/ic-icrc1-archive.wasm.gz")
.canonicalize()
.expect("failed to canonicalize a path"),
};

println!("cargo:rerun-if-changed={}", archive_path.display());
println!("cargo:rerun-if-env-changed={}", env_var);
println!("cargo:rustc-env={}={}", env_var, archive_path.display());
println!("cargo:rerun-if-changed={}", archive_path.display());
println!("cargo:rerun-if-env-changed={}", env_var);
println!("cargo:rustc-env={}={}", env_var, archive_path.display());
}
}

// Build reproducibility. askama adds a include_bytes! call when it's generating
// a template impl so that rustc will recompile the module when the file changes
// on disk. See https://github.com/djc/askama/blob/180696053833147a61b3348646a953e7d92ae582/askama_shared/src/generator.rs#L141
// The stringified output of every proc-macro is added to the metadata hash for
// a crate. That output includes the full filepath to include_bytes!. It may be
// different on two machines, if they use different tempdir paths for the build.
// The metadata hash is an input to generated symbol names.
// So using the askama proc-macro could result in slightly different symbols.
// However, if we include the html source directly in the output, no
// inconsistency is introduced.
//
// This should really be fixed in askama. See:
// https://github.com/askama-rs/askama/issues/461
println!("cargo:rerun-if-changed=templates/dashboard.html");
let mut f = File::create(
PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("dashboard_template.rs"),
)
.unwrap();
f.write_all(
format!(
r#"
#[derive(Template)]
#[template(escape = "html", source = {:?}, ext = "html")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

understanding question: why was this line added?

pub struct DashboardTemplate {{
managed_canisters: BTreeMap<Erc20Token, CanistersDashboardData>,
other_canisters: BTreeMap<String, Vec<CanisterDashboardData>>,
wasm_store: Vec<DashboardStoredWasm>,
}}
"#,
std::fs::read_to_string("templates/dashboard.html").unwrap()
)
.as_bytes(),
)
.unwrap();
}
9 changes: 2 additions & 7 deletions rs/ethereum/ledger-suite-orchestrator/src/dashboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,8 @@ mod filters {
}
}

#[derive(Template)]
#[template(path = "dashboard.html")]
pub struct DashboardTemplate {
managed_canisters: BTreeMap<Erc20Token, CanistersDashboardData>,
other_canisters: BTreeMap<String, Vec<CanisterDashboardData>>,
wasm_store: Vec<DashboardStoredWasm>,
}
// See build-canister.rs
include!(concat!(env!("OUT_DIR"), "/dashboard_template.rs"));

#[derive(Clone, PartialEq, Debug, Default)]
pub struct CanistersDashboardData {
Expand Down