Skip to content
Merged
Changes from 23 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
76971dc
cost api
michael-weigelt Jan 27, 2025
d7ccf82
title link
michael-weigelt Jan 27, 2025
3c04c79
Merge remote-tracking branch 'origin' into mwe/cost_api
michael-weigelt Jan 27, 2025
dd4dd3d
Update docs/references/ic-interface-spec.md
michael-weigelt Jan 28, 2025
75356a7
Update docs/references/ic-interface-spec.md
michael-weigelt Jan 28, 2025
a58f10c
Update docs/references/ic-interface-spec.md
michael-weigelt Jan 28, 2025
1dda5a1
Update docs/references/ic-interface-spec.md
michael-weigelt Jan 28, 2025
4bc2bbb
Update docs/references/ic-interface-spec.md
michael-weigelt Jan 28, 2025
d30ff7f
Update docs/references/ic-interface-spec.md
michael-weigelt Jan 28, 2025
46f09cd
suggestions
michael-weigelt Jan 29, 2025
c14e718
semantics
michael-weigelt Jan 29, 2025
364a80f
typo
michael-weigelt Jan 29, 2025
1a9c592
semantics fix
michael-weigelt Jan 29, 2025
ea6a75d
arbitrary
michael-weigelt Jan 29, 2025
8bfa142
quotes
michael-weigelt Jan 29, 2025
6f97a68
renaming, adding curve arg
michael-weigelt Feb 3, 2025
2158afa
Update docs/references/ic-interface-spec.md
michael-weigelt Feb 4, 2025
e8bca2b
comments
michael-weigelt Feb 10, 2025
c277bae
semantics
michael-weigelt Feb 10, 2025
8c380b5
Merge remote-tracking branch 'origin' into mwe/cost_api
michael-weigelt Feb 12, 2025
c359747
clarify cost_call
michael-weigelt Feb 12, 2025
2b05f70
comments
michael-weigelt Feb 18, 2025
6eabee4
Merge branch 'master' into mwe/cost_api
michael-weigelt Feb 18, 2025
2ea843e
Update docs/references/ic-interface-spec.md
michael-weigelt Feb 18, 2025
4494d94
Update docs/references/ic-interface-spec.md
michael-weigelt Feb 18, 2025
7ca24c6
Update docs/references/ic-interface-spec.md
michael-weigelt Feb 18, 2025
b2744cd
comment
michael-weigelt Feb 18, 2025
d4aa91a
Merge branch 'mwe/cost_api' of github.com:dfinity/portal into mwe/cos…
michael-weigelt Feb 18, 2025
0f97f22
comment
michael-weigelt Feb 27, 2025
681b2a5
fix
michael-weigelt Feb 27, 2025
c981dc7
Merge branch 'master' into mwe/cost_api
Dfinity-Bjoern Mar 4, 2025
e0c97fd
Merge branch 'master' into mwe/cost_api
mraszyk Mar 5, 2025
938806b
remove bitflags
mraszyk Mar 7, 2025
830add8
Merge branch 'master' into mwe/cost_api
mraszyk Mar 10, 2025
b7785dd
changelog
mraszyk Mar 10, 2025
816aca1
Merge branch 'master' into mwe/cost_api
mraszyk Mar 10, 2025
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
103 changes: 101 additions & 2 deletions docs/references/ic-interface-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -1490,8 +1490,15 @@ defaulting to `I = i32` if the canister declares no memory.
ic0.time : () -> (timestamp : i64); // *
ic0.global_timer_set : (timestamp : i64) -> i64; // I G U Ry Rt C T
ic0.performance_counter : (counter_type : i32) -> (counter : i64); // * s
ic0.is_controller: (src : I, size : I) -> ( result: i32); // * s
ic0.in_replicated_execution: () -> (result: i32); // * s
ic0.is_controller : (src : I, size : I) -> ( result : i32); // * s
ic0.in_replicated_execution : () -> (result : i32); // * s

ic0.cost_call : (method_name_size: i64, payload_size : i64, dst : I) -> (); // * s
ic0.cost_create_canister : (dst : I) -> (); // * s
ic0.cost_http_request : (request_size : i64, max_res_bytes : i64, dst : I) -> (); // * s
ic0.cost_sign_with_ecdsa : (src : I, size : I, ecdsa_curve: i32, dst : I) -> i32; // * s
ic0.cost_sign_with_schnorr : (src : I, size : I, algorithm: i32, dst : I) -> i32; // * s
ic0.cost_vetkd_derive_encrypted_key : (src : I, size : I, vetkd_curve: i32, dst : I) -> i32; // * s

