Skip to content

refactor: require HTTP outcall base fee#185

Merged
lpahlavi merged 24 commits intomainfrom
pahlavi/require-http-outcall-base-fee
Jul 29, 2025
Merged

refactor: require HTTP outcall base fee#185
lpahlavi merged 24 commits intomainfrom
pahlavi/require-http-outcall-base-fee

Conversation

@lpahlavi
Copy link
Contributor

@lpahlavi lpahlavi commented Jul 9, 2025

(XC-416) Require all requests to endpoints making an HTTP outcall to have at least the base cycles fee of an HTTP outcall attached when not in demo mode.

@lpahlavi lpahlavi force-pushed the pahlavi/require-http-outcall-base-fee branch 3 times, most recently from 5ac86a8 to ad65b99 Compare July 9, 2025 13:32
@lpahlavi lpahlavi requested a review from gregorydemay July 9, 2025 13:58
@lpahlavi lpahlavi marked this pull request as ready for review July 9, 2025 13:58
@lpahlavi lpahlavi requested a review from a team as a code owner July 9, 2025 13:58
Copy link
Contributor

@gregorydemay gregorydemay left a comment

Choose a reason for hiding this comment

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

Thanks @lpahlavi for this PR! Main concern is related to the exposed error code, but otherwise LGTM!

@lpahlavi lpahlavi requested a review from gregorydemay July 10, 2025 09:07
Copy link
Contributor

@gregorydemay gregorydemay left a comment

Choose a reason for hiding this comment

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

Thanks for the improvements @lpahlavi! Some remarks regarding the error mapping.

Comment on lines 37 to 42
fn base_fee() -> u128 {
let num_nodes = read_state(|state| state.get_num_subnet_nodes());
3_000_000_u128
.saturating_add(60_000_u128.saturating_mul(num_nodes as u128))
.saturating_mul(num_nodes as u128)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: note that the base fee only changes with state.get_num_subnet_nodes(). In other words, we could have a new private field in State that contains that value so that it's computed only once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes! Good idea! Done.

@lpahlavi lpahlavi force-pushed the pahlavi/require-http-outcall-base-fee branch from 79122f2 to 8ba52de Compare July 11, 2025 14:35
@lpahlavi lpahlavi changed the base branch from main to lpahlavi/add-try-send-method July 11, 2025 14:36
@lpahlavi
Copy link
Contributor Author

Thanks a lot for the review and comments @gregorydemay! I moved the refactoring related to the new try_send method (and the whole RejectCode vs RejectionCode) to #187 so unfortunately I had to rebase this PR, but it's quite a bit smaller now so it should be hopefully easier to review!

@lpahlavi lpahlavi requested a review from gregorydemay July 11, 2025 14:48
log_filter: LogFilter,
mode: Mode,
num_subnet_nodes: u32,
base_http_outcall_fee: u128,
Copy link
Contributor

Choose a reason for hiding this comment

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

note that adding a mandatory field to a struct serialized in stable memory will fail to upgrade, as shown by the CI pipeline

Client error: failed to call getBalance: (SysFatal, "An error happened during the call: 5: IC0503: Error from Canister zaylz-mqaaa-aaaar-qaqzq-cai: Canister called ic0.trap with message: 'Panicked at 'failed to decode memory bytes a6686170695f6b657973a96e416c6368656d794d61696e6e65747820306e6d7372394e755a4c347a57744f62544f7747467035314e776638626969346d416c6368656d794465766e65747820306e6d7372394e755a4c347a57744f62544f7747467035314e776638626969346b416e6b724d61696e6e65747840663330663736633030386361626539343130373238363130383161373862326661313865643937383630616263366432373534656563373332646236383532316a416e6b724465766e657478406633306637366330303863616265393431303732383631303831613738623266613138656439373836306162633664323735346565633733326462363835323171436861696e737461636b4d61696e6e65747820323334303131643131326336303339666531663837363038663139306662636570436861696e737461636b4465766e6574782066323562396561656635626263653031313235333639643734643434663230626a447270634465766e6574782c416d5356303941636845703874447a4243743873796a55625530524f45377752384c30464e6a57436e30326a6d48656c6975734d61696e6e6574782438623464643638612d383031322d346533342d396361352d3337356664333732323938636c48656c6975734465766e6574782438623464643638612d383031322d346533342d396361352d333735666433373232393863726170695f6b65795f7072696e636970616c7381581dce7a4082861dd14808ea4b8ac53a9f2a59e35747757afd24c2d00a7302716f766572726964655f70726f7669646572a16c6f766572726964655f75726cf66a6c6f675f66696c7465726753686f77416c6c646d6f6465664e6f726d616c706e756d5f7375626e65745f6e6f6465731822: Semantic(None, "missing field base_http_outcall_fee")', canister/src/memory/mod.rs:88:29'.\nConsider gracefully handling failures from this canister or altering the canister to handle exceptions. See documentation: https://internetcomputer.org/docs/current/references/execution-errors#trapped-explicitly")

It would be a good idea to

  1. add a test to ensure state compatibility, e.g. like this
  2. Make this field optional and change the getter to something like pub fn compute_base_http_outcall_fee(&mut self) -> u128 that returns the previously computed value if there is one and otherwise set it and returns.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch! I've modified State to have an optional base_http_outcall_fee field instead and added some tests.

Base automatically changed from lpahlavi/add-try-send-method to main July 28, 2025 11:55
@lpahlavi lpahlavi requested a review from gregorydemay July 28, 2025 14:49
Copy link
Contributor

@gregorydemay gregorydemay left a comment

Choose a reason for hiding this comment

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

Thanks for adding the test! I think there is a minor problem with the lazy_ method but otherwise code LGTM!

}

pub fn get_base_http_outcall_fee(&self) -> u128 {
pub fn lazy_compute_base_http_outcall_fee(&self) -> u128 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that this will constantly re-evaluate compute_base_http_outcall_fee(self.num_subnet_nodes) if the initial value is empty. To be lazy, it's unavoidable that this method must be able to mutate the underlying state (i.e. parameter &mut self instead of &self).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

🙈 I think my brain was mush because of the jetlag yesterday, thanks for catching that!

@lpahlavi lpahlavi requested a review from gregorydemay July 29, 2025 06:04
Copy link
Contributor

@gregorydemay gregorydemay left a comment

Choose a reason for hiding this comment

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

Thanks @lpahlavi for the improvements!

@lpahlavi lpahlavi merged commit 4d142a5 into main Jul 29, 2025
12 checks passed
@lpahlavi lpahlavi deleted the pahlavi/require-http-outcall-base-fee branch July 29, 2025 09:36
This was referenced Jul 30, 2025
lpahlavi added a commit that referenced this pull request Jul 31, 2025
## 🤖 New release

* `sol_rpc_types`: 1.0.0 -> 2.0.0 (⚠ API breaking changes)
* `sol_rpc_canister`: 1.0.0 -> 1.1.0 (✓ API compatible changes)
* `sol_rpc_client`: 1.0.0 -> 2.0.0 (⚠ API breaking changes)

### ⚠ `sol_rpc_types` breaking changes

```text
--- failure constructible_struct_adds_field: externally-constructible struct adds field ---

Description:
A pub struct constructible with a struct literal has a new pub field. Existing struct literals must be updated to include the new field.
        ref: https://doc.rust-lang.org/reference/expressions/struct-expr.html
       impl: https://github.com/obi1kenobi/cargo-semver-checks/tree/v0.41.0/src/lints/constructible_struct_adds_field.ron

Failed in:
  field TransactionStatusMeta.cost_units in /tmp/.tmpuppblp/sol-rpc-canister/libs/types/src/solana/transaction/mod.rs:286
```

<details><summary><i><b>Changelog</b></i></summary><p>

## `sol_rpc_types`

<blockquote>

## [2.0.0] - 2025-07-31

### Added

- Add optional `cost_units` to `TransactionStatusMeta`
([#180](#180))
- Add build requirements to READMEs and rustdoc
([#169](#169))
- Add `Cargo.toml` linting to CI pipeline
([#155](#155))

### Changed

- Require HTTP outcall base fee
([#185](#185))
- Select supported providers based on successful responses
([#183](#183))
- Migrate dependencies to `solana-sdk` repository
([#55](#55))
- Improve docs for `InstallArgs`
([#172](#172))

[2.0.0]:
https://github.com/dfinity/sol-rpc-canister/compare/1.0.0..2.0.0
</blockquote>

## `sol_rpc_canister`

<blockquote>

## [1.1.0] - 2025-07-31

### Added

- Add optional `cost_units` to `TransactionStatusMeta` (#180)
- Add more metrics (#144)

### Changed

- Do not record metrics for requests with insufficient cycles (#184)
- Require HTTP outcall base fee (#185)
- Select supported providers based on successful responses (#183)

### Fixed

- Change `nat16` to `nat32` in examples (#151)
</blockquote>

## `sol_rpc_client`

<blockquote>

## [2.0.0] - 2025-07-31

### Added

- Add `try_send` method to SOL RPC client
([#187](#187))
- Add build requirements to READMEs and rustdoc
([#169](#169))
- Add `Cargo.toml` linting to CI pipeline
([#155](#155))

### Changed

- Revert `sol_rpc_client` bump
([#178](#178))
- Migrate dependencies to `solana-sdk` repository
([#55](#55))
- Bump `sol_rpc_client` to `v1.0.1`
([#164](#164))
- Enable `ed25519` feature in docs
([#162](#162))

### Fixed

- Use correct fee for t-sig with local development key
([#160](#160))

[2.0.0]:
https://github.com/dfinity/sol-rpc-canister/compare/1.0.0..2.0.0
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Louis Pahlavi <louis.pahlavi@dfinity.org>
@github-actions github-actions bot mentioned this pull request Aug 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants