Skip to content

ci(DEFI-2487): add ic-wasm check-endpoints to DeFi-team canisters#10147

Draft
gregorydemay wants to merge 9 commits intomasterfrom
gdemay/check-endpoints-ic-canisters
Draft

ci(DEFI-2487): add ic-wasm check-endpoints to DeFi-team canisters#10147
gregorydemay wants to merge 9 commits intomasterfrom
gdemay/check-endpoints-ic-canisters

Conversation

@gregorydemay
Copy link
Copy Markdown
Contributor

Summary

Wraps the existing ic-wasm invocation in bazel/canisters.bzl's finalize_wasm rule with an optional check-endpoints step, then opts the five DeFi-team canisters in dfinity/ic into it. The check fails the build if a canister WASM exports a method that is neither in the candid service declaration nor explicitly allowlisted in a per-canister hidden_endpoints.conf — catching accidental public exports (a dropped #[query(hidden = true)], a leaked FFI symbol, etc.) before they ship.

Mirrors the pattern in dfinity/bitcoin-canister, dfinity/dogecoin-canister, dfinity/exchange-rate-canister, and the rest of the standalone DeFi-team repos.

The five DEFI-2487 sub-tasks (ICP & ICRC1 ledgers, ckBTC minter, ckETH/ckERC20 minter, LSO, BTC checker) all close together when this lands.

Closes DEFI-2501.
Closes DEFI-2502.
Closes DEFI-2503.
Closes DEFI-2504.
Closes DEFI-2511.

Extends rust_canister and finalize_wasm in bazel/canisters.bzl with
an optional hidden_endpoints kwarg pointing at a hidden_endpoints.conf
file. When provided, ic-wasm check-endpoints --hidden <conf> runs
between the metadata-stamping and gzip steps of the existing
finalize_wasm cmd_bash chain, failing the build if the wasm exports
a method that is neither in the candid service nor allowlisted in
the conf.

The kwarg defaults to None, so existing canisters that don't opt in
see no behavior change. The rust_ledger_canister wrapper in
rs/ledger_suite/icp/ledger/ledger_canisters.bzl threads the kwarg
through to rust_canister.

