You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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
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:
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.
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
The text was updated successfully, but these errors were encountered:
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?
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
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
wasmer
) must still use the old max_gasDefinitions
0.5s
.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 startsgas
starts burning and when / if it reaches0
the operation is stopped. (enough gas VS too much gas ?).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: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" toexecute_async_message
andexecute_operation
. Forexecute_operation
the gas consumption is estimated byget_gas_usage
. The async messages to run are selected bytake_batch_to_execute
.Overload with operations
Currently:
get_gas_usage
returns0
for: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
We see that if
message_info.max_gas
is0
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 inget_gas_usage
:execute_roll_sell_op
,execute_roll_buy_op
andexecute_transaction_op
and updateget_gas_usage
#4467async 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.send_massage
with it's called withmax_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
andmassa_execution_worker::execution::ExecutionState::execute_callsc_op
may also benefit from the same kind of filterOptimization
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.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
The text was updated successfully, but these errors were encountered: