Skip to content

Commit 94c3f59

Browse files
eclark0426jhunsaker
authored andcommitted
Update runloop_monad_ethblocks for monad replay
1 parent 43e0f86 commit 94c3f59

File tree

2 files changed

+161
-17
lines changed

2 files changed

+161
-17
lines changed

cmd/monad/runloop_monad_ethblocks.cpp

Lines changed: 158 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// You should have received a copy of the GNU General Public License
1414
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1515

16-
#include "runloop_ethereum.hpp"
16+
#include "runloop_monad_ethblocks.hpp"
1717

1818
#include <category/core/assert.h>
1919
#include <category/core/bytes.hpp>
@@ -22,7 +22,6 @@
2222
#include <category/core/keccak.hpp>
2323
#include <category/core/procfs/statm.h>
2424
#include <category/execution/ethereum/block_hash_buffer.hpp>
25-
#include <category/execution/ethereum/chain/chain.hpp>
2625
#include <category/execution/ethereum/core/block.hpp>
2726
#include <category/execution/ethereum/core/rlp/block_rlp.hpp>
2827
#include <category/execution/ethereum/db/block_db.hpp>
@@ -34,15 +33,20 @@
3433
#include <category/execution/ethereum/trace/call_tracer.hpp>
3534
#include <category/execution/ethereum/validate_block.hpp>
3635
#include <category/execution/ethereum/validate_transaction.hpp>
36+
#include <category/execution/monad/chain/monad_chain.hpp>
37+
#include <category/execution/monad/validate_monad_block.hpp>
3738
#include <category/vm/evm/switch_traits.hpp>
3839
#include <category/vm/evm/traits.hpp>
3940

41+
#include <ankerl/unordered_dense.h>
42+
4043
#include <boost/outcome/try.hpp>
4144
#include <quill/Quill.h>
4245

4346
#include <algorithm>
4447
#include <chrono>
4548
#include <memory>
49+
#include <optional>
4650
#include <vector>
4751

4852
MONAD_ANONYMOUS_NAMESPACE_BEGIN
@@ -77,13 +81,19 @@ void log_tps(
7781

7882
#pragma GCC diagnostic pop
7983

80-
// Process a single historical Ethereum block
84+
// Process a single Monad block stored in Ethereum format
8185
template <Traits traits>
82-
Result<void> process_ethereum_block(
83-
Chain const &chain, Db &db, vm::VM &vm,
86+
Result<void> process_monad_block(
87+
MonadChain const &chain, Db &db, vm::VM &vm,
8488
BlockHashBufferFinalized &block_hash_buffer,
8589
fiber::PriorityPool &priority_pool, Block &block, bytes32_t const &block_id,
86-
bytes32_t const &parent_block_id, bool const enable_tracing)
90+
bytes32_t const &parent_block_id, bool const enable_tracing,
91+
ankerl::unordered_dense::segmented_set<Address> const
92+
*grandparent_senders_and_authorities,
93+
ankerl::unordered_dense::segmented_set<Address> const
94+
*parent_senders_and_authorities,
95+
ankerl::unordered_dense::segmented_set<Address>
96+
&senders_and_authorities_out)
8797
{
8898
[[maybe_unused]] auto const block_start = std::chrono::system_clock::now();
8999
auto const block_begin = std::chrono::steady_clock::now();
@@ -110,6 +120,19 @@ Result<void> process_ethereum_block(
110120
return TransactionError::MissingSender;
111121
}
112122
}
123+
ankerl::unordered_dense::segmented_set<Address> senders_and_authorities;
124+
for (Address const &sender : senders) {
125+
senders_and_authorities.insert(sender);
126+
}
127+
for (std::vector<std::optional<Address>> const &authorities :
128+
recovered_authorities) {
129+
for (std::optional<Address> const &authority : authorities) {
130+
if (authority.has_value()) {
131+
senders_and_authorities.insert(authority.value());
132+
}
133+
}
134+
}
135+
BOOST_OUTCOME_TRY(static_validate_monad_senders<traits>(senders));
113136

114137
// Call tracer initialization
115138
std::vector<std::vector<CallFrame>> call_frames{block.transactions.size()};
@@ -128,9 +151,22 @@ Result<void> process_ethereum_block(
128151
std::make_unique<trace::StateTracer>(std::monostate{})};
129152
}
130153