Mirrors the pattern already shipped in dfinity/bitcoin-canister and
dfinity/dogecoin-canister, where hidden_endpoints.conf lists
legitimate non-candid exports (lifecycle hooks, http_request,
canister_global_timer, ic_cdk_timers' timer_executor, vendored FFI
symbols, and Rust's main).

Per-canister opt-in lands in subsequent commits (DEFI-2501, 2502,
2503, 2504, 2511).
…eature

ic-wasm 0.9.x introduces a `check-endpoints` subcommand that fails
the canister build if the wasm exports a method that is neither in
the candid `service` nor allowlisted in a `hidden_endpoints.conf`
file. The IC repo previously pinned ^0.8.4 (predates the
subcommand) with `default_features = False` and only the `exe`
feature enabled — `check-endpoints` lives behind its own cargo
feature, so opting in requires both bumping the version and adding
the feature flag.

Verified the existing `shrink` and `metadata` invocations in
`bazel/canisters.bzl`'s `finalize_wasm` rule still work unchanged
(the BTC checker rebuild succeeds end-to-end on 0.9.11 with the
existing pipeline).

Subsequent commits opt individual canisters into the new check
(DEFI-2501, 2502, 2503, 2504, 2511).
Adds rs/bitcoin/checker/hidden_endpoints.conf and threads it into
the rust_canister rule via the new optional `hidden_endpoints` kwarg.
The conf lists the legitimate non-candid exports of the BTC checker:
the metrics http_request, the HTTP-outcall transform query, the two
lifecycle hooks, and Rust's `main` symbol.

`bazel build //rs/bitcoin/checker:btc_checker_canister.wasm.gz`
now reports `Canister WASM and Candid interface match!` as part of
finalization and fails the build if a future change exports an
unlisted method.
Both variants (`ledger_suite_orchestrator_canister` and
`..._getblocksdisabled`) now go through `ic-wasm check-endpoints`
during finalization. The shared hidden_endpoints.conf lists
canister_global_timer, the metrics http_request, lifecycle hooks,
and Rust's main symbol.
Two confs because the ckbtc_minter_debug variant compiles in three
extra endpoints behind the `self_check` cargo feature
(canister_query:self_check, canister_update:refresh_fee_percentiles,
canister_update:upload_events) that are not present in the
production ckbtc_minter wasm. ic-wasm check-endpoints is strict in
both directions (extra entries in --hidden are also flagged), so a
single permissive conf can't satisfy both variants.

Both confs share the timer, http_request metrics endpoint, the
__get_candid_interface_tmp_hack candid-extraction helper (declared
#[query(hidden = true)] in main.rs), the lifecycle hooks, and the
Rust main symbol.
Two confs because the cketh_minter_debug variant exports an extra
`check_audit_log` query gated behind the `debug_checks` cargo
feature, which is absent from cketh_minter.did.

Both confs share the IC system-level `canister_global_timer` plus
the ic-cdk-timers dispatcher `<ic-cdk internal> timer_executor`,
the metrics http_request, the lifecycle hooks (init, pre_upgrade,
post_upgrade), and the Rust main symbol. No FFI symbols from
ic_secp256k1 / ic_sha3 leaked into the WASM exports — the IC's
ic_secp256k1 wrapper appears to keep them internal.
Wires the production-shape variants (`ledger_canister`,
`_u256`, `_nextledgerversion`, `_u256_nextledgerversion`) of the
ICRC1 ledger through ic-wasm check-endpoints, against a single
hidden_endpoints.conf listing the lifecycle hooks, the
#[query(hidden = true)] http_request metrics endpoint, the
__get_candid_interface_tmp_hack helper (declared #[query] but
absent from ledger.did), and Rust's main symbol.

The `_getblocksdisabled` and `_canbench` variants are deliberately
opted out of the check (hidden_endpoints = None) because they
ship with a wasm shape that diverges from `ledger.did`: the former
disables `get_blocks` in code while the .did still declares it,
and the latter compiles in canbench-rs's `__canbench__*` /
`__tracing__*` benchmark exports and replaces `canister_init`
with the canbench harness's own. Both are test-only variants;
gating them on check-endpoints would either require a separate
.did or upstream changes to canbench-rs / the get-blocks-disabled
feature itself.
All 4 variants of the ICP ledger now go through ic-wasm
check-endpoints during finalization. The base hidden_endpoints.conf
covers the 12 legacy `_pb` protobuf endpoints (declared via
#[unsafe(export_name = "canister_query <name>")] /
#[unsafe(export_name = "canister_update <name>")]), the metrics
http_request, the candid-extraction __get_candid_interface_tmp_hack
helper (declared #[query] but absent from ledger.did), the
lifecycle hooks, and Rust's main symbol.

The `_allowance-getter` variant gets a separate
hidden_endpoints_allowance_getter.conf because the
`icp-allowance-getter` cargo feature compiles in an extra
`canister_query:allowance` endpoint not present in ledger.did.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an opt-in ic-wasm check-endpoints validation step to the Bazel canister finalization pipeline and enables it for selected DeFi-team canisters, using per-canister allowlists to prevent accidental public exports from shipping.

Changes:

  • Extend bazel/canisters.bzl finalize_wasm to optionally run ic-wasm check-endpoints using a hidden_endpoints.conf allowlist.
  • Add hidden_endpoints.conf allowlists and Bazel wiring for the ICP/ICRC1 ledgers and DeFi canisters (ckBTC minter, ckETH minter, ledger-suite orchestrator, BTC checker).
  • Bump ic-wasm (and Bazel crate metadata/locks) to a version that supports the check-endpoints feature.

Reviewed changes

Copilot reviewed 18 out of 20 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rs/ledger_suite/icrc1/ledger/hidden_endpoints.conf Adds allowlist of lifecycle/hidden exports for ic-wasm check-endpoints.
rs/ledger_suite/icrc1/ledger/BUILD.bazel Enables hidden_endpoints for production variants; opts test-only variants out.
rs/ledger_suite/icp/ledger/ledger_canisters.bzl Adds hidden_endpoints parameter pass-through to rust_canister.
rs/ledger_suite/icp/ledger/hidden_endpoints.conf Adds allowlist for ICP ledger hidden/system/legacy exports.
rs/ledger_suite/icp/ledger/hidden_endpoints_allowance_getter.conf Adds allowlist variant for the allowance-getter build that exports allowance.
rs/ledger_suite/icp/ledger/BUILD.bazel Opts ICP ledger wasm targets into endpoint checking with the appropriate allowlist.
rs/ethereum/ledger-suite-orchestrator/hidden_endpoints.conf Adds allowlist for orchestrator hidden/system exports.
rs/ethereum/ledger-suite-orchestrator/BUILD.bazel Opts orchestrator canister into endpoint checking.
rs/ethereum/cketh/minter/hidden_endpoints.conf Adds allowlist for ckETH minter hidden/system exports (timers, metrics, lifecycle).
rs/ethereum/cketh/minter/hidden_endpoints_debug.conf Adds debug-variant allowlist for extra debug-only exported endpoints.
rs/ethereum/cketh/minter/BUILD.bazel Wires allowlists into both prod and debug ckETH minter builds.
rs/bitcoin/ckbtc/minter/hidden_endpoints.conf Adds allowlist for ckBTC minter hidden/system exports.
rs/bitcoin/ckbtc/minter/hidden_endpoints_debug.conf Adds debug-variant allowlist for self-check/debug-only endpoints.
rs/bitcoin/ckbtc/minter/BUILD.bazel Wires allowlists into both prod and debug ckBTC minter builds.
rs/bitcoin/checker/hidden_endpoints.conf Adds allowlist for BTC checker hidden/system exports (metrics, transform, lifecycle).
rs/bitcoin/checker/BUILD.bazel Opts BTC checker canister into endpoint checking.
Cargo.Bazel.toml.lock Updates locked Rust dependencies for the ic-wasm bump (incl. new transitive deps).
Cargo.Bazel.json.lock Updates Bazel crate universe lock for the ic-wasm bump and new dependencies.
bazel/rust.MODULE.bazel Enables ic-wasm check-endpoints feature and bumps the allowed ic-wasm version range.
bazel/canisters.bzl Adds hidden_endpoints plumbing and optional check-endpoints genrule step.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants