Skip to content

Commit

Permalink
Support pending transaction score when saving and restoring txpool
Browse files Browse the repository at this point in the history
Signed-off-by: Fabio Di Fabio <[email protected]>
  • Loading branch information
fab-10 committed Feb 27, 2025
1 parent 3d41ccb commit bd10304
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static org.assertj.core.api.Assertions.fail;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
Expand Down Expand Up @@ -1080,7 +1081,8 @@ private PendingTransaction createLocalTransaction(final long transactionNumber)
.nonce(transactionNumber)
.createTransaction(KEYS1),
true,
true);
true,
MAX_SCORE);
}

private static BlockHeader mockBlockHeader() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOBS_FULL;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.TX_TOO_LARGE_FOR_REMAINING_BLOB_GAS;
Expand Down Expand Up @@ -172,12 +173,12 @@ private void evaluateAndAssertNotSelected(

private PendingTransaction createEIP1559PendingTransaction() {
return PendingTransaction.newPendingTransaction(
createTransaction(TransactionType.EIP1559, 0), false, false);
createTransaction(TransactionType.EIP1559, 0), false, false, MAX_SCORE);
}

private PendingTransaction createBlobPendingTransaction(final int blobCount) {
return PendingTransaction.newPendingTransaction(
createTransaction(TransactionType.BLOB, blobCount), false, false);
createTransaction(TransactionType.BLOB, blobCount), false, false, MAX_SCORE);
}

private Transaction createTransaction(final TransactionType type, final int blobCount) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.blockcreation.txselection.selectors;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_FULL;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.BLOCK_OCCUPANCY_ABOVE_THRESHOLD;
import static org.hyperledger.besu.plugin.data.TransactionSelectionResult.SELECTED;
Expand Down Expand Up @@ -247,7 +248,7 @@ private void evaluateAndAssertNotSelected(

private PendingTransaction createPendingTransaction(final long gasLimit) {
return PendingTransaction.newPendingTransaction(
createTransaction(TransactionType.EIP1559, gasLimit), false, false);
createTransaction(TransactionType.EIP1559, gasLimit), false, false, MAX_SCORE);
}

private Transaction createTransaction(final TransactionType type, final long gasLimit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
*/
public abstract class PendingTransaction
implements org.hyperledger.besu.datatypes.PendingTransaction {
static final int NOT_INITIALIZED = -1;
public static final Byte MAX_SCORE = Byte.MAX_VALUE;
private static final int NOT_INITIALIZED = -1;
private static final AtomicLong TRANSACTIONS_ADDED = new AtomicLong();
private final Transaction transaction;
private final long addedAt;
Expand All @@ -58,37 +59,42 @@ public abstract class PendingTransaction
private int memorySize = NOT_INITIALIZED;

private PendingTransaction(
final Transaction transaction, final long addedAt, final long sequence, final byte score) {
final Transaction transaction, final byte score, final long addedAt, final long sequence) {
this.transaction = transaction;
this.addedAt = addedAt;
this.sequence = sequence;
this.score = score;
}

private PendingTransaction(final Transaction transaction, final long addedAt) {
this(transaction, addedAt, TRANSACTIONS_ADDED.getAndIncrement(), Byte.MAX_VALUE);
private PendingTransaction(final Transaction transaction, final byte score, final long addedAt) {
this(transaction, score, addedAt, TRANSACTIONS_ADDED.getAndIncrement());
}

public static PendingTransaction newPendingTransaction(
final Transaction transaction, final boolean isLocal, final boolean hasPriority) {
return newPendingTransaction(transaction, isLocal, hasPriority, System.currentTimeMillis());
final Transaction transaction,
final boolean isLocal,
final boolean hasPriority,
final byte score) {
return newPendingTransaction(
transaction, isLocal, hasPriority, score, System.currentTimeMillis());
}

public static PendingTransaction newPendingTransaction(
final Transaction transaction,
final boolean isLocal,
final boolean hasPriority,
final byte score,
final long addedAt) {
if (isLocal) {
if (hasPriority) {
return new Local.Priority(transaction, addedAt);
return new Local.Priority(transaction, score, addedAt);
}
return new Local(transaction, addedAt);
return new Local(transaction, score, addedAt);
}
if (hasPriority) {
return new Remote.Priority(transaction, addedAt);
return new Remote.Priority(transaction, score, addedAt);
}
return new Remote(transaction, addedAt);
return new Remote(transaction, score, addedAt);
}

@Override
Expand Down Expand Up @@ -311,16 +317,16 @@ public String toTraceLog() {

public static class Local extends PendingTransaction {

public Local(final Transaction transaction, final long addedAt) {
super(transaction, addedAt);
public Local(final Transaction transaction, final byte score, final long addedAt) {
super(transaction, score, addedAt);
}

public Local(final Transaction transaction) {
this(transaction, System.currentTimeMillis());
this(transaction, MAX_SCORE, System.currentTimeMillis());
}

private Local(final long sequence, final byte score, final Transaction transaction) {
super(transaction, System.currentTimeMillis(), sequence, score);
super(transaction, score, System.currentTimeMillis(), sequence);
}

@Override
Expand All @@ -340,11 +346,11 @@ public boolean hasPriority() {

public static class Priority extends Local {
public Priority(final Transaction transaction) {
this(transaction, System.currentTimeMillis());
this(transaction, MAX_SCORE, System.currentTimeMillis());
}

public Priority(final Transaction transaction, final long addedAt) {
super(transaction, addedAt);
public Priority(final Transaction transaction, final byte score, final long addedAt) {
super(transaction, score, addedAt);
}

public Priority(final long sequence, final byte score, final Transaction transaction) {
Expand All @@ -365,16 +371,16 @@ public boolean hasPriority() {

public static class Remote extends PendingTransaction {

public Remote(final Transaction transaction, final long addedAt) {
super(transaction, addedAt);
public Remote(final Transaction transaction, final byte score, final long addedAt) {
super(transaction, score, addedAt);
}

public Remote(final Transaction transaction) {
this(transaction, System.currentTimeMillis());
this(transaction, MAX_SCORE, System.currentTimeMillis());
}

private Remote(final long sequence, final byte score, final Transaction transaction) {
super(transaction, System.currentTimeMillis(), sequence, score);
super(transaction, score, System.currentTimeMillis(), sequence);
}

@Override
Expand All @@ -394,11 +400,11 @@ public boolean hasPriority() {

public static class Priority extends Remote {
public Priority(final Transaction transaction) {
this(transaction, System.currentTimeMillis());
this(transaction, MAX_SCORE, System.currentTimeMillis());
}

public Priority(final Transaction transaction, final long addedAt) {
super(transaction, addedAt);
public Priority(final Transaction transaction, final byte score, final long addedAt) {
super(transaction, score, addedAt);
}

public Priority(final long sequence, final byte score, final Transaction transaction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.ethereum.eth.transactions;

import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_NOT_AVAILABLE;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.CHAIN_HEAD_WORLD_STATE_NOT_AVAILABLE;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INTERNAL_ERROR;
Expand Down Expand Up @@ -190,7 +191,7 @@ void handleConnect(final EthPeer peer) {
public ValidationResult<TransactionInvalidReason> addTransactionViaApi(
final Transaction transaction) {

final var result = addTransaction(transaction, true);
final var result = addTransaction(transaction, true, MAX_SCORE);
if (result.isValid()) {
localSenders.add(transaction.getSender());
transactionBroadcaster.onTransactionsAdded(List.of(transaction));
Expand All @@ -211,7 +212,7 @@ public Map<Hash, ValidationResult<TransactionInvalidReason>> addRemoteTransactio
Collectors.toMap(
Transaction::getHash,
transaction -> {
final var result = addTransaction(transaction, false);
final var result = addTransaction(transaction, false, MAX_SCORE);
if (result.isValid()) {
addedTransactions.add(transaction);
}
Expand Down Expand Up @@ -241,7 +242,7 @@ public Map<Hash, ValidationResult<TransactionInvalidReason>> addRemoteTransactio
}

private ValidationResult<TransactionInvalidReason> addTransaction(
final Transaction transaction, final boolean isLocal) {
final Transaction transaction, final boolean isLocal, final byte score) {

final boolean hasPriority = isPriorityTransaction(transaction, isLocal);

Expand All @@ -261,7 +262,7 @@ private ValidationResult<TransactionInvalidReason> addTransaction(
if (validationResult.result.isValid()) {
final TransactionAddedResult status =
pendingTransactions.addTransaction(
PendingTransaction.newPendingTransaction(transaction, isLocal, hasPriority),
PendingTransaction.newPendingTransaction(transaction, isLocal, hasPriority, score),
validationResult.maybeAccount);
if (status.isSuccess()) {
LOG.atTrace()
Expand Down Expand Up @@ -823,7 +824,8 @@ private void executeSaveToDisk(final PendingTransactions pendingTransactionsToSa
ptx -> {
final BytesValueRLPOutput rlp = new BytesValueRLPOutput();
ptx.getTransaction().writeTo(rlp);
return (ptx.isReceivedFromLocalSource() ? "l" : "r")
return ptx.getScore()
+ (ptx.isReceivedFromLocalSource() ? "l" : "r")
+ rlp.encoded().toBase64String();
})
.mapToInt(
Expand Down Expand Up @@ -870,12 +872,19 @@ private void executeLoadFromDisk() {
.takeWhile(unused -> !isCancelled.get())
.map(
line -> {
final boolean isLocal = line.charAt(0) == 'l';
int i = 0;
final var sbScore = new StringBuilder();
while ("1234567890-".indexOf(line.charAt(i)) >= 0) {
sbScore.append(line.charAt(i++));
}
final byte score =
sbScore.isEmpty() ? MAX_SCORE : Byte.parseByte(sbScore.toString());
final boolean isLocal = line.charAt(i) == 'l';
final Transaction tx =
Transaction.readFrom(Bytes.fromBase64String(line.substring(1)));
Transaction.readFrom(Bytes.fromBase64String(line.substring(i + 1)));

final ValidationResult<TransactionInvalidReason> result =
addTransaction(tx, isLocal);
addTransaction(tx, isLocal, score);
return result.isValid() ? "OK" : result.getInvalidReason().name();
})
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.TransactionTestFixture.createSignedCodeDelegation;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;

import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
Expand Down Expand Up @@ -253,7 +254,7 @@ protected PendingTransaction createRemotePendingTransaction(final Transaction tr

protected PendingTransaction createRemotePendingTransaction(
final Transaction transaction, final boolean hasPriority) {
return PendingTransaction.newPendingTransaction(transaction, false, hasPriority);
return PendingTransaction.newPendingTransaction(transaction, false, hasPriority, MAX_SCORE);
}

protected PendingTransaction createLocalPendingTransaction(final Transaction transaction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;
import static org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredRemovalReason.PoolRemovalReason.INVALIDATED;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
Expand Down Expand Up @@ -307,7 +308,7 @@ private void processTransaction(
}
assertThat(
pendingTransactions.addTransaction(
PendingTransaction.newPendingTransaction(tx, false, false),
PendingTransaction.newPendingTransaction(tx, false, false, MAX_SCORE),
Optional.of(mockAccount)))
.isNotEqualTo(TransactionAddedResult.INTERNAL_ERROR);
if (tx.getSender().equals(senderToLog)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.eth.transactions.sorter;

import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MAX_SCORE;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ADDED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.ALREADY_KNOWN;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionAddedResult.REJECTED_UNDERPRICED_REPLACEMENT;
Expand Down Expand Up @@ -762,15 +763,15 @@ protected Transaction createZeroGasPriceTransactionSender2(final long transactio

private PendingTransaction createRemotePendingTransaction(
final Transaction transaction, final long addedAt) {
return PendingTransaction.newPendingTransaction(transaction, false, false, addedAt);
return PendingTransaction.newPendingTransaction(transaction, false, false, MAX_SCORE, addedAt);
}

private PendingTransaction createRemotePendingTransaction(final Transaction transaction) {
return PendingTransaction.newPendingTransaction(transaction, false, false);
return PendingTransaction.newPendingTransaction(transaction, false, false, MAX_SCORE);
}

private PendingTransaction createLocalPendingTransaction(final Transaction transaction) {
return PendingTransaction.newPendingTransaction(transaction, true, true);
return PendingTransaction.newPendingTransaction(transaction, true, true, MAX_SCORE);
}

@Test
Expand Down

0 comments on commit bd10304

Please sign in to comment.