Skip to content
Draft
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,352 changes: 1,220 additions & 132 deletions Cargo.Bazel.json.lock

Large diffs are not rendered by default.

254 changes: 220 additions & 34 deletions Cargo.Bazel.toml.lock

Large diffs are not rendered by default.

41 changes: 32 additions & 9 deletions bazel/canisters.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ def rust_canister(name, service_file, visibility = ["//visibility:public"], test
# The option to keep the name section is only required for wasm finalization.
keep_name_section = kwargs.pop("keep_name_section", False)

# Optional path to a hidden_endpoints.conf for `ic-wasm check-endpoints`.
hidden_endpoints = kwargs.pop("hidden_endpoints", None)

# Sanity checking (no '.' in name)
if name.count(".") > 0:
fail("name '{}' should not include dots".format(name))
Expand Down Expand Up @@ -126,6 +129,7 @@ def rust_canister(name, service_file, visibility = ["//visibility:public"], test
visibility = visibility,
testonly = testonly,
keep_name_section = keep_name_section,
hidden_endpoints = hidden_endpoints,
)

native.alias(
Expand Down Expand Up @@ -181,27 +185,46 @@ def motoko_canister(name, entry, deps, **kwargs):
actual = final_name,
)

def finalize_wasm(*, name, src_wasm, service_file = None, version_file, testonly, visibility = ["//visibility:public"], keep_name_section = False):
def finalize_wasm(*, name, src_wasm, service_file = None, version_file, testonly, visibility = ["//visibility:public"], keep_name_section = False, hidden_endpoints = None):
"""Generates an output file name `name + '.wasm.gz'`.

The input file is shrunk, annotated with metadata, and gzipped. The canister
metadata consists of:
'icp:public git_commit_id': version used in the build
'icp:public candid:service': the canister's candid service description

When `hidden_endpoints` is provided (a label pointing at a `hidden_endpoints.conf`
file), `ic-wasm check-endpoints --hidden <conf>` is also run on the finalized
wasm before gzip, failing the build if the wasm exports a method that is
neither in the candid `service` nor allowlisted in the conf.
"""

steps = [
"{ic_wasm} {input_wasm} -o $@.shrunk shrink {keep_name_section}",
"{ic_wasm} $@.shrunk -o $@.meta metadata candid:service {keep_name_section} --visibility public --file " + "$(location {})".format(service_file) if not (service_file == None) else "cp $@.shrunk $@.meta", # if service_file is None, don't include a service file
"{ic_wasm} $@.meta -o $@.ver metadata git_commit_id {keep_name_section} --visibility public --file {version_file}",
]
if hidden_endpoints != None:
steps.append("{ic_wasm} $@.ver check-endpoints --hidden $(location {hidden_endpoints})")
steps.append("{pigz} --processes 16 --no-name $@.ver --stdout > $@")

native.genrule(
name = "_" + name + "_finalize",
srcs = [src_wasm, version_file] + ([service_file] if not (service_file == None) else []),
srcs = [src_wasm, version_file] +
([service_file] if not (service_file == None) else []) +
([hidden_endpoints] if hidden_endpoints != None else []),
outs = [name],
visibility = visibility,
testonly = testonly,
message = "Finalizing canister " + name,
tools = ["@crate_index//:ic-wasm__ic-wasm", "@pigz"],
cmd_bash = " && ".join([
"{ic_wasm} {input_wasm} -o $@.shrunk shrink {keep_name_section}",
"{ic_wasm} $@.shrunk -o $@.meta metadata candid:service {keep_name_section} --visibility public --file " + "$(location {})".format(service_file) if not (service_file == None) else "cp $@.shrunk $@.meta", # if service_file is None, don't include a service file
"{ic_wasm} $@.meta -o $@.ver metadata git_commit_id {keep_name_section} --visibility public --file {version_file}",
"{pigz} --processes 16 --no-name $@.ver --stdout > $@",
])
.format(input_wasm = "$(location {})".format(src_wasm), ic_wasm = "$(location @crate_index//:ic-wasm__ic-wasm)", version_file = "$(location {})".format(version_file), pigz = "$(location @pigz)", keep_name_section = "--keep-name-section" if keep_name_section else ""),
cmd_bash = " && ".join(steps)
.format(
input_wasm = "$(location {})".format(src_wasm),
ic_wasm = "$(location @crate_index//:ic-wasm__ic-wasm)",
version_file = "$(location {})".format(version_file),
pigz = "$(location @pigz)",
keep_name_section = "--keep-name-section" if keep_name_section else "",
hidden_endpoints = hidden_endpoints if hidden_endpoints != None else "",
),
)
3 changes: 2 additions & 1 deletion bazel/rust.MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -771,10 +771,11 @@ crate.spec(
crate.spec(
default_features = False,
features = [
"check-endpoints",
"exe",
],
package = "ic-wasm",
version = "^0.8.4",
version = "^0.9.10",
)
crate.spec(
package = "ic-xrc-types",
Expand Down
1 change: 1 addition & 0 deletions rs/bitcoin/checker/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ rust_canister(
compile_data = [
"templates/dashboard.html",
],
hidden_endpoints = "hidden_endpoints.conf",
service_file = "btc_checker_canister.did",
deps = [
# Keep sorted.
Expand Down
9 changes: 9 additions & 0 deletions rs/bitcoin/checker/hidden_endpoints.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# HTTP endpoint for fetching metrics
canister_query:http_request
# Transform function for HTTP outcalls
canister_query:transform
# Canister lifecycle
canister_init
canister_post_upgrade
# Exported by the `main()` function in `main.rs`; cannot be called
main
5 changes: 4 additions & 1 deletion rs/bitcoin/ckbtc/minter/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ rust_doc_test(
compile_data = [":ckbtc_minter.did"],
crate_features = features,
crate_name = "ic_ckbtc_minter_canister",
hidden_endpoints = hidden_endpoints,
proc_macro_deps = [
# Keep sorted.
],
Expand All @@ -112,16 +113,18 @@ rust_doc_test(
"@crate_index//:serde_json",
],
)
for (name, features) in [
for (name, features, hidden_endpoints) in [
# Production version without debug assertions.
(
"ckbtc_minter",
[],
"hidden_endpoints.conf",
),
# Test version with internal consistency checks.
(
"ckbtc_minter_debug",
["self_check"],
"hidden_endpoints_debug.conf",
),
]
]
Expand Down
11 changes: 11 additions & 0 deletions rs/bitcoin/ckbtc/minter/hidden_endpoints.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# IC system-level timer (wired via #[unsafe(export_name = "canister_global_timer")])
canister_global_timer
# HTTP endpoint for fetching metrics
canister_query:http_request
# Candid extraction tmp-hack endpoint (#[query(hidden = true)] in main.rs)
canister_query:__get_candid_interface_tmp_hack
# Canister lifecycle
canister_init
canister_post_upgrade
# Exported by the `main()` function in `main.rs`; cannot be called
main
15 changes: 15 additions & 0 deletions rs/bitcoin/ckbtc/minter/hidden_endpoints_debug.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Same as hidden_endpoints.conf plus the `self_check` query, which is
# only compiled in when the `self_check` cargo feature is enabled (the
# `ckbtc_minter_debug` variant). It is declared `#[query]` (i.e. not
# hidden) but absent from the canonical `ckbtc_minter.did`, so it must
# be allowlisted here.
canister_global_timer
canister_query:http_request
canister_query:__get_candid_interface_tmp_hack
canister_query:self_check
# self_check-only update endpoints, also gated on the cargo feature
canister_update:refresh_fee_percentiles
canister_update:upload_events
canister_init
canister_post_upgrade
main
6 changes: 4 additions & 2 deletions rs/ethereum/cketh/minter/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ rust_test(
],
crate_features = features,
crate_name = "ic_cketh_minter_canister",
hidden_endpoints = hidden_endpoints,
proc_macro_deps = [
# Keep sorted.
],
Expand All @@ -175,11 +176,12 @@ rust_test(
"@crate_index//:serde_bytes",
"@crate_index//:time",
],
) for (target_suffix, features) in [
("", []),
) for (target_suffix, features, hidden_endpoints) in [
("", [], "hidden_endpoints.conf"),
(
"_debug",
["debug_checks"],
"hidden_endpoints_debug.conf",
),
]]

Expand Down
13 changes: 13 additions & 0 deletions rs/ethereum/cketh/minter/hidden_endpoints.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Timer endpoints exported by ic-cdk-timers (the dispatcher
# `<ic-cdk internal> timer_executor` plus the IC system-level
# `canister_global_timer` it registers itself against)
canister_global_timer
canister_update:<ic-cdk internal> timer_executor
# HTTP endpoint for fetching metrics
canister_query:http_request
# Canister lifecycle
canister_init
canister_pre_upgrade
canister_post_upgrade
# Exported by the `main()` function in `main.rs`; cannot be called
main
13 changes: 13 additions & 0 deletions rs/ethereum/cketh/minter/hidden_endpoints_debug.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Same as hidden_endpoints.conf plus the `check_audit_log` query, which
# is only compiled in when the `debug_checks` cargo feature is enabled
# (the `cketh_minter_debug` variant). It is declared `#[query]` (not
# hidden) but absent from cketh_minter.did, so it must be allowlisted
# here.
canister_global_timer
canister_update:<ic-cdk internal> timer_executor
canister_query:http_request
canister_query:check_audit_log
canister_init
canister_pre_upgrade
canister_post_upgrade
main
1 change: 1 addition & 0 deletions rs/ethereum/ledger-suite-orchestrator/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ rust_test(
"templates/dashboard.html",
],
crate_name = "ic_ledger_suite_orchestrator_canister" + name_suffix,
hidden_endpoints = "hidden_endpoints.conf",
opt = "z",
proc_macro_deps = [
# Keep sorted.
Expand Down
9 changes: 9 additions & 0 deletions rs/ethereum/ledger-suite-orchestrator/hidden_endpoints.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# IC system-level timer (wired via #[unsafe(export_name = "canister_global_timer")])
canister_global_timer
# HTTP endpoint for fetching metrics
canister_query:http_request
# Canister lifecycle
canister_init
canister_post_upgrade
# Exported by the `main()` function in `main.rs`; cannot be called
main
8 changes: 7 additions & 1 deletion rs/ledger_suite/icp/ledger/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,27 @@ rust_test(
deps = ["@crate_index//:proptest"],
)

rust_ledger_canister(name = "ledger-canister-wasm")
rust_ledger_canister(
name = "ledger-canister-wasm",
hidden_endpoints = "hidden_endpoints.conf",
)

rust_ledger_canister(
name = "ledger-canister-wasm-allowance-getter",
crate_features = ["icp-allowance-getter"],
hidden_endpoints = "hidden_endpoints_allowance_getter.conf",
)

rust_ledger_canister(
name = "ledger-canister-wasm-next-version",
extra_deps = [":ledger_next_version"],
hidden_endpoints = "hidden_endpoints.conf",
)

rust_ledger_canister(
name = "ledger-canister-wasm-prev-version",
extra_deps = [":ledger_prev_version"],
hidden_endpoints = "hidden_endpoints.conf",
)

rust_test(
Expand Down
24 changes: 24 additions & 0 deletions rs/ledger_suite/icp/ledger/hidden_endpoints.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Canister lifecycle (canister_init declared via #[unsafe(export_name = ...)])
canister_init
canister_pre_upgrade
canister_post_upgrade
# HTTP endpoint for fetching metrics (#[query(hidden = true)])
canister_query:http_request
# Candid extraction tmp-hack endpoint (#[query] but absent from ledger.did)
canister_query:__get_candid_interface_tmp_hack
# Legacy protobuf query endpoints (#[unsafe(export_name = "canister_query <name>")])
canister_query:account_balance_pb
canister_query:block_pb
canister_query:get_archive_index_pb
canister_query:get_blocks_pb
canister_query:get_nodes
canister_query:iter_blocks_pb
canister_query:tip_of_chain_pb
canister_query:total_supply_pb
canister_query:transfer_fee_pb
# Legacy protobuf update endpoints
canister_update:notify_dfx
canister_update:notify_pb
canister_update:send_pb
# Exported by the `main()` function in `main.rs`; cannot be called
main
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Same as hidden_endpoints.conf plus the `allowance` query, which is
# only compiled in when the `icp-allowance-getter` cargo feature is
# enabled (the `ledger-canister-wasm-allowance-getter` variant). It is
# declared `#[query(name = "allowance")]` (not hidden) but absent from
# ledger.did, so it must be allowlisted here.
canister_init
canister_pre_upgrade
canister_post_upgrade
canister_query:http_request
canister_query:__get_candid_interface_tmp_hack
canister_query:allowance
canister_query:account_balance_pb
canister_query:block_pb
canister_query:get_archive_index_pb
canister_query:get_blocks_pb
canister_query:get_nodes
canister_query:iter_blocks_pb
canister_query:tip_of_chain_pb
canister_query:total_supply_pb
canister_query:transfer_fee_pb
canister_update:notify_dfx
canister_update:notify_pb
canister_update:send_pb
main
3 changes: 2 additions & 1 deletion rs/ledger_suite/icp/ledger/ledger_canisters.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ LEDGER_CANISTER_DEPS = [
"@crate_index//:serde_bytes",
]

def rust_ledger_canister(name, extra_deps = [":ledger"], crate_features = None):
def rust_ledger_canister(name, extra_deps = [":ledger"], crate_features = None, hidden_endpoints = None):
rust_canister(
name = name,
srcs = ["src/main.rs"],
Expand All @@ -55,6 +55,7 @@ def rust_ledger_canister(name, extra_deps = [":ledger"], crate_features = None):
service_file = "//rs/ledger_suite/icp:ledger.did",
deps = LEDGER_CANISTER_DEPS + extra_deps,
crate_features = crate_features if crate_features else [],
hidden_endpoints = hidden_endpoints,
proc_macro_deps = [
# Keep sorted.
],
Expand Down
8 changes: 8 additions & 0 deletions rs/ledger_suite/icrc1/ledger/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ package(default_visibility = ["//visibility:public"])
srcs = ["src/main.rs"] + glob(["src/benches/**/*.rs"]),
crate_features = features,
crate_name = "ic_icrc1_ledger_canister" + name_suffix,
# The `_getblocksdisabled` variants compile without `get_blocks`
# but share the same `ledger.did` (which still declares it). The
# `_canbench` variants compile in benchmark-only `__canbench__*`
# and `__tracing__*` query endpoints from canbench-rs that aren't
# in `ledger.did` either, and replace `canister_init` with the
# canbench harness's own. Opt both kinds of variants out of
# check-endpoints — they're test-only and not production canisters.
hidden_endpoints = None if ("get-blocks-disabled" in features or "canbench-rs" in features) else "hidden_endpoints.conf",
opt = "z",
proc_macro_deps = [
# Keep sorted.
Expand Down
10 changes: 10 additions & 0 deletions rs/ledger_suite/icrc1/ledger/hidden_endpoints.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Canister lifecycle
canister_init
canister_pre_upgrade
canister_post_upgrade
# HTTP endpoint for fetching metrics (#[query(hidden = true)])
canister_query:http_request
# Candid extraction tmp-hack endpoint (#[query] but absent from ledger.did)
canister_query:__get_candid_interface_tmp_hack
# Exported by the `main()` function in `main.rs`; cannot be called
main
Loading