mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-08 21:38:15 -05:00
New option tx-pool-min-gas-price to set a lower bound when accepting txs to the pool (#6098)
Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
### Additions and Improvements
|
||||
- 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)
|
||||
|
||||
## 23.10.2
|
||||
|
||||
|
||||
@@ -2830,6 +2830,23 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
txPoolConfBuilder.priceBump(Percentage.ZERO);
|
||||
}
|
||||
|
||||
if (getMiningParameters().getMinTransactionGasPrice().lessThan(txPoolConf.getMinGasPrice())) {
|
||||
if (transactionPoolOptions.isMinGasPriceSet(commandLine)) {
|
||||
throw new ParameterException(
|
||||
commandLine, "tx-pool-min-gas-price cannot be greater than the value of min-gas-price");
|
||||
|
||||
} else {
|
||||
// for backward compatibility, if tx-pool-min-gas-price is not set, we adjust its value
|
||||
// to be the same as min-gas-price, so the behavior is as before this change, and we notify
|
||||
// the user of the change
|
||||
logger.warn(
|
||||
"Forcing tx-pool-min-gas-price="
|
||||
+ getMiningParameters().getMinTransactionGasPrice().toDecimalString()
|
||||
+ ", since it cannot be greater than the value of min-gas-price");
|
||||
txPoolConfBuilder.minGasPrice(getMiningParameters().getMinTransactionGasPrice());
|
||||
}
|
||||
}
|
||||
|
||||
return txPoolConfBuilder.build();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
private static final String STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG =
|
||||
"--strict-tx-replay-protection-enabled";
|
||||
private static final String TX_POOL_PRIORITY_SENDERS = "--tx-pool-priority-senders";
|
||||
private static final String TX_POOL_MIN_GAS_PRICE = "--tx-pool-min-gas-price";
|
||||
|
||||
@CommandLine.Option(
|
||||
names = {TX_POOL_IMPLEMENTATION},
|
||||
@@ -122,6 +123,15 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
arity = "1..*")
|
||||
private Set<Address> prioritySenders = TransactionPoolConfiguration.DEFAULT_PRIORITY_SENDERS;
|
||||
|
||||
@CommandLine.Option(
|
||||
names = {TX_POOL_MIN_GAS_PRICE},
|
||||
paramLabel = "<Wei>",
|
||||
description =
|
||||
"Transactions with gas price (in Wei) lower than this minimum will not be accepted into the txpool"
|
||||
+ "(not to be confused with min-gas-price, that is applied on block creation) (default: ${DEFAULT-VALUE})",
|
||||
arity = "1")
|
||||
private Wei minGasPrice = TransactionPoolConfiguration.DEFAULT_TX_POOL_MIN_GAS_PRICE;
|
||||
|
||||
@CommandLine.ArgGroup(
|
||||
validate = false,
|
||||
heading = "@|bold Tx Pool Layered Implementation Options|@%n")
|
||||
@@ -257,6 +267,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
options.saveFile = config.getSaveFile();
|
||||
options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled();
|
||||
options.prioritySenders = config.getPrioritySenders();
|
||||
options.minGasPrice = config.getMinGasPrice();
|
||||
options.layeredOptions.txPoolLayerMaxCapacity =
|
||||
config.getPendingTransactionsLayerMaxCapacityBytes();
|
||||
options.layeredOptions.txPoolMaxPrioritized = config.getMaxPrioritizedTransactions();
|
||||
@@ -312,6 +323,7 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
.saveFile(saveFile)
|
||||
.strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled)
|
||||
.prioritySenders(prioritySenders)
|
||||
.minGasPrice(minGasPrice)
|
||||
.pendingTransactionsLayerMaxCapacityBytes(layeredOptions.txPoolLayerMaxCapacity)
|
||||
.maxPrioritizedTransactions(layeredOptions.txPoolMaxPrioritized)
|
||||
.maxFutureBySender(layeredOptions.txPoolMaxFutureBySender)
|
||||
@@ -340,4 +352,14 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
|
||||
public boolean isPriceBumpSet(final CommandLine commandLine) {
|
||||
return CommandLineUtils.isOptionSet(commandLine, TransactionPoolOptions.TX_POOL_PRICE_BUMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is min gas price option set?
|
||||
*
|
||||
* @param commandLine the command line
|
||||
* @return true if tx-pool-min-gas-price is set
|
||||
*/
|
||||
public boolean isMinGasPriceSet(final CommandLine commandLine) {
|
||||
return CommandLineUtils.isOptionSet(commandLine, TransactionPoolOptions.TX_POOL_MIN_GAS_PRICE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -722,7 +722,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
|
||||
clock,
|
||||
metricsSystem,
|
||||
syncState,
|
||||
miningParameters,
|
||||
transactionPoolConfiguration,
|
||||
pluginTransactionValidatorFactory,
|
||||
besuComponent.map(BesuComponent::getBlobCache).orElse(new BlobCache()));
|
||||
|
||||
@@ -5248,6 +5248,31 @@ public class BesuCommandTest extends CommandTestAbstract {
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txpoolWhenNotSetForceTxPoolMinGasPriceToZeroWhenMinGasPriceZero() {
|
||||
parseCommand("--min-gas-price", "0");
|
||||
verify(mockControllerBuilder)
|
||||
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
|
||||
|
||||
final Wei txPoolMinGasPrice = transactionPoolConfigCaptor.getValue().getMinGasPrice();
|
||||
assertThat(txPoolMinGasPrice).isEqualTo(Wei.ZERO);
|
||||
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
verify(mockLogger, atLeast(1))
|
||||
.warn(
|
||||
contains(
|
||||
"Forcing tx-pool-min-gas-price=0, since it cannot be greater than the value of min-gas-price"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void txpoolTxPoolMinGasPriceMustNotBeGreaterThanMinGasPriceZero() {
|
||||
parseCommand("--min-gas-price", "100", "--tx-pool-min-gas-price", "101");
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains("tx-pool-min-gas-price cannot be greater than the value of min-gas-price");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void snapsyncHealingOptionShouldBeDisabledByDefault() {
|
||||
final TestBesuCommand besuCommand = parseCommand();
|
||||
|
||||
@@ -33,8 +33,6 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
|
||||
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters.MutableInitValues;
|
||||
import org.hyperledger.besu.ethereum.core.MutableWorldState;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
|
||||
@@ -147,7 +145,10 @@ public class BesuEventsImplTest {
|
||||
blockBroadcaster = new BlockBroadcaster(mockEthContext);
|
||||
syncState = new SyncState(blockchain, mockEthPeers);
|
||||
TransactionPoolConfiguration txPoolConfig =
|
||||
ImmutableTransactionPoolConfiguration.builder().txPoolMaxSize(1).build();
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(1)
|
||||
.minGasPrice(Wei.ZERO)
|
||||
.build();
|
||||
|
||||
transactionPool =
|
||||
TransactionPoolFactory.createTransactionPool(
|
||||
@@ -157,10 +158,6 @@ public class BesuEventsImplTest {
|
||||
TestClock.system(ZoneId.systemDefault()),
|
||||
new NoOpMetricsSystem(),
|
||||
syncState,
|
||||
ImmutableMiningParameters.builder()
|
||||
.mutableInitValues(
|
||||
MutableInitValues.builder().minTransactionGasPrice(Wei.ZERO).build())
|
||||
.build(),
|
||||
txPoolConfig,
|
||||
null,
|
||||
new BlobCache());
|
||||
|
||||
@@ -188,6 +188,7 @@ tx-pool-max-future-by-sender=321
|
||||
tx-pool-retention-hours=999
|
||||
tx-pool-max-size=1234
|
||||
tx-pool-limit-by-account-percentage=0.017
|
||||
tx-pool-min-gas-price=1000
|
||||
|
||||
# Revert Reason
|
||||
revert-reason-enabled=false
|
||||
|
||||
@@ -238,7 +238,6 @@ public class CliqueBlockCreatorTest {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
conf,
|
||||
null);
|
||||
|
||||
@@ -222,7 +222,6 @@ public class CliqueMinerExecutorTest {
|
||||
cliqueProtocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
cliqueEthContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
conf,
|
||||
null);
|
||||
|
||||
@@ -362,7 +362,6 @@ public class TestContextBuilder {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParams,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -146,7 +146,6 @@ public class BftBlockCreatorTest {
|
||||
protContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -227,7 +227,6 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -450,7 +450,6 @@ public class TestContextBuilder {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParams,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
@@ -119,7 +118,6 @@ public class EthGetFilterChangesIntegrationTest {
|
||||
protocolContext,
|
||||
batchAddedListener,
|
||||
ethContext,
|
||||
MiningParameters.newDefault(),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null);
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
@@ -119,7 +118,6 @@ public class EthGetFilterChangesIntegrationTest {
|
||||
protocolContext,
|
||||
batchAddedListener,
|
||||
ethContext,
|
||||
MiningParameters.newDefault(),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null);
|
||||
|
||||
@@ -383,7 +383,6 @@ abstract class AbstractBlockCreatorTest {
|
||||
executionContextTestFixture.getProtocolContext(),
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -181,7 +181,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
|
||||
protected abstract ProtocolSchedule createProtocolSchedule();
|
||||
|
||||
protected abstract TransactionPool createTransactionPool(final MiningParameters miningParameters);
|
||||
protected abstract TransactionPool createTransactionPool();
|
||||
|
||||
private Boolean isCancelled() {
|
||||
return false;
|
||||
@@ -1026,7 +1026,7 @@ public abstract class AbstractBlockTransactionSelectorTest {
|
||||
final Wei blobGasPrice,
|
||||
final PluginTransactionSelectorFactory transactionSelectorFactory) {
|
||||
|
||||
transactionPool = createTransactionPool(miningParameters);
|
||||
transactionPool = createTransactionPool();
|
||||
|
||||
return createBlockSelector(
|
||||
miningParameters,
|
||||
|
||||
@@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.config.GenesisConfigFile;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.datatypes.Wei;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
|
||||
@@ -62,11 +62,12 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionPool createTransactionPool(final MiningParameters miningParameters) {
|
||||
protected TransactionPool createTransactionPool() {
|
||||
final TransactionPoolConfiguration poolConf =
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(5)
|
||||
.txPoolLimitByAccountPercentage(Fraction.fromFloat(1f))
|
||||
.minGasPrice(Wei.ONE)
|
||||
.build();
|
||||
|
||||
final PendingTransactions pendingTransactions =
|
||||
@@ -86,7 +87,6 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -74,11 +74,12 @@ public class LondonFeeMarketBlockTransactionSelectorTest
|
||||
}
|
||||
|
||||
@Override
|
||||
protected TransactionPool createTransactionPool(final MiningParameters miningParameters) {
|
||||
protected TransactionPool createTransactionPool() {
|
||||
final TransactionPoolConfiguration poolConf =
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(5)
|
||||
.txPoolLimitByAccountPercentage(Fraction.fromFloat(1f))
|
||||
.minGasPrice(Wei.ONE)
|
||||
.build();
|
||||
final PendingTransactions pendingTransactions =
|
||||
new BaseFeePendingTransactionsSorter(
|
||||
@@ -94,7 +95,6 @@ public class LondonFeeMarketBlockTransactionSelectorTest
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -332,7 +332,6 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest {
|
||||
executionContextTestFixture.getProtocolContext(),
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -52,7 +52,7 @@ public class PoWMinerExecutorTest {
|
||||
public void startingMiningWithoutCoinbaseThrowsException() {
|
||||
final MiningParameters miningParameters = MiningParameters.newDefault();
|
||||
|
||||
final TransactionPool transactionPool = createTransactionPool(miningParameters);
|
||||
final TransactionPool transactionPool = createTransactionPool();
|
||||
|
||||
final PoWMinerExecutor executor =
|
||||
new PoWMinerExecutor(
|
||||
@@ -73,7 +73,7 @@ public class PoWMinerExecutorTest {
|
||||
public void settingCoinbaseToNullThrowsException() {
|
||||
final MiningParameters miningParameters = MiningParameters.newDefault();
|
||||
|
||||
final TransactionPool transactionPool = createTransactionPool(miningParameters);
|
||||
final TransactionPool transactionPool = createTransactionPool();
|
||||
|
||||
final PoWMinerExecutor executor =
|
||||
new PoWMinerExecutor(
|
||||
@@ -96,7 +96,7 @@ public class PoWMinerExecutorTest {
|
||||
return blockHeader;
|
||||
}
|
||||
|
||||
private TransactionPool createTransactionPool(final MiningParameters miningParameters) {
|
||||
private TransactionPool createTransactionPool() {
|
||||
final TransactionPoolConfiguration poolConf =
|
||||
ImmutableTransactionPoolConfiguration.builder().txPoolMaxSize(1).build();
|
||||
final GasPricePendingTransactionsSorter pendingTransactions =
|
||||
@@ -116,7 +116,6 @@ public class PoWMinerExecutorTest {
|
||||
mock(ProtocolContext.class),
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
poolConf,
|
||||
null);
|
||||
|
||||
@@ -170,7 +170,6 @@ public abstract class AbstractIsolationTests {
|
||||
protocolContext,
|
||||
mock(TransactionBroadcaster.class),
|
||||
ethContext,
|
||||
mock(MiningParameters.class),
|
||||
txPoolMetrics,
|
||||
poolConfiguration,
|
||||
null);
|
||||
|
||||
@@ -28,7 +28,6 @@ import org.hyperledger.besu.ethereum.chain.BlockAddedEvent;
|
||||
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.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthPeer;
|
||||
@@ -100,7 +99,6 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
private final ProtocolContext protocolContext;
|
||||
private final EthContext ethContext;
|
||||
private final TransactionBroadcaster transactionBroadcaster;
|
||||
private final MiningParameters miningParameters;
|
||||
private final TransactionPoolMetrics metrics;
|
||||
private final TransactionPoolConfiguration configuration;
|
||||
private final AtomicBoolean isPoolEnabled = new AtomicBoolean(false);
|
||||
@@ -118,7 +116,6 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
final ProtocolContext protocolContext,
|
||||
final TransactionBroadcaster transactionBroadcaster,
|
||||
final EthContext ethContext,
|
||||
final MiningParameters miningParameters,
|
||||
final TransactionPoolMetrics metrics,
|
||||
final TransactionPoolConfiguration configuration,
|
||||
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory) {
|
||||
@@ -127,7 +124,6 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
this.protocolContext = protocolContext;
|
||||
this.ethContext = ethContext;
|
||||
this.transactionBroadcaster = transactionBroadcaster;
|
||||
this.miningParameters = miningParameters;
|
||||
this.metrics = metrics;
|
||||
this.configuration = configuration;
|
||||
this.pluginTransactionValidator =
|
||||
@@ -289,7 +285,7 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
|
||||
private boolean isMaxGasPriceBelowConfiguredMinGasPrice(final Transaction transaction) {
|
||||
return getMaxGasPrice(transaction)
|
||||
.map(g -> g.lessThan(miningParameters.getMinTransactionGasPrice()))
|
||||
.map(g -> g.lessThan(configuration.getMinGasPrice()))
|
||||
.orElse(true);
|
||||
}
|
||||
|
||||
@@ -510,11 +506,9 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
}
|
||||
}
|
||||
if (hasPriority) {
|
||||
// allow priority transactions to be below minGas as long as we are mining
|
||||
// or at least gas price is above the configured floor
|
||||
if ((!miningParameters.isMiningEnabled()
|
||||
&& isMaxGasPriceBelowConfiguredMinGasPrice(transaction))
|
||||
|| !feeMarket.satisfiesFloorTxFee(transaction)) {
|
||||
// allow priority transactions to be below minGas as long as the gas price is above the
|
||||
// configured floor
|
||||
if (!feeMarket.satisfiesFloorTxFee(transaction)) {
|
||||
return TransactionInvalidReason.GAS_PRICE_TOO_LOW;
|
||||
}
|
||||
} else {
|
||||
@@ -522,7 +516,7 @@ public class TransactionPool implements BlockAddedObserver {
|
||||
LOG.atTrace()
|
||||
.setMessage("Discard transaction {} below min gas price {}")
|
||||
.addArgument(transaction::toTraceLog)
|
||||
.addArgument(miningParameters::getMinTransactionGasPrice)
|
||||
.addArgument(configuration::getMinGasPrice)
|
||||
.log();
|
||||
return TransactionInvalidReason.GAS_PRICE_TOO_LOW;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public interface TransactionPoolConfiguration {
|
||||
int DEFAULT_MAX_FUTURE_BY_SENDER = 200;
|
||||
Implementation DEFAULT_TX_POOL_IMPLEMENTATION = Implementation.LAYERED;
|
||||
Set<Address> DEFAULT_PRIORITY_SENDERS = Set.of();
|
||||
Wei DEFAULT_TX_POOL_MIN_GAS_PRICE = Wei.of(1000);
|
||||
|
||||
TransactionPoolConfiguration DEFAULT = ImmutableTransactionPoolConfiguration.builder().build();
|
||||
|
||||
@@ -147,6 +148,11 @@ public interface TransactionPoolConfiguration {
|
||||
return DEFAULT_PRIORITY_SENDERS;
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
default Wei getMinGasPrice() {
|
||||
return DEFAULT_TX_POOL_MIN_GAS_PRICE;
|
||||
}
|
||||
|
||||
@Value.Default
|
||||
default Unstable getUnstable() {
|
||||
return Unstable.DEFAULT;
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.hyperledger.besu.ethereum.eth.transactions;
|
||||
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LAYERED;
|
||||
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
import org.hyperledger.besu.ethereum.eth.messages.EthPV62;
|
||||
import org.hyperledger.besu.ethereum.eth.messages.EthPV65;
|
||||
@@ -54,7 +53,6 @@ public class TransactionPoolFactory {
|
||||
final Clock clock,
|
||||
final MetricsSystem metricsSystem,
|
||||
final SyncState syncState,
|
||||
final MiningParameters miningParameters,
|
||||
final TransactionPoolConfiguration transactionPoolConfiguration,
|
||||
final PluginTransactionValidatorFactory pluginTransactionValidatorFactory,
|
||||
final BlobCache blobCache) {
|
||||
@@ -75,7 +73,6 @@ public class TransactionPoolFactory {
|
||||
clock,
|
||||
metrics,
|
||||
syncState,
|
||||
miningParameters,
|
||||
transactionPoolConfiguration,
|
||||
transactionTracker,
|
||||
transactionsMessageSender,
|
||||
@@ -91,7 +88,6 @@ public class TransactionPoolFactory {
|
||||
final Clock clock,
|
||||
final TransactionPoolMetrics metrics,
|
||||
final SyncState syncState,
|
||||
final MiningParameters miningParameters,
|
||||
final TransactionPoolConfiguration transactionPoolConfiguration,
|
||||
final PeerTransactionTracker transactionTracker,
|
||||
final TransactionsMessageSender transactionsMessageSender,
|
||||
@@ -117,7 +113,6 @@ public class TransactionPoolFactory {
|
||||
transactionsMessageSender,
|
||||
newPooledTransactionHashesMessageSender),
|
||||
ethContext,
|
||||
miningParameters,
|
||||
metrics,
|
||||
transactionPoolConfiguration,
|
||||
pluginTransactionValidatorFactory);
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeader;
|
||||
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
@@ -1117,7 +1116,6 @@ public final class EthProtocolManagerTest {
|
||||
TestClock.system(ZoneId.systemDefault()),
|
||||
metricsSystem,
|
||||
new SyncState(blockchain, ethManager.ethContext().getEthPeers()),
|
||||
MiningParameters.newDefault(),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null,
|
||||
new BlobCache())
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.hyperledger.besu.datatypes.Hash;
|
||||
import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.EthProtocol;
|
||||
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
@@ -136,7 +135,6 @@ public abstract class AbstractMessageTaskTest<T, R> {
|
||||
TestClock.system(ZoneId.systemDefault()),
|
||||
metricsSystem,
|
||||
syncState,
|
||||
MiningParameters.newDefault(),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null,
|
||||
new BlobCache());
|
||||
|
||||
@@ -60,7 +60,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.Difficulty;
|
||||
import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
|
||||
@@ -102,6 +101,7 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -110,6 +110,8 @@ import org.junit.jupiter.api.condition.EnabledIf;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
@@ -133,9 +135,6 @@ public abstract class AbstractTransactionPoolTest {
|
||||
|
||||
@Mock protected PendingTransactionAddedListener listener;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
protected MiningParameters miningParameters;
|
||||
|
||||
@Mock protected TransactionsMessageSender transactionsMessageSender;
|
||||
@Mock protected NewPooledTransactionHashesMessageSender newPooledTransactionHashesMessageSender;
|
||||
@Mock protected ProtocolSpec protocolSpec;
|
||||
@@ -253,11 +252,10 @@ public abstract class AbstractTransactionPoolTest {
|
||||
|
||||
transactionPool = createTransactionPool();
|
||||
blockchain.observeBlockAdded(transactionPool);
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.of(2));
|
||||
}
|
||||
|
||||
protected TransactionPool createTransactionPool() {
|
||||
return createTransactionPool(b -> {});
|
||||
return createTransactionPool(b -> b.minGasPrice(Wei.of(2)));
|
||||
}
|
||||
|
||||
protected TransactionPool createTransactionPool(
|
||||
@@ -290,7 +288,6 @@ public abstract class AbstractTransactionPoolTest {
|
||||
protocolContext,
|
||||
transactionBroadcaster,
|
||||
ethContext,
|
||||
miningParameters,
|
||||
new TransactionPoolMetrics(metricsSystem),
|
||||
poolConfig,
|
||||
pluginTransactionValidatorFactory);
|
||||
@@ -625,7 +622,8 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldNotNotifyBatchListenerWhenLocalTransactionDoesNotReplaceExisting(
|
||||
final boolean noLocalPriority) {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(noLocalPriority));
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.minGasPrice(Wei.of(2)).noLocalPriority(noLocalPriority));
|
||||
final Transaction transaction0a = createTransaction(0, Wei.of(10));
|
||||
final Transaction transaction0b = createTransaction(0, Wei.of(9));
|
||||
|
||||
@@ -792,58 +790,6 @@ public abstract class AbstractTransactionPoolTest {
|
||||
addAndAssertRemoteTransactionsValid(hasPriority, remoteTransaction);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldRejectZeroGasPriceLocalTransactionWhenNotMining(final boolean noLocalPriority) {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.isMiningEnabled()).thenReturn(false);
|
||||
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
addAndAssertTransactionViaApiInvalid(transaction, GAS_PRICE_TOO_LOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIf("isBaseFeeMarket")
|
||||
public void shouldAcceptZeroGasPriceFrontierLocalPriorityTransactionsWhenMining() {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(false));
|
||||
when(miningParameters.isMiningEnabled()).thenReturn(true);
|
||||
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
addAndAssertTransactionViaApiValid(transaction, false);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldRejectZeroGasPriceRemoteTransactionWhenNotMining(final boolean hasPriority) {
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
final Set<Address> prioritySenders = hasPriority ? Set.of(transaction.getSender()) : Set.of();
|
||||
transactionPool = createTransactionPool(b -> b.prioritySenders(prioritySenders));
|
||||
when(miningParameters.isMiningEnabled()).thenReturn(false);
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
addAndAssertRemoteTransactionInvalid(transaction);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledIf("isBaseFeeMarket")
|
||||
public void shouldAcceptZeroGasPriceFrontierRemotePriorityTransactionsWhenMining() {
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.prioritySenders(Set.of(transaction.getSender())));
|
||||
when(miningParameters.isMiningEnabled()).thenReturn(true);
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
addAndAssertRemoteTransactionsValid(true, transaction);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void transactionNotRejectedByPluginShouldBeAdded(final boolean noLocalPriority) {
|
||||
@@ -998,54 +944,104 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
@DisabledIf("isBaseFeeMarket")
|
||||
public void shouldAcceptZeroGasPriceTransactionWhenMinGasPriceIsZero(
|
||||
final boolean noLocalPriority) {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
public void shouldAcceptZeroGasPriceFrontierPriorityTransactions(final boolean isLocal) {
|
||||
final Transaction transaction = createFrontierTransaction(0, Wei.ZERO);
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.prioritySenders(List.of(transaction.getSender())));
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
if (isLocal) {
|
||||
addAndAssertTransactionViaApiValid(transaction, false);
|
||||
} else {
|
||||
addAndAssertRemoteTransactionsValid(true, transaction);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldRejectZeroGasPriceNoPriorityTransaction(final boolean isLocal) {
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(true));
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
if (isLocal) {
|
||||
addAndAssertTransactionViaApiInvalid(transaction, GAS_PRICE_TOO_LOW);
|
||||
} else {
|
||||
addAndAssertRemoteTransactionInvalid(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
@DisabledIf("isBaseFeeMarket")
|
||||
public void shouldAcceptZeroGasPriceNoPriorityTransactionWhenMinGasPriceIsZero(
|
||||
final boolean isLocal) {
|
||||
transactionPool = createTransactionPool(b -> b.minGasPrice(Wei.ZERO).noLocalPriority(true));
|
||||
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
addAndAssertTransactionViaApiValid(transaction, noLocalPriority);
|
||||
if (isLocal) {
|
||||
addAndAssertTransactionViaApiValid(transaction, true);
|
||||
} else {
|
||||
addAndAssertRemoteTransactionsValid(false, transaction);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
@MethodSource("provideHasPriorityAndIsLocal")
|
||||
public void shouldAcceptZeroGasPriceFrontierTxsWhenMinGasPriceIsZeroAndLondonWithZeroBaseFee(
|
||||
final boolean noLocalPriority) {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0, Optional.of(Wei.ZERO)));
|
||||
whenBlockBaseFeeIs(Wei.ZERO);
|
||||
|
||||
final boolean hasPriority, final boolean isLocal) {
|
||||
final Transaction frontierTransaction = createFrontierTransaction(0, Wei.ZERO);
|
||||
|
||||
givenTransactionIsValid(frontierTransaction);
|
||||
addAndAssertTransactionViaApiValid(frontierTransaction, noLocalPriority);
|
||||
internalAcceptZeroGasPriceTxsWhenMinGasPriceIsZeroAndZeroBaseFee(
|
||||
hasPriority, isLocal, frontierTransaction);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
@MethodSource("provideHasPriorityAndIsLocal")
|
||||
public void shouldAcceptZeroGasPrice1559TxsWhenMinGasPriceIsZeroAndLondonWithZeroBaseFee(
|
||||
final boolean noLocalPriority) {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
final boolean hasPriority, final boolean isLocal) {
|
||||
final Transaction transaction = createTransactionBaseFeeMarket(0, Wei.ZERO);
|
||||
internalAcceptZeroGasPriceTxsWhenMinGasPriceIsZeroAndZeroBaseFee(
|
||||
hasPriority, isLocal, transaction);
|
||||
}
|
||||
|
||||
private void internalAcceptZeroGasPriceTxsWhenMinGasPriceIsZeroAndZeroBaseFee(
|
||||
final boolean hasPriority, final boolean isLocal, final Transaction transaction) {
|
||||
transactionPool =
|
||||
createTransactionPool(
|
||||
b -> {
|
||||
b.minGasPrice(Wei.ZERO);
|
||||
if (hasPriority) {
|
||||
b.prioritySenders(List.of(transaction.getSender()));
|
||||
} else {
|
||||
b.noLocalPriority(true);
|
||||
}
|
||||
});
|
||||
|
||||
when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0, Optional.of(Wei.ZERO)));
|
||||
whenBlockBaseFeeIs(Wei.ZERO);
|
||||
|
||||
final Transaction transaction = createTransaction(0, Wei.ZERO);
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
addAndAssertTransactionViaApiValid(transaction, noLocalPriority);
|
||||
if (isLocal) {
|
||||
addAndAssertTransactionViaApiValid(transaction, !hasPriority);
|
||||
} else {
|
||||
addAndAssertRemoteTransactionsValid(hasPriority, transaction);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void samePriceTxReplacementWhenPriceBumpIsZeroFrontier(final boolean noLocalPriority) {
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.priceBump(Percentage.ZERO).noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
createTransactionPool(
|
||||
b ->
|
||||
b.priceBump(Percentage.ZERO)
|
||||
.noLocalPriority(noLocalPriority)
|
||||
.minGasPrice(Wei.ZERO));
|
||||
|
||||
final Transaction transaction1a =
|
||||
createBaseTransactionGasPriceMarket(0)
|
||||
@@ -1081,8 +1077,11 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@EnabledIf("isBaseFeeMarket")
|
||||
public void replaceSamePriceTxWhenPriceBumpIsZeroLondon(final boolean noLocalPriority) {
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.priceBump(Percentage.ZERO).noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
createTransactionPool(
|
||||
b ->
|
||||
b.priceBump(Percentage.ZERO)
|
||||
.noLocalPriority(noLocalPriority)
|
||||
.minGasPrice(Wei.ZERO));
|
||||
|
||||
final Transaction transaction1a =
|
||||
createBaseTransactionBaseFeeMarket(0)
|
||||
@@ -1120,8 +1119,11 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@EnabledIf("isBaseFeeMarket")
|
||||
public void replaceSamePriceTxWhenPriceBumpIsZeroLondonToFrontier(final boolean noLocalPriority) {
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.priceBump(Percentage.ZERO).noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
createTransactionPool(
|
||||
b ->
|
||||
b.priceBump(Percentage.ZERO)
|
||||
.noLocalPriority(noLocalPriority)
|
||||
.minGasPrice(Wei.ZERO));
|
||||
|
||||
final Transaction transaction1a =
|
||||
createBaseTransactionBaseFeeMarket(0)
|
||||
@@ -1158,8 +1160,11 @@ public abstract class AbstractTransactionPoolTest {
|
||||
@EnabledIf("isBaseFeeMarket")
|
||||
public void replaceSamePriceTxWhenPriceBumpIsZeroFrontierToLondon(final boolean noLocalPriority) {
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.priceBump(Percentage.ZERO).noLocalPriority(noLocalPriority));
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(Wei.ZERO);
|
||||
createTransactionPool(
|
||||
b ->
|
||||
b.priceBump(Percentage.ZERO)
|
||||
.noLocalPriority(noLocalPriority)
|
||||
.minGasPrice(Wei.ZERO));
|
||||
|
||||
final Transaction transaction1a =
|
||||
createBaseTransactionGasPriceMarket(0)
|
||||
@@ -1191,79 +1196,56 @@ public abstract class AbstractTransactionPoolTest {
|
||||
.containsOnly(transaction1b);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptBaseFeeFloorGasPriceFrontierLocalPriorityTransactionsWhenMining() {
|
||||
transactionPool = createTransactionPool(b -> b.noLocalPriority(false));
|
||||
final Transaction frontierTransaction = createFrontierTransaction(0, BASE_FEE_FLOOR);
|
||||
|
||||
givenTransactionIsValid(frontierTransaction);
|
||||
|
||||
addAndAssertTransactionViaApiValid(frontierTransaction, false);
|
||||
private static Stream<Arguments> provideHasPriorityAndIsLocal() {
|
||||
return Stream.of(
|
||||
Arguments.of(true, true),
|
||||
Arguments.of(true, false),
|
||||
Arguments.of(false, true),
|
||||
Arguments.of(false, false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptBaseFeeFloorGasPriceFrontierRemotePriorityTransactionsWhenMining() {
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldAcceptBaseFeeFloorGasPriceFrontierPriorityTransactions(final boolean isLocal) {
|
||||
final Transaction frontierTransaction = createFrontierTransaction(0, BASE_FEE_FLOOR);
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.prioritySenders(Set.of(frontierTransaction.getSender())));
|
||||
createTransactionPool(b -> b.prioritySenders(List.of(frontierTransaction.getSender())));
|
||||
|
||||
givenTransactionIsValid(frontierTransaction);
|
||||
|
||||
addAndAssertRemoteTransactionsValid(frontierTransaction);
|
||||
if (isLocal) {
|
||||
addAndAssertTransactionViaApiValid(frontierTransaction, false);
|
||||
} else {
|
||||
addAndAssertRemoteTransactionsValid(true, frontierTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldRejectRemote1559TxsWhenMaxFeePerGasBelowMinGasPrice(final boolean hasPriority) {
|
||||
public void shouldRejectNoPriorityTxsWhenMaxFeePerGasBelowMinGasPrice(final boolean isLocal) {
|
||||
final Wei genesisBaseFee = Wei.of(100L);
|
||||
final Wei minGasPrice = Wei.of(200L);
|
||||
final Wei lastBlockBaseFee = minGasPrice.add(50L);
|
||||
final Wei txMaxFeePerGas = minGasPrice.subtract(1L);
|
||||
|
||||
assertThat(
|
||||
add1559TxAndGetPendingTxsCount(
|
||||
genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, false, hasPriority))
|
||||
addTxAndGetPendingTxsCount(
|
||||
genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, isLocal, false))
|
||||
.isZero();
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(booleans = {true, false})
|
||||
public void shouldAcceptRemote1559TxsWhenMaxFeePerGasIsAtLeastEqualToMinGasPrice(
|
||||
final boolean hasPriority) {
|
||||
public void shouldAcceptNoPriorityTxsWhenMaxFeePerGasIsAtLeastEqualToMinGasPrice(
|
||||
final boolean isLocal) {
|
||||
final Wei genesisBaseFee = Wei.of(100L);
|
||||
final Wei minGasPrice = Wei.of(200L);
|
||||
final Wei lastBlockBaseFee = minGasPrice.add(50L);
|
||||
final Wei txMaxFeePerGas = minGasPrice;
|
||||
|
||||
assertThat(
|
||||
add1559TxAndGetPendingTxsCount(
|
||||
genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, false, hasPriority))
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRejectLocal1559TxsWhenMaxFeePerGasBelowMinGasPrice() {
|
||||
final Wei genesisBaseFee = Wei.of(100L);
|
||||
final Wei minGasPrice = Wei.of(200L);
|
||||
final Wei lastBlockBaseFee = minGasPrice.add(50L);
|
||||
final Wei txMaxFeePerGas = minGasPrice.subtract(1L);
|
||||
|
||||
assertThat(
|
||||
add1559TxAndGetPendingTxsCount(
|
||||
genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, true, true))
|
||||
.isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAcceptLocal1559TxsWhenMaxFeePerGasIsAtLeastEqualToMinMinGasPrice() {
|
||||
final Wei genesisBaseFee = Wei.of(100L);
|
||||
final Wei minGasPrice = Wei.of(200L);
|
||||
final Wei lastBlockBaseFee = minGasPrice.add(50L);
|
||||
final Wei txMaxFeePerGas = minGasPrice;
|
||||
|
||||
assertThat(
|
||||
add1559TxAndGetPendingTxsCount(
|
||||
genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, true, true))
|
||||
addTxAndGetPendingTxsCount(
|
||||
genesisBaseFee, minGasPrice, lastBlockBaseFee, txMaxFeePerGas, isLocal, false))
|
||||
.isEqualTo(1);
|
||||
}
|
||||
|
||||
@@ -1470,22 +1452,26 @@ public abstract class AbstractTransactionPoolTest {
|
||||
.createTransaction(KEY_PAIR1);
|
||||
}
|
||||
|
||||
protected int add1559TxAndGetPendingTxsCount(
|
||||
protected int addTxAndGetPendingTxsCount(
|
||||
final Wei genesisBaseFee,
|
||||
final Wei minGasPrice,
|
||||
final Wei lastBlockBaseFee,
|
||||
final Wei txMaxFeePerGas,
|
||||
final boolean isLocal,
|
||||
final boolean hasPriority) {
|
||||
when(miningParameters.getMinTransactionGasPrice()).thenReturn(minGasPrice);
|
||||
when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0, Optional.of(genesisBaseFee)));
|
||||
whenBlockBaseFeeIs(lastBlockBaseFee);
|
||||
|
||||
final Transaction transaction = createTransaction(0, txMaxFeePerGas);
|
||||
if (hasPriority) {
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.prioritySenders(Set.of(transaction.getSender())));
|
||||
createTransactionPool(
|
||||
b -> b.minGasPrice(minGasPrice).prioritySenders(Set.of(transaction.getSender())));
|
||||
} else {
|
||||
transactionPool =
|
||||
createTransactionPool(b -> b.minGasPrice(minGasPrice).noLocalPriority(true));
|
||||
}
|
||||
|
||||
givenTransactionIsValid(transaction);
|
||||
|
||||
if (isLocal) {
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.chain.GenesisState;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions;
|
||||
import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.Transaction;
|
||||
import org.hyperledger.besu.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule;
|
||||
import org.hyperledger.besu.ethereum.eth.EthProtocol;
|
||||
@@ -162,7 +161,6 @@ public class TestNode implements Closeable {
|
||||
TestClock.system(ZoneId.systemDefault()),
|
||||
metricsSystem,
|
||||
syncState,
|
||||
MiningParameters.newDefault(),
|
||||
TransactionPoolConfiguration.DEFAULT,
|
||||
null,
|
||||
new BlobCache());
|
||||
|
||||
@@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
|
||||
import org.hyperledger.besu.ethereum.chain.BlockAddedObserver;
|
||||
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
|
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
|
||||
import org.hyperledger.besu.ethereum.core.MiningParameters;
|
||||
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
|
||||
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
|
||||
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
|
||||
@@ -240,7 +239,6 @@ public class TransactionPoolFactoryTest {
|
||||
TestClock.fixed(),
|
||||
new TransactionPoolMetrics(new NoOpMetricsSystem()),
|
||||
syncState,
|
||||
MiningParameters.newDefault(),
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolMaxSize(1)
|
||||
.pendingTxRetentionPeriod(1)
|
||||
@@ -350,7 +348,6 @@ public class TransactionPoolFactoryTest {
|
||||
TestClock.fixed(),
|
||||
new NoOpMetricsSystem(),
|
||||
syncState,
|
||||
MiningParameters.newDefault(),
|
||||
ImmutableTransactionPoolConfiguration.builder()
|
||||
.txPoolImplementation(implementation)
|
||||
.txPoolMaxSize(1)
|
||||
|
||||
@@ -251,7 +251,6 @@ public class RetestethContext {
|
||||
retestethClock,
|
||||
metricsSystem,
|
||||
syncState,
|
||||
miningParameters,
|
||||
transactionPoolConfiguration,
|
||||
null,
|
||||
new BlobCache());
|
||||
|
||||
Reference in New Issue
Block a user