Skip to content

feat: Cap the amount of cycles that move into the per-replica HTTP outcalls allowance - #11012

Merged
eichhorl merged 18 commits into
masterfrom
eichhorl/http-cost-bound
Aug 14, 2026
Merged

feat: Cap the amount of cycles that move into the per-replica HTTP outcalls allowance#11012
eichhorl merged 18 commits into
masterfrom
eichhorl/http-cost-bound

Conversation

@eichhorl

@eichhorl eichhorl commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

... and other smaller fixes.

Background

The new pay-as-you-go pricing for HTTP outcalls consists of three parts:

  1. Base fee. This fee is charged for every request upfront.
  2. Per-replica fee. The remaining cycles after charging the base fee are split evenly between the participating replicas. Each replica consumes some of their allowance as the HTTP request is processed. In the end, the amount of consumed cycles is gossiped as part of the response share.
  3. Consensus cost. This fee is charged for including the aggregated HTTP response as part of a block. The cost is covered by the sum of cycles, that each replica didn't consume out of their per-replica allowance to produce its share.

If the call runs out of cycles at any point in time, it will fail. Therefore, in order to determine the correct amount of cycles to attach to the call, the system API offers a function http_request_fee_v2 which may be used to estimate the expected cost based on some parameters.

Proposed Changes

  1. Until now http_request_fee_v2 did not have a parameter to choose the "replication" of the outcall (i.e. fully-/non-/flexible-replication), which does have an effect on the cost. We introduce this missing parameter.
  2. The existing http_request_fee_v2 implementation duplicated the same calculation and constants of the newer pricing crate. We move the implementation of http_request_fee_v2 into the pricing crate, to ensure the functions don't diverge.
  3. The existing http_request_fee_v2 was charging for gossiping the response during fully replicated calls (see the original 650 consensus cost literal, vs. 600 now). This is incorrect since responses aren't gossiped in this case, therefore, the unification with the pricing crate removes this extra charge.
  4. The caller of http_request_fee_v2 is of course free to disregard the returned estimate, and attach as many cycles to the outcall as they please (say, their entire life savings). This is dangerous because in the current model, each malicious replica can burn the entirety of their allocated allowance share. To reduce this risk, we use the same functionality called by http_request_fee_v2 (but with parameters chosen to be as big as possible), to derive a maximum cost. When deriving the per-replica allowance, we now deduct at most the maximum possible cost from the caller's payment. The remaining balance is refunded when a response is delivered, like it is in legacy pricing.
  5. Previously, the per-replica allowance was defined as (payment - base_cost) / committee_size. Any remainder of this division was silently lost (i.e. charged to the caller but not observed by metrics). With this PR, any remainder is refunded back to the caller instead.

Future Work

We can use the function calculating the maximum outcall cost to tighten the bound on cycles that each replica on a free subnet may use to answer a request (currently set to 1T).

@github-actions github-actions Bot added the feat label Aug 3, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR updates HTTP outcalls pay-as-you-go pricing to (a) support estimating costs for different replication modes via http_request_fee_v2, (b) centralize the pricing formulas in the dedicated pricing crate, and (c) cap per-replica allowances withheld from a caller’s payment to the worst-case spendable amount (while refunding any split remainder instead of silently losing it).

Changes:

  • Introduces an explicit replication-kind parameter for http_request_fee_v2 and unifies the implementation under rs/https_outcalls/pricing.
  • Adds worst-case usage fee computation and uses it to cap withheld per-replica allowances; remainder from allowance splitting stays refundable via the response path.
  • Updates system API decoding/encoding + tests/benches to support the extended cost_http_request_v2 payload.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
rs/types/types/src/canister_http.rs Extends replication representation with ReplicationKind carrying flexible counts; adds defaults and node-count logic.
rs/test_utilities/execution_environment/src/lib.rs Exposes a helper to query max HTTP request usage fee in execution tests.
rs/https_outcalls/pricing/src/payg.rs Refactors tracker charging to use shared fee helpers; adds tests ensuring max-usage bound covers worst-case spend.
rs/https_outcalls/pricing/src/fees.rs Centralizes pricing formulas, adds total_fee and max_usage_fee, and refactors consensus/gossip fee computations.
rs/execution_environment/tests/hypervisor.rs Extends ic0.cost_http_request_v2 tests to cover replication variants and default flexible counts.
rs/execution_environment/src/execution_environment/tests.rs Updates execution-environment tests for new allowance/refund behavior, adds new refund/cap tests.
rs/execution_environment/src/execution_environment.rs Caps withheld allowances by worst-case usage fee and preserves remainder in payment for later refund.
rs/execution_environment/benches/system_api/execute_update.rs Updates benchmark params to include replication mode for cost_http_request_v2.
rs/cycles_account_manager/src/cycles_account_manager.rs Moves fee calculation to pricing crate, adds max-usage-fee API, and extends http_request_fee_v2 signature.
Suppressed comments (1)

rs/types/types/src/canister_http.rs:257

  • Doc comment is grammatically incorrect ("The flexible replication a request...") and is hard to parse. Rewording helps keep the public API docs clear.
    /// The flexible replication a request that does not specify its response counts
    /// gets on a subnet of `subnet_size` nodes, see [`Self::default_flexible_counts`].
    pub fn default_flexible(subnet_size: NumberOfNodes) -> Self {

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

Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
Comment thread rs/types/types/src/canister_http.rs Outdated
Comment thread rs/execution_environment/benches/system_api/execute_update.rs Outdated
@eichhorl
eichhorl marked this pull request as ready for review August 4, 2026 08:56
@eichhorl
eichhorl requested a review from a team as a code owner August 4, 2026 08:56
@zeropath-ai

zeropath-ai Bot commented Aug 4, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to d8bb97d.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/cycles_account_manager/src/cycles_account_manager.rs
    Add http_request_base_fee and max_http_request_usage_fee methods
► rs/cycles_account_manager/src/cycles_account_manager.rs
    Update http_request_fee_v2 signature and integration with ReplicationKind
Enhancement ► rs/embedders/src/wasmtime_embedder/system_api.rs
    Introduce ReplicationKind imports and CostHttpRequestOutcallType handling
► rs/embedders/src/wasmtime_embedder/system_api.rs
    Add CostHttpRequestV2Params with outcall_type and related logic
► rs/embedders/src/wasmtime_embedder/system_api.rs
    Adjust decoder quota for V2 cost params and integrate replication_kind in cost calculation
Enhancement ► rs/execution_environment/BUILD.bazel
    Add dependency on //rs/types/management_canister_types
Enhancement ► rs/execution_environment/benches/system_api/execute_update.rs
    Include ReplicationCounts import and extend test params with outcall_type
Enhancement ► rs/execution_environment/benches/system_api/execute_update.rs
    Update COST_HTTP_REQUEST_V2_PARAMS to include outcall_type and Flexible replication counts
Enhancement ► rs/execution_environment/src/execution_environment.rs
    Refactor wording: refundable cycles -> refundable payment
► rs/execution_environment/src/execution_environment.rs
    Change refund calculation to use max_http_request_usage_fee and per-replica allowances, adjust per-replica remaining payment logic
Enhancement ► rs/execution_environment/src/execution_environment/tests.rs
    Update tests to reflect per_replica_allowance and refundable_cycles calculations based on new pricing model
► rs/execution_environment/src/execution_environment/tests.rs
    Add tests for truncated allowance remainder and worst-case cost handling
Enhancement ► rs/execution_environment/tests/hypervisor.rs
    Update test code to align with V2 cost params and ReplicationKind usage
Enhancement ► rs/https_outcalls/pricing/src/fees.rs
    Introduce subnet_size_of helper and base_fee_amount adjustments for ReplicationKind
► rs/https_outcalls/pricing/src/fees.rs
    Add gossipping_base_fee, network_usage_fee, transform_usage_fee, and gossip_usage_fee helpers
► rs/https_outcalls/pricing/src/fees.rs
    Move to using ReplicationKind and adjust per-replica fee computations
► rs/https_outcalls/pricing/src/fees.rs
    Update base_fee to use fully replicated/non-replicated/flexible logic via ReplicationKind
Enhancement ► rs/https_outcalls/pricing/src/fees.rs
    Introduce MAX_COST_HTTP_REQUEST_V2_PARAMS_SIZE related constants and related quota-skip logic (MAX_COST_HTTP_REQUEST_V2_SKIPPING_QUOTA)
Enhancement ► rs/https_outcalls/pricing/src/fees.rs
    Adjust documentation and comments to reflect new pricing model and cost components
Enhancement ► rs/https_outcalls/consensus/src/payload_builder/tests.rs
    Adjust tests to use consensus_fee for non-flexible cost calculations and related imports

@pierugo-dfinity pierugo-dfinity left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would be happy if someone else had a second look on the execution layer parts, as I'm less comfortable with that part of the code 🙏 Maybe @mraszyk

Comment thread rs/execution_environment/src/execution_environment/tests.rs
Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
Comment thread rs/https_outcalls/pricing/src/fees.rs
Comment thread rs/https_outcalls/pricing/src/fees.rs
Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
Comment thread rs/types/types/src/canister_http.rs
eichhorl and others added 2 commits August 5, 2026 17:09
Co-authored-by: Pierugo Pace <pierugo.pace@dfinity.org>
Co-authored-by: Pierugo Pace <pierugo.pace@dfinity.org>
@eichhorl
eichhorl requested a review from mraszyk August 6, 2026 06:44
Comment thread rs/cycles_account_manager/src/cycles_account_manager.rs Outdated
Comment thread rs/embedders/src/wasmtime_embedder/system_api.rs
Comment thread rs/execution_environment/tests/hypervisor.rs Outdated
Comment thread rs/execution_environment/tests/hypervisor.rs Outdated
Comment thread rs/https_outcalls/pricing/src/payg.rs Outdated
Comment thread rs/execution_environment/src/execution_environment/tests.rs Outdated
Comment thread rs/execution_environment/src/execution_environment/tests.rs
Comment thread rs/https_outcalls/pricing/src/fees.rs Outdated
@eichhorl
eichhorl requested a review from mraszyk August 14, 2026 06:39

@mraszyk mraszyk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM I didn't review all the formulas in the file rs/https_outcalls/pricing/src/fees.rs so I don't approve

@eichhorl
eichhorl added this pull request to the merge queue Aug 14, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Aug 14, 2026
@eichhorl
eichhorl added this pull request to the merge queue Aug 14, 2026
Merged via the queue into master with commit 22f461c Aug 14, 2026
43 of 44 checks passed
@eichhorl
eichhorl deleted the eichhorl/http-cost-bound branch August 14, 2026 12:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants