Skip to content

Commit

Permalink
Merge pull request ethereum#14843 from ethereum/separate-code-deposit…
Browse files Browse the repository at this point in the history
…-cost-in-semantic-tests

Separate code deposit cost in semantic tests
  • Loading branch information
cameel authored Feb 21, 2024
2 parents 4438082 + 381b149 commit acf382b
Show file tree
Hide file tree
Showing 89 changed files with 823 additions and 271 deletions.
5 changes: 4 additions & 1 deletion scripts/gas_diff_stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import sys
from pathlib import Path
from enum import Enum
from parsec import generate, ParseError, regex, string
from parsec import generate, ParseError, regex, string, optional
from tabulate import tabulate

class Kind(Enum):
Expand All @@ -49,6 +49,7 @@ class Diff(Enum):
gas_ir_optimized = string("gas irOptimized").result(Kind.IrOptimized)
gas_legacy_optimized = string("gas legacyOptimized").result(Kind.LegacyOptimized)
gas_legacy = string("gas legacy").result(Kind.Legacy)
code_suffix = string("code")

def number() -> int:
"""Parse number."""
Expand All @@ -67,6 +68,8 @@ def diff_string() -> (Kind, Diff, int):
yield comment
yield space
codegen_kind = yield gas_ir_optimized ^ gas_ir ^ gas_legacy_optimized ^ gas_legacy
yield optional(space)
yield optional(code_suffix)
yield colon
yield space
val = yield number()
Expand Down
7 changes: 6 additions & 1 deletion test/EVMHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ void EVMHost::reset()
recorded_calls.clear();
// Clear EIP-2929 account access indicator
recorded_account_accesses.clear();
m_totalCodeDepositGas = 0;

// Mark all precompiled contracts as existing. Existing here means to have a balance (as per EIP-161).
// NOTE: keep this in sync with `EVMHost::call` below.
Expand Down Expand Up @@ -203,6 +204,7 @@ void EVMHost::newTransactionFrame()
// Otherwise, the previous behavior (pre-Cancun) is maintained.
accounts.erase(address);
newlyCreatedAccounts.clear();
m_totalCodeDepositGas = 0;
recorded_selfdestructs.clear();
}

Expand Down Expand Up @@ -392,15 +394,18 @@ evmc::Result EVMHost::call(evmc_message const& _message) noexcept

if (message.kind == EVMC_CREATE || message.kind == EVMC_CREATE2)
{
result.gas_left -= static_cast<int64_t>(evmasm::GasCosts::createDataGas * result.output_size);
int64_t codeDepositGas = static_cast<int64_t>(evmasm::GasCosts::createDataGas * result.output_size);
result.gas_left -= codeDepositGas;
if (result.gas_left < 0)
{
m_totalCodeDepositGas += -result.gas_left;
result.gas_left = 0;
result.status_code = EVMC_OUT_OF_GAS;
// TODO clear some fields?
}
else
{
m_totalCodeDepositGas += codeDepositGas;
result.create_address = message.recipient;
destination.code = evmc::bytes(result.output_data, result.output_data + result.output_size);
destination.codehash = convertToEVMC(keccak256({result.output_data, result.output_size}));
Expand Down
7 changes: 7 additions & 0 deletions test/EVMHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class EVMHost: public evmc::MockedHost
/// @returns contents of storage at @param _addr.
StorageMap const& get_address_storage(evmc::address const& _addr);

u256 totalCodeDepositGas() const { return m_totalCodeDepositGas; }

static Address convertFromEVMC(evmc::address const& _addr);
static evmc::address convertToEVMC(Address const& _addr);
static util::h256 convertFromEVMC(evmc::bytes32 const& _data);
Expand Down Expand Up @@ -137,6 +139,11 @@ class EVMHost: public evmc::MockedHost
langutil::EVMVersion m_evmVersion;
/// EVM version requested from EVMC (matches the above)
evmc_revision m_evmRevision;

/// The part of the total cost of the current transaction that paid for the code deposits.
/// I.e. GAS_CODE_DEPOSIT times the total size of deployed code of all newly created contracts,
/// including the current contract itself if it was a creation transaction.
u256 m_totalCodeDepositGas;
};

class EVMHostPrinter
Expand Down
2 changes: 2 additions & 0 deletions test/ExecutionFramework.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256
auto const gasRefund = std::min(u256(result.gas_refund), totalGasUsed / refundRatio);

m_gasUsed = totalGasUsed - gasRefund;
m_gasUsedForCodeDeposit = m_evmcHost->totalCodeDepositGas();
m_transactionSuccessful = (result.status_code == EVMC_SUCCESS);

if (m_showMessages)
Expand All @@ -199,6 +200,7 @@ void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256
std::cout << " result: " << static_cast<size_t>(result.status_code) << std::endl;
std::cout << " gas used: " << m_gasUsed.str() << std::endl;
std::cout << " gas used (without refund): " << totalGasUsed.str() << std::endl;
std::cout << " code deposits only: " << m_gasUsedForCodeDeposit.str() << std::endl;
std::cout << " gas refund (total): " << result.gas_refund << std::endl;
std::cout << " gas refund (bound): " << gasRefund.str() << std::endl;
}
Expand Down
6 changes: 6 additions & 0 deletions test/ExecutionFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,13 @@ class ExecutionFramework
util::h160 m_sender = account(0);
util::h160 m_contractAddress;
bytes m_output;

/// Total gas used by the transaction, after refund.
u256 m_gasUsed;

/// The portion of @a m_gasUsed spent on code deposits of newly created contracts.
/// May exceed @a m_gasUsed in rare corner cases due to refunds.
u256 m_gasUsedForCodeDeposit;
};

#define ABI_CHECK(result, expectation) do { \
Expand Down
19 changes: 15 additions & 4 deletions test/libsolidity/SemanticTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,11 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp
(_compileViaYul ? "ir"s : "legacy"s) +
(m_optimiserSettings == OptimiserSettings::full() ? "Optimized" : "");

soltestAssert(
io_test.call().expectations.gasUsedExcludingCode.count(setting) ==
io_test.call().expectations.gasUsedForCodeDeposit.count(setting)
);

// We don't check gas if enforce gas cost is not active
// or test is run with abi encoder v1 only
// or gas used less than threshold for enforcing feature
Expand All @@ -579,17 +584,23 @@ bool SemanticTest::checkGasCostExpectation(TestFunctionCall& io_test, bool _comp
!m_enforceGasCost ||
m_gasUsed < m_enforceGasCostMinValue ||
m_gasUsed >= InitialGas ||
(setting == "ir" && io_test.call().expectations.gasUsed.count(setting) == 0) ||
(setting == "ir" && io_test.call().expectations.gasUsedExcludingCode.count(setting) == 0) ||
io_test.call().kind == FunctionCall::Kind::Builtin
)
return true;

solAssert(!m_runWithABIEncoderV1Only, "");

io_test.setGasCost(setting, m_gasUsed);
// NOTE: Cost excluding code is unlikely to be negative but it may still be possible due to refunds.
// We'll deal with it when we actually have a test case like that.
solUnimplementedAssert(m_gasUsed >= m_gasUsedForCodeDeposit);
io_test.setGasCostExcludingCode(setting, m_gasUsed - m_gasUsedForCodeDeposit);
io_test.setCodeDepositGasCost(setting, m_gasUsedForCodeDeposit);

return
io_test.call().expectations.gasUsed.count(setting) > 0 &&
m_gasUsed == io_test.call().expectations.gasUsed.at(setting);
io_test.call().expectations.gasUsedExcludingCode.count(setting) > 0 &&
m_gasUsed - m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedExcludingCode.at(setting) &&
m_gasUsedForCodeDeposit == io_test.call().expectations.gasUsedForCodeDeposit.at(setting);
}

void SemanticTest::printSource(std::ostream& _stream, std::string const& _linePrefix, bool _formatted) const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ contract C is B {
}
// ----
// test() -> 77
// gas irOptimized: 110348
// gas legacy: 151866
// gas legacyOptimized: 110373
// gas irOptimized: 55148
// gas irOptimized code: 55200
// gas legacy: 57266
// gas legacy code: 94600
// gas legacyOptimized: 55173
// gas legacyOptimized code: 55200
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ contract C is B {
// ----
// test() -> 5, 10
// gas irOptimized: 87337
// gas legacy: 102651
// gas legacy: 66251
// gas legacy code: 36400
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ contract D {
// ----
// f() -> FAILURE, hex"4e487b71", 0x11
// g(), 100 wei -> 1
// gas legacy: 100380
// gas legacy: 76780
// gas legacy code: 23600
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ contract C {
}
// ----
// constructor(): 1, 2, 3 ->
// gas irOptimized: 139616
// gas legacy: 180517
// gas legacyOptimized: 150462
// gas irOptimized: 124816
// gas irOptimized code: 14800
// gas legacy: 134317
// gas legacy code: 46200
// gas legacyOptimized: 127062
// gas legacyOptimized code: 23400
// a(uint256): 0 -> 1
// a(uint256): 1 -> 2
// a(uint256): 2 -> 3
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ contract C {
}
// ----
// constructor()
// gas irOptimized: 226321
// gas legacy: 215753
// gas legacyOptimized: 181756
// gas irOptimized: 89121
// gas irOptimized code: 137200
// gas legacy: 89553
// gas legacy code: 126200
// gas legacyOptimized: 83556
// gas legacyOptimized code: 98200
// f() -> 0
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ contract B {
}
// ----
// f() -> 2, 3, 4, 5, 6, 1000, 1001, 1002, 1003, 1004
// gas irOptimized: 114404
// gas legacy: 230001
// gas legacyOptimized: 130637
// gas irOptimized: 59204
// gas irOptimized code: 55200
// gas legacy: 68001
// gas legacy code: 162000
// gas legacyOptimized: 60037
// gas legacyOptimized code: 70600
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ contract Creator {
}
// ----
// constructor(): 1, 2, 3, 4 ->
// gas irOptimized: 126327
// gas legacy: 174186
// gas legacyOptimized: 128709
// gas irOptimized: 103927
// gas irOptimized code: 22400
// gas legacy: 115186
// gas legacy code: 59000
// gas legacyOptimized: 104909
// gas legacyOptimized code: 23800
// r() -> 4
// ch() -> 3
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ contract C {
}
// ----
// test() -> 5, 6, 7
// gas irOptimized: 255728
// gas legacy: 440376
// gas legacyOptimized: 278651
// gas irOptimized: 86128
// gas irOptimized code: 169600
// gas legacy: 97576
// gas legacy code: 342800
// gas legacyOptimized: 87851
// gas legacyOptimized code: 190800
9 changes: 6 additions & 3 deletions test/libsolidity/semanticTests/array/reusing_memory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ contract Main {
}
// ----
// f(uint256): 0x34 -> 0x46bddb1178e94d7f2892ff5f366840eb658911794f2c3a44c450aa2c505186c1
// gas irOptimized: 111924
// gas legacy: 125154
// gas legacyOptimized: 113012
// gas irOptimized: 99524
// gas irOptimized code: 12400
// gas legacy: 101554
// gas legacy code: 23600
// gas legacyOptimized: 99612
// gas legacyOptimized code: 13400
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ contract C {
// compileViaYul: also
// ----
// constructor() ->
// gas irOptimized: 443402
// gas legacy: 711295
// gas legacyOptimized: 482378
// gas irOptimized: 82402
// gas irOptimized code: 361000
// gas legacy: 101895
// gas legacy code: 609400
// gas legacyOptimized: 85378
// gas legacyOptimized code: 397000
// h() -> 0x20, 0x40, 0x00, 0
// ~ emit ev(uint256[],uint256): 0x40, 0x21, 0x02, 0x00, 0x00
// g() -> 0x20, 0x40, 0, 0x00
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ contract Creator {
}
// ----
// f(uint256,address[]): 7, 0x40, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 -> 7, 8
// gas irOptimized: 424526
// gas legacy: 581426
// gas legacyOptimized: 444599
// gas irOptimized: 328126
// gas irOptimized code: 96400
// gas legacy: 336626
// gas legacy code: 244800
// gas legacyOptimized: 329599
// gas legacyOptimized code: 115000
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ contract Creator {
}
// ----
// f(uint256,bytes): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" -> 7, "h"
// gas irOptimized: 275102
// gas legacy: 418433
// gas legacyOptimized: 291960
// gas irOptimized: 169902
// gas irOptimized code: 105200
// gas legacy: 173433
// gas legacy code: 245000
// gas legacyOptimized: 170360
// gas legacyOptimized code: 121600
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ contract Test {
}
// ----
// constructor(): 7, 0x40, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz" ->
// gas irOptimized: 269225
// gas legacy: 310820
// gas legacyOptimized: 258604
// gas irOptimized: 182025
// gas irOptimized code: 87200
// gas legacy: 196220
// gas legacy code: 114600
// gas legacyOptimized: 182604
// gas legacyOptimized code: 76000
// m_x() -> 7
// m_s() -> 0x20, 78, "abcdefghijklmnopqrstuvwxyzabcdef", "ghijklmnopqrstuvwxyzabcdefghijkl", "mnopqrstuvwxyz"
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ contract Main {
}
// ----
// constructor(): "abc", true
// gas irOptimized: 104374
// gas legacy: 143300
// gas legacyOptimized: 102933
// gas irOptimized: 80174
// gas irOptimized code: 24200
// gas legacy: 85100
// gas legacy code: 58200
// gas legacyOptimized: 80133
// gas legacyOptimized code: 22800
// getFlag() -> true
// getName() -> "abc"
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ contract C {
}
// ----
// f() -> 16
// gas legacy: 102082
// gas legacy: 78482
// gas legacy code: 23600
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ contract C {
}
// ----
// constructor(): 1, 2, 3, 4 ->
// gas irOptimized: 170975
// gas legacy: 218378
// gas legacyOptimized: 176211
// gas irOptimized: 147975
// gas irOptimized code: 23000
// gas legacy: 157978
// gas legacy code: 60400
// gas legacyOptimized: 150011
// gas legacyOptimized code: 26200
// a() -> 1
// b(uint256): 0 -> 2
// b(uint256): 1 -> 3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ contract C {
}
// ----
// f(), 2000 ether -> true
// gas irOptimized: 119441
// gas legacy: 122621
// gas legacyOptimized: 122490
// gas irOptimized: 117641
// gas irOptimized code: 1800
// gas legacy: 117821
// gas legacy code: 4800
// gas legacyOptimized: 117690
// gas legacyOptimized code: 4800
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ contract B is A {
// compileViaYul: true
// ----
// constructor() ->
// gas irOptimized: 119636
// gas irOptimized: 99436
// gas irOptimized code: 20200
// y() -> 42
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ contract B is A {
}
// ----
// constructor() ->
// gas irOptimized: 119636
// gas legacy: 133574
// gas legacyOptimized: 115337
// gas irOptimized: 99436
// gas irOptimized code: 20200
// gas legacy: 100974
// gas legacy code: 32600
// gas legacyOptimized: 99137
// gas legacyOptimized code: 16200
// y() -> 42
Loading

0 comments on commit acf382b

Please sign in to comment.