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

calibrate gas for transaction/roll_buy/roll_sell operations #4464

Closed
3 tasks done
Tracked by #4415
bilboquet opened this issue Oct 10, 2023 · 3 comments
Closed
3 tasks done
Tracked by #4415

calibrate gas for transaction/roll_buy/roll_sell operations #4464

bilboquet opened this issue Oct 10, 2023 · 3 comments
Assignees

Comments

@bilboquet
Copy link
Contributor

bilboquet commented Oct 10, 2023

relates to: https://www.notion.so/massa-innoteam/Operation-base-gas-98e2f29a11ce41aa8765e7bdb458aac0

Description

Executing an operation costs a "base" amount of computational power.
For example, the execution thread is loaded at 60% when we have 5000 simple Transaction operations per second.
Transactions, RollBuys, RollSells, ExecuteSCs (with max_gas=0) and CallSCs (with max_gas=0) all cost zero gas.

This means that if someone emits blocks with 4999 Transactions, and a callSC with max_gas=MAX_BLOCK_GAS, the execution of that slot will take more time than allowed by MAX_BLOCK_GAS which causes a security issue.

Same problem for async executions: if max_gas = 0 we will end up executing many async messages without any cost.

Constraints and requirements

  • the VM (currently wasmer) must still use the old max_gas
  • block production, op pool, op execution gas limits must be updated
  • async message pool, async message execution limits must be updated

Definitions

  • Gas: is (has to be?) a common mesure, shared between all operations (in the general sense), of the CPU time usage. It’s a measure of computation time (on the reference architecture).
  • MAX_BLOC_GAS: represents the quantity of gas that can be consumed by operation executions on the reference architecture in 0.5s.
  • Max_gas: the parameter max_gas is an estimation of the time that the operation will take to execute on the reference architecture. Note: max_gas is declarative. When the execution of the operation starts gas starts burning and when / if it reaches 0 the operation is stopped. (enough gas VS too much gas ?).
  • Max_gas VS Fee (comparison with Ethereum)?
  • Define the limits we use

Remark: gas emerged from wasmer metering. According to previous definitions, for simple operation like execute_transaction_op one can estimate the gas as the ratio:

$$gas = {MAX\_BLOC\_GAS \over number\ of\ operation\ in\ 0.5s}$$

Problem analysis

Involved components

The call graph below shows the main entry point where the gas is consumed: execute_slot. This functions delegates the "real job" to execute_async_message and execute_operation. For execute_operation the gas consumption is estimated by get_gas_usage. The async messages to run are selected by take_batch_to_execute.

Overload with operations

Currently:

  • get_gas_usage returns 0 for:
    • execute_roll_sell_op
    • execute_roll_buy_op
    • execute_transaction_op
      This is what can trigger a kind of overload of the computational power regarding the operations.

Overload with async messages

The following code is an extract of take_batch_to_execute

for (message_id, message_info) in message_infos.iter() {
    if available_gas >= message_info.max_gas
        && slot >= message_info.validity_start
        && slot < message_info.validity_end
        && message_info.can_be_executed
    {
        available_gas -= message_info.max_gas;
        wanted_messages.push(message_id);
    }
}

We see that if message_info.max_gas is 0 a lots of async messages can be selected without taking into account the initialization cost of the virtual machine and leads to an overload of the computational power.

Counter measure

operations

The best solution here seems to evaluate the gas that operations cost and use those values in get_gas_usage:

async messages

Here we want to prevent the selection of message with a max_gas that is less than the gas needed to initialize the VM. The best solution that appears is prevent such messages to even be sent.

  • Do a gas calibration for the VM instantiation / initialization
  • Return "not enough gas" from send_massage with it's called with max_gas <= init_gas_cost
    see massa_execution_worker::interface_impl::InterfaceImpl fn send_message

The drawback of this solution is that it will fail at runtime while in most circumstance it should be possible to validate the condition before hand.

Note:
massa_execution_worker::execution::ExecutionState::execute_executesc_op and massa_execution_worker::execution::ExecutionState::execute_callsc_op may also benefit from the same kind of filter

Optimization

As show below, execute_slot is composed of two major blocs. Simply executing the operations before the async messages would allow to use the "operations gas" to compute more async messages.
image

What is unknown for the moment is if there is a requirement to execute operations before async messages.

Note: similarly if there is no async message, maybe we can spend more gas executing operations

Testing

@Leo-Besancon
Copy link
Contributor

Leo-Besancon commented Oct 16, 2023

Thanks for this write-up! The development aspect of this task seems on track.
The only additionnal feedback I would provide is to make sure that it is clear when reading the code what gas-related variable we should use where. (This will disambiguate max_block_gas, max_gas, and the quantity recovered from get_gas_usage).

@Eitu33, could you link your work on the cache and (briefly) edit the relevant paragraphs here?

@Eitu33
Copy link
Contributor

Eitu33 commented Oct 16, 2023

Here is all the information: #4483

@bilboquet
Copy link
Contributor Author

Update regarding async messages:
We changed our mind and applied a different solution:
We are now applaying a constant cost to async messages, like what is done for operations.
see #4546

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

No branches or pull requests

3 participants