154+
senders_and_authorities_out = senders_and_authorities;
155+
156+
MonadChainContext chain_context{
157+
.grandparent_senders_and_authorities =
158+
grandparent_senders_and_authorities,
159+
.parent_senders_and_authorities = parent_senders_and_authorities,
160+
.senders_and_authorities = senders_and_authorities,
161+
.senders = senders,
162+
.authorities = recovered_authorities};
163+
131164
// Core execution: transaction-level EVM execution that tracks state
132165
// changes but does not commit them
133166
db.set_block_and_prefix(block.header.number - 1, parent_block_id);
167+
block.header.parent_hash =
168+
to_bytes(keccak256(rlp::encode_block_header(db.read_eth_header())));
169+
134170
BlockMetrics block_metrics;
135171
BlockState block_state(db, vm);
136172
BOOST_OUTCOME_TRY(
@@ -145,13 +181,28 @@ Result<void> process_ethereum_block(
145181
priority_pool,
146182
block_metrics,
147183
call_tracers,
148-
state_tracers));
184+
state_tracers,
185+
[&chain, &block, &chain_context](
186+
Address const &sender,
187+
Transaction const &tx,
188+
uint64_t const i,
189+
State &state) {
190+
return chain.revert_transaction(
191+
block.header.number,
192+
block.header.timestamp,
193+
sender,
194+
tx,
195+
block.header.base_fee_per_gas.value_or(0),
196+
i,
197+
state,
198+
chain_context);
199+
}));
149200

150201
// Database commit of state changes (incl. Merkle root calculations)
151202
block_state.log_debug();
152203
auto const commit_begin = std::chrono::steady_clock::now();
153204
block_state.commit(
154-
bytes32_t{block.header.number},
205+
block_id,
155206
block.header,
156207
receipts,
157208
call_frames,
@@ -222,9 +273,9 @@ MONAD_ANONYMOUS_NAMESPACE_END
222273
MONAD_NAMESPACE_BEGIN
223274

224275
Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
225-
Chain const &chain, std::filesystem::path const &ledger_dir, Db &db,
276+
MonadChain const &chain, std::filesystem::path const &ledger_dir, Db &db,
226277
vm::VM &vm, BlockHashBufferFinalized &block_hash_buffer,
227-
fiber::PriorityPool &priority_pool, uint64_t &block_num,
278+
fiber::PriorityPool &priority_pool, uint64_t &finalized_block_num,
228279
uint64_t const end_block_num, sig_atomic_t const volatile &stop,
229280
bool const enable_tracing)
230281
{
@@ -239,6 +290,84 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
239290

240291
BlockDb block_db(ledger_dir);
241292
bytes32_t parent_block_id{};
293+
uint64_t block_num = finalized_block_num;
294+
295+
std::optional<ankerl::unordered_dense::segmented_set<Address>>
296+
parent_senders_and_authorities;
297+
std::optional<ankerl::unordered_dense::segmented_set<Address>>
298+
grandparent_senders_and_authorities;
299+
300+
if (block_num > 0) {
301+
parent_block_id = bytes32_t{block_num - 1};
302+
if (block_num > 1) {
303+
Block parent_block;
304+
MONAD_ASSERT_PRINTF(
305+
block_db.get(block_num - 1, parent_block),
306+
"Could not query %lu from blockdb for parent",
307+
block_num - 1);
308+
auto const recovered_senders =
309+
recover_senders(parent_block.transactions, priority_pool);
310+
auto const recovered_authorities =
311+
recover_authorities(parent_block.transactions, priority_pool);
312+
std::vector<Address> senders(parent_block.transactions.size());
313+
for (unsigned j = 0; j < recovered_senders.size(); ++j) {
314+
if (recovered_senders[j].has_value()) {
315+
senders[j] = recovered_senders[j].value();
316+
}
317+
}
318+
ankerl::unordered_dense::segmented_set<Address> parent_set;
319+
for (Address const &sender : senders) {
320+
parent_set.insert(sender);
321+
}
322+
for (std::vector<std::optional<Address>> const &authorities :
323+
recovered_authorities) {
324+
for (std::optional<Address> const &authority : authorities) {
325+
if (authority.has_value()) {
326+
parent_set.insert(authority.value());
327+
}
328+
}
329+
}
330+
parent_senders_and_authorities = std::move(parent_set);
331+
332+
if (block_num > 2) {
333+
Block grandparent_block;
334+
MONAD_ASSERT_PRINTF(
335+
block_db.get(block_num - 2, grandparent_block),
336+
"Could not query %lu from blockdb for grandparent",
337+
block_num - 2);
338+
auto const grandparent_recovered_senders = recover_senders(
339+
grandparent_block.transactions, priority_pool);
340+
auto const grandparent_recovered_authorities =
341+
recover_authorities(
342+
grandparent_block.transactions, priority_pool);
343+
std::vector<Address> grandparent_senders(
344+
grandparent_block.transactions.size());
345+
for (unsigned j = 0; j < grandparent_recovered_senders.size();
346+
++j) {
347+
if (grandparent_recovered_senders[j].has_value()) {
348+
grandparent_senders[j] =
349+
grandparent_recovered_senders[j].value();
350+
}
351+
}
352+
ankerl::unordered_dense::segmented_set<Address> grandparent_set;
353+
for (Address const &sender : grandparent_senders) {
354+
grandparent_set.insert(sender);
355+
}
356+
for (std::vector<std::optional<Address>> const &authorities :
357+
grandparent_recovered_authorities) {
358+
for (std::optional<Address> const &authority :
359+
authorities) {
360+
if (authority.has_value()) {
361+
grandparent_set.insert(authority.value());
362+
}
363+
}
364+
}
365+
grandparent_senders_and_authorities =
366+
std::move(grandparent_set);
367+
}
368+
}
369+
}
370+
242371
while (block_num <= end_block_num && stop == 0) {
243372
Block block;
244373
MONAD_ASSERT_PRINTF(
@@ -247,12 +376,13 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
247376
block_num);
248377

249378
bytes32_t const block_id = bytes32_t{block.header.number};
250-
evmc_revision const rev =
251-
chain.get_revision(block.header.number, block.header.timestamp);
379+
monad_revision const rev =
380+
chain.get_monad_revision(block.header.timestamp);
252381

382+
ankerl::unordered_dense::segmented_set<Address> senders_and_authorities;
253383
BOOST_OUTCOME_TRY([&] {
254-
SWITCH_EVM_TRAITS(
255-
process_ethereum_block,
384+
SWITCH_MONAD_TRAITS(
385+
process_monad_block,
256386
chain,
257387
db,
258388
vm,
@@ -261,7 +391,14 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
261391
block,
262392
block_id,
263393
parent_block_id,
264-
enable_tracing);
394+
enable_tracing,
395+
grandparent_senders_and_authorities.has_value()
396+
? &grandparent_senders_and_authorities.value()
397+
: nullptr,
398+
parent_senders_and_authorities.has_value()
399+
? &parent_senders_and_authorities.value()
400+
: nullptr,
401+
senders_and_authorities);
265402
MONAD_ABORT_PRINTF("unhandled rev switch case: %d", rev);
266403
}());
267404

@@ -283,13 +420,19 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
283420
batch_gas = 0;
284421
batch_begin = std::chrono::steady_clock::now();
285422
}
423+
424+
grandparent_senders_and_authorities =
425+
std::move(parent_senders_and_authorities);
426+
parent_senders_and_authorities = std::move(senders_and_authorities);
427+
286428
parent_block_id = block_id;
287429
++block_num;
288430
}
289431
if (batch_num_blocks > 0) {
290432
log_tps(
291433
block_num, batch_num_blocks, batch_num_txs, batch_gas, batch_begin);
292434
}
435+
finalized_block_num = block_num;
293436
return {ntxs, total_gas};
294437
}
295438

cmd/monad/runloop_monad_ethblocks.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include <category/core/config.hpp>
1919
#include <category/core/result.hpp>
20+
#include <category/execution/ethereum/chain/chain_config.h>
2021
#include <category/vm/vm.hpp>
2122

2223
#include <cstdint>
@@ -27,7 +28,7 @@
2728

2829
MONAD_NAMESPACE_BEGIN
2930

30-
struct Chain;
31+
struct MonadChain;
3132
struct Db;
3233
class BlockHashBufferFinalized;
3334

@@ -37,7 +38,7 @@ namespace fiber
3738
}
3839

3940
Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
40-
Chain const &, std::filesystem::path const &, Db &, vm::VM &,
41+
MonadChain const &, std::filesystem::path const &, Db &, vm::VM &,
4142
BlockHashBufferFinalized &, fiber::PriorityPool &, uint64_t &, uint64_t,
4243
sig_atomic_t const volatile &, bool enable_tracing);
4344

0 commit comments

Comments
 (0)