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

Remove 0 as a special case in gas/storage meters #6890

Open
wants to merge 36 commits into
base: master
Choose a base branch
from

Conversation

rockbmb
Copy link
Contributor

@rockbmb rockbmb commented Dec 13, 2024

Closes #6846 .

@rockbmb rockbmb added T2-pallets This PR/Issue is related to a particular pallet. T7-smart_contracts This PR/Issue is related to smart contracts. T10-tests This PR/Issue is related to tests. labels Dec 13, 2024
@rockbmb rockbmb self-assigned this Dec 13, 2024
@rockbmb rockbmb force-pushed the evm-contracts-limit-nested-calls-gas branch 2 times, most recently from 376e944 to 4832380 Compare December 17, 2024 02:17
Also, a limit of 0 when determining a nested call's metering limit would
mean it was free to use all of the callee's resources.
Now, a limit of 0 means that the nested call will have an empty storage
meter.
In particular, this commit removes the usage of `0` as unlimited
metering in the following tests:

- `nonce`
- `last_frame_output_works_on_instantiate`
- `instantiation_from_contract`
- `immutable_data_set_works_only_once`
- `immutable_data_set_errors_with_empty_data`
- `immutable_data_access_checks_work`
@rockbmb rockbmb force-pushed the evm-contracts-limit-nested-calls-gas branch from ed1f312 to 8e66f50 Compare December 17, 2024 19:15
@rockbmb rockbmb marked this pull request as ready for review December 17, 2024 19:31
@athei athei requested review from athei and xermicus December 17, 2024 20:08
Copy link
Member

@xermicus xermicus left a comment

Choose a reason for hiding this comment

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

The basic idea of the 63/64 rule looks correct to me but there are many failing tests. I left some nits.

.min(self.gas_left);
self.gas_left -= amount;
GasMeter::new(amount)
// The reduction to 63/64 is to emulate EIP-150
Copy link
Member

Choose a reason for hiding this comment

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

This should be a doc-comment

substrate/frame/revive/src/storage/meter.rs Outdated Show resolved Hide resolved
debug_assert!(matches!(self.contract_state(), ContractState::Alive));

// Limit gas for nested call, per EIP-150.
Copy link
Member

Choose a reason for hiding this comment

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

This could go into the doc-comment (which is no no-longer correct I think)

This fixes, among other tests:
* `tests::gas_consumed_is_linear_for_nested_calls` test
* `tests::deposit_limit_in_nested_calls`
* `tests::transient_storage_limit_in_call`
* `tests::call_return_code`
* `test::chain_extension_temp_storage_works`
* `tests::origin_api_works`
* `tests::read_only_call_works`
@rockbmb
Copy link
Contributor Author

rockbmb commented Dec 19, 2024

@xermicus the meters in frame::contracts::{gas, storage::meter} also need to reflect this, correct?

@athei
Copy link
Member

athei commented Dec 19, 2024

Sorry if this wasn't clear: Only pallet_revive and its supporting crates should be changed. pallet_contracts should remain untouched. It does't receive any updates beyond critical bug fixes anymore. Can you roll back the changes there? Will have a deeper look then.

@rockbmb
Copy link
Contributor Author

rockbmb commented Dec 19, 2024

@athei frame/contracts changes have been reverted, thanks for explaining this.

Most of the previously failing tests were caused by the contract code of those tests using the now-removed '0 means "use all available gas"' semantic.

After fixing this, cargo test --package pallet-revive:0.1.0 --lib --all-features yields:

failures:
    benchmarking::benchmarks::bench_seal_instantiate
    tests::call_diverging_out_len_works
    tests::create1_with_value_works
    tests::delegate_call
    tests::deploy_and_call_other_contract
    tests::deposit_limit_in_nested_calls
    tests::deposit_limit_in_nested_instantiate
    tests::destroy_contract_and_transfer_funds
    tests::failed_deposit_charge_should_roll_back_call
    tests::gas_estimation_call_runtime
    tests::gas_estimation_for_subcalls
    tests::return_data_api_works
    tests::skip_transfer_works
    tests::storage_deposit_callee_works
    tests::test_debug::debugging_works

The contracts the above tests rely on have removed usages of 0 as "use all", so their failures are somewhere else.

Copy link

github-actions bot commented Jan 6, 2025

Command "fmt" has started 🚀 See logs here

Copy link

github-actions bot commented Jan 6, 2025

Command "fmt" has finished ✅ See logs here

A deposit limit of 0 no longer is a special case, and is treated as
no limit being available for use in a benchmarking function.
@rockbmb
Copy link
Contributor Author

rockbmb commented Jan 6, 2025

The only tests that still need to be addressed:

failures:
    tests::gas_estimation_for_subcalls
    tests::skip_transfer_works

substrate/frame/revive/src/wasm/runtime.rs Outdated Show resolved Hide resolved
substrate/frame/revive/src/wasm/runtime.rs Outdated Show resolved Hide resolved
@rockbmb
Copy link
Contributor Author

rockbmb commented Jan 7, 2025

@athei One question:

What is the meaning of value: 0u32.into()?
I.e. after the semantic change in the meaning of 0 introduced by this PR, should its default still be 0?

This is causing tests::gas_estimation_for_subcalls to fail when creating the storage meter for Pallet::bare_call by creating a meter with 0 limit, eventually leading to ContractTrapped.

@athei
Copy link
Member

athei commented Jan 8, 2025

@athei One question:

What is the meaning of value: 0u32.into()? I.e. after the semantic change in the meaning of 0 introduced by this PR, should its default still be 0?

This is causing tests::gas_estimation_for_subcalls to fail when creating the storage meter for Pallet::bare_call by creating a meter with 0 limit, eventually leading to ContractTrapped.

The line you quoted is value which is the amount of balance sent to the callee as part of the call. This is unrelated to the deposit limit you changed. Its behavior should be unaffected by this PR.

There, its meaning was "use all available gas", which needed to be
updated to `Weight::MAX`.
substrate/frame/revive/uapi/src/lib.rs Outdated Show resolved Hide resolved
substrate/frame/revive/src/exec.rs Outdated Show resolved Hide resolved
@athei
Copy link
Member

athei commented Jan 10, 2025

For context, we agreed to roll back the EIP-150 changes because limiting the amount of gas that can be used depending on call depth breaks dry running: You can't just run the dry-run once with a lot of gas. The gas that was consumed in this run will not be enough if used as a gas limit. This is because not all of the available gas can be used if sub calls are involved.

So this PR only removes the special casing of 0 meaning "all resources".

@rockbmb rockbmb changed the title Reduce gas/storage limits in nested calls Remove 0 as a special case in gas/storage meters Jan 10, 2025
substrate/frame/revive/src/storage/meter.rs Outdated Show resolved Hide resolved
@athei
Copy link
Member

athei commented Jan 10, 2025

I don't get why the benchmarks are failing.

@rockbmb
Copy link
Contributor Author

rockbmb commented Jan 10, 2025

@athei I can always run /cmd bench --pallet pallet_revive.

No significant code was added, only removed (enfore_subcall_limit is only a handful of instructions), but maybe the numbers were lowered enough to warrant rerunning benchmarks.

@paritytech-workflow-stopper
Copy link

All GitHub workflows were cancelled due to failure one of the required jobs.
Failed workflow url: https://github.com/paritytech/polkadot-sdk/actions/runs/12714362978
Failed job name: run-frame-omni-bencher

@rockbmb
Copy link
Contributor Author

rockbmb commented Jan 10, 2025

/cmd bench --pallet pallet_revive

Copy link

Command "bench --pallet pallet_revive" has started 🚀 See logs here

Copy link

Command "bench --pallet pallet_revive" has failed ❌! See logs here

Command output:

❌ Failed benchmarks of runtimes/pallets:
-- dev: ['pallet_revive']
-- asset-hub-westend: ['pallet_revive']

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T2-pallets This PR/Issue is related to a particular pallet. T7-smart_contracts This PR/Issue is related to smart contracts. T10-tests This PR/Issue is related to tests.
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

Limit resources to 63/64 on sub calls and remove 0 as special case for "take all"
3 participants