-
Notifications
You must be signed in to change notification settings - Fork 462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add system API endpoints for cycle cost calculation #4110
base: master
Are you sure you want to change the base?
Conversation
🤖 Here's your preview: https://c4y23-xqaaa-aaaam-abayq-cai.icp0.io |
docs/references/ic-interface-spec.md
Outdated
- 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
`max_res_bytes` is the maximum response length the caller wishes to accept. | |
`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). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this syscall, the max_res_bytes is not optional, so there is no default value here. If the user follows the documentation of http_request, they will get the full picture. But I think here this formulation is misleading.
In other words: The function signature tells the caller that they MUST provide this data explicitly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a sentence to clarify, let me know what you think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this syscall, the max_res_bytes is not optional, so there is no default value here.
There is a default value in the replica implementation that the caller has to supply here because system API doesn't allow easily modelling optional values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a sentence to clarify, let me know what you think.
I don't see it. Could you please share a link?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pushed now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another suggestion: We can specify that the passed value is clamped to the true replica's maximum. So if the user does not want to bound the max_response_bytes in the call to the management canister, they can supply u64::MAX here and we clamp it to the true 2_000_000 (or whatever this evolves to).
This would save the caller from having to know the true maximum when they only want to call mgmt with None.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's a reasonable suggestion, but I'll bring this up in the spec meeting to gather more feedback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rephrased the suggestion to
(the caller should provide the default value of `2,000,000` if no maximum response length is provided in the actual request).
(as discussed separately)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please also add functions into the formal semantics: the actual return value can be abstracted over as arbitrary()
, but the rest should follow, e.g., ic0.canister_cycles_balance128
.
Co-authored-by: mraszyk <[email protected]>
Co-authored-by: mraszyk <[email protected]>
Co-authored-by: mraszyk <[email protected]>
Co-authored-by: mraszyk <[email protected]>
Co-authored-by: mraszyk <[email protected]>
Co-authored-by: mraszyk <[email protected]>
Here's an idea for a different approach:
The advantages as I see them:
The only downside that I see is that the cost of the |
@oggy-dfin thanks for the input. I like that this approach leads to a smaller API surface and covers current and future use cases. The problem I see is with parsing the payload, as you have pointed out yourself: This is cheap and constant effort for the So we would buy extensibility with 1) more complexity in the impl and 2) more costs to the caller. But is extensibility really worth that? I would consider adding a new system API endpoint of an existing type is a small effort already. Although granted, it is less pleasant than an API that just covers it by design. Another downside of simulating a call is that you have to have your payload ready to know the cost. If you have access to the proposed API, where you can just provide some payload lengths, you can make decisions based on costs before deciding on the details of a call. Not sure how interesting this is in reality, but it would suck if people had to compose some dummy data just to predict the cost of a similar call. |
is this benchmark using serde_bytes for decoding Vec?
a dependency on candid already exists in the system-api crate for the sake of routing
this complexity can't be avoided, it can only be pushed to the CDKs |
I measured the instructions on a canister that turns a Vec into a struct using candid::Decode!(). Whether candid uses serde_bytes itself, idk.
Yes. But there, the precise call type is already known without inspecting a blob. |
serde_bytes are used if the type you want to decode contains corresponding serde_bytes annotation. Could you please share the type definition you're decoding to? |
I think what rubs me the wrong way about the current proposal and the problem of possible future extensions is that the couples the System API (which is currently oblivious to the existence of the management canister and all other functionality) with these other special aspects of the system. Obviously my proposal would also couple them, just at the implementation level (by having to understand the payload) instead of the API level, and in some sense it's inevitable if we want to provide a synchronous API. |
While I agree with your analysis, I'd make a different trade-off. Having an API that is agnostic to the details has these disadvantages:
|
|
||
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 | ||
- method |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- method |
this is not part of the formula and it'd be unclear anyway how to compute the byte length of the enumeration variant
|
||
- `ic0.cost_sign_with_schnorr(src : I, size : I, algorithm: i32, dst : I) -> ()`; `I ∈ {i32, i64}` | ||
|
||
- `ic0.cost_vetkd_derive_encrypted_key(src : I, vetkd_curve: i32, size : I, dst : I) -> ()`; `I ∈ {i32, i64}` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't src and size be next to each other?
Design Doc