Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow a transaction selection plugin to specify custom selection results #6190

Merged
merged 3 commits into from
Nov 21, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Implement debug_traceCall [#5885](https://github.com/hyperledger/besu/pull/5885)
- Transactions that takes too long to evaluate, during block creation, are dropped from the txpool [#6163](https://github.com/hyperledger/besu/pull/6163)
- New option `tx-pool-min-gas-price` to set a lower bound when accepting txs to the pool [#6098](https://github.com/hyperledger/besu/pull/6098)
- Allow a transaction selection plugin to specify custom selection results [#6190](https://github.com/hyperledger/besu/pull/6190)

## 23.10.2

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void logSelectionStats() {
"Selection stats: Totals[Evaluated={}, Selected={}, NotSelected={}, Discarded={}]; Detailed[{}]",
selectedTransactions.size() + notSelectedTxs.size(),
selectedTransactions.size(),
notSelectedStats.size(),
notSelectedTxs.size(),
notSelectedStats.entrySet().stream()
.filter(e -> e.getKey().discard())
.map(Map.Entry::getValue)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,9 @@ private boolean transactionCurrentPriceBelowMin(final PendingTransaction pending
.setMessage(
"Current gas price of {} is {} and lower than the configured minimum {}, skipping")
.addArgument(pendingTransaction::toTraceLog)
.addArgument(transactionGasPriceInBlock)
.addArgument(context.miningParameters()::getMinTransactionGasPrice)
.addArgument(transactionGasPriceInBlock::toHumanReadableString)
.addArgument(
context.miningParameters().getMinTransactionGasPrice()::toHumanReadableString)
.log();
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -583,9 +583,9 @@ public void transactionSelectionPluginShouldWork_PreProcessing() {
public TransactionSelectionResult evaluateTransactionPreProcessing(
final PendingTransaction pendingTransaction) {
if (pendingTransaction.getTransaction().equals(notSelectedTransient))
return TransactionSelectionResult.invalidTransient("transient");
return PluginTrasactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT;
if (pendingTransaction.getTransaction().equals(notSelectedInvalid))
return TransactionSelectionResult.invalid("invalid");
return PluginTrasactionSelectionResult.GENERIC_PLUGIN_INVALID;
return SELECTED;
}

Expand Down Expand Up @@ -618,8 +618,10 @@ public TransactionSelectionResult evaluateTransactionPostProcessing(
assertThat(transactionSelectionResults.getSelectedTransactions()).containsOnly(selected);
assertThat(transactionSelectionResults.getNotSelectedTransactions())
.containsOnly(
entry(notSelectedTransient, TransactionSelectionResult.invalidTransient("transient")),
entry(notSelectedInvalid, TransactionSelectionResult.invalid("invalid")));
entry(
notSelectedTransient,
PluginTrasactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT),
entry(notSelectedInvalid, PluginTrasactionSelectionResult.GENERIC_PLUGIN_INVALID));
}

@Test
Expand Down Expand Up @@ -654,7 +656,7 @@ public TransactionSelectionResult evaluateTransactionPostProcessing(
processingResult) {
// the transaction with max gas +1 should fail
if (processingResult.getEstimateGasUsedByTransaction() > maxGasUsedByTransaction) {
return TransactionSelectionResult.invalidTransient("Invalid");
return PluginTrasactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT;
}
return SELECTED;
}
Expand All @@ -678,7 +680,8 @@ public TransactionSelectionResult evaluateTransactionPostProcessing(

assertThat(transactionSelectionResults.getSelectedTransactions()).contains(selected, selected3);
assertThat(transactionSelectionResults.getNotSelectedTransactions())
.containsOnly(entry(notSelected, TransactionSelectionResult.invalidTransient("Invalid")));
.containsOnly(
entry(notSelected, PluginTrasactionSelectionResult.GENERIC_PLUGIN_INVALID_TRANSIENT));
}

@Test
Expand Down Expand Up @@ -1189,4 +1192,48 @@ protected MiningParameters createMiningParameters(
.build())
.build();
}

private static class PluginTrasactionSelectionResult extends TransactionSelectionResult {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo here -> PluginTraNsactionSelectionResult

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, fixed

private enum PluginStatus implements Status {
PLUGIN_INVALID(false, true),
PLUGIN_INVALID_TRANSIENT(false, false);

private final boolean stop;
private final boolean discard;

PluginStatus(final boolean stop, final boolean discard) {
this.stop = stop;
this.discard = discard;
}

@Override
public boolean stop() {
return stop;
}

@Override
public boolean discard() {
return discard;
}
}

public static final TransactionSelectionResult GENERIC_PLUGIN_INVALID_TRANSIENT =
invalidTransient("GENERIC_PLUGIN_INVALID_TRANSIENT");

public static final TransactionSelectionResult GENERIC_PLUGIN_INVALID =
invalid("GENERIC_PLUGIN_INVALID");

private PluginTrasactionSelectionResult(final Status status, final String invalidReason) {
super(status, invalidReason);
}

public static TransactionSelectionResult invalidTransient(final String invalidReason) {
return new PluginTrasactionSelectionResult(
PluginStatus.PLUGIN_INVALID_TRANSIENT, invalidReason);
}

public static TransactionSelectionResult invalid(final String invalidReason) {
return new PluginTrasactionSelectionResult(PluginStatus.PLUGIN_INVALID, invalidReason);
}
}
}
2 changes: 1 addition & 1 deletion plugin-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files
knownHash = 'gKRXd2Ow7wYKSgeGrDMRj0+2LdCzjOhLx8UEno9btGw='
knownHash = 'nB1LhUpMWYFQpBdNJ/3Q79c8kLgUgPmEFzlRMlLUl1Y='
}
check.dependsOn('checkAPIChanges')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,34 @@
*/
public class TransactionSelectionResult {

private enum Status {
/**
* Represent the status of a transaction selection result. Plugin can extend this to implement its
* own statuses.
*/
protected interface Status {
/**
* Should the selection process be stopped?
*
* @return true if the selection process needs to be stopped
*/
boolean stop();

/**
* Should the current transaction be removed from the txpool?
*
* @return yes if the transaction should be removed from the txpool
*/
boolean discard();

/**
* Name of this status
*
* @return the name
*/
String name();
}

private enum BaseStatus implements Status {
SELECTED,
BLOCK_FULL(true, false),
BLOCK_OCCUPANCY_ABOVE_THRESHOLD(true, false),
Expand All @@ -36,12 +63,12 @@ private enum Status {
private final boolean stop;
private final boolean discard;

Status() {
BaseStatus() {
this.stop = false;
this.discard = false;
}

Status(final boolean stop, final boolean discard) {
BaseStatus(final boolean stop, final boolean discard) {
this.stop = stop;
this.discard = discard;
}
Expand All @@ -50,26 +77,36 @@ private enum Status {
public String toString() {
return name() + " (stop=" + stop + ", discard=" + discard + ")";
}

@Override
public boolean stop() {
return stop;
}

@Override
public boolean discard() {
return discard;
}
}

/** The transaction has been selected to be included in the new block */
public static final TransactionSelectionResult SELECTED =
new TransactionSelectionResult(Status.SELECTED);
new TransactionSelectionResult(BaseStatus.SELECTED);
/** The transaction has not been selected since the block is full. */
public static final TransactionSelectionResult BLOCK_FULL =
new TransactionSelectionResult(Status.BLOCK_FULL);
new TransactionSelectionResult(BaseStatus.BLOCK_FULL);
/** There was no more time to add transaction to the block */
public static final TransactionSelectionResult BLOCK_SELECTION_TIMEOUT =
new TransactionSelectionResult(Status.BLOCK_SELECTION_TIMEOUT);
new TransactionSelectionResult(BaseStatus.BLOCK_SELECTION_TIMEOUT);
/** Transaction took too much to evaluate */
public static final TransactionSelectionResult TX_EVALUATION_TOO_LONG =
new TransactionSelectionResult(Status.TX_EVALUATION_TOO_LONG);
new TransactionSelectionResult(BaseStatus.TX_EVALUATION_TOO_LONG);
/**
* The transaction has not been selected since too large and the occupancy of the block is enough
* to stop the selection.
*/
public static final TransactionSelectionResult BLOCK_OCCUPANCY_ABOVE_THRESHOLD =
new TransactionSelectionResult(Status.BLOCK_OCCUPANCY_ABOVE_THRESHOLD);
new TransactionSelectionResult(BaseStatus.BLOCK_OCCUPANCY_ABOVE_THRESHOLD);
/**
* The transaction has not been selected since its gas limit is greater than the block remaining
* gas, but the selection should continue.
Expand Down Expand Up @@ -99,11 +136,22 @@ public String toString() {
private final Status status;
private final Optional<String> maybeInvalidReason;

private TransactionSelectionResult(final Status status) {
/**
* Create a new transaction selection result with the passed status
*
* @param status the selection result status
*/
protected TransactionSelectionResult(final Status status) {
this(status, null);
}

private TransactionSelectionResult(final Status status, final String invalidReason) {
/**
* Create a new transaction selection result with the passed status and invalid reason
*
* @param status the selection result status
* @param invalidReason string with a custom invalid reason
*/
protected TransactionSelectionResult(final Status status, final String invalidReason) {
this.status = status;
this.maybeInvalidReason = Optional.ofNullable(invalidReason);
}
Expand All @@ -116,7 +164,7 @@ private TransactionSelectionResult(final Status status, final String invalidReas
* @return the selection result
*/
public static TransactionSelectionResult invalidTransient(final String invalidReason) {
return new TransactionSelectionResult(Status.INVALID_TRANSIENT, invalidReason);
return new TransactionSelectionResult(BaseStatus.INVALID_TRANSIENT, invalidReason);
}

/**
Expand All @@ -127,7 +175,7 @@ public static TransactionSelectionResult invalidTransient(final String invalidRe
* @return the selection result
*/
public static TransactionSelectionResult invalid(final String invalidReason) {
return new TransactionSelectionResult(Status.INVALID, invalidReason);
return new TransactionSelectionResult(BaseStatus.INVALID, invalidReason);
}

/**
Expand All @@ -136,7 +184,7 @@ public static TransactionSelectionResult invalid(final String invalidReason) {
* @return true if the selection process should stop, false otherwise
*/
public boolean stop() {
return status.stop;
return status.stop();
}

/**
Expand All @@ -146,7 +194,7 @@ public boolean stop() {
* otherwise
*/
public boolean discard() {
return status.discard;
return status.discard();
}

/**
Expand All @@ -155,7 +203,7 @@ public boolean discard() {
* @return true if the candidate transaction is included in the new block, false otherwise
*/
public boolean selected() {
return Status.SELECTED.equals(status);
return BaseStatus.SELECTED.equals(status);
}

/**
Expand Down