EIP-2929: Gas cost increases for state access opcodes#289
EIP-2929: Gas cost increases for state access opcodes#289yperbasis wants to merge 8 commits intoipsilon:evmcfrom
Conversation
lib/evmone/instructions_calls.cpp
Outdated
|
|
||
| state.stack.push(0); // Assume failure. | ||
|
|
||
| if (state.rev >= EVMC_BERLIN && state.host.access_account(dst) == EVMC_COLD_ACCESS) |
There was a problem hiding this comment.
Minimal improvement here would be to merge access_account() and account_exists(). I believe the account can have 3 statuses then: hot, cold, non-existing.
BTW, can a non-existing account become hot?
There was a problem hiding this comment.
There was a problem hiding this comment.
SELFDESTRUCT puts non-existing beneficiary into a warm set, the same I thihk with calls, so warm/cold and existing/non-existing seem to be orthogonal.
One could also think that account_exists puts non-existing account into a warm set, it's used only in SELFDESTRUCT and calls which do it, and it would reflect reality of updating non-existence caches in clients.
| return EVMC_OUT_OF_GAS; | ||
| } | ||
|
|
||
| x = intx::be::load<uint256>(state.host.get_balance(addr)); |
There was a problem hiding this comment.
Here and with other methods accessing information about accounts the get_balance() can be extended to return both account status and the balance. The gas check should be done after the call, although I'm sure @holiman would be happy with such implementation. But my reasoning that even "access account" makes it hot so it can also return the balance in the same time.
There was a problem hiding this comment.
That was my thinking at first with sload, to return both the value and the access status. But then I realised that it complicates the API. I believe that having a separate method specifically to record access in the sense of EIP-2929 leads to a simpler API compared to reporting access status in various methods. The performance overhead shouldn't be too big, just an extra function call.
Codecov Report
@@ Coverage Diff @@
## master #289 +/- ##
==========================================
- Coverage 99.75% 99.07% -0.68%
==========================================
Files 24 24
Lines 3659 3694 +35
==========================================
+ Hits 3650 3660 +10
- Misses 9 34 +25
Flags with carried forward coverage won't be shown. Click here to find out more.
|
c53634e to
915c089
Compare
|
Consensus tests are going to be updated later in #298. |
6f18e82 to
c63312d
Compare
| namespace evmone::instr | ||
| { | ||
| /// EIP-2929 constants (https://eips.ethereum.org/EIPS/eip-2929). | ||
| inline constexpr auto cold_sload_cost = 2100; |
There was a problem hiding this comment.
Not sure what we're going to do with these constants if they change in future forks... Mabye just prepend with berlin_. But I guess it's ok to leave like this now.
There was a problem hiding this comment.
True. But it would be easy to move them to constexpr array. E.g. instr::constants[EVMC_BERLIN].cold_sload_cost.
| inline constexpr auto cold_sload_cost = 2100; | ||
| inline constexpr auto cold_account_access_cost = 2600; | ||
| inline constexpr auto warm_storage_read_cost = 100; | ||
| inline constexpr auto additional_cold_account_access_cost = |
There was a problem hiding this comment.
Maybe introduce also additional_sload_cost and use it in sload for consistency.
There was a problem hiding this comment.
I used the name, but only locally where it is used. Also explained the global definition.
|
|
||
| const auto& r = host.recorded_account_accesses; | ||
| ASSERT_EQ(r.size(), 24); | ||
| EXPECT_EQ(r[0], msg.sender); |
There was a problem hiding this comment.
Maybe could be better-looking with some fancy assert
EXPECT_THAT(r, ElementsAre(msg.sender, msg.destination, ...));
There was a problem hiding this comment.
This is fine so I don't need to count these in my head. And I don't need to import Google Mock.
| state.host.get_storage(state.msg->destination, intx::be::store<evmc::bytes32>(x))); | ||
| const auto key = intx::be::store<evmc::bytes32>(x); | ||
|
|
||
| if (state.rev >= EVMC_BERLIN && |
There was a problem hiding this comment.
Is there any measureable performance diff for these revision checks? Should we templetize based on version at some point?
There was a problem hiding this comment.
There are not benchmarks for state access. I could add some, but these are may not be "portable" because depending on the pre-state initialization.
I don't think it is worth duplicating the code with templates for these. However, it may be good to priorities the most recent revision in the code.
lib/evmone/instructions.cpp
Outdated
| table[OP_SHL] = op<shl>; | ||
| table[OP_SHR] = op<shr>; | ||
| table[OP_SAR] = op<sar>; | ||
| table[OP_EXTCODEHASH] = op<extcodehash>; |
There was a problem hiding this comment.
Oh, I simply removed duplicated code; see line 323.
There was a problem hiding this comment.
Ah ok. I will sort these in separate PR then.
This uses temporary Silkworm version matching EVMC 8.0.0-alpha.1 ABI.
|
This was merged under #301. |
Keeping as draft until ipsilon/evmc#571 is merged.