Release Notes
Release Notes for icpp-pro
Semantic Versioning
We use semantic versioning (semver) for the release numbers:
Given a version number MAJOR.MINOR.PATCH, increment the:
- MAJOR version when you make incompatible API changes
- MINOR version when you add functionality in a backwards compatible manner
- PATCH version when you make backwards compatible bug fixes
Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.
Changelog
| Version | Changes |
|---|---|
| 7.0.0rc4 Oct 23, '26 |
New: the complete management canister interface. IC_Management has a typed helper for every method of the IC's interface that a canister can call, except the deprecated bitcoin_* methods and the subnet admins' list_canisters- Lifecycle: update_settings (all canister settings, also the log, snapshot and status visibility and the environment variables), start_canister, stop_canister, delete_canister, deposit_cycles, and the full canister_status (memory metrics, query stats, version, reserved cycles, all settings)- Code: install_code (install, reinstall, upgrade), the chunk store (upload_chunk, stored_chunks, clear_chunk_store, install_chunked_code), uninstall_code, canister_metadata and canister_info with the change history- Snapshots: take, load, list and delete, and read and upload a snapshot's metadata and data - Observability: fetch_canister_logs, canister_metrics, subnet_info, subnet_metrics, node_metrics_history- Outcalls and local testing: flexible_http_request, http_request with pay-as-you-go pricing (pricing_version), provisional_create_canister_with_cycles and provisional_top_up_canister- Threshold ECDSA with secp256r1 keys. A field the IC added recently stays at its default when an older replica leaves it out - Docs: creating a canister on another subnet, through the cycles minting canister New: icpp run-native [--max-gb N] runs build-native/mockic.exe under a memory guard- Natively nothing caps a canister's memory. Over the limit (default 4 GiB, the IC's limit for a wasm32 heap), the run is killed with an ERROR and fails, in CI too New: Candid CandidTypeVecOf, a vec of any element type, also of records and variants with payloads; and CandidTypeRecord::append_optional, a field that may be absent on the wireNew: the Mock IC answers the state-changing management methods with an empty reply, and mockIC.last_call_arg_hex / last_call_cycles give what a call sent; run_trap_test can check the trap messageSecurity fix: a truncated Candid message traps. Before, a message that ended before a fixed-width integer, a float or a blob was read past its end, and a blob longer than the bytes left was filled with memory beyond the message. Every canister decodes messages from callers it does not control: upgrade Bug fix: a vec of variants is decoded by the case's id, so a case with a payload, or cases in another order, decode right. Before, cases were matched by position Bug fix: decoding a vec of records is linear in its size. Before, each element copied the whole message Bug fix: cost_http_request_v2 no longer clears the type tables of an argument that is being encodedCheck how your code reopens a file. Since 7.0.0rc3, opening a file with std::ios::out alone (fopen "w") really empties it, as POSIX does. Open a file you write over several calls with std::ios::in \| std::ios::out (see persistence) |
| 7.0.0rc3 Oct 21, '26 |
New: IC_Management::canister_status returns the status of a canister: running, stopping or stopped, its cycles, the cycles it burns per day while idle, its memory size, its module hash, its controllers and its freezing threshold- A canister may read its own status and that of a canister it controls. In a native build, set the reply with mockIC.expect_call("aaaaa-aa", "canister_status", ...)Changed: a record is decoded with Candid's record width subtyping - A record on the wire may have more fields than the record you decode it into, of any type, at any position: they are skipped. That holds at every level, also for a record in a variant, an opt or a vec. So a service can add a field to its reply, and a caller built before that keeps working - Before, only an extra opt field was skipped, and an extra field of another type trapped. A declared opt field that is not on the wire is left empty, as beforeBug fix: a file overwritten in place reads as fast as a new file - The file system in stable memory is upgraded from stable-fs 0.5.1 to 0.13.0 (ic-wasi-polyfill v0.13.0). Before, a file that was truncated and written again, e.g. opened with std::ios::trunc, kept the chunks of its earlier content, and a read past the end walked over all of them- Files written with an earlier icpp-pro keep working after an upgrade, and new files are stored in larger chunks Check how your code reopens a file. Opening a file with std::ios::out alone (fopen "w") now really empties it, as POSIX does. Code that reopened a file this way and wrote at an offset, e.g. a file uploaded in chunks, only worked on the old file system: every write but the last is lost. Open it with std::ios::in | std::ios::out instead (see persistence)The Rust toolchain is reinstalled once. ~/.icpp/rust gets a new folder named after the pinned versions, so icpp build-wasm installs the new toolchain on its first run. The old ~/.icpp/rust/1.93.0 folder can be deleted |
| 7.0.0rc2 Oct 19, '26 |
Changed: co_await ic_api.yield_fresh_budget() returns the new error IC_CallError::Kind::CanisterStopping when the canister is stopping, so a yield loop can reply with what it has, and a stop or upgrade does not wait for the loop to end- The Mock IC rejects calls to the canister itself while it is stopping, and a trap after a co_await, anywhere in the call, now fails run_test and passes run_trap_test- New Mock IC methods: start_call with call_done, was_rejected, reply_hex and reject_message for the reply of each interleaved call, drain_one, and set_performance_counter to feed an instruction counter natively- Docs: the instruction limit after a co_await is 38B, and state set before a commit point stays when a later message traps |
| 7.0.0rc1 Oct 16, '26 |
New: async inter-canister calls with C++20 coroutines - co_await IC_Call::bounded_wait(callee, method) / unbounded_wait, with arguments, cycles and a timeout; IC_CallResult holds the reply or the error- A canister can call itself, and co_await ic_api.yield_fresh_budget() continues in a new message with a fresh instruction limit- A coroutine can co_await another coroutine (IC_Task<T>) and get its result; IC_CallAll makes several calls at once- Composite queries: canister_composite_query methods that call queries, with IC_API(CanisterCompositeQuery{...})- The management canister: IC_Management::raw_rand, create_canister, threshold ECDSA & Schnorr, vetKD and HTTPS outcalls (with a transform), each attaching the cycles it costs- New ic0 binding: cost_http_request_v2; new Candid types vec blob and func- A canister that makes calls refuses to upgrade while calls are in flight; every unbounded_wait call gives a compiler warning, because a callee that never responds blocks upgrades- The Mock IC delivers calls natively: self-calls run the registered methods, other canisters answer with programmed responses - New ic0 bindings: call_with_best_effort_response, msg_deadline- Docs: inter-canister calls, with an ICRC-1 client example |
| 6.6.0 Oct 14, '26 |
New IC_API capability: cycle costs - cost_call / cost_create_canister / cost_http_request- cost_sign_with_ecdsa / cost_sign_with_schnorr / cost_vetkd_derive_key, which tell an unknown curve or key name apart- The Mock IC returns the fees of a 13-node application subnet - Docs: cycle costs |
| 6.5.0 Oct 14, '26 |
New IC_API capability: environment variables - get_env_vars / get_env_var read the variables set in the canister settings (icp.yaml: settings.environment_variables)- getenv() now reads them too. Before, a canister always had an empty environment. In a static constructor the environment is still empty- The Mock IC implements them, and refuses them in canister_start like the IC does- Docs: environment variables |
| 6.4.0 Oct 14, '26 |
New IC_API capabilities: system introspection, subnet, root key & caller info - get_canister_version / get_canister_status / in_replicated_execution / performance_counter- get_subnet_self / get_subnet_node_count / get_root_key- get_caller_info_data / get_caller_info_signer- The Mock IC implements all of them, and refuses each where the IC does - Docs: system introspection & caller info |
| 6.3.2 Oct 13, '26 |
The Mock IC refuses ic0 calls where the IC does - mockic.exe now traps when msg_arg_data is read in canister_pre_upgrade, reject-callback, cleanup-callback, heartbeat & timer entry points, and when the caller or canister id is read in canister_start, with a message naming the refused call and the entry point. Native code that passed before, but would trap on the IC, now fails natively tooNew regression canister for the upgrade hooks - canister_upgrade constructs an IC_API in canister_pre_upgrade & canister_post_upgrade, and is upgraded in place by the CI suite and by the release upgrade test- New example & docs: upgrade hooks Toolchain installs fail on a failed download & retry network errors - icpp install-rust downloads rustup-init before running it. Before, it piped the download into sh, so a failed download exited 0 and the install failed a step later on a missing rustup, with the real error hidden in the log- The git clones & the rustup-init download in icpp install-rust, and the wasi-sdk download in icpp install-wasi-sdk, retry a transient network error up to 3 times |
| 6.3.1 Oct 8, '26 |
Bug fixes - icpp build-wasm & icpp build-native now fail when a C or C++ file fails to compile. Before, the parallel compile step dropped the compiler's error, so the build exited 0 and linked a canister that silently lacked that file- A variant with several fields is now encoded with its fields sorted by id (hash), as the Candid spec requires. Before, they were encoded in the order they were appended, and every spec-following decoder returned the wrong labels - An implicit variant field id is now the previously appended id + 1, and the first implicit append adds one field instead of two Wire bytes change for multi-field variants appended out of hash order. Those bytes were wrong before. Single-field variants such as {"Ok", value}, and variants appended in hash order, encode exactly as before |
| 6.3.0 Oct 5, '26 |
Reproducible builds: the same icpp-pro version always builds the same wasm - icpp install-rust now builds ic-wasi-polyfill & wasi2ic from Cargo.lock files shipped inside icpp-pro, with cargo --locked. Before, every crates.io dependency resolved to its newest version at install time, so the toolchain - and the wasm hash - drifted from one install to the next- icpp-pro now pins icpp-candid==6.3.0 & icpp-binaryen==116.0.1 exactly, so a fresh install cannot pick up a newer icpp-candid, whose C++ is compiled into every canisterAlready have a toolchain in ~/.icpp? It is kept as is. Run icpp install-rust once to rebuild it from the locked dependencies |
| 6.2.0 Sep 21, '26 |
icpp build-wasm fixes the globals limit (IC0505) for you- The IC refuses a wasm with more than 1000 defined globals; a wasi-sdk build of a large C++ project passes that easily. icpp-pro now removes the global exports and optimizes them away as a standard post-link step - for a real project, 1048 globals become 1 - Runs after wasi2ic and BEFORE your post_wasm_function, so your own step always receives an already-valid wasm (the post-link pipeline)- Writes build/<canister>_before_opt_internal.wasm, the pre-optimize wasm that still has its name section, for named backtraces while debugging. The _internal name keeps it clear of the _before_opt a hand-written post_wasm_function conventionally writes, so both survive- Opt out with fix_globals_limit = false in [build-wasm]Your wasm hash changes. This adds an optimization step to every build, so the bytes differ from the previous release. Re-record any hash you track. If your own post_wasm_function already applies this fix, set fix_globals_limit = false in the same upgrade, so it does not run twiceNarrower install surface. icpp-pro now depends on icpp-binaryen >= 116.0.1, which ships wheels for macOS and linux x86_64 (glibc >= 2.35) only. There is no arm64-linux wheel and no sdist, so pip install icpp-pro no longer works on arm64 linux |
| 6.1.0 Sep 21, '26 |
New IC_API capabilities: 128-bit cycles, ingress inspection & certified data - Cycles: get_msg_cycles_available / accept_msg_cycles / get_msg_cycles_refunded / burn_cycles / get_canister_liquid_cycle_balance- Ingress inspection: get_msg_method_name / accept_message, with a user-declared canister_inspect_message hook (canister_inspect)- Certified data: set_certified_data / data_certificate_present / get_data_certificate- All new methods enforce the IC's permitted-entry-point rules with clear trap messages - Purely additive: canisters built with the previous release upgrade as-is Entry-context guards retrofitted onto the pre-existing IC_API methods - The timer family ( set_timer / set_timer_recurring / cancel_timer / cancel_all_timers) now traps with a clear message in query, inspect_message & start entry points, where the IC refuses ic0.global_timer_set- Bug fix: IC_API can now be constructed in canister_pre_upgrade, reject-callback & cleanup-callback entry points (it no longer reads msg_arg_data where the IC refuses it)- Bug fix: get_caller() returns the real caller in heartbeat & timer entry points (was a default principal)- New make upgrade-test-llama: released→dev upgrade gate against llama_cpp_canister's model-free API suite |
| 6.0.0 Aug 5, '26 |
Tests never use the machine-wide active identity - IMPORTANT: Breaking change: name the identity with pytest --identity <name>, or export ICPP_PRO_TEST_IDENTITY=<name>- The name is passed to every icp command as --identity. icp identity default is never read and never written- Fixes a cross-process race: another terminal, agent or CI job can no longer change who your tests call as, mid-run - A killed run can no longer leave your active identity clobbered - identity_default is now the session identity, not an identity literally named default- identity_anonymous uses a process-local override; test bodies are unchanged- New: identity= argument on call_canister_api, get_canister_id, get_principal & the url helpers, to call as a specific identity- Removed: smoketest.set_identity()- Deploy with the same identity you test with, so the caller of a test is the controller Upgrading an existing project? See Migrating to 6.0.0. |
| 5.6.0 Jul 27, '26 |
Drops support for Python 3.10 - icpp-pro & icpp-candid now require Python 3.11 or higher- Python 3.10 reaches end-of-life in October 2026 - Tested against Python 3.11, 3.12, 3.13 & 3.14 - Issue 46 / PR 48 |
| 5.5.1 Jul 27, '26 |
call_canister_api now auto-detects query methods- Reads the canister's Candid interface & sends a query request for methods declared query- Roughly 2x faster test suites; fixes timing-sensitive tests - query=True / query=False remain available as an explicit override- Recommended upgrade for anyone on 5.5.0 |
| 5.5.0 Jul 26, '26 |
Now built on icp-cli - Requires icp-cli >= 1.2.0: npm install -g @icp-sdk/icp-cli- Each canister is configured with an icp.yaml- Local networks are per project & use an ephemeral port ( gateway.port: 0), so projects never collide- icpp.smoketest keeps the same function names & signatures- New: flatten_candid_text() helper & a query argument on call_canister_api- Javascript bindings are generated with didc- Create a default identity yourself: icp identity new default --storage plaintextUpgrading an existing project? See Migrating from dfx. - PR 45 |
| 5.4.2 Jul 22, '26 |
Bug fix: getenv() no longer traps in a canister- __wasilibc_environ now initializes to an empty environment- getenv() returns NULL instead of trapping (IC0502)- Removes per-project getenv workarounds- Native + wasm regression tests (canister_1) - PR 39 |
| 5.4.1 May 8, '26 |
Multi-timer support via IC_API - IC_API::set_timer / set_timer_recurring / cancel_timer / cancel_all_timers- Motoko-style catch-up math: skip missed periods, no fire-storm - Example: canister_timers - PR 37 Bug fix: integer overflow in idl_hash (icpp-candid)Security: bump black dev-dep to 26.3.1 (CVE-2026-32274) |
| 5.3.1 Feb 9, '26 |
Bump Rust version from 1.86.0 to 1.93.0 Issue 34 |
| 5.3.0 Jan 4, '26 |
Implements CandidTypeVecVariant |
| 5.2.0 Apr 22, '25 |
icpp-pro pulls message from icpp_pro_messaging_canister |
| 5.1.0 Apr 4, '25 |
Fix installation of icpp-pro, due to embedded Rust package Issue 31 |
| 5.0.3 Feb 20, '25 |
Small changes to the greet project. |
| 5.0.2 Jan 25, '25 |
Add [[noreturn]] attribute to IC_API::trap This avoids compiler warnings when using trap in a function that must return something. |
| 5.0.1 Jan 17, '25 |
Fix installation of icpp-pro.The previous release, 5.0.0, did not install icpp-candid automatically. |
| 5.0.0 Jan 5, '25 |
Upgrade to wasi-sdk-25.0 & Remove support for Windows. With wasi-sdk 25.0, the approach we used to support Windows is no longer valid. We did extensive testing and reached out to the community, and the best way forward is to drop support for Windows. When you use icpp-pro on Windows, use WSL Ubuntu. IMPORTANT: Breaking change: - the optional argument run_in_powershell was removed from run_dfx_cmd |
| 4.3.0 Dec 31, '24 |
Remove support for Python 3.8, which has reached end-of-life. |
| 4.2.3 Dec 30, '24 |
The latest clang++ compiler on macOS threw an error on icpp build-native. |
| 4.2.2 Dec 5, '24 |
Update curl commands in README & scripts for canister_http QA canister. |
| 4.2.1 Nov 30, '24 |
Support for dfx 0.14.1 & higher The http_request behavior changed as described in this forum post dfx-0-24-1-breaks-the-http-request-endpoint-New smoketest helper function get_canister_url_with_headers -Depecrated smoketest helper function get_canister_url Example: canister_http |
| 4.2.0 Sep 7, '24 |
Hooks into build process icpp-pro will call your python function at the appropriate time Allows you to customize/optimize/merge the wasm Example: canister_hooks |
| 4.1.0 Jul 20, '24 |
Orthogonal persistence now works for ALL data structures Fixed issue with STL containers. |
| 4.0.0 Jul 17, '24 |
- All items listed for 4.0.0rc# - Upgraded to wasi2ic v0.2.12 and ic-wasi-polyfill v0.5.0 |
| 4.0.0rc1 Jul 14, '24 |
Thanks to the integration of ic-wasi-polyfill & wasi2ic, many new features come available: - stdio - file io - file upload/download - files persist across upgrades (files written during an update call are stored in stable memory) We recommend that you review the new icpp-demos/canister/files demo to check out how awesome it all is 🎉🎉🎉 There are two new commands to install the tool chains, but you don't have to even execute them yourself. The first time you are building something, icpp-pro will check if the tool chain is available, and if not, it will install it in ~/.icpp: - icpp install-rust- icpp install-mingw64 (windows only)As before, the tool chains and the dependencies are residing in the folder ~/.icpp, but the folder structure has been refactored. Everything is completely isolated from your system, and to clean it, just delete that folder/The build-native command on Windows has been majorly refactored, but again you do not have to worry about it, everything happens automatic.When running the native debug executable, build-native\mockic.exe, it relies on runtime DLLs that come with the mingw64 compiler. Because we now install our own mingw64 compiler in the ~/.icpp folder, we needed to decide how to make mockic.exe aware of the location of those DLLs. We decided to simply copy the DLLs into the build-native folder. That way, everything stays isolated, without need for clumsy additions to your system's PATH. Again, you do not have to worry about it, it is done for you.We also added a whole new set of automated testing to cover all these new features, and now the GitHub actions test: - On Windows / Ubuntu / Mac - The embedded commands to install the tool chain, including the C++ wasi-sdk compiler, the rust compiler, and on windows the WinGW-w64 compiler - Static libraries in C++ & Rust - File open/write/read/upload/download & persistence across upgrades - Orthogonal persisted memory of many C++ data structures - Many candid api test - All tests we reference from the docs - All tests from icpp-demos repo Have fun & looking forward to your feedback on this first release candidate. |
| 3.17.0 Jun 18, '24 |
- All items listed for 3.17.0rc# - Fixed bug in names of object files on Windows. |
| 3.17.0rc3 Jun 14, '24 |
- Unique names for *.o across directories - Reduce output during compile |
| 3.17.0rc2 Jun 14, '24 |
- Building with -std=c++17 is now supported. -> Run icpp init to see an example config icpp-c++17.toml- Add option: icpp build-wasm --config [toml-file] - Add option: icpp build-native --config [toml-file] - Add option: icpp build-library --config [toml-file] - Add option: icpp build-library-native --config [toml-file] - Bugfix: Remove stubs from unreachable.c that are unrelated to io - Bugfix: Expand cpp_include_dirs for build-library to full path |
| 3.17.0rc1 Jun 11, '24 |
- Support static libraries in an icpp-pro project |
| 3.16.1 May 25, '24 |
- Bug fix for cpp_link_flags of icpp.toml. It was ignored- Removed -Wl,--strip-all, because this removed symbols from the wasm that are used by other tools. This is a first step towards enabling use of wasi2ic |
| 3.16.0 May 22, '24 |
- Upgrade to wasi-sdk 22.0 - Upgrade ubuntu install to Clang 18 - Update Windows wsl commands to dfxvm based install |
| 3.15.3 May 15, '24 |
The metadata dfx.tech_stack is now added to the wasm file according to the standard spec. Note: it is automatic, you do not need to do anything. |
| 3.15.2 Mar 25, '24 |
Update greet_0_auth in greet canister to use best practices for forward compatibility. Return a record wrapped in a variant. No impact on functionality. |
| 3.15.1 Feb 11, '24 |
Small fix to demo.ps1 in greet canister. No impact on functionality. |
| 3.15.0 Feb 11, '24 |
- Upgrade to wasi-sdk 21.0 (LLVM 17) - Windows: Upgrade to MinGW-w64 11.0.1 (UCRT) => This fixes build-native !!! |
| 3.14.1 Feb 11, '24 |
- The Candid File is now embedded in the wasm file, and CandidUI works - Added custom sections cdk:name & cdk:languages for usage aggregation purposes. |
| 3.13.0 Jan 2, '24 |
Additional ic_api methods: - is_controller - get_canister_self - get_canister_self_cycle_balance -> example: canister_1 |
| 3.12.0 Dec 29, '23 |
Turn your C++ canister into a HTTP Webserver -> http_request & http_request_update -> example: canister_http ![]() |
| 3.11.0 Dec 19, '23 |
You can now overwrite default compile & link flags in icpp.toml -> cpp_compile_flags_defaults -> cpp_link_flags_defaults -> c_compile_flags_defaults -> example: canister_flags |
| 3.10.0 Dec 16, '23 |
- Fix python 3.8 - Fix bug for CandidTypeRecord short form - http_request -> example: canister_http |
| 3.9.0 Dec 8, '23 |
CandidTypeRecord with VecRecord field |
| 3.8.1 Nov 27, '23 |
Turn off debug printout. |
| 3.8.0 Nov 25, '23 |
CandidTypeOptVec |
| 3.7.0 Nov 10, '23 |
CandidTypeOptVariant |
| 3.6.0 Nov 4, '23 |
CandidTypeOptRecord |
| 3.5.0 Oct 19, '23 |
CandidTypeVecRecord - Updates to Type Tables |
| 3.4.2 Oct 9, '23 |
add 'native' as a default include directory during 'build-native' command |
| 3.4.1 Oct 9, '23 |
deprecate cpp_header_paths & c_header_paths in icpp.toml |
| 3.4.0 Oct 9, '23 |
Add cpp_include_dirs & c_include_dirs to icpp.toml |
| 3.3.0 Sep 27, '23 |
- Generate Javascript bindings as part of build - Additional run_test API with candid_out |
| 3.2.0 Sep 6, '23 |
Wildcard patterns in icpp.toml |
| 3.1.1 Aug 13,'23 |
Add deprecation warning for Orthogonal Persistence methods. They are not needed based on this study and have a downside that they involve a copy of the data. |
| 3.1.0 Aug 7, '23 |
Updates enabling running karpathy/llama2.c in a canister for inference. |
| 3.0.2 Aug 1, '23 |
Better error messages - Docs for orthogonal persistence |
| 3.0.1 July 16, '23 |
- Faster compile using concurrency. - Support for Windows PowerShell. - Getting started example is fully cross-platform - BREAKING CHANGE! from_wire & to_wire use CandidArgs.See icpp init |
| 2.9.0 July 11, '23 |
- icpp-candid |
| 2.8.1 July 7, '23 |
- Upgrade to wasi-sdk-20 & clang++ 16 |
| 2.7.0 June 13, '23 |
- IC_API constructor update to support additional system api calls, like canister_init. |
| 2.6.0 June 8, '23 |
- Add sha256 to embedded hash library - IC_API::time as static - Additional constructor for CandidTypeVariant(label, CandidType) for simpler usage. - Fix implementation of orthogonal persistence for associative containers (std::map & std::unordered_map) |
| 2.5.0 June 2, '23 |
- Orthogonal persistence for containers. - Smoketest can optionally specify a timeout |
| 2.4.0 May 30, '23 |
- update calls - automatic to_wire() call |
| 2.3.0 May 19, '23 |
- api-reference |
| 2.2.0 May 10, '23 |
- CandidTypeVariant - Smoketest against MainNet |
| 2.1.0 May 1, '23 |
- ic_api.get_caller() |
| 2.0.0 Apr 29, '23 |
Initial BETA release |
