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>
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>
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
4852MONAD_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
8185template <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
222273MONAD_NAMESPACE_BEGIN
223274
224275Result<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
0 commit comments