Skip to content

Commit a79218c

Browse files
authored
Remove TXCREATE (#992)
`TXCREATE` and initcode transactions are not scheduled for any upgrade currently, and it doesn't make sense to maintain this code at the moment.
2 parents 12766de + 814b8cc commit a79218c

20 files changed

+16
-1333
lines changed

lib/evmone/advanced_instructions.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,6 @@ constexpr std::array<instruction_exec_fn, 256> instruction_implementations = [](
310310
table[OP_SWAPN] = op_undefined;
311311
table[OP_EXCHANGE] = op_undefined;
312312
table[OP_EOFCREATE] = op_undefined;
313-
table[OP_TXCREATE] = op_undefined;
314313
table[OP_RETURNCONTRACT] = op_undefined;
315314

316315
return table;

lib/evmone/eof.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ enum class EOFValidationError
149149

150150
enum class ContainerKind : uint8_t
151151
{
152-
/// Container that uses RETURNCONTRACT. Can be used by EOFCREATE/TXCREATE/Creation transaction.
152+
/// Container that uses RETURNCONTRACT. Can be used by EOFCREATE/Creation transaction.
153153
initcode,
154154
/// Container that uses STOP/RETURN. Can be returned by RETURNCONTRACT.
155155
runtime,

lib/evmone/execution_state.hpp

-21
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ class ExecutionState
175175

176176
private:
177177
evmc_tx_context m_tx = {};
178-
std::optional<std::unordered_map<evmc::bytes32, bytes_view>> m_initcodes;
179178

180179
public:
181180
/// Pointer to code analysis.
@@ -232,25 +231,5 @@ class ExecutionState
232231
m_tx = host.get_tx_context();
233232
return m_tx;
234233
}
235-
236-
/// Get initcode by its hash from transaction initcodes.
237-
///
238-
/// Returns empty bytes_view if no such initcode was found.
239-
[[nodiscard]] bytes_view get_tx_initcode_by_hash(const evmc_bytes32& hash) noexcept
240-
{
241-
if (!m_initcodes.has_value())
242-
{
243-
m_initcodes.emplace();
244-
const auto& tx_context = get_tx_context();
245-
for (size_t i = 0; i < tx_context.initcodes_count; ++i)
246-
{
247-
const auto& initcode = tx_context.initcodes[i];
248-
m_initcodes->insert({initcode.hash, {initcode.code, initcode.code_size}});
249-
}
250-
}
251-
252-
const auto it = m_initcodes->find(hash);
253-
return it != m_initcodes->end() ? it->second : bytes_view{};
254-
}
255234
};
256235
} // namespace evmone

lib/evmone/instructions.hpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -1092,11 +1092,8 @@ Result create_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noex
10921092
inline constexpr auto create = create_impl<OP_CREATE>;
10931093
inline constexpr auto create2 = create_impl<OP_CREATE2>;
10941094

1095-
template <Opcode Op>
1096-
Result create_eof_impl(
1095+
Result eofcreate(
10971096
StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept;
1098-
inline constexpr auto eofcreate = create_eof_impl<OP_EOFCREATE>;
1099-
inline constexpr auto txcreate = create_eof_impl<OP_TXCREATE>;
11001097

11011098
inline code_iterator callf(StackTop stack, ExecutionState& state, code_iterator pos) noexcept
11021099
{

lib/evmone/instructions_calls.cpp

+7-45
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ consteval evmc_call_kind to_call_kind(Opcode op) noexcept
3636
case OP_CREATE2:
3737
return EVMC_CREATE2;
3838
case OP_EOFCREATE:
39-
case OP_TXCREATE:
4039
return EVMC_EOFCREATE;
4140
default:
4241
intx::unreachable();
@@ -332,17 +331,12 @@ Result create_impl(StackTop stack, int64_t gas_left, ExecutionState& state) noex
332331
return {EVMC_SUCCESS, gas_left};
333332
}
334333

335-
template <Opcode Op>
336-
Result create_eof_impl(
334+
Result eofcreate(
337335
StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept
338336
{
339-
static_assert(Op == OP_EOFCREATE || Op == OP_TXCREATE);
340-
341337
if (state.in_static_mode())
342338
return {EVMC_STATIC_MODE_VIOLATION, gas_left};
343339

344-
const auto initcode_hash =
345-
(Op == OP_TXCREATE) ? intx::be::store<evmc::bytes32>(stack.pop()) : evmc::bytes32{};
346340
const auto endowment = stack.pop();
347341
const auto salt = stack.pop();
348342
const auto input_offset_u256 = stack.pop();
@@ -354,32 +348,11 @@ Result create_eof_impl(
354348
if (!check_memory(gas_left, state.memory, input_offset_u256, input_size_u256))
355349
return {EVMC_OUT_OF_GAS, gas_left};
356350

357-
bytes_view initcontainer;
358-
if constexpr (Op == OP_EOFCREATE)
359-
{
360-
const auto initcontainer_index = pos[1];
361-
pos += 2;
362-
const auto& container = state.original_code;
363-
const auto& eof_header = state.analysis.baseline->eof_header;
364-
initcontainer = eof_header.get_container(container, initcontainer_index);
365-
}
366-
else
367-
{
368-
pos += 1;
369-
370-
initcontainer = state.get_tx_initcode_by_hash(initcode_hash);
371-
// In case initcode was not found, empty bytes_view was returned.
372-
// Transaction initcodes are not allowed to be empty.
373-
if (initcontainer.empty())
374-
return {EVMC_SUCCESS, gas_left}; // "Light" failure
375-
376-
// Charge for initcode validation.
377-
constexpr auto initcode_word_cost_validation = 2;
378-
const auto initcode_cost_validation =
379-
num_words(initcontainer.size()) * initcode_word_cost_validation;
380-
if ((gas_left -= initcode_cost_validation) < 0)
381-
return {EVMC_OUT_OF_GAS, gas_left};
382-
}
351+
const auto initcontainer_index = pos[1];
352+
pos += 2;
353+
const auto& container = state.original_code;
354+
const auto& eof_header = state.analysis.baseline->eof_header;
355+
const auto initcontainer = eof_header.get_container(container, initcontainer_index);
383356

384357
// Charge for initcode hashing.
385358
constexpr auto initcode_word_cost_hashing = 6;
@@ -397,14 +370,7 @@ Result create_eof_impl(
397370
intx::be::load<uint256>(state.host.get_balance(state.msg->recipient)) < endowment)
398371
return {EVMC_SUCCESS, gas_left}; // "Light" failure.
399372

400-
if constexpr (Op == OP_TXCREATE)
401-
{
402-
const auto error_subcont = validate_eof(state.rev, ContainerKind::initcode, initcontainer);
403-
if (error_subcont != EOFValidationError::success)
404-
return {EVMC_SUCCESS, gas_left}; // "Light" failure.
405-
}
406-
407-
evmc_message msg{.kind = to_call_kind(Op)};
373+
evmc_message msg{.kind = EVMC_EOFCREATE};
408374
msg.gas = gas_left - gas_left / 64;
409375
if (input_size > 0)
410376
{
@@ -436,8 +402,4 @@ template Result create_impl<OP_CREATE>(
436402
StackTop stack, int64_t gas_left, ExecutionState& state) noexcept;
437403
template Result create_impl<OP_CREATE2>(
438404
StackTop stack, int64_t gas_left, ExecutionState& state) noexcept;
439-
template Result create_eof_impl<OP_EOFCREATE>(
440-
StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept;
441-
template Result create_eof_impl<OP_TXCREATE>(
442-
StackTop stack, int64_t gas_left, ExecutionState& state, code_iterator& pos) noexcept;
443405
} // namespace evmone::instr::core

lib/evmone/instructions_opcodes.hpp

-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,6 @@ enum Opcode : uint8_t
175175
OP_EXCHANGE = 0xe8,
176176

177177
OP_EOFCREATE = 0xec,
178-
OP_TXCREATE = 0xed,
179178
OP_RETURNCONTRACT = 0xee,
180179

181180
OP_CREATE = 0xf0,

lib/evmone/instructions_traits.hpp

-2
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,6 @@ constexpr inline GasCostTable gas_costs = []() noexcept {
192192
table[EVMC_PRAGUE][OP_RETURNCONTRACT] = 0;
193193

194194
table[EVMC_OSAKA] = table[EVMC_PRAGUE];
195-
table[EVMC_OSAKA][OP_TXCREATE] = 32000;
196195

197196
return table;
198197
}();
@@ -421,7 +420,6 @@ constexpr inline std::array<Traits, 256> traits = []() noexcept {
421420
table[OP_CREATE2] = {"CREATE2", 0, false, 4, -3, EVMC_CONSTANTINOPLE};
422421
table[OP_RETURNDATALOAD] = {"RETURNDATALOAD", 0, false, 1, 0, {}, REV_EOF1};
423422
table[OP_EOFCREATE] = {"EOFCREATE", 1, false, 4, -3, {}, REV_EOF1};
424-
table[OP_TXCREATE] = {"TXCREATE", 0, false, 5, -4, {}, EVMC_OSAKA};
425423
table[OP_RETURNCONTRACT] = {"RETURNCONTRACT", 1, true, 2, -2, {}, REV_EOF1};
426424
table[OP_EXTCALL] = {"EXTCALL", 0, false, 4, -3, {}, REV_EOF1};
427425
table[OP_EXTDELEGATECALL] = {"EXTDELEGATECALL", 0, false, 3, -2, {}, REV_EOF1};

lib/evmone/instructions_xmacro.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@
283283
ON_OPCODE_UNDEFINED(0xea) \
284284
ON_OPCODE_UNDEFINED(0xeb) \
285285
ON_OPCODE_IDENTIFIER(OP_EOFCREATE, eofcreate) \
286-
ON_OPCODE_IDENTIFIER(OP_TXCREATE, txcreate) \
286+
ON_OPCODE_UNDEFINED(0xed) \
287287
ON_OPCODE_IDENTIFIER(OP_RETURNCONTRACT, returncontract) \
288288
ON_OPCODE_UNDEFINED(0xef) \
289289
\

test/state/errors.hpp

-9
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ enum ErrorCode : int
2323
GAS_LIMIT_REACHED,
2424
SENDER_NOT_EOA,
2525
INIT_CODE_SIZE_LIMIT_EXCEEDED,
26-
INIT_CODE_EMPTY,
27-
INIT_CODE_COUNT_LIMIT_EXCEEDED,
28-
INIT_CODE_COUNT_ZERO,
2926
CREATE_BLOB_TX,
3027
EMPTY_BLOB_HASHES_LIST,
3128
INVALID_BLOB_HASH_VERSION,
@@ -68,12 +65,6 @@ inline const std::error_category& evmone_category() noexcept
6865
return "sender not an eoa:";
6966
case INIT_CODE_SIZE_LIMIT_EXCEEDED:
7067
return "max initcode size exceeded";
71-
case INIT_CODE_EMPTY:
72-
return "initcode empty";
73-
case INIT_CODE_COUNT_LIMIT_EXCEEDED:
74-
return "max initcode count exceeded";
75-
case INIT_CODE_COUNT_ZERO:
76-
return "initcode list empty";
7768
case CREATE_BLOB_TX:
7869
return "blob transaction must not be a create transaction";
7970
case EMPTY_BLOB_HASHES_LIST:

test/state/host.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ std::optional<evmc_message> Host::prepare_message(evmc_message msg) noexcept
258258

259259
msg.recipient = compute_create_address(msg.sender, sender_nonce);
260260
}
261-
// EOFCREATE or TXCREATE
261+
// EOFCREATE
262262
else
263263
{
264264
const bytes_view initcontainer{msg.code, msg.code_size};
@@ -345,7 +345,7 @@ evmc::Result Host::create(const evmc_message& msg) noexcept
345345
{
346346
if (m_rev >= EVMC_PRAGUE)
347347
{
348-
// Only EOFCREATE/TXCREATE/EOF-creation-tx is allowed to deploy code starting with EF.
348+
// Only EOFCREATE/EOF-creation-tx is allowed to deploy code starting with EF.
349349
// It must be valid EOF, which was validated before execution.
350350
if (msg.kind != EVMC_EOFCREATE)
351351
return evmc::Result{EVMC_CONTRACT_VALIDATION_FAILURE};
@@ -449,8 +449,6 @@ evmc_tx_context Host::get_tx_context() const noexcept
449449
intx::be::store<uint256be>(m_block.blob_base_fee),
450450
m_tx.blob_hashes.data(),
451451
m_tx.blob_hashes.size(),
452-
m_tx_initcodes.data(),
453-
m_tx_initcodes.size(),
454452
};
455453
}
456454

test/state/host.hpp

+1-11
Original file line numberDiff line numberDiff line change
@@ -42,22 +42,12 @@ class Host : public evmc::Host
4242
const BlockInfo& m_block;
4343
const Transaction& m_tx;
4444
std::vector<Log> m_logs;
45-
std::vector<evmc_tx_initcode> m_tx_initcodes;
4645

4746
public:
4847
Host(evmc_revision rev, evmc::VM& vm, State& state, const BlockInfo& block,
4948
const Transaction& tx) noexcept
5049
: m_rev{rev}, m_vm{vm}, m_state{state}, m_block{block}, m_tx{tx}
51-
{
52-
if (tx.type == Transaction::Type::initcodes)
53-
{
54-
for (const auto& initcode : tx.initcodes)
55-
{
56-
const auto hash = keccak256({initcode.data(), initcode.size()});
57-
m_tx_initcodes.push_back({hash, initcode.data(), initcode.size()});
58-
}
59-
}
60-
}
50+
{}
6151

6252
[[nodiscard]] std::vector<Log>&& take_logs() noexcept { return std::move(m_logs); }
6353

test/state/state.cpp

+1-33
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ namespace evmone::state
1616
{
1717
namespace
1818
{
19-
constexpr auto MAX_INITCODE_COUNT = 256;
20-
2119
inline constexpr int64_t num_words(size_t size_in_bytes) noexcept
2220
{
2321
return static_cast<int64_t>((size_in_bytes + 31) / 32);
@@ -44,14 +42,6 @@ int64_t compute_access_list_cost(const AccessList& access_list) noexcept
4442
return cost;
4543
}
4644

47-
int64_t compute_initcode_list_cost(evmc_revision rev, std::span<const bytes> initcodes) noexcept
48-
{
49-
int64_t cost = 0;
50-
for (const auto& initcode : initcodes)
51-
cost += compute_tx_data_cost(rev, initcode);
52-
return cost;
53-
}
54-
5545
int64_t compute_tx_intrinsic_cost(evmc_revision rev, const Transaction& tx) noexcept
5646
{
5747
static constexpr auto call_tx_cost = 21000;
@@ -62,7 +52,7 @@ int64_t compute_tx_intrinsic_cost(evmc_revision rev, const Transaction& tx) noex
6252
is_create && rev >= EVMC_SHANGHAI ? initcode_word_cost * num_words(tx.data.size()) : 0;
6353
const auto tx_cost = is_create && rev >= EVMC_HOMESTEAD ? create_tx_cost : call_tx_cost;
6454
return tx_cost + compute_tx_data_cost(rev, tx.data) + compute_access_list_cost(tx.access_list) +
65-
compute_initcode_list_cost(rev, tx.initcodes) + initcode_cost;
55+
initcode_cost;
6656
}
6757

6858
evmc_message build_message(
@@ -283,28 +273,12 @@ std::variant<int64_t, std::error_code> validate_transaction(const Account& sende
283273
return make_error_code(BLOB_GAS_LIMIT_EXCEEDED);
284274
break;
285275

286-
case Transaction::Type::initcodes:
287-
if (rev < EVMC_OSAKA)
288-
return make_error_code(TX_TYPE_NOT_SUPPORTED);
289-
if (tx.initcodes.size() > MAX_INITCODE_COUNT)
290-
return make_error_code(INIT_CODE_COUNT_LIMIT_EXCEEDED);
291-
if (tx.initcodes.empty())
292-
return make_error_code(INIT_CODE_COUNT_ZERO);
293-
if (std::any_of(tx.initcodes.begin(), tx.initcodes.end(),
294-
[](const bytes& v) { return v.size() > MAX_INITCODE_SIZE; }))
295-
return make_error_code(INIT_CODE_SIZE_LIMIT_EXCEEDED);
296-
if (std::any_of(
297-
tx.initcodes.begin(), tx.initcodes.end(), [](const bytes& v) { return v.empty(); }))
298-
return make_error_code(INIT_CODE_EMPTY);
299-
break;
300-
301276
default:;
302277
}
303278

304279
switch (tx.type)
305280
{
306281
case Transaction::Type::blob:
307-
case Transaction::Type::initcodes:
308282
case Transaction::Type::eip1559:
309283
if (rev < EVMC_LONDON)
310284
return make_error_code(TX_TYPE_NOT_SUPPORTED);
@@ -620,12 +594,6 @@ std::variant<TransactionReceipt, std::error_code> transition(State& state, const
620594
return "SenderNotEOA";
621595
case INIT_CODE_SIZE_LIMIT_EXCEEDED:
622596
return "TR_InitCodeLimitExceeded";
623-
case INIT_CODE_EMPTY:
624-
return "TR_InitCodeEmpty";
625-
case INIT_CODE_COUNT_LIMIT_EXCEEDED:
626-
return "TR_InitCodeCountLimitExceeded";
627-
case INIT_CODE_COUNT_ZERO:
628-
return "TR_InitCodeCountZero";
629597
case CREATE_BLOB_TX:
630598
return "TR_BLOBCREATE";
631599
case EMPTY_BLOB_HASHES_LIST:

test/state/state.hpp

-4
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,6 @@ struct Transaction
196196
/// The typed blob transaction (with array of blob hashes).
197197
/// Introduced by EIP-4844 https://eips.ethereum.org/EIPS/eip-4844.
198198
blob = 3,
199-
200-
/// The typed transaction with initcode list.
201-
initcodes = 4,
202199
};
203200

204201
/// Returns amount of blob gas used by this transaction
@@ -224,7 +221,6 @@ struct Transaction
224221
intx::uint256 r;
225222
intx::uint256 s;
226223
uint8_t v = 0;
227-
std::vector<bytes> initcodes;
228224
};
229225

230226
struct Log

test/statetest/statetest_loader.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -331,12 +331,6 @@ static void from_json_tx_common(const json::json& j, state::Transaction& o)
331331
for (const auto& hash : *it)
332332
o.blob_hashes.push_back(from_json<bytes32>(hash));
333333
}
334-
else if (const auto it_initcodes = j.find("initcodes"); it_initcodes != j.end())
335-
{
336-
o.type = state::Transaction::Type::initcodes;
337-
for (const auto& initcode : *it_initcodes)
338-
o.initcodes.push_back(from_json<bytes>(initcode));
339-
}
340334
}
341335

342336
template <>

test/unittests/eof_validation_test.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -1223,7 +1223,6 @@ TEST_F(eof_validation, max_nested_containers_eofcreate_returncontract)
12231223
// | ---------------------------- | ------ | ------ | ------ | -------------- |
12241224
// | top-level initcode | - | - | + | + |
12251225
// | EOFCREATE | - | - | + | + |
1226-
// | TXCREATE | - | - | + | + |
12271226
// | top-level runtime | + | + | + | - |
12281227
// | RETURNCONTRACT | + | + | + | - |
12291228
// | EOFCREATE and RETURNCONTRACT | - | - | + | - |

test/unittests/instructions_test.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ constexpr bool instruction_only_in_evmone(evmc_revision rev, Opcode op) noexcept
137137
case OP_EXTDELEGATECALL:
138138
case OP_EXTSTATICCALL:
139139
case OP_EOFCREATE:
140-
case OP_TXCREATE:
141140
case OP_RETURNCONTRACT:
142141
return true;
143142
default:

test/unittests/state_transition.cpp

-7
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,6 @@ void state_transition::export_state_test(
200200
jtx["maxPriorityFeePerGas"] = hex0x(tx.max_priority_gas_price);
201201
}
202202

203-
if (tx.type == Transaction::Type::initcodes)
204-
{
205-
auto& jinitcodes = jtx["initcodes"] = json::json::array();
206-
for (const auto& initcode : tx.initcodes)
207-
jinitcodes.emplace_back(hex0x(initcode));
208-
}
209-
210203
jtx["data"][0] = hex0x(tx.data);
211204
jtx["gasLimit"][0] = hex0x(tx.gas_limit);
212205
jtx["value"][0] = hex0x(tx.value);

0 commit comments

Comments
 (0)