Support pending transaction score when saving and restoring txpool (#8363)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
This commit is contained in:
Fabio Di Fabio
2025-03-04 09:24:30 +01:00
committed by GitHub
parent a68b462ae5
commit 74a1d8a1ea
11 changed files with 364 additions and 45 deletions

View File

@@ -37,6 +37,7 @@
- Add TLS/mTLS options and configure the GraphQL HTTP service[#7910](https://github.com/hyperledger/besu/pull/7910)
- Update `eth_getLogs` to return a `Block not found` error when the requested block is not found. [#8290](https://github.com/hyperledger/besu/pull/8290)
- Change `Invalid block, unable to parse RLP` RPC error message to `Invalid block param (block not found)` [#8328](https://github.com/hyperledger/besu/pull/8328)
- Support pending transaction score when saving and restoring txpool [#8363](https://github.com/hyperledger/besu/pull/8363)
### Bug fixes
- Add missing RPC method `debug_accountRange` to `RpcMethod.java` so this method can be used with `--rpc-http-api-method-no-auth` [#8153](https://github.com/hyperledger/besu/issues/8153)

View File

@@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat;
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;
@@ -1080,7 +1081,8 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
.nonce(transactionNumber)
.createTransaction(KEYS1),
true,
true);
true,
MAX_SCORE);
}
private static BlockHeader mockBlockHeader() {

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.blockcreation.txselection.selectors;
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;
@@ -172,12 +173,12 @@ class BlobSizeTransactionSelectorTest {
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) {

View File

@@ -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;
@@ -247,7 +248,7 @@ class BlockSizeTransactionSelectorTest {
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) {

View File

@@ -48,7 +48,8 @@ import java.util.concurrent.atomic.AtomicLong;
*/
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;
@@ -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);
}
public static PendingTransaction newPendingTransaction(
final Transaction transaction, final boolean isLocal, final boolean hasPriority) {
return newPendingTransaction(transaction, isLocal, hasPriority, System.currentTimeMillis());
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,
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
@@ -311,16 +317,16 @@ public abstract class PendingTransaction
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
@@ -340,11 +346,11 @@ public abstract class PendingTransaction
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) {
@@ -365,16 +371,16 @@ public abstract class PendingTransaction
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
@@ -394,11 +400,11 @@ public abstract class PendingTransaction
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) {

View File

@@ -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;
@@ -32,6 +33,8 @@ import org.hyperledger.besu.ethereum.chain.BlockAddedObserver;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
@@ -190,7 +193,7 @@ public class TransactionPool implements BlockAddedObserver {
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));
@@ -211,7 +214,7 @@ public class TransactionPool implements BlockAddedObserver {
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);
}
@@ -241,7 +244,7 @@ public class TransactionPool implements BlockAddedObserver {
}
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);
@@ -261,7 +264,7 @@ public class TransactionPool implements BlockAddedObserver {
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()
@@ -822,8 +825,10 @@ public class TransactionPool implements BlockAddedObserver {
.map(
ptx -> {
final BytesValueRLPOutput rlp = new BytesValueRLPOutput();
ptx.getTransaction().writeTo(rlp);
return (ptx.isReceivedFromLocalSource() ? "l" : "r")
TransactionEncoder.encodeRLP(
ptx.getTransaction(), rlp, EncodingContext.POOLED_TRANSACTION);
return ptx.getScore()
+ (ptx.isReceivedFromLocalSource() ? "l" : "r")
+ rlp.encoded().toBase64String();
})
.mapToInt(
@@ -870,12 +875,16 @@ public class TransactionPool implements BlockAddedObserver {
.takeWhile(unused -> !isCancelled.get())
.map(
line -> {
final boolean isLocal = line.charAt(0) == 'l';
final var scoreStr = parseScore(line);
final byte score =
scoreStr.isEmpty() ? MAX_SCORE : Byte.parseByte(scoreStr);
final boolean isLocal = line.charAt(scoreStr.length()) == 'l';
final Transaction tx =
Transaction.readFrom(Bytes.fromBase64String(line.substring(1)));
Transaction.readFrom(
Bytes.fromBase64String(line.substring(scoreStr.length() + 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()));
@@ -909,6 +918,15 @@ public class TransactionPool implements BlockAddedObserver {
}
}
private String parseScore(final String line) {
int i = 0;
final var sbScore = new StringBuilder();
while ("1234567890-".indexOf(line.charAt(i)) >= 0) {
sbScore.append(line.charAt(i++));
}
return sbScore.toString();
}
private void removeProcessedLines(final File saveFile, final long processedLines)
throws IOException {

View File

@@ -386,6 +386,18 @@ public abstract class AbstractTransactionPoolTestBase {
.thenReturn(valid());
}
protected void givenAllTransactionsAreValid() {
when(transactionValidatorFactory
.get()
.validate(any(), any(Optional.class), any(Optional.class), any()))
.thenReturn(valid());
when(transactionValidatorFactory
.get()
.validateForSender(
any(), nullable(Account.class), any(TransactionValidationParams.class)))
.thenReturn(valid());
}
protected abstract Block appendBlock(
final Difficulty difficulty,
final BlockHeader parentBlock,

View File

@@ -0,0 +1,275 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.eth.transactions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
import org.hyperledger.besu.ethereum.core.MiningConfiguration;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.eth.transactions.layered.BaseFeePrioritizedTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.layered.EndLayer;
import org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredPendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.layered.ReadyTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.layered.SparseTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.layered.TransactionsLayer;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiFunction;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class TransactionPoolSaveRestoreTest extends AbstractTransactionPoolTestBase {
@TempDir static Path tempDir;
Path saveFilePath;
@BeforeEach
public void setup() {
saveFilePath = tempDir.resolve("txpool.dump");
}
@AfterEach
public void cleanup() {
saveFilePath.toFile().delete();
}
@Override
protected PendingTransactions createPendingTransactions(
final TransactionPoolConfiguration poolConfig,
final BiFunction<PendingTransaction, PendingTransaction, Boolean>
transactionReplacementTester) {
final var txPoolMetrics = new TransactionPoolMetrics(metricsSystem);
final TransactionsLayer sparseLayer =
new SparseTransactions(
poolConfig,
ethScheduler,
new EndLayer(txPoolMetrics),
txPoolMetrics,
transactionReplacementTester,
new BlobCache());
final TransactionsLayer readyLayer =
new ReadyTransactions(
poolConfig,
ethScheduler,
sparseLayer,
txPoolMetrics,
transactionReplacementTester,
new BlobCache());
return new LayeredPendingTransactions(
poolConfig,
new BaseFeePrioritizedTransactions(
poolConfig,
protocolContext.getBlockchain()::getChainHeadHeader,
ethScheduler,
readyLayer,
txPoolMetrics,
transactionReplacementTester,
FeeMarket.london(0L),
new BlobCache(),
MiningConfiguration.newDefault()),
ethScheduler);
}
@Override
protected ExecutionContextTestFixture createExecutionContextTestFixture() {
return createExecutionContextTestFixtureBaseFeeMarket();
}
@Override
protected FeeMarket getFeeMarket() {
return FeeMarket.london(0L, Optional.of(BASE_FEE_FLOOR));
}
@Override
protected Block appendBlock(
final Difficulty difficulty,
final BlockHeader parentBlock,
final Transaction... transactionsToAdd) {
return appendBlockBaseFeeMarket(difficulty, parentBlock, transactionsToAdd);
}
@Override
protected TransactionTestFixture createBaseTransaction(final int nonce) {
return createBaseTransactionBaseFeeMarket(nonce);
}
@Override
protected Transaction createTransaction(final int nonce, final Wei maxPrice) {
return createTransactionBaseFeeMarket(nonce, maxPrice);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void localTransactionIsSavedAndRestored(final boolean noLocalPriority)
throws ExecutionException, InterruptedException, TimeoutException, IOException {
// create a txpool with save and restore enabled
this.transactionPool =
createTransactionPool(
b ->
b.noLocalPriority(noLocalPriority)
.enableSaveRestore(true)
.saveFile(saveFilePath.toFile()));
final Transaction transaction = createTransaction(noLocalPriority ? 0 : 1);
givenTransactionIsValid(transaction);
addAndAssertTransactionViaApiValid(transaction, noLocalPriority);
// disabling the txpool, forces a save to file
transactionPool.setDisabled().get(10, TimeUnit.SECONDS);
// after being disabled the txpool must be empty
assertThat(transactionPool.getPendingTransactions()).isEmpty();
final var savedContent = Files.readString(saveFilePath, StandardCharsets.US_ASCII);
assertThat(savedContent).isEqualToIgnoringNewLines("127l" + transaction2Base64(transaction));
// re-enabling the txpool restores from file
transactionPool.setEnabled().get(10, TimeUnit.SECONDS);
assertThat(transactionPool.getPendingTransactions()).size().isEqualTo(1);
final var restoredPendingTx = transactionPool.getPendingTransactions().iterator().next();
assertThat(restoredPendingTx.getTransaction()).isEqualTo(transaction);
assertThat(restoredPendingTx.isReceivedFromLocalSource()).isTrue();
assertThat(restoredPendingTx.hasPriority()).isNotEqualTo(noLocalPriority);
}
@Test
public void remoteTransactionIsSavedAndRestored()
throws ExecutionException, InterruptedException, TimeoutException, IOException {
// create a txpool with save and restore enabled
this.transactionPool =
createTransactionPool(b -> b.enableSaveRestore(true).saveFile(saveFilePath.toFile()));
final Transaction transaction = createTransaction(2);
givenTransactionIsValid(transaction);
addAndAssertRemoteTransactionsValid(transaction);
// disabling the txpool, forces a save to file
transactionPool.setDisabled().get(10, TimeUnit.SECONDS);
// after being disabled the txpool must be empty
assertThat(transactionPool.getPendingTransactions()).isEmpty();
final var savedContent = Files.readString(saveFilePath, StandardCharsets.US_ASCII);
assertThat(savedContent).isEqualToIgnoringNewLines("127r" + transaction2Base64(transaction));
// re-enabling the txpool restores from file
transactionPool.setEnabled().get(10, TimeUnit.SECONDS);
assertThat(transactionPool.getPendingTransactions()).size().isEqualTo(1);
final var restoredPendingTx = transactionPool.getPendingTransactions().iterator().next();
assertThat(restoredPendingTx.getTransaction()).isEqualTo(transaction);
assertThat(restoredPendingTx.isReceivedFromLocalSource()).isFalse();
}
@Test
public void dumpFileWithoutScoreIsRestored() throws IOException {
// create a save file with one local and one remote tx, both without score
final var noScoreContent =
"""
luFoC+FcBgIID6IITiIcf////////gASAwAGga1337/7O7cp7jaMTu9X230+6mLJciebaO5nrsgDRp1CgA5MCvzfmS4H3NqF0DIxJGl8atRTkKmFwLMZgPpkVTqQ=
ruFoC+FcBgIID6IITiIcf////////gASAwAGglm0VMcNQmOS0aE5CJP1Lm7eBbFQIRvmwgUcfEka9sVagYWy/2d2tJHojo2smAIJgwLbud9Dr+f1lbxo1dSOBfmE=
""";
Files.writeString(saveFilePath, noScoreContent);
givenAllTransactionsAreValid();
// create a txpool with save and restore enabled
this.transactionPool =
createTransactionPool(b -> b.enableSaveRestore(true).saveFile(saveFilePath.toFile()));
await().until(() -> transactionPool.getPendingTransactions().size() == 2);
assertThat(transactionPool.getPendingTransactions())
.map(PendingTransaction::getScore)
.allMatch(score -> score == Byte.MAX_VALUE);
assertThat(transactionPool.getPendingTransactions())
.map(PendingTransaction::isReceivedFromLocalSource)
.filteredOn(Boolean::booleanValue)
.hasSize(1);
}
@Test
public void dumpFileWithLowestScoreTxIsRestored() throws IOException {
// create a save file with one remote tx with the lowest score
final var noScoreContent =
"""
-128ruFoC+FcBgIID6IITiIcf////////gASAwAGga1337/7O7cp7jaMTu9X230+6mLJciebaO5nrsgDRp1CgA5MCvzfmS4H3NqF0DIxJGl8atRTkKmFwLMZgPpkVTqQ=
""";
Files.writeString(saveFilePath, noScoreContent);
givenAllTransactionsAreValid();
// create a txpool with save and restore enabled
this.transactionPool =
createTransactionPool(b -> b.enableSaveRestore(true).saveFile(saveFilePath.toFile()));
await().until(() -> transactionPool.getPendingTransactions().size() == 1);
assertThat(transactionPool.getPendingTransactions())
.map(PendingTransaction::getScore)
.allMatch(score -> score == Byte.MIN_VALUE);
assertThat(transactionPool.getPendingTransactions())
.map(PendingTransaction::isReceivedFromLocalSource)
.first()
.isEqualTo(false);
}
private String transaction2Base64(final Transaction transaction) {
final BytesValueRLPOutput rlp = new BytesValueRLPOutput();
TransactionEncoder.encodeRLP(transaction, rlp, EncodingContext.POOLED_TRANSACTION);
return rlp.encoded().toBase64String();
}
}

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.eth.transactions.layered;
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;
@@ -253,7 +254,7 @@ public class BaseTransactionPoolTest {
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) {

View File

@@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.eth.transactions.layered;
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;
@@ -307,7 +308,7 @@ public class ReplayTest {
}
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)) {

View File

@@ -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;
@@ -762,15 +763,15 @@ public abstract class AbstractPendingTransactionsTestBase {
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