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

EIP-2929: Gas cost increases for state access opcodes #289

Closed
wants to merge 8 commits into from

Conversation

yperbasis
Copy link
Member

@yperbasis yperbasis commented Feb 15, 2021

Keeping as draft until ethereum/evmc#571 is merged.

@@ -20,6 +20,13 @@ evmc_status_code call(ExecutionState& state) noexcept

state.stack.push(0); // Assume failure.

if (state.rev >= EVMC_BERLIN && state.host.access_account(dst) == EVMC_COLD_ACCESS)
Copy link
Member

Choose a reason for hiding this comment

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

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?

Copy link
Member Author

@yperbasis yperbasis Feb 16, 2021

Choose a reason for hiding this comment

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

Not sure that merging access_account() with account_exists() is worth it. It might save a function call, but the two are quite different: account_exists() (EIP-161) is a constant operation that doesn't change anything, while access_account() modifies accessed_addresses substate (EIP-2929).

Copy link
Member

Choose a reason for hiding this comment

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

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));
Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Member Author

@yperbasis yperbasis Feb 16, 2021

Choose a reason for hiding this comment

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

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.

@chfast chfast requested review from axic, gumb0 and holiman February 16, 2021 17:29
@yperbasis yperbasis changed the title [WIP] EIP-2929: Gas cost increases for state access opcodes EIP-2929: Gas cost increases for state access opcodes Feb 19, 2021
@codecov-io
Copy link

Codecov Report

Merging #289 (cc7614b) into master (b9facfa) will decrease coverage by 0.67%.
The diff coverage is 60.93%.

❗ Current head cc7614b differs from pull request most recent head 3b07834. Consider uploading reports for the commit 3b07834 to get more accurate results

@@            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     
Flag Coverage Δ
unittests 99.07% <60.93%> (-0.68%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
lib/evmone/instructions.cpp 100.00% <ø> (ø)
lib/evmone/instructions_calls.cpp 97.93% <33.33%> (-2.07%) ⬇️
lib/evmone/baseline.cpp 98.42% <50.00%> (-1.40%) ⬇️
lib/evmone/instructions.hpp 96.58% <66.66%> (-3.42%) ⬇️

@chfast chfast force-pushed the eip-2929 branch 4 times, most recently from c53634e to 915c089 Compare April 7, 2021 13:37
@chfast chfast changed the base branch from master to evmc April 7, 2021 13:38
@chfast
Copy link
Member

chfast commented Apr 7, 2021

Consensus tests are going to be updated later in #298.

@chfast chfast force-pushed the eip-2929 branch 4 times, most recently from 6f18e82 to c63312d Compare April 8, 2021 15:15

#include <evmc/instructions.h>
#include <array>

namespace evmone::instr
{
/// EIP-2929 constants (https://eips.ethereum.org/EIPS/eip-2929).
inline constexpr auto cold_sload_cost = 2100;
Copy link
Member

Choose a reason for hiding this comment

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

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.

Copy link
Member

@chfast chfast Apr 9, 2021

Choose a reason for hiding this comment

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

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 =
Copy link
Member

Choose a reason for hiding this comment

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

Maybe introduce also additional_sload_cost and use it in sload for consistency.

Copy link
Member

Choose a reason for hiding this comment

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

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);
Copy link
Member

Choose a reason for hiding this comment

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

Maybe could be better-looking with some fancy assert

EXPECT_THAT(r, ElementsAre(msg.sender, msg.destination, ...));

Copy link
Member

Choose a reason for hiding this comment

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

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 &&
Copy link
Member

Choose a reason for hiding this comment

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

Is there any measureable performance diff for these revision checks? Should we templetize based on version at some point?

Copy link
Member

Choose a reason for hiding this comment

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

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.

@@ -316,7 +316,7 @@ constexpr std::array<instruction_exec_fn, 256> instruction_implementations = [](
table[OP_SHL] = op<shl>;
table[OP_SHR] = op<shr>;
table[OP_SAR] = op<sar>;
table[OP_EXTCODEHASH] = op<extcodehash>;
Copy link
Member

Choose a reason for hiding this comment

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

Why is this removed here?

Copy link
Member

Choose a reason for hiding this comment

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

Oh yeah, I was wandering the same @yperbasis.

Copy link
Member Author

Choose a reason for hiding this comment

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

Oh, I simply removed duplicated code; see line 323.

Copy link
Member

Choose a reason for hiding this comment

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

Ah ok. I will sort these in separate PR then.

@axic
Copy link
Member

axic commented Apr 20, 2021

This was merged under #301.

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

Successfully merging this pull request may close these issues.

6 participants