Skip to content
Open
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
54 changes: 22 additions & 32 deletions category/execution/runloop/runloop_interface_monad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@
#include <category/execution/ethereum/block_hash_buffer/util.hpp>
#include <category/execution/ethereum/core/fmt/bytes_fmt.hpp>
#include <category/execution/ethereum/db/block_db.hpp>
#include <category/execution/ethereum/db/state_machine_init.hpp>
#include <category/execution/ethereum/db/trie_db.hpp>
#include <category/execution/ethereum/state2/block_state.hpp>
#include <category/execution/ethereum/state3/state.hpp>
#include <category/execution/monad/chain/monad_chain.hpp>
#include <category/execution/monad/chain/monad_devnet.hpp>
#include <category/execution/monad/chain/monad_mainnet.hpp>
#include <category/execution/monad/chain/monad_testnet.hpp>
#include <category/execution/monad/db/state_machine_init.hpp>
#include <category/execution/runloop/runloop_interface_monad.h>
#include <category/execution/runloop/runloop_monad.hpp>
#include <category/mpt/db.hpp>
Expand Down Expand Up @@ -211,11 +213,8 @@ struct MonadRunloopImpl
fs::path ledger_dir;
AccountOverrideMap account_override;
mpt::Db raw_db;
mpt::Db secondary_raw_db;
TrieDb triedb;
TrieDb secondary_triedb;
MonadRunloopTrieDb runloop_db;
MonadRunloopTrieDb secondary_runloop_db;
vm::VM vm;
BlockHashBufferFinalized block_hash_buffer;
fiber::PriorityPool priority_pool;
Expand All @@ -226,40 +225,35 @@ struct MonadRunloopImpl
uint64_t chain_id, char const *ledger_path, char const *db_path);
};

mpt::Db get_secondary_raw_db(mpt::Db &db)
{
if (db.timeline_active(mpt::timeline_id::secondary)) {
auto db2 =
db.open_secondary_timeline(std::make_unique<MonadOnDiskMachine>());
MONAD_ASSERT(db2.has_value());
return std::move(*db2);
}
return db.activate_secondary_timeline(
std::make_unique<MonadOnDiskMachine>());
}

MonadRunloopImpl::MonadRunloopImpl(
uint64_t const chain_id, char const *const ledger_path,
char const *const db_path)
: chain{monad_chain_from_chain_id(chain_id)}
, ledger_dir{ledger_path}
, raw_db{std::make_unique<OnDiskMachine>(), mpt::OnDiskDbConfig{.append = true, .compaction = true, .rewind_to_latest_finalized = true, .rd_buffers = 8192, .wr_buffers = 32, .uring_entries = 128, .sq_thread_cpu = sq_thread_cpu, .dbname_paths = {fs::path{db_path}}}}
, secondary_raw_db{get_secondary_raw_db(raw_db)}
, raw_db{mpt::OnDiskDbConfig{
.append = true,
.compaction = true,
.rewind_to_latest_finalized = true,
.rd_buffers = 8192,
.wr_buffers = 32,
.uring_entries = 128,
.sq_thread_cpu = sq_thread_cpu,
.dbname_paths = {fs::path{db_path}}}}
, triedb{raw_db, /*enable_multiblock_cache=*/true}
, secondary_triedb{secondary_raw_db}
, runloop_db{triedb, account_override}
, secondary_runloop_db{secondary_triedb, account_override}
, vm{}
, block_hash_buffer{}
, priority_pool{nthreads, nfibers}
{
MONAD_ASSERT(triedb.is_page_encoded() == false);
MONAD_ASSERT(secondary_triedb.is_page_encoded() == true);
// runloop_monad requires a single page-encoded timeline. The encoding
// comes from the state_machine_kind persisted when the pool was created
// (monad-mpt --create --state-machine monad); it is never stamped here.
MONAD_ASSERT(triedb.is_page_encoded());
MONAD_ASSERT(!raw_db.timeline_active(mpt::timeline_id::secondary));
if (triedb.get_root() == nullptr) {
LOG_INFO("loading from genesis");
GenesisState const genesis_state = chain->get_genesis_state();
load_genesis_state(genesis_state, triedb);
load_genesis_state(genesis_state, secondary_triedb);
}
else {
LOG_INFO("loading from previous DB state");
Expand Down Expand Up @@ -379,6 +373,11 @@ extern "C" MonadRunloop *monad_runloop_new(
init_root_logger(log_level);
is_quill_running = true;
}
// The on-disk Db ctor reads the persisted state_machine_kind and builds
// the StateMachine through the registry, so the factories must be
// registered first. Idempotent.
register_ethereum_state_machines();
register_monad_state_machines();
return from_impl(new MonadRunloopImpl{chain_id, ledger_path, db_path});
}

Expand Down Expand Up @@ -406,7 +405,6 @@ try {
runloop->ledger_dir,
runloop->raw_db,
runloop->runloop_db,
&runloop->secondary_runloop_db,
runloop->vm,
runloop->block_hash_buffer,
runloop->priority_pool,
Expand Down Expand Up @@ -463,22 +461,14 @@ extern "C" void monad_runloop_get_balance(
store_be(result_balance->bytes, bal);
}

extern "C" void monad_runloop_get_primary_state_root(
extern "C" void monad_runloop_get_state_root(
MonadRunloop *const pre_runloop, MonadRunloopWord *const result_state_root)
{
MonadRunloopImpl *const runloop = to_impl(pre_runloop);
*result_state_root =
std::bit_cast<MonadRunloopWord>(runloop->triedb.state_root());
}

extern "C" void monad_runloop_get_secondary_state_root(
MonadRunloop *const pre_runloop, MonadRunloopWord *const result_state_root)
{
MonadRunloopImpl *const runloop = to_impl(pre_runloop);
*result_state_root = std::bit_cast<MonadRunloopWord>(
runloop->secondary_runloop_db.state_root());
}

extern "C" void monad_runloop_dump(MonadRunloop *const pre_runloop)
{
MonadRunloopImpl *const runloop = to_impl(pre_runloop);
Expand Down
11 changes: 4 additions & 7 deletions category/execution/runloop/runloop_interface_monad.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ struct MonadRunloopAddress
// Opaque runloop structure:
typedef void MonadRunloop;

// Make a new runloop client
// Make a new runloop client. The pool at db_path must already exist and be
// page-encoded (created with monad-mpt --create --state-machine monad).
MonadRunloop *monad_runloop_new(
uint64_t chain_id, char const *ledger_path, char const *db_path);

Expand All @@ -55,12 +56,8 @@ void monad_runloop_get_balance(
MonadRunloop *, MonadRunloopAddress const *,
MonadRunloopWord *result_balance);

// Store current primary state root in `result_state_root`.
void monad_runloop_get_primary_state_root(
MonadRunloop *, MonadRunloopWord *result_state_root);

// Store current secondary state root in `result_state_root`.
void monad_runloop_get_secondary_state_root(
// Store current state root in `result_state_root`.
void monad_runloop_get_state_root(
MonadRunloop *, MonadRunloopWord *result_state_root);

// Dump the current state of the database to stdout
Expand Down
53 changes: 24 additions & 29 deletions category/execution/runloop/runloop_monad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ Result<BlockExecOutput> propose_block(
BlockHashChain &block_hash_chain, MonadChain const &chain, Db &db,
vm::VM &vm, fiber::PriorityPool &priority_pool, bool const is_first_block,
bool const enable_tracing, BlockCache &block_cache,
ExecutionEventRecorder *const exec_recorder, Db *secondary_db,
ExecutionEventRecorder *const exec_recorder,
RunloopMonadOverride const runloop_override)
{
[[maybe_unused]] auto const block_start = std::chrono::system_clock::now();
Expand Down Expand Up @@ -282,11 +282,9 @@ Result<BlockExecOutput> propose_block(

// Core execution: transaction-level EVM execution that tracks state
// changes but does not commit them
for_each_db(db, secondary_db, [&](Db &d) {
d.set_block_and_prefix(
block.header.number - 1,
is_first_block ? bytes32_t{} : consensus_header.parent_id());
});
db.set_block_and_prefix(
block.header.number - 1,
is_first_block ? bytes32_t{} : consensus_header.parent_id());
block.header.parent_hash =
to_bytes(keccak256(rlp::encode_block_header(db.read_eth_header())));

Expand All @@ -300,7 +298,7 @@ Result<BlockExecOutput> propose_block(
BlockExecOutput exec_output;
BlockMetrics block_metrics;

BlockState block_state(db, vm, secondary_db);
BlockState block_state(db, vm);
record_block_marker_event(exec_recorder, MONAD_EXEC_BLOCK_PERF_EVM_ENTER);
BOOST_OUTCOME_TRY(
auto const results,
Expand Down Expand Up @@ -337,7 +335,8 @@ Result<BlockExecOutput> propose_block(
.call_frames = call_frames,
.ommers = block.ommers,
.withdrawals = block.withdrawals};
commit_block<traits>(db, secondary_db, block_id, block.header, *state, anc);
commit_block<traits>(
db, /*secondary_db=*/nullptr, block_id, block.header, *state, anc);
[[maybe_unused]] auto const commit_time =
std::chrono::duration_cast<std::chrono::microseconds>(
std::chrono::steady_clock::now() - commit_begin);
Expand All @@ -363,16 +362,11 @@ Result<BlockExecOutput> propose_block(
block_id,
consensus_header.parent_id());

// Dual-db migration: log both timelines' state roots (slot primary vs
// page secondary) so a divergence is visible per block.
LOG_INFO(
"block={}, block_id={} state_root primary={}{}",
"block={}, block_id={} state_root={}",
block.header.number,
block_id,
db.state_root(),
secondary_db != nullptr
? fmt::format(" secondary={}", secondary_db->state_root())
: std::string{});
db.state_root());

// Emit the block metrics log line
[[maybe_unused]] auto const block_time =
Expand Down Expand Up @@ -493,13 +487,23 @@ MONAD_NAMESPACE_BEGIN

Result<std::pair<uint64_t, uint64_t>> runloop_monad(
MonadChain const &chain, std::filesystem::path const &ledger_dir,
mpt::Db &raw_db, Db &db, Db *secondary_db, vm::VM &vm,
mpt::Db &raw_db, Db &db, vm::VM &vm,
BlockHashBufferFinalized &block_hash_buffer,
fiber::PriorityPool &priority_pool, uint64_t &block_num,
uint64_t const end_block_num, sig_atomic_t const volatile &stop,
bool const enable_tracing, ExecutionEventRecorder *const exec_recorder,
RunloopMonadOverride const runloop_override)
{
// Live execution runs on a single page-encoded timeline. A db that is
// still slot-encoded, or still carries a secondary timeline from the
// dual-db migration, is rejected here instead of being executed against.
MONAD_ASSERT(
db.is_page_encoded(), "runloop_monad requires a page-encoded db");
MONAD_ASSERT(
!raw_db.is_on_disk() ||
!raw_db.timeline_active(mpt::timeline_id::secondary),
"runloop_monad requires a single timeline; deactivate the secondary");

constexpr auto SLEEP_TIME = std::chrono::microseconds(100);
uint64_t const start_block_num =
runloop_override.start_block_num(block_num);
Expand Down Expand Up @@ -652,15 +656,12 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad(
enable_tracing,
&block_cache,
exec_recorder,
secondary_db,
runloop_override](
bytes32_t const &block_id,
auto const &header) -> Result<std::pair<uint64_t, uint64_t>> {
auto const block_time_start = std::chrono::steady_clock::now();

for_each_db(db, secondary_db, [&](Db &d) {
d.update_voted_metadata(header.seqno - 1, header.parent_id());
});
db.update_voted_metadata(header.seqno - 1, header.parent_id());
record_block_qc(exec_recorder, header, last_finalized_block_number);

uint64_t const block_number = header.execution_inputs.number;
Expand Down Expand Up @@ -713,17 +714,14 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad(
enable_tracing,
block_cache,
exec_recorder,
secondary_db,
runloop_override);
MONAD_ABORT_PRINTF("handled rev value %d", rev);
};
BOOST_OUTCOME_TRY(
BlockExecOutput const exec_output,
record_block_result(exec_recorder, propose_dispatch()));

for_each_db(db, secondary_db, [&](Db &d) {
d.update_proposed_metadata(header.seqno, block_id);
});
db.update_proposed_metadata(header.seqno, block_id);

log_tps(
block_number,
Expand All @@ -748,17 +746,14 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad(
"Processing finalization for block {} with block_id {}",
block,
block_id);
for_each_db(
db, secondary_db, [&](Db &d) { d.finalize(block, block_id); });
db.finalize(block, block_id);
block_hash_chain.finalize(block_id);
record_block_finalized(exec_recorder, block_id, block);
finalized_block_num = block;

if (!verified_blocks.empty() &&
verified_blocks.back() != mpt::INVALID_BLOCK_NUM) {
for_each_db(db, secondary_db, [&](Db &d) {
d.update_verified_block(verified_blocks.back());
});
db.update_verified_block(verified_blocks.back());
}
record_block_verified(exec_recorder, verified_blocks);
}
Expand Down
8 changes: 4 additions & 4 deletions category/execution/runloop/runloop_monad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ namespace fiber
class PriorityPool;
}

// `db` must be a single page-encoded timeline; both are asserted on entry.
Result<std::pair<uint64_t, uint64_t>> runloop_monad(
MonadChain const &, std::filesystem::path const &, mpt::Db &, Db &,
Db *secondary_db, vm::VM &, BlockHashBufferFinalized &,
fiber::PriorityPool &, uint64_t &, uint64_t, sig_atomic_t const volatile &,
bool enable_tracing, ExecutionEventRecorder *,
RunloopMonadOverride runloop_override = {});
vm::VM &, BlockHashBufferFinalized &, fiber::PriorityPool &, uint64_t &,
uint64_t, sig_atomic_t const volatile &, bool enable_tracing,
ExecutionEventRecorder *, RunloopMonadOverride runloop_override = {});

MONAD_NAMESPACE_END
Loading
Loading