Skip to content

Commit affe07d

Browse files
committed
Reduce code duplication for sender/authority recovery in monad_ethblocks runloop
1 parent bb42317 commit affe07d

File tree

1 file changed

+92
-102
lines changed

1 file changed

+92
-102
lines changed

cmd/monad/runloop_monad_ethblocks.cpp

Lines changed: 92 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include <quill/Quill.h>
4545

4646
#include <algorithm>
47+
#include <array>
4748
#include <chrono>
4849
#include <memory>
4950
#include <optional>
@@ -81,17 +82,61 @@ void log_tps(
8182

8283
#pragma GCC diagnostic pop
8384

85+
struct RecoveredSendersAndAuthorities
86+
{
87+
std::vector<Address> senders;
88+
ankerl::unordered_dense::segmented_set<Address> senders_and_authorities;
89+
std::vector<std::vector<std::optional<Address>>> authorities;
90+
};
91+
92+
// Recover senders and authorities from a block
93+
Result<RecoveredSendersAndAuthorities> recover_senders_and_authorities(
94+
std::vector<Transaction> const &transactions,
95+
fiber::PriorityPool &priority_pool, bool require_all_senders)
96+
{
97+
auto const recovered_senders = recover_senders(transactions, priority_pool);
98+
auto const recovered_authorities =
99+
recover_authorities(transactions, priority_pool);
100+
std::vector<Address> senders(transactions.size());
101+
for (unsigned i = 0; i < recovered_senders.size(); ++i) {
102+
if (recovered_senders[i].has_value()) {
103+
senders[i] = recovered_senders[i].value();
104+
}
105+
else if (require_all_senders) {
106+
return TransactionError::MissingSender;
107+
}
108+
}
109+
ankerl::unordered_dense::segmented_set<Address> senders_and_authorities;
110+
for (unsigned i = 0; i < recovered_senders.size(); ++i) {
111+
if (recovered_senders[i].has_value()) {
112+
senders_and_authorities.insert(recovered_senders[i].value());
113+
}
114+
}
115+
for (std::vector<std::optional<Address>> const &authorities :
116+
recovered_authorities) {
117+
for (std::optional<Address> const &authority : authorities) {
118+
if (authority.has_value()) {
119+
senders_and_authorities.insert(authority.value());
120+
}
121+
}
122+
}
123+
return RecoveredSendersAndAuthorities{
124+
.senders = std::move(senders),
125+
.senders_and_authorities = std::move(senders_and_authorities),
126+
.authorities = std::move(recovered_authorities)};
127+
}
128+
84129
// Process a single Monad block stored in Ethereum format
85130
template <Traits traits>
86131
Result<void> process_monad_block(
87132
MonadChain const &chain, Db &db, vm::VM &vm,
88133
BlockHashBufferFinalized &block_hash_buffer,
89134
fiber::PriorityPool &priority_pool, Block &block, bytes32_t const &block_id,
90135
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,
136+
uint64_t const block_num,
137+
std::array<
138+
std::optional<ankerl::unordered_dense::segmented_set<Address>>, 3> const
139+
&block_senders_and_authorities,
95140
ankerl::unordered_dense::segmented_set<Address>
96141
&senders_and_authorities_out)
97142
{
@@ -104,36 +149,15 @@ Result<void> process_monad_block(
104149

105150
// Sender and authority recovery
106151
auto const sender_recovery_begin = std::chrono::steady_clock::now();
107-
auto const recovered_senders =
108-
recover_senders(block.transactions, priority_pool);
109-
auto const recovered_authorities =
110-
recover_authorities(block.transactions, priority_pool);
152+
BOOST_OUTCOME_TRY(
153+
auto const recovered,
154+
recover_senders_and_authorities(
155+
block.transactions, priority_pool, true));
111156
[[maybe_unused]] auto const sender_recovery_time =
112157
std::chrono::duration_cast<std::chrono::microseconds>(
113158
std::chrono::steady_clock::now() - sender_recovery_begin);
114-
std::vector<Address> senders(block.transactions.size());
115-
for (unsigned i = 0; i < recovered_senders.size(); ++i) {
116-
if (recovered_senders[i].has_value()) {
117-
senders[i] = recovered_senders[i].value();
118-
}
119-
else {
120-
return TransactionError::MissingSender;
121-
}
122-
}
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(
136-
static_validate_monad_body<traits>(senders, block.transactions));
159+
BOOST_OUTCOME_TRY(static_validate_monad_body<traits>(
160+
recovered.senders, block.transactions));
137161

138162
// Call tracer initialization
139163
std::vector<std::vector<CallFrame>> call_frames{block.transactions.size()};
@@ -152,15 +176,24 @@ Result<void> process_monad_block(
152176
std::make_unique<trace::StateTracer>(std::monostate{})};
153177
}
154178

155-
senders_and_authorities_out = senders_and_authorities;
179+
senders_and_authorities_out = recovered.senders_and_authorities;
156180

181+
auto const grandparent_idx = (block_num - 2) % 3;
182+
auto const parent_idx = (block_num - 1) % 3;
157183
MonadChainContext chain_context{
158184
.grandparent_senders_and_authorities =
159-
grandparent_senders_and_authorities,
160-
.parent_senders_and_authorities = parent_senders_and_authorities,
161-
.senders_and_authorities = senders_and_authorities,
162-
.senders = senders,
163-
.authorities = recovered_authorities};
185+
(block_num > 2 &&
186+
block_senders_and_authorities[grandparent_idx].has_value())
187+
? &block_senders_and_authorities[grandparent_idx].value()
188+
: nullptr,
189+
.parent_senders_and_authorities =
190+
(block_num > 1 &&
191+
block_senders_and_authorities[parent_idx].has_value())
192+
? &block_senders_and_authorities[parent_idx].value()
193+
: nullptr,
194+
.senders_and_authorities = recovered.senders_and_authorities,
195+
.senders = recovered.senders,
196+
.authorities = recovered.authorities};
164197

165198
// Core execution: transaction-level EVM execution that tracks state
166199
// changes but does not commit them
@@ -175,8 +208,8 @@ Result<void> process_monad_block(
175208
execute_block<traits>(
176209
chain,
177210
block,
178-
senders,
179-
recovered_authorities,
211+
recovered.senders,
212+
recovered.authorities,
180213
block_state,
181214
block_hash_buffer,
182215
priority_pool.fiber_group(),
@@ -207,7 +240,7 @@ Result<void> process_monad_block(
207240
block.header,
208241
receipts,
209242
call_frames,
210-
senders,
243+
recovered.senders,
211244
block.transactions,
212245
block.ommers,
213246
block.withdrawals);
@@ -293,73 +326,35 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
293326
bytes32_t parent_block_id{};
294327
uint64_t block_num = finalized_block_num;
295328

296-
std::optional<ankerl::unordered_dense::segmented_set<Address>>
297-
parent_senders_and_authorities;
298-
std::optional<ankerl::unordered_dense::segmented_set<Address>>
299-
grandparent_senders_and_authorities;
329+
std::
330+
array<std::optional<ankerl::unordered_dense::segmented_set<Address>>, 3>
331+
block_senders_and_authorities;
300332

301333
if (block_num > 1) {
302334
Block parent_block;
303335
MONAD_ASSERT_PRINTF(
304336
block_db.get(block_num - 1, parent_block),
305337
"Could not query %lu from blockdb for parent",
306338
block_num - 1);
307-
auto const recovered_senders =
308-
recover_senders(parent_block.transactions, priority_pool);
309-
auto const recovered_authorities =
310-
recover_authorities(parent_block.transactions, priority_pool);
311-
std::vector<Address> senders(parent_block.transactions.size());
312-
for (unsigned j = 0; j < recovered_senders.size(); ++j) {
313-
if (recovered_senders[j].has_value()) {
314-
senders[j] = recovered_senders[j].value();
315-
}
316-
}
317-
ankerl::unordered_dense::segmented_set<Address> parent_set;
318-
for (Address const &sender : senders) {
319-
parent_set.insert(sender);
320-
}
321-
for (std::vector<std::optional<Address>> const &authorities :
322-
recovered_authorities) {
323-
for (std::optional<Address> const &authority : authorities) {
324-
if (authority.has_value()) {
325-
parent_set.insert(authority.value());
326-
}
327-
}
328-
}
329-
parent_senders_and_authorities = std::move(parent_set);
339+
BOOST_OUTCOME_TRY(
340+
auto const parent_recovered,
341+
recover_senders_and_authorities(
342+
parent_block.transactions, priority_pool, false));
343+
block_senders_and_authorities[(block_num - 1) % 3] =
344+
std::move(parent_recovered.senders_and_authorities);
330345

331346
if (block_num > 2) {
332347
Block grandparent_block;
333348
MONAD_ASSERT_PRINTF(
334349
block_db.get(block_num - 2, grandparent_block),
335350
"Could not query %lu from blockdb for grandparent",
336351
block_num - 2);
337-
auto const grandparent_recovered_senders =
338-
recover_senders(grandparent_block.transactions, priority_pool);
339-
auto const grandparent_recovered_authorities = recover_authorities(
340-
grandparent_block.transactions, priority_pool);
341-
std::vector<Address> grandparent_senders(
342-
grandparent_block.transactions.size());
343-
for (unsigned j = 0; j < grandparent_recovered_senders.size();
344-
++j) {
345-
if (grandparent_recovered_senders[j].has_value()) {
346-
grandparent_senders[j] =
347-
grandparent_recovered_senders[j].value();
348-
}
349-
}
350-
ankerl::unordered_dense::segmented_set<Address> grandparent_set;
351-
for (Address const &sender : grandparent_senders) {
352-
grandparent_set.insert(sender);
353-
}
354-
for (std::vector<std::optional<Address>> const &authorities :
355-
grandparent_recovered_authorities) {
356-
for (std::optional<Address> const &authority : authorities) {
357-
if (authority.has_value()) {
358-
grandparent_set.insert(authority.value());
359-
}
360-
}
361-
}
362-
grandparent_senders_and_authorities = std::move(grandparent_set);
352+
BOOST_OUTCOME_TRY(
353+
auto const grandparent_recovered,
354+
recover_senders_and_authorities(
355+
grandparent_block.transactions, priority_pool, false));
356+
block_senders_and_authorities[(block_num - 2) % 3] =
357+
std::move(grandparent_recovered.senders_and_authorities);
363358
}
364359
}
365360

@@ -387,12 +382,8 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
387382
block_id,
388383
parent_block_id,
389384
enable_tracing,
390-
grandparent_senders_and_authorities.has_value()
391-
? &grandparent_senders_and_authorities.value()
392-
: nullptr,
393-
parent_senders_and_authorities.has_value()
394-
? &parent_senders_and_authorities.value()
395-
: nullptr,
385+
block_num,
386+
block_senders_and_authorities,
396387
senders_and_authorities);
397388
MONAD_ABORT_PRINTF("unhandled rev switch case: %d", rev);
398389
}());
@@ -416,9 +407,8 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
416407
batch_begin = std::chrono::steady_clock::now();
417408
}
418409

419-
grandparent_senders_and_authorities =
420-
std::move(parent_senders_and_authorities);
421-
parent_senders_and_authorities = std::move(senders_and_authorities);
410+
block_senders_and_authorities[block_num % 3] =
411+
std::move(senders_and_authorities);
422412

423413
parent_block_id = block_id;
424414
++block_num;

0 commit comments

Comments
 (0)