1616
1717import org .hyperledger .besu .datatypes .Address ;
1818import org .hyperledger .besu .datatypes .Wei ;
19+ import org .hyperledger .besu .ethereum .BlockProcessingResult ;
20+ import org .hyperledger .besu .ethereum .chain .Blockchain ;
1921import org .hyperledger .besu .ethereum .core .BlockHeader ;
2022import org .hyperledger .besu .ethereum .core .MutableWorldState ;
2123import org .hyperledger .besu .ethereum .core .Transaction ;
24+ import org .hyperledger .besu .ethereum .core .Withdrawal ;
25+ import org .hyperledger .besu .ethereum .mainnet .AbstractBlockProcessor .PreprocessingFunction .NoPreprocessing ;
2226import org .hyperledger .besu .ethereum .mainnet .BlockProcessor ;
2327import org .hyperledger .besu .ethereum .mainnet .MainnetBlockProcessor ;
2428import org .hyperledger .besu .ethereum .mainnet .MainnetTransactionProcessor ;
3741import java .util .List ;
3842import java .util .Optional ;
3943
44+ import org .slf4j .Logger ;
45+ import org .slf4j .LoggerFactory ;
46+
4047public class MainnetParallelBlockProcessor extends MainnetBlockProcessor {
4148
49+ private static final Logger LOG = LoggerFactory .getLogger (MainnetParallelBlockProcessor .class );
50+
4251 private final Optional <MetricsSystem > metricsSystem ;
4352 private final Optional <Counter > confirmedParallelizedTransactionCounter ;
4453 private final Optional <Counter > conflictingButCachedTransactionCounter ;
@@ -78,34 +87,6 @@ public MainnetParallelBlockProcessor(
7887 "Counter for the number of conflicted transactions during block processing" ));
7988 }
8089
81- @ Override
82- protected Optional <PreprocessingContext > runBlockPreProcessing (
83- final MutableWorldState worldState ,
84- final PrivateMetadataUpdater privateMetadataUpdater ,
85- final BlockHeader blockHeader ,
86- final List <Transaction > transactions ,
87- final Address miningBeneficiary ,
88- final BlockHashLookup blockHashLookup ,
89- final Wei blobGasPrice ) {
90- if ((worldState instanceof DiffBasedWorldState )) {
91- ParallelizedConcurrentTransactionProcessor parallelizedConcurrentTransactionProcessor =
92- new ParallelizedConcurrentTransactionProcessor (transactionProcessor );
93- // runAsyncBlock, if activated, facilitates the non-blocking parallel execution of
94- // transactions in the background through an optimistic strategy.
95- parallelizedConcurrentTransactionProcessor .runAsyncBlock (
96- worldState ,
97- blockHeader ,
98- transactions ,
99- miningBeneficiary ,
100- blockHashLookup ,
101- blobGasPrice ,
102- privateMetadataUpdater );
103- return Optional .of (
104- new ParallelizedPreProcessingContext (parallelizedConcurrentTransactionProcessor ));
105- }
106- return Optional .empty ();
107- }
108-
10990 @ Override
11091 protected TransactionProcessingResult getTransactionProcessingResult (
11192 final Optional <PreprocessingContext > preProcessingContext ,
@@ -126,7 +107,7 @@ protected TransactionProcessingResult getTransactionProcessingResult(
126107 (ParallelizedPreProcessingContext ) preProcessingContext .get ();
127108 transactionProcessingResult =
128109 parallelizedPreProcessingContext
129- .getParallelizedConcurrentTransactionProcessor ()
110+ .parallelizedConcurrentTransactionProcessor ()
130111 .applyParallelizedTransactionResult (
131112 worldState ,
132113 miningBeneficiary ,
@@ -154,21 +135,48 @@ protected TransactionProcessingResult getTransactionProcessingResult(
154135 }
155136 }
156137
157- static class ParallelizedPreProcessingContext implements PreprocessingContext {
158- final ParallelizedConcurrentTransactionProcessor parallelizedConcurrentTransactionProcessor ;
159-
160- public ParallelizedPreProcessingContext (
161- final ParallelizedConcurrentTransactionProcessor
162- parallelizedConcurrentTransactionProcessor ) {
163- this .parallelizedConcurrentTransactionProcessor = parallelizedConcurrentTransactionProcessor ;
164- }
165-
166- public ParallelizedConcurrentTransactionProcessor
167- getParallelizedConcurrentTransactionProcessor () {
168- return parallelizedConcurrentTransactionProcessor ;
138+ @ Override
139+ public BlockProcessingResult processBlock (
140+ final Blockchain blockchain ,
141+ final MutableWorldState worldState ,
142+ final BlockHeader blockHeader ,
143+ final List <Transaction > transactions ,
144+ final List <BlockHeader > ommers ,
145+ final Optional <List <Withdrawal >> maybeWithdrawals ,
146+ final PrivateMetadataUpdater privateMetadataUpdater ) {
147+ final BlockProcessingResult blockProcessingResult =
148+ super .processBlock (
149+ blockchain ,
150+ worldState ,
151+ blockHeader ,
152+ transactions ,
153+ ommers ,
154+ maybeWithdrawals ,
155+ privateMetadataUpdater ,
156+ new ParallelTransactionPreprocessing ());
157+ if (blockProcessingResult .isFailed ()) {
158+ // Fallback to non-parallel processing if there is a block processing exception .
159+ LOG .info (
160+ "Parallel transaction processing failure. Falling back to non-parallel processing for block #{} ({})" ,
161+ blockHeader .getNumber (),
162+ blockHeader .getBlockHash ());
163+ return super .processBlock (
164+ blockchain ,
165+ worldState ,
166+ blockHeader ,
167+ transactions ,
168+ ommers ,
169+ maybeWithdrawals ,
170+ privateMetadataUpdater ,
171+ new NoPreprocessing ());
169172 }
173+ return blockProcessingResult ;
170174 }
171175
176+ record ParallelizedPreProcessingContext (
177+ ParallelizedConcurrentTransactionProcessor parallelizedConcurrentTransactionProcessor )
178+ implements PreprocessingContext {}
179+
172180 public static class ParallelBlockProcessorBuilder
173181 implements ProtocolSpecBuilder .BlockProcessorBuilder {
174182
@@ -196,4 +204,35 @@ public BlockProcessor apply(
196204 metricsSystem );
197205 }
198206 }
207+
208+ class ParallelTransactionPreprocessing implements PreprocessingFunction {
209+
210+ @ Override
211+ public Optional <PreprocessingContext > run (
212+ final MutableWorldState worldState ,
213+ final PrivateMetadataUpdater privateMetadataUpdater ,
214+ final BlockHeader blockHeader ,
215+ final List <Transaction > transactions ,
216+ final Address miningBeneficiary ,
217+ final BlockHashLookup blockHashLookup ,
218+ final Wei blobGasPrice ) {
219+ if ((worldState instanceof DiffBasedWorldState )) {
220+ ParallelizedConcurrentTransactionProcessor parallelizedConcurrentTransactionProcessor =
221+ new ParallelizedConcurrentTransactionProcessor (transactionProcessor );
222+ // When enabled, runAsyncBlock performs non-conflicting parallel execution of transactions
223+ // in the background using an optimistic approach.
224+ parallelizedConcurrentTransactionProcessor .runAsyncBlock (
225+ worldState ,
226+ blockHeader ,
227+ transactions ,
228+ miningBeneficiary ,
229+ blockHashLookup ,
230+ blobGasPrice ,
231+ privateMetadataUpdater );
232+ return Optional .of (
233+ new ParallelizedPreProcessingContext (parallelizedConcurrentTransactionProcessor ));
234+ }
235+ return Optional .empty ();
236+ }
237+ }
199238}
0 commit comments