Skip to content
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

Contracts: xcm host fn fixes #3086

Merged
merged 16 commits into from
Feb 19, 2024
Merged

Contracts: xcm host fn fixes #3086

merged 16 commits into from
Feb 19, 2024

Conversation

pgherveou
Copy link
Contributor

@pgherveou pgherveou commented Jan 26, 2024

Xcm changes:

  • Fix pallet_xcm::execute, move the logic into The ExecuteController so it can be shared with anything that implement that trait.
  • Make ExecuteController::execute retursn DispatchErrorWithPostInfo instead of DispatchError, so that we don't charge the full max_weight provided if the execution is incomplete (useful for force_batch or contracts calls)
  • Fix docstring for pallet_xcm::execute, to reflect the changes from pallet-xcm: ensure xcm outcome is complete, or discard all state changes done by extrinsic #2405
  • Update the signature for ExecuteController::execute, we don't need to return the Outcome anymore since we only care about Outcome::Complete

Contracts changes:

  • Update host fn xcm_exexute, we don't need to write the Outcome to the sandbox memory anymore. This was also not charged as well before so it if fixes this too.
  • One of the issue was that the dry_run of a contract that call xcm_execute would exhaust the gas_limit.

This is because XcmExecuteController::execute takes a max_weight argument, and since we don't want the user to specify it manually we were passing everything left by pre-charghing ctx.ext.gas_meter().gas_left()

  • To fix it I added a fn influence_lowest_limit on the Token trait and make it return false for RuntimeCost::XcmExecute.
  • Got rid of the RuntimeToken indirection, we can just use RuntimeCost directly.

@pgherveou pgherveou requested a review from athei as a code owner January 26, 2024 16:57
@pgherveou pgherveou requested a review from a team January 26, 2024 16:57
@pgherveou pgherveou requested a review from a team as a code owner January 26, 2024 16:57
@pgherveou pgherveou added the R0-silent Changes should not be mentioned in any release notes label Jan 26, 2024
@pgherveou
Copy link
Contributor Author

bot fmt

@command-bot
Copy link

command-bot bot commented Jan 26, 2024

@pgherveou https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5043153 was started for your command "$PIPELINE_SCRIPTS_DIR/commands/fmt/fmt.sh". Check out https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/pipelines?page=1&scope=all&username=group_605_bot to know what else is being executed currently.

Comment bot cancel 9-403653df-b076-43e1-8125-fe33c8cb6b14 to cancel this command or bot cancel to cancel all commands in this pull request.

@command-bot
Copy link

command-bot bot commented Jan 26, 2024

@pgherveou Command "$PIPELINE_SCRIPTS_DIR/commands/fmt/fmt.sh" has finished. Result: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5043153 has finished. If any artifacts were generated, you can download them from https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5043153/artifacts/download.

@pgherveou pgherveou changed the title Contracts: Fix xcm_execute Contracts: xcm host fn fixes Jan 26, 2024
@pgherveou pgherveou requested a review from a team January 29, 2024 09:37
@pgherveou pgherveou changed the base branch from master to pg/fix-mdlint January 29, 2024 09:38
Base automatically changed from pg/fix-mdlint to master January 29, 2024 10:49
Copy link
Member

@athei athei left a comment

Choose a reason for hiding this comment

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

This fixes the problem but maybe we can side step it entirely. See my comment.

substrate/frame/contracts/src/wasm/runtime.rs Show resolved Hide resolved
@athei
Copy link
Member

athei commented Feb 2, 2024

I thought about this change again. While this fixes the problem that the gas_required will be too high it will introduce the inverse problem: It might be too low. Since we require the gas to be there before calling into the XCM it has influence the lowest experienced gas. Otherwise it will become too optimistic. Reason is that the XCM execution itself is not metered. So we have to check that the gas is actually there before executing as we do.

So the current code (before the PR) is actually correct with regard to influencing the lowest experienced gas.

The actual problem here is that taking "all the gas" is a very vast overestimation of what the XCM needs. Especially in case of dry run where we supply the whole block gas limit.

There are only two fixes for my problem I can thing of:

  • Let the contract specify a limit
  • Use a Weigher as pallet-xcm does in order to come up with a better upper bound

The problem of the second approach is that WeightInfo::weight() is fallible. I assume we cannot find out the pre-dispatch weight for all XCM programs. I hope there is some metering going on in the background in those causes. I assume there has to be since pallet-xcm::execute uses the same mechanism.

You have to investigate what is going on there? What if a program is not Weighable? How does pallet-xcm handle this situation? Does the executor about the execution some where?

@pgherveou
Copy link
Contributor Author

It might be too low

why is that? We know that the pre-dispatch weight is execute_weight don't we get exactly what we need by letting the xcm run with a lot of weight and then using the refund to calculate a precise dry-run weight for the call.

@athei
Copy link
Member

athei commented Feb 3, 2024

You are right this should work because the weight we take is dependent on the remaining weight. As long as it is not a fixed number it should work.

@paritytech-review-bot paritytech-review-bot bot requested a review from a team February 3, 2024 12:09
@pgherveou
Copy link
Contributor Author

@paritytech/xcm can you take a look at these minor changes in pallet-xcm when you have a chance 🙏

Copy link
Member

@athei athei left a comment

Choose a reason for hiding this comment

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

Yes the change makes sense to me that we are only return Ok for a complete execution.

@pgherveou
Copy link
Contributor Author

Ping @KiChjang or @franciscoaguirre

@pgherveou pgherveou enabled auto-merge February 19, 2024 12:38
@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
Job name: test-linux-stable 1/3
Logs: https://gitlab.parity.io/parity/mirrors/polkadot-sdk/-/jobs/5262268

@pgherveou pgherveou added this pull request to the merge queue Feb 19, 2024
Merged via the queue into master with commit ca382f3 Feb 19, 2024
113 of 129 checks passed
@pgherveou pgherveou deleted the pg/fix_xcm_execute branch February 19, 2024 15:54
bgallois pushed a commit to duniter/duniter-polkadot-sdk that referenced this pull request Mar 25, 2024
## Xcm changes:
- Fix `pallet_xcm::execute`, move the logic into The `ExecuteController`
so it can be shared with anything that implement that trait.
- Make `ExecuteController::execute` retursn `DispatchErrorWithPostInfo`
instead of `DispatchError`, so that we don't charge the full
`max_weight` provided if the execution is incomplete (useful for
force_batch or contracts calls)
- Fix docstring for `pallet_xcm::execute`, to reflect the changes from
paritytech#2405
- Update the signature for `ExecuteController::execute`, we don't need
to return the `Outcome` anymore since we only care about
`Outcome::Complete`

## Contracts changes:

- Update host fn `xcm_exexute`, we don't need to write the `Outcome` to
the sandbox memory anymore. This was also not charged as well before so
it if fixes this too.
- One of the issue was that the dry_run of a contract that call
`xcm_execute` would exhaust the `gas_limit`.

This is because `XcmExecuteController::execute` takes a `max_weight`
argument, and since we don't want the user to specify it manually we
were passing everything left by pre-charghing
`ctx.ext.gas_meter().gas_left()`

- To fix it I added a `fn influence_lowest_limit` on the `Token` trait
and make it return false for `RuntimeCost::XcmExecute`.
- Got rid of the `RuntimeToken` indirection, we can just use
`RuntimeCost` directly.

---------

Co-authored-by: command-bot <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
R0-silent Changes should not be mentioned in any release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants