Skip to content

fix: Reserve enough HTTP outcall cycles for any deliverable result to fund itself - #11200

Open
eichhorl wants to merge 14 commits into
masterfrom
eichhorl/scale-consensus-cost
Open

fix: Reserve enough HTTP outcall cycles for any deliverable result to fund itself#11200
eichhorl wants to merge 14 commits into
masterfrom
eichhorl/scale-consensus-cost

Conversation

@eichhorl

@eichhorl eichhorl commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Background

Under pay-as-you-go pricing, the canister making an HTTP outcall can compute an estimate of the expected cycles cost (and thus the recommended amount of cycles to attach), by calling the ic0_cost_http_request_v2 function.

The attached cycles are then split evenly among all participating replicas, into the "per-replica allowances". Each replica consumes some of this allowance while making the HTTP request, and transforming and gossiping the response shares.

Aggregating the shares into the final response, which will be included and delivered as part of a block, costs a separate consensus fee. This consensus fee must be covered by the "unspent allowances" of replicas participating in the response.

Problem

If the recommended amount of cycles returned by ic0_cost_http_request_v2 tightly bounds the real cost of the outcall, this represents a liveness risk for the request.

Because the attached cycles are evenly split between participating replicas, this means that also the cycles intended to cover the consensus fee are split evenly between them. In the worst case, this means that aggregating a response into a block requires the unspent allowance of all participating replicas in order to cover the fee. For example:

  • A fully replicated outcall on a 13 node subnet, means that the attached cycles are split evenly between all 13 nodes.
  • All 13 nodes will make the HTTP request, and gossip their share
  • In order to reach consensus on the response, only 9 (= n - f) responses need to agree.
  • However, in order to cover the consensus cost, responses from all n replicas are required, leaving a fault tolerance of 0.

The same problem exists for flexible outcalls under most configurations. Notably, this problem does not exist for non-replicated outcalls, and more generally flexible outcalls where min == max == total, since in those cases all nodes making the call need to participate in the response regardless.

Proposed Changes

With this PR we therefore increase the recommended amount of cycles to attach to the call.

Specifically, for fully-replicated outcalls, we increase the cycles reserved for the consensus cost such that (after it is split into the allowances) shares from any set of threshold many nodes are enough to cover it.

For flexible outcalls, we increase the reserved cycles, such that each replica obtains enough allowance to cover for its own response to be included into the block.

@eichhorl eichhorl changed the title scale consensus cost fix: Scale the estimated consensus cost by the fraction of nodes required to reach consensus Aug 19, 2026
@github-actions github-actions Bot added the fix label Aug 19, 2026
@eichhorl eichhorl changed the title fix: Scale the estimated consensus cost by the fraction of nodes required to reach consensus fix: Scale the estimated consensus cost by the number of nodes required to reach consensus Aug 19, 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

Scales HTTP outcall consensus reserves so the minimum required contributors can fund response delivery.

Changes:

  • Adds a shared canister HTTP consensus-threshold helper.
  • Rounds and distributes consensus reserves per replica.
  • Expands pricing and payload-validation coverage.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
rs/types/types/src/canister_http.rs Adds the shared threshold calculation.
rs/types/cycles/src/cycles.rs Adds ceiling division for cycles.
rs/https_outcalls/pricing/src/payg.rs Verifies per-replica reserves.
rs/https_outcalls/pricing/src/fees.rs Scales and rounds consensus fees.
rs/https_outcalls/consensus/src/payload_builder/tests.rs Tests delivery at the quoted price.
rs/https_outcalls/consensus/benches/payload_validation.rs Uses the shared threshold helper.
rs/consensus/utils/src/membership.rs Centralizes committee threshold calculation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@eichhorl eichhorl changed the title fix: Scale the estimated consensus cost by the number of nodes required to reach consensus fix: Reserve enough HTTP outcall cycles for any deliverable result to fund itself Aug 19, 2026
@eichhorl
eichhorl marked this pull request as ready for review August 19, 2026 14:55
@eichhorl
eichhorl requested a review from a team as a code owner August 19, 2026 14:55
@zeropath-ai

zeropath-ai Bot commented Aug 19, 2026

Copy link
Copy Markdown

No security or compliance issues detected. Reviewed everything up to 8f1f1cf.

Security Overview
Detected Code Changes
Change Type Relevant files
Enhancement ► rs/consensus/utils/src/membership.rs
     Use canister_http_threshold for threshold calculation
► rs/https_outcalls/consensus/benches/payload_validation.rs
     Import canister_http_threshold and use it for threshold
► rs/https_outcalls/consensus/src/payload_builder/tests.rs
     Update thresholds in tests to canister_http_threshold(subnet_size) and adjust related expectations
► rs/https_outcalls/pricing/src/fees.rs
     Switch to canister_http_threshold in multiple places and enhance comments around max_consensus_fee/max_usage_fee
► rs/https_outcalls/pricing/src/payg.rs
     Add test case for threshold-based rounding behavior and related checks
► rs/types/cycles/src/cycles.rs
     Add div_ceil method and tests for ceiling division and panic on zero
► rs/types/types/src/canister_http.rs
     Expose canister_http_threshold and add tests for threshold behavior

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.

2 participants