Optimize context representation and gas counting
The current implementation witnesses gas consumption by updating two gas levels, one to respect the operation gas limit and the other to respect the block gas limit. These updates decrement the levels by exactly the same amount. Two ZArith subtractions and two ZArith comparisons are paid while only one subtraction and only one comparison are actually needed.
Indeed, let min_gas
be the minimum between block_gas
and operation_gas
, and max_gas
for their maximum. If one of the two counters has to hit 0, then it must be min_gas
.
With the first commit of this MR, gas updates and checks are only done on min_gas
. By remembering which of block_gas
and operation_gas
was the minimum using a boolean, we can update max_gas
afterward. This boolean can also be used to produce the right error message in case of gas exhaustion. This optimization removes two ZArith
operations over four in the critical routine consume_gas
.
The second commit of this MR introduces a layered representation for the context to get faster functional updates of the gas counter. Currently, each of these functional updates requires a copy of 200 bytes while this commit reduces this number to 16. This optimization is important because the updates of the gas counter are extremely frequent during script evaluation.