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

Priority senders #5959

Merged
merged 36 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
17220d8
Improve performance when promoting transaction from next layers
fab-10 Sep 13, 2023
80a0845
Always enforce promotion filter for transactions in the prioritized l…
fab-10 Sep 12, 2023
919734e
Fix typo
fab-10 Sep 22, 2023
0b4bfa9
Apply suggestions from code review
fab-10 Sep 26, 2023
b4e74e9
implement code review suggestions
fab-10 Sep 26, 2023
0b72427
Merge branch 'main' into txpool-promotion-performance
fab-10 Sep 26, 2023
b393618
Add priority senders option
fab-10 Sep 25, 2023
c3e1fd8
Merge branch 'main' into txpool-promotion-performance
fab-10 Sep 26, 2023
fa50005
Merge branch 'txpool-promotion-performance' into prioritized-promotio…
fab-10 Sep 26, 2023
4d5e015
Merge branch 'prioritized-promotion-filter2' into priority-senders
fab-10 Sep 26, 2023
f4e04a2
Transaction pool unit tests refactoring to remove duplications
fab-10 Sep 26, 2023
8b45df7
Merge branch 'txpool-test-refactor' into priority-senders
fab-10 Sep 26, 2023
8a612b9
Merge branch 'main' into priority-senders
fab-10 Sep 27, 2023
e6d2761
Use a Set for priority senders and remove commented code
fab-10 Sep 27, 2023
185dcc6
use hasPriority instead of isLocalSender when selecting txs for block…
fab-10 Sep 27, 2023
b36a09d
Rename disable-locals to no-local-priority and unit tests
fab-10 Sep 27, 2023
3506f63
Sort transactions by priority
fab-10 Sep 27, 2023
712b2c0
Merge branch 'main' into priority-senders
fab-10 Sep 28, 2023
542ef6f
[skip-ci] Add tests
fab-10 Sep 28, 2023
33c0ded
Discard priority sender at last and more tests
fab-10 Sep 28, 2023
bbaa4d8
Merge branch 'main' into priority-senders
fab-10 Sep 28, 2023
ff1944c
Update CHANGELOG
fab-10 Sep 28, 2023
bb9c972
Merge branch 'main' into priority-senders
fab-10 Oct 2, 2023
66a5f03
Update ReplayTest and txpool metrics for priority senders
fab-10 Oct 2, 2023
f7d98a4
Merge branch 'main' into priority-senders
fab-10 Oct 5, 2023
3b0d49b
Merge branch 'main' into priority-senders
fab-10 Oct 12, 2023
f1b7111
Update CHANGELOG
fab-10 Oct 12, 2023
2d0e09c
Add detachedCopy to priority pending transaction
fab-10 Oct 12, 2023
a44a7bb
Apply suggestions from code review
fab-10 Oct 16, 2023
09f3738
Merge branch 'main' into priority-senders
fab-10 Oct 16, 2023
e4f5ac4
Merge branch 'priority-senders' of github.com:fab-10/besu into priori…
fab-10 Oct 16, 2023
0faf055
Fix tests
fab-10 Oct 16, 2023
a1466b8
Merge branch 'main' into priority-senders
fab-10 Oct 17, 2023
1b785d0
Spotless
fab-10 Oct 17, 2023
2257731
[skip-ci] Update CHANGELOG.md
fab-10 Oct 17, 2023
f4254e5
Merge branch 'main' into priority-senders
fab-10 Oct 17, 2023
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
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@

### Breaking Changes

### Deprecations
- `--tx-pool-disable-locals` has been deprecated for removal in favor of `--tx-pool-no-local-priority`, no semantic change, only a renaming [#5959](https://github.com/hyperledger/besu/pull/5959)

### Additions and Improvements
- New option `--tx-pool-priority-senders` to specify a list of senders, that has the effect to prioritize any transactions sent by these senders from any source [#5959](https://github.com/hyperledger/besu/pull/5959)

### Bug Fixes

Expand Down Expand Up @@ -46,7 +50,7 @@ By default, the txpool is tuned for mainnet usage, but if you are using private
- Layered transaction pool implementation is now stable and enabled by default. If you want still to use the legacy implementation, use `--tx-pool=legacy`.
By default, the new transaction pool is capped at using 25MB of memory, this limit can be raised using `--layered-tx-pool-layer-max-capacity` options [#5772](https://github.com/hyperledger/besu/pull/5772)
- Tune G1GC to reduce Besu memory footprint, and new `besu-untuned` start scripts to run without any specific G1GC flags [#5879](https://github.com/hyperledger/besu/pull/5879)
- Reduce `engine_forkchoiceUpdatedV?` response time by asynchronously process block added events in the transaction pool [#5909](https://github.com/hyperledger/besu/pull/5909)
- Reduce `engine_forkchoiceUpdatedV?` response time by asynchronously process block added events in the transaction pool [#5909](https://github.com/hyperledger/besu/pull/5909)

### Bug Fixes
- do not create ignorable storage on revert storage-variables subcommand [#5830](https://github.com/hyperledger/besu/pull/5830)
Expand All @@ -55,7 +59,6 @@ By default, the txpool is tuned for mainnet usage, but if you are using private

### Download Links
https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.10.0/besu-23.10.0.tar.gz / sha256: 3c75f3792bfdb0892705b378f0b8bfc14ef6cecf1d8afe711d8d8687ed6687cf

https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/23.10.0/besu-23.10.0.zip / sha256: d5dafff4c3cbf104bf75b34a9f108dcdd7b08d2759de75ec65cd997f38f52866

## 23.7.3
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.hyperledger.besu.cli.converter.PercentageConverter;
import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
Expand All @@ -32,19 +33,25 @@

import java.io.File;
import java.util.List;
import java.util.Set;

import picocli.CommandLine;

/** The Transaction pool Cli stable options. */
public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfiguration> {
private static final String TX_POOL_IMPLEMENTATION = "--tx-pool";
/** Use TX_POOL_NO_LOCAL_PRIORITY instead */
@Deprecated(forRemoval = true)
private static final String TX_POOL_DISABLE_LOCALS = "--tx-pool-disable-locals";

private static final String TX_POOL_NO_LOCAL_PRIORITY = "--tx-pool-no-local-priority";
private static final String TX_POOL_ENABLE_SAVE_RESTORE = "--tx-pool-enable-save-restore";
private static final String TX_POOL_SAVE_FILE = "--tx-pool-save-file";
private static final String TX_POOL_PRICE_BUMP = "--tx-pool-price-bump";
private static final String RPC_TX_FEECAP = "--rpc-tx-feecap";
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";

@CommandLine.Option(
names = {TX_POOL_IMPLEMENTATION},
Expand All @@ -54,13 +61,13 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
private TransactionPoolConfiguration.Implementation txPoolImplementation = LAYERED;

@CommandLine.Option(
names = {TX_POOL_DISABLE_LOCALS},
names = {TX_POOL_NO_LOCAL_PRIORITY, TX_POOL_DISABLE_LOCALS},
paramLabel = "<Boolean>",
description =
"Set to true if transactions sent via RPC should have the same checks and not be prioritized over remote ones (default: ${DEFAULT-VALUE})",
"Set to true if senders of transactions sent via RPC should not have priority (default: ${DEFAULT-VALUE})",
macfarla marked this conversation as resolved.
Show resolved Hide resolved
fallbackValue = "true",
arity = "0..1")
private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS;
private Boolean noLocalPriority = TransactionPoolConfiguration.DEFAULT_NO_LOCAL_PRIORITY;

@CommandLine.Option(
names = {TX_POOL_ENABLE_SAVE_RESTORE},
Expand Down Expand Up @@ -104,6 +111,15 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
arity = "0..1")
private Boolean strictTxReplayProtectionEnabled = false;

@CommandLine.Option(
names = {TX_POOL_PRIORITY_SENDERS},
split = ",",
paramLabel = "Comma separated list of addresses",
description =
"Pending transactions sent exclusively by these addresses, from any source, are prioritized and only evicted after all others. If not specified, then only the senders submitting transactions via RPC have priority (default: ${DEFAULT-VALUE})",
arity = "1..*")
private Set<Address> prioritySenders = TransactionPoolConfiguration.DEFAULT_PRIORITY_SENDERS;

@CommandLine.ArgGroup(
validate = false,
heading = "@|bold Tx Pool Layered Implementation Options|@%n")
Expand Down Expand Up @@ -200,11 +216,12 @@ public static TransactionPoolOptions fromConfig(final TransactionPoolConfigurati
final TransactionPoolOptions options = TransactionPoolOptions.create();
options.txPoolImplementation = config.getTxPoolImplementation();
options.saveRestoreEnabled = config.getEnableSaveRestore();
options.disableLocalTxs = config.getDisableLocalTransactions();
options.noLocalPriority = config.getNoLocalPriority();
options.priceBump = config.getPriceBump();
options.txFeeCap = config.getTxFeeCap();
options.saveFile = config.getSaveFile();
options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled();
options.prioritySenders = config.getPrioritySenders();
options.layeredOptions.txPoolLayerMaxCapacity =
config.getPendingTransactionsLayerMaxCapacityBytes();
options.layeredOptions.txPoolMaxPrioritized = config.getMaxPrioritizedTransactions();
Expand Down Expand Up @@ -242,11 +259,12 @@ public TransactionPoolConfiguration toDomainObject() {
return ImmutableTransactionPoolConfiguration.builder()
.txPoolImplementation(txPoolImplementation)
.enableSaveRestore(saveRestoreEnabled)
.disableLocalTransactions(disableLocalTxs)
.noLocalPriority(noLocalPriority)
.priceBump(priceBump)
.txFeeCap(txFeeCap)
.saveFile(saveFile)
.strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled)
.prioritySenders(prioritySenders)
.pendingTransactionsLayerMaxCapacityBytes(layeredOptions.txPoolLayerMaxCapacity)
.maxPrioritizedTransactions(layeredOptions.txPoolMaxPrioritized)
.maxFutureBySender(layeredOptions.txPoolMaxFutureBySender)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest;
import org.hyperledger.besu.cli.options.OptionParser;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
Expand Down Expand Up @@ -73,20 +74,20 @@ public void pendingTransactionRetentionPeriod() {

@Test
public void disableLocalsDefault() {
internalTestSuccess(config -> assertThat(config.getDisableLocalTransactions()).isFalse());
internalTestSuccess(config -> assertThat(config.getNoLocalPriority()).isFalse());
}

@Test
public void disableLocalsOn() {
internalTestSuccess(
config -> assertThat(config.getDisableLocalTransactions()).isTrue(),
config -> assertThat(config.getNoLocalPriority()).isTrue(),
"--tx-pool-disable-locals=true");
}

@Test
public void disableLocalsOff() {
internalTestSuccess(
config -> assertThat(config.getDisableLocalTransactions()).isFalse(),
config -> assertThat(config.getNoLocalPriority()).isFalse(),
"--tx-pool-disable-locals=false");
}

Expand Down Expand Up @@ -214,6 +215,61 @@ public void failIfLayeredOptionsWhenLegacySelectedByArg() {
"--tx-pool-max-prioritized=1000");
}

@Test
public void byDefaultNoPrioritySenders() {
internalTestSuccess(config -> assertThat(config.getPrioritySenders()).isEmpty());
}

@Test
public void onePrioritySenderWorks() {
final Address prioritySender = Address.fromHexString("0xABC123");
internalTestSuccess(
config -> assertThat(config.getPrioritySenders()).containsExactly(prioritySender),
"--tx-pool-priority-senders",
prioritySender.toHexString());
}

@Test
public void morePrioritySendersWorks() {
final Address prioritySender1 = Address.fromHexString("0xABC123");
final Address prioritySender2 = Address.fromHexString("0xDEF456");
final Address prioritySender3 = Address.fromHexString("0x789000");
internalTestSuccess(
config ->
assertThat(config.getPrioritySenders())
.containsExactly(prioritySender1, prioritySender2, prioritySender3),
"--tx-pool-priority-senders",
prioritySender1.toHexString()
+ ","
+ prioritySender2.toHexString()
+ ","
+ prioritySender3.toHexString());
}

@Test
public void atLeastOnePrioritySenders() {
internalTestFailure(
"Missing required parameter for option '--tx-pool-priority-senders' at index 0 (Comma separated list of addresses)",
"--tx-pool-priority-senders");
}

@Test
public void malformedListOfPrioritySenders() {
final Address prioritySender1 = Address.fromHexString("0xABC123");
final Address prioritySender2 = Address.fromHexString("0xDEF456");
final Address prioritySender3 = Address.fromHexString("0x789000");
internalTestFailure(
"Invalid value for option '--tx-pool-priority-senders' at index 0 (Comma separated list of addresses): "
+ "cannot convert '0x0000000000000000000000000000000000abc123;0x0000000000000000000000000000000000def456' "
+ "to Address (java.lang.IllegalArgumentException: Invalid odd-length hex binary representation)",
"--tx-pool-priority-senders",
prioritySender1.toHexString()
+ ";"
+ prioritySender2.toHexString()
+ ","
+ prioritySender3.toHexString());
}

@Override
protected TransactionPoolConfiguration createDefaultDomainObject() {
return TransactionPoolConfiguration.DEFAULT;
Expand Down
3 changes: 2 additions & 1 deletion besu/src/test/resources/everything_config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ tx-pool="layered"
tx-pool-price-bump=13
rpc-tx-feecap=2000000000000000000
strict-tx-replay-protection-enabled=true
tx-pool-disable-locals=false
tx-pool-no-local-priority=false
tx-pool-priority-senders=["0xABC0000000000000000000000000000000001234","0xDEF0000000000000000000000000000000001234"]
tx-pool-enable-save-restore=true
tx-pool-save-file="txpool.dump"
## Layered
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardSyncContext;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
Expand Down Expand Up @@ -314,8 +314,8 @@ public void exceptionDuringBuildingBlockShouldNotBeInvalid()
invocation -> {
if (retries.getAndIncrement() < txPerBlock) {
// a new transaction every time a block is built
transactions.addLocalTransaction(
createTransaction(retries.get() - 1), Optional.empty());
transactions.addTransaction(
createLocalTransaction(retries.get() - 1), Optional.empty());
} else {
// when we have 5 transactions finalize block creation
willThrow.finalizeProposalById(
Expand Down Expand Up @@ -387,8 +387,8 @@ public void shouldContinueBuildingBlocksUntilFinalizeIsCalled()
invocation -> {
if (retries.getAndIncrement() < 5) {
// a new transaction every time a block is built
transactions.addLocalTransaction(
createTransaction(retries.get() - 1), Optional.empty());
transactions.addTransaction(
createLocalTransaction(retries.get() - 1), Optional.empty());
} else {
// when we have 5 transactions finalize block creation
coordinator.finalizeProposalById(
Expand Down Expand Up @@ -506,7 +506,7 @@ public void shouldRetryBlockCreationOnRecoverableError()
.when(mergeContext)
.putPayloadById(any());

transactions.addLocalTransaction(createTransaction(0), Optional.empty());
transactions.addTransaction(createLocalTransaction(0), Optional.empty());

var payloadId =
coordinator.preparePayload(
Expand Down Expand Up @@ -643,8 +643,8 @@ public void shouldNotStartAnotherBlockCreationJobIfCalledAgainWithTheSamePayload
invocation -> {
if (retries.getAndIncrement() < 5) {
// a new transaction every time a block is built
transactions.addLocalTransaction(
createTransaction(retries.get() - 1), Optional.empty());
transactions.addTransaction(
createLocalTransaction(retries.get() - 1), Optional.empty());
} else {
// when we have 5 transactions finalize block creation
coordinator.finalizeProposalById(
Expand Down Expand Up @@ -1022,20 +1022,24 @@ private BlockHeader nextBlockHeader(
.buildHeader();
}

private Transaction createTransaction(final long transactionNumber) {
return new TransactionTestFixture()
.value(Wei.of(transactionNumber + 1))
.to(Optional.of(Address.ZERO))
.gasLimit(53000L)
.gasPrice(
Wei.fromHexString("0x00000000000000000000000000000000000000000000000000000013b9aca00"))
.maxFeePerGas(
Optional.of(
private PendingTransaction createLocalTransaction(final long transactionNumber) {
return PendingTransaction.newPendingTransaction(
new TransactionTestFixture()
.value(Wei.of(transactionNumber + 1))
.to(Optional.of(Address.ZERO))
.gasLimit(53000L)
.gasPrice(
Wei.fromHexString(
"0x00000000000000000000000000000000000000000000000000000013b9aca00")))
.maxPriorityFeePerGas(Optional.of(Wei.of(100_000)))
.nonce(transactionNumber)
.createTransaction(KEYS1);
"0x00000000000000000000000000000000000000000000000000000013b9aca00"))
.maxFeePerGas(
Optional.of(
Wei.fromHexString(
"0x00000000000000000000000000000000000000000000000000000013b9aca00")))
.maxPriorityFeePerGas(Optional.of(Wei.of(100_000)))
.nonce(transactionNumber)
.createTransaction(KEYS1),
true,
true);
}

private static BlockHeader mockBlockHeader() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ public interface PendingTransaction {
*/
boolean isReceivedFromLocalSource();

/**
* Should this transaction be prioritized?
*
* @return true if it is a transaction with priority
*/
boolean hasPriority();

/**
* Timestamp in millisecond when this transaction has been added to the pool
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionBroadcaster;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
Expand Down Expand Up @@ -90,7 +91,8 @@ public class EthGetFilterChangesIntegrationTest {

private static final int MAX_TRANSACTIONS = 5;
private static final KeyPair keyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
private final Transaction transaction = createTransaction(1);
private final PendingTransaction pendingTransaction =
new PendingTransaction.Local((createTransaction(1)));
private FilterManager filterManager;
private EthGetFilterChanges method;

Expand Down Expand Up @@ -193,7 +195,7 @@ public void shouldReturnHashesIfNewBlocks() {
JsonRpcResponse actual = method.response(request);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);

final Block block = appendBlock(transaction);
final Block block = appendBlock(pendingTransaction.getTransaction());

// We've added one block, so there should be one new hash.
expected = new JsonRpcSuccessResponse(null, Lists.newArrayList(block.getHash().toString()));
Expand Down Expand Up @@ -223,11 +225,12 @@ public void shouldReturnHashesIfNewPendingTransactions() {
JsonRpcResponse actual = method.response(request);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);

transactions.addRemoteTransaction(transaction, Optional.empty());
transactions.addTransaction(pendingTransaction, Optional.empty());

// We've added one transaction, so there should be one new hash.
expected =
new JsonRpcSuccessResponse(null, Lists.newArrayList(String.valueOf(transaction.getHash())));
new JsonRpcSuccessResponse(
null, Lists.newArrayList(String.valueOf(pendingTransaction.getHash())));
actual = method.response(request);
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);

Expand Down
Loading
Loading