Release 23.7.3-RC2 - Holesky Hotfix (#5938)

* Revert "Burn in candidate for 23.7.3 (#5906)"

This reverts commit ed9d80e10e.

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* Update holesky with fixed extraData, genesis time, shanghaiTime (#5890)

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* 23.7.3-RC2 version bump and 23.7.2 release SHAs
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

* updated gradle verification metadata (#5870)

* removed old artefacts

* works with compileTestJava

* restored metadata needed for codeQL and trusted-artifacts block for javadoc/sources

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

---------

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

* Add rocksdbjni-8.0.0 gradle verification back in

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>

---------

Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
release-23.7.x
Simon Dudley 1 year ago committed by GitHub
parent ed9d80e10e
commit 7cb1dda986
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .github/workflows/checks.yml
  2. 2
      .github/workflows/codeql.yml
  3. 4
      .github/workflows/dco-merge-group.yml
  4. 4
      .github/workflows/dco.yml
  5. 2
      .github/workflows/gradle-wrapper-validation.yml
  6. 2
      .github/workflows/pr-checklist-on-open.yml
  7. 2
      .github/workflows/release.yml
  8. 2
      .github/workflows/repolinter.yml
  9. 15
      CHANGELOG.md
  10. 2
      README.md
  11. 130
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  12. 15
      besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java
  13. 4
      besu/src/main/java/org/hyperledger/besu/cli/DefaultCommandValues.java
  14. 2
      besu/src/main/java/org/hyperledger/besu/cli/config/NetworkName.java
  15. 44
      besu/src/main/java/org/hyperledger/besu/cli/converter/DurationMillisConverter.java
  16. 6
      besu/src/main/java/org/hyperledger/besu/cli/converter/FractionConverter.java
  17. 6
      besu/src/main/java/org/hyperledger/besu/cli/converter/PercentageConverter.java
  18. 39
      besu/src/main/java/org/hyperledger/besu/cli/converter/exception/DurationConversionException.java
  19. 45
      besu/src/main/java/org/hyperledger/besu/cli/options/OptionParser.java
  20. 263
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/TransactionPoolOptions.java
  21. 122
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptions.java
  22. 2
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java
  23. 104
      besu/src/main/java/org/hyperledger/besu/cli/util/CommandLineUtils.java
  24. 6
      besu/src/main/java/org/hyperledger/besu/cli/util/TomlConfigFileDefaultProvider.java
  25. 26
      besu/src/main/java/org/hyperledger/besu/controller/IbftBesuControllerBuilder.java
  26. 26
      besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java
  27. 157
      besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java
  28. 11
      besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java
  29. 209
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  30. 7
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  31. 22
      besu/src/test/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilderTest.java
  32. 2
      besu/src/test/java/org/hyperledger/besu/cli/NetworkDeprecationMessageTest.java
  33. 5
      besu/src/test/java/org/hyperledger/besu/cli/converter/FractionConverterTest.java
  34. 5
      besu/src/test/java/org/hyperledger/besu/cli/converter/PercentageConverterTest.java
  35. 27
      besu/src/test/java/org/hyperledger/besu/cli/options/AbstractCLIOptionsTest.java
  36. 9
      besu/src/test/java/org/hyperledger/besu/cli/options/EthProtocolOptionsTest.java
  37. 9
      besu/src/test/java/org/hyperledger/besu/cli/options/MetricsCLIOptionsTest.java
  38. 8
      besu/src/test/java/org/hyperledger/besu/cli/options/NetworkingOptionsTest.java
  39. 21
      besu/src/test/java/org/hyperledger/besu/cli/options/OptionParserTest.java
  40. 8
      besu/src/test/java/org/hyperledger/besu/cli/options/SynchronizerOptionsTest.java
  41. 155
      besu/src/test/java/org/hyperledger/besu/cli/options/TransactionPoolOptionsTest.java
  42. 243
      besu/src/test/java/org/hyperledger/besu/cli/options/stable/TransactionPoolOptionsTest.java
  43. 105
      besu/src/test/java/org/hyperledger/besu/cli/options/unstable/TransactionPoolOptionsTest.java
  44. 11
      besu/src/test/java/org/hyperledger/besu/controller/BesuControllerBuilderTest.java
  45. 11
      besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java
  46. 11
      besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java
  47. 19
      besu/src/test/java/org/hyperledger/besu/ethereum/p2p/config/DefaultDiscoveryConfiguration.java
  48. 211
      besu/src/test/java/org/hyperledger/besu/services/TraceServiceImplTest.java
  49. 13
      besu/src/test/resources/everything_config.toml
  50. 22
      build.gradle
  51. 815
      config/src/main/resources/kotti.json
  52. 1
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/MigratingMiningCoordinator.java
  53. 14
      consensus/common/src/main/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinator.java
  54. 1
      consensus/common/src/test/java/org/hyperledger/besu/consensus/common/bft/blockcreation/BftMiningCoordinatorTest.java
  55. 7
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinator.java
  56. 7
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifier.java
  57. 3
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java
  58. 93
      consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/PayloadIdentifierTest.java
  59. 22
      datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java
  60. 8
      datatypes/src/main/java/org/hyperledger/besu/datatypes/BlobsWithCommitments.java
  61. 57
      datatypes/src/test/java/org/hyperledger/besu/datatypes/BlobsWithCommitmentsTest.java
  62. 11
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/authentication/DefaultAuthenticationService.java
  63. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceBlock.java
  64. 9
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java
  65. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java
  66. 36
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java
  67. 13
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResultFactory.java
  68. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/EngineGetPayloadBodiesResultV1.java
  69. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/TransactionPendingResult.java
  70. 3
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/util/DomainObjectDecodeUtils.java
  71. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdatedTest.java
  72. 14
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineGetPayloadTest.java
  73. 1
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadV3Test.java
  74. 55
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineNewPayloadV3Test.java
  75. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/util/DomainObjectDecodeUtilsTest.java
  76. 18
      ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java
  77. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java
  78. 3
      ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java
  79. 12
      ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/EntriesFromIntegrationTest.java
  80. 2
      ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/TransientStorageOperationBenchmark.java
  81. 31
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiAccount.java
  82. 2
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/BonsaiWorldStateProvider.java
  83. 68
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiPreImageProxy.java
  84. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/BonsaiWorldStateKeyValueStorage.java
  85. 13
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/storage/flat/FlatDbReaderStrategy.java
  86. 80
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldState.java
  87. 178
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/bonsai/worldview/BonsaiWorldStateUpdateAccumulator.java
  88. 6
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java
  89. 48
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java
  90. 74
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AccessListTransactionDecoder.java
  91. 109
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/AccessListTransactionEncoder.java
  92. 50
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlobPooledTransactionDecoder.java
  93. 47
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlobPooledTransactionEncoder.java
  94. 47
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlobTransactionDecoder.java
  95. 35
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/BlobTransactionEncoder.java
  96. 74
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/EIP1559TransactionDecoder.java
  97. 41
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/EIP1559TransactionEncoder.java
  98. 41
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/EncodingContext.java
  99. 76
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/FrontierTransactionDecoder.java
  100. 36
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/FrontierTransactionEncoder.java
  101. Some files were not shown because too many files have changed in this diff Show More

@ -7,7 +7,7 @@ on:
jobs:
spotless:
runs-on: [besu-research-ubuntu-16]
runs-on: [besu,Linux,self-hosted,X64,nodocker]
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- name: Checkout Repo
@ -21,7 +21,7 @@ jobs:
- name: spotless
run: ./gradlew --no-daemon --parallel clean spotlessCheck
javadoc_17:
runs-on: [besu-research-ubuntu-8]
runs-on: [besu,Linux,self-hosted,X64,nodocker]
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- name: Checkout Repo

@ -24,7 +24,7 @@ on:
jobs:
analyze:
name: Analyze
runs-on: [besu-research-ubuntu-16]
runs-on: [besu,Linux,self-hosted,X64,nodocker]
permissions:
actions: read
contents: read

@ -4,7 +4,7 @@ on:
jobs:
dco:
runs-on: [besu-research-ubuntu-8]
runs-on: [besu,Linux,self-hosted,nodocker]
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- run: echo "This DCO job runs on merge_queue event and doesn't check PR contents"
- run: echo "This DCO job runs on merge_queue event and doesn't check PR contents"

@ -5,7 +5,7 @@ on:
jobs:
dco:
runs-on: [besu-research-ubuntu-8]
runs-on: [besu,Linux,self-hosted,nodocker]
if: ${{ github.actor != 'dependabot[bot]' }}
steps:
- run: echo "This DCO job runs on pull_request event and workflow_dispatch"
@ -17,4 +17,4 @@ jobs:
- name: DCO Check
uses: tim-actions/dco@v1.1.0
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}
commits: ${{ steps.get-pr-commits.outputs.commits }}

@ -5,7 +5,7 @@ on: [push, pull_request]
jobs:
validation:
name: "Gradle Wrapper Validation"
runs-on: [besu-research-ubuntu-8]
runs-on: [besu,Linux,self-hosted,nodocker]
steps:
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1

@ -6,7 +6,7 @@ on:
jobs:
checklist:
name: "add checklist as a comment on newly opened PRs"
runs-on: [besu-research-ubuntu-8]
runs-on: [besu,Linux,self-hosted,nodocker]
steps:
- uses: actions/github-script@v5
with:

@ -4,7 +4,7 @@ on:
types: released
jobs:
dockerPromoteX64:
runs-on: [besu-research-ubuntu-16]
runs-on: [besu,Linux,self-hosted,nodocker]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3

@ -15,7 +15,7 @@ on:
jobs:
build:
runs-on: [besu-research-ubuntu-16]
runs-on: [besu,Linux,self-hosted,X64,docker]
container: ghcr.io/todogroup/repolinter:v0.10.1
steps:
- name: Checkout Code

@ -2,21 +2,8 @@
## 23.7.3
### Breaking Changes
- Removed support for Kotti network (ETC) [#5816](https://github.com/hyperledger/besu/pull/5816)
- Layered transaction pool implementation is now stable and enabled by default, so the following changes to experimental options have been done [#5772](https://github.com/hyperledger/besu):
- `--Xlayered-tx-pool` is gone, to select the implementation use the new `--tx-pool` option with values `layered` (default) or `legacy`
- `--Xlayered-tx-pool-layer-max-capacity`, `--Xlayered-tx-pool-max-prioritized` and `--Xlayered-tx-pool-max-future-by-sender` just drop the `X` and keep the same behavior
### Additions and Improvements
- Add access to an immutable world view to start/end transaction hooks in the tracing API[#5836](https://github.com/hyperledger/besu/pull/5836)
- Layered transaction pool implementation is now stable and enabled by default. If you want still to use the legacy implementation, use `--tx-pool=legacy` [#5772](https://github.com/hyperledger/besu)
- 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)
- Update Holešky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890)
### Bug Fixes
- do not create ignorable storage on revert storage-variables subcommand [#5830](https://github.com/hyperledger/besu/pull/5830)
- fix duplicate key errors in EthScheduler-Transactions [#5857](https://github.com/hyperledger/besu/pull/5857)
- Update Holesky config for re-launch [#5890](https://github.com/hyperledger/besu/pull/5890)
### Download Links

@ -28,7 +28,7 @@ If you have any questions, queries or comments, [Besu channel on Hyperledger Dis
## Besu Users
To install the Besu binary, follow [these instructions](https://besu.hyperledger.org/public-networks/get-started/install/binary-distribution).
To install the Besu binary, follow [these instructions](https://besu.hyperledger.org/HowTo/Get-Started/Install-Binaries/).
## Besu Developers

@ -46,6 +46,7 @@ import org.hyperledger.besu.chainimport.JsonBlockImporter;
import org.hyperledger.besu.chainimport.RlpBlockImporter;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.cli.converter.FractionConverter;
import org.hyperledger.besu.cli.converter.MetricCategoryConverter;
import org.hyperledger.besu.cli.converter.PercentageConverter;
import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty;
@ -58,7 +59,6 @@ import org.hyperledger.besu.cli.options.stable.EthstatsOptions;
import org.hyperledger.besu.cli.options.stable.LoggingLevelOption;
import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption;
import org.hyperledger.besu.cli.options.stable.P2PTLSConfigOptions;
import org.hyperledger.besu.cli.options.stable.TransactionPoolOptions;
import org.hyperledger.besu.cli.options.unstable.ChainPruningOptions;
import org.hyperledger.besu.cli.options.unstable.DnsOptions;
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
@ -73,6 +73,7 @@ import org.hyperledger.besu.cli.options.unstable.PkiBlockCreationOptions;
import org.hyperledger.besu.cli.options.unstable.PrivacyPluginOptions;
import org.hyperledger.besu.cli.options.unstable.RPCOptions;
import org.hyperledger.besu.cli.options.unstable.SynchronizerOptions;
import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions;
import org.hyperledger.besu.cli.presynctasks.PreSynchronizationTaskRunner;
import org.hyperledger.besu.cli.presynctasks.PrivateDatabaseMigrationPreSyncTask;
import org.hyperledger.besu.cli.subcommands.PasswordSubCommand;
@ -126,7 +127,6 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.sync.SyncMode;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.mainnet.FrontierTargetingGasLimitCalculator;
import org.hyperledger.besu.ethereum.p2p.config.DiscoveryConfiguration;
@ -280,9 +280,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final SynchronizerOptions unstableSynchronizerOptions = SynchronizerOptions.create();
final EthProtocolOptions unstableEthProtocolOptions = EthProtocolOptions.create();
final MetricsCLIOptions unstableMetricsCLIOptions = MetricsCLIOptions.create();
final org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions
unstableTransactionPoolOptions =
org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions.create();
final TransactionPoolOptions unstableTransactionPoolOptions = TransactionPoolOptions.create();
private final DnsOptions unstableDnsOptions = DnsOptions.create();
private final MiningOptions unstableMiningOptions = MiningOptions.create();
private final NatOptions unstableNatOptions = NatOptions.create();
@ -300,10 +298,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
NodePrivateKeyFileOption.create();
private final LoggingLevelOption loggingLevelOption = LoggingLevelOption.create();
@CommandLine.ArgGroup(validate = false, heading = "@|bold Tx Pool Common Options|@%n")
final org.hyperledger.besu.cli.options.stable.TransactionPoolOptions
stableTransactionPoolOptions = TransactionPoolOptions.create();
private final RunnerBuilder runnerBuilder;
private final BesuController.Builder controllerBuilderFactory;
private final BesuPluginContextImpl besuPluginContext;
@ -460,8 +454,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
"The maximum percentage of P2P connections that can be initiated remotely. Must be between 0 and 100 inclusive. (default: ${DEFAULT-VALUE})",
arity = "1",
converter = PercentageConverter.class)
private final Percentage maxRemoteConnectionsPercentage =
Fraction.fromFloat(DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED).toPercentage();
private final Integer maxRemoteConnectionsPercentage =
Fraction.fromFloat(DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED)
.toPercentage()
.getValue();
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@CommandLine.Option(
@ -1115,6 +1111,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
arity = "1")
private final Wei minTransactionGasPrice = DEFAULT_MIN_TRANSACTION_GAS_PRICE;
@Option(
names = {"--rpc-tx-feecap"},
description =
"Maximum transaction fees (in Wei) accepted for transaction submitted through RPC (default: ${DEFAULT-VALUE})",
arity = "1")
private final Wei txFeeCap = DEFAULT_RPC_TX_FEE_CAP;
@Option(
names = {"--min-block-occupancy-ratio"},
description = "Minimum occupancy ratio for a mined block (default: ${DEFAULT-VALUE})",
@ -1206,6 +1209,75 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
"Sets target gas limit per block. If set, each block's gas limit will approach this setting over time if the current gas limit is different.")
private final Long targetGasLimit = null;
// Tx Pool Option Group
@CommandLine.ArgGroup(validate = false, heading = "@|bold Tx Pool Options|@%n")
TxPoolOptionGroup txPoolOptionGroup = new TxPoolOptionGroup();
static class TxPoolOptionGroup {
@CommandLine.Option(
names = {"--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})",
fallbackValue = "true",
arity = "0..1")
private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS;
@CommandLine.Option(
names = {"--tx-pool-enable-save-restore"},
paramLabel = "<Boolean>",
description =
"Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})",
fallbackValue = "true",
arity = "0..1")
private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE;
@CommandLine.Option(
names = {"--tx-pool-limit-by-account-percentage"},
paramLabel = "<DOUBLE>",
converter = FractionConverter.class,
description =
"Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})",
arity = "1")
private Float txPoolLimitByAccountPercentage =
TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE;
@CommandLine.Option(
names = {"--tx-pool-save-file"},
paramLabel = "<STRING>",
description =
"If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)",
arity = "1")
private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE;
@Option(
names = {"--tx-pool-max-size"},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Maximum number of pending transactions that will be kept in the transaction pool (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer txPoolMaxSize =
TransactionPoolConfiguration.DEFAULT_MAX_PENDING_TRANSACTIONS;
@Option(
names = {"--tx-pool-retention-hours"},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer pendingTxRetentionPeriod =
TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS;
@Option(
names = {"--tx-pool-price-bump"},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
converter = PercentageConverter.class,
description =
"Price bump percentage to replace an already existing transaction (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer priceBump = TransactionPoolConfiguration.DEFAULT_PRICE_BUMP.getValue();
}
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@Option(
names = {"--key-value-storage"},
@ -1834,15 +1906,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
validateRpcOptionsParams();
validateChainDataPruningParams();
validatePostMergeCheckpointBlockRequirements();
validateTransactionPoolOptions();
p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine);
pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine);
}
private void validateTransactionPoolOptions() {
stableTransactionPoolOptions.validate(commandLine);
}
private void validateRequiredOptions() {
commandLine
.getCommandSpec()
@ -2920,14 +2987,28 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
private TransactionPoolConfiguration buildTransactionPoolConfiguration() {
final var stableTxPoolOption = stableTransactionPoolOptions.toDomainObject();
return ImmutableTransactionPoolConfiguration.builder()
.from(stableTxPoolOption)
.unstable(unstableTransactionPoolOptions.toDomainObject())
.saveFile((dataPath.resolve(stableTxPoolOption.getSaveFile().getPath()).toFile()))
return unstableTransactionPoolOptions
.toDomainObject()
.enableSaveRestore(txPoolOptionGroup.saveRestoreEnabled)
.disableLocalTransactions(txPoolOptionGroup.disableLocalTxs)
.txPoolLimitByAccountPercentage(txPoolOptionGroup.txPoolLimitByAccountPercentage)
.txPoolMaxSize(txPoolOptionGroup.txPoolMaxSize)
.pendingTxRetentionPeriod(txPoolOptionGroup.pendingTxRetentionPeriod)
.priceBump(Percentage.fromInt(txPoolOptionGroup.priceBump))
.txFeeCap(txFeeCap)
.saveFile(dataPath.resolve(txPoolOptionGroup.saveFile.getPath()).toFile())
.build();
}
/**
* Return the file where to save txpool content if the relative option is enabled.
*
* @return the save file
*/
public File getSaveFile() {
return txPoolOptionGroup.saveFile;
}
private boolean isPruningEnabled() {
return pruningEnabled;
}
@ -3408,8 +3489,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
getActualGenesisConfigOptions().getTerminalTotalDifficulty().isPresent());
}
/** Set ignorable segments in RocksDB Storage Provider plugin. */
public void setIgnorableStorageSegments() {
private void setIgnorableStorageSegments() {
if (!unstableChainPruningOptions.getChainDataPruningEnabled()) {
rocksDBPlugin.addIgnorableSegmentIdentifier(KeyValueSegmentIdentifier.CHAIN_PRUNER_STATE);
}
@ -3532,7 +3612,9 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
builder.setHighSpecEnabled();
}
builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation());
if (buildTransactionPoolConfiguration().getLayeredTxPoolEnabled()) {
builder.setLayeredTxPoolEnabled();
}
return builder.build();
}

@ -15,7 +15,6 @@
package org.hyperledger.besu.cli;
import org.hyperledger.besu.BesuInfo;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.util.log.FramedLogMessage;
import org.hyperledger.besu.util.platform.PlatformDetector;
@ -48,7 +47,7 @@ public class ConfigurationOverviewBuilder {
private Collection<String> engineApis;
private String engineJwtFilePath;
private boolean isHighSpec = false;
private TransactionPoolConfiguration.Implementation txPoolImplementation;
private boolean isLayeredTxPool = false;
private Map<String, String> environment;
/**
@ -168,14 +167,12 @@ public class ConfigurationOverviewBuilder {
}
/**
* Sets the txpool implementation in use.
* Sets experimental layered txpool enabled.
*
* @param implementation the txpool implementation
* @return the builder
*/
public ConfigurationOverviewBuilder setTxPoolImplementation(
final TransactionPoolConfiguration.Implementation implementation) {
txPoolImplementation = implementation;
public ConfigurationOverviewBuilder setLayeredTxPoolEnabled() {
isLayeredTxPool = true;
return this;
}
@ -254,7 +251,9 @@ public class ConfigurationOverviewBuilder {
lines.add("Experimental high spec configuration enabled");
}
lines.add("Using " + txPoolImplementation + " transaction pool implementation");
if (isLayeredTxPool) {
lines.add("Experimental layered transaction pool configuration enabled");
}
lines.add("");
lines.add("Host:");

@ -16,6 +16,7 @@ package org.hyperledger.besu.cli;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration;
import org.hyperledger.besu.nat.NatMethod;
@ -60,6 +61,9 @@ public interface DefaultCommandValues {
String MANDATORY_NODE_ID_FORMAT_HELP = "<NODEID>";
/** The constant DEFAULT_MIN_TRANSACTION_GAS_PRICE. */
Wei DEFAULT_MIN_TRANSACTION_GAS_PRICE = Wei.of(1000);
/** The constant DEFAULT_RPC_TX_FEE_CAP. */
Wei DEFAULT_RPC_TX_FEE_CAP = TransactionPoolConfiguration.DEFAULT_RPC_TX_FEE_CAP;
/** The constant DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO. */
Double DEFAULT_MIN_BLOCK_OCCUPANCY_RATIO = 0.8;
/** The constant DEFAULT_EXTRA_DATA. */

@ -38,6 +38,8 @@ public enum NetworkName {
EXPERIMENTAL_EIPS("/experimental.json", BigInteger.valueOf(2023), false),
/** Classic network name. */
CLASSIC("/classic.json", BigInteger.valueOf(1)),
/** Kotti network name. */
KOTTI("/kotti.json", BigInteger.valueOf(6)),
/** Mordor network name. */
MORDOR("/mordor.json", BigInteger.valueOf(7));

@ -1,44 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.cli.converter;
import org.hyperledger.besu.cli.converter.exception.DurationConversionException;
import java.time.Duration;
import picocli.CommandLine;
/** The Duration (milliseconds) Cli type converter. */
public class DurationMillisConverter
implements CommandLine.ITypeConverter<Duration>, TypeFormatter<Duration> {
@Override
public Duration convert(final String value) throws DurationConversionException {
try {
final long millis = Long.parseLong(value);
if (millis < 0) {
throw new DurationConversionException(millis);
}
return Duration.ofMillis(Long.parseLong(value));
} catch (NullPointerException | IllegalArgumentException e) {
throw new DurationConversionException(value);
}
}
@Override
public String format(final Duration value) {
return Long.toString(value.toMillis());
}
}

@ -20,12 +20,12 @@ import org.hyperledger.besu.util.number.Fraction;
import picocli.CommandLine;
/** The Fraction converter to convert floats in CLI. */
public class FractionConverter implements CommandLine.ITypeConverter<Fraction> {
public class FractionConverter implements CommandLine.ITypeConverter<Float> {
@Override
public Fraction convert(final String value) throws FractionConversionException {
public Float convert(final String value) throws FractionConversionException {
try {
return Fraction.fromString(value);
return Fraction.fromString(value).getValue();
} catch (final NullPointerException | IllegalArgumentException e) {
throw new FractionConversionException(value);
}

@ -20,12 +20,12 @@ import org.hyperledger.besu.util.number.Percentage;
import picocli.CommandLine;
/** The Percentage Cli type converter. */
public class PercentageConverter implements CommandLine.ITypeConverter<Percentage> {
public class PercentageConverter implements CommandLine.ITypeConverter<Integer> {
@Override
public Percentage convert(final String value) throws PercentageConversionException {
public Integer convert(final String value) throws PercentageConversionException {
try {
return Percentage.fromString(value);
return Percentage.fromString(value).getValue();
} catch (NullPointerException | IllegalArgumentException e) {
throw new PercentageConversionException(value);
}

@ -1,39 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.cli.converter.exception;
import static java.lang.String.format;
/** The custom Duration conversion exception. */
public final class DurationConversionException extends Exception {
/**
* Instantiates a new Duration conversion exception for malformed value.
*
* @param value the value
*/
public DurationConversionException(final String value) {
super(format("'%s' is not a long", value));
}
/**
* Instantiates a new Duration conversion exception for negative value.
*
* @param value the millis
*/
public DurationConversionException(final long value) {
super(format("negative value '%d' is not allowed", value));
}
}

@ -16,11 +16,6 @@ package org.hyperledger.besu.cli.options;
import static com.google.common.base.Preconditions.checkArgument;
import org.hyperledger.besu.datatypes.Wei;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Iterator;
import com.google.common.base.Splitter;
@ -101,44 +96,4 @@ public class OptionParser {
public static String format(final UInt256 value) {
return value.toBigInteger().toString(10);
}
/**
* Format Wei to string.
*
* @param value the value
* @return the string
*/
public static String format(final Wei value) {
return format(value.toUInt256());
}
/**
* Format any object to string. This implementation tries to find an existing format method, in
* this class, that matches the type of the passed object, and if not found just invoke, to string
* on the passed object
*
* @param value the object
* @return the string
*/
public static String format(final Object value) {
Method formatMethod;
try {
formatMethod = OptionParser.class.getMethod("format", value.getClass());
} catch (NoSuchMethodException e) {
try {
// maybe a primitive version of the method exists
formatMethod =
OptionParser.class.getMethod(
"format", MethodType.methodType(value.getClass()).unwrap().returnType());
} catch (NoSuchMethodException ex) {
return value.toString();
}
}
try {
return (String) formatMethod.invoke(null, value);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}

@ -1,263 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.cli.options.stable;
import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_DOUBLE_FORMAT_HELP;
import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_INTEGER_FORMAT_HELP;
import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_LONG_FORMAT_HELP;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LAYERED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LEGACY;
import org.hyperledger.besu.cli.converter.FractionConverter;
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.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.util.number.Fraction;
import org.hyperledger.besu.util.number.Percentage;
import java.io.File;
import java.util.List;
import picocli.CommandLine;
/** The Transaction pool Cli stable options. */
public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfiguration> {
private static final String TX_POOL_IMPLEMENTATION = "--tx-pool";
private static final String TX_POOL_DISABLE_LOCALS = "--tx-pool-disable-locals";
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";
@CommandLine.Option(
names = {TX_POOL_IMPLEMENTATION},
paramLabel = "<Enum>",
description = "The Transaction Pool implementation to use(default: ${DEFAULT-VALUE})",
arity = "0..1")
private TransactionPoolConfiguration.Implementation txPoolImplementation = LAYERED;
@CommandLine.Option(
names = {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})",
fallbackValue = "true",
arity = "0..1")
private Boolean disableLocalTxs = TransactionPoolConfiguration.DEFAULT_DISABLE_LOCAL_TXS;
@CommandLine.Option(
names = {TX_POOL_ENABLE_SAVE_RESTORE},
paramLabel = "<Boolean>",
description =
"Set to true to enable saving the txpool content to file on shutdown and reloading it on startup (default: ${DEFAULT-VALUE})",
fallbackValue = "true",
arity = "0..1")
private Boolean saveRestoreEnabled = TransactionPoolConfiguration.DEFAULT_ENABLE_SAVE_RESTORE;
@CommandLine.Option(
names = {TX_POOL_SAVE_FILE},
paramLabel = "<STRING>",
description =
"If saving the txpool content is enabled, define a custom path for the save file (default: ${DEFAULT-VALUE} in the data-dir)",
arity = "1")
private File saveFile = TransactionPoolConfiguration.DEFAULT_SAVE_FILE;
@CommandLine.Option(
names = {TX_POOL_PRICE_BUMP},
paramLabel = "<Percentage>",
converter = PercentageConverter.class,
description =
"Price bump percentage to replace an already existing transaction (default: ${DEFAULT-VALUE})",
arity = "1")
private Percentage priceBump = TransactionPoolConfiguration.DEFAULT_PRICE_BUMP;
@CommandLine.Option(
names = {RPC_TX_FEECAP},
description =
"Maximum transaction fees (in Wei) accepted for transaction submitted through RPC (default: ${DEFAULT-VALUE})",
arity = "1")
private Wei txFeeCap = TransactionPoolConfiguration.DEFAULT_RPC_TX_FEE_CAP;
@CommandLine.Option(
names = {STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG},
paramLabel = "<Boolean>",
description =
"Require transactions submitted via JSON-RPC to use replay protection in accordance with EIP-155 (default: ${DEFAULT-VALUE})",
fallbackValue = "true",
arity = "0..1")
private Boolean strictTxReplayProtectionEnabled = false;
@CommandLine.ArgGroup(
validate = false,
heading = "@|bold Tx Pool Layered Implementation Options|@%n")
private final Layered layeredOptions = new Layered();
static class Layered {
private static final String TX_POOL_LAYER_MAX_CAPACITY = "--tx-pool-layer-max-capacity";
private static final String TX_POOL_MAX_PRIORITIZED = "--tx-pool-max-prioritized";
private static final String TX_POOL_MAX_FUTURE_BY_SENDER = "--tx-pool-max-future-by-sender";
@CommandLine.Option(
names = {TX_POOL_LAYER_MAX_CAPACITY},
paramLabel = MANDATORY_LONG_FORMAT_HELP,
description =
"Max amount of memory space, in bytes, that any layer within the transaction pool could occupy (default: ${DEFAULT-VALUE})",
arity = "1")
Long txPoolLayerMaxCapacity =
TransactionPoolConfiguration.DEFAULT_PENDING_TRANSACTIONS_LAYER_MAX_CAPACITY_BYTES;
@CommandLine.Option(
names = {TX_POOL_MAX_PRIORITIZED},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Max number of pending transactions that are prioritized and thus kept sorted (default: ${DEFAULT-VALUE})",
arity = "1")
Integer txPoolMaxPrioritized =
TransactionPoolConfiguration.DEFAULT_MAX_PRIORITIZED_TRANSACTIONS;
@CommandLine.Option(
names = {TX_POOL_MAX_FUTURE_BY_SENDER},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Max number of future pending transactions allowed for a single sender (default: ${DEFAULT-VALUE})",
arity = "1")
Integer txPoolMaxFutureBySender = TransactionPoolConfiguration.DEFAULT_MAX_FUTURE_BY_SENDER;
}
@CommandLine.ArgGroup(
validate = false,
heading = "@|bold Tx Pool Legacy Implementation Options|@%n")
private final Legacy legacyOptions = new Legacy();
static class Legacy {
private static final String TX_POOL_RETENTION_HOURS = "--tx-pool-retention-hours";
private static final String TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE =
"--tx-pool-limit-by-account-percentage";
private static final String TX_POOL_MAX_SIZE = "--tx-pool-max-size";
@CommandLine.Option(
names = {TX_POOL_RETENTION_HOURS},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Maximum retention period of pending transactions in hours (default: ${DEFAULT-VALUE})",
arity = "1")
Integer pendingTxRetentionPeriod = TransactionPoolConfiguration.DEFAULT_TX_RETENTION_HOURS;
@CommandLine.Option(
names = {TX_POOL_LIMIT_BY_ACCOUNT_PERCENTAGE},
paramLabel = MANDATORY_DOUBLE_FORMAT_HELP,
converter = FractionConverter.class,
description =
"Maximum portion of the transaction pool which a single account may occupy with future transactions (default: ${DEFAULT-VALUE})",
arity = "1")
Fraction txPoolLimitByAccountPercentage =
TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE;
@CommandLine.Option(
names = {TX_POOL_MAX_SIZE},
paramLabel = MANDATORY_INTEGER_FORMAT_HELP,
description =
"Maximum number of pending transactions that will be kept in the transaction pool (default: ${DEFAULT-VALUE})",
arity = "1")
Integer txPoolMaxSize = TransactionPoolConfiguration.DEFAULT_MAX_PENDING_TRANSACTIONS;
}
private TransactionPoolOptions() {}
/**
* Create transaction pool options.
*
* @return the transaction pool options
*/
public static TransactionPoolOptions create() {
return new TransactionPoolOptions();
}
/**
* Create Transaction Pool Options from Transaction Pool Configuration.
*
* @param config the Transaction Pool Configuration
* @return the transaction pool options
*/
public static TransactionPoolOptions fromConfig(final TransactionPoolConfiguration config) {
final TransactionPoolOptions options = TransactionPoolOptions.create();
options.txPoolImplementation = config.getTxPoolImplementation();
options.saveRestoreEnabled = config.getEnableSaveRestore();
options.disableLocalTxs = config.getDisableLocalTransactions();
options.priceBump = config.getPriceBump();
options.txFeeCap = config.getTxFeeCap();
options.saveFile = config.getSaveFile();
options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled();
options.layeredOptions.txPoolLayerMaxCapacity =
config.getPendingTransactionsLayerMaxCapacityBytes();
options.layeredOptions.txPoolMaxPrioritized = config.getMaxPrioritizedTransactions();
options.layeredOptions.txPoolMaxFutureBySender = config.getMaxFutureBySender();
options.legacyOptions.txPoolLimitByAccountPercentage =
config.getTxPoolLimitByAccountPercentage();
options.legacyOptions.txPoolMaxSize = config.getTxPoolMaxSize();
options.legacyOptions.pendingTxRetentionPeriod = config.getPendingTxRetentionPeriod();
return options;
}
/**
* Validate that there are no inconsistencies in the specified options. For example that the
* options are valid for the selected implementation.
*
* @param commandLine the full commandLine to check all the options specified by the user
*/
public void validate(final CommandLine commandLine) {
CommandLineUtils.failIfOptionDoesntMeetRequirement(
commandLine,
"Could not use legacy transaction pool options with layered implementation",
!txPoolImplementation.equals(LAYERED),
CommandLineUtils.getCLIOptionNames(Legacy.class));
CommandLineUtils.failIfOptionDoesntMeetRequirement(
commandLine,
"Could not use layered transaction pool options with legacy implementation",
!txPoolImplementation.equals(LEGACY),
CommandLineUtils.getCLIOptionNames(Layered.class));
}
@Override
public TransactionPoolConfiguration toDomainObject() {
return ImmutableTransactionPoolConfiguration.builder()
.txPoolImplementation(txPoolImplementation)
.enableSaveRestore(saveRestoreEnabled)
.disableLocalTransactions(disableLocalTxs)
.priceBump(priceBump)
.txFeeCap(txFeeCap)
.saveFile(saveFile)
.strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled)
.pendingTransactionsLayerMaxCapacityBytes(layeredOptions.txPoolLayerMaxCapacity)
.maxPrioritizedTransactions(layeredOptions.txPoolMaxPrioritized)
.maxFutureBySender(layeredOptions.txPoolMaxFutureBySender)
.txPoolLimitByAccountPercentage(legacyOptions.txPoolLimitByAccountPercentage)
.txPoolMaxSize(legacyOptions.txPoolMaxSize)
.pendingTxRetentionPeriod(legacyOptions.pendingTxRetentionPeriod)
.build();
}
@Override
public List<String> getCLIOptions() {
return CommandLineUtils.getCLIOptions(this, new TransactionPoolOptions());
}
}

@ -14,25 +14,50 @@
*/
package org.hyperledger.besu.cli.options.unstable;
import org.hyperledger.besu.cli.converter.DurationMillisConverter;
import org.hyperledger.besu.cli.options.CLIOptions;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.cli.options.OptionParser;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
/** The Transaction pool Cli unstable options. */
public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfiguration.Unstable> {
/** The Transaction pool Cli options. */
public class TransactionPoolOptions
implements CLIOptions<ImmutableTransactionPoolConfiguration.Builder> {
private static final Logger LOG = LoggerFactory.getLogger(TransactionPoolOptions.class);
private static final String TX_MESSAGE_KEEP_ALIVE_SEC_FLAG =
"--Xincoming-tx-messages-keep-alive-seconds";
private static final String ETH65_TX_ANNOUNCED_BUFFERING_PERIOD_FLAG =
"--Xeth65-tx-announced-buffering-period-milliseconds";
private static final String STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG =
"--strict-tx-replay-protection-enabled";
private static final String LAYERED_TX_POOL_ENABLED_FLAG = "--Xlayered-tx-pool";
private static final String LAYERED_TX_POOL_LAYER_MAX_CAPACITY =
"--Xlayered-tx-pool-layer-max-capacity";
private static final String LAYERED_TX_POOL_MAX_PRIORITIZED =
"--Xlayered-tx-pool-max-prioritized";
private static final String LAYERED_TX_POOL_MAX_FUTURE_BY_SENDER =
"--Xlayered-tx-pool-max-future-by-sender";
@CommandLine.Option(
names = {STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG},
paramLabel = "<Boolean>",
description =
"Require transactions submitted via JSON-RPC to use replay protection in accordance with EIP-155 (default: ${DEFAULT-VALUE})",
fallbackValue = "true",
arity = "0..1")
private Boolean strictTxReplayProtectionEnabled = false;
@CommandLine.Option(
names = {TX_MESSAGE_KEEP_ALIVE_SEC_FLAG},
paramLabel = "<INTEGER>",
@ -41,18 +66,56 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
"Keep alive of incoming transaction messages in seconds (default: ${DEFAULT-VALUE})",
arity = "1")
private Integer txMessageKeepAliveSeconds =
TransactionPoolConfiguration.Unstable.DEFAULT_TX_MSG_KEEP_ALIVE;
TransactionPoolConfiguration.DEFAULT_TX_MSG_KEEP_ALIVE;
@CommandLine.Option(
names = {ETH65_TX_ANNOUNCED_BUFFERING_PERIOD_FLAG},
paramLabel = "<LONG>",
converter = DurationMillisConverter.class,
hidden = true,
description =
"The period for which the announced transactions remain in the buffer before being requested from the peers in milliseconds (default: ${DEFAULT-VALUE})",
arity = "1")
private Duration eth65TrxAnnouncedBufferingPeriod =
TransactionPoolConfiguration.Unstable.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD;
private long eth65TrxAnnouncedBufferingPeriod =
TransactionPoolConfiguration.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD.toMillis();
@CommandLine.Option(
names = {LAYERED_TX_POOL_ENABLED_FLAG},
paramLabel = "<Boolean>",
hidden = true,
description = "Enable the Layered Transaction Pool (default: ${DEFAULT-VALUE})",
arity = "0..1")
private Boolean layeredTxPoolEnabled =
TransactionPoolConfiguration.DEFAULT_LAYERED_TX_POOL_ENABLED;
@CommandLine.Option(
names = {LAYERED_TX_POOL_LAYER_MAX_CAPACITY},
paramLabel = "<Long>",
hidden = true,
description =
"Max amount of memory space, in bytes, that any layer within the transaction pool could occupy (default: ${DEFAULT-VALUE})",
arity = "1")
private long layeredTxPoolLayerMaxCapacity =
TransactionPoolConfiguration.DEFAULT_PENDING_TRANSACTIONS_LAYER_MAX_CAPACITY_BYTES;
@CommandLine.Option(
names = {LAYERED_TX_POOL_MAX_PRIORITIZED},
paramLabel = "<Int>",
hidden = true,
description =
"Max number of pending transactions that are prioritized and thus kept sorted (default: ${DEFAULT-VALUE})",
arity = "1")
private int layeredTxPoolMaxPrioritized =
TransactionPoolConfiguration.DEFAULT_MAX_PRIORITIZED_TRANSACTIONS;
@CommandLine.Option(
names = {LAYERED_TX_POOL_MAX_FUTURE_BY_SENDER},
paramLabel = "<Int>",
hidden = true,
description =
"Max number of future pending transactions allowed for a single sender (default: ${DEFAULT-VALUE})",
arity = "1")
private int layeredTxPoolMaxFutureBySender =
TransactionPoolConfiguration.DEFAULT_MAX_FUTURE_BY_SENDER;
private TransactionPoolOptions() {}
@ -71,24 +134,51 @@ public class TransactionPoolOptions implements CLIOptions<TransactionPoolConfigu
* @param config the Transaction Pool Configuration
* @return the transaction pool options
*/
public static TransactionPoolOptions fromConfig(
final TransactionPoolConfiguration.Unstable config) {
public static TransactionPoolOptions fromConfig(final TransactionPoolConfiguration config) {
final TransactionPoolOptions options = TransactionPoolOptions.create();
options.txMessageKeepAliveSeconds = config.getTxMessageKeepAliveSeconds();
options.eth65TrxAnnouncedBufferingPeriod = config.getEth65TrxAnnouncedBufferingPeriod();
options.eth65TrxAnnouncedBufferingPeriod =
config.getEth65TrxAnnouncedBufferingPeriod().toMillis();
options.strictTxReplayProtectionEnabled = config.getStrictTransactionReplayProtectionEnabled();
options.layeredTxPoolEnabled = config.getLayeredTxPoolEnabled();
options.layeredTxPoolLayerMaxCapacity = config.getPendingTransactionsLayerMaxCapacityBytes();
options.layeredTxPoolMaxPrioritized = config.getMaxPrioritizedTransactions();
options.layeredTxPoolMaxFutureBySender = config.getMaxFutureBySender();
return options;
}
@Override
public TransactionPoolConfiguration.Unstable toDomainObject() {
return ImmutableTransactionPoolConfiguration.Unstable.builder()
public ImmutableTransactionPoolConfiguration.Builder toDomainObject() {
if (layeredTxPoolEnabled) {
LOG.warn(
"Layered transaction pool enabled, ignoring settings for "
+ "--tx-pool-max-size and --tx-pool-limit-by-account-percentage");
}
return ImmutableTransactionPoolConfiguration.builder()
.strictTransactionReplayProtectionEnabled(strictTxReplayProtectionEnabled)
.txMessageKeepAliveSeconds(txMessageKeepAliveSeconds)
.eth65TrxAnnouncedBufferingPeriod(eth65TrxAnnouncedBufferingPeriod)
.build();
.eth65TrxAnnouncedBufferingPeriod(Duration.ofMillis(eth65TrxAnnouncedBufferingPeriod))
.layeredTxPoolEnabled(layeredTxPoolEnabled)
.pendingTransactionsLayerMaxCapacityBytes(layeredTxPoolLayerMaxCapacity)
.maxPrioritizedTransactions(layeredTxPoolMaxPrioritized)
.maxFutureBySender(layeredTxPoolMaxFutureBySender);
}
@Override
public List<String> getCLIOptions() {
return CommandLineUtils.getCLIOptions(this, new TransactionPoolOptions());
return Arrays.asList(
STRICT_TX_REPLAY_PROTECTION_ENABLED_FLAG + "=" + strictTxReplayProtectionEnabled,
TX_MESSAGE_KEEP_ALIVE_SEC_FLAG,
OptionParser.format(txMessageKeepAliveSeconds),
ETH65_TX_ANNOUNCED_BUFFERING_PERIOD_FLAG,
OptionParser.format(eth65TrxAnnouncedBufferingPeriod),
LAYERED_TX_POOL_ENABLED_FLAG + "=" + layeredTxPoolEnabled,
LAYERED_TX_POOL_LAYER_MAX_CAPACITY,
OptionParser.format(layeredTxPoolLayerMaxCapacity),
LAYERED_TX_POOL_MAX_PRIORITIZED,
OptionParser.format(layeredTxPoolMaxPrioritized),
LAYERED_TX_POOL_MAX_FUTURE_BY_SENDER,
OptionParser.format(layeredTxPoolMaxFutureBySender));
}
}

@ -99,8 +99,6 @@ public class StorageSubCommand implements Runnable {
}
private StorageProvider getStorageProvider() {
// init collection of ignorable segments
parentCommand.parentCommand.setIgnorableStorageSegments();
return parentCommand.parentCommand.getStorageProvider();
}

@ -14,17 +14,10 @@
*/
package org.hyperledger.besu.cli.util;
import org.hyperledger.besu.cli.converter.TypeFormatter;
import org.hyperledger.besu.cli.options.OptionParser;
import org.hyperledger.besu.util.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.google.common.base.Strings;
@ -131,103 +124,6 @@ public class CommandLineUtils {
}
}
/**
* Return all the option names declared in a class. Note this will recursively check in any inner
* option class if present.
*
* @param optClass the class to look for options
* @return a list of option names found in the class
*/
public static List<String> getCLIOptionNames(final Class<?> optClass) {
final List<String> cliOpts = new ArrayList<>();
final Field[] fields = optClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Annotation ann = field.getAnnotation(CommandLine.Option.class);
if (ann != null) {
final var optAnn = CommandLine.Option.class.cast(ann);
cliOpts.add(optAnn.names()[0]);
} else {
ann = field.getAnnotation(CommandLine.ArgGroup.class);
if (ann != null) {
cliOpts.addAll(getCLIOptionNames(field.getType()));
}
}
}
return cliOpts;
}
/**
* Converts the runtime options into their CLI representation. Options with a value equals to its
* default are not included in the result since redundant. Note this will recursively check in any
* inner option class if present.
*
* @param currOptions the actual runtime options
* @param defaults the default option values
* @return a list of CLI arguments
*/
public static List<String> getCLIOptions(final Object currOptions, final Object defaults) {
final List<String> cliOpts = new ArrayList<>();
final Field[] fields = currOptions.getClass().getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
Annotation ann = field.getAnnotation(CommandLine.Option.class);
if (ann != null) {
try {
var optVal = field.get(currOptions);
if (!Objects.equals(optVal, field.get(defaults))) {
var optAnn = CommandLine.Option.class.cast(ann);
cliOpts.add(optAnn.names()[0]);
final var optConverter = optAnn.converter();
cliOpts.add(formatValue(optConverter, optVal));
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
} else {
ann = field.getAnnotation(CommandLine.ArgGroup.class);
if (ann != null) {
try {
cliOpts.addAll(getCLIOptions(field.get(currOptions), field.get(defaults)));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
return cliOpts;
}
/**
* There are different ways to format an option value back to its CLI form, the first is to use a
* {@link TypeFormatter} if present, otherwise the formatting it is delegated to {@link
* OptionParser#format(Object)}
*
* @param optConverter the list of converter types for the option
* @param optVal the value of the options
* @return a string with the CLI form of the value
*/
@SuppressWarnings("unchecked")
private static String formatValue(
final Class<? extends CommandLine.ITypeConverter<?>>[] optConverter, final Object optVal) {
return Arrays.stream(optConverter)
.filter(c -> Arrays.stream(c.getInterfaces()).anyMatch(i -> i.equals(TypeFormatter.class)))
.findFirst()
.map(
ctf -> {
try {
return (TypeFormatter) ctf.getDeclaredConstructor().newInstance();
} catch (InstantiationException
| IllegalAccessException
| InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
})
.map(tf -> tf.format(optVal))
.orElseGet(() -> OptionParser.format(optVal));
}
private static String getAffectedOptions(
final CommandLine commandLine, final List<String> dependentOptionsNames) {
return commandLine.getCommandSpec().options().stream()

@ -15,8 +15,6 @@
package org.hyperledger.besu.cli.util;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.util.number.Fraction;
import org.hyperledger.besu.util.number.Percentage;
import java.io.File;
import java.io.IOException;
@ -91,10 +89,6 @@ public class TomlConfigFileDefaultProvider implements IDefaultValueProvider {
defaultValue = getNumericEntryAsString(optionSpec);
} else if (optionSpec.type().equals(Float.class) || optionSpec.type().equals(float.class)) {
defaultValue = getNumericEntryAsString(optionSpec);
} else if (optionSpec.type().equals(Percentage.class)) {
defaultValue = getNumericEntryAsString(optionSpec);
} else if (optionSpec.type().equals(Fraction.class)) {
defaultValue = getNumericEntryAsString(optionSpec);
} else { // else will be treated as String
defaultValue = getEntryAsString(optionSpec);
}

@ -72,7 +72,6 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.util.Subscribers;
import java.util.HashMap;
@ -232,30 +231,7 @@ public class IbftBesuControllerBuilder extends BftBesuControllerBuilder {
blockCreatorFactory,
blockchain,
bftEventQueue);
if (syncState.isInitialSyncPhaseDone()) {
LOG.info("Starting IBFT mining coordinator");
ibftMiningCoordinator.enable();
ibftMiningCoordinator.start();
} else {
LOG.info("IBFT mining coordinator not starting while initial sync in progress");
}
syncState.subscribeCompletionReached(
new BesuEvents.InitialSyncCompletionListener() {
@Override
public void onInitialSyncCompleted() {
LOG.info("Starting IBFT mining coordinator following initial sync");
ibftMiningCoordinator.enable();
ibftMiningCoordinator.start();
}
@Override
public void onInitialSyncRestart() {
// Nothing to do. The mining coordinator won't be started until
// sync has completed.
}
});
ibftMiningCoordinator.enable();
return ibftMiningCoordinator;
}

@ -82,7 +82,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.util.Subscribers;
import java.util.HashMap;
@ -272,30 +271,7 @@ public class QbftBesuControllerBuilder extends BftBesuControllerBuilder {
blockCreatorFactory,
blockchain,
bftEventQueue);
if (syncState.isInitialSyncPhaseDone()) {
LOG.info("Starting QBFT mining coordinator");
miningCoordinator.enable();
miningCoordinator.start();
} else {
LOG.info("QBFT mining coordinator not starting while initial sync in progress");
}
syncState.subscribeCompletionReached(
new BesuEvents.InitialSyncCompletionListener() {
@Override
public void onInitialSyncCompleted() {
LOG.info("Starting QBFT mining coordinator following initial sync");
miningCoordinator.enable();
miningCoordinator.start();
}
@Override
public void onInitialSyncRestart() {
// Nothing to do. The mining coordinator won't be started until
// sync has completed.
}
});
miningCoordinator.enable();
return miningCoordinator;
}

@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.Unstable;
import org.hyperledger.besu.plugin.services.TraceService;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
@ -39,8 +38,6 @@ import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.LongStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -91,117 +88,61 @@ public class TraceServiceImpl implements TraceService {
block.ifPresent(value -> trace(value, tracer));
}
/**
* Traces range of blocks
*
* @param fromBlockNumber the beginning of the range (inclusive)
* @param toBlockNumber the end of the range (inclusive)
* @param beforeTracing Function which performs an operation on a MutableWorldState before tracing
* @param afterTracing Function which performs an operation on a MutableWorldState after tracing
* @param tracer an instance of OperationTracer
*/
@Override
public void trace(
final long fromBlockNumber,
final long toBlockNumber,
final Consumer<WorldUpdater> beforeTracing,
final Consumer<WorldUpdater> afterTracing,
final BlockAwareOperationTracer tracer) {
checkArgument(tracer != null);
LOG.debug("Tracing from block {} to block {}", fromBlockNumber, toBlockNumber);
final Blockchain blockchain = blockchainQueries.getBlockchain();
final List<Block> blocks =
LongStream.rangeClosed(fromBlockNumber, toBlockNumber)
.mapToObj(
number ->
blockchain
.getBlockByNumber(number)
.orElseThrow(() -> new RuntimeException("Block not found " + number)))
.toList();
Tracer.processTracing(
blockchainQueries,
blocks.get(0).getHash(),
traceableState -> {
final WorldUpdater worldStateUpdater = traceableState.updater();
final ChainUpdater chainUpdater = new ChainUpdater(traceableState, worldStateUpdater);
beforeTracing.accept(worldStateUpdater);
final List<TransactionProcessingResult> results = new ArrayList<>();
blocks.forEach(
block -> {
results.addAll(trace(blockchain, block, chainUpdater, tracer));
tracer.traceEndBlock(block.getHeader(), block.getBody());
});
afterTracing.accept(chainUpdater.getNextUpdater());
return Optional.of(results);
});
}
private void trace(final Block block, final BlockAwareOperationTracer tracer) {
LOG.debug("Tracing block {}", block.toLogString());
final Blockchain blockchain = blockchainQueries.getBlockchain();
final List<TransactionProcessingResult> results = new ArrayList<>();
Tracer.processTracing(
blockchainQueries,
block.getHash(),
traceableState ->
Optional.of(trace(blockchain, block, new ChainUpdater(traceableState), tracer)));
tracer.traceEndBlock(block.getHeader(), block.getBody());
}
private List<TransactionProcessingResult> trace(
final Blockchain blockchain,
final Block block,
final ChainUpdater chainUpdater,
final BlockAwareOperationTracer tracer) {
final List<TransactionProcessingResult> results = new ArrayList<>();
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(block.getHeader());
final MainnetTransactionProcessor transactionProcessor = protocolSpec.getTransactionProcessor();
final BlockHeader header = block.getHeader();
tracer.traceStartBlock(block.getHeader(), block.getBody());
block
.getBody()
.getTransactions()
.forEach(
transaction -> {
final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(header.getParentHash());
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.blobGasPricePerGas(
maybeParentHeader
.map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
final WorldUpdater worldUpdater = chainUpdater.getNextUpdater();
tracer.traceStartTransaction(worldUpdater, transaction);
final TransactionProcessingResult result =
transactionProcessor.processTransaction(
blockchain,
worldUpdater,
header,
transaction,
header.getCoinbase(),
tracer,
new CachingBlockHashLookup(header, blockchain),
false,
blobGasPrice);
long transactionGasUsed = transaction.getGasLimit() - result.getGasRemaining();
tracer.traceEndTransaction(
worldUpdater,
transaction,
result.isSuccessful(),
result.getOutput(),
result.getLogs(),
transactionGasUsed,
0);
results.add(result);
});
traceableState -> {
final Blockchain blockchain = blockchainQueries.getBlockchain();
final ChainUpdater chainUpdater = new ChainUpdater(traceableState);
final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(block.getHeader());
final MainnetTransactionProcessor transactionProcessor =
protocolSpec.getTransactionProcessor();
final BlockHeader header = block.getHeader();
tracer.traceStartBlock(block.getHeader(), block.getBody());
block
.getBody()
.getTransactions()
.forEach(
transaction -> {
final Optional<BlockHeader> maybeParentHeader =
blockchain.getBlockHeader(header.getParentHash());
final Wei blobGasPrice =
protocolSpec
.getFeeMarket()
.blobGasPricePerGas(
maybeParentHeader
.map(
parent ->
calculateExcessBlobGasForParent(protocolSpec, parent))
.orElse(BlobGas.ZERO));
tracer.traceStartTransaction(transaction);
final TransactionProcessingResult result =
transactionProcessor.processTransaction(
blockchain,
chainUpdater.getNextUpdater(),
header,
transaction,
header.getCoinbase(),
tracer,
new CachingBlockHashLookup(header, blockchain),
false,
blobGasPrice);
long transactionGasUsed = transaction.getGasLimit() - result.getGasRemaining();
tracer.traceEndTransaction(result.getOutput(), transactionGasUsed, 0);
results.add(result);
});
return Optional.of(results);
});
tracer.traceEndBlock(block.getHeader(), block.getBody());
return results;
}
}

@ -130,6 +130,17 @@ public class ForkIdsNetworkConfigTest {
new ForkId(Bytes.ofUnsignedInt(0x8c9b1797L), 0L),
new ForkId(Bytes.ofUnsignedInt(0x8c9b1797L), 0L))
},
new Object[] {
NetworkName.KOTTI,
List.of(
new ForkId(Bytes.ofUnsignedInt(0x550152eL), 716617L),
new ForkId(Bytes.ofUnsignedInt(0xa3270822L), 1705549L),
new ForkId(Bytes.ofUnsignedInt(0x8f3698e0L), 2200013L),
new ForkId(Bytes.ofUnsignedInt(0x6f402821L), 4368634),
new ForkId(Bytes.ofUnsignedInt(0xf03e54e7L), 5578000L),
new ForkId(Bytes.ofUnsignedInt(0xc5459816L), 0L),
new ForkId(Bytes.ofUnsignedInt(0xc5459816L), 0L))
},
new Object[] {
NetworkName.CLASSIC,
List.of(

@ -25,6 +25,7 @@ import static org.hyperledger.besu.cli.config.NetworkName.EXPERIMENTAL_EIPS;
import static org.hyperledger.besu.cli.config.NetworkName.FUTURE_EIPS;
import static org.hyperledger.besu.cli.config.NetworkName.GOERLI;
import static org.hyperledger.besu.cli.config.NetworkName.HOLESKY;
import static org.hyperledger.besu.cli.config.NetworkName.KOTTI;
import static org.hyperledger.besu.cli.config.NetworkName.MAINNET;
import static org.hyperledger.besu.cli.config.NetworkName.MORDOR;
import static org.hyperledger.besu.cli.config.NetworkName.SEPOLIA;
@ -58,6 +59,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.BesuInfo;
import org.hyperledger.besu.cli.config.EthNetworkConfig;
import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions;
import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.MergeConfigOptions;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
@ -4107,6 +4109,22 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void kottiValuesAreUsed() throws Exception {
parseCommand("--network", "kotti");
final ArgumentCaptor<EthNetworkConfig> networkArg =
ArgumentCaptor.forClass(EthNetworkConfig.class);
verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any(), any());
verify(mockControllerBuilder).build();
assertThat(networkArg.getValue()).isEqualTo(EthNetworkConfig.getNetworkConfig(KOTTI));
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void mordorValuesAreUsed() throws Exception {
parseCommand("--network", "mordor");
@ -4148,6 +4166,11 @@ public class BesuCommandTest extends CommandTestAbstract {
networkValuesCanBeOverridden("classic");
}
@Test
public void kottiValuesCanBeOverridden() throws Exception {
networkValuesCanBeOverridden("kotti");
}
@Test
public void mordorValuesCanBeOverridden() throws Exception {
networkValuesCanBeOverridden("mordor");
@ -4596,6 +4619,192 @@ public class BesuCommandTest extends CommandTestAbstract {
.contains(staticNodeURI.toString(), "not in nodes-allowlist");
}
@Test
public void disableLocalsDefault() {
parseCommand();
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getDisableLocalTransactions()).isFalse();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void disableLocalsOn() {
parseCommand("--tx-pool-disable-locals=true");
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getDisableLocalTransactions()).isTrue();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void disableLocalsOff() {
parseCommand("--tx-pool-disable-locals=false");
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getDisableLocalTransactions()).isFalse();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void saveToFileDisabledByDefault() {
parseCommand();
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getEnableSaveRestore()).isFalse();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void saveToFileEnabledDefaultPath() {
parseCommand("--tx-pool-enable-save-restore=true");
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getEnableSaveRestore()).isTrue();
assertThat(transactionPoolConfigCaptor.getValue().getSaveFile())
.hasName(TransactionPoolConfiguration.DEFAULT_SAVE_FILE_NAME);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void saveToFileEnabledCustomPath() {
parseCommand("--tx-pool-enable-save-restore=true", "--tx-pool-save-file=my.save.file");
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getEnableSaveRestore()).isTrue();
assertThat(transactionPoolConfigCaptor.getValue().getSaveFile()).hasName("my.save.file");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void senderLimitedTxPool_derived() {
parseCommand("--tx-pool-limit-by-account-percentage=0.002");
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getTxPoolMaxFutureTransactionByAccount())
.isEqualTo(9);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void senderLimitedTxPoolFloor_derived() {
parseCommand("--tx-pool-limit-by-account-percentage=0.0001");
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getTxPoolMaxFutureTransactionByAccount())
.isEqualTo(1);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void senderLimitedTxPoolCeiling_violated() {
TestBesuCommand commandTest = parseCommand("--tx-pool-limit-by-account-percentage=1.00002341");
TransactionPoolOptions txPoolOption = commandTest.getTransactionPoolOptions();
final TransactionPoolConfiguration config = txPoolOption.toDomainObject().build();
assertThat(config.getTxPoolLimitByAccountPercentage())
.isEqualTo(TransactionPoolConfiguration.DEFAULT_LIMIT_TX_POOL_BY_ACCOUNT_PERCENTAGE);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
.contains("Invalid value for option '--tx-pool-limit-by-account-percentage'");
}
@Test
public void pendingTransactionRetentionPeriod() {
final int pendingTxRetentionHours = 999;
parseCommand("--tx-pool-retention-hours", String.valueOf(pendingTxRetentionHours));
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getPendingTxRetentionPeriod())
.isEqualTo(pendingTxRetentionHours);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void transactionPoolPriceBump() {
final Percentage priceBump = Percentage.fromInt(13);
parseCommand("--tx-pool-price-bump", priceBump.toString());
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getPriceBump()).isEqualTo(priceBump);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void invalidTansactionPoolPriceBumpShouldFail() {
parseCommand("--tx-pool-price-bump", "101");
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"Invalid value for option '--tx-pool-price-bump'",
"should be a number between 0 and 100 inclusive");
}
@Test
public void transactionPoolTxFeeCap() {
final Wei txFeeCap = Wei.fromEth(2);
parseCommand("--rpc-tx-feecap", txFeeCap.toDecimalString());
verify(mockControllerBuilder)
.transactionPoolConfiguration(transactionPoolConfigCaptor.capture());
assertThat(transactionPoolConfigCaptor.getValue().getTxFeeCap()).isEqualTo(txFeeCap);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void invalidTansactionPoolTxFeeCapShouldFail() {
parseCommand("--rpc-tx-feecap", "abcd");
assertThat(commandErrorOutput.toString(UTF_8))
.contains("Invalid value for option '--rpc-tx-feecap'", "cannot convert 'abcd' to Wei");
}
@Test
public void txMessageKeepAliveSecondsWithInvalidInputShouldFail() {
parseCommand("--Xincoming-tx-messages-keep-alive-seconds", "acbd");
Mockito.verifyNoInteractions(mockRunnerBuilder);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"Invalid value for option '--Xincoming-tx-messages-keep-alive-seconds': 'acbd' is not an int");
}
@Test
public void eth65TrxAnnouncedBufferingPeriodWithInvalidInputShouldFail() {
parseCommand("--Xeth65-tx-announced-buffering-period-milliseconds", "acbd");
Mockito.verifyNoInteractions(mockRunnerBuilder);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"Invalid value for option '--Xeth65-tx-announced-buffering-period-milliseconds': 'acbd' is not a long");
}
@Test
public void tomlThatHasInvalidOptions() throws IOException {
final URL configFile = this.getClass().getResource("/complete_config.toml");

@ -519,12 +519,7 @@ public abstract class CommandTestAbstract {
return unstableEthProtocolOptions;
}
public org.hyperledger.besu.cli.options.stable.TransactionPoolOptions
getStableTransactionPoolOptions() {
return stableTransactionPoolOptions;
}
public TransactionPoolOptions getUnstableTransactionPoolOptions() {
public TransactionPoolOptions getTransactionPoolOptions() {
return unstableTransactionPoolOptions;
}

@ -15,8 +15,6 @@
package org.hyperledger.besu.cli;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LAYERED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LEGACY;
import static org.mockito.Mockito.mock;
import java.math.BigInteger;
@ -147,16 +145,14 @@ class ConfigurationOverviewBuilderTest {
}
@Test
void setTxPoolImplementationLayered() {
builder.setTxPoolImplementation(LAYERED);
final String layeredTxPoolSelected = builder.build();
assertThat(layeredTxPoolSelected).contains("Using LAYERED transaction pool implementation");
}
@Test
void setTxPoolImplementationLegacy() {
builder.setTxPoolImplementation(LEGACY);
final String legacyTxPoolSelected = builder.build();
assertThat(legacyTxPoolSelected).contains("Using LEGACY transaction pool implementation");
void setLayeredTxPoolEnabled() {
final String layeredTxPoolDisabled = builder.build();
assertThat(layeredTxPoolDisabled)
.doesNotContain("Experimental layered transaction pool configuration enabled");
builder.setLayeredTxPoolEnabled();
final String layeredTxPoolEnabled = builder.build();
assertThat(layeredTxPoolEnabled)
.contains("Experimental layered transaction pool configuration enabled");
}
}

@ -39,7 +39,7 @@ class NetworkDeprecationMessageTest {
@EnumSource(
value = NetworkName.class,
names = {
"MAINNET", "SEPOLIA", "GOERLI", "DEV", "CLASSIC", "MORDOR", "HOLESKY",
"MAINNET", "SEPOLIA", "GOERLI", "DEV", "CLASSIC", "KOTTI", "MORDOR", "HOLESKY",
})
void shouldThrowErrorForNonDeprecatedNetworks(final NetworkName network) {
assertThatThrownBy(() -> NetworkDeprecationMessage.generate(network))

@ -18,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import org.hyperledger.besu.cli.converter.exception.FractionConversionException;
import org.hyperledger.besu.util.number.Fraction;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -31,9 +30,9 @@ public class FractionConverterTest {
@Test
public void assertThatConvertHandlesProperlyAValidString() throws FractionConversionException {
final Fraction fraction = fractionConverter.convert("0.58");
final float fraction = fractionConverter.convert("0.58");
assertThat(fraction).isNotNull();
assertThat(fraction.getValue()).isEqualTo(0.58f);
assertThat(fraction).isEqualTo(0.58f);
}
@Test

@ -18,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import org.hyperledger.besu.cli.converter.exception.PercentageConversionException;
import org.hyperledger.besu.util.number.Percentage;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -31,9 +30,9 @@ public class PercentageConverterTest {
@Test
public void assertThatConvertHandlesProperlyAValidString() throws PercentageConversionException {
final Percentage percentage = percentageConverter.convert("58");
final int percentage = percentageConverter.convert("58");
assertThat(percentage).isNotNull();
assertThat(percentage.getValue()).isEqualTo(58);
assertThat(percentage).isEqualTo(58);
}
@Test

@ -21,7 +21,6 @@ import org.hyperledger.besu.cli.CommandTestAbstract;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import org.junit.Test;
@ -88,9 +87,9 @@ public abstract class AbstractCLIOptionsTest<D, T extends CLIOptions<D>>
.isEqualTo(defaultOptions);
}
protected abstract D createDefaultDomainObject();
abstract D createDefaultDomainObject();
protected abstract D createCustomizedDomainObject();
abstract D createCustomizedDomainObject();
protected List<String> getFieldsWithComputedDefaults() {
return Collections.emptyList();
@ -100,25 +99,7 @@ public abstract class AbstractCLIOptionsTest<D, T extends CLIOptions<D>>
return Collections.emptyList();
}
protected abstract T optionsFromDomainObject(D domainObject);
abstract T optionsFromDomainObject(D domainObject);
protected abstract T getOptionsFromBesuCommand(final TestBesuCommand besuCommand);
protected void internalTestSuccess(final Consumer<D> assertion, final String... args) {
final TestBesuCommand cmd = parseCommand(args);
final T options = getOptionsFromBesuCommand(cmd);
final D config = options.toDomainObject();
assertion.accept(config);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
protected void internalTestFailure(final String errorMsg, final String... args) {
parseCommand(args);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).contains(errorMsg);
}
abstract T getOptionsFromBesuCommand(final TestBesuCommand besuCommand);
}

@ -165,12 +165,12 @@ public class EthProtocolOptionsTest
}
@Override
protected EthProtocolConfiguration createDefaultDomainObject() {
EthProtocolConfiguration createDefaultDomainObject() {
return EthProtocolConfiguration.builder().build();
}
@Override
protected EthProtocolConfiguration createCustomizedDomainObject() {
EthProtocolConfiguration createCustomizedDomainObject() {
return EthProtocolConfiguration.builder()
.maxMessageSize(EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE * 2)
.maxGetBlockHeaders(EthProtocolConfiguration.DEFAULT_MAX_GET_BLOCK_HEADERS + 2)
@ -184,13 +184,12 @@ public class EthProtocolOptionsTest
}
@Override
protected EthProtocolOptions optionsFromDomainObject(
final EthProtocolConfiguration domainObject) {
EthProtocolOptions optionsFromDomainObject(final EthProtocolConfiguration domainObject) {
return EthProtocolOptions.fromConfig(domainObject);
}
@Override
protected EthProtocolOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
EthProtocolOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getEthProtocolOptions();
}
}

@ -25,25 +25,24 @@ public class MetricsCLIOptionsTest
extends AbstractCLIOptionsTest<MetricsConfiguration.Builder, MetricsCLIOptions> {
@Override
protected MetricsConfiguration.Builder createDefaultDomainObject() {
MetricsConfiguration.Builder createDefaultDomainObject() {
return MetricsConfiguration.builder();
}
@Override
protected MetricsConfiguration.Builder createCustomizedDomainObject() {
MetricsConfiguration.Builder createCustomizedDomainObject() {
return MetricsConfiguration.builder()
.timersEnabled(!MetricsConfiguration.DEFAULT_METRICS_TIMERS_ENABLED)
.idleTimeout(MetricsConfiguration.DEFAULT_METRICS_IDLE_TIMEOUT_SECONDS);
}
@Override
protected MetricsCLIOptions optionsFromDomainObject(
final MetricsConfiguration.Builder domainObject) {
MetricsCLIOptions optionsFromDomainObject(final MetricsConfiguration.Builder domainObject) {
return MetricsCLIOptions.fromConfiguration(domainObject.build());
}
@Override
protected MetricsCLIOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
MetricsCLIOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getMetricsCLIOptions();
}
}

@ -165,12 +165,12 @@ public class NetworkingOptionsTest
}
@Override
protected NetworkingConfiguration createDefaultDomainObject() {
NetworkingConfiguration createDefaultDomainObject() {
return NetworkingConfiguration.create();
}
@Override
protected NetworkingConfiguration createCustomizedDomainObject() {
NetworkingConfiguration createCustomizedDomainObject() {
final NetworkingConfiguration config = NetworkingConfiguration.create();
config.setInitiateConnectionsFrequency(
NetworkingConfiguration.DEFAULT_INITIATE_CONNECTIONS_FREQUENCY_SEC + 10);
@ -181,12 +181,12 @@ public class NetworkingOptionsTest
}
@Override
protected NetworkingOptions optionsFromDomainObject(final NetworkingConfiguration domainObject) {
NetworkingOptions optionsFromDomainObject(final NetworkingConfiguration domainObject) {
return NetworkingOptions.fromConfig(domainObject);
}
@Override
protected NetworkingOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
NetworkingOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getNetworkingOptions();
}

@ -104,25 +104,4 @@ public class OptionParserTest {
final String expected = "-1233";
assertThat(OptionParser.format(input)).isEqualTo(expected);
}
@Test
public void format_object_int() {
final Object input = 1233;
final String expected = "1233";
assertThat(OptionParser.format(input)).isEqualTo(expected);
}
@Test
public void format_object_Integer() {
final Object input = Integer.valueOf(1233);
final String expected = "1233";
assertThat(OptionParser.format(input)).isEqualTo(expected);
}
@Test
public void format_object_uint256() {
final Object input = UInt256.valueOf(new BigInteger("123456789", 10));
final String expected = "123456789";
assertThat(OptionParser.format(input)).isEqualTo(expected);
}
}

@ -31,12 +31,12 @@ public class SynchronizerOptionsTest
extends AbstractCLIOptionsTest<SynchronizerConfiguration.Builder, SynchronizerOptions> {
@Override
protected SynchronizerConfiguration.Builder createDefaultDomainObject() {
SynchronizerConfiguration.Builder createDefaultDomainObject() {
return SynchronizerConfiguration.builder();
}
@Override
protected SynchronizerConfiguration.Builder createCustomizedDomainObject() {
SynchronizerConfiguration.Builder createCustomizedDomainObject() {
return SynchronizerConfiguration.builder()
.fastSyncPivotDistance(SynchronizerConfiguration.DEFAULT_PIVOT_DISTANCE_FROM_HEAD + 10)
.fastSyncFullValidationRate(SynchronizerConfiguration.DEFAULT_FULL_VALIDATION_RATE / 2)
@ -87,7 +87,7 @@ public class SynchronizerOptionsTest
}
@Override
protected SynchronizerOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
SynchronizerOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getSynchronizerOptions();
}
@ -97,7 +97,7 @@ public class SynchronizerOptionsTest
}
@Override
protected SynchronizerOptions optionsFromDomainObject(
SynchronizerOptions optionsFromDomainObject(
final SynchronizerConfiguration.Builder domainObject) {
return SynchronizerOptions.fromConfig(domainObject.build());
}

@ -0,0 +1,155 @@
/*
* Copyright ConsenSys AG.
*
* 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.cli.options;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.cli.options.unstable.TransactionPoolOptions;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import java.time.Duration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class TransactionPoolOptionsTest
extends AbstractCLIOptionsTest<
ImmutableTransactionPoolConfiguration.Builder, TransactionPoolOptions> {
@Test
public void strictTxReplayProtection_enabled() {
final TestBesuCommand cmd = parseCommand("--strict-tx-replay-protection-enabled");
final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd);
final TransactionPoolConfiguration config = options.toDomainObject().build();
assertThat(config.getStrictTransactionReplayProtectionEnabled()).isTrue();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void strictTxReplayProtection_enabledWithBooleanArg() {
final TestBesuCommand cmd = parseCommand("--strict-tx-replay-protection-enabled=true");
final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd);
final TransactionPoolConfiguration config = options.toDomainObject().build();
assertThat(config.getStrictTransactionReplayProtectionEnabled()).isTrue();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void strictTxReplayProtection_disabled() {
final TestBesuCommand cmd = parseCommand("--strict-tx-replay-protection-enabled=false");
final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd);
final TransactionPoolConfiguration config = options.toDomainObject().build();
assertThat(config.getStrictTransactionReplayProtectionEnabled()).isFalse();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void strictTxReplayProtection_default() {
final TestBesuCommand cmd = parseCommand();
final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd);
final TransactionPoolConfiguration config = options.toDomainObject().build();
assertThat(config.getStrictTransactionReplayProtectionEnabled()).isFalse();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void txMessageKeepAliveSeconds() {
final int txMessageKeepAliveSeconds = 999;
final TestBesuCommand cmd =
parseCommand(
"--Xincoming-tx-messages-keep-alive-seconds",
String.valueOf(txMessageKeepAliveSeconds));
final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd);
final TransactionPoolConfiguration config = options.toDomainObject().build();
assertThat(config.getTxMessageKeepAliveSeconds()).isEqualTo(txMessageKeepAliveSeconds);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void eth65TrxAnnouncedBufferingPeriod() {
final long eth65TrxAnnouncedBufferingPeriod = 999;
final TestBesuCommand cmd =
parseCommand(
"--Xeth65-tx-announced-buffering-period-milliseconds",
String.valueOf(eth65TrxAnnouncedBufferingPeriod));
final TransactionPoolOptions options = getOptionsFromBesuCommand(cmd);
final TransactionPoolConfiguration config = options.toDomainObject().build();
assertThat(config.getEth65TrxAnnouncedBufferingPeriod())
.hasMillis(eth65TrxAnnouncedBufferingPeriod);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Override
ImmutableTransactionPoolConfiguration.Builder createDefaultDomainObject() {
final ImmutableTransactionPoolConfiguration defaultValue =
ImmutableTransactionPoolConfiguration.builder().build();
return ImmutableTransactionPoolConfiguration.builder()
.strictTransactionReplayProtectionEnabled(false)
.txMessageKeepAliveSeconds(defaultValue.getTxMessageKeepAliveSeconds())
.eth65TrxAnnouncedBufferingPeriod(defaultValue.getEth65TrxAnnouncedBufferingPeriod())
.layeredTxPoolEnabled(defaultValue.getLayeredTxPoolEnabled())
.pendingTransactionsLayerMaxCapacityBytes(
defaultValue.getPendingTransactionsLayerMaxCapacityBytes())
.maxPrioritizedTransactions(defaultValue.getMaxPrioritizedTransactions())
.maxFutureBySender(defaultValue.getMaxFutureBySender());
}
@Override
ImmutableTransactionPoolConfiguration.Builder createCustomizedDomainObject() {
return ImmutableTransactionPoolConfiguration.builder()
.strictTransactionReplayProtectionEnabled(true)
.txMessageKeepAliveSeconds(TransactionPoolConfiguration.DEFAULT_TX_MSG_KEEP_ALIVE + 1)
.eth65TrxAnnouncedBufferingPeriod(
TransactionPoolConfiguration.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD.plus(
Duration.ofMillis(100)))
.layeredTxPoolEnabled(true)
.pendingTransactionsLayerMaxCapacityBytes(1_000_000L)
.maxPrioritizedTransactions(1000)
.maxFutureBySender(10);
}
@Override
TransactionPoolOptions optionsFromDomainObject(
final ImmutableTransactionPoolConfiguration.Builder domainObject) {
return TransactionPoolOptions.fromConfig(domainObject.build());
}
@Override
TransactionPoolOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getTransactionPoolOptions();
}
}

@ -1,243 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.cli.options.stable;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LAYERED;
import static org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration.Implementation.LEGACY;
import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest;
import org.hyperledger.besu.cli.options.OptionParser;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.util.number.Percentage;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class TransactionPoolOptionsTest
extends AbstractCLIOptionsTest<TransactionPoolConfiguration, TransactionPoolOptions> {
@Test
public void strictTxReplayProtection_enabled() {
internalTestSuccess(
config -> assertThat(config.getStrictTransactionReplayProtectionEnabled()).isTrue(),
"--strict-tx-replay-protection-enabled");
}
@Test
public void strictTxReplayProtection_enabledWithBooleanArg() {
internalTestSuccess(
config -> assertThat(config.getStrictTransactionReplayProtectionEnabled()).isTrue(),
"--strict-tx-replay-protection-enabled=true");
}
@Test
public void strictTxReplayProtection_disabled() {
internalTestSuccess(
config -> assertThat(config.getStrictTransactionReplayProtectionEnabled()).isFalse(),
"--strict-tx-replay-protection-enabled=false");
}
@Test
public void strictTxReplayProtection_default() {
internalTestSuccess(
config -> assertThat(config.getStrictTransactionReplayProtectionEnabled()).isFalse());
}
@Test
public void pendingTransactionRetentionPeriod() {
final int pendingTxRetentionHours = 999;
internalTestSuccess(
config ->
assertThat(config.getPendingTxRetentionPeriod()).isEqualTo(pendingTxRetentionHours),
"--tx-pool-retention-hours",
String.valueOf(pendingTxRetentionHours),
"--tx-pool=legacy");
}
@Test
public void disableLocalsDefault() {
internalTestSuccess(config -> assertThat(config.getDisableLocalTransactions()).isFalse());
}
@Test
public void disableLocalsOn() {
internalTestSuccess(
config -> assertThat(config.getDisableLocalTransactions()).isTrue(),
"--tx-pool-disable-locals=true");
}
@Test
public void disableLocalsOff() {
internalTestSuccess(
config -> assertThat(config.getDisableLocalTransactions()).isFalse(),
"--tx-pool-disable-locals=false");
}
@Test
public void saveToFileDisabledByDefault() {
internalTestSuccess(config -> assertThat(config.getEnableSaveRestore()).isFalse());
}
@Test
public void saveToFileEnabledDefaultPath() {
internalTestSuccess(
config -> assertThat(config.getEnableSaveRestore()).isTrue(),
"--tx-pool-enable-save-restore=true");
}
@Test
public void saveToFileEnabledCustomPath() {
internalTestSuccess(
config -> {
assertThat(config.getEnableSaveRestore()).isTrue();
assertThat(config.getSaveFile()).hasName("my.save.file");
},
"--tx-pool-enable-save-restore=true",
"--tx-pool-save-file=my.save.file");
}
@Test
public void senderLimited_derived() {
internalTestSuccess(
config -> assertThat(config.getTxPoolMaxFutureTransactionByAccount()).isEqualTo(9),
"--tx-pool-limit-by-account-percentage=0.002",
"--tx-pool=legacy");
}
@Test
public void senderLimitedFloor_derived() {
internalTestSuccess(
config -> assertThat(config.getTxPoolMaxFutureTransactionByAccount()).isEqualTo(1),
"--tx-pool-limit-by-account-percentage=0.0001",
"--tx-pool=legacy");
}
@Test
public void senderLimitedCeiling_violated() {
internalTestFailure(
"Invalid value for option '--tx-pool-limit-by-account-percentage'",
"--tx-pool-limit-by-account-percentage=1.00002341",
"--tx-pool=legacy");
}
@Test
public void priceBump() {
final Percentage priceBump = Percentage.fromInt(13);
internalTestSuccess(
config -> assertThat(config.getPriceBump()).isEqualTo(priceBump),
"--tx-pool-price-bump",
priceBump.toString());
}
@Test
public void invalidPriceBumpShouldFail() {
internalTestFailure(
"Invalid value: 101, should be a number between 0 and 100 inclusive",
"--tx-pool-price-bump",
"101");
}
@Test
public void txFeeCap() {
final Wei txFeeCap = Wei.fromEth(2);
internalTestSuccess(
config -> assertThat(config.getTxFeeCap()).isEqualTo(txFeeCap),
"--rpc-tx-feecap",
OptionParser.format(txFeeCap));
}
@Test
public void invalidTxFeeCapShouldFail() {
internalTestFailure(
"Invalid value for option '--rpc-tx-feecap'",
"cannot convert 'abcd' to Wei",
"--rpc-tx-feecap",
"abcd");
}
@Test
public void selectLayeredImplementationByDefault() {
internalTestSuccess(config -> assertThat(config.getTxPoolImplementation()).isEqualTo(LAYERED));
}
@Test
public void selectLayeredImplementationByArg() {
internalTestSuccess(
config -> assertThat(config.getTxPoolImplementation()).isEqualTo(LAYERED),
"--tx-pool=layered");
}
@Test
public void selectLegacyImplementationByArg() {
internalTestSuccess(
config -> assertThat(config.getTxPoolImplementation()).isEqualTo(LEGACY),
"--tx-pool=legacy");
}
@Test
public void failIfLegacyOptionsWhenLayeredSelectedByDefault() {
internalTestFailure(
"Could not use legacy transaction pool options with layered implementation",
"--tx-pool-max-size=1000");
}
@Test
public void failIfLegacyOptionsWhenLayeredSelectedByArg() {
internalTestFailure(
"Could not use legacy transaction pool options with layered implementation",
"--tx-pool=layered",
"--tx-pool-max-size=1000");
}
@Test
public void failIfLayeredOptionsWhenLegacySelectedByArg() {
internalTestFailure(
"Could not use layered transaction pool options with legacy implementation",
"--tx-pool=legacy",
"--tx-pool-max-prioritized=1000");
}
@Override
protected TransactionPoolConfiguration createDefaultDomainObject() {
return TransactionPoolConfiguration.DEFAULT;
}
@Override
protected TransactionPoolConfiguration createCustomizedDomainObject() {
return ImmutableTransactionPoolConfiguration.builder()
.strictTransactionReplayProtectionEnabled(true)
.txPoolImplementation(LAYERED)
.pendingTransactionsLayerMaxCapacityBytes(1_000_000L)
.maxPrioritizedTransactions(1000)
.maxFutureBySender(10)
.build();
}
@Override
protected TransactionPoolOptions optionsFromDomainObject(
final TransactionPoolConfiguration domainObject) {
return TransactionPoolOptions.fromConfig(domainObject);
}
@Override
protected TransactionPoolOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getStableTransactionPoolOptions();
}
}

@ -1,105 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.cli.options.unstable;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.cli.converter.DurationMillisConverter;
import org.hyperledger.besu.cli.options.AbstractCLIOptionsTest;
import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import java.time.Duration;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class TransactionPoolOptionsTest
extends AbstractCLIOptionsTest<TransactionPoolConfiguration.Unstable, TransactionPoolOptions> {
@Test
public void txMessageKeepAliveSeconds() {
final int txMessageKeepAliveSeconds = 999;
internalTestSuccess(
config ->
assertThat(config.getTxMessageKeepAliveSeconds()).isEqualTo(txMessageKeepAliveSeconds),
"--Xincoming-tx-messages-keep-alive-seconds",
String.valueOf(txMessageKeepAliveSeconds));
}
@Test
public void txMessageKeepAliveSecondsWithInvalidInputShouldFail() {
internalTestFailure(
"Invalid value for option '--Xincoming-tx-messages-keep-alive-seconds': 'acbd' is not an int",
"--Xincoming-tx-messages-keep-alive-seconds",
"acbd");
}
@Test
public void eth65TrxAnnouncedBufferingPeriod() {
final Duration eth65TrxAnnouncedBufferingPeriod = Duration.ofMillis(999);
internalTestSuccess(
config ->
assertThat(config.getEth65TrxAnnouncedBufferingPeriod())
.isEqualTo(eth65TrxAnnouncedBufferingPeriod),
"--Xeth65-tx-announced-buffering-period-milliseconds",
new DurationMillisConverter().format(eth65TrxAnnouncedBufferingPeriod));
}
@Test
public void eth65TrxAnnouncedBufferingPeriodWithInvalidInputShouldFail() {
internalTestFailure(
"Invalid value for option '--Xeth65-tx-announced-buffering-period-milliseconds': cannot convert 'acbd' to Duration (org.hyperledger.besu.cli.converter.exception.DurationConversionException: 'acbd' is not a long)",
"--Xeth65-tx-announced-buffering-period-milliseconds",
"acbd");
}
@Test
public void eth65TrxAnnouncedBufferingPeriodWithInvalidInputShouldFail2() {
internalTestFailure(
"Invalid value for option '--Xeth65-tx-announced-buffering-period-milliseconds': cannot convert '-1' to Duration (org.hyperledger.besu.cli.converter.exception.DurationConversionException: negative value '-1' is not allowed)",
"--Xeth65-tx-announced-buffering-period-milliseconds",
"-1");
}
@Override
protected TransactionPoolConfiguration.Unstable createDefaultDomainObject() {
return TransactionPoolConfiguration.Unstable.DEFAULT;
}
@Override
protected TransactionPoolConfiguration.Unstable createCustomizedDomainObject() {
return ImmutableTransactionPoolConfiguration.Unstable.builder()
.txMessageKeepAliveSeconds(
TransactionPoolConfiguration.Unstable.DEFAULT_TX_MSG_KEEP_ALIVE + 1)
.eth65TrxAnnouncedBufferingPeriod(
TransactionPoolConfiguration.Unstable.ETH65_TRX_ANNOUNCED_BUFFERING_PERIOD.plus(
Duration.ofMillis(100)))
.build();
}
@Override
protected TransactionPoolOptions optionsFromDomainObject(
final TransactionPoolConfiguration.Unstable domainObject) {
return TransactionPoolOptions.fromConfig(domainObject);
}
@Override
protected TransactionPoolOptions getOptionsFromBesuCommand(final TestBesuCommand besuCommand) {
return besuCommand.getUnstableTransactionPoolOptions();
}
}

@ -15,6 +15,7 @@
package org.hyperledger.besu.controller;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@ -54,7 +55,6 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import java.math.BigInteger;
@ -85,17 +85,16 @@ public class BesuControllerBuilderTest {
@Mock SynchronizerConfiguration synchronizerConfiguration;
@Mock EthProtocolConfiguration ethProtocolConfiguration;
@Mock MiningParameters miningParameters;
@Mock ObservableMetricsSystem observableMetricsSystem;
@Mock PrivacyParameters privacyParameters;
@Mock Clock clock;
@Mock TransactionPoolConfiguration poolConfiguration;
@Mock StorageProvider storageProvider;
@Mock GasLimitCalculator gasLimitCalculator;
@Mock WorldStateStorage worldStateStorage;
@Mock WorldStateArchive worldStateArchive;
@Mock BonsaiWorldStateKeyValueStorage bonsaiWorldStateStorage;
@Mock WorldStatePreimageStorage worldStatePreimageStorage;
private final TransactionPoolConfiguration poolConfiguration =
TransactionPoolConfiguration.DEFAULT;
private final ObservableMetricsSystem observableMetricsSystem = new NoOpMetricsSystem();
BigInteger networkId = BigInteger.ONE;
@ -128,6 +127,10 @@ public class BesuControllerBuilderTest {
when(synchronizerConfiguration.getBlockPropagationRange()).thenReturn(Range.closed(1L, 2L));
when(observableMetricsSystem.createLabelledCounter(
any(), anyString(), anyString(), anyString()))
.thenReturn(labels -> null);
when(storageProvider.createWorldStateStorage(DataStorageFormat.FOREST))
.thenReturn(worldStateStorage);
when(storageProvider.createWorldStatePreimageStorage()).thenReturn(worldStatePreimageStorage);

@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@ -57,7 +58,6 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import java.math.BigInteger;
@ -90,8 +90,10 @@ public class MergeBesuControllerBuilderTest {
@Mock EthProtocolConfiguration ethProtocolConfiguration;
@Mock CheckpointConfigOptions checkpointConfigOptions;
@Mock MiningParameters miningParameters;
@Mock ObservableMetricsSystem observableMetricsSystem;
@Mock PrivacyParameters privacyParameters;
@Mock Clock clock;
@Mock TransactionPoolConfiguration poolConfiguration;
@Mock StorageProvider storageProvider;
@Mock GasLimitCalculator gasLimitCalculator;
@Mock WorldStateStorage worldStateStorage;
@ -100,9 +102,6 @@ public class MergeBesuControllerBuilderTest {
BigInteger networkId = BigInteger.ONE;
private final BlockHeaderTestFixture headerGenerator = new BlockHeaderTestFixture();
private final BaseFeeMarket feeMarket = new LondonFeeMarket(0, Optional.of(Wei.of(42)));
private final TransactionPoolConfiguration poolConfiguration =
TransactionPoolConfiguration.DEFAULT;
private final ObservableMetricsSystem observableMetricsSystem = new NoOpMetricsSystem();
@Rule public final TemporaryFolder tempDirRule = new TemporaryFolder();
@ -135,6 +134,10 @@ public class MergeBesuControllerBuilderTest {
when(synchronizerConfiguration.getBlockPropagationRange()).thenReturn(Range.closed(1L, 2L));
when(observableMetricsSystem.createLabelledCounter(
any(), anyString(), anyString(), anyString()))
.thenReturn(labels -> null);
when(storageProvider.createWorldStateStorage(DataStorageFormat.FOREST))
.thenReturn(worldStateStorage);
when(storageProvider.createWorldStatePreimageStorage()).thenReturn(worldStatePreimageStorage);

@ -17,6 +17,7 @@ package org.hyperledger.besu.controller;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -52,7 +53,6 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import java.math.BigInteger;
@ -80,17 +80,16 @@ public class QbftBesuControllerBuilderTest {
@Mock private EthProtocolConfiguration ethProtocolConfiguration;
@Mock CheckpointConfigOptions checkpointConfigOptions;
@Mock private MiningParameters miningParameters;
@Mock private ObservableMetricsSystem observableMetricsSystem;
@Mock private PrivacyParameters privacyParameters;
@Mock private Clock clock;
@Mock private TransactionPoolConfiguration poolConfiguration;
@Mock private StorageProvider storageProvider;
@Mock private GasLimitCalculator gasLimitCalculator;
@Mock private WorldStateStorage worldStateStorage;
@Mock private WorldStatePreimageStorage worldStatePreimageStorage;
private static final BigInteger networkId = BigInteger.ONE;
private static final NodeKey nodeKey = NodeKeyUtils.generate();
private final TransactionPoolConfiguration poolConfiguration =
TransactionPoolConfiguration.DEFAULT;
private final ObservableMetricsSystem observableMetricsSystem = new NoOpMetricsSystem();
@Rule public final TemporaryFolder tempDirRule = new TemporaryFolder();
@ -121,7 +120,9 @@ public class QbftBesuControllerBuilderTest {
when(synchronizerConfiguration.getDownloaderParallelism()).thenReturn(1);
when(synchronizerConfiguration.getTransactionsParallelism()).thenReturn(1);
when(synchronizerConfiguration.getComputationParallelism()).thenReturn(1);
when(observableMetricsSystem.createLabelledCounter(
any(), anyString(), anyString(), anyString()))
.thenReturn(labels -> null);
when(synchronizerConfiguration.getBlockPropagationRange()).thenReturn(Range.closed(1L, 2L));
// qbft prepForBuild setup

@ -109,6 +109,25 @@ public class DefaultDiscoveryConfiguration {
"enode://5cd218959f8263bc3721d7789070806b0adff1a0ed3f95ec886fb469f9362c7507e3b32b256550b9a7964a23a938e8d42d45a0c34b332bfebc54b29081e83b93@35.187.57.94:30303")
.map(EnodeURLImpl::fromString)
.collect(toList()));
public static final List<EnodeURL> KOTTI_BOOTSTRAP_NODES =
Collections.unmodifiableList(
Stream.of(
// Authority Nodes
"enode://a59e33ccd2b3e52d578f1fbd70c6f9babda2650f0760d6ff3b37742fdcdfdb3defba5d56d315b40c46b70198c7621e63ffa3f987389c7118634b0fefbbdfa7fd@51.158.191.43:37956", // @q9f Mizar
"enode://93c94e999be5dd854c5d82a7cf5c14822973b5d9badb56ad4974586ec4d4f1995c815af795c20bb6e0a6226d3ee55808435c4dc89baf94ee581141b064d19dfc@80.187.116.161:25720",
"enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303",
"enode://b477ca6d507a3f57070783eb62ba838847635f8b1a0cbffb8b7f8173f5894cf550f0225a5c279341e2d862a606e778b57180a4f1db3db78c51eadcfa4fdc6963@40.68.240.160:30303",
// @q9f Bootnodes
"enode://4956f6924335c951cb70cbc169a85c081f6ff0b374aa2815453b8a3132b49613f38a1a6b8e103f878dbec86364f60091e92a376d7cd3aca9d82d2f2554794e63@51.15.97.240:41235", // @q9f Ginan
"enode://6c9a052c01bb9995fa53bebfcdbc17733fe90708270d0e6d8e38dc57b32e1dbe8c287590b634ee9753b94ba302f411c96519c7fa07df0df6a6848149d819b2c5@51.15.70.7:41235", // @q9f Polis
"enode://95a7302fd8f35d9ad716a591b90dfe839dbf2d3d6a6737ef39e07899f844ad82f1659dd6212492922dd36705fb0a1e984c1d5d5c42069d5bd329388831e820c1@51.15.97.240:45678", // @q9f Ginan
"enode://8c5c4dec9a0728c7058d3c29698bae888adc244e443cebc21f3d708a20751511acbf98a52b5e5ea472f8715c658913e8084123461fd187a4980a0600420b0791@51.15.70.7:45678", // @q9f Polis
"enode://efd7391a3bed73ad74ae5760319bb48f9c9f1983ff22964422688cdb426c5d681004ece26c47121396653cf9bafe7104aa4ecff70e24cc5b11fd76be8e5afce0@51.158.191.43:45678", // @q9f Mizar
"enode://93b12383c74c39b67afa99a7ff44ce250fe94295fa1fc087465cc4fe2d0b33b91a8d8cabe03b250104a9096aa0e06bcde5f95665a5bd9f890edd2ab33e16ae47@51.15.41.19:30303" // @q9f Zibal
)
.map(EnodeURLImpl::fromString)
.collect(toList()));
public static final List<EnodeURL> MORDOR_BOOTSTRAP_NODES =
Collections.unmodifiableList(
Stream.of(

@ -1,211 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.services;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Transaction;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.log.Log;
import org.hyperledger.besu.evm.worldstate.WorldView;
import org.hyperledger.besu.plugin.services.TraceService;
import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
class TraceServiceImplTest {
TraceService traceService;
private MutableBlockchain blockchain;
private WorldStateArchive worldStateArchive;
private BlockchainQueries blockchainQueries;
/**
* The blockchain for testing has a height of 32 and the account
* 0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b makes a transaction per block. So, in the head, the
* nonce of this account should be 32.
*/
@BeforeEach
public void setup() {
final BlockchainSetupUtil blockchainSetupUtil =
BlockchainSetupUtil.forTesting(DataStorageFormat.BONSAI);
blockchainSetupUtil.importAllBlocks();
blockchain = blockchainSetupUtil.getBlockchain();
worldStateArchive = blockchainSetupUtil.getWorldArchive();
blockchainQueries = new BlockchainQueries(blockchain, worldStateArchive);
traceService =
new TraceServiceImpl(blockchainQueries, blockchainSetupUtil.getProtocolSchedule());
}
@Test
void shouldRetrieveStateUpdatePostTracingForOneBlock() {
final Address addressToVerify =
Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b");
final long persistedNonceForAccount =
worldStateArchive.getMutable().get(addressToVerify).getNonce();
traceService.trace(
2,
2,
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce()).isEqualTo(1);
},
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce()).isEqualTo(2);
},
BlockAwareOperationTracer.NO_TRACING);
assertThat(worldStateArchive.getMutable().get(addressToVerify).getNonce())
.isEqualTo(persistedNonceForAccount);
}
@Test
void shouldRetrieveStateUpdatePostTracingForAllBlocks() {
final Address addressToVerify =
Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b");
final long persistedNonceForAccount =
worldStateArchive.getMutable().get(addressToVerify).getNonce();
traceService.trace(
0,
32,
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce()).isEqualTo(0);
},
worldState -> {
assertThat(worldState.get(addressToVerify).getNonce())
.isEqualTo(persistedNonceForAccount);
},
BlockAwareOperationTracer.NO_TRACING);
assertThat(worldStateArchive.getMutable().get(addressToVerify).getNonce())
.isEqualTo(persistedNonceForAccount);
}
@Test
void shouldReturnTheCorrectWorldViewForTxStartEnd() {
final TxStartEndTracer txStartEndTracer = new TxStartEndTracer();
// block contains 1 transaction
traceService.traceBlock(31, txStartEndTracer);
assertThat(txStartEndTracer.txStartWorldView).isNotNull();
assertThat(txStartEndTracer.txEndWorldView).isNotNull();
assertThat(txStartEndTracer.txStartTransaction.getNonce())
.isEqualTo(txStartEndTracer.txEndTransaction.getNonce())
.isEqualTo(30);
assertThat(txStartEndTracer.txStartTransaction.getGasLimit())
.isEqualTo(txStartEndTracer.txEndTransaction.getGasLimit())
.isEqualTo(314159);
assertThat(txStartEndTracer.txStartTransaction.getTo().get())
.isEqualTo(txStartEndTracer.txEndTransaction.getTo().get())
.isEqualTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"));
assertThat(txStartEndTracer.txStartTransaction.getValue())
.isEqualTo(txStartEndTracer.txEndTransaction.getValue())
.isEqualTo(
Wei.fromHexString(
"0x000000000000000000000000000000000000000000000000000000000000000a"));
assertThat(txStartEndTracer.txStartTransaction.getPayload())
.isEqualTo(txStartEndTracer.txEndTransaction.getPayload())
.isEqualTo(Bytes.fromHexString("0xfd408767"));
assertThat(txStartEndTracer.txEndStatus).isTrue();
assertThat(txStartEndTracer.txEndOutput).isEqualTo(Bytes.fromHexString("0x"));
assertThat(txStartEndTracer.txEndGasUsed).isEqualTo(24303);
assertThat(txStartEndTracer.txEndTimeNs).isNotNull();
assertThat(txStartEndTracer.txEndLogs).isNotEmpty();
final Log actualLog = txStartEndTracer.txEndLogs.get(0);
assertThat(actualLog.getLogger())
.isEqualTo(Address.fromHexString("0x6295ee1b4f6dd65047762f924ecd367c17eabf8f"));
assertThat(actualLog.getData())
.isEqualTo(
Bytes.fromHexString(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9000000000000000000000000000000000000000000000000000000000000002a"));
assertThat(actualLog.getTopics()).hasSize(4);
assertThat(actualLog.getTopics().get(0))
.isEqualTo(
Bytes.fromHexString(
"0xd5f0a30e4be0c6be577a71eceb7464245a796a7e6a55c0d971837b250de05f4e"));
assertThat(actualLog.getTopics().get(1))
.isEqualTo(
Bytes.fromHexString(
"0x0000000000000000000000000000000000000000000000000000000000000001"));
assertThat(actualLog.getTopics().get(2))
.isEqualTo(
Bytes.fromHexString(
"0x000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b"));
assertThat(actualLog.getTopics().get(3))
.isEqualTo(
Bytes.fromHexString(
"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"));
}
private static class TxStartEndTracer implements BlockAwareOperationTracer {
public WorldView txStartWorldView;
public WorldView txEndWorldView;
public Transaction txStartTransaction;
public Transaction txEndTransaction;
public boolean txEndStatus;
public Bytes txEndOutput;
public List<Log> txEndLogs;
public long txEndGasUsed;
public Long txEndTimeNs;
@Override
public void traceStartTransaction(final WorldView worldView, final Transaction transaction) {
txStartWorldView = worldView;
txStartTransaction = transaction;
}
@Override
public void traceEndTransaction(
final WorldView worldView,
final Transaction transaction,
final boolean status,
final Bytes output,
final List<Log> logs,
final long gasUsed,
final long timeNs) {
txEndWorldView = worldView;
txEndTransaction = transaction;
txEndStatus = status;
txEndOutput = output;
txEndLogs = logs;
txEndGasUsed = gasUsed;
txEndTimeNs = timeNs;
}
}
}

@ -170,21 +170,16 @@ privacy-onchain-groups-enabled=false
privacy-flexible-groups-enabled=false
# Transaction Pool
tx-pool="layered"
tx-pool-retention-hours=999
tx-pool-price-bump=13
tx-pool-max-size=1234
tx-pool-limit-by-account-percentage=0.017
Xincoming-tx-messages-keep-alive-seconds=60
rpc-tx-feecap=2000000000000000000
strict-tx-replay-protection-enabled=true
tx-pool-disable-locals=false
tx-pool-enable-save-restore=true
tx-pool-save-file="txpool.dump"
## Layered
tx-pool-layer-max-capacity=12345678
tx-pool-max-prioritized=9876
tx-pool-max-future-by-sender=321
## Legacy
tx-pool-retention-hours=999
tx-pool-max-size=1234
tx-pool-limit-by-account-percentage=0.017
# Revert Reason
revert-reason-enabled=false

@ -551,22 +551,6 @@ def tweakStartScript(createScriptTask) {
}
startScripts {
defaultJvmOpts = applicationDefaultJvmArgs + [
"-XX:G1ConcRefinementThreads=2",
"-XX:G1HeapWastePercent=15",
"-XX:MaxGCPauseMillis=100"
]
unixStartScriptGenerator.template = resources.text.fromFile("${projectDir}/besu/src/main/scripts/unixStartScript.txt")
windowsStartScriptGenerator.template = resources.text.fromFile("${projectDir}/besu/src/main/scripts/windowsStartScript.txt")
doLast { tweakStartScript(startScripts) }
}
task untunedStartScripts(type: CreateStartScripts) {
mainClass = 'org.hyperledger.besu.Besu'
classpath = startScripts.classpath
outputDir = startScripts.outputDir
applicationName = 'besu-untuned'
defaultJvmOpts = applicationDefaultJvmArgs
unixStartScriptGenerator.template = resources.text.fromFile("${projectDir}/besu/src/main/scripts/unixStartScript.txt")
windowsStartScriptGenerator.template = resources.text.fromFile("${projectDir}/besu/src/main/scripts/windowsStartScript.txt")
doLast { tweakStartScript(startScripts) }
@ -603,10 +587,10 @@ task autocomplete(type: JavaExec) {
}
}
installDist { dependsOn checkLicenses, untunedStartScripts, evmToolStartScripts }
installDist { dependsOn checkLicenses, evmToolStartScripts }
distTar {
dependsOn checkLicenses, autocomplete, untunedStartScripts, evmToolStartScripts
dependsOn checkLicenses, autocomplete, evmToolStartScripts
doFirst {
delete fileTree(dir: 'build/distributions', include: '*.tar.gz')
}
@ -615,7 +599,7 @@ distTar {
}
distZip {
dependsOn checkLicenses, autocomplete, untunedStartScripts, evmToolStartScripts
dependsOn checkLicenses, autocomplete, evmToolStartScripts
doFirst {
delete fileTree(dir: 'build/distributions', include: '*.zip')
}

@ -0,0 +1,815 @@
{
"config": {
"chainId": 6,
"ecip1041Block": 0,
"atlantisBlock": 716617,
"aghartaBlock": 1705549,
"phoenixBlock": 2200013,
"magnetoBlock": 4368634,
"mystiqueBlock": 5578000,
"clique":{
"blockperiodseconds":15,
"epochlength":30000
},
"discovery": {
"bootnodes": [
"enode://a59e33ccd2b3e52d578f1fbd70c6f9babda2650f0760d6ff3b37742fdcdfdb3defba5d56d315b40c46b70198c7621e63ffa3f987389c7118634b0fefbbdfa7fd@51.158.191.43:37956",
"enode://93c94e999be5dd854c5d82a7cf5c14822973b5d9badb56ad4974586ec4d4f1995c815af795c20bb6e0a6226d3ee55808435c4dc89baf94ee581141b064d19dfc@80.187.116.161:25720",
"enode://ae8658da8d255d1992c3ec6e62e11d6e1c5899aa1566504bc1ff96a0c9c8bd44838372be643342553817f5cc7d78f1c83a8093dee13d77b3b0a583c050c81940@18.232.185.151:30303",
"enode://b477ca6d507a3f57070783eb62ba838847635f8b1a0cbffb8b7f8173f5894cf550f0225a5c279341e2d862a606e778b57180a4f1db3db78c51eadcfa4fdc6963@40.68.240.160:30303",
"enode://4956f6924335c951cb70cbc169a85c081f6ff0b374aa2815453b8a3132b49613f38a1a6b8e103f878dbec86364f60091e92a376d7cd3aca9d82d2f2554794e63@51.15.97.240:41235",
"enode://6c9a052c01bb9995fa53bebfcdbc17733fe90708270d0e6d8e38dc57b32e1dbe8c287590b634ee9753b94ba302f411c96519c7fa07df0df6a6848149d819b2c5@51.15.70.7:41235",
"enode://95a7302fd8f35d9ad716a591b90dfe839dbf2d3d6a6737ef39e07899f844ad82f1659dd6212492922dd36705fb0a1e984c1d5d5c42069d5bd329388831e820c1@51.15.97.240:45678",
"enode://8c5c4dec9a0728c7058d3c29698bae888adc244e443cebc21f3d708a20751511acbf98a52b5e5ea472f8715c658913e8084123461fd187a4980a0600420b0791@51.15.70.7:45678",
"enode://efd7391a3bed73ad74ae5760319bb48f9c9f1983ff22964422688cdb426c5d681004ece26c47121396653cf9bafe7104aa4ecff70e24cc5b11fd76be8e5afce0@51.158.191.43:45678",
"enode://93b12383c74c39b67afa99a7ff44ce250fe94295fa1fc087465cc4fe2d0b33b91a8d8cabe03b250104a9096aa0e06bcde5f95665a5bd9f890edd2ab33e16ae47@51.15.41.19:30303"
]
}
},
"nonce": "0x0",
"timestamp": "0x5c2d2287",
"extraData": "0x000000000000000000000000000000000000000000000000000000000000000025b7955e43adf9c2a01a9475908702cce67f302a6aaf8cba3c9255a2b863415d4db7bae4f4bbca020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit": "0xa00000",
"difficulty": "0x1",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"0000000000000000000000000000000000000000": {
"balance": "0x1"
},
"0000000000000000000000000000000000000001": {
"balance": "0x1"
},
"0000000000000000000000000000000000000002": {
"balance": "0x1"
},
"0000000000000000000000000000000000000003": {
"balance": "0x1"
},
"0000000000000000000000000000000000000004": {
"balance": "0x1"
},
"0000000000000000000000000000000000000005": {
"balance": "0x1"
},
"0000000000000000000000000000000000000006": {
"balance": "0x1"
},
"0000000000000000000000000000000000000007": {
"balance": "0x1"
},
"0000000000000000000000000000000000000008": {
"balance": "0x1"
},
"0000000000000000000000000000000000000009": {
"balance": "0x1"
},
"000000000000000000000000000000000000000a": {
"balance": "0x1"
},
"000000000000000000000000000000000000000b": {
"balance": "0x1"
},
"000000000000000000000000000000000000000c": {
"balance": "0x1"
},
"000000000000000000000000000000000000000d": {
"balance": "0x1"
},
"000000000000000000000000000000000000000e": {
"balance": "0x1"
},
"000000000000000000000000000000000000000f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000010": {
"balance": "0x1"
},
"0000000000000000000000000000000000000011": {
"balance": "0x1"
},
"0000000000000000000000000000000000000012": {
"balance": "0x1"
},
"0000000000000000000000000000000000000013": {
"balance": "0x1"
},
"0000000000000000000000000000000000000014": {
"balance": "0x1"
},
"0000000000000000000000000000000000000015": {
"balance": "0x1"
},
"0000000000000000000000000000000000000016": {
"balance": "0x1"
},
"0000000000000000000000000000000000000017": {
"balance": "0x1"
},
"0000000000000000000000000000000000000018": {
"balance": "0x1"
},
"0000000000000000000000000000000000000019": {
"balance": "0x1"
},
"000000000000000000000000000000000000001a": {
"balance": "0x1"
},
"000000000000000000000000000000000000001b": {
"balance": "0x1"
},
"000000000000000000000000000000000000001c": {
"balance": "0x1"
},
"000000000000000000000000000000000000001d": {
"balance": "0x1"
},
"000000000000000000000000000000000000001e": {
"balance": "0x1"
},
"000000000000000000000000000000000000001f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000020": {
"balance": "0x1"
},
"0000000000000000000000000000000000000021": {
"balance": "0x1"
},
"0000000000000000000000000000000000000022": {
"balance": "0x1"
},
"0000000000000000000000000000000000000023": {
"balance": "0x1"
},
"0000000000000000000000000000000000000024": {
"balance": "0x1"
},
"0000000000000000000000000000000000000025": {
"balance": "0x1"
},
"0000000000000000000000000000000000000026": {
"balance": "0x1"
},
"0000000000000000000000000000000000000027": {
"balance": "0x1"
},
"0000000000000000000000000000000000000028": {
"balance": "0x1"
},
"0000000000000000000000000000000000000029": {
"balance": "0x1"
},
"000000000000000000000000000000000000002a": {
"balance": "0x1"
},
"000000000000000000000000000000000000002b": {
"balance": "0x1"
},
"000000000000000000000000000000000000002c": {
"balance": "0x1"
},
"000000000000000000000000000000000000002d": {
"balance": "0x1"
},
"000000000000000000000000000000000000002e": {
"balance": "0x1"
},
"000000000000000000000000000000000000002f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000030": {
"balance": "0x1"
},
"0000000000000000000000000000000000000031": {
"balance": "0x1"
},
"0000000000000000000000000000000000000032": {
"balance": "0x1"
},
"0000000000000000000000000000000000000033": {
"balance": "0x1"
},
"0000000000000000000000000000000000000034": {
"balance": "0x1"
},
"0000000000000000000000000000000000000035": {
"balance": "0x1"
},
"0000000000000000000000000000000000000036": {
"balance": "0x1"
},
"0000000000000000000000000000000000000037": {
"balance": "0x1"
},
"0000000000000000000000000000000000000038": {
"balance": "0x1"
},
"0000000000000000000000000000000000000039": {
"balance": "0x1"
},
"000000000000000000000000000000000000003a": {
"balance": "0x1"
},
"000000000000000000000000000000000000003b": {
"balance": "0x1"
},
"000000000000000000000000000000000000003c": {
"balance": "0x1"
},
"000000000000000000000000000000000000003d": {
"balance": "0x1"
},
"000000000000000000000000000000000000003e": {
"balance": "0x1"
},
"000000000000000000000000000000000000003f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000040": {
"balance": "0x1"
},
"0000000000000000000000000000000000000041": {
"balance": "0x1"
},
"0000000000000000000000000000000000000042": {
"balance": "0x1"
},
"0000000000000000000000000000000000000043": {
"balance": "0x1"
},
"0000000000000000000000000000000000000044": {
"balance": "0x1"
},
"0000000000000000000000000000000000000045": {
"balance": "0x1"
},
"0000000000000000000000000000000000000046": {
"balance": "0x1"
},
"0000000000000000000000000000000000000047": {
"balance": "0x1"
},
"0000000000000000000000000000000000000048": {
"balance": "0x1"
},
"0000000000000000000000000000000000000049": {
"balance": "0x1"
},
"000000000000000000000000000000000000004a": {
"balance": "0x1"
},
"000000000000000000000000000000000000004b": {
"balance": "0x1"
},
"000000000000000000000000000000000000004c": {
"balance": "0x1"
},
"000000000000000000000000000000000000004d": {
"balance": "0x1"
},
"000000000000000000000000000000000000004e": {
"balance": "0x1"
},
"000000000000000000000000000000000000004f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000050": {
"balance": "0x1"
},
"0000000000000000000000000000000000000051": {
"balance": "0x1"
},
"0000000000000000000000000000000000000052": {
"balance": "0x1"
},
"0000000000000000000000000000000000000053": {
"balance": "0x1"
},
"0000000000000000000000000000000000000054": {
"balance": "0x1"
},
"0000000000000000000000000000000000000055": {
"balance": "0x1"
},
"0000000000000000000000000000000000000056": {
"balance": "0x1"
},
"0000000000000000000000000000000000000057": {
"balance": "0x1"
},
"0000000000000000000000000000000000000058": {
"balance": "0x1"
},
"0000000000000000000000000000000000000059": {
"balance": "0x1"
},
"000000000000000000000000000000000000005a": {
"balance": "0x1"
},
"000000000000000000000000000000000000005b": {
"balance": "0x1"
},
"000000000000000000000000000000000000005c": {
"balance": "0x1"
},
"000000000000000000000000000000000000005d": {
"balance": "0x1"
},
"000000000000000000000000000000000000005e": {
"balance": "0x1"
},
"000000000000000000000000000000000000005f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000060": {
"balance": "0x1"
},
"0000000000000000000000000000000000000061": {
"balance": "0x1"
},
"0000000000000000000000000000000000000062": {
"balance": "0x1"
},
"0000000000000000000000000000000000000063": {
"balance": "0x1"
},
"0000000000000000000000000000000000000064": {
"balance": "0x1"
},
"0000000000000000000000000000000000000065": {
"balance": "0x1"
},
"0000000000000000000000000000000000000066": {
"balance": "0x1"
},
"0000000000000000000000000000000000000067": {
"balance": "0x1"
},
"0000000000000000000000000000000000000068": {
"balance": "0x1"
},
"0000000000000000000000000000000000000069": {
"balance": "0x1"
},
"000000000000000000000000000000000000006a": {
"balance": "0x1"
},
"000000000000000000000000000000000000006b": {
"balance": "0x1"
},
"000000000000000000000000000000000000006c": {
"balance": "0x1"
},
"000000000000000000000000000000000000006d": {
"balance": "0x1"
},
"000000000000000000000000000000000000006e": {
"balance": "0x1"
},
"000000000000000000000000000000000000006f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000070": {
"balance": "0x1"
},
"0000000000000000000000000000000000000071": {
"balance": "0x1"
},
"0000000000000000000000000000000000000072": {
"balance": "0x1"
},
"0000000000000000000000000000000000000073": {
"balance": "0x1"
},
"0000000000000000000000000000000000000074": {
"balance": "0x1"
},
"0000000000000000000000000000000000000075": {
"balance": "0x1"
},
"0000000000000000000000000000000000000076": {
"balance": "0x1"
},
"0000000000000000000000000000000000000077": {
"balance": "0x1"
},
"0000000000000000000000000000000000000078": {
"balance": "0x1"
},
"0000000000000000000000000000000000000079": {
"balance": "0x1"
},
"000000000000000000000000000000000000007a": {
"balance": "0x1"
},
"000000000000000000000000000000000000007b": {
"balance": "0x1"
},
"000000000000000000000000000000000000007c": {
"balance": "0x1"
},
"000000000000000000000000000000000000007d": {
"balance": "0x1"
},
"000000000000000000000000000000000000007e": {
"balance": "0x1"
},
"000000000000000000000000000000000000007f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000080": {
"balance": "0x1"
},
"0000000000000000000000000000000000000081": {
"balance": "0x1"
},
"0000000000000000000000000000000000000082": {
"balance": "0x1"
},
"0000000000000000000000000000000000000083": {
"balance": "0x1"
},
"0000000000000000000000000000000000000084": {
"balance": "0x1"
},
"0000000000000000000000000000000000000085": {
"balance": "0x1"
},
"0000000000000000000000000000000000000086": {
"balance": "0x1"
},
"0000000000000000000000000000000000000087": {
"balance": "0x1"
},
"0000000000000000000000000000000000000088": {
"balance": "0x1"
},
"0000000000000000000000000000000000000089": {
"balance": "0x1"
},
"000000000000000000000000000000000000008a": {
"balance": "0x1"
},
"000000000000000000000000000000000000008b": {
"balance": "0x1"
},
"000000000000000000000000000000000000008c": {
"balance": "0x1"
},
"000000000000000000000000000000000000008d": {
"balance": "0x1"
},
"000000000000000000000000000000000000008e": {
"balance": "0x1"
},
"000000000000000000000000000000000000008f": {
"balance": "0x1"
},
"0000000000000000000000000000000000000090": {
"balance": "0x1"
},
"0000000000000000000000000000000000000091": {
"balance": "0x1"
},
"0000000000000000000000000000000000000092": {
"balance": "0x1"
},
"0000000000000000000000000000000000000093": {
"balance": "0x1"
},
"0000000000000000000000000000000000000094": {
"balance": "0x1"
},
"0000000000000000000000000000000000000095": {
"balance": "0x1"
},
"0000000000000000000000000000000000000096": {
"balance": "0x1"
},
"0000000000000000000000000000000000000097": {
"balance": "0x1"
},
"0000000000000000000000000000000000000098": {
"balance": "0x1"
},
"0000000000000000000000000000000000000099": {
"balance": "0x1"
},
"000000000000000000000000000000000000009a": {
"balance": "0x1"
},
"000000000000000000000000000000000000009b": {
"balance": "0x1"
},
"000000000000000000000000000000000000009c": {
"balance": "0x1"
},
"000000000000000000000000000000000000009d": {
"balance": "0x1"
},
"000000000000000000000000000000000000009e": {
"balance": "0x1"
},
"000000000000000000000000000000000000009f": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000a9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000aa": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ab": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ac": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ad": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ae": {
"balance": "0x1"
},
"00000000000000000000000000000000000000af": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000b9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ba": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000be": {
"balance": "0x1"
},
"00000000000000000000000000000000000000bf": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000c9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ca": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ce": {
"balance": "0x1"
},
"00000000000000000000000000000000000000cf": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000d9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000da": {
"balance": "0x1"
},
"00000000000000000000000000000000000000db": {
"balance": "0x1"
},
"00000000000000000000000000000000000000dc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000dd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000de": {
"balance": "0x1"
},
"00000000000000000000000000000000000000df": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000e9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ea": {
"balance": "0x1"
},
"00000000000000000000000000000000000000eb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ec": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ed": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ee": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ef": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f0": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f1": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f2": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f3": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f4": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f5": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f6": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f7": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f8": {
"balance": "0x1"
},
"00000000000000000000000000000000000000f9": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fa": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fb": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fc": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fd": {
"balance": "0x1"
},
"00000000000000000000000000000000000000fe": {
"balance": "0x1"
},
"00000000000000000000000000000000000000ff": {
"balance": "0x1"
},
"25b7955e43adf9c2a01a9475908702cce67f302a": {
"balance": "0x84595161401484a000000"
},
"6aaf8cba3c9255a2b863415d4db7bae4f4bbca02": {
"balance": "0x4a723dc6b40b8a9a000000"
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000"
}

@ -65,7 +65,6 @@ public class MigratingMiningCoordinator implements MiningCoordinator, BlockAdded
}
private void startActiveMiningCoordinator() {
activeMiningCoordinator.enable();
activeMiningCoordinator.start();
if (activeMiningCoordinator instanceof BlockAddedObserver) {
((BlockAddedObserver) activeMiningCoordinator).removeObserver();

@ -46,9 +46,7 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv
/** Running state. */
RUNNING,
/** Stopped state. */
STOPPED,
/** Paused state. */
PAUSED,
STOPPED
}
private static final Logger LOG = LoggerFactory.getLogger(BftMiningCoordinator.class);
@ -63,7 +61,7 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv
private final BftExecutors bftExecutors;
private long blockAddedObserverId;
private final AtomicReference<State> state = new AtomicReference<>(State.PAUSED);
private final AtomicReference<State> state = new AtomicReference<>(State.IDLE);
/**
* Instantiates a new Bft mining coordinator.
@ -124,13 +122,7 @@ public class BftMiningCoordinator implements MiningCoordinator, BlockAddedObserv
@Override
public boolean enable() {
// Return true if we're already running or idle, or successfully switch to idle
if (state.get() == State.RUNNING
|| state.get() == State.IDLE
|| state.compareAndSet(State.PAUSED, State.IDLE)) {
return true;
}
return false;
return true;
}
@Override

@ -75,7 +75,6 @@ public class BftMiningCoordinatorTest {
bftMiningCoordinator.stop();
verify(bftProcessor, never()).stop();
bftMiningCoordinator.enable();
bftMiningCoordinator.start();
bftMiningCoordinator.stop();
verify(bftProcessor).stop();

@ -254,12 +254,7 @@ public class MergeCoordinator implements MergeMiningCoordinator, BadChainListene
final PayloadIdentifier payloadIdentifier =
PayloadIdentifier.forPayloadParams(
parentHeader.getBlockHash(),
timestamp,
prevRandao,
feeRecipient,
withdrawals,
parentBeaconBlockRoot);
parentHeader.getBlockHash(), timestamp, prevRandao, feeRecipient, withdrawals);
if (blockCreationTasks.containsKey(payloadIdentifier)) {
LOG.debug(

@ -62,7 +62,6 @@ public class PayloadIdentifier implements Quantity {
* @param prevRandao the prev randao
* @param feeRecipient the fee recipient
* @param withdrawals the withdrawals
* @param parentBeaconBlockRoot the parent beacon block root
* @return the payload identifier
*/
public static PayloadIdentifier forPayloadParams(
@ -70,8 +69,7 @@ public class PayloadIdentifier implements Quantity {
final Long timestamp,
final Bytes32 prevRandao,
final Address feeRecipient,
final Optional<List<Withdrawal>> withdrawals,
final Optional<Bytes32> parentBeaconBlockRoot) {
final Optional<List<Withdrawal>> withdrawals) {
return new PayloadIdentifier(
timestamp
@ -86,8 +84,7 @@ public class PayloadIdentifier implements Quantity {
.sorted(Comparator.comparing(Withdrawal::getIndex))
.map(Withdrawal::hashCode)
.reduce(1, (a, b) -> a ^ (b * 31)))
.orElse(0)
^ ((long) parentBeaconBlockRoot.hashCode()) << 40);
.orElse(0));
}
@Override

@ -76,7 +76,6 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.metrics.StubMetricsSystem;
import org.hyperledger.besu.testutil.TestClock;
import org.hyperledger.besu.util.number.Fraction;
import java.time.ZoneId;
import java.util.ArrayList;
@ -162,7 +161,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper {
private final TransactionPoolConfiguration poolConf =
ImmutableTransactionPoolConfiguration.builder()
.txPoolMaxSize(10)
.txPoolLimitByAccountPercentage(Fraction.fromPercentage(100))
.txPoolLimitByAccountPercentage(100.0f)
.build();
private final BaseFeePendingTransactionsSorter transactions =
new BaseFeePendingTransactionsSorter(

@ -48,12 +48,7 @@ public class PayloadIdentifierTest {
public void conversionCoverage() {
var idTest =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
Bytes32.random(),
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty());
Hash.ZERO, 1337L, Bytes32.random(), Address.fromHexString("0x42"), Optional.empty());
assertThat(new PayloadIdentifier(idTest.getAsBigInteger().longValue())).isEqualTo(idTest);
assertThat(new PayloadIdentifier(idTest.getAsBigInteger().longValue())).isEqualTo(idTest);
}
@ -87,20 +82,10 @@ public class PayloadIdentifierTest {
final Bytes32 prevRandao = Bytes32.random();
var idForWithdrawals1 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.of(withdrawals1),
Optional.empty());
Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals1));
var idForWithdrawals2 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.of(withdrawals2),
Optional.empty());
Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals2));
assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2);
}
@ -133,20 +118,10 @@ public class PayloadIdentifierTest {
final Bytes32 prevRandao = Bytes32.random();
var idForWithdrawals1 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.of(withdrawals1),
Optional.empty());
Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals1));
var idForWithdrawals2 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.of(withdrawals2),
Optional.empty());
Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(withdrawals2));
assertThat(idForWithdrawals1).isEqualTo(idForWithdrawals2);
}
@ -155,64 +130,10 @@ public class PayloadIdentifierTest {
final Bytes32 prevRandao = Bytes32.random();
var idForWithdrawals1 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty());
Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.empty());
var idForWithdrawals2 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.of(emptyList()),
Optional.empty());
assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2);
}
@Test
public void emptyOptionalAndNonEmptyParentBeaconBlockRootYieldDifferentHash() {
final Bytes32 prevRandao = Bytes32.random();
var idForWithdrawals1 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty());
var idForWithdrawals2 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.empty(),
Optional.of(Bytes32.ZERO));
assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2);
}
@Test
public void differentParentBeaconBlockRootYieldDifferentHash() {
final Bytes32 prevRandao = Bytes32.random();
var idForWithdrawals1 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.empty(),
Optional.of(Bytes32.fromHexStringLenient("0x1")));
var idForWithdrawals2 =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
prevRandao,
Address.fromHexString("0x42"),
Optional.empty(),
Optional.of(Bytes32.ZERO));
Hash.ZERO, 1337L, prevRandao, Address.fromHexString("0x42"), Optional.of(emptyList()));
assertThat(idForWithdrawals1).isNotEqualTo(idForWithdrawals2);
}
}

@ -59,24 +59,28 @@ public class Address extends DelegatingBytes {
public static final Address BLAKE2B_F_COMPRESSION = Address.precompiled(0x09);
/** The constant KZG_POINT_EVAL aka POINT_EVALUATION_PRECOMPILE_ADDRESS. */
public static final Address KZG_POINT_EVAL = Address.precompiled(0xA);
/** The constant PARENT_BEACON_BLOCK_ROOT_REGISTRY aka HISTORY_STORAGE_ADDRESS. */
public static final Address PARENT_BEACON_BLOCK_ROOT_REGISTRY = Address.precompiled(0xB);
// TODO: this is not a precompile anymore. The address is correct for testnet 8. Fix after testnet
// 8 when we know what the real address is
/** The constant BLS12_G1ADD. */
public static final Address BLS12_G1ADD = Address.precompiled(0xB);
public static final Address BLS12_G1ADD = Address.precompiled(0xC);
/** The constant BLS12_G1MUL. */
public static final Address BLS12_G1MUL = Address.precompiled(0xC);
public static final Address BLS12_G1MUL = Address.precompiled(0xD);
/** The constant BLS12_G1MULTIEXP. */
public static final Address BLS12_G1MULTIEXP = Address.precompiled(0xD);
public static final Address BLS12_G1MULTIEXP = Address.precompiled(0xE);
/** The constant BLS12_G2ADD. */
public static final Address BLS12_G2ADD = Address.precompiled(0xE);
public static final Address BLS12_G2ADD = Address.precompiled(0xF);
/** The constant BLS12_G2MUL. */
public static final Address BLS12_G2MUL = Address.precompiled(0xF);
public static final Address BLS12_G2MUL = Address.precompiled(0x10);
/** The constant BLS12_G2MULTIEXP. */
public static final Address BLS12_G2MULTIEXP = Address.precompiled(0x10);
public static final Address BLS12_G2MULTIEXP = Address.precompiled(0x11);
/** The constant BLS12_PAIRING. */
public static final Address BLS12_PAIRING = Address.precompiled(0x11);
public static final Address BLS12_PAIRING = Address.precompiled(0x12);
/** The constant BLS12_MAP_FP_TO_G1. */
public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x12);
public static final Address BLS12_MAP_FP_TO_G1 = Address.precompiled(0x13);
/** The constant BLS12_MAP_FP2_TO_G2. */
public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x13);
public static final Address BLS12_MAP_FP2_TO_G2 = Address.precompiled(0x14);
/** The constant ZERO. */
public static final Address ZERO = Address.fromHexString("0x0");

@ -38,15 +38,11 @@ public class BlobsWithCommitments {
final List<Blob> blobs,
final List<KZGProof> kzgProofs,
final List<VersionedHash> versionedHashes) {
if (blobs.size() == 0) {
throw new InvalidParameterException(
"There needs to be a minimum of one blob in a blob transaction with commitments");
}
if (blobs.size() != kzgCommitments.size()
|| blobs.size() != kzgProofs.size()
|| blobs.size() != versionedHashes.size()) {
|| kzgCommitments.size() != versionedHashes.size()) {
throw new InvalidParameterException(
"There must be an equal number of blobs, commitments, proofs, and versioned hashes");
"There must be an equal number of blobs, commitments and proofs");
}
this.kzgCommitments = kzgCommitments;
this.blobs = blobs;

@ -22,70 +22,19 @@ import java.security.InvalidParameterException;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.Test;
public class BlobsWithCommitmentsTest {
@Test
public void blobsWithCommitmentsMustHaveAtLeastOneBlob() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() -> new BlobsWithCommitments(List.of(), List.of(), List.of(), List.of()))
.getMessage();
final String expectedMessage =
"There needs to be a minimum of one blob in a blob transaction with commitments";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
@Test
public void blobsWithCommitmentsMustHaveSameNumberOfElementsVersionedHashes() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.of(1))),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of()))
.getMessage();
final String expectedMessage =
"There must be an equal number of blobs, commitments, proofs, and versioned hashes";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
@Test
public void blobsWithCommitmentsMustHaveSameNumberOfElementsKZGCommitment() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(),
List.of(new Blob(Bytes.EMPTY)),
List.of(new KZGProof(Bytes.EMPTY)),
List.of(new VersionedHash(Bytes32.rightPad(Bytes.fromHexString("0x01"))))))
.getMessage();
final String expectedMessage =
"There must be an equal number of blobs, commitments, proofs, and versioned hashes";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
@Test
public void blobsWithCommitmentsMustHaveSameNumberOfElementsKZGProof() {
public void blobsWithCommitmentsMustHaveSameNumberOfElements() {
String actualMessage =
assertThrows(
InvalidParameterException.class,
() ->
new BlobsWithCommitments(
List.of(new KZGCommitment(Bytes.of(1))),
List.of(new Blob(Bytes.EMPTY)),
List.of(),
List.of(new VersionedHash(Bytes32.rightPad(Bytes.fromHexString("0x01"))))))
List.of(new KZGCommitment(Bytes.of(1))), List.of(), List.of(), List.of()))
.getMessage();
final String expectedMessage =
"There must be an equal number of blobs, commitments, proofs, and versioned hashes";
final String expectedMessage = "There must be an equal number of blobs, commitments and proofs";
assertThat(actualMessage).isEqualTo(expectedMessage);
}
}

@ -33,9 +33,6 @@ import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.JWTOptions;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.authentication.AuthenticationProvider;
import io.vertx.ext.auth.authentication.Credentials;
import io.vertx.ext.auth.authentication.TokenCredentials;
import io.vertx.ext.auth.authentication.UsernamePasswordCredentials;
import io.vertx.ext.auth.jwt.JWTAuth;
import io.vertx.ext.auth.jwt.JWTAuthOptions;
import io.vertx.ext.web.RoutingContext;
@ -169,7 +166,7 @@ public class DefaultAuthenticationService implements AuthenticationService {
private void login(
final RoutingContext routingContext, final AuthenticationProvider credentialAuthProvider) {
final JsonObject requestBody = routingContext.body().asJsonObject();
final JsonObject requestBody = routingContext.getBodyAsJson();
if (requestBody == null) {
routingContext
@ -184,10 +181,8 @@ public class DefaultAuthenticationService implements AuthenticationService {
final JsonObject authParams = new JsonObject();
authParams.put(USERNAME, requestBody.getValue(USERNAME));
authParams.put("password", requestBody.getValue("password"));
final Credentials credentials = new UsernamePasswordCredentials(authParams);
credentialAuthProvider.authenticate(
credentials,
authParams,
r -> {
if (r.failed()) {
routingContext
@ -232,7 +227,7 @@ public class DefaultAuthenticationService implements AuthenticationService {
try {
getJwtAuthProvider()
.authenticate(
new TokenCredentials(new JsonObject().put("token", token)),
new JsonObject().put("token", token),
r -> {
if (r.succeeded()) {
final Optional<User> user = Optional.ofNullable(r.result());

@ -199,11 +199,6 @@ public class TraceBlock extends AbstractBlockParameterMethod {
this.worldState = worldState;
}
public ChainUpdater(final MutableWorldState worldState, final WorldUpdater updater) {
this.worldState = worldState;
this.updater = updater;
}
public WorldUpdater getNextUpdater() {
// if we have no prior updater, it must be the first TX, so use the block's initial state
if (updater == null) {

@ -219,14 +219,9 @@ public abstract class AbstractEngineForkchoiceUpdated extends ExecutionEngineJso
return false;
}
if (payloadAttributes.getTimestamp() < cancunTimestamp) {
if (payloadAttributes.getParentBeaconBlockRoot() != null) {
LOG.error(
"Parent beacon block root hash present in payload attributes before cancun hardfork");
return false;
}
LOG.warn("Payload attributes are present before cancun hardfork");
} else if (payloadAttributes.getParentBeaconBlockRoot() == null) {
LOG.error(
"Parent beacon block root hash not present in payload attributes after cancun hardfork");
LOG.warn("Parent beacon block root not present in payload attributes after cancun hardfork");
return false;
}
if (!getWithdrawalsValidator(

@ -50,7 +50,6 @@ import org.hyperledger.besu.ethereum.core.Deposit;
import org.hyperledger.besu.ethereum.core.Difficulty;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Withdrawal;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
import org.hyperledger.besu.ethereum.eth.manager.EthPeers;
import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
@ -171,7 +170,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
transactions =
blockParam.getTransactions().stream()
.map(Bytes::fromHexString)
.map(in -> TransactionDecoder.decodeOpaqueBytes(in, EncodingContext.BLOCK_BODY))
.map(TransactionDecoder::decodeOpaqueBytes)
.collect(Collectors.toList());
} catch (final RLPException | IllegalArgumentException e) {
return respondWithInvalid(
@ -210,7 +209,7 @@ public abstract class AbstractEngineNewPayload extends ExecutionEngineJsonRpcMet
blockParam.getPrevRandao(),
0,
maybeWithdrawals.map(BodyValidation::withdrawalsRoot).orElse(null),
blockParam.getBlobGasUsed(),
blockParam.getBlobGasUsed() == null ? null : blockParam.getBlobGasUsed(),
blockParam.getExcessBlobGas() == null
? null
: BlobGas.fromHexString(blockParam.getExcessBlobGas()),

@ -69,22 +69,24 @@ public class TransactionTracer {
final Hash blockHash,
final Hash transactionHash,
final DebugOperationTracer tracer) {
return blockReplay.beforeTransactionInBlock(
mutableWorldState,
blockHash,
transactionHash,
(transaction, header, blockchain, transactionProcessor, blobGasPrice) -> {
final TransactionProcessingResult result =
processTransaction(
header,
blockchain,
mutableWorldState.updater(),
transaction,
transactionProcessor,
tracer,
blobGasPrice);
return new TransactionTrace(transaction, result, tracer.getTraceFrames());
});
Optional<TransactionTrace> transactionTrace =
blockReplay.beforeTransactionInBlock(
mutableWorldState,
blockHash,
transactionHash,
(transaction, header, blockchain, transactionProcessor, blobGasPrice) -> {
final TransactionProcessingResult result =
processTransaction(
header,
blockchain,
mutableWorldState.updater(),
transaction,
transactionProcessor,
tracer,
blobGasPrice);
return new TransactionTrace(transaction, result, tracer.getTraceFrames());
});
return transactionTrace;
}
public List<String> traceTransactionToFile(
@ -137,7 +139,7 @@ public class TransactionTracer {
stackedUpdater,
transaction,
transactionProcessor,
new StandardJsonTracer(out, showMemory, true, true, false),
new StandardJsonTracer(out, showMemory, true, true),
blobGasPrice);
out.println(
summaryTrace(

@ -24,7 +24,6 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockValueCalculator;
import org.hyperledger.besu.ethereum.core.BlockWithReceipts;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import java.util.ArrayList;
@ -96,9 +95,7 @@ public class BlockResultFactory {
public EngineGetPayloadResultV1 payloadTransactionCompleteV1(final Block block) {
final List<String> txs =
block.getBody().getTransactions().stream()
.map(
transaction ->
TransactionEncoder.encodeOpaqueBytes(transaction, EncodingContext.BLOCK_BODY))
.map(TransactionEncoder::encodeOpaqueBytes)
.map(Bytes::toHexString)
.collect(Collectors.toList());
@ -109,9 +106,7 @@ public class BlockResultFactory {
final BlockWithReceipts blockWithReceipts) {
final List<String> txs =
blockWithReceipts.getBlock().getBody().getTransactions().stream()
.map(
transaction ->
TransactionEncoder.encodeOpaqueBytes(transaction, EncodingContext.BLOCK_BODY))
.map(TransactionEncoder::encodeOpaqueBytes)
.map(Bytes::toHexString)
.collect(Collectors.toList());
@ -137,9 +132,7 @@ public class BlockResultFactory {
final BlockWithReceipts blockWithReceipts) {
final List<String> txs =
blockWithReceipts.getBlock().getBody().getTransactions().stream()
.map(
transaction ->
TransactionEncoder.encodeOpaqueBytes(transaction, EncodingContext.BLOCK_BODY))
.map(TransactionEncoder::encodeOpaqueBytes)
.map(Bytes::toHexString)
.collect(Collectors.toList());

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter;
import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import java.util.Collections;
@ -53,9 +52,7 @@ public class EngineGetPayloadBodiesResultV1 {
public PayloadBody(final BlockBody blockBody) {
this.transactions =
blockBody.getTransactions().stream()
.map(
transaction ->
TransactionEncoder.encodeOpaqueBytes(transaction, EncodingContext.BLOCK_BODY))
.map(TransactionEncoder::encodeOpaqueBytes)
.map(Bytes::toHexString)
.collect(Collectors.toList());
this.withdrawals =

@ -20,7 +20,6 @@ import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import java.util.List;
@ -100,9 +99,7 @@ public class TransactionPendingResult implements TransactionResult {
this.input = transaction.getPayload().toString();
this.nonce = Quantity.create(transaction.getNonce());
this.publicKey = transaction.getPublicKey().orElse(null);
this.raw =
TransactionEncoder.encodeOpaqueBytes(transaction, EncodingContext.POOLED_TRANSACTION)
.toString();
this.raw = TransactionEncoder.encodeOpaqueBytes(transaction).toString();
this.to = transaction.getTo().map(Address::toHexString).orElse(null);
this.type =
transactionType.equals(TransactionType.FRONTIER)

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.api.util;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
import org.hyperledger.besu.ethereum.rlp.RLPException;
@ -28,7 +27,7 @@ public class DomainObjectDecodeUtils {
throws InvalidJsonRpcRequestException {
try {
Bytes txnBytes = Bytes.fromHexString(rawTransaction);
return TransactionDecoder.decodeOpaqueBytes(txnBytes, EncodingContext.POOLED_TRANSACTION);
return TransactionDecoder.decodeOpaqueBytes(txnBytes);
} catch (final IllegalArgumentException e) {
throw new InvalidJsonRpcRequestException("Invalid raw transaction hex", e);
} catch (final RLPException r) {

@ -242,7 +242,6 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
payloadParams.getSuggestedFeeRecipient(),
Optional.empty(),
Optional.empty());
when(mergeCoordinator.preparePayload(
@ -519,7 +518,6 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
payloadParams.getSuggestedFeeRecipient(),
Optional.empty(),
Optional.empty());
when(mergeCoordinator.preparePayload(
@ -605,8 +603,7 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
payloadParams.getSuggestedFeeRecipient(),
withdrawals,
Optional.empty());
withdrawals);
when(mergeCoordinator.preparePayload(
mockHeader,
@ -648,7 +645,6 @@ public abstract class AbstractEngineForkchoiceUpdatedTest {
payloadParams.getTimestamp(),
payloadParams.getPrevRandao(),
payloadParams.getSuggestedFeeRecipient(),
Optional.empty(),
Optional.empty());
when(mergeCoordinator.preparePayload(

@ -85,12 +85,7 @@ public abstract class AbstractEngineGetPayloadTest extends AbstractScheduledApiT
protected static final BlockResultFactory factory = new BlockResultFactory();
protected static final PayloadIdentifier mockPid =
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
1337L,
Bytes32.random(),
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty());
Hash.ZERO, 1337L, Bytes32.random(), Address.fromHexString("0x42"), Optional.empty());
protected static final BlockHeader mockHeader =
new BlockHeaderTestFixture().prevRandao(Bytes32.random()).buildHeader();
private static final Block mockBlock =
@ -152,12 +147,7 @@ public abstract class AbstractEngineGetPayloadTest extends AbstractScheduledApiT
resp(
getMethodName(),
PayloadIdentifier.forPayloadParams(
Hash.ZERO,
0L,
Bytes32.random(),
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty()));
Hash.ZERO, 0L, Bytes32.random(), Address.fromHexString("0x42"), Optional.empty()));
assertThat(resp).isInstanceOf(JsonRpcErrorResponse.class);
verify(engineCallListener, times(1)).executionEngineCalled();
}

@ -104,7 +104,6 @@ public class EngineGetPayloadV3Test extends AbstractEngineGetPayloadTest {
cancunHardfork.milestone(),
Bytes32.random(),
Address.fromHexString("0x42"),
Optional.empty(),
Optional.empty());
BlobTestFixture blobTestFixture = new BlobTestFixture();

@ -23,13 +23,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.BlobGas;
import org.hyperledger.besu.datatypes.BlobsWithCommitments;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.BlockProcessingOutputs;
import org.hyperledger.besu.ethereum.BlockProcessingResult;
@ -41,26 +35,18 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EnginePayloadStatusResult;
import org.hyperledger.besu.ethereum.core.BlobTestFixture;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.Deposit;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.TransactionTestFixture;
import org.hyperledger.besu.ethereum.core.Withdrawal;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.mainnet.BodyValidation;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.BeforeEach;
@ -70,9 +56,6 @@ import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
protected static final KeyPair senderKeys = SIGNATURE_ALGORITHM.get().generateKeyPair();
public EngineNewPayloadV3Test() {}
@ -211,42 +194,4 @@ public class EngineNewPayloadV3Test extends EngineNewPayloadV2Test {
assertThat(jsonRpcError.getData()).isEqualTo("Missing blob gas fields");
verify(engineCallListener, times(1)).executionEngineCalled();
}
@Test
public void shouldRejectTransactionsWithFullBlobs() {
Bytes transactionWithBlobsBytes =
TransactionEncoder.encodeOpaqueBytes(
createTransactionWithBlobs(), EncodingContext.POOLED_TRANSACTION);
List<String> transactions = List.of(transactionWithBlobsBytes.toString());
BlockHeader mockHeader =
setupValidPayload(
new BlockProcessingResult(Optional.of(new BlockProcessingOutputs(null, List.of()))),
Optional.empty(),
Optional.empty());
var resp = resp(mockEnginePayload(mockHeader, transactions));
EnginePayloadStatusResult res = fromSuccessResp(resp);
assertThat(res.getStatusAsString()).isEqualTo(INVALID.name());
assertThat(res.getError()).isEqualTo("Failed to decode transactions from block parameter");
verify(engineCallListener, times(1)).executionEngineCalled();
}
private Transaction createTransactionWithBlobs() {
BlobTestFixture blobTestFixture = new BlobTestFixture();
BlobsWithCommitments bwc = blobTestFixture.createBlobsWithCommitments(1);
return new TransactionTestFixture()
.to(Optional.of(Address.fromHexString("0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF")))
.type(TransactionType.BLOB)
.chainId(Optional.of(BigInteger.ONE))
.maxFeePerGas(Optional.of(Wei.of(15)))
.maxFeePerBlobGas(Optional.of(Wei.of(128)))
.maxPriorityFeePerGas(Optional.of(Wei.of(1)))
.blobsWithCommitments(Optional.of(bwc))
.versionedHashes(Optional.of(bwc.getVersionedHashes()))
.createTransaction(senderKeys);
}
}

@ -23,7 +23,6 @@ import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
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.rlp.BytesValueRLPOutput;
@ -60,7 +59,7 @@ public class DomainObjectDecodeUtilsTest {
@Test
public void testAccessListRLPSerDes() {
final BytesValueRLPOutput encoded = new BytesValueRLPOutput();
TransactionEncoder.encodeRLP(accessListTxn, encoded, EncodingContext.POOLED_TRANSACTION);
TransactionEncoder.encodeForWire(accessListTxn, encoded);
Transaction decoded =
DomainObjectDecodeUtils.decodeRawTransaction(encoded.encoded().toHexString());
Assertions.assertThat(decoded.getAccessList().isPresent()).isTrue();
@ -69,8 +68,7 @@ public class DomainObjectDecodeUtilsTest {
@Test
public void testAccessList2718OpaqueSerDes() {
final Bytes encoded =
TransactionEncoder.encodeOpaqueBytes(accessListTxn, EncodingContext.POOLED_TRANSACTION);
final Bytes encoded = TransactionEncoder.encodeOpaqueBytes(accessListTxn);
Transaction decoded = DomainObjectDecodeUtils.decodeRawTransaction(encoded.toString());
Assertions.assertThat(decoded.getAccessList().isPresent()).isTrue();
Assertions.assertThat(decoded.getAccessList().map(List::size).get()).isEqualTo(1);

@ -50,7 +50,7 @@ import org.hyperledger.besu.ethereum.mainnet.WithdrawalsProcessor;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
import org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.account.EvmAccount;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
@ -190,10 +190,10 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
final List<BlockHeader> ommers = maybeOmmers.orElse(selectOmmers());
maybeParentBeaconBlockRoot.ifPresent(
bytes32 ->
ParentBeaconBlockRootHelper.storeParentBeaconBlockRoot(
disposableWorldState.updater(), timestamp, bytes32));
if (maybeParentBeaconBlockRoot.isPresent()) {
ParentBeaconBlockRootHelper.storeParentBeaconBlockRoot(
disposableWorldState.updater(), timestamp, maybeParentBeaconBlockRoot.get());
}
throwIfStopped();
final TransactionSelectionResults transactionResults =
@ -466,9 +466,9 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
.getBlockProcessor()
.getCoinbaseReward(blockReward, header.getNumber(), ommers.size());
final WorldUpdater updater = worldState.updater();
final MutableAccount beneficiary = updater.getOrCreate(miningBeneficiary);
final EvmAccount beneficiary = updater.getOrCreate(miningBeneficiary);
beneficiary.incrementBalance(coinbaseReward);
beneficiary.getMutable().incrementBalance(coinbaseReward);
for (final BlockHeader ommerHeader : ommers) {
if (ommerHeader.getNumber() - header.getNumber() > MAX_GENERATION) {
LOG.trace(
@ -479,12 +479,12 @@ public abstract class AbstractBlockCreator implements AsyncBlockCreator {
return false;
}
final MutableAccount ommerCoinbase = updater.getOrCreate(ommerHeader.getCoinbase());
final EvmAccount ommerCoinbase = updater.getOrCreate(ommerHeader.getCoinbase());
final Wei ommerReward =
protocolSpec
.getBlockProcessor()
.getOmmerReward(blockReward, header.getNumber(), ommerHeader.getNumber());
ommerCoinbase.incrementBalance(ommerReward);
ommerCoinbase.getMutable().incrementBalance(ommerReward);
}
updater.commit();

@ -34,7 +34,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.testutil.TestClock;
import org.hyperledger.besu.util.number.Fraction;
import java.time.ZoneId;
import java.util.function.Function;
@ -65,7 +64,7 @@ public class LegacyFeeMarketBlockTransactionSelectorTest
final TransactionPoolConfiguration poolConf =
ImmutableTransactionPoolConfiguration.builder()
.txPoolMaxSize(5)
.txPoolLimitByAccountPercentage(Fraction.fromFloat(1f))
.txPoolLimitByAccountPercentage(1)
.build();
final PendingTransactions pendingTransactions =

@ -39,7 +39,6 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.plugin.data.TransactionSelectionResult;
import org.hyperledger.besu.testutil.TestClock;
import org.hyperledger.besu.util.number.Fraction;
import java.time.ZoneId;
import java.util.List;
@ -73,7 +72,7 @@ public class LondonFeeMarketBlockTransactionSelectorTest
final TransactionPoolConfiguration poolConf =
ImmutableTransactionPoolConfiguration.builder()
.txPoolMaxSize(5)
.txPoolLimitByAccountPercentage(Fraction.fromFloat(1f))
.txPoolLimitByAccountPercentage(1)
.build();
final PendingTransactions pendingTransactions =
new BaseFeePendingTransactionsSorter(

@ -39,7 +39,7 @@ public class EntriesFromIntegrationTest {
public void shouldCollectStateEntries() {
final MutableWorldState worldState = createInMemoryWorldStateArchive().getMutable();
final WorldUpdater updater = worldState.updater();
MutableAccount account = updater.getOrCreate(Address.fromHexString("0x56"));
MutableAccount account = updater.getOrCreate(Address.fromHexString("0x56")).getMutable();
final Map<Bytes32, AccountStorageEntry> expectedValues = new TreeMap<>();
final int nodeCount = 100_000;
final Random random = new Random(42989428249L);
@ -49,19 +49,19 @@ public class EntriesFromIntegrationTest {
addExpectedValue(
account,
expectedValues,
UInt256.valueOf(random.nextLong(Long.MAX_VALUE)),
UInt256.valueOf(i * 10 + 1L));
UInt256.valueOf(Math.abs(random.nextLong())),
UInt256.valueOf(i * 10 + 1));
}
updater.commit();
// Add some changes on top that AbstractWorldUpdater.UpdateTrackingAccount will have to merge.
account = worldState.updater().getOrCreate(Address.fromHexString("0x56"));
account = worldState.updater().getOrCreate(Address.fromHexString("0x56")).getMutable();
for (int i = 0; i <= nodeCount; i++) {
addExpectedValue(
account,
expectedValues,
UInt256.valueOf(random.nextLong(Long.MAX_VALUE)),
UInt256.valueOf(i * 10 + 1L));
UInt256.valueOf(Math.abs(random.nextLong())),
UInt256.valueOf(i * 10 + 1));
}
final Map<Bytes32, AccountStorageEntry> values =

@ -59,7 +59,7 @@ public class TransientStorageOperationBenchmark {
.blockHeader(blockHeader)
.blockchain(blockchain)
.build();
worldStateUpdater.getOrCreate(address).setBalance(Wei.of(1));
worldStateUpdater.getOrCreate(address).getMutable().setBalance(Wei.of(1));
worldStateUpdater.commit();
return benchmarkFrame;

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.rlp.RLPInput;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.hyperledger.besu.evm.ModificationNotAllowedException;
import org.hyperledger.besu.evm.account.AccountStorageEntry;
import org.hyperledger.besu.evm.account.EvmAccount;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
@ -40,9 +41,9 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
public class BonsaiAccount implements MutableAccount, AccountValue {
public class BonsaiAccount implements MutableAccount, EvmAccount, AccountValue {
private final BonsaiWorldView context;
private boolean mutable;
private final boolean mutable;
private final Address address;
private final Hash addressHash;
@ -162,7 +163,7 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
@Override
public void setNonce(final long value) {
if (!mutable) {
throw new ModificationNotAllowedException();
throw new UnsupportedOperationException("Account is immutable");
}
nonce = value;
}
@ -175,7 +176,7 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
@Override
public void setBalance(final Wei value) {
if (!mutable) {
throw new ModificationNotAllowedException();
throw new UnsupportedOperationException("Account is immutable");
}
balance = value;
}
@ -191,7 +192,7 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
@Override
public void setCode(final Bytes code) {
if (!mutable) {
throw new ModificationNotAllowedException();
throw new UnsupportedOperationException("Account is immutable");
}
this.code = code;
if (code == null || code.isEmpty()) {
@ -219,7 +220,7 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
@Override
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
final Bytes32 startKeyHash, final int limit) {
return context.getWorldStateStorage().storageEntriesFrom(this.addressHash, startKeyHash, limit);
throw new RuntimeException("Bonsai Tries does not currently support enumerating storage");
}
public Bytes serializeAccount() {
@ -243,7 +244,7 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
@Override
public void setStorageValue(final UInt256 key, final UInt256 value) {
if (!mutable) {
throw new ModificationNotAllowedException();
throw new UnsupportedOperationException("Account is immutable");
}
updatedStorage.put(key, value);
}
@ -258,6 +259,15 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
return updatedStorage;
}
@Override
public MutableAccount getMutable() throws ModificationNotAllowedException {
if (mutable) {
return this;
} else {
throw new ModificationNotAllowedException();
}
}
@Override
public Hash getStorageRoot() {
return storageRoot;
@ -265,16 +275,11 @@ public class BonsaiAccount implements MutableAccount, AccountValue {
public void setStorageRoot(final Hash storageRoot) {
if (!mutable) {
throw new ModificationNotAllowedException();
throw new UnsupportedOperationException("Account is immutable");
}
this.storageRoot = storageRoot;
}
@Override
public void becomeImmutable() {
mutable = false;
}
@Override
public String toString() {
return "AccountState{"

@ -102,8 +102,8 @@ public class BonsaiWorldStateProvider implements WorldStateArchive {
pluginContext);
this.blockchain = blockchain;
this.worldStateStorage = worldStateStorage;
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
this.persistedState = new BonsaiWorldState(this, worldStateStorage);
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
blockchain
.getBlockHeader(persistedState.getWorldStateBlockHash())
.ifPresent(

@ -1,68 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.bonsai.storage;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage;
import java.util.Optional;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
/** Acts as both a Hasher and PreImageStorage for Bonsai storage format. */
public interface BonsaiPreImageProxy extends WorldStatePreimageStorage {
/**
* If this value is not already present, save in preImage store and return the hash value.
*
* @param value value to hash
* @return Hash of value
*/
Hash hashAndSavePreImage(Bytes value);
/**
* A caching PreImageProxy suitable for ReferenceTestWorldState which saves hashes in an unbounded
* BiMap.
*/
class BonsaiReferenceTestPreImageProxy implements BonsaiPreImageProxy {
BiMap<Hash, Bytes> preImageCache = HashBiMap.create();
@Override
public synchronized Hash hashAndSavePreImage(final Bytes value) {
return preImageCache.inverse().computeIfAbsent(value, Hash::hash);
}
@Override
public Optional<UInt256> getStorageTrieKeyPreimage(final Bytes32 trieKey) {
return Optional.ofNullable(preImageCache.get(trieKey)).map(UInt256::fromBytes);
}
@Override
public Optional<Address> getAccountTrieKeyPreimage(final Bytes32 trieKey) {
return Optional.ofNullable(preImageCache.get(trieKey)).map(Address::wrap);
}
@Override
public Updater updater() {
throw new UnsupportedOperationException(
"BonsaiReferenceTestPreImageProxy does not implement an updater");
}
}
}

@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.worldstate.DataStorageFormat;
import org.hyperledger.besu.ethereum.worldstate.FlatDbMode;
import org.hyperledger.besu.ethereum.worldstate.StateTrieAccountValue;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage;
import org.hyperledger.besu.evm.account.AccountStorageEntry;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorageTransaction;
@ -42,7 +41,6 @@ import org.hyperledger.besu.util.Subscribers;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Predicate;
@ -55,6 +53,7 @@ import org.slf4j.LoggerFactory;
@SuppressWarnings("unused")
public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldStateKeyValueStorage.class);
// 0x776f726c64526f6f74
@ -251,11 +250,6 @@ public class BonsaiWorldStateKeyValueStorage implements WorldStateStorage, AutoC
composedWorldStateStorage, accountHash, startKeyHash, endKeyHash, max);
}
public NavigableMap<Bytes32, AccountStorageEntry> storageEntriesFrom(
final Hash addressHash, final Bytes32 startKeyHash, final int limit) {
throw new RuntimeException("Bonsai Tries does not currently support enumerating storage");
}
@Override
public Optional<Bytes> getNodeData(final Bytes location, final Bytes32 hash) {
return Optional.empty();

@ -135,10 +135,10 @@ public abstract class FlatDbReaderStrategy {
final long max) {
final Stream<Pair<Bytes32, Bytes>> pairStream =
storage
.streamFromKey(
ACCOUNT_INFO_STATE, startKeyHash.toArrayUnsafe(), endKeyHash.toArrayUnsafe())
.streamFromKey(ACCOUNT_INFO_STATE, startKeyHash.toArrayUnsafe())
.limit(max)
.map(pair -> new Pair<>(Bytes32.wrap(pair.getKey()), Bytes.wrap(pair.getValue())));
.map(pair -> new Pair<>(Bytes32.wrap(pair.getKey()), Bytes.wrap(pair.getValue())))
.takeWhile(pair -> pair.getFirst().compareTo(endKeyHash) <= 0);
final TreeMap<Bytes32, Bytes> collected =
pairStream.collect(
@ -157,14 +157,15 @@ public abstract class FlatDbReaderStrategy {
storage
.streamFromKey(
ACCOUNT_STORAGE_STORAGE,
Bytes.concatenate(accountHash, startKeyHash).toArrayUnsafe(),
Bytes.concatenate(accountHash, endKeyHash).toArrayUnsafe())
Bytes.concatenate(accountHash, startKeyHash).toArrayUnsafe())
.takeWhile(pair -> Bytes.wrap(pair.getKey()).slice(0, Hash.SIZE).equals(accountHash))
.limit(max)
.map(
pair ->
new Pair<>(
Bytes32.wrap(Bytes.wrap(pair.getKey()).slice(Hash.SIZE)),
RLP.encodeValue(Bytes.wrap(pair.getValue()).trimLeadingZeros())));
RLP.encodeValue(Bytes.wrap(pair.getValue()).trimLeadingZeros())))
.takeWhile(pair -> pair.getFirst().compareTo(endKeyHash) <= 0);
final TreeMap<Bytes32, Bytes> collected =
pairStream.collect(

@ -27,7 +27,6 @@ import org.hyperledger.besu.datatypes.StorageSlotKey;
import org.hyperledger.besu.ethereum.bonsai.BonsaiAccount;
import org.hyperledger.besu.ethereum.bonsai.BonsaiValue;
import org.hyperledger.besu.ethereum.bonsai.BonsaiWorldStateProvider;
import org.hyperledger.besu.ethereum.bonsai.cache.CachedMerkleTrieLoader;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiSnapshotWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage;
import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStorage.BonsaiStorageSubscriber;
@ -66,52 +65,51 @@ public class BonsaiWorldState
private static final Logger LOG = LoggerFactory.getLogger(BonsaiWorldState.class);
protected BonsaiWorldStateKeyValueStorage worldStateStorage;
private BonsaiWorldStateKeyValueStorage worldStateStorage;
protected final CachedMerkleTrieLoader cachedMerkleTrieLoader;
protected final TrieLogManager trieLogManager;
private BonsaiWorldStateUpdateAccumulator accumulator;
private final BonsaiWorldStateProvider archive;
private final BonsaiWorldStateUpdateAccumulator accumulator;
protected Hash worldStateRootHash;
private Hash worldStateRootHash;
Hash worldStateBlockHash;
private boolean isFrozen;
public BonsaiWorldState(
final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateStorage) {
this(worldStateStorage, archive.getCachedMerkleTrieLoader(), archive.getTrieLogManager());
}
protected BonsaiWorldState(
final BonsaiWorldStateKeyValueStorage worldStateStorage,
final CachedMerkleTrieLoader cachedMerkleTrieLoader,
final TrieLogManager trieLogManager) {
this.archive = archive;
this.worldStateStorage = worldStateStorage;
this.worldStateRootHash =
worldStateRootHash =
Hash.wrap(
Bytes32.wrap(worldStateStorage.getWorldStateRootHash().orElse(Hash.EMPTY_TRIE_HASH)));
this.worldStateBlockHash =
worldStateBlockHash =
Hash.wrap(Bytes32.wrap(worldStateStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.accumulator =
accumulator =
new BonsaiWorldStateUpdateAccumulator(
this,
(addr, value) ->
cachedMerkleTrieLoader.preLoadAccount(
getWorldStateStorage(), worldStateRootHash, addr),
archive
.getCachedMerkleTrieLoader()
.preLoadAccount(getWorldStateStorage(), worldStateRootHash, addr),
(addr, value) ->
cachedMerkleTrieLoader.preLoadStorageSlot(getWorldStateStorage(), addr, value));
this.cachedMerkleTrieLoader = cachedMerkleTrieLoader;
this.trieLogManager = trieLogManager;
archive
.getCachedMerkleTrieLoader()
.preLoadStorageSlot(getWorldStateStorage(), addr, value));
}
/**
* Having a protected method to override the accumulator solves the chicken-egg problem of needing
* a worldstate reference (this) when construction the Accumulator.
*
* @param accumulator accumulator to use.
*/
protected void setAccumulator(final BonsaiWorldStateUpdateAccumulator accumulator) {
this.accumulator = accumulator;
public BonsaiWorldState(
final BonsaiWorldStateProvider archive,
final BonsaiWorldStateKeyValueStorage worldStateStorage,
final BonsaiWorldStateUpdateAccumulator updater) {
this.archive = archive;
this.worldStateStorage = worldStateStorage;
this.worldStateRootHash =
Hash.wrap(
Bytes32.wrap(worldStateStorage.getWorldStateRootHash().orElse(Hash.EMPTY_TRIE_HASH)));
this.worldStateBlockHash =
Hash.wrap(Bytes32.wrap(worldStateStorage.getWorldStateBlockHash().orElse(Hash.ZERO)));
this.accumulator = updater;
}
/**
@ -132,6 +130,10 @@ public class BonsaiWorldState
return worldStateRootHash;
}
public BonsaiWorldStateProvider getArchive() {
return archive;
}
@Override
public boolean isPersisted() {
return isPersisted(worldStateStorage);
@ -187,7 +189,9 @@ public class BonsaiWorldState
final StoredMerklePatriciaTrie<Bytes, Bytes> accountTrie =
createTrie(
(location, hash) ->
cachedMerkleTrieLoader.getAccountStateTrieNode(worldStateStorage, location, hash),
archive
.getCachedMerkleTrieLoader()
.getAccountStateTrieNode(worldStateStorage, location, hash),
worldStateRootHash);
// for manicured tries and composting, collect branches here (not implemented)
@ -219,7 +223,7 @@ public class BonsaiWorldState
final BonsaiAccount updatedAccount = bonsaiValue.getUpdated();
try {
if (updatedAccount == null) {
final Hash addressHash = hashAndSavePreImage(accountKey);
final Hash addressHash = Hash.hash(accountKey);
accountTrie.remove(addressHash);
maybeStateUpdater.ifPresent(
bonsaiUpdater -> bonsaiUpdater.removeAccountInfoState(addressHash));
@ -228,7 +232,7 @@ public class BonsaiWorldState
final Bytes accountValue = updatedAccount.serializeAccount();
maybeStateUpdater.ifPresent(
bonsaiUpdater ->
bonsaiUpdater.putAccountInfoState(hashAndSavePreImage(accountKey), accountValue));
bonsaiUpdater.putAccountInfoState(Hash.hash(accountKey), accountValue));
accountTrie.put(addressHash, accountValue);
}
} catch (MerkleTrieException e) {
@ -273,8 +277,10 @@ public class BonsaiWorldState
final StoredMerklePatriciaTrie<Bytes, Bytes> storageTrie =
createTrie(
(location, key) ->
cachedMerkleTrieLoader.getAccountStorageTrieNode(
worldStateStorage, updatedAddressHash, location, key),
archive
.getCachedMerkleTrieLoader()
.getAccountStorageTrieNode(
worldStateStorage, updatedAddressHash, location, key),
storageRoot);
// for manicured tries and composting, collect branches here (not implemented)
@ -399,6 +405,7 @@ public class BonsaiWorldState
}
saveTrieLog =
() -> {
final TrieLogManager trieLogManager = archive.getTrieLogManager();
trieLogManager.saveTrieLog(localCopy, newWorldStateRootHash, blockHeader, this);
// not save a frozen state in the cache
if (!isFrozen) {
@ -619,9 +626,4 @@ public class BonsaiWorldState
// no op
}
}
protected Hash hashAndSavePreImage(final Bytes value) {
// by default do not save has preImages
return Hash.hash(value);
}
}

@ -27,9 +27,10 @@ import org.hyperledger.besu.ethereum.bonsai.storage.BonsaiWorldStateKeyValueStor
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.trie.MerkleTrieException;
import org.hyperledger.besu.evm.account.Account;
import org.hyperledger.besu.evm.account.MutableAccount;
import org.hyperledger.besu.evm.account.EvmAccount;
import org.hyperledger.besu.evm.worldstate.AbstractWorldUpdater;
import org.hyperledger.besu.evm.worldstate.UpdateTrackingAccount;
import org.hyperledger.besu.evm.worldstate.WrappedEvmAccount;
import org.hyperledger.besu.plugin.services.trielogs.TrieLog;
import org.hyperledger.besu.plugin.services.trielogs.TrieLogAccumulator;
@ -43,7 +44,6 @@ import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import com.google.common.collect.ForwardingMap;
@ -115,37 +115,33 @@ public class BonsaiWorldStateUpdateAccumulator
}
@Override
public MutableAccount getAccount(final Address address) {
public EvmAccount getAccount(final Address address) {
return super.getAccount(address);
}
@Override
public MutableAccount createAccount(final Address address, final long nonce, final Wei balance) {
public EvmAccount createAccount(final Address address, final long nonce, final Wei balance) {
BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) {
bonsaiValue = new BonsaiValue<>(null, null);
accountsToUpdate.put(address, bonsaiValue);
} else if (bonsaiValue.getUpdated() != null) {
if (bonsaiValue.getUpdated().isEmpty()) {
return track(new UpdateTrackingAccount<>(bonsaiValue.getUpdated()));
} else {
throw new IllegalStateException("Cannot create an account when one already exists");
}
throw new IllegalStateException("Cannot create an account when one already exists");
}
final BonsaiAccount newAccount =
new BonsaiAccount(
this,
address,
hashAndSavePreImage(address),
address.addressHash(),
nonce,
balance,
Hash.EMPTY_TRIE_HASH,
Hash.EMPTY,
true);
bonsaiValue.setUpdated(newAccount);
return track(new UpdateTrackingAccount<>(newAccount));
return new WrappedEvmAccount(track(new UpdateTrackingAccount<>(newAccount)));
}
@Override
@ -180,15 +176,17 @@ public class BonsaiWorldStateUpdateAccumulator
final BonsaiValue<BonsaiAccount> bonsaiValue = accountsToUpdate.get(address);
if (bonsaiValue == null) {
final Account account;
if (wrappedWorldView()
instanceof BonsaiWorldStateUpdateAccumulator bonsaiWorldStateUpdateAccumulator) {
account = bonsaiWorldStateUpdateAccumulator.loadAccount(address, bonsaiAccountFunction);
if (wrappedWorldView() instanceof BonsaiWorldStateUpdateAccumulator) {
account =
((BonsaiWorldStateUpdateAccumulator) wrappedWorldView())
.loadAccount(address, bonsaiAccountFunction);
} else {
account = wrappedWorldView().get(address);
}
if (account instanceof BonsaiAccount bonsaiAccount) {
BonsaiAccount mutableAccount = new BonsaiAccount(bonsaiAccount, this, true);
accountsToUpdate.put(address, new BonsaiValue<>(bonsaiAccount, mutableAccount));
BonsaiAccount mutableAccount = null;
if (account instanceof BonsaiAccount) {
mutableAccount = new BonsaiAccount((BonsaiAccount) account, this, true);
accountsToUpdate.put(address, new BonsaiValue<>((BonsaiAccount) account, mutableAccount));
return mutableAccount;
} else {
// add the empty read in accountsToUpdate
@ -292,19 +290,6 @@ public class BonsaiWorldStateUpdateAccumulator
final BonsaiAccount updatedAccount;
final BonsaiValue<BonsaiAccount> updatedAccountValue =
accountsToUpdate.get(updatedAddress);
final Map<StorageSlotKey, BonsaiValue<UInt256>> pendingStorageUpdates =
storageToUpdate.computeIfAbsent(
updatedAddress,
k ->
new StorageConsumingMap<>(
updatedAddress, new ConcurrentHashMap<>(), storagePreloader));
if (tracked.getStorageWasCleared()) {
storageToClear.add(updatedAddress);
pendingStorageUpdates.clear();
}
if (tracked.getWrappedAccount() == null) {
updatedAccount = new BonsaiAccount(this, tracked);
tracked.setWrappedAccount(updatedAccount);
@ -324,17 +309,6 @@ public class BonsaiWorldStateUpdateAccumulator
}
if (tracked.getStorageWasCleared()) {
updatedAccount.clearStorage();
wrappedWorldView()
.getAllAccountStorage(updatedAddress, updatedAccount.getStorageRoot())
.forEach(
(keyHash, entryValue) -> {
final StorageSlotKey storageSlotKey =
new StorageSlotKey(Hash.wrap(keyHash), Optional.empty());
final UInt256 value = UInt256.fromBytes(RLP.decodeOne(entryValue));
pendingStorageUpdates.put(
storageSlotKey, new BonsaiValue<>(value, null, true));
});
updatedAccount.setStorageRoot(Hash.EMPTY_TRIE_HASH);
}
tracked.getUpdatedStorage().forEach(updatedAccount::setStorageValue);
}
@ -357,12 +331,24 @@ public class BonsaiWorldStateUpdateAccumulator
pendingCode.setUpdated(updatedAccount.getCode());
}
// This is especially to avoid unnecessary computation for withdrawals and
// self-destruct beneficiaries
// This is especially to avoid unnecessary computation for withdrawals
if (updatedAccount.getUpdatedStorage().isEmpty()) {
return;
}
final StorageConsumingMap<StorageSlotKey, BonsaiValue<UInt256>>
pendingStorageUpdates =
storageToUpdate.computeIfAbsent(
updatedAddress,
__ ->
new StorageConsumingMap<>(
updatedAddress, new ConcurrentHashMap<>(), storagePreloader));
if (tracked.getStorageWasCleared()) {
storageToClear.add(updatedAddress);
pendingStorageUpdates.clear();
}
final TreeSet<Map.Entry<UInt256, UInt256>> entries =
new TreeSet<>(Map.Entry.comparingByKey());
entries.addAll(updatedAccount.getUpdatedStorage().entrySet());
@ -371,7 +357,7 @@ public class BonsaiWorldStateUpdateAccumulator
entries.forEach(
storageUpdate -> {
final UInt256 keyUInt = storageUpdate.getKey();
final Hash slotHash = hashAndSavePreImage(keyUInt);
final Hash slotHash = Hash.hash(keyUInt);
final StorageSlotKey slotKey =
new StorageSlotKey(slotHash, Optional.of(keyUInt));
final UInt256 value = storageUpdate.getValue();
@ -415,8 +401,7 @@ public class BonsaiWorldStateUpdateAccumulator
@Override
public UInt256 getStorageValue(final Address address, final UInt256 slotKey) {
StorageSlotKey storageSlotKey =
new StorageSlotKey(hashAndSavePreImage(slotKey), Optional.of(slotKey));
StorageSlotKey storageSlotKey = new StorageSlotKey(Hash.hash(slotKey), Optional.of(slotKey));
return getStorageValueByStorageSlotKey(address, storageSlotKey).orElse(UInt256.ZERO);
}
@ -433,13 +418,14 @@ public class BonsaiWorldStateUpdateAccumulator
}
try {
final Optional<UInt256> valueUInt =
(wrappedWorldView() instanceof BonsaiWorldState bonsaiWorldState)
? bonsaiWorldState.getStorageValueByStorageSlotKey(
() ->
Optional.ofNullable(loadAccount(address, BonsaiValue::getPrior))
.map(BonsaiAccount::getStorageRoot),
address,
storageSlotKey)
(wrappedWorldView() instanceof BonsaiWorldState)
? ((BonsaiWorldState) wrappedWorldView())
.getStorageValueByStorageSlotKey(
() ->
Optional.ofNullable(loadAccount(address, BonsaiValue::getPrior))
.map(BonsaiAccount::getStorageRoot),
address,
storageSlotKey)
: wrappedWorldView().getStorageValueByStorageSlotKey(address, storageSlotKey);
storageToUpdate
.computeIfAbsent(
@ -460,7 +446,7 @@ public class BonsaiWorldStateUpdateAccumulator
public UInt256 getPriorStorageValue(final Address address, final UInt256 storageKey) {
// TODO maybe log the read into the trie layer?
StorageSlotKey storageSlotKey =
new StorageSlotKey(hashAndSavePreImage(storageKey), Optional.of(storageKey));
new StorageSlotKey(Hash.hash(storageKey), Optional.of(storageKey));
final Map<StorageSlotKey, BonsaiValue<UInt256>> localAccountStorage =
storageToUpdate.get(address);
if (localAccountStorage != null) {
@ -509,43 +495,53 @@ public class BonsaiWorldStateUpdateAccumulator
}
public void rollForward(final TrieLog layer) {
layer
.getAccountChanges()
layer.getAccountChanges().entrySet().stream()
.forEach(
(address, change) ->
rollAccountChange(address, change.getPrior(), change.getUpdated()));
layer
.getCodeChanges()
entry ->
rollAccountChange(
entry.getKey(), entry.getValue().getPrior(), entry.getValue().getUpdated()));
layer.getCodeChanges().entrySet().stream()
.forEach(
(address, change) -> rollCodeChange(address, change.getPrior(), change.getUpdated()));
layer
.getStorageChanges()
entry ->
rollCodeChange(
entry.getKey(), entry.getValue().getPrior(), entry.getValue().getUpdated()));
layer.getStorageChanges().entrySet().stream()
.forEach(
(address, storage) ->
storage.forEach(
(storageSlotKey, value) ->
rollStorageChange(
address, storageSlotKey, value.getPrior(), value.getUpdated())));
entry ->
entry
.getValue()
.forEach(
(storageSlotKey, value) ->
rollStorageChange(
entry.getKey(),
storageSlotKey,
value.getPrior(),
value.getUpdated())));
}
public void rollBack(final TrieLog layer) {
layer
.getAccountChanges()
layer.getAccountChanges().entrySet().stream()
.forEach(
(address, change) ->
rollAccountChange(address, change.getUpdated(), change.getPrior()));
layer
.getCodeChanges()
entry ->
rollAccountChange(
entry.getKey(), entry.getValue().getUpdated(), entry.getValue().getPrior()));
layer.getCodeChanges().entrySet().stream()
.forEach(
(address, change) -> rollCodeChange(address, change.getUpdated(), change.getPrior()));
layer
.getStorageChanges()
entry ->
rollCodeChange(
entry.getKey(), entry.getValue().getUpdated(), entry.getValue().getPrior()));
layer.getStorageChanges().entrySet().stream()
.forEach(
(address, storage) ->
storage.forEach(
(storageSlotKey, value) ->
rollStorageChange(
address, storageSlotKey, value.getUpdated(), value.getPrior())));
entry ->
entry
.getValue()
.forEach(
(storageSlotKey, value) ->
rollStorageChange(
entry.getKey(),
storageSlotKey,
value.getUpdated(),
value.getPrior())));
}
private void rollAccountChange(
@ -602,7 +598,8 @@ public class BonsaiWorldStateUpdateAccumulator
final Address address, final BonsaiValue<BonsaiAccount> defaultValue) {
try {
final Account parentAccount = wrappedWorldView().get(address);
if (parentAccount instanceof BonsaiAccount account) {
if (parentAccount instanceof BonsaiAccount) {
final BonsaiAccount account = (BonsaiAccount) parentAccount;
final BonsaiValue<BonsaiAccount> loadedAccountValue =
new BonsaiValue<>(new BonsaiAccount(account), account);
accountsToUpdate.put(address, loadedAccountValue);
@ -637,7 +634,7 @@ public class BonsaiWorldStateUpdateAccumulator
}
if (codeValue == null) {
if ((expectedCode == null || expectedCode.isEmpty()) && replacementCode != null) {
if ((expectedCode == null || expectedCode.size() == 0) && replacementCode != null) {
codeToUpdate.put(address, new BonsaiValue<>(null, replacementCode));
} else {
throw new IllegalStateException(
@ -775,11 +772,11 @@ public class BonsaiWorldStateUpdateAccumulator
public static class AccountConsumingMap<T> extends ForwardingMap<Address, T> {
private final ConcurrentMap<Address, T> accounts;
private final ConcurrentHashMap<Address, T> accounts;
private final Consumer<T> consumer;
public AccountConsumingMap(
final ConcurrentMap<Address, T> accounts, final Consumer<T> consumer) {
final ConcurrentHashMap<Address, T> accounts, final Consumer<T> consumer) {
this.accounts = accounts;
this.consumer = consumer;
}
@ -804,11 +801,11 @@ public class BonsaiWorldStateUpdateAccumulator
private final Address address;
private final ConcurrentMap<K, T> storages;
private final ConcurrentHashMap<K, T> storages;
private final Consumer<K> consumer;
public StorageConsumingMap(
final Address address, final ConcurrentMap<K, T> storages, final Consumer<K> consumer) {
final Address address, final ConcurrentHashMap<K, T> storages, final Consumer<K> consumer) {
this.address = address;
this.storages = storages;
this.consumer = consumer;
@ -833,9 +830,4 @@ public class BonsaiWorldStateUpdateAccumulator
public interface Consumer<T> {
void process(final Address address, T value);
}
protected Hash hashAndSavePreImage(final Bytes bytes) {
// by default do not save hash preImages
return Hash.hash(bytes);
}
}

@ -48,6 +48,7 @@ import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.base.MoreObjects;
@ -85,7 +86,8 @@ public final class GenesisState {
*/
public static GenesisState fromConfig(
final GenesisConfigFile config, final ProtocolSchedule protocolSchedule) {
final List<GenesisAccount> genesisAccounts = parseAllocations(config).toList();
final List<GenesisAccount> genesisAccounts =
parseAllocations(config).collect(Collectors.toList());
final Block block =
new Block(
buildHeader(config, calculateGenesisStateHash(genesisAccounts), protocolSchedule),
@ -122,7 +124,7 @@ public final class GenesisState {
final WorldUpdater updater = target.updater();
genesisAccounts.forEach(
genesisAccount -> {
final MutableAccount account = updater.getOrCreate(genesisAccount.address);
final MutableAccount account = updater.getOrCreate(genesisAccount.address).getMutable();
account.setNonce(genesisAccount.nonce);
account.setBalance(genesisAccount.balance);
account.setCode(genesisAccount.code);

@ -35,9 +35,7 @@ import org.hyperledger.besu.datatypes.Sha256Hash;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.encoding.AccessListTransactionEncoder;
import org.hyperledger.besu.ethereum.core.encoding.BlobTransactionEncoder;
import org.hyperledger.besu.ethereum.core.encoding.EncodingContext;
import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder;
import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
@ -128,7 +126,7 @@ public class Transaction
}
public static Transaction readFrom(final RLPInput rlpInput) {
return TransactionDecoder.decodeRLP(rlpInput, EncodingContext.BLOCK_BODY);
return TransactionDecoder.decodeForWire(rlpInput);
}
/**
@ -191,15 +189,14 @@ public class Transaction
if (versionedHashes.isPresent() || maxFeePerBlobGas.isPresent()) {
checkArgument(
transactionType.supportsBlob(),
"Must not specify blob versioned hashes or max fee per blob gas for transaction not supporting it");
"Must not specify blob versioned hashes of max fee per blob gas for transaction not supporting it");
}
if (transactionType.supportsBlob()) {
checkArgument(
versionedHashes.isPresent(), "Must specify blob versioned hashes for blob transaction");
checkArgument(
!versionedHashes.get().isEmpty(),
"Blob transaction must have at least one versioned hash");
!versionedHashes.get().isEmpty(), "Blob transaction must have at least one blob");
checkArgument(
maxFeePerBlobGas.isPresent(), "Must specify max fee per blob gas for blob transaction");
}
@ -615,7 +612,7 @@ public class Transaction
* @param out the output to write the transaction to
*/
public void writeTo(final RLPOutput out) {
TransactionEncoder.encodeRLP(this, out, EncodingContext.BLOCK_BODY);
TransactionEncoder.encodeForWire(this, out);
}
@Override
@ -678,17 +675,18 @@ public class Transaction
}
private void memoizeHashAndSize() {
final Bytes bytes = TransactionEncoder.encodeOpaqueBytes(this, EncodingContext.BLOCK_BODY);
final Bytes bytes = TransactionEncoder.encodeOpaqueBytes(this);
hash = Hash.hash(bytes);
if (transactionType.supportsBlob()) {
if (getBlobsWithCommitments().isPresent()) {
final Bytes pooledBytes =
TransactionEncoder.encodeOpaqueBytes(this, EncodingContext.POOLED_TRANSACTION);
size = pooledBytes.size();
return;
size = TransactionEncoder.encodeOpaqueBytes(this).size();
}
} else {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
TransactionEncoder.encodeForWire(transactionType, bytes, rlpOutput);
size = rlpOutput.encodedSize();
}
size = bytes.size();
}
/**
@ -969,7 +967,7 @@ public class Transaction
rlpOutput.writeBytes(to.map(Bytes::copy).orElse(Bytes.EMPTY));
rlpOutput.writeUInt256Scalar(value);
rlpOutput.writeBytes(payload);
AccessListTransactionEncoder.writeAccessList(rlpOutput, accessList);
TransactionEncoder.writeAccessList(rlpOutput, accessList);
}
private static Bytes blobPreimage(
@ -1020,7 +1018,7 @@ public class Transaction
RLP.encode(
rlpOutput -> {
rlpOutput.startList();
AccessListTransactionEncoder.encodeAccessListInner(
TransactionEncoder.encodeAccessListInner(
chainId, nonce, gasPrice, gasLimit, to, value, payload, accessList, rlpOutput);
rlpOutput.endList();
});
@ -1092,26 +1090,10 @@ public class Transaction
sb.append("value=").append(getValue()).append(", ");
sb.append("sig=").append(getSignature()).append(", ");
if (chainId.isPresent()) sb.append("chainId=").append(getChainId().get()).append(", ");
sb.append("payload=").append(getPayload());
if (transactionType.equals(TransactionType.ACCESS_LIST)) {
sb.append("accessList=").append(maybeAccessList).append(", ");
sb.append(", ").append("accessList=").append(maybeAccessList);
}
if (versionedHashes.isPresent()) {
final List<VersionedHash> vhs = versionedHashes.get();
if (!vhs.isEmpty()) {
sb.append("versionedHashes=[");
sb.append(
vhs.get(0)
.toString()); // can't be empty if present, as this is checked in the constructor
for (int i = 1; i < vhs.size(); i++) {
sb.append(", ").append(vhs.get(i).toString());
}
sb.append("], ");
}
}
if (transactionType.supportsBlob() && this.blobsWithCommitments.isPresent()) {
sb.append("numberOfBlobs=").append(blobsWithCommitments.get().getBlobs().size()).append(", ");
}
sb.append("payload=").append(getPayload());
return sb.append("}").toString();
}

@ -1,74 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.math.BigInteger;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
class AccessListTransactionDecoder {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
public static Transaction decode(final RLPInput rlpInput) {
rlpInput.enterList();
final Transaction.Builder preSignatureTransactionBuilder =
Transaction.builder()
.type(TransactionType.ACCESS_LIST)
.chainId(BigInteger.valueOf(rlpInput.readLongScalar()))
.nonce(rlpInput.readLongScalar())
.gasPrice(Wei.of(rlpInput.readUInt256Scalar()))
.gasLimit(rlpInput.readLongScalar())
.to(
rlpInput.readBytes(
addressBytes -> addressBytes.size() == 0 ? null : Address.wrap(addressBytes)))
.value(Wei.of(rlpInput.readUInt256Scalar()))
.payload(rlpInput.readBytes())
.accessList(
rlpInput.readList(
accessListEntryRLPInput -> {
accessListEntryRLPInput.enterList();
final AccessListEntry accessListEntry =
new AccessListEntry(
Address.wrap(accessListEntryRLPInput.readBytes()),
accessListEntryRLPInput.readList(RLPInput::readBytes32));
accessListEntryRLPInput.leaveList();
return accessListEntry;
}));
final byte recId = (byte) rlpInput.readIntScalar();
final Transaction transaction =
preSignatureTransactionBuilder
.signature(
SIGNATURE_ALGORITHM
.get()
.createSignature(
rlpInput.readUInt256Scalar().toUnsignedBigInteger(),
rlpInput.readUInt256Scalar().toUnsignedBigInteger(),
recId))
.build();
rlpInput.leaveList();
return transaction;
}
}

@ -1,109 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.writeSignature;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
public class AccessListTransactionEncoder {
public static void encode(final Transaction transaction, final RLPOutput rlpOutput) {
rlpOutput.startList();
encodeAccessListInner(
transaction.getChainId(),
transaction.getNonce(),
transaction.getGasPrice().orElseThrow(),
transaction.getGasLimit(),
transaction.getTo(),
transaction.getValue(),
transaction.getPayload(),
transaction
.getAccessList()
.orElseThrow(
() ->
new IllegalStateException(
"Developer error: access list should be guaranteed to be present")),
rlpOutput);
rlpOutput.writeIntScalar(transaction.getSignature().getRecId());
writeSignature(transaction, rlpOutput);
rlpOutput.endList();
}
public static void encodeAccessListInner(
final Optional<BigInteger> chainId,
final long nonce,
final Wei gasPrice,
final long gasLimit,
final Optional<Address> to,
final Wei value,
final Bytes payload,
final List<AccessListEntry> accessList,
final RLPOutput rlpOutput) {
rlpOutput.writeBigIntegerScalar(chainId.orElseThrow());
rlpOutput.writeLongScalar(nonce);
rlpOutput.writeUInt256Scalar(gasPrice);
rlpOutput.writeLongScalar(gasLimit);
rlpOutput.writeBytes(to.map(Bytes::copy).orElse(Bytes.EMPTY));
rlpOutput.writeUInt256Scalar(value);
rlpOutput.writeBytes(payload);
/*
Access List encoding should look like this
where hex strings represent raw bytes
[
[
"0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
[
"0x0000000000000000000000000000000000000000000000000000000000000003",
"0x0000000000000000000000000000000000000000000000000000000000000007"
]
],
[
"0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
[]
]
] */
writeAccessList(rlpOutput, Optional.of(accessList));
}
public static void writeAccessList(
final RLPOutput out, final Optional<List<AccessListEntry>> accessListEntries) {
if (accessListEntries.isEmpty()) {
out.writeEmptyList();
} else {
out.writeList(
accessListEntries.get(),
(accessListEntry, accessListEntryRLPOutput) -> {
accessListEntryRLPOutput.startList();
out.writeBytes(accessListEntry.address());
out.writeList(
accessListEntry.storageKeys(),
(storageKeyBytes, storageKeyBytesRLPOutput) ->
storageKeyBytesRLPOutput.writeBytes(storageKeyBytes));
accessListEntryRLPOutput.endList();
});
}
}
}

@ -1,50 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.KZGCommitment;
import org.hyperledger.besu.datatypes.KZGProof;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.util.List;
/**
* Class responsible for decoding blob transactions from the transaction pool. Blob transactions
* have two network representations. During transaction gossip responses (PooledTransactions), the
* EIP-2718 TransactionPayload of the blob transaction is wrapped to become: rlp([tx_payload_body,
* blobs, commitments, proofs]).
*/
public class BlobPooledTransactionDecoder {
/**
* Decodes a blob transaction from the provided RLP input.
*
* @param input the RLP input to decode
* @return the decoded transaction
*/
public static Transaction decode(final RLPInput input) {
input.enterList();
final Transaction.Builder builder = Transaction.builder();
BlobTransactionDecoder.readTransactionPayloadInner(builder, input);
List<Blob> blobs = input.readList(Blob::readFrom);
List<KZGCommitment> commitments = input.readList(KZGCommitment::readFrom);
List<KZGProof> proofs = input.readList(KZGProof::readFrom);
input.leaveList();
builder.kzgBlobs(commitments, blobs, proofs);
return builder.build();
}
}

@ -1,47 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import static org.slf4j.LoggerFactory.getLogger;
import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.KZGCommitment;
import org.hyperledger.besu.datatypes.KZGProof;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.security.InvalidParameterException;
import org.slf4j.Logger;
public class BlobPooledTransactionEncoder {
private static final Logger LOG = getLogger(BlobPooledTransactionEncoder.class);
static final String NO_BLOBS_ERROR =
"Transaction with no blobsWithCommitments cannot be encoded for Pooled Transaction";
public static void encode(final Transaction transaction, final RLPOutput out) {
LOG.trace("Encoding transaction with blobs {}", transaction);
var blobsWithCommitments = transaction.getBlobsWithCommitments();
if (blobsWithCommitments.isEmpty() || blobsWithCommitments.get().getBlobs().isEmpty()) {
throw new InvalidParameterException(NO_BLOBS_ERROR);
}
out.startList();
BlobTransactionEncoder.encode(transaction, out);
out.writeList(blobsWithCommitments.get().getBlobs(), Blob::writeTo);
out.writeList(blobsWithCommitments.get().getKzgCommitments(), KZGCommitment::writeTo);
out.writeList(blobsWithCommitments.get().getKzgProofs(), KZGProof::writeTo);
out.endList();
}
}

@ -18,12 +18,16 @@ import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.KZGCommitment;
import org.hyperledger.besu.datatypes.KZGProof;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.util.List;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
@ -32,15 +36,17 @@ public class BlobTransactionDecoder {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
/**
* Decodes a blob transaction from the provided RLP input.
*
* @param input the RLP input to decode
* @return the decoded transaction
*/
public static Transaction decode(final RLPInput input) {
static Transaction decode(final RLPInput input) {
Transaction transaction;
transaction = readTransactionPayload(input);
input.enterList();
// BlobTransactionNetworkWrapper
if (input.nextIsList()) {
transaction = readNetworkWrapperInner(input);
} else {
transaction = readTransactionPayload(input);
}
input.leaveList();
return transaction;
}
@ -50,17 +56,8 @@ public class BlobTransactionDecoder {
return builder.build();
}
/**
* Reads the payload of a blob transaction from the provided RLP input.
*
* <p>[chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data,
* access_list, max_fee_per_blob_gas, blob_versioned_hashes, y_parity, r, s]
*
* @param builder the transaction builder
* @param input the RLP input to read from
*/
static void readTransactionPayloadInner(final Transaction.Builder builder, final RLPInput input) {
input.enterList();
private static void readTransactionPayloadInner(
final Transaction.Builder builder, final RLPInput input) {
builder
.type(TransactionType.BLOB)
.chainId(input.readBigIntegerScalar())
@ -94,6 +91,18 @@ public class BlobTransactionDecoder {
input.readUInt256Scalar().toUnsignedBigInteger(),
input.readUInt256Scalar().toUnsignedBigInteger(),
recId));
}
private static Transaction readNetworkWrapperInner(final RLPInput input) {
final Transaction.Builder builder = Transaction.builder();
input.enterList();
readTransactionPayloadInner(builder, input);
input.leaveList();
List<Blob> blobs = input.readList(Blob::readFrom);
List<KZGCommitment> commitments = input.readList(KZGCommitment::readFrom);
List<KZGProof> proofs = input.readList(KZGProof::readFrom);
builder.kzgBlobs(commitments, blobs, proofs);
return builder.build();
}
}

@ -14,17 +14,25 @@
*/
package org.hyperledger.besu.ethereum.core.encoding;
import static org.slf4j.LoggerFactory.getLogger;
import org.hyperledger.besu.datatypes.Blob;
import org.hyperledger.besu.datatypes.KZGCommitment;
import org.hyperledger.besu.datatypes.KZGProof;
import org.hyperledger.besu.datatypes.VersionedHash;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
public class BlobTransactionEncoder {
private static final Logger LOG = getLogger(BlobTransactionEncoder.class);
public static void encode(final Transaction transaction, final RLPOutput out) {
public static void encodeEIP4844(final Transaction transaction, final RLPOutput out) {
out.startList();
out.writeBigIntegerScalar(transaction.getChainId().orElseThrow());
out.writeLongScalar(transaction.getNonce());
@ -34,7 +42,7 @@ public class BlobTransactionEncoder {
out.writeBytes(transaction.getTo().map(Bytes::copy).orElse(Bytes.EMPTY));
out.writeUInt256Scalar(transaction.getValue());
out.writeBytes(transaction.getPayload());
AccessListTransactionEncoder.writeAccessList(out, transaction.getAccessList());
TransactionEncoder.writeAccessList(out, transaction.getAccessList());
out.writeUInt256Scalar(transaction.getMaxFeePerBlobGas().orElseThrow());
out.startList();
transaction
@ -49,6 +57,29 @@ public class BlobTransactionEncoder {
out.endList();
}
private static void encodeEIP4844Network(final Transaction transaction, final RLPOutput out) {
LOG.trace("Encoding transaction with blobs {}", transaction);
out.startList();
var blobsWithCommitments = transaction.getBlobsWithCommitments().orElseThrow();
encodeEIP4844(transaction, out);
out.writeList(blobsWithCommitments.getBlobs(), Blob::writeTo);
out.writeList(blobsWithCommitments.getKzgCommitments(), KZGCommitment::writeTo);
out.writeList(blobsWithCommitments.getKzgProofs(), KZGProof::writeTo);
out.endList();
}
public static void encodeForWireNetwork(
final Transaction transaction, final RLPOutput rlpOutput) {
rlpOutput.writeBytes(encodeOpaqueBytesNetwork(transaction));
}
private static Bytes encodeOpaqueBytesNetwork(final Transaction transaction) {
return Bytes.concatenate(
Bytes.of(transaction.getType().getSerializedType()),
RLP.encode(rlpOutput -> encodeEIP4844Network(transaction, rlpOutput)));
}
public static void writeBlobVersionedHashes(
final RLPOutput rlpOutput, final List<VersionedHash> versionedHashes) {
rlpOutput.writeList(versionedHashes, (h, out) -> out.writeBytes(h.toBytes()));

@ -1,74 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.AccessListEntry;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.math.BigInteger;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
public class EIP1559TransactionDecoder {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
public static Transaction decode(final RLPInput input) {
input.enterList();
final BigInteger chainId = input.readBigIntegerScalar();
final Transaction.Builder builder =
Transaction.builder()
.type(TransactionType.EIP1559)
.chainId(chainId)
.nonce(input.readLongScalar())
.maxPriorityFeePerGas(Wei.of(input.readUInt256Scalar()))
.maxFeePerGas(Wei.of(input.readUInt256Scalar()))
.gasLimit(input.readLongScalar())
.to(input.readBytes(v -> v.size() == 0 ? null : Address.wrap(v)))
.value(Wei.of(input.readUInt256Scalar()))
.payload(input.readBytes())
.accessList(
input.readList(
accessListEntryRLPInput -> {
accessListEntryRLPInput.enterList();
final AccessListEntry accessListEntry =
new AccessListEntry(
Address.wrap(accessListEntryRLPInput.readBytes()),
accessListEntryRLPInput.readList(RLPInput::readBytes32));
accessListEntryRLPInput.leaveList();
return accessListEntry;
}));
final byte recId = (byte) input.readIntScalar();
final Transaction transaction =
builder
.signature(
SIGNATURE_ALGORITHM
.get()
.createSignature(
input.readUInt256Scalar().toUnsignedBigInteger(),
input.readUInt256Scalar().toUnsignedBigInteger(),
recId))
.build();
input.leaveList();
return transaction;
}
}

@ -1,41 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import static org.hyperledger.besu.ethereum.core.encoding.AccessListTransactionEncoder.writeAccessList;
import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.writeSignatureAndRecoveryId;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.apache.tuweni.bytes.Bytes;
public class EIP1559TransactionEncoder {
public static void encode(final Transaction transaction, final RLPOutput out) {
out.startList();
out.writeBigIntegerScalar(transaction.getChainId().orElseThrow());
out.writeLongScalar(transaction.getNonce());
out.writeUInt256Scalar(transaction.getMaxPriorityFeePerGas().orElseThrow());
out.writeUInt256Scalar(transaction.getMaxFeePerGas().orElseThrow());
out.writeLongScalar(transaction.getGasLimit());
out.writeBytes(transaction.getTo().map(Bytes::copy).orElse(Bytes.EMPTY));
out.writeUInt256Scalar(transaction.getValue());
out.writeBytes(transaction.getPayload());
writeAccessList(out, transaction.getAccessList());
writeSignatureAndRecoveryId(transaction, out);
out.endList();
}
}

@ -1,41 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
/**
* Enum representing the context in which a transaction is being encoded. This context is used to
* determine the appropriate encoding strategy for a transaction.
*
* <p>The context can be one of the following:
*
* <ul>
* <li>{@link #BLOCK_BODY}: The transaction is part of a block body. This context is used when
* encoding transactions for inclusion in a block.
* <li>{@link #POOLED_TRANSACTION}: The transaction is part of a transaction pool. This context is
* used when encoding transactions that are currently in the transaction pool, waiting to be
* included in a block. It is also used when encoding transactions for RPC calls related to
* the transaction pool.
* </ul>
*/
public enum EncodingContext {
/** Represents the context where the transaction is part of a block body. */
BLOCK_BODY,
/**
* Represents the context where the transaction is part of a transaction pool. This context is
* also used when encoding transactions for RPC calls related to the transaction pool.
*/
POOLED_TRANSACTION,
}

@ -1,76 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_BASE;
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_PROTECTED_V_MIN;
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE;
import static org.hyperledger.besu.ethereum.core.Transaction.REPLAY_UNPROTECTED_V_BASE_PLUS_1;
import static org.hyperledger.besu.ethereum.core.Transaction.TWO;
import org.hyperledger.besu.crypto.SECPSignature;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.TransactionType;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPInput;
import java.math.BigInteger;
import java.util.Optional;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
public class FrontierTransactionDecoder {
// Supplier for the signature algorithm
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
public static Transaction decode(final RLPInput input) {
input.enterList();
final Transaction.Builder builder =
Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(input.readLongScalar())
.gasPrice(Wei.of(input.readUInt256Scalar()))
.gasLimit(input.readLongScalar())
.to(input.readBytes(v -> v.size() == 0 ? null : Address.wrap(v)))
.value(Wei.of(input.readUInt256Scalar()))
.payload(input.readBytes());
final BigInteger v = input.readBigIntegerScalar();
final byte recId;
Optional<BigInteger> chainId = Optional.empty();
if (v.equals(REPLAY_UNPROTECTED_V_BASE) || v.equals(REPLAY_UNPROTECTED_V_BASE_PLUS_1)) {
recId = v.subtract(REPLAY_UNPROTECTED_V_BASE).byteValueExact();
} else if (v.compareTo(REPLAY_PROTECTED_V_MIN) > 0) {
chainId = Optional.of(v.subtract(REPLAY_PROTECTED_V_BASE).divide(TWO));
recId = v.subtract(TWO.multiply(chainId.get()).add(REPLAY_PROTECTED_V_BASE)).byteValueExact();
} else {
throw new RuntimeException(
String.format("An unsupported encoded `v` value of %s was found", v));
}
final BigInteger r = input.readUInt256Scalar().toUnsignedBigInteger();
final BigInteger s = input.readUInt256Scalar().toUnsignedBigInteger();
final SECPSignature signature = SIGNATURE_ALGORITHM.get().createSignature(r, s, recId);
input.leaveList();
chainId.ifPresent(builder::chainId);
return builder.signature(signature).build();
}
}

@ -1,36 +0,0 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.core.encoding;
import static org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder.writeSignatureAndV;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import org.apache.tuweni.bytes.Bytes;
public class FrontierTransactionEncoder {
public static void encode(final Transaction transaction, final RLPOutput out) {
out.startList();
out.writeLongScalar(transaction.getNonce());
out.writeUInt256Scalar(transaction.getGasPrice().orElseThrow());
out.writeLongScalar(transaction.getGasLimit());
out.writeBytes(transaction.getTo().map(Bytes::copy).orElse(Bytes.EMPTY));
out.writeUInt256Scalar(transaction.getValue());
out.writeBytes(transaction.getPayload());
writeSignatureAndV(transaction, out);
out.endList();
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save