ic0.debug_print : (src : I, size : I) -> (); // * s
ic0.trap : (src : I, size : I) -> (); // * s
Expand Down Expand Up @@ -2036,6 +2043,50 @@ When executing a query or composite query method via a query call (i.e. in non-r

This traps if `ic0.data_certificate_present()` returns `0`.

### Cycle cost calculation {#system-api-cycle-cost}

Inter-canister calls have an implicit cost, and some calls to the management canister require the caller to attach cycles to the call explicitly.
The various cost factors may change over time, so the following system calls give the canister programmatic, up-to-date information about the costs.

These system calls return costs in Cycles, represented by 128 bits, which will be written to the heap memory starting at offset `dst`.

- `ic0.cost_call : (method_name_size: i64, payload_size : i64, dst : I) -> ()`; `I ∈ {i32, i64}`

This system call returns the amount of cycles that a canister needs to be above the freezing threshold in order to successfully make an inter-canister call. This includes the base cost for an inter-canister call, the cost for each byte transmitted in the request, the cost for the transmission of the largest possible response, and the cost for executing the largest possible response callback. The last two are cost _reservations_, which must be possible for a call to succeed, but they will be partially refunded if the real response and callback are smaller. So the cost of the actual inter-canister call may be less than this system call predicts, but it cannot be more.
`method_name_size` is the byte length of the method name, and `payload_size` is the byte length of the argument to the method.

- `ic0.cost_create_canister : (dst : I) -> ()`; `I ∈ {i32, i64}`

The cost of creating a canister on the same subnet as the calling canister via [`create_canister`](#ic-create_canister). Note that canister creation via a call to the CMC can have a different cost if the target subnet has a different replication factor.

- `ic0.cost_http_request(request_size : i64, max_res_bytes : i64, dst : I) -> ()`; `I ∈ {i32, i64}`

The cost of a canister http outcall via [`http_request`](#ic-http_request). `request_size` is the sum of the byte lengths of the following components of an http request:
- url
- headers - i.e., the sum of the lengths of all keys and values
- body
- transform - i.e., the sum of the transform method name length and the length of the transform context

`max_res_bytes` is the maximum response length the caller wishes to accept (the caller should provide the default value of `2,000,000` if no maximum response length is provided in the actual request to the management canister).

- `ic0.cost_sign_with_ecdsa(src : I, size : I, ecdsa_curve: i32, dst : I) -> i32`; `I ∈ {i32, i64}`

- `ic0.cost_sign_with_schnorr(src : I, size : I, algorithm: i32, dst : I) -> i32`; `I ∈ {i32, i64}`

- `ic0.cost_vetkd_derive_encrypted_key(src : I, size : I, vetkd_curve: i32, dst : I) -> i32`; `I ∈ {i32, i64}`

These system calls accept a key name via a textual representation for the specific signing scheme / key of a given size stored in the heap memory starting at offset `src`. They also accept an `i32` with the following interpretations:
- `ecdsa_curve: 0 → secp256k1`
- `schnorr_algorithm: 0 → bip340secp256k1, 1 → ed25519`
- `vetkd_curve: 0 → bls12_381`

See [`sign_with_ecdsa`](#ic-sign_with_ecdsa), [`sign_with_schnorr`](#ic-sign_with_schnorr) and [`vetkd_encrypted_key`](#ic-vetkd_encrypted_key) for more information.

These system calls trap if `src` + `size` or `dst` + 16 exceed the size of the WebAssembly memory. Otherwise, they return an `i32` with the following meaning:
- `0 (00)`: Success. The result can be found at the memory address `dst`.
- `1 (01)`: Invalid curve or algorithm. Memory at `dst` is left unchanged.
- `2 (10)`: Invalid key name for the given scheme/curve. Memory at `dst` is left unchanged.

### Debugging aids

In a local canister execution environment, the canister needs a way to emit textual trace messages. On the "real" network, these do not do anything.
Expand Down Expand Up @@ -7490,6 +7541,54 @@ ic0.in_replicated_execution<es>() : i32 =
then return 1
else return 0

I ∈ {i32, i64}
ic0.cost_call<es>(method_name_size: i64, payload_size: i64, dst: I) : () =
copy_cycles_to_canister<es>(dst, arbitrary())

I ∈ {i32, i64}
ic0.cost_create_canister<es>(dst: I) : () =
copy_cycles_to_canister<es>(dst, arbitrary())

I ∈ {i32, i64}
ic0.cost_cost_http_request<es>(request_size: i64, max_res_bytes: i64, dst: I) : () =
copy_cycles_to_canister<es>(dst, arbitrary())

I ∈ {i32, i64}
ic0.cost_sign_with_ecdsa<es>(src: I, size: I, ecdsa_curve: i32, dst: I) : i32 =
known_keys = arbitrary()
known_curves = arbitrary()
key_name = copy_from_canister<es>(src, size)
if ecdsa_curve ∉ known_curves then
return 1
if key_name ∉ known_keys then
return 2
copy_cycles_to_canister<es>(dst, arbitrary())
return 0

I ∈ {i32, i64}
ic0.cost_sign_with_schnorr<es>(src: I, size: I, algorithm: i32, dst: I) : i32 =
known_keys = arbitrary()
known_curves = arbitrary()
key_name = copy_from_canister<es>(src, size)
if algorithm ∉ known_algorithms then
return 1
if key_name ∉ known_keys then
return 2
copy_cycles_to_canister<es>(dst, arbitrary())
return 0

I ∈ {i32, i64}
ic0.cost_vetkd_derive_encrypted_key<es>(src: I, size: I, vetkd_curve: i32, dst: I) : i32 =
known_keys = arbitrary()
known_curves = arbitrary()
key_name = copy_from_canister<es>(src, size)
if vetkd_curve ∉ known_curves then
return 1
if key_name ∉ known_keys then
return 2
copy_cycles_to_canister<es>(dst, arbitrary())
return 0

I ∈ {i32, i64}
ic0.debug_print<es>(src : I, size : I) =
return
Expand Down