Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 95 additions & 6 deletions cmd/monad/runloop_ethereum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#include <category/execution/ethereum/trace/call_tracer.hpp>
#include <category/execution/ethereum/validate_block.hpp>
#include <category/execution/ethereum/validate_transaction.hpp>
#include <category/execution/monad/chain/monad_chain.hpp>
#include <category/execution/monad/validate_monad_block.hpp>
#include <category/vm/evm/explicit_traits.hpp>
#include <category/vm/evm/switch_traits.hpp>
#include <category/vm/evm/traits.hpp>

Expand Down Expand Up @@ -79,13 +82,18 @@ void log_tps(

#pragma GCC diagnostic pop

MONAD_ANONYMOUS_NAMESPACE_END

MONAD_NAMESPACE_BEGIN

// Process a single historical Ethereum block
template <Traits traits>
Result<BlockHeader> process_ethereum_block(
Chain const &chain, Db &db, vm::VM &vm, BlockHashBuffer &block_hash_buffer,
Chain const &chain, Db &db, vm::VM &vm,
BlockHashBuffer const &block_hash_buffer,
fiber::PriorityPool &priority_pool, Block const &block,
bytes32_t const &block_id, bytes32_t const &parent_block_id,
bool const enable_tracing)
bool const enable_tracing, BlockCache *const block_cache)
{
[[maybe_unused]] auto const block_start = std::chrono::system_clock::now();
auto const block_begin = std::chrono::steady_clock::now();
Expand Down Expand Up @@ -135,6 +143,88 @@ Result<BlockHeader> process_ethereum_block(
db.set_block_and_prefix(block.header.number - 1, parent_block_id);
BlockMetrics block_metrics;
BlockState block_state(db, vm);

// Build the revert transaction function
RevertTransactionFn revert_transaction =
[](Address const &, Transaction const &, uint64_t, State &) {
return false;
};
if constexpr (is_monad_trait_v<traits>) {
// Monad-specific revert transaction logic
BOOST_OUTCOME_TRY(static_validate_monad_senders<traits>(senders));

// Update the BlockCache with this block's senders and authorities
MONAD_ASSERT(block_cache, "block_cache required for Monad traits");
auto [entry, success] = block_cache->emplace(
block_id,
BlockCacheEntry{
.block_number = block.header.number,
.parent_id = parent_block_id,
.senders_and_authorities = {}});
MONAD_ASSERT(success, "should never be processing duplicate block");
for (Address const &sender : senders) {
entry->second.senders_and_authorities.insert(sender);
}
for (std::vector<std::optional<Address>> const &authorities :
recovered_authorities) {
for (std::optional<Address> const &authority : authorities) {
if (authority.has_value()) {
entry->second.senders_and_authorities.insert(
authority.value());
}
}
}

// Make the chain context, providing the parent and grandparent
MonadChainContext chain_context{
.grandparent_senders_and_authorities = nullptr,
.parent_senders_and_authorities = nullptr,
.senders_and_authorities =
block_cache->at(block_id).senders_and_authorities,
.senders = senders,
.authorities = recovered_authorities};

if (block.header.number > 1) {
MONAD_ASSERT(
block_cache->contains(parent_block_id),
"block cache must contain parent");
BlockCacheEntry const &parent_entry =
block_cache->at(parent_block_id);
chain_context.parent_senders_and_authorities =
&parent_entry.senders_and_authorities;
if (block.header.number > 2) {
bytes32_t const &grandparent_id = parent_entry.parent_id;
MONAD_ASSERT(
block_cache->contains(grandparent_id),
"block cache must contain grandparent");
BlockCacheEntry const &grandparent_entry =
block_cache->at(grandparent_id);
chain_context.grandparent_senders_and_authorities =
&grandparent_entry.senders_and_authorities;
}
}

// Capture chain reference for the revert transaction function
MonadChain const *const monad_chain =
dynamic_cast<MonadChain const *>(&chain);
MONAD_ASSERT(monad_chain, "chain must be a MonadChain");
revert_transaction = [monad_chain, &block, chain_context](
Address const &sender,
Transaction const &tx,
uint64_t const i,
State &state) {
return monad_chain->revert_transaction(
block.header.number,
block.header.timestamp,
sender,
tx,
block.header.base_fee_per_gas.value_or(0),
i,
state,
chain_context);
};
}

record_block_marker_event(MONAD_EXEC_BLOCK_PERF_EVM_ENTER);
BOOST_OUTCOME_TRY(
auto const receipts,
Expand All @@ -148,7 +238,8 @@ Result<BlockHeader> process_ethereum_block(
priority_pool,
block_metrics,
call_tracers,
state_tracers));
state_tracers,
revert_transaction));
record_block_marker_event(MONAD_EXEC_BLOCK_PERF_EVM_EXIT);

// Database commit of state changes (incl. Merkle root calculations)
Expand Down Expand Up @@ -208,9 +299,7 @@ Result<BlockHeader> process_ethereum_block(
return output_header;
}

MONAD_ANONYMOUS_NAMESPACE_END

MONAD_NAMESPACE_BEGIN
EXPLICIT_TRAITS(process_ethereum_block);

Result<std::pair<uint64_t, uint64_t>> runloop_ethereum(
Chain const &chain, std::filesystem::path const &ledger_dir, Db &db,
Expand Down
26 changes: 26 additions & 0 deletions cmd/monad/runloop_ethereum.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,15 @@

#pragma once

#include <category/core/bytes.hpp>
#include <category/core/config.hpp>
#include <category/core/result.hpp>
#include <category/execution/ethereum/core/address.hpp>
#include <category/vm/evm/traits.hpp>
#include <category/vm/vm.hpp>

#include <ankerl/unordered_dense.h>

#include <cstdint>
#include <filesystem>
#include <utility>
Expand All @@ -27,6 +32,9 @@

MONAD_NAMESPACE_BEGIN

struct Block;
struct BlockHeader;
class BlockHashBuffer;
struct Chain;
struct Db;
class BlockHashBufferFinalized;
Expand All @@ -36,6 +44,24 @@ namespace fiber
class PriorityPool;
}

struct BlockCacheEntry
{
uint64_t block_number;
bytes32_t parent_id;
ankerl::unordered_dense::segmented_set<Address> senders_and_authorities;
};

using BlockCache =
ankerl::unordered_dense::segmented_map<bytes32_t, BlockCacheEntry>;

template <Traits traits>
Result<BlockHeader> process_ethereum_block(
Chain const &chain, Db &db, vm::VM &vm,
BlockHashBuffer const &block_hash_buffer,
fiber::PriorityPool &priority_pool, Block const &block,
bytes32_t const &block_id, bytes32_t const &parent_block_id,
bool const enable_tracing, BlockCache * = nullptr);

Result<std::pair<uint64_t, uint64_t>> runloop_ethereum(
Chain const &, std::filesystem::path const &, Db &, vm::VM &,
BlockHashBufferFinalized &, fiber::PriorityPool &, uint64_t &, uint64_t,
Expand Down
Loading
Loading