Skip to content

Commit 69c863c

Browse files
eclark0426jhunsaker
authored andcommitted
Reduce code duplication for sender/authority recovery in monad_ethblocks runloop
1 parent 650e023 commit 69c863c

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);
@@ -292,73 +325,35 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
292325
bytes32_t parent_block_id{};
293326
uint64_t block_num = finalized_block_num;
294327

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;
328+
std::
329+
array<std::optional<ankerl::unordered_dense::segmented_set<Address>>, 3>
330+
block_senders_and_authorities;
299331

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

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

@@ -386,12 +381,8 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
386381
block_id,
387382
parent_block_id,
388383
enable_tracing,
389-
grandparent_senders_and_authorities.has_value()
390-
? &grandparent_senders_and_authorities.value()
391-
: nullptr,
392-
parent_senders_and_authorities.has_value()
393-
? &parent_senders_and_authorities.value()
394-
: nullptr,
384+
block_num,
385+
block_senders_and_authorities,
395386
senders_and_authorities);
396387
MONAD_ABORT_PRINTF("unhandled rev switch case: %d", rev);
397388
}());
@@ -415,9 +406,8 @@ Result<std::pair<uint64_t, uint64_t>> runloop_monad_ethblocks(
415406
batch_begin = std::chrono::steady_clock::now();
416407
}
417408

418-
grandparent_senders_and_authorities =
419-
std::move(parent_senders_and_authorities);
420-
parent_senders_and_authorities = std::move(senders_and_authorities);
409+
block_senders_and_authorities[block_num % 3] =
410+
std::move(senders_and_authorities);
421411

422412
parent_block_id = block_id;
423413
++block_num;

0 commit comments

Comments
 (0)