Feature request: deterministic canister ID derivation

Background

The IC lacks the ability to deterministically calculate canister IDs. This functionality is useful in a handful of scenarios as proven in other chains such as ETH and TON.

Proposal

I therefore propose a way to deterministically generate canister IDs in the following manner.

Deterministic canister principals

According to the Internet Computer Specification, I propose to add another category of principals: “deterministic ids” with the format blob · 0x05.

Canister principal calcutation

The canister principal shall be calculated as H( H(bytecode) · H(init params) · H(controller) · subnet id · salt) · 0x05 (29 bytes).

This allows anyone to derive the pricipal of a canister deployed with a particular bytecode to a specific controller (i.e. in a deterministic state), without actually deploying the canister.

Mapping to canister IDs

Those deterministic canister principals are mapped to the real canister IDs in the IC when used.

Deployment

Anyone can deploy the canister by paying the cycles required for deployment, calling a special IC API function deploy_deterministic.

Special considerations

When a canister ID exists in the deterministic canister ID map, the caller shall resolve to the deterministic canister ID instead.

Isn’t this problematic since canisters can be upgraded which changes the bytecode but keeps the canister id?

Currently, the routing table defines a hierarchical mapping based on contiguous ranges. Thus, for a given registry version, one can map a canister id to the respective subnet id.

Unless I misunderstood, while the deterministic canister id from OP is known ahead of time, we would lose the ability to map to a subnet (w/o sharing the full mapping across all subnets).

I’m wondering, why not go all in an invent a CNS (hierarchical human* readable names) for canisters.

(*) I mean American readable—of course, we would only support ASCII. :wink: