Skip to content

Commit 820cc51

Browse files
committed
Add a tx selector to skip txs from the same sender after the first not selected
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
1 parent a94f376 commit 820cc51

File tree

10 files changed

+327
-158
lines changed

10 files changed

+327
-158
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
### Breaking Changes
55
### Upcoming Breaking Changes
66
### Additions and Improvements
7+
- Add a tx selector to skip txs from the same sender after the first not selected [#8216](https://github.com/hyperledger/besu/pull/8216)
8+
79
#### Prague
810
- Add timestamps to enable Prague hardfork on Sepolia and Holesky test networks [#8163](https://github.com/hyperledger/besu/pull/8163)
911
- Update system call addresses to match [devnet-6](https://github.com/ethereum/execution-spec-tests/releases/) values [#8209](https://github.com/hyperledger/besu/issues/8209)
12+
1013
#### Plugins
1114
- Extend simulate transaction on pending block plugin API [#8174](https://github.com/hyperledger/besu/pull/8174)
1215

ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.MinPriorityFeePerGasTransactionSelector;
3131
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.PriceTransactionSelector;
3232
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.ProcessingResultTransactionSelector;
33+
import org.hyperledger.besu.ethereum.blockcreation.txselection.selectors.SkipSenderTransactionSelector;
3334
import org.hyperledger.besu.ethereum.chain.Blockchain;
3435
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
3536
import org.hyperledger.besu.ethereum.core.MutableWorldState;
@@ -151,6 +152,7 @@ public BlockTransactionSelector(
151152
private List<AbstractTransactionSelector> createTransactionSelectors(
152153
final BlockSelectionContext context) {
153154
return List.of(
155+
new SkipSenderTransactionSelector(context),
154156
new BlockSizeTransactionSelector(context),
155157
new BlobSizeTransactionSelector(context),
156158
new PriceTransactionSelector(context),
@@ -442,7 +444,8 @@ private TransactionSelectionResult handleTransactionSelected(
442444
evaluationContext, BLOCK_SELECTION_TIMEOUT, txWorldStateUpdater);
443445
}
444446

445-
pluginTransactionSelector.onTransactionSelected(evaluationContext, processingResult);
447+
notifySelected(evaluationContext, processingResult);
448+
446449
blockWorldStateUpdater = worldState.updater();
447450
LOG.atTrace()
448451
.setMessage("Selected {} for block creation, evaluated in {}")
@@ -475,7 +478,7 @@ private TransactionSelectionResult handleTransactionNotSelected(
475478
: selectionResult;
476479

477480
transactionSelectionResults.updateNotSelected(evaluationContext.getTransaction(), actualResult);
478-
pluginTransactionSelector.onTransactionNotSelected(evaluationContext, actualResult);
481+
notifyNotSelected(evaluationContext, actualResult);
479482
LOG.atTrace()
480483
.setMessage(
481484
"Not selected {} for block creation with result {} (original result {}), evaluated in {}")
@@ -550,6 +553,26 @@ private TransactionSelectionResult handleTransactionNotSelected(
550553
return handleTransactionNotSelected(evaluationContext, selectionResult);
551554
}
552555

556+
private void notifySelected(
557+
final TransactionEvaluationContext evaluationContext,
558+
final TransactionProcessingResult processingResult) {
559+
560+
for (var selector : transactionSelectors) {
561+
selector.onTransactionSelected(evaluationContext, processingResult);
562+
}
563+
pluginTransactionSelector.onTransactionSelected(evaluationContext, processingResult);
564+
}
565+
566+
private void notifyNotSelected(
567+
final TransactionEvaluationContext evaluationContext,
568+
final TransactionSelectionResult selectionResult) {
569+
570+
for (var selector : transactionSelectors) {
571+
selector.onTransactionNotSelected(evaluationContext, selectionResult);
572+
}
573+
pluginTransactionSelector.onTransactionNotSelected(evaluationContext, selectionResult);
574+
}
575+
553576
private void checkCancellation() {
554577
if (isCancelled.get()) {
555578
throw new CancellationException("Cancelled during transaction selection.");

ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/AbstractTransactionSelector.java

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
* transactions.
2626
*/
2727
public abstract class AbstractTransactionSelector {
28-
final BlockSelectionContext context;
28+
protected final BlockSelectionContext context;
2929

3030
public AbstractTransactionSelector(final BlockSelectionContext context) {
3131
this.context = context;
@@ -55,4 +55,24 @@ public abstract TransactionSelectionResult evaluateTransactionPostProcessing(
5555
final TransactionEvaluationContext evaluationContext,
5656
final TransactionSelectionResults blockTransactionResults,
5757
final TransactionProcessingResult processingResult);
58+
59+
/**
60+
* Method called when a transaction is selected to be added to a block.
61+
*
62+
* @param evaluationContext The current selection context
63+
* @param processingResult The result of processing the selected transaction.
64+
*/
65+
public void onTransactionSelected(
66+
final TransactionEvaluationContext evaluationContext,
67+
final TransactionProcessingResult processingResult) {}
68+
69+
/**
70+
* Method called when a transaction is not selected to be added to a block.
71+
*
72+
* @param evaluationContext The current selection context
73+
* @param transactionSelectionResult The transaction selection result
74+
*/
75+
public void onTransactionNotSelected(
76+
final TransactionEvaluationContext evaluationContext,
77+
final TransactionSelectionResult transactionSelectionResult) {}
5878
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright contributors to Besu.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*
13+
* SPDX-License-Identifier: Apache-2.0
14+
*/
15+
package org.hyperledger.besu.ethereum.blockcreation.txselection.selectors;
16+
17+
import org.hyperledger.besu.datatypes.Address;
18+
import org.hyperledger.besu.ethereum.blockcreation.txselection.BlockSelectionContext;
19+
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionEvaluationContext;
20+
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults;
21+
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
22+
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
23+
24+
import java.util.HashSet;
25+
import java.util.Set;
26+
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
29+
30+
public class SkipSenderTransactionSelector extends AbstractTransactionSelector {
31+
private static final Logger LOG = LoggerFactory.getLogger(SkipSenderTransactionSelector.class);
32+
private final Set<Address> skippedSenders = new HashSet<>();
33+
34+
public SkipSenderTransactionSelector(final BlockSelectionContext context) {
35+
super(context);
36+
}
37+
38+
@Override
39+
public TransactionSelectionResult evaluateTransactionPreProcessing(
40+
final TransactionEvaluationContext evaluationContext,
41+
final TransactionSelectionResults ignored) {
42+
final var sender = evaluationContext.getTransaction().getSender();
43+
if (skippedSenders.contains(sender)) {
44+
LOG.atTrace()
45+
.setMessage("Not selecting tx {} since its sender {} is in the skip list")
46+
.addArgument(() -> evaluationContext.getPendingTransaction().toTraceLog())
47+
.addArgument(sender)
48+
.log();
49+
50+
return TransactionSelectionResult.SENDER_WITH_PREVIOUS_TX_NOT_SELECTED;
51+
}
52+
return TransactionSelectionResult.SELECTED;
53+
}
54+
55+
@Override
56+
public TransactionSelectionResult evaluateTransactionPostProcessing(
57+
final TransactionEvaluationContext evaluationContext,
58+
final TransactionSelectionResults blockTransactionResults,
59+
final TransactionProcessingResult processingResult) {
60+
// All necessary checks were done in the pre-processing method, so nothing to do here.
61+
return TransactionSelectionResult.SELECTED;
62+
}
63+
64+
/**
65+
* When a transaction is not selected we can skip processing any following transaction from the
66+
* same sender, since it will never be selected due to the nonce gap, so we add the sender to the
67+
* skip list.
68+
*
69+
* @param evaluationContext The current selection context
70+
* @param transactionSelectionResult The transaction selection result
71+
*/
72+
@Override
73+
public void onTransactionNotSelected(
74+
final TransactionEvaluationContext evaluationContext,
75+
final TransactionSelectionResult transactionSelectionResult) {
76+
final var sender = evaluationContext.getTransaction().getSender();
77+
skippedSenders.add(sender);
78+
LOG.trace("Sender {} added to the skip list", sender);
79+
}
80+
}

0 commit comments

Comments
 (0)