From 62391739dcd09cc73f07e3f9a8ef21ec5fff240c Mon Sep 17 00:00:00 2001 From: Luis Pinto Date: Tue, 7 Jan 2025 13:32:13 +0000 Subject: [PATCH] merge main@b3b33da540 into verkle@1412aefd8b Signed-off-by: Luis Pinto --- .github/ISSUE_TEMPLATE/release-checklist.md | 25 +- .github/workflows/acceptance-tests.yml | 1 + .github/workflows/integration-tests.yml | 1 + .github/workflows/pre-review.yml | 1 + .github/workflows/reference-tests.yml | 1 + CHANGELOG.md | 71 +- CONTRIBUTING.md | 3 + acceptance-tests/dsl/build.gradle | 2 - .../condition/clique/CliqueConditions.java | 6 +- .../tests/acceptance/dsl/node/BesuNode.java | 8 - .../dsl/node/ProcessBesuNodeRunner.java | 21 - .../dsl/node/ThreadBesuNodeRunner.java | 22 +- .../configuration/BesuNodeConfiguration.java | 8 - .../BesuNodeConfigurationBuilder.java | 66 - .../node/configuration/BesuNodeFactory.java | 18 - .../node/configuration/pki/PKCS11Utils.java | 60 - .../TestPrivacyPluginPayloadProvider.java | 2 +- .../clique/CliqueMiningAcceptanceTest.java | 5 + .../CliqueProposeRpcAcceptanceTest.java | 27 + .../src/test/resources/dev/dev_prague.json | 14 + benchmark/docker-compose.yml | 4 +- besu/build.gradle | 2 +- .../org/hyperledger/besu/RunnerBuilder.java | 65 +- .../org/hyperledger/besu/cli/BesuCommand.java | 83 +- .../cli/ConfigurationOverviewBuilder.java | 3 +- .../besu/cli/config/EthNetworkConfig.java | 28 +- .../besu/cli/options/JsonRpcHttpOptions.java | 74 +- .../besu/cli/options/MiningOptions.java | 37 +- .../besu/cli/options/P2PTLSConfigOptions.java | 163 - .../besu/cli/options/PermissionsOptions.java | 20 +- .../cli/options/PrivacyPluginOptions.java | 2 +- .../besu/cli/options/RpcWebsocketOptions.java | 66 +- .../subcommands/blocks/BlocksSubCommand.java | 4 +- .../operator/GenerateBlockchainConfig.java | 4 +- .../besu/controller/BesuController.java | 41 +- .../controller/BesuControllerBuilder.java | 80 +- ...onsensusScheduleBesuControllerBuilder.java | 8 +- .../MergeBesuControllerBuilder.java | 9 +- .../controller/QbftBesuControllerBuilder.java | 17 +- .../TransitionBesuControllerBuilder.java | 9 +- .../services/BlockSimulatorServiceImpl.java | 158 + .../besu/services/BlockchainServiceImpl.java | 2 +- .../services/PrivacyPluginServiceImpl.java | 2 +- .../services/SynchronizationServiceImpl.java | 15 + .../besu/services/TraceServiceImpl.java | 5 +- .../TransactionSimulationServiceImpl.java | 54 +- .../besu/util/EphemeryGenesisUpdater.java | 16 +- .../besu/FlexGroupPrivacyTest.java | 6 +- .../besu/ForkIdsNetworkConfigTest.java | 17 +- .../hyperledger/besu/PrivacyReorgTest.java | 12 +- .../org/hyperledger/besu/PrivacyTest.java | 6 +- .../java/org/hyperledger/besu/RunnerTest.java | 20 +- .../chainexport/RlpBlockExporterTest.java | 2 + .../chainimport/JsonBlockImporterTest.java | 20 +- .../chainimport/RlpBlockImporterTest.java | 4 + .../hyperledger/besu/cli/BesuCommandTest.java | 36 +- .../cli/CascadingDefaultProviderTest.java | 7 +- .../besu/cli/CommandTestAbstract.java | 1 + .../besu/cli/HostAllowlistOptionsTest.java | 35 - .../besu/cli/config/EthNetworkConfigTest.java | 8 +- .../cli/options/JsonRpcHttpOptionsTest.java | 90 +- .../besu/components/GenesisConfigModule.java | 10 +- .../AbstractBftBesuControllerBuilderTest.java | 24 +- .../besu/controller/BesuControllerTest.java | 27 +- .../CliqueBesuControllerBuilderTest.java | 22 +- ...nsusScheduleBesuControllerBuilderTest.java | 8 +- .../IbftBesuControllerBuilderTest.java | 4 +- .../MergeBesuControllerBuilderTest.java | 25 +- .../QbftBesuControllerBuilderTest.java | 4 +- .../TransitionControllerBuilderTest.java | 12 +- .../besu/util/EphemeryGenesisUpdaterTest.java | 24 +- .../src/test/resources/everything_config.toml | 16 +- build.gradle | 2 +- .../besu/config/BlobScheduleOptions.java | 137 + ...esisConfigFile.java => GenesisConfig.java} | 40 +- .../besu/config/GenesisConfigOptions.java | 7 + .../besu/config/JsonGenesisConfigOptions.java | 11 + .../besu/config/StubGenesisConfigOptions.java | 5 + config/src/main/resources/mainnet.json | 10 + .../besu/config/BlobScheduleOptionsTest.java | 41 + .../besu/config/CliqueConfigOptionsTest.java | 2 +- .../besu/config/GenesisConfigOptionsTest.java | 48 +- ...igFileTest.java => GenesisConfigTest.java} | 72 +- .../besu/config/JsonBftConfigOptionsTest.java | 2 +- .../resources/mainnet_with_blob_schedule.json | 37 + .../clique/CliqueProtocolScheduleTest.java | 8 +- .../blockcreation/CliqueBlockCreatorTest.java | 6 +- .../CliqueMinerExecutorTest.java | 6 +- .../common/bft/BftContextBuilder.java | 10 +- .../blockcreation/BftBlockCreatorTest.java | 5 +- .../merge/TransitionBackwardSyncContext.java | 3 + .../merge/MergeProtocolScheduleTest.java | 12 +- .../blockcreation/MergeCoordinatorTest.java | 4 +- .../MergeGenesisConfigHelper.java | 14 +- .../merge/blockcreation/MergeReorgTest.java | 6 +- consensus/qbft-core/build.gradle | 82 + .../core}/support/IntegrationTestHelpers.java | 8 +- .../core}/support/RoundSpecificPeers.java | 20 +- .../qbft/core}/support/TestContext.java | 40 +- .../core}/support/TestContextBuilder.java | 27 +- .../qbft/core}/support/ValidatorPeer.java | 28 +- .../qbft/core}/test/FutureHeightTest.java | 16 +- .../qbft/core}/test/FutureRoundTest.java | 18 +- .../consensus/qbft/core}/test/GossipTest.java | 22 +- .../core}/test/LocalNodeIsProposerTest.java | 18 +- .../core}/test/LocalNodeNotProposerTest.java | 16 +- .../test/ReceivedFutureProposalTest.java | 26 +- .../qbft/core}/test/RoundChangeTest.java | 40 +- .../core}/test/SpuriousBehaviourTest.java | 20 +- .../qbft/core}/test/TransitionsTest.java | 6 +- .../core}/test/ValidatorContractTest.java | 10 +- .../test/round/QbftRoundIntegrationTest.java | 12 +- .../genesis_migrating_validator_contract.json | 0 .../resources/genesis_validator_contract.json | 0 .../genesis_validator_contract_london.json | 0 .../genesis_validator_contract_shanghai.json | 0 .../src/integration-test/resources/log4j2.xml | 0 .../resources/validator_contract.sol | 0 .../core}/messagedata/CommitMessageData.java | 4 +- .../core}/messagedata/PrepareMessageData.java | 4 +- .../messagedata/ProposalMessageData.java | 4 +- .../qbft/core}/messagedata/QbftV1.java | 2 +- .../messagedata/RoundChangeMessageData.java | 4 +- .../qbft/core}/messagewrappers/Commit.java | 4 +- .../qbft/core}/messagewrappers/Prepare.java | 4 +- .../qbft/core}/messagewrappers/Proposal.java | 8 +- .../core}/messagewrappers/RoundChange.java | 8 +- .../qbft/core/network}/QbftGossip.java | 12 +- .../core}/network/QbftMessageTransmitter.java | 26 +- .../qbft/core}/payload/CommitPayload.java | 4 +- .../qbft/core}/payload/MessageFactory.java | 12 +- .../qbft/core}/payload/PreparePayload.java | 4 +- .../core}/payload/PreparedRoundMetadata.java | 2 +- .../qbft/core}/payload/ProposalPayload.java | 4 +- .../qbft/core}/payload/QbftPayload.java | 2 +- .../core}/payload/RoundChangePayload.java | 4 +- .../BaseQbftBlockHeightManager.java | 10 +- .../statemachine/NoOpBlockHeightManager.java | 10 +- .../statemachine/PreparedCertificate.java | 4 +- .../statemachine/QbftBlockHeightManager.java | 18 +- .../QbftBlockHeightManagerFactory.java | 8 +- .../core}/statemachine/QbftController.java | 12 +- .../qbft/core}/statemachine/QbftRound.java | 32 +- .../core}/statemachine/QbftRoundFactory.java | 11 +- .../statemachine/RoundChangeArtifacts.java | 6 +- .../statemachine/RoundChangeManager.java | 6 +- .../qbft/core}/statemachine/RoundState.java | 10 +- .../core}/validation/CommitValidator.java | 6 +- .../FutureRoundProposalMessageValidator.java | 4 +- .../core}/validation/MessageValidator.java | 8 +- .../validation/MessageValidatorFactory.java | 4 +- .../core}/validation/PrepareValidator.java | 6 +- .../validation/ProposalPayloadValidator.java | 4 +- .../core}/validation/ProposalValidator.java | 23 +- .../RoundChangeMessageValidator.java | 8 +- .../RoundChangePayloadValidator.java | 6 +- .../ValidatorModeTransitionLogger.java | 2 +- .../core}/messagewrappers/CommitTest.java | 6 +- .../core}/messagewrappers/PrepareTest.java | 6 +- .../core}/messagewrappers/ProposalTest.java | 27 +- .../messagewrappers/RoundChangeTest.java | 26 +- .../qbft/core}/payload/QbftPayloadTest.java | 2 +- .../QbftBlockHeightManagerTest.java | 39 +- .../statemachine/QbftControllerTest.java | 26 +- .../core}/statemachine/QbftRoundTest.java | 52 +- .../core}/statemachine/RoundStateTest.java | 14 +- .../core}/validation/CommitValidatorTest.java | 4 +- .../validation/PrepareValidatorTest.java | 4 +- .../ProposalPayloadValidatorTest.java | 17 +- .../validation/ProposalValidatorTest.java | 63 +- .../qbft/core}/validation/QbftNode.java | 4 +- .../qbft/core}/validation/QbftNodeList.java | 4 +- .../RoundChangeMessageValidatorTest.java | 53 +- .../RoundChangePayloadValidatorTest.java | 6 +- .../validation/ValidationTestHelpers.java | 8 +- consensus/qbft/build.gradle | 17 +- .../qbft/BFTPivotSelectorFromPeers.java | 5 +- .../qbft/protocol/Istanbul100SubProtocol.java | 2 +- .../ValidatorContractController.java | 6 +- .../qbft/sync/QbftPivotSelectorTest.java | 34 +- .../ValidatorModeTransitionLoggerTest.java | 1 + .../besu/crypto/AbstractSECP256.java | 2 +- .../besu/crypto/CodeDelegationSignature.java | 9 +- .../besu/crypto/SignatureAlgorithm.java | 2 +- .../crypto/CodeDelegationSignatureTest.java | 27 +- .../besu/datatypes/AccountOverride.java | 9 +- .../hyperledger/besu/datatypes/Address.java | 13 + .../besu/datatypes/CodeDelegation.java | 2 +- .../org/hyperledger/besu/datatypes/Hash.java | 12 + .../org/hyperledger/besu/datatypes/Wei.java | 22 +- .../parameters/UInt256Parameter.java | 13 +- .../parameters/UnsignedIntParameter.java | 18 +- .../parameters/UnsignedLongParameter.java | 18 +- .../hyperledger/besu/datatypes/WeiTest.java | 24 + .../api/jsonrpc/BlockchainImporter.java | 4 +- .../api/jsonrpc/JsonRpcResponseKey.java | 2 +- .../api/jsonrpc/JsonRpcResponseUtils.java | 8 +- .../jsonrpc/JsonRpcTestMethodsFactory.java | 31 +- .../london/EthEstimateGasIntegrationTest.java | 1 + .../api/graphql/GraphQLContextType.java | 4 +- .../pojoadapter/BlockAdapterBase.java | 12 +- .../pojoadapter/NormalBlockAdapter.java | 18 +- .../pojoadapter/PendingStateAdapter.java | 6 +- .../pojoadapter/TransactionAdapter.java | 20 + .../api/jsonrpc/JsonRpcHttpService.java | 10 +- .../execution/BaseJsonRpcProcessor.java | 5 +- .../execution/TracedJsonRpcProcessor.java | 2 +- .../internal/methods/AbstractEstimateGas.java | 104 +- .../methods/AbstractTraceByBlock.java | 5 +- .../internal/methods/DebugMetrics.java | 12 +- .../api/jsonrpc/internal/methods/EthCall.java | 17 +- .../internal/methods/EthCreateAccessList.java | 70 +- .../internal/methods/EthEstimateGas.java | 61 +- .../internal/methods/EthFeeHistory.java | 2 +- .../internal/methods/EthGetBlockReceipts.java | 34 +- .../methods/EthGetMinerDataByBlockHash.java | 23 +- .../methods/EthGetMinerDataByBlockNumber.java | 1 + .../internal/methods/EthGetStorageAt.java | 2 +- .../EthGetTransactionByBlockHashAndIndex.java | 2 +- ...thGetTransactionByBlockNumberAndIndex.java | 2 +- .../EthGetUncleByBlockHashAndIndex.java | 2 +- .../EthGetUncleByBlockNumberAndIndex.java | 2 +- .../jsonrpc/internal/methods/EthGetWork.java | 1 + .../jsonrpc/internal/methods/EthHashrate.java | 1 + .../internal/methods/EthSubmitHashRate.java | 1 + .../internal/methods/EthSubmitWork.java | 1 + .../methods/ExecuteTransactionStep.java | 6 +- .../methods/JsonCallParameterUtil.java | 17 +- .../internal/methods/TraceCallMany.java | 11 +- .../AbstractEngineForkchoiceUpdated.java | 9 +- .../engine/AbstractEngineNewPayload.java | 92 +- .../EngineGetPayloadBodiesByRangeV1.java | 2 +- .../internal/methods/miner/MinerStart.java | 1 + .../internal/methods/miner/MinerStop.java | 1 + .../parameters/BlockOverridesParameter.java | 76 + ...hangeTransitionConfigurationParameter.java | 1 + .../parameters/EnginePayloadParameter.java | 1 + .../EnginePreparePayloadParameter.java | 1 + .../methods/DisabledPrivacyRpcMethod.java | 2 +- .../MultiTenancyRpcMethodDecorator.java | 2 +- .../privacy/methods/MultiTenancyUserUtil.java | 2 +- .../privacy/methods/PrivGetFilterChanges.java | 2 +- .../privacy/methods/PrivGetFilterLogs.java | 2 +- .../privacy/methods/PrivUninstallFilter.java | 2 +- .../privacy/methods/PrivacyIdProvider.java | 2 +- .../eea/AbstractEeaSendRawTransaction.java | 2 +- .../eea/JsonRpcErrorResponseException.java | 2 +- .../eea/PluginEeaSendRawTransaction.java | 2 +- ...strictedFlexibleEeaSendRawTransaction.java | 2 +- ...strictedOffchainEeaSendRawTransaction.java | 2 +- .../priv/AbstractPrivateTraceByHash.java | 2 +- .../privacy/methods/priv/PrivCall.java | 2 +- .../methods/priv/PrivCreatePrivacyGroup.java | 2 +- .../methods/priv/PrivDebugGetStateRoot.java | 2 +- .../methods/priv/PrivDeletePrivacyGroup.java | 2 +- .../priv/PrivDistributeRawTransaction.java | 2 +- .../methods/priv/PrivFindPrivacyGroup.java | 2 +- .../privacy/methods/priv/PrivGetCode.java | 2 +- .../priv/PrivGetEeaTransactionCount.java | 2 +- .../privacy/methods/priv/PrivGetLogs.java | 2 +- .../priv/PrivGetPrivacyPrecompileAddress.java | 2 +- .../priv/PrivGetPrivateTransaction.java | 2 +- .../methods/priv/PrivGetTransactionCount.java | 2 +- .../priv/PrivGetTransactionReceipt.java | 2 +- .../privacy/methods/priv/PrivNewFilter.java | 2 +- .../methods/priv/PrivTraceTransaction.java | 2 +- .../privacy/methods/priv/PrivUtil.java | 2 +- .../privx/PrivxFindFlexiblePrivacyGroup.java | 2 +- .../CreatePrivacyGroupParameter.java | 2 +- .../internal/processor/BlockReplay.java | 12 +- .../internal/processor/BlockTracer.java | 6 +- .../internal/processor/TransactionTracer.java | 6 +- .../privateProcessor/PrivateBlockReplay.java | 4 + .../privateProcessor/PrivateBlockTracer.java | 6 +- .../internal/response/RpcErrorType.java | 2 +- .../jsonrpc/internal/results/BlockResult.java | 29 +- .../results/CallProcessingResult.java | 95 + .../internal/results/MinerDataResult.java | 1 + .../jsonrpc/internal/results/PeerResult.java | 3 +- .../jsonrpc/methods/DebugJsonRpcMethods.java | 16 +- .../jsonrpc/methods/EthJsonRpcMethods.java | 29 +- .../methods/JsonRpcMethodsFactory.java | 10 +- .../jsonrpc/methods/PrivJsonRpcMethods.java | 2 +- .../PrivacyApiGroupJsonRpcMethods.java | 2 +- .../jsonrpc/methods/TraceJsonRpcMethods.java | 30 +- .../websocket/WebSocketConfiguration.java | 52 +- .../jsonrpc/websocket/WebSocketService.java | 18 +- .../request/SubscriptionRequestMapper.java | 2 +- .../ethereum/api/query/BlockchainQueries.java | 57 + .../api/tls/TlsClientAuthConfiguration.java | 41 +- .../AbstractEthGraphQLHttpServiceTest.java | 14 +- .../AbstractJsonRpcHttpServiceTest.java | 15 +- .../jsonrpc/AdminJsonRpcHttpServiceTest.java | 3 - .../JsonRpcHttpServiceHostAllowlistTest.java | 4 +- .../jsonrpc/JsonRpcHttpServiceLoginTest.java | 4 +- .../JsonRpcHttpServiceRpcApisTest.java | 7 +- .../jsonrpc/JsonRpcHttpServiceTestBase.java | 4 +- .../JsonRpcHttpServiceTlsClientAuthTest.java | 54 +- ...RpcHttpServiceTlsMisconfigurationTest.java | 4 +- .../jsonrpc/JsonRpcHttpServiceTlsTest.java | 4 +- .../internal/methods/AdminPeersTest.java | 1 - .../jsonrpc/internal/methods/EthCallTest.java | 4 +- .../methods/EthCreateAccessListTest.java | 64 +- .../internal/methods/EthEstimateGasTest.java | 113 +- .../engine/AbstractEngineNewPayloadTest.java | 2 +- ...neExchangeTransitionConfigurationTest.java | 2 +- .../processor/TransactionTracerTest.java | 7 +- .../websocket/WebSocketServiceLoginTest.java | 4 +- .../websocket/WebSocketServiceTLSTest.java | 13 +- .../api/query/BlockchainQueriesTest.java | 35 + .../api/query/PrivacyQueriesTest.java | 7 +- ...stateOverride_movePrecompileToAddress.json | 33 + .../blockcreation/AbstractBlockCreator.java | 75 +- .../blockcreation/PoWMiningCoordinator.java | 1 + .../txselection/BlockTransactionSelector.java | 7 +- .../BlobSizeTransactionSelector.java | 3 +- .../AbstractBlockCreatorTest.java | 8 +- .../AbstractBlockTransactionSelectorTest.java | 13 +- ...FeeMarketBlockTransactionSelectorTest.java | 8 +- ...FeeMarketBlockTransactionSelectorTest.java | 8 +- .../blockcreation/PoWBlockCreatorTest.java | 38 +- .../BlobSizeTransactionSelectorTest.java | 12 +- .../vm/TraceTransactionIntegrationTest.java | 21 +- .../BlockHashOperationBenchmark.java | 4 +- .../operations/OperationBenchmarkHelper.java | 4 +- .../besu/ethereum/BlockProcessingResult.java | 25 + .../besu/ethereum/GasLimitCalculator.java | 7 +- .../besu/ethereum/MainnetBlockValidator.java | 3 +- .../ethereum/chain/DefaultBlockchain.java | 34 +- .../besu/ethereum/chain/GenesisState.java | 86 +- .../besu/ethereum/core/BlockHeader.java | 19 +- .../ethereum/core/BlockHeaderBuilder.java | 73 +- .../besu/ethereum/core/CodeDelegation.java | 15 +- .../ethereum/core/ProcessableBlockHeader.java | 35 +- .../ethereum/core/SealableBlockHeader.java | 4 +- .../besu/ethereum/core/Transaction.java | 20 +- .../CodeDelegationTransactionDecoder.java | 2 +- ... => CodeDelegationTransactionEncoder.java} | 6 +- .../core/encoding/TransactionEncoder.java | 2 +- .../mainnet/AbstractBlockProcessor.java | 27 +- .../CancunTargetingGasLimitCalculator.java | 20 +- .../mainnet/CodeDelegationProcessor.java | 27 +- .../mainnet/MainnetBlockHeaderValidator.java | 8 +- .../mainnet/MainnetProtocolSpecs.java | 108 +- .../mainnet/MainnetTransactionProcessor.java | 14 +- .../mainnet/MainnetTransactionValidator.java | 22 +- .../OsakaTargetingGasLimitCalculator.java | 37 + .../PragueTargetingGasLimitCalculator.java | 37 + .../ethereum/mainnet/SystemCallProcessor.java | 6 +- .../mainnet/TransactionValidationParams.java | 7 + .../mainnet/blockhash/BlockHashProcessor.java | 10 +- .../blockhash/CancunBlockHashProcessor.java | 9 +- .../blockhash/Eip7709BlockHashProcessor.java | 34 + .../blockhash/FrontierBlockHashProcessor.java | 25 +- .../blockhash/PragueBlockHashProcessor.java | 23 +- .../mainnet/feemarket/LondonFeeMarket.java | 5 +- .../BlobGasValidationRule.java | 6 +- .../MainnetParallelBlockProcessor.java | 6 +- ...lelizedConcurrentTransactionProcessor.java | 10 +- .../PrivacyPluginPrecompiledContract.java | 2 +- .../requests/ProcessRequestContext.java | 2 +- .../requests/RequestContractAddresses.java | 4 +- ...PrivateGroupRehydrationBlockProcessor.java | 2 +- .../privacy/PrivateStateRehydration.java | 3 +- .../privacy/PrivateTransactionProcessor.java | 2 +- .../privacy/PrivateTransactionSimulator.java | 3 +- .../PrivateMigrationBlockProcessor.java | 3 +- .../migration/PrivateStorageMigration.java | 3 +- .../TransactionProcessingResult.java | 21 + .../transaction/BlockSimulationException.java | 21 + .../transaction/BlockSimulationResult.java | 58 + .../ethereum/transaction/BlockSimulator.java | 423 ++ .../ethereum/transaction/BlockStateCall.java | 61 + .../transaction/TransactionSimulator.java | 212 +- .../TransactionSimulatorResult.java | 6 + .../DiffBasedWorldStateUpdateAccumulator.java | 2 + ...va => BlockchainBasedBlockHashLookup.java} | 20 +- .../ethereum/vm/Eip7709BlockHashLookup.java | 108 + .../ethereum/core/BlockHeaderTestFixture.java | 8 +- .../ethereum/core/BlockchainSetupUtil.java | 16 +- .../core/ExecutionContextTestFixture.java | 22 +- .../core/MessageFrameTestFixture.java | 11 +- .../core/ProtocolScheduleFixture.java | 4 +- .../ethereum/core/TransactionTestFixture.java | 18 +- .../besu/ethereum/chain/GenesisStateTest.java | 4 +- ...CodeDelegationTransactionEncoderTest.java} | 8 +- .../fixed/FixedProtocolScheduleTest.java | 4 +- ...AbstractBlockProcessorIntegrationTest.java | 6 +- ...CancunTargetingGasLimitCalculatorTest.java | 33 + .../mainnet/CodeDelegationProcessorTest.java | 236 + .../mainnet/MainnetProtocolScheduleTest.java | 8 +- .../MainnetTransactionProcessorTest.java | 4 +- .../MainnetTransactionValidatorTest.java | 4 +- ...PragueTargetingGasLimitCalculatorTest.java | 33 + .../mainnet/PrivacyBlockProcessorTest.java | 3 + .../mainnet/SystemCallProcessorTest.java | 6 +- .../blockhash/BlockHashProcessorTest.java | 14 +- .../BlobGasValidationRuleTest.java | 74 +- ...zedConcurrentTransactionProcessorTest.java | 12 +- ...lexiblePrivacyPrecompiledContractTest.java | 2 +- .../PrivacyPluginPrecompiledContractTest.java | 2 +- .../PrivacyPrecompiledContractTest.java | 2 +- .../transaction/BlockSimulatorTest.java | 251 + .../transaction/TransactionSimulatorTest.java | 118 +- .../bonsai/AbstractIsolationTests.java | 8 +- .../util/AccountOverrideParameterTest.java | 44 +- ...> BlockchainBasedBlockHashLookupTest.java} | 83 +- .../ethereum/vm/DebugOperationTracerTest.java | 2 + .../vm/Eip7709BlockHashLookupTest.java | 189 + .../besu/ethereum/chain/genesis_prague.json | 2 +- .../WorldStateDownloaderBenchmark.java | 15 +- .../besu/ethereum/eth/manager/EthContext.java | 17 +- .../besu/ethereum/eth/manager/EthPeer.java | 39 +- .../besu/ethereum/eth/manager/EthPeers.java | 41 +- .../InvalidPeerTaskResponseException.java | 4 + .../eth/manager/peertask/PeerSelector.java | 9 + .../eth/manager/peertask/PeerTask.java | 10 +- .../manager/peertask/PeerTaskExecutor.java | 47 +- .../peertask/PeerTaskExecutorResult.java | 4 +- .../peertask/PeerTaskValidationResponse.java | 37 + .../peertask/task/GetHeadersFromPeerTask.java | 263 + .../task/GetReceiptsFromPeerTask.java | 19 +- .../task/AbstractRetryingPeerTask.java | 8 +- .../manager/task/GetBlockFromPeerTask.java | 127 +- .../task/RetryingGetBlockFromPeersTask.java | 20 +- .../eth/manager/task/WaitForPeerTask.java | 64 - .../eth/manager/task/WaitForPeersTask.java | 83 - .../AbstractPeerBlockValidator.java | 111 +- .../CheckpointBlocksPeerValidator.java | 23 +- .../ClassicForkPeerValidator.java | 22 +- .../peervalidation/DaoForkPeerValidator.java | 22 +- .../RequiredBlocksPeerValidator.java | 22 +- .../eth/sync/AbstractSyncTargetManager.java | 15 +- .../eth/sync/BlockPropagationManager.java | 1 + .../ethereum/eth/sync/ChainHeadTracker.java | 111 +- .../eth/sync/DefaultSynchronizer.java | 4 +- .../eth/sync/DownloadHeadersStep.java | 50 +- .../backwardsync/BackwardSyncAlgorithm.java | 14 +- .../backwardsync/BackwardSyncContext.java | 10 + .../sync/backwardsync/BackwardSyncStep.java | 78 +- .../eth/sync/backwardsync/SyncStepStep.java | 1 + .../CheckpointDownloadBlockStep.java | 7 +- .../CheckpointDownloaderFactory.java | 4 - .../checkpointsync/CheckpointSyncActions.java | 4 - .../CheckpointSyncChainDownloader.java | 10 +- ...CheckpointSyncDownloadPipelineFactory.java | 13 +- .../sync/fastsync/DownloadReceiptsStep.java | 6 +- .../eth/sync/fastsync/FastSyncActions.java | 82 +- .../fastsync/FastSyncChainDownloader.java | 10 +- .../FastSyncDownloadPipelineFactory.java | 8 +- .../eth/sync/fastsync/FastSyncDownloader.java | 7 + .../sync/fastsync/PivotBlockConfirmer.java | 90 +- .../sync/fastsync/PivotBlockRetriever.java | 7 + .../sync/fastsync/PivotSelectorFromPeers.java | 65 +- .../fastsync/PivotSelectorFromSafeBlock.java | 76 +- .../eth/sync/fastsync/SyncTargetManager.java | 61 +- .../worldstate/FastDownloaderFactory.java | 3 - .../FullSyncDownloadPipelineFactory.java | 1 + .../eth/sync/range/RangeHeadersFetcher.java | 87 +- .../sync/snapsync/SnapDownloaderFactory.java | 3 - .../tasks/DetermineCommonAncestorTask.java | 96 +- .../tasks/DownloadHeaderSequenceTask.java | 195 +- .../eth/transactions/PendingTransaction.java | 106 +- .../eth/transactions/TransactionPool.java | 129 +- .../ethereum/eth/manager/EthPeerTest.java | 2 - .../ethereum/eth/manager/EthPeersTest.java | 2 +- .../eth/manager/EthProtocolManagerTest.java | 396 +- .../EthProtocolManagerTestBuilder.java | 256 + .../manager/EthProtocolManagerTestUtil.java | 282 - .../eth/manager/RequestManagerTest.java | 1 - .../ethtaskutils/AbstractMessageTaskTest.java | 28 +- .../ethtaskutils/PeerMessageTaskTest.java | 1 - .../peertask/PeerTaskExecutorTest.java | 47 +- .../GetHeadersFromPeerTaskExecutorAnswer.java | 88 + .../task/GetHeadersFromPeerTaskTest.java | 172 + .../task/GetReceiptsFromPeerTaskTest.java | 21 +- .../task/GetBlockFromPeerTaskTest.java | 5 + .../RetryingGetBlockFromPeersTaskTest.java | 2 + .../eth/manager/task/WaitForPeerTaskTest.java | 86 - .../manager/task/WaitForPeersTaskTest.java | 104 - .../eth/messages/BlockBodiesMessageTest.java | 4 +- .../eth/messages/BlockHeadersMessageTest.java | 4 +- .../AbstractPeerBlockValidatorTest.java | 15 +- .../DaoForkPeerValidatorTest.java | 36 +- .../PeerValidatorRunnerTest.java | 9 +- .../RequiredBlocksPeerValidatorTest.java | 30 +- .../AbstractBlockPropagationManagerTest.java | 22 +- .../eth/sync/ChainHeadTrackerTest.java | 85 +- .../eth/sync/DownloadHeadersStepTest.java | 101 +- .../eth/sync/RangeHeadersFetcherTest.java | 149 +- .../backwardsync/BackwardSyncContextTest.java | 12 +- .../backwardsync/BackwardSyncStepTest.java | 146 +- .../backwardsync/ChainForTestCreator.java | 2 +- .../backwardsync/ForwardSyncStepTest.java | 3 +- .../CheckPointSyncChainDownloaderTest.java | 83 +- .../fastsync/DownloadReceiptsStepTest.java | 22 +- .../fastsync/FastDownloaderFactoryTest.java | 7 - .../sync/fastsync/FastSyncActionsTest.java | 218 +- .../fastsync/FastSyncChainDownloaderTest.java | 12 +- .../fastsync/PivotBlockConfirmerTest.java | 181 +- .../fastsync/PivotBlockRetrieverTest.java | 31 +- .../fastsync/PivotSelectorFromPeersTest.java | 91 + .../FastWorldStateDownloaderTest.java | 16 +- .../FullSyncChainDownloaderForkTest.java | 16 +- .../fullsync/FullSyncChainDownloaderTest.java | 16 +- ...DownloaderTotalTerminalDifficultyTest.java | 16 +- .../sync/fullsync/FullSyncDownloaderTest.java | 16 +- .../fullsync/FullSyncTargetManagerTest.java | 16 +- .../eth/sync/state/SyncStateTest.java | 3 +- ...neCommonAncestorTaskParameterizedTest.java | 62 +- .../DetermineCommonAncestorTaskTest.java | 209 +- .../tasks/DownloadHeaderSequenceTaskTest.java | 141 + .../eth/sync/tasks/PersistBlockTaskTest.java | 8 +- .../AbstractTransactionPoolTestBase.java | 12 +- ...ingTransactionEstimatedMemorySizeTest.java | 251 +- .../ethereum/eth/transactions/TestNode.java | 11 +- .../TransactionPoolFactoryTest.java | 1 - .../besu/evmtool/EvmToolCommand.java | 12 +- .../besu/evmtool/GenesisFileModule.java | 14 +- .../besu/evmtool/StateTestSubCommand.java | 5 +- .../hyperledger/besu/evmtool/T8nExecutor.java | 38 +- .../evmtool/benchmarks/BenchmarkExecutor.java | 2 +- ...al.json => prague-withdrawal-request.json} | 59 +- ethereum/p2p/build.gradle | 1 - .../p2p/network/DefaultP2PNetwork.java | 9 - .../besu/ethereum/p2p/rlpx/RlpxAgent.java | 29 +- .../netty/NettyTLSConnectionInitializer.java | 159 - .../connections/netty/TLSConfiguration.java | 197 - .../connections/netty/TLSContextFactory.java | 230 - .../p2p/network/DefaultP2PNetworkTest.java | 2 +- .../p2p/network/P2PPlainNetworkTest.java | 156 +- .../NettyTLSConnectionInitializerTest.java | 195 - .../netty/TLSContextFactoryTest.java | 504 -- ...odeLocalConfigPermissioningController.java | 3 +- ...ocalConfigPermissioningControllerTest.java | 51 + ...rtContractPermissioningControllerTest.java | 8 +- ...rtContractPermissioningControllerTest.java | 9 +- .../BlockchainReferenceTestCaseSpec.java | 2 +- .../referencetests/ReferenceTestEnv.java | 2 +- .../ReferenceTestWorldState.java | 1 + .../mainnet/DifficultyCalculatorTests.java | 4 +- .../vm/GeneralStateReferenceTestTools.java | 2 +- .../ethereum/stratum/GetWorkProtocol.java | 1 + .../stratum/Stratum1EthProxyProtocol.java | 1 + .../ethereum/stratum/Stratum1Protocol.java | 1 + .../ethereum/stratum/StratumConnection.java | 1 + .../ethereum/stratum/StratumProtocol.java | 1 + .../besu/ethereum/stratum/StratumServer.java | 1 + evm/build.gradle | 1 - .../evm/account/BaseDelegatedCodeAccount.java | 10 +- .../evm/account/DelegatedCodeAccount.java | 7 +- .../account/MutableDelegatedCodeAccount.java | 7 +- .../besu/evm/blockhash/BlockHashLookup.java | 28 + .../besu/evm/fluent/EVMExecutor.java | 4 +- .../besu/evm/frame/MessageFrame.java | 2 +- .../hyperledger/besu/evm/frame/TxValues.java | 3 +- .../gascalculator/CancunGasCalculator.java | 65 +- .../besu/evm/gascalculator/GasCalculator.java | 32 +- .../evm/gascalculator/OsakaGasCalculator.java | 28 +- .../gascalculator/PragueGasCalculator.java | 27 +- .../operation/AbstractCreateOperation.java | 15 +- .../operation/AbstractExtCallOperation.java | 32 +- .../evm/operation/BlockHashOperation.java | 65 +- .../evm/operation/EOFCreateOperation.java | 14 +- .../tracing/AccessListOperationTracer.java | 5 +- .../DelegatedCodeGasCostHelper.java | 14 +- .../evm/worldstate/DelegatedCodeService.java | 31 +- .../besu/evm/worldstate/EVMWorldUpdater.java | 11 +- .../evm/worldstate/UpdateTrackingAccount.java | 1 + .../besu/evm/worldstate/WorldUpdater.java | 27 +- .../hyperledger/besu/evm/code/CodeV0Test.java | 2 +- .../besu/evm/fluent/EVMExecutorTest.java | 2 +- .../besu/evm/frame/MessageFrameTest.java | 2 +- .../CancunGasCalculatorTest.java | 15 +- .../gascalculator/OsakaGasCalculatorTest.java | 43 +- .../PragueGasCalculatorTest.java | 39 + .../AbstractCreateOperationTest.java | 3 +- .../evm/operation/BlockHashOperationTest.java | 84 +- .../evm/operation/Create2OperationTest.java | 5 +- .../evm/operation/CreateOperationTest.java | 3 +- .../evm/operation/EofCreateOperationTest.java | 3 +- .../besu/evm/operation/PushOperationTest.java | 2 +- .../operation/SelfDestructOperationTest.java | 3 +- .../besu/evm/precompile/Benchmarks.java | 2 +- .../testutils/TestMessageFrameBuilder.java | 5 +- .../besu/evm/toy/EvmToyCommand.java | 2 +- gradle/verification-metadata.xml | 6726 +++++++++++++++++ gradle/versions.gradle | 0 metrics/core/build.gradle | 11 +- .../besu/metrics/MetricsService.java | 16 +- .../hyperledger/besu/metrics/Observation.java | 105 +- .../besu/metrics/noop/NoOpMetricsSystem.java | 106 +- .../opentelemetry/MetricsOtelPushService.java | 14 +- .../opentelemetry/OpenTelemetrySystem.java | 24 +- .../AbstractPrometheusHistogram.java | 113 + .../prometheus/AbstractPrometheusSummary.java | 132 + ...tractPrometheusSuppliedValueCollector.java | 96 + .../CategorizedPrometheusCollector.java | 50 + .../prometheus/CurrentValueCollector.java | 59 - .../prometheus/MetricsHttpService.java | 211 +- .../prometheus/MetricsPushGatewayService.java | 23 +- .../prometheus/PrometheusCollector.java | 82 + .../metrics/prometheus/PrometheusCounter.java | 74 +- .../prometheus/PrometheusGuavaCache.java | 171 + .../prometheus/PrometheusHistogram.java | 41 + .../prometheus/PrometheusMetricsSystem.java | 386 +- .../prometheus/PrometheusSimpleTimer.java | 25 +- .../prometheus/PrometheusSuppliedCounter.java | 73 + .../prometheus/PrometheusSuppliedGauge.java | 73 + .../prometheus/PrometheusSuppliedSummary.java | 83 + .../PrometheusSuppliedValueCollector.java | 81 - .../metrics/prometheus/PrometheusTimer.java | 28 +- .../besu/metrics/StubMetricsSystem.java | 20 +- .../OpenTelemetryMetricsSystemTest.java | 10 +- .../prometheus/MetricsHttpServiceTest.java | 76 +- .../PrometheusMetricsSystemTest.java | 153 +- .../besu/metrics/rocksdb/RocksDBStats.java | 2 +- pki/build.gradle | 49 - .../hyperledger/besu/pki/PkiException.java | 54 - .../hyperledger/besu/pki/cms/CmsCreator.java | 142 - .../besu/pki/cms/CmsValidator.java | 203 - .../pki/config/PkiKeyStoreConfiguration.java | 303 - .../org/hyperledger/besu/pki/crl/CRLUtil.java | 53 - .../pki/keystore/AbstractKeyStoreWrapper.java | 68 - .../pki/keystore/HardwareKeyStoreWrapper.java | 210 - .../besu/pki/keystore/KeyStoreWrapper.java | 88 - .../pki/keystore/SoftwareKeyStoreWrapper.java | 269 - .../besu/pki/util/TestCertificateUtils.java | 217 - .../keystore/invalidpartner1client1/crl.pem | 27 - .../keystore/invalidpartner1client1/keys.p12 | Bin 6250 -> 0 bytes .../invalidpartner1client1/keystore.jks | Bin 7159 -> 0 bytes .../keystore/invalidpartner1client1/nss.cfg | 6 - .../invalidpartner1client1/nssdb/cert8.db | Bin 65536 -> 0 bytes .../invalidpartner1client1/nssdb/key3.db | Bin 16384 -> 0 bytes .../invalidpartner1client1/nssdb/secmod.db | Bin 16384 -> 0 bytes .../invalidpartner1client1/nsspin.txt | 1 - .../invalidpartner1client1/ssl-ca.pem | 72 - .../keystore/invalidpartner1client1/ssl.pem | 129 - .../invalidpartner1client1/truststore.jks | Bin 3252 -> 0 bytes pki/src/test/resources/keystore/keystore | Bin 6773 -> 0 bytes .../keystore/partner1client1/crl.pem | 27 - .../keystore/partner1client1/nssdb/cert8.db | Bin 65536 -> 0 bytes .../keystore/partner1client1/nssdb/key3.db | Bin 16384 -> 0 bytes .../keystore/partner1client1/nssdb/secmod.db | Bin 16384 -> 0 bytes .../keystore/partner1client1/nsspin.txt | 1 - .../keystore/partner1client1/ssl-ca.pem | 70 - .../keystore/partner1client1/ssl.pem | 126 - .../keystore/partner2client1/crl.pem | 27 - .../keystore/partner2client1/keys.p12 | Bin 6068 -> 0 bytes .../keystore/partner2client1/keystore.jks | Bin 6817 -> 0 bytes .../keystore/partner2client1/nss.cfg | 6 - .../keystore/partner2client1/nssdb/cert8.db | Bin 65536 -> 0 bytes .../keystore/partner2client1/nssdb/key3.db | Bin 16384 -> 0 bytes .../keystore/partner2client1/nssdb/secmod.db | Bin 16384 -> 0 bytes .../keystore/partner2client1/nsspin.txt | 1 - .../keystore/partner2client1/ssl-ca.pem | 70 - .../keystore/partner2client1/ssl.pem | 126 - .../keystore/partner2client1/truststore.jks | Bin 3135 -> 0 bytes pki/src/test/resources/keystore/truststore | Bin 2378 -> 0 bytes .../org.mockito.plugins.MockMaker | 1 - platform/build.gradle | 17 +- plugin-api/build.gradle | 2 +- .../hyperledger/besu/plugin/BesuContext.java | 2 +- .../besu/plugin/data/BlockOverrides.java | 382 + .../data/PluginBlockSimulationResult.java | 80 + .../plugin/data/ProcessableBlockHeader.java | 6 +- .../services/BlockSimulationService.java | 59 + .../plugin/services/BlockchainService.java | 3 +- .../besu/plugin/services/MetricsSystem.java | 62 +- .../plugin/services/PrivacyPluginService.java | 2 +- .../TransactionSimulationService.java | 75 +- .../plugin/services/metrics/Histogram.java | 21 +- .../metrics/LabelledSuppliedSummary.java | 28 + .../privacy/PrivacyPluginPayloadProvider.java | 2 +- .../services/sync/SynchronizationService.java | 6 + ...imisticRocksDBColumnarKeyValueStorage.java | 2 +- .../RocksDBColumnarKeyValueStorage.java | 43 +- .../rocksdb/segmented/RocksDBOpener.java | 172 + ...ctionDBRocksDBColumnarKeyValueStorage.java | 2 +- settings.gradle | 2 +- 680 files changed, 19590 insertions(+), 9348 deletions(-) delete mode 100644 acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/pki/PKCS11Utils.java delete mode 100644 besu/src/main/java/org/hyperledger/besu/cli/options/P2PTLSConfigOptions.java create mode 100644 besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java create mode 100644 config/src/main/java/org/hyperledger/besu/config/BlobScheduleOptions.java rename config/src/main/java/org/hyperledger/besu/config/{GenesisConfigFile.java => GenesisConfig.java} (87%) create mode 100644 config/src/test/java/org/hyperledger/besu/config/BlobScheduleOptionsTest.java rename config/src/test/java/org/hyperledger/besu/config/{GenesisConfigFileTest.java => GenesisConfigTest.java} (89%) create mode 100644 config/src/test/resources/mainnet_with_blob_schedule.json create mode 100644 consensus/qbft-core/build.gradle rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/support/IntegrationTestHelpers.java (90%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/support/RoundSpecificPeers.java (91%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/support/TestContext.java (82%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/support/TestContextBuilder.java (96%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/support/ValidatorPeer.java (76%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/FutureHeightTest.java (94%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/FutureRoundTest.java (89%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/GossipTest.java (88%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/LocalNodeIsProposerTest.java (90%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/LocalNodeNotProposerTest.java (89%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/ReceivedFutureProposalTest.java (90%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/RoundChangeTest.java (91%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/SpuriousBehaviourTest.java (88%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/TransitionsTest.java (93%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/ValidatorContractTest.java (98%) rename consensus/{qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core}/test/round/QbftRoundIntegrationTest.java (95%) rename consensus/{qbft => qbft-core}/src/integration-test/resources/genesis_migrating_validator_contract.json (100%) rename consensus/{qbft => qbft-core}/src/integration-test/resources/genesis_validator_contract.json (100%) rename consensus/{qbft => qbft-core}/src/integration-test/resources/genesis_validator_contract_london.json (100%) rename consensus/{qbft => qbft-core}/src/integration-test/resources/genesis_validator_contract_shanghai.json (100%) rename consensus/{qbft => qbft-core}/src/integration-test/resources/log4j2.xml (100%) rename consensus/{qbft => qbft-core}/src/integration-test/resources/validator_contract.sol (100%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagedata/CommitMessageData.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagedata/PrepareMessageData.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagedata/ProposalMessageData.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagedata/QbftV1.java (94%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagedata/RoundChangeMessageData.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/Commit.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/Prepare.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/Proposal.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/RoundChange.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network}/QbftGossip.java (87%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/network/QbftMessageTransmitter.java (82%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/CommitPayload.java (96%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/MessageFactory.java (90%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/PreparePayload.java (96%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/PreparedRoundMetadata.java (98%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/ProposalPayload.java (96%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/QbftPayload.java (97%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/payload/RoundChangePayload.java (96%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/BaseQbftBlockHeightManager.java (79%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/NoOpBlockHeightManager.java (83%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/PreparedCertificate.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftBlockHeightManager.java (95%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftBlockHeightManagerFactory.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftController.java (90%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftRound.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftRoundFactory.java (91%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/RoundChangeArtifacts.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/RoundChangeManager.java (96%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/RoundState.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/CommitValidator.java (94%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/FutureRoundProposalMessageValidator.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/MessageValidator.java (94%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/MessageValidatorFactory.java (97%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/PrepareValidator.java (92%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/ProposalPayloadValidator.java (96%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/ProposalValidator.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/RoundChangeMessageValidator.java (94%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validation/RoundChangePayloadValidator.java (93%) rename consensus/{qbft/src/main/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core}/validator/ValidatorModeTransitionLogger.java (98%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/CommitTest.java (91%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/PrepareTest.java (90%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/ProposalTest.java (79%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/messagewrappers/RoundChangeTest.java (82%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/payload/QbftPayloadTest.java (97%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftBlockHeightManagerTest.java (94%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftControllerTest.java (95%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/QbftRoundTest.java (89%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/statemachine/RoundStateTest.java (96%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/CommitValidatorTest.java (96%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/PrepareValidatorTest.java (95%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/ProposalPayloadValidatorTest.java (92%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/ProposalValidatorTest.java (87%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/QbftNode.java (91%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/QbftNodeList.java (92%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/RoundChangeMessageValidatorTest.java (89%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/RoundChangePayloadValidatorTest.java (96%) rename consensus/{qbft/src/test/java/org/hyperledger/besu/consensus/qbft => qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core}/validation/ValidationTestHelpers.java (88%) rename {ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal => datatypes/src/main/java/org/hyperledger/besu/datatypes}/parameters/UInt256Parameter.java (79%) rename {ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal => datatypes/src/main/java/org/hyperledger/besu/datatypes}/parameters/UnsignedIntParameter.java (76%) rename {ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal => datatypes/src/main/java/org/hyperledger/besu/datatypes}/parameters/UnsignedLongParameter.java (78%) create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockOverridesParameter.java create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/CallProcessingResult.java create mode 100644 ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_stateOverride_movePrecompileToAddress.json rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/{CodeDelegationEncoder.java => CodeDelegationTransactionEncoder.java} (95%) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/OsakaTargetingGasLimitCalculator.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculator.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/Eip7709BlockHashProcessor.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationException.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationResult.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockStateCall.java rename ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/{CachingBlockHashLookup.java => BlockchainBasedBlockHashLookup.java} (75%) create mode 100644 ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java rename ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/{CodeDelegationEncoderTest.java => CodeDelegationTransactionEncoderTest.java} (93%) create mode 100644 ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculatorTest.java create mode 100644 ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessorTest.java create mode 100644 ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculatorTest.java create mode 100644 ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java rename ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/{CachingBlockHashLookupTest.java => BlockchainBasedBlockHashLookupTest.java} (61%) create mode 100644 ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookupTest.java create mode 100644 ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskValidationResponse.java create mode 100644 ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTask.java delete mode 100644 ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTask.java delete mode 100644 ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTask.java create mode 100644 ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestBuilder.java create mode 100644 ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskExecutorAnswer.java create mode 100644 ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskTest.java delete mode 100644 ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTaskTest.java delete mode 100644 ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTaskTest.java create mode 100644 ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeersTest.java rename ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/{prague-withdrawal.json => prague-withdrawal-request.json} (88%) delete mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializer.java delete mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSConfiguration.java delete mode 100644 ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactory.java delete mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializerTest.java delete mode 100644 ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactoryTest.java create mode 100644 evm/src/main/java/org/hyperledger/besu/evm/blockhash/BlockHashLookup.java create mode 100644 gradle/verification-metadata.xml delete mode 100644 gradle/versions.gradle create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/AbstractPrometheusHistogram.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/AbstractPrometheusSummary.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/AbstractPrometheusSuppliedValueCollector.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/CategorizedPrometheusCollector.java delete mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/CurrentValueCollector.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusCollector.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusGuavaCache.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusHistogram.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusSuppliedCounter.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusSuppliedGauge.java create mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusSuppliedSummary.java delete mode 100644 metrics/core/src/main/java/org/hyperledger/besu/metrics/prometheus/PrometheusSuppliedValueCollector.java delete mode 100644 pki/build.gradle delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/PkiException.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/cms/CmsCreator.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/cms/CmsValidator.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/config/PkiKeyStoreConfiguration.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/crl/CRLUtil.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/keystore/AbstractKeyStoreWrapper.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/keystore/HardwareKeyStoreWrapper.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/keystore/KeyStoreWrapper.java delete mode 100644 pki/src/main/java/org/hyperledger/besu/pki/keystore/SoftwareKeyStoreWrapper.java delete mode 100644 pki/src/test/java/org/hyperledger/besu/pki/util/TestCertificateUtils.java delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/crl.pem delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/keys.p12 delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/keystore.jks delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/nss.cfg delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/nssdb/cert8.db delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/nssdb/key3.db delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/nssdb/secmod.db delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/nsspin.txt delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/ssl-ca.pem delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/ssl.pem delete mode 100644 pki/src/test/resources/keystore/invalidpartner1client1/truststore.jks delete mode 100644 pki/src/test/resources/keystore/keystore delete mode 100644 pki/src/test/resources/keystore/partner1client1/crl.pem delete mode 100644 pki/src/test/resources/keystore/partner1client1/nssdb/cert8.db delete mode 100644 pki/src/test/resources/keystore/partner1client1/nssdb/key3.db delete mode 100644 pki/src/test/resources/keystore/partner1client1/nssdb/secmod.db delete mode 100644 pki/src/test/resources/keystore/partner1client1/nsspin.txt delete mode 100644 pki/src/test/resources/keystore/partner1client1/ssl-ca.pem delete mode 100644 pki/src/test/resources/keystore/partner1client1/ssl.pem delete mode 100644 pki/src/test/resources/keystore/partner2client1/crl.pem delete mode 100644 pki/src/test/resources/keystore/partner2client1/keys.p12 delete mode 100644 pki/src/test/resources/keystore/partner2client1/keystore.jks delete mode 100644 pki/src/test/resources/keystore/partner2client1/nss.cfg delete mode 100644 pki/src/test/resources/keystore/partner2client1/nssdb/cert8.db delete mode 100644 pki/src/test/resources/keystore/partner2client1/nssdb/key3.db delete mode 100644 pki/src/test/resources/keystore/partner2client1/nssdb/secmod.db delete mode 100644 pki/src/test/resources/keystore/partner2client1/nsspin.txt delete mode 100644 pki/src/test/resources/keystore/partner2client1/ssl-ca.pem delete mode 100644 pki/src/test/resources/keystore/partner2client1/ssl.pem delete mode 100644 pki/src/test/resources/keystore/partner2client1/truststore.jks delete mode 100644 pki/src/test/resources/keystore/truststore delete mode 100644 pki/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/data/BlockOverrides.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/data/PluginBlockSimulationResult.java create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/BlockSimulationService.java rename consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/CreateBlockForProposalBehaviour.java => plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/Histogram.java (58%) create mode 100644 plugin-api/src/main/java/org/hyperledger/besu/plugin/services/metrics/LabelledSuppliedSummary.java create mode 100644 plugins/rocksdb/src/main/java/org/hyperledger/besu/plugin/services/storage/rocksdb/segmented/RocksDBOpener.java diff --git a/.github/ISSUE_TEMPLATE/release-checklist.md b/.github/ISSUE_TEMPLATE/release-checklist.md index dcf10977f0d..8919d682e97 100644 --- a/.github/ISSUE_TEMPLATE/release-checklist.md +++ b/.github/ISSUE_TEMPLATE/release-checklist.md @@ -7,14 +7,14 @@ assignees: '' --- -- [ ] Confirm anything outstanding for release with other maintainers on #besu-release in Discord +- [ ] Confirm at least 24 hours prior anything outstanding for release with other maintainers on #besu-release in Discord - [ ] Update changelog if necessary, and merge a PR for it to main - [ ] Notify maintainers about updating changelog for in-flight PRs - [ ] Optional: for hotfixes, create a release branch and cherry-pick, e.g. `release--hotfix` - [ ] Optional: for hotfixes, create a PR into main from the hotfix branch to see the CI checks pass - [ ] On the appropriate branch/commit, create a calver tag for the release candidate, format example: `24.4.0-RC1` - - [ ] git tag 24.4.0-RC1 - - [ ] git push upstream 24.4.0-RC1 + - [ ] `git tag 24.4.0-RC1` + - [ ] `git push upstream 24.4.0-RC1` - [ ] Sign-off with team; announce the tag in #besu-release in Discord - [ ] Targeting this tag for the burn-in: https://github.com/hyperledger/besu/releases/tag/24.4.0-RC1 - [ ] Consensys staff start burn-in using this tag @@ -22,26 +22,27 @@ assignees: '' - [ ] Pass? Go ahead and complete the release process - [ ] Fail? Put a message in #besu-release in Discord indicating the release will be aborted because it failed burn-in - [ ] Optional: Perform a dry run with https://github.com/consensys/protocols-release-sandbox to test the workflows - - [ ] Sync fork - - [ ] git checkout - - [ ] git tag 24.4.0 - - [ ] git push origin 24.4.0 + - [ ] Sync fork in github + - [ ] `git checkout ` + - [ ] `git tag 24.4.0` + - [ ] `git push 24.4.0` - [ ] Manually run https://github.com/Consensys/protocols-release-sandbox/actions/workflows/draft-release.yml using `main` branch and `24.4.0` tag - [ ] Back on besu, using the same git sha as 24.4.0-RC1, create a calver tag for the FULL RELEASE, example format `24.4.0` - - [ ] git checkout 24.4.0-RC1 - - [ ] git tag 24.4.0 - - [ ] git push upstream 24.4.0 + - [ ] `git checkout 24.4.0-RC1` + - [ ] `git tag 24.4.0` + - [ ] `git push upstream 24.4.0` - [ ] Manually run https://github.com/hyperledger/besu/actions/workflows/draft-release.yml using `main` branch` and the FULL RELEASE tag name, i.e. `24.4.0`. Note, this workflow should always be run from `main` branch (hotfix tags will still be released even if they were created based on another branch) - publishes artefacts and version-specific docker tags but does not fully publish the GitHub release so subscribers are not yet notified - [ ] Check all draft-release workflow jobs went green - [ ] Check binary SHAs are correct on the release page +- [ ] Check artifacts exist in https://hyperledger.jfrog.io/ui/repos/tree/General/besu-maven - [ ] Update release notes in the GitHub draft release, save draft and sign-off with team - [ ] Publish draft release ensuring it is marked as latest release (if appropriate) - this is now public and notifies subscribed users - makes the release "latest" in github - publishes the docker `latest` tag variants -- [ ] Create homebrew release using [update-version workflow](https://github.com/hyperledger/homebrew-besu/actions/workflows/update-version.yml) +- [ ] Create homebrew release PR using [update-version workflow](https://github.com/hyperledger/homebrew-besu/actions/workflows/update-version.yml) - If the PR has not been automatically created, create the PR manually using the created branch `update-` - - Run commands `brew tap hyperledger/besu && brew install besu` on MacOSX and verify latest version has been installed +- [ ] Verify homebrew release once the PR has merged using `brew tap hyperledger/besu && brew install besu` on MacOSX to verify latest version has been installed - [ ] Delete the burn-in nodes (unless required for further analysis eg performance) - [ ] Social announcements diff --git a/.github/workflows/acceptance-tests.yml b/.github/workflows/acceptance-tests.yml index e1549b2357d..94c6d0b8453 100644 --- a/.github/workflows/acceptance-tests.yml +++ b/.github/workflows/acceptance-tests.yml @@ -5,6 +5,7 @@ on: branches: - main - release-* + - verkle concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 171ddeb85ec..22468e62cc3 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -5,6 +5,7 @@ on: branches: - main - release-* + - verkle concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/pre-review.yml b/.github/workflows/pre-review.yml index 93bfcfa9f50..7bed8bcd3c1 100644 --- a/.github/workflows/pre-review.yml +++ b/.github/workflows/pre-review.yml @@ -5,6 +5,7 @@ on: branches: - main - release-* + - verkle concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} diff --git a/.github/workflows/reference-tests.yml b/.github/workflows/reference-tests.yml index d27114ebc1e..a53580ba094 100644 --- a/.github/workflows/reference-tests.yml +++ b/.github/workflows/reference-tests.yml @@ -5,6 +5,7 @@ on: branches: - main - release-* + - verkle env: GRADLE_OPTS: "-Xmx6g -Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.caching=true" diff --git a/CHANGELOG.md b/CHANGELOG.md index 5472920ef59..efaca489248 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,68 @@ # Changelog -## [Unreleased] +## Unreleased + +### Breaking Changes +- `--host-whitelist` has been deprecated since 2020 and this option is removed. Use the equivalent `--host-allowlist` instead. + +### Upcoming Breaking Changes +- `MetricSystem::createLabelledGauge` is deprecated and will be removed in a future release, replace it with `MetricSystem::createLabelledSuppliedGauge` +- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release. Use docker or none instead. +- Sunsetting features - for more context on the reasoning behind the deprecation of these features, including alternative options, read [this blog post](https://www.lfdecentralizedtrust.org/blog/sunsetting-tessera-and-simplifying-hyperledger-besu) + - Tessera privacy + - Smart-contract-based (onchain) permissioning + - Proof of Work consensus + - Fast Sync + +### Additions and Improvements +- Add RPC HTTP options to specify custom truststore and its password [#7978](https://github.com/hyperledger/besu/pull/7978) +- Retrieve all transaction receipts for a block in one request [#6646](https://github.com/hyperledger/besu/pull/6646) +- Implement EIP-7840: Add blob schedule to config files [#8042](https://github.com/hyperledger/besu/pull/8042) +- Allow gasPrice (legacy) and 1559 gasPrice params to be specified simultaneously for `eth_call`, `eth_createAccessList`, and `eth_estimateGas` [#8059](https://github.com/hyperledger/besu/pull/8059) + + +### Bug fixes +- Fix serialization of state overrides when `movePrecompileToAddress` is present [#8204](https://github.com/hyperledger/besu/pull/8024) +- Revise the approach for setting level_compaction_dynamic_level_bytes RocksDB configuration option [#8037](https://github.com/hyperledger/besu/pull/8037) +- Fix possible incomplete txpool restore from dump file [#7991](https://github.com/hyperledger/besu/pull/7991) + +## 24.12.2 Hotfix + +This is an optional hotfix to address serialization of state overrides parameter when `movePrecompileToAddress` is present. + +There is no need to upgrade from 24.12.0 (or 24.12.1) to this release if you are not yet using this functionality. + +### Bug fixes +- Fix serialization of state overrides when `movePrecompileToAddress` is present [#8204](https://github.com/hyperledger/besu/pull/8024) + +## 24.12.1 Hotfix + +This is a hotfix to address publishing besu maven artifacts. There are no issues with 24.12.0 other than incomplete artifact publishing, and there is no functional difference between 24.12.0 and 24.12.1 release binaries. + +### Bug fixes +- Fix BOM pom publication to Artifactory [#8201](https://github.com/hyperledger/besu/pull/8021) + +## 24.12.0 ### Breaking Changes - Removed Retesteth rpc service and commands [#7833](https://github.com/hyperledger/besu/pull/7783) +- TLS for P2P (early access feature) has been removed [#7942](https://github.com/hyperledger/besu/pull/7942) +- In the plugin API, `BesuContext` has been renamed to `ServiceManager` to better reflect its function, plugins must be updated to work with this version +- With the upgrade of the Prometheus Java Metrics library, there are the following changes: + - Gauge names are not allowed to end with `total`, therefore the metric `besu_blockchain_difficulty_total` is losing the `_total` suffix + - The `_created` timestamps are not returned by default, you can set the env var `BESU_OPTS="-Dio.prometheus.exporter.includeCreatedTimestamps=true"` to enable them + - Some JVM metrics have changed name to adhere to the OTEL standard (see the table below), [Besu Full Grafana dashboard](https://grafana.com/grafana/dashboards/16455-besu-full/) is updated to support both names + + | Old Name | New Name | + |---------------------------------|---------------------------------| + | jvm_memory_bytes_committed | jvm_memory_committed_bytes | + | jvm_memory_bytes_init | jvm_memory_init_bytes | + | jvm_memory_bytes_max | jvm_memory_max_bytes | + | jvm_memory_bytes_used | jvm_memory_used_bytes | + | jvm_memory_pool_bytes_committed | jvm_memory_pool_committed_bytes | + | jvm_memory_pool_bytes_init | jvm_memory_pool_init_bytes | + | jvm_memory_pool_bytes_max | jvm_memory_pool_max_bytes | + | jvm_memory_pool_bytes_used | jvm_memory_pool_used_bytes | ### Upcoming Breaking Changes - Plugin API will be deprecating the BesuContext interface to be replaced with the ServiceManager interface. @@ -12,7 +71,7 @@ - `--host-whitelist` has been deprecated in favor of `--host-allowlist` since 2020 and will be removed in a future release - Sunsetting features - for more context on the reasoning behind the deprecation of these features, including alternative options, read [this blog post](https://www.lfdecentralizedtrust.org/blog/sunsetting-tessera-and-simplifying-hyperledger-besu) - Tessera privacy - - Smart-contract-based permissioning + - Smart-contract-based (onchain) permissioning - Proof of Work consensus - Fast Sync @@ -26,10 +85,18 @@ - Add a method to check if a metric category is enabled to the plugin API [#7832](https://github.com/hyperledger/besu/pull/7832) - Add a new metric collector for counters which get their value from suppliers [#7894](https://github.com/hyperledger/besu/pull/7894) - Add account and state overrides to `eth_call` [#7801](https://github.com/hyperledger/besu/pull/7801) and `eth_estimateGas` [#7890](https://github.com/hyperledger/besu/pull/7890) +- Add RPC WS options to specify password file for keystore and truststore [#7970](https://github.com/hyperledger/besu/pull/7970) +- Prometheus Java Metrics library upgraded to version 1.3.3 [#7880](https://github.com/hyperledger/besu/pull/7880) +- Add histogram to Prometheus metrics system [#7944](https://github.com/hyperledger/besu/pull/7944) +- Improve newPayload and FCU logs [#7961](https://github.com/hyperledger/besu/pull/7961) +- Proper support for `pending` block tag when calling `eth_estimateGas` and `eth_createAccessList` [#7951](https://github.com/hyperledger/besu/pull/7951) ### Bug fixes - Fix registering new metric categories from plugins [#7825](https://github.com/hyperledger/besu/pull/7825) - Fix CVE-2024-47535 [7878](https://github.com/hyperledger/besu/pull/7878) +- Fix QBFT prepared block based proposal validation [#7875](https://github.com/hyperledger/besu/pull/7875) +- Correct default parameters for frontier transactions in `eth_call` and `eth_estimateGas` [#7965](https://github.com/hyperledger/besu/pull/7965) +- Correctly parse nonce as hex in `eth_call` account overrides [#7999](https://github.com/hyperledger/besu/pull/7999) ## 24.10.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c13ea678524..8f2fdade398 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,9 @@ Having the following accounts is necessary for contributing code/issues to Besu. * To ask questions or chat with us, join our [Discord](https://discord.com/invite/hyperledger) * To edit pages in our wiki, you'll need a [Linux Foundation (LF) account]. +### Guidelines for Non-Code and other Trivial Contributions +Please keep in mind that we do not accept non-code contributions like fixing comments, typos or some other trivial fixes. Although we appreciate the extra help, managing lots of these small contributions is unfeasible, and puts extra pressure in our continuous delivery systems (running all tests, etc). Feel free to open an issue pointing any of those errors, and we will batch them into a single change. + ### Useful contributing links * [I just have a quick question](https://wiki.hyperledger.org/display/BESU/I+just+have+a+quick+question) diff --git a/acceptance-tests/dsl/build.gradle b/acceptance-tests/dsl/build.gradle index 0b664c52556..6602fda58b8 100644 --- a/acceptance-tests/dsl/build.gradle +++ b/acceptance-tests/dsl/build.gradle @@ -18,8 +18,6 @@ dependencies { implementation project(':ethereum:permissioning') implementation project(':ethereum:rlp') implementation project(':metrics:core') - implementation project(':pki') - implementation project(path: ':pki', configuration: 'testArtifacts') implementation project(':plugin-api') implementation project(':plugins:rocksdb') implementation project(':services:kvstore') diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java index 750e587f6e3..4490a2b2a2e 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/clique/CliqueConditions.java @@ -19,7 +19,7 @@ import static org.hyperledger.besu.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; import org.hyperledger.besu.config.CliqueConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition; import org.hyperledger.besu.tests.acceptance.dsl.condition.blockchain.ExpectBlockNotCreated; @@ -89,9 +89,9 @@ public Condition awaitSignerSetChange(final Node node) { private int cliqueBlockPeriod(final BesuNode node) { final String config = node.getGenesisConfigProvider().create(emptyList()).get(); - final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(config); + final GenesisConfig genesisConfig = GenesisConfig.fromConfig(config); final CliqueConfigOptions cliqueConfigOptions = - genesisConfigFile.getConfigOptions().getCliqueConfigOptions(); + genesisConfig.getConfigOptions().getCliqueConfigOptions(); return cliqueConfigOptions.getBlockPeriodSeconds(); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java index 76e18812b09..3f18a543152 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/BesuNode.java @@ -32,7 +32,6 @@ import org.hyperledger.besu.ethereum.core.Util; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -96,7 +95,6 @@ public class BesuNode implements NodeConfiguration, RunnableNode, AutoCloseable private final Properties portsProperties = new Properties(); private final Boolean p2pEnabled; private final int p2pPort; - private final Optional tlsConfiguration; private final NetworkingConfiguration networkingConfiguration; private final boolean revertReasonEnabled; @@ -156,7 +154,6 @@ public BesuNode( final GenesisConfigurationProvider genesisConfigProvider, final boolean p2pEnabled, final int p2pPort, - final Optional tlsConfiguration, final NetworkingConfiguration networkingConfiguration, final boolean discoveryEnabled, final boolean bootnodeEligible, @@ -207,7 +204,6 @@ public BesuNode( this.network = network; this.p2pEnabled = p2pEnabled; this.p2pPort = p2pPort; - this.tlsConfiguration = tlsConfiguration; this.networkingConfiguration = networkingConfiguration; this.discoveryEnabled = discoveryEnabled; this.bootnodeEligible = bootnodeEligible; @@ -659,10 +655,6 @@ public boolean isP2pEnabled() { return p2pEnabled; } - public Optional getTLSConfiguration() { - return tlsConfiguration; - } - public NetworkingConfiguration getNetworkingConfiguration() { return networkingConfiguration; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java index ee865a81425..33a9a1cfba2 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ProcessBesuNodeRunner.java @@ -22,7 +22,6 @@ import org.hyperledger.besu.cli.options.storage.DataStorageOptions; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.services.metrics.MetricCategory; @@ -365,26 +364,6 @@ private List commandlineArgs(final BesuNode node, final Path dataDir) { final List networkConfigParams = NetworkingOptions.fromConfig(node.getNetworkingConfiguration()).getCLIOptions(); params.addAll(networkConfigParams); - if (node.getTLSConfiguration().isPresent()) { - final TLSConfiguration config = node.getTLSConfiguration().get(); - params.add("--Xp2p-tls-enabled"); - params.add("--Xp2p-tls-keystore-type"); - params.add(config.getKeyStoreType()); - params.add("--Xp2p-tls-keystore-file"); - params.add(config.getKeyStorePath().toAbsolutePath().toString()); - params.add("--Xp2p-tls-keystore-password-file"); - params.add(config.getKeyStorePasswordPath().toAbsolutePath().toString()); - params.add("--Xp2p-tls-crl-file"); - params.add(config.getCrlPath().toAbsolutePath().toString()); - if (null != config.getTrustStoreType()) { - params.add("--Xp2p-tls-truststore-type"); - params.add(config.getTrustStoreType()); - params.add("--Xp2p-tls-truststore-file"); - params.add(config.getTrustStorePath().toAbsolutePath().toString()); - params.add("--Xp2p-tls-truststore-password-file"); - params.add(config.getTrustStorePasswordPath().toAbsolutePath().toString()); - } - } } if (node.isRevertReasonEnabled()) { diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 9effaff4d44..c18f71c4b09 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -25,7 +25,7 @@ import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.components.BesuComponent; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; import org.hyperledger.besu.crypto.KeyPairUtil; @@ -155,8 +155,8 @@ public void startNode(final BesuNode node) { networkConfigBuilder.setBootNodes(bootnodes); node.getConfiguration() .getGenesisConfig() - .map(GenesisConfigFile::fromConfig) - .ifPresent(networkConfigBuilder::setGenesisConfigFile); + .map(GenesisConfig::fromConfig) + .ifPresent(networkConfigBuilder::setGenesisConfig); final EthNetworkConfig ethNetworkConfig = networkConfigBuilder.build(); final BesuControllerBuilder builder = component.besuControllerBuilder(); builder.isRevertReasonEnabled(node.isRevertReasonEnabled()); @@ -166,9 +166,7 @@ public void startNode(final BesuNode node) { builder.nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir)))); builder.privacyParameters(node.getPrivacyParameters()); - node.getGenesisConfig() - .map(GenesisConfigFile::fromConfig) - .ifPresent(builder::genesisConfigFile); + node.getGenesisConfig().map(GenesisConfig::fromConfig).ifPresent(builder::genesisConfig); final BesuController besuController = component.besuController(); @@ -197,7 +195,6 @@ public void startNode(final BesuNode node) { .permissioningService(permissioningService) .metricsConfiguration(node.getMetricsConfiguration()) .p2pEnabled(node.isP2pEnabled()) - .p2pTLSConfiguration(node.getTLSConfiguration()) .graphQLConfiguration(GraphQLConfiguration.createDefault()) .staticNodes(node.getStaticNodes().stream().map(EnodeURLImpl::fromString).toList()) .besuPluginContext(besuPluginContext) @@ -397,9 +394,14 @@ TransactionSimulator provideTransactionSimulator( final Blockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, + final MiningConfiguration miningConfiguration, final ApiConfiguration apiConfiguration) { return new TransactionSimulator( - blockchain, worldStateArchive, protocolSchedule, apiConfiguration.getGasCap()); + blockchain, + worldStateArchive, + protocolSchedule, + miningConfiguration, + apiConfiguration.getGasCap()); } @Provides @@ -459,7 +461,8 @@ public BesuController provideBesuController( final BesuControllerBuilder builder, final MetricsSystem metricsSystem, final KeyValueStorageProvider storageProvider, - final MiningConfiguration miningConfiguration) { + final MiningConfiguration miningConfiguration, + final ApiConfiguration apiConfiguration) { builder .synchronizerConfiguration(synchronizerConfiguration) @@ -474,6 +477,7 @@ public BesuController provideBesuController( .maxRemotelyInitiatedPeers(15) .miningParameters(miningConfiguration) .randomPeerPriority(false) + .apiConfiguration(apiConfiguration) .besuComponent(null); return builder.build(); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java index 5840f1e4f1f..f6a8cfb57ae 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfiguration.java @@ -25,7 +25,6 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -56,7 +55,6 @@ public class BesuNodeConfiguration { private final GenesisConfigurationProvider genesisConfigProvider; private final boolean p2pEnabled; private final int p2pPort; - private final Optional tlsConfiguration; private final NetworkingConfiguration networkingConfiguration; private final boolean discoveryEnabled; private final boolean bootnodeEligible; @@ -95,7 +93,6 @@ public class BesuNodeConfiguration { final GenesisConfigurationProvider genesisConfigProvider, final boolean p2pEnabled, final int p2pPort, - final Optional tlsConfiguration, final NetworkingConfiguration networkingConfiguration, final boolean discoveryEnabled, final boolean bootnodeEligible, @@ -131,7 +128,6 @@ public class BesuNodeConfiguration { this.genesisConfigProvider = genesisConfigProvider; this.p2pEnabled = p2pEnabled; this.p2pPort = p2pPort; - this.tlsConfiguration = tlsConfiguration; this.networkingConfiguration = networkingConfiguration; this.discoveryEnabled = discoveryEnabled; this.bootnodeEligible = bootnodeEligible; @@ -226,10 +222,6 @@ public int getP2pPort() { return p2pPort; } - public Optional getTLSConfiguration() { - return tlsConfiguration; - } - public NetworkingConfiguration getNetworkingConfiguration() { return networkingConfiguration; } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java index 9b000f56f12..f7342a4c8fb 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeConfigurationBuilder.java @@ -16,9 +16,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static java.util.Collections.singletonList; -import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_JKS; -import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS11; -import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS12; import org.hyperledger.besu.cli.config.NetworkName; import org.hyperledger.besu.crypto.KeyPair; @@ -31,7 +28,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import org.hyperledger.besu.ethereum.api.jsonrpc.ipc.JsonRpcIpcConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration; -import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; import org.hyperledger.besu.ethereum.core.AddressHelpers; import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration; import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration.MutableInitValues; @@ -39,12 +35,10 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider; -import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PKCS11Utils; import java.io.File; import java.net.URISyntaxException; @@ -84,7 +78,6 @@ public class BesuNodeConfigurationBuilder { private GenesisConfigurationProvider genesisConfigProvider = ignore -> Optional.empty(); private Boolean p2pEnabled = true; private int p2pPort = 0; - private Optional tlsConfiguration = Optional.empty(); private final NetworkingConfiguration networkingConfiguration = NetworkingConfiguration.create(); private boolean discoveryEnabled = true; private boolean bootnodeEligible = true; @@ -381,64 +374,6 @@ public BesuNodeConfigurationBuilder p2pPort(final int p2pPort) { return this; } - private static Path toPath(final String path) throws Exception { - return Path.of(BesuNodeConfigurationBuilder.class.getResource(path).toURI()); - } - - public BesuNodeConfigurationBuilder p2pTLSEnabled(final String name, final String type) { - final TLSConfiguration.Builder builder = TLSConfiguration.Builder.tlsConfiguration(); - try { - final String nsspin = "/pki-certs/%s/nsspin.txt"; - final String truststore = "/pki-certs/%s/truststore.p12"; - final String crl = "/pki-certs/crl/crl.pem"; - switch (type) { - case KEYSTORE_TYPE_JKS: - builder - .withKeyStoreType(type) - .withKeyStorePath(toPath(String.format("/pki-certs/%s/% bannedNodeIds = new ArrayList<>(); private boolean p2pEnabled = true; - private Optional p2pTLSConfiguration = Optional.empty(); private boolean discovery; private String p2pAdvertisedHost; private String p2pListenInterface = NetworkUtility.INADDR_ANY; @@ -235,30 +233,6 @@ public RunnerBuilder p2pEnabled(final boolean p2pEnabled) { return this; } - /** - * TLSConfiguration p2pTLSConfiguration. - * - * @param p2pTLSConfiguration the TLSConfiguration p2pTLSConfiguration - * @return the runner builder - */ - public RunnerBuilder p2pTLSConfiguration(final TLSConfiguration p2pTLSConfiguration) { - this.p2pTLSConfiguration = Optional.of(p2pTLSConfiguration); - return this; - } - - /** - * Optional TLSConfiguration p2pTLSConfiguration. - * - * @param p2pTLSConfiguration the TLSConfiguration p2pTLSConfiguration - * @return the runner builder - */ - public RunnerBuilder p2pTLSConfiguration(final Optional p2pTLSConfiguration) { - if (null != p2pTLSConfiguration) { - this.p2pTLSConfiguration = p2pTLSConfiguration; - } - return this; - } - /** * Enable Discovery. * @@ -698,12 +672,7 @@ public Runner build() { final Synchronizer synchronizer = besuController.getSynchronizer(); - final TransactionSimulator transactionSimulator = - new TransactionSimulator( - context.getBlockchain(), - context.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap()); + final TransactionSimulator transactionSimulator = besuController.getTransactionSimulator(); final Bytes localNodeId = nodeKey.getPublicKey().getEncodedBytes(); final Optional nodePermissioningController = @@ -735,7 +704,6 @@ public Runner build() { .supportedCapabilities(caps) .natService(natService) .storageProvider(storageProvider) - .p2pTLSConfiguration(p2pTLSConfiguration) .blockchain(context.getBlockchain()) .blockNumberForks(besuController.getGenesisConfigOptions().getForkBlockNumbers()) .timestampForks(besuController.getGenesisConfigOptions().getForkBlockTimestamps()) @@ -867,7 +835,8 @@ public Runner build() { natService, besuPluginContext.getNamedPlugins(), dataDir, - rpcEndpointServiceImpl); + rpcEndpointServiceImpl, + transactionSimulator); jsonRpcHttpService = Optional.of( @@ -912,7 +881,8 @@ public Runner build() { natService, besuPluginContext.getNamedPlugins(), dataDir, - rpcEndpointServiceImpl); + rpcEndpointServiceImpl, + transactionSimulator); final Optional authToUse = engineJsonRpcConfiguration.get().isAuthenticationEnabled() @@ -959,7 +929,7 @@ public Runner build() { graphQlContextMap.putIfAbsent(GraphQLContextType.SYNCHRONIZER, synchronizer); graphQlContextMap.putIfAbsent( GraphQLContextType.CHAIN_ID, protocolSchedule.getChainId().map(UInt256::valueOf)); - graphQlContextMap.putIfAbsent(GraphQLContextType.GAS_CAP, apiConfiguration.getGasCap()); + graphQlContextMap.putIfAbsent(GraphQLContextType.TRANSACTION_SIMULATOR, transactionSimulator); final GraphQL graphQL; try { graphQL = GraphQLProvider.buildGraphQL(fetchers); @@ -1007,7 +977,8 @@ public Runner build() { natService, besuPluginContext.getNamedPlugins(), dataDir, - rpcEndpointServiceImpl); + rpcEndpointServiceImpl, + transactionSimulator); createLogsSubscriptionService( context.getBlockchain(), subscriptionManager, privacyParameters, blockchainQueries); @@ -1034,8 +1005,7 @@ public Runner build() { subscriptionManager, privacyParameters, context.getBlockchain().getGenesisBlockHeader()); } - final Optional metricsService = - createMetricsService(vertx, metricsConfiguration); + final Optional metricsService = createMetricsService(metricsConfiguration); final Optional ethStatsService; if (isEthStatsEnabled()) { @@ -1088,7 +1058,8 @@ public Runner build() { natService, besuPluginContext.getNamedPlugins(), dataDir, - rpcEndpointServiceImpl); + rpcEndpointServiceImpl, + transactionSimulator); jsonRpcIpcService = Optional.of( @@ -1127,7 +1098,8 @@ public Runner build() { natService, besuPluginContext.getNamedPlugins(), dataDir, - rpcEndpointServiceImpl); + rpcEndpointServiceImpl, + transactionSimulator); } else { inProcessRpcMethods = Map.of(); } @@ -1289,7 +1261,8 @@ private Map jsonRpcMethods( final NatService natService, final Map namedPlugins, final Path dataDir, - final RpcEndpointServiceImpl rpcEndpointServiceImpl) { + final RpcEndpointServiceImpl rpcEndpointServiceImpl, + final TransactionSimulator transactionSimulator) { // sync vertx for engine consensus API, to process requests in FIFO order; final Vertx consensusEngineServer = Vertx.vertx(new VertxOptions().setWorkerPoolSize(1)); @@ -1326,7 +1299,8 @@ private Map jsonRpcMethods( besuController.getProtocolManager().ethContext().getEthPeers(), consensusEngineServer, apiConfiguration, - enodeDnsConfiguration); + enodeDnsConfiguration, + transactionSimulator); methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis)); final var pluginMethods = @@ -1469,9 +1443,8 @@ private WebSocketService createWebsocketService( vertx, configuration, websocketMessageHandler, authenticationService, metricsSystem); } - private Optional createMetricsService( - final Vertx vertx, final MetricsConfiguration configuration) { - return MetricsService.create(vertx, configuration, metricsSystem); + private Optional createMetricsService(final MetricsConfiguration configuration) { + return MetricsService.create(configuration, metricsSystem); } /** diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index fe25edaf72a..b19e2c5aae3 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -60,7 +60,6 @@ import org.hyperledger.besu.cli.options.NetworkingOptions; import org.hyperledger.besu.cli.options.NodePrivateKeyFileOption; import org.hyperledger.besu.cli.options.P2PDiscoveryOptions; -import org.hyperledger.besu.cli.options.P2PTLSConfigOptions; import org.hyperledger.besu.cli.options.PermissionsOptions; import org.hyperledger.besu.cli.options.PluginsConfigurationOptions; import org.hyperledger.besu.cli.options.PrivacyPluginOptions; @@ -86,7 +85,7 @@ import org.hyperledger.besu.cli.util.VersionProvider; import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.MergeConfiguration; import org.hyperledger.besu.controller.BesuController; @@ -127,7 +126,6 @@ import org.hyperledger.besu.ethereum.p2p.peers.EnodeDnsConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.p2p.peers.StaticNodesParser; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.permissioning.LocalPermissioningConfiguration; import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration; import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProvider; @@ -136,7 +134,6 @@ import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; -import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.DiffBasedSubStorageConfiguration; import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration; @@ -155,6 +152,7 @@ import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.plugin.services.BesuConfiguration; import org.hyperledger.besu.plugin.services.BesuEvents; +import org.hyperledger.besu.plugin.services.BlockSimulationService; import org.hyperledger.besu.plugin.services.BlockchainService; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.PermissioningService; @@ -181,6 +179,7 @@ import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.services.BesuEventsImpl; import org.hyperledger.besu.services.BesuPluginContextImpl; +import org.hyperledger.besu.services.BlockSimulatorServiceImpl; import org.hyperledger.besu.services.BlockchainServiceImpl; import org.hyperledger.besu.services.MiningServiceImpl; import org.hyperledger.besu.services.P2PServiceImpl; @@ -259,7 +258,6 @@ import picocli.CommandLine.Command; import picocli.CommandLine.ExecutionException; import picocli.CommandLine.IExecutionStrategy; -import picocli.CommandLine.Mixin; import picocli.CommandLine.Option; import picocli.CommandLine.ParameterException; @@ -336,12 +334,14 @@ public class BesuCommand implements DefaultCommandValues, Runnable { new PreSynchronizationTaskRunner(); private final Set allocatedPorts = new HashSet<>(); - private final Supplier genesisConfigFileSupplier = - Suppliers.memoize(this::readGenesisConfigFile); + private final Supplier genesisConfigSupplier = + Suppliers.memoize(this::readGenesisConfig); private final Supplier genesisConfigOptionsSupplier = Suppliers.memoize(this::readGenesisConfigOptions); private final Supplier miningParametersSupplier = Suppliers.memoize(this::getMiningParameters); + private final Supplier apiConfigurationSupplier = + Suppliers.memoize(this::getApiConfiguration); private RocksDBPlugin rocksDBPlugin; @@ -612,14 +612,6 @@ static class PrivacyOptionGroup { defaultValue = "localhost,127.0.0.1") private final JsonRPCAllowlistHostsProperty hostsAllowlist = new JsonRPCAllowlistHostsProperty(); - @Option( - names = {"--host-whitelist"}, - hidden = true, - paramLabel = "[,...]... or * or all", - description = - "Deprecated in favor of --host-allowlist. Comma separated list of hostnames to allow for RPC access, or * to accept any host (default: ${DEFAULT-VALUE})") - private final JsonRPCAllowlistHostsProperty hostsWhitelist = new JsonRPCAllowlistHostsProperty(); - @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) @Option( names = {"--color-enabled"}, @@ -704,8 +696,6 @@ static class PrivacyOptionGroup { description = "Specifies the number of last blocks to cache (default: ${DEFAULT-VALUE})") private final Integer numberOfblocksToCache = 0; - @Mixin private P2PTLSConfigOptions p2pTLSConfigOptions; - // Plugins Configuration Option Group @CommandLine.ArgGroup(validate = false) PluginsConfigurationOptions pluginsConfigurationOptions = new PluginsConfigurationOptions(); @@ -717,10 +707,8 @@ static class PrivacyOptionGroup { private WebSocketConfiguration webSocketConfiguration; private JsonRpcIpcConfiguration jsonRpcIpcConfiguration; private InProcessRpcConfiguration inProcessRpcConfiguration; - private ApiConfiguration apiConfiguration; private MetricsConfiguration metricsConfiguration; private Optional permissioningConfiguration; - private Optional p2pTLSConfiguration; private DataStorageConfiguration dataStorageConfiguration; private Collection staticNodes; private BesuController besuController; @@ -1232,7 +1220,6 @@ private Runner buildRunner() { return synchronize( besuController, p2PDiscoveryConfig.p2pEnabled(), - p2pTLSConfiguration, p2PDiscoveryConfig.peerDiscoveryEnabled(), ethNetworkConfig, p2PDiscoveryConfig.p2pHost(), @@ -1244,7 +1231,7 @@ private Runner buildRunner() { webSocketConfiguration, jsonRpcIpcConfiguration, inProcessRpcConfiguration, - apiConfiguration, + apiConfigurationSupplier.get(), metricsConfiguration, permissioningConfiguration, staticNodes, @@ -1256,11 +1243,7 @@ private void startPlugins(final Runner runner) { besuController.getProtocolContext().getBlockchain(), besuController.getProtocolSchedule()); transactionSimulationServiceImpl.init( besuController.getProtocolContext().getBlockchain(), - new TransactionSimulator( - besuController.getProtocolContext().getBlockchain(), - besuController.getProtocolContext().getWorldStateArchive(), - besuController.getProtocolSchedule(), - apiConfiguration.getGasCap())); + besuController.getTransactionSimulator()); rpcEndpointServiceImpl.init(runner.getInProcessRpcMethods()); besuPluginContext.addService( @@ -1278,6 +1261,7 @@ private void startPlugins(final Runner runner) { besuPluginContext.addService( SynchronizationService.class, new SynchronizationServiceImpl( + besuController.getSynchronizer(), besuController.getProtocolContext(), besuController.getProtocolSchedule(), besuController.getSyncState(), @@ -1306,6 +1290,15 @@ private void startPlugins(final Runner runner) { besuPluginContext.addService( MiningService.class, new MiningServiceImpl(besuController.getMiningCoordinator())); + besuPluginContext.addService( + BlockSimulationService.class, + new BlockSimulatorServiceImpl( + besuController.getProtocolContext().getWorldStateArchive(), + miningParametersSupplier.get(), + besuController.getTransactionSimulator(), + besuController.getProtocolSchedule(), + besuController.getProtocolContext().getBlockchain())); + besuController.getAdditionalPluginServices().appendPluginServices(besuPluginContext); besuPluginContext.startPlugins(); } @@ -1453,10 +1446,8 @@ private void validateOptions() { validateTransactionPoolOptions(); validateDataStorageOptions(); validateGraphQlOptions(); - validateApiOptions(); validateConsensusSyncCompatibilityOptions(); validatePluginOptions(); - p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine); } private void validateConsensusSyncCompatibilityOptions() { @@ -1607,21 +1598,21 @@ private void validateChainDataPruningParams() { } } - private GenesisConfigFile readGenesisConfigFile() { - GenesisConfigFile effectiveGenesisFile; + private GenesisConfig readGenesisConfig() { + GenesisConfig effectiveGenesisFile; effectiveGenesisFile = network.equals(EPHEMERY) ? EphemeryGenesisUpdater.updateGenesis(genesisConfigOverrides) : genesisFile != null - ? GenesisConfigFile.fromSource(genesisConfigSource(genesisFile)) - : GenesisConfigFile.fromResource( + ? GenesisConfig.fromSource(genesisConfigSource(genesisFile)) + : GenesisConfig.fromResource( Optional.ofNullable(network).orElse(MAINNET).getGenesisFile()); return effectiveGenesisFile.withOverrides(genesisConfigOverrides); } private GenesisConfigOptions readGenesisConfigOptions() { try { - return genesisConfigFileSupplier.get().getConfigOptions(); + return genesisConfigSupplier.get().getConfigOptions(); } catch (final Exception e) { throw new ParameterException( this.commandLine, "Unable to load genesis file. " + e.getCause()); @@ -1647,6 +1638,10 @@ private void issueOptionWarnings() { "--p2p-port", "--remote-connections-max-percentage")); + if (SyncMode.FAST == syncMode) { + logger.warn("FAST sync is deprecated. Recommend using SNAP sync instead."); + } + if (SyncMode.isFullSync(getDefaultSyncModeIfNotSet()) && isOptionSet(commandLine, "--sync-min-peers")) { logger.warn("--sync-min-peers is ignored in FULL sync-mode"); @@ -1695,7 +1690,6 @@ private void configure() throws Exception { if (isEngineApiEnabled()) { engineJsonRpcConfiguration = createEngineJsonRpcConfiguration(); } - p2pTLSConfiguration = p2pTLSConfigOptions.p2pTLSConfiguration(commandLine); graphQLConfiguration = graphQlOptions.graphQLConfiguration( hostsAllowlist, p2PDiscoveryOptions.p2pHost, unstableRPCOptions.getHttpTimeoutSec()); @@ -1709,17 +1703,7 @@ private void configure() throws Exception { unstableIpcOptions.getIpcPath(), unstableIpcOptions.getRpcIpcApis()); inProcessRpcConfiguration = inProcessRpcOptions.toDomainObject(); - apiConfiguration = apiConfigurationOptions.apiConfiguration(); dataStorageConfiguration = getDataStorageConfiguration(); - // hostsWhitelist is a hidden option. If it is specified, add the list to hostAllowlist - if (!hostsWhitelist.isEmpty()) { - // if allowlist == default values, remove the default values - if (hostsAllowlist.size() == 2 - && hostsAllowlist.containsAll(List.of("localhost", "127.0.0.1"))) { - hostsAllowlist.removeAll(List.of("localhost", "127.0.0.1")); - } - hostsAllowlist.addAll(hostsWhitelist); - } permissioningConfiguration = permissioningConfiguration(); staticNodes = loadStaticNodes(); @@ -1827,6 +1811,7 @@ public BesuControllerBuilder setupControllerBuilder() { .chainPruningConfiguration(unstableChainPruningOptions.toDomainObject()) .cacheLastBlocks(numberOfblocksToCache) .genesisStateHashCacheEnabled(genesisStateHashCacheEnabled) + .apiConfiguration(apiConfigurationSupplier.get()) .besuComponent(besuComponent); if (DataStorageFormat.BONSAI.equals(getDataStorageConfiguration().getDataStorageFormat())) { final DiffBasedSubStorageConfiguration subStorageConfiguration = @@ -2152,6 +2137,11 @@ private MiningConfiguration getMiningParameters() { return miningParameters; } + private ApiConfiguration getApiConfiguration() { + validateApiOptions(); + return apiConfigurationOptions.apiConfiguration(); + } + /** * Get the data storage configuration * @@ -2220,7 +2210,6 @@ private OptionalInt getGenesisBlockPeriodSeconds( private Runner synchronize( final BesuController controller, final boolean p2pEnabled, - final Optional p2pTLSConfiguration, final boolean peerDiscoveryEnabled, final EthNetworkConfig ethNetworkConfig, final String p2pAdvertisedHost, @@ -2240,8 +2229,6 @@ private Runner synchronize( checkNotNull(runnerBuilder); - p2pTLSConfiguration.ifPresent(runnerBuilder::p2pTLSConfiguration); - final Runner runner = runnerBuilder .vertx(vertx) @@ -2361,7 +2348,7 @@ private EthNetworkConfig updateNetworkConfig(final NetworkName network) { builder.setDnsDiscoveryUrl(null); } - builder.setGenesisConfigFile(genesisConfigFileSupplier.get()); + builder.setGenesisConfig(genesisConfigSupplier.get()); if (networkId != null) { builder.setNetworkId(networkId); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java index a7b43d0d9e5..9e69cb608c8 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java @@ -349,7 +349,8 @@ public String build() { } if (syncMode != null) { - lines.add("Sync mode: " + syncMode); + lines.add( + "Sync mode: " + syncMode + (syncMode.equalsIgnoreCase("FAST") ? " (Deprecated)" : "")); } if (syncMinPeers != null) { diff --git a/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java b/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java index dab3a4c227c..0a8d86c795a 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/config/EthNetworkConfig.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.cli.config; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.plugin.data.EnodeURL; @@ -33,13 +33,13 @@ /** * The Eth network config. * - * @param genesisConfigFile Genesis Config File + * @param genesisConfig Genesis Config File * @param networkId Network Id * @param bootNodes Boot Nodes * @param dnsDiscoveryUrl DNS Discovery URL */ public record EthNetworkConfig( - GenesisConfigFile genesisConfigFile, + GenesisConfig genesisConfig, BigInteger networkId, List bootNodes, String dnsDiscoveryUrl) { @@ -47,7 +47,7 @@ public record EthNetworkConfig( /** * Validate parameters on new record creation * - * @param genesisConfigFile the genesis config + * @param genesisConfig the genesis config * @param networkId the network id * @param bootNodes the boot nodes * @param dnsDiscoveryUrl the dns discovery url @@ -55,7 +55,7 @@ public record EthNetworkConfig( @SuppressWarnings( "MethodInputParametersMustBeFinal") // needed since record constructors are not yet supported public EthNetworkConfig { - Objects.requireNonNull(genesisConfigFile); + Objects.requireNonNull(genesisConfig); Objects.requireNonNull(bootNodes); } @@ -67,8 +67,8 @@ public record EthNetworkConfig( */ public static EthNetworkConfig getNetworkConfig(final NetworkName networkName) { final URL genesisSource = jsonConfigSource(networkName.getGenesisFile()); - final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromSource(genesisSource); - final GenesisConfigOptions genesisConfigOptions = genesisConfigFile.getConfigOptions(); + final GenesisConfig genesisConfig = GenesisConfig.fromSource(genesisSource); + final GenesisConfigOptions genesisConfigOptions = genesisConfig.getConfigOptions(); final Optional> rawBootNodes = genesisConfigOptions.getDiscoveryOptions().getBootNodes(); final List bootNodes = @@ -79,7 +79,7 @@ public static EthNetworkConfig getNetworkConfig(final NetworkName networkName) { .orElse(Collections.emptyList()); return new EthNetworkConfig( - genesisConfigFile, + genesisConfig, networkName.getNetworkId(), bootNodes, genesisConfigOptions.getDiscoveryOptions().getDiscoveryDnsUrl().orElse(null)); @@ -108,7 +108,7 @@ public static String jsonConfig(final NetworkName network) { public static class Builder { private String dnsDiscoveryUrl; - private GenesisConfigFile genesisConfigFile; + private GenesisConfig genesisConfig; private BigInteger networkId; private List bootNodes; @@ -118,7 +118,7 @@ public static class Builder { * @param ethNetworkConfig the eth network config */ public Builder(final EthNetworkConfig ethNetworkConfig) { - this.genesisConfigFile = ethNetworkConfig.genesisConfigFile; + this.genesisConfig = ethNetworkConfig.genesisConfig; this.networkId = ethNetworkConfig.networkId; this.bootNodes = ethNetworkConfig.bootNodes; this.dnsDiscoveryUrl = ethNetworkConfig.dnsDiscoveryUrl; @@ -127,11 +127,11 @@ public Builder(final EthNetworkConfig ethNetworkConfig) { /** * Sets genesis config file. * - * @param genesisConfigFile the genesis config + * @param genesisConfig the genesis config * @return this builder */ - public Builder setGenesisConfigFile(final GenesisConfigFile genesisConfigFile) { - this.genesisConfigFile = genesisConfigFile; + public Builder setGenesisConfig(final GenesisConfig genesisConfig) { + this.genesisConfig = genesisConfig; return this; } @@ -174,7 +174,7 @@ public Builder setDnsDiscoveryUrl(final String dnsDiscoveryUrl) { * @return the eth network config */ public EthNetworkConfig build() { - return new EthNetworkConfig(genesisConfigFile, networkId, bootNodes, dnsDiscoveryUrl); + return new EthNetworkConfig(genesisConfig, networkId, bootNodes, dnsDiscoveryUrl); } } } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptions.java index c8c2c733440..371f855b7a0 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptions.java @@ -176,6 +176,20 @@ public class JsonRpcHttpOptions { "Enable to accept clients certificate signed by a valid CA for client authentication (default: ${DEFAULT-VALUE})") private final Boolean isRpcHttpTlsCAClientsEnabled = false; + @CommandLine.Option( + names = {"--rpc-http-tls-truststore-file"}, + paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP, + description = "Path to the truststore file for the JSON-RPC HTTP service.", + arity = "1") + private final Path rpcHttpTlsTruststoreFile = null; + + @CommandLine.Option( + names = {"--rpc-http-tls-truststore-password-file"}, + paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP, + description = "Path to the file containing the password for the truststore.", + arity = "1") + private final Path rpcHttpTlsTruststorePasswordFile = null; + @CommandLine.Option( names = {"--rpc-http-tls-protocol", "--rpc-http-tls-protocols"}, description = "Comma separated list of TLS protocols to support (default: ${DEFAULT-VALUE})", @@ -306,7 +320,6 @@ public JsonRpcConfiguration jsonRpcConfiguration( jsonRpcConfiguration.setHost( Strings.isNullOrEmpty(rpcHttpHost) ? defaultHostAddress : rpcHttpHost); jsonRpcConfiguration.setHostsAllowlist(hostsAllowlist); - ; jsonRpcConfiguration.setHttpTimeoutSec(timoutSec); return jsonRpcConfiguration; } @@ -330,7 +343,18 @@ private void checkRpcTlsClientAuthOptionsDependencies( commandLine, "--rpc-http-tls-client-auth-enabled", !isRpcHttpTlsClientAuthEnabled, - asList("--rpc-http-tls-known-clients-file", "--rpc-http-tls-ca-clients-enabled")); + asList( + "--rpc-http-tls-known-clients-file", + "--rpc-http-tls-ca-clients-enabled", + "--rpc-http-tls-truststore-file", + "--rpc-http-tls-truststore-password-file")); + + CommandLineUtils.checkOptionDependencies( + logger, + commandLine, + "--rpc-http-tls-truststore-file", + rpcHttpTlsTruststoreFile == null, + asList("--rpc-http-tls-truststore-password-file")); } private void checkRpcTlsOptionsDependencies(final Logger logger, final CommandLine commandLine) { @@ -392,12 +416,31 @@ private void validateTls(final CommandLine commandLine) { "File containing password to unlock keystore is required when TLS is enabled for JSON-RPC HTTP endpoint"); } - if (isRpcHttpTlsClientAuthEnabled - && !isRpcHttpTlsCAClientsEnabled - && rpcHttpTlsKnownClientsFile == null) { - throw new CommandLine.ParameterException( - commandLine, - "Known-clients file must be specified or CA clients must be enabled when TLS client authentication is enabled for JSON-RPC HTTP endpoint"); + if (isRpcHttpTlsClientAuthEnabled) { + if (!isRpcHttpTlsCAClientsEnabled + && rpcHttpTlsKnownClientsFile == null + && rpcHttpTlsTruststoreFile == null) { + throw new CommandLine.ParameterException( + commandLine, + "Configuration error: TLS client authentication is enabled, but none of the following options are provided: " + + "1. Specify a known-clients file (--rpc-http-tls-known-clients-file) and/or Enable CA clients (--rpc-http-tls-ca-clients-enabled). " + + "2. Specify a truststore file and its password file (--rpc-http-tls-truststore-file and --rpc-http-tls-truststore-password-file). " + + "Only one of these options must be configured"); + } + + if (rpcHttpTlsTruststoreFile != null && rpcHttpTlsTruststorePasswordFile == null) { + throw new CommandLine.ParameterException( + commandLine, + "Configuration error: A truststore file is specified for JSON RPC HTTP endpoint, but the corresponding truststore password file (--rpc-http-tls-truststore-password-file) is missing"); + } + + if ((isRpcHttpTlsCAClientsEnabled || rpcHttpTlsKnownClientsFile != null) + && rpcHttpTlsTruststoreFile != null) { + throw new CommandLine.ParameterException( + commandLine, + "Configuration error: Truststore file (--rpc-http-tls-truststore-file) cannot be used together with CA clients (--rpc-http-tls-ca-clients-enabled) or a known-clients (--rpc-http-tls-known-clients-file) option. " + + "These options are mutually exclusive. Choose either truststore-based authentication or known-clients/CA clients configuration."); + } } rpcHttpTlsProtocols.retainAll(getJDKEnabledProtocols()); @@ -441,10 +484,17 @@ private boolean isRpcTlsConfigurationRequired() { private TlsClientAuthConfiguration rpcHttpTlsClientAuthConfiguration() { if (isRpcHttpTlsClientAuthEnabled) { - return TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration() - .withKnownClientsFile(rpcHttpTlsKnownClientsFile) - .withCaClientsEnabled(isRpcHttpTlsCAClientsEnabled) - .build(); + TlsClientAuthConfiguration.Builder tlsClientAuthConfigurationBuilder = + TlsClientAuthConfiguration.Builder.aTlsClientAuthConfiguration() + .withKnownClientsFile(rpcHttpTlsKnownClientsFile) + .withCaClientsEnabled(isRpcHttpTlsCAClientsEnabled) + .withTruststorePath(rpcHttpTlsTruststoreFile); + + if (rpcHttpTlsTruststorePasswordFile != null) { + tlsClientAuthConfigurationBuilder.withTruststorePasswordSupplier( + new FileBasedPasswordProvider(rpcHttpTlsTruststorePasswordFile)); + } + return tlsClientAuthConfigurationBuilder.build(); } return null; diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java index fa0cf4dc068..55c8c167af9 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/MiningOptions.java @@ -52,27 +52,34 @@ /** The Mining CLI options. */ public class MiningOptions implements CLIOptions { + private static final String DEPRECATION_PREFIX = + "Deprecated. PoW consensus is deprecated. See CHANGELOG for alternative options. "; + @Option( names = {"--miner-enabled"}, - description = "Set if node will perform mining (default: ${DEFAULT-VALUE})") + description = + DEPRECATION_PREFIX + "Set if node will perform mining (default: ${DEFAULT-VALUE})") private Boolean isMiningEnabled = false; @Option( names = {"--miner-stratum-enabled"}, description = - "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})." + DEPRECATION_PREFIX + + "Set if node will perform Stratum mining (default: ${DEFAULT-VALUE})." + " Compatible with Proof of Work (PoW) only." + " Requires the network option (--network) to be set to CLASSIC.") private Boolean iStratumMiningEnabled = false; @Option( names = {"--miner-stratum-host"}, - description = "Host for Stratum network mining service (default: ${DEFAULT-VALUE})") + description = + DEPRECATION_PREFIX + + "Host for Stratum network mining service (default: ${DEFAULT-VALUE})") private String stratumNetworkInterface = "0.0.0.0"; @Option( names = {"--miner-stratum-port"}, - description = "Stratum port binding (default: ${DEFAULT-VALUE})") + description = DEPRECATION_PREFIX + "Stratum port binding (default: ${DEFAULT-VALUE})") private Integer stratumPort = 8008; @Option( @@ -124,7 +131,8 @@ public class MiningOptions implements CLIOptions { names = {"--block-txs-selection-max-time"}, converter = PositiveNumberConverter.class, description = - "Specifies the maximum time, in milliseconds, that could be spent selecting transactions to be included in the block." + DEPRECATION_PREFIX + + "Specifies the maximum time, in milliseconds, that could be spent selecting transactions to be included in the block." + " Not compatible with PoA networks, see poa-block-txs-selection-max-time. (default: ${DEFAULT-VALUE})") private PositiveNumber nonPoaBlockTxsSelectionMaxTime = DEFAULT_NON_POA_BLOCK_TXS_SELECTION_MAX_TIME; @@ -146,34 +154,40 @@ static class Unstable { hidden = true, names = {"--Xminer-remote-sealers-limit"}, description = - "Limits the number of remote sealers that can submit their hashrates (default: ${DEFAULT-VALUE})") + DEPRECATION_PREFIX + + "Limits the number of remote sealers that can submit their hashrates (default: ${DEFAULT-VALUE})") private Integer remoteSealersLimit = DEFAULT_REMOTE_SEALERS_LIMIT; @CommandLine.Option( hidden = true, names = {"--Xminer-remote-sealers-hashrate-ttl"}, description = - "Specifies the lifetime of each entry in the cache. An entry will be automatically deleted if no update has been received before the deadline (default: ${DEFAULT-VALUE} minutes)") + DEPRECATION_PREFIX + + "Specifies the lifetime of each entry in the cache. An entry will be automatically deleted if no update has been received before the deadline (default: ${DEFAULT-VALUE} minutes)") private Long remoteSealersTimeToLive = DEFAULT_REMOTE_SEALERS_TTL; @CommandLine.Option( hidden = true, names = {"--Xminer-pow-job-ttl"}, description = - "Specifies the time PoW jobs are kept in cache and will accept a solution from miners (default: ${DEFAULT-VALUE} milliseconds)") + DEPRECATION_PREFIX + + "Specifies the time PoW jobs are kept in cache and will accept a solution from miners (default: ${DEFAULT-VALUE} milliseconds)") private Long powJobTimeToLive = DEFAULT_POW_JOB_TTL; @CommandLine.Option( hidden = true, names = {"--Xmax-ommers-depth"}, description = - "Specifies the depth of ommer blocks to accept when receiving solutions (default: ${DEFAULT-VALUE})") + DEPRECATION_PREFIX + + "Specifies the depth of ommer blocks to accept when receiving solutions (default: ${DEFAULT-VALUE})") private Integer maxOmmersDepth = DEFAULT_MAX_OMMERS_DEPTH; @CommandLine.Option( hidden = true, names = {"--Xminer-stratum-extranonce"}, - description = "Extranonce for Stratum network miners (default: ${DEFAULT-VALUE})") + description = + DEPRECATION_PREFIX + + "Extranonce for Stratum network miners (default: ${DEFAULT-VALUE})") private String stratumExtranonce = "080c"; @CommandLine.Option( @@ -230,6 +244,9 @@ public void validate( final GenesisConfigOptions genesisConfigOptions, final boolean isMergeEnabled, final Logger logger) { + if (Boolean.TRUE.equals(isMiningEnabled)) { + logger.warn("PoW consensus is deprecated. See CHANGELOG for alternative options."); + } if (Boolean.TRUE.equals(isMiningEnabled) && coinbase == null) { throw new ParameterException( commandLine, diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/P2PTLSConfigOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/P2PTLSConfigOptions.java deleted file mode 100644 index ee53a5e96f4..00000000000 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/P2PTLSConfigOptions.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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.util.Arrays.asList; -import static org.hyperledger.besu.cli.DefaultCommandValues.DEFAULT_KEYSTORE_TYPE; -import static org.hyperledger.besu.cli.DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP; - -import org.hyperledger.besu.cli.util.CommandLineUtils; -import org.hyperledger.besu.ethereum.api.tls.FileBasedPasswordProvider; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; - -import java.nio.file.Path; -import java.util.Optional; - -import org.slf4j.Logger; -import picocli.CommandLine; -import picocli.CommandLine.Option; -import picocli.CommandLine.ParameterException; - -/** The P2P TLS Config Cli Options. */ -public class P2PTLSConfigOptions { - @Option( - names = {"--Xp2p-tls-enabled"}, - hidden = true, - description = "Enable P2P TLS functionality (default: ${DEFAULT-VALUE})") - private final Boolean p2pTLSEnabled = false; - - @SuppressWarnings({ - "FieldCanBeFinal", - "FieldMayBeFinal" - }) // p2pTLSKeyStoreType requires non-final Strings. - @Option( - names = {"--Xp2p-tls-keystore-type"}, - hidden = true, - paramLabel = "", - description = "P2P service keystore type. Required if P2P TLS is enabled.") - private String p2pTLSKeyStoreType = DEFAULT_KEYSTORE_TYPE; - - @Option( - names = {"--Xp2p-tls-keystore-file"}, - hidden = true, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "Keystore containing key/certificate for the P2P service.") - private final Path p2pTLSKeyStoreFile = null; - - @Option( - names = {"--Xp2p-tls-keystore-password-file"}, - hidden = true, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = - "File containing password to unlock keystore for the P2P service. Required if P2P TLS is enabled.") - private final Path p2pTLSKeyStorePasswordFile = null; - - @SuppressWarnings({ - "FieldCanBeFinal", - "FieldMayBeFinal" - }) // p2pTLSTrustStoreType requires non-final Strings. - @Option( - names = {"--Xp2p-tls-truststore-type"}, - hidden = true, - paramLabel = "", - description = "P2P service truststore type.") - private String p2pTLSTrustStoreType = DEFAULT_KEYSTORE_TYPE; - - @Option( - names = {"--Xp2p-tls-truststore-file"}, - hidden = true, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "Truststore containing trusted certificates for the P2P service.") - private final Path p2pTLSTrustStoreFile = null; - - @Option( - names = {"--Xp2p-tls-truststore-password-file"}, - hidden = true, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "File containing password to unlock truststore for the P2P service.") - private final Path p2pTLSTrustStorePasswordFile = null; - - @Option( - names = {"--Xp2p-tls-crl-file"}, - hidden = true, - paramLabel = MANDATORY_FILE_FORMAT_HELP, - description = "Certificate revocation list for the P2P service.") - private final Path p2pCrlFile = null; - - @Option( - names = {"--Xp2p-tls-clienthello-sni"}, - hidden = true, - description = - "Whether to send a SNI header in the TLS ClientHello message (default: ${DEFAULT-VALUE})") - private final Boolean p2pTlsClientHelloSniHeaderEnabled = false; - - /** Default constructor. */ - P2PTLSConfigOptions() {} - - /** - * Generate P2p tls configuration. - * - * @param commandLine the command line object to report exceptions - * @return the optional TLSConfiguration - */ - public Optional p2pTLSConfiguration(final CommandLine commandLine) { - if (!p2pTLSEnabled) { - return Optional.empty(); - } - - if (p2pTLSKeyStoreType == null) { - throw new ParameterException( - commandLine, "Keystore type is required when p2p TLS is enabled"); - } - - if (p2pTLSKeyStorePasswordFile == null) { - throw new ParameterException( - commandLine, - "File containing password to unlock keystore is required when p2p TLS is enabled"); - } - - return Optional.of( - TLSConfiguration.Builder.tlsConfiguration() - .withKeyStoreType(p2pTLSKeyStoreType) - .withKeyStorePath(p2pTLSKeyStoreFile) - .withKeyStorePasswordSupplier(new FileBasedPasswordProvider(p2pTLSKeyStorePasswordFile)) - .withKeyStorePasswordPath(p2pTLSKeyStorePasswordFile) - .withTrustStoreType(p2pTLSTrustStoreType) - .withTrustStorePath(p2pTLSTrustStoreFile) - .withTrustStorePasswordSupplier( - null == p2pTLSTrustStorePasswordFile - ? null - : new FileBasedPasswordProvider(p2pTLSTrustStorePasswordFile)) - .withTrustStorePasswordPath(p2pTLSTrustStorePasswordFile) - .withCrlPath(p2pCrlFile) - .withClientHelloSniEnabled(p2pTlsClientHelloSniHeaderEnabled) - .build()); - } - - /** - * Check P2P Tls options dependencies. - * - * @param logger the logger - * @param commandLine the command line - */ - public void checkP2PTLSOptionsDependencies(final Logger logger, final CommandLine commandLine) { - CommandLineUtils.checkOptionDependencies( - logger, - commandLine, - "--Xp2p-tls-enabled", - !p2pTLSEnabled, - asList("--Xp2p-tls-keystore-type", "--Xp2p-tls-keystore-password-file")); - } -} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/PermissionsOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/PermissionsOptions.java index b6c744c98f7..0a2e9e967fc 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/PermissionsOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/PermissionsOptions.java @@ -56,32 +56,40 @@ public class PermissionsOptions { "Account permissioning config TOML file (default: a file named \"permissions_config.toml\" in the Besu data folder)") private String accountPermissionsConfigFile = null; + private static final String DEPRECATION_PREFIX = + "Deprecated. Onchain permissioning is deprecated. See CHANGELOG for alternative options. "; + @CommandLine.Option( names = {"--permissions-nodes-contract-address"}, - description = "Address of the node permissioning smart contract", + description = DEPRECATION_PREFIX + "Address of the node permissioning smart contract", arity = "1") private final Address permissionsNodesContractAddress = null; @CommandLine.Option( names = {"--permissions-nodes-contract-version"}, - description = "Version of the EEA Node Permissioning interface (default: ${DEFAULT-VALUE})") + description = + DEPRECATION_PREFIX + + "Version of the EEA Node Permissioning interface (default: ${DEFAULT-VALUE})") private final Integer permissionsNodesContractVersion = 1; @CommandLine.Option( names = {"--permissions-nodes-contract-enabled"}, - description = "Enable node level permissions via smart contract (default: ${DEFAULT-VALUE})") + description = + DEPRECATION_PREFIX + + "Enable node level permissions via smart contract (default: ${DEFAULT-VALUE})") private final Boolean permissionsNodesContractEnabled = false; @CommandLine.Option( names = {"--permissions-accounts-contract-address"}, - description = "Address of the account permissioning smart contract", + description = DEPRECATION_PREFIX + "Address of the account permissioning smart contract", arity = "1") private final Address permissionsAccountsContractAddress = null; @CommandLine.Option( names = {"--permissions-accounts-contract-enabled"}, description = - "Enable account level permissions via smart contract (default: ${DEFAULT-VALUE})") + DEPRECATION_PREFIX + + "Enable account level permissions via smart contract (default: ${DEFAULT-VALUE})") private final Boolean permissionsAccountsContractEnabled = false; /** Default constructor. */ @@ -151,6 +159,7 @@ public Optional permissioningConfiguration( SmartContractPermissioningConfiguration.createDefault(); if (Boolean.TRUE.equals(permissionsNodesContractEnabled)) { + logger.warn("Onchain (contract) node permissioning options are " + DEPRECATION_PREFIX); if (permissionsNodesContractAddress == null) { throw new CommandLine.ParameterException( commandLine, @@ -170,6 +179,7 @@ public Optional permissioningConfiguration( } if (Boolean.TRUE.equals(permissionsAccountsContractEnabled)) { + logger.warn("Onchain (contract) account permissioning options are " + DEPRECATION_PREFIX); if (permissionsAccountsContractAddress == null) { throw new CommandLine.ParameterException( commandLine, diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/PrivacyPluginOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/PrivacyPluginOptions.java index 7842c09923f..4574bf8a997 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/PrivacyPluginOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/PrivacyPluginOptions.java @@ -17,7 +17,7 @@ import static picocli.CommandLine.Option; /** The Privacy plugin Cli options. */ -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivacyPluginOptions { /** Default Constructor. */ PrivacyPluginOptions() {} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/options/RpcWebsocketOptions.java b/besu/src/main/java/org/hyperledger/besu/cli/options/RpcWebsocketOptions.java index 2dde517ccc7..fb7c73e7eae 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/options/RpcWebsocketOptions.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/options/RpcWebsocketOptions.java @@ -37,6 +37,35 @@ /** This class represents the WebSocket options for the RPC. */ public class RpcWebsocketOptions { + + static class KeystorePasswordOptions { + @CommandLine.Option( + names = {"--rpc-ws-ssl-keystore-password"}, + paramLabel = "", + description = "Password for the WebSocket RPC keystore file") + private String rpcWsKeyStorePassword; + + @CommandLine.Option( + names = {"--rpc-ws-ssl-keystore-password-file"}, + paramLabel = "", + description = "File containing the password for WebSocket keystore.") + private String rpcWsKeystorePasswordFile; + } + + static class TruststorePasswordOptions { + @CommandLine.Option( + names = {"--rpc-ws-ssl-truststore-password"}, + paramLabel = "", + description = "Password for the WebSocket RPC truststore file") + private String rpcWsTrustStorePassword; + + @CommandLine.Option( + names = {"--rpc-ws-ssl-truststore-password-file"}, + paramLabel = "", + description = "File containing the password for WebSocket truststore.") + private String rpcWsTruststorePasswordFile; + } + @CommandLine.Option( names = {"--rpc-ws-authentication-jwt-algorithm"}, description = @@ -131,12 +160,6 @@ public class RpcWebsocketOptions { description = "Path to the keystore file for the WebSocket RPC service") private String rpcWsKeyStoreFile = null; - @CommandLine.Option( - names = {"--rpc-ws-ssl-keystore-password"}, - paramLabel = "", - description = "Password for the WebSocket RPC keystore file") - private String rpcWsKeyStorePassword = null; - @CommandLine.Option( names = {"--rpc-ws-ssl-key-file"}, paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP, @@ -167,12 +190,6 @@ public class RpcWebsocketOptions { description = "Path to the truststore file for the WebSocket RPC service") private String rpcWsTrustStoreFile = null; - @CommandLine.Option( - names = {"--rpc-ws-ssl-truststore-password"}, - paramLabel = "", - description = "Password for the WebSocket RPC truststore file") - private String rpcWsTrustStorePassword = null; - @CommandLine.Option( names = {"--rpc-ws-ssl-trustcert-file"}, paramLabel = DefaultCommandValues.MANDATORY_FILE_FORMAT_HELP, @@ -185,6 +202,12 @@ public class RpcWebsocketOptions { description = "Type of the truststore (JKS, PKCS12, PEM)") private String rpcWsTrustStoreType = null; + @CommandLine.ArgGroup(exclusive = true, multiplicity = "1") + private KeystorePasswordOptions keystorePasswordOptions; + + @CommandLine.ArgGroup(exclusive = true, multiplicity = "1") + private TruststorePasswordOptions truststorePasswordOptions; + /** Default Constructor. */ public RpcWebsocketOptions() {} @@ -292,7 +315,7 @@ private void checkOptionDependencies(final Logger logger, final CommandLine comm commandLine, "--rpc-ws-ssl-keystore-file", rpcWsKeyStoreFile == null, - List.of("--rpc-ws-ssl-keystore-password")); + List.of("--rpc-ws-ssl-keystore-password", "--rpc-ws-ssl-keystore-password-file")); } } @@ -302,7 +325,7 @@ private void checkOptionDependencies(final Logger logger, final CommandLine comm commandLine, "--rpc-ws-ssl-truststore-file", rpcWsTrustStoreFile == null, - List.of("--rpc-ws-ssl-truststore-password")); + List.of("--rpc-ws-ssl-truststore-password", "--rpc-ws-ssl-truststore-password-file")); } if (isRpcWsAuthenticationEnabled) { @@ -343,16 +366,27 @@ public WebSocketConfiguration webSocketConfiguration( webSocketConfiguration.setTimeoutSec(wsTimoutSec); webSocketConfiguration.setSslEnabled(isRpcWsSslEnabled); webSocketConfiguration.setKeyStorePath(rpcWsKeyStoreFile); - webSocketConfiguration.setKeyStorePassword(rpcWsKeyStorePassword); webSocketConfiguration.setKeyStoreType(rpcWsKeyStoreType); webSocketConfiguration.setClientAuthEnabled(isRpcWsClientAuthEnabled); webSocketConfiguration.setTrustStorePath(rpcWsTrustStoreFile); - webSocketConfiguration.setTrustStorePassword(rpcWsTrustStorePassword); webSocketConfiguration.setTrustStoreType(rpcWsTrustStoreType); webSocketConfiguration.setKeyPath(rpcWsKeyFile); webSocketConfiguration.setCertPath(rpcWsCertFile); webSocketConfiguration.setTrustCertPath(rpcWsTrustCertFile); + if (keystorePasswordOptions != null) { + webSocketConfiguration.setKeyStorePassword(keystorePasswordOptions.rpcWsKeyStorePassword); + webSocketConfiguration.setKeyStorePasswordFile( + keystorePasswordOptions.rpcWsKeystorePasswordFile); + } + + if (truststorePasswordOptions != null) { + webSocketConfiguration.setTrustStorePassword( + truststorePasswordOptions.rpcWsTrustStorePassword); + webSocketConfiguration.setTrustStorePasswordFile( + truststorePasswordOptions.rpcWsTruststorePasswordFile); + } + return webSocketConfiguration; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java index 95617fe8ca1..5862b11c19b 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java @@ -53,7 +53,6 @@ import java.util.function.Function; import java.util.function.Supplier; -import io.vertx.core.Vertx; import jakarta.validation.constraints.NotBlank; import org.apache.tuweni.bytes.Bytes; import org.slf4j.Logger; @@ -458,8 +457,7 @@ private static Optional initMetrics(final BlocksSubCommand paren parentCommand.parentCommand.metricsConfiguration(); Optional metricsService = - MetricsService.create( - Vertx.vertx(), metricsConfiguration, parentCommand.parentCommand.getMetricsSystem()); + MetricsService.create(metricsConfiguration, parentCommand.parentCommand.getMetricsSystem()); metricsService.ifPresent(MetricsService::start); return metricsService; } diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java index d71cf652a5f..368f6da3800 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/operator/GenerateBlockchainConfig.java @@ -19,7 +19,7 @@ import org.hyperledger.besu.cli.DefaultCommandValues; import org.hyperledger.besu.cli.util.VersionProvider; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.JsonGenesisConfigOptions; import org.hyperledger.besu.config.JsonUtil; @@ -286,7 +286,7 @@ private void parseConfig() throws IOException { /** Sets the selected signature algorithm instance in SignatureAlgorithmFactory. */ private void processEcCurve() { - GenesisConfigOptions options = GenesisConfigFile.fromConfig(genesisConfig).getConfigOptions(); + GenesisConfigOptions options = GenesisConfig.fromConfig(genesisConfig).getConfigOptions(); Optional ecCurve = options.getEcCurve(); if (ecCurve.isEmpty()) { diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java index 238e5c3c1c0..700b414edce 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuController.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.controller; import org.hyperledger.besu.cli.config.EthNetworkConfig; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.PowAlgorithm; import org.hyperledger.besu.config.QbftConfigOptions; @@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration; import org.hyperledger.besu.ethereum.storage.StorageProvider; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import java.io.Closeable; @@ -66,7 +67,6 @@ public class BesuController implements java.io.Closeable { private final NodeKey nodeKey; private final Synchronizer synchronizer; private final JsonRpcMethods additionalJsonRpcMethodsFactory; - private final TransactionPool transactionPool; private final MiningCoordinator miningCoordinator; private final PrivacyParameters privacyParameters; @@ -77,6 +77,7 @@ public class BesuController implements java.io.Closeable { private final EthPeers ethPeers; private final StorageProvider storageProvider; private final DataStorageConfiguration dataStorageConfiguration; + private final TransactionSimulator transactionSimulator; /** * Instantiates a new Besu controller. @@ -99,6 +100,7 @@ public class BesuController implements java.io.Closeable { * @param ethPeers the eth peers * @param storageProvider the storage provider * @param dataStorageConfiguration the data storage configuration + * @param transactionSimulator the transaction simulator */ BesuController( final ProtocolSchedule protocolSchedule, @@ -118,7 +120,8 @@ public class BesuController implements java.io.Closeable { final PluginServiceFactory additionalPluginServices, final EthPeers ethPeers, final StorageProvider storageProvider, - final DataStorageConfiguration dataStorageConfiguration) { + final DataStorageConfiguration dataStorageConfiguration, + final TransactionSimulator transactionSimulator) { this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.ethProtocolManager = ethProtocolManager; @@ -137,6 +140,7 @@ public class BesuController implements java.io.Closeable { this.ethPeers = ethPeers; this.storageProvider = storageProvider; this.dataStorageConfiguration = dataStorageConfiguration; + this.transactionSimulator = transactionSimulator; } /** @@ -307,6 +311,15 @@ public DataStorageConfiguration getDataStorageConfiguration() { return dataStorageConfiguration; } + /** + * Gets the transaction simulator + * + * @return the transaction simulator + */ + public TransactionSimulator getTransactionSimulator() { + return transactionSimulator; + } + /** The type Builder. */ public static class Builder { /** Instantiates a new Builder. */ @@ -321,24 +334,24 @@ public Builder() {} */ public BesuControllerBuilder fromEthNetworkConfig( final EthNetworkConfig ethNetworkConfig, final SyncMode syncMode) { - return fromGenesisFile(ethNetworkConfig.genesisConfigFile(), syncMode) + return fromGenesisFile(ethNetworkConfig.genesisConfig(), syncMode) .networkId(ethNetworkConfig.networkId()); } /** * From genesis config besu controller builder. * - * @param genesisConfigFile the genesis config file + * @param genesisConfig the genesis config file * @param syncMode the sync mode * @return the besu controller builder */ public BesuControllerBuilder fromGenesisFile( - final GenesisConfigFile genesisConfigFile, final SyncMode syncMode) { + final GenesisConfig genesisConfig, final SyncMode syncMode) { final BesuControllerBuilder builder; - final var configOptions = genesisConfigFile.getConfigOptions(); + final var configOptions = genesisConfig.getConfigOptions(); if (configOptions.isConsensusMigration()) { - return createConsensusScheduleBesuControllerBuilder(genesisConfigFile); + return createConsensusScheduleBesuControllerBuilder(genesisConfig); } if (configOptions.getPowAlgorithm() != PowAlgorithm.UNSUPPORTED) { @@ -360,22 +373,22 @@ public BesuControllerBuilder fromGenesisFile( if (configOptions.getTerminalTotalDifficulty().isPresent()) { // Enable start with vanilla MergeBesuControllerBuilder for PoS checkpoint block if (syncMode == SyncMode.CHECKPOINT && isCheckpointPoSBlock(configOptions)) { - return new MergeBesuControllerBuilder().genesisConfigFile(genesisConfigFile); + return new MergeBesuControllerBuilder().genesisConfig(genesisConfig); } else { // TODO this should be changed to vanilla MergeBesuControllerBuilder and the Transition* // series of classes removed after we successfully transition to PoS // https://github.com/hyperledger/besu/issues/2897 return new TransitionBesuControllerBuilder(builder, new MergeBesuControllerBuilder()) - .genesisConfigFile(genesisConfigFile); + .genesisConfig(genesisConfig); } - } else return builder.genesisConfigFile(genesisConfigFile); + } else return builder.genesisConfig(genesisConfig); } private BesuControllerBuilder createConsensusScheduleBesuControllerBuilder( - final GenesisConfigFile genesisConfigFile) { + final GenesisConfig genesisConfig) { final Map besuControllerBuilderSchedule = new HashMap<>(); - final var configOptions = genesisConfigFile.getConfigOptions(); + final var configOptions = genesisConfig.getConfigOptions(); final BesuControllerBuilder originalControllerBuilder; if (configOptions.isIbft2()) { @@ -394,7 +407,7 @@ private BesuControllerBuilder createConsensusScheduleBesuControllerBuilder( besuControllerBuilderSchedule.put(qbftBlock, new QbftBesuControllerBuilder()); return new ConsensusScheduleBesuControllerBuilder(besuControllerBuilderSchedule) - .genesisConfigFile(genesisConfigFile); + .genesisConfig(genesisConfig); } private Long readQbftStartBlockConfig(final QbftConfigOptions qbftConfigOptions) { diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index 1953e1aa318..7e53410f225 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -18,7 +18,7 @@ import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.consensus.merge.UnverifiedForkchoiceSupplier; @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.ConsensusContext; import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; import org.hyperledger.besu.ethereum.chain.BadBlockManager; @@ -84,6 +85,7 @@ import org.hyperledger.besu.ethereum.p2p.config.SubProtocolConfiguration; import org.hyperledger.besu.ethereum.storage.StorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.BonsaiWorldStateProvider; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoader; import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.storage.BonsaiWorldStateKeyValueStorage; @@ -127,7 +129,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides private static final Logger LOG = LoggerFactory.getLogger(BesuControllerBuilder.class); /** The genesis file */ - protected GenesisConfigFile genesisConfigFile; + protected GenesisConfig genesisConfig; /** The genesis config options; */ protected GenesisConfigOptions genesisConfigOptions; @@ -213,6 +215,12 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides /** whether parallel transaction processing is enabled or not */ protected boolean isParallelTxProcessingEnabled; + /** The API configuration */ + protected ApiConfiguration apiConfiguration; + + /** The transaction simulator */ + protected TransactionSimulator transactionSimulator; + /** Instantiates a new Besu controller builder. */ protected BesuControllerBuilder() {} @@ -244,8 +252,8 @@ public BesuControllerBuilder storageProvider(final StorageProvider storageProvid * @param genesisConfig the genesis config * @return the besu controller builder */ - public BesuControllerBuilder genesisConfigFile(final GenesisConfigFile genesisConfig) { - this.genesisConfigFile = genesisConfig; + public BesuControllerBuilder genesisConfig(final GenesisConfig genesisConfig) { + this.genesisConfig = genesisConfig; this.genesisConfigOptions = genesisConfig.getConfigOptions(); return this; } @@ -274,6 +282,17 @@ public BesuControllerBuilder synchronizerConfiguration( return this; } + /** + * API configuration besu controller builder. + * + * @param apiConfiguration the API config + * @return the besu controller builder + */ + public BesuControllerBuilder apiConfiguration(final ApiConfiguration apiConfiguration) { + this.apiConfiguration = apiConfiguration; + return this; + } + /** * Eth protocol configuration besu controller builder. * @@ -542,7 +561,7 @@ public BesuControllerBuilder isParallelTxProcessingEnabled( * @return the besu controller */ public BesuController build() { - checkNotNull(genesisConfigFile, "Missing genesis config file"); + checkNotNull(genesisConfig, "Missing genesis config file"); checkNotNull(genesisConfigOptions, "Missing genesis config options"); checkNotNull(syncConfig, "Missing sync config"); checkNotNull(ethereumWireProtocolConfiguration, "Missing ethereum protocol configuration"); @@ -558,6 +577,7 @@ public BesuController build() { checkNotNull(gasLimitCalculator, "Missing gas limit calculator"); checkNotNull(evmConfiguration, "Missing evm config"); checkNotNull(networkingConfiguration, "Missing network configuration"); + checkNotNull(apiConfiguration, "Missing API configuration"); checkNotNull(dataStorageConfiguration, "Missing data storage configuration"); checkNotNull(besuComponent, "Must supply a BesuComponent"); prepForBuild(); @@ -606,6 +626,14 @@ public BesuController build() { genesisState.writeStateTo(worldStateArchive.getMutable()); } + transactionSimulator = + new TransactionSimulator( + blockchain, + worldStateArchive, + protocolSchedule, + miningConfiguration, + apiConfiguration.getGasCap()); + final var consensusContext = createConsensusContext(blockchain, worldStateArchive, protocolSchedule); @@ -627,7 +655,6 @@ public BesuController build() { ethereumWireProtocolConfiguration.isLegacyEth64ForkIdEnabled()); final EthPeers ethPeers = new EthPeers( - EthProtocol.NAME, currentProtocolSpecSupplier, clock, metricsSystem, @@ -665,9 +692,10 @@ public BesuController build() { .build()); } - final EthContext ethContext = new EthContext(ethPeers, ethMessages, snapMessages, scheduler); final PeerTaskExecutor peerTaskExecutor = new PeerTaskExecutor(ethPeers, new PeerTaskRequestSender(), metricsSystem); + final EthContext ethContext = + new EthContext(ethPeers, ethMessages, snapMessages, scheduler, peerTaskExecutor); final boolean fullSyncDisabled = !SyncMode.isFullSync(syncConfig.getSyncMode()); final SyncState syncState = new SyncState(blockchain, ethPeers, fullSyncDisabled, checkpoint); @@ -693,7 +721,8 @@ public BesuController build() { besuComponent.map(BesuComponent::getBlobCache).orElse(new BlobCache()), miningConfiguration); - final List peerValidators = createPeerValidators(protocolSchedule); + final List peerValidators = + createPeerValidators(protocolSchedule, peerTaskExecutor); final EthProtocolManager ethProtocolManager = createEthProtocolManager( @@ -798,7 +827,8 @@ public BesuController build() { additionalPluginServices, ethPeers, storageProvider, - dataStorageConfiguration); + dataStorageConfiguration, + transactionSimulator); } private GenesisState getGenesisState( @@ -812,11 +842,10 @@ private GenesisState getGenesisState( return maybeGenesisStateRoot .map( genesisStateRoot -> - GenesisState.fromStorage(genesisStateRoot, genesisConfigFile, protocolSchedule)) + GenesisState.fromStorage(genesisStateRoot, genesisConfig, protocolSchedule)) .orElseGet( () -> - GenesisState.fromConfig( - dataStorageConfiguration, genesisConfigFile, protocolSchedule)); + GenesisState.fromConfig(dataStorageConfiguration, genesisConfig, protocolSchedule)); } private TrieLogPruner createTrieLogPruner( @@ -896,7 +925,6 @@ private PivotBlockSelector createPivotSelector( ethContext, syncConfig, syncState, - metricsSystem, protocolContext, nodeKey, blockchain.getChainHeadHeader()); @@ -921,11 +949,12 @@ private PivotBlockSelector createPivotSelector( ethContext, metricsSystem, genesisConfigOptions, + syncConfig, unverifiedForkchoiceSupplier, unsubscribeForkchoiceListener); } else { LOG.info("TTD difficulty is not present, creating initial sync phase for PoW"); - return new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem); + return new PivotSelectorFromPeers(ethContext, syncConfig, syncState); } } @@ -1166,29 +1195,42 @@ private ChainDataPruner createChainPruner(final BlockchainStorage blockchainStor * Create peer validators list. * * @param protocolSchedule the protocol schedule + * @param peerTaskExecutor the peer task executor * @return the list */ - protected List createPeerValidators(final ProtocolSchedule protocolSchedule) { + protected List createPeerValidators( + final ProtocolSchedule protocolSchedule, final PeerTaskExecutor peerTaskExecutor) { final List validators = new ArrayList<>(); final OptionalLong daoBlock = genesisConfigOptions.getDaoForkBlock(); if (daoBlock.isPresent()) { // Setup dao validator validators.add( - new DaoForkPeerValidator(protocolSchedule, metricsSystem, daoBlock.getAsLong())); + new DaoForkPeerValidator( + protocolSchedule, peerTaskExecutor, syncConfig, metricsSystem, daoBlock.getAsLong())); } final OptionalLong classicBlock = genesisConfigOptions.getClassicForkBlock(); // setup classic validator if (classicBlock.isPresent()) { validators.add( - new ClassicForkPeerValidator(protocolSchedule, metricsSystem, classicBlock.getAsLong())); + new ClassicForkPeerValidator( + protocolSchedule, + peerTaskExecutor, + syncConfig, + metricsSystem, + classicBlock.getAsLong())); } for (final Map.Entry requiredBlock : requiredBlocks.entrySet()) { validators.add( new RequiredBlocksPeerValidator( - protocolSchedule, metricsSystem, requiredBlock.getKey(), requiredBlock.getValue())); + protocolSchedule, + peerTaskExecutor, + syncConfig, + metricsSystem, + requiredBlock.getKey(), + requiredBlock.getValue())); } final CheckpointConfigOptions checkpointConfigOptions = @@ -1197,6 +1239,8 @@ protected List createPeerValidators(final ProtocolSchedule protoc validators.add( new CheckpointBlocksPeerValidator( protocolSchedule, + peerTaskExecutor, + syncConfig, metricsSystem, checkpointConfigOptions.getNumber().orElseThrow(), checkpointConfigOptions.getHash().map(Hash::fromHexString).orElseThrow())); diff --git a/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java index 31f84b6ae04..0b7299cedb5 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilder.java @@ -16,7 +16,7 @@ import static org.hyperledger.besu.ethereum.core.BlockHeader.GENESIS_BLOCK_NUMBER; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.consensus.common.CombinedProtocolScheduleFactory; import org.hyperledger.besu.consensus.common.ForkSpec; import org.hyperledger.besu.consensus.common.ForksSchedule; @@ -264,9 +264,9 @@ public BesuControllerBuilder storageProvider(final StorageProvider storageProvid } @Override - public BesuControllerBuilder genesisConfigFile(final GenesisConfigFile genesisConfig) { - besuControllerBuilderSchedule.values().forEach(b -> b.genesisConfigFile(genesisConfig)); - return super.genesisConfigFile(genesisConfig); + public BesuControllerBuilder genesisConfig(final GenesisConfig genesisConfig) { + besuControllerBuilderSchedule.values().forEach(b -> b.genesisConfig(genesisConfig)); + return super.genesisConfig(genesisConfig); } @Override diff --git a/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java index e7c1a5c40d8..2352f9d3965 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/MergeBesuControllerBuilder.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.MergePeerFilter; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; import org.hyperledger.besu.ethereum.eth.peervalidation.RequiredBlocksPeerValidator; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -79,6 +80,7 @@ protected MiningCoordinator createMiningCoordinator( new BackwardSyncContext( protocolContext, protocolSchedule, + syncConfig, metricsSystem, ethProtocolManager.ethContext(), syncState, @@ -235,14 +237,17 @@ protected PluginServiceFactory createAdditionalPluginServices( } @Override - protected List createPeerValidators(final ProtocolSchedule protocolSchedule) { - List retval = super.createPeerValidators(protocolSchedule); + protected List createPeerValidators( + final ProtocolSchedule protocolSchedule, final PeerTaskExecutor peerTaskExecutor) { + List retval = super.createPeerValidators(protocolSchedule, peerTaskExecutor); final OptionalLong powTerminalBlockNumber = genesisConfigOptions.getTerminalBlockNumber(); final Optional powTerminalBlockHash = genesisConfigOptions.getTerminalBlockHash(); if (powTerminalBlockHash.isPresent() && powTerminalBlockNumber.isPresent()) { retval.add( new RequiredBlocksPeerValidator( protocolSchedule, + peerTaskExecutor, + syncConfig, metricsSystem, powTerminalBlockNumber.getAsLong(), powTerminalBlockHash.get(), diff --git a/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java index b6f579ea68e..4143d034058 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/QbftBesuControllerBuilder.java @@ -47,20 +47,20 @@ import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.QbftForksSchedulesFactory; -import org.hyperledger.besu.consensus.qbft.QbftGossip; import org.hyperledger.besu.consensus.qbft.QbftProtocolScheduleBuilder; import org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory; +import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftBlockHeightManagerFactory; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftController; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftRoundFactory; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger; import org.hyperledger.besu.consensus.qbft.jsonrpc.QbftJsonRpcMethods; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; import org.hyperledger.besu.consensus.qbft.protocol.Istanbul100SubProtocol; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftBlockHeightManagerFactory; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftController; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftRoundFactory; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory; import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider; import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider; import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController; -import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods; @@ -79,7 +79,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.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.plugin.services.BesuEvents; import org.hyperledger.besu.util.Subscribers; @@ -399,8 +398,6 @@ protected BftContext createConsensusContext( BlockValidatorProvider.forkingValidatorProvider( blockchain, epochManager, bftBlockInterface().get(), validatorOverrides); - final TransactionSimulator transactionSimulator = - new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule, 0L); transactionValidatorProvider = new TransactionValidatorProvider( blockchain, new ValidatorContractController(transactionSimulator), qbftForksSchedule); diff --git a/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java index 75abca6a574..9d37f594e8a 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/TransitionBesuControllerBuilder.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.controller; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.consensus.merge.PostMergeContext; import org.hyperledger.besu.consensus.merge.TransitionBackwardSyncContext; @@ -119,6 +119,7 @@ protected MiningCoordinator createMiningCoordinator( new TransitionBackwardSyncContext( protocolContext, transitionProtocolSchedule, + syncConfig, metricsSystem, ethProtocolManager.ethContext(), syncState, @@ -300,9 +301,9 @@ public BesuControllerBuilder evmConfiguration(final EvmConfiguration evmConfigur } @Override - public BesuControllerBuilder genesisConfigFile(final GenesisConfigFile genesisConfig) { - super.genesisConfigFile(genesisConfig); - return propagateConfig(z -> z.genesisConfigFile(genesisConfig)); + public BesuControllerBuilder genesisConfig(final GenesisConfig genesisConfig) { + super.genesisConfig(genesisConfig); + return propagateConfig(z -> z.genesisConfig(genesisConfig)); } @Override diff --git a/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java new file mode 100644 index 00000000000..f840cd30273 --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/services/BlockSimulatorServiceImpl.java @@ -0,0 +1,158 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.services; + +import org.hyperledger.besu.datatypes.AccountOverrideMap; +import org.hyperledger.besu.datatypes.Transaction; +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.transaction.BlockSimulationResult; +import org.hyperledger.besu.ethereum.transaction.BlockSimulator; +import org.hyperledger.besu.ethereum.transaction.BlockStateCall; +import org.hyperledger.besu.ethereum.transaction.CallParameter; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; +import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.plugin.Unstable; +import org.hyperledger.besu.plugin.data.BlockOverrides; +import org.hyperledger.besu.plugin.data.PluginBlockSimulationResult; +import org.hyperledger.besu.plugin.data.TransactionSimulationResult; +import org.hyperledger.besu.plugin.services.BlockSimulationService; + +import java.util.List; + +/** This class is a service that simulates the processing of a block */ +public class BlockSimulatorServiceImpl implements BlockSimulationService { + private final BlockSimulator blockSimulator; + private final WorldStateArchive worldStateArchive; + private final Blockchain blockchain; + + /** + * This constructor creates a BlockSimulatorServiceImpl object + * + * @param worldStateArchive the world state archive + * @param miningConfiguration the mining configuration + * @param transactionSimulator the transaction simulator + * @param protocolSchedule the protocol schedule + * @param blockchain the blockchain + */ + public BlockSimulatorServiceImpl( + final WorldStateArchive worldStateArchive, + final MiningConfiguration miningConfiguration, + final TransactionSimulator transactionSimulator, + final ProtocolSchedule protocolSchedule, + final Blockchain blockchain) { + this.blockchain = blockchain; + blockSimulator = + new BlockSimulator( + worldStateArchive, protocolSchedule, transactionSimulator, miningConfiguration); + this.worldStateArchive = worldStateArchive; + } + + /** + * Simulate the processing of a block given a header, a list of transactions, and blockOverrides. + * + * @param blockNumber the block number + * @param transactions the transactions to include in the block + * @param blockOverrides the blockSimulationOverride of the block + * @param accountOverrides state overrides of the block + * @return the block context + */ + @Override + public PluginBlockSimulationResult simulate( + final long blockNumber, + final List transactions, + final BlockOverrides blockOverrides, + final AccountOverrideMap accountOverrides) { + return processSimulation(blockNumber, transactions, blockOverrides, accountOverrides, false); + } + + /** + * This method is experimental and should be used with caution. Simulate the processing of a block + * given a header, a list of transactions, and blockOverrides and persist the WorldState + * + * @param blockNumber the block number + * @param transactions the transactions to include in the block + * @param blockOverrides block overrides for the block + * @param accountOverrides state overrides of the block + * @return the PluginBlockSimulationResult + */ + @Unstable + @Override + public PluginBlockSimulationResult simulateAndPersistWorldState( + final long blockNumber, + final List transactions, + final BlockOverrides blockOverrides, + final AccountOverrideMap accountOverrides) { + return processSimulation(blockNumber, transactions, blockOverrides, accountOverrides, true); + } + + private PluginBlockSimulationResult processSimulation( + final long blockNumber, + final List transactions, + final BlockOverrides blockOverrides, + final AccountOverrideMap accountOverrides, + final boolean persistWorldState) { + BlockHeader header = getBlockHeader(blockNumber); + List callParameters = + transactions.stream().map(CallParameter::fromTransaction).toList(); + BlockStateCall blockStateCall = + new BlockStateCall(callParameters, blockOverrides, accountOverrides, true); + try (final MutableWorldState ws = getWorldState(header, persistWorldState)) { + List results = + blockSimulator.process(header, List.of(blockStateCall), ws); + BlockSimulationResult result = results.getFirst(); + if (persistWorldState) { + ws.persist(result.getBlock().getHeader()); + } + return response(result); + } catch (final Exception e) { + throw new RuntimeException("Error simulating block", e); + } + } + + private BlockHeader getBlockHeader(final long blockNumber) { + return blockchain + .getBlockHeader(blockNumber) + .orElseThrow( + () -> + new IllegalArgumentException( + "Block header not found for block number: " + blockNumber)); + } + + private MutableWorldState getWorldState(final BlockHeader header, final boolean isPersisting) { + return worldStateArchive + .getMutable(header, isPersisting) + .orElseThrow( + () -> + new IllegalArgumentException( + "World state not available for block number (block hash): " + + header.toLogString())); + } + + private PluginBlockSimulationResult response(final BlockSimulationResult result) { + return new PluginBlockSimulationResult( + result.getBlockHeader(), + result.getBlockBody(), + result.getReceipts(), + result.getTransactionSimulations().stream() + .map( + simulation -> + new TransactionSimulationResult(simulation.transaction(), simulation.result())) + .toList()); + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java index 76b4d7e1509..b1893ef37fb 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java @@ -108,7 +108,7 @@ public Optional> getReceiptsByBlockHash(final Hash bloc public void storeBlock( final BlockHeader blockHeader, final BlockBody blockBody, - final List receipts) { + final List receipts) { final org.hyperledger.besu.ethereum.core.BlockHeader coreHeader = (org.hyperledger.besu.ethereum.core.BlockHeader) blockHeader; final org.hyperledger.besu.ethereum.core.BlockBody coreBody = diff --git a/besu/src/main/java/org/hyperledger/besu/services/PrivacyPluginServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/PrivacyPluginServiceImpl.java index fe61c7a4507..0dbb518d281 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/PrivacyPluginServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/PrivacyPluginServiceImpl.java @@ -24,7 +24,7 @@ import org.slf4j.LoggerFactory; /** The Privacy plugin service implementation. */ -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivacyPluginServiceImpl implements PrivacyPluginService { private static final Logger LOG = LoggerFactory.getLogger(PrivacyPluginServiceImpl.class); diff --git a/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java index 2e15e2ab82f..cd4f494dc65 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/SynchronizationServiceImpl.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockImporter; +import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -45,6 +46,7 @@ public class SynchronizationServiceImpl implements SynchronizationService { private final ProtocolContext protocolContext; private final ProtocolSchedule protocolSchedule; + private final Synchronizer synchronizer; private final SyncState syncState; private final Optional worldStateArchive; @@ -52,16 +54,19 @@ public class SynchronizationServiceImpl implements SynchronizationService { /** * Constructor for SynchronizationServiceImpl. * + * @param synchronizer synchronizer * @param protocolContext protocol context * @param protocolSchedule protocol schedule * @param syncState sync state * @param worldStateArchive world state archive */ public SynchronizationServiceImpl( + final Synchronizer synchronizer, final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, final SyncState syncState, final WorldStateArchive worldStateArchive) { + this.synchronizer = synchronizer; this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; this.syncState = syncState; @@ -157,4 +162,14 @@ public void disableWorldStateTrie() { } }); } + + @Override + public void stop() { + synchronizer.stop(); + } + + @Override + public void start() { + synchronizer.start(); + } } diff --git a/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java index 6a0804b6f46..225825c72e0 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/TraceServiceImpl.java @@ -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.data.BlockTraceResult; @@ -217,7 +216,9 @@ private List trace( transaction, protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(header), tracer, - new CachingBlockHashLookup(header, blockchain), + protocolSpec + .getBlockHashProcessor() + .createBlockHashLookup(blockchain, header), false, blobGasPrice); diff --git a/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java index 4dc411ee0be..5244229c1df 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java @@ -18,7 +18,6 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Transaction; import org.hyperledger.besu.ethereum.chain.Blockchain; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; @@ -35,11 +34,6 @@ /** TransactionSimulationServiceImpl */ @Unstable public class TransactionSimulationServiceImpl implements TransactionSimulationService { - private static final TransactionValidationParams SIMULATOR_ALLOWING_EXCEEDING_BALANCE = - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(true) - .build(); private Blockchain blockchain; private TransactionSimulator transactionSimulator; @@ -57,46 +51,50 @@ public void init(final Blockchain blockchain, final TransactionSimulator transac this.transactionSimulator = transactionSimulator; } - @Override - public Optional simulate( - final Transaction transaction, - final Hash blockHash, - final OperationTracer operationTracer, - final boolean isAllowExceedingBalance) { - return simulate( - transaction, Optional.empty(), blockHash, operationTracer, isAllowExceedingBalance); - } - @Override public Optional simulate( final Transaction transaction, final Optional maybeAccountOverrides, - final Hash blockHash, + final Optional maybeBlockHash, final OperationTracer operationTracer, final boolean isAllowExceedingBalance) { final CallParameter callParameter = CallParameter.fromTransaction(transaction); - final var maybeBlockHeader = - blockchain.getBlockHeader(blockHash).or(() -> blockchain.getBlockHeaderSafe(blockHash)); + if (maybeBlockHash.isPresent()) { + final Hash blockHash = maybeBlockHash.get(); + + final var maybeBlockHeader = + blockchain.getBlockHeader(blockHash).or(() -> blockchain.getBlockHeaderSafe(blockHash)); + + if (maybeBlockHeader.isEmpty()) { + return Optional.of( + new TransactionSimulationResult( + transaction, + TransactionProcessingResult.invalid( + ValidationResult.invalid(TransactionInvalidReason.BLOCK_NOT_FOUND)))); + } - if (maybeBlockHeader.isEmpty()) { - return Optional.of( - new TransactionSimulationResult( - transaction, - TransactionProcessingResult.invalid( - ValidationResult.invalid(TransactionInvalidReason.BLOCK_NOT_FOUND)))); + return transactionSimulator + .process( + callParameter, + isAllowExceedingBalance + ? TransactionValidationParams.transactionSimulatorAllowExceedingBalance() + : TransactionValidationParams.transactionSimulator(), + operationTracer, + maybeBlockHeader.get()) + .map(res -> new TransactionSimulationResult(transaction, res.result())); } return transactionSimulator - .process( + .processOnPending( callParameter, maybeAccountOverrides, isAllowExceedingBalance - ? SIMULATOR_ALLOWING_EXCEEDING_BALANCE + ? TransactionValidationParams.transactionSimulatorAllowExceedingBalance() : TransactionValidationParams.transactionSimulator(), operationTracer, - maybeBlockHeader.get()) + transactionSimulator.simulatePendingBlockHeader()) .map(res -> new TransactionSimulationResult(transaction, res.result())); } } diff --git a/besu/src/main/java/org/hyperledger/besu/util/EphemeryGenesisUpdater.java b/besu/src/main/java/org/hyperledger/besu/util/EphemeryGenesisUpdater.java index 0b970a6809c..c022f84adae 100644 --- a/besu/src/main/java/org/hyperledger/besu/util/EphemeryGenesisUpdater.java +++ b/besu/src/main/java/org/hyperledger/besu/util/EphemeryGenesisUpdater.java @@ -16,7 +16,7 @@ import static org.hyperledger.besu.cli.config.NetworkName.EPHEMERY; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import java.io.IOException; import java.math.BigInteger; @@ -46,16 +46,16 @@ public EphemeryGenesisUpdater() {} * @return the updated GenesisConfigFile * @throws RuntimeException if an error occurs during the update process */ - public static GenesisConfigFile updateGenesis(final Map overrides) + public static GenesisConfig updateGenesis(final Map overrides) throws RuntimeException { - GenesisConfigFile genesisConfigFile; + GenesisConfig genesisConfig; try { if (EPHEMERY.getGenesisFile() == null) { throw new IOException("Genesis file or config options are null"); } - genesisConfigFile = GenesisConfigFile.fromResource(EPHEMERY.getGenesisFile()); - long genesisTimestamp = genesisConfigFile.getTimestamp(); - Optional genesisChainId = genesisConfigFile.getConfigOptions().getChainId(); + genesisConfig = GenesisConfig.fromResource(EPHEMERY.getGenesisFile()); + long genesisTimestamp = genesisConfig.getTimestamp(); + Optional genesisChainId = genesisConfig.getConfigOptions().getChainId(); long currentTimestamp = Instant.now().getEpochSecond(); long periodsSinceGenesis = ChronoUnit.DAYS.between(Instant.ofEpochSecond(genesisTimestamp), Instant.now()) @@ -71,9 +71,9 @@ public static GenesisConfigFile updateGenesis(final Map override if (currentTimestamp > (genesisTimestamp + PERIOD_IN_SECONDS)) { overrides.put("chainId", String.valueOf(updatedChainId)); overrides.put("timestamp", String.valueOf(updatedTimestamp)); - genesisConfigFile = genesisConfigFile.withOverrides(overrides); + genesisConfig = genesisConfig.withOverrides(overrides); } - return genesisConfigFile.withOverrides(overrides); + return genesisConfig.withOverrides(overrides); } catch (IOException e) { throw new RuntimeException("Error updating ephemery genesis: " + e.getMessage(), e); } diff --git a/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java index ff205e87519..5298633ff9b 100644 --- a/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java +++ b/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java @@ -22,12 +22,13 @@ import org.hyperledger.besu.components.MockBesuCommandModule; import org.hyperledger.besu.components.NoOpMetricsSystemModule; import org.hyperledger.besu.components.PrivacyTestModule; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.enclave.EnclaveFactory; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; @@ -145,7 +146,7 @@ BesuController provideBesuController( @Named("dataDir") final Path dataDir) { return new BesuController.Builder() - .fromGenesisFile(GenesisConfigFile.mainnet(), SyncMode.FULL) + .fromGenesisFile(GenesisConfig.mainnet(), SyncMode.FULL) .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) @@ -162,6 +163,7 @@ BesuController provideBesuController( .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(context) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); } } diff --git a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java index 87bab916f23..e4ac7d5b5fc 100644 --- a/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/ForkIdsNetworkConfigTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.cli.config.NetworkName; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.merge.MergeProtocolSchedule; import org.hyperledger.besu.consensus.merge.PostMergeContext; @@ -133,10 +133,9 @@ public static Collection parameters() { @ParameterizedTest @MethodSource("parameters") public void testForkId(final NetworkName chainName, final List expectedForkIds) { - final GenesisConfigFile genesisConfigFile = - GenesisConfigFile.fromResource(chainName.getGenesisFile()); - final MilestoneStreamingTransitionProtocolSchedule schedule = createSchedule(genesisConfigFile); - final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, schedule); + final GenesisConfig genesisConfig = GenesisConfig.fromResource(chainName.getGenesisFile()); + final MilestoneStreamingTransitionProtocolSchedule schedule = createSchedule(genesisConfig); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, schedule); final Blockchain mockBlockchain = mock(Blockchain.class); final BlockHeader mockBlockHeader = mock(BlockHeader.class); @@ -150,8 +149,8 @@ public void testForkId(final NetworkName chainName, final List expectedF final ForkIdManager forkIdManager = new ForkIdManager( mockBlockchain, - genesisConfigFile.getForkBlockNumbers(), - genesisConfigFile.getForkTimestamps(), + genesisConfig.getForkBlockNumbers(), + genesisConfig.getForkTimestamps(), false); final List actualForkIds = @@ -167,8 +166,8 @@ public void testForkId(final NetworkName chainName, final List expectedF } private static MilestoneStreamingTransitionProtocolSchedule createSchedule( - final GenesisConfigFile genesisConfigFile) { - final GenesisConfigOptions configOptions = genesisConfigFile.getConfigOptions(); + final GenesisConfig genesisConfig) { + final GenesisConfigOptions configOptions = genesisConfig.getConfigOptions(); MilestoneStreamingProtocolSchedule preMergeProtocolSchedule = new MilestoneStreamingProtocolSchedule( (DefaultProtocolSchedule) diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java index a79b6644587..6ddaa618635 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java @@ -27,7 +27,7 @@ import org.hyperledger.besu.components.MockBesuCommandModule; import org.hyperledger.besu.components.NoOpMetricsSystemModule; import org.hyperledger.besu.components.PrivacyTestModule; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithm; @@ -41,6 +41,7 @@ import org.hyperledger.besu.enclave.types.ReceiveResponse; import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockDataGenerator; @@ -534,7 +535,7 @@ static class PrivacyReorgTestBesuControllerModule { @SuppressWarnings("CloseableProvides") BesuController provideBesuController( final PrivacyParameters privacyParameters, - final GenesisConfigFile genesisConfigFile, + final GenesisConfig genesisConfig, final PrivacyReorgTestComponent context, final @Named("dataDir") Path dataDir) { @@ -542,7 +543,7 @@ BesuController provideBesuController( // named privacyReorgParams BesuController retval = new BesuController.Builder() - .fromGenesisFile(genesisConfigFile, SyncMode.FULL) + .fromGenesisFile(genesisConfig, SyncMode.FULL) .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) @@ -558,6 +559,7 @@ BesuController provideBesuController( .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(context) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); return retval; } @@ -566,8 +568,8 @@ BesuController provideBesuController( @Module static class PrivacyReorgTestGenesisConfigModule { @Provides - GenesisConfigFile providePrivacyReorgGenesisConfigFile() { - return GenesisConfigFile.fromResource("/privacy_reorg_genesis.json"); + GenesisConfig providePrivacyReorgGenesisConfig() { + return GenesisConfig.fromResource("/privacy_reorg_genesis.json"); } } } diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java index 305d786b8bd..32f2b1f6176 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java @@ -23,11 +23,12 @@ import org.hyperledger.besu.components.NoOpMetricsSystemModule; import org.hyperledger.besu.components.PrivacyParametersModule; import org.hyperledger.besu.components.PrivacyTestModule; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; @@ -120,7 +121,7 @@ BesuController provideBesuController( @Named("dataDir") final Path dataDir) { return new BesuController.Builder() - .fromGenesisFile(GenesisConfigFile.mainnet(), SyncMode.FULL) + .fromGenesisFile(GenesisConfig.mainnet(), SyncMode.FULL) .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) @@ -137,6 +138,7 @@ BesuController provideBesuController( .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(context) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); } } diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 4239cbdc344..2fc89285668 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -26,7 +26,7 @@ import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.components.BesuComponent; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.config.MergeConfiguration; import org.hyperledger.besu.controller.BesuController; @@ -181,9 +181,7 @@ public void fastSyncFromGenesisUsingPeerTaskSystem() throws Exception { } private void syncFromGenesis( - final SyncMode mode, - final GenesisConfigFile genesisConfig, - final boolean isPeerTaskSystemEnabled) + final SyncMode mode, final GenesisConfig genesisConfig, final boolean isPeerTaskSystemEnabled) throws Exception { final Path dataDirAhead = Files.createTempDirectory(temp, "db-ahead"); final Path dbAhead = dataDirAhead.resolve("database"); @@ -270,7 +268,7 @@ private void syncFromGenesis( final EnodeURL aheadEnode = runnerAhead.getLocalEnode().get(); final EthNetworkConfig behindEthNetworkConfiguration = new EthNetworkConfig( - GenesisConfigFile.fromResource(DEV.getGenesisFile()), + GenesisConfig.fromResource(DEV.getGenesisFile()), DEV.getNetworkId(), Collections.singletonList(aheadEnode), null); @@ -395,11 +393,10 @@ private Request getRequest(final String method, final String baseUrl) { .build(); } - private GenesisConfigFile getFastSyncGenesis() throws IOException { + private GenesisConfig getFastSyncGenesis() throws IOException { final ObjectNode jsonNode = (ObjectNode) - new ObjectMapper() - .readTree(GenesisConfigFile.class.getResource(MAINNET.getGenesisFile())); + new ObjectMapper().readTree(GenesisConfig.class.getResource(MAINNET.getGenesisFile())); final Optional configNode = JsonUtil.getObjectNode(jsonNode, "config"); configNode.ifPresent( (node) -> { @@ -408,7 +405,7 @@ private GenesisConfigFile getFastSyncGenesis() throws IOException { // remove merge terminal difficulty for fast sync in the absence of a CL mock node.remove("terminalTotalDifficulty"); }); - return GenesisConfigFile.fromConfig(jsonNode); + return GenesisConfig.fromConfig(jsonNode); } private StorageProvider createKeyValueStorageProvider( @@ -482,7 +479,7 @@ private static void setupState( } private BesuController getController( - final GenesisConfigFile genesisConfig, + final GenesisConfig genesisConfig, final SynchronizerConfiguration syncConfig, final Path dataDir, final NodeKey nodeKey, @@ -490,7 +487,7 @@ private BesuController getController( final ObservableMetricsSystem metricsSystem, final MiningConfiguration miningConfiguration) { return new MainnetBesuControllerBuilder() - .genesisConfigFile(genesisConfig) + .genesisConfig(genesisConfig) .synchronizerConfiguration(syncConfig) .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .dataDirectory(dataDir) @@ -510,6 +507,7 @@ private BesuController getController( .besuComponent(mock(BesuComponent.class)) .maxPeers(25) .maxRemotelyInitiatedPeers(15) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); } } diff --git a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java index e76c06fe2d4..a0e596a0005 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; @@ -105,6 +106,7 @@ private static BesuController createController(final @TempDir Path dataDir) thro .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(mock(BesuComponent.class)) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); } diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java index 2b534660ed2..1b1c914d411 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java @@ -21,13 +21,14 @@ import org.hyperledger.besu.components.BesuCommandModule; import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.components.BesuPluginContextModule; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; @@ -77,14 +78,14 @@ public abstract class JsonBlockImporterTest { @TempDir public Path dataDir; protected String consensusEngine; - protected GenesisConfigFile genesisConfigFile; + protected GenesisConfig genesisConfig; protected boolean isEthash; protected void setup(final String consensusEngine) throws IOException { this.consensusEngine = consensusEngine; final String genesisData = getFileContents("genesis.json"); - this.genesisConfigFile = GenesisConfigFile.fromConfig(genesisData); - this.isEthash = genesisConfigFile.getConfigOptions().isEthHash(); + this.genesisConfig = GenesisConfig.fromConfig(genesisData); + this.isEthash = genesisConfig.getConfigOptions().isEthHash(); } public static class SingletonTests extends JsonBlockImporterTest { @@ -105,7 +106,7 @@ public void importChain_unsupportedConsensusAlgorithm() throws IOException { .isInstanceOf(IllegalArgumentException.class) .hasMessage( "Unable to create block using current consensus engine: " - + genesisConfigFile.getConfigOptions().getConsensusEngine()); + + genesisConfig.getConfigOptions().getConsensusEngine()); } } @@ -418,7 +419,7 @@ public void importChain_specialFields(final String consensusEngine) throws IOExc .isInstanceOf(IllegalArgumentException.class) .hasMessage( "Some fields (coinbase, extraData) are unsupported by the current consensus engine: " - + genesisConfigFile.getConfigOptions().getConsensusEngine()); + + genesisConfig.getConfigOptions().getConsensusEngine()); } } @@ -447,12 +448,12 @@ protected String getFileContents(final String folder, final String filename) thr } protected BesuController createController() throws IOException { - return createController(genesisConfigFile); + return createController(genesisConfig); } - protected BesuController createController(final GenesisConfigFile genesisConfigFile) { + protected BesuController createController(final GenesisConfig genesisConfig) { return new BesuController.Builder() - .fromGenesisFile(genesisConfigFile, SyncMode.FAST) + .fromGenesisFile(genesisConfig, SyncMode.FAST) .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) .storageProvider(new InMemoryKeyValueStorageProvider()) @@ -475,6 +476,7 @@ protected BesuController createController(final GenesisConfigFile genesisConfigF .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(DaggerJsonBlockImporterTest_JsonBlockImportComponent.builder().build()) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); } diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java index 9f405d4cb39..2f707edc6f4 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -80,6 +81,7 @@ public void blockImport() throws IOException { .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(mock(BesuComponent.class)) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); final RlpBlockImporter.ImportResult result = rlpBlockImporter.importBlockchain(source, targetController, false); @@ -114,6 +116,7 @@ public void blockImportRejectsBadPow() throws IOException { .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(mock(BesuComponent.class)) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); assertThatThrownBy( @@ -145,6 +148,7 @@ public void blockImportCanSkipPow() throws IOException { .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(mock(BesuComponent.class)) + .apiConfiguration(ImmutableApiConfiguration.builder().build()) .build(); final RlpBlockImporter.ImportResult result = diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index eb789478b9a..a8bcde0e27d 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -46,7 +46,7 @@ import org.hyperledger.besu.BesuInfo; import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.MergeConfiguration; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Hash; @@ -188,11 +188,10 @@ public void testGenesisOverrideOptions() throws Exception { assertThat(config.networkId()).isEqualTo(BigInteger.valueOf(1)); // assert that shanghaiTime override is applied - final GenesisConfigFile actualGenesisConfigFile = (config.genesisConfigFile()); - assertThat(actualGenesisConfigFile).isNotNull(); - assertThat(actualGenesisConfigFile.getConfigOptions().getShanghaiTime()).isNotEmpty(); - assertThat(actualGenesisConfigFile.getConfigOptions().getShanghaiTime().getAsLong()) - .isEqualTo(123); + final GenesisConfig actualGenesisConfig = (config.genesisConfig()); + assertThat(actualGenesisConfig).isNotNull(); + assertThat(actualGenesisConfig.getConfigOptions().getShanghaiTime()).isNotEmpty(); + assertThat(actualGenesisConfig.getConfigOptions().getShanghaiTime().getAsLong()).isEqualTo(123); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); @@ -217,11 +216,10 @@ public void testGenesisOverrideOptionsWithCustomGenesis() throws Exception { assertThat(config.networkId()).isEqualTo(BigInteger.valueOf(3141592)); // then assert that the shanghaiTime is applied - final GenesisConfigFile actualGenesisConfigFile = (config.genesisConfigFile()); - assertThat(actualGenesisConfigFile).isNotNull(); - assertThat(actualGenesisConfigFile.getConfigOptions().getShanghaiTime()).isNotEmpty(); - assertThat(actualGenesisConfigFile.getConfigOptions().getShanghaiTime().getAsLong()) - .isEqualTo(123); + final GenesisConfig actualGenesisConfig = (config.genesisConfig()); + assertThat(actualGenesisConfig).isNotNull(); + assertThat(actualGenesisConfig.getConfigOptions().getShanghaiTime()).isNotEmpty(); + assertThat(actualGenesisConfig.getConfigOptions().getShanghaiTime().getAsLong()).isEqualTo(123); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); @@ -262,7 +260,7 @@ public void callingBesuCommandWithoutOptionsMustSyncWithDefaultValues() { verify(mockRunnerBuilder) .ethNetworkConfig( new EthNetworkConfig( - GenesisConfigFile.fromResource(MAINNET.getGenesisFile()), + GenesisConfig.fromResource(MAINNET.getGenesisFile()), MAINNET.getNetworkId(), MAINNET_BOOTSTRAP_NODES, MAINNET_DISCOVERY_URL)); @@ -470,8 +468,8 @@ public void genesisPathOptionMustBeUsed() throws Exception { verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any()); verify(mockControllerBuilder).build(); - assertThat(networkArg.getValue().genesisConfigFile()) - .isEqualTo(GenesisConfigFile.fromConfig(encodeJsonGenesis(GENESIS_VALID_JSON))); + assertThat(networkArg.getValue().genesisConfig()) + .isEqualTo(GenesisConfig.fromConfig(encodeJsonGenesis(GENESIS_VALID_JSON))); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); @@ -636,8 +634,8 @@ public void defaultNetworkIdAndBootnodesForCustomNetworkOptions() throws Excepti verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any()); verify(mockControllerBuilder).build(); - assertThat(networkArg.getValue().genesisConfigFile()) - .isEqualTo(GenesisConfigFile.fromConfig(encodeJsonGenesis(GENESIS_VALID_JSON))); + assertThat(networkArg.getValue().genesisConfig()) + .isEqualTo(GenesisConfig.fromConfig(encodeJsonGenesis(GENESIS_VALID_JSON))); assertThat(networkArg.getValue().bootNodes()).isEmpty(); assertThat(networkArg.getValue().networkId()).isEqualTo(GENESIS_CONFIG_TEST_CHAINID); @@ -657,8 +655,8 @@ public void defaultNetworkIdForInvalidGenesisMustBeMainnetNetworkId() throws Exc verify(mockControllerBuilderFactory).fromEthNetworkConfig(networkArg.capture(), any()); verify(mockControllerBuilder).build(); - assertThat(networkArg.getValue().genesisConfigFile()) - .isEqualTo(GenesisConfigFile.fromConfig(encodeJsonGenesis(GENESIS_INVALID_DATA))); + assertThat(networkArg.getValue().genesisConfig()) + .isEqualTo(GenesisConfig.fromConfig(encodeJsonGenesis(GENESIS_INVALID_DATA))); assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); @@ -672,7 +670,7 @@ public void predefinedNetworkIdsMustBeEqualToChainIds() { // in this network genesis file. final var genesisConfig = - EthNetworkConfig.getNetworkConfig(MAINNET).genesisConfigFile().getConfigOptions(); + EthNetworkConfig.getNetworkConfig(MAINNET).genesisConfig().getConfigOptions(); assertThat(genesisConfig.getChainId().isPresent()).isTrue(); assertThat(genesisConfig.getChainId().get()) .isEqualTo(EthNetworkConfig.getNetworkConfig(MAINNET).networkId()); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CascadingDefaultProviderTest.java b/besu/src/test/java/org/hyperledger/besu/cli/CascadingDefaultProviderTest.java index c1428388149..c2c10ef73c7 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CascadingDefaultProviderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CascadingDefaultProviderTest.java @@ -28,7 +28,7 @@ import static org.mockito.Mockito.verify; import org.hyperledger.besu.cli.config.EthNetworkConfig; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration; @@ -128,8 +128,7 @@ public void overrideDefaultValuesIfKeyIsPresentInConfigFile(final @TempDir File final EthNetworkConfig networkConfig = new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(MAINNET)) .setNetworkId(BigInteger.valueOf(42)) - .setGenesisConfigFile( - GenesisConfigFile.fromConfig(encodeJsonGenesis(GENESIS_VALID_JSON))) + .setGenesisConfig(GenesisConfig.fromConfig(encodeJsonGenesis(GENESIS_VALID_JSON))) .setBootNodes(nodes) .setDnsDiscoveryUrl(null) .build(); @@ -166,7 +165,7 @@ public void noOverrideDefaultValuesIfKeyIsNotPresentInConfigFile() { verify(mockRunnerBuilder) .ethNetworkConfig( new EthNetworkConfig( - GenesisConfigFile.fromResource(MAINNET.getGenesisFile()), + GenesisConfig.fromResource(MAINNET.getGenesisFile()), MAINNET.getNetworkId(), MAINNET_BOOTSTRAP_NODES, MAINNET_DISCOVERY_URL)); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java index 72396593985..78f782d5e55 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java @@ -296,6 +296,7 @@ public void initMocks() throws Exception { when(mockControllerBuilder.cacheLastBlocks(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.genesisStateHashCacheEnabled(any())) .thenReturn(mockControllerBuilder); + when(mockControllerBuilder.apiConfiguration(any())).thenReturn(mockControllerBuilder); when(mockControllerBuilder.build()).thenReturn(mockController); lenient().when(mockController.getProtocolManager()).thenReturn(mockEthProtocolManager); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/HostAllowlistOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/HostAllowlistOptionsTest.java index c1f867f4892..21dd587ce7f 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/HostAllowlistOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/HostAllowlistOptionsTest.java @@ -23,24 +23,6 @@ public class HostAllowlistOptionsTest extends CommandTestAbstract { - /** test deprecated CLI option * */ - @Deprecated - @Test - public void rpcHttpHostWhitelistAcceptsSingleArgument() { - parseCommand("--host-whitelist", "a"); - - verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); - verify(mockRunnerBuilder).build(); - - assertThat(jsonRpcConfigArgumentCaptor.getValue().getHostsAllowlist().size()).isEqualTo(1); - assertThat(jsonRpcConfigArgumentCaptor.getValue().getHostsAllowlist()).contains("a"); - assertThat(jsonRpcConfigArgumentCaptor.getValue().getHostsAllowlist()) - .doesNotContain("localhost"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - @Test public void rpcHttpHostAllowlistAcceptsSingleArgument() { parseCommand("--host-allowlist", "a"); @@ -89,23 +71,6 @@ public void rpcHttpHostAllowlistAcceptsDoubleComma() { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } - @Deprecated - @Test - public void rpcHttpHostWhitelistAllowlistAcceptsMultipleFlags() { - parseCommand("--host-whitelist=a", "--host-allowlist=b"); - - verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); - verify(mockRunnerBuilder).build(); - - assertThat(jsonRpcConfigArgumentCaptor.getValue().getHostsAllowlist().size()).isEqualTo(2); - assertThat(jsonRpcConfigArgumentCaptor.getValue().getHostsAllowlist()).contains("a", "b"); - assertThat(jsonRpcConfigArgumentCaptor.getValue().getHostsAllowlist()) - .doesNotContain("*", "localhost"); - - assertThat(commandOutput.toString(UTF_8)).isEmpty(); - assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); - } - @Test public void rpcHttpHostAllowlistAcceptsMultipleFlags() { parseCommand("--host-allowlist=a", "--host-allowlist=b"); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java b/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java index 3af43eb4e5f..768ca09e971 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/config/EthNetworkConfigTest.java @@ -21,7 +21,7 @@ import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.SEPOLIA_BOOTSTRAP_NODES; import static org.hyperledger.besu.ethereum.p2p.config.DefaultDiscoveryConfiguration.SEPOLIA_DISCOVERY_URL; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import java.math.BigInteger; @@ -77,8 +77,8 @@ public void testBuilderWithNetworkId() { EthNetworkConfig config = new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(MAINNET)) .setNetworkId(BigInteger.valueOf(42)) - .setGenesisConfigFile( - GenesisConfigFile.fromConfig( + .setGenesisConfig( + GenesisConfig.fromConfig( """ { "config":{ @@ -87,7 +87,7 @@ public void testBuilderWithNetworkId() { } """)) .build(); - assertThat(config.genesisConfigFile().getConfigOptions().getChainId()) + assertThat(config.genesisConfig().getConfigOptions().getChainId()) .contains(BigInteger.valueOf(1234567)); assertThat(config.dnsDiscoveryUrl()).isNotNull(); assertThat(config.bootNodes()).isNotEmpty(); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptionsTest.java b/besu/src/test/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptionsTest.java index afb53bac934..e29b16c573e 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptionsTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/options/JsonRpcHttpOptionsTest.java @@ -332,7 +332,10 @@ public void rpcHttpTlsClientAuthWithoutKnownFileReportsError() { assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)) .contains( - "Known-clients file must be specified or CA clients must be enabled when TLS client authentication is enabled for JSON-RPC HTTP endpoint"); + "Configuration error: TLS client authentication is enabled, but none of the following options are provided: " + + "1. Specify a known-clients file (--rpc-http-tls-known-clients-file) and/or Enable CA clients (--rpc-http-tls-ca-clients-enabled). " + + "2. Specify a truststore file and its password file (--rpc-http-tls-truststore-file and --rpc-http-tls-truststore-password-file). " + + "Only one of these options must be configured"); } @Test @@ -342,6 +345,7 @@ public void rpcHttpTlsClientAuthWithKnownClientFile() { final String keystoreFile = "/tmp/test.p12"; final String keystorePasswordFile = "/tmp/test.txt"; final String knownClientFile = "/tmp/knownClientFile"; + parseCommand( "--rpc-http-enabled", "--rpc-http-host", @@ -422,6 +426,90 @@ public void rpcHttpTlsClientAuthWithCAClient() { assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); } + @Test + public void rpcHttpTlsClientAuthWithTrustStore() throws IOException { + final String host = "1.2.3.4"; + final int port = 1234; + final String keystoreFile = "/tmp/test.p12"; + final String keystorePasswordFile = "/tmp/test.txt"; + final String truststoreFile = "/tmp/truststore.p12"; + final String truststorePasswordFile = "/tmp/truststore.txt"; + + Files.writeString(Path.of(truststorePasswordFile), "password"); + parseCommand( + "--rpc-http-enabled", + "--rpc-http-host", + host, + "--rpc-http-port", + String.valueOf(port), + "--rpc-http-tls-enabled", + "--rpc-http-tls-keystore-file", + keystoreFile, + "--rpc-http-tls-keystore-password-file", + keystorePasswordFile, + "--rpc-http-tls-client-auth-enabled", + "--rpc-http-tls-truststore-file", + truststoreFile, + "--rpc-http-tls-truststore-password-file", + truststorePasswordFile); + + verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); + verify(mockRunnerBuilder).build(); + + assertThat(jsonRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo(host); + assertThat(jsonRpcConfigArgumentCaptor.getValue().getPort()).isEqualTo(port); + final Optional tlsConfiguration = + jsonRpcConfigArgumentCaptor.getValue().getTlsConfiguration(); + assertThat(tlsConfiguration.isPresent()).isTrue(); + assertThat(tlsConfiguration.get().getKeyStorePath()).isEqualTo(Path.of(keystoreFile)); + assertThat(tlsConfiguration.get().getClientAuthConfiguration().isPresent()).isTrue(); + assertThat(tlsConfiguration.get().getClientAuthConfiguration().get().getTruststorePath()) + .isEqualTo(Optional.of(Path.of(truststoreFile))); + assertThat(tlsConfiguration.get().getClientAuthConfiguration().get().getTrustStorePassword()) + .isEqualTo(Files.readString(Path.of(truststorePasswordFile))); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); + } + + @Test + public void rpcHttpTlsClientAuthWithTrustStoreAndKnownClientsFileReportsError() + throws IOException { + final String host = "1.2.3.4"; + final int port = 1234; + final String keystoreFile = "/tmp/test.p12"; + final String keystorePasswordFile = "/tmp/test.txt"; + final String truststoreFile = "/tmp/truststore.p12"; + final String truststorePasswordFile = "/tmp/truststore.txt"; + final String knownClientFile = "/tmp/knownClientFile"; + + Files.writeString(Path.of(truststorePasswordFile), "password"); + parseCommand( + "--rpc-http-enabled", + "--rpc-http-host", + host, + "--rpc-http-port", + String.valueOf(port), + "--rpc-http-tls-enabled", + "--rpc-http-tls-keystore-file", + keystoreFile, + "--rpc-http-tls-keystore-password-file", + keystorePasswordFile, + "--rpc-http-tls-client-auth-enabled", + "--rpc-http-tls-truststore-file", + truststoreFile, + "--rpc-http-tls-truststore-password-file", + truststorePasswordFile, + "--rpc-http-tls-known-clients-file", + knownClientFile); + + assertThat(commandOutput.toString(UTF_8)).isEmpty(); + assertThat(commandErrorOutput.toString(UTF_8)) + .contains( + "Configuration error: Truststore file (--rpc-http-tls-truststore-file) cannot be used together with CA clients (--rpc-http-tls-ca-clients-enabled) or a known-clients (--rpc-http-tls-known-clients-file) option. " + + "These options are mutually exclusive. Choose either truststore-based authentication or known-clients/CA clients configuration."); + } + @Test public void rpcHttpTlsClientAuthWithCAClientAndKnownClientFile() { final String host = "1.2.3.4"; diff --git a/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java b/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java index ae82b8b9288..c43d49cd8ef 100644 --- a/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java +++ b/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.components; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import javax.inject.Named; @@ -26,13 +26,13 @@ public class GenesisConfigModule { @Named("default") @Provides - GenesisConfigFile provideDefaultGenesisConfigFile() { - return GenesisConfigFile.DEFAULT; + GenesisConfig provideDefaultGenesisConfig() { + return GenesisConfig.DEFAULT; } @Named("mainnet") @Provides - GenesisConfigFile provideMainnetGenesisConfigFile() { - return GenesisConfigFile.mainnet(); + GenesisConfig provideMainnetGenesisConfig() { + return GenesisConfig.mainnet(); } } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java index da58e2d67cd..185f88f6b6d 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java @@ -21,7 +21,7 @@ import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; @@ -29,6 +29,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -74,7 +75,7 @@ public abstract class AbstractBftBesuControllerBuilderTest { protected BesuControllerBuilder bftBesuControllerBuilder; - @Mock protected GenesisConfigFile genesisConfigFile; + @Mock protected GenesisConfig genesisConfig; @Mock protected GenesisConfigOptions genesisConfigOptions; @Mock private SynchronizerConfiguration synchronizerConfiguration; @Mock private EthProtocolConfiguration ethProtocolConfiguration; @@ -101,11 +102,11 @@ public void setup() throws JsonProcessingException { final WorldStateStorageCoordinator worldStateStorageCoordinator = new WorldStateStorageCoordinator(worldStateKeyValueStorage); - lenient().when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString()); - lenient().when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString()); - lenient().when(genesisConfigFile.getMixHash()).thenReturn(Hash.ZERO.toHexString()); - lenient().when(genesisConfigFile.getNonce()).thenReturn(Long.toHexString(1)); - lenient().when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); + lenient().when(genesisConfig.getParentHash()).thenReturn(Hash.ZERO.toHexString()); + lenient().when(genesisConfig.getDifficulty()).thenReturn(Bytes.of(0).toHexString()); + lenient().when(genesisConfig.getMixHash()).thenReturn(Hash.ZERO.toHexString()); + lenient().when(genesisConfig.getNonce()).thenReturn(Long.toHexString(1)); + lenient().when(genesisConfig.getConfigOptions()).thenReturn(genesisConfigOptions); lenient().when(genesisConfigOptions.getCheckpointOptions()).thenReturn(checkpointConfigOptions); lenient() .when(storageProvider.createBlockchainStorage(any(), any(), any())) @@ -138,11 +139,11 @@ public void setup() throws JsonProcessingException { .when(synchronizerConfiguration.getBlockPropagationRange()) .thenReturn(Range.closed(1L, 2L)); - setupBftGenesisConfigFile(); + setupBftGenesisConfig(); bftBesuControllerBuilder = createBftControllerBuilder() - .genesisConfigFile(genesisConfigFile) + .genesisConfig(genesisConfig) .synchronizerConfiguration(synchronizerConfiguration) .ethProtocolConfiguration(ethProtocolConfiguration) .networkId(networkId) @@ -158,10 +159,11 @@ public void setup() throws JsonProcessingException { .gasLimitCalculator(gasLimitCalculator) .evmConfiguration(EvmConfiguration.DEFAULT) .besuComponent(mock(BesuComponent.class)) - .networkConfiguration(NetworkingConfiguration.create()); + .networkConfiguration(NetworkingConfiguration.create()) + .apiConfiguration(ImmutableApiConfiguration.builder().build()); } - protected abstract void setupBftGenesisConfigFile() throws JsonProcessingException; + protected abstract void setupBftGenesisConfig() throws JsonProcessingException; protected abstract BesuControllerBuilder createBftControllerBuilder(); diff --git a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerTest.java b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerTest.java index 94c68f7cbe2..1f6927ca995 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/BesuControllerTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.QbftConfigOptions; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; @@ -39,20 +39,20 @@ @ExtendWith(MockitoExtension.class) public class BesuControllerTest { - @Mock GenesisConfigFile genesisConfigFile; + @Mock GenesisConfig genesisConfig; @Mock GenesisConfigOptions genesisConfigOptions; @Mock QbftConfigOptions qbftConfigOptions; @BeforeEach public void setUp() { - lenient().when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); + lenient().when(genesisConfig.getConfigOptions()).thenReturn(genesisConfigOptions); } @Test public void missingQbftStartBlock() { mockGenesisConfigForMigration("ibft2", OptionalLong.empty()); assertThatThrownBy( - () -> new BesuController.Builder().fromGenesisFile(genesisConfigFile, SyncMode.FULL)) + () -> new BesuController.Builder().fromGenesisFile(genesisConfig, SyncMode.FULL)) .isInstanceOf(IllegalStateException.class) .hasMessage("Missing QBFT startBlock config in genesis file"); } @@ -61,7 +61,7 @@ public void missingQbftStartBlock() { public void invalidQbftStartBlock() { mockGenesisConfigForMigration("ibft2", OptionalLong.of(-1L)); assertThatThrownBy( - () -> new BesuController.Builder().fromGenesisFile(genesisConfigFile, SyncMode.FULL)) + () -> new BesuController.Builder().fromGenesisFile(genesisConfig, SyncMode.FULL)) .isInstanceOf(IllegalStateException.class) .hasMessage("Invalid QBFT startBlock config in genesis file"); } @@ -72,7 +72,7 @@ public void invalidConsensusCombination() { // explicitly not setting isIbft2() for genesisConfigOptions assertThatThrownBy( - () -> new BesuController.Builder().fromGenesisFile(genesisConfigFile, SyncMode.FULL)) + () -> new BesuController.Builder().fromGenesisFile(genesisConfig, SyncMode.FULL)) .isInstanceOf(IllegalStateException.class) .hasMessage( "Invalid genesis migration config. Migration is supported from IBFT (legacy) or IBFT2 to QBFT)"); @@ -84,7 +84,7 @@ public void createConsensusScheduleBesuControllerBuilderWhenMigratingFromIbft2To mockGenesisConfigForMigration("ibft2", OptionalLong.of(qbftStartBlock)); final BesuControllerBuilder besuControllerBuilder = - new BesuController.Builder().fromGenesisFile(genesisConfigFile, SyncMode.FULL); + new BesuController.Builder().fromGenesisFile(genesisConfig, SyncMode.FULL); assertThat(besuControllerBuilder).isInstanceOf(ConsensusScheduleBesuControllerBuilder.class); @@ -118,8 +118,8 @@ private void mockGenesisConfigForMigration( @Test public void postMergeCheckpointSyncUsesMergeControllerBuilder() { - final GenesisConfigFile postMergeGenesisFile = - GenesisConfigFile.fromResource("/valid_post_merge_near_head_checkpoint.json"); + final GenesisConfig postMergeGenesisFile = + GenesisConfig.fromResource("/valid_post_merge_near_head_checkpoint.json"); final BesuControllerBuilder besuControllerBuilder = new BesuController.Builder().fromGenesisFile(postMergeGenesisFile, SyncMode.CHECKPOINT); @@ -130,8 +130,8 @@ public void postMergeCheckpointSyncUsesMergeControllerBuilder() { @Test public void postMergeCheckpointSyncWithTotalDifficultyEqualsTTDUsesTransitionControllerBuilder() throws IOException { - final GenesisConfigFile mergeAtGenesisFile = - GenesisConfigFile.fromResource( + final GenesisConfig mergeAtGenesisFile = + GenesisConfig.fromResource( "/invalid_post_merge_checkpoint_total_difficulty_same_as_TTD.json"); final BesuControllerBuilder besuControllerBuilder = @@ -143,8 +143,7 @@ public void postMergeCheckpointSyncWithTotalDifficultyEqualsTTDUsesTransitionCon @Test public void preMergeCheckpointSyncUsesTransitionControllerBuilder() { final BesuControllerBuilder besuControllerBuilder = - new BesuController.Builder() - .fromGenesisFile(GenesisConfigFile.mainnet(), SyncMode.CHECKPOINT); + new BesuController.Builder().fromGenesisFile(GenesisConfig.mainnet(), SyncMode.CHECKPOINT); assertThat(besuControllerBuilder).isInstanceOf(TransitionBesuControllerBuilder.class); } @@ -152,7 +151,7 @@ public void preMergeCheckpointSyncUsesTransitionControllerBuilder() { @Test public void nonCheckpointSyncUsesTransitionControllerBuild() { final BesuControllerBuilder besuControllerBuilder = - new BesuController.Builder().fromGenesisFile(GenesisConfigFile.mainnet(), SyncMode.SNAP); + new BesuController.Builder().fromGenesisFile(GenesisConfig.mainnet(), SyncMode.SNAP); assertThat(besuControllerBuilder).isInstanceOf(TransitionBesuControllerBuilder.class); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java index 5fe349644e1..b1e8ac5845c 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java @@ -22,7 +22,7 @@ import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.ImmutableCliqueConfigOptions; import org.hyperledger.besu.config.TransitionsConfigOptions; @@ -33,6 +33,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -79,7 +80,7 @@ public class CliqueBesuControllerBuilderTest { private BesuControllerBuilder cliqueBesuControllerBuilder; - @Mock private GenesisConfigFile genesisConfigFile; + @Mock private GenesisConfig genesisConfig; @Mock private GenesisConfigOptions genesisConfigOptions; @Mock private SynchronizerConfiguration synchronizerConfiguration; @Mock private EthProtocolConfiguration ethProtocolConfiguration; @@ -107,14 +108,14 @@ public void setup() throws JsonProcessingException { final WorldStateStorageCoordinator worldStateStorageCoordinator = new WorldStateStorageCoordinator(worldStateKeyValueStorage); - lenient().when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString()); - lenient().when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString()); - when(genesisConfigFile.getExtraData()) + lenient().when(genesisConfig.getParentHash()).thenReturn(Hash.ZERO.toHexString()); + lenient().when(genesisConfig.getDifficulty()).thenReturn(Bytes.of(0).toHexString()); + when(genesisConfig.getExtraData()) .thenReturn( "0x0000000000000000000000000000000000000000000000000000000000000000b9b81ee349c3807e46bc71aa2632203c5b4620340000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); - lenient().when(genesisConfigFile.getMixHash()).thenReturn(Hash.ZERO.toHexString()); - lenient().when(genesisConfigFile.getNonce()).thenReturn(Long.toHexString(1)); - lenient().when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); + lenient().when(genesisConfig.getMixHash()).thenReturn(Hash.ZERO.toHexString()); + lenient().when(genesisConfig.getNonce()).thenReturn(Long.toHexString(1)); + lenient().when(genesisConfig.getConfigOptions()).thenReturn(genesisConfigOptions); lenient().when(genesisConfigOptions.getCheckpointOptions()).thenReturn(checkpointConfigOptions); lenient() .when(storageProvider.createBlockchainStorage(any(), any(), any())) @@ -175,7 +176,7 @@ public void setup() throws JsonProcessingException { cliqueBesuControllerBuilder = new CliqueBesuControllerBuilder() - .genesisConfigFile(genesisConfigFile) + .genesisConfig(genesisConfig) .synchronizerConfiguration(synchronizerConfiguration) .ethProtocolConfiguration(ethProtocolConfiguration) .networkId(networkId) @@ -191,7 +192,8 @@ public void setup() throws JsonProcessingException { .gasLimitCalculator(gasLimitCalculator) .evmConfiguration(EvmConfiguration.DEFAULT) .besuComponent(mock(BesuComponent.class)) - .networkConfiguration(NetworkingConfiguration.create()); + .networkConfiguration(NetworkingConfiguration.create()) + .apiConfiguration(ImmutableApiConfiguration.builder().build()); } @Test diff --git a/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java index 4e38e03c062..4a4ae8530e3 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/ConsensusScheduleBesuControllerBuilderTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.StubGenesisConfigOptions; import org.hyperledger.besu.consensus.common.ForkSpec; import org.hyperledger.besu.consensus.common.ForksSchedule; @@ -60,7 +60,7 @@ public class ConsensusScheduleBesuControllerBuilderTest { private @Mock BiFunction< NavigableSet>, Optional, ProtocolSchedule> combinedProtocolScheduleFactory; - private @Mock GenesisConfigFile genesisConfigFile; + private @Mock GenesisConfig genesisConfig; private @Mock BesuControllerBuilder besuControllerBuilder1; private @Mock BesuControllerBuilder besuControllerBuilder2; private @Mock BesuControllerBuilder besuControllerBuilder3; @@ -103,8 +103,8 @@ public void mustCreateCombinedProtocolScheduleUsingProtocolSchedulesOrderedByBlo final ConsensusScheduleBesuControllerBuilder consensusScheduleBesuControllerBuilder = new ConsensusScheduleBesuControllerBuilder( besuControllerBuilderSchedule, combinedProtocolScheduleFactory); - when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); - consensusScheduleBesuControllerBuilder.genesisConfigFile(genesisConfigFile); + when(genesisConfig.getConfigOptions()).thenReturn(genesisConfigOptions); + consensusScheduleBesuControllerBuilder.genesisConfig(genesisConfig); consensusScheduleBesuControllerBuilder.createProtocolSchedule(); final NavigableSet> expectedProtocolSchedulesSpecs = diff --git a/besu/src/test/java/org/hyperledger/besu/controller/IbftBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/IbftBesuControllerBuilderTest.java index 055e136c8ca..1a2f45eac8b 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/IbftBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/IbftBesuControllerBuilderTest.java @@ -33,7 +33,7 @@ public class IbftBesuControllerBuilderTest extends AbstractBftBesuControllerBuilderTest { @Override - public void setupBftGenesisConfigFile() throws JsonProcessingException { + public void setupBftGenesisConfig() throws JsonProcessingException { // Ibft prepForBuild setup lenient() @@ -56,7 +56,7 @@ public void setupBftGenesisConfigFile() throws JsonProcessingException { .when(genesisConfigOptions.getTransitions()) .thenReturn(new TransitionsConfigOptions(jsonTransitions)); - when(genesisConfigFile.getExtraData()) + when(genesisConfig.getExtraData()) .thenReturn( "0xf83ea00000000000000000000000000000000000000000000000000000000000000000d594c2ab482b506de561668e07f04547232a72897daf808400000000c0"); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java index 47971b6442e..ce2dab822ff 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java @@ -25,7 +25,7 @@ import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.merge.MergeContext; import org.hyperledger.besu.cryptoservices.NodeKey; @@ -33,6 +33,7 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.api.ImmutableApiConfiguration; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; @@ -88,7 +89,7 @@ public class MergeBesuControllerBuilderTest { private MergeBesuControllerBuilder besuControllerBuilder; private static final NodeKey nodeKey = NodeKeyUtils.generate(); - @Mock GenesisConfigFile genesisConfigFile; + @Mock GenesisConfig genesisConfig; @Mock GenesisConfigOptions genesisConfigOptions; @Mock SynchronizerConfiguration synchronizerConfiguration; @Mock EthProtocolConfiguration ethProtocolConfiguration; @@ -120,12 +121,12 @@ public void setup() { final WorldStateStorageCoordinator worldStateStorageCoordinator = new WorldStateStorageCoordinator(worldStateKeyValueStorage); - lenient().when(genesisConfigFile.getParentHash()).thenReturn(Hash.ZERO.toHexString()); - lenient().when(genesisConfigFile.getDifficulty()).thenReturn(Bytes.of(0).toHexString()); - lenient().when(genesisConfigFile.getExtraData()).thenReturn(Bytes.EMPTY.toHexString()); - lenient().when(genesisConfigFile.getMixHash()).thenReturn(Hash.ZERO.toHexString()); - lenient().when(genesisConfigFile.getNonce()).thenReturn(Long.toHexString(1)); - lenient().when(genesisConfigFile.getConfigOptions()).thenReturn(genesisConfigOptions); + lenient().when(genesisConfig.getParentHash()).thenReturn(Hash.ZERO.toHexString()); + lenient().when(genesisConfig.getDifficulty()).thenReturn(Bytes.of(0).toHexString()); + lenient().when(genesisConfig.getExtraData()).thenReturn(Bytes.EMPTY.toHexString()); + lenient().when(genesisConfig.getMixHash()).thenReturn(Hash.ZERO.toHexString()); + lenient().when(genesisConfig.getNonce()).thenReturn(Long.toHexString(1)); + lenient().when(genesisConfig.getConfigOptions()).thenReturn(genesisConfigOptions); lenient().when(genesisConfigOptions.getCheckpointOptions()).thenReturn(checkpointConfigOptions); when(genesisConfigOptions.getTerminalTotalDifficulty()) .thenReturn((Optional.of(UInt256.valueOf(100L)))); @@ -176,7 +177,7 @@ MergeBesuControllerBuilder visitWithMockConfigs(final MergeBesuControllerBuilder return (MergeBesuControllerBuilder) builder .gasLimitCalculator(gasLimitCalculator) - .genesisConfigFile(genesisConfigFile) + .genesisConfig(genesisConfig) .synchronizerConfiguration(synchronizerConfiguration) .ethProtocolConfiguration(ethProtocolConfiguration) .miningParameters(miningConfiguration) @@ -191,7 +192,8 @@ MergeBesuControllerBuilder visitWithMockConfigs(final MergeBesuControllerBuilder .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .besuComponent(mock(BesuComponent.class)) - .networkId(networkId); + .networkId(networkId) + .apiConfiguration(ImmutableApiConfiguration.builder().build()); } @Test @@ -225,8 +227,7 @@ public void assertConfiguredBlock() { @Test public void assertBuiltContextMonitorsTTD() { final GenesisState genesisState = - GenesisState.fromConfig( - genesisConfigFile, this.besuControllerBuilder.createProtocolSchedule()); + GenesisState.fromConfig(genesisConfig, this.besuControllerBuilder.createProtocolSchedule()); final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final MergeContext mergeContext = spy( diff --git a/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java index 5e41a65bd03..92fa2327d88 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/QbftBesuControllerBuilderTest.java @@ -47,7 +47,7 @@ public class QbftBesuControllerBuilderTest extends AbstractBftBesuControllerBuilderTest { @Override - public void setupBftGenesisConfigFile() throws JsonProcessingException { + public void setupBftGenesisConfig() throws JsonProcessingException { // qbft prepForBuild setup lenient() @@ -72,7 +72,7 @@ public void setupBftGenesisConfigFile() throws JsonProcessingException { .thenReturn(new TransitionsConfigOptions(jsonTransitions)); lenient() - .when(genesisConfigFile.getExtraData()) + .when(genesisConfig.getExtraData()) .thenReturn( QbftExtraDataCodec.createGenesisExtraDataString(List.of(Address.fromHexString("1")))); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java index 24b0133a0f1..dc8eee16eb5 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/TransitionControllerBuilderTest.java @@ -21,7 +21,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.consensus.clique.BlockHeaderValidationRulesetFactory; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.common.EpochManager; @@ -40,6 +40,7 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; @@ -73,6 +74,7 @@ public class TransitionControllerBuilderTest { @Mock ProtocolContext protocolContext; @Mock MutableBlockchain mockBlockchain; @Mock TransactionPool transactionPool; + @Mock PeerTaskExecutor peerTaskExecutor; @Mock SyncState syncState; @Mock(answer = Answers.RETURNS_DEEP_STUBS) @@ -96,9 +98,9 @@ public void setup() { preMergeProtocolSchedule, postMergeProtocolSchedule, mergeContext)); transitionProtocolSchedule.setProtocolContext(protocolContext); cliqueBuilder.nodeKey(NodeKeyUtils.generate()); - cliqueBuilder.genesisConfigFile(GenesisConfigFile.DEFAULT); - powBuilder.genesisConfigFile(GenesisConfigFile.DEFAULT); - postMergeBuilder.genesisConfigFile(GenesisConfigFile.DEFAULT); + cliqueBuilder.genesisConfig(GenesisConfig.DEFAULT); + powBuilder.genesisConfig(GenesisConfig.DEFAULT); + postMergeBuilder.genesisConfig(GenesisConfig.DEFAULT); postMergeBuilder.storageProvider(storageProvider); lenient().when(protocolContext.getBlockchain()).thenReturn(mockBlockchain); lenient() @@ -265,7 +267,7 @@ void assertDetachedRulesForPostMergeBlocks(final BlockHeaderValidator validator) TransitionCoordinator buildTransitionCoordinator( final BesuControllerBuilder preMerge, final MergeBesuControllerBuilder postMerge) { var builder = new TransitionBesuControllerBuilder(preMerge, postMerge); - builder.genesisConfigFile(GenesisConfigFile.mainnet()); + builder.genesisConfig(GenesisConfig.mainnet()); builder.storageProvider(storageProvider); builder.metricsSystem(new NoOpMetricsSystem()); var coordinator = diff --git a/besu/src/test/java/org/hyperledger/besu/util/EphemeryGenesisUpdaterTest.java b/besu/src/test/java/org/hyperledger/besu/util/EphemeryGenesisUpdaterTest.java index fe21c1e6d72..704f26f8e87 100644 --- a/besu/src/test/java/org/hyperledger/besu/util/EphemeryGenesisUpdaterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/util/EphemeryGenesisUpdaterTest.java @@ -16,9 +16,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hyperledger.besu.config.GenesisConfigFile.fromConfig; +import static org.hyperledger.besu.config.GenesisConfig.fromConfig; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import java.math.BigInteger; import java.util.Map; @@ -44,7 +44,7 @@ public class EphemeryGenesisUpdaterTest { .put("config", (new JsonObject()).put("chainId", GENESIS_CONFIG_TEST_CHAINID)) .put("timestamp", GENESIS_TEST_TIMESTAMP); - private static final GenesisConfigFile INVALID_GENESIS_JSON = fromConfig("{}"); + private static final GenesisConfig INVALID_GENESIS_JSON = fromConfig("{}"); private static final JsonObject INVALID_GENESIS_JSON_WITHOUT_CHAINID = (new JsonObject()).put("timestamp", GENESIS_TEST_TIMESTAMP); @@ -54,16 +54,16 @@ public class EphemeryGenesisUpdaterTest { @Test public void testEphemeryWhenChainIdIsAbsent() { - final GenesisConfigFile config = - GenesisConfigFile.fromConfig(INVALID_GENESIS_JSON_WITHOUT_CHAINID.toString()); + final GenesisConfig config = + GenesisConfig.fromConfig(INVALID_GENESIS_JSON_WITHOUT_CHAINID.toString()); Optional chainId = config.getConfigOptions().getChainId(); assertThat(chainId).isNotPresent(); } @Test public void testShouldDefaultTimestampToZero() { - final GenesisConfigFile config = - GenesisConfigFile.fromConfig(INVALID_GENESIS_JSON_WITHOUT_TIMESTAMP.toString()); + final GenesisConfig config = + GenesisConfig.fromConfig(INVALID_GENESIS_JSON_WITHOUT_TIMESTAMP.toString()); assertThat(config.getTimestamp()).isZero(); } @@ -76,7 +76,7 @@ public void testEphemeryWhenGenesisJsonIsInvalid() { @Test public void testEphemeryWhenGenesisJsonIsValid() { - final GenesisConfigFile config = GenesisConfigFile.fromConfig(VALID_GENESIS_JSON.toString()); + final GenesisConfig config = GenesisConfig.fromConfig(VALID_GENESIS_JSON.toString()); assertThat(String.valueOf(config.getTimestamp())) .isEqualTo(String.valueOf(GENESIS_TEST_TIMESTAMP)); assertThat(config.getConfigOptions().getChainId()) @@ -87,7 +87,7 @@ public void testEphemeryWhenGenesisJsonIsValid() { @Test public void testEphemeryNotYetDueForUpdate() { - final GenesisConfigFile config = GenesisConfigFile.fromConfig(VALID_GENESIS_JSON.toString()); + final GenesisConfig config = GenesisConfig.fromConfig(VALID_GENESIS_JSON.toString()); assertThat(EARLIER_TIMESTAMP).isLessThan(config.getTimestamp() + PERIOD_IN_SECONDS); } @@ -100,7 +100,7 @@ void testOverrideWithUpdatedChainIdAndTimeStamp() { long expectedGenesisTimestamp = GENESIS_TEST_TIMESTAMP + (PERIOD_SINCE_GENESIS * PERIOD_IN_SECONDS); - final GenesisConfigFile config = GenesisConfigFile.fromResource("/ephemery.json"); + final GenesisConfig config = GenesisConfig.fromResource("/ephemery.json"); final Map override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); override.put("chainId", String.valueOf(expectedChainId)); @@ -116,7 +116,7 @@ void testOverrideWithUpdatedChainIdAndTimeStamp() { @Test public void testEphemeryWhenSuccessful() { - final GenesisConfigFile config = GenesisConfigFile.fromConfig(VALID_GENESIS_JSON.toString()); + final GenesisConfig config = GenesisConfig.fromConfig(VALID_GENESIS_JSON.toString()); BigInteger expectedChainId = BigInteger.valueOf(GENESIS_CONFIG_TEST_CHAINID) @@ -127,7 +127,7 @@ public void testEphemeryWhenSuccessful() { final Map override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); override.put("chainId", String.valueOf(expectedChainId)); override.put("timestamp", String.valueOf(expectedGenesisTimestamp)); - final GenesisConfigFile updatedConfig = config.withOverrides(override); + final GenesisConfig updatedConfig = config.withOverrides(override); assertThat(LATER_TIMESTAMP) .isGreaterThan(Long.parseLong(String.valueOf(GENESIS_TEST_TIMESTAMP + PERIOD_IN_SECONDS))); diff --git a/besu/src/test/resources/everything_config.toml b/besu/src/test/resources/everything_config.toml index 960b2b5772c..0e944e7f0cf 100644 --- a/besu/src/test/resources/everything_config.toml +++ b/besu/src/test/resources/everything_config.toml @@ -44,7 +44,6 @@ max-peers=42 remote-connections-limit-enabled=true remote-connections-max-percentage=60 random-peer-priority-enabled=false -host-whitelist=["all"] host-allowlist=["all"] engine-host-allowlist=["all"] engine-rpc-enabled=true @@ -85,6 +84,8 @@ rpc-http-tls-keystore-password-file="none.passwd" rpc-http-tls-client-auth-enabled=false rpc-http-tls-known-clients-file="rpc_tls_clients.txt" rpc-http-tls-ca-clients-enabled=false +rpc-http-tls-truststore-file="none.pfx" +rpc-http-tls-truststore-password-file="none.passwd" rpc-http-authentication-jwt-algorithm="RS256" rpc-ws-authentication-jwt-algorithm="RS256" rpc-http-tls-protocols=["TLSv1.2,TlSv1.1"] @@ -123,10 +124,12 @@ rpc-ws-authentication-jwt-public-key-file="none" rpc-ws-ssl-enabled=false rpc-ws-ssl-keystore-file="none.pfx" rpc-ws-ssl-keystore-password="none.passwd" +rpc-ws-ssl-keystore-password-file="none.txt" rpc-ws-ssl-keystore-type="none" rpc-ws-ssl-client-auth-enabled=false rpc-ws-ssl-truststore-file="none.pfx" rpc-ws-ssl-truststore-password="none.passwd" +rpc-ws-ssl-truststore-password-file="none.txt" rpc-ws-ssl-truststore-type="none" rpc-ws-ssl-key-file="none.pfx" rpc-ws-ssl-cert-file="none.pfx" @@ -244,17 +247,6 @@ Xpeertask-system-enabled=false # compatibility flags compatibility-eth64-forkid-enabled=false -#p2p over ssl -Xp2p-tls-enabled=false -Xp2p-tls-keystore-type="none" -Xp2p-tls-keystore-file="none.file" -Xp2p-tls-truststore-password-file="none" -Xp2p-tls-truststore-type="none" -Xp2p-tls-truststore-file="none.file" -Xp2p-tls-keystore-password-file="none" -Xp2p-tls-crl-file="none.file" -Xp2p-tls-clienthello-sni=false - #contracts Xevm-jumpdest-cache-weight-kb=32000 diff --git a/build.gradle b/build.gradle index 1981965a8e6..78908ae68f3 100644 --- a/build.gradle +++ b/build.gradle @@ -580,7 +580,7 @@ subprojects { password = artifactoryKey } defaults { - publications('mavenJava') + publications('mavenJava', 'mavenJavaPlatform') publishArtifacts = true publishPom = true } diff --git a/config/src/main/java/org/hyperledger/besu/config/BlobScheduleOptions.java b/config/src/main/java/org/hyperledger/besu/config/BlobScheduleOptions.java new file mode 100644 index 00000000000..1ad458fa398 --- /dev/null +++ b/config/src/main/java/org/hyperledger/besu/config/BlobScheduleOptions.java @@ -0,0 +1,137 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.config; + +import java.util.Map; +import java.util.Optional; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.collect.ImmutableMap; + +/** The Blob Schedule config options. */ +public class BlobScheduleOptions { + + private final ObjectNode blobScheduleOptionsConfigRoot; + + private static final String CANCUN_KEY = "cancun"; + private static final String PRAGUE_KEY = "prague"; + private static final String OSAKA_KEY = "osaka"; + + /** + * Instantiates a new Blob Schedule config options. + * + * @param blobScheduleConfigRoot the blob schedule config root + */ + public BlobScheduleOptions(final ObjectNode blobScheduleConfigRoot) { + this.blobScheduleOptionsConfigRoot = blobScheduleConfigRoot; + } + + /** + * Gets cancun blob schedule. + * + * @return the cancun blob schedule + */ + public Optional getCancun() { + return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, CANCUN_KEY).map(BlobSchedule::new); + } + + /** + * Gets prague blob schedule. + * + * @return the prague blob schedule + */ + public Optional getPrague() { + return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, PRAGUE_KEY).map(BlobSchedule::new); + } + + /** + * Gets osaka blob schedule. + * + * @return the osaka blob schedule + */ + public Optional getOsaka() { + return JsonUtil.getObjectNode(blobScheduleOptionsConfigRoot, OSAKA_KEY).map(BlobSchedule::new); + } + + /** + * As map. + * + * @return the map + */ + public Map asMap() { + final ImmutableMap.Builder builder = ImmutableMap.builder(); + getCancun().ifPresent(bs -> builder.put(CANCUN_KEY, bs.asMap())); + getPrague().ifPresent(bs -> builder.put(PRAGUE_KEY, bs.asMap())); + getOsaka().ifPresent(bs -> builder.put(OSAKA_KEY, bs.asMap())); + return builder.build(); + } + + /** The Blob schedule for a particular fork. */ + public static class BlobSchedule { + private final int target; + private final int max; + + /** The constant CANCUN_DEFAULT. */ + public static final BlobSchedule CANCUN_DEFAULT = new BlobSchedule(3, 6); + + /** The constant PRAGUE_DEFAULT. */ + public static final BlobSchedule PRAGUE_DEFAULT = new BlobSchedule(6, 9); + + /** The constant OSAKA_DEFAULT. */ + public static final BlobSchedule OSAKA_DEFAULT = new BlobSchedule(9, 12); + + /** + * Instantiates a new Blob schedule. + * + * @param blobScheduleConfigRoot the blob schedule config root + */ + public BlobSchedule(final ObjectNode blobScheduleConfigRoot) { + this.target = JsonUtil.getInt(blobScheduleConfigRoot, "target").orElseThrow(); + this.max = JsonUtil.getInt(blobScheduleConfigRoot, "max").orElseThrow(); + } + + private BlobSchedule(final int target, final int max) { + this.target = target; + this.max = max; + } + + /** + * Gets target. + * + * @return the target + */ + public int getTarget() { + return target; + } + + /** + * Gets max. + * + * @return the max + */ + public int getMax() { + return max; + } + + /** + * As map. + * + * @return the map + */ + Map asMap() { + return Map.of("target", target, "max", max); + } + } +} diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfig.java similarity index 87% rename from config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java rename to config/src/main/java/org/hyperledger/besu/config/GenesisConfig.java index eae9bc3d109..47fa2967451 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigFile.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfig.java @@ -29,11 +29,11 @@ import com.fasterxml.jackson.databind.node.ObjectNode; /** The Genesis config file. */ -public class GenesisConfigFile { +public class GenesisConfig { /** The constant DEFAULT. */ - public static final GenesisConfigFile DEFAULT = - new GenesisConfigFile(new GenesisReader.FromObjectNode(JsonUtil.createEmptyObjectNode())); + public static final GenesisConfig DEFAULT = + new GenesisConfig(new GenesisReader.FromObjectNode(JsonUtil.createEmptyObjectNode())); /** The constant BASEFEE_AT_GENESIS_DEFAULT_VALUE. */ public static final Wei BASEFEE_AT_GENESIS_DEFAULT_VALUE = Wei.of(1_000_000_000L); @@ -42,7 +42,7 @@ public class GenesisConfigFile { private final ObjectNode genesisRoot; private Map overrides; - private GenesisConfigFile(final GenesisReader loader) { + private GenesisConfig(final GenesisReader loader) { this.loader = loader; this.genesisRoot = loader.getRoot(); } @@ -52,8 +52,8 @@ private GenesisConfigFile(final GenesisReader loader) { * * @return the genesis config file */ - public static GenesisConfigFile mainnet() { - return fromSource(GenesisConfigFile.class.getResource("/mainnet.json")); + public static GenesisConfig mainnet() { + return fromSource(GenesisConfig.class.getResource("/mainnet.json")); } /** @@ -62,7 +62,7 @@ public static GenesisConfigFile mainnet() { * @param jsonSource the URL * @return the genesis config file */ - public static GenesisConfigFile fromSource(final URL jsonSource) { + public static GenesisConfig fromSource(final URL jsonSource) { return fromConfig(JsonUtil.objectNodeFromURL(jsonSource, false)); } @@ -72,8 +72,8 @@ public static GenesisConfigFile fromSource(final URL jsonSource) { * @param resourceName the resource name * @return the genesis config file */ - public static GenesisConfigFile fromResource(final String resourceName) { - return fromConfig(GenesisConfigFile.class.getResource(resourceName)); + public static GenesisConfig fromResource(final String resourceName) { + return fromConfig(GenesisConfig.class.getResource(resourceName)); } /** @@ -82,8 +82,8 @@ public static GenesisConfigFile fromResource(final String resourceName) { * @param jsonSource the json string * @return the genesis config file */ - public static GenesisConfigFile fromConfig(final URL jsonSource) { - return new GenesisConfigFile(new GenesisReader.FromURL(jsonSource)); + public static GenesisConfig fromConfig(final URL jsonSource) { + return new GenesisConfig(new GenesisReader.FromURL(jsonSource)); } /** @@ -92,7 +92,7 @@ public static GenesisConfigFile fromConfig(final URL jsonSource) { * @param json the json string * @return the genesis config file */ - public static GenesisConfigFile fromConfig(final String json) { + public static GenesisConfig fromConfig(final String json) { return fromConfig(JsonUtil.objectNodeFromString(json, false)); } @@ -102,8 +102,8 @@ public static GenesisConfigFile fromConfig(final String json) { * @param config the config * @return the genesis config file */ - public static GenesisConfigFile fromConfig(final ObjectNode config) { - return new GenesisConfigFile(new GenesisReader.FromObjectNode(config)); + public static GenesisConfig fromConfig(final ObjectNode config) { + return new GenesisConfig(new GenesisReader.FromObjectNode(config)); } /** @@ -137,7 +137,7 @@ public GenesisConfigOptions getConfigOptions() { * @param overrides the overrides * @return the config options */ - public GenesisConfigFile withOverrides(final Map overrides) { + public GenesisConfig withOverrides(final Map overrides) { this.overrides = overrides; return this; @@ -266,14 +266,14 @@ public String getParentBeaconBlockRoot() { } /** - * Gets target blob count. + * Gets target blobs per block. * - * @return the target blob count + * @return the target blobs per block */ - public Optional getTargetBlobCount() { + public Optional getTargetBlobsPerBlock() { // TODO SLD EIP-7742 not sure if we should use a default value here or enforce any // "pragueAtGenesis" genesis file (used in devnets) to have this value - return JsonUtil.getValueAsString(genesisRoot, "targetblobcount"); + return JsonUtil.getValueAsString(genesisRoot, "targetblobsperblock"); } /** @@ -350,7 +350,7 @@ public List getForkTimestamps() { public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - final GenesisConfigFile that = (GenesisConfigFile) o; + final GenesisConfig that = (GenesisConfig) o; return Objects.equals(genesisRoot, that.genesisRoot); } diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index 1ab5598b86e..e94cafda3c8 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -553,4 +553,11 @@ default boolean isConsensusMigration() { * @return the consolidation request contract address */ Optional
getConsolidationRequestContractAddress(); + + /** + * The blob schedule is a list of hardfork names and their associated target and max blob values. + * + * @return the blob schedule + */ + Optional getBlobScheduleOptions(); } diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index 73f5cde78c8..93aef4288e7 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -47,6 +47,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { private static final String TRANSITIONS_CONFIG_KEY = "transitions"; private static final String DISCOVERY_CONFIG_KEY = "discovery"; private static final String CHECKPOINT_CONFIG_KEY = "checkpoint"; + private static final String BLOB_SCHEDULE_CONFIG_KEY = "blobschedule"; private static final String ZERO_BASE_FEE_KEY = "zerobasefee"; private static final String FIXED_BASE_FEE_KEY = "fixedbasefee"; private static final String WITHDRAWAL_REQUEST_CONTRACT_ADDRESS_KEY = @@ -199,6 +200,12 @@ public EthashConfigOptions getEthashConfigOptions() { .orElse(EthashConfigOptions.DEFAULT); } + @Override + public Optional getBlobScheduleOptions() { + return JsonUtil.getObjectNode(configRoot, BLOB_SCHEDULE_CONFIG_KEY) + .map(BlobScheduleOptions::new); + } + @Override public TransitionsConfigOptions getTransitions() { return transitions; @@ -543,6 +550,10 @@ public Map asMap() { builder.put("fixedBaseFee", true); } + if (getBlobScheduleOptions().isPresent()) { + builder.put("blobSchedule", getBlobScheduleOptions().get().asMap()); + } + return builder.build(); } diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index e5db82944d1..671f8bbdcaf 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -478,6 +478,11 @@ public Optional
getConsolidationRequestContractAddress() { return Optional.empty(); } + @Override + public Optional getBlobScheduleOptions() { + return Optional.empty(); + } + /** * Homestead block stub genesis config options. * diff --git a/config/src/main/resources/mainnet.json b/config/src/main/resources/mainnet.json index ab35a5aba35..5a0fd8d725f 100644 --- a/config/src/main/resources/mainnet.json +++ b/config/src/main/resources/mainnet.json @@ -16,6 +16,16 @@ "terminalTotalDifficulty": 58750000000000000000000, "shanghaiTime": 1681338455, "cancunTime": 1710338135, + "blobSchedule": { + "cancun": { + "target": 3, + "max": 6 + }, + "prague": { + "target": 6, + "max": 9 + } + }, "ethash": { }, "discovery": { diff --git a/config/src/test/java/org/hyperledger/besu/config/BlobScheduleOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/BlobScheduleOptionsTest.java new file mode 100644 index 00000000000..fc746362929 --- /dev/null +++ b/config/src/test/java/org/hyperledger/besu/config/BlobScheduleOptionsTest.java @@ -0,0 +1,41 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.config; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +public class BlobScheduleOptionsTest { + + @Test + public void blobScheduleIsParsed() { + final GenesisConfig genesisConfigFile = + GenesisConfig.fromResource("/mainnet_with_blob_schedule.json"); + final GenesisConfigOptions configOptions = genesisConfigFile.getConfigOptions(); + + assertThat(configOptions.getBlobScheduleOptions()).isNotEmpty(); + final BlobScheduleOptions blobScheduleOptions = configOptions.getBlobScheduleOptions().get(); + assertThat(blobScheduleOptions.getCancun()).isNotEmpty(); + assertThat(blobScheduleOptions.getCancun().get().getTarget()).isEqualTo(4); + assertThat(blobScheduleOptions.getCancun().get().getMax()).isEqualTo(7); + assertThat(blobScheduleOptions.getPrague()).isNotEmpty(); + assertThat(blobScheduleOptions.getPrague().get().getTarget()).isEqualTo(7); + assertThat(blobScheduleOptions.getPrague().get().getMax()).isEqualTo(10); + assertThat(blobScheduleOptions.getOsaka()).isNotEmpty(); + assertThat(blobScheduleOptions.getOsaka().get().getTarget()).isEqualTo(10); + assertThat(blobScheduleOptions.getOsaka().get().getMax()).isEqualTo(13); + } +} diff --git a/config/src/test/java/org/hyperledger/besu/config/CliqueConfigOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/CliqueConfigOptionsTest.java index f445730ac18..c8fb01b6a1c 100644 --- a/config/src/test/java/org/hyperledger/besu/config/CliqueConfigOptionsTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/CliqueConfigOptionsTest.java @@ -78,6 +78,6 @@ private CliqueConfigOptions fromConfigOptions(final Map cliqueCo final ObjectNode options = JsonUtil.objectNodeFromMap(cliqueConfigOptions); configNode.set("clique", options); rootNode.set("config", configNode); - return GenesisConfigFile.fromConfig(rootNode).getConfigOptions().getCliqueConfigOptions(); + return GenesisConfig.fromConfig(rootNode).getConfigOptions().getCliqueConfigOptions(); } } diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java index fe8149cc654..16622f35c21 100644 --- a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java @@ -260,7 +260,7 @@ void shouldGetChainIdWhenSpecified() { @Test void shouldSupportEmptyGenesisConfig() { - final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig("{}").getConfigOptions(); assertThat(config.isEthHash()).isFalse(); assertThat(config.isClique()).isFalse(); assertThat(config.isPoa()).isFalse(); @@ -291,7 +291,7 @@ void shouldNotReturnTerminalTotalDifficultyWhenNotSpecified() { @Test void isZeroBaseFeeShouldDefaultToFalse() { - final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig("{}").getConfigOptions(); assertThat(config.isZeroBaseFee()).isFalse(); } @@ -312,7 +312,7 @@ void asMapIncludesZeroBaseFee() { @Test void isFixedBaseFeeShouldDefaultToFalse() { - final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig("{}").getConfigOptions(); assertThat(config.isFixedBaseFee()).isFalse(); } @@ -408,10 +408,50 @@ void asMapIncludesConsolidationRequestContractAddress() { .containsValue(Address.ZERO); } + @SuppressWarnings("unchecked") + @Test + void asMapIncludesBlobFeeSchedule() { + final GenesisConfigOptions config = + GenesisConfig.fromConfig( + "{\n" + + " \"config\": {\n" + + " \"blobSchedule\": {\n" + + " \"cancun\": {\n" + + " \"target\": 1,\n" + + " \"max\": 2\n" + + " },\n" + + " \"prague\": {\n" + + " \"target\": 3,\n" + + " \"max\": 4\n" + + " },\n" + + " \"osaka\": {\n" + + " \"target\": 4,\n" + + " \"max\": 5\n" + + " }\n" + + " }\n" + + " }\n" + + "}") + .getConfigOptions(); + + final Map map = config.asMap(); + assertThat(map).containsOnlyKeys("blobSchedule"); + final Map blobSchedule = (Map) map.get("blobSchedule"); + assertThat(blobSchedule).containsOnlyKeys("cancun", "prague", "osaka"); + assertThat((Map) blobSchedule.get("cancun")) + .containsOnlyKeys("target", "max") + .containsValues(1, 2); + assertThat((Map) blobSchedule.get("prague")) + .containsOnlyKeys("target", "max") + .containsValues(3, 4); + assertThat((Map) blobSchedule.get("osaka")) + .containsOnlyKeys("target", "max") + .containsValues(4, 5); + } + private GenesisConfigOptions fromConfigOptions(final Map configOptions) { final ObjectNode rootNode = JsonUtil.createEmptyObjectNode(); final ObjectNode options = JsonUtil.objectNodeFromMap(configOptions); rootNode.set("config", options); - return GenesisConfigFile.fromConfig(rootNode).getConfigOptions(); + return GenesisConfig.fromConfig(rootNode).getConfigOptions(); } } diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigTest.java similarity index 89% rename from config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java rename to config/src/test/java/org/hyperledger/besu/config/GenesisConfigTest.java index 3e6b488b9bd..33ff2eb0a36 100644 --- a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigTest.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hyperledger.besu.config.GenesisConfigFile.fromConfig; +import static org.hyperledger.besu.config.GenesisConfig.fromConfig; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; @@ -39,15 +39,15 @@ import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.Test; -class GenesisConfigFileTest { +class GenesisConfigTest { private static final BigInteger MAINNET_CHAIN_ID = BigInteger.ONE; private static final BigInteger DEVELOPMENT_CHAIN_ID = BigInteger.valueOf(1337); - private static final GenesisConfigFile EMPTY_CONFIG = fromConfig("{}"); + private static final GenesisConfig EMPTY_CONFIG = fromConfig("{}"); @Test void shouldLoadMainnetConfigFile() { - final GenesisConfigFile config = GenesisConfigFile.mainnet(); + final GenesisConfig config = GenesisConfig.mainnet(); // Sanity check some basic properties to confirm this is the mainnet file. assertThat(config.getConfigOptions().isEthHash()).isTrue(); assertThat(config.getConfigOptions().getChainId()).hasValue(MAINNET_CHAIN_ID); @@ -64,7 +64,7 @@ void shouldLoadMainnetConfigFile() { @Test void shouldLoadDevelopmentConfigFile() { - final GenesisConfigFile config = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig config = GenesisConfig.fromResource("/dev.json"); // Sanity check some basic properties to confirm this is the dev file. assertThat(config.getConfigOptions().isEthHash()).isTrue(); assertThat(config.getConfigOptions().getChainId()).hasValue(DEVELOPMENT_CHAIN_ID); @@ -156,27 +156,27 @@ void shouldGetTimestamp() { @Test void shouldGetBaseFeeAtGenesis() { - GenesisConfigFile withBaseFeeAtGenesis = - GenesisConfigFile.fromConfig("{\"config\":{\"londonBlock\":0},\"baseFeePerGas\":\"0xa\"}"); + GenesisConfig withBaseFeeAtGenesis = + GenesisConfig.fromConfig("{\"config\":{\"londonBlock\":0},\"baseFeePerGas\":\"0xa\"}"); assertThat(withBaseFeeAtGenesis.getBaseFeePerGas()).isPresent(); assertThat(withBaseFeeAtGenesis.getBaseFeePerGas().get().toLong()).isEqualTo(10L); } @Test void shouldGetDefaultBaseFeeAtGenesis() { - GenesisConfigFile withBaseFeeAtGenesis = - GenesisConfigFile.fromConfig("{\"config\":{\"londonBlock\":0}}"); + GenesisConfig withBaseFeeAtGenesis = + GenesisConfig.fromConfig("{\"config\":{\"londonBlock\":0}}"); // no specified baseFeePerGas: assertThat(withBaseFeeAtGenesis.getBaseFeePerGas()).isNotPresent(); // supply a default genesis baseFeePerGas when london-at-genesis: assertThat(withBaseFeeAtGenesis.getGenesisBaseFeePerGas()) - .contains(GenesisConfigFile.BASEFEE_AT_GENESIS_DEFAULT_VALUE); + .contains(GenesisConfig.BASEFEE_AT_GENESIS_DEFAULT_VALUE); } @Test void shouldGetBaseFeeExplicitlyAtGenesis() { - GenesisConfigFile withBaseFeeNotAtGenesis = - GenesisConfigFile.fromConfig("{\"config\":{\"londonBlock\":10},\"baseFeePerGas\":\"0xa\"}"); + GenesisConfig withBaseFeeNotAtGenesis = + GenesisConfig.fromConfig("{\"config\":{\"londonBlock\":10},\"baseFeePerGas\":\"0xa\"}"); // specified baseFeePerGas: Wei expectedBaseFee = Wei.of(0xa); assertThat(withBaseFeeNotAtGenesis.getBaseFeePerGas()).contains(expectedBaseFee); @@ -195,7 +195,7 @@ void shouldOverrideConfigOptionsBaseFeeWhenSpecified() { @Test void shouldGetTerminalTotalDifficultyAtGenesis() { - GenesisConfigFile withTerminalTotalDifficultyAtGenesis = + GenesisConfig withTerminalTotalDifficultyAtGenesis = fromConfig("{\"config\":{\"terminalTotalDifficulty\":1000}}"); assertThat(withTerminalTotalDifficultyAtGenesis.getConfigOptions().getTerminalTotalDifficulty()) .contains(UInt256.valueOf(1000L)); @@ -209,7 +209,7 @@ void shouldGetEmptyTerminalTotalDifficultyAtGenesis() { @Test void assertSepoliaTerminalTotalDifficulty() { GenesisConfigOptions sepoliaOptions = - GenesisConfigFile.fromResource("/sepolia.json").getConfigOptions(); + GenesisConfig.fromResource("/sepolia.json").getConfigOptions(); assertThat(sepoliaOptions.getTerminalTotalDifficulty()).isPresent(); assertThat(sepoliaOptions.getTerminalTotalDifficulty()) @@ -219,7 +219,7 @@ void assertSepoliaTerminalTotalDifficulty() { @Test void assertMainnetTerminalTotalDifficulty() { GenesisConfigOptions mainnetOptions = - GenesisConfigFile.fromResource("/mainnet.json").getConfigOptions(); + GenesisConfig.fromResource("/mainnet.json").getConfigOptions(); assertThat(mainnetOptions.getTerminalTotalDifficulty()).isPresent(); // tentative as of 2022-08-11: @@ -230,7 +230,7 @@ void assertMainnetTerminalTotalDifficulty() { @Test void assertTerminalTotalDifficultyOverride() { GenesisConfigOptions sepoliaOverrideOptions = - GenesisConfigFile.fromResource("/sepolia.json") + GenesisConfig.fromResource("/sepolia.json") .withOverrides(Map.of("terminalTotalDifficulty", String.valueOf(Long.MAX_VALUE))) .getConfigOptions(); @@ -241,8 +241,8 @@ void assertTerminalTotalDifficultyOverride() { @Test void shouldFindMergeNetSplitForkAndAlias() { - GenesisConfigFile mergeNetSplitGenesis = - GenesisConfigFile.fromConfig( + GenesisConfig mergeNetSplitGenesis = + GenesisConfig.fromConfig( "{\"config\":{\"mergeNetsplitBlock\":11},\"baseFeePerGas\":\"0xa\"}"); assertThat(mergeNetSplitGenesis.getForkBlockNumbers()).hasSize(1); assertThat(mergeNetSplitGenesis.getConfigOptions().getMergeNetSplitBlockNumber()).isPresent(); @@ -250,8 +250,8 @@ void shouldFindMergeNetSplitForkAndAlias() { .isEqualTo(11L); // assert empty if not present: - GenesisConfigFile londonGenesis = - GenesisConfigFile.fromConfig("{\"config\":{\"londonBlock\":11},\"baseFeePerGas\":\"0xa\"}"); + GenesisConfig londonGenesis = + GenesisConfig.fromConfig("{\"config\":{\"londonBlock\":11},\"baseFeePerGas\":\"0xa\"}"); assertThat(londonGenesis.getForkBlockNumbers()).hasSize(1); assertThat(londonGenesis.getConfigOptions().getMergeNetSplitBlockNumber()).isEmpty(); } @@ -263,7 +263,7 @@ void shouldDefaultTimestampToZero() { @Test void shouldGetAllocations() { - final GenesisConfigFile config = + final GenesisConfig config = fromConfig( "{" + " \"alloc\": {" @@ -322,13 +322,13 @@ void shouldGetAllocations() { @Test void shouldGetEmptyAllocationsWhenAllocNotPresent() { - final GenesisConfigFile config = fromConfig("{}"); + final GenesisConfig config = fromConfig("{}"); assertThat(config.streamAllocations()).isEmpty(); } @Test void shouldGetLargeChainId() { - final GenesisConfigFile config = + final GenesisConfig config = fromConfig( "{\"config\": { \"chainId\": 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095 }}"); assertThat(config.getConfigOptions().getChainId()) @@ -349,7 +349,7 @@ void mustNotAcceptComments() { @Test void testOverridePresent() { - final GenesisConfigFile config = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig config = GenesisConfig.fromResource("/dev.json"); final int bigBlock = 999_999_999; final String bigBlockString = Integer.toString(bigBlock); final Map override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); @@ -368,7 +368,7 @@ void testOverridePresent() { @Test void testOverrideNull() { - final GenesisConfigFile config = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig config = GenesisConfig.fromResource("/dev.json"); final Map override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); override.put("istanbulBlock", null); override.put("chainId", null); @@ -384,7 +384,7 @@ void testOverrideNull() { @Test void testOverrideCaseInsensitivity() { - final GenesisConfigFile config = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig config = GenesisConfig.fromResource("/dev.json"); final int bigBlock = 999_999_999; final String bigBlockString = Integer.toString(bigBlock); final Map override = new HashMap<>(); @@ -405,7 +405,7 @@ void testOverrideCaseInsensitivity() { @Test void testOverrideEmptyString() { - final GenesisConfigFile config = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig config = GenesisConfig.fromResource("/dev.json"); final Map override = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); override.put("istanbulBlock", ""); override.put("chainId", ""); @@ -420,7 +420,7 @@ void testOverrideEmptyString() { @Test void testNoOverride() { - final GenesisConfigFile config = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig config = GenesisConfig.fromResource("/dev.json"); assertThat(config.getConfigOptions().getLondonBlockNumber()).hasValue(0); assertThat(config.getConfigOptions().getIstanbulBlockNumber()).isNotPresent(); @@ -433,7 +433,7 @@ void testNoOverride() { @Test void testConstantinopleFixShouldNotBeSupportedAlongPetersburg() { // petersburg node - final GenesisConfigFile config = GenesisConfigFile.fromResource("/all_forks.json"); + final GenesisConfig config = GenesisConfig.fromResource("/all_forks.json"); assertThat(config.getConfigOptions().getPetersburgBlockNumber()).hasValue(7); @@ -463,7 +463,7 @@ void shouldLoadForksInSortedOrder() throws IOException { "valid_config_with_custom_forks.json"), StandardCharsets.UTF_8))); - final GenesisConfigFile config = fromConfig(configNode); + final GenesisConfig config = fromConfig(configNode); assertThat(config.getForkBlockNumbers()).containsExactly(1L, 2L, 3L, 1035301L, 2222222L); assertThat(config.getConfigOptions().getChainId()).hasValue(BigInteger.valueOf(4)); @@ -483,7 +483,7 @@ void shouldLoadForksIgnoreClassicForkBlock() throws IOException { // declared (which we want to ignore) "valid_config_with_etc_forks.json"), StandardCharsets.UTF_8))); - final GenesisConfigFile config = fromConfig(configNode); + final GenesisConfig config = fromConfig(configNode); assertThat(config.getForkBlockNumbers()).containsExactly(1L, 2L, 3L, 1035301L); assertThat(config.getConfigOptions().getChainId()).hasValue(BigInteger.valueOf(61)); @@ -528,9 +528,9 @@ void shouldLoadForksIgnoreUnexpectedValues() throws IOException { "valid_config_with_unexpected_forks.json"), StandardCharsets.UTF_8))); - final GenesisConfigFile configFileNoUnexpectedForks = fromConfig(configNoUnexpectedForks); - final GenesisConfigFile configFileClassicFork = fromConfig(configClassicFork); - final GenesisConfigFile configFileMultipleUnexpectedForks = + final GenesisConfig configFileNoUnexpectedForks = fromConfig(configNoUnexpectedForks); + final GenesisConfig configFileClassicFork = fromConfig(configClassicFork); + final GenesisConfig configFileMultipleUnexpectedForks = fromConfig(configMultipleUnexpectedForks); assertThat(configFileNoUnexpectedForks.getForkBlockNumbers()) @@ -559,7 +559,7 @@ void roundTripForkIdBlocks() throws IOException { Resources.toString(Resources.getResource("all_forks.json"), StandardCharsets.UTF_8); final ObjectNode genesisNode = JsonUtil.objectNodeFromString(configText); - final GenesisConfigFile genesisConfig = fromConfig(genesisNode); + final GenesisConfig genesisConfig = fromConfig(genesisNode); final ObjectNode output = JsonUtil.objectNodeFromMap(genesisConfig.getConfigOptions().asMap()); @@ -567,7 +567,7 @@ void roundTripForkIdBlocks() throws IOException { .isEqualTo(JsonUtil.getJson(genesisNode.get("config"), true)); } - private GenesisConfigFile configWithProperty(final String key, final String value) { + private GenesisConfig configWithProperty(final String key, final String value) { return fromConfig("{\"" + key + "\":\"" + value + "\"}"); } diff --git a/config/src/test/java/org/hyperledger/besu/config/JsonBftConfigOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/JsonBftConfigOptionsTest.java index bbb4c4a6ceb..5a81108f0c8 100644 --- a/config/src/test/java/org/hyperledger/besu/config/JsonBftConfigOptionsTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/JsonBftConfigOptionsTest.java @@ -254,6 +254,6 @@ private BftConfigOptions fromConfigOptions(final Map ibftConfigO final ObjectNode options = JsonUtil.objectNodeFromMap(ibftConfigOptions); configNode.set("ibft2", options); rootNode.set("config", configNode); - return GenesisConfigFile.fromConfig(rootNode).getConfigOptions().getBftConfigOptions(); + return GenesisConfig.fromConfig(rootNode).getConfigOptions().getBftConfigOptions(); } } diff --git a/config/src/test/resources/mainnet_with_blob_schedule.json b/config/src/test/resources/mainnet_with_blob_schedule.json new file mode 100644 index 00000000000..b313a7dbabe --- /dev/null +++ b/config/src/test/resources/mainnet_with_blob_schedule.json @@ -0,0 +1,37 @@ +{ + "config": { + "chainId": 3151908, + "homesteadBlock": 0, + "eip150Block": 0, + "eip155Block": 0, + "eip158Block": 0, + "byzantiumBlock": 0, + "constantinopleBlock": 0, + "petersburgBlock": 0, + "istanbulBlock": 0, + "berlinBlock": 0, + "londonBlock": 0, + "preMergeForkBlock": 0, + "terminalTotalDifficulty": 0, + "ethash": {}, + "shanghaiTime": 0, + "cancunTime": 0, + "blobSchedule": { + "cancun": { + "target": 4, + "max": 7 + }, + "prague": { + "target": 7, + "max": 10 + }, + "osaka": { + "target": 10, + "max": 13 + } + }, + "depositContractAddress": "0x4242424242424242424242424242424242424242", + "pragueTime": 1734106711, + "osakaTime": 1734107095 + } +} \ No newline at end of file diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueProtocolScheduleTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueProtocolScheduleTest.java index 47741206229..fcbf10e7ac3 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueProtocolScheduleTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/CliqueProtocolScheduleTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.CliqueConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.JsonCliqueConfigOptions; import org.hyperledger.besu.consensus.common.ForkSpec; @@ -61,7 +61,7 @@ public void protocolSpecsAreCreatedAtBlockDefinedInJson() { + "\"byzantiumBlock\": 1035301}" + "}"; - final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig(jsonInput).getConfigOptions(); final ProtocolSchedule protocolSchedule = CliqueProtocolSchedule.create( config, @@ -91,7 +91,7 @@ public void parametersAlignWithMainnetWithAdjustments() { new ForksSchedule<>(List.of(new ForkSpec<>(0, JsonCliqueConfigOptions.DEFAULT))); final ProtocolSpec homestead = CliqueProtocolSchedule.create( - GenesisConfigFile.DEFAULT.getConfigOptions(), + GenesisConfig.DEFAULT.getConfigOptions(), forksSchedule, NODE_KEY, PrivacyParameters.DEFAULT, @@ -163,7 +163,7 @@ public void shouldValidateBaseFeeMarketTransition() { final String jsonInput = "{\"config\": " + "\t{\"chainId\": 1337,\n" + "\t\"londonBlock\": 2}\n" + "}"; - final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig(jsonInput).getConfigOptions(); final ForksSchedule forksSchedule = new ForksSchedule<>(List.of(new ForkSpec<>(0, JsonCliqueConfigOptions.DEFAULT))); final ProtocolSchedule protocolSchedule = diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java index 0ece2823327..51c55e52935 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueBlockCreatorTest.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.consensus.clique.CliqueBlockInterface; import org.hyperledger.besu.consensus.clique.CliqueContext; import org.hyperledger.besu.consensus.clique.CliqueExtraData; @@ -110,7 +110,7 @@ void setup() { protocolSchedule = CliqueProtocolSchedule.create( - GenesisConfigFile.DEFAULT.getConfigOptions(), + GenesisConfig.DEFAULT.getConfigOptions(), new ForksSchedule<>(List.of()), proposerNodeKey, PrivacyParameters.DEFAULT, @@ -125,7 +125,7 @@ void setup() { CliqueHelpers.setCliqueContext(cliqueContext); final Block genesis = - GenesisState.fromConfig(GenesisConfigFile.mainnet(), protocolSchedule).getBlock(); + GenesisState.fromConfig(GenesisConfig.mainnet(), protocolSchedule).getBlock(); blockchain = createInMemoryBlockchain(genesis); protocolContext = new ProtocolContext(blockchain, stateArchive, cliqueContext, new BadBlockManager()); diff --git a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java index 9c2bf04bce7..cd2130599e5 100644 --- a/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java +++ b/consensus/clique/src/test/java/org/hyperledger/besu/consensus/clique/blockcreation/CliqueMinerExecutorTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.clique.CliqueBlockHeaderFunctions; import org.hyperledger.besu.consensus.clique.CliqueBlockInterface; @@ -74,7 +74,7 @@ public class CliqueMinerExecutorTest { private static final int EPOCH_LENGTH = 10; private static final GenesisConfigOptions GENESIS_CONFIG_OPTIONS = - GenesisConfigFile.fromConfig("{}").getConfigOptions(); + GenesisConfig.fromConfig("{}").getConfigOptions(); private final NodeKey proposerNodeKey = NodeKeyUtils.generate(); private final Random random = new Random(21341234L); private Address localAddress; @@ -154,7 +154,7 @@ public void extraDataCreatedOnEpochBlocksContainsValidators() { } @Test - public void extraDataForNonEpochBlocksDoesNotContainValidaors() { + public void extraDataForNonEpochBlocksDoesNotContainValidators() { final Bytes vanityData = generateRandomVanityData(); final MiningConfiguration miningConfiguration = createMiningConfiguration(vanityData); diff --git a/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java b/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java index 890045bf365..0a848c737cc 100644 --- a/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java +++ b/consensus/common/src/test-support/java/org/hyperledger/besu/consensus/common/bft/BftContextBuilder.java @@ -73,12 +73,20 @@ public static T setupContextWithBftExtraDataEncoder( final Class contextClazz, final Collection
validators, final BftExtraDataCodec bftExtraDataCodec) { + return setupContextWithBftBlockInterface( + contextClazz, validators, new BftBlockInterface(bftExtraDataCodec)); + } + + public static T setupContextWithBftBlockInterface( + final Class contextClazz, + final Collection
validators, + final BftBlockInterface bftBlockInterface) { final T bftContext = mock(contextClazz, withSettings().strictness(Strictness.LENIENT)); final ValidatorProvider mockValidatorProvider = mock(ValidatorProvider.class, withSettings().strictness(Strictness.LENIENT)); when(bftContext.getValidatorProvider()).thenReturn(mockValidatorProvider); when(mockValidatorProvider.getValidatorsAfterBlock(any())).thenReturn(validators); - when(bftContext.getBlockInterface()).thenReturn(new BftBlockInterface(bftExtraDataCodec)); + when(bftContext.getBlockInterface()).thenReturn(bftBlockInterface); when(bftContext.as(any())).thenReturn(bftContext); return bftContext; diff --git a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java index df5a313ae77..a4373b2aa36 100644 --- a/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java +++ b/consensus/ibft/src/test/java/org/hyperledger/besu/consensus/ibft/blockcreation/BftBlockCreatorTest.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.BftConfigOptions; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.consensus.common.ForkSpec; import org.hyperledger.besu.consensus.common.ForksSchedule; @@ -110,8 +110,7 @@ public BlockHeaderValidator.Builder createBlockHeaderRuleset( } }; final GenesisConfigOptions configOptions = - GenesisConfigFile.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}") - .getConfigOptions(); + GenesisConfig.fromConfig("{\"config\": {\"spuriousDragonBlock\":0}}").getConfigOptions(); final ForksSchedule forksSchedule = new ForksSchedule<>(List.of(new ForkSpec<>(0, configOptions.getBftConfigOptions()))); final ProtocolSchedule protocolSchedule = diff --git a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionBackwardSyncContext.java b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionBackwardSyncContext.java index 4f0531a1bc4..37eb53cc58b 100644 --- a/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionBackwardSyncContext.java +++ b/consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/TransitionBackwardSyncContext.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardChain; import org.hyperledger.besu.ethereum.eth.sync.backwardsync.BackwardSyncContext; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; @@ -43,6 +44,7 @@ public class TransitionBackwardSyncContext extends BackwardSyncContext { public TransitionBackwardSyncContext( final ProtocolContext protocolContext, final TransitionProtocolSchedule transitionProtocolSchedule, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final EthContext ethContext, final SyncState syncState, @@ -50,6 +52,7 @@ public TransitionBackwardSyncContext( super( protocolContext, transitionProtocolSchedule, + synchronizerConfiguration, metricsSystem, ethContext, syncState, diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/MergeProtocolScheduleTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/MergeProtocolScheduleTest.java index 2fff61a8299..9bf74d0d085 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/MergeProtocolScheduleTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/MergeProtocolScheduleTest.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.BadBlockManager; @@ -46,7 +46,7 @@ public void protocolSpecsAreCreatedAtBlockDefinedInJson() { + "\"LondonBlock\": 1559}" + "}"; - final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig(jsonInput).getConfigOptions(); final ProtocolSchedule protocolSchedule = MergeProtocolSchedule.create( config, @@ -67,7 +67,7 @@ public void protocolSpecsAreCreatedAtBlockDefinedInJson() { @Test public void mergeSpecificModificationsAreUnappliedForShanghai() { - final GenesisConfigOptions config = GenesisConfigFile.mainnet().getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.mainnet().getConfigOptions(); final ProtocolSchedule protocolSchedule = MergeProtocolSchedule.create( config, @@ -108,7 +108,7 @@ public void mergeSpecificModificationsAreUnappliedForCancun_whenShanghaiNotConfi + "\"cancunTime\": 1000}" + "}"; - final GenesisConfigOptions config = GenesisConfigFile.fromConfig(jsonInput).getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.fromConfig(jsonInput).getConfigOptions(); final ProtocolSchedule protocolSchedule = MergeProtocolSchedule.create( config, @@ -141,7 +141,7 @@ public void mergeSpecificModificationsAreUnappliedForCancun_whenShanghaiNotConfi @Test public void mergeSpecificModificationsAreUnappliedForAllMainnetForksAfterParis() { - final GenesisConfigOptions config = GenesisConfigFile.mainnet().getConfigOptions(); + final GenesisConfigOptions config = GenesisConfig.mainnet().getConfigOptions(); final ProtocolSchedule protocolSchedule = MergeProtocolSchedule.create( config, @@ -178,7 +178,7 @@ public void mergeSpecificModificationsAreUnappliedForAllMainnetForksAfterParis() public void parametersAlignWithMainnetWithAdjustments() { final ProtocolSpec london = MergeProtocolSchedule.create( - GenesisConfigFile.DEFAULT.getConfigOptions(), + GenesisConfig.DEFAULT.getConfigOptions(), false, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java index 90c4b6866e4..ea1fa73eaa5 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeCoordinatorTest.java @@ -132,7 +132,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper { @Mock EthScheduler ethScheduler; - private final Address coinbase = genesisAllocations(getPosGenesisConfigFile()).findFirst().get(); + private final Address coinbase = genesisAllocations(getPosGenesisConfig()).findFirst().get(); private MiningConfiguration miningConfiguration = ImmutableMiningConfiguration.builder() @@ -148,7 +148,7 @@ public class MergeCoordinatorTest implements MergeGenesisConfigHelper { private final ProtocolSchedule protocolSchedule = spy(getMergeProtocolSchedule()); private final GenesisState genesisState = - GenesisState.fromConfig(getPosGenesisConfigFile(), protocolSchedule); + GenesisState.fromConfig(getPosGenesisConfig(), protocolSchedule); private final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java index 582c8c5dd55..49174351cb0 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeGenesisConfigHelper.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.consensus.merge.blockcreation; import org.hyperledger.besu.config.GenesisAccount; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.consensus.merge.MergeProtocolSchedule; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.chain.BadBlockManager; @@ -30,31 +30,31 @@ public interface MergeGenesisConfigHelper { - default GenesisConfigFile getPosGenesisConfigFile() { + default GenesisConfig getPosGenesisConfig() { try { final URI uri = MergeGenesisConfigHelper.class.getResource("/posAtGenesis.json").toURI(); - return GenesisConfigFile.fromSource(uri.toURL()); + return GenesisConfig.fromSource(uri.toURL()); } catch (final URISyntaxException | IOException e) { throw new IllegalStateException(e); } } - default GenesisConfigFile getPowGenesisConfigFile() { + default GenesisConfig getPowGenesisConfig() { try { final URI uri = MergeGenesisConfigHelper.class.getResource("/powAtGenesis.json").toURI(); - return GenesisConfigFile.fromSource(uri.toURL()); + return GenesisConfig.fromSource(uri.toURL()); } catch (final URISyntaxException | IOException e) { throw new IllegalStateException(e); } } - default Stream
genesisAllocations(final GenesisConfigFile configFile) { + default Stream
genesisAllocations(final GenesisConfig configFile) { return configFile.streamAllocations().map(GenesisAccount::address); } default ProtocolSchedule getMergeProtocolSchedule() { return MergeProtocolSchedule.create( - getPosGenesisConfigFile().getConfigOptions(), + getPosGenesisConfig().getConfigOptions(), false, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), diff --git a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java index 22153eeceee..7ec2df35f23 100644 --- a/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java +++ b/consensus/merge/src/test/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeReorgTest.java @@ -70,7 +70,7 @@ public class MergeReorgTest implements MergeGenesisConfigHelper { private final MergeContext mergeContext = PostMergeContext.get(); private final ProtocolSchedule mockProtocolSchedule = getMergeProtocolSchedule(); private final GenesisState genesisState = - GenesisState.fromConfig(getPowGenesisConfigFile(), mockProtocolSchedule); + GenesisState.fromConfig(getPowGenesisConfig(), mockProtocolSchedule); private final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); private final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); @@ -78,7 +78,7 @@ public class MergeReorgTest implements MergeGenesisConfigHelper { private final ProtocolContext protocolContext = new ProtocolContext(blockchain, worldStateArchive, mergeContext, new BadBlockManager()); - private final Address coinbase = genesisAllocations(getPowGenesisConfigFile()).findFirst().get(); + private final Address coinbase = genesisAllocations(getPowGenesisConfig()).findFirst().get(); private final BlockHeaderTestFixture headerGenerator = new BlockHeaderTestFixture(); private final BaseFeeMarket feeMarket = new LondonFeeMarket(0, genesisState.getBlock().getHeader().getBaseFee()); @@ -132,7 +132,7 @@ public void reorgsAcrossTDDToDifferentTargetsWhenNotFinal() { Difficulty tdd = blockchain.getTotalDifficultyByHash(ttdA.getHash()).get(); assertThat(tdd.getAsBigInteger()) .isGreaterThan( - getPosGenesisConfigFile() + getPosGenesisConfig() .getConfigOptions() .getTerminalTotalDifficulty() .get() diff --git a/consensus/qbft-core/build.gradle b/consensus/qbft-core/build.gradle new file mode 100644 index 00000000000..5631f314f9c --- /dev/null +++ b/consensus/qbft-core/build.gradle @@ -0,0 +1,82 @@ +/* + * Copyright 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 + */ + +apply plugin: 'java-library' + +jar { + archiveBaseName = 'besu-qbft-core' + manifest { + attributes( + 'Specification-Title': archiveBaseName, + 'Specification-Version': project.version, + 'Implementation-Title': archiveBaseName, + 'Implementation-Version': calculateVersion(), + 'Commit-Hash': getGitCommitDetails(40).hash + ) + } +} + +dependencies { + implementation project(':config') + implementation project(':consensus:common') + implementation project(':crypto:services') + implementation project(':datatypes') + implementation project(':ethereum:blockcreation') + implementation project(':ethereum:core') + implementation project(':ethereum:eth') + implementation project(':ethereum:p2p') + implementation project(':ethereum:rlp') + implementation project(':evm') + + implementation 'com.google.guava:guava' + implementation 'io.tmio:tuweni-bytes' + + integrationTestImplementation project(path: ':config', configuration: 'testSupportArtifacts') + integrationTestImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') + + testImplementation project(path: ':crypto:services', configuration: 'testSupportArtifacts') + testImplementation project(path: ':config', configuration: 'testSupportArtifacts') + testImplementation project(path: ':consensus:common', configuration: 'testArtifacts') + testImplementation project(path: ':consensus:common', configuration: 'testSupportArtifacts') + testImplementation project(':ethereum:core') + testImplementation project(path: ':ethereum:core', configuration: 'testSupportArtifacts') + testImplementation project(':crypto:algorithms') + testImplementation project(':evm') + testImplementation project(':metrics:core') + testImplementation project(':testutil') + + testImplementation 'org.assertj:assertj-core' + testImplementation 'org.awaitility:awaitility' + testImplementation 'org.junit.jupiter:junit-jupiter' + testImplementation 'org.mockito:mockito-core' + testImplementation 'org.mockito:mockito-junit-jupiter' + + integrationTestImplementation project(':crypto:algorithms') + integrationTestImplementation project(path: ':crypto:services', configuration: 'testSupportArtifacts') + integrationTestImplementation project(path: ':consensus:common', configuration: 'testSupportArtifacts') + integrationTestImplementation project(':consensus:qbft') + integrationTestImplementation project(':evm') + integrationTestImplementation project(':metrics:core') + integrationTestImplementation project(':testutil') + + integrationTestImplementation 'org.assertj:assertj-core' + integrationTestImplementation 'org.junit.jupiter:junit-jupiter-api' + integrationTestImplementation 'org.mockito:mockito-core' + integrationTestImplementation 'org.mockito:mockito-junit-jupiter' + + integrationTestRuntimeOnly 'org.junit.jupiter:junit-jupiter' + + testSupportImplementation 'org.mockito:mockito-core' +} diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/IntegrationTestHelpers.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/IntegrationTestHelpers.java similarity index 90% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/IntegrationTestHelpers.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/IntegrationTestHelpers.java index 4a9f8e7057a..390302eb880 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/IntegrationTestHelpers.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/IntegrationTestHelpers.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.support; +package org.hyperledger.besu.consensus.qbft.core.support; import org.hyperledger.besu.consensus.common.bft.BftBlockHashing; import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; @@ -20,9 +20,9 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.payload.CommitPayload; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/RoundSpecificPeers.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/RoundSpecificPeers.java similarity index 91% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/RoundSpecificPeers.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/RoundSpecificPeers.java index dc35796d0dc..afa07b31a4d 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/RoundSpecificPeers.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/RoundSpecificPeers.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.support; +package org.hyperledger.besu.consensus.qbft.core.support; import static java.util.Optional.empty; import static org.assertj.core.api.Assertions.assertThat; @@ -23,15 +23,15 @@ import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.Payload; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagedata.CommitMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.PrepareMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContext.java similarity index 82% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContext.java index 10cdfa91501..0a65d03bcd3 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContext.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContext.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.support; +package org.hyperledger.besu.consensus.qbft.core.support; import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; import org.hyperledger.besu.consensus.common.bft.BftExecutors; @@ -23,7 +23,7 @@ import org.hyperledger.besu.consensus.common.bft.statemachine.BftEventHandler; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; @@ -97,13 +97,37 @@ public MessageFactory getLocalNodeMessageFactory() { } public Block createBlockForProposalFromChainHead(final long timestamp) { - return createBlockForProposalFromChainHead(timestamp, finalState.getLocalAddress()); + return createBlockForProposalFromChainHead(timestamp, finalState.getLocalAddress(), 0); + } + + public Block createBlockForProposalFromChainHead(final long timestamp, final int roundNumber) { + return createBlockForProposalFromChainHead( + timestamp, finalState.getLocalAddress(), roundNumber); + } + + public Block createBlockForProposalFromChainHead(final long timestamp, final Address proposer) { + // this implies that EVERY block will have this node as the proposer :/ + return createBlockForProposal(blockchain.getChainHeadHeader(), timestamp, proposer, 0); + } + + public Block createBlockForProposalFromChainHead( + final long timestamp, final Address proposer, final int roundNumber) { + // this implies that EVERY block will have this node as the proposer :/ + return createBlockForProposal( + blockchain.getChainHeadHeader(), timestamp, proposer, roundNumber); } public Block createBlockForProposal( - final BlockHeader parent, final long timestamp, final Address proposer) { + final BlockHeader parent, + final long timestamp, + final Address proposer, + final int roundNumber) { final Block block = - finalState.getBlockCreatorFactory().create(0).createBlock(timestamp, parent).getBlock(); + finalState + .getBlockCreatorFactory() + .create(roundNumber) + .createBlock(timestamp, parent) + .getBlock(); final BlockHeaderBuilder headerBuilder = BlockHeaderBuilder.fromHeader(block.getHeader()); headerBuilder @@ -114,9 +138,9 @@ public Block createBlockForProposal( return new Block(newHeader, block.getBody()); } - public Block createBlockForProposalFromChainHead(final long timestamp, final Address proposer) { - // this implies that EVERY block will have this node as the proposer :/ - return createBlockForProposal(blockchain.getChainHeadHeader(), timestamp, proposer); + public Block createBlockForProposal( + final BlockHeader parent, final long timestamp, final Address proposer) { + return createBlockForProposal(parent, timestamp, proposer, 0); } public RoundSpecificPeers roundSpecificPeers(final ConsensusRoundIdentifier roundId) { diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java similarity index 96% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java index cc7066f17ee..29d65eda0b6 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/TestContextBuilder.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/TestContextBuilder.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.support; +package org.hyperledger.besu.consensus.qbft.core.support; import static java.nio.charset.StandardCharsets.UTF_8; import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain; @@ -23,7 +23,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.BftFork; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.JsonQbftConfigOptions; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.config.QbftConfigOptions; @@ -64,18 +64,18 @@ import org.hyperledger.besu.consensus.qbft.MutableQbftConfigOptions; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; import org.hyperledger.besu.consensus.qbft.QbftForksSchedulesFactory; -import org.hyperledger.besu.consensus.qbft.QbftGossip; import org.hyperledger.besu.consensus.qbft.QbftProtocolScheduleBuilder; import org.hyperledger.besu.consensus.qbft.blockcreation.QbftBlockCreatorFactory; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftBlockHeightManagerFactory; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftController; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftRoundFactory; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftBlockHeightManagerFactory; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftController; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftRoundFactory; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger; import org.hyperledger.besu.consensus.qbft.validator.ForkingValidatorProvider; import org.hyperledger.besu.consensus.qbft.validator.TransactionValidatorProvider; import org.hyperledger.besu.consensus.qbft.validator.ValidatorContractController; -import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -367,7 +367,7 @@ private static Block createGenesisBlock(final Set
validators) { private GenesisState createGenesisBlock(final String genesisFile) throws IOException { return GenesisState.fromConfig( - GenesisConfigFile.fromSource(Path.of(genesisFile).toUri().toURL()), + GenesisConfig.fromSource(Path.of(genesisFile).toUri().toURL()), ProtocolScheduleFixture.MAINNET); } @@ -387,7 +387,7 @@ private static ControllerAndState createControllerAndFinalState( final boolean useFixedBaseFee, final List qbftForks) { - final MiningConfiguration miningParams = + final MiningConfiguration miningConfiguration = ImmutableMiningConfiguration.builder() .mutableInitValues( MutableInitValues.builder() @@ -445,7 +445,8 @@ private static ControllerAndState createControllerAndFinalState( final BftValidatorOverrides validatorOverrides = convertBftForks(qbftForks); final TransactionSimulator transactionSimulator = - new TransactionSimulator(blockChain, worldStateArchive, protocolSchedule, 0L); + new TransactionSimulator( + blockChain, worldStateArchive, protocolSchedule, miningConfiguration, 0L); final BlockValidatorProvider blockValidatorProvider = BlockValidatorProvider.forkingValidatorProvider( @@ -496,7 +497,7 @@ private static ControllerAndState createControllerAndFinalState( protocolContext, protocolSchedule, forksSchedule, - miningParams, + miningConfiguration, localAddress, BFT_EXTRA_DATA_ENCODER, ethScheduler); diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/ValidatorPeer.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/ValidatorPeer.java similarity index 76% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/ValidatorPeer.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/ValidatorPeer.java index af764bfed72..a4e482c7a1b 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/support/ValidatorPeer.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/support/ValidatorPeer.java @@ -12,27 +12,27 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.support; +package org.hyperledger.besu.consensus.qbft.core.support; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createCommitBlockFromProposalBlock; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createCommitBlockFromProposalBlock; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.EventMultiplexer; import org.hyperledger.besu.consensus.common.bft.inttest.DefaultValidatorPeer; import org.hyperledger.besu.consensus.common.bft.inttest.NodeParams; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagedata.CommitMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.PrepareMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/FutureHeightTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/FutureHeightTest.java similarity index 94% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/FutureHeightTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/FutureHeightTest.java index 811899bc7f5..a8438d3c01e 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/FutureHeightTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/FutureHeightTest.java @@ -12,23 +12,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.util.Lists.emptyList; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createSignedCommitPayload; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createSignedCommitPayload; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.events.NewChainHead; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; import org.hyperledger.besu.ethereum.core.Block; import java.time.Clock; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/FutureRoundTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/FutureRoundTest.java similarity index 89% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/FutureRoundTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/FutureRoundTest.java index 9681ca4f7d6..c2920619e46 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/FutureRoundTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/FutureRoundTest.java @@ -12,22 +12,22 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createCommitBlockFromProposalBlock; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createCommitBlockFromProposalBlock; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/GossipTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/GossipTest.java similarity index 88% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/GossipTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/GossipTest.java index fbe98de6b79..acafe66a055 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/GossipTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/GossipTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static java.util.Collections.emptyList; @@ -20,16 +20,16 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.events.NewChainHead; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; -import org.hyperledger.besu.consensus.qbft.support.ValidatorPeer; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/LocalNodeIsProposerTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/LocalNodeIsProposerTest.java similarity index 90% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/LocalNodeIsProposerTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/LocalNodeIsProposerTest.java index e5885d96a4f..85896bda3e4 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/LocalNodeIsProposerTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/LocalNodeIsProposerTest.java @@ -12,22 +12,22 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createSignedCommitPayload; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createSignedCommitPayload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry; import org.hyperledger.besu.consensus.common.bft.events.NewChainHead; import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; import org.hyperledger.besu.ethereum.core.Block; import java.time.Clock; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/LocalNodeNotProposerTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/LocalNodeNotProposerTest.java similarity index 89% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/LocalNodeNotProposerTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/LocalNodeNotProposerTest.java index 9d386178686..16cc4f87807 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/LocalNodeNotProposerTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/LocalNodeNotProposerTest.java @@ -12,18 +12,18 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createSignedCommitPayload; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createSignedCommitPayload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; import org.hyperledger.besu.ethereum.core.Block; import org.junit.jupiter.api.BeforeEach; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/ReceivedFutureProposalTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/ReceivedFutureProposalTest.java similarity index 90% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/ReceivedFutureProposalTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/ReceivedFutureProposalTest.java index 77b33ad2adc..260e996c223 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/ReceivedFutureProposalTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/ReceivedFutureProposalTest.java @@ -12,23 +12,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createValidPreparedCertificate; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createValidPreparedCertificate; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; -import org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; -import org.hyperledger.besu.consensus.qbft.support.ValidatorPeer; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer; import org.hyperledger.besu.ethereum.core.Block; import java.util.Collections; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/RoundChangeTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/RoundChangeTest.java similarity index 91% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/RoundChangeTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/RoundChangeTest.java index be439e4c1ec..79761b10064 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/RoundChangeTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/RoundChangeTest.java @@ -12,27 +12,27 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static java.util.Collections.emptyList; import static java.util.Optional.empty; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createValidPreparedCertificate; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createValidPreparedCertificate; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.events.BlockTimerExpiry; import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; -import org.hyperledger.besu.consensus.qbft.support.ValidatorPeer; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer; import org.hyperledger.besu.ethereum.core.Block; import java.time.Clock; @@ -144,7 +144,8 @@ public void roundChangeHasPopulatedCertificateIfQuorumPrepareMessagesAndProposal public void whenSufficientRoundChangeMessagesAreReceivedForNewRoundLocalNodeCreatesProposalMsg() { // Note: Round-4 is the next round for which the local node is Proposer final ConsensusRoundIdentifier targetRound = new ConsensusRoundIdentifier(1, 4); - final Block locallyProposedBlock = context.createBlockForProposalFromChainHead(blockTimeStamp); + final Block locallyProposedBlock = + context.createBlockForProposalFromChainHead(blockTimeStamp, 4); final RoundChange rc1 = peers.getNonProposing(0).injectRoundChange(targetRound, empty()); final RoundChange rc2 = peers.getNonProposing(1).injectRoundChange(targetRound, empty()); @@ -177,14 +178,14 @@ public void proposalMessageContainsBlockOnWhichPeerPrepared() { context, new ConsensusRoundIdentifier(1, 1), context.createBlockForProposalFromChainHead( - ARBITRARY_BLOCKTIME / 2, peers.getProposer().getNodeAddress())); + ARBITRARY_BLOCKTIME / 2, peers.getProposer().getNodeAddress(), 1)); final PreparedCertificate bestPrepCert = createValidPreparedCertificate( context, new ConsensusRoundIdentifier(1, 2), context.createBlockForProposalFromChainHead( - ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress())); + ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress(), 2)); final ConsensusRoundIdentifier targetRound = new ConsensusRoundIdentifier(1, 4); @@ -206,7 +207,7 @@ public void proposalMessageContainsBlockOnWhichPeerPrepared() { // round number. final Block expectedBlockToPropose = context.createBlockForProposalFromChainHead( - ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress()); + ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress(), 4); final Proposal expectedProposal = localNodeMessageFactory.createProposal( @@ -234,7 +235,8 @@ public void cannotRoundChangeToAnEarlierRound() { final ConsensusRoundIdentifier priorRound = new ConsensusRoundIdentifier(1, 4); peers.roundChange(priorRound); - final Block locallyProposedBlock = context.createBlockForProposalFromChainHead(blockTimeStamp); + final Block locallyProposedBlock = + context.createBlockForProposalFromChainHead(blockTimeStamp, 9); final Proposal expectedProposal = localNodeMessageFactory.createProposal( @@ -271,7 +273,7 @@ public void subsequentRoundChangeMessagesFromPeerDoNotOverwritePriorMessage() { context, new ConsensusRoundIdentifier(1, 2), context.createBlockForProposalFromChainHead( - ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress())); + ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress(), 2)); final List> roundChangeMessages = Lists.newArrayList(); // Create a roundChange containing a PreparedCertificate @@ -288,7 +290,7 @@ public void subsequentRoundChangeMessagesFromPeerDoNotOverwritePriorMessage() { final Block expectedBlockToPropose = context.createBlockForProposalFromChainHead( - ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress()); + ARBITRARY_BLOCKTIME, peers.getProposer().getNodeAddress(), 4); final Proposal expectedProposal = localNodeMessageFactory.createProposal( diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/SpuriousBehaviourTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/SpuriousBehaviourTest.java similarity index 88% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/SpuriousBehaviourTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/SpuriousBehaviourTest.java index 8f1bfb9a7fd..a18a885bafd 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/SpuriousBehaviourTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/SpuriousBehaviourTest.java @@ -12,21 +12,21 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.qbft.support.IntegrationTestHelpers.createSignedCommitPayload; +import static org.hyperledger.besu.consensus.qbft.core.support.IntegrationTestHelpers.createSignedCommitPayload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.inttest.NodeParams; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; -import org.hyperledger.besu.consensus.qbft.support.ValidatorPeer; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/TransitionsTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/TransitionsTest.java similarity index 93% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/TransitionsTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/TransitionsTest.java index 93268ab1b81..1c57e532b33 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/TransitionsTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/TransitionsTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static org.assertj.core.api.Assertions.assertThat; @@ -21,8 +21,8 @@ import org.hyperledger.besu.config.QbftFork; import org.hyperledger.besu.consensus.common.bft.BftEventQueue; import org.hyperledger.besu.consensus.common.bft.events.NewChainHead; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.testutil.TestClock; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/ValidatorContractTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/ValidatorContractTest.java similarity index 98% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/ValidatorContractTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/ValidatorContractTest.java index c5978560065..4ab147989e3 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/ValidatorContractTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/ValidatorContractTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test; +package org.hyperledger.besu.consensus.qbft.core.test; import static java.time.temporal.ChronoUnit.SECONDS; import static org.assertj.core.api.Assertions.assertThat; @@ -27,10 +27,10 @@ import org.hyperledger.besu.consensus.common.bft.inttest.NodeParams; import org.hyperledger.besu.consensus.common.validator.ValidatorProvider; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.support.RoundSpecificPeers; -import org.hyperledger.besu.consensus.qbft.support.TestContext; -import org.hyperledger.besu.consensus.qbft.support.TestContextBuilder; -import org.hyperledger.besu.consensus.qbft.support.ValidatorPeer; +import org.hyperledger.besu.consensus.qbft.core.support.RoundSpecificPeers; +import org.hyperledger.besu.consensus.qbft.core.support.TestContext; +import org.hyperledger.besu.consensus.qbft.core.support.TestContextBuilder; +import org.hyperledger.besu.consensus.qbft.core.support.ValidatorPeer; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/round/QbftRoundIntegrationTest.java similarity index 95% rename from consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java rename to consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/round/QbftRoundIntegrationTest.java index 7dcca442a7f..e93b2e7f40e 100644 --- a/consensus/qbft/src/integration-test/java/org/hyperledger/besu/consensus/qbft/test/round/QbftRoundIntegrationTest.java +++ b/consensus/qbft-core/src/integration-test/java/org/hyperledger/besu/consensus/qbft/core/test/round/QbftRoundIntegrationTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.test.round; +package org.hyperledger.besu.consensus.qbft.core.test.round; import static java.util.Collections.emptyList; import static java.util.Optional.empty; @@ -32,11 +32,11 @@ import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator; import org.hyperledger.besu.consensus.common.bft.inttest.StubValidatorMulticaster; import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.network.QbftMessageTransmitter; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.statemachine.QbftRound; -import org.hyperledger.besu.consensus.qbft.statemachine.RoundState; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidator; +import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.statemachine.QbftRound; +import org.hyperledger.besu.consensus.qbft.core.statemachine.RoundState; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.cryptoservices.NodeKey; diff --git a/consensus/qbft/src/integration-test/resources/genesis_migrating_validator_contract.json b/consensus/qbft-core/src/integration-test/resources/genesis_migrating_validator_contract.json similarity index 100% rename from consensus/qbft/src/integration-test/resources/genesis_migrating_validator_contract.json rename to consensus/qbft-core/src/integration-test/resources/genesis_migrating_validator_contract.json diff --git a/consensus/qbft/src/integration-test/resources/genesis_validator_contract.json b/consensus/qbft-core/src/integration-test/resources/genesis_validator_contract.json similarity index 100% rename from consensus/qbft/src/integration-test/resources/genesis_validator_contract.json rename to consensus/qbft-core/src/integration-test/resources/genesis_validator_contract.json diff --git a/consensus/qbft/src/integration-test/resources/genesis_validator_contract_london.json b/consensus/qbft-core/src/integration-test/resources/genesis_validator_contract_london.json similarity index 100% rename from consensus/qbft/src/integration-test/resources/genesis_validator_contract_london.json rename to consensus/qbft-core/src/integration-test/resources/genesis_validator_contract_london.json diff --git a/consensus/qbft/src/integration-test/resources/genesis_validator_contract_shanghai.json b/consensus/qbft-core/src/integration-test/resources/genesis_validator_contract_shanghai.json similarity index 100% rename from consensus/qbft/src/integration-test/resources/genesis_validator_contract_shanghai.json rename to consensus/qbft-core/src/integration-test/resources/genesis_validator_contract_shanghai.json diff --git a/consensus/qbft/src/integration-test/resources/log4j2.xml b/consensus/qbft-core/src/integration-test/resources/log4j2.xml similarity index 100% rename from consensus/qbft/src/integration-test/resources/log4j2.xml rename to consensus/qbft-core/src/integration-test/resources/log4j2.xml diff --git a/consensus/qbft/src/integration-test/resources/validator_contract.sol b/consensus/qbft-core/src/integration-test/resources/validator_contract.sol similarity index 100% rename from consensus/qbft/src/integration-test/resources/validator_contract.sol rename to consensus/qbft-core/src/integration-test/resources/validator_contract.sol diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/CommitMessageData.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/CommitMessageData.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/CommitMessageData.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/CommitMessageData.java index c0e8c537cd6..f39c3e66e19 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/CommitMessageData.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/CommitMessageData.java @@ -12,10 +12,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagedata; +package org.hyperledger.besu.consensus.qbft.core.messagedata; import org.hyperledger.besu.consensus.common.bft.messagedata.AbstractBftMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import org.apache.tuweni.bytes.Bytes; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/PrepareMessageData.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/PrepareMessageData.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/PrepareMessageData.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/PrepareMessageData.java index 30ed2e33dac..564468cfe6e 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/PrepareMessageData.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/PrepareMessageData.java @@ -12,10 +12,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagedata; +package org.hyperledger.besu.consensus.qbft.core.messagedata; import org.hyperledger.besu.consensus.common.bft.messagedata.AbstractBftMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import org.apache.tuweni.bytes.Bytes; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/ProposalMessageData.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/ProposalMessageData.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/ProposalMessageData.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/ProposalMessageData.java index 28d8c8d82e9..e474c5cfd86 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/ProposalMessageData.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/ProposalMessageData.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagedata; +package org.hyperledger.besu.consensus.qbft.core.messagedata; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.messagedata.AbstractBftMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import org.apache.tuweni.bytes.Bytes; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/QbftV1.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/QbftV1.java similarity index 94% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/QbftV1.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/QbftV1.java index ef42312b37a..a598308b39c 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/QbftV1.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/QbftV1.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagedata; +package org.hyperledger.besu.consensus.qbft.core.messagedata; /** Message codes for QBFT v1 messages */ public interface QbftV1 { diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/RoundChangeMessageData.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/RoundChangeMessageData.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/RoundChangeMessageData.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/RoundChangeMessageData.java index 6b017b0a1a2..37ebe4c0a2a 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagedata/RoundChangeMessageData.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagedata/RoundChangeMessageData.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagedata; +package org.hyperledger.besu.consensus.qbft.core.messagedata; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.messagedata.AbstractBftMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import org.apache.tuweni.bytes.Bytes; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Commit.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Commit.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Commit.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Commit.java index 5745f7af9de..142069ec708 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Commit.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Commit.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.CommitPayload; +import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.rlp.RLP; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Prepare.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Prepare.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Prepare.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Prepare.java index 2ffd0bf180f..28bcae7bf80 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Prepare.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Prepare.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPInput; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Proposal.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Proposal.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java index 8650a9c6b66..20847236f14 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/Proposal.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/Proposal.java @@ -12,14 +12,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.ProposalPayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.ProposalPayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.RLP; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChange.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChange.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java index cbebdf7debd..945a4bafb63 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChange.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChange.java @@ -12,15 +12,15 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.RLP; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftGossip.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftGossip.java similarity index 87% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftGossip.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftGossip.java index d0965e11620..c2ebf480a79 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/QbftGossip.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftGossip.java @@ -12,17 +12,17 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft; +package org.hyperledger.besu.consensus.qbft.core.network; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.Gossiper; import org.hyperledger.besu.consensus.common.bft.network.ValidatorMulticaster; import org.hyperledger.besu.consensus.common.bft.payload.Authored; -import org.hyperledger.besu.consensus.qbft.messagedata.CommitMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.PrepareMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/network/QbftMessageTransmitter.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java similarity index 82% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/network/QbftMessageTransmitter.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java index 7c5b93c24a7..5aaa4887fe0 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/network/QbftMessageTransmitter.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/network/QbftMessageTransmitter.java @@ -12,23 +12,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.network; +package org.hyperledger.besu.consensus.qbft.core.network; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.network.ValidatorMulticaster; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagedata.CommitMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.PrepareMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/CommitPayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java similarity index 96% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/CommitPayload.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java index 716417922c4..824bd063bd6 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/CommitPayload.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/CommitPayload.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.Payload; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Hash; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/MessageFactory.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java similarity index 90% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/MessageFactory.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java index 860a4c9c418..c359c7ef597 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/MessageFactory.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/MessageFactory.java @@ -12,16 +12,16 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.Payload; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.datatypes.Hash; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparePayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java similarity index 96% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparePayload.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java index b0198058e45..58470b2a4d6 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparePayload.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparePayload.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.Payload; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparedRoundMetadata.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparedRoundMetadata.java similarity index 98% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparedRoundMetadata.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparedRoundMetadata.java index 5e534a7178c..4b732d1551b 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/PreparedRoundMetadata.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/PreparedRoundMetadata.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.rlp.RLPInput; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/ProposalPayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java similarity index 96% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/ProposalPayload.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java index 3bbe48dec0f..81a5caa2d94 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/ProposalPayload.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/ProposalPayload.java @@ -12,12 +12,12 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/QbftPayload.java similarity index 97% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayload.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/QbftPayload.java index 4cc64e9d0d0..57faa3225fb 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayload.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/QbftPayload.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.Payload; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/RoundChangePayload.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java similarity index 96% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/RoundChangePayload.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java index f40e0464c32..9f4d9abedbd 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/payload/RoundChangePayload.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/payload/RoundChangePayload.java @@ -12,10 +12,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.ethereum.rlp.RLPInput; import org.hyperledger.besu.ethereum.rlp.RLPOutput; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/BaseQbftBlockHeightManager.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/BaseQbftBlockHeightManager.java similarity index 79% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/BaseQbftBlockHeightManager.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/BaseQbftBlockHeightManager.java index 6f1cca0d350..b426263c25b 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/BaseQbftBlockHeightManager.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/BaseQbftBlockHeightManager.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.statemachine.BaseBlockHeightManager; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; /** The interface Base qbft block height manager. */ public interface BaseQbftBlockHeightManager extends BaseBlockHeightManager { diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/NoOpBlockHeightManager.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/NoOpBlockHeightManager.java similarity index 83% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/NoOpBlockHeightManager.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/NoOpBlockHeightManager.java index ae5bde0e9a2..4ad83333d6c 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/NoOpBlockHeightManager.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/NoOpBlockHeightManager.java @@ -12,14 +12,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; import org.hyperledger.besu.ethereum.core.BlockHeader; /** The type NoOp block height manager. */ diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/PreparedCertificate.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/PreparedCertificate.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/PreparedCertificate.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/PreparedCertificate.java index 3b5a8df848a..aa72d62fef0 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/PreparedCertificate.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/PreparedCertificate.java @@ -12,10 +12,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; import org.hyperledger.besu.ethereum.core.Block; import java.util.List; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManager.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManager.java similarity index 95% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManager.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManager.java index 757998b5ca6..2c7e55cbf66 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManager.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManager.java @@ -12,21 +12,21 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.Payload; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.network.QbftMessageTransmitter; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.validation.FutureRoundProposalMessageValidator; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.validation.FutureRoundProposalMessageValidator; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerFactory.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerFactory.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerFactory.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerFactory.java index 889f83f98a7..679ef222eb6 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerFactory.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerFactory.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory; -import org.hyperledger.besu.consensus.qbft.validator.ValidatorModeTransitionLogger; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.slf4j.Logger; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftController.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftController.java similarity index 90% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftController.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftController.java index 57737542eaf..4944aba53bc 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftController.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftController.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.Gossiper; @@ -22,11 +22,11 @@ import org.hyperledger.besu.consensus.common.bft.statemachine.BaseBlockHeightManager; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer; -import org.hyperledger.besu.consensus.qbft.messagedata.CommitMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.PrepareMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java index e0a8cb1c726..6a7ce1042a7 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRound.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRound.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import static java.util.Collections.emptyList; @@ -26,13 +26,13 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.RoundTimer; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.network.QbftMessageTransmitter; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.datatypes.Hash; @@ -160,9 +160,18 @@ public void startRoundWith( } else { LOG.debug( "Sending proposal from PreparedCertificate. round={}", roundState.getRoundIdentifier()); - blockToPublish = bestPreparedCertificate.get().getBlock(); + Block preparedBlock = bestPreparedCertificate.get().getBlock(); + final BftBlockInterface bftBlockInterface = + protocolContext.getConsensusContext(BftContext.class).getBlockInterface(); + blockToPublish = + bftBlockInterface.replaceRoundInBlock( + preparedBlock, + roundState.getRoundIdentifier().getRoundNumber(), + BftBlockHeaderFunctions.forCommittedSeal(bftExtraDataCodec)); } + LOG.debug(" proposal - new/prepared block hash : {}", blockToPublish.getHash()); + updateStateWithProposalAndTransmit( blockToPublish, roundChangeArtifacts.getRoundChanges(), @@ -202,8 +211,9 @@ protected void updateStateWithProposalAndTransmit( proposal.getSignedPayload().getPayload().getProposedBlock(), roundChanges, prepares); - updateStateWithProposedBlock(proposal); - sendPrepare(block); + if (updateStateWithProposedBlock(proposal)) { + sendPrepare(block); + } } /** diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java similarity index 91% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java index 30253300096..ca57b50baa5 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundFactory.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundFactory.java @@ -12,16 +12,16 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreatorFactory; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; -import org.hyperledger.besu.consensus.qbft.network.QbftMessageTransmitter; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.blockcreation.BlockCreator; import org.hyperledger.besu.ethereum.chain.MinedBlockObserver; @@ -99,7 +99,8 @@ public QbftRound createNewRound(final BlockHeader parentHeader, final int round) */ public QbftRound createNewRoundWithState( final BlockHeader parentHeader, final RoundState roundState) { - final BlockCreator blockCreator = blockCreatorFactory.create(0); + final BlockCreator blockCreator = + blockCreatorFactory.create(roundState.getRoundIdentifier().getRoundNumber()); // TODO(tmm): Why is this created everytime?! final QbftMessageTransmitter messageTransmitter = diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundChangeArtifacts.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundChangeArtifacts.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundChangeArtifacts.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundChangeArtifacts.java index 322d6990ac4..773ff06ef25 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundChangeArtifacts.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundChangeArtifacts.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import java.util.Collection; import java.util.Comparator; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundChangeManager.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundChangeManager.java similarity index 96% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundChangeManager.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundChangeManager.java index 89e2888395c..aa4f605c7c5 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundChangeManager.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundChangeManager.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.validation.RoundChangeMessageValidator; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.validation.RoundChangeMessageValidator; import org.hyperledger.besu.datatypes.Address; import java.util.Collection; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundState.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundState.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java index 6acbae56558..d9a9221e4a3 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundState.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundState.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidator; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java similarity index 94% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java index 35e49dbb171..e211c6a8ede 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidator.java @@ -12,12 +12,12 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.payload.CommitPayload; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Util; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/FutureRoundProposalMessageValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/FutureRoundProposalMessageValidator.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/FutureRoundProposalMessageValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/FutureRoundProposalMessageValidator.java index 3c401bb203c..dd585c26fda 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/FutureRoundProposalMessageValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/FutureRoundProposalMessageValidator.java @@ -12,10 +12,10 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; import org.hyperledger.besu.ethereum.core.BlockHeader; /** The Future round proposal message validator. */ diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/MessageValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/MessageValidator.java similarity index 94% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/MessageValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/MessageValidator.java index ac112baa051..f526f2b7a3a 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/MessageValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/MessageValidator.java @@ -12,15 +12,15 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.BftBlockHeaderFunctions; import org.hyperledger.besu.consensus.common.bft.BftBlockInterface; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/MessageValidatorFactory.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/MessageValidatorFactory.java similarity index 97% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/MessageValidatorFactory.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/MessageValidatorFactory.java index b5164746bf6..17795acfb21 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/MessageValidatorFactory.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/MessageValidatorFactory.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.BftBlockInterface; import org.hyperledger.besu.consensus.common.bft.BftContext; @@ -21,7 +21,7 @@ import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.blockcreation.ProposerSelector; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidator.SubsequentMessageValidator; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator.SubsequentMessageValidator; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PrepareValidator.java similarity index 92% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PrepareValidator.java index 54fbaef855f..61bde6a802d 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/PrepareValidator.java @@ -12,12 +12,12 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidator.java similarity index 96% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidator.java index 3d04f699c04..a50f2c79345 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidator.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static com.google.common.base.Preconditions.checkState; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.ProposalPayload; +import org.hyperledger.besu.consensus.qbft.core.payload.ProposalPayload; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.BlockValidator; import org.hyperledger.besu.ethereum.ProtocolContext; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidator.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidator.java index 81cbffdff96..094521133cd 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidator.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static org.hyperledger.besu.consensus.common.bft.validation.ValidationHelpers.hasDuplicateAuthors; import static org.hyperledger.besu.consensus.common.bft.validation.ValidationHelpers.hasSufficientEntries; @@ -24,10 +24,10 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.Payload; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.BlockValidator; @@ -137,6 +137,13 @@ private boolean validateProposalAndRoundChangeAreConsistent(final Proposal propo final PreparedRoundMetadata metadata = roundChangeWithLatestPreparedRound.get().getPayload().getPreparedRoundMetadata().get(); + LOG.debug( + "Prepared Metadata blockhash : {}, proposal blockhash: {}, prepared round in message: {}, proposal round in message: {}", + metadata.getPreparedBlockHash(), + proposal.getBlock().getHash(), + metadata.getPreparedRound(), + proposal.getRoundIdentifier().getRoundNumber()); + // The Hash in the roundchange/proposals is NOT the same as the value in the // prepares/roundchanges // as said payloads reference the block with an OLD round number in it - therefore, need @@ -155,8 +162,10 @@ private boolean validateProposalAndRoundChangeAreConsistent(final Proposal propo if (!metadata.getPreparedBlockHash().equals(expectedPriorBlockHash)) { LOG.info( - "{}: Latest Prepared Metadata blockhash does not align with proposed block", - ERROR_PREFIX); + "{}: Latest Prepared Metadata blockhash does not align with proposed block. Expected: {}, Actual: {}", + ERROR_PREFIX, + expectedPriorBlockHash, + metadata.getPreparedBlockHash()); return false; } diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidator.java similarity index 94% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidator.java index 0f0761d4621..1420c32c418 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidator.java @@ -12,16 +12,16 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static org.hyperledger.besu.consensus.common.bft.validation.ValidationHelpers.hasDuplicateAuthors; import static org.hyperledger.besu.consensus.common.bft.validation.ValidationHelpers.hasSufficientEntries; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.BlockValidator; import org.hyperledger.besu.ethereum.ProtocolContext; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidator.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java similarity index 93% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidator.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java index 18977bf2902..549acdd9c55 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidator.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidator.java @@ -12,11 +12,11 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.datatypes.Address; import java.util.Collection; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLogger.java b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validator/ValidatorModeTransitionLogger.java similarity index 98% rename from consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLogger.java rename to consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validator/ValidatorModeTransitionLogger.java index 83c18262c66..8265959ef63 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLogger.java +++ b/consensus/qbft-core/src/main/java/org/hyperledger/besu/consensus/qbft/core/validator/ValidatorModeTransitionLogger.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validator; +package org.hyperledger.besu.consensus.qbft.core.validator; import org.hyperledger.besu.config.QbftConfigOptions; import org.hyperledger.besu.consensus.common.ForkSpec; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/CommitTest.java similarity index 91% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/CommitTest.java index 87d3a46abe5..11cc9cbeb41 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/CommitTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/CommitTest.java @@ -12,14 +12,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.payload.CommitPayload; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.payload.CommitPayload; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/PrepareTest.java similarity index 90% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/PrepareTest.java index 0aed7ed554e..adff617af1c 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/PrepareTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/PrepareTest.java @@ -12,14 +12,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java similarity index 79% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java index 5b7314f94a2..52946270031 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/ProposalTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/ProposalTest.java @@ -12,20 +12,18 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.ProposalPayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.ProposalPayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; @@ -38,19 +36,18 @@ import java.util.List; import java.util.Optional; -import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) public class ProposalTest { - private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - - private static final BftExtraData extraData = - new BftExtraData( - Bytes32.ZERO, Collections.emptyList(), Optional.empty(), 1, Collections.emptyList()); + @Mock private BftExtraDataCodec bftExtraDataCodec; private static final Block BLOCK = new Block( - new BlockHeaderTestFixture().extraData(bftExtraDataCodec.encode(extraData)).buildHeader(), + new BlockHeaderTestFixture().buildHeader(), new BlockBody( Collections.emptyList(), Collections.emptyList(), diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java similarity index 82% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java index 23de31417c6..1f38cb787eb 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/messagewrappers/RoundChangeTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/messagewrappers/RoundChangeTest.java @@ -12,19 +12,17 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.messagewrappers; +package org.hyperledger.besu.consensus.qbft.core.messagewrappers; import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.consensus.common.bft.BftExtraData; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; @@ -37,20 +35,18 @@ import java.util.List; import java.util.Optional; -import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +@ExtendWith(MockitoExtension.class) public class RoundChangeTest { - private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - private static final BftExtraData extraData = - new BftExtraData( - Bytes32.ZERO, Collections.emptyList(), Optional.empty(), 1, Collections.emptyList()); + @Mock private BftExtraDataCodec bftExtraDataCodec; private static final Block BLOCK = new Block( - new BlockHeaderTestFixture() - .extraData(new QbftExtraDataCodec().encode(extraData)) - .buildHeader(), + new BlockHeaderTestFixture().buildHeader(), new BlockBody(Collections.emptyList(), Collections.emptyList())); @Test diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/payload/QbftPayloadTest.java similarity index 97% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/payload/QbftPayloadTest.java index 820b0f976f9..38db37cca76 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/payload/QbftPayloadTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/payload/QbftPayloadTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.payload; +package org.hyperledger.besu.consensus.qbft.core.payload; import static org.assertj.core.api.Assertions.assertThat; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java similarity index 94% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java index b6adcb73e62..d77a28867bb 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftBlockHeightManagerTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftBlockHeightManagerTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; @@ -43,17 +43,16 @@ import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; import org.hyperledger.besu.consensus.common.bft.network.ValidatorMulticaster; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.network.QbftMessageTransmitter; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.validation.FutureRoundProposalMessageValidator; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidator; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidatorFactory; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.validation.FutureRoundProposalMessageValidator; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidatorFactory; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; @@ -107,7 +106,6 @@ public class QbftBlockHeightManagerTest { private final NodeKey nodeKey = NodeKeyUtils.generate(); private final MessageFactory messageFactory = new MessageFactory(nodeKey); private final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture(); - private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); @Mock private BftFinalState finalState; @Mock private QbftMessageTransmitter messageTransmitter; @@ -122,6 +120,7 @@ public class QbftBlockHeightManagerTest { @Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator; @Mock private ValidatorMulticaster validatorMulticaster; @Mock private BlockHeader parentHeader; + @Mock private BftExtraDataCodec bftExtraDataCodec; @Captor private ArgumentCaptor sentMessageArgCaptor; @@ -133,11 +132,6 @@ public class QbftBlockHeightManagerTest { private Block createdBlock; private void buildCreatedBlock() { - - final BftExtraData extraData = - new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), Optional.empty(), 0, validators); - - headerTestFixture.extraData(bftExtraDataCodec.encode(extraData)); final BlockHeader header = headerTestFixture.buildHeader(); createdBlock = new Block(header, new BlockBody(emptyList(), emptyList())); } @@ -175,8 +169,7 @@ public void setup() { new ProtocolContext( blockchain, null, - setupContextWithBftExtraDataEncoder( - BftContext.class, validators, new QbftExtraDataCodec()), + setupContextWithBftExtraDataEncoder(BftContext.class, validators, bftExtraDataCodec), new BadBlockManager()); final ProtocolScheduleBuilder protocolScheduleBuilder = @@ -234,6 +227,12 @@ BftContext.class, validators, new QbftExtraDataCodec()), bftExtraDataCodec, parentHeader); }); + + when(bftExtraDataCodec.decode(any())) + .thenReturn( + new BftExtraData( + Bytes.wrap(new byte[32]), emptyList(), Optional.empty(), 0, validators)); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); } @Test diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java similarity index 95% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java index 3e3a38af824..d6e6fb9fc6f 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftControllerTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftControllerTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import static org.assertj.core.util.Lists.newArrayList; import static org.mockito.ArgumentMatchers.any; @@ -35,17 +35,16 @@ import org.hyperledger.besu.consensus.common.bft.events.RoundExpiry; import org.hyperledger.besu.consensus.common.bft.statemachine.BftFinalState; import org.hyperledger.besu.consensus.common.bft.statemachine.FutureMessageBuffer; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.QbftGossip; -import org.hyperledger.besu.consensus.qbft.messagedata.CommitMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.PrepareMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.ProposalMessageData; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; -import org.hyperledger.besu.consensus.qbft.messagedata.RoundChangeMessageData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.messagedata.CommitMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.PrepareMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.ProposalMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.RoundChangeMessageData; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.network.QbftGossip; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.Blockchain; @@ -68,14 +67,13 @@ @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) public class QbftControllerTest { - private static final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); - @Mock private Blockchain blockChain; @Mock private BftFinalState bftFinalState; @Mock private QbftBlockHeightManagerFactory blockHeightManagerFactory; @Mock private BlockHeader chainHeadBlockHeader; @Mock private BlockHeader nextBlock; @Mock private BaseQbftBlockHeightManager blockHeightManager; + @Mock private BftExtraDataCodec bftExtraDataCodec; @Mock private Proposal proposal; private Message proposalMessage; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java similarity index 89% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java index 4919e2886d5..8f02c0b50dd 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/QbftRoundTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/QbftRoundTest.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; import static java.util.Optional.empty; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; +import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftBlockInterface; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; @@ -29,6 +29,7 @@ import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; +import org.hyperledger.besu.consensus.common.bft.BftBlockInterface; import org.hyperledger.besu.consensus.common.bft.BftContext; import org.hyperledger.besu.consensus.common.bft.BftExtraData; import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; @@ -37,12 +38,11 @@ import org.hyperledger.besu.consensus.common.bft.RoundTimer; import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.network.QbftMessageTransmitter; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidator; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.network.QbftMessageTransmitter; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.cryptoservices.NodeKey; @@ -91,7 +91,6 @@ public class QbftRoundTest { private final MessageFactory messageFactory = new MessageFactory(nodeKey); private final MessageFactory messageFactory2 = new MessageFactory(nodeKey2); private final Subscribers subscribers = Subscribers.create(); - private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); private ProtocolContext protocolContext; @Mock private BftProtocolSchedule protocolSchedule; @@ -105,11 +104,12 @@ public class QbftRoundTest { @Mock private ProtocolSpec protocolSpec; @Mock private BlockImporter blockImporter; @Mock private BlockHeader parentHeader; + @Mock private BftExtraDataCodec bftExtraDataCodec; + @Mock private BftBlockInterface bftBlockInteface; @Captor private ArgumentCaptor blockCaptor; private Block proposedBlock; - private BftExtraData proposedExtraData; private final SECPSignature remoteCommitSeal = SignatureAlgorithmFactory.getInstance() @@ -121,18 +121,14 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder( - BftContext.class, emptyList(), new QbftExtraDataCodec()), + setupContextWithBftBlockInterface(BftContext.class, emptyList(), bftBlockInteface), new BadBlockManager()); when(messageValidator.validateProposal(any())).thenReturn(true); when(messageValidator.validatePrepare(any())).thenReturn(true); when(messageValidator.validateCommit(any())).thenReturn(true); - proposedExtraData = - new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), empty(), 0, emptyList()); final BlockHeaderTestFixture headerTestFixture = new BlockHeaderTestFixture(); - headerTestFixture.extraData(new QbftExtraDataCodec().encode(proposedExtraData)); headerTestFixture.number(1); final BlockHeader header = headerTestFixture.buildHeader(); @@ -148,6 +144,16 @@ BftContext.class, emptyList(), new QbftExtraDataCodec()), when(blockImporter.importBlock(any(), any(), any())) .thenReturn(new BlockImportResult(BlockImportResult.BlockImportStatus.IMPORTED)); + BftExtraData bftExtraData = + new BftExtraData(Bytes.wrap(new byte[32]), emptyList(), empty(), 0, emptyList()); + when(bftExtraDataCodec.decode(any())).thenReturn(bftExtraData); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSealsAndRoundNumber(any())).thenReturn(Bytes.EMPTY); + when(bftBlockInteface.replaceRoundInBlock( + eq(proposedBlock), eq(roundIdentifier.getRoundNumber()), any())) + .thenReturn(proposedBlock); + subscribers.subscribe(minedBlockObserver); } @@ -186,6 +192,9 @@ public void onReceptionOfValidProposalSendsAPrepareToNetworkPeers() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleProposalMessage( messageFactory.createProposal( roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList())); @@ -255,10 +264,6 @@ public void aProposalMessageWithTheSameBlockIsSentUponReceptionOfARoundChangeWit verify(transmitter, times(1)) .multicastPrepare(eq(roundIdentifier), eq(blockCaptor.getValue().getHash())); - final BftExtraData proposedExtraData = - new QbftExtraDataCodec().decode(blockCaptor.getValue().getHeader()); - assertThat(proposedExtraData.getRound()).isEqualTo(roundIdentifier.getRoundNumber()); - // Inject a single Prepare message, and confirm the roundState has gone to Prepared (which // indicates the block has entered the roundState (note: all msgs are deemed valid due to mocks) round.handlePrepareMessage( @@ -325,6 +330,9 @@ public void blockIsOnlyImportedOnceWhenCommitsAreReceivedBeforeProposal() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -351,6 +359,9 @@ public void blockIsImportedOnlyOnceIfQuorumCommitsAreReceivedPriorToProposal() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleCommitMessage( messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal)); @@ -381,6 +392,9 @@ public void exceptionDuringNodeKeySigningDoesNotEscape() { bftExtraDataCodec, parentHeader); + when(bftBlockInteface.replaceRoundInBlock(eq(proposedBlock), eq(0), any())) + .thenReturn(proposedBlock); + round.handleProposalMessage( messageFactory.createProposal( roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList())); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundStateTest.java similarity index 96% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundStateTest.java index ff76a19b8ad..8cdd29c4009 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/statemachine/RoundStateTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/statemachine/RoundStateTest.java @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.statemachine; +package org.hyperledger.besu.consensus.qbft.core.statemachine; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -23,12 +23,12 @@ import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.messagewrappers.BftMessage; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.validation.MessageValidator; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.validation.MessageValidator; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.cryptoservices.NodeKey; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidatorTest.java similarity index 96% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidatorTest.java index 02ca653f2a3..3960cf64f9b 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/CommitValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/CommitValidatorTest.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Commit; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Commit; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PrepareValidatorTest.java similarity index 95% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PrepareValidatorTest.java index b6c63b5598b..91a36ee61a0 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/PrepareValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/PrepareValidatorTest.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; import org.hyperledger.besu.datatypes.Hash; import org.junit.jupiter.api.Test; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java similarity index 92% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java index 09e9455d89e..0cc93a4c46d 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalPayloadValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalPayloadValidatorTest.java @@ -12,22 +12,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; @@ -43,6 +44,7 @@ import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -55,6 +57,7 @@ public class ProposalPayloadValidatorTest { @Mock private BlockValidator blockValidator; @Mock private MutableBlockchain blockChain; @Mock private WorldStateArchive worldStateArchive; + @Mock private BftExtraDataCodec bftExtraDataCodec; private ProtocolContext protocolContext; private static final int CHAIN_HEIGHT = 3; @@ -66,7 +69,6 @@ public class ProposalPayloadValidatorTest { private final MessageFactory messageFactory = new MessageFactory(nodeKey); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundHelpers.createFrom(targetRound, 1, 0); - final QbftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec(); @BeforeEach public void setup() { @@ -80,6 +82,7 @@ public void setup() { @Test public void validationPassesWhenProposerAndRoundMatchAndBlockIsValid() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( expectedProposer, roundIdentifier, blockValidator, protocolContext); @@ -101,6 +104,7 @@ public void validationPassesWhenProposerAndRoundMatchAndBlockIsValid() { @Test public void validationPassesWhenBlockRoundDoesNotMatchProposalRound() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( expectedProposer, roundIdentifier, blockValidator, protocolContext); @@ -126,6 +130,7 @@ public void validationPassesWhenBlockRoundDoesNotMatchProposalRound() { @Test public void validationFailsWhenBlockFailsValidation() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundHelpers.createFrom(targetRound, 1, 0); @@ -199,6 +204,8 @@ public void validationFailsWhenMessageMismatchesExpectedHeight() { @Test public void validationFailsForBlockWithIncorrectHeight() { + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + final ProposalPayloadValidator payloadValidator = new ProposalPayloadValidator( expectedProposer, roundIdentifier, blockValidator, protocolContext); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java similarity index 87% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java index 43afff35018..c5c2627427d 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ProposalValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ProposalValidatorTest.java @@ -12,32 +12,33 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; -import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createEmptyRoundChangePayloads; -import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createPreparePayloads; +import static org.hyperledger.besu.consensus.qbft.core.validation.ValidationTestHelpers.createEmptyRoundChangePayloads; +import static org.hyperledger.besu.consensus.qbft.core.validation.ValidationTestHelpers.createPreparePayloads; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.bft.BftExtraData; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Prepare; -import org.hyperledger.besu.consensus.qbft.messagewrappers.Proposal; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Prepare; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.Proposal; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.BlockProcessingResult; import org.hyperledger.besu.ethereum.BlockValidator; @@ -54,6 +55,7 @@ import java.util.Map; import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -91,10 +93,10 @@ public RoundSpecificItems( @Mock private WorldStateArchive worldStateArchive; @Mock private BftProtocolSchedule protocolSchedule; @Mock private ProtocolSpec protocolSpec; + @Mock private BftExtraDataCodec bftExtraDataCodec; private ProtocolContext protocolContext; private final Map roundItems = new HashMap<>(); - final QbftExtraDataCodec bftExtraDataEncoder = new QbftExtraDataCodec(); @BeforeEach public void setup() { @@ -102,7 +104,7 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataEncoder), + setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataCodec), new BadBlockManager()); // typically tests require the blockValidation to be successful @@ -118,6 +120,7 @@ public void setup() { when(protocolSpec.getBlockValidator()).thenReturn(blockValidator); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); roundItems.put(ROUND_ID.ZERO, createRoundSpecificItems(0)); roundItems.put(ROUND_ID.ONE, createRoundSpecificItems(1)); } @@ -127,7 +130,7 @@ private RoundSpecificItems createRoundSpecificItems(final int roundNumber) { return new RoundSpecificItems( ProposedBlockHelpers.createProposalBlock( - validators.getNodeAddresses(), roundIdentifier, bftExtraDataEncoder), + validators.getNodeAddresses(), roundIdentifier, bftExtraDataCodec), roundIdentifier, new ProposalValidator( protocolContext, @@ -136,7 +139,7 @@ private RoundSpecificItems createRoundSpecificItems(final int roundNumber) { validators.getNodeAddresses(), roundIdentifier, validators.getNode(0).getAddress(), - bftExtraDataEncoder)); + bftExtraDataCodec)); } // NOTE: tests herein assume the ProposalPayloadValidator works as expected, so other than @@ -177,6 +180,10 @@ public void validationFailsIfBlockIsInvalid() { @Test public void validationFailsIfRoundZeroHasNonEmptyPrepares() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final Prepare prepareMsg = validators .getMessageFactory(1) @@ -350,6 +357,10 @@ public void validationFailsIfBlockHashInLatestPreparedMetadataDoesNotMatchPropos roundChanges.add(preparedRoundChange); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final Proposal proposal = validators .getMessageFactory(0) @@ -395,6 +406,10 @@ public void validationFailsIfPreparesAreNonEmptyButNoRoundChangeHasPreparedMetad @Test public void validationFailsIfPiggybackedPreparePayloadIsFromNonValidator() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -418,6 +433,10 @@ public void validationFailsIfPiggybackedPreparePayloadIsFromNonValidator() { @Test public void validationFailsIfPiggybackedPreparePayloadHasDuplicatedAuthors() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -440,6 +459,10 @@ public void validationFailsIfPiggybackedPreparePayloadHasDuplicatedAuthors() { @Test public void validationFailsIfInsufficientPiggybackedPreparePayloads() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -461,6 +484,10 @@ public void validationFailsIfInsufficientPiggybackedPreparePayloads() { @Test public void validationFailsIfPreparePayloadsDoNotMatchMetadataInRoundChanges() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -483,6 +510,10 @@ public void validationFailsIfPreparePayloadsDoNotMatchMetadataInRoundChanges() { @Test public void validationFailsIfPreparePayloadsDoNotMatchBlockHashInRoundChanges() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); @@ -505,6 +536,10 @@ public void validationFailsIfPreparePayloadsDoNotMatchBlockHashInRoundChanges() @Test public void validationFailsIfTwoRoundChangesArePreparedOnSameRoundDifferentBlock() { + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.decode(any())) + .thenReturn(new BftExtraData(Bytes.EMPTY, emptyList(), Optional.empty(), 0, emptyList())); + final RoundSpecificItems roundItem = roundItems.get(ROUND_ID.ONE); final List> roundChanges = createPreparedRoundZeroRoundChanges(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/QbftNode.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/QbftNode.java similarity index 91% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/QbftNode.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/QbftNode.java index d66952b6960..0d8f6cb00bf 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/QbftNode.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/QbftNode.java @@ -12,9 +12,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/QbftNodeList.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/QbftNodeList.java similarity index 92% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/QbftNodeList.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/QbftNodeList.java index 2f1ac09af12..c787cbc5acb 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/QbftNodeList.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/QbftNodeList.java @@ -12,9 +12,9 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; -import org.hyperledger.besu.consensus.qbft.payload.MessageFactory; +import org.hyperledger.besu.consensus.qbft.core.payload.MessageFactory; import org.hyperledger.besu.datatypes.Address; import java.util.Collection; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java similarity index 89% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java index 82e8fb5c7a8..573caa4bad5 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangeMessageValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangeMessageValidatorTest.java @@ -12,30 +12,30 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static com.google.common.collect.Iterables.toArray; import static java.util.Collections.emptyList; import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.consensus.common.bft.BftContextBuilder.setupContextWithBftExtraDataEncoder; -import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createPreparePayloads; -import static org.hyperledger.besu.consensus.qbft.validation.ValidationTestHelpers.createPreparedCertificate; +import static org.hyperledger.besu.consensus.qbft.core.validation.ValidationTestHelpers.createPreparePayloads; +import static org.hyperledger.besu.consensus.qbft.core.validation.ValidationTestHelpers.createPreparedCertificate; import static org.mockito.Mockito.any; import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.when; import org.hyperledger.besu.consensus.common.bft.BftContext; +import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec; import org.hyperledger.besu.consensus.common.bft.BftHelpers; import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundHelpers; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec; -import org.hyperledger.besu.consensus.qbft.messagewrappers.RoundChange; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.messagewrappers.RoundChange; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.BlockProcessingResult; @@ -51,6 +51,7 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -66,6 +67,7 @@ public class RoundChangeMessageValidatorTest { @Mock private BftProtocolSchedule protocolSchedule; @Mock private BlockValidator blockValidator; @Mock private ProtocolSpec protocolSpec; + @Mock private BftExtraDataCodec bftExtraDataCodec; private ProtocolContext protocolContext; private RoundChangeMessageValidator messageValidator; @@ -76,7 +78,6 @@ public class RoundChangeMessageValidatorTest { new ConsensusRoundIdentifier(CHAIN_HEIGHT, 3); private final ConsensusRoundIdentifier roundIdentifier = ConsensusRoundHelpers.createFrom(targetRound, 0, -1); - private final QbftExtraDataCodec bftExtraDataEncoder = new QbftExtraDataCodec(); @BeforeEach public void setup() { @@ -84,7 +85,7 @@ public void setup() { new ProtocolContext( blockChain, worldStateArchive, - setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataEncoder), + setupContextWithBftExtraDataEncoder(BftContext.class, emptyList(), bftExtraDataCodec), new BadBlockManager()); lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); @@ -116,6 +117,8 @@ public void roundChangeWithValidPiggyBackDataIsValid() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -127,7 +130,7 @@ public void roundChangeWithValidPiggyBackDataIsValid() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, roundIdentifier, toArray(validators.getNodes(), QbftNode.class)); @@ -142,6 +145,8 @@ public void roundChangeWithBlockRoundMismatchingPreparesIsValid() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -153,7 +158,7 @@ public void roundChangeWithBlockRoundMismatchingPreparesIsValid() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, @@ -212,6 +217,8 @@ public void insufficientPiggyBackedPrepareMessagesIsInvalid() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -223,7 +230,7 @@ public void insufficientPiggyBackedPrepareMessagesIsInvalid() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, roundIdentifier, validators.getNode(0), validators.getNode(1)); @@ -238,6 +245,8 @@ public void prepareFromNonValidatorFails() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -251,7 +260,7 @@ public void prepareFromNonValidatorFails() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, roundIdentifier, validators.getNode(0), validators.getNode(1), nonValidator); @@ -266,6 +275,8 @@ public void validationFailsIfPreparedMetadataContainsDifferentRoundToBlock() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -277,7 +288,7 @@ public void validationFailsIfPreparedMetadataContainsDifferentRoundToBlock() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = new PreparedCertificate( block, @@ -300,6 +311,8 @@ public void validationFailsIfPreparesContainsDifferentRoundToBlock() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -311,7 +324,7 @@ public void validationFailsIfPreparesContainsDifferentRoundToBlock() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = new PreparedCertificate( block, @@ -336,6 +349,8 @@ public void validationFailsIfPreparesContainsWrongHeight() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -347,7 +362,7 @@ public void validationFailsIfPreparesContainsWrongHeight() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = new PreparedCertificate( block, @@ -372,6 +387,8 @@ public void validationFailsIfPreparesHaveDuplicateAuthors() { when(payloadValidator.validate(any())).thenReturn(true); when(blockValidator.validateAndProcessBlock(any(), any(), any(), any())) .thenReturn(new BlockProcessingResult(Optional.empty())); + when(bftExtraDataCodec.encode(any())).thenReturn(Bytes.EMPTY); + when(bftExtraDataCodec.encodeWithoutCommitSeals(any())).thenReturn(Bytes.EMPTY); messageValidator = new RoundChangeMessageValidator( payloadValidator, @@ -383,7 +400,7 @@ public void validationFailsIfPreparesHaveDuplicateAuthors() { final Block block = ProposedBlockHelpers.createProposalBlock( - Collections.emptyList(), roundIdentifier, bftExtraDataEncoder); + Collections.emptyList(), roundIdentifier, bftExtraDataCodec); final PreparedCertificate prepCert = createPreparedCertificate( block, diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidatorTest.java similarity index 96% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidatorTest.java index f4a91024b4a..e1f1df801ad 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/RoundChangePayloadValidatorTest.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/RoundChangePayloadValidatorTest.java @@ -12,14 +12,14 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import static org.assertj.core.api.Assertions.assertThat; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparedRoundMetadata; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparedRoundMetadata; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ValidationTestHelpers.java b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ValidationTestHelpers.java similarity index 88% rename from consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ValidationTestHelpers.java rename to consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ValidationTestHelpers.java index 63a6e4e8e2d..e8b6538e81a 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validation/ValidationTestHelpers.java +++ b/consensus/qbft-core/src/test/java/org/hyperledger/besu/consensus/qbft/core/validation/ValidationTestHelpers.java @@ -12,13 +12,13 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.consensus.qbft.validation; +package org.hyperledger.besu.consensus.qbft.core.validation; import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier; import org.hyperledger.besu.consensus.common.bft.payload.SignedData; -import org.hyperledger.besu.consensus.qbft.payload.PreparePayload; -import org.hyperledger.besu.consensus.qbft.payload.RoundChangePayload; -import org.hyperledger.besu.consensus.qbft.statemachine.PreparedCertificate; +import org.hyperledger.besu.consensus.qbft.core.payload.PreparePayload; +import org.hyperledger.besu.consensus.qbft.core.payload.RoundChangePayload; +import org.hyperledger.besu.consensus.qbft.core.statemachine.PreparedCertificate; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.Block; diff --git a/consensus/qbft/build.gradle b/consensus/qbft/build.gradle index 23e5576ebac..5481d9776e8 100644 --- a/consensus/qbft/build.gradle +++ b/consensus/qbft/build.gradle @@ -31,6 +31,7 @@ jar { dependencies { implementation project(':config') implementation project(':consensus:common') + implementation project(':consensus:qbft-core') implementation project(':crypto:services') implementation project(':datatypes') implementation project(':ethereum:api') @@ -67,20 +68,4 @@ dependencies { testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.mockito:mockito-core' testImplementation 'org.mockito:mockito-junit-jupiter' - - integrationTestImplementation project(':crypto:algorithms') - integrationTestImplementation project(path: ':crypto:services', configuration: 'testSupportArtifacts') - integrationTestImplementation project(path: ':consensus:common', configuration: 'testSupportArtifacts') - integrationTestImplementation project(':evm') - integrationTestImplementation project(':metrics:core') - integrationTestImplementation project(':testutil') - - integrationTestImplementation 'org.assertj:assertj-core' - integrationTestImplementation 'org.junit.jupiter:junit-jupiter-api' - integrationTestImplementation 'org.mockito:mockito-core' - integrationTestImplementation 'org.mockito:mockito-junit-jupiter' - - integrationTestRuntimeOnly 'org.junit.jupiter:junit-jupiter' - - testSupportImplementation 'org.mockito:mockito-core' } diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java index 7437b349a2a..78ad1816635 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/BFTPivotSelectorFromPeers.java @@ -26,7 +26,6 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.NoSyncRequiredException; import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromPeers; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; -import org.hyperledger.besu.plugin.services.MetricsSystem; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; @@ -56,7 +55,6 @@ public class BFTPivotSelectorFromPeers extends PivotSelectorFromPeers { * @param ethContext the eth context * @param syncConfig the sync config * @param syncState the sync state - * @param metricsSystem the metrics * @param protocolContext the protocol context * @param nodeKey the node key * @param blockHeader the block header @@ -65,11 +63,10 @@ public BFTPivotSelectorFromPeers( final EthContext ethContext, final SynchronizerConfiguration syncConfig, final SyncState syncState, - final MetricsSystem metricsSystem, final ProtocolContext protocolContext, final NodeKey nodeKey, final BlockHeader blockHeader) { - super(ethContext, syncConfig, syncState, metricsSystem); + super(ethContext, syncConfig, syncState); this.protocolContext = protocolContext; this.blockHeader = blockHeader; this.nodeKey = nodeKey; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocol.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocol.java index 37f04391cbd..70e4a8e5445 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocol.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/protocol/Istanbul100SubProtocol.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.consensus.qbft.protocol; -import org.hyperledger.besu.consensus.qbft.messagedata.QbftV1; +import org.hyperledger.besu.consensus.qbft.core.messagedata.QbftV1; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol; diff --git a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractController.java b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractController.java index 5b561856ecf..de3e9cf1703 100644 --- a/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractController.java +++ b/consensus/qbft/src/main/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorContractController.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.consensus.qbft.validator; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; @@ -94,10 +93,7 @@ private Optional callFunction( final CallParameter callParams = new CallParameter(null, contractAddress, -1, null, null, payload); final TransactionValidationParams transactionValidationParams = - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(true) - .build(); + TransactionValidationParams.transactionSimulatorAllowExceedingBalance(); return transactionSimulator.process( callParams, transactionValidationParams, OperationTracer.NO_TRACING, blockNumber); } diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/sync/QbftPivotSelectorTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/sync/QbftPivotSelectorTest.java index 2f3013ea714..76f41dc6506 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/sync/QbftPivotSelectorTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/sync/QbftPivotSelectorTest.java @@ -33,7 +33,6 @@ import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncState; import org.hyperledger.besu.ethereum.eth.sync.fastsync.NoSyncRequiredException; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; -import org.hyperledger.besu.plugin.services.MetricsSystem; import java.util.ArrayList; import java.util.List; @@ -55,7 +54,6 @@ public class QbftPivotSelectorTest { @Mock private ProtocolContext protocolContext; @Mock private BftContext bftContext; @Mock private SyncState syncState; - @Mock private MetricsSystem metricsSystem; @Mock private EthContext ethContext; @Mock private EthPeers ethPeers; @Mock private ValidatorProvider validatorProvider; @@ -80,13 +78,7 @@ public void returnEmptySyncStateIfValidatorWithOtherValidatorsButNoPeers() { when(validatorProvider.getValidatorsAtHead()).thenReturn(validatorList); BFTPivotSelectorFromPeers pivotSelector = new BFTPivotSelectorFromPeers( - ethContext, - syncConfig, - syncState, - metricsSystem, - protocolContext, - nodeKey, - blockHeader); + ethContext, syncConfig, syncState, protocolContext, nodeKey, blockHeader); Optional pivotState = pivotSelector.selectNewPivotBlock(); assertThat(pivotState.isEmpty()).isTrue(); } @@ -104,13 +96,7 @@ public void returnNoSyncRequiredIfOnlyValidatorAndNoPeers() { when(validatorProvider.getValidatorsAtHead()).thenReturn(validatorList); BFTPivotSelectorFromPeers pivotSelector = new BFTPivotSelectorFromPeers( - ethContext, - syncConfig, - syncState, - metricsSystem, - protocolContext, - nodeKey, - blockHeader); + ethContext, syncConfig, syncState, protocolContext, nodeKey, blockHeader); try { Optional pivotState = pivotSelector.selectNewPivotBlock(); @@ -126,13 +112,7 @@ public void returnEmptySyncStateIfNonValidatorWithNoBestPeer() { when(validatorProvider.nodeIsValidator(any())).thenReturn(false); BFTPivotSelectorFromPeers pivotSelector = new BFTPivotSelectorFromPeers( - ethContext, - syncConfig, - syncState, - metricsSystem, - protocolContext, - nodeKey, - blockHeader); + ethContext, syncConfig, syncState, protocolContext, nodeKey, blockHeader); Optional pivotState = pivotSelector.selectNewPivotBlock(); assertThat(pivotState.isEmpty()).isTrue(); @@ -145,13 +125,7 @@ public void returnEmptySyncStateIfValidatorAndNotAtGenesisAndOtherValidators() { when(blockHeader.getNumber()).thenReturn(10L); BFTPivotSelectorFromPeers pivotSelector = new BFTPivotSelectorFromPeers( - ethContext, - syncConfig, - syncState, - metricsSystem, - protocolContext, - nodeKey, - blockHeader); + ethContext, syncConfig, syncState, protocolContext, nodeKey, blockHeader); Optional pivotState = pivotSelector.selectNewPivotBlock(); assertThat(pivotState.isEmpty()).isTrue(); diff --git a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java index dabf26749a5..1a531cb344f 100644 --- a/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java +++ b/consensus/qbft/src/test/java/org/hyperledger/besu/consensus/qbft/validator/ValidatorModeTransitionLoggerTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.consensus.common.ForkSpec; import org.hyperledger.besu.consensus.common.ForksSchedule; import org.hyperledger.besu.consensus.qbft.MutableQbftConfigOptions; +import org.hyperledger.besu.consensus.qbft.core.validator.ValidatorModeTransitionLogger; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; diff --git a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java index bd450b206e9..4e228441cc4 100644 --- a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java +++ b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/AbstractSECP256.java @@ -214,7 +214,7 @@ public SECPSignature createSignature(final BigInteger r, final BigInteger s, fin @Override public CodeDelegationSignature createCodeDelegationSignature( - final BigInteger r, final BigInteger s, final BigInteger yParity) { + final BigInteger r, final BigInteger s, final byte yParity) { return CodeDelegationSignature.create(r, s, yParity); } diff --git a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/CodeDelegationSignature.java b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/CodeDelegationSignature.java index 06ec72bf0a9..e68f30727ca 100644 --- a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/CodeDelegationSignature.java +++ b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/CodeDelegationSignature.java @@ -42,7 +42,7 @@ public CodeDelegationSignature(final BigInteger r, final BigInteger s, final byt * @return the new CodeDelegationSignature */ public static CodeDelegationSignature create( - final BigInteger r, final BigInteger s, final BigInteger yParity) { + final BigInteger r, final BigInteger s, final byte yParity) { checkNotNull(r); checkNotNull(s); @@ -56,11 +56,6 @@ public static CodeDelegationSignature create( "Invalid 's' value, should be < 2^256 but got " + s.toString(16)); } - if (yParity.compareTo(TWO_POW_256) >= 0) { - throw new IllegalArgumentException( - "Invalid 'yParity' value, should be < 2^256 but got " + yParity.toString(16)); - } - - return new CodeDelegationSignature(r, s, yParity.byteValue()); + return new CodeDelegationSignature(r, s, yParity); } } diff --git a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java index 4bf8d89c825..a1a79d057a5 100644 --- a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java +++ b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/SignatureAlgorithm.java @@ -224,7 +224,7 @@ Optional recoverPublicKeyFromSignature( * @return the code delegation signature */ CodeDelegationSignature createCodeDelegationSignature( - final BigInteger r, final BigInteger s, final BigInteger yParity); + final BigInteger r, final BigInteger s, final byte yParity); /** * Decode secp signature. diff --git a/crypto/algorithms/src/test/java/org/hyperledger/besu/crypto/CodeDelegationSignatureTest.java b/crypto/algorithms/src/test/java/org/hyperledger/besu/crypto/CodeDelegationSignatureTest.java index 332aa14893f..1c0cc95ffd9 100644 --- a/crypto/algorithms/src/test/java/org/hyperledger/besu/crypto/CodeDelegationSignatureTest.java +++ b/crypto/algorithms/src/test/java/org/hyperledger/besu/crypto/CodeDelegationSignatureTest.java @@ -29,19 +29,19 @@ class CodeDelegationSignatureTest { void testValidInputs() { BigInteger r = BigInteger.ONE; BigInteger s = BigInteger.TEN; - BigInteger yParity = BigInteger.ONE; + byte yParity = (byte) 1; CodeDelegationSignature result = CodeDelegationSignature.create(r, s, yParity); assertThat(r).isEqualTo(result.getR()); assertThat(s).isEqualTo(result.getS()); - assertThat(yParity.byteValue()).isEqualTo(result.getRecId()); + assertThat(yParity).isEqualTo(result.getRecId()); } @Test void testNullRValue() { BigInteger s = BigInteger.TEN; - BigInteger yParity = BigInteger.ZERO; + byte yParity = (byte) 0; assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> CodeDelegationSignature.create(null, s, yParity)); @@ -50,7 +50,7 @@ void testNullRValue() { @Test void testNullSValue() { BigInteger r = BigInteger.ONE; - BigInteger yParity = BigInteger.ZERO; + byte yParity = (byte) 0; assertThatExceptionOfType(NullPointerException.class) .isThrownBy(() -> CodeDelegationSignature.create(r, null, yParity)); @@ -60,7 +60,7 @@ void testNullSValue() { void testRValueExceedsTwoPow256() { BigInteger r = TWO_POW_256; BigInteger s = BigInteger.TEN; - BigInteger yParity = BigInteger.ZERO; + byte yParity = (byte) 0; assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CodeDelegationSignature.create(r, s, yParity)) @@ -71,34 +71,23 @@ void testRValueExceedsTwoPow256() { void testSValueExceedsTwoPow256() { BigInteger r = BigInteger.ONE; BigInteger s = TWO_POW_256; - BigInteger yParity = BigInteger.ZERO; + byte yParity = (byte) 0; assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy(() -> CodeDelegationSignature.create(r, s, yParity)) .withMessageContainingAll("Invalid 's' value, should be < 2^256"); } - @Test - void testYParityExceedsTwoPow256() { - BigInteger r = BigInteger.ONE; - BigInteger s = BigInteger.TWO; - BigInteger yParity = TWO_POW_256; - - assertThatExceptionOfType(IllegalArgumentException.class) - .isThrownBy(() -> CodeDelegationSignature.create(r, s, yParity)) - .withMessageContainingAll("Invalid 'yParity' value, should be < 2^256"); - } - @Test void testValidYParityZero() { BigInteger r = BigInteger.ONE; BigInteger s = BigInteger.TEN; - BigInteger yParity = BigInteger.ZERO; + byte yParity = (byte) 0; CodeDelegationSignature result = CodeDelegationSignature.create(r, s, yParity); assertThat(r).isEqualTo(result.getR()); assertThat(s).isEqualTo(result.getS()); - assertThat(yParity.byteValue()).isEqualTo(result.getRecId()); + assertThat(yParity).isEqualTo(result.getRecId()); } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccountOverride.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccountOverride.java index e414e97eb5d..e33f6feef54 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccountOverride.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/AccountOverride.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.datatypes; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; + import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -83,6 +85,7 @@ public Optional> getStateDiff() { } /** Builder class for Account overrides */ + @JsonIgnoreProperties(ignoreUnknown = true) public static class Builder { private Optional balance = Optional.empty(); private Optional nonce = Optional.empty(); @@ -106,11 +109,11 @@ public Builder withBalance(final Wei balance) { /** * Sets the nonce override * - * @param nonce the nonce override + * @param nonce the nonce override in hex * @return the builder */ - public Builder withNonce(final Long nonce) { - this.nonce = Optional.ofNullable(nonce); + public Builder withNonce(final UnsignedLongParameter nonce) { + this.nonce = Optional.of(nonce.getValue()); return this; } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java index bea562ee1f4..1f21dd2fd85 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Address.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.rlp.RLPException; import org.hyperledger.besu.ethereum.rlp.RLPInput; +import java.util.Arrays; import java.util.concurrent.ExecutionException; import com.fasterxml.jackson.annotation.JsonCreator; @@ -291,4 +292,16 @@ public Hash addressHash() { return Hash.hash(this); } } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Address)) { + return false; + } + Address other = (Address) obj; + return Arrays.equals(this.toArrayUnsafe(), other.toArrayUnsafe()); + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/CodeDelegation.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/CodeDelegation.java index 7b9e3d7d447..aab8203e296 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/CodeDelegation.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/CodeDelegation.java @@ -25,7 +25,7 @@ */ public interface CodeDelegation { /** The cost of delegating code on an existing account. */ - long PER_AUTH_BASE_COST = 2_500L; + long PER_AUTH_BASE_COST = 12_500L; /** * Return the chain id. diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Hash.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Hash.java index 3777169ed4d..53a19399a97 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Hash.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Hash.java @@ -118,4 +118,16 @@ public static Hash fromHexString(final String str) { public static Hash fromHexStringLenient(final String str) { return new Hash(Bytes32.fromHexStringLenient(str)); } + + /*** + * For logging purposes, this method returns a shortened hex representation + * + * @return shortened string with only the beginning and the end of the hex representation + */ + public String toShortLogString() { + final var hexRepresentation = toFastHex(false); + String firstPart = hexRepresentation.substring(0, 5); + String lastPart = hexRepresentation.substring(hexRepresentation.length() - 5); + return firstPart + "....." + lastPart; + } } diff --git a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Wei.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Wei.java index 7b097a9dd1a..1fe2a5ffea5 100644 --- a/datatypes/src/main/java/org/hyperledger/besu/datatypes/Wei.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/Wei.java @@ -161,11 +161,31 @@ public static Wei fromQuantity(final Quantity quantity) { * @return the string */ public String toHumanReadableString() { + return toHumanReadableStringWithPadding(1); + } + + /** + * Wei to human-readable string, with padding + * + * @return the string + */ + public String toHumanReadablePaddedString() { + return toHumanReadableStringWithPadding(6); + } + + /** + * Returns a human-readable String, the number of returned characters depends on the width + * parameter + * + * @param width the number of digits to use + * @return a human-readable String + */ + private String toHumanReadableStringWithPadding(final int width) { final BigInteger amount = toBigInteger(); final int numOfDigits = amount.toString().length(); final Unit preferredUnit = Unit.getPreferred(numOfDigits); final double res = amount.doubleValue() / preferredUnit.divisor; - return String.format("%1." + preferredUnit.decimals + "f %s", res, preferredUnit); + return String.format("%" + width + "." + preferredUnit.decimals + "f %s", res, preferredUnit); } /** The enum Unit. */ diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UInt256Parameter.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UInt256Parameter.java similarity index 79% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UInt256Parameter.java rename to datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UInt256Parameter.java index 308df3f290e..d05fed7804a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UInt256Parameter.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UInt256Parameter.java @@ -12,20 +12,31 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; +package org.hyperledger.besu.datatypes.parameters; import com.fasterxml.jackson.annotation.JsonCreator; import org.apache.tuweni.units.bigints.UInt256; +/** A parameter that represents a UInt256 value. */ public class UInt256Parameter { private final UInt256 value; + /** + * Create a new UInt256Parameter + * + * @param value the value + */ @JsonCreator public UInt256Parameter(final String value) { this.value = UInt256.fromHexString(value); } + /** + * Get the value + * + * @return the value + */ public UInt256 getValue() { return value; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedIntParameter.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UnsignedIntParameter.java similarity index 76% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedIntParameter.java rename to datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UnsignedIntParameter.java index a21917dc0ba..1e9caa48e1e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedIntParameter.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UnsignedIntParameter.java @@ -12,28 +12,44 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; +package org.hyperledger.besu.datatypes.parameters; import static com.google.common.base.Preconditions.checkArgument; import com.fasterxml.jackson.annotation.JsonCreator; +/** A parameter that represents an unsigned int value. */ public class UnsignedIntParameter { private final int value; + /** + * Create a new UnsignedIntParameter + * + * @param value the value + */ @JsonCreator public UnsignedIntParameter(final String value) { this.value = Integer.decode(value); checkArgument(this.value >= 0); } + /** + * Create a new UnsignedIntParameter + * + * @param value the value + */ @JsonCreator public UnsignedIntParameter(final int value) { this.value = value; checkArgument(this.value >= 0); } + /** + * Get the value of the parameter + * + * @return the value + */ public int getValue() { return value; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedLongParameter.java b/datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UnsignedLongParameter.java similarity index 78% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedLongParameter.java rename to datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UnsignedLongParameter.java index 2e9ae8087ec..364b3b340fa 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/UnsignedLongParameter.java +++ b/datatypes/src/main/java/org/hyperledger/besu/datatypes/parameters/UnsignedLongParameter.java @@ -12,17 +12,23 @@ * * SPDX-License-Identifier: Apache-2.0 */ -package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; +package org.hyperledger.besu.datatypes.parameters; import static com.google.common.base.Preconditions.checkArgument; import com.fasterxml.jackson.annotation.JsonCreator; import org.checkerframework.checker.signedness.qual.Unsigned; +/** A parameter that represents an unsigned long value. */ public class UnsignedLongParameter { @Unsigned private final long value; + /** + * Create a new UnsignedLongParameter + * + * @param value the value + */ @JsonCreator public UnsignedLongParameter(final String value) { checkArgument(value != null); @@ -33,11 +39,21 @@ public UnsignedLongParameter(final String value) { } } + /** + * Create a new UnsignedLongParameter + * + * @param value the value + */ @JsonCreator public UnsignedLongParameter(final @Unsigned long value) { this.value = value; } + /** + * Get the value of the parameter + * + * @return the value + */ public @Unsigned long getValue() { return value; } diff --git a/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java b/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java index 7162f98b026..39162fd2cfd 100644 --- a/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java +++ b/datatypes/src/test/java/org/hyperledger/besu/datatypes/WeiTest.java @@ -44,4 +44,28 @@ public void toHumanReadableString() { assertThat(Wei.of(new BigInteger("1" + String.valueOf(manyZeros))).toHumanReadableString()) .isEqualTo("100.00 tether"); } + + @Test + public void toHumanReadablePaddedString() { + assertThat(Wei.ZERO.toHumanReadablePaddedString()).isEqualTo(" 0 wei"); + assertThat(Wei.ONE.toHumanReadablePaddedString()).isEqualTo(" 1 wei"); + + assertThat(Wei.of(999).toHumanReadablePaddedString()).isEqualTo(" 999 wei"); + assertThat(Wei.of(1000).toHumanReadablePaddedString()).isEqualTo(" 1.00 kwei"); + + assertThat(Wei.of(1009).toHumanReadablePaddedString()).isEqualTo(" 1.01 kwei"); + assertThat(Wei.of(1011).toHumanReadablePaddedString()).isEqualTo(" 1.01 kwei"); + + assertThat(Wei.of(new BigInteger("1000000000")).toHumanReadablePaddedString()) + .isEqualTo(" 1.00 gwei"); + + assertThat(Wei.of(new BigInteger("1000000000000000000")).toHumanReadablePaddedString()) + .isEqualTo(" 1.00 ether"); + + final char[] manyZeros = new char[32]; + Arrays.fill(manyZeros, '0'); + assertThat( + Wei.of(new BigInteger("1" + String.valueOf(manyZeros))).toHumanReadablePaddedString()) + .isEqualTo("100.00 tether"); + } } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/BlockchainImporter.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/BlockchainImporter.java index 7e1be90e10e..307979f827f 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/BlockchainImporter.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/BlockchainImporter.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.core.Block; @@ -45,7 +45,7 @@ public class BlockchainImporter { public BlockchainImporter(final URL blocksUrl, final String genesisJson) throws Exception { protocolSchedule = MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.fromConfig(genesisJson).getConfigOptions(), + GenesisConfig.fromConfig(genesisJson).getConfigOptions(), MiningConfiguration.newDefault(), new BadBlockManager(), false, diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java index 045b4ad02d3..d29ca873902 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseKey.java @@ -39,5 +39,5 @@ public enum JsonRpcResponseKey { BASEFEE, WITHDRAWALS_ROOT, REQUESTS_HASH, - TARGET_BLOB_COUNT + TARGET_BLOBS_PER_BLOCK } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java index 18208272d9d..2ea18ca8fe8 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcResponseUtils.java @@ -107,9 +107,9 @@ public JsonRpcResponse response( values.containsKey(WITHDRAWALS_ROOT) ? hash(values.get(WITHDRAWALS_ROOT)) : null; final Hash requestsHash = values.containsKey(REQUESTS_HASH) ? hash(values.get(REQUESTS_HASH)) : null; - final UInt64 targetBlobCount = - values.containsKey(JsonRpcResponseKey.TARGET_BLOB_COUNT) - ? UInt64.fromHexString(values.get(JsonRpcResponseKey.TARGET_BLOB_COUNT)) + final UInt64 targetBlobsPerBlock = + values.containsKey(JsonRpcResponseKey.TARGET_BLOBS_PER_BLOCK) + ? UInt64.fromHexString(values.get(JsonRpcResponseKey.TARGET_BLOBS_PER_BLOCK)) : null; final List ommers = new ArrayList<>(); @@ -136,7 +136,7 @@ public JsonRpcResponse response( null, // ToDo 4844: set with the value of excess_blob_gas field null, // TODO 4788: set with the value of the parent beacon block root field requestsHash, - targetBlobCount, + targetBlobsPerBlock, null, blockHeaderFunctions); diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index 2a65b1e7cb0..63554577c4b 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -77,6 +78,7 @@ public class JsonRpcTestMethodsFactory { private final BlockchainQueries blockchainQueries; private final Synchronizer synchronizer; private final ProtocolSchedule protocolSchedule; + private final TransactionSimulator transactionSimulator; public JsonRpcTestMethodsFactory(final BlockchainImporter importer) { this.importer = importer; @@ -95,9 +97,13 @@ public JsonRpcTestMethodsFactory(final BlockchainImporter importer) { final BlockImporter blockImporter = protocolSpec.getBlockImporter(); blockImporter.importBlock(context, block, HeaderValidationMode.FULL); } + final var miningConfiguration = MiningConfiguration.newDefault(); this.blockchainQueries = - new BlockchainQueries( - protocolSchedule, blockchain, stateArchive, MiningConfiguration.newDefault()); + new BlockchainQueries(protocolSchedule, blockchain, stateArchive, miningConfiguration); + + this.transactionSimulator = + new TransactionSimulator( + blockchain, stateArchive, protocolSchedule, miningConfiguration, 0L); } public JsonRpcTestMethodsFactory( @@ -110,13 +116,14 @@ public JsonRpcTestMethodsFactory( this.stateArchive = stateArchive; this.context = context; this.protocolSchedule = importer.getProtocolSchedule(); + final var miningConfiguration = MiningConfiguration.newDefault(); this.blockchainQueries = new BlockchainQueries( - importer.getProtocolSchedule(), - blockchain, - stateArchive, - MiningConfiguration.newDefault()); + importer.getProtocolSchedule(), blockchain, stateArchive, miningConfiguration); this.synchronizer = mock(Synchronizer.class); + this.transactionSimulator = + new TransactionSimulator( + blockchain, stateArchive, protocolSchedule, miningConfiguration, 0L); } public JsonRpcTestMethodsFactory( @@ -131,12 +138,13 @@ public JsonRpcTestMethodsFactory( this.context = context; this.synchronizer = synchronizer; this.protocolSchedule = importer.getProtocolSchedule(); + final var miningConfiguration = MiningConfiguration.newDefault(); this.blockchainQueries = new BlockchainQueries( - importer.getProtocolSchedule(), - blockchain, - stateArchive, - MiningConfiguration.newDefault()); + importer.getProtocolSchedule(), blockchain, stateArchive, miningConfiguration); + this.transactionSimulator = + new TransactionSimulator( + blockchain, stateArchive, protocolSchedule, miningConfiguration, 0L); } public BlockchainQueries getBlockchainQueries() { @@ -219,6 +227,7 @@ public Map methods() { ethPeers, Vertx.vertx(new VertxOptions().setWorkerPoolSize(1)), ImmutableApiConfiguration.builder().build(), - Optional.empty()); + Optional.empty(), + transactionSimulator); } } diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java index 5fde9ccecbd..7c8cb8a08d7 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/london/EthEstimateGasIntegrationTest.java @@ -137,6 +137,7 @@ public void shouldReturnErrorWithInvalidChainId() { .withChainId(BLOCKCHAIN.getChainId().add(BigInteger.ONE)) .withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b")) .withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1")) + .withMaxFeePerGas(Wei.ONE) .withValue(Wei.ONE) .build(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java index c12f7578c6c..f689f191e6c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/GraphQLContextType.java @@ -41,6 +41,6 @@ public enum GraphQLContextType { /** Represents chain ID context. */ CHAIN_ID, - /** Represents gas cap context. */ - GAS_CAP + /** Represents the transaction simulator. */ + TRANSACTION_SIMULATOR } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java index 6d5b696353a..f49fa0a4c8f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/BlockAdapterBase.java @@ -26,7 +26,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.LogWithMetadata; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; @@ -332,10 +331,8 @@ private Optional executeCall(final DataFetchingEnvironment environme final ProtocolSchedule protocolSchedule = environment.getGraphQlContext().get(GraphQLContextType.PROTOCOL_SCHEDULE); final long bn = header.getNumber(); - final long gasCap = environment.getGraphQlContext().get(GraphQLContextType.GAS_CAP); final TransactionSimulator transactionSimulator = - new TransactionSimulator( - query.getBlockchain(), query.getWorldStateArchive(), protocolSchedule, gasCap); + environment.getGraphQlContext().get(GraphQLContextType.TRANSACTION_SIMULATOR); long gasParam = -1; Wei gasPriceParam = null; @@ -361,14 +358,9 @@ private Optional executeCall(final DataFetchingEnvironment environme data, Optional.empty()); - ImmutableTransactionValidationParams.Builder transactionValidationParams = - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()); - transactionValidationParams.isAllowExceedingBalance(true); - return transactionSimulator.process( param, - transactionValidationParams.build(), + TransactionValidationParams.transactionSimulatorAllowExceedingBalance(), OperationTracer.NO_TRACING, (mutableWorldState, transactionSimulatorResult) -> transactionSimulatorResult.map( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java index fa75028a383..f1a953481f3 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/NormalBlockAdapter.java @@ -15,11 +15,14 @@ package org.hyperledger.besu.ethereum.api.graphql.internal.pojoadapter; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.api.graphql.GraphQLContextType; import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.api.query.TransactionReceiptWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import java.util.ArrayList; import java.util.List; @@ -122,13 +125,22 @@ public Optional getOmmerAt(final DataFetchingEnvironment envi * *

Each TransactionAdapter object is created by adapting a TransactionWithMetadata object. * + * @param environment the data fetching environment. * @return a list of TransactionAdapter objects for the transactions in the block. */ - public List getTransactions() { + public List getTransactions(final DataFetchingEnvironment environment) { + final BlockchainQueries query = getBlockchainQueries(environment); + final Hash hash = blockWithMetaData.getHeader().getHash(); + final ProtocolSchedule protocolSchedule = + environment.getGraphQlContext().get(GraphQLContextType.PROTOCOL_SCHEDULE); + final List trans = blockWithMetaData.getTransactions(); + final List transReceipts = + query.transactionReceiptsByBlockHash(hash, protocolSchedule).get(); + final List results = new ArrayList<>(); - for (final TransactionWithMetadata tran : trans) { - results.add(new TransactionAdapter(tran)); + for (int i = 0; i < trans.size(); i++) { + results.add(new TransactionAdapter(trans.get(i), transReceipts.get(i))); } return results; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java index 49f6bc890f9..73e0d4cb570 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/PendingStateAdapter.java @@ -75,7 +75,7 @@ public List getTransactions() { return transactionPool.getPendingTransactions().stream() .map(PendingTransaction::getTransaction) .map(TransactionWithMetadata::new) - .map(TransactionAdapter::new) + .map(tx -> new TransactionAdapter(tx, null)) .toList(); } @@ -145,10 +145,8 @@ public Optional getCall(final DataFetchingEnvironment environment) { final BlockchainQueries query = getBlockchainQueries(environment); final ProtocolSchedule protocolSchedule = environment.getGraphQlContext().get(GraphQLContextType.PROTOCOL_SCHEDULE); - final long gasCap = environment.getGraphQlContext().get(GraphQLContextType.GAS_CAP); final TransactionSimulator transactionSimulator = - new TransactionSimulator( - query.getBlockchain(), query.getWorldStateArchive(), protocolSchedule, gasCap); + environment.getGraphQlContext().get(GraphQLContextType.TRANSACTION_SIMULATOR); long gasParam = -1; Wei gasPriceParam = null; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java index f8e60c5527c..4f26273112e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/graphql/internal/pojoadapter/TransactionAdapter.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Optional; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import graphql.schema.DataFetchingEnvironment; import org.apache.tuweni.bytes.Bytes; @@ -65,6 +66,25 @@ public TransactionAdapter(final @Nonnull TransactionWithMetadata transactionWith this.transactionWithMetadata = transactionWithMetadata; } + /** + * Constructs a new TransactionAdapter object with receipt. + * + * @param transactionWithMetadata the TransactionWithMetadata object to adapt. + * @param transactionReceiptWithMetadata the TransactionReceiptWithMetadata object to adapt. + */ + public TransactionAdapter( + final @Nonnull TransactionWithMetadata transactionWithMetadata, + final @Nullable TransactionReceiptWithMetadata transactionReceiptWithMetadata) { + this.transactionWithMetadata = transactionWithMetadata; + this.transactionReceiptWithMetadata = Optional.ofNullable(transactionReceiptWithMetadata); + } + + /** + * Reurns the receipt of the transaction. + * + * @param environment the data fetching environment. + * @return the receipt of the transaction. + */ private Optional getReceipt( final DataFetchingEnvironment environment) { if (transactionReceiptWithMetadata == null) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpService.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpService.java index af50b53bb1c..5f746304c97 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpService.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpService.java @@ -429,7 +429,7 @@ private void applyTlsConfig(final HttpServerOptions httpServerOptions) { try { httpServerOptions .setSsl(true) - .setPfxKeyCertOptions( + .setKeyCertOptions( new PfxOptions() .setPath(tlsConfiguration.getKeyStorePath().toString()) .setPassword(tlsConfiguration.getKeyStorePassword())) @@ -472,6 +472,14 @@ private void applyTlsClientAuth( httpServerOptions.setTrustOptions( allowlistClients( knownClientsFile, clientAuthConfiguration.isCaClientsEnabled()))); + clientAuthConfiguration + .getTruststorePath() + .ifPresent( + truststorePath -> + httpServerOptions.setTrustOptions( + new PfxOptions() + .setPath(truststorePath.toString()) + .setPassword(clientAuthConfiguration.getTrustStorePassword()))); } private String tlsLogMessage() { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/BaseJsonRpcProcessor.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/BaseJsonRpcProcessor.java index db6481b46aa..a8225f9bfb2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/BaseJsonRpcProcessor.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/BaseJsonRpcProcessor.java @@ -24,6 +24,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.privacy.MultiTenancyValidationException; +import java.util.Arrays; + import io.opentelemetry.api.trace.Span; import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; @@ -44,7 +46,8 @@ public JsonRpcResponse process( return method.response(request); } catch (final InvalidJsonRpcParameters e) { LOG.debug( - "Invalid Params for method: {}, error: {}", + "Invalid Params {} for method: {}, error: {}", + Arrays.toString(request.getRequest().getParams()), method.getName(), e.getRpcErrorType().getMessage(), e); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/TracedJsonRpcProcessor.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/TracedJsonRpcProcessor.java index 2a38afd630c..f86918b9b97 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/TracedJsonRpcProcessor.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/execution/TracedJsonRpcProcessor.java @@ -82,7 +82,6 @@ public JsonRpcResponse process( case INVALID_EXECUTION_REQUESTS_PARAMS: case INVALID_EXTRA_DATA_PARAMS: case INVALID_FILTER_PARAMS: - case INVALID_GAS_PRICE_PARAMS: case INVALID_HASH_RATE_PARAMS: case INVALID_ID_PARAMS: case INVALID_RETURN_COMPLETE_TRANSACTION_PARAMS: @@ -107,6 +106,7 @@ public JsonRpcResponse process( case INVALID_PROPOSAL_PARAMS: case INVALID_REMOTE_CAPABILITIES_PARAMS: case INVALID_REWARD_PERCENTILES_PARAMS: + case INVALID_REQUESTS_PARAMS: case INVALID_SEALER_ID_PARAMS: case INVALID_STORAGE_KEYS_PARAMS: case INVALID_SUBSCRIPTION_PARAMS: diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java index 8e826caf9e4..dc61b3bb27e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractEstimateGas.java @@ -16,10 +16,12 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonCallParameterUtil.validateAndGetCallParams; +import org.hyperledger.besu.datatypes.AccountOverrideMap; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter; @@ -28,6 +30,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.transaction.CallParameter; @@ -35,9 +38,12 @@ import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; import org.hyperledger.besu.evm.tracing.EstimateGasOperationTracer; +import org.hyperledger.besu.evm.tracing.OperationTracer; import java.util.Optional; +import com.google.common.annotations.VisibleForTesting; + public abstract class AbstractEstimateGas extends AbstractBlockParameterMethod { private static final double SUB_CALL_REMAINING_GAS_RATIO = 65D / 64D; @@ -60,7 +66,53 @@ protected BlockParameter blockParameter(final JsonRpcRequestContext request) { } } - protected Optional blockHeader(final long blockNumber) { + protected abstract Object simulate( + final JsonRpcRequestContext requestContext, + final CallParameter callParams, + final long gasLimit, + final TransactionSimulationFunction simulationFunction); + + @Override + protected Object pendingResult(final JsonRpcRequestContext requestContext) { + final JsonCallParameter jsonCallParameter = validateAndGetCallParams(requestContext); + final var validationParams = getTransactionValidationParams(jsonCallParameter); + final var maybeStateOverrides = getAddressAccountOverrideMap(requestContext); + final var pendingBlockHeader = transactionSimulator.simulatePendingBlockHeader(); + final TransactionSimulationFunction simulationFunction = + (cp, op) -> + transactionSimulator.processOnPending( + cp, maybeStateOverrides, validationParams, op, pendingBlockHeader); + return simulate( + requestContext, jsonCallParameter, pendingBlockHeader.getGasLimit(), simulationFunction); + } + + @Override + protected Object resultByBlockNumber( + final JsonRpcRequestContext requestContext, final long blockNumber) { + final JsonCallParameter jsonCallParameter = validateAndGetCallParams(requestContext); + final Optional maybeBlockHeader = blockHeader(blockNumber); + final Optional jsonRpcError = validateBlockHeader(maybeBlockHeader); + if (jsonRpcError.isPresent()) { + return errorResponse(requestContext, jsonRpcError.get()); + } + return resultByBlockHeader(requestContext, jsonCallParameter, maybeBlockHeader.get()); + } + + private Object resultByBlockHeader( + final JsonRpcRequestContext requestContext, + final JsonCallParameter jsonCallParameter, + final BlockHeader blockHeader) { + final var validationParams = getTransactionValidationParams(jsonCallParameter); + final var maybeStateOverrides = getAddressAccountOverrideMap(requestContext); + final TransactionSimulationFunction simulationFunction = + (cp, op) -> + transactionSimulator.process( + cp, maybeStateOverrides, validationParams, op, blockHeader); + return simulate( + requestContext, jsonCallParameter, blockHeader.getGasLimit(), simulationFunction); + } + + private Optional blockHeader(final long blockNumber) { if (getBlockchainQueries().headBlockNumber() == blockNumber) { // chain head header if cached, and we can return it form memory return Optional.of(getBlockchainQueries().getBlockchain().getChainHeadHeader()); @@ -68,8 +120,7 @@ protected Optional blockHeader(final long blockNumber) { return getBlockchainQueries().getBlockHeaderByNumber(blockNumber); } - protected Optional validateBlockHeader( - final Optional maybeBlockHeader) { + private Optional validateBlockHeader(final Optional maybeBlockHeader) { if (maybeBlockHeader.isEmpty()) { return Optional.of(RpcErrorType.BLOCK_NOT_FOUND); } @@ -83,25 +134,7 @@ protected Optional validateBlockHeader( return Optional.empty(); } - @Override - protected Object resultByBlockNumber( - final JsonRpcRequestContext requestContext, final long blockNumber) { - final JsonCallParameter jsonCallParameter = validateAndGetCallParams(requestContext); - final Optional maybeBlockHeader = blockHeader(blockNumber); - final Optional jsonRpcError = validateBlockHeader(maybeBlockHeader); - if (jsonRpcError.isPresent()) { - return errorResponse(requestContext, jsonRpcError.get()); - } - return resultByBlockHeader(requestContext, jsonCallParameter, maybeBlockHeader.get()); - } - - protected abstract Object resultByBlockHeader( - final JsonRpcRequestContext requestContext, - final JsonCallParameter jsonCallParameter, - final BlockHeader blockHeader); - - protected CallParameter overrideGasLimitAndPrice( - final JsonCallParameter callParams, final long gasLimit) { + protected CallParameter overrideGasLimit(final CallParameter callParams, final long gasLimit) { return new CallParameter( callParams.getChainId(), callParams.getFrom(), @@ -142,7 +175,7 @@ protected JsonRpcErrorResponse errorResponse( final ValidationResult validationResult = result.getValidationResult(); if (validationResult != null && !validationResult.isValid()) { - if (validationResult.getErrorMessage().length() > 0) { + if (!validationResult.getErrorMessage().isEmpty()) { return errorResponse(request, JsonRpcError.from(validationResult)); } return errorResponse( @@ -170,4 +203,29 @@ protected JsonRpcErrorResponse errorResponse( final JsonRpcRequestContext request, final JsonRpcError jsonRpcError) { return new JsonRpcErrorResponse(request.getRequest().getId(), jsonRpcError); } + + protected static TransactionValidationParams getTransactionValidationParams( + final JsonCallParameter callParams) { + final boolean isAllowExceedingBalance = !callParams.isMaybeStrict().orElse(Boolean.FALSE); + + return isAllowExceedingBalance + ? TransactionValidationParams.transactionSimulatorAllowExceedingBalance() + : TransactionValidationParams.transactionSimulator(); + } + + @VisibleForTesting + protected Optional getAddressAccountOverrideMap( + final JsonRpcRequestContext request) { + try { + return request.getOptionalParameter(2, AccountOverrideMap.class); + } catch (JsonRpcParameter.JsonRpcParameterException e) { + throw new InvalidJsonRpcRequestException( + "Invalid account overrides parameter (index 2)", RpcErrorType.INVALID_CALL_PARAMS, e); + } + } + + protected interface TransactionSimulationFunction { + Optional simulate( + CallParameter callParams, OperationTracer operationTracer); + } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java index 36991796b51..b7ec1449e95 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AbstractTraceByBlock.java @@ -33,7 +33,6 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.debug.TraceOptions; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; @@ -117,9 +116,7 @@ protocolSchedule, transactionTrace, block, new AtomicInteger(), false) } protected TransactionValidationParams buildTransactionValidationParams() { - return ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .build(); + return TransactionValidationParams.transactionSimulator(); } protected TraceOptions buildTraceOptions(final Set traceTypes) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugMetrics.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugMetrics.java index b5c74245ce4..c3eb1906f30 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugMetrics.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugMetrics.java @@ -50,9 +50,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { private void addObservation( final Map observations, final Observation observation) { final Map categoryObservations = - getNextMapLevel(observations, observation.getCategory().getName()); - if (observation.getLabels().isEmpty()) { - categoryObservations.put(observation.getMetricName(), observation.getValue()); + getNextMapLevel(observations, observation.category().getName()); + if (observation.labels().isEmpty()) { + categoryObservations.put(observation.metricName(), observation.value()); } else { addLabelledObservation(categoryObservations, observation); } @@ -60,12 +60,12 @@ private void addObservation( private void addLabelledObservation( final Map categoryObservations, final Observation observation) { - final List labels = observation.getLabels(); - Map values = getNextMapLevel(categoryObservations, observation.getMetricName()); + final List labels = observation.labels(); + Map values = getNextMapLevel(categoryObservations, observation.metricName()); for (int i = 0; i < labels.size() - 1; i++) { values = getNextMapLevel(values, labels.get(i)); } - values.put(labels.get(labels.size() - 1), observation.getValue()); + values.put(labels.get(labels.size() - 1), observation.value()); } @SuppressWarnings("unchecked") diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java index ef5c8c7a6cf..39a5c7487da 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCall.java @@ -35,7 +35,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; @@ -169,20 +168,18 @@ private JsonRpcErrorResponse errorResponse( private TransactionValidationParams buildTransactionValidationParams( final BlockHeader header, final JsonCallParameter callParams) { - ImmutableTransactionValidationParams.Builder transactionValidationParams = - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()); - + final boolean isAllowExceedingBalance; // if it is not set explicitly whether we want a strict check of the balance or not. this will // be decided according to the provided parameters if (callParams.isMaybeStrict().isEmpty()) { - transactionValidationParams.isAllowExceedingBalance( - isAllowExceedingBalanceAutoSelection(header, callParams)); + isAllowExceedingBalance = isAllowExceedingBalanceAutoSelection(header, callParams); + } else { - transactionValidationParams.isAllowExceedingBalance( - !callParams.isMaybeStrict().orElse(Boolean.FALSE)); + isAllowExceedingBalance = !callParams.isMaybeStrict().orElse(Boolean.FALSE); } - return transactionValidationParams.build(); + return isAllowExceedingBalance + ? TransactionValidationParams.transactionSimulatorAllowExceedingBalance() + : TransactionValidationParams.transactionSimulator(); } private boolean isAllowExceedingBalanceAutoSelection( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java index 2b8e79a81e9..7d4ba313cf1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessList.java @@ -18,13 +18,9 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.CreateAccessListResult; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; -import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; @@ -48,20 +44,24 @@ public String getName() { } @Override - protected Object resultByBlockHeader( + protected Object simulate( final JsonRpcRequestContext requestContext, - final JsonCallParameter jsonCallParameter, - final BlockHeader blockHeader) { - final AccessListSimulatorResult maybeResult = - processTransaction(jsonCallParameter, blockHeader); + final CallParameter callParams, + final long gasLimit, + final TransactionSimulationFunction simulationFunction) { + + final AccessListOperationTracer tracer = AccessListOperationTracer.create(); + final Optional firstResult = + simulationFunction.simulate(overrideGasLimit(callParams, gasLimit), tracer); + // if the call accessList is different from the simulation result, calculate gas and return - if (shouldProcessWithAccessListOverride(jsonCallParameter, maybeResult.tracer())) { + if (shouldProcessWithAccessListOverride(callParams, tracer)) { final AccessListSimulatorResult result = processTransactionWithAccessListOverride( - jsonCallParameter, blockHeader, maybeResult.tracer().getAccessList()); + callParams, gasLimit, tracer.getAccessList(), simulationFunction); return createResponse(requestContext, result); } else { - return createResponse(requestContext, maybeResult); + return createResponse(requestContext, new AccessListSimulatorResult(firstResult, tracer)); } } @@ -73,16 +73,8 @@ private Object createResponse( .orElseGet(() -> errorResponse(requestContext, RpcErrorType.INTERNAL_ERROR)); } - private TransactionValidationParams transactionValidationParams( - final boolean isAllowExceedingBalance) { - return ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(isAllowExceedingBalance) - .build(); - } - private boolean shouldProcessWithAccessListOverride( - final JsonCallParameter parameters, final AccessListOperationTracer tracer) { + final CallParameter parameters, final AccessListOperationTracer tracer) { // if empty, transaction did not access any storage, does not need to reprocess if (tracer.getAccessList().isEmpty()) { @@ -107,39 +99,23 @@ private Function createResponse( : errorResponse(request, result); } - private AccessListSimulatorResult processTransaction( - final JsonCallParameter jsonCallParameter, final BlockHeader blockHeader) { - final TransactionValidationParams transactionValidationParams = - transactionValidationParams(!jsonCallParameter.isMaybeStrict().orElse(Boolean.FALSE)); - - final CallParameter callParams = - overrideGasLimitAndPrice(jsonCallParameter, blockHeader.getGasLimit()); - - final AccessListOperationTracer tracer = AccessListOperationTracer.create(); - final Optional result = - transactionSimulator.process(callParams, transactionValidationParams, tracer, blockHeader); - return new AccessListSimulatorResult(result, tracer); - } - private AccessListSimulatorResult processTransactionWithAccessListOverride( - final JsonCallParameter jsonCallParameter, - final BlockHeader blockHeader, - final List accessList) { - final TransactionValidationParams transactionValidationParams = - transactionValidationParams(!jsonCallParameter.isMaybeStrict().orElse(Boolean.FALSE)); + final CallParameter callParameter, + final long gasLimit, + final List accessList, + final TransactionSimulationFunction simulationFunction) { final AccessListOperationTracer tracer = AccessListOperationTracer.create(); - final CallParameter callParameter = - overrideAccessList(jsonCallParameter, blockHeader.getGasLimit(), accessList); + final CallParameter modifiedCallParameter = + overrideAccessList(callParameter, gasLimit, accessList); final Optional result = - transactionSimulator.process( - callParameter, transactionValidationParams, tracer, blockHeader); + simulationFunction.simulate(modifiedCallParameter, tracer); return new AccessListSimulatorResult(result, tracer); } - protected CallParameter overrideAccessList( - final JsonCallParameter callParams, + private CallParameter overrideAccessList( + final CallParameter callParams, final long gasLimit, final List accessListEntries) { return new CallParameter( @@ -151,7 +127,7 @@ protected CallParameter overrideAccessList( callParams.getMaxFeePerGas(), callParams.getValue(), callParams.getPayload(), - Optional.ofNullable(accessListEntries)); + Optional.of(accessListEntries)); } private record AccessListSimulatorResult( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java index 2352a5a8c37..05d5f78e0ff 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGas.java @@ -14,19 +14,12 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; -import org.hyperledger.besu.datatypes.AccountOverrideMap; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; -import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; -import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.transaction.CallParameter; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult; @@ -34,7 +27,6 @@ import java.util.Optional; -import com.google.common.annotations.VisibleForTesting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,33 +44,17 @@ public String getName() { } @Override - protected Object resultByBlockHeader( + protected Object simulate( final JsonRpcRequestContext requestContext, - final JsonCallParameter callParams, - final BlockHeader blockHeader) { - - final CallParameter modifiedCallParams = - overrideGasLimitAndPrice(callParams, blockHeader.getGasLimit()); - Optional maybeStateOverrides = getAddressAccountOverrideMap(requestContext); - // TODO implement for block overrides - - final boolean isAllowExceedingBalance = !callParams.isMaybeStrict().orElse(Boolean.FALSE); + final CallParameter callParams, + final long gasLimit, + final TransactionSimulationFunction simulationFunction) { final EstimateGasOperationTracer operationTracer = new EstimateGasOperationTracer(); - final var transactionValidationParams = - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(isAllowExceedingBalance) - .build(); - LOG.debug("Processing transaction with params: {}", modifiedCallParams); + LOG.debug("Processing transaction with params: {}", callParams); final var maybeResult = - transactionSimulator.process( - modifiedCallParams, - maybeStateOverrides, - transactionValidationParams, - operationTracer, - blockHeader); + simulationFunction.simulate(overrideGasLimit(callParams, gasLimit), operationTracer); final Optional maybeErrorResponse = validateSimulationResult(requestContext, maybeResult); @@ -89,12 +65,7 @@ protected Object resultByBlockHeader( final var result = maybeResult.get(); long low = result.result().getEstimateGasUsedByTransaction(); final var lowResult = - transactionSimulator.process( - overrideGasLimitAndPrice(callParams, low), - maybeStateOverrides, - transactionValidationParams, - operationTracer, - blockHeader); + simulationFunction.simulate(overrideGasLimit(callParams, low), operationTracer); if (lowResult.isPresent() && lowResult.get().isSuccessful()) { return Quantity.create(low); @@ -106,12 +77,7 @@ protected Object resultByBlockHeader( while (low + 1 < high) { mid = (low + high) / 2; var binarySearchResult = - transactionSimulator.process( - overrideGasLimitAndPrice(callParams, mid), - maybeStateOverrides, - transactionValidationParams, - operationTracer, - blockHeader); + simulationFunction.simulate(overrideGasLimit(callParams, mid), operationTracer); if (binarySearchResult.isEmpty() || !binarySearchResult.get().isSuccessful()) { low = mid; @@ -139,15 +105,4 @@ private Optional validateSimulationResult( } return Optional.empty(); } - - @VisibleForTesting - protected Optional getAddressAccountOverrideMap( - final JsonRpcRequestContext request) { - try { - return request.getOptionalParameter(2, AccountOverrideMap.class); - } catch (JsonRpcParameter.JsonRpcParameterException e) { - throw new InvalidJsonRpcRequestException( - "Invalid account overrides parameter (index 2)", RpcErrorType.INVALID_CALL_PARAMS, e); - } - } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java index 2c5c6afd055..50c499bca47 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthFeeHistory.java @@ -18,13 +18,13 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockReceipts.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockReceipts.java index 819ac5e1eb4..aaa2fa7e082 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockReceipts.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetBlockReceipts.java @@ -27,13 +27,11 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.TransactionReceiptStatusResult; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.TransactionReceiptWithMetadata; -import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.TransactionReceiptType; import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; import com.google.common.base.Suppliers; @@ -70,35 +68,21 @@ protected Object resultByBlockHash(final JsonRpcRequestContext request, final Ha } /* - * For a given transaction, get its receipt and if it exists, wrap in a transaction receipt of the correct type + * For a given block, get receipts of transactions in the block and if they exist, wrap in transaction receipts of the correct type */ - private Optional txReceipt(final TransactionWithMetadata tx) { - Optional receipt = - blockchainQueries - .get() - .transactionReceiptByTransactionHash(tx.getTransaction().getHash(), protocolSchedule); - if (receipt.isPresent()) { - if (receipt.get().getReceipt().getTransactionReceiptType() == TransactionReceiptType.ROOT) { - return Optional.of(new TransactionReceiptRootResult(receipt.get())); - } else { - return Optional.of(new TransactionReceiptStatusResult(receipt.get())); - } - } - return Optional.empty(); - } - private BlockReceiptsResult getBlockReceiptsResult(final Hash blockHash) { final List receiptList = blockchainQueries .get() - .blockByHash(blockHash) + .transactionReceiptsByBlockHash(blockHash, protocolSchedule) + .orElse(new ArrayList()) + .stream() .map( - block -> - block.getTransactions().stream() - .map(this::txReceipt) - .flatMap(Optional::stream) - .collect(Collectors.toList())) - .orElse(new ArrayList<>()); + receipt -> + receipt.getReceipt().getTransactionReceiptType() == TransactionReceiptType.ROOT + ? new TransactionReceiptRootResult(receipt) + : new TransactionReceiptStatusResult(receipt)) + .collect(Collectors.toList()); return new BlockReceiptsResult(receiptList); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java index 8b54364a999..8fc3e6d732a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockHash.java @@ -29,6 +29,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.MinerDataResult.UncleRewardResult; import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.api.query.TransactionReceiptWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -41,6 +42,7 @@ import com.google.common.base.Suppliers; import org.apache.tuweni.units.bigints.BaseUInt256Value; +@Deprecated(since = "24.12.0") public class EthGetMinerDataByBlockHash implements JsonRpcMethod { private final Supplier blockchain; private final ProtocolSchedule protocolSchedule; @@ -90,19 +92,16 @@ public static MinerDataResult createMinerDataResult( final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(blockHeader); final Wei staticBlockReward = protocolSpec.getBlockReward(); final Wei transactionFee = - block.getTransactions().stream() + blockchainQueries + .transactionReceiptsByBlockHash(blockHeader.getHash(), protocolSchedule) + .orElse(new ArrayList()) + .stream() .map( - t -> - blockchainQueries - .transactionReceiptByTransactionHash( - t.getTransaction().getHash(), protocolSchedule) - .map( - receipt -> - receipt - .getTransaction() - .getEffectiveGasPrice(receipt.getBaseFee()) - .multiply(receipt.getGasUsed())) - .orElse(Wei.ZERO)) + receipt -> + receipt + .getTransaction() + .getEffectivePriorityFeePerGas(receipt.getBaseFee()) + .multiply(receipt.getGasUsed())) .reduce(Wei.ZERO, BaseUInt256Value::add); final Wei uncleInclusionReward = staticBlockReward.multiply(block.getOmmers().size()).divide(32); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockNumber.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockNumber.java index e0fe2460626..7782b79085a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockNumber.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetMinerDataByBlockNumber.java @@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +@Deprecated(since = "24.12.0") public class EthGetMinerDataByBlockNumber extends AbstractBlockParameterMethod { private final ProtocolSchedule protocolSchedule; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java index a171fc16d1d..22de0da4446 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetStorageAt.java @@ -16,12 +16,12 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.parameters.UInt256Parameter; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameterOrBlockHash; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UInt256Parameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockHashAndIndex.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockHashAndIndex.java index 917c09a3265..54a9aba09cc 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockHashAndIndex.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockHashAndIndex.java @@ -15,11 +15,11 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockNumberAndIndex.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockNumberAndIndex.java index 338a8783688..1aad570a5df 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockNumberAndIndex.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetTransactionByBlockNumberAndIndex.java @@ -14,12 +14,12 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; +import org.hyperledger.besu.datatypes.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.TransactionCompleteResult; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockHashAndIndex.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockHashAndIndex.java index f76b461ceff..167c6587816 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockHashAndIndex.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockHashAndIndex.java @@ -15,11 +15,11 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockNumberAndIndex.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockNumberAndIndex.java index f7c9ecb0dd9..2cab8792597 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockNumberAndIndex.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetUncleByBlockNumberAndIndex.java @@ -14,12 +14,12 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods; +import org.hyperledger.besu.datatypes.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedIntParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.BlockResult; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.UncleBlockResult; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetWork.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetWork.java index 5c9a413eb3a..e376b54acb4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetWork.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthGetWork.java @@ -35,6 +35,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Deprecated(since = "24.12.0") public class EthGetWork implements JsonRpcMethod { private final MiningCoordinator miner; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthHashrate.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthHashrate.java index 855a757562f..c21c12834a4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthHashrate.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthHashrate.java @@ -23,6 +23,7 @@ import java.util.Optional; +@Deprecated(since = "24.12.0") public class EthHashrate implements JsonRpcMethod { private final MiningCoordinator miningCoordinator; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitHashRate.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitHashRate.java index 488f89b3a58..c93263c4986 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitHashRate.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitHashRate.java @@ -25,6 +25,7 @@ import org.apache.tuweni.bytes.Bytes; +@Deprecated(since = "24.12.0") public class EthSubmitHashRate implements JsonRpcMethod { private final MiningCoordinator miningCoordinator; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitWork.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitWork.java index 9002b2a0ddf..59adf311dca 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitWork.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthSubmitWork.java @@ -33,6 +33,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +@Deprecated(since = "24.12.0") public class EthSubmitWork implements JsonRpcMethod { private final MiningCoordinator miner; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java index db062a64d95..9f596b8a436 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/ExecuteTransactionStep.java @@ -26,9 +26,8 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; 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.ethereum.vm.DebugOperationTracer; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import java.util.List; import java.util.Optional; @@ -95,7 +94,8 @@ public TransactionTrace apply(final TransactionTrace transactionTrace) { maybeParentHeader .map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent)) .orElse(BlobGas.ZERO)); - final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(header, blockchain); + final BlockHashLookup blockHashLookup = + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, header); result = transactionProcessor.processTransaction( chainUpdater.getNextUpdater(), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/JsonCallParameterUtil.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/JsonCallParameterUtil.java index df593f9fbc3..6c73e99a9c9 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/JsonCallParameterUtil.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/JsonCallParameterUtil.java @@ -20,7 +20,13 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; +import java.util.Arrays; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class JsonCallParameterUtil { + private static final Logger LOG = LoggerFactory.getLogger(JsonCallParameterUtil.class); private JsonCallParameterUtil() {} @@ -36,9 +42,14 @@ public static JsonCallParameter validateAndGetCallParams(final JsonRpcRequestCon if (callParams.getGasPrice() != null && (callParams.getMaxFeePerGas().isPresent() || callParams.getMaxPriorityFeePerGas().isPresent())) { - throw new InvalidJsonRpcParameters( - "gasPrice cannot be used with maxFeePerGas or maxPriorityFeePerGas", - RpcErrorType.INVALID_GAS_PRICE_PARAMS); + try { + LOG.debug( + "gasPrice will be ignored since 1559 values are defined (maxFeePerGas or maxPriorityFeePerGas). {}", + Arrays.toString(request.getRequest().getParams())); + } catch (Exception e) { + LOG.debug( + "gasPrice will be ignored since 1559 values are defined (maxFeePerGas or maxPriorityFeePerGas)"); + } } return callParams; } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java index 1601241db62..aba51eb7a69 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/TraceCallMany.java @@ -116,8 +116,7 @@ protected Object resultByBlockNumber( .getAndMapWorldState( blockHeader.getBlockHash(), ws -> { - final WorldUpdater updater = - transactionSimulator.getEffectiveWorldStateUpdater(blockHeader, ws); + final WorldUpdater updater = transactionSimulator.getEffectiveWorldStateUpdater(ws); try { Arrays.stream(transactionsAndTraceTypeParameters) .forEachOrdered( @@ -158,6 +157,11 @@ private JsonNode getSingleCallResult( final Set traceTypes = traceTypeParameter.getTraceTypes(); final DebugOperationTracer tracer = new DebugOperationTracer(buildTraceOptions(traceTypes), false); + final var miningBeneficiary = + protocolSchedule + .getByBlockHeader(header) + .getMiningBeneficiaryCalculator() + .calculateBeneficiary(header); final Optional maybeSimulatorResult = transactionSimulator.processWithWorldUpdater( callParameter, @@ -165,7 +169,8 @@ private JsonNode getSingleCallResult( buildTransactionValidationParams(), tracer, header, - worldUpdater); + worldUpdater, + miningBeneficiary); LOG.trace("Executing {} call for transaction {}", traceTypeParameter, callParameter); if (maybeSimulatorResult.isEmpty()) { diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java index 11ec3d04c59..727677aa8ed 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineForkchoiceUpdated.java @@ -389,8 +389,7 @@ protected RpcErrorType getInvalidPayloadAttributesError() { // fcU calls are synchronous, no need to make volatile private long lastFcuInfoLog = System.currentTimeMillis(); - private static final String logMessage = - "{} for fork-choice-update: head: {}, finalized: {}, safeBlockHash: {}"; + private static final String logMessage = "FCU({}) | head: {} | finalized: {} | safeBlockHash: {}"; private void logForkchoiceUpdatedCall( final EngineStatus status, final EngineForkchoiceUpdatedParameter forkChoice) { @@ -413,9 +412,9 @@ private void logAtInfo( LOG.info( logMessage, status.name(), - forkChoice.getHeadBlockHash(), - forkChoice.getFinalizedBlockHash(), - forkChoice.getSafeBlockHash()); + forkChoice.getHeadBlockHash().toShortLogString(), + forkChoice.getFinalizedBlockHash().toShortLogString(), + forkChoice.getSafeBlockHash().toShortLogString()); } private void logAtDebug( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java index 6369a53cdf3..15caa56219e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayload.java @@ -25,7 +25,6 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine.WithdrawalsValidatorProvider.getWithdrawalsValidator; import org.hyperledger.besu.consensus.merge.blockcreation.MergeMiningCoordinator; -import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.RequestType; @@ -236,20 +235,8 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) blockParam.getTransactions().stream() .map(Bytes::fromHexString) .map(in -> TransactionDecoder.decodeOpaqueBytes(in, EncodingContext.BLOCK_BODY)) - .collect(Collectors.toList()); - transactions.forEach( - transaction -> - mergeCoordinator - .getEthScheduler() - .scheduleTxWorkerTask( - () -> { - Address sender = transaction.getSender(); - LOG.atTrace() - .setMessage("The sender for transaction {} is calculated : {}") - .addArgument(transaction::getHash) - .addArgument(sender) - .log(); - })); + .toList(); + precomputeSenders(transactions); } catch (final RLPException | IllegalArgumentException e) { return respondWithInvalid( reqId, @@ -385,7 +372,8 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) .flatMap(Optional::stream) .mapToInt(List::size) .sum(), - (System.currentTimeMillis() - startTimeMs) / 1000.0); + (System.currentTimeMillis() - startTimeMs) / 1000.0, + executionResult.getNbParallelizedTransations()); // TODO Added this line to accelerate block import, should be removed later mergeCoordinator.updateForkChoice( newBlockHeader, newBlockHeader.getBlockHash(), newBlockHeader.getBlockHash()); @@ -409,6 +397,47 @@ public JsonRpcResponse syncResponse(final JsonRpcRequestContext requestContext) } } + private void precomputeSenders(final List transactions) { + transactions.forEach( + transaction -> { + mergeCoordinator + .getEthScheduler() + .scheduleTxWorkerTask( + () -> { + final var sender = transaction.getSender(); + LOG.atTrace() + .setMessage("The sender for transaction {} is calculated : {}") + .addArgument(transaction::getHash) + .addArgument(sender) + .log(); + }); + if (transaction.getType().supportsDelegateCode()) { + precomputeAuthorities(transaction); + } + }); + } + + private void precomputeAuthorities(final Transaction transaction) { + final var codeDelegations = transaction.getCodeDelegationList().get(); + int index = 0; + for (final var codeDelegation : codeDelegations) { + final var constIndex = index++; + mergeCoordinator + .getEthScheduler() + .scheduleTxWorkerTask( + () -> { + final var authority = codeDelegation.authorizer(); + LOG.atTrace() + .setMessage( + "The code delegation authority at index {} for transaction {} is calculated : {}") + .addArgument(constIndex) + .addArgument(transaction::getHash) + .addArgument(authority) + .log(); + }); + } + } + JsonRpcResponse respondWith( final Object requestId, final EnginePayloadParameter param, @@ -582,26 +611,41 @@ private Optional> extractRequests(final Optional> may .collect(Collectors.toList())); } - private void logImportedBlockInfo(final Block block, final int blobCount, final double timeInS) { + private void logImportedBlockInfo( + final Block block, + final int blobCount, + final double timeInS, + final Optional nbParallelizedTransations) { final StringBuilder message = new StringBuilder(); - message.append("Imported #%,d / %d tx"); + final int nbTransactions = block.getBody().getTransactions().size(); + message.append("Imported #%,d (%s)|%5d tx"); final List messageArgs = new ArrayList<>( - List.of(block.getHeader().getNumber(), block.getBody().getTransactions().size())); + List.of( + block.getHeader().getNumber(), block.getHash().toShortLogString(), nbTransactions)); if (block.getBody().getWithdrawals().isPresent()) { - message.append(" / %d ws"); + message.append("|%3d ws"); messageArgs.add(block.getBody().getWithdrawals().get().size()); } - message.append(" / %d blobs / base fee %s / %,d (%01.1f%%) gas / (%s) in %01.3fs. Peers: %d"); + double mgasPerSec = (timeInS != 0) ? block.getHeader().getGasUsed() / (timeInS * 1_000_000) : 0; + message.append( + "|%2d blobs| base fee %s| gas used %,11d (%5.1f%%)| exec time %01.3fs| mgas/s %6.2f"); messageArgs.addAll( List.of( blobCount, - block.getHeader().getBaseFee().map(Wei::toHumanReadableString).orElse("N/A"), + block.getHeader().getBaseFee().map(Wei::toHumanReadablePaddedString).orElse("N/A"), block.getHeader().getGasUsed(), (block.getHeader().getGasUsed() * 100.0) / block.getHeader().getGasLimit(), - block.getHash().toHexString(), timeInS, - ethPeers.peerCount())); + mgasPerSec)); + if (nbParallelizedTransations.isPresent()) { + double parallelizedTxPercentage = + (double) (nbParallelizedTransations.get() * 100) / nbTransactions; + message.append("| parallel txs %5.1f%%"); + messageArgs.add(parallelizedTxPercentage); + } + message.append("| peers: %2d"); + messageArgs.add(ethPeers.peerCount()); LOG.info(String.format(message.toString(), messageArgs.toArray())); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadBodiesByRangeV1.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadBodiesByRangeV1.java index 2d21a7282ae..0dde728f57a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadBodiesByRangeV1.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineGetPayloadBodiesByRangeV1.java @@ -14,13 +14,13 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.engine; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStart.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStart.java index ca8c341823e..33a0793d907 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStart.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStart.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.blockcreation.CoinbaseNotSetException; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; +@Deprecated(since = "24.12.0") public class MinerStart implements JsonRpcMethod { private final MiningCoordinator miningCoordinator; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStop.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStop.java index 267fe0877b9..a30b0e35497 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStop.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/miner/MinerStop.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator; +@Deprecated(since = "24.12.0") public class MinerStop implements JsonRpcMethod { private final MiningCoordinator miningCoordinator; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockOverridesParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockOverridesParameter.java new file mode 100644 index 00000000000..9cd6e880b42 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/BlockOverridesParameter.java @@ -0,0 +1,76 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; +import org.hyperledger.besu.plugin.data.BlockOverrides; + +import java.math.BigInteger; +import java.util.Optional; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; + +public class BlockOverridesParameter extends BlockOverrides { + /** + * Constructs a new BlockOverrides instance. + * + * @param timestamp the optional timestamp + * @param blockNumber the optional block number + * @param blockHash the optional block hash + * @param prevRandao the optional previous Randao + * @param gasLimit the optional gas limit + * @param feeRecipient the optional fee recipient + * @param baseFeePerGas the optional base fee per gas + * @param blobBaseFee the optional blob base fee + * @param stateRoot the optional state root + * @param difficulty the optional difficulty + * @param extraData the optional extra data + * @param mixHashOrPrevRandao the optional mix hash or previous Randao + */ + @JsonCreator + public BlockOverridesParameter( + @JsonProperty("time") final Optional timestamp, + @JsonProperty("number") final Optional blockNumber, + @JsonProperty("hash") final Optional blockHash, + @JsonProperty("prevRandao") final Optional prevRandao, + @JsonProperty("gasLimit") final Optional gasLimit, + @JsonProperty("feeRecipient") final Optional
feeRecipient, + @JsonProperty("baseFeePerGas") final Optional baseFeePerGas, + @JsonProperty("blobBaseFee") final Optional blobBaseFee, + @JsonProperty("stateRoot") final Optional stateRoot, + @JsonProperty("difficulty") final Optional difficulty, + @JsonProperty("extraData") final Optional extraData, + @JsonProperty("mixHashOrPrevRandao") final Optional mixHashOrPrevRandao) { + super( + timestamp, + blockNumber, + blockHash, + prevRandao, + gasLimit, + feeRecipient, + baseFeePerGas, + blobBaseFee, + stateRoot, + difficulty, + extraData, + mixHashOrPrevRandao); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExchangeTransitionConfigurationParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExchangeTransitionConfigurationParameter.java index 2f8e2be8e00..3258c4f9d67 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExchangeTransitionConfigurationParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EngineExchangeTransitionConfigurationParameter.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.core.Difficulty; import com.fasterxml.jackson.annotation.JsonCreator; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java index a6730689689..a41b06cecc1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePayloadParameter.java @@ -17,6 +17,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.evm.log.LogsBloomFilter; import java.util.List; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java index 2ce52341028..1485209d593 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/EnginePreparePayloadParameter.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import java.util.Collections; import java.util.List; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/DisabledPrivacyRpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/DisabledPrivacyRpcMethod.java index 04e7dd4067b..359ff3f8136 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/DisabledPrivacyRpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/DisabledPrivacyRpcMethod.java @@ -20,7 +20,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class DisabledPrivacyRpcMethod implements JsonRpcMethod { private final String methodName; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyRpcMethodDecorator.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyRpcMethodDecorator.java index 3f7a87c7f45..b8a21d22510 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyRpcMethodDecorator.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyRpcMethodDecorator.java @@ -27,7 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class MultiTenancyRpcMethodDecorator implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(MultiTenancyRpcMethodDecorator.class); private final JsonRpcMethod rpcMethod; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyUserUtil.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyUserUtil.java index 54daee347dc..87c9958f46c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyUserUtil.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/MultiTenancyUserUtil.java @@ -18,7 +18,7 @@ import io.vertx.ext.auth.User; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class MultiTenancyUserUtil { private static final String PRIVACY_USER_ID_CLAIM = "privacyUserId"; private static final String ENCLAVE_PRIVACY_PUBLIC_KEY_CLAIM = "privacyPublicKey"; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterChanges.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterChanges.java index 9175464fe2e..10a74cfd8bd 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterChanges.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterChanges.java @@ -31,7 +31,7 @@ import java.util.List; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetFilterChanges implements JsonRpcMethod { private final PrivacyController privacyController; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterLogs.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterLogs.java index bf497d41aab..b5c96f4d477 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterLogs.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivGetFilterLogs.java @@ -31,7 +31,7 @@ import java.util.List; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetFilterLogs implements JsonRpcMethod { private final PrivacyController privacyController; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivUninstallFilter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivUninstallFilter.java index aeaa2613b08..48ab850baa3 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivUninstallFilter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivUninstallFilter.java @@ -26,7 +26,7 @@ import org.hyperledger.besu.ethereum.privacy.MultiTenancyPrivacyController; import org.hyperledger.besu.ethereum.privacy.PrivacyController; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivUninstallFilter implements JsonRpcMethod { private final FilterManager filterManager; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivacyIdProvider.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivacyIdProvider.java index d59a64b0bab..338510aec2d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivacyIdProvider.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivacyIdProvider.java @@ -23,7 +23,7 @@ import io.vertx.ext.auth.User; @FunctionalInterface -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public interface PrivacyIdProvider { String getPrivacyUserId(Optional user); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java index b8e78621ef2..3eabd84c41c 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java @@ -48,7 +48,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(AbstractEeaSendRawTransaction.class); private final TransactionPool transactionPool; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/JsonRpcErrorResponseException.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/JsonRpcErrorResponseException.java index 7b22ebcef1d..ec856205903 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/JsonRpcErrorResponseException.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/JsonRpcErrorResponseException.java @@ -16,7 +16,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class JsonRpcErrorResponseException extends RuntimeException { private final RpcErrorType jsonRpcError; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java index 513d0fa351f..146ef2c722d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java @@ -33,7 +33,7 @@ import io.vertx.ext.auth.User; import org.apache.tuweni.bytes.Bytes; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PluginEeaSendRawTransaction extends AbstractEeaSendRawTransaction { private final PrivacyController privacyController; private final PrivacyIdProvider privacyIdProvider; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedFlexibleEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedFlexibleEeaSendRawTransaction.java index 6c300fbc301..0d2aa9d94b6 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedFlexibleEeaSendRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedFlexibleEeaSendRawTransaction.java @@ -37,7 +37,7 @@ import io.vertx.ext.auth.User; import org.apache.tuweni.bytes.Bytes; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class RestrictedFlexibleEeaSendRawTransaction extends AbstractEeaSendRawTransaction { private final PrivacyController privacyController; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffchainEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffchainEeaSendRawTransaction.java index de467e31bcc..1c2a9fdd8ab 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffchainEeaSendRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffchainEeaSendRawTransaction.java @@ -35,7 +35,7 @@ import io.vertx.ext.auth.User; import org.apache.tuweni.bytes.Bytes; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class RestrictedOffchainEeaSendRawTransaction extends AbstractEeaSendRawTransaction { final PrivacyController privacyController; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/AbstractPrivateTraceByHash.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/AbstractPrivateTraceByHash.java index 209d5bf3bf4..8852cac0d0d 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/AbstractPrivateTraceByHash.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/AbstractPrivateTraceByHash.java @@ -41,7 +41,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public abstract class AbstractPrivateTraceByHash implements JsonRpcMethod { protected final Supplier blockTracerSupplier; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCall.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCall.java index 5be9a9f2ab6..08e70df50f0 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCall.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCall.java @@ -33,7 +33,7 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivCall extends AbstractBlockParameterMethod { private final PrivacyIdProvider privacyIdProvider; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroup.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroup.java index 09ff5b19f96..f90dedc9a57 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroup.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroup.java @@ -32,7 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivCreatePrivacyGroup implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivCreatePrivacyGroup.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDebugGetStateRoot.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDebugGetStateRoot.java index d8c411c0853..8ea6729259f 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDebugGetStateRoot.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDebugGetStateRoot.java @@ -39,7 +39,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivDebugGetStateRoot extends AbstractBlockParameterMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivDebugGetStateRoot.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDeletePrivacyGroup.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDeletePrivacyGroup.java index 73849eb92e5..bce6ab850d1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDeletePrivacyGroup.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDeletePrivacyGroup.java @@ -32,7 +32,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivDeletePrivacyGroup implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivDeletePrivacyGroup.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDistributeRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDistributeRawTransaction.java index 7375590d55c..017af626aa7 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDistributeRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDistributeRawTransaction.java @@ -48,7 +48,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivDistributeRawTransaction implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivDistributeRawTransaction.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivFindPrivacyGroup.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivFindPrivacyGroup.java index e41728b044e..0c200702c90 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivFindPrivacyGroup.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivFindPrivacyGroup.java @@ -37,7 +37,7 @@ import org.slf4j.LoggerFactory; @SuppressWarnings("MockNotUsedInProduction") -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivFindPrivacyGroup implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivFindPrivacyGroup.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetCode.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetCode.java index da3179834f0..ec6a11d115e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetCode.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetCode.java @@ -28,7 +28,7 @@ import org.apache.tuweni.bytes.Bytes; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetCode extends AbstractBlockParameterMethod { private final PrivacyController privacyController; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetEeaTransactionCount.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetEeaTransactionCount.java index e35ad79da77..b751db900d2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetEeaTransactionCount.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetEeaTransactionCount.java @@ -42,7 +42,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetEeaTransactionCount implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivGetEeaTransactionCount.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetLogs.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetLogs.java index 735eb9bf9d9..ef68e610b68 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetLogs.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetLogs.java @@ -38,7 +38,7 @@ import java.util.List; import java.util.Optional; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetLogs implements JsonRpcMethod { private final BlockchainQueries blockchainQueries; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivacyPrecompileAddress.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivacyPrecompileAddress.java index 46e52525bea..6b096db17f5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivacyPrecompileAddress.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivacyPrecompileAddress.java @@ -22,7 +22,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.core.PrivacyParameters; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetPrivacyPrecompileAddress implements JsonRpcMethod { private final Address privacyAddress; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransaction.java index 4419b82d50e..234c279d6b9 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransaction.java @@ -38,7 +38,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetPrivateTransaction implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivGetPrivateTransaction.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionCount.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionCount.java index fc547e88640..ce7a8806816 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionCount.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionCount.java @@ -34,7 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetTransactionCount implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivGetTransactionCount.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceipt.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceipt.java index b7c7f25b4dd..702c228cd35 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceipt.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceipt.java @@ -43,7 +43,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivGetTransactionReceipt implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivGetTransactionReceipt.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivNewFilter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivNewFilter.java index bd2ece37b94..9e1893620fe 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivNewFilter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivNewFilter.java @@ -29,7 +29,7 @@ import org.hyperledger.besu.ethereum.privacy.MultiTenancyPrivacyController; import org.hyperledger.besu.ethereum.privacy.PrivacyController; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivNewFilter implements JsonRpcMethod { private final FilterManager filterManager; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivTraceTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivTraceTransaction.java index f044b39f774..dc59233ad5e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivTraceTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivTraceTransaction.java @@ -43,7 +43,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivTraceTransaction extends AbstractPrivateTraceByHash implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(TraceTransaction.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivUtil.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivUtil.java index a3ca662fd12..79c6da00367 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivUtil.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivUtil.java @@ -20,7 +20,7 @@ import java.util.Optional; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivUtil { public static void checkMembershipForAuthenticatedUser( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/privx/PrivxFindFlexiblePrivacyGroup.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/privx/PrivxFindFlexiblePrivacyGroup.java index 925dc4ec65d..b8377760ed1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/privx/PrivxFindFlexiblePrivacyGroup.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/privx/PrivxFindFlexiblePrivacyGroup.java @@ -36,7 +36,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivxFindFlexiblePrivacyGroup implements JsonRpcMethod { private static final Logger LOG = LoggerFactory.getLogger(PrivxFindFlexiblePrivacyGroup.class); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/parameters/CreatePrivacyGroupParameter.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/parameters/CreatePrivacyGroupParameter.java index c66f754d203..bd19035ddcd 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/parameters/CreatePrivacyGroupParameter.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/parameters/CreatePrivacyGroupParameter.java @@ -20,7 +20,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class CreatePrivacyGroupParameter { private final List addresses; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java index b1a9be021e9..ddd09c28a65 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockReplay.java @@ -30,8 +30,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import java.util.List; import java.util.Optional; @@ -90,7 +89,8 @@ public Optional beforeTransactionInBlock( return performActionWithBlock( blockHash, (body, header, blockchain, transactionProcessor, protocolSpec) -> { - final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(header, blockchain); + final BlockHashLookup blockHashLookup = + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, header); final Wei blobGasPrice = protocolSpec .getFeeMarket() @@ -137,7 +137,7 @@ public Optional afterTransactionInBlock( blockHeader, transaction, spec.getMiningBeneficiaryCalculator().calculateBeneficiary(blockHeader), - new CachingBlockHashLookup(blockHeader, blockchain), + spec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader), false, TransactionValidationParams.blockReplay(), blobGasPrice); @@ -180,6 +180,10 @@ private Optional getBlock(final Hash blockHash) { return Optional.empty(); } + public ProtocolSpec getProtocolSpec(final BlockHeader header) { + return protocolSchedule.getByBlockHeader(header); + } + @FunctionalInterface public interface BlockAction { Optional perform( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java index 5ede2d4a7b2..67395c6999e 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.debug.TraceFrame; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -69,7 +68,10 @@ private BlockReplay.TransactionAction prepareReplayAction( transaction, header.getCoinbase(), tracer, - new CachingBlockHashLookup(header, blockchain), + blockReplay + .getProtocolSpec(header) + .getBlockHashProcessor() + .createBlockHashLookup(blockchain, header), false, blobGasPrice); final List traceFrames = tracer.copyTraceFrames(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java index 6524109ac6f..8416b499bc2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java @@ -29,7 +29,6 @@ import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.tracing.StandardJsonTracer; @@ -192,7 +191,10 @@ private TransactionProcessingResult processTransaction( transaction, header.getCoinbase(), tracer, - new CachingBlockHashLookup(header, blockchain), + blockReplay + .getProtocolSpec(header) + .getBlockHashProcessor() + .createBlockHashLookup(blockchain, header), false, ImmutableTransactionValidationParams.builder().isAllowFutureNonce(true).build(), blobGasPrice); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockReplay.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockReplay.java index de5c11940b5..80721c90cbd 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockReplay.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockReplay.java @@ -89,6 +89,10 @@ private Optional performActionWithBlock( return action.perform(body, header, blockchain, transactionProcessor, protocolSpec); } + public ProtocolSpec getProtocolSpec(final BlockHeader header) { + return protocolSchedule.getByBlockHeader(header); + } + @FunctionalInterface public interface BlockAction { Optional perform( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockTracer.java index c58af8fc3fc..cbf4870f903 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/privateProcessor/PrivateBlockTracer.java @@ -18,7 +18,6 @@ import org.hyperledger.besu.ethereum.debug.TraceFrame; import org.hyperledger.besu.ethereum.privacy.storage.PrivateBlockMetadata; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import org.hyperledger.besu.evm.worldstate.StackedUpdater; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -76,7 +75,10 @@ private PrivateBlockReplay.TransactionAction prepareRep transaction, header.getCoinbase(), tracer, - new CachingBlockHashLookup(header, blockchain), + blockReplay + .getProtocolSpec(header) + .getBlockHashProcessor() + .createBlockHashLookup(blockchain, header), Bytes32.wrap(Bytes.fromBase64String(privacyGroupId))); final List traceFrames = tracer.copyTraceFrames(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java index a2b7d175918..57e09ed5ffb 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/RpcErrorType.java @@ -65,7 +65,6 @@ public enum RpcErrorType implements RpcMethodError { INVALID_EXECUTION_REQUESTS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid execution requests params"), INVALID_EXTRA_DATA_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid extra data params"), INVALID_FILTER_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid filter params"), - INVALID_GAS_PRICE_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid gas price params"), INVALID_HASH_RATE_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid hash rate params"), INVALID_ID_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid ID params"), INVALID_RETURN_COMPLETE_TRANSACTION_PARAMS( @@ -95,6 +94,7 @@ public enum RpcErrorType implements RpcMethodError { INVALID_REMOTE_CAPABILITIES_PARAMS( INVALID_PARAMS_ERROR_CODE, "Invalid remote capabilities params"), INVALID_REWARD_PERCENTILES_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid reward percentiles params"), + INVALID_REQUESTS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid requests params"), INVALID_SEALER_ID_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid sealer ID params"), INVALID_STORAGE_KEYS_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid storage keys params"), INVALID_SUBSCRIPTION_PARAMS(INVALID_PARAMS_ERROR_CODE, "Invalid subscription params"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java index 25e6763edac..e74cf2f4e0a 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/BlockResult.java @@ -88,7 +88,8 @@ public class BlockResult implements JsonRpcResult { private final String blobGasUsed; private final String excessBlobGas; private final String parentBeaconBlockRoot; - private final String targetBlobCount; + private final String targetBlobsPerBlock; + private final List callProcessingResults; public BlockResult( final BlockHeader header, @@ -107,6 +108,18 @@ public BlockResult( final int size, final boolean includeCoinbase, final Optional> withdrawals) { + this(header, transactions, ommers, null, totalDifficulty, size, includeCoinbase, withdrawals); + } + + public BlockResult( + final BlockHeader header, + final List transactions, + final List ommers, + final List callProcessingResults, + final Difficulty totalDifficulty, + final int size, + final boolean includeCoinbase, + final Optional> withdrawals) { this.number = Quantity.create(header.getNumber()); this.hash = header.getHash().toString(); this.mixHash = header.getMixHash().toString(); @@ -128,6 +141,7 @@ public BlockResult( this.timestamp = Quantity.create(header.getTimestamp()); this.ommers = ommers; this.transactions = transactions; + this.callProcessingResults = callProcessingResults; this.coinbase = includeCoinbase ? header.getCoinbase().toString() : null; this.withdrawalsRoot = header.getWithdrawalsRoot().map(Hash::toString).orElse(null); this.withdrawals = @@ -139,7 +153,7 @@ public BlockResult( this.excessBlobGas = header.getExcessBlobGas().map(Quantity::create).orElse(null); this.parentBeaconBlockRoot = header.getParentBeaconBlockRoot().map(Bytes32::toHexString).orElse(null); - this.targetBlobCount = header.getTargetBlobCount().map(Quantity::create).orElse(null); + this.targetBlobsPerBlock = header.getTargetBlobsPerBlock().map(Quantity::create).orElse(null); } @JsonGetter(value = "number") @@ -278,8 +292,13 @@ public String getParentBeaconBlockRoot() { return parentBeaconBlockRoot; } - @JsonGetter(value = "targetBlobCount") - public String getTargetBlobCount() { - return targetBlobCount; + @JsonGetter(value = "targetBlobsPerBlock") + public String getTargetBlobsPerBlock() { + return targetBlobsPerBlock; + } + + @JsonGetter(value = "calls") + public List getTransactionProcessingResults() { + return callProcessingResults; } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/CallProcessingResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/CallProcessingResult.java new file mode 100644 index 00000000000..9015a61c854 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/CallProcessingResult.java @@ -0,0 +1,95 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import org.apache.tuweni.bytes.Bytes; + +public class CallProcessingResult { + @JsonProperty("status") + private final String status; + + @JsonProperty("returnData") + private final String returnData; + + @JsonProperty("gasUsed") + private final String gasUsed; + + @JsonProperty("error") + private final ErrorDetails error; + + @JsonProperty("logs") + private final List logs; + + public CallProcessingResult( + @JsonProperty("status") final int status, + @JsonProperty("returnData") final Bytes returnData, + @JsonProperty("gasUsed") final long gasUsed, + @JsonProperty("error") final ErrorDetails error, + @JsonProperty("logs") final List logs) { + this.status = Quantity.create(status); + this.returnData = returnData.toString(); + + this.gasUsed = Quantity.create(gasUsed); + this.error = error; + this.logs = logs; + } + + public String getStatus() { + return status; + } + + public String getReturnData() { + return returnData; + } + + public String getGasUsed() { + return gasUsed; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public ErrorDetails getError() { + return error; + } + + @JsonInclude(JsonInclude.Include.NON_NULL) + public List getLogs() { + return logs; + } + + public record ErrorDetails( + @JsonProperty("code") long code, + @JsonProperty("message") String message, + @JsonProperty("data") Bytes data) { + + @Override + public long code() { + return code; + } + + @Override + public String message() { + return message; + } + + @Override + public Bytes data() { + return data; + } + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/MinerDataResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/MinerDataResult.java index 63fb4dde513..80bc9d34445 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/MinerDataResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/MinerDataResult.java @@ -19,6 +19,7 @@ import org.immutables.value.Value; @Value.Immutable +@Deprecated(since = "24.12.0") public abstract class MinerDataResult implements JsonRpcResult { public abstract String getNetBlockReward(); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/PeerResult.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/PeerResult.java index 1bc2283acc3..99b7688c980 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/PeerResult.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/results/PeerResult.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.results; +import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; @@ -52,7 +53,7 @@ static PeerResult fromEthPeer(final EthPeer peer) { connection.inboundInitiated())) .port(Quantity.create(peerInfo.getPort())) .id(peerInfo.getNodeId().toString()) - .protocols(Map.of(peer.getProtocolName(), ProtocolsResult.fromEthPeer(peer))) + .protocols(Map.of(EthProtocol.NAME, ProtocolsResult.fromEthPeer(peer))) .enode(connection.getRemoteEnode().toString()) .build(); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java index 90ae97c5c4f..9ca0bb6c1a4 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import org.hyperledger.besu.ethereum.ProtocolContext; -import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.DebugReplayBlock; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugAccountAt; @@ -64,7 +63,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { private final TransactionPool transactionPool; private final Synchronizer synchronizer; private final Path dataDir; - private final ApiConfiguration apiConfiguration; + private final TransactionSimulator transactionSimulator; DebugJsonRpcMethods( final BlockchainQueries blockchainQueries, @@ -74,7 +73,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { final TransactionPool transactionPool, final Synchronizer synchronizer, final Path dataDir, - final ApiConfiguration apiConfiguration) { + final TransactionSimulator transactionSimulator) { this.blockchainQueries = blockchainQueries; this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; @@ -82,7 +81,7 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { this.transactionPool = transactionPool; this.synchronizer = synchronizer; this.dataDir = dataDir; - this.apiConfiguration = apiConfiguration; + this.transactionSimulator = transactionSimulator; } @Override @@ -120,13 +119,6 @@ protected Map create() { new DebugGetRawBlock(blockchainQueries), new DebugGetRawReceipts(blockchainQueries), new DebugGetRawTransaction(blockchainQueries), - new DebugTraceCall( - blockchainQueries, - protocolSchedule, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap()))); + new DebugTraceCall(blockchainQueries, protocolSchedule, transactionSimulator)); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java index de5662692ff..0ddcb564963 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EthJsonRpcMethods.java @@ -89,6 +89,7 @@ public class EthJsonRpcMethods extends ApiGroupJsonRpcMethods { private final MiningCoordinator miningCoordinator; private final Set supportedCapabilities; private final ApiConfiguration apiConfiguration; + private final TransactionSimulator transactionSimulator; public EthJsonRpcMethods( final BlockchainQueries blockchainQueries, @@ -98,7 +99,8 @@ public EthJsonRpcMethods( final TransactionPool transactionPool, final MiningCoordinator miningCoordinator, final Set supportedCapabilities, - final ApiConfiguration apiConfiguration) { + final ApiConfiguration apiConfiguration, + final TransactionSimulator transactionSimulator) { this.blockchainQueries = blockchainQueries; this.synchronizer = synchronizer; this.protocolSchedule = protocolSchedule; @@ -107,6 +109,7 @@ public EthJsonRpcMethods( this.miningCoordinator = miningCoordinator; this.supportedCapabilities = supportedCapabilities; this.apiConfiguration = apiConfiguration; + this.transactionSimulator = transactionSimulator; } @Override @@ -125,13 +128,7 @@ protected Map create() { new EthGetBlockReceipts(blockchainQueries, protocolSchedule), new EthGetBlockTransactionCountByNumber(blockchainQueries), new EthGetBlockTransactionCountByHash(blockchainQueries), - new EthCall( - blockchainQueries, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap())), + new EthCall(blockchainQueries, transactionSimulator), new EthFeeHistory(protocolSchedule, blockchainQueries, miningCoordinator, apiConfiguration), new EthGetCode(blockchainQueries), new EthGetLogs(blockchainQueries, apiConfiguration.getMaxLogsRange()), @@ -155,20 +152,8 @@ protected Map create() { new EthGetStorageAt(blockchainQueries), new EthSendRawTransaction(transactionPool), new EthSendTransaction(), - new EthEstimateGas( - blockchainQueries, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap())), - new EthCreateAccessList( - blockchainQueries, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap())), + new EthEstimateGas(blockchainQueries, transactionSimulator), + new EthCreateAccessList(blockchainQueries, transactionSimulator), new EthMining(miningCoordinator), new EthCoinbase(miningCoordinator), new EthProtocolVersion(supportedCapabilities), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index 2e68576fca7..476da3ee304 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.ObservableMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -85,7 +86,8 @@ public Map methods( final EthPeers ethPeers, final Vertx consensusEngineServer, final ApiConfiguration apiConfiguration, - final Optional enodeDnsConfiguration) { + final Optional enodeDnsConfiguration, + final TransactionSimulator transactionSimulator) { final Map enabled = new HashMap<>(); if (!rpcApis.isEmpty()) { final JsonRpcMethod modules = new RpcModules(rpcApis); @@ -111,7 +113,7 @@ public Map methods( transactionPool, synchronizer, dataDir, - apiConfiguration), + transactionSimulator), new EeaJsonRpcMethods( blockchainQueries, protocolSchedule, transactionPool, privacyParameters), new ExecutionEngineJsonRpcMethods( @@ -131,7 +133,8 @@ public Map methods( transactionPool, miningCoordinator, supportedCapabilities, - apiConfiguration), + apiConfiguration, + transactionSimulator), new NetJsonRpcMethods( p2pNetwork, networkId, @@ -155,6 +158,7 @@ public Map methods( protocolSchedule, protocolContext, apiConfiguration, + transactionSimulator, metricsSystem), new TxPoolJsonRpcMethods(transactionPool), new PluginsJsonRpcMethods(namedPlugins)); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java index 48d1dccee90..e6c1612f3d1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java @@ -46,7 +46,7 @@ import java.util.Map; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods { private final FilterManager filterManager; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java index e648febc379..142a82ccbb5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java @@ -42,7 +42,7 @@ import java.util.Optional; import java.util.stream.Collectors; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMethods { private final BlockchainQueries blockchainQueries; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java index 4638e90a625..0a2c090e5a5 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/TraceJsonRpcMethods.java @@ -41,6 +41,7 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods { private final ProtocolSchedule protocolSchedule; private final ApiConfiguration apiConfiguration; private final ProtocolContext protocolContext; + private final TransactionSimulator transactionSimulator; private final MetricsSystem metricsSystem; TraceJsonRpcMethods( @@ -48,11 +49,13 @@ public class TraceJsonRpcMethods extends ApiGroupJsonRpcMethods { final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final ApiConfiguration apiConfiguration, + final TransactionSimulator transactionSimulator, final MetricsSystem metricsSystem) { this.blockchainQueries = blockchainQueries; this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.apiConfiguration = apiConfiguration; + this.transactionSimulator = transactionSimulator; this.metricsSystem = metricsSystem; } @@ -76,29 +79,8 @@ protected Map create() { new TraceTransaction( () -> new BlockTracer(blockReplay), protocolSchedule, blockchainQueries), new TraceBlock(protocolSchedule, blockchainQueries, metricsSystem), - new TraceCall( - blockchainQueries, - protocolSchedule, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap())), - new TraceCallMany( - blockchainQueries, - protocolSchedule, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap())), - new TraceRawTransaction( - protocolSchedule, - blockchainQueries, - new TransactionSimulator( - blockchainQueries.getBlockchain(), - blockchainQueries.getWorldStateArchive(), - protocolSchedule, - apiConfiguration.getGasCap()))); + new TraceCall(blockchainQueries, protocolSchedule, transactionSimulator), + new TraceCallMany(blockchainQueries, protocolSchedule, transactionSimulator), + new TraceRawTransaction(protocolSchedule, blockchainQueries, transactionSimulator)); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java index 42905b96a70..278e06bd7dd 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketConfiguration.java @@ -20,6 +20,10 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.authentication.JwtAlgorithm; import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -54,11 +58,13 @@ public class WebSocketConfiguration { private Optional keyStorePath = Optional.empty(); private Optional keyStorePassword = Optional.empty(); private Optional keyStoreType = Optional.of("JKS"); // Default to JKS + private Optional keyStorePasswordFile = Optional.empty(); private boolean clientAuthEnabled = false; private Optional trustStorePath = Optional.empty(); private Optional trustStorePassword = Optional.empty(); private Optional trustStoreType = Optional.of("JKS"); // Default to JKS + private Optional trustStorePasswordFile = Optional.empty(); // For PEM format private Optional keyPath = Optional.empty(); @@ -191,8 +197,11 @@ public void setKeyStorePath(final String keyStorePath) { this.keyStorePath = Optional.ofNullable(keyStorePath); } - public Optional getKeyStorePassword() { - return keyStorePassword; + public Optional getKeyStorePassword() throws IOException { + if (keyStorePassword.isPresent()) { + return keyStorePassword; + } + return Optional.ofNullable(getKeystorePasswordFromFile()); } public void setKeyStorePassword(final String keyStorePassword) { @@ -245,8 +254,11 @@ public void setTrustStorePath(final String trustStorePath) { } // Truststore Password - public Optional getTrustStorePassword() { - return trustStorePassword; + public Optional getTrustStorePassword() throws IOException { + if (trustStorePassword.isPresent()) { + return trustStorePassword; + } + return Optional.ofNullable(getTruststorePasswordFromFile()); } public void setTrustStorePassword(final String trustStorePassword) { @@ -258,6 +270,38 @@ public Optional getTrustStoreType() { return trustStoreType; } + public void setKeyStorePasswordFile(final String keyStorePasswordFile) { + this.keyStorePasswordFile = Optional.ofNullable(keyStorePasswordFile); + } + + public void setTrustStorePasswordFile(final String trustStorePasswordFile) { + this.trustStorePasswordFile = Optional.ofNullable(trustStorePasswordFile); + } + + private String loadPasswordFromFile(final String passwordFile) throws IOException { + if (passwordFile != null) { + Path path = Path.of(passwordFile); + if (Files.exists(path)) { + return Files.readString(path, StandardCharsets.UTF_8).trim(); + } + } + return null; + } + + public String getKeystorePasswordFromFile() throws IOException { + if (keyStorePasswordFile.isPresent()) { + return loadPasswordFromFile(keyStorePasswordFile.get()); + } + return null; + } + + public String getTruststorePasswordFromFile() throws IOException { + if (trustStorePasswordFile.isPresent()) { + return loadPasswordFromFile(trustStorePasswordFile.get()); + } + return null; + } + public void setTrustStoreType(final String trustStoreType) { this.trustStoreType = Optional.ofNullable(trustStoreType); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketService.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketService.java index 31c86b18d21..d72a659cd74 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketService.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketService.java @@ -122,9 +122,16 @@ public CompletableFuture start() { // Check if SSL/TLS is enabled in the configuration if (configuration.isSslEnabled()) { serverOptions.setSsl(true); + String keystorePassword = null; String keystorePath = configuration.getKeyStorePath().orElse(null); - String keystorePassword = configuration.getKeyStorePassword().orElse(null); + try { + keystorePassword = configuration.getKeyStorePassword().orElse(null); + } catch (Exception e) { + LOG.error("Error reading keystore password", e); + resultFuture.completeExceptionally(e); + return resultFuture; + } String keyPath = configuration.getKeyPath().orElse(null); String certPath = configuration.getCertPath().orElse(null); @@ -146,9 +153,16 @@ public CompletableFuture start() { // Set up truststore for client authentication (mTLS) if (configuration.isClientAuthEnabled()) { serverOptions.setClientAuth(ClientAuth.REQUIRED); + String truststorePassword; String truststorePath = configuration.getTrustStorePath().orElse(null); - String truststorePassword = configuration.getTrustStorePassword().orElse(""); + try { + truststorePassword = configuration.getTrustStorePassword().orElse(null); + } catch (Exception e) { + LOG.error("Error reading truststore password", e); + resultFuture.completeExceptionally(e); + return resultFuture; + } String truststoreType = configuration.getTrustStoreType().orElse("JKS"); String trustCertPath = configuration.getTrustCertPath().orElse(null); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/request/SubscriptionRequestMapper.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/request/SubscriptionRequestMapper.java index 8bc35798495..f8cfc181122 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/request/SubscriptionRequestMapper.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/subscription/request/SubscriptionRequestMapper.java @@ -14,11 +14,11 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.request; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.FilterParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonRpcParameter.JsonRpcParameterException; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType; import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.methods.WebSocketRpcRequest; diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java index 7e5a7c6fe04..a673e1df7b1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueries.java @@ -631,6 +631,63 @@ public Optional transactionLocationByHash(final Hash transa return blockchain.getTransactionLocation(transactionHash); } + /** + * Returns the transaction receipts associated with the given block hash. + * + * @param blockHash The hash of the block that corresponds to the receipts to retrieve. + * @return The transaction receipts associated with the referenced block. + */ + public Optional> transactionReceiptsByBlockHash( + final Hash blockHash, final ProtocolSchedule protocolSchedule) { + final Optional block = blockchain.getBlockByHash(blockHash); + if (block.isEmpty()) { + return Optional.empty(); + } + final BlockHeader header = block.get().getHeader(); + final List transactions = block.get().getBody().getTransactions(); + + final List transactionReceipts = + blockchain.getTxReceipts(blockHash).orElseThrow(); + + long cumulativeGasUsedUntilTx = 0; + int logIndexOffset = 0; + + List receiptsResult = + new ArrayList(transactions.size()); + + for (int transactionIndex = 0; transactionIndex < transactions.size(); transactionIndex++) { + final Transaction transaction = transactions.get(transactionIndex); + final TransactionReceipt transactionReceipt = transactionReceipts.get(transactionIndex); + final Hash transactionHash = transaction.getHash(); + + long gasUsed = transactionReceipt.getCumulativeGasUsed() - cumulativeGasUsedUntilTx; + + Optional maybeBlobGasUsed = + getBlobGasUsed(transaction, protocolSchedule.getByBlockHeader(header)); + + Optional maybeBlobGasPrice = + getBlobGasPrice(transaction, header, protocolSchedule.getByBlockHeader(header)); + + receiptsResult.add( + TransactionReceiptWithMetadata.create( + transactionReceipt, + transaction, + transactionHash, + transactionIndex, + gasUsed, + header.getBaseFee(), + blockHash, + header.getNumber(), + maybeBlobGasUsed, + maybeBlobGasPrice, + logIndexOffset)); + + cumulativeGasUsedUntilTx = transactionReceipt.getCumulativeGasUsed(); + logIndexOffset += transactionReceipt.getLogsList().size(); + } + return Optional.of(receiptsResult); + } + /** * Returns the transaction receipt associated with the given transaction hash. * diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/tls/TlsClientAuthConfiguration.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/tls/TlsClientAuthConfiguration.java index f765405bcaf..885bc22e3da 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/tls/TlsClientAuthConfiguration.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/tls/TlsClientAuthConfiguration.java @@ -17,15 +17,23 @@ import java.nio.file.Path; import java.util.Objects; import java.util.Optional; +import java.util.function.Supplier; public class TlsClientAuthConfiguration { private final Optional knownClientsFile; private final boolean caClientsEnabled; + private final Optional truststorePath; + private final Supplier trustStorePasswordSupplier; private TlsClientAuthConfiguration( - final Optional knownClientsFile, final boolean caClientsEnabled) { + final Optional knownClientsFile, + final boolean caClientsEnabled, + final Optional truststorePath, + final Supplier trustStorePasswordSupplier) { this.knownClientsFile = knownClientsFile; this.caClientsEnabled = caClientsEnabled; + this.truststorePath = truststorePath; + this.trustStorePasswordSupplier = trustStorePasswordSupplier; } public Optional getKnownClientsFile() { @@ -36,9 +44,19 @@ public boolean isCaClientsEnabled() { return caClientsEnabled; } + public Optional getTruststorePath() { + return truststorePath; + } + + public String getTrustStorePassword() { + return trustStorePasswordSupplier.get(); + } + public static final class Builder { private Path knownClientsFile; private boolean caClientsEnabled; + private Path truststorePath; + private Supplier trustStorePasswordSupplier; private Builder() {} @@ -56,12 +74,29 @@ public Builder withCaClientsEnabled(final boolean caClientsEnabled) { return this; } + public Builder withTruststorePath(final Path truststorePath) { + this.truststorePath = truststorePath; + return this; + } + + public Builder withTruststorePasswordSupplier(final Supplier keyStorePasswordSupplier) { + this.trustStorePasswordSupplier = keyStorePasswordSupplier; + return this; + } + public TlsClientAuthConfiguration build() { - if (!caClientsEnabled) { + if (!caClientsEnabled && truststorePath == null) { Objects.requireNonNull(knownClientsFile, "Known Clients File is required"); } + if (!caClientsEnabled && knownClientsFile == null) { + Objects.requireNonNull(truststorePath, "Truststore File is required"); + } + return new TlsClientAuthConfiguration( - Optional.ofNullable(knownClientsFile), caClientsEnabled); + Optional.ofNullable(knownClientsFile), + caClientsEnabled, + Optional.ofNullable(truststorePath), + trustStorePasswordSupplier); } } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java index 08cfc3d7bd4..967a803f99d 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/graphql/AbstractEthGraphQLHttpServiceTest.java @@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.DefaultSyncStatus; +import org.hyperledger.besu.ethereum.core.ImmutableMiningConfiguration; import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.Synchronizer; import org.hyperledger.besu.ethereum.core.Transaction; @@ -38,6 +39,7 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.plugin.data.SyncStatus; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; @@ -135,6 +137,14 @@ public void setupTest() throws Exception { final GraphQLDataFetchers dataFetchers = new GraphQLDataFetchers(supportedCapabilities); final GraphQL graphQL = GraphQLProvider.buildGraphQL(dataFetchers); + final var transactionSimulator = + new TransactionSimulator( + blockchain, + blockchainSetupUtil.getWorldArchive(), + blockchainSetupUtil.getProtocolSchedule(), + ImmutableMiningConfiguration.newDefault(), + 0L); + service = new GraphQLHttpService( vertx, @@ -152,8 +162,8 @@ public void setupTest() throws Exception { miningCoordinatorMock, GraphQLContextType.SYNCHRONIZER, synchronizerMock, - GraphQLContextType.GAS_CAP, - 0L), + GraphQLContextType.TRANSACTION_SIMULATOR, + transactionSimulator), mock(EthScheduler.class)); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java index db896a94856..5afbbbfebd8 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java @@ -21,6 +21,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.StubGenesisConfigOptions; +import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.ApiConfiguration; import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; @@ -46,6 +47,7 @@ import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -146,6 +148,8 @@ protected Map getRpcMethods( .thenReturn(ValidationResult.invalid(TransactionInvalidReason.NONCE_TOO_LOW)); final PrivacyParameters privacyParameters = mock(PrivacyParameters.class); + when(miningConfiguration.getCoinbase()).thenReturn(Optional.of(Address.ZERO)); + final BlockchainQueries blockchainQueries = new BlockchainQueries( blockchainSetupUtil.getProtocolSchedule(), @@ -169,6 +173,14 @@ protected Map getRpcMethods( final NatService natService = new NatService(Optional.empty()); + final var transactionSimulator = + new TransactionSimulator( + blockchainSetupUtil.getBlockchain(), + blockchainSetupUtil.getWorldArchive(), + blockchainSetupUtil.getProtocolSchedule(), + miningConfiguration, + 0L); + return new JsonRpcMethodsFactory() .methods( CLIENT_NODE_NAME, @@ -201,7 +213,8 @@ protected Map getRpcMethods( mock(EthPeers.class), syncVertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + transactionSimulator); } protected void startService() throws Exception { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AdminJsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AdminJsonRpcHttpServiceTest.java index 4a03b2eb938..50d13b3d506 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AdminJsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AdminJsonRpcHttpServiceTest.java @@ -74,7 +74,6 @@ public void getPeers() throws Exception { peerList.add( new EthPeer( MockPeerConnection.create(info1, addr60301, addr30302), - "eth", c -> {}, List.of(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, @@ -84,7 +83,6 @@ public void getPeers() throws Exception { peerList.add( new EthPeer( MockPeerConnection.create(info2, addr30301, addr60302), - "eth", c -> {}, List.of(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, @@ -94,7 +92,6 @@ public void getPeers() throws Exception { peerList.add( new EthPeer( MockPeerConnection.create(info3, addr30301, addr60303), - "eth", c -> {}, List.of(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java index 9113e15a12d..b3f650302a9 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostAllowlistTest.java @@ -41,6 +41,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -138,7 +139,8 @@ public void initServerAndClient() throws Exception { mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); service = createJsonRpcHttpService(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java index aacf1157965..72e947436dd 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java @@ -46,6 +46,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -169,7 +170,8 @@ public static void initServerAndClient() throws Exception { mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); service = createJsonRpcHttpService(); jwtAuth = service.authenticationService.get().getJwtAuthProvider(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index ae66f2ac760..4db5c019c3e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -51,6 +51,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -235,7 +236,8 @@ private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final JsonRpcConf mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( vertx, @@ -346,7 +348,8 @@ private JsonRpcHttpService createJsonRpcHttpService( mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( vertx, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java index ec4f6c6e2b4..6f67cdeb3f9 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTestBase.java @@ -41,6 +41,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; @@ -147,7 +148,8 @@ public static void initServerAndClient() throws Exception { ethPeersMock, vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); disabledRpcMethods = new HashMap<>(); addedRpcMethods = new HashSet<>(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java index fa336169b9a..c2b1f4e3285 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java @@ -48,15 +48,18 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; +import java.io.FileOutputStream; import java.io.IOException; import java.io.UncheckedIOException; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; +import java.security.KeyStore; import java.util.Collections; import java.util.HashSet; import java.util.Map; @@ -152,7 +155,8 @@ public void initServer() throws Exception { mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString()); System.setProperty( @@ -185,6 +189,37 @@ private JsonRpcConfiguration createJsonRpcConfig( return config; } + private Optional getRpcHttpTlsConfigurationOnlyWithTruststore() { + final Path truststorePath = createTempFile(); + + // Create a new truststore and add the okHttpClientCertificate to it + try (FileOutputStream truststoreOutputStream = new FileOutputStream(truststorePath.toFile())) { + KeyStore truststore = KeyStore.getInstance("PKCS12"); + truststore.load(null, null); + truststore.setCertificateEntry( + "okHttpClientCertificate", okHttpClientCertificate.getCertificate()); + truststore.store(truststoreOutputStream, okHttpClientCertificate.getPassword()); + } catch (Exception e) { + throw new RuntimeException("Failed to create truststore", e); + } + + final FileBasedPasswordProvider trustStorePasswordProvider = + new FileBasedPasswordProvider(createPasswordFile(okHttpClientCertificate)); + + final TlsConfiguration tlsConfiguration = + aTlsConfiguration() + .withKeyStorePath(besuCertificate.getKeyStoreFile()) + .withKeyStorePasswordSupplier(fileBasedPasswordProvider) + .withClientAuthConfiguration( + aTlsClientAuthConfiguration() + .withTruststorePath(truststorePath) + .withTruststorePasswordSupplier(trustStorePasswordProvider) + .build()) + .build(); + + return Optional.of(tlsConfiguration); + } + private Optional getRpcHttpTlsConfiguration() { final Path knownClientsFile = createTempFile(); writeToKnownClientsFile( @@ -258,6 +293,23 @@ public void netVersionSuccessfulOnTlsWithClientCertInKnownClientsFile() throws E netVersionSuccessful(this::getTlsHttpClient, baseUrl); } + @Test + public void netVersionSuccessfulOnTlsWithClientCertInTruststore() throws Exception { + + JsonRpcHttpService jsonRpcHttpService = null; + try { + jsonRpcHttpService = + createJsonRpcHttpService( + createJsonRpcConfig(this::getRpcHttpTlsConfigurationOnlyWithTruststore)); + jsonRpcHttpService.start().join(); + netVersionSuccessful(this::getTlsHttpClient, jsonRpcHttpService.url()); + } finally { + if (jsonRpcHttpService != null) { + jsonRpcHttpService.stop().join(); + } + } + } + @Test public void netVersionSuccessfulOnTlsWithClientCertAddedAsCA() throws Exception { netVersionSuccessful(this::getTlsHttpClientAddedAsCA, baseUrl); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java index b675430c49e..dfa519f7464 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java @@ -47,6 +47,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -140,7 +141,8 @@ public void beforeEach() { mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); } @AfterEach diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java index de5683ad5c0..705ccdd994c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java @@ -47,6 +47,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.permissioning.AccountLocalConfigPermissioningController; import org.hyperledger.besu.ethereum.permissioning.NodeLocalConfigPermissioningController; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -141,7 +142,8 @@ public void initServer() throws Exception { mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty()); + Optional.empty(), + mock(TransactionSimulator.class)); service = createJsonRpcHttpService(createJsonRpcConfig()); service.start().join(); baseUrl = service.url(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminPeersTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminPeersTest.java index 1835a498835..5eef2f3d579 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminPeersTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/AdminPeersTest.java @@ -120,7 +120,6 @@ private Collection peerList() { final EthPeer ethPeer = new EthPeer( p, - "eth", c -> {}, List.of(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java index 7de6f65aae2..477e06f7039 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCallTest.java @@ -32,6 +32,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; @@ -104,7 +105,8 @@ public void noAccountOverrides() { @Test public void someAccountOverrides() { AccountOverrideMap expectedOverrides = new AccountOverrideMap(); - AccountOverride override = new AccountOverride.Builder().withNonce(88L).build(); + AccountOverride override = + new AccountOverride.Builder().withNonce(new UnsignedLongParameter("0x9e")).build(); final Address address = Address.fromHexString("0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3"); expectedOverrides.put(address, override); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java index f7c0c31914f..7cb68b79dea 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthCreateAccessListTest.java @@ -27,7 +27,6 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; @@ -51,7 +50,6 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -72,6 +70,7 @@ public class EthCreateAccessListTest { @Mock private BlockHeader latestBlockHeader; @Mock private BlockHeader finalizedBlockHeader; @Mock private BlockHeader genesisBlockHeader; + @Mock private BlockHeader pendingBlockHeader; @Mock private Blockchain blockchain; @Mock private BlockchainQueries blockchainQueries; @Mock private TransactionSimulator transactionSimulator; @@ -93,6 +92,9 @@ public void setUp() { when(blockchain.getChainHeadHeader()).thenReturn(latestBlockHeader); when(latestBlockHeader.getGasLimit()).thenReturn(Long.MAX_VALUE); when(latestBlockHeader.getNumber()).thenReturn(2L); + when(pendingBlockHeader.getGasLimit()).thenReturn(Long.MAX_VALUE); + when(pendingBlockHeader.getNumber()).thenReturn(3L); + when(transactionSimulator.simulatePendingBlockHeader()).thenReturn(pendingBlockHeader); when(worldStateArchive.isWorldStateAvailable(any(), any())).thenReturn(true); method = new EthCreateAccessList(blockchainQueries, transactionSimulator); @@ -140,14 +142,28 @@ public void shouldUseGasPriceParameterWhenIsPresent() { } @Test - public void shouldReturnGasEstimateErrorWhenGasPricePresentForEip1559Transaction() { + public void pendingBlockTagEstimateOnPendingBlock() { final JsonRpcRequestContext request = - ethCreateAccessListRequest(eip1559TransactionCallParameter(Optional.of(Wei.of(10)))); - mockTransactionSimulatorResult(false, false, 1L, latestBlockHeader); + ethCreateAccessListRequest(legacyTransactionCallParameter(Wei.ZERO), "pending"); + mockTransactionSimulatorResult(true, false, 1L, pendingBlockHeader); - Assertions.assertThatThrownBy(() -> method.response(request)) - .isInstanceOf(InvalidJsonRpcParameters.class) - .hasMessageContaining("gasPrice cannot be used with maxFeePerGas or maxPriorityFeePerGas"); + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(null, new CreateAccessListResult(new ArrayList<>(), 1L)); + + assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void shouldNotErrorWhenGasPricePresentForEip1559Transaction() { + final Wei gasPrice = Wei.of(1000); + final List expectedAccessList = new ArrayList<>(); + final JsonRpcRequestContext request = + ethCreateAccessListRequest(eip1559TransactionCallParameter(Optional.of(gasPrice))); + mockTransactionSimulatorResult(true, false, 1L, latestBlockHeader); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse(null, new CreateAccessListResult(expectedAccessList, 1L)); + assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); } @Test @@ -186,7 +202,8 @@ public void shouldReturnEmptyAccessListIfNoParameterAndWithoutAccessedStorage() mockTransactionSimulatorResult(true, false, 1L, latestBlockHeader); assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); - verify(transactionSimulator, times(1)).process(any(), any(), any(), eq(latestBlockHeader)); + verify(transactionSimulator, times(1)) + .process(any(), eq(Optional.empty()), any(), any(), eq(latestBlockHeader)); } @Test @@ -207,7 +224,8 @@ public void shouldReturnAccessListIfNoParameterAndWithAccessedStorage() { assertThat(responseWithMockTracer(request, tracer)) .usingRecursiveComparison() .isEqualTo(expectedResponse); - verify(transactionSimulator, times(2)).process(any(), any(), any(), eq(latestBlockHeader)); + verify(transactionSimulator, times(2)) + .process(any(), eq(Optional.empty()), any(), any(), eq(latestBlockHeader)); } @Test @@ -224,7 +242,8 @@ public void shouldReturnEmptyAccessListIfNoAccessedStorage() { // Set TransactionSimulator.process response mockTransactionSimulatorResult(true, false, 1L, latestBlockHeader); assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); - verify(transactionSimulator, times(1)).process(any(), any(), any(), eq(latestBlockHeader)); + verify(transactionSimulator, times(1)) + .process(any(), eq(Optional.empty()), any(), any(), eq(latestBlockHeader)); } @Test @@ -245,7 +264,8 @@ public void shouldReturnAccessListIfParameterAndSameAccessedStorage() { assertThat(responseWithMockTracer(request, tracer)) .usingRecursiveComparison() .isEqualTo(expectedResponse); - verify(transactionSimulator, times(1)).process(any(), any(), any(), eq(latestBlockHeader)); + verify(transactionSimulator, times(1)) + .process(any(), eq(Optional.empty()), any(), any(), eq(latestBlockHeader)); } @Test @@ -269,7 +289,8 @@ public void shouldReturnAccessListIfWithParameterAndDifferentAccessedStorage() { assertThat(responseWithMockTracer(request, tracer)) .usingRecursiveComparison() .isEqualTo(expectedResponse); - verify(transactionSimulator, times(2)).process(any(), any(), any(), eq(latestBlockHeader)); + verify(transactionSimulator, times(2)) + .process(any(), eq(Optional.empty()), any(), any(), eq(latestBlockHeader)); } @Test @@ -289,7 +310,8 @@ public void shouldReturnAccessListWhenBlockTagParamIsPresent() { assertThat(responseWithMockTracer(request, tracer)) .usingRecursiveComparison() .isEqualTo(expectedResponse); - verify(transactionSimulator, times(2)).process(any(), any(), any(), eq(finalizedBlockHeader)); + verify(transactionSimulator, times(2)) + .process(any(), eq(Optional.empty()), any(), any(), eq(finalizedBlockHeader)); } @Test @@ -309,7 +331,8 @@ public void shouldReturnAccessListWhenBlockNumberParamIsPresent() { assertThat(responseWithMockTracer(request, tracer)) .usingRecursiveComparison() .isEqualTo(expectedResponse); - verify(transactionSimulator, times(2)).process(any(), any(), any(), eq(genesisBlockHeader)); + verify(transactionSimulator, times(2)) + .process(any(), eq(Optional.empty()), any(), any(), eq(genesisBlockHeader)); } private JsonRpcResponse responseWithMockTracer( @@ -328,14 +351,21 @@ private AccessListOperationTracer createMockTracer( return tracer; } + @SuppressWarnings("ReferenceEquality") private void mockTransactionSimulatorResult( final boolean isSuccessful, final boolean isReverted, final long estimateGas, final BlockHeader blockHeader) { final TransactionSimulatorResult mockTxSimResult = mock(TransactionSimulatorResult.class); - when(transactionSimulator.process(any(), any(), any(), eq(blockHeader))) - .thenReturn(Optional.of(mockTxSimResult)); + if (blockHeader == pendingBlockHeader) { + when(transactionSimulator.processOnPending( + any(), eq(Optional.empty()), any(), any(), eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + } else { + when(transactionSimulator.process(any(), eq(Optional.empty()), any(), any(), eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + } final TransactionProcessingResult mockResult = mock(TransactionProcessingResult.class); when(mockResult.getEstimateGasUsedByTransaction()).thenReturn(estimateGas); when(mockResult.getRevertReason()) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java index 7c770f08a2d..13237ecc145 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/EthEstimateGasTest.java @@ -25,9 +25,9 @@ import org.hyperledger.besu.datatypes.AccountOverrideMap; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; @@ -38,7 +38,6 @@ import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; @@ -52,7 +51,6 @@ import java.util.Optional; import org.apache.tuweni.bytes.Bytes; -import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -70,6 +68,7 @@ public class EthEstimateGasTest { @Mock private BlockHeader latestBlockHeader; @Mock private BlockHeader finalizedBlockHeader; @Mock private BlockHeader genesisBlockHeader; + @Mock private BlockHeader pendingBlockHeader; @Mock private Blockchain blockchain; @Mock private BlockchainQueries blockchainQueries; @Mock private TransactionSimulator transactionSimulator; @@ -91,6 +90,9 @@ public void setUp() { when(blockchain.getChainHeadHeader()).thenReturn(latestBlockHeader); when(latestBlockHeader.getGasLimit()).thenReturn(Long.MAX_VALUE); when(latestBlockHeader.getNumber()).thenReturn(2L); + when(pendingBlockHeader.getGasLimit()).thenReturn(Long.MAX_VALUE); + when(pendingBlockHeader.getNumber()).thenReturn(3L); + when(transactionSimulator.simulatePendingBlockHeader()).thenReturn(pendingBlockHeader); when(worldStateArchive.isWorldStateAvailable(any(), any())).thenReturn(true); method = new EthEstimateGas(blockchainQueries, transactionSimulator); @@ -113,7 +115,8 @@ public void noAccountOverrides() { @Test public void someAccountOverrides() { AccountOverrideMap expectedOverrides = new AccountOverrideMap(); - AccountOverride override = new AccountOverride.Builder().withNonce(88L).build(); + AccountOverride override = + new AccountOverride.Builder().withNonce(new UnsignedLongParameter("0x9e")).build(); final Address address = Address.fromHexString("0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3"); expectedOverrides.put(address, override); @@ -191,13 +194,15 @@ public void shouldUseGasPriceParameterWhenIsPresent() { } @Test - public void shouldReturnGasEstimateErrorWhenGasPricePresentForEip1559Transaction() { + public void shouldNotErrorWhenGasPricePresentForEip1559Transaction() { + final Wei gasPrice = Wei.of(1000); final JsonRpcRequestContext request = - ethEstimateGasRequest(eip1559TransactionCallParameter(Optional.of(Wei.of(10)))); - mockTransientProcessorResultGasEstimate(1L, false, false, latestBlockHeader); - Assertions.assertThatThrownBy(() -> method.response(request)) - .isInstanceOf(InvalidJsonRpcParameters.class) - .hasMessageContaining("gasPrice cannot be used with maxFeePerGas or maxPriorityFeePerGas"); + ethEstimateGasRequest(eip1559TransactionCallParameter(Optional.of(gasPrice))); + mockTransientProcessorResultGasEstimate( + 1L, true, gasPrice, Optional.empty(), latestBlockHeader); + + final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Quantity.create(1L)); + assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); } @Test @@ -376,11 +381,7 @@ public void shouldIgnoreSenderBalanceAccountWhenStrictModeDisabled() { .process( eq(modifiedLegacyTransactionCallParameter(Wei.ZERO)), eq(Optional.empty()), // no account overrides - eq( - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(true) - .build()), + eq(TransactionValidationParams.transactionSimulatorAllowExceedingBalance()), any(OperationTracer.class), eq(latestBlockHeader)); } @@ -397,11 +398,7 @@ public void shouldNotIgnoreSenderBalanceAccountWhenStrictModeEnabled() { .process( eq(modifiedLegacyTransactionCallParameter(Wei.ZERO)), eq(Optional.empty()), // no account overrides - eq( - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(false) - .build()), + eq(TransactionValidationParams.transactionSimulator()), any(OperationTracer.class), eq(latestBlockHeader)); } @@ -432,6 +429,17 @@ public void shouldUseBlockTagParamWhenPresent() { assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); } + @Test + public void pendingBlockTagEstimateOnPendingBlock() { + final JsonRpcRequestContext request = + ethEstimateGasRequest(eip1559TransactionCallParameter(), "pending"); + mockTransientProcessorResultGasEstimate(1L, true, false, pendingBlockHeader); + + final JsonRpcResponse expectedResponse = new JsonRpcSuccessResponse(null, Quantity.create(1L)); + + assertThat(method.response(request)).usingRecursiveComparison().isEqualTo(expectedResponse); + } + @Test public void shouldUseBlockNumberParamWhenPresent() { final JsonRpcRequestContext request = @@ -488,6 +496,7 @@ private void mockTransientProcessorResultGasEstimate( isSuccessful, estimateGas, gasPrice, revertReason, blockHeader); } + @SuppressWarnings("ReferenceEquality") private TransactionSimulatorResult getMockTransactionSimulatorResult( final boolean isSuccessful, final long estimateGas, @@ -495,21 +504,45 @@ private TransactionSimulatorResult getMockTransactionSimulatorResult( final Optional revertReason, final BlockHeader blockHeader) { final TransactionSimulatorResult mockTxSimResult = mock(TransactionSimulatorResult.class); - when(transactionSimulator.process( - eq(modifiedLegacyTransactionCallParameter(gasPrice)), - eq(Optional.empty()), // no account overrides - any(TransactionValidationParams.class), - any(OperationTracer.class), - eq(blockHeader))) - .thenReturn(Optional.of(mockTxSimResult)); - when(transactionSimulator.process( - eq(modifiedEip1559TransactionCallParameter()), - eq(Optional.empty()), // no account overrides - any(TransactionValidationParams.class), - any(OperationTracer.class), - eq(blockHeader))) - .thenReturn(Optional.of(mockTxSimResult)); - + if (blockHeader == pendingBlockHeader) { + when(transactionSimulator.processOnPending( + eq(modifiedLegacyTransactionCallParameter(gasPrice)), + eq(Optional.empty()), // no account overrides + any(TransactionValidationParams.class), + any(OperationTracer.class), + eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + when(transactionSimulator.processOnPending( + eq(modifiedEip1559TransactionCallParameter()), + eq(Optional.empty()), // no account overrides + any(TransactionValidationParams.class), + any(OperationTracer.class), + eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + } else { + when(transactionSimulator.process( + eq(modifiedLegacyTransactionCallParameter(gasPrice)), + eq(Optional.empty()), // no account overrides + any(TransactionValidationParams.class), + any(OperationTracer.class), + eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + when(transactionSimulator.process( + eq(modifiedEip1559TransactionCallParameter()), + eq(Optional.empty()), // no account overrides + any(TransactionValidationParams.class), + any(OperationTracer.class), + eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + // for testing different combination of gasPrice params + when(transactionSimulator.process( + eq(modifiedEip1559TransactionCallParameter(Optional.of(gasPrice))), + eq(Optional.empty()), // no account overrides + any(TransactionValidationParams.class), + any(OperationTracer.class), + eq(blockHeader))) + .thenReturn(Optional.of(mockTxSimResult)); + } final TransactionProcessingResult mockResult = mock(TransactionProcessingResult.class); when(mockResult.getEstimateGasUsedByTransaction()).thenReturn(estimateGas); when(mockResult.getRevertReason()).thenReturn(revertReason); @@ -553,11 +586,11 @@ private CallParameter eip1559TransactionCallParameter() { return eip1559TransactionCallParameter(Optional.empty()); } - private JsonCallParameter eip1559TransactionCallParameter(final Optional gasPrice) { + private JsonCallParameter eip1559TransactionCallParameter(final Optional maybeGasPrice) { return new JsonCallParameter.JsonCallParameterBuilder() .withFrom(Address.fromHexString("0x0")) .withTo(Address.fromHexString("0x0")) - .withGasPrice(gasPrice.orElse(null)) + .withGasPrice(maybeGasPrice.orElse(null)) .withMaxPriorityFeePerGas(Wei.fromHexString("0x10")) .withMaxFeePerGas(Wei.fromHexString("0x10")) .withValue(Wei.ZERO) @@ -567,11 +600,15 @@ private JsonCallParameter eip1559TransactionCallParameter(final Optional ga } private CallParameter modifiedEip1559TransactionCallParameter() { + return modifiedEip1559TransactionCallParameter(Optional.empty()); + } + + private CallParameter modifiedEip1559TransactionCallParameter(final Optional gasPrice) { return new CallParameter( Address.fromHexString("0x0"), Address.fromHexString("0x0"), Long.MAX_VALUE, - Wei.ZERO, + gasPrice.orElse(Wei.ZERO), Optional.of(Wei.fromHexString("0x10")), Optional.of(Wei.fromHexString("0x10")), Wei.ZERO, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java index 616f5145217..4b8614916d5 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/AbstractEngineNewPayloadTest.java @@ -33,6 +33,7 @@ import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.BlockProcessingOutputs; import org.hyperledger.besu.ethereum.BlockProcessingResult; import org.hyperledger.besu.ethereum.ProtocolContext; @@ -41,7 +42,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.ExecutionEngineJsonRpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EnginePayloadParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.ExecutionWitnessParameter; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.WithdrawalParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java index 72dad46476c..1f4a1cd67b8 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/engine/EngineExchangeTransitionConfigurationTest.java @@ -23,12 +23,12 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.datatypes.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.EngineExchangeTransitionConfigurationParameter; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.UnsignedLongParameter; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.EngineExchangeTransitionConfigurationResult; diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java index 6626a66bb09..8d428f7ff45 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java @@ -16,10 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -36,6 +33,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.ethereum.mainnet.blockhash.BlockHashProcessor; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; @@ -87,6 +85,7 @@ public class TransactionTracerTest { @Mock private ProtocolSpec protocolSpec; @Mock private GasCalculator gasCalculator; + @Mock private BlockHashProcessor blockHashProcessor; @Mock private Tracer.TraceableState mutableWorldState; @@ -123,8 +122,8 @@ public void setUp() throws Exception { when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0L)); when(blockchain.getChainHeadHeader()).thenReturn(blockHeader); when(protocolSpec.getGasCalculator()).thenReturn(gasCalculator); + when(protocolSpec.getBlockHashProcessor()).thenReturn(blockHashProcessor); when(protocolContext.getBadBlockManager()).thenReturn(badBlockManager); - lenient().when(gasCalculator.computeExcessBlobGas(anyLong(), anyInt())).thenReturn(0L); } @Test diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java index 53785012d09..e1a5b1a75fd 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceLoginTest.java @@ -54,6 +54,7 @@ import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.network.P2PNetwork; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; +import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.nat.NatService; @@ -205,7 +206,8 @@ public void before() throws URISyntaxException { mock(EthPeers.class), vertx, mock(ApiConfiguration.class), - Optional.empty())); + Optional.empty(), + mock(TransactionSimulator.class))); websocketMethods.putAll(rpcMethods); webSocketMessageHandlerSpy = diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceTLSTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceTLSTest.java index 9a227dc4326..da4fd9458d0 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceTLSTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/WebSocketServiceTLSTest.java @@ -30,6 +30,9 @@ import java.io.File; import java.io.FileOutputStream; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.file.Files; import java.security.KeyStore; import java.util.Base64; import java.util.HashMap; @@ -390,14 +393,20 @@ public void shouldAuthenticateClient(final VertxTestContext testContext) throws clientTrustStore.store(fos, "password".toCharArray()); } + File tempFile = File.createTempFile("pwdfile", ".txt"); + tempFile.deleteOnExit(); + try (Writer writer = Files.newBufferedWriter(tempFile.toPath(), Charset.defaultCharset())) { + writer.write("password"); + } + // Configure WebSocket with SSL and client authentication enabled config.setSslEnabled(true); config.setKeyStorePath(serverKeystoreFile.getAbsolutePath()); - config.setKeyStorePassword("password"); + config.setKeyStorePasswordFile(tempFile.getAbsolutePath()); config.setKeyStoreType("PKCS12"); config.setClientAuthEnabled(true); config.setTrustStorePath(serverTruststoreFile.getAbsolutePath()); - config.setTrustStorePassword("password"); + config.setTrustStorePasswordFile(tempFile.getAbsolutePath()); config.setTrustStoreType("PKCS12"); // Create and start WebSocketService diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesTest.java index a0213a41a80..e9235f38d4b 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/BlockchainQueriesTest.java @@ -330,6 +330,41 @@ public void getOmmerCountForLatestBlock() { assertThat(result).contains(targetBlock.getBody().getOmmers().size()); } + @Test + public void getTransactionReceiptsByHash() { + final BlockchainWithData data = setupBlockchain(3); + final BlockchainQueries queries = data.blockchainQueries; + + final Block targetBlock = data.blockData.get(1).block; + + final Optional> receipts = + queries.transactionReceiptsByBlockHash( + targetBlock.getHash(), Mockito.mock(ProtocolSchedule.class)); + assertThat(receipts).isNotEmpty(); + + receipts + .get() + .forEach( + receipt -> { + final long gasUsed = receipt.getGasUsed(); + + assertThat(gasUsed) + .isEqualTo( + targetBlock.getHeader().getGasUsed() + / targetBlock.getBody().getTransactions().size()); + }); + } + + @Test + public void getTransactionReceiptsByInvalidHash() { + final BlockchainWithData data = setupBlockchain(3); + final BlockchainQueries queries = data.blockchainQueries; + + final Optional> result = + queries.transactionReceiptsByBlockHash(gen.hash(), Mockito.mock(ProtocolSchedule.class)); + assertThat(result).isEmpty(); + } + @Test public void logsShouldBeFlaggedAsRemovedWhenBlockIsNotInCanonicalChain() { // create initial blockchain diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java index 23790371503..8c31f7894d5 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java @@ -223,10 +223,11 @@ private void mockBlockchainWithPMTs( final BlockHeader blockHeader, final List transactionMetadataList) { - for (int i = 0; i < transactionMetadataList.size(); i++) { - final PrivateTransactionMetadata privateTransactionMetadata = transactionMetadataList.get(i); + for (int index = 0; index < transactionMetadataList.size(); index++) { + final PrivateTransactionMetadata privateTransactionMetadata = + transactionMetadataList.get(index); final Hash pmtHash = privateTransactionMetadata.getPrivateMarkerTransactionHash(); - final TransactionLocation pmtLocation = new TransactionLocation(blockHeader.getHash(), i); + final TransactionLocation pmtLocation = new TransactionLocation(blockHeader.getHash(), index); when(blockchainQueries.transactionLocationByHash(pmtHash)) .thenReturn(Optional.of(pmtLocation)); } diff --git a/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_stateOverride_movePrecompileToAddress.json b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_stateOverride_movePrecompileToAddress.json new file mode 100644 index 00000000000..c49130c00bd --- /dev/null +++ b/ethereum/api/src/test/resources/org/hyperledger/besu/ethereum/api/jsonrpc/eth/eth_call_stateOverride_movePrecompileToAddress.json @@ -0,0 +1,33 @@ +{ + "request": { + "id": 3, + "jsonrpc": "2.0", + "method": "eth_call", + "params": [ + { + "to": "0x6295ee1b4f6dd65047762f924ecd367c17eabf8f", + "from": "a94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "data": "0x12a7b914" + }, + "latest", + { + "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { + "balance": "0xde0b6b3a7640000", + "nonce": 88 + }, + "0xb9741079a300Cb3B8f324CdDB847c0d1d273a05E": { + "stateDiff": { + "0x1cf7945003fc5b59d2f6736f0704557aa805c4f2844084ccd1173b8d56946962": "0x000000000000000000000000000000000000000000000000000000110ed03bf7" + }, + "movePrecompileToAddress":null + } + } + ] + }, + "response": { + "jsonrpc": "2.0", + "id": 3, + "result": "0x0000000000000000000000000000000000000000000000000000000000000001" + }, + "statusCode": 200 +} \ No newline at end of file diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java index c4a3f89aaa3..2b9714384b3 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreator.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.blockcreation; +import static org.hyperledger.besu.ethereum.core.BlockHeaderBuilder.createPending; import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; import org.hyperledger.besu.datatypes.Address; @@ -29,7 +30,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; @@ -41,18 +41,14 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.AbstractBlockProcessor; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; -import org.hyperledger.besu.ethereum.mainnet.DifficultyCalculator; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; 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.ethereum.mainnet.requests.ProcessRequestContext; import org.hyperledger.besu.ethereum.mainnet.requests.RequestProcessorCoordinator; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.plugin.services.exception.StorageException; @@ -60,7 +56,6 @@ import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer; import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelector; -import java.math.BigInteger; import java.util.List; import java.util.Optional; import java.util.concurrent.CancellationException; @@ -198,12 +193,15 @@ protected BlockCreationResult createBlock( protocolSchedule.getForNextBlockHeader(parentHeader, timestamp); final ProcessableBlockHeader processableBlockHeader = - createPendingBlockHeader( - timestamp, - maybePrevRandao, - maybeParentBeaconBlockRoot, - newProtocolSpec, - parentHeader); + createPending( + newProtocolSpec, + parentHeader, + miningConfiguration, + timestamp, + maybePrevRandao, + maybeParentBeaconBlockRoot) + .buildProcessableBlockHeader(); + final Address miningBeneficiary = miningBeneficiaryCalculator.getMiningBeneficiary(processableBlockHeader.getNumber()); @@ -213,8 +211,7 @@ protected BlockCreationResult createBlock( newProtocolSpec .getBlockHashProcessor() - .processBlockHashes( - protocolContext.getBlockchain(), disposableWorldState, processableBlockHeader); + .processBlockHashes(disposableWorldState, processableBlockHeader); throwIfStopped(); @@ -261,7 +258,9 @@ protected BlockCreationResult createBlock( disposableWorldState, newProtocolSpec, transactionResults.getReceipts(), - new CachingBlockHashLookup(processableBlockHeader, protocolContext.getBlockchain()), + newProtocolSpec + .getBlockHashProcessor() + .createBlockHashLookup(protocolContext.getBlockchain(), processableBlockHeader), operationTracer); Optional> maybeRequests = @@ -421,52 +420,6 @@ private List selectOmmers() { return Lists.newArrayList(); } - private ProcessableBlockHeader createPendingBlockHeader( - final long timestamp, - final Optional maybePrevRandao, - final Optional maybeParentBeaconBlockRoot, - final ProtocolSpec protocolSpec, - final BlockHeader parentHeader) { - final long newBlockNumber = parentHeader.getNumber() + 1; - long gasLimit = - protocolSpec - .getGasLimitCalculator() - .nextGasLimit( - parentHeader.getGasLimit(), - miningConfiguration.getTargetGasLimit().orElse(parentHeader.getGasLimit()), - newBlockNumber); - - final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator(); - final BigInteger difficulty = difficultyCalculator.nextDifficulty(timestamp, parentHeader); - - final Wei baseFee = - Optional.of(protocolSpec.getFeeMarket()) - .filter(FeeMarket::implementsBaseFee) - .map(BaseFeeMarket.class::cast) - .map( - feeMarket -> - feeMarket.computeBaseFee( - newBlockNumber, - parentHeader.getBaseFee().orElse(Wei.ZERO), - parentHeader.getGasUsed(), - feeMarket.targetGasUsed(parentHeader))) - .orElse(null); - - final Bytes32 prevRandao = maybePrevRandao.orElse(null); - final Bytes32 parentBeaconBlockRoot = maybeParentBeaconBlockRoot.orElse(null); - return BlockHeaderBuilder.create() - .parentHash(parentHeader.getHash()) - .coinbase(miningConfiguration.getCoinbase().orElseThrow()) - .difficulty(Difficulty.of(difficulty)) - .number(newBlockNumber) - .gasLimit(gasLimit) - .timestamp(timestamp) - .baseFee(baseFee) - .prevRandao(prevRandao) - .parentBeaconBlockRoot(parentBeaconBlockRoot) - .buildProcessableBlockHeader(); - } - @Override public void cancel() { isCancelled.set(true); diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinator.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinator.java index 1c94bb7821a..bc47d422843 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinator.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/PoWMiningCoordinator.java @@ -35,6 +35,7 @@ * Responsible for determining when a block mining operation should be started/stopped, then * creating an appropriate miner and starting it running in a thread. */ +@Deprecated(since = "24.12.0") public class PoWMiningCoordinator extends AbstractMiningCoordinator implements BlockAddedObserver { diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java index a9b57a697ae..b353a1a01d5 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/BlockTransactionSelector.java @@ -45,9 +45,8 @@ import org.hyperledger.besu.ethereum.mainnet.blockhash.BlockHashProcessor; import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.gascalculator.GasCalculator; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.plugin.data.TransactionSelectionResult; import org.hyperledger.besu.plugin.services.tracer.BlockAwareOperationTracer; @@ -376,7 +375,9 @@ private TransactionSelectionResult evaluatePostProcessing( private TransactionProcessingResult processTransaction( final PendingTransaction pendingTransaction, final WorldUpdater worldStateUpdater) { final BlockHashLookup blockHashLookup = - new CachingBlockHashLookup(blockSelectionContext.pendingBlockHeader(), blockchain); + blockSelectionContext + .blockHashProcessor() + .createBlockHashLookup(blockchain, blockSelectionContext.pendingBlockHeader()); return transactionProcessor.processTransaction( worldStateUpdater, blockSelectionContext.pendingBlockHeader(), diff --git a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java index 9a4c83e9625..d5fd4212ec4 100644 --- a/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java +++ b/ethereum/blockcreation/src/main/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelector.java @@ -61,7 +61,8 @@ public TransactionSelectionResult evaluateTransactionPreProcessing( if (remainingBlobGas == 0) { LOG.atTrace() - .setMessage("The block already contains the max number of allowed blobs") + .setMessage( + "The block already contains the max number of allowed blobs, pending tx: {}") .addArgument(evaluationContext.getPendingTransaction()::toTraceLog) .log(); return TransactionSelectionResult.BLOBS_FULL; diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java index b70c48ad026..4c4bf134855 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockCreatorTest.java @@ -24,7 +24,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SECPPrivateKey; import org.hyperledger.besu.crypto.SignatureAlgorithm; @@ -298,12 +298,12 @@ record CreateOn(AbstractBlockCreator blockCreator, BlockHeader parentHeader) {} private CreateOn createBlockCreator(final ProtocolSpecAdapters protocolSpecAdapters) { - final var genesisConfigFile = GenesisConfigFile.fromResource("/block-creation-genesis.json"); + final var genesisConfig = GenesisConfig.fromResource("/block-creation-genesis.json"); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder(genesisConfigFile) + ExecutionContextTestFixture.builder(genesisConfig) .protocolSchedule( new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(BigInteger.valueOf(42)), protocolSpecAdapters, PrivacyParameters.DEFAULT, diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java index 2787189ece7..202b0fdee66 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/AbstractBlockTransactionSelectorTest.java @@ -33,7 +33,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Address; @@ -132,7 +132,7 @@ public abstract class AbstractBlockTransactionSelectorTest { Address.extract(Hash.hash(keyPair.getPublicKey().getEncodedBytes())); protected final MetricsSystem metricsSystem = new NoOpMetricsSystem(); - protected GenesisConfigFile genesisConfigFile; + protected GenesisConfig genesisConfig; protected MutableBlockchain blockchain; protected TransactionPool transactionPool; protected MutableWorldState worldState; @@ -152,7 +152,7 @@ public abstract class AbstractBlockTransactionSelectorTest { @BeforeEach public void setup() { - genesisConfigFile = getGenesisConfigFile(); + genesisConfig = getGenesisConfig(); protocolSchedule = createProtocolSchedule(); transactionSelectionService = new TransactionSelectionServiceImpl(); defaultTestMiningConfiguration = @@ -162,8 +162,7 @@ public void setup() { MIN_OCCUPANCY_80_PERCENT, DEFAULT_NON_POA_BLOCK_TXS_SELECTION_MAX_TIME); - final Block genesisBlock = - GenesisState.fromConfig(genesisConfigFile, protocolSchedule).getBlock(); + final Block genesisBlock = GenesisState.fromConfig(genesisConfig, protocolSchedule).getBlock(); blockchain = DefaultBlockchain.createMutable( @@ -198,7 +197,7 @@ public void setup() { }); } - protected abstract GenesisConfigFile getGenesisConfigFile(); + protected abstract GenesisConfig getGenesisConfig(); protected abstract ProtocolSchedule createProtocolSchedule(); @@ -232,7 +231,7 @@ protected ProcessableBlockHeader createBlock(final long gasLimit, final Wei base public void emptyPendingTransactionsResultsInEmptyVettingResult() { final ProtocolSchedule protocolSchedule = FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java index 327d4bd37d0..4aad300d511 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LegacyFeeMarketBlockTransactionSelectorTest.java @@ -19,7 +19,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.core.MiningConfiguration; @@ -49,14 +49,14 @@ public class LegacyFeeMarketBlockTransactionSelectorTest extends AbstractBlockTransactionSelectorTest { @Override - protected GenesisConfigFile getGenesisConfigFile() { - return GenesisConfigFile.fromResource("/block-transaction-selector/gas-price-genesis.json"); + protected GenesisConfig getGenesisConfig() { + return GenesisConfig.fromResource("/block-transaction-selector/gas-price-genesis.json"); } @Override protected ProtocolSchedule createProtocolSchedule() { return new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java index 62eaf713c54..eb77c6df658 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/LondonFeeMarketBlockTransactionSelectorTest.java @@ -19,7 +19,7 @@ import static org.hyperledger.besu.ethereum.core.MiningConfiguration.DEFAULT_NON_POA_BLOCK_TXS_SELECTION_MAX_TIME; import static org.mockito.Mockito.mock; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.blockcreation.txselection.BlockTransactionSelector; @@ -60,14 +60,14 @@ public class LondonFeeMarketBlockTransactionSelectorTest extends AbstractBlockTransactionSelectorTest { @Override - protected GenesisConfigFile getGenesisConfigFile() { - return GenesisConfigFile.fromResource("/block-transaction-selector/london-genesis.json"); + protected GenesisConfig getGenesisConfig() { + return GenesisConfig.fromResource("/block-transaction-selector/london-genesis.json"); } @Override protected ProtocolSchedule createProtocolSchedule() { return new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(CHAIN_ID), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java index e8b9baa0a73..8813fcf38c7 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/PoWBlockCreatorTest.java @@ -20,7 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; @@ -85,15 +85,15 @@ class PoWBlockCreatorTest extends AbstractBlockCreatorTest { @Test void createMainnetBlock1() throws IOException { - final var genesisConfigFile = GenesisConfigFile.mainnet(); + final var genesisConfig = GenesisConfig.mainnet(); final MiningConfiguration miningConfiguration = createMiningParameters(BLOCK_1_NONCE); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder(genesisConfigFile) + ExecutionContextTestFixture.builder(genesisConfig) .protocolSchedule( new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create(0, Function.identity()), PrivacyParameters.DEFAULT, @@ -143,23 +143,23 @@ void createMainnetBlock1() throws IOException { @Test void createMainnetBlock1_fixedDifficulty1() { - final var genesisConfigFile = - GenesisConfigFile.fromResource("/block-creation-fixed-difficulty-genesis.json"); + final var genesisConfig = + GenesisConfig.fromResource("/block-creation-fixed-difficulty-genesis.json"); final MiningConfiguration miningConfiguration = createMiningParameters(FIXED_DIFFICULTY_NONCE); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder(genesisConfigFile) + ExecutionContextTestFixture.builder(genesisConfig) .protocolSchedule( new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create( 0, specBuilder -> specBuilder.difficultyCalculator( FixedDifficultyCalculators.calculator( - genesisConfigFile.getConfigOptions()))), + genesisConfig.getConfigOptions()))), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, @@ -201,21 +201,21 @@ void createMainnetBlock1_fixedDifficulty1() { @Test void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { - final var genesisConfigFile = - GenesisConfigFile.fromResource("/block-creation-fixed-difficulty-genesis.json"); + final var genesisConfig = + GenesisConfig.fromResource("/block-creation-fixed-difficulty-genesis.json"); final MiningConfiguration miningConfiguration = createMiningParameters(FIXED_DIFFICULTY_NONCE); ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create( 0, specBuilder -> specBuilder.difficultyCalculator( FixedDifficultyCalculators.calculator( - genesisConfigFile.getConfigOptions()))), + genesisConfig.getConfigOptions()))), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, @@ -225,7 +225,7 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { new NoOpMetricsSystem()) .createProtocolSchedule(); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder(genesisConfigFile) + ExecutionContextTestFixture.builder(genesisConfig) .protocolSchedule(protocolSchedule) .build(); @@ -278,21 +278,21 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsFalse() { @Test void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { - final var genesisConfigFile = - GenesisConfigFile.fromResource("/block-creation-fixed-difficulty-genesis.json"); + final var genesisConfig = + GenesisConfig.fromResource("/block-creation-fixed-difficulty-genesis.json"); final MiningConfiguration miningConfiguration = createMiningParameters(FIXED_DIFFICULTY_NONCE); ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create( 0, specBuilder -> specBuilder.difficultyCalculator( FixedDifficultyCalculators.calculator( - genesisConfigFile.getConfigOptions()))), + genesisConfig.getConfigOptions()))), PrivacyParameters.DEFAULT, false, EvmConfiguration.DEFAULT, @@ -302,7 +302,7 @@ void rewardBeneficiary_zeroReward_skipZeroRewardsTrue() { new NoOpMetricsSystem()) .createProtocolSchedule(); final ExecutionContextTestFixture executionContextTestFixture = - ExecutionContextTestFixture.builder(genesisConfigFile) + ExecutionContextTestFixture.builder(genesisConfig) .protocolSchedule(protocolSchedule) .build(); diff --git a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelectorTest.java b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelectorTest.java index 123faf2d18a..7d9292935e9 100644 --- a/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelectorTest.java +++ b/ethereum/blockcreation/src/test/java/org/hyperledger/besu/ethereum/blockcreation/txselection/selectors/BlobSizeTransactionSelectorTest.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.mockito.Answers.RETURNS_DEEP_STUBS; -import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -61,7 +61,7 @@ class BlobSizeTransactionSelectorTest { Suppliers.memoize(SignatureAlgorithmFactory::getInstance); private static final KeyPair KEYS = SIGNATURE_ALGORITHM.get().generateKeyPair(); - private static final long BLOB_GAS_PER_BLOB = CancunGasCalculator.BLOB_GAS_PER_BLOB; + private static final long BLOB_GAS_PER_BLOB = new CancunGasCalculator().getBlobGasPerBlob(); private static final int MAX_BLOBS = 6; private static final long MAX_BLOB_GAS = BLOB_GAS_PER_BLOB * MAX_BLOBS; @@ -89,8 +89,8 @@ void notBlobTransactionsAreSelectedWithoutAnyCheck() { @Test void firstBlobTransactionIsSelected() { when(blockSelectionContext.gasLimitCalculator().currentBlobGasLimit()).thenReturn(MAX_BLOB_GAS); - when(blockSelectionContext.gasCalculator().blobGasCost(anyInt())) - .thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Integer.class)); + when(blockSelectionContext.gasCalculator().blobGasCost(anyLong())) + .thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Long.class)); final var selector = new BlobSizeTransactionSelector(blockSelectionContext); @@ -131,8 +131,8 @@ void returnsBlobsFullWhenMaxNumberOfBlobsAlreadyPresent() { @Test void returnsTooLargeForRemainingBlobGas() { when(blockSelectionContext.gasLimitCalculator().currentBlobGasLimit()).thenReturn(MAX_BLOB_GAS); - when(blockSelectionContext.gasCalculator().blobGasCost(anyInt())) - .thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Integer.class)); + when(blockSelectionContext.gasCalculator().blobGasCost(anyLong())) + .thenAnswer(iom -> BLOB_GAS_PER_BLOB * iom.getArgument(0, Long.class)); final var selector = new BlobSizeTransactionSelector(blockSelectionContext); diff --git a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java index a029c4b4a49..6ea4a25f5fa 100644 --- a/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java +++ b/ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/vm/TraceTransactionIntegrationTest.java @@ -16,9 +16,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.TransactionType; @@ -34,11 +33,13 @@ import org.hyperledger.besu.ethereum.debug.TraceOptions; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.List; @@ -70,17 +71,19 @@ public class TraceTransactionIntegrationTest { @BeforeEach public void setUp() { final ExecutionContextTestFixture contextTestFixture = - ExecutionContextTestFixture.builder(GenesisConfigFile.fromResource("/genesis-it.json")) - .build(); + ExecutionContextTestFixture.builder(GenesisConfig.fromResource("/genesis-it.json")).build(); genesisBlock = contextTestFixture.getGenesis(); blockchain = contextTestFixture.getBlockchain(); worldStateArchive = contextTestFixture.getStateArchive(); final ProtocolSchedule protocolSchedule = contextTestFixture.getProtocolSchedule(); - transactionProcessor = - protocolSchedule - .getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()) - .getTransactionProcessor(); - blockHashLookup = new CachingBlockHashLookup(genesisBlock.getHeader(), blockchain); + final ProtocolSpec protocolSpec = + protocolSchedule.getByBlockHeader(new BlockHeaderTestFixture().number(0L).buildHeader()); + + transactionProcessor = protocolSpec.getTransactionProcessor(); + blockHashLookup = + protocolSpec + .getBlockHashProcessor() + .createBlockHashLookup(blockchain, genesisBlock.getHeader()); } @Test diff --git a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/BlockHashOperationBenchmark.java b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/BlockHashOperationBenchmark.java index e431e1420cd..c44bc660c91 100644 --- a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/BlockHashOperationBenchmark.java +++ b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/BlockHashOperationBenchmark.java @@ -15,7 +15,7 @@ package org.hyperledger.besu.ethereum.vm.operations; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; +import org.hyperledger.besu.ethereum.vm.BlockchainBasedBlockHashLookup; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.PetersburgGasCalculator; import org.hyperledger.besu.evm.operation.BlockHashOperation; @@ -68,7 +68,7 @@ public Bytes executeOperationWithEmptyHashCache() { operationBenchmarkHelper .createMessageFrameBuilder() .blockHashLookup( - new CachingBlockHashLookup( + new BlockchainBasedBlockHashLookup( (ProcessableBlockHeader) frame.getBlockValues(), operationBenchmarkHelper.getBlockchain())) .build(); diff --git a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java index 4289a91a3c8..cff04abbdc5 100644 --- a/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java +++ b/ethereum/core/src/jmh/java/org/hyperledger/besu/ethereum/vm/operations/OperationBenchmarkHelper.java @@ -16,7 +16,7 @@ import static java.util.Collections.emptyList; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.core.Block; @@ -75,7 +75,7 @@ public static OperationBenchmarkHelper create() throws IOException { KeyValueSegmentIdentifier.BLOCKCHAIN, optimisticRocksDBColumnarKeyValueStorage); final ExecutionContextTestFixture executionContext = - ExecutionContextTestFixture.builder(GenesisConfigFile.fromResource("/genesis-jmh.json")) + ExecutionContextTestFixture.builder(GenesisConfig.fromResource("/genesis-jmh.json")) .blockchainKeyValueStorage(keyValueStorage) .build(); final MutableBlockchain blockchain = executionContext.getBlockchain(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockProcessingResult.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockProcessingResult.java index f34bd056c64..77276caecde 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockProcessingResult.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/BlockProcessingResult.java @@ -26,6 +26,7 @@ public class BlockProcessingResult extends BlockValidationResult { private final Optional yield; private final boolean isPartial; + private Optional nbParallelizedTransations = Optional.empty(); /** A result indicating that processing failed. */ public static final BlockProcessingResult FAILED = new BlockProcessingResult("processing failed"); @@ -40,6 +41,21 @@ public BlockProcessingResult(final Optional yield) { this.isPartial = false; } + /** + * A result indicating that processing was successful but incomplete. + * + * @param yield the outputs of processing a block + * @param nbParallelizedTransations potential number of parallelized transactions during block + * processing + */ + public BlockProcessingResult( + final Optional yield, + final Optional nbParallelizedTransations) { + this.yield = yield; + this.isPartial = false; + this.nbParallelizedTransations = nbParallelizedTransations; + } + /** * A result indicating that processing was successful but incomplete. * @@ -144,4 +160,13 @@ public List getReceipts() { public Optional> getRequests() { return yield.flatMap(BlockProcessingOutputs::getRequests); } + + /** + * Returns an optional that contains the number of parallelized transactions (if there is any) + * + * @return Optional of parallelized transactions during the block execution + */ + public Optional getNbParallelizedTransations() { + return nbParallelizedTransations; + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/GasLimitCalculator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/GasLimitCalculator.java index 7c15d6229c0..0d1a09511a5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/GasLimitCalculator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/GasLimitCalculator.java @@ -17,8 +17,11 @@ /** The GasLimitCalculator interface defines methods for calculating the gas limit. */ public interface GasLimitCalculator { - /** The constant BLOB_GAS_LIMIT represents the gas limit for blob data. */ - long BLOB_GAS_LIMIT = 786432; + /** + * The constant BLOB_GAS_LIMIT represents the gas limit for blob data. Defaults to the Cancun + * value where it was first introduced as part of EIP-4844 + */ + long BLOB_GAS_LIMIT = 0xC0000; /** * Calculates the next gas limit based on the current gas limit, target gas limit, and new block diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java index 00766cdf574..c2925d651bd 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/MainnetBlockValidator.java @@ -183,7 +183,8 @@ public BlockProcessingResult validateAndProcessBlock( } return new BlockProcessingResult( - Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests))); + Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests)), + result.getNbParallelizedTransations()); } } catch (MerkleTrieException ex) { context.getWorldStateArchive().heal(ex.getMaybeAddress(), ex.getLocation()); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java index f6e06f82d2e..5b1fa1effb5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/DefaultBlockchain.java @@ -183,7 +183,7 @@ private void createGauges(final MetricsSystem metricsSystem) { metricsSystem.createGauge( BLOCKCHAIN, - "difficulty_total", + "difficulty", "Total difficulty of the chainhead", () -> this.getChainHead().getTotalDifficulty().toBigInteger().doubleValue()); @@ -485,18 +485,14 @@ public synchronized void unsafeImportBlock( final List transactionReceipts, final Optional maybeTotalDifficulty) { final BlockchainStorage.Updater updater = blockchainStorage.updater(); - final Hash hash = block.getHash(); - updater.putBlockHeader(hash, block.getHeader()); - updater.putBlockHash(block.getHeader().getNumber(), hash); - updater.putBlockBody(hash, block.getBody()); - final int nbTrx = block.getBody().getTransactions().size(); - for (int i = 0; i < nbTrx; i++) { - final Hash transactionHash = block.getBody().getTransactions().get(i).getHash(); - updater.putTransactionLocation(transactionHash, new TransactionLocation(transactionHash, i)); - } - updater.putTransactionReceipts(hash, transactionReceipts); + final Hash blockHash = block.getHash(); + updater.putBlockHeader(blockHash, block.getHeader()); + updater.putBlockHash(block.getHeader().getNumber(), blockHash); + updater.putBlockBody(blockHash, block.getBody()); + indexTransactionsForBlock(updater, blockHash, block.getBody().getTransactions()); + updater.putTransactionReceipts(blockHash, transactionReceipts); maybeTotalDifficulty.ifPresent( - totalDifficulty -> updater.putTotalDifficulty(hash, totalDifficulty)); + totalDifficulty -> updater.putTotalDifficulty(blockHash, totalDifficulty)); updater.commit(); } @@ -563,7 +559,7 @@ private BlockAddedEvent handleNewHead( updater.putBlockHash(blockWithReceipts.getNumber(), newBlockHash); updater.setChainHead(newBlockHash); - indexTransactionForBlock( + indexTransactionsForBlock( updater, newBlockHash, blockWithReceipts.getBlock().getBody().getTransactions()); gasUsedCounter.inc(blockWithReceipts.getHeader().getGasUsed()); numberOfTransactionsCounter.inc( @@ -652,7 +648,7 @@ private BlockAddedEvent handleChainReorg( // Update indexed transactions newTransactions.forEach( (blockHash, transactionsInBlock) -> { - indexTransactionForBlock(updater, blockHash, transactionsInBlock); + indexTransactionsForBlock(updater, blockHash, transactionsInBlock); // Don't remove transactions that are being re-indexed. removedTransactions.removeAll(transactionsInBlock); }); @@ -792,11 +788,11 @@ private void updateCacheForNewCanonicalHead(final Block block, final Difficulty chainHeadOmmerCount = block.getBody().getOmmers().size(); } - private static void indexTransactionForBlock( - final BlockchainStorage.Updater updater, final Hash hash, final List txs) { - for (int i = 0; i < txs.size(); i++) { - final Hash txHash = txs.get(i).getHash(); - final TransactionLocation loc = new TransactionLocation(hash, i); + private static void indexTransactionsForBlock( + final BlockchainStorage.Updater updater, final Hash blockHash, final List txs) { + for (int index = 0; index < txs.size(); index++) { + final Hash txHash = txs.get(index).getHash(); + final TransactionLocation loc = new TransactionLocation(blockHash, index); updater.putTransactionLocation(txHash, loc); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java index 0282ff28a8e..fdb4f949c22 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java @@ -18,7 +18,7 @@ import static org.hyperledger.besu.ethereum.trie.common.GenesisWorldStateProvider.createGenesisWorldState; import org.hyperledger.besu.config.GenesisAccount; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.datatypes.Hash; @@ -53,11 +53,11 @@ public final class GenesisState { private final Block block; - private final GenesisConfigFile genesisConfigFile; + private final GenesisConfig genesisConfig; - private GenesisState(final Block block, final GenesisConfigFile genesisConfigFile) { + private GenesisState(final Block block, final GenesisConfig genesisConfig) { this.block = block; - this.genesisConfigFile = genesisConfigFile; + this.genesisConfig = genesisConfig; } /** @@ -68,7 +68,7 @@ private GenesisState(final Block block, final GenesisConfigFile genesisConfigFil * @return A new {@link GenesisState}. */ public static GenesisState fromJson(final String json, final ProtocolSchedule protocolSchedule) { - return fromConfig(GenesisConfigFile.fromConfig(json), protocolSchedule); + return fromConfig(GenesisConfig.fromConfig(json), protocolSchedule); } /** @@ -86,18 +86,18 @@ static GenesisState fromJsonSource( final URL jsonSource, final ProtocolSchedule protocolSchedule) { return fromConfig( - dataStorageConfiguration, GenesisConfigFile.fromConfig(jsonSource), protocolSchedule); + dataStorageConfiguration, GenesisConfig.fromConfig(jsonSource), protocolSchedule); } /** * Construct a {@link GenesisState} from a genesis file object. * - * @param config A {@link GenesisConfigFile} describing the genesis block. + * @param config A {@link GenesisConfig} describing the genesis block. * @param protocolSchedule A protocol Schedule associated with * @return A new {@link GenesisState}. */ public static GenesisState fromConfig( - final GenesisConfigFile config, final ProtocolSchedule protocolSchedule) { + final GenesisConfig config, final ProtocolSchedule protocolSchedule) { return fromConfig(DataStorageConfiguration.DEFAULT_CONFIG, config, protocolSchedule); } @@ -106,43 +106,42 @@ public static GenesisState fromConfig( * * @param dataStorageConfiguration A {@link DataStorageConfiguration} describing the storage * configuration - * @param genesisConfigFile A {@link GenesisConfigFile} describing the genesis block. + * @param genesisConfig A {@link GenesisConfig} describing the genesis block. * @param protocolSchedule A protocol Schedule associated with * @return A new {@link GenesisState}. */ public static GenesisState fromConfig( final DataStorageConfiguration dataStorageConfiguration, - final GenesisConfigFile genesisConfigFile, + final GenesisConfig genesisConfig, final ProtocolSchedule protocolSchedule) { - final var genesisStateRoot = - calculateGenesisStateRoot(dataStorageConfiguration, genesisConfigFile); + final var genesisStateRoot = calculateGenesisStateRoot(dataStorageConfiguration, genesisConfig); final Block block = new Block( - buildHeader(genesisConfigFile, genesisStateRoot, protocolSchedule), - buildBody(genesisConfigFile)); - return new GenesisState(block, genesisConfigFile); + buildHeader(genesisConfig, genesisStateRoot, protocolSchedule), + buildBody(genesisConfig)); + return new GenesisState(block, genesisConfig); } /** * Construct a {@link GenesisState} from a JSON object. * * @param genesisStateRoot The root of the genesis state. - * @param genesisConfigFile A {@link GenesisConfigFile} describing the genesis block. + * @param genesisConfig A {@link GenesisConfig} describing the genesis block. * @param protocolSchedule A protocol Schedule associated with * @return A new {@link GenesisState}. */ public static GenesisState fromStorage( final Hash genesisStateRoot, - final GenesisConfigFile genesisConfigFile, + final GenesisConfig genesisConfig, final ProtocolSchedule protocolSchedule) { final Block block = new Block( - buildHeader(genesisConfigFile, genesisStateRoot, protocolSchedule), - buildBody(genesisConfigFile)); - return new GenesisState(block, genesisConfigFile); + buildHeader(genesisConfig, genesisStateRoot, protocolSchedule), + buildBody(genesisConfig)); + return new GenesisState(block, genesisConfig); } - private static BlockBody buildBody(final GenesisConfigFile config) { + private static BlockBody buildBody(final GenesisConfig config) { final Optional> withdrawals = isShanghaiAtGenesis(config) ? Optional.of(emptyList()) : Optional.empty(); @@ -159,7 +158,7 @@ public Block getBlock() { * @param target WorldView to write genesis state to */ public void writeStateTo(final MutableWorldState target) { - writeAccountsTo(target, genesisConfigFile.streamAllocations(), block.getHeader()); + writeAccountsTo(target, genesisConfig.streamAllocations(), block.getHeader()); } private static void writeAccountsTo( @@ -180,10 +179,9 @@ private static void writeAccountsTo( } private static Hash calculateGenesisStateRoot( - final DataStorageConfiguration dataStorageConfiguration, - final GenesisConfigFile genesisConfigFile) { + final DataStorageConfiguration dataStorageConfiguration, final GenesisConfig genesisConfig) { try (var worldState = createGenesisWorldState(dataStorageConfiguration)) { - writeAccountsTo(worldState, genesisConfigFile.streamAllocations(), null); + writeAccountsTo(worldState, genesisConfig.streamAllocations(), null); return worldState.rootHash(); } catch (Exception e) { throw new RuntimeException(e); @@ -191,7 +189,7 @@ private static Hash calculateGenesisStateRoot( } private static BlockHeader buildHeader( - final GenesisConfigFile genesis, + final GenesisConfig genesis, final Hash genesisRootHash, final ProtocolSchedule protocolSchedule) { @@ -219,16 +217,16 @@ private static BlockHeader buildHeader( .parentBeaconBlockRoot( (isCancunAtGenesis(genesis) ? parseParentBeaconBlockRoot(genesis) : null)) .requestsHash(isPragueAtGenesis(genesis) ? Hash.EMPTY_REQUESTS_HASH : null) - .targetBlobCount( + .targetBlobsPerBlock( isPragueAtGenesis(genesis) // TODO SLD EIP-7742 Currently defaulting to null due to dependency on web3j // BlockHeader in CodeDelegationTransactionAcceptanceTest - ? genesis.getTargetBlobCount().map(UInt64::fromHexString).orElse(null) + ? genesis.getTargetBlobsPerBlock().map(UInt64::fromHexString).orElse(null) : null) .buildBlockHeader(); } - private static Address parseCoinbase(final GenesisConfigFile genesis) { + private static Address parseCoinbase(final GenesisConfig genesis) { return genesis .getCoinbase() .map(str -> withNiceErrorMessage("coinbase", str, Address::fromHexString)) @@ -250,39 +248,39 @@ private static IllegalArgumentException createInvalidBlockConfigException( "Invalid " + name + " in genesis block configuration: " + value, e); } - private static Hash parseParentHash(final GenesisConfigFile genesis) { + private static Hash parseParentHash(final GenesisConfig genesis) { return withNiceErrorMessage("parentHash", genesis.getParentHash(), Hash::fromHexStringLenient); } - private static Bytes parseExtraData(final GenesisConfigFile genesis) { + private static Bytes parseExtraData(final GenesisConfig genesis) { return withNiceErrorMessage("extraData", genesis.getExtraData(), Bytes::fromHexString); } - private static Difficulty parseDifficulty(final GenesisConfigFile genesis) { + private static Difficulty parseDifficulty(final GenesisConfig genesis) { return withNiceErrorMessage("difficulty", genesis.getDifficulty(), Difficulty::fromHexString); } - private static Hash parseMixHash(final GenesisConfigFile genesis) { + private static Hash parseMixHash(final GenesisConfig genesis) { return withNiceErrorMessage("mixHash", genesis.getMixHash(), Hash::fromHexStringLenient); } - private static long parseNonce(final GenesisConfigFile genesis) { + private static long parseNonce(final GenesisConfig genesis) { return withNiceErrorMessage("nonce", genesis.getNonce(), GenesisState::parseUnsignedLong); } - private static long parseBlobGasUsed(final GenesisConfigFile genesis) { + private static long parseBlobGasUsed(final GenesisConfig genesis) { return withNiceErrorMessage( "blobGasUsed", genesis.getBlobGasUsed(), GenesisState::parseUnsignedLong); } - private static BlobGas parseExcessBlobGas(final GenesisConfigFile genesis) { + private static BlobGas parseExcessBlobGas(final GenesisConfig genesis) { long excessBlobGas = withNiceErrorMessage( "excessBlobGas", genesis.getExcessBlobGas(), GenesisState::parseUnsignedLong); return BlobGas.of(excessBlobGas); } - private static Bytes32 parseParentBeaconBlockRoot(final GenesisConfigFile genesis) { + private static Bytes32 parseParentBeaconBlockRoot(final GenesisConfig genesis) { return withNiceErrorMessage( "parentBeaconBlockRoot", genesis.getParentBeaconBlockRoot(), Bytes32::fromHexString); } @@ -295,7 +293,7 @@ private static long parseUnsignedLong(final String value) { return Long.parseUnsignedLong(v, 16); } - private static boolean isShanghaiAtGenesis(final GenesisConfigFile genesis) { + private static boolean isShanghaiAtGenesis(final GenesisConfig genesis) { final OptionalLong shanghaiTimestamp = genesis.getConfigOptions().getShanghaiTime(); if (shanghaiTimestamp.isPresent()) { return genesis.getTimestamp() >= shanghaiTimestamp.getAsLong(); @@ -303,7 +301,7 @@ private static boolean isShanghaiAtGenesis(final GenesisConfigFile genesis) { return isCancunAtGenesis(genesis); } - private static boolean isCancunAtGenesis(final GenesisConfigFile genesis) { + private static boolean isCancunAtGenesis(final GenesisConfig genesis) { final OptionalLong cancunTimestamp = genesis.getConfigOptions().getCancunTime(); if (cancunTimestamp.isPresent()) { return genesis.getTimestamp() >= cancunTimestamp.getAsLong(); @@ -311,7 +309,7 @@ private static boolean isCancunAtGenesis(final GenesisConfigFile genesis) { return isPragueAtGenesis(genesis) || isCancunEOFAtGenesis(genesis); } - private static boolean isCancunEOFAtGenesis(final GenesisConfigFile genesis) { + private static boolean isCancunEOFAtGenesis(final GenesisConfig genesis) { final OptionalLong cancunEOFTimestamp = genesis.getConfigOptions().getCancunEOFTime(); if (cancunEOFTimestamp.isPresent()) { return genesis.getTimestamp() >= cancunEOFTimestamp.getAsLong(); @@ -319,7 +317,7 @@ private static boolean isCancunEOFAtGenesis(final GenesisConfigFile genesis) { return false; } - private static boolean isPragueAtGenesis(final GenesisConfigFile genesis) { + private static boolean isPragueAtGenesis(final GenesisConfig genesis) { final OptionalLong pragueTimestamp = genesis.getConfigOptions().getPragueTime(); if (pragueTimestamp.isPresent()) { return genesis.getTimestamp() >= pragueTimestamp.getAsLong(); @@ -327,7 +325,7 @@ private static boolean isPragueAtGenesis(final GenesisConfigFile genesis) { return isOsakaAtGenesis(genesis); } - private static boolean isOsakaAtGenesis(final GenesisConfigFile genesis) { + private static boolean isOsakaAtGenesis(final GenesisConfig genesis) { final OptionalLong osakaTimestamp = genesis.getConfigOptions().getOsakaTime(); if (osakaTimestamp.isPresent()) { return genesis.getTimestamp() >= osakaTimestamp.getAsLong(); @@ -343,7 +341,7 @@ private static boolean isVerkleAtGenesis(final GenesisConfigFile genesis) { return isFutureEipsTimeAtGenesis(genesis); } - private static boolean isFutureEipsTimeAtGenesis(final GenesisConfigFile genesis) { + private static boolean isFutureEipsTimeAtGenesis(final GenesisConfig genesis) { final OptionalLong futureEipsTime = genesis.getConfigOptions().getFutureEipsTime(); if (futureEipsTime.isPresent()) { return genesis.getTimestamp() >= futureEipsTime.getAsLong(); @@ -351,7 +349,7 @@ private static boolean isFutureEipsTimeAtGenesis(final GenesisConfigFile genesis return isExperimentalEipsTimeAtGenesis(genesis); } - private static boolean isExperimentalEipsTimeAtGenesis(final GenesisConfigFile genesis) { + private static boolean isExperimentalEipsTimeAtGenesis(final GenesisConfig genesis) { final OptionalLong experimentalEipsTime = genesis.getConfigOptions().getExperimentalEipsTime(); if (experimentalEipsTime.isPresent()) { return genesis.getTimestamp() >= experimentalEipsTime.getAsLong(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java index ef1adbb228d..8b9b0b2a967 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeader.java @@ -67,7 +67,7 @@ public BlockHeader( final BlobGas excessBlobGas, final Bytes32 parentBeaconBlockRoot, final Hash requestsHash, - final UInt64 targetBlobCount, + final UInt64 targetBlobsPerBlock, final ExecutionWitness executionWitness, final BlockHeaderFunctions blockHeaderFunctions) { super( @@ -91,7 +91,7 @@ public BlockHeader( excessBlobGas, parentBeaconBlockRoot, requestsHash, - targetBlobCount, + targetBlobsPerBlock, executionWitness); this.nonce = nonce; this.hash = Suppliers.memoize(() -> blockHeaderFunctions.hash(this)); @@ -194,8 +194,8 @@ public void writeTo(final RLPOutput out) { if (requestsHash == null) break; out.writeBytes(requestsHash); - if (targetBlobCount == null) break; - out.writeUInt64Scalar(targetBlobCount); + if (targetBlobsPerBlock == null) break; + out.writeUInt64Scalar(targetBlobsPerBlock); } while (false); out.endList(); } @@ -230,7 +230,8 @@ public static BlockHeader readFrom( final Bytes32 parentBeaconBlockRoot = !input.isEndOfCurrentList() ? input.readBytes32() : null; final Hash requestsHash = !input.isEndOfCurrentList() ? Hash.wrap(input.readBytes32()) : null; - final UInt64 targetBlobCount = !input.isEndOfCurrentList() ? input.readUInt64Scalar() : null; + final UInt64 targetBlobsPerBlock = + !input.isEndOfCurrentList() ? input.readUInt64Scalar() : null; final ExecutionWitness executionWitness = !input.isEndOfCurrentList() ? ExecutionWitness.readFrom(input) : null; @@ -258,7 +259,7 @@ public static BlockHeader readFrom( excessBlobGas, parentBeaconBlockRoot, requestsHash, - targetBlobCount, + targetBlobsPerBlock, executionWitness, blockHeaderFunctions); } @@ -313,8 +314,8 @@ public String toString() { if (requestsHash != null) { sb.append("requestsHash=").append(requestsHash); } - if (targetBlobCount != null) { - sb.append("targetBlobCount=").append(targetBlobCount); + if (targetBlobsPerBlock != null) { + sb.append("targetBlobsPerBlock=").append(targetBlobsPerBlock); } return sb.append("}").toString(); } @@ -350,7 +351,7 @@ public static org.hyperledger.besu.ethereum.core.BlockHeader convertPluginBlockH .getRequestsHash() .map(h -> Hash.fromHexString(h.toHexString())) .orElse(null), - pluginBlockHeader.getTargetBlobCount().orElse(null), + pluginBlockHeader.getTargetBlobsPerBlock().orElse(null), (ExecutionWitness) pluginBlockHeader.getExecutionWitness().orElse(null), blockHeaderFunctions); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java index a78dd281579..0258e546cad 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/BlockHeaderBuilder.java @@ -23,10 +23,14 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.witness.ExecutionWitness; +import org.hyperledger.besu.ethereum.mainnet.DifficultyCalculator; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; import org.hyperledger.besu.evm.log.LogsBloomFilter; import java.time.Instant; +import java.util.Optional; import java.util.OptionalLong; import org.apache.tuweni.bytes.Bytes; @@ -78,7 +82,7 @@ public class BlockHeaderBuilder { private Long blobGasUsed = null; private BlobGas excessBlobGas = null; private Bytes32 parentBeaconBlockRoot = null; - private UInt64 targetBlobCount = null; + private UInt64 targetBlobsPerBlock = null; private ExecutionWitness executionWitness = null; public static BlockHeaderBuilder create() { @@ -129,7 +133,7 @@ public static BlockHeaderBuilder fromHeader(final BlockHeader header) { .excessBlobGas(header.getExcessBlobGas().orElse(null)) .parentBeaconBlockRoot(header.getParentBeaconBlockRoot().orElse(null)) .requestsHash(header.getRequestsHash().orElse(null)) - .targetBlobCount(header.getTargetBlobCount().orElse(null)) + .targetBlobsPerBlock(header.getTargetBlobsPerBlock().orElse(null)) .executionWitness(header.getExecutionWitness().orElse(null)); } @@ -155,13 +159,62 @@ public static BlockHeaderBuilder fromBuilder(final BlockHeaderBuilder fromBuilde .excessBlobGas(fromBuilder.excessBlobGas) .parentBeaconBlockRoot(fromBuilder.parentBeaconBlockRoot) .requestsHash(fromBuilder.requestsHash) - .targetBlobCount(fromBuilder.targetBlobCount) + .targetBlobsPerBlock(fromBuilder.targetBlobsPerBlock) .executionWitness(fromBuilder.executionWitness) .blockHeaderFunctions(fromBuilder.blockHeaderFunctions); toBuilder.nonce = fromBuilder.nonce; return toBuilder; } + public static BlockHeaderBuilder createPending( + final ProtocolSpec protocolSpec, + final BlockHeader parentHeader, + final MiningConfiguration miningConfiguration, + final long timestamp, + final Optional maybePrevRandao, + final Optional maybeParentBeaconBlockRoot) { + + final long newBlockNumber = parentHeader.getNumber() + 1; + final long gasLimit = + protocolSpec + .getGasLimitCalculator() + .nextGasLimit( + parentHeader.getGasLimit(), + miningConfiguration.getTargetGasLimit().orElse(parentHeader.getGasLimit()), + newBlockNumber); + + final DifficultyCalculator difficultyCalculator = protocolSpec.getDifficultyCalculator(); + final var difficulty = + Difficulty.of(difficultyCalculator.nextDifficulty(timestamp, parentHeader)); + + final Wei baseFee; + if (protocolSpec.getFeeMarket().implementsBaseFee()) { + final var baseFeeMarket = (BaseFeeMarket) protocolSpec.getFeeMarket(); + baseFee = + baseFeeMarket.computeBaseFee( + newBlockNumber, + parentHeader.getBaseFee().orElse(Wei.ZERO), + parentHeader.getGasUsed(), + baseFeeMarket.targetGasUsed(parentHeader)); + } else { + baseFee = null; + } + + final Bytes32 prevRandao = maybePrevRandao.orElse(null); + final Bytes32 parentBeaconBlockRoot = maybeParentBeaconBlockRoot.orElse(null); + + return BlockHeaderBuilder.create() + .parentHash(parentHeader.getHash()) + .coinbase(miningConfiguration.getCoinbase().orElseThrow()) + .difficulty(difficulty) + .number(newBlockNumber) + .gasLimit(gasLimit) + .timestamp(timestamp) + .baseFee(baseFee) + .prevRandao(prevRandao) + .parentBeaconBlockRoot(parentBeaconBlockRoot); + } + public BlockHeader buildBlockHeader() { validateBlockHeader(); @@ -187,7 +240,7 @@ public BlockHeader buildBlockHeader() { excessBlobGas, parentBeaconBlockRoot, requestsHash, - targetBlobCount, + targetBlobsPerBlock, executionWitness, blockHeaderFunctions); } @@ -205,7 +258,7 @@ public ProcessableBlockHeader buildProcessableBlockHeader() { baseFee, mixHashOrPrevRandao, parentBeaconBlockRoot, - targetBlobCount); + targetBlobsPerBlock); } public SealableBlockHeader buildSealableBlockHeader() { @@ -232,7 +285,7 @@ public SealableBlockHeader buildSealableBlockHeader() { excessBlobGas, parentBeaconBlockRoot, requestsHash, - targetBlobCount, + targetBlobsPerBlock, executionWitness); } @@ -273,7 +326,7 @@ public BlockHeaderBuilder populateFrom(final ProcessableBlockHeader processableB baseFee(processableBlockHeader.getBaseFee().orElse(null)); processableBlockHeader.getPrevRandao().ifPresent(this::prevRandao); processableBlockHeader.getParentBeaconBlockRoot().ifPresent(this::parentBeaconBlockRoot); - processableBlockHeader.getTargetBlobCount().ifPresent(this::targetBlobCount); + processableBlockHeader.getTargetBlobsPerBlock().ifPresent(this::targetBlobsPerBlock); return this; } @@ -299,7 +352,7 @@ public BlockHeaderBuilder populateFrom(final SealableBlockHeader sealableBlockHe sealableBlockHeader.getExcessBlobGas().ifPresent(this::excessBlobGas); sealableBlockHeader.getParentBeaconBlockRoot().ifPresent(this::parentBeaconBlockRoot); requestsHash(sealableBlockHeader.getRequestsHash().orElse(null)); - sealableBlockHeader.getTargetBlobCount().ifPresent(this::targetBlobCount); + sealableBlockHeader.getTargetBlobsPerBlock().ifPresent(this::targetBlobsPerBlock); executionWitness(sealableBlockHeader.getExecutionWitness().orElse(null)); return this; } @@ -435,8 +488,8 @@ public BlockHeaderBuilder parentBeaconBlockRoot(final Bytes32 parentBeaconBlockR return this; } - public BlockHeaderBuilder targetBlobCount(final UInt64 targetBlobCount) { - this.targetBlobCount = targetBlobCount; + public BlockHeaderBuilder targetBlobsPerBlock(final UInt64 targetBlobsPerBlock) { + this.targetBlobsPerBlock = targetBlobsPerBlock; return this; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/CodeDelegation.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/CodeDelegation.java index 68fa958a8d5..ecf1da973f3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/CodeDelegation.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/CodeDelegation.java @@ -20,7 +20,7 @@ import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationEncoder; +import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import java.math.BigInteger; @@ -42,8 +42,8 @@ public class CodeDelegation implements org.hyperledger.besu.datatypes.CodeDelega private final Address address; private final long nonce; private final SECPSignature signature; - private Optional
authorizer = Optional.empty(); - private boolean isAuthorityComputed = false; + private final Supplier> authorizerSupplier = + Suppliers.memoize(this::computeAuthority); /** * An access list entry as defined in EIP-7702 @@ -107,12 +107,7 @@ public SECPSignature signature() { @Override public Optional
authorizer() { - if (!isAuthorityComputed) { - authorizer = computeAuthority(); - isAuthorityComputed = true; - } - - return authorizer; + return authorizerSupplier.get(); } @Override @@ -140,7 +135,7 @@ public BigInteger s() { private Optional
computeAuthority() { BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput(); - CodeDelegationEncoder.encodeSingleCodeDelegationWithoutSignature(this, rlpOutput); + CodeDelegationTransactionEncoder.encodeSingleCodeDelegationWithoutSignature(this, rlpOutput); final Hash hash = Hash.hash(Bytes.concatenate(MAGIC, rlpOutput.encoded())); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java index 7e037dff3a7..20650bc74aa 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/ProcessableBlockHeader.java @@ -48,7 +48,7 @@ public class ProcessableBlockHeader // parentBeaconBlockRoot is included for Cancun protected final Bytes32 parentBeaconBlockRoot; // TODO SLD Quantity or UInt64Value instead? - protected final UInt64 targetBlobCount; + protected final UInt64 targetBlobsPerBlock; protected ProcessableBlockHeader( final Hash parentHash, @@ -60,7 +60,7 @@ protected ProcessableBlockHeader( final Wei baseFee, final Bytes32 mixHashOrPrevRandao, final Bytes32 parentBeaconBlockRoot, - final UInt64 targetBlobCount) { + final UInt64 targetBlobsPerBlock) { this.parentHash = parentHash; this.coinbase = coinbase; this.difficulty = difficulty; @@ -70,7 +70,7 @@ protected ProcessableBlockHeader( this.baseFee = baseFee; this.mixHashOrPrevRandao = mixHashOrPrevRandao; this.parentBeaconBlockRoot = parentBeaconBlockRoot; - this.targetBlobCount = targetBlobCount; + this.targetBlobsPerBlock = targetBlobsPerBlock; } /** @@ -184,16 +184,37 @@ public Optional getParentBeaconBlockRoot() { } /** - * Returns the target blob count if available. + * Returns the target blobs per block if available. * - * @return the target blob count if available. + * @return the target blobs per block if available. */ @Override - public Optional getTargetBlobCount() { - return Optional.ofNullable(targetBlobCount); + public Optional getTargetBlobsPerBlock() { + return Optional.ofNullable(targetBlobsPerBlock); } public String toLogString() { return getNumber() + " (time: " + getTimestamp() + ")"; } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + sb.append("ProcessableBlockHeader{"); + sb.append("number=").append(number).append(", "); + sb.append("parentHash=").append(parentHash).append(", "); + sb.append("coinbase=").append(coinbase).append(", "); + sb.append("difficulty=").append(difficulty).append(", "); + sb.append("gasLimit=").append(gasLimit).append(", "); + sb.append("timestamp=").append(timestamp).append(", "); + sb.append("baseFee=").append(baseFee).append(", "); + sb.append("mixHashOrPrevRandao=").append(mixHashOrPrevRandao).append(", "); + if (parentBeaconBlockRoot != null) { + sb.append("parentBeaconBlockRoot=").append(parentBeaconBlockRoot).append(", "); + } + if (targetBlobsPerBlock != null) { + sb.append("targetBlobsPerBlock=").append(targetBlobsPerBlock); + } + return sb.append("}").toString(); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java index 0eefee7d184..74b0c31212d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/SealableBlockHeader.java @@ -73,7 +73,7 @@ protected SealableBlockHeader( final BlobGas excessBlobGas, final Bytes32 parentBeaconBlockRoot, final Hash requestsHash, - final UInt64 targetBlobCount, + final UInt64 targetBlobsPerBlock, final ExecutionWitness executionWitness) { super( parentHash, @@ -85,7 +85,7 @@ protected SealableBlockHeader( baseFee, mixHashOrPrevRandao, parentBeaconBlockRoot, - targetBlobCount); + targetBlobsPerBlock); this.ommersHash = ommersHash; this.stateRoot = stateRoot; this.transactionsRoot = transactionsRoot; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java index 0da8f8f28a2..e3fde4c32be 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java @@ -38,7 +38,7 @@ 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.CodeDelegationEncoder; +import org.hyperledger.besu.ethereum.core.encoding.CodeDelegationTransactionEncoder; import org.hyperledger.besu.ethereum.core.encoding.EncodingContext; import org.hyperledger.besu.ethereum.core.encoding.TransactionDecoder; import org.hyperledger.besu.ethereum.core.encoding.TransactionEncoder; @@ -937,7 +937,8 @@ private static Bytes codeDelegationPreimage( chainId, accessList, rlpOutput); - CodeDelegationEncoder.encodeCodeDelegationInner(authorizationList, rlpOutput); + CodeDelegationTransactionEncoder.encodeCodeDelegationInner( + authorizationList, rlpOutput); rlpOutput.endList(); }); return Bytes.concatenate(Bytes.of(TransactionType.DELEGATE_CODE.getSerializedType()), encoded); @@ -1091,6 +1092,10 @@ public Transaction detachedCopy() { blobsWithCommitments.map( withCommitments -> blobsWithCommitmentsDetachedCopy(withCommitments, detachedVersionedHashes.get())); + final Optional> detachedCodeDelegationList = + maybeCodeDelegationList.map( + codeDelegations -> + codeDelegations.stream().map(this::codeDelegationDetachedCopy).toList()); final var copiedTx = new Transaction( @@ -1111,7 +1116,7 @@ public Transaction detachedCopy() { chainId, detachedVersionedHashes, detachedBlobsWithCommitments, - maybeCodeDelegationList); + detachedCodeDelegationList); // copy also the computed fields, to avoid to recompute them copiedTx.sender = this.sender; @@ -1128,6 +1133,15 @@ private AccessListEntry accessListDetachedCopy(final AccessListEntry accessListE return new AccessListEntry(detachedAddress, detachedStorage); } + private CodeDelegation codeDelegationDetachedCopy(final CodeDelegation codeDelegation) { + final Address detachedAddress = Address.wrap(codeDelegation.address().copy()); + return new org.hyperledger.besu.ethereum.core.CodeDelegation( + codeDelegation.chainId(), + detachedAddress, + codeDelegation.nonce(), + codeDelegation.signature()); + } + private BlobsWithCommitments blobsWithCommitmentsDetachedCopy( final BlobsWithCommitments blobsWithCommitments, final List versionedHashes) { final var detachedCommitments = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionDecoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionDecoder.java index 6448940d8d5..88d502f7a18 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionDecoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionDecoder.java @@ -81,7 +81,7 @@ public static CodeDelegation decodeInnerPayload(final RLPInput input) { final Address address = Address.wrap(input.readBytes()); final long nonce = input.readLongScalar(); - final BigInteger yParity = input.readUInt256Scalar().toUnsignedBigInteger(); + final byte yParity = (byte) input.readUnsignedByteScalar(); final BigInteger r = input.readUInt256Scalar().toUnsignedBigInteger(); final BigInteger s = input.readUInt256Scalar().toUnsignedBigInteger(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionEncoder.java similarity index 95% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationEncoder.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionEncoder.java index 4cedf93adc2..c34de129251 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionEncoder.java @@ -25,9 +25,9 @@ import org.apache.tuweni.bytes.Bytes; -public class CodeDelegationEncoder { +public class CodeDelegationTransactionEncoder { - private CodeDelegationEncoder() { + private CodeDelegationTransactionEncoder() { // private constructor } @@ -49,7 +49,7 @@ public static void encodeSingleCodeDelegation( final CodeDelegation payload, final RLPOutput rlpOutput) { rlpOutput.startList(); encodeAuthorizationDetails(payload, rlpOutput); - rlpOutput.writeIntScalar(payload.signature().getRecId()); + rlpOutput.writeUnsignedByte(payload.signature().getRecId() & 0xFF); rlpOutput.writeBigIntegerScalar(payload.signature().getR()); rlpOutput.writeBigIntegerScalar(payload.signature().getS()); rlpOutput.endList(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java index 26bad56c6da..a97f24cbd04 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/encoding/TransactionEncoder.java @@ -41,7 +41,7 @@ interface Encoder { TransactionType.BLOB, BlobTransactionEncoder::encode, TransactionType.DELEGATE_CODE, - CodeDelegationEncoder::encode); + CodeDelegationTransactionEncoder::encode); private static final ImmutableMap POOLED_TRANSACTION_ENCODERS = ImmutableMap.of(TransactionType.BLOB, BlobPooledTransactionEncoder::encode); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java index a4772bc94d9..c86fb4d9c97 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessor.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.mainnet; import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.TransactionType; @@ -36,9 +35,7 @@ import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; -import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; -import org.hyperledger.besu.evm.operation.BlockHashOperation; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldState; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -108,8 +105,9 @@ public BlockProcessingResult processBlock( final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(blockHeader); - protocolSpec.getBlockHashProcessor().processBlockHashes(blockchain, worldState, blockHeader); - final BlockHashLookup blockHashLookup = new CachingBlockHashLookup(blockHeader, blockchain); + protocolSpec.getBlockHashProcessor().processBlockHashes(worldState, blockHeader); + final BlockHashLookup blockHashLookup = + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader); final Address miningBeneficiary = miningBeneficiaryCalculator.calculateBeneficiary(blockHeader); @@ -136,6 +134,8 @@ public BlockProcessingResult processBlock( blockHashLookup, blobGasPrice); + boolean parallelizedTxFound = false; + int nbParallelTx = 0; for (int i = 0; i < transactions.size(); i++) { final Transaction transaction = transactions.get(i); if (!hasAvailableBlockBudget(blockHeader, transaction, currentGasUsed)) { @@ -174,13 +174,21 @@ public BlockProcessingResult processBlock( currentGasUsed += transaction.getGasLimit() - transactionProcessingResult.getGasRemaining(); if (transaction.getVersionedHashes().isPresent()) { currentBlobGasUsed += - (transaction.getVersionedHashes().get().size() * CancunGasCalculator.BLOB_GAS_PER_BLOB); + (transaction.getVersionedHashes().get().size() + * protocolSpec.getGasCalculator().getBlobGasPerBlob()); } final TransactionReceipt transactionReceipt = transactionReceiptFactory.create( transaction.getType(), transactionProcessingResult, worldState, currentGasUsed); receipts.add(transactionReceipt); + if (!parallelizedTxFound + && transactionProcessingResult.getIsProcessedInParallel().isPresent()) { + parallelizedTxFound = true; + nbParallelTx = 1; + } else if (transactionProcessingResult.getIsProcessedInParallel().isPresent()) { + nbParallelTx++; + } } if (blockHeader.getBlobGasUsed().isPresent() && currentBlobGasUsed != blockHeader.getBlobGasUsed().get()) { @@ -243,7 +251,8 @@ public BlockProcessingResult processBlock( } return new BlockProcessingResult( - Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests))); + Optional.of(new BlockProcessingOutputs(worldState, receipts, maybeRequests)), + parallelizedTxFound ? Optional.of(nbParallelTx) : Optional.empty()); } protected Optional runBlockPreProcessing( @@ -252,7 +261,7 @@ protected Optional runBlockPreProcessing( final BlockHeader blockHeader, final List transactions, final Address miningBeneficiary, - final BlockHashOperation.BlockHashLookup blockHashLookup, + final BlockHashLookup blockHashLookup, final Wei blobGasPrice) { return Optional.empty(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculator.java index 7dd1be481f6..707abda32a6 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculator.java @@ -15,17 +15,33 @@ package org.hyperledger.besu.ethereum.mainnet; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; +import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; public class CancunTargetingGasLimitCalculator extends LondonTargetingGasLimitCalculator { - private static final long MAX_BLOB_GAS_PER_BLOCK = 786432L; + + /** The mainnet default maximum number of blobs per block for Cancun */ + private static final int DEFAULT_MAX_BLOBS_PER_BLOCK_CANCUN = 6; + + private final long maxBlobGasPerBlock; public CancunTargetingGasLimitCalculator( final long londonForkBlock, final BaseFeeMarket feeMarket) { + this(londonForkBlock, feeMarket, DEFAULT_MAX_BLOBS_PER_BLOCK_CANCUN); + } + + /** + * Using Cancun mainnet default of 6 blobs for maxBlobsPerBlock: getBlobGasPerBlob() * 6 blobs = + * 131072 * 6 = 786432 = 0xC0000 + */ + public CancunTargetingGasLimitCalculator( + final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) { super(londonForkBlock, feeMarket); + final CancunGasCalculator cancunGasCalculator = new CancunGasCalculator(); + this.maxBlobGasPerBlock = cancunGasCalculator.getBlobGasPerBlob() * maxBlobsPerBlock; } @Override public long currentBlobGasLimit() { - return MAX_BLOB_GAS_PER_BLOCK; + return maxBlobGasPerBlock; } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java index 58f66b6afb4..977b5031936 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessor.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.mainnet; +import static org.hyperledger.besu.evm.account.Account.MAX_NONCE; + import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.core.CodeDelegation; import org.hyperledger.besu.ethereum.core.Transaction; @@ -30,9 +32,12 @@ public class CodeDelegationProcessor { private static final Logger LOG = LoggerFactory.getLogger(CodeDelegationProcessor.class); private final Optional maybeChainId; + private final BigInteger halfCurveOrder; - public CodeDelegationProcessor(final Optional maybeChainId) { + public CodeDelegationProcessor( + final Optional maybeChainId, final BigInteger halfCurveOrder) { this.maybeChainId = maybeChainId; + this.halfCurveOrder = halfCurveOrder; } /** @@ -89,6 +94,22 @@ private void processAuthorization( return; } + if (codeDelegation.nonce() == MAX_NONCE) { + LOG.trace("Nonce of code delegation must be less than 2^64-1"); + return; + } + + if (codeDelegation.signature().getS().compareTo(halfCurveOrder) > 0) { + LOG.trace( + "Invalid signature for code delegation. S value must be less or equal than the half curve order."); + return; + } + + if (codeDelegation.signature().getRecId() != 0 && codeDelegation.signature().getRecId() != 1) { + LOG.trace("Invalid signature for code delegation. RecId must be 0 or 1."); + return; + } + final Optional
authorizer = codeDelegation.authorizer(); if (authorizer.isEmpty()) { LOG.trace("Invalid signature for code delegation"); @@ -128,7 +149,9 @@ private void processAuthorization( result.incremenentAlreadyExistingDelegators(); } - evmWorldUpdater.authorizedCodeService().addDelegatedCode(authority, codeDelegation.address()); + evmWorldUpdater + .authorizedCodeService() + .processDelegatedCodeAuthorization(authority, codeDelegation.address()); authority.incrementNonce(); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java index 0598c817bd0..79927d28cf9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetBlockHeaderValidator.java @@ -33,9 +33,10 @@ import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.ProofOfWorkValidationRule; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampBoundedByFutureParameter; import org.hyperledger.besu.ethereum.mainnet.headervalidationrules.TimestampMoreRecentThanParent; -import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import java.util.Optional; +import java.util.function.Supplier; import com.google.common.annotations.VisibleForTesting; import org.apache.tuweni.bytes.Bytes; @@ -197,8 +198,9 @@ public static BlockHeaderValidator.Builder mergeBlockHeaderValidator(final FeeMa .addRule(new IncrementalTimestampRule()); } - public static BlockHeaderValidator.Builder cancunBlockHeaderValidator(final FeeMarket feeMarket) { + public static BlockHeaderValidator.Builder blobAwareBlockHeaderValidator( + final FeeMarket feeMarket, final Supplier gasCalculator) { return mergeBlockHeaderValidator(feeMarket) - .addRule(new BlobGasValidationRule(new CancunGasCalculator())); + .addRule(new BlobGasValidationRule(gasCalculator.get())); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index 181a76b7296..766ae81a7aa 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -16,8 +16,11 @@ import static org.hyperledger.besu.ethereum.mainnet.requests.MainnetRequestsProcessor.pragueRequestsProcessors; +import org.hyperledger.besu.config.BlobScheduleOptions; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.PowAlgorithm; +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; @@ -57,6 +60,7 @@ import org.hyperledger.besu.evm.gascalculator.ConstantinopleGasCalculator; import org.hyperledger.besu.evm.gascalculator.Eip4762GasCalculator; import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.HomesteadGasCalculator; import org.hyperledger.besu.evm.gascalculator.IstanbulGasCalculator; import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; @@ -83,6 +87,8 @@ import java.util.Set; import java.util.stream.IntStream; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import com.google.common.io.Resources; import io.vertx.core.json.JsonArray; @@ -92,6 +98,9 @@ public abstract class MainnetProtocolSpecs { private static final Address RIPEMD160_PRECOMPILE = Address.fromHexString("0x0000000000000000000000000000000000000003"); + private static final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + // A consensus bug at Ethereum mainnet transaction 0xcf416c53 // deleted an empty account even when the message execution scope // failed, but the transaction itself succeeded. @@ -681,6 +690,15 @@ static ProtocolSpecBuilder cancunDefinition( FeeMarket.cancun(londonForkBlockNumber, genesisConfigOptions.getBaseFeePerGas()); } + final var cancunBlobSchedule = + genesisConfigOptions + .getBlobScheduleOptions() + .flatMap(BlobScheduleOptions::getCancun) + .orElse(BlobScheduleOptions.BlobSchedule.CANCUN_DEFAULT); + + final java.util.function.Supplier cancunGasCalcSupplier = + () -> new CancunGasCalculator(cancunBlobSchedule.getTarget()); + return shanghaiDefinition( chainId, enableRevertReason, @@ -691,12 +709,12 @@ static ProtocolSpecBuilder cancunDefinition( metricsSystem) .feeMarket(cancunFeeMarket) // gas calculator for EIP-4844 blob gas - .gasCalculator(CancunGasCalculator::new) + .gasCalculator(cancunGasCalcSupplier) // gas limit with EIP-4844 max blob gas per block .gasLimitCalculatorBuilder( feeMarket -> new CancunTargetingGasLimitCalculator( - londonForkBlockNumber, (BaseFeeMarket) feeMarket)) + londonForkBlockNumber, (BaseFeeMarket) feeMarket, cancunBlobSchedule.getMax())) // EVM changes to support EIP-1153: TSTORE and EIP-5656: MCOPY .evmBuilder( (gasCalculator, jdCacheConfig) -> @@ -719,7 +737,8 @@ static ProtocolSpecBuilder cancunDefinition( evmConfiguration.evmStackSize(), feeMarket, CoinbaseFeePriceCalculator.eip1559(), - new CodeDelegationProcessor(chainId))) + new CodeDelegationProcessor( + chainId, SIGNATURE_ALGORITHM.get().getHalfCurveOrder()))) // change to check for max blob gas per block for EIP-4844 .transactionValidatorFactoryBuilder( (evm, gasLimitCalculator, feeMarket) -> @@ -736,7 +755,10 @@ static ProtocolSpecBuilder cancunDefinition( TransactionType.BLOB), evm.getMaxInitcodeSize())) .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::cancun) - .blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator) + .blockHeaderValidatorBuilder( + fm -> + MainnetBlockHeaderValidator.blobAwareBlockHeaderValidator( + fm, cancunGasCalcSupplier)) .blockHashProcessor(new CancunBlockHashProcessor()) .name("Cancun"); } @@ -750,6 +772,12 @@ static ProtocolSpecBuilder cancunEOFDefinition( final boolean isParallelTxProcessingEnabled, final MetricsSystem metricsSystem) { + final var cancunBlobSchedule = + genesisConfigOptions + .getBlobScheduleOptions() + .flatMap(BlobScheduleOptions::getCancun) + .orElse(BlobScheduleOptions.BlobSchedule.CANCUN_DEFAULT); + ProtocolSpecBuilder protocolSpecBuilder = cancunDefinition( chainId, @@ -759,7 +787,14 @@ static ProtocolSpecBuilder cancunEOFDefinition( miningConfiguration, isParallelTxProcessingEnabled, metricsSystem); - return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("CancunEOF"); + return addEOF( + genesisConfigOptions, + chainId, + evmConfiguration, + protocolSpecBuilder, + cancunBlobSchedule.getTarget(), + cancunBlobSchedule.getMax()) + .name("CancunEOF"); } static ProtocolSpecBuilder pragueDefinition( @@ -774,6 +809,17 @@ static ProtocolSpecBuilder pragueDefinition( RequestContractAddresses requestContractAddresses = RequestContractAddresses.fromGenesis(genesisConfigOptions); + final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L); + final var pragueBlobSchedule = + genesisConfigOptions + .getBlobScheduleOptions() + .flatMap(BlobScheduleOptions::getPrague) + .orElse(BlobScheduleOptions.BlobSchedule.PRAGUE_DEFAULT); + + // EIP-3074 AUTH and AUTHCALL gas | EIP-7840 Blob schedule | EIP-7691 6/9 blob increase + final java.util.function.Supplier pragueGasCalcSupplier = + () -> new PragueGasCalculator(pragueBlobSchedule.getTarget()); + return cancunDefinition( chainId, enableRevertReason, @@ -782,8 +828,12 @@ static ProtocolSpecBuilder pragueDefinition( miningConfiguration, isParallelTxProcessingEnabled, metricsSystem) - // EIP-3074 AUTH and AUTCALL gas - .gasCalculator(PragueGasCalculator::new) + .gasCalculator(pragueGasCalcSupplier) + // EIP-7840 Blob schedule | EIP-7691 6/9 blob increase + .gasLimitCalculatorBuilder( + feeMarket -> + new PragueTargetingGasLimitCalculator( + londonForkBlockNumber, (BaseFeeMarket) feeMarket, pragueBlobSchedule.getMax())) // EIP-3074 AUTH and AUTHCALL .evmBuilder( (gasCalculator, jdCacheConfig) -> @@ -815,6 +865,14 @@ static ProtocolSpecBuilder pragueDefinition( TransactionType.DELEGATE_CODE), evm.getMaxInitcodeSize())) + // TODO SLD EIP-7840 Can we dynamically wire in the appropriate GasCalculator instead of + // overriding + // blockHeaderValidatorBuilder every time the GasCalculator changes? + // EIP-7840 blob schedule | EIP-7691 6/9 blob increase + .blockHeaderValidatorBuilder( + fm -> + MainnetBlockHeaderValidator.blobAwareBlockHeaderValidator( + fm, pragueGasCalcSupplier)) // EIP-2935 Blockhash processor .blockHashProcessor(new PragueBlockHashProcessor()) .name("Prague"); @@ -829,6 +887,12 @@ static ProtocolSpecBuilder osakaDefinition( final boolean isParallelTxProcessingEnabled, final MetricsSystem metricsSystem) { + final var osakaBlobSchedule = + genesisConfigOptions + .getBlobScheduleOptions() + .flatMap(BlobScheduleOptions::getOsaka) + .orElse(BlobScheduleOptions.BlobSchedule.OSAKA_DEFAULT); + ProtocolSpecBuilder protocolSpecBuilder = pragueDefinition( chainId, @@ -838,16 +902,34 @@ static ProtocolSpecBuilder osakaDefinition( miningConfiguration, isParallelTxProcessingEnabled, metricsSystem); - return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("Osaka"); + return addEOF( + genesisConfigOptions, + chainId, + evmConfiguration, + protocolSpecBuilder, + osakaBlobSchedule.getTarget(), + osakaBlobSchedule.getMax()) + .name("Osaka"); } private static ProtocolSpecBuilder addEOF( + final GenesisConfigOptions genesisConfigOptions, final Optional chainId, final EvmConfiguration evmConfiguration, - final ProtocolSpecBuilder protocolSpecBuilder) { + final ProtocolSpecBuilder protocolSpecBuilder, + final int targetBlobsPerBlock, + final int maxBlobsPerBlock) { + + final long londonForkBlockNumber = genesisConfigOptions.getLondonBlockNumber().orElse(0L); + final java.util.function.Supplier osakaGasCalcSupplier = + () -> new OsakaGasCalculator(targetBlobsPerBlock); return protocolSpecBuilder // EIP-7692 EOF v1 Gas calculator - .gasCalculator(OsakaGasCalculator::new) + .gasCalculator(osakaGasCalcSupplier) + .gasLimitCalculatorBuilder( + feeMarket -> + new OsakaTargetingGasLimitCalculator( + londonForkBlockNumber, (BaseFeeMarket) feeMarket, maxBlobsPerBlock)) // EIP-7692 EOF v1 EVM and opcodes .evmBuilder( (gasCalculator, jdCacheConfig) -> @@ -860,7 +942,11 @@ private static ProtocolSpecBuilder addEOF( true, List.of(MaxCodeSizeRule.from(evm), EOFValidationCodeRule.from(evm)), 1, - SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES)); + SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES)) + .blockHeaderValidatorBuilder( + fm -> + MainnetBlockHeaderValidator.blobAwareBlockHeaderValidator( + fm, osakaGasCalcSupplier)); } static ProtocolSpecBuilder verkleDefinition( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java index 2948f6d7225..66475e44176 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessor.java @@ -18,7 +18,6 @@ import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.AccessListEntry; @@ -37,6 +36,7 @@ import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.code.CodeInvalid; import org.hyperledger.besu.evm.code.CodeV0; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; @@ -296,7 +296,7 @@ public TransactionProcessingResult processTransaction( final TransactionValidationParams transactionValidationParams, final PrivateMetadataUpdater privateMetadataUpdater, final Wei blobGasPrice) { - final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState); + final EVMWorldUpdater evmWorldUpdater = new EVMWorldUpdater(worldState, gasCalculator); try { final var transactionValidator = transactionValidatorFactory.get(); LOG.trace("Starting execution of {}", transaction); @@ -362,6 +362,8 @@ public TransactionProcessingResult processTransaction( codeDelegationRefund = gasCalculator.calculateDelegateCodeGasRefund( (codeDelegationResult.alreadyExistingDelegators())); + + evmWorldUpdater.commit(); } final List accessListEntries = transaction.getAccessList().orElse(List.of()); @@ -428,7 +430,6 @@ public TransactionProcessingResult processTransaction( .miningBeneficiary(miningBeneficiary) .blockHashLookup(blockHashLookup) .contextVariables(contextVariablesBuilder.build()) - .accessListWarmAddresses(warmAddressList) .accessListWarmStorage(storageList) .accessWitness(accessWitness); @@ -453,11 +454,17 @@ public TransactionProcessingResult processTransaction( .contract(contractAddress) .inputData(initCodeBytes.slice(code.getSize())) .code(code) + .accessListWarmAddresses(warmAddressList) .build(); } else { @SuppressWarnings("OptionalGetWithoutIsPresent") // isContractCall tests isPresent final Address to = transaction.getTo().get(); final Optional maybeContract = Optional.ofNullable(evmWorldUpdater.get(to)); + + if (maybeContract.isPresent() && maybeContract.get().hasDelegatedCode()) { + warmAddressList.add(maybeContract.get().delegatedCodeAddress().get()); + } + initialFrame = commonMessageFrameBuilder .type(MessageFrame.Type.MESSAGE_CALL) @@ -468,6 +475,7 @@ public TransactionProcessingResult processTransaction( maybeContract .map(c -> messageCallProcessor.getCodeFromEVM(c.getCodeHash(), c.getCode())) .orElse(CodeV0.EMPTY_CODE)) + .accessListWarmAddresses(warmAddressList) .build(); } Deque messageFrameStack = initialFrame.getMessageFrameStack(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java index a00531b404c..c1438e2f8e8 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidator.java @@ -52,6 +52,8 @@ */ public class MainnetTransactionValidator implements TransactionValidator { + public static final BigInteger TWO_POW_8 = BigInteger.TWO.pow(8); + public static final BigInteger TWO_POW_64 = BigInteger.TWO.pow(64); public static final BigInteger TWO_POW_256 = BigInteger.TWO.pow(256); private final GasCalculator gasCalculator; @@ -158,30 +160,26 @@ private static ValidationResult validateCodeDelegation "transaction code delegation transactions must have a to address"); } - final BigInteger halfCurveOrder = SignatureAlgorithmFactory.getInstance().getHalfCurveOrder(); final Optional> validationResult = transaction .getCodeDelegationList() .map( codeDelegations -> { for (CodeDelegation codeDelegation : codeDelegations) { - if (codeDelegation.chainId().compareTo(TWO_POW_256) >= 0) { + if (codeDelegation.chainId().compareTo(TWO_POW_64) >= 0) { throw new IllegalArgumentException( - "Invalid 'chainId' value, should be < 2^256 but got " + "Invalid 'chainId' value, should be < 2^64 but got " + codeDelegation.chainId()); } - if (codeDelegation.signature().getS().compareTo(halfCurveOrder) > 0) { - return ValidationResult.invalid( - TransactionInvalidReason.INVALID_SIGNATURE, - "Invalid signature for code delegation. S value must be less or equal than the half curve order."); + if (codeDelegation.r().compareTo(TWO_POW_256) >= 0) { + throw new IllegalArgumentException( + "Invalid 'r' value, should be < 2^256 but got " + codeDelegation.r()); } - if (codeDelegation.signature().getRecId() != 0 - && codeDelegation.signature().getRecId() != 1) { - return ValidationResult.invalid( - TransactionInvalidReason.INVALID_SIGNATURE, - "Invalid signature for code delegation. RecId value must be 0 or 1."); + if (codeDelegation.s().compareTo(TWO_POW_256) >= 0) { + throw new IllegalArgumentException( + "Invalid 's' value, should be < 2^256 but got " + codeDelegation.s()); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/OsakaTargetingGasLimitCalculator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/OsakaTargetingGasLimitCalculator.java new file mode 100644 index 00000000000..903cce27dff --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/OsakaTargetingGasLimitCalculator.java @@ -0,0 +1,37 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; + +public class OsakaTargetingGasLimitCalculator extends PragueTargetingGasLimitCalculator { + + /** The mainnet default maximum number of blobs per block for Osaka */ + private static final int DEFAULT_MAX_BLOBS_PER_BLOCK_OSAKA = 12; + + public OsakaTargetingGasLimitCalculator( + final long londonForkBlock, final BaseFeeMarket feeMarket) { + super(londonForkBlock, feeMarket, DEFAULT_MAX_BLOBS_PER_BLOCK_OSAKA); + } + + /** + * Using Osaka mainnet default of 12 blobs for maxBlobsPerBlock: + * CancunGasCalculator.BLOB_GAS_PER_BLOB * 12 blobs = 131072 * 12 = 1572864 = 0x180000 + */ + public OsakaTargetingGasLimitCalculator( + final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) { + super(londonForkBlock, feeMarket, maxBlobsPerBlock); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculator.java new file mode 100644 index 00000000000..b7574c3f3db --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculator.java @@ -0,0 +1,37 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; + +public class PragueTargetingGasLimitCalculator extends CancunTargetingGasLimitCalculator { + + /** The mainnet default maximum number of blobs per block for Prague */ + private static final int DEFAULT_MAX_BLOBS_PER_BLOCK_PRAGUE = 9; + + public PragueTargetingGasLimitCalculator( + final long londonForkBlock, final BaseFeeMarket feeMarket) { + super(londonForkBlock, feeMarket, DEFAULT_MAX_BLOBS_PER_BLOCK_PRAGUE); + } + + /** + * Using Prague mainnet default of 9 blobs for maxBlobsPerBlock: + * CancunGasCalculator.BLOB_GAS_PER_BLOB * 9 blobs = 131072 * 9 = 1179648 = 0x120000 + */ + public PragueTargetingGasLimitCalculator( + final long londonForkBlock, final BaseFeeMarket feeMarket, final int maxBlobsPerBlock) { + super(londonForkBlock, feeMarket, maxBlobsPerBlock); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessor.java index 06aa3efd8ef..ccf6703bef6 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessor.java @@ -20,9 +20,9 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.code.CodeV0; import org.hyperledger.besu.evm.frame.MessageFrame; -import org.hyperledger.besu.evm.operation.BlockHashOperation; import org.hyperledger.besu.evm.processor.AbstractMessageProcessor; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -64,7 +64,7 @@ public Bytes process( final WorldUpdater worldState, final ProcessableBlockHeader blockHeader, final OperationTracer operationTracer, - final BlockHashOperation.BlockHashLookup blockHashLookup) { + final BlockHashLookup blockHashLookup) { // if no code exists at CALL_ADDRESS, the call must fail silently final Account maybeContract = worldState.get(callAddress); @@ -109,7 +109,7 @@ private MessageFrame createCallFrame( final Address callAddress, final WorldUpdater worldUpdater, final ProcessableBlockHeader blockHeader, - final BlockHashOperation.BlockHashLookup blockHashLookup) { + final BlockHashLookup blockHashLookup) { final Optional maybeContract = Optional.ofNullable(worldUpdater.get(callAddress)); final AbstractMessageProcessor processor = diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java index be2185b09a7..78d6497335a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java @@ -35,6 +35,9 @@ public interface TransactionValidationParams { TransactionValidationParams transactionSimulatorParams = ImmutableTransactionValidationParams.of(false, false, false, false, false, true); + TransactionValidationParams transactionSimulatorAllowExceedingBalanceParams = + ImmutableTransactionValidationParams.of(false, true, false, false, false, true); + @Value.Default default boolean isAllowFutureNonce() { return false; @@ -69,6 +72,10 @@ static TransactionValidationParams transactionSimulator() { return transactionSimulatorParams; } + static TransactionValidationParams transactionSimulatorAllowExceedingBalance() { + return transactionSimulatorAllowExceedingBalanceParams; + } + static TransactionValidationParams processingBlock() { return processingBlockParams; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java index e64b51afa41..ae4bf5b6f34 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessor.java @@ -16,12 +16,12 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.MutableWorldState; -import org.hyperledger.besu.plugin.data.ProcessableBlockHeader; +import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; public interface BlockHashProcessor { - void processBlockHashes( - Blockchain blockchain, - MutableWorldState worldState, - ProcessableBlockHeader currentBlockHeader); + void processBlockHashes(MutableWorldState worldState, ProcessableBlockHeader currentBlockHeader); + + BlockHashLookup createBlockHashLookup(Blockchain blockchain, ProcessableBlockHeader blockHeader); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java index 0e8b1ae8afa..3be30719e18 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/CancunBlockHashProcessor.java @@ -14,20 +14,17 @@ */ package org.hyperledger.besu.ethereum.mainnet.blockhash; -import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.mainnet.ParentBeaconBlockRootHelper; import org.hyperledger.besu.evm.worldstate.WorldUpdater; -import org.hyperledger.besu.plugin.data.ProcessableBlockHeader; /** Processes the beacon block storage if it is present in the block header. */ -public class CancunBlockHashProcessor implements BlockHashProcessor { +public class CancunBlockHashProcessor extends FrontierBlockHashProcessor { @Override public void processBlockHashes( - final Blockchain blockchain, - final MutableWorldState mutableWorldState, - final ProcessableBlockHeader currentBlockHeader) { + final MutableWorldState mutableWorldState, final ProcessableBlockHeader currentBlockHeader) { currentBlockHeader .getParentBeaconBlockRoot() .ifPresent( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/Eip7709BlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/Eip7709BlockHashProcessor.java new file mode 100644 index 00000000000..2688d400ce9 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/Eip7709BlockHashProcessor.java @@ -0,0 +1,34 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet.blockhash; + +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; +import org.hyperledger.besu.ethereum.vm.Eip7709BlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; + +/** + * Provides a way to create a BlockHashLookup that fetches hashes from system contract storage, in + * accordance with EIP-7709. It is not used yet since the fork that this EIP should go in has not + * been decided yet. + */ +public class Eip7709BlockHashProcessor extends PragueBlockHashProcessor { + + @Override + public BlockHashLookup createBlockHashLookup( + final Blockchain blockchain, final ProcessableBlockHeader blockHeader) { + return new Eip7709BlockHashLookup(historyStorageAddress, historyServeWindow); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java index f1722936b58..eba80a0eb82 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/FrontierBlockHashProcessor.java @@ -16,14 +16,31 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.MutableWorldState; -import org.hyperledger.besu.plugin.data.ProcessableBlockHeader; +import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; +import org.hyperledger.besu.ethereum.vm.BlockchainBasedBlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; +import org.hyperledger.besu.evm.operation.BlockHashOperation; public class FrontierBlockHashProcessor implements BlockHashProcessor { + @Override public void processBlockHashes( - final Blockchain blockchain, - final MutableWorldState mutableWorldState, - final ProcessableBlockHeader currentBlockHeader) { + final MutableWorldState mutableWorldState, final ProcessableBlockHeader currentBlockHeader) { // do nothing } + + /** + * Creates a new BlockHashLookup function that calculates and caches block hashes by number + * following the chain for a specific branch. This is used by {@link BlockHashOperation} and + * ensures that the correct block hash is returned even when the block being imported is on a + * fork. + * + *

A new BlockHashCache must be created for each block being processed but should be reused for + * all transactions within that block. + */ + @Override + public BlockHashLookup createBlockHashLookup( + final Blockchain blockchain, final ProcessableBlockHeader blockHeader) { + return new BlockchainBasedBlockHashLookup(blockHeader, blockchain); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java index 46a83c8b3b4..b059688c605 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/blockhash/PragueBlockHashProcessor.java @@ -16,11 +16,10 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.worldstate.WorldUpdater; -import org.hyperledger.besu.plugin.data.ProcessableBlockHeader; import com.google.common.annotations.VisibleForTesting; import org.apache.tuweni.units.bigints.UInt256; @@ -40,10 +39,10 @@ public class PragueBlockHashProcessor extends CancunBlockHashProcessor { // 0x0aae40965e6800cd9b1f4b05ff21581047e3f91e /** The HISTORY_SERVE_WINDOW */ - public static final long HISTORY_SERVE_WINDOW = 8192; + private static final long HISTORY_SERVE_WINDOW = 8192; - private final long historySaveWindow; - private final Address historyStorageAddress; + protected final long historyServeWindow; + protected final Address historyStorageAddress; /** Constructs a BlockHashProcessor. */ public PragueBlockHashProcessor() { @@ -55,21 +54,19 @@ public PragueBlockHashProcessor() { * primarily used for testing. * * @param historyStorageAddress the address of the contract storing the history - * @param historySaveWindow The number of blocks for which history should be saved. + * @param historyServeWindow The number of blocks for which history should be saved. */ @VisibleForTesting public PragueBlockHashProcessor( - final Address historyStorageAddress, final long historySaveWindow) { + final Address historyStorageAddress, final long historyServeWindow) { this.historyStorageAddress = historyStorageAddress; - this.historySaveWindow = historySaveWindow; + this.historyServeWindow = historyServeWindow; } @Override public void processBlockHashes( - final Blockchain blockchain, - final MutableWorldState mutableWorldState, - final ProcessableBlockHeader currentBlockHeader) { - super.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader); + final MutableWorldState mutableWorldState, final ProcessableBlockHeader currentBlockHeader) { + super.processBlockHashes(mutableWorldState, currentBlockHeader); WorldUpdater worldUpdater = mutableWorldState.updater(); final MutableAccount historyStorageAccount = worldUpdater.getOrCreate(historyStorageAddress); @@ -98,7 +95,7 @@ private void storeParentHash(final MutableAccount account, final ProcessableBloc * @param hash The hash to be stored. */ private void storeHash(final MutableAccount account, final long number, final Hash hash) { - UInt256 slot = UInt256.valueOf(number % historySaveWindow); + UInt256 slot = UInt256.valueOf(number % historyServeWindow); UInt256 value = UInt256.fromBytes(hash); LOG.trace( "Writing to {} {}=%{}", account.getAddress(), slot.toDecimalString(), value.toHexString()); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java index d1a148ceedf..5ba94a78ad1 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/feemarket/LondonFeeMarket.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet.feemarket; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.feemarket.TransactionPriceCalculator; @@ -28,8 +28,7 @@ public class LondonFeeMarket implements BaseFeeMarket { private static final Logger LOG = LoggerFactory.getLogger(LondonFeeMarket.class); - static final Wei DEFAULT_BASEFEE_INITIAL_VALUE = - GenesisConfigFile.BASEFEE_AT_GENESIS_DEFAULT_VALUE; + static final Wei DEFAULT_BASEFEE_INITIAL_VALUE = GenesisConfig.BASEFEE_AT_GENESIS_DEFAULT_VALUE; static final long DEFAULT_BASEFEE_MAX_CHANGE_DENOMINATOR = 8L; static final long DEFAULT_SLACK_COEFFICIENT = 2L; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java index 3a34d7be307..c986ec08588 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRule.java @@ -17,7 +17,6 @@ import org.hyperledger.besu.datatypes.BlobGas; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.mainnet.DetachedBlockHeaderValidationRule; -import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.slf4j.Logger; @@ -55,10 +54,9 @@ public boolean validate(final BlockHeader header, final BlockHeader parent) { return false; } long headerBlobGasUsed = header.getBlobGasUsed().orElse(0L); - if (headerBlobGasUsed % CancunGasCalculator.BLOB_GAS_PER_BLOB != 0) { + if (headerBlobGasUsed % gasCalculator.getBlobGasPerBlob() != 0) { LOG.info( - "blob gas used must be multiple of GAS_PER_BLOB ({})", - CancunGasCalculator.BLOB_GAS_PER_BLOB); + "blob gas used must be multiple of GAS_PER_BLOB ({})", gasCalculator.getBlobGasPerBlob()); return false; } return true; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java index d1f0d9c5127..688ff918cb4 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/MainnetParallelBlockProcessor.java @@ -28,7 +28,7 @@ import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; -import org.hyperledger.besu.evm.operation.BlockHashOperation; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.metrics.BesuMetricCategory; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -85,7 +85,7 @@ protected Optional runBlockPreProcessing( final BlockHeader blockHeader, final List transactions, final Address miningBeneficiary, - final BlockHashOperation.BlockHashLookup blockHashLookup, + final BlockHashLookup blockHashLookup, final Wei blobGasPrice) { if ((worldState instanceof DiffBasedWorldState)) { ParallelizedConcurrentTransactionProcessor parallelizedConcurrentTransactionProcessor = @@ -117,7 +117,7 @@ protected TransactionProcessingResult getTransactionProcessingResult( final Address miningBeneficiary, final Transaction transaction, final int location, - final BlockHashOperation.BlockHashLookup blockHashLookup) { + final BlockHashLookup blockHashLookup) { TransactionProcessingResult transactionProcessingResult = null; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessor.java index c6beaa2f40e..d5217bfc670 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessor.java @@ -27,7 +27,7 @@ import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.worldview.BonsaiWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldState; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; -import org.hyperledger.besu.evm.operation.BlockHashOperation; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldView; import org.hyperledger.besu.plugin.services.metrics.Counter; @@ -102,7 +102,7 @@ public void runAsyncBlock( final BlockHeader blockHeader, final List transactions, final Address miningBeneficiary, - final BlockHashOperation.BlockHashLookup blockHashLookup, + final BlockHashLookup blockHashLookup, final Wei blobGasPrice, final PrivateMetadataUpdater privateMetadataUpdater) { for (int i = 0; i < transactions.size(); i++) { @@ -133,7 +133,7 @@ public void runTransaction( final int transactionLocation, final Transaction transaction, final Address miningBeneficiary, - final BlockHashOperation.BlockHashLookup blockHashLookup, + final BlockHashLookup blockHashLookup, final Wei blobGasPrice, final PrivateMetadataUpdater privateMetadataUpdater) { try (final DiffBasedWorldState roundWorldState = @@ -251,8 +251,10 @@ public Optional applyParallelizedTransactionResult( blockAccumulator.importStateChangesFromSource(transactionAccumulator); - if (confirmedParallelizedTransactionCounter.isPresent()) + if (confirmedParallelizedTransactionCounter.isPresent()) { confirmedParallelizedTransactionCounter.get().inc(); + transactionProcessingResult.setIsProcessedInParallel(Optional.of(Boolean.TRUE)); + } return Optional.of(transactionProcessingResult); } else { blockAccumulator.importPriorStateFromSource(transactionAccumulator); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java index 708aa118f09..cf1a3dc198f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContract.java @@ -34,7 +34,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@Deprecated(since = "24.11.0") +@Deprecated(since = "24.12.0") public class PrivacyPluginPrecompiledContract extends PrivacyPrecompiledContract { private static final Logger LOG = LoggerFactory.getLogger(PrivacyPluginPrecompiledContract.class); private final PrivacyParameters privacyParameters; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/ProcessRequestContext.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/ProcessRequestContext.java index 63f4a8d5144..5615d41d716 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/ProcessRequestContext.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/ProcessRequestContext.java @@ -18,7 +18,7 @@ import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.tracing.OperationTracer; import java.util.List; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestContractAddresses.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestContractAddresses.java index d16d1bddbc0..ebc48a10fb9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestContractAddresses.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/requests/RequestContractAddresses.java @@ -23,9 +23,9 @@ public class RequestContractAddresses { private final Address consolidationRequestContractAddress; public static final Address DEFAULT_WITHDRAWAL_REQUEST_CONTRACT_ADDRESS = - Address.fromHexString("0x09FC772D0857550724B07B850A4323F39112AAAA"); + Address.fromHexString("0x0c15F14308530b7CDB8460094BbB9cC28b9AaaAA"); public static final Address DEFAULT_CONSOLIDATION_REQUEST_CONTRACT_ADDRESS = - Address.fromHexString("0x01ABEA29659E5E97C95107F20BB753CD3E09BBBB"); + Address.fromHexString("0x00431F263cE400f4455c2dCf564e53007Ca4bbBb"); public static final Address DEFAULT_DEPOSIT_CONTRACT_ADDRESS = Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa"); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java index 307a1d1e6fa..cab4d148fa7 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateGroupRehydrationBlockProcessor.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.privacy; import static org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver.EMPTY_ROOT_HASH; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -39,6 +38,7 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldUpdater; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java index 6d4811a4bca..dc2d991258a 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java @@ -25,7 +25,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import java.util.LinkedHashMap; @@ -167,7 +166,7 @@ public void rehydrate( privateStateStorage, privateStateRootResolver, block, - new CachingBlockHashLookup(blockHeader, blockchain), + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader), pmtHashToPrivateTransactionMap, block.getBody().getOmmers()); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java index ad7de59aee7..73061a86c30 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionProcessor.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.privacy; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION_HASH; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -28,6 +27,7 @@ import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.code.CodeV0; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.processor.AbstractMessageProcessor; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java index 061c56353fb..218c88f4cb2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionSimulator.java @@ -28,7 +28,6 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.transaction.CallParameter; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.tracing.OperationTracer; @@ -140,7 +139,7 @@ private Optional process( transaction, protocolSpec.getMiningBeneficiaryCalculator().calculateBeneficiary(header), OperationTracer.NO_TRACING, - new CachingBlockHashLookup(header, blockchain), + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, header), privacyGroupId); return Optional.of(result); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateMigrationBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateMigrationBlockProcessor.java index 7c51ac01cb2..d76b1a4bf7b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateMigrationBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateMigrationBlockProcessor.java @@ -14,8 +14,6 @@ */ package org.hyperledger.besu.ethereum.privacy.storage.migration; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; - import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.BlockProcessingOutputs; @@ -33,6 +31,7 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.ArrayList; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java index 834633a997d..3a005db5bc3 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java @@ -29,7 +29,6 @@ import org.hyperledger.besu.ethereum.privacy.storage.LegacyPrivateStateStorage; import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import java.util.List; @@ -113,7 +112,7 @@ public void migratePrivateStorage() { privateMigrationBlockProcessor.processBlock( blockchain, publicWorldState, - new CachingBlockHashLookup(blockHeader, blockchain), + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader), blockHeader, transactionsToProcess, ommers); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/processing/TransactionProcessingResult.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/processing/TransactionProcessingResult.java index eca28927bdd..a05ecf3d8fb 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/processing/TransactionProcessingResult.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/processing/TransactionProcessingResult.java @@ -49,6 +49,8 @@ public enum Status { private final Bytes output; + private Optional isProcessedInParallel = Optional.empty(); + private final ValidationResult validationResult; private final Optional revertReason; @@ -194,6 +196,25 @@ public ValidationResult getValidationResult() { return validationResult; } + /** + * Set isProcessedInParallel to the value in parameter + * + * @param isProcessedInParallel new value of isProcessedInParallel + */ + public void setIsProcessedInParallel(final Optional isProcessedInParallel) { + this.isProcessedInParallel = isProcessedInParallel; + } + + /** + * Returns a flag that indicates if the transaction was executed in parallel + * + * @return Optional of Boolean, the value of the boolean is true if the transaction was executed + * in parallel + */ + public Optional getIsProcessedInParallel() { + return isProcessedInParallel; + } + /** * Returns the reason why a transaction was reverted (if applicable). * diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationException.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationException.java new file mode 100644 index 00000000000..c304ed9ae1a --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationException.java @@ -0,0 +1,21 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.transaction; + +public class BlockSimulationException extends RuntimeException { + public BlockSimulationException(final String message) { + super(message); + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationResult.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationResult.java new file mode 100644 index 00000000000..da0846890f6 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulationResult.java @@ -0,0 +1,58 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.transaction; + +import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.plugin.data.BlockBody; +import org.hyperledger.besu.plugin.data.BlockHeader; +import org.hyperledger.besu.plugin.data.TransactionReceipt; + +import java.util.ArrayList; +import java.util.List; + +public class BlockSimulationResult { + final Block block; + final List receipts; + List transactionSimulationResults; + + public BlockSimulationResult( + final Block block, + final List receipts, + final List transactionSimulationResults) { + this.block = block; + this.receipts = new ArrayList<>(receipts); + this.transactionSimulationResults = transactionSimulationResults; + } + + public BlockHeader getBlockHeader() { + return block.getHeader(); + } + + public BlockBody getBlockBody() { + return block.getBody(); + } + + public List getReceipts() { + return receipts; + } + + public List getTransactionSimulations() { + return transactionSimulationResults; + } + + public Block getBlock() { + return block; + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java new file mode 100644 index 00000000000..018ce76ca7b --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockSimulator.java @@ -0,0 +1,423 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.transaction; + +import org.hyperledger.besu.datatypes.AccountOverride; +import org.hyperledger.besu.datatypes.AccountOverrideMap; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.ethereum.core.BlockBody; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.core.ParsedExtraData; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.mainnet.BodyValidation; +import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; +import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; +import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; +import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.tracing.OperationTracer; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import org.hyperledger.besu.plugin.data.BlockOverrides; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import com.google.common.annotations.VisibleForTesting; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; + +/** + * Simulates the execution of a block, processing transactions and applying state overrides. This + * class is responsible for simulating the execution of a block, which involves processing + * transactions and applying state overrides. It provides a way to test and validate the behavior of + * a block without actually executing it on the blockchain. The simulator takes into account various + * factors, such as the block header, transaction calls, and state overrides, to simulate the + * execution of the block. It returns a list of simulation results, which include the final block + * header, transaction receipts, and other relevant information. + */ +public class BlockSimulator { + private final TransactionSimulator transactionSimulator; + private final WorldStateArchive worldStateArchive; + private final ProtocolSchedule protocolSchedule; + private final MiningConfiguration miningConfiguration; + + public BlockSimulator( + final WorldStateArchive worldStateArchive, + final ProtocolSchedule protocolSchedule, + final TransactionSimulator transactionSimulator, + final MiningConfiguration miningConfiguration) { + this.worldStateArchive = worldStateArchive; + this.protocolSchedule = protocolSchedule; + this.miningConfiguration = miningConfiguration; + this.transactionSimulator = transactionSimulator; + } + + /** + * Processes a list of BlockStateCalls sequentially, collecting the results. + * + * @param header The block header for all simulations. + * @param blockStateCalls The list of BlockStateCalls to process. + * @return A list of BlockSimulationResult objects from processing each BlockStateCall. + */ + public List process( + final BlockHeader header, final List blockStateCalls) { + try (final MutableWorldState ws = + worldStateArchive + .getMutable(header, false) + .orElseThrow( + () -> + new IllegalArgumentException( + "Public world state not available for block " + header.toLogString()))) { + return process(header, blockStateCalls, ws); + } catch (IllegalArgumentException e) { + throw e; + } catch (final Exception e) { + throw new RuntimeException("Error simulating block", e); + } + } + + /** + * Processes a list of BlockStateCalls sequentially, collecting the results. + * + * @param header The block header for all simulations. + * @param blockStateCalls The list of BlockStateCalls to process. + * @param worldState The initial MutableWorldState to start with. + * @return A list of BlockSimulationResult objects from processing each BlockStateCall. + */ + public List process( + final BlockHeader header, + final List blockStateCalls, + final MutableWorldState worldState) { + List simulationResults = new ArrayList<>(); + for (BlockStateCall blockStateCall : blockStateCalls) { + BlockSimulationResult simulationResult = + processSingleBlockStateCall(header, blockStateCall, worldState); + simulationResults.add(simulationResult); + } + return simulationResults; + } + + /** + * Processes a single BlockStateCall, simulating the block execution. + * + * @param header The block header for the simulation. + * @param blockStateCall The BlockStateCall to process. + * @param ws The MutableWorldState to use for the simulation. + * @return A BlockSimulationResult from processing the BlockStateCall. + */ + private BlockSimulationResult processSingleBlockStateCall( + final BlockHeader header, final BlockStateCall blockStateCall, final MutableWorldState ws) { + BlockOverrides blockOverrides = blockStateCall.getBlockOverrides(); + long timestamp = blockOverrides.getTimestamp().orElse(header.getTimestamp() + 1); + ProtocolSpec newProtocolSpec = protocolSchedule.getForNextBlockHeader(header, timestamp); + + // Apply block header overrides and state overrides + BlockHeader blockHeader = applyBlockHeaderOverrides(header, newProtocolSpec, blockOverrides); + blockStateCall.getAccountOverrides().ifPresent(overrides -> applyStateOverrides(overrides, ws)); + + // Override the mining beneficiary calculator if a fee recipient is specified, otherwise use the + // default + MiningBeneficiaryCalculator miningBeneficiaryCalculator = + getMiningBeneficiaryCalculator(blockOverrides, newProtocolSpec); + + List transactionSimulatorResults = + processTransactions(blockHeader, blockStateCall, ws, miningBeneficiaryCalculator); + + return finalizeBlock( + blockHeader, blockStateCall, ws, newProtocolSpec, transactionSimulatorResults); + } + + @VisibleForTesting + protected List processTransactions( + final BlockHeader blockHeader, + final BlockStateCall blockStateCall, + final MutableWorldState ws, + final MiningBeneficiaryCalculator miningBeneficiaryCalculator) { + + List transactionSimulations = new ArrayList<>(); + + for (CallParameter callParameter : blockStateCall.getCalls()) { + final WorldUpdater transactionUpdater = ws.updater(); + + final Optional transactionSimulatorResult = + transactionSimulator.processWithWorldUpdater( + callParameter, + Optional.empty(), // We have already applied state overrides on block level + buildTransactionValidationParams(blockStateCall.isValidate()), + OperationTracer.NO_TRACING, + blockHeader, + transactionUpdater, + miningBeneficiaryCalculator); + + if (transactionSimulatorResult.isEmpty()) { + throw new BlockSimulationException("Transaction simulator result is empty"); + } + + TransactionSimulatorResult result = transactionSimulatorResult.get(); + if (result.isInvalid()) { + throw new BlockSimulationException( + "Transaction simulator result is invalid: " + result.getInvalidReason().orElse(null)); + } + transactionSimulations.add(transactionSimulatorResult.get()); + transactionUpdater.commit(); + } + return transactionSimulations; + } + + @VisibleForTesting + protected BlockSimulationResult finalizeBlock( + final BlockHeader blockHeader, + final BlockStateCall blockStateCall, + final MutableWorldState ws, + final ProtocolSpec protocolSpec, + final List transactionSimulations) { + + long currentGasUsed = 0; + final var transactionReceiptFactory = protocolSpec.getTransactionReceiptFactory(); + + final List receipts = new ArrayList<>(); + final List transactions = new ArrayList<>(); + + for (TransactionSimulatorResult transactionSimulatorResult : transactionSimulations) { + + TransactionProcessingResult transactionProcessingResult = transactionSimulatorResult.result(); + final Transaction transaction = transactionSimulatorResult.transaction(); + + currentGasUsed += transaction.getGasLimit() - transactionProcessingResult.getGasRemaining(); + + final TransactionReceipt transactionReceipt = + transactionReceiptFactory.create( + transaction.getType(), transactionProcessingResult, ws, currentGasUsed); + + receipts.add(transactionReceipt); + transactions.add(transaction); + } + + BlockHeader finalBlockHeader = + createFinalBlockHeader( + blockHeader, + ws, + transactions, + blockStateCall.getBlockOverrides(), + receipts, + currentGasUsed); + Block block = new Block(finalBlockHeader, new BlockBody(transactions, List.of())); + return new BlockSimulationResult(block, receipts, transactionSimulations); + } + + /** + * Applies state overrides to the world state. + * + * @param accountOverrideMap The AccountOverrideMap containing the state overrides. + * @param ws The MutableWorldState to apply the overrides to. + */ + @VisibleForTesting + protected void applyStateOverrides( + final AccountOverrideMap accountOverrideMap, final MutableWorldState ws) { + var updater = ws.updater(); + for (Address accountToOverride : accountOverrideMap.keySet()) { + final AccountOverride override = accountOverrideMap.get(accountToOverride); + MutableAccount account = updater.getOrCreate(accountToOverride); + override.getNonce().ifPresent(account::setNonce); + if (override.getBalance().isPresent()) { + account.setBalance(override.getBalance().get()); + } + override.getCode().ifPresent(n -> account.setCode(Bytes.fromHexString(n))); + override + .getStateDiff() + .ifPresent( + d -> + d.forEach( + (key, value) -> + account.setStorageValue( + UInt256.fromHexString(key), UInt256.fromHexString(value)))); + } + updater.commit(); + } + + /** + * Applies block header overrides to the block header. + * + * @param header The original block header. + * @param newProtocolSpec The ProtocolSpec for the block. + * @param blockOverrides The BlockOverrides to apply. + * @return The modified block header. + */ + @VisibleForTesting + protected BlockHeader applyBlockHeaderOverrides( + final BlockHeader header, + final ProtocolSpec newProtocolSpec, + final BlockOverrides blockOverrides) { + long timestamp = blockOverrides.getTimestamp().orElse(header.getTimestamp() + 1); + long blockNumber = blockOverrides.getBlockNumber().orElse(header.getNumber() + 1); + + return BlockHeaderBuilder.createDefault() + .parentHash(header.getHash()) + .timestamp(timestamp) + .number(blockNumber) + .coinbase( + blockOverrides + .getFeeRecipient() + .orElseGet(() -> miningConfiguration.getCoinbase().orElseThrow())) + .difficulty( + blockOverrides.getDifficulty().isPresent() + ? Difficulty.of(blockOverrides.getDifficulty().get()) + : header.getDifficulty()) + .gasLimit( + blockOverrides + .getGasLimit() + .orElseGet(() -> getNextGasLimit(newProtocolSpec, header, blockNumber))) + .baseFee( + blockOverrides + .getBaseFeePerGas() + .orElseGet(() -> getNextBaseFee(newProtocolSpec, header, blockNumber))) + .mixHash(blockOverrides.getMixHashOrPrevRandao().orElse(Hash.EMPTY)) + .extraData(blockOverrides.getExtraData().orElse(Bytes.EMPTY)) + .blockHeaderFunctions(new SimulatorBlockHeaderFunctions(blockOverrides)) + .buildBlockHeader(); + } + + /** + * Creates the final block header after applying state changes and transaction processing. + * + * @param blockHeader The original block header. + * @param ws The MutableWorldState after applying state overrides. + * @param transactions The list of transactions in the block. + * @param blockOverrides The BlockOverrides to apply. + * @param receipts The list of transaction receipts. + * @param currentGasUsed The total gas used in the block. + * @return The final block header. + */ + private BlockHeader createFinalBlockHeader( + final BlockHeader blockHeader, + final MutableWorldState ws, + final List transactions, + final BlockOverrides blockOverrides, + final List receipts, + final long currentGasUsed) { + + return BlockHeaderBuilder.createDefault() + .populateFrom(blockHeader) + .ommersHash(BodyValidation.ommersHash(List.of())) + .stateRoot(blockOverrides.getStateRoot().orElse(ws.rootHash())) + .transactionsRoot(BodyValidation.transactionsRoot(transactions)) + .receiptsRoot(BodyValidation.receiptsRoot(receipts)) + .logsBloom(BodyValidation.logsBloom(receipts)) + .gasUsed(currentGasUsed) + .withdrawalsRoot(null) + .requestsHash(null) + .mixHash(blockOverrides.getMixHashOrPrevRandao().orElse(Hash.EMPTY)) + .extraData(blockOverrides.getExtraData().orElse(Bytes.EMPTY)) + .blockHeaderFunctions(new SimulatorBlockHeaderFunctions(blockOverrides)) + .buildBlockHeader(); + } + + /** + * Builds the TransactionValidationParams for the block simulation. + * + * @param shouldValidate Whether to validate transactions. + * @return The TransactionValidationParams for the block simulation. + */ + @VisibleForTesting + ImmutableTransactionValidationParams buildTransactionValidationParams( + final boolean shouldValidate) { + + if (shouldValidate) { + return ImmutableTransactionValidationParams.builder() + .from(TransactionValidationParams.processingBlock()) + .build(); + } + + return ImmutableTransactionValidationParams.builder() + .from(TransactionValidationParams.transactionSimulator()) + .isAllowExceedingBalance(true) + .build(); + } + + private long getNextGasLimit( + final ProtocolSpec protocolSpec, final BlockHeader parentHeader, final long blockNumber) { + return protocolSpec + .getGasLimitCalculator() + .nextGasLimit( + parentHeader.getGasLimit(), + miningConfiguration.getTargetGasLimit().orElse(parentHeader.getGasLimit()), + blockNumber); + } + + /** + * Override the mining beneficiary calculator if a fee recipient is specified, otherwise use the + * default + */ + private MiningBeneficiaryCalculator getMiningBeneficiaryCalculator( + final BlockOverrides blockOverrides, final ProtocolSpec newProtocolSpec) { + if (blockOverrides.getFeeRecipient().isPresent()) { + return blockHeader -> blockOverrides.getFeeRecipient().get(); + } else { + return newProtocolSpec.getMiningBeneficiaryCalculator(); + } + } + + private Wei getNextBaseFee( + final ProtocolSpec protocolSpec, final BlockHeader parentHeader, final long blockNumber) { + return Optional.of(protocolSpec.getFeeMarket()) + .filter(FeeMarket::implementsBaseFee) + .map(BaseFeeMarket.class::cast) + .map( + feeMarket -> + feeMarket.computeBaseFee( + blockNumber, + parentHeader.getBaseFee().orElse(Wei.ZERO), + parentHeader.getGasUsed(), + feeMarket.targetGasUsed(parentHeader))) + .orElse(null); + } + + private static class SimulatorBlockHeaderFunctions implements BlockHeaderFunctions { + + private final BlockOverrides blockOverrides; + private final MainnetBlockHeaderFunctions blockHeaderFunctions = + new MainnetBlockHeaderFunctions(); + + private SimulatorBlockHeaderFunctions(final BlockOverrides blockOverrides) { + this.blockOverrides = blockOverrides; + } + + @Override + public Hash hash(final BlockHeader header) { + return blockOverrides.getBlockHash().orElseGet(() -> blockHeaderFunctions.hash(header)); + } + + @Override + public ParsedExtraData parseExtraData(final BlockHeader header) { + return blockHeaderFunctions.parseExtraData(header); + } + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockStateCall.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockStateCall.java new file mode 100644 index 00000000000..5db5faee23c --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/BlockStateCall.java @@ -0,0 +1,61 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.transaction; + +import org.hyperledger.besu.datatypes.AccountOverrideMap; +import org.hyperledger.besu.plugin.data.BlockOverrides; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class BlockStateCall { + + private final BlockOverrides blockOverrides; + + private final List calls; + + private final AccountOverrideMap accountOverrides; + + private final boolean validation; + + public BlockStateCall( + final List calls, + final BlockOverrides blockOverrides, + final AccountOverrideMap accountOverrides, + final boolean validation) { + this.calls = calls != null ? calls : new ArrayList<>(); + this.blockOverrides = + blockOverrides != null ? blockOverrides : BlockOverrides.builder().build(); + this.accountOverrides = accountOverrides; + this.validation = validation; + } + + public boolean isValidate() { + return validation; + } + + public BlockOverrides getBlockOverrides() { + return blockOverrides; + } + + public Optional getAccountOverrides() { + return Optional.ofNullable(accountOverrides); + } + + public List getCalls() { + return calls; + } +} diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java index 1c6140f1d1f..5d715f136a2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulator.java @@ -14,6 +14,7 @@ */ package org.hyperledger.besu.ethereum.transaction; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.hyperledger.besu.ethereum.mainnet.feemarket.ExcessBlobGasCalculator.calculateExcessBlobGasForParent; import org.hyperledger.besu.crypto.SECPSignature; @@ -28,15 +29,16 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor; +import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.account.Account; @@ -84,16 +86,19 @@ public class TransactionSimulator { private final Blockchain blockchain; private final WorldStateArchive worldStateArchive; private final ProtocolSchedule protocolSchedule; + private final MiningConfiguration miningConfiguration; private final long rpcGasCap; public TransactionSimulator( final Blockchain blockchain, final WorldStateArchive worldStateArchive, final ProtocolSchedule protocolSchedule, + final MiningConfiguration miningConfiguration, final long rpcGasCap) { this.blockchain = blockchain; this.worldStateArchive = worldStateArchive; this.protocolSchedule = protocolSchedule; + this.miningConfiguration = miningConfiguration; this.rpcGasCap = rpcGasCap; } @@ -141,14 +146,82 @@ public Optional process( blockHeader); } + public Optional processOnPending( + final CallParameter callParams, + final Optional maybeStateOverrides, + final TransactionValidationParams transactionValidationParams, + final OperationTracer operationTracer, + final ProcessableBlockHeader pendingBlockHeader) { + + try (final MutableWorldState disposableWorldState = + duplicateWorldStateAtParent(pendingBlockHeader.getParentHash())) { + WorldUpdater updater = getEffectiveWorldStateUpdater(disposableWorldState); + + // in order to trace the state diff we need to make sure that + // the world updater always has a parent + if (operationTracer instanceof DebugOperationTracer) { + updater = updater.parentUpdater().isPresent() ? updater : updater.updater(); + } + + return processWithWorldUpdater( + callParams, + maybeStateOverrides, + transactionValidationParams, + operationTracer, + pendingBlockHeader, + updater, + Address.ZERO); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public ProcessableBlockHeader simulatePendingBlockHeader() { + final long timestamp = MILLISECONDS.toSeconds(System.currentTimeMillis()); + final var chainHeadHeader = blockchain.getChainHeadHeader(); + final ProtocolSpec protocolSpec = + protocolSchedule.getForNextBlockHeader(chainHeadHeader, timestamp); + + final var simulatedBlockHeader = + BlockHeaderBuilder.createPending( + protocolSpec, + chainHeadHeader, + miningConfiguration, + timestamp, + Optional.empty(), + Optional.empty()) + .buildProcessableBlockHeader(); + + LOG.trace("Simulated block header: {}", simulatedBlockHeader); + + return simulatedBlockHeader; + } + + private MutableWorldState duplicateWorldStateAtParent(final Hash parentHash) { + final var parentHeader = + blockchain + .getBlockHeader(parentHash) + .orElseThrow( + () -> + new IllegalStateException("Block with hash " + parentHash + " not available")); + + final Hash parentStateRoot = parentHeader.getStateRoot(); + return worldStateArchive + .getMutable(parentHeader, false) + .orElseThrow( + () -> + new IllegalArgumentException( + "World state not available for block " + + parentHeader.getNumber() + + " with state root " + + parentStateRoot)); + } + public Optional processAtHead(final CallParameter callParams) { final var chainHeadHash = blockchain.getChainHeadHash(); return process( callParams, - ImmutableTransactionValidationParams.builder() - .from(TransactionValidationParams.transactionSimulator()) - .isAllowExceedingBalance(true) - .build(), + TransactionValidationParams.transactionSimulatorAllowExceedingBalance(), OperationTracer.NO_TRACING, (mutableWorldState, transactionSimulatorResult) -> transactionSimulatorResult, blockchain @@ -209,7 +282,7 @@ public Optional process( try (final MutableWorldState ws = getWorldState(header)) { - WorldUpdater updater = getEffectiveWorldStateUpdater(header, ws); + WorldUpdater updater = getEffectiveWorldStateUpdater(ws); // in order to trace the state diff we need to make sure that // the world updater always has a parent @@ -217,6 +290,12 @@ public Optional process( updater = updater.parentUpdater().isPresent() ? updater : updater.updater(); } + final var miningBeneficiary = + protocolSchedule + .getByBlockHeader(header) + .getMiningBeneficiaryCalculator() + .calculateBeneficiary(header); + return preWorldStateCloseGuard.apply( ws, processWithWorldUpdater( @@ -225,7 +304,8 @@ public Optional process( transactionValidationParams, operationTracer, header, - updater)); + updater, + miningBeneficiary)); } catch (final Exception e) { return Optional.empty(); @@ -268,20 +348,46 @@ public Optional processWithWorldUpdater( final TransactionValidationParams transactionValidationParams, final OperationTracer operationTracer, final BlockHeader header, - final WorldUpdater updater) { - final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(header); + final WorldUpdater updater, + final MiningBeneficiaryCalculator miningBeneficiaryCalculator) { + + final Address miningBeneficiary = miningBeneficiaryCalculator.calculateBeneficiary(header); + + return processWithWorldUpdater( + callParams, + maybeStateOverrides, + transactionValidationParams, + operationTracer, + header, + updater, + miningBeneficiary); + } + + @Nonnull + public Optional processWithWorldUpdater( + final CallParameter callParams, + final Optional maybeStateOverrides, + final TransactionValidationParams transactionValidationParams, + final OperationTracer operationTracer, + final ProcessableBlockHeader processableHeader, + final WorldUpdater updater, + final Address miningBeneficiary) { + final ProtocolSpec protocolSpec = protocolSchedule.getByBlockHeader(processableHeader); final Address senderAddress = callParams.getFrom() != null ? callParams.getFrom() : DEFAULT_FROM; - BlockHeader blockHeaderToProcess = header; - - if (transactionValidationParams.isAllowExceedingBalance() && header.getBaseFee().isPresent()) { + final ProcessableBlockHeader blockHeaderToProcess; + if (transactionValidationParams.isAllowExceedingBalance() + && processableHeader.getBaseFee().isPresent()) { blockHeaderToProcess = - BlockHeaderBuilder.fromHeader(header) + new BlockHeaderBuilder() + .populateFrom(processableHeader) .baseFee(Wei.ZERO) .blockHeaderFunctions(protocolSpec.getBlockHeaderFunctions()) - .buildBlockHeader(); + .buildProcessableBlockHeader(); + } else { + blockHeaderToProcess = processableHeader; } if (maybeStateOverrides.isPresent()) { for (Address accountToOverride : maybeStateOverrides.get().keySet()) { @@ -296,9 +402,6 @@ public Optional processWithWorldUpdater( final long simulationGasCap = calculateSimulationGasCap(callParams.getGasLimit(), blockHeaderToProcess.getGasLimit()); - final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO; - final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY; - final MainnetTransactionProcessor transactionProcessor = protocolSchedule.getByBlockHeader(blockHeaderToProcess).getTransactionProcessor(); @@ -318,12 +421,10 @@ public Optional processWithWorldUpdater( buildTransaction( callParams, transactionValidationParams, - header, + processableHeader, senderAddress, nonce, simulationGasCap, - value, - payload, blobGasPrice); if (maybeTransaction.isEmpty()) { return Optional.empty(); @@ -335,10 +436,10 @@ public Optional processWithWorldUpdater( updater, blockHeaderToProcess, transaction, + miningBeneficiary, protocolSpec - .getMiningBeneficiaryCalculator() - .calculateBeneficiary(blockHeaderToProcess), - new CachingBlockHashLookup(blockHeaderToProcess, blockchain), + .getBlockHashProcessor() + .createBlockHashLookup(blockchain, blockHeaderToProcess), false, transactionValidationParams, operationTracer, @@ -400,13 +501,15 @@ private long calculateSimulationGasCap( private Optional buildTransaction( final CallParameter callParams, final TransactionValidationParams transactionValidationParams, - final BlockHeader header, + final ProcessableBlockHeader processableHeader, final Address senderAddress, final long nonce, final long gasLimit, - final Wei value, - final Bytes payload, final Wei blobGasPrice) { + + final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO; + final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY; + final Transaction.Builder transactionBuilder = Transaction.builder() .nonce(nonce) @@ -437,18 +540,21 @@ private Optional buildTransaction( maxPriorityFeePerGas = callParams.getMaxPriorityFeePerGas().orElse(gasPrice); maxFeePerBlobGas = callParams.getMaxFeePerBlobGas().orElse(blobGasPrice); } - if (header.getBaseFee().isEmpty()) { + + if (shouldSetGasPrice(callParams, processableHeader)) { transactionBuilder.gasPrice(gasPrice); - } else if (protocolSchedule.getChainId().isPresent()) { + } + + if (shouldSetMaxFeePerGas(callParams, processableHeader)) { transactionBuilder.maxFeePerGas(maxFeePerGas).maxPriorityFeePerGas(maxPriorityFeePerGas); - } else { - return Optional.empty(); } - transactionBuilder.guessType(); - if (transactionBuilder.getTransactionType().supportsBlob()) { + if (shouldSetBlobGasPrice(callParams)) { transactionBuilder.maxFeePerBlobGas(maxFeePerBlobGas); } + + transactionBuilder.guessType(); + if (transactionBuilder.getTransactionType().requiresChainId()) { callParams .getChainId() @@ -463,8 +569,7 @@ private Optional buildTransaction( return Optional.ofNullable(transaction); } - public WorldUpdater getEffectiveWorldStateUpdater( - final BlockHeader header, final MutableWorldState publicWorldState) { + public WorldUpdater getEffectiveWorldStateUpdater(final MutableWorldState publicWorldState) { return publicWorldState.updater(); } @@ -489,4 +594,41 @@ public Optional doesAddressExist( return Optional.of(worldState.get(address) != null); } + + private boolean shouldSetGasPrice( + final CallParameter callParams, final ProcessableBlockHeader header) { + if (header.getBaseFee().isEmpty()) { + return true; + } + + // if maxPriorityFeePerGas and maxFeePerGas are not set, use gasPrice + return callParams.getMaxPriorityFeePerGas().isEmpty() && callParams.getMaxFeePerGas().isEmpty(); + } + + private boolean shouldSetMaxFeePerGas( + final CallParameter callParams, final ProcessableBlockHeader header) { + if (protocolSchedule.getChainId().isEmpty()) { + return false; + } + + if (header.getBaseFee().isEmpty()) { + return false; + } + + if (shouldSetBlobGasPrice(callParams)) { + return true; + } + + // only set maxFeePerGas and maxPriorityFeePerGas if they are present, otherwise transaction + // will be considered EIP-1559 transaction even if the simulation is for a legacy transaction + return callParams.getMaxPriorityFeePerGas().isPresent() + || callParams.getMaxFeePerGas().isPresent(); + } + + private boolean shouldSetBlobGasPrice(final CallParameter callParams) { + if (protocolSchedule.getChainId().isEmpty()) { + return false; + } + return callParams.getBlobVersionedHashes().isPresent(); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorResult.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorResult.java index 853bc4611a3..d06c6722505 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorResult.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorResult.java @@ -18,6 +18,8 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; +import java.util.Optional; + import org.apache.tuweni.bytes.Bytes; public record TransactionSimulatorResult( @@ -42,4 +44,8 @@ public Bytes getOutput() { public ValidationResult getValidationResult() { return result.getValidationResult(); } + + public Optional getInvalidReason() { + return result.getInvalidReason(); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java index ed19b80ef18..b3afcbdacb9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/trie/diffbased/common/worldview/accumulator/DiffBasedWorldStateUpdateAccumulator.java @@ -505,6 +505,8 @@ public void commit() { tracked.setStorageWasCleared(false); // storage already cleared for this transaction } }); + getUpdatedAccounts().clear(); + getDeletedAccounts().clear(); } @Override diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/BlockchainBasedBlockHashLookup.java similarity index 75% rename from ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/BlockchainBasedBlockHashLookup.java index c70af6b836b..9c09956aba9 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookup.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/BlockchainBasedBlockHashLookup.java @@ -19,8 +19,9 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; +import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.operation.BlockHashOperation; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import java.util.HashMap; import java.util.Map; @@ -33,21 +34,32 @@ *

A new BlockHashCache must be created for each block being processed but should be reused for * all transactions within that block. */ -public class CachingBlockHashLookup implements BlockHashLookup { +public class BlockchainBasedBlockHashLookup implements BlockHashLookup { + private static final int MAX_RELATIVE_BLOCK = 256; + private final long currentBlockNumber; private ProcessableBlockHeader searchStartHeader; private final Blockchain blockchain; private final Map hashByNumber = new HashMap<>(); - public CachingBlockHashLookup( + public BlockchainBasedBlockHashLookup( final ProcessableBlockHeader currentBlock, final Blockchain blockchain) { + this.currentBlockNumber = currentBlock.getNumber(); this.searchStartHeader = currentBlock; this.blockchain = blockchain; hashByNumber.put(currentBlock.getNumber() - 1, currentBlock.getParentHash()); } @Override - public Hash apply(final Long blockNumber) { + public Hash apply(final MessageFrame frame, final Long blockNumber) { + // If the current block is the genesis block or the sought block is + // not within the last 256 completed blocks, zero is returned. + if (currentBlockNumber == 0 + || blockNumber >= currentBlockNumber + || blockNumber < (currentBlockNumber - MAX_RELATIVE_BLOCK)) { + return ZERO; + } + final Hash cachedHash = hashByNumber.get(blockNumber); if (cachedHash != null) { return cachedHash; diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java new file mode 100644 index 00000000000..0627a416109 --- /dev/null +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookup.java @@ -0,0 +1,108 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.vm; + +import static org.hyperledger.besu.datatypes.Hash.ZERO; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; + +import java.util.HashMap; + +import com.google.common.annotations.VisibleForTesting; +import org.apache.tuweni.units.bigints.UInt256; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Retrieves block hashes from system contract storage and caches hashes by number, used by + * BLOCKHASH operation. + */ +public class Eip7709BlockHashLookup implements BlockHashLookup { + private static final Logger LOG = LoggerFactory.getLogger(Eip7709BlockHashLookup.class); + private static final long BLOCKHASH_SERVE_WINDOW = 256L; + + private final Address contractAddress; + private final long historyServeWindow; + private final long blockHashServeWindow; + private final HashMap hashByNumber = new HashMap<>(); + + /** + * Constructs a Eip7709BlockHashLookup. + * + * @param contractAddress the address of the contract storing the history. + * @param historyServeWindow the number of blocks for which history should be saved. + */ + public Eip7709BlockHashLookup(final Address contractAddress, final long historyServeWindow) { + this(contractAddress, historyServeWindow, BLOCKHASH_SERVE_WINDOW); + } + + /** + * Constructs a Eip7709BlockHashLookup with a specified blockHashServeWindow. This constructor is + * only used for testing. + * + * @param contractAddress the address of the contract storing the history. + * @param historyServeWindow the number of blocks for which history should be saved. + * @param blockHashServeWindow the number of block for which contract can serve the BLOCKHASH + * opcode. + */ + @VisibleForTesting + Eip7709BlockHashLookup( + final Address contractAddress, + final long historyServeWindow, + final long blockHashServeWindow) { + this.contractAddress = contractAddress; + this.historyServeWindow = historyServeWindow; + this.blockHashServeWindow = blockHashServeWindow; + } + + @Override + public Hash apply(final MessageFrame frame, final Long blockNumber) { + final long currentBlockNumber = frame.getBlockValues().getNumber(); + final long minBlockServe = Math.max(0, currentBlockNumber - blockHashServeWindow); + if (blockNumber >= currentBlockNumber || blockNumber < minBlockServe) { + LOG.trace("failed to read hash from system account for block {}", blockNumber); + return ZERO; + } + + final Hash cachedHash = hashByNumber.get(blockNumber); + if (cachedHash != null) { + return cachedHash; + } + + final WorldUpdater worldUpdater = frame.getWorldUpdater(); + Account account = worldUpdater.get(contractAddress); + if (account == null) { + LOG.error("cannot query system contract {}", contractAddress); + return ZERO; + } + + UInt256 slot = UInt256.valueOf(blockNumber % historyServeWindow); + final UInt256 value = account.getStorageValue(slot); + LOG.atTrace() + .log( + () -> + String.format( + "Read block %s for account %s returned value %s", + account.getAddress(), slot.toDecimalString(), value.toString())); + Hash blockHash = Hash.wrap(value); + hashByNumber.put(blockNumber, blockHash); + return blockHash; + } +} diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java index b0b9aa6497e..825cdec29b2 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockHeaderTestFixture.java @@ -56,7 +56,7 @@ public class BlockHeaderTestFixture { private Optional excessBlobGas = Optional.empty(); private Optional blobGasUsed = Optional.empty(); private Optional parentBeaconBlockRoot = Optional.empty(); - private Optional targetBlobCount = Optional.empty(); + private Optional targetBlobsPerBlock = Optional.empty(); public BlockHeader buildHeader() { final BlockHeaderBuilder builder = BlockHeaderBuilder.create(); @@ -82,7 +82,7 @@ public BlockHeader buildHeader() { blobGasUsed.ifPresent(builder::blobGasUsed); requestsHash.ifPresent(builder::requestsHash); parentBeaconBlockRoot.ifPresent(builder::parentBeaconBlockRoot); - targetBlobCount.ifPresent(builder::targetBlobCount); + targetBlobsPerBlock.ifPresent(builder::targetBlobsPerBlock); builder.blockHeaderFunctions(blockHeaderFunctions); return builder.buildBlockHeader(); @@ -205,8 +205,8 @@ public BlockHeaderTestFixture parentBeaconBlockRoot( return this; } - public BlockHeaderTestFixture targetBlobCount(final UInt64 targetBlobCount) { - this.targetBlobCount = Optional.of(targetBlobCount); + public BlockHeaderTestFixture targetBlobsPerBlock(final UInt64 targetBlobsPerBlock) { + this.targetBlobsPerBlock = Optional.of(targetBlobsPerBlock); return this; } } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java index 3391a0e162c..b705ba01117 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/BlockchainSetupUtil.java @@ -20,7 +20,7 @@ import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive; import static org.mockito.Mockito.mock; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.chain.Blockchain; @@ -147,9 +147,9 @@ public static BlockchainSetupUtil createForEthashChain( } private static ProtocolSchedule mainnetProtocolScheduleProvider( - final GenesisConfigFile genesisConfigFile) { + final GenesisConfig genesisConfig) { return MainnetProtocolSchedule.fromConfig( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.newDefault(), new BadBlockManager(), @@ -170,12 +170,10 @@ private static BlockchainSetupUtil create( final ProtocolContextProvider protocolContextProvider, final EthScheduler scheduler) { try { - final GenesisConfigFile genesisConfigFile = - GenesisConfigFile.fromSource(chainResources.getGenesisURL()); - final ProtocolSchedule protocolSchedule = protocolScheduleProvider.get(genesisConfigFile); + final GenesisConfig genesisConfig = GenesisConfig.fromSource(chainResources.getGenesisURL()); + final ProtocolSchedule protocolSchedule = protocolScheduleProvider.get(genesisConfig); - final GenesisState genesisState = - GenesisState.fromConfig(genesisConfigFile, protocolSchedule); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final WorldStateArchive worldArchive = storageFormat == DataStorageFormat.BONSAI @@ -267,7 +265,7 @@ private void importBlocks( } private interface ProtocolScheduleProvider { - ProtocolSchedule get(GenesisConfigFile genesisConfig); + ProtocolSchedule get(GenesisConfig genesisConfig); } private interface ProtocolContextProvider { diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java index b4eaec04d3e..873490fd451 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ExecutionContextTestFixture.java @@ -17,7 +17,7 @@ import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createBonsaiInMemoryWorldStateArchive; import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryWorldStateArchive; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; @@ -52,12 +52,12 @@ public class ExecutionContextTestFixture { private final ProtocolContext protocolContext; private ExecutionContextTestFixture( - final GenesisConfigFile genesisConfigFile, + final GenesisConfig genesisConfig, final ProtocolSchedule protocolSchedule, final KeyValueStorage blockchainKeyValueStorage, final KeyValueStorage variablesKeyValueStorage, final Optional dataStorageFormat) { - final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); this.genesis = genesisState.getBlock(); this.blockchainKeyValueStorage = blockchainKeyValueStorage; this.variablesKeyValueStorage = variablesKeyValueStorage; @@ -82,11 +82,11 @@ private ExecutionContextTestFixture( } public static ExecutionContextTestFixture create() { - return new Builder(GenesisConfigFile.mainnet()).build(); + return new Builder(GenesisConfig.mainnet()).build(); } - public static Builder builder(final GenesisConfigFile genesisConfigFile) { - return new Builder(genesisConfigFile); + public static Builder builder(final GenesisConfig genesisConfig) { + return new Builder(genesisConfig); } public Block getGenesis() { @@ -118,14 +118,14 @@ public ProtocolContext getProtocolContext() { } public static class Builder { - private final GenesisConfigFile genesisConfigFile; + private final GenesisConfig genesisConfig; private KeyValueStorage variablesKeyValueStorage; private KeyValueStorage blockchainKeyValueStorage; private ProtocolSchedule protocolSchedule; private Optional dataStorageFormat = Optional.empty(); - public Builder(final GenesisConfigFile genesisConfigFile) { - this.genesisConfigFile = genesisConfigFile; + public Builder(final GenesisConfig genesisConfig) { + this.genesisConfig = genesisConfig; } public Builder variablesKeyValueStorage(final KeyValueStorage keyValueStorage) { @@ -152,7 +152,7 @@ public ExecutionContextTestFixture build() { if (protocolSchedule == null) { protocolSchedule = new ProtocolScheduleBuilder( - genesisConfigFile.getConfigOptions(), + genesisConfig.getConfigOptions(), Optional.of(BigInteger.valueOf(42)), ProtocolSpecAdapters.create(0, Function.identity()), new PrivacyParameters(), @@ -172,7 +172,7 @@ public ExecutionContextTestFixture build() { } return new ExecutionContextTestFixture( - genesisConfigFile, + genesisConfig, protocolSchedule, variablesKeyValueStorage, blockchainKeyValueStorage, diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java index 800af844fb0..c4f492e3c80 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/MessageFrameTestFixture.java @@ -15,13 +15,13 @@ package org.hyperledger.besu.ethereum.core; import static org.hyperledger.besu.evm.frame.MessageFrame.DEFAULT_MAX_STACK_SIZE; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.chain.Blockchain; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.evm.Code; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.code.CodeV0; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -157,6 +157,8 @@ public MessageFrame build() { final Blockchain localBlockchain = this.blockchain.orElseGet(this::createDefaultBlockchain); final BlockHeader localBlockHeader = this.blockHeader.orElseGet(() -> localBlockchain.getBlockHeader(0).get()); + final ProtocolSpec protocolSpec = + executionContextTestFixture.getProtocolSchedule().getByBlockHeader(localBlockHeader); final MessageFrame frame = MessageFrame.builder() .parentMessageFrame(parentFrame) @@ -178,7 +180,10 @@ public MessageFrame build() { .miningBeneficiary(localBlockHeader.getCoinbase()) .blockHashLookup( blockHashLookup.orElseGet( - () -> new CachingBlockHashLookup(localBlockHeader, localBlockchain))) + () -> + protocolSpec + .getBlockHashProcessor() + .createBlockHashLookup(localBlockchain, localBlockHeader))) .maxStackSize(maxStackSize) .build(); stackItems.forEach(frame::pushStackItem); diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java index db1114e832b..fc5ca291233 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/ProtocolScheduleFixture.java @@ -16,7 +16,7 @@ import static org.hyperledger.besu.config.JsonUtil.normalizeKeys; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.config.JsonGenesisConfigOptions; import org.hyperledger.besu.ethereum.chain.BadBlockManager; @@ -47,7 +47,7 @@ public class ProtocolScheduleFixture { private static GenesisConfigOptions getMainnetConfigOptions() { // this method avoids reading all the alloc accounts when all we want is the "config" section try (final JsonParser jsonParser = - new JsonFactory().createParser(GenesisConfigFile.class.getResource("/mainnet.json"))) { + new JsonFactory().createParser(GenesisConfig.class.getResource("/mainnet.json"))) { while (jsonParser.nextToken() != JsonToken.END_OBJECT) { if ("config".equals(jsonParser.getCurrentName())) { diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java index 602116749b6..5cef826ed68 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/TransactionTestFixture.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.core; import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SECPSignature; import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobsWithCommitments; @@ -29,7 +30,8 @@ import org.apache.tuweni.bytes.Bytes; public class TransactionTestFixture { - + private final SECPSignature signature = + new SECPSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0); private TransactionType transactionType = TransactionType.FRONTIER; private long nonce = 0; @@ -56,6 +58,8 @@ public class TransactionTestFixture { private Optional blobs = Optional.empty(); private Optional v = Optional.empty(); + private Optional> codeDelegations = + Optional.empty(); public Transaction createTransaction(final KeyPair keys) { final Transaction.Builder builder = Transaction.builder(); @@ -93,6 +97,12 @@ public Transaction createTransaction(final KeyPair keys) { } break; case DELEGATE_CODE: + builder.maxPriorityFeePerGas(maxPriorityFeePerGas.orElse(Wei.of(500))); + builder.maxFeePerGas(maxFeePerGas.orElse(Wei.of(5000))); + builder.accessList(accessListEntries.orElse(List.of())); + builder.codeDelegations( + codeDelegations.orElse( + List.of(new CodeDelegation(chainId.get(), sender, 0, signature)))); break; } @@ -183,4 +193,10 @@ public TransactionTestFixture blobsWithCommitments(final Optional codeDelegations) { + this.codeDelegations = Optional.of(codeDelegations); + return this; + } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java index 83c0f1a4c46..a4584cc938a 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/chain/GenesisStateTest.java @@ -328,8 +328,8 @@ void genesisFromPrague(final DataStorageConfiguration dataStorageConfiguration) .isEqualTo( Hash.fromHexString( "0x6036c41849da9c076ed79654d434017387a88fb833c2856b32e18218b3341c5f")); - assertThat(header.getTargetBlobCount().isPresent()).isTrue(); - assertThat(header.getTargetBlobCount().get()).isEqualTo(UInt64.ONE); + assertThat(header.getTargetBlobsPerBlock().isPresent()).isTrue(); + assertThat(header.getTargetBlobsPerBlock().get()).isEqualTo(UInt64.ONE); assertThat(header.getHash()) .isEqualTo( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationEncoderTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionEncoderTest.java similarity index 93% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationEncoderTest.java rename to ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionEncoderTest.java index 34b7c6d4491..b09fde48dd1 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationEncoderTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/core/encoding/CodeDelegationTransactionEncoderTest.java @@ -30,7 +30,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -class CodeDelegationEncoderTest { +class CodeDelegationTransactionEncoderTest { private static final Supplier SIGNATURE_ALGORITHM = Suppliers.memoize(SignatureAlgorithmFactory::getInstance); @@ -59,7 +59,7 @@ void shouldEncodeSingleCodeDelegationWithNonceAndChainId() { "3b1dbace38ceb862a65bf2eac0637693b5c3493bcb2a022dd614c0a74cce0b99", 16), (byte) 0)); - CodeDelegationEncoder.encodeSingleCodeDelegation(authorization, output); + CodeDelegationTransactionEncoder.encodeSingleCodeDelegation(authorization, output); assertThat(output.encoded()) .isEqualTo( @@ -85,7 +85,7 @@ void shouldEncodeSingleCodeDelegationWithNonceZero() { "25b58a1ff8ad00bddbbfa1d5c2411961cbb6d08dcdc8ae88303db3c6cf983031", 16), (byte) 1)); - CodeDelegationEncoder.encodeSingleCodeDelegation(authorization, output); + CodeDelegationTransactionEncoder.encodeSingleCodeDelegation(authorization, output); assertThat(output.encoded()) .isEqualTo( @@ -111,7 +111,7 @@ void shouldEncodeSingleCodeDelegationWithChainIdZero() { "3c8a25b2becd6e666f69803d1ae3322f2e137b7745c2c7f19da80f993ffde4df", 16), (byte) 1)); - CodeDelegationEncoder.encodeSingleCodeDelegation(authorization, output); + CodeDelegationTransactionEncoder.encodeSingleCodeDelegation(authorization, output); assertThat(output.encoded()) .isEqualTo( diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java index 9a6ddeaeb73..6d8d7350a25 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/difficulty/fixed/FixedProtocolScheduleTest.java @@ -16,7 +16,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; @@ -34,7 +34,7 @@ public void reportedDifficultyForAllBlocksIsAFixedValue() { final ProtocolSchedule schedule = FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java index c9e43327d96..0d05376183d 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/AbstractBlockProcessorIntegrationTest.java @@ -17,7 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SECPPrivateKey; import org.hyperledger.besu.crypto.SignatureAlgorithm; @@ -87,7 +87,7 @@ class AbstractBlockProcessorIntegrationTest { public void setUp() { final ExecutionContextTestFixture contextTestFixture = ExecutionContextTestFixture.builder( - GenesisConfigFile.fromResource( + GenesisConfig.fromResource( "/org/hyperledger/besu/ethereum/mainnet/genesis-bp-it.json")) .dataStorageFormat(DataStorageFormat.BONSAI) .build(); @@ -100,7 +100,7 @@ public void setUp() { private static Stream blockProcessorProvider() { final ExecutionContextTestFixture contextTestFixture = ExecutionContextTestFixture.builder( - GenesisConfigFile.fromResource( + GenesisConfig.fromResource( "/org/hyperledger/besu/ethereum/mainnet/genesis-bp-it.json")) .dataStorageFormat(DataStorageFormat.BONSAI) .build(); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculatorTest.java new file mode 100644 index 00000000000..c732aeafb75 --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CancunTargetingGasLimitCalculatorTest.java @@ -0,0 +1,33 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; + +class CancunTargetingGasLimitCalculatorTest { + + @Test + void currentBlobGasLimitIs6Blobs() { + var cancunTargetingGasLimitCalculator = + new CancunTargetingGasLimitCalculator(0L, FeeMarket.cancun(0L, Optional.empty())); + assertThat(cancunTargetingGasLimitCalculator.currentBlobGasLimit()).isEqualTo(0xC0000); + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessorTest.java new file mode 100644 index 00000000000..c4b45f9e08c --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/CodeDelegationProcessorTest.java @@ -0,0 +1,236 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.crypto.SECPSignature; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.CodeDelegation; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.worldstate.DelegatedCodeService; +import org.hyperledger.besu.evm.worldstate.EVMWorldUpdater; + +import java.math.BigInteger; +import java.util.List; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class CodeDelegationProcessorTest { + + @Mock private EVMWorldUpdater worldUpdater; + + @Mock private Transaction transaction; + + @Mock private DelegatedCodeService authorizedCodeService; + + @Mock private MutableAccount authority; + + private CodeDelegationProcessor processor; + private static final BigInteger CHAIN_ID = BigInteger.valueOf(1); + private static final BigInteger HALF_CURVE_ORDER = BigInteger.valueOf(1000); + private static final Address DELEGATE_ADDRESS = + Address.fromHexString("0x9876543210987654321098765432109876543210"); + + @BeforeEach + void setUp() { + processor = new CodeDelegationProcessor(Optional.of(CHAIN_ID), HALF_CURVE_ORDER); + } + + @Test + void shouldRejectInvalidChainId() { + // Arrange + CodeDelegation codeDelegation = createCodeDelegation(BigInteger.valueOf(2), 0L); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(worldUpdater, never()).createAccount(any()); + verify(worldUpdater, never()).getAccount(any()); + } + + @Test + void shouldRejectMaxNonce() { + // Arrange + CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, Account.MAX_NONCE); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(worldUpdater, never()).createAccount(any()); + verify(worldUpdater, never()).getAccount(any()); + } + + @Test + void shouldProcessValidDelegationForNewAccount() { + // Arrange + when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService); + CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 0L); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + when(worldUpdater.getAccount(any())).thenReturn(null); + when(worldUpdater.createAccount(any())).thenReturn(authority); + when(authority.getNonce()).thenReturn(0L); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(worldUpdater).createAccount(any()); + verify(authority).incrementNonce(); + verify(authorizedCodeService).processDelegatedCodeAuthorization(authority, DELEGATE_ADDRESS); + } + + @Test + void shouldProcessValidDelegationForExistingAccount() { + // Arrange + when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService); + CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 1L); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + when(worldUpdater.getAccount(any())).thenReturn(authority); + when(authority.getNonce()).thenReturn(1L); + when(authorizedCodeService.canSetDelegatedCode(any())).thenReturn(true); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isEqualTo(1); + verify(worldUpdater, never()).createAccount(any()); + verify(authority).incrementNonce(); + verify(authorizedCodeService).processDelegatedCodeAuthorization(authority, DELEGATE_ADDRESS); + } + + @Test + void shouldRejectDelegationWithInvalidNonce() { + // Arrange + when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService); + CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 2L); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + when(worldUpdater.getAccount(any())).thenReturn(authority); + when(authorizedCodeService.canSetDelegatedCode(any())).thenReturn(true); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(authority, never()).incrementNonce(); + verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any()); + } + + @Test + void shouldRejectDelegationWithSGreaterThanHalfCurveOrder() { + // Arrange + CodeDelegation codeDelegation = + createCodeDelegation(CHAIN_ID, 1L, HALF_CURVE_ORDER.add(BigInteger.ONE)); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(authority, never()).incrementNonce(); + verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any()); + } + + @Test + void shouldRejectDelegationWithRecIdNeitherZeroNorOne() { + // Arrange + final SECPSignature signature = new SECPSignature(BigInteger.ONE, BigInteger.ONE, (byte) 2); + CodeDelegation codeDelegation = + new org.hyperledger.besu.ethereum.core.CodeDelegation( + CHAIN_ID, CodeDelegationProcessorTest.DELEGATE_ADDRESS, 1L, signature); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(authority, never()).incrementNonce(); + verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any()); + } + + @Test + void shouldRejectDelegationWithInvalidSignature() { + // Arrange + CodeDelegation codeDelegation = mock(org.hyperledger.besu.ethereum.core.CodeDelegation.class); + when(codeDelegation.chainId()).thenReturn(CHAIN_ID); + when(codeDelegation.nonce()).thenReturn(1L); + when(codeDelegation.signature()) + .thenReturn(new SECPSignature(BigInteger.ONE, BigInteger.ONE, (byte) 0)); + when(codeDelegation.authorizer()).thenReturn(Optional.empty()); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(authority, never()).incrementNonce(); + verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any()); + } + + @Test + void shouldRejectDelegationWhenCannotSetDelegatedCode() { + // Arrange + when(worldUpdater.authorizedCodeService()).thenReturn(authorizedCodeService); + CodeDelegation codeDelegation = createCodeDelegation(CHAIN_ID, 1L); + when(transaction.getCodeDelegationList()).thenReturn(Optional.of(List.of(codeDelegation))); + when(worldUpdater.getAccount(any())).thenReturn(authority); + when(authorizedCodeService.canSetDelegatedCode(any())).thenReturn(false); + + // Act + CodeDelegationResult result = processor.process(worldUpdater, transaction); + + // Assert + assertThat(result.alreadyExistingDelegators()).isZero(); + verify(authority, never()).incrementNonce(); + verify(authorizedCodeService, never()).processDelegatedCodeAuthorization(any(), any()); + } + + private CodeDelegation createCodeDelegation(final BigInteger chainId, final long nonce) { + return createCodeDelegation(chainId, nonce, BigInteger.ONE); + } + + private CodeDelegation createCodeDelegation( + final BigInteger chainId, final long nonce, final BigInteger s) { + final SECPSignature signature = new SECPSignature(BigInteger.ONE, s, (byte) 0); + + return new org.hyperledger.besu.ethereum.core.CodeDelegation( + chainId, CodeDelegationProcessorTest.DELEGATE_ADDRESS, nonce, signature); + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java index 9ce20cb6267..bec03463336 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolScheduleTest.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.mainnet; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; @@ -71,7 +71,7 @@ public void shouldReturnDefaultProtocolSpecsWhenCustomNumbersAreNotUsed() { public void shouldOnlyUseFrontierWhenEmptyJsonConfigIsUsed() { final ProtocolSchedule sched = MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.fromConfig("{}").getConfigOptions(), + GenesisConfig.fromConfig("{}").getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), @@ -88,7 +88,7 @@ public void createFromConfigWithSettings() { "{\"config\": {\"homesteadBlock\": 2, \"daoForkBlock\": 3, \"eip150Block\": 14, \"eip158Block\": 15, \"byzantiumBlock\": 16, \"constantinopleBlock\": 18, \"petersburgBlock\": 19, \"chainId\":1234}}"; final ProtocolSchedule sched = MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.fromConfig(json).getConfigOptions(), + GenesisConfig.fromConfig(json).getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), @@ -122,7 +122,7 @@ public void outOfOrderConstantinoplesFail() { .isThrownBy( () -> MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.fromConfig(json).getConfigOptions(), + GenesisConfig.fromConfig(json).getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java index ea09dacc127..ecaa2a009f6 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionProcessorTest.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.mainnet; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.when; @@ -31,6 +30,7 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.ethereum.trie.MerkleTrieException; import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.gascalculator.LondonGasCalculator; @@ -90,7 +90,7 @@ MainnetTransactionProcessor createTransactionProcessor(final boolean warmCoinbas MAX_STACK_SIZE, FeeMarket.legacy(), CoinbaseFeePriceCalculator.frontier(), - new CodeDelegationProcessor(Optional.of(BigInteger.ONE))); + new CodeDelegationProcessor(Optional.of(BigInteger.ONE), BigInteger.TEN)); } @Test diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java index 182f1b609e8..c673bf08f68 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/MainnetTransactionValidatorTest.java @@ -24,7 +24,7 @@ import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.UPFRONT_COST_EXCEEDS_BALANCE; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -589,7 +589,7 @@ public void shouldRejectContractCreateWithBlob() { @Test public void shouldAcceptTransactionWithAtLeastOneBlob() { - when(gasCalculator.blobGasCost(anyInt())).thenReturn(2L); + when(gasCalculator.blobGasCost(anyLong())).thenReturn(2L); final TransactionValidator validator = createTransactionValidator( gasCalculator, diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculatorTest.java new file mode 100644 index 00000000000..e85b89bdfec --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PragueTargetingGasLimitCalculatorTest.java @@ -0,0 +1,33 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.mainnet; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; + +import java.util.Optional; + +import org.junit.jupiter.api.Test; + +class PragueTargetingGasLimitCalculatorTest { + + @Test + void currentBlobGasLimitIs9BlobsByDefault() { + var pragueTargetingGasLimitCalculator = + new PragueTargetingGasLimitCalculator(0L, FeeMarket.cancun(0L, Optional.empty())); + assertThat(pragueTargetingGasLimitCalculator.currentBlobGasLimit()).isEqualTo(0x120000); + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java index 2749b37fcdc..d80e183da28 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java @@ -34,6 +34,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture; import org.hyperledger.besu.ethereum.core.TransactionReceipt; +import org.hyperledger.besu.ethereum.mainnet.blockhash.BlockHashProcessor; import org.hyperledger.besu.ethereum.privacy.PrivateStateGenesisAllocator; import org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver; import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor; @@ -221,6 +222,8 @@ private ProtocolSpec mockProtocolSpec() { when(protocolSpec.getMiningBeneficiaryCalculator()) .thenReturn(mock(MiningBeneficiaryCalculator.class)); when(protocolSpec.isSkipZeroBlockRewards()).thenReturn(true); + final BlockHashProcessor blockHashProcessor = mock(BlockHashProcessor.class); + when(protocolSpec.getBlockHashProcessor()).thenReturn(blockHashProcessor); return protocolSpec; } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessorTest.java index 14275f7d12e..fe44c3ce4c6 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/SystemCallProcessorTest.java @@ -25,8 +25,8 @@ import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.frame.MessageFrame; -import org.hyperledger.besu.evm.operation.BlockHashOperation; import org.hyperledger.besu.evm.processor.AbstractMessageProcessor; import org.hyperledger.besu.evm.processor.MessageCallProcessor; import org.hyperledger.besu.evm.tracing.OperationTracer; @@ -41,7 +41,7 @@ public class SystemCallProcessorTest { private static final Bytes EXPECTED_OUTPUT = Bytes.fromHexString("0x01"); private ProcessableBlockHeader mockBlockHeader; private MainnetTransactionProcessor mockTransactionProcessor; - private BlockHashOperation.BlockHashLookup mockBlockHashLookup; + private BlockHashLookup mockBlockHashLookup; private AbstractMessageProcessor mockMessageCallProcessor; @BeforeEach @@ -49,7 +49,7 @@ public void setUp() { mockBlockHeader = mock(ProcessableBlockHeader.class); mockTransactionProcessor = mock(MainnetTransactionProcessor.class); mockMessageCallProcessor = mock(MessageCallProcessor.class); - mockBlockHashLookup = mock(BlockHashOperation.BlockHashLookup.class); + mockBlockHashLookup = mock(BlockHashLookup.class); when(mockTransactionProcessor.getMessageProcessor(any())).thenReturn(mockMessageCallProcessor); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java index 8ef178559a9..b558b0f2759 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/blockhash/BlockHashProcessorTest.java @@ -23,20 +23,16 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.datatypes.Hash; -import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.evm.account.MutableAccount; import org.hyperledger.besu.evm.worldstate.WorldUpdater; -import java.util.Optional; - import org.apache.tuweni.units.bigints.UInt256; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; class BlockHashProcessorTest { - private Blockchain blockchain; private WorldUpdater worldUpdater; private MutableWorldState mutableWorldState; private MutableAccount account; @@ -46,7 +42,6 @@ class BlockHashProcessorTest { @BeforeEach void setUp() { - blockchain = mock(Blockchain.class); mutableWorldState = mock(MutableWorldState.class); worldUpdater = mock(WorldUpdater.class); account = mock(MutableAccount.class); @@ -61,7 +56,7 @@ void shouldStoreParentBlockHash() { processor = new PragueBlockHashProcessor(); BlockHeader currentBlockHeader = mockBlockHeader(currentBlock); mockAncestorHeaders(currentBlockHeader, 3); - processor.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader); + processor.processBlockHashes(mutableWorldState, currentBlockHeader); // only parent slot number must be set verify(account, times(1)).setStorageValue(any(), any()); verifyAccount(currentBlock - 1, historicalWindow); @@ -76,7 +71,7 @@ void shouldNotStoreBlockHashForGenesisBlock() { BlockHeader currentBlockHeader = mockBlockHeader(currentBlock); mockAncestorHeaders(currentBlockHeader, 0); - processor.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader); + processor.processBlockHashes(mutableWorldState, currentBlockHeader); verifyNoInteractions(account); } @@ -89,7 +84,7 @@ void shouldStoreAncestorBlockHashesAtForkCorrectlyParentIsGenesis() { BlockHeader currentBlockHeader = mockBlockHeader(currentBlock); mockAncestorHeaders(currentBlockHeader, 10); - processor.processBlockHashes(blockchain, mutableWorldState, currentBlockHeader); + processor.processBlockHashes(mutableWorldState, currentBlockHeader); verify(account, times(1)).setStorageValue(any(), any()); verifyAccount(0, historicalWindow); } @@ -99,7 +94,7 @@ void shouldWriteGenesisHashAtSlot0() { processor = new PragueBlockHashProcessor(); BlockHeader header = mockBlockHeader(1); mockAncestorHeaders(header, 1); - processor.processBlockHashes(blockchain, mutableWorldState, header); + processor.processBlockHashes(mutableWorldState, header); verify(account) .setStorageValue(UInt256.valueOf(0), UInt256.fromHexString(Hash.ZERO.toHexString())); } @@ -126,7 +121,6 @@ private BlockHeader mockBlockHeader(final long currentNumber) { when(blockHeader.getHash()).thenReturn(hash); when(blockHeader.getTimestamp()).thenReturn(currentNumber); when(blockHeader.getParentHash()).thenReturn(parentHash); - when(blockchain.getBlockHeader(hash)).thenReturn(Optional.of(blockHeader)); return blockHeader; } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRuleTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRuleTest.java index 858a8a9a26c..c188f38d937 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRuleTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/headervalidationrules/BlobGasValidationRuleTest.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.evm.gascalculator.CancunGasCalculator; +import org.hyperledger.besu.evm.gascalculator.PragueGasCalculator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -27,19 +28,28 @@ /** Tests for the {@link BlobGasValidationRule} class. */ public class BlobGasValidationRuleTest { - private CancunGasCalculator gasCalculator; - private BlobGasValidationRule blobGasValidationRule; + private CancunGasCalculator cancunGasCalculator; + private BlobGasValidationRule cancunBlobGasValidationRule; + + private PragueGasCalculator pragueGasCalculator; + private BlobGasValidationRule pragueBlobGasValidationRule; @BeforeEach public void setUp() { - gasCalculator = new CancunGasCalculator(); - blobGasValidationRule = new BlobGasValidationRule(gasCalculator); + cancunGasCalculator = new CancunGasCalculator(); + cancunBlobGasValidationRule = new BlobGasValidationRule(cancunGasCalculator); + + pragueGasCalculator = new PragueGasCalculator(); + pragueBlobGasValidationRule = new BlobGasValidationRule(pragueGasCalculator); } - /** Tests that the header blob gas matches the calculated blob gas and passes validation. */ + /** + * Cancun EIP-4844 - Tests that the header blob gas matches the calculated blob gas and passes + * validation. + */ @Test public void validateHeader_BlobGasMatchesCalculated_SuccessValidation() { - long target = gasCalculator.getTargetBlobGasPerBlock(); + long target = cancunGasCalculator.getTargetBlobGasPerBlock(); // Create parent header final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture(); @@ -52,15 +62,59 @@ public void validateHeader_BlobGasMatchesCalculated_SuccessValidation() { headerBuilder.excessBlobGas(BlobGas.of(1L)); final BlockHeader header = headerBuilder.buildHeader(); - assertThat(blobGasValidationRule.validate(header, parentHeader)).isTrue(); + assertThat(cancunBlobGasValidationRule.validate(header, parentHeader)).isTrue(); } /** - * Tests that the header blob gas is different from the calculated blob gas and fails validation. + * Cancun EIP-4844 - Tests that the header blob gas is different from the calculated blob gas and + * fails validation. */ @Test public void validateHeader_BlobGasDifferentFromCalculated_FailsValidation() { - long target = gasCalculator.getTargetBlobGasPerBlock(); + long target = cancunGasCalculator.getTargetBlobGasPerBlock(); + + // Create parent header + final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture(); + parentBuilder.excessBlobGas(BlobGas.of(1L)); + parentBuilder.blobGasUsed(target); + final BlockHeader parentHeader = parentBuilder.buildHeader(); + + // Create block header with different excessBlobGas + final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); + final BlockHeader header = headerBuilder.buildHeader(); + + assertThat(cancunBlobGasValidationRule.validate(header, parentHeader)).isFalse(); + } + + /** + * Prague EIP-7840 - Tests that the header blob gas matches the calculated blob gas and passes + * validation. + */ + @Test + public void validateHeader_BlobGasMatchesCalculated_SuccessValidation_Prague() { + long target = pragueGasCalculator.getTargetBlobGasPerBlock(); + + // Create parent header + final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture(); + parentBuilder.excessBlobGas(BlobGas.of(1L)); + parentBuilder.blobGasUsed(target); + final BlockHeader parentHeader = parentBuilder.buildHeader(); + + // Create block header with matching excessBlobGas + final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); + headerBuilder.excessBlobGas(BlobGas.of(1L)); + final BlockHeader header = headerBuilder.buildHeader(); + + assertThat(pragueBlobGasValidationRule.validate(header, parentHeader)).isTrue(); + } + + /** + * Prague EIP-7840 - Tests that the header blob gas is different from the calculated blob gas and + * fails validation. + */ + @Test + public void validateHeader_BlobGasDifferentFromCalculated_FailsValidation_Prague() { + long target = pragueGasCalculator.getTargetBlobGasPerBlock(); // Create parent header final BlockHeaderTestFixture parentBuilder = new BlockHeaderTestFixture(); @@ -72,6 +126,6 @@ public void validateHeader_BlobGasDifferentFromCalculated_FailsValidation() { final BlockHeaderTestFixture headerBuilder = new BlockHeaderTestFixture(); final BlockHeader header = headerBuilder.buildHeader(); - assertThat(blobGasValidationRule.validate(header, parentHeader)).isFalse(); + assertThat(pragueBlobGasValidationRule.validate(header, parentHeader)).isFalse(); } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java index bba91843568..c446b18f28b 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/parallelization/ParallelizedConcurrentTransactionProcessorTest.java @@ -42,8 +42,8 @@ import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.DiffBasedWorldStateConfig; import org.hyperledger.besu.ethereum.trie.diffbased.common.worldview.accumulator.DiffBasedWorldStateUpdateAccumulator; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.evm.operation.BlockHashOperation; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -110,7 +110,7 @@ void testRunTransaction() { 0, transaction, miningBeneficiary, - (blockNumber) -> Hash.EMPTY, + (__, ___) -> Hash.EMPTY, blobGasPrice, privateMetadataUpdater); @@ -121,7 +121,7 @@ void testRunTransaction() { eq(transaction), eq(miningBeneficiary), any(OperationTracer.class), - any(BlockHashOperation.BlockHashLookup.class), + any(BlockHashLookup.class), eq(true), eq(TransactionValidationParams.processingBlock()), eq(privateMetadataUpdater), @@ -156,7 +156,7 @@ void testRunTransactionWithFailure() { 0, transaction, miningBeneficiary, - (blockNumber) -> Hash.EMPTY, + (__, ___) -> Hash.EMPTY, blobGasPrice, privateMetadataUpdater); @@ -185,7 +185,7 @@ void testRunTransactionWithConflict() { 0, transaction, miningBeneficiary, - (blockNumber) -> Hash.EMPTY, + (__, ___) -> Hash.EMPTY, blobGasPrice, privateMetadataUpdater); @@ -196,7 +196,7 @@ void testRunTransactionWithConflict() { eq(transaction), eq(miningBeneficiary), any(OperationTracer.class), - any(BlockHashOperation.BlockHashLookup.class), + any(BlockHashLookup.class), eq(true), eq(TransactionValidationParams.processingBlock()), eq(privateMetadataUpdater), diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java index fc08f519d3d..c4653856ef1 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/FlexiblePrivacyPrecompiledContractTest.java @@ -20,7 +20,6 @@ import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.versionedPrivateTransactionBesu; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_IS_PERSISTING_PRIVATE_STATE; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; @@ -51,6 +50,7 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator; import org.hyperledger.besu.evm.log.Log; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContractTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContractTest.java index 34a5c3af355..abe356c944e 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContractTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContractTest.java @@ -21,7 +21,6 @@ import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_TRANSACTION; import static org.hyperledger.besu.ethereum.privacy.PrivateTransaction.readFrom; import static org.hyperledger.besu.ethereum.privacy.PrivateTransaction.serialize; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import static org.mockito.ArgumentMatchers.nullable; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -43,6 +42,7 @@ import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator; import org.hyperledger.besu.evm.log.Log; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java index 7d253057ac7..6b333ef3497 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java @@ -21,7 +21,6 @@ import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateTransactionBesu; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_IS_PERSISTING_PRIVATE_STATE; import static org.hyperledger.besu.ethereum.mainnet.PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.nullable; @@ -54,6 +53,7 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator; import org.hyperledger.besu.evm.log.Log; diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java new file mode 100644 index 00000000000..bb1225107ec --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/BlockSimulatorTest.java @@ -0,0 +1,251 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.transaction; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.datatypes.AccountOverride; +import org.hyperledger.besu.datatypes.AccountOverrideMap; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; +import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; +import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.MiningBeneficiaryCalculator; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; +import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket; +import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.evm.account.MutableAccount; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; +import org.hyperledger.besu.plugin.data.BlockOverrides; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.units.bigints.UInt256; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +public class BlockSimulatorTest { + + @Mock private WorldStateArchive worldStateArchive; + @Mock private ProtocolSchedule protocolSchedule; + @Mock private TransactionSimulator transactionSimulator; + @Mock private MiningConfiguration miningConfiguration; + @Mock private MutableWorldState mutableWorldState; + private BlockHeader blockHeader; + + private BlockSimulator blockSimulator; + + @BeforeEach + public void setUp() { + blockSimulator = + new BlockSimulator( + worldStateArchive, protocolSchedule, transactionSimulator, miningConfiguration); + blockHeader = BlockHeaderBuilder.createDefault().buildBlockHeader(); + ProtocolSpec protocolSpec = mock(ProtocolSpec.class); + when(miningConfiguration.getCoinbase()) + .thenReturn(Optional.ofNullable(Address.fromHexString("0x1"))); + when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(protocolSpec); + when(protocolSpec.getMiningBeneficiaryCalculator()) + .thenReturn(mock(MiningBeneficiaryCalculator.class)); + GasLimitCalculator gasLimitCalculator = mock(GasLimitCalculator.class); + when(protocolSpec.getGasLimitCalculator()).thenReturn(gasLimitCalculator); + when(gasLimitCalculator.nextGasLimit(anyLong(), anyLong(), anyLong())).thenReturn(1L); + when(protocolSpec.getFeeMarket()).thenReturn(mock(FeeMarket.class)); + } + + @Test + public void shouldProcessWithValidWorldState() { + when(worldStateArchive.getMutable(any(BlockHeader.class), eq(false))) + .thenReturn(Optional.of(mutableWorldState)); + + List results = + blockSimulator.process(blockHeader, Collections.emptyList()); + + assertNotNull(results); + verify(worldStateArchive).getMutable(any(BlockHeader.class), eq(false)); + } + + @Test + public void shouldNotProcessWithInvalidWorldState() { + when(worldStateArchive.getMutable(any(BlockHeader.class), eq(false))) + .thenReturn(Optional.empty()); + + IllegalArgumentException exception = + assertThrows( + IllegalArgumentException.class, + () -> blockSimulator.process(blockHeader, Collections.emptyList())); + + assertEquals( + String.format("Public world state not available for block %s", blockHeader.toLogString()), + exception.getMessage()); + } + + @Test + public void shouldStopWhenTransactionSimulationIsInvalid() { + + CallParameter callParameter = mock(CallParameter.class); + BlockStateCall blockStateCall = new BlockStateCall(List.of(callParameter), null, null, true); + + TransactionSimulatorResult transactionSimulatorResult = mock(TransactionSimulatorResult.class); + when(transactionSimulatorResult.isInvalid()).thenReturn(true); + when(transactionSimulatorResult.getInvalidReason()) + .thenReturn(Optional.of("Invalid Transaction")); + + when(transactionSimulator.processWithWorldUpdater( + any(), any(), any(), any(), any(), any(), any(MiningBeneficiaryCalculator.class))) + .thenReturn(Optional.of(transactionSimulatorResult)); + + BlockSimulationException exception = + assertThrows( + BlockSimulationException.class, + () -> blockSimulator.process(blockHeader, List.of(blockStateCall), mutableWorldState)); + + assertEquals( + "Transaction simulator result is invalid: Invalid Transaction", exception.getMessage()); + } + + @Test + public void shouldStopWhenTransactionSimulationIsEmpty() { + + CallParameter callParameter = mock(CallParameter.class); + BlockStateCall blockStateCall = new BlockStateCall(List.of(callParameter), null, null, true); + + when(transactionSimulator.processWithWorldUpdater( + any(), any(), any(), any(), any(), any(), any(MiningBeneficiaryCalculator.class))) + .thenReturn(Optional.empty()); + + BlockSimulationException exception = + assertThrows( + BlockSimulationException.class, + () -> blockSimulator.process(blockHeader, List.of(blockStateCall), mutableWorldState)); + + assertEquals("Transaction simulator result is empty", exception.getMessage()); + } + + @Test + public void shouldApplyStateOverridesCorrectly() { + AccountOverrideMap accountOverrideMap = mock(AccountOverrideMap.class); + Address address = mock(Address.class); + AccountOverride accountOverride = mock(AccountOverride.class); + MutableAccount mutableAccount = mock(MutableAccount.class); + + when(accountOverrideMap.keySet()).thenReturn(Set.of(address)); + when(accountOverrideMap.get(address)).thenReturn(accountOverride); + + WorldUpdater worldUpdater = mock(WorldUpdater.class); + when(mutableWorldState.updater()).thenReturn(worldUpdater); + + when(worldUpdater.getOrCreate(address)).thenReturn(mutableAccount); + + when(accountOverride.getNonce()).thenReturn(Optional.of(123L)); + when(accountOverride.getBalance()).thenReturn(Optional.of(Wei.of(456L))); + when(accountOverride.getCode()).thenReturn(Optional.of("")); + when(accountOverride.getStateDiff()) + .thenReturn(Optional.of(new HashMap<>(Map.of("0x0", "0x1")))); + + blockSimulator.applyStateOverrides(accountOverrideMap, mutableWorldState); + + verify(mutableAccount).setNonce(anyLong()); + verify(mutableAccount).setBalance(any(Wei.class)); + verify(mutableAccount).setCode(any(Bytes.class)); + verify(mutableAccount).setStorageValue(any(UInt256.class), any(UInt256.class)); + } + + @Test + public void shouldApplyBlockHeaderOverridesCorrectly() { + ProtocolSpec protocolSpec = mock(ProtocolSpec.class); + + var expectedTimestamp = 1L; + var expectedBlockNumber = 2L; + var expectedFeeRecipient = Address.fromHexString("0x1"); + var expectedBaseFeePerGas = Wei.of(7L); + var expectedGasLimit = 5L; + var expectedDifficulty = BigInteger.ONE; + var expectedMixHashOrPrevRandao = Hash.hash(Bytes.fromHexString("0x01")); + var expectedExtraData = Bytes.fromHexString("0x02"); + + BlockOverrides blockOverrides = + BlockOverrides.builder() + .timestamp(expectedTimestamp) + .blockNumber(expectedBlockNumber) + .feeRecipient(expectedFeeRecipient) + .baseFeePerGas(expectedBaseFeePerGas) + .gasLimit(expectedGasLimit) + .difficulty(expectedDifficulty) + .mixHashOrPrevRandao(expectedMixHashOrPrevRandao) + .extraData(expectedExtraData) + .build(); + + BlockHeader result = + blockSimulator.applyBlockHeaderOverrides(blockHeader, protocolSpec, blockOverrides); + + assertNotNull(result); + assertEquals(expectedTimestamp, result.getTimestamp()); + assertEquals(expectedBlockNumber, result.getNumber()); + assertEquals(expectedFeeRecipient, result.getCoinbase()); + assertEquals(Optional.of(expectedBaseFeePerGas), result.getBaseFee()); + assertEquals(expectedGasLimit, result.getGasLimit()); + assertThat(result.getDifficulty()).isEqualTo(Difficulty.of(expectedDifficulty)); + assertEquals(expectedMixHashOrPrevRandao, result.getMixHash()); + assertEquals(expectedExtraData, result.getExtraData()); + } + + @Test + public void testBuildTransactionValidationParams() { + var configWhenValidate = + ImmutableTransactionValidationParams.builder() + .from(TransactionValidationParams.processingBlock()) + .build(); + + ImmutableTransactionValidationParams params = + blockSimulator.buildTransactionValidationParams(true); + assertThat(params).isEqualTo(configWhenValidate); + assertThat(params.isAllowExceedingBalance()).isFalse(); + + params = blockSimulator.buildTransactionValidationParams(false); + assertThat(params.isAllowExceedingBalance()).isTrue(); + } +} diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java index e0715e58477..233d16ca2ff 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/transaction/TransactionSimulatorTest.java @@ -15,8 +15,10 @@ package org.hyperledger.besu.ethereum.transaction; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.evm.tracing.OperationTracer.NO_TRACING; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -32,12 +34,14 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlobTestFixture; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.Difficulty; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams; @@ -52,7 +56,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; import org.hyperledger.besu.evm.account.Account; import org.hyperledger.besu.evm.account.MutableAccount; -import org.hyperledger.besu.evm.tracing.OperationTracer; +import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.math.BigInteger; @@ -99,10 +103,13 @@ public class TransactionSimulatorTest { @BeforeEach public void setUp() { + final var miningConfiguration = MiningConfiguration.newDefault().setCoinbase(Address.ZERO); this.transactionSimulator = - new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule, 0); + new TransactionSimulator( + blockchain, worldStateArchive, protocolSchedule, miningConfiguration, 0); this.cappedTransactionSimulator = - new TransactionSimulator(blockchain, worldStateArchive, protocolSchedule, GAS_CAP); + new TransactionSimulator( + blockchain, worldStateArchive, protocolSchedule, miningConfiguration, GAS_CAP); } @Test @@ -182,6 +189,43 @@ public void shouldReturnSuccessfulResultWhenProcessingIsSuccessful() { verifyTransactionWasProcessed(expectedTransaction); } + @Test + public void simulateOnPendingBlockWorks() { + final CallParameter callParameter = eip1559TransactionCallParameter(); + + final BlockHeader blockHeader = mockBlockHeader(Hash.ZERO, 1L, Wei.ONE); + + mockBlockchainForBlockHeader(blockHeader); + mockWorldStateForAccount(blockHeader, callParameter.getFrom(), 1L); + + final Transaction expectedTransaction = + Transaction.builder() + .type(TransactionType.EIP1559) + .chainId(BigInteger.ONE) + .nonce(1L) + .gasLimit(blockHeader.getGasLimit()) + .maxFeePerGas(callParameter.getMaxFeePerGas().orElseThrow()) + .maxPriorityFeePerGas(callParameter.getMaxPriorityFeePerGas().orElseThrow()) + .to(callParameter.getTo()) + .sender(callParameter.getFrom()) + .value(callParameter.getValue()) + .payload(callParameter.getPayload()) + .signature(FAKE_SIGNATURE) + .build(); + mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL); + + final Optional result = + transactionSimulator.processOnPending( + callParameter, + Optional.empty(), + TransactionValidationParams.transactionSimulator(), + NO_TRACING, + transactionSimulator.simulatePendingBlockHeader()); + + assertThat(result.get().isSuccessful()).isTrue(); + verifyTransactionWasProcessed(expectedTransaction); + } + @Test public void shouldSetGasPriceToZeroWhenExceedingBalanceAllowed() { final CallParameter callParameter = legacyTransactionCallParameter(Wei.ONE); @@ -209,7 +253,7 @@ public void shouldSetGasPriceToZeroWhenExceedingBalanceAllowed() { transactionSimulator.process( callParameter, ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(true).build(), - OperationTracer.NO_TRACING, + NO_TRACING, 1L); verifyTransactionWasProcessed(expectedTransaction); @@ -245,7 +289,7 @@ public void shouldSetFeePerGasToZeroWhenExceedingBalanceAllowed() { transactionSimulator.process( callParameter, ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(true).build(), - OperationTracer.NO_TRACING, + NO_TRACING, 1L); verifyTransactionWasProcessed(expectedTransaction); @@ -279,7 +323,7 @@ public void shouldNotSetGasPriceToZeroWhenExceedingBalanceIsNotAllowed() { transactionSimulator.process( callParameter, ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(false).build(), - OperationTracer.NO_TRACING, + NO_TRACING, 1L); verifyTransactionWasProcessed(expectedTransaction); @@ -314,7 +358,7 @@ public void shouldNotSetFeePerGasToZeroWhenExceedingBalanceIsNotAllowed() { transactionSimulator.process( callParameter, ImmutableTransactionValidationParams.builder().isAllowExceedingBalance(false).build(), - OperationTracer.NO_TRACING, + NO_TRACING, 1L); verifyTransactionWasProcessed(expectedTransaction); @@ -600,10 +644,7 @@ public void shouldCapGasLimitWhenOriginalTransactionExceedsGasCap() { // call process with original transaction cappedTransactionSimulator.process( - callParameter, - TransactionValidationParams.transactionSimulator(), - OperationTracer.NO_TRACING, - 1L); + callParameter, TransactionValidationParams.transactionSimulator(), NO_TRACING, 1L); // expect overwritten transaction to be processed verifyTransactionWasProcessed(expectedTransaction); @@ -638,10 +679,7 @@ public void shouldUseProvidedGasLimitWhenBelowRpcCapGas() { // call process with original transaction cappedTransactionSimulator.process( - callParameter, - TransactionValidationParams.transactionSimulator(), - OperationTracer.NO_TRACING, - 1L); + callParameter, TransactionValidationParams.transactionSimulator(), NO_TRACING, 1L); // expect overwritten transaction to be processed verifyTransactionWasProcessed(expectedTransaction); @@ -677,10 +715,7 @@ public void shouldUseRpcGasCapWhenGasLimitNoPresent() { // call process with original transaction cappedTransactionSimulator.process( - callParameter, - TransactionValidationParams.transactionSimulator(), - OperationTracer.NO_TRACING, - 1L); + callParameter, TransactionValidationParams.transactionSimulator(), NO_TRACING, 1L); // expect transaction with the original gas limit to be processed verifyTransactionWasProcessed(expectedTransaction); @@ -799,6 +834,8 @@ private void mockBlockchainForBlockHeader(final BlockHeader blockHeader) { when(blockchain.getBlockHeader(blockHeader.getNumber())).thenReturn(Optional.of(blockHeader)); when(blockchain.getBlockHeader(blockHeader.getBlockHash())) .thenReturn(Optional.of(blockHeader)); + when(blockchain.getChainHeadHash()).thenReturn(blockHeader.getHash()); + when(blockchain.getChainHeadHeader()).thenReturn(blockHeader); } private void mockProtocolSpecForProcessWithWorldUpdater() { @@ -806,11 +843,15 @@ private void mockProtocolSpecForProcessWithWorldUpdater() { final BlockHashProcessor blockHashProcessor = mock(BlockHashProcessor.class); when(protocolSchedule.getChainId()).thenReturn(Optional.of(BigInteger.ONE)); when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec); + when(protocolSchedule.getForNextBlockHeader(any(), anyLong())).thenReturn(protocolSpec); when(protocolSpec.getTransactionProcessor()).thenReturn(transactionProcessor); when(protocolSpec.getMiningBeneficiaryCalculator()).thenReturn(BlockHeader::getCoinbase); when(protocolSpec.getBlockHeaderFunctions()).thenReturn(blockHeaderFunctions); when(protocolSpec.getFeeMarket()).thenReturn(FeeMarket.london(0)); when(protocolSpec.getBlockHashProcessor()).thenReturn(blockHashProcessor); + when(protocolSpec.getGasCalculator()).thenReturn(new FrontierGasCalculator()); + when(protocolSpec.getGasLimitCalculator()).thenReturn(GasLimitCalculator.constant()); + when(protocolSpec.getDifficultyCalculator()).thenReturn((time, parent) -> BigInteger.TEN); } private void mockProcessorStatusForTransaction( @@ -912,4 +953,43 @@ private CallParameter blobTransactionCallParameter( Optional.of(maxFeePerBlobGas), Optional.of(bwc.getVersionedHashes())); } + + @Test + public void shouldSimulateLegacyTransactionWhenBaseFeeNotZero() { + // tests that the transaction simulator will simulate a legacy transaction when the base fee is + // not zero + // and the transaction is a legacy transaction + + final CallParameter callParameter = legacyTransactionCallParameter(); + + final BlockHeader blockHeader = + blockHeaderTestFixture + .number(1L) + .stateRoot(Hash.ZERO) + .baseFeePerGas(Wei.of(7)) + .buildHeader(); + + mockBlockchainForBlockHeader(blockHeader); + mockWorldStateForAccount(blockHeader, callParameter.getFrom(), 1L); + + final Transaction expectedTransaction = + Transaction.builder() + .type(TransactionType.FRONTIER) + .nonce(1L) + .gasPrice(callParameter.getGasPrice()) + .gasLimit(blockHeader.getGasLimit()) + .to(callParameter.getTo()) + .sender(callParameter.getFrom()) + .value(callParameter.getValue()) + .payload(callParameter.getPayload()) + .signature(FAKE_SIGNATURE) + .build(); + mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL); + + final Optional result = + transactionSimulator.process(callParameter, 1L); + + verifyTransactionWasProcessed(expectedTransaction); + assertThat(result.get().isSuccessful()).isTrue(); + } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java index 275adc9ff43..de0aa4a8cb8 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/trie/diffbased/bonsai/AbstractIsolationTests.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.when; import org.hyperledger.besu.config.GenesisAccount; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SECPPrivateKey; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; @@ -105,13 +105,13 @@ public abstract class AbstractIsolationTests { .createKeyPair(SECPPrivateKey.create(key, "ECDSA")); protected final ProtocolSchedule protocolSchedule = MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), MiningConfiguration.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem()); protected final GenesisState genesisState = - GenesisState.fromConfig(GenesisConfigFile.fromResource("/dev.json"), protocolSchedule); + GenesisState.fromConfig(GenesisConfig.fromResource("/dev.json"), protocolSchedule); protected final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); protected final TransactionPoolConfiguration poolConfiguration = @@ -144,7 +144,7 @@ public abstract class AbstractIsolationTests { ethScheduler); protected final List accounts = - GenesisConfigFile.fromResource("/dev.json") + GenesisConfig.fromResource("/dev.json") .streamAllocations() .filter(ga -> ga.privateKey() != null) .toList(); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/util/AccountOverrideParameterTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/util/AccountOverrideParameterTest.java index 1b6d8c1cbe3..1b676e8c5ea 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/util/AccountOverrideParameterTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/util/AccountOverrideParameterTest.java @@ -52,7 +52,7 @@ public void jsonDeserializesCorrectly() throws Exception { + "\":" + "{" + "\"balance\": \"0x01\"," - + "\"nonce\": 88" + + "\"nonce\": \"0x9e\"" + "}}],\"id\":1}"; final JsonRpcRequestContext request = new JsonRpcRequestContext(readJsonAsJsonRpcRequest(json)); @@ -62,7 +62,7 @@ public void jsonDeserializesCorrectly() throws Exception { final AccountOverride accountOverride = accountOverrideParam.get(Address.fromHexString(ADDRESS_HEX1)); - assertThat(accountOverride.getNonce()).isEqualTo(Optional.of(88L)); + assertThat(accountOverride.getNonce().get()).isEqualTo(158); assertThat(accountOverride.getBalance()).isEqualTo(Optional.of(Wei.of(1))); assertFalse(accountOverride.getStateDiff().isPresent()); } @@ -96,6 +96,34 @@ public void jsonWithCodeDeserializesCorrectly() throws Exception { assertFalse(accountOverride.getStateDiff().isPresent()); } + @Test + public void jsonWithHexNonceDeserializesCorrectly() throws Exception { + final String json = + "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{" + + "\"from\":\"0x0\", \"to\": \"0x0\"}, " + + "\"latest\"," + + "{\"" + + ADDRESS_HEX1 + + "\":" + + "{" + + "\"balance\": \"0x01\"," + + "\"nonce\": \"" + + "0x9e" + + "\"" + + "}}],\"id\":1}"; + + final JsonRpcRequestContext request = new JsonRpcRequestContext(readJsonAsJsonRpcRequest(json)); + final AccountOverrideMap accountOverrideParam = + request.getRequiredParameter(2, AccountOverrideMap.class); + + final AccountOverride accountOverride = + accountOverrideParam.get(Address.fromHexString(ADDRESS_HEX1)); + + assertThat(accountOverride.getBalance()).isEqualTo(Optional.of(Wei.of(1))); + assertThat(accountOverride.getNonce().get()).isEqualTo(158); // 0x9e + assertFalse(accountOverride.getStateDiff().isPresent()); + } + @Test public void jsonWithStorageOverridesDeserializesCorrectly() throws Exception { final String json = @@ -107,7 +135,7 @@ public void jsonWithStorageOverridesDeserializesCorrectly() throws Exception { + "\":" + "{" + "\"balance\": \"0x01\"," - + "\"nonce\": 88," + + "\"nonce\": \"0x9E\"," + "\"stateDiff\": {" + "\"" + STORAGE_KEY @@ -124,7 +152,7 @@ public void jsonWithStorageOverridesDeserializesCorrectly() throws Exception { final AccountOverride accountOverride = accountOverrideParam.get(Address.fromHexString(ADDRESS_HEX1)); - assertThat(accountOverride.getNonce()).isEqualTo(Optional.of(88L)); + assertThat(accountOverride.getNonce().get()).isEqualTo(158); assertTrue(accountOverride.getStateDiff().isPresent()); assertThat(accountOverride.getStateDiff().get().get(STORAGE_KEY)).isEqualTo(STORAGE_VALUE); @@ -141,7 +169,7 @@ public void jsonWithMultipleAccountOverridesDeserializesCorrectly() throws Excep + "\":" + "{" + "\"balance\": \"0x01\"," - + "\"nonce\": 88," + + "\"nonce\": \"0x9E\"," + "\"stateDiff\": {" + "\"" + STORAGE_KEY @@ -154,7 +182,7 @@ public void jsonWithMultipleAccountOverridesDeserializesCorrectly() throws Excep + "\":" + "{" + "\"balance\": \"0xFF\"," - + "\"nonce\": 99," + + "\"nonce\": \"0x9D\"," + "\"stateDiff\": {" + "\"" + STORAGE_KEY @@ -171,14 +199,14 @@ public void jsonWithMultipleAccountOverridesDeserializesCorrectly() throws Excep final AccountOverride accountOverride1 = accountOverrideParam.get(Address.fromHexString(ADDRESS_HEX1)); - assertThat(accountOverride1.getNonce()).isEqualTo(Optional.of(88L)); + assertThat(accountOverride1.getNonce().get()).isEqualTo(158); assertThat(accountOverride1.getBalance()).isEqualTo(Optional.of(Wei.fromHexString("0x01"))); assertTrue(accountOverride1.getStateDiff().isPresent()); assertThat(accountOverride1.getStateDiff().get().get(STORAGE_KEY)).isEqualTo(STORAGE_VALUE); final AccountOverride accountOverride2 = accountOverrideParam.get(Address.fromHexString(ADDRESS_HEX2)); - assertThat(accountOverride2.getNonce()).isEqualTo(Optional.of(99L)); + assertThat(accountOverride2.getNonce().get()).isEqualTo(157); assertThat(accountOverride2.getBalance()).isEqualTo(Optional.of(Wei.fromHexString("0xFF"))); assertTrue(accountOverride2.getStateDiff().isPresent()); assertThat(accountOverride2.getStateDiff().get().get(STORAGE_KEY)).isEqualTo(STORAGE_VALUE); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/BlockchainBasedBlockHashLookupTest.java similarity index 61% rename from ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java rename to ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/BlockchainBasedBlockHashLookupTest.java index 9ea4219a1ac..8504d613967 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/CachingBlockHashLookupTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/BlockchainBasedBlockHashLookupTest.java @@ -14,11 +14,11 @@ */ package org.hyperledger.besu.ethereum.vm; +import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; @@ -26,7 +26,8 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; +import org.hyperledger.besu.evm.frame.MessageFrame; import java.util.Optional; @@ -38,15 +39,25 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class CachingBlockHashLookupTest { +class BlockchainBasedBlockHashLookupTest { - private static final int CURRENT_BLOCK_NUMBER = 256; + private static final int MAXIMUM_COMPLETE_BLOCKS_BEHIND = 256; + private static final int CURRENT_BLOCK_NUMBER = MAXIMUM_COMPLETE_BLOCKS_BEHIND * 2; private final Blockchain blockchain = mock(Blockchain.class); - private final BlockHeader[] headers = new BlockHeader[CURRENT_BLOCK_NUMBER]; + private BlockHeader[] headers; private BlockHashLookup lookup; + private final MessageFrame messageFrameMock = mock(MessageFrame.class); @BeforeEach void setUp() { + setUpBlockchain(CURRENT_BLOCK_NUMBER); + lookup = + new BlockchainBasedBlockHashLookup( + createHeader(CURRENT_BLOCK_NUMBER, headers[headers.length - 1]), blockchain); + } + + private void setUpBlockchain(final int blockNumberAtHead) { + headers = new BlockHeader[blockNumberAtHead]; BlockHeader parentHeader = null; for (int i = 0; i < headers.length; i++) { final BlockHeader header = createHeader(i, parentHeader); @@ -54,9 +65,6 @@ void setUp() { headers[i] = header; parentHeader = headers[i]; } - lookup = - new CachingBlockHashLookup( - createHeader(CURRENT_BLOCK_NUMBER, headers[headers.length - 1]), blockchain); } @AfterEach @@ -72,50 +80,65 @@ void shouldGetHashOfImmediateParent() { } @Test - void shouldGetHashOfGenesisBlock() { - assertHashForBlockNumber(0); - } - - @Test - void shouldGetHashForRecentBlockAfterOlderBlock() { - assertHashForBlockNumber(10); - assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 1); + void shouldGetHashOfMaxBlocksBehind() { + assertHashForBlockNumber(MAXIMUM_COMPLETE_BLOCKS_BEHIND); } @Test void shouldReturnEmptyHashWhenRequestedBlockNotOnchain() { - Assertions.assertThat(lookup.apply(CURRENT_BLOCK_NUMBER + 20L)).isEqualTo(Hash.ZERO); + assertThat(lookup.apply(messageFrameMock, CURRENT_BLOCK_NUMBER + 20L)).isEqualTo(Hash.ZERO); } @Test void shouldReturnEmptyHashWhenParentBlockNotOnchain() { final BlockHashLookup lookupWithUnavailableParent = - new CachingBlockHashLookup( + new BlockchainBasedBlockHashLookup( new BlockHeaderTestFixture().number(CURRENT_BLOCK_NUMBER + 20).buildHeader(), blockchain); - Assertions.assertThat(lookupWithUnavailableParent.apply((long) CURRENT_BLOCK_NUMBER)) + Assertions.assertThat( + lookupWithUnavailableParent.apply(messageFrameMock, (long) CURRENT_BLOCK_NUMBER)) .isEqualTo(Hash.ZERO); } - @Test - void shouldGetParentHashFromCurrentBlock() { - assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 1); - verifyNoInteractions(blockchain); - } - @Test void shouldCacheBlockHashesWhileIteratingBackToPreviousHeader() { assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 4); assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 1); - verify(blockchain).getBlockHeader(headers[CURRENT_BLOCK_NUMBER - 1].getHash()); - verify(blockchain).getBlockHeader(headers[CURRENT_BLOCK_NUMBER - 2].getHash()); - verify(blockchain).getBlockHeader(headers[CURRENT_BLOCK_NUMBER - 3].getHash()); + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 7); + for (int i = 1; i < 7; i++) { + verify(blockchain).getBlockHeader(headers[CURRENT_BLOCK_NUMBER - i].getHash()); + } verifyNoMoreInteractions(blockchain); } + @Test + void shouldReturnZeroWhenCurrentBlockIsGenesis() { + lookup = new BlockchainBasedBlockHashLookup(createHeader(0, null), mock(Blockchain.class)); + assertHashForBlockNumber(0, Hash.ZERO); + } + + @Test + void shouldReturnZeroWhenRequestedBlockEqualToImportingBlock() { + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER, Hash.ZERO); + } + + @Test + void shouldReturnZeroWhenRequestedBlockAheadOfCurrent() { + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER + 1, Hash.ZERO); + } + + @Test + void shouldReturnZeroWhenRequestedBlockTooFarBehindCurrent() { + assertHashForBlockNumber(MAXIMUM_COMPLETE_BLOCKS_BEHIND - 1, Hash.ZERO); + assertHashForBlockNumber(10, Hash.ZERO); + } + private void assertHashForBlockNumber(final int blockNumber) { - Assertions.assertThat(lookup.apply((long) blockNumber)) - .isEqualTo(headers[blockNumber].getHash()); + assertHashForBlockNumber(blockNumber, headers[blockNumber].getHash()); + } + + private void assertHashForBlockNumber(final int blockNumber, final Hash hash) { + Assertions.assertThat(lookup.apply(messageFrameMock, (long) blockNumber)).isEqualTo(hash); } private BlockHeader createHeader(final int blockNumber, final BlockHeader parentHeader) { diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracerTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracerTest.java index 2a1bb23a097..2d97f4308bc 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracerTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/DebugOperationTracerTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.ExecutionContextTestFixture; import org.hyperledger.besu.ethereum.core.MessageFrameTestFixture; import org.hyperledger.besu.ethereum.debug.TraceFrame; import org.hyperledger.besu.ethereum.debug.TraceOptions; @@ -240,6 +241,7 @@ private MessageFrameTestFixture validMessageFrameBuilder() { return new MessageFrameTestFixture() .initialGas(INITIAL_GAS) .worldUpdater(worldUpdater) + .executionContextTestFixture(ExecutionContextTestFixture.create()) .gasPrice(Wei.of(25)) .blockHeader(blockHeader) .blockchain(blockchain); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookupTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookupTest.java new file mode 100644 index 00000000000..d9cf91d78b8 --- /dev/null +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/vm/Eip7709BlockHashLookupTest.java @@ -0,0 +1,189 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.vm; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; +import org.hyperledger.besu.evm.fluent.SimpleAccount; +import org.hyperledger.besu.evm.fluent.SimpleWorld; +import org.hyperledger.besu.evm.frame.BlockValues; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.worldstate.WorldUpdater; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.tuweni.units.bigints.UInt256; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class Eip7709BlockHashLookupTest { + private static final long BLOCKHASH_SERVE_WINDOW = 160; + private static final Address STORAGE_ADDRESS = Address.fromHexString("0x0"); + private static final long HISTORY_SERVE_WINDOW = 200L; + private static final int CURRENT_BLOCK_NUMBER = + Math.toIntExact(HISTORY_SERVE_WINDOW + BLOCKHASH_SERVE_WINDOW / 2); + private List headers; + private BlockHashLookup lookup; + private MessageFrame frame; + + @BeforeEach + void setUp() { + headers = new ArrayList<>(); + frame = createMessageFrame(CURRENT_BLOCK_NUMBER, createWorldUpdater(0, CURRENT_BLOCK_NUMBER)); + lookup = + new Eip7709BlockHashLookup(STORAGE_ADDRESS, HISTORY_SERVE_WINDOW, BLOCKHASH_SERVE_WINDOW); + } + + private WorldUpdater createWorldUpdater(final int fromBlockNumber, final int toBlockNumber) { + WorldUpdater worldUpdaterMock = mock(WorldUpdater.class); + SimpleAccount contractAccount = spy(new SimpleAccount(STORAGE_ADDRESS, 0, Wei.ZERO)); + when(worldUpdaterMock.get(STORAGE_ADDRESS)).thenReturn(contractAccount); + BlockHeader parentHeader = null; + for (int i = fromBlockNumber; i < toBlockNumber; i++) { + final BlockHeader header = createHeader(i, parentHeader); + headers.add(header); + contractAccount.setStorageValue( + UInt256.valueOf(i % HISTORY_SERVE_WINDOW), UInt256.fromBytes(header.getHash())); + parentHeader = header; + } + return worldUpdaterMock; + } + + private MessageFrame createMessageFrame( + final long currentBlockNumber, final WorldUpdater worldUpdater) { + final MessageFrame messageFrame = mock(MessageFrame.class); + final BlockValues blockValues = mock(BlockValues.class); + when(blockValues.getNumber()).thenReturn(currentBlockNumber); + when(messageFrame.getBlockValues()).thenReturn(blockValues); + when(messageFrame.getWorldUpdater()).thenReturn(worldUpdater); + return messageFrame; + } + + @Test + void shouldGetHashOfImmediateParent() { + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 1); + } + + @Test + void shouldGetHashOfMaxBlocksBehind() { + assertHashForBlockNumber(Math.toIntExact(CURRENT_BLOCK_NUMBER - BLOCKHASH_SERVE_WINDOW)); + } + + @Test + void shouldReturnEmptyHashWhenRequestedBlockHigherThanHead() { + assertThat(lookup.apply(frame, CURRENT_BLOCK_NUMBER + 20L)).isEqualTo(Hash.ZERO); + } + + @Test + void shouldReturnEmptyHashWhenSystemContractNotExists() { + final WorldUpdater worldUpdater = new SimpleWorld(); + when(frame.getWorldUpdater()).thenReturn(worldUpdater); + assertThat(lookup.apply(frame, CURRENT_BLOCK_NUMBER - 1L)).isEqualTo(Hash.ZERO); + } + + @Test + void shouldReturnEmptyHashWhenParentBlockNotInContract() { + frame = + createMessageFrame( + CURRENT_BLOCK_NUMBER, + createWorldUpdater(CURRENT_BLOCK_NUMBER - 10, CURRENT_BLOCK_NUMBER)); + lookup = + new Eip7709BlockHashLookup(STORAGE_ADDRESS, HISTORY_SERVE_WINDOW, BLOCKHASH_SERVE_WINDOW); + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER - 20, Hash.ZERO); + } + + @Test + void shouldCacheBlockHashes() { + final WorldUpdater worldUpdater = createWorldUpdater(0, CURRENT_BLOCK_NUMBER); + when(frame.getWorldUpdater()).thenReturn(worldUpdater); + final Account account = worldUpdater.get(STORAGE_ADDRESS); + clearInvocations(account); + + int blockNumber1 = CURRENT_BLOCK_NUMBER - 1; + int blockNumber2 = CURRENT_BLOCK_NUMBER - 4; + int blockNumber3 = CURRENT_BLOCK_NUMBER - 5; + assertHashForBlockNumber(blockNumber1); + assertHashForBlockNumber(blockNumber1); + assertHashForBlockNumber(blockNumber2); + assertHashForBlockNumber(blockNumber3); + assertHashForBlockNumber(blockNumber3); + assertHashForBlockNumber(blockNumber3); + + verify(account, times(1)) + .getStorageValue(eq(UInt256.valueOf(blockNumber1 % HISTORY_SERVE_WINDOW))); + verify(account, times(1)) + .getStorageValue(eq(UInt256.valueOf(blockNumber2 % HISTORY_SERVE_WINDOW))); + verify(account, times(1)) + .getStorageValue(eq(UInt256.valueOf(blockNumber3 % HISTORY_SERVE_WINDOW))); + verifyNoMoreInteractions(account); + } + + @Test + void shouldGetHashWhenParentIsGenesis() { + frame = createMessageFrame(1, createWorldUpdater(0, 1)); + lookup = + new Eip7709BlockHashLookup(STORAGE_ADDRESS, HISTORY_SERVE_WINDOW, BLOCKHASH_SERVE_WINDOW); + assertHashForBlockNumber(0); + } + + @Test + void shouldReturnZeroWhenRequestedBlockEqualToImportingBlock() { + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER, Hash.ZERO); + } + + @Test + void shouldReturnZeroWhenRequestedBlockAheadOfCurrent() { + assertHashForBlockNumber(CURRENT_BLOCK_NUMBER + 1, Hash.ZERO); + } + + @Test + void shouldReturnZeroWhenRequestedBlockTooFarBehindCurrent() { + assertHashForBlockNumber( + Math.toIntExact(CURRENT_BLOCK_NUMBER - BLOCKHASH_SERVE_WINDOW - 1), Hash.ZERO); + assertHashForBlockNumber(10, Hash.ZERO); + } + + private void assertHashForBlockNumber(final int blockNumber) { + assertHashForBlockNumber(blockNumber, headers.get(blockNumber).getHash()); + } + + private void assertHashForBlockNumber(final int blockNumber, final Hash hash) { + Assertions.assertThat(lookup.apply(frame, (long) blockNumber)).isEqualTo(hash); + } + + private BlockHeader createHeader(final long blockNumber, final BlockHeader parentHeader) { + return new BlockHeaderTestFixture() + .number(blockNumber) + .parentHash(parentHeader != null ? parentHeader.getHash() : Hash.EMPTY) + .buildHeader(); + } +} diff --git a/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json b/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json index f9aa3ff4663..10cf0191824 100644 --- a/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json +++ b/ethereum/core/src/test/resources/org/hyperledger/besu/ethereum/chain/genesis_prague.json @@ -4074,5 +4074,5 @@ "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "baseFeePerGas": "0x3b9aca00", - "targetBlobCount": "0x1" + "targetBlobsPerBlock": "0x1" } diff --git a/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java b/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java index 079b6ba47fa..f4764f129dd 100644 --- a/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java +++ b/ethereum/eth/src/jmh/java/org/hyperledger/besu/ethereum/eth/sync/worldstate/WorldStateDownloaderBenchmark.java @@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -94,12 +95,14 @@ public void setUpUnchangedState() { tempDir = Files.createTempDir().toPath(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - new EthScheduler( - syncConfig.getDownloaderParallelism(), - syncConfig.getTransactionsParallelism(), - syncConfig.getComputationParallelism(), - metricsSystem)); + EthProtocolManagerTestBuilder.builder() + .setEthScheduler( + new EthScheduler( + syncConfig.getDownloaderParallelism(), + syncConfig.getTransactionsParallelism(), + syncConfig.getComputationParallelism(), + metricsSystem)) + .build(); peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, blockHeader.getNumber()); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthContext.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthContext.java index b33fda3bc64..88e1b64e64b 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthContext.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthContext.java @@ -14,6 +14,8 @@ */ package org.hyperledger.besu.ethereum.eth.manager; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; + import java.util.Optional; public class EthContext { @@ -22,24 +24,31 @@ public class EthContext { private final EthMessages ethMessages; private final Optional snapMessages; private final EthScheduler scheduler; + private final PeerTaskExecutor peerTaskExecutor; public EthContext( final EthPeers ethPeers, final EthMessages ethMessages, final EthMessages snapMessages, - final EthScheduler scheduler) { + final EthScheduler scheduler, + final PeerTaskExecutor peerTaskExecutor) { this.ethPeers = ethPeers; this.ethMessages = ethMessages; this.snapMessages = Optional.of(snapMessages); this.scheduler = scheduler; + this.peerTaskExecutor = peerTaskExecutor; } public EthContext( - final EthPeers ethPeers, final EthMessages ethMessages, final EthScheduler scheduler) { + final EthPeers ethPeers, + final EthMessages ethMessages, + final EthScheduler scheduler, + final PeerTaskExecutor peerTaskExecutor) { this.ethPeers = ethPeers; this.ethMessages = ethMessages; this.snapMessages = Optional.empty(); this.scheduler = scheduler; + this.peerTaskExecutor = peerTaskExecutor; } public EthPeers getEthPeers() { @@ -57,4 +66,8 @@ public Optional getSnapMessages() { public EthScheduler getScheduler() { return scheduler; } + + public PeerTaskExecutor getPeerTaskExecutor() { + return peerTaskExecutor; + } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeer.java index 899e7027243..a4c7dd1bf6f 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeer.java @@ -85,7 +85,6 @@ protected boolean removeEldestEntry(final Map.Entry eldest) { private Optional checkpointHeader = Optional.empty(); - private final String protocolName; private final int maxMessageSize; private final Clock clock; private final List permissioningProviders; @@ -124,7 +123,6 @@ protected boolean removeEldestEntry(final Map.Entry eldest) { @VisibleForTesting public EthPeer( final PeerConnection connection, - final String protocolName, final Consumer onStatusesExchanged, final List peerValidators, final int maxMessageSize, @@ -132,7 +130,6 @@ public EthPeer( final List permissioningProviders, final Bytes localNodeId) { this.connection = connection; - this.protocolName = protocolName; this.maxMessageSize = maxMessageSize; this.clock = clock; this.permissioningProviders = permissioningProviders; @@ -153,21 +150,23 @@ private void initEthRequestManagers() { getAgreedCapabilities().stream().anyMatch(EthProtocol::isEth66Compatible); // eth protocol requestManagers.put( - protocolName, + EthProtocol.NAME, Map.ofEntries( Map.entry( EthPV62.GET_BLOCK_HEADERS, - new RequestManager(this, supportsRequestId, protocolName)), + new RequestManager(this, supportsRequestId, EthProtocol.NAME)), Map.entry( EthPV62.GET_BLOCK_BODIES, - new RequestManager(this, supportsRequestId, protocolName)), + new RequestManager(this, supportsRequestId, EthProtocol.NAME)), Map.entry( - EthPV63.GET_RECEIPTS, new RequestManager(this, supportsRequestId, protocolName)), + EthPV63.GET_RECEIPTS, + new RequestManager(this, supportsRequestId, EthProtocol.NAME)), Map.entry( - EthPV63.GET_NODE_DATA, new RequestManager(this, supportsRequestId, protocolName)), + EthPV63.GET_NODE_DATA, + new RequestManager(this, supportsRequestId, EthProtocol.NAME)), Map.entry( EthPV65.GET_POOLED_TRANSACTIONS, - new RequestManager(this, supportsRequestId, protocolName)))); + new RequestManager(this, supportsRequestId, EthProtocol.NAME)))); } private void initSnapRequestManagers() { @@ -237,7 +236,7 @@ public void disconnect(final DisconnectReason reason) { } public RequestManager.ResponseStream send(final MessageData messageData) throws PeerNotConnected { - return send(messageData, this.protocolName); + return send(messageData, EthProtocol.NAME); } public RequestManager.ResponseStream send( @@ -317,7 +316,7 @@ public RequestManager.ResponseStream getHeadersByHash( final GetBlockHeadersMessage message = GetBlockHeadersMessage.create(hash, maxHeaders, skip, reverse); final RequestManager requestManager = - requestManagers.get(protocolName).get(EthPV62.GET_BLOCK_HEADERS); + requestManagers.get(EthProtocol.NAME).get(EthPV62.GET_BLOCK_HEADERS); return sendRequest(requestManager, message); } @@ -326,32 +325,34 @@ public RequestManager.ResponseStream getHeadersByNumber( throws PeerNotConnected { final GetBlockHeadersMessage message = GetBlockHeadersMessage.create(blockNumber, maxHeaders, skip, reverse); - return sendRequest(requestManagers.get(protocolName).get(EthPV62.GET_BLOCK_HEADERS), message); + return sendRequest( + requestManagers.get(EthProtocol.NAME).get(EthPV62.GET_BLOCK_HEADERS), message); } public RequestManager.ResponseStream getBodies(final List blockHashes) throws PeerNotConnected { final GetBlockBodiesMessage message = GetBlockBodiesMessage.create(blockHashes); - return sendRequest(requestManagers.get(protocolName).get(EthPV62.GET_BLOCK_BODIES), message); + return sendRequest( + requestManagers.get(EthProtocol.NAME).get(EthPV62.GET_BLOCK_BODIES), message); } public RequestManager.ResponseStream getReceipts(final List blockHashes) throws PeerNotConnected { final GetReceiptsMessage message = GetReceiptsMessage.create(blockHashes); - return sendRequest(requestManagers.get(protocolName).get(EthPV63.GET_RECEIPTS), message); + return sendRequest(requestManagers.get(EthProtocol.NAME).get(EthPV63.GET_RECEIPTS), message); } public RequestManager.ResponseStream getNodeData(final Iterable nodeHashes) throws PeerNotConnected { final GetNodeDataMessage message = GetNodeDataMessage.create(nodeHashes); - return sendRequest(requestManagers.get(protocolName).get(EthPV63.GET_NODE_DATA), message); + return sendRequest(requestManagers.get(EthProtocol.NAME).get(EthPV63.GET_NODE_DATA), message); } public RequestManager.ResponseStream getPooledTransactions(final List hashes) throws PeerNotConnected { final GetPooledTransactionsMessage message = GetPooledTransactionsMessage.create(hashes); return sendRequest( - requestManagers.get(protocolName).get(EthPV65.GET_POOLED_TRANSACTIONS), message); + requestManagers.get(EthProtocol.NAME).get(EthPV65.GET_POOLED_TRANSACTIONS), message); } public RequestManager.ResponseStream getSnapAccountRange( @@ -461,7 +462,7 @@ Optional dispatch(final EthMessage ethMessage, final String prot * @param ethMessage the Eth message to dispatch */ void dispatch(final EthMessage ethMessage) { - dispatch(ethMessage, protocolName); + dispatch(ethMessage, EthProtocol.NAME); } /** @@ -587,10 +588,6 @@ public int getLastProtocolVersion() { return lastProtocolVersion.get(); } - public String getProtocolName() { - return protocolName; - } - /** * Return A read-only snapshot of this peer's current {@code chainState} * diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java index d19c7dfca2e..c91ed9646d2 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/EthPeers.java @@ -15,6 +15,7 @@ package org.hyperledger.besu.ethereum.eth.manager; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.SnapProtocol; import org.hyperledger.besu.ethereum.eth.manager.EthPeer.DisconnectCallback; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerSelector; @@ -92,7 +93,6 @@ public class EthPeers implements PeerSelector { .concurrencyLevel(1) .removalListener(this::onCacheRemoval) .build(); - private final String protocolName; private final Clock clock; private final List permissioningProviders; private final int maxMessageSize; @@ -122,7 +122,6 @@ public class EthPeers implements PeerSelector { () -> TrailingPeerRequirements.UNRESTRICTED; public EthPeers( - final String protocolName, final Supplier currentProtocolSpecSupplier, final Clock clock, final MetricsSystem metricsSystem, @@ -134,7 +133,6 @@ public EthPeers( final Boolean randomPeerPriority, final SyncMode syncMode, final ForkIdManager forkIdManager) { - this.protocolName = protocolName; this.currentProtocolSpecSupplier = currentProtocolSpecSupplier; this.clock = clock; this.permissioningProviders = permissioningProviders; @@ -191,7 +189,6 @@ public void registerNewConnection( peerInList.orElse( new EthPeer( newConnection, - protocolName, this::ethPeerStatusExchanged, peerValidators, maxMessageSize, @@ -294,7 +291,7 @@ public void dispatchMessage( } public void dispatchMessage(final EthPeer peer, final EthMessage ethMessage) { - dispatchMessage(peer, ethMessage, protocolName); + dispatchMessage(peer, ethMessage, EthProtocol.NAME); } @VisibleForTesting @@ -477,6 +474,40 @@ public Optional getPeer(final Predicate filter) { .min(LEAST_TO_MOST_BUSY); } + // Part of the PeerSelector interface, to be split apart later + @Override + public CompletableFuture waitForPeer(final Predicate filter) { + final CompletableFuture future = new CompletableFuture<>(); + LOG.debug("Waiting for peer matching filter. {} peers currently connected.", peerCount()); + // check for an existing peer matching the filter and use that if one is found + Optional maybePeer = getPeer(filter); + if (maybePeer.isPresent()) { + LOG.debug("Found peer matching filter already connected!"); + future.complete(maybePeer.get()); + } else { + // no existing peer matches our filter. Subscribe to new connections until we find one + LOG.debug("Subscribing to new peer connections to wait until one matches filter"); + final long subscriptionId = + subscribeConnect( + (peer) -> { + if (!future.isDone() && filter.test(peer)) { + LOG.debug("Found new peer matching filter!"); + future.complete(peer); + } else { + LOG.debug("New peer does not match filter"); + } + }); + future.handle( + (peer, throwable) -> { + LOG.debug("Unsubscribing from new peer connections with ID {}", subscriptionId); + unsubscribeConnect(subscriptionId); + return null; + }); + } + + return future; + } + // Part of the PeerSelector interface, to be split apart later @Override public Optional getPeerByPeerId(final PeerId peerId) { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/InvalidPeerTaskResponseException.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/InvalidPeerTaskResponseException.java index 824c0860d70..3cea6088e16 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/InvalidPeerTaskResponseException.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/InvalidPeerTaskResponseException.java @@ -20,6 +20,10 @@ public InvalidPeerTaskResponseException() { super(); } + public InvalidPeerTaskResponseException(final String message) { + super(message); + } + public InvalidPeerTaskResponseException(final Throwable cause) { super(cause); } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerSelector.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerSelector.java index 8f7ab33e42d..73f01e71c74 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerSelector.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerSelector.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.p2p.peers.PeerId; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.function.Predicate; /** Selects the EthPeers for the PeerTaskExecutor */ @@ -31,6 +32,14 @@ public interface PeerSelector { */ Optional getPeer(final Predicate filter); + /** + * Waits for a peer matching the supplied filter + * + * @param filter a Predicate\ matching desirable peers + * @return a CompletableFuture into which a peer will be placed + */ + CompletableFuture waitForPeer(final Predicate filter); + /** * Attempts to get the EthPeer identified by peerId * diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTask.java index fed671d38d2..5439da7deab 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTask.java @@ -75,9 +75,13 @@ default int getRetriesWithSamePeer() { Predicate getPeerRequirementFilter(); /** - * Checks if the supplied result is considered a success + * Performs a high level check of the results, returning a PeerTaskValidationResponse to describe + * the result of the check * - * @return true if the supplied result is considered a success + * @param result The results of the PeerTask, as returned by processResponse + * @return a PeerTaskValidationResponse to describe the result of the check */ - boolean isSuccess(T result); + PeerTaskValidationResponse validateResult(T result); + + default void postProcessResult(final PeerTaskExecutorResult result) {} } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java index c8eed6e1f1f..8f5e411f6c5 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutor.java @@ -29,12 +29,15 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** Manages the execution of PeerTasks, respecting their PeerTaskRetryBehavior */ public class PeerTaskExecutor { + private static final Logger LOG = LoggerFactory.getLogger(PeerTaskExecutor.class); private final PeerSelector peerSelector; private final PeerTaskRequestSender requestSender; @@ -98,8 +101,8 @@ public PeerTaskExecutorResult execute(final PeerTask peerTask) { if (peer.isEmpty()) { executorResult = new PeerTaskExecutorResult<>( - Optional.empty(), PeerTaskExecutorResponseCode.NO_PEER_AVAILABLE); - continue; + Optional.empty(), PeerTaskExecutorResponseCode.NO_PEER_AVAILABLE, Optional.empty()); + break; } usedEthPeers.add(peer.get()); executorResult = executeAgainstPeer(peerTask, peer.get()); @@ -138,43 +141,59 @@ public PeerTaskExecutorResult executeAgainstPeer( inflightRequestCountForThisTaskClass.decrementAndGet(); } - if (peerTask.isSuccess(result)) { + PeerTaskValidationResponse validationResponse = peerTask.validateResult(result); + if (validationResponse == PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD) { peer.recordUsefulResponse(); executorResult = new PeerTaskExecutorResult<>( - Optional.ofNullable(result), PeerTaskExecutorResponseCode.SUCCESS); + Optional.ofNullable(result), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(peer)); + peerTask.postProcessResult(executorResult); } else { - // At this point, the result is most likely empty. Technically, this is a valid result, so - // we don't penalise the peer, but it's also a useless result, so we return - // INVALID_RESPONSE code + LOG.debug( + "Invalid response found for {} from peer {}", taskClassName, peer.getLoggableId()); + validationResponse + .getDisconnectReason() + .ifPresent((disconnectReason) -> peer.disconnect(disconnectReason)); executorResult = new PeerTaskExecutorResult<>( - Optional.ofNullable(result), PeerTaskExecutorResponseCode.INVALID_RESPONSE); + Optional.ofNullable(result), + PeerTaskExecutorResponseCode.INVALID_RESPONSE, + Optional.of(peer)); } } catch (PeerNotConnected e) { executorResult = new PeerTaskExecutorResult<>( - Optional.empty(), PeerTaskExecutorResponseCode.PEER_DISCONNECTED); + Optional.empty(), + PeerTaskExecutorResponseCode.PEER_DISCONNECTED, + Optional.of(peer)); } catch (InterruptedException | TimeoutException e) { peer.recordRequestTimeout(requestMessageData.getCode()); timeoutCounter.labels(taskClassName).inc(); executorResult = - new PeerTaskExecutorResult<>(Optional.empty(), PeerTaskExecutorResponseCode.TIMEOUT); + new PeerTaskExecutorResult<>( + Optional.empty(), PeerTaskExecutorResponseCode.TIMEOUT, Optional.of(peer)); } catch (InvalidPeerTaskResponseException e) { peer.recordUselessResponse(e.getMessage()); invalidResponseCounter.labels(taskClassName).inc(); + LOG.debug( + "Invalid response found for {} from peer {}", taskClassName, peer.getLoggableId(), e); executorResult = new PeerTaskExecutorResult<>( - Optional.empty(), PeerTaskExecutorResponseCode.INVALID_RESPONSE); + Optional.empty(), PeerTaskExecutorResponseCode.INVALID_RESPONSE, Optional.of(peer)); - } catch (ExecutionException e) { + } catch (Exception e) { internalExceptionCounter.labels(taskClassName).inc(); + LOG.error("Server error found for {} from peer {}", taskClassName, peer.getLoggableId(), e); executorResult = new PeerTaskExecutorResult<>( - Optional.empty(), PeerTaskExecutorResponseCode.INTERNAL_SERVER_ERROR); + Optional.empty(), + PeerTaskExecutorResponseCode.INTERNAL_SERVER_ERROR, + Optional.of(peer)); } } while (retriesRemaining-- > 0 && executorResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorResult.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorResult.java index 86dec85c295..b3874011c85 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorResult.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorResult.java @@ -14,7 +14,9 @@ */ package org.hyperledger.besu.ethereum.eth.manager.peertask; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; + import java.util.Optional; public record PeerTaskExecutorResult( - Optional result, PeerTaskExecutorResponseCode responseCode) {} + Optional result, PeerTaskExecutorResponseCode responseCode, Optional ethPeer) {} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskValidationResponse.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskValidationResponse.java new file mode 100644 index 00000000000..5fd4e6a98b8 --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskValidationResponse.java @@ -0,0 +1,37 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth.manager.peertask; + +import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage; + +import java.util.Optional; + +public enum PeerTaskValidationResponse { + NO_RESULTS_RETURNED(null), + TOO_MANY_RESULTS_RETURNED(null), + RESULTS_DO_NOT_MATCH_QUERY(null), + NON_SEQUENTIAL_HEADERS_RETURNED( + DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL_NON_SEQUENTIAL_HEADERS), + RESULTS_VALID_AND_GOOD(null); + private final Optional disconnectReason; + + PeerTaskValidationResponse(final DisconnectMessage.DisconnectReason disconnectReason) { + this.disconnectReason = Optional.ofNullable(disconnectReason); + } + + public Optional getDisconnectReason() { + return disconnectReason; + } +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTask.java new file mode 100644 index 00000000000..4cde0a8b776 --- /dev/null +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTask.java @@ -0,0 +1,263 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth.manager.peertask.task; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.eth.EthProtocol; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.InvalidPeerTaskResponseException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskValidationResponse; +import org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage; +import org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; +import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol; + +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class GetHeadersFromPeerTask implements PeerTask> { + private static final Logger LOG = LoggerFactory.getLogger(GetHeadersFromPeerTask.class); + private final long blockNumber; + private final Hash blockHash; + private final int maxHeaders; + private final int skip; + private final Direction direction; + private final int maximumRetriesAgainstDifferentPeers; + private final ProtocolSchedule protocolSchedule; + private final long requiredBlockchainHeight; + + public GetHeadersFromPeerTask( + final long blockNumber, + final int maxHeaders, + final int skip, + final Direction direction, + final ProtocolSchedule protocolSchedule) { + this(blockNumber, maxHeaders, skip, direction, 5, protocolSchedule); + } + + public GetHeadersFromPeerTask( + final long blockNumber, + final int maxHeaders, + final int skip, + final Direction direction, + final int maximumRetriesAgainstDifferentPeers, + final ProtocolSchedule protocolSchedule) { + this( + null, + blockNumber, + maxHeaders, + skip, + direction, + maximumRetriesAgainstDifferentPeers, + protocolSchedule); + } + + public GetHeadersFromPeerTask( + final Hash blockHash, + final long blockNumber, + final int maxHeaders, + final int skip, + final Direction direction, + final ProtocolSchedule protocolSchedule) { + this(blockHash, blockNumber, maxHeaders, skip, direction, 5, protocolSchedule); + } + + public GetHeadersFromPeerTask( + final Hash blockHash, + final long blockNumber, + final int maxHeaders, + final int skip, + final Direction direction, + final int maximumRetriesAgainstDifferentPeers, + final ProtocolSchedule protocolSchedule) { + LOG.debug( + "Constructing GetHeadersFromPeerTask with hash {}, number {}, maxHeaders {}, skip {}, direction {}", + blockHash, + blockNumber, + maxHeaders, + skip, + direction); + this.blockHash = blockHash; + this.blockNumber = blockNumber; + this.maxHeaders = maxHeaders; + this.skip = skip; + this.direction = direction; + this.maximumRetriesAgainstDifferentPeers = maximumRetriesAgainstDifferentPeers; + this.protocolSchedule = protocolSchedule; + + requiredBlockchainHeight = + direction == Direction.FORWARD + ? blockNumber + (long) (maxHeaders - 1) * (skip + 1) + : blockNumber; + } + + @Override + public SubProtocol getSubProtocol() { + return EthProtocol.get(); + } + + @Override + public MessageData getRequestMessage() { + if (blockHash != null) { + return GetBlockHeadersMessage.create( + blockHash, maxHeaders, skip, direction == Direction.REVERSE); + } else { + return GetBlockHeadersMessage.create( + blockNumber, maxHeaders, skip, direction == Direction.REVERSE); + } + } + + @Override + public List processResponse(final MessageData messageData) + throws InvalidPeerTaskResponseException { + if (messageData == null) { + throw new InvalidPeerTaskResponseException("Response MessageData is null"); + } + return BlockHeadersMessage.readFrom(messageData).getHeaders(protocolSchedule); + } + + @Override + public Predicate getPeerRequirementFilter() { + return (ethPeer) -> + protocolSchedule.anyMatch((ps) -> ps.spec().isPoS()) + || ethPeer.chainState().getEstimatedHeight() >= requiredBlockchainHeight; + } + + @Override + public PeerTaskValidationResponse validateResult(final List blockHeaders) { + if (blockHeaders.isEmpty()) { + // Message contains no data - nothing to do + LOG.debug( + "No blockheaders returned for query starting at {}", + blockHash != null ? blockHash : blockNumber); + return PeerTaskValidationResponse.NO_RESULTS_RETURNED; + } + + if (blockHeaders.size() > maxHeaders) { + // Too many headers - this isn't our response + LOG.debug( + "Too many blockheaders returned for query starting at {}", + blockHash != null ? blockHash : blockNumber); + return PeerTaskValidationResponse.TOO_MANY_RESULTS_RETURNED; + } + + if ((blockHash != null && !blockHeaders.getFirst().getHash().equals(blockHash)) + || (blockHash == null && blockHeaders.getFirst().getNumber() != blockNumber)) { + // This isn't our message - nothing to do + LOG.debug( + "First header returned doesn't match query starting at {}", + blockHash != null ? blockHash : blockNumber); + return PeerTaskValidationResponse.RESULTS_DO_NOT_MATCH_QUERY; + } + + if (!isBlockHeadersMatchingRequest(blockHeaders)) { + LOG.debug( + "Blockheaders do not match expected headers from request for query starting at {}", + blockHash != null ? blockHash : blockNumber); + return PeerTaskValidationResponse.RESULTS_DO_NOT_MATCH_QUERY; + } + + if (blockHeaders.size() >= 2 && skip == 0) { + // headers are supposed to be sequential and at least 2 have been returned, check if a chain + // is formed + for (int i = 0; i < blockHeaders.size() - 1; i++) { + BlockHeader parentHeader = null; + BlockHeader childHeader = null; + switch (direction) { + case FORWARD: + parentHeader = blockHeaders.get(i); + childHeader = blockHeaders.get(i + 1); + break; + case REVERSE: + childHeader = blockHeaders.get(i); + parentHeader = blockHeaders.get(i + 1); + break; + } + if (!parentHeader.getHash().equals(childHeader.getParentHash())) { + LOG.warn( + "Blockheaders were non-sequential for query starting at {}", + blockHash != null ? blockHash : blockNumber); + return PeerTaskValidationResponse.NON_SEQUENTIAL_HEADERS_RETURNED; + } + } + } + return PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD; + } + + @Override + public void postProcessResult(final PeerTaskExecutorResult> result) { + final AtomicReference highestBlockHeader = + new AtomicReference<>(result.result().get().getFirst()); + for (BlockHeader blockHeader : result.result().get()) { + if (highestBlockHeader.get().getNumber() < blockHeader.getNumber()) { + highestBlockHeader.set(blockHeader); + } + } + result.ethPeer().ifPresent((ethPeer) -> ethPeer.chainState().update(highestBlockHeader.get())); + } + + @Override + public int getRetriesWithOtherPeer() { + return maximumRetriesAgainstDifferentPeers; + } + + public Long getBlockNumber() { + return blockNumber; + } + + public Hash getBlockHash() { + return blockHash; + } + + public int getMaxHeaders() { + return maxHeaders; + } + + public int getSkip() { + return skip; + } + + public Direction getDirection() { + return direction; + } + + public enum Direction { + FORWARD, + REVERSE + } + + private boolean isBlockHeadersMatchingRequest(final List blockHeaders) { + BlockHeader prevBlockHeader = blockHeaders.getFirst(); + final int expectedDelta = direction == Direction.REVERSE ? -(skip + 1) : (skip + 1); + BlockHeader header; + for (int i = 1; i < blockHeaders.size(); i++) { + header = blockHeaders.get(i); + if (header.getNumber() != prevBlockHeader.getNumber() + expectedDelta) { + // Skip doesn't match, this isn't our data + return false; + } + prevBlockHeader = header; + } + return true; + } +} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTask.java index 7d4b5d585e5..850adb85c28 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTask.java @@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.peertask.InvalidPeerTaskResponseException; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskValidationResponse; import org.hyperledger.besu.ethereum.eth.messages.GetReceiptsMessage; import org.hyperledger.besu.ethereum.eth.messages.ReceiptsMessage; import org.hyperledger.besu.ethereum.mainnet.BodyValidation; @@ -123,13 +124,21 @@ public Map> processResponse(final MessageD @Override public Predicate getPeerRequirementFilter() { return (ethPeer) -> - ethPeer.getProtocolName().equals(getSubProtocol().getName()) - && (protocolSchedule.anyMatch((ps) -> ps.spec().isPoS()) - || ethPeer.chainState().getEstimatedHeight() >= requiredBlockchainHeight); + (protocolSchedule.anyMatch((ps) -> ps.spec().isPoS()) + || ethPeer.chainState().getEstimatedHeight() >= requiredBlockchainHeight); } @Override - public boolean isSuccess(final Map> result) { - return !result.isEmpty(); + public PeerTaskValidationResponse validateResult( + final Map> result) { + if (result.isEmpty()) { + return PeerTaskValidationResponse.NO_RESULTS_RETURNED; + } + + return PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD; + } + + public Collection getBlockHeaders() { + return blockHeaders; } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/AbstractRetryingPeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/AbstractRetryingPeerTask.java index e7f1556b5a2..dd75a6eff98 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/AbstractRetryingPeerTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/AbstractRetryingPeerTask.java @@ -26,6 +26,7 @@ import java.time.Duration; import java.util.Optional; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Predicate; @@ -129,13 +130,12 @@ protected void handleTaskError(final Throwable error) { "No useful peer found, wait max 5 seconds for new peer to connect: current peers {}", ethContext.getEthPeers().peerCount()); - final WaitForPeerTask waitTask = WaitForPeerTask.create(ethContext, metricsSystem); executeSubTask( () -> ethContext - .getScheduler() - // wait for a new peer for up to 5 seconds - .timeout(waitTask, Duration.ofSeconds(5)) + .getEthPeers() + .waitForPeer(this::isSuitablePeer) + .orTimeout(5, TimeUnit.SECONDS) // execute the task again .whenComplete((r, t) -> executeTaskTimed())); return; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTask.java index c352fbc3009..ddb0271378d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTask.java @@ -20,6 +20,12 @@ import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.exceptions.IncompleteResultsException; +import org.hyperledger.besu.ethereum.eth.manager.exceptions.PeerDisconnectedException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask.Direction; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -35,6 +41,7 @@ public class GetBlockFromPeerTask extends AbstractPeerTask { private static final Logger LOG = LoggerFactory.getLogger(GetBlockFromPeerTask.class); private final ProtocolSchedule protocolSchedule; + private final SynchronizerConfiguration synchronizerConfiguration; private final Optional hash; private final long blockNumber; private final MetricsSystem metricsSystem; @@ -42,10 +49,12 @@ public class GetBlockFromPeerTask extends AbstractPeerTask { protected GetBlockFromPeerTask( final ProtocolSchedule protocolSchedule, final EthContext ethContext, + final SynchronizerConfiguration synchronizerConfiguration, final Optional hash, final long blockNumber, final MetricsSystem metricsSystem) { super(ethContext, metricsSystem); + this.synchronizerConfiguration = synchronizerConfiguration; this.blockNumber = blockNumber; this.metricsSystem = metricsSystem; this.protocolSchedule = protocolSchedule; @@ -55,10 +64,12 @@ protected GetBlockFromPeerTask( public static GetBlockFromPeerTask create( final ProtocolSchedule protocolSchedule, final EthContext ethContext, + final SynchronizerConfiguration synchronizerConfiguration, final Optional hash, final long blockNumber, final MetricsSystem metricsSystem) { - return new GetBlockFromPeerTask(protocolSchedule, ethContext, hash, blockNumber, metricsSystem); + return new GetBlockFromPeerTask( + protocolSchedule, ethContext, synchronizerConfiguration, hash, blockNumber, metricsSystem); } @Override @@ -68,31 +79,22 @@ protected void executeTask() { "Downloading block {} from peer {}.", blockIdentifier, assignedPeer.map(EthPeer::toString).orElse("")); - downloadHeader() - .thenCompose(this::completeBlock) - .whenComplete( - (r, t) -> { - if (t != null) { - LOG.debug( - "Failed to download block {} from peer {} with message '{}' and cause '{}'", - blockIdentifier, - assignedPeer.map(EthPeer::toString).orElse(""), - t.getMessage(), - t.getCause()); - result.completeExceptionally(t); - } else if (r.getResult().isEmpty()) { - r.getPeer().recordUselessResponse("Download block returned an empty result"); - LOG.debug( - "Failed to download block {} from peer {} with empty result.", - blockIdentifier, - r.getPeer()); - result.completeExceptionally(new IncompleteResultsException()); - } else { - LOG.debug( - "Successfully downloaded block {} from peer {}.", blockIdentifier, r.getPeer()); - result.complete(new PeerTaskResult<>(r.getPeer(), r.getResult().get(0))); - } - }); + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + downloadHeaderUsingPeerTaskSystem() + .thenCompose(this::completeBlock) + .whenComplete((r, t) -> completeTask(r, t, blockIdentifier)); + }); + } else { + downloadHeader() + .thenCompose( + (peerTaskResult) -> CompletableFuture.completedFuture(peerTaskResult.getResult())) + .thenCompose(this::completeBlock) + .whenComplete((r, t) -> completeTask(r, t, blockIdentifier)); + } } private CompletableFuture>> downloadHeader() { @@ -113,9 +115,45 @@ private CompletableFuture>> downloadHeader() { }); } + private CompletableFuture> downloadHeaderUsingPeerTaskSystem() { + GetHeadersFromPeerTask task = + hash.map( + (h) -> + new GetHeadersFromPeerTask( + h, blockNumber, 1, 0, Direction.FORWARD, protocolSchedule)) + .orElseGet( + () -> + new GetHeadersFromPeerTask( + blockNumber, 1, 0, Direction.FORWARD, protocolSchedule)); + PeerTaskExecutorResult> taskResult; + if (assignedPeer.isPresent()) { + taskResult = ethContext.getPeerTaskExecutor().executeAgainstPeer(task, assignedPeer.get()); + } else { + taskResult = ethContext.getPeerTaskExecutor().execute(task); + } + + CompletableFuture> returnValue = new CompletableFuture>(); + if (taskResult.responseCode() == PeerTaskExecutorResponseCode.PEER_DISCONNECTED + && taskResult.ethPeer().isPresent()) { + returnValue.completeExceptionally(new PeerDisconnectedException(taskResult.ethPeer().get())); + } else if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + String logMessage = + "Peer " + + taskResult.ethPeer().map(EthPeer::getLoggableId).orElse("UNKNOWN") + + " failed to successfully return requested block headers. Response code was " + + taskResult.responseCode(); + returnValue.completeExceptionally(new RuntimeException(logMessage)); + LOG.debug(logMessage); + } else { + returnValue.complete(taskResult.result().get()); + } + return returnValue; + } + private CompletableFuture>> completeBlock( - final PeerTaskResult> headerResult) { - if (headerResult.getResult().isEmpty()) { + final List headers) { + if (headers.isEmpty()) { LOG.debug("header result is empty."); return CompletableFuture.failedFuture(new IncompleteResultsException()); } @@ -124,9 +162,38 @@ private CompletableFuture>> completeBlock( () -> { final GetBodiesFromPeerTask task = GetBodiesFromPeerTask.forHeaders( - protocolSchedule, ethContext, headerResult.getResult(), metricsSystem); - task.assignPeer(headerResult.getPeer()); + protocolSchedule, ethContext, headers, metricsSystem); + assignedPeer.ifPresent(task::assignPeer); return task.run(); }); } + + private void completeTask( + final PeerTaskResult> blockTaskResult, + final Throwable throwable, + final String blockIdentifier) { + if (throwable != null) { + LOG.debug( + "Failed to download block {} from peer {} with message '{}' and cause '{}'", + blockIdentifier, + assignedPeer.map(EthPeer::toString).orElse(""), + throwable.getMessage(), + throwable.getCause()); + result.completeExceptionally(throwable); + } else if (blockTaskResult.getResult().isEmpty()) { + blockTaskResult.getPeer().recordUselessResponse("Download block returned an empty result"); + LOG.debug( + "Failed to download block {} from peer {} with empty result.", + blockIdentifier, + blockTaskResult.getPeer()); + result.completeExceptionally(new IncompleteResultsException()); + } else { + LOG.debug( + "Successfully downloaded block {} from peer {}.", + blockIdentifier, + blockTaskResult.getPeer()); + result.complete( + new PeerTaskResult<>(blockTaskResult.getPeer(), blockTaskResult.getResult().get(0))); + } + } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTask.java index e4e472f4f4c..592e2786acc 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTask.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.exceptions.IncompleteResultsException; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask.PeerTaskResult; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -36,18 +37,21 @@ public class RetryingGetBlockFromPeersTask private static final Logger LOG = LoggerFactory.getLogger(RetryingGetBlockFromPeersTask.class); private final ProtocolSchedule protocolSchedule; + private final SynchronizerConfiguration synchronizerConfiguration; private final Optional maybeBlockHash; private final long blockNumber; protected RetryingGetBlockFromPeersTask( final EthContext ethContext, final ProtocolSchedule protocolSchedule, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final int maxRetries, final Optional maybeBlockHash, final long blockNumber) { super(ethContext, metricsSystem, Objects::isNull, maxRetries); this.protocolSchedule = protocolSchedule; + this.synchronizerConfiguration = synchronizerConfiguration; this.maybeBlockHash = maybeBlockHash; this.blockNumber = blockNumber; } @@ -55,12 +59,19 @@ protected RetryingGetBlockFromPeersTask( public static RetryingGetBlockFromPeersTask create( final ProtocolSchedule protocolSchedule, final EthContext ethContext, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final int maxRetries, final Optional maybeHash, final long blockNumber) { return new RetryingGetBlockFromPeersTask( - ethContext, protocolSchedule, metricsSystem, maxRetries, maybeHash, blockNumber); + ethContext, + protocolSchedule, + synchronizerConfiguration, + metricsSystem, + maxRetries, + maybeHash, + blockNumber); } @Override @@ -68,7 +79,12 @@ protected CompletableFuture> executeTaskOnCurrentPeer( final EthPeer currentPeer) { final GetBlockFromPeerTask getBlockTask = GetBlockFromPeerTask.create( - protocolSchedule, getEthContext(), maybeBlockHash, blockNumber, getMetricsSystem()); + protocolSchedule, + getEthContext(), + synchronizerConfiguration, + maybeBlockHash, + blockNumber, + getMetricsSystem()); getBlockTask.assignPeer(currentPeer); return executeSubTask(getBlockTask::run) diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTask.java deleted file mode 100644 index 44ced57e7ba..00000000000 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTask.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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.ethereum.eth.manager.task; - -import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.EthPeers; -import org.hyperledger.besu.plugin.services.MetricsSystem; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Wait for a single new peer to connect. */ -public class WaitForPeerTask extends AbstractEthTask { - private static final Logger LOG = LoggerFactory.getLogger(WaitForPeerTask.class); - - private final EthContext ethContext; - private volatile Long peerListenerId; - - private WaitForPeerTask(final EthContext ethContext, final MetricsSystem metricsSystem) { - super(metricsSystem); - this.ethContext = ethContext; - } - - public static WaitForPeerTask create( - final EthContext ethContext, final MetricsSystem metricsSystem) { - return new WaitForPeerTask(ethContext, metricsSystem); - } - - @Override - protected void executeTask() { - final EthPeers ethPeers = ethContext.getEthPeers(); - LOG.debug( - "Waiting for new peer connection. {} peers currently connected.", ethPeers.peerCount()); - // Listen for peer connections and complete task when we hit our target - peerListenerId = - ethPeers.subscribeConnect( - (peer) -> { - LOG.debug("Finished waiting for peer connection."); - // We hit our target - result.complete(null); - }); - } - - @Override - protected void cleanup() { - super.cleanup(); - final Long listenerId = peerListenerId; - if (listenerId != null) { - ethContext.getEthPeers().unsubscribeConnect(listenerId); - } - } -} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTask.java deleted file mode 100644 index b0d40770293..00000000000 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTask.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.ethereum.eth.manager.task; - -import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.EthPeers; -import org.hyperledger.besu.plugin.services.MetricsSystem; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** Waits for some number of peers to connect. */ -public class WaitForPeersTask extends AbstractEthTask { - private static final Logger LOG = LoggerFactory.getLogger(WaitForPeersTask.class); - - private final int targetPeerCount; - private final EthContext ethContext; - private volatile Long peerListenerId; - - private WaitForPeersTask( - final EthContext ethContext, final int targetPeerCount, final MetricsSystem metricsSystem) { - super(metricsSystem); - this.targetPeerCount = targetPeerCount; - this.ethContext = ethContext; - } - - public static WaitForPeersTask create( - final EthContext ethContext, final int targetPeerCount, final MetricsSystem metricsSystem) { - return new WaitForPeersTask(ethContext, targetPeerCount, metricsSystem); - } - - @Override - protected void executeTask() { - final EthPeers ethPeers = ethContext.getEthPeers(); - if (ethPeers.peerCount() >= targetPeerCount) { - LOG.debug("We already hit our target of at least {} peers connected", targetPeerCount); - result.complete(null); - return; - } - - LOG.info( - "Waiting for {} total peers to connect. {} peers currently connected.", - targetPeerCount, - ethPeers.peerCount()); - // Listen for peer connections and complete task when we hit our target - peerListenerId = - ethPeers.subscribeConnect( - (peer) -> { - final int peerCount = ethPeers.peerCount(); - if (peerCount >= targetPeerCount) { - LOG.debug("Complete: {} peers connected.", targetPeerCount); - // We hit our target - result.complete(null); - } else { - LOG.debug( - "Waiting for {} total peers to connect. {} peers currently connected.", - targetPeerCount, - peerCount); - } - }); - } - - @Override - protected void cleanup() { - super.cleanup(); - final Long listenerId = peerListenerId; - if (listenerId != null) { - ethContext.getEthPeers().unsubscribeConnect(peerListenerId); - } - } -} diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidator.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidator.java index dfc5b49d9bc..1e86f62b472 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidator.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidator.java @@ -19,8 +19,13 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.GetHeadersFromPeerByNumberTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -36,6 +41,8 @@ abstract class AbstractPeerBlockValidator implements PeerValidator { static long DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER = 10L; private final ProtocolSchedule protocolSchedule; + private final PeerTaskExecutor peerTaskExecutor; + private final SynchronizerConfiguration synchronizerConfiguration; private final MetricsSystem metricsSystem; final long blockNumber; @@ -44,11 +51,15 @@ abstract class AbstractPeerBlockValidator implements PeerValidator { AbstractPeerBlockValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long blockNumber, final long chainHeightEstimationBuffer) { checkArgument(chainHeightEstimationBuffer >= 0); this.protocolSchedule = protocolSchedule; + this.peerTaskExecutor = peerTaskExecutor; + this.synchronizerConfiguration = synchronizerConfiguration; this.metricsSystem = metricsSystem; this.blockNumber = blockNumber; this.chainHeightEstimationBuffer = chainHeightEstimationBuffer; @@ -57,44 +68,76 @@ abstract class AbstractPeerBlockValidator implements PeerValidator { @Override public CompletableFuture validatePeer( final EthContext ethContext, final EthPeer ethPeer) { - final AbstractPeerTask> getHeaderTask = - GetHeadersFromPeerByNumberTask.forSingleNumber( - protocolSchedule, ethContext, blockNumber, metricsSystem) - .setTimeout(Duration.ofSeconds(20)) - .assignPeer(ethPeer); - return getHeaderTask - .run() - .handle( - (res, err) -> { - if (err != null) { - // Mark peer as invalid on error - LOG.debug( - "Peer {} is invalid because required block ({}) is unavailable: {}", - ethPeer, - blockNumber, - err.toString()); - return false; - } - final List headers = res.getResult(); - if (headers.size() == 0) { - if (blockIsRequired()) { - // If no headers are returned, fail - LOG.debug( - "Peer {} is invalid because required block ({}) is unavailable.", - ethPeer, - blockNumber); - return false; + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + return ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + blockNumber, + 1, + 0, + GetHeadersFromPeerTask.Direction.FORWARD, + protocolSchedule); + PeerTaskExecutorResult> taskResult = + peerTaskExecutor.executeAgainstPeer(task, ethPeer); + CompletableFuture resultFuture; + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + resultFuture = CompletableFuture.completedFuture(false); } else { + resultFuture = + CompletableFuture.completedFuture( + validateBlockHeaders(ethPeer, taskResult.result().get())); + } + return resultFuture; + }); + } else { + final AbstractPeerTask> getHeaderTask = + GetHeadersFromPeerByNumberTask.forSingleNumber( + protocolSchedule, ethContext, blockNumber, metricsSystem) + .setTimeout(Duration.ofSeconds(20)) + .assignPeer(ethPeer); + return getHeaderTask + .run() + .handle( + (res, err) -> { + if (err != null) { + // Mark peer as invalid on error LOG.debug( - "Peer {} deemed valid because unavailable block ({}) is not required.", + "Peer {} is invalid because required block ({}) is unavailable: {}", ethPeer, - blockNumber); - return true; + blockNumber, + err.toString()); + return false; } - } - final BlockHeader header = headers.get(0); - return validateBlockHeader(ethPeer, header); - }); + final List headers = res.getResult(); + return validateBlockHeaders(ethPeer, headers); + }); + } + } + + private Boolean validateBlockHeaders(final EthPeer ethPeer, final List headers) { + boolean isValid; + if (headers.isEmpty()) { + if (blockIsRequired()) { + // If no headers are returned, fail + LOG.debug( + "Peer {} is invalid because required block ({}) is unavailable.", ethPeer, blockNumber); + isValid = false; + } else { + LOG.debug( + "Peer {} deemed valid because unavailable block ({}) is not required.", + ethPeer, + blockNumber); + isValid = true; + } + } else { + final BlockHeader header = headers.getFirst(); + isValid = validateBlockHeader(ethPeer, header); + } + return isValid; } abstract boolean validateBlockHeader(EthPeer ethPeer, BlockHeader header); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/CheckpointBlocksPeerValidator.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/CheckpointBlocksPeerValidator.java index a66cc16785d..734017d1a6f 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/CheckpointBlocksPeerValidator.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/CheckpointBlocksPeerValidator.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -24,20 +26,37 @@ public class CheckpointBlocksPeerValidator extends RequiredBlocksPeerValidator { public CheckpointBlocksPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long blockNumber, final Hash hash, final long chainHeightEstimationBuffer) { - super(protocolSchedule, metricsSystem, blockNumber, hash, chainHeightEstimationBuffer); + super( + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + blockNumber, + hash, + chainHeightEstimationBuffer); } public CheckpointBlocksPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long blockNumber, final Hash hash) { this( - protocolSchedule, metricsSystem, blockNumber, hash, DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + blockNumber, + hash, + DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/ClassicForkPeerValidator.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/ClassicForkPeerValidator.java index 2958ec8e551..2ce969b8cd3 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/ClassicForkPeerValidator.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/ClassicForkPeerValidator.java @@ -16,6 +16,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderValidator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -28,17 +30,33 @@ public class ClassicForkPeerValidator extends AbstractPeerBlockValidator { ClassicForkPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long daoBlockNumber, final long chainHeightEstimationBuffer) { - super(protocolSchedule, metricsSystem, daoBlockNumber, chainHeightEstimationBuffer); + super( + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + daoBlockNumber, + chainHeightEstimationBuffer); } public ClassicForkPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long daoBlockNumber) { - this(protocolSchedule, metricsSystem, daoBlockNumber, DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); + this( + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + daoBlockNumber, + DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidator.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidator.java index 01ce6144ee0..89bb36ec82f 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidator.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidator.java @@ -16,6 +16,8 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderValidator; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -28,17 +30,33 @@ public class DaoForkPeerValidator extends AbstractPeerBlockValidator { DaoForkPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long daoBlockNumber, final long chainHeightEstimationBuffer) { - super(protocolSchedule, metricsSystem, daoBlockNumber, chainHeightEstimationBuffer); + super( + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + daoBlockNumber, + chainHeightEstimationBuffer); } public DaoForkPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long daoBlockNumber) { - this(protocolSchedule, metricsSystem, daoBlockNumber, DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); + this( + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + daoBlockNumber, + DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidator.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidator.java index bf8716c328b..aa423a56cd1 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidator.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidator.java @@ -17,6 +17,8 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -30,21 +32,37 @@ public class RequiredBlocksPeerValidator extends AbstractPeerBlockValidator { public RequiredBlocksPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long blockNumber, final Hash hash, final long chainHeightEstimationBuffer) { - super(protocolSchedule, metricsSystem, blockNumber, chainHeightEstimationBuffer); + super( + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + blockNumber, + chainHeightEstimationBuffer); this.hash = hash; } public RequiredBlocksPeerValidator( final ProtocolSchedule protocolSchedule, + final PeerTaskExecutor peerTaskExecutor, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final long blockNumber, final Hash hash) { this( - protocolSchedule, metricsSystem, blockNumber, hash, DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); + protocolSchedule, + peerTaskExecutor, + synchronizerConfiguration, + metricsSystem, + blockNumber, + hash, + DEFAULT_CHAIN_HEIGHT_ESTIMATION_BUFFER); } @Override diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java index f5b5f978cb3..46d9aed20a4 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/AbstractSyncTargetManager.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; -import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeerTask; import org.hyperledger.besu.ethereum.eth.sync.state.SyncTarget; import org.hyperledger.besu.ethereum.eth.sync.tasks.DetermineCommonAncestorTask; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -73,6 +72,7 @@ public CompletableFuture findSyncTarget() { ethContext, bestPeer, config.getDownloaderHeaderRequestSize(), + config, metricsSystem) .run() .handle( @@ -116,13 +116,16 @@ protected Optional finalizeSelectedSyncTarget(final SyncTarget syncT protected abstract CompletableFuture> selectBestAvailableSyncTarget(); private CompletableFuture waitForPeerAndThenSetSyncTarget() { - return waitForNewPeer().handle((r, t) -> r).thenCompose((r) -> findSyncTarget()); - } - - private CompletableFuture waitForNewPeer() { return ethContext .getScheduler() - .timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5)); + .scheduleFutureTask( + () -> + ethContext + .getEthPeers() + .waitForPeer((peer) -> true) + .handle((ignored, ignored2) -> null) + .thenCompose((r) -> findSyncTarget()), + Duration.ofSeconds(5)); } private boolean isCancelled() { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java index aee8ec48ea7..ab7e65f103e 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/BlockPropagationManager.java @@ -536,6 +536,7 @@ private CompletableFuture scheduleGetBlockFromPeers( RetryingGetBlockFromPeersTask.create( protocolSchedule, ethContext, + config, metricsSystem, Math.max(1, ethContext.getEthPeers().peerCount()), maybeBlockHash, diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTracker.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTracker.java index 67681acf6a7..08284e88fff 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTracker.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTracker.java @@ -19,6 +19,10 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask.Direction; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.GetHeadersFromPeerByHashTask; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -38,28 +42,32 @@ public class ChainHeadTracker { private final EthContext ethContext; private final ProtocolSchedule protocolSchedule; + private final SynchronizerConfiguration synchronizerConfiguration; private final MetricsSystem metricsSystem; public ChainHeadTracker( final EthContext ethContext, final ProtocolSchedule protocolSchedule, - final TrailingPeerLimiter trailingPeerLimiter, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem) { this.ethContext = ethContext; this.protocolSchedule = protocolSchedule; + this.synchronizerConfiguration = synchronizerConfiguration; this.metricsSystem = metricsSystem; } public static void trackChainHeadForPeers( final EthContext ethContext, final ProtocolSchedule protocolSchedule, + final SynchronizerConfiguration synchronizerConfiguration, final Blockchain blockchain, final Supplier trailingPeerRequirementsCalculator, final MetricsSystem metricsSystem) { final TrailingPeerLimiter trailingPeerLimiter = new TrailingPeerLimiter(ethContext.getEthPeers(), trailingPeerRequirementsCalculator); final ChainHeadTracker tracker = - new ChainHeadTracker(ethContext, protocolSchedule, trailingPeerLimiter, metricsSystem); + new ChainHeadTracker( + ethContext, protocolSchedule, synchronizerConfiguration, metricsSystem); ethContext.getEthPeers().setChainHeadTracker(tracker); blockchain.observeBlockAdded(trailingPeerLimiter); } @@ -69,33 +77,78 @@ public CompletableFuture getBestHeaderFromPeer(final EthPeer peer) .setMessage("Requesting chain head info from {}...") .addArgument(peer::getLoggableId) .log(); - final CompletableFuture>> - bestHeaderFromPeerCompletableFuture = getBestHeaderFromPeerCompletableFuture(peer); - final CompletableFuture future = new CompletableFuture<>(); - bestHeaderFromPeerCompletableFuture.whenComplete( - (peerResult, error) -> { - if (peerResult != null && !peerResult.getResult().isEmpty()) { - final BlockHeader chainHeadHeader = peerResult.getResult().get(0); - peer.chainState().update(chainHeadHeader); - future.complete(chainHeadHeader); - LOG.atDebug() - .setMessage("Retrieved chain head info {} from {}...") - .addArgument( - () -> chainHeadHeader.getNumber() + " (" + chainHeadHeader.getBlockHash() + ")") - .addArgument(peer::getLoggableId) - .log(); - } else { - LOG.atDebug() - .setMessage("Failed to retrieve chain head info. Disconnecting {}... {}") - .addArgument(peer::getLoggableId) - .addArgument(error != null ? error : "Empty Response") - .log(); - peer.disconnect( - DisconnectMessage.DisconnectReason.USELESS_PEER_FAILED_TO_RETRIEVE_CHAIN_HEAD); - future.complete(null); - } - }); - return future; + + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + return ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + Hash.wrap(peer.chainState().getBestBlock().getHash()), + 0, + 1, + 0, + Direction.FORWARD, + protocolSchedule); + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().executeAgainstPeer(task, peer); + if (taskResult.responseCode() == PeerTaskExecutorResponseCode.SUCCESS + && taskResult.result().isPresent()) { + BlockHeader chainHeadHeader = taskResult.result().get().getFirst(); + LOG.atDebug() + .setMessage("Retrieved chain head info {} from {}...") + .addArgument( + () -> + chainHeadHeader.getNumber() + + " (" + + chainHeadHeader.getBlockHash() + + ")") + .addArgument(peer::getLoggableId) + .log(); + return CompletableFuture.completedFuture(chainHeadHeader); + } else { + LOG.atDebug() + .setMessage("Failed to retrieve chain head info. Disconnecting {}... {}") + .addArgument(peer::getLoggableId) + .addArgument(taskResult.responseCode()) + .log(); + peer.disconnect( + DisconnectMessage.DisconnectReason + .USELESS_PEER_FAILED_TO_RETRIEVE_CHAIN_HEAD); + return CompletableFuture.completedFuture(null); + } + }); + } else { + final CompletableFuture>> + bestHeaderFromPeerCompletableFuture = getBestHeaderFromPeerCompletableFuture(peer); + final CompletableFuture future = new CompletableFuture<>(); + bestHeaderFromPeerCompletableFuture.whenComplete( + (peerResult, error) -> { + if (peerResult != null && !peerResult.getResult().isEmpty()) { + final BlockHeader chainHeadHeader = peerResult.getResult().get(0); + peer.chainState().update(chainHeadHeader); + future.complete(chainHeadHeader); + LOG.atDebug() + .setMessage("Retrieved chain head info {} from {}...") + .addArgument( + () -> + chainHeadHeader.getNumber() + " (" + chainHeadHeader.getBlockHash() + ")") + .addArgument(peer::getLoggableId) + .log(); + } else { + LOG.atDebug() + .setMessage("Failed to retrieve chain head info. Disconnecting {}... {}") + .addArgument(peer::getLoggableId) + .addArgument(error != null ? error : "Empty Response") + .log(); + peer.disconnect( + DisconnectMessage.DisconnectReason.USELESS_PEER_FAILED_TO_RETRIEVE_CHAIN_HEAD); + future.complete(null); + } + }); + return future; + } } public CompletableFuture>> diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java index 66684ab7873..43dfa275eba 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DefaultSynchronizer.java @@ -99,6 +99,7 @@ public DefaultSynchronizer( ChainHeadTracker.trackChainHeadForPeers( ethContext, protocolSchedule, + syncConfig, protocolContext.getBlockchain(), this::calculateTrailingPeerRequirements, metricsSystem); @@ -149,7 +150,6 @@ public DefaultSynchronizer( protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, @@ -166,7 +166,6 @@ public DefaultSynchronizer( protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, @@ -183,7 +182,6 @@ public DefaultSynchronizer( protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStep.java index 6e404305823..240a7502a64 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStep.java @@ -20,6 +20,9 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask.PeerTaskResult; import org.hyperledger.besu.ethereum.eth.manager.task.GetHeadersFromPeerByHashTask; import org.hyperledger.besu.ethereum.eth.sync.range.RangeHeaders; @@ -44,6 +47,7 @@ public class DownloadHeadersStep private final ProtocolContext protocolContext; private final EthContext ethContext; private final ValidationPolicy validationPolicy; + private final SynchronizerConfiguration synchronizerConfiguration; private final int headerRequestSize; private final MetricsSystem metricsSystem; @@ -52,12 +56,14 @@ public DownloadHeadersStep( final ProtocolContext protocolContext, final EthContext ethContext, final ValidationPolicy validationPolicy, + final SynchronizerConfiguration synchronizerConfiguration, final int headerRequestSize, final MetricsSystem metricsSystem) { this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.ethContext = ethContext; this.validationPolicy = validationPolicy; + this.synchronizerConfiguration = synchronizerConfiguration; this.headerRequestSize = headerRequestSize; this.metricsSystem = metricsSystem; } @@ -85,6 +91,7 @@ private CompletableFuture> downloadHeaders(final SyncTargetRan protocolSchedule, protocolContext, ethContext, + synchronizerConfiguration, range.getEnd(), range.getSegmentLengthExclusive(), validationPolicy, @@ -92,16 +99,39 @@ private CompletableFuture> downloadHeaders(final SyncTargetRan .run(); } else { LOG.debug("Downloading headers starting from {}", range.getStart().getNumber()); - return GetHeadersFromPeerByHashTask.startingAtHash( - protocolSchedule, - ethContext, - range.getStart().getHash(), - range.getStart().getNumber(), - headerRequestSize, - metricsSystem) - .assignPeer(range.getSyncTarget()) - .run() - .thenApply(PeerTaskResult::getResult); + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + return ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + range.getStart().getHash(), + range.getStart().getNumber(), + headerRequestSize, + 0, + GetHeadersFromPeerTask.Direction.FORWARD, + protocolSchedule); + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().execute(task); + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + return CompletableFuture.failedFuture( + new RuntimeException("Unable to download headers for range " + range)); + } + return CompletableFuture.completedFuture(taskResult.result().get()); + }); + } else { + return GetHeadersFromPeerByHashTask.startingAtHash( + protocolSchedule, + ethContext, + range.getStart().getHash(), + range.getStart().getNumber(), + headerRequestSize, + metricsSystem) + .run() + .thenApply(PeerTaskResult::getResult); + } } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgorithm.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgorithm.java index 506b360730e..a7311ac469a 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgorithm.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncAlgorithm.java @@ -21,7 +21,6 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.exceptions.MaxRetriesReachedException; -import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeersTask; import org.hyperledger.besu.plugin.services.BesuEvents; import java.util.Optional; @@ -189,7 +188,12 @@ private void checkReadiness(final long idTTD, final long idIS) { final boolean await = latch.get().await(2, TimeUnit.MINUTES); if (await) { LOG.debug("Preconditions meet, ensure at least one peer is connected"); - waitForPeers(1).get(); + context + .getEthContext() + .getEthPeers() + .waitForPeer((peer) -> true) + .orTimeout(5, TimeUnit.SECONDS) + .get(); } } } catch (InterruptedException e) { @@ -211,12 +215,6 @@ private void countDownIfReady() { } } - private CompletableFuture waitForPeers(final int count) { - final WaitForPeersTask waitForPeersTask = - WaitForPeersTask.create(context.getEthContext(), count, context.getMetricsSystem()); - return waitForPeersTask.run(); - } - @Override public void onInitialSyncCompleted() { countDownIfReady(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContext.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContext.java index bef62ec927e..ab0b94ab616 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContext.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContext.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -52,6 +53,7 @@ public class BackwardSyncContext { protected final ProtocolContext protocolContext; private final ProtocolSchedule protocolSchedule; private final EthContext ethContext; + private final SynchronizerConfiguration synchronizerConfiguration; private final MetricsSystem metricsSystem; private final SyncState syncState; private final AtomicReference currentBackwardSyncStatus = new AtomicReference<>(); @@ -65,6 +67,7 @@ public class BackwardSyncContext { public BackwardSyncContext( final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final EthContext ethContext, final SyncState syncState, @@ -72,6 +75,7 @@ public BackwardSyncContext( this( protocolContext, protocolSchedule, + synchronizerConfiguration, metricsSystem, ethContext, syncState, @@ -83,6 +87,7 @@ public BackwardSyncContext( public BackwardSyncContext( final ProtocolContext protocolContext, final ProtocolSchedule protocolSchedule, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem, final EthContext ethContext, final SyncState syncState, @@ -93,6 +98,7 @@ public BackwardSyncContext( this.protocolContext = protocolContext; this.protocolSchedule = protocolSchedule; this.ethContext = ethContext; + this.synchronizerConfiguration = synchronizerConfiguration; this.metricsSystem = metricsSystem; this.syncState = syncState; this.backwardChain = backwardChain; @@ -431,6 +437,10 @@ private void logBlockImportProgress(final long currImportedHeight) { } } + public SynchronizerConfiguration getSynchronizerConfiguration() { + return synchronizerConfiguration; + } + class Status { private final CompletableFuture currentFuture; private final long initialChainHeight; diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStep.java index 748c71fc6f6..60baee2b640 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStep.java @@ -16,6 +16,10 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask.Direction; import org.hyperledger.besu.ethereum.eth.manager.task.RetryingGetHeadersEndingAtFromPeerByHashTask; import java.util.List; @@ -69,29 +73,57 @@ protected CompletableFuture> requestHeaders(final Hash hash) { final int batchSize = context.getBatchSize(); LOG.trace("Requesting headers for hash {}, with batch size {}", hash, batchSize); - final RetryingGetHeadersEndingAtFromPeerByHashTask - retryingGetHeadersEndingAtFromPeerByHashTask = - RetryingGetHeadersEndingAtFromPeerByHashTask.endingAtHash( - context.getProtocolSchedule(), - context.getEthContext(), - hash, - 0, - batchSize, - context.getMetricsSystem(), - context.getEthContext().getEthPeers().peerCount()); - return context - .getEthContext() - .getScheduler() - .scheduleSyncWorkerTask(retryingGetHeadersEndingAtFromPeerByHashTask::run) - .thenApply( - blockHeaders -> { - LOG.atDebug() - .setMessage("Got headers {} -> {}") - .addArgument(blockHeaders.get(0)::getNumber) - .addArgument(blockHeaders.get(blockHeaders.size() - 1)::getNumber) - .log(); - return blockHeaders; - }); + CompletableFuture> headersResult; + if (context.getSynchronizerConfiguration().isPeerTaskSystemEnabled()) { + headersResult = + context + .getEthContext() + .getScheduler() + .scheduleSyncWorkerTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + hash, + 0, + batchSize, + 0, + Direction.REVERSE, + context.getEthContext().getEthPeers().peerCount(), + context.getProtocolSchedule()); + PeerTaskExecutorResult> taskResult = + context.getEthContext().getPeerTaskExecutor().execute(task); + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + throw new RuntimeException("Unable to retrieve headers"); + } + return CompletableFuture.completedFuture(taskResult.result().get()); + }); + } else { + final RetryingGetHeadersEndingAtFromPeerByHashTask + retryingGetHeadersEndingAtFromPeerByHashTask = + RetryingGetHeadersEndingAtFromPeerByHashTask.endingAtHash( + context.getProtocolSchedule(), + context.getEthContext(), + hash, + 0, + batchSize, + context.getMetricsSystem(), + context.getEthContext().getEthPeers().peerCount()); + headersResult = + context + .getEthContext() + .getScheduler() + .scheduleSyncWorkerTask(retryingGetHeadersEndingAtFromPeerByHashTask::run); + } + return headersResult.thenApply( + blockHeaders -> { + LOG.atDebug() + .setMessage("Got headers {} -> {}") + .addArgument(blockHeaders.get(0)::getNumber) + .addArgument(blockHeaders.get(blockHeaders.size() - 1)::getNumber) + .log(); + return blockHeaders; + }); } @VisibleForTesting diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/SyncStepStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/SyncStepStep.java index 1f7bc8979b9..890d51ee82e 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/SyncStepStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/SyncStepStep.java @@ -50,6 +50,7 @@ private CompletableFuture requestBlock(final Hash targetHash) { RetryingGetBlockFromPeersTask.create( context.getProtocolSchedule(), context.getEthContext(), + context.getSynchronizerConfiguration(), context.getMetricsSystem(), context.getEthContext().getEthPeers().peerCount(), Optional.of(targetHash), diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloadBlockStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloadBlockStep.java index 72f1fae764f..303a728cd2b 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloadBlockStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloadBlockStep.java @@ -20,7 +20,6 @@ import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetReceiptsFromPeerTask; @@ -40,7 +39,6 @@ public class CheckpointDownloadBlockStep { private final ProtocolSchedule protocolSchedule; private final EthContext ethContext; - private final PeerTaskExecutor peerTaskExecutor; private final Checkpoint checkpoint; private final SynchronizerConfiguration synchronizerConfiguration; private final MetricsSystem metricsSystem; @@ -48,13 +46,11 @@ public class CheckpointDownloadBlockStep { public CheckpointDownloadBlockStep( final ProtocolSchedule protocolSchedule, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final Checkpoint checkpoint, final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem) { this.protocolSchedule = protocolSchedule; this.ethContext = ethContext; - this.peerTaskExecutor = peerTaskExecutor; this.checkpoint = checkpoint; this.synchronizerConfiguration = synchronizerConfiguration; this.metricsSystem = metricsSystem; @@ -65,6 +61,7 @@ public CompletableFuture> downloadBlock(final Hash h GetBlockFromPeerTask.create( protocolSchedule, ethContext, + synchronizerConfiguration, Optional.of(hash), checkpoint.blockNumber(), metricsSystem); @@ -85,7 +82,7 @@ private CompletableFuture> downloadReceipts( GetReceiptsFromPeerTask task = new GetReceiptsFromPeerTask(List.of(block.getHeader()), protocolSchedule); PeerTaskExecutorResult>> executorResult = - peerTaskExecutor.execute(task); + ethContext.getPeerTaskExecutor().execute(task); if (executorResult.responseCode() == PeerTaskExecutorResponseCode.SUCCESS) { List transactionReceipts = diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloaderFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloaderFactory.java index 30134d9f6c5..03df47e4407 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloaderFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointDownloaderFactory.java @@ -17,7 +17,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -62,7 +61,6 @@ public static Optional> createCheckpointDownloader( final ProtocolContext protocolContext, final MetricsSystem metricsSystem, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final WorldStateStorageCoordinator worldStateStorageCoordinator, final SyncState syncState, final Clock clock, @@ -112,7 +110,6 @@ public static Optional> createCheckpointDownloader( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, pivotBlockSelector, metricsSystem); @@ -130,7 +127,6 @@ public static Optional> createCheckpointDownloader( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, pivotBlockSelector, metricsSystem); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncActions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncActions.java index 61b997e6c53..5096b74e24f 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncActions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncActions.java @@ -16,7 +16,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -35,7 +34,6 @@ public CheckpointSyncActions( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final SyncState syncState, final PivotBlockSelector pivotBlockSelector, final MetricsSystem metricsSystem) { @@ -45,7 +43,6 @@ public CheckpointSyncActions( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, pivotBlockSelector, metricsSystem); @@ -60,7 +57,6 @@ public ChainDownloader createChainDownloader( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, metricsSystem, currentState, diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncChainDownloader.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncChainDownloader.java index 2590e4736ae..5450b9e5a49 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncChainDownloader.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncChainDownloader.java @@ -16,7 +16,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.PipelineChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -37,7 +36,6 @@ public static ChainDownloader create( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final SyncState syncState, final MetricsSystem metricsSystem, final FastSyncState fastSyncState, @@ -57,13 +55,7 @@ public static ChainDownloader create( syncState, syncTargetManager, new CheckpointSyncDownloadPipelineFactory( - config, - protocolSchedule, - protocolContext, - ethContext, - peerTaskExecutor, - fastSyncState, - metricsSystem), + config, protocolSchedule, protocolContext, ethContext, fastSyncState, metricsSystem), ethContext.getScheduler(), metricsSystem, syncDurationMetrics); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncDownloadPipelineFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncDownloadPipelineFactory.java index 0be10869861..27dc032b915 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncDownloadPipelineFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckpointSyncDownloadPipelineFactory.java @@ -19,7 +19,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncDownloadPipelineFactory; import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncState; @@ -41,17 +40,9 @@ public CheckpointSyncDownloadPipelineFactory( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final FastSyncState fastSyncState, final MetricsSystem metricsSystem) { - super( - syncConfig, - protocolSchedule, - protocolContext, - ethContext, - peerTaskExecutor, - fastSyncState, - metricsSystem); + super(syncConfig, protocolSchedule, protocolContext, ethContext, fastSyncState, metricsSystem); } @Override @@ -86,7 +77,7 @@ protected Pipeline createDownloadCheckPointPipeline( final CheckpointDownloadBlockStep checkPointDownloadBlockStep = new CheckpointDownloadBlockStep( - protocolSchedule, ethContext, peerTaskExecutor, checkpoint, syncConfig, metricsSystem); + protocolSchedule, ethContext, checkpoint, syncConfig, metricsSystem); return PipelineBuilder.createPipelineFrom( "fetchCheckpoints", diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStep.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStep.java index 876e96d1072..c2b7ee56901 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStep.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStep.java @@ -22,7 +22,6 @@ import org.hyperledger.besu.ethereum.core.BlockWithReceipts; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetReceiptsFromPeerTask; @@ -42,19 +41,16 @@ public class DownloadReceiptsStep private final ProtocolSchedule protocolSchedule; private final EthContext ethContext; - private final PeerTaskExecutor peerTaskExecutor; private final SynchronizerConfiguration synchronizerConfiguration; private final MetricsSystem metricsSystem; public DownloadReceiptsStep( final ProtocolSchedule protocolSchedule, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem) { this.protocolSchedule = protocolSchedule; this.ethContext = ethContext; - this.peerTaskExecutor = peerTaskExecutor; this.synchronizerConfiguration = synchronizerConfiguration; this.metricsSystem = metricsSystem; } @@ -81,7 +77,7 @@ public CompletableFuture> apply(final List blocks do { GetReceiptsFromPeerTask task = new GetReceiptsFromPeerTask(headers, protocolSchedule); PeerTaskExecutorResult>> getReceiptsResult = - peerTaskExecutor.execute(task); + ethContext.getPeerTaskExecutor().execute(task); if (getReceiptsResult.responseCode() == PeerTaskExecutorResponseCode.SUCCESS && getReceiptsResult.result().isPresent()) { Map> taskResult = getReceiptsResult.result().get(); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActions.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActions.java index 58a64bd562a..2eb6b460375 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActions.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActions.java @@ -18,9 +18,12 @@ import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.ProtocolContext; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; -import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeersTask; +import org.hyperledger.besu.ethereum.eth.manager.exceptions.NoAvailablePeersException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -34,6 +37,7 @@ import org.hyperledger.besu.plugin.services.metrics.Counter; import java.time.Duration; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Supplier; @@ -49,7 +53,6 @@ public class FastSyncActions { protected final ProtocolSchedule protocolSchedule; protected final ProtocolContext protocolContext; protected final EthContext ethContext; - protected final PeerTaskExecutor peerTaskExecutor; protected final SyncState syncState; protected final PivotBlockSelector pivotBlockSelector; protected final MetricsSystem metricsSystem; @@ -62,7 +65,6 @@ public FastSyncActions( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final SyncState syncState, final PivotBlockSelector pivotBlockSelector, final MetricsSystem metricsSystem) { @@ -71,7 +73,6 @@ public FastSyncActions( this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.ethContext = ethContext; - this.peerTaskExecutor = peerTaskExecutor; this.syncState = syncState; this.pivotBlockSelector = pivotBlockSelector; this.metricsSystem = metricsSystem; @@ -103,7 +104,6 @@ public CompletableFuture selectPivotBlock(final FastSyncState fas } private CompletableFuture selectNewPivotBlock() { - return pivotBlockSelector .selectNewPivotBlock() .map(CompletableFuture::completedFuture) @@ -134,7 +134,9 @@ private CompletableFuture internalDownloadPivotBlockHeader( return completedFuture(currentState); } - return waitForPeers(1) + return ethContext + .getEthPeers() + .waitForPeer((peer) -> true) .thenCompose( unused -> currentState @@ -146,6 +148,7 @@ private CompletableFuture internalDownloadPivotBlockHeader( protocolSchedule, ethContext, metricsSystem, + syncConfig, currentState.getPivotBlockNumber().getAsLong(), syncConfig.getSyncMinimumPeerCount(), syncConfig.getSyncPivotDistance()) @@ -168,7 +171,6 @@ public ChainDownloader createChainDownloader( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, metricsSystem, currentState, @@ -177,13 +179,56 @@ public ChainDownloader createChainDownloader( private CompletableFuture downloadPivotBlockHeader(final Hash hash) { LOG.debug("Downloading pivot block header by hash {}", hash); - return RetryingGetHeaderFromPeerByHashTask.byHash( - protocolSchedule, - ethContext, - hash, - pivotBlockSelector.getMinRequiredBlockNumber(), - metricsSystem) - .getHeader() + CompletableFuture blockHeaderFuture; + if (syncConfig.isPeerTaskSystemEnabled()) { + blockHeaderFuture = + ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + hash, + pivotBlockSelector.getMinRequiredBlockNumber(), + 1, + 0, + GetHeadersFromPeerTask.Direction.FORWARD, + ethContext.getEthPeers().peerCount(), + protocolSchedule); + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().execute(task); + if (taskResult.responseCode() == PeerTaskExecutorResponseCode.NO_PEER_AVAILABLE + || taskResult.responseCode() + == PeerTaskExecutorResponseCode.PEER_DISCONNECTED) { + LOG.error( + "Failed to download pivot block header. Response Code was {}", + taskResult.responseCode()); + return CompletableFuture.failedFuture(new NoAvailablePeersException()); + } else if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + LOG.error( + "Failed to download pivot block header. Response Code was {}", + taskResult.responseCode()); + return CompletableFuture.failedFuture( + new RuntimeException( + "Failed to download pivot block header. Response Code was " + + taskResult.responseCode())); + } else { + return CompletableFuture.completedFuture( + taskResult.result().get().getFirst()); + } + }); + } else { + blockHeaderFuture = + RetryingGetHeaderFromPeerByHashTask.byHash( + protocolSchedule, + ethContext, + hash, + pivotBlockSelector.getMinRequiredBlockNumber(), + metricsSystem) + .getHeader(); + } + return blockHeaderFuture .whenComplete( (blockHeader, throwable) -> { if (throwable != null) { @@ -201,11 +246,4 @@ private CompletableFuture downloadPivotBlockHeader(final Hash has public boolean isBlockchainBehind(final long blockNumber) { return protocolContext.getBlockchain().getChainHeadHeader().getNumber() < blockNumber; } - - private CompletableFuture waitForPeers(final int count) { - - final WaitForPeersTask waitForPeersTask = - WaitForPeersTask.create(ethContext, count, metricsSystem); - return waitForPeersTask.run(); - } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloader.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloader.java index 1bf55a3811a..c36ff7cb482 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloader.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloader.java @@ -16,7 +16,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.PipelineChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -36,7 +35,6 @@ public static ChainDownloader create( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final SyncState syncState, final MetricsSystem metricsSystem, final FastSyncState fastSyncState, @@ -55,13 +53,7 @@ public static ChainDownloader create( syncState, syncTargetManager, new FastSyncDownloadPipelineFactory( - config, - protocolSchedule, - protocolContext, - ethContext, - peerTaskExecutor, - fastSyncState, - metricsSystem), + config, protocolSchedule, protocolContext, ethContext, fastSyncState, metricsSystem), ethContext.getScheduler(), metricsSystem, syncDurationMetrics); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java index 67085252e8f..707fc6aa13f 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloadPipelineFactory.java @@ -26,7 +26,6 @@ import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.DownloadBodiesStep; import org.hyperledger.besu.ethereum.eth.sync.DownloadHeadersStep; import org.hyperledger.besu.ethereum.eth.sync.DownloadPipelineFactory; @@ -58,7 +57,6 @@ public class FastSyncDownloadPipelineFactory implements DownloadPipelineFactory protected final ProtocolSchedule protocolSchedule; protected final ProtocolContext protocolContext; protected final EthContext ethContext; - protected final PeerTaskExecutor peerTaskExecutor; protected final FastSyncState fastSyncState; protected final MetricsSystem metricsSystem; protected final FastSyncValidationPolicy attachedValidationPolicy; @@ -70,14 +68,12 @@ public FastSyncDownloadPipelineFactory( final ProtocolSchedule protocolSchedule, final ProtocolContext protocolContext, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final FastSyncState fastSyncState, final MetricsSystem metricsSystem) { this.syncConfig = syncConfig; this.protocolSchedule = protocolSchedule; this.protocolContext = protocolContext; this.ethContext = ethContext; - this.peerTaskExecutor = peerTaskExecutor; this.fastSyncState = fastSyncState; this.metricsSystem = metricsSystem; final LabelledMetric fastSyncValidationCounter = @@ -138,6 +134,7 @@ public Pipeline createDownloadPipelineForSyncTarget(final SyncT protocolContext, ethContext, detachedValidationPolicy, + syncConfig, headerRequestSize, metricsSystem); final RangeHeadersValidationStep validateHeadersJoinUpStep = @@ -145,8 +142,7 @@ public Pipeline createDownloadPipelineForSyncTarget(final SyncT final DownloadBodiesStep downloadBodiesStep = new DownloadBodiesStep(protocolSchedule, ethContext, metricsSystem); final DownloadReceiptsStep downloadReceiptsStep = - new DownloadReceiptsStep( - protocolSchedule, ethContext, peerTaskExecutor, syncConfig, metricsSystem); + new DownloadReceiptsStep(protocolSchedule, ethContext, syncConfig, metricsSystem); final ImportBlocksStep importBlockStep = new ImportBlocksStep( protocolSchedule, diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java index 0aaeefc6d6e..da3f12390ab 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncDownloader.java @@ -17,6 +17,7 @@ import static org.hyperledger.besu.util.FutureUtils.exceptionallyCompose; import org.hyperledger.besu.ethereum.eth.manager.exceptions.MaxRetriesReachedException; +import org.hyperledger.besu.ethereum.eth.manager.exceptions.NoAvailablePeersException; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerRequirements; import org.hyperledger.besu.ethereum.eth.sync.worldstate.StalledDownloadException; @@ -132,6 +133,12 @@ protected CompletableFuture handleFailure(final Throwable error) LOG.debug( "A download operation reached the max number of retries, re-pivoting to newer block"); return start(FastSyncState.EMPTY_SYNC_STATE); + } else if (rootCause instanceof NoAvailablePeersException) { + LOG.debug( + "No peers available for sync. Restarting sync in {} seconds", + FAST_SYNC_RETRY_DELAY.getSeconds()); + return fastSyncActions.scheduleFutureTask( + () -> start(FastSyncState.EMPTY_SYNC_STATE), FAST_SYNC_RETRY_DELAY); } else { LOG.error( "Encountered an unexpected error during sync. Restarting sync in " diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmer.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmer.java index c5c586ea77c..9b3b40f8a8c 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmer.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmer.java @@ -17,8 +17,11 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; -import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeerTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByNumberTask; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -26,8 +29,12 @@ import java.time.Duration; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; @@ -52,6 +59,7 @@ class PivotBlockConfirmer { private final EthContext ethContext; private final MetricsSystem metricsSystem; private final ProtocolSchedule protocolSchedule; + private final SynchronizerConfiguration synchronizerConfiguration; // The number of peers we need to query to confirm our pivot block private final int numberOfPeersToQuery; @@ -64,6 +72,7 @@ class PivotBlockConfirmer { private final Collection> runningQueries = new ConcurrentLinkedQueue<>(); private final Map pivotBlockQueriesByPeerId = new ConcurrentHashMap<>(); + private final Set peerIdsUsed = Collections.synchronizedSet(new HashSet<>()); private final Map pivotBlockVotes = new ConcurrentHashMap<>(); private final AtomicBoolean isStarted = new AtomicBoolean(false); @@ -73,12 +82,14 @@ class PivotBlockConfirmer { final ProtocolSchedule protocolSchedule, final EthContext ethContext, final MetricsSystem metricsSystem, + final SynchronizerConfiguration synchronizerConfiguration, final long pivotBlockNumber, final int numberOfPeersToQuery, final int numberOfRetriesPerPeer) { this.protocolSchedule = protocolSchedule; this.ethContext = ethContext; this.metricsSystem = metricsSystem; + this.synchronizerConfiguration = synchronizerConfiguration; this.pivotBlockNumber = pivotBlockNumber; this.numberOfPeersToQuery = numberOfPeersToQuery; this.numberOfRetriesPerPeer = numberOfRetriesPerPeer; @@ -97,8 +108,14 @@ public CompletableFuture confirmPivotBlock() { private void queryPeers(final long blockNumber) { synchronized (runningQueries) { for (int i = 0; i < numberOfPeersToQuery; i++) { - final CompletableFuture query = - executePivotQuery(blockNumber).whenComplete(this::processReceivedHeader); + final CompletableFuture query; + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + query = + executePivotQueryWithPeerTaskSystem(blockNumber) + .whenComplete(this::processReceivedHeader); + } else { + query = executePivotQuery(blockNumber).whenComplete(this::processReceivedHeader); + } runningQueries.add(query); } } @@ -157,7 +174,6 @@ private CompletableFuture executePivotQuery(final long blockNumber) // Stop loop if this task is done return CompletableFuture.failedFuture(new CancellationException()); } - final Optional query = createPivotQuery(blockNumber); final CompletableFuture pivotHeaderFuture; if (query.isPresent()) { @@ -170,14 +186,74 @@ private CompletableFuture executePivotQuery(final long blockNumber) pivotHeaderFuture = ethContext .getScheduler() - .timeout(WaitForPeerTask.create(ethContext, metricsSystem), Duration.ofSeconds(5)) - .handle((err, res) -> null) // Ignore result - .thenCompose(res -> executePivotQuery(blockNumber)); + .scheduleFutureTask( + () -> + ethContext + .getEthPeers() + .waitForPeer( + (peer) -> !pivotBlockQueriesByPeerId.containsKey(peer.nodeId())) + // Ignore result, ensure even a timeout will result in calling + // executePivotQuery + .handle((r, e) -> null) + .thenCompose(res -> executePivotQuery(blockNumber)), + Duration.ofSeconds(5)); } return pivotHeaderFuture; } + private CompletableFuture executePivotQueryWithPeerTaskSystem( + final long blockNumber) { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + blockNumber, 1, 0, GetHeadersFromPeerTask.Direction.FORWARD, protocolSchedule); + Optional maybeEthPeer; + final EthPeer ethPeer; + try { + do { + if (isCancelled.get()) { + return CompletableFuture.failedFuture( + new CancellationException("Pivot block confirmation has been cancelled")); + } + maybeEthPeer = + ethContext + .getEthPeers() + .getPeer( + (p) -> + task.getPeerRequirementFilter().test(p) + && !peerIdsUsed.contains(p.nodeId())); + } while (maybeEthPeer.isEmpty() && waitForPeer()); + ethPeer = maybeEthPeer.get(); + peerIdsUsed.add(ethPeer.nodeId()); + } catch (InterruptedException e) { + return CompletableFuture.failedFuture(e); + } + + return ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().executeAgainstPeer(task, ethPeer); + if (taskResult.responseCode() == PeerTaskExecutorResponseCode.INTERNAL_SERVER_ERROR) { + // something is probably wrong with the request, so we won't retry as below + return CompletableFuture.failedFuture( + new RuntimeException("Unexpected internal issue")); + } else if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + // recursively call executePivotQueryWithPeerTaskSystem to retry with a different + // peer. + return executePivotQueryWithPeerTaskSystem(blockNumber); + } + return CompletableFuture.completedFuture(taskResult.result().get().getFirst()); + }); + } + + private boolean waitForPeer() throws InterruptedException { + Thread.sleep(Duration.ofSeconds(5)); + return true; + } + private Optional createPivotQuery(final long blockNumber) { return ethContext .getEthPeers() diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetriever.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetriever.java index d8ff3627101..6198c2c85b9 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetriever.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetriever.java @@ -16,6 +16,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.util.ExceptionUtils; @@ -46,6 +47,7 @@ public class PivotBlockRetriever { private final EthContext ethContext; private final MetricsSystem metricsSystem; private final ProtocolSchedule protocolSchedule; + private final SynchronizerConfiguration synchronizerConfiguration; // The number of peers we need to query to confirm our pivot block private final int peersToQuery; @@ -66,6 +68,7 @@ public class PivotBlockRetriever { final ProtocolSchedule protocolSchedule, final EthContext ethContext, final MetricsSystem metricsSystem, + final SynchronizerConfiguration synchronizerConfiguration, final long pivotBlockNumber, final int peersToQuery, final long pivotBlockNumberResetDelta, @@ -73,6 +76,7 @@ public class PivotBlockRetriever { this.protocolSchedule = protocolSchedule; this.ethContext = ethContext; this.metricsSystem = metricsSystem; + this.synchronizerConfiguration = synchronizerConfiguration; this.pivotBlockNumber = new AtomicLong(pivotBlockNumber); this.peersToQuery = peersToQuery; this.pivotBlockNumberResetDelta = pivotBlockNumberResetDelta; @@ -83,6 +87,7 @@ public PivotBlockRetriever( final ProtocolSchedule protocolSchedule, final EthContext ethContext, final MetricsSystem metricsSystem, + final SynchronizerConfiguration synchronizerConfiguration, final long pivotBlockNumber, final int peersToQuery, final long pivotBlockNumberResetDelta) { @@ -90,6 +95,7 @@ public PivotBlockRetriever( protocolSchedule, ethContext, metricsSystem, + synchronizerConfiguration, pivotBlockNumber, peersToQuery, pivotBlockNumberResetDelta, @@ -111,6 +117,7 @@ private void confirmBlock(final long blockNumber) { protocolSchedule, ethContext, metricsSystem, + synchronizerConfiguration, pivotBlockNumber.get(), peersToQuery, MAX_QUERY_RETRIES_PER_PEER); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java index 16f7e09d6d1..e917c56a6c1 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeers.java @@ -17,14 +17,13 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; -import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeersTask; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerLimiter; import org.hyperledger.besu.ethereum.eth.sync.TrailingPeerRequirements; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; -import org.hyperledger.besu.plugin.services.MetricsSystem; +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -38,17 +37,14 @@ public class PivotSelectorFromPeers implements PivotBlockSelector { protected final EthContext ethContext; protected final SynchronizerConfiguration syncConfig; private final SyncState syncState; - private final MetricsSystem metricsSystem; public PivotSelectorFromPeers( final EthContext ethContext, final SynchronizerConfiguration syncConfig, - final SyncState syncState, - final MetricsSystem metricsSystem) { + final SyncState syncState) { this.ethContext = ethContext; this.syncConfig = syncConfig; this.syncState = syncState; - this.metricsSystem = metricsSystem; } @Override @@ -58,15 +54,19 @@ public Optional selectNewPivotBlock() { @Override public CompletableFuture prepareRetry() { + final long estimatedPivotBlock = conservativelyEstimatedPivotBlock(); final TrailingPeerLimiter trailingPeerLimiter = new TrailingPeerLimiter( ethContext.getEthPeers(), () -> new TrailingPeerRequirements( - conservativelyEstimatedPivotBlock(), syncConfig.getMaxTrailingPeers())); + estimatedPivotBlock, syncConfig.getMaxTrailingPeers())); trailingPeerLimiter.enforceTrailingPeerLimit(); - return waitForPeers(syncConfig.getSyncMinimumPeerCount()); + return ethContext + .getEthPeers() + .waitForPeer((peer) -> peer.chainState().getEstimatedHeight() >= estimatedPivotBlock) + .thenRun(() -> {}); } @Override @@ -87,41 +87,24 @@ protected Optional fromBestPeer(final EthPeer peer) { } protected Optional selectBestPeer() { - return ethContext - .getEthPeers() - .bestPeerMatchingCriteria(this::canPeerDeterminePivotBlock) - // Only select a pivot block number when we have a minimum number of height estimates - .filter(unused -> enoughFastSyncPeersArePresent()); - } - - private boolean enoughFastSyncPeersArePresent() { - final long peerCount = countPeersThatCanDeterminePivotBlock(); + List peers = + ethContext + .getEthPeers() + .streamAvailablePeers() + .filter((peer) -> peer.chainState().hasEstimatedHeight() && peer.isFullyValidated()) + .toList(); + + // Only select a pivot block number when we have a minimum number of height estimates final int minPeerCount = syncConfig.getSyncMinimumPeerCount(); - if (peerCount < minPeerCount) { + if (peers.size() < minPeerCount) { LOG.info( "Waiting for valid peers with chain height information. {} / {} required peers currently available.", - peerCount, + peers.size(), minPeerCount); - return false; + return Optional.empty(); + } else { + return peers.stream().max(ethContext.getEthPeers().getBestPeerComparator()); } - return true; - } - - private long countPeersThatCanDeterminePivotBlock() { - return ethContext - .getEthPeers() - .streamAvailablePeers() - .filter(this::canPeerDeterminePivotBlock) - .count(); - } - - private boolean canPeerDeterminePivotBlock(final EthPeer peer) { - LOG.debug( - "peer {} hasEstimatedHeight {} isFullyValidated? {}", - peer.getLoggableId(), - peer.chainState().hasEstimatedHeight(), - peer.isFullyValidated()); - return peer.chainState().hasEstimatedHeight() && peer.isFullyValidated(); } private long conservativelyEstimatedPivotBlock() { @@ -129,10 +112,4 @@ private long conservativelyEstimatedPivotBlock() { syncState.getLocalChainHeight() + syncConfig.getSyncPivotDistance(); return Math.min(syncState.bestChainHeight(), estimatedNextPivot); } - - private CompletableFuture waitForPeers(final int count) { - final WaitForPeersTask waitForPeersTask = - WaitForPeersTask.create(ethContext, count, metricsSystem); - return waitForPeersTask.run(); - } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromSafeBlock.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromSafeBlock.java index c3bc9a5f903..f30fb54e22c 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromSafeBlock.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromSafeBlock.java @@ -20,12 +20,16 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeersTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByHashTask; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.plugin.services.MetricsSystem; +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; @@ -42,6 +46,7 @@ public class PivotSelectorFromSafeBlock implements PivotBlockSelector { private final EthContext ethContext; private final MetricsSystem metricsSystem; private final GenesisConfigOptions genesisConfig; + private final SynchronizerConfiguration synchronizerConfiguration; private final Supplier> forkchoiceStateSupplier; private final Runnable cleanupAction; @@ -55,6 +60,7 @@ public PivotSelectorFromSafeBlock( final EthContext ethContext, final MetricsSystem metricsSystem, final GenesisConfigOptions genesisConfig, + final SynchronizerConfiguration synchronizerConfiguration, final Supplier> forkchoiceStateSupplier, final Runnable cleanupAction) { this.protocolContext = protocolContext; @@ -62,6 +68,7 @@ public PivotSelectorFromSafeBlock( this.ethContext = ethContext; this.metricsSystem = metricsSystem; this.genesisConfig = genesisConfig; + this.synchronizerConfiguration = synchronizerConfiguration; this.forkchoiceStateSupplier = forkchoiceStateSupplier; this.cleanupAction = cleanupAction; } @@ -121,7 +128,9 @@ public long getBestChainHeight() { LOG.debug( "Downloading chain head block header by hash {}", headBlockHash); try { - return waitForPeers(1) + return ethContext + .getEthPeers() + .waitForPeer((peer) -> true) .thenCompose(unused -> downloadBlockHeader(headBlockHash)) .thenApply( blockHeader -> { @@ -142,26 +151,47 @@ public long getBestChainHeight() { } private CompletableFuture downloadBlockHeader(final Hash hash) { - return RetryingGetHeaderFromPeerByHashTask.byHash( - protocolSchedule, ethContext, hash, 0, metricsSystem) - .getHeader() - .whenComplete( - (blockHeader, throwable) -> { - if (throwable != null) { - LOG.debug("Error downloading block header by hash {}", hash); - } else { - LOG.atDebug() - .setMessage("Successfully downloaded pivot block header by hash {}") - .addArgument(blockHeader::toLogString) - .log(); - } - }); - } - - private CompletableFuture waitForPeers(final int count) { - - final WaitForPeersTask waitForPeersTask = - WaitForPeersTask.create(ethContext, count, metricsSystem); - return waitForPeersTask.run(); + CompletableFuture resultFuture; + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + resultFuture = + ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + hash, + 0, + 1, + 0, + GetHeadersFromPeerTask.Direction.FORWARD, + ethContext.getEthPeers().peerCount(), + protocolSchedule); + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().execute(task); + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + return CompletableFuture.failedFuture( + new RuntimeException("Unable to retrieve header")); + } + return CompletableFuture.completedFuture(taskResult.result().get().getFirst()); + }); + } else { + resultFuture = + RetryingGetHeaderFromPeerByHashTask.byHash( + protocolSchedule, ethContext, hash, 0, metricsSystem) + .getHeader(); + } + return resultFuture.whenComplete( + (blockHeader, throwable) -> { + if (throwable != null) { + LOG.debug("Error downloading block header by hash {}", hash); + } else { + LOG.atDebug() + .setMessage("Successfully downloaded pivot block header by hash {}") + .addArgument(blockHeader::toLogString) + .log(); + } + }); } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/SyncTargetManager.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/SyncTargetManager.java index c4ac358b806..16f996605eb 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/SyncTargetManager.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/SyncTargetManager.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.ethereum.eth.sync.fastsync; import static java.util.concurrent.CompletableFuture.completedFuture; -import static org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotBlockRetriever.MAX_QUERY_RETRIES_PER_PEER; import static org.hyperledger.besu.util.log.LogUtil.throttledLog; import org.hyperledger.besu.ethereum.ProtocolContext; @@ -23,6 +22,9 @@ import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.sync.AbstractSyncTargetManager; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByNumberTask; @@ -120,18 +122,51 @@ protected CompletableFuture> selectBestAvailableSyncTarget() { private CompletableFuture> confirmPivotBlockHeader(final EthPeer bestPeer) { final BlockHeader pivotBlockHeader = fastSyncState.getPivotBlockHeader().get(); - final RetryingGetHeaderFromPeerByNumberTask task = - RetryingGetHeaderFromPeerByNumberTask.forSingleNumber( - protocolSchedule, - ethContext, - metricsSystem, - pivotBlockHeader.getNumber(), - MAX_QUERY_RETRIES_PER_PEER); - task.assignPeer(bestPeer); - return ethContext - .getScheduler() - // Task is a retrying task. Make sure that the timeout is long enough to allow for retries. - .timeout(task, Duration.ofSeconds(MAX_QUERY_RETRIES_PER_PEER * SECONDS_PER_REQUEST + 2)) + CompletableFuture> headersFuture; + if (config.isPeerTaskSystemEnabled()) { + headersFuture = + ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + pivotBlockHeader.getNumber(), + 1, + 0, + GetHeadersFromPeerTask.Direction.FORWARD, + PivotBlockRetriever.MAX_QUERY_RETRIES_PER_PEER, + protocolSchedule); + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().executeAgainstPeer(task, bestPeer); + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + return CompletableFuture.failedFuture( + new RuntimeException("Unable to retrieve requested header from peer")); + } + return CompletableFuture.completedFuture(taskResult.result().get()); + }); + + } else { + final RetryingGetHeaderFromPeerByNumberTask task = + RetryingGetHeaderFromPeerByNumberTask.forSingleNumber( + protocolSchedule, + ethContext, + metricsSystem, + pivotBlockHeader.getNumber(), + PivotBlockRetriever.MAX_QUERY_RETRIES_PER_PEER); + task.assignPeer(bestPeer); + headersFuture = + ethContext + .getScheduler() + // Task is a retrying task. Make sure that the timeout is long enough to allow for + // retries. + .timeout( + task, + Duration.ofSeconds( + PivotBlockRetriever.MAX_QUERY_RETRIES_PER_PEER * SECONDS_PER_REQUEST + 2)); + } + return headersFuture .thenCompose( result -> { if (peerHasDifferentPivotBlock(result)) { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastDownloaderFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastDownloaderFactory.java index 1d775cc80fd..8b71a57885d 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastDownloaderFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastDownloaderFactory.java @@ -17,7 +17,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -60,7 +59,6 @@ public static Optional> create( final ProtocolContext protocolContext, final MetricsSystem metricsSystem, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final WorldStateStorageCoordinator worldStateStorageCoordinator, final SyncState syncState, final Clock clock, @@ -128,7 +126,6 @@ public static Optional> create( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, pivotBlockSelector, metricsSystem), diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloadPipelineFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloadPipelineFactory.java index b822236b8f0..570ef303779 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloadPipelineFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloadPipelineFactory.java @@ -99,6 +99,7 @@ public Pipeline createDownloadPipelineForSyncTarget(final SyncTarget target) protocolContext, ethContext, detachedValidationPolicy, + syncConfig, headerRequestSize, metricsSystem); final RangeHeadersValidationStep validateHeadersJoinUpStep = diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/range/RangeHeadersFetcher.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/range/RangeHeadersFetcher.java index e73c5aa9f5f..cf5e6025182 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/range/RangeHeadersFetcher.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/range/RangeHeadersFetcher.java @@ -21,6 +21,10 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask.Direction; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask.PeerTaskResult; import org.hyperledger.besu.ethereum.eth.manager.task.GetHeadersFromPeerByHashTask; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -116,31 +120,64 @@ private CompletableFuture> requestHeaders( .addArgument(referenceHeader.getNumber()) .addArgument(skip) .log(); - return GetHeadersFromPeerByHashTask.startingAtHash( - protocolSchedule, - ethContext, - referenceHeader.getHash(), - referenceHeader.getNumber(), - // + 1 because lastHeader will be returned as well. - headerCount + 1, - skip, - metricsSystem) - .assignPeer(peer) - .run() - .thenApply(PeerTaskResult::getResult) - .thenApply( - headers -> { - if (headers.size() < headerCount) { - LOG.atTrace() - .setMessage( - "Peer {} returned fewer headers than requested. Expected: {}, Actual: {}") - .addArgument(peer) - .addArgument(headerCount) - .addArgument(headers.size()) - .log(); - } - return stripExistingRangeHeaders(referenceHeader, headers); - }); + CompletableFuture> headersFuture; + if (syncConfig.isPeerTaskSystemEnabled()) { + headersFuture = + ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + referenceHeader.getHash(), + referenceHeader.getNumber(), + // + 1 because lastHeader will be returned as well. + headerCount + 1, + skip, + Direction.FORWARD, + protocolSchedule); + PeerTaskExecutorResult> taskResult = + ethContext.getPeerTaskExecutor().executeAgainstPeer(task, peer); + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + LOG.warn( + "Unsuccessfully used peer task system to fetch headers. Response code was {}", + taskResult.responseCode()); + return CompletableFuture.failedFuture( + new RuntimeException( + "Unable to retrieve headers. Response code was " + + taskResult.responseCode())); + } + return CompletableFuture.completedFuture(taskResult.result().get()); + }); + } else { + headersFuture = + GetHeadersFromPeerByHashTask.startingAtHash( + protocolSchedule, + ethContext, + referenceHeader.getHash(), + referenceHeader.getNumber(), + // + 1 because lastHeader will be returned as well. + headerCount + 1, + skip, + metricsSystem) + .assignPeer(peer) + .run() + .thenApply(PeerTaskResult::getResult); + } + return headersFuture.thenApply( + headers -> { + if (headers.size() < headerCount) { + LOG.atTrace() + .setMessage( + "Peer {} returned fewer headers than requested. Expected: {}, Actual: {}") + .addArgument(peer) + .addArgument(headerCount) + .addArgument(headers.size()) + .log(); + } + return stripExistingRangeHeaders(referenceHeader, headers); + }); } private List stripExistingRangeHeaders( diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapDownloaderFactory.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapDownloaderFactory.java index 6c5ce0b04e9..5de8ceb9843 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapDownloaderFactory.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapDownloaderFactory.java @@ -17,7 +17,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -58,7 +57,6 @@ public static Optional> createSnapDownloader( final ProtocolContext protocolContext, final MetricsSystem metricsSystem, final EthContext ethContext, - final PeerTaskExecutor peerTaskExecutor, final WorldStateStorageCoordinator worldStateStorageCoordinator, final SyncState syncState, final Clock clock, @@ -123,7 +121,6 @@ public static Optional> createSnapDownloader( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, pivotBlockSelector, metricsSystem), diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTask.java index 91aa6e5ff8d..2f622e4470e 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTask.java @@ -18,9 +18,15 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.exceptions.PeerDisconnectedException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask.Direction; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractEthTask; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.GetHeadersFromPeerByNumberTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.util.BlockchainUtil; import org.hyperledger.besu.plugin.services.MetricsSystem; @@ -46,6 +52,7 @@ public class DetermineCommonAncestorTask extends AbstractEthTask { private final ProtocolContext protocolContext; private final EthPeer peer; private final int headerRequestSize; + private final SynchronizerConfiguration synchronizerConfiguration; private final MetricsSystem metricsSystem; private long maximumPossibleCommonAncestorNumber; @@ -59,6 +66,7 @@ private DetermineCommonAncestorTask( final EthContext ethContext, final EthPeer peer, final int headerRequestSize, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem) { super(metricsSystem); this.protocolSchedule = protocolSchedule; @@ -66,6 +74,7 @@ private DetermineCommonAncestorTask( this.protocolContext = protocolContext; this.peer = peer; this.headerRequestSize = headerRequestSize; + this.synchronizerConfiguration = synchronizerConfiguration; this.metricsSystem = metricsSystem; maximumPossibleCommonAncestorNumber = @@ -83,9 +92,16 @@ public static DetermineCommonAncestorTask create( final EthContext ethContext, final EthPeer peer, final int headerRequestSize, + final SynchronizerConfiguration synchronizerConfiguration, final MetricsSystem metricsSystem) { return new DetermineCommonAncestorTask( - protocolSchedule, protocolContext, ethContext, peer, headerRequestSize, metricsSystem); + protocolSchedule, + protocolContext, + ethContext, + peer, + headerRequestSize, + synchronizerConfiguration, + metricsSystem); } @Override @@ -100,16 +116,50 @@ protected void executeTask() { result.completeExceptionally(new IllegalStateException("No common ancestor.")); return; } - requestHeaders() - .thenCompose(this::processHeaders) - .whenComplete( - (peerResult, error) -> { - if (error != null) { - result.completeExceptionally(error); - } else if (!result.isDone()) { - executeTaskTimed(); - } - }); + + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + do { + PeerTaskExecutorResult> taskResult = + requestHeadersUsingPeerTaskSystem(); + if (taskResult.responseCode() == PeerTaskExecutorResponseCode.PEER_DISCONNECTED) { + result.completeExceptionally(new PeerDisconnectedException(peer)); + continue; + } else if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + result.completeExceptionally( + new RuntimeException( + "Peer failed to successfully return requested block headers")); + continue; + } + taskResult.ethPeer().ifPresent((peer) -> taskResult.result().get().getFirst()); + processHeaders(taskResult.result().get()); + if (maximumPossibleCommonAncestorNumber == minimumPossibleCommonAncestorNumber) { + // Bingo, we found our common ancestor. + result.complete(commonAncestorCandidate); + } else if (maximumPossibleCommonAncestorNumber < BlockHeader.GENESIS_BLOCK_NUMBER + && !result.isDone()) { + result.completeExceptionally(new IllegalStateException("No common ancestor.")); + } + } while (!result.isDone()); + }); + + } else { + requestHeaders() + .thenApply(AbstractPeerTask.PeerTaskResult::getResult) + .thenCompose(this::processHeaders) + .whenComplete( + (peerResult, error) -> { + if (error != null) { + result.completeExceptionally(error); + } else if (!result.isDone()) { + executeTaskTimed(); + } + }); + } } @VisibleForTesting @@ -136,6 +186,26 @@ CompletableFuture>> requestHea .run()); } + PeerTaskExecutorResult> requestHeadersUsingPeerTaskSystem() { + final long range = maximumPossibleCommonAncestorNumber - minimumPossibleCommonAncestorNumber; + final int skipInterval = initialQuery ? 0 : calculateSkipInterval(range, headerRequestSize); + final int count = + initialQuery ? headerRequestSize : calculateCount((double) range, skipInterval); + LOG.debug( + "Searching for common ancestor with {} between {} and {}", + peer, + minimumPossibleCommonAncestorNumber, + maximumPossibleCommonAncestorNumber); + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + maximumPossibleCommonAncestorNumber, + count, + skipInterval, + Direction.REVERSE, + protocolSchedule); + return ethContext.getPeerTaskExecutor().executeAgainstPeer(task, peer); + } + /** * In the case where the remote chain contains 100 blocks, the initial count work out to 11, and * the skip interval would be 9. This would yield the headers (0, 10, 20, 30, 40, 50, 60, 70, 80, @@ -151,10 +221,8 @@ static int calculateCount(final double range, final int skipInterval) { return Math.toIntExact((long) Math.ceil(range / (skipInterval + 1)) + 1); } - private CompletableFuture processHeaders( - final AbstractPeerTask.PeerTaskResult> headersResult) { + private CompletableFuture processHeaders(final List headers) { initialQuery = false; - final List headers = headersResult.getResult(); if (headers.isEmpty()) { // Nothing to do return CompletableFuture.completedFuture(null); diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTask.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTask.java index 8ca376902e4..5eee6495ebd 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTask.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTask.java @@ -25,11 +25,15 @@ import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractGetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask.PeerTaskResult; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractRetryingPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.GetBodiesFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.GetHeadersFromPeerByHashTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.ValidationPolicy; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; @@ -61,6 +65,7 @@ public class DownloadHeaderSequenceTask extends AbstractRetryingPeerTask> executePeerTask( final Optional assignedPeer) { LOG.debug( "Downloading headers from {} to {}.", startingBlockNumber, referenceHeader.getNumber()); - final CompletableFuture> task = - downloadHeaders(assignedPeer).thenCompose(this::processHeaders); - return task.whenComplete( + final CompletableFuture> headersFuture; + if (synchronizerConfiguration.isPeerTaskSystemEnabled()) { + headersFuture = + downloadHeadersUsingPeerTaskSystem(assignedPeer) + .thenCompose(this::processHeadersUsingPeerTask); + } else { + headersFuture = downloadHeaders(assignedPeer).thenCompose(this::processHeaders); + } + return headersFuture.whenComplete( (r, t) -> { // We're done if we've filled all requested headers if (lastFilledHeaderIndex == 0) { @@ -179,73 +196,127 @@ private CompletableFuture>> downloadHeaders( }); } + private CompletableFuture>> + downloadHeadersUsingPeerTaskSystem(final Optional ethPeer) { + return ethContext + .getScheduler() + .scheduleServiceTask( + () -> { + // Figure out parameters for our headers request + final boolean partiallyFilled = lastFilledHeaderIndex < segmentLength; + final BlockHeader referenceHeaderForNextRequest = + partiallyFilled ? headers[lastFilledHeaderIndex] : referenceHeader; + final Hash referenceHash = referenceHeaderForNextRequest.getHash(); + final int count = partiallyFilled ? lastFilledHeaderIndex : segmentLength; + + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + referenceHash, + referenceHeaderForNextRequest.getNumber(), + count + 1, + 0, + GetHeadersFromPeerTask.Direction.REVERSE, + protocolSchedule); + PeerTaskExecutorResult> taskResult; + if (ethPeer.isPresent()) { + taskResult = + ethContext.getPeerTaskExecutor().executeAgainstPeer(task, ethPeer.get()); + } else { + taskResult = ethContext.getPeerTaskExecutor().execute(task); + } + + if (taskResult.responseCode() != PeerTaskExecutorResponseCode.SUCCESS + || taskResult.result().isEmpty()) { + return CompletableFuture.failedFuture( + new RuntimeException( + "Failed to download headers. Response code was " + + taskResult.responseCode())); + } + return CompletableFuture.completedFuture(taskResult); + }); + } + @VisibleForTesting CompletableFuture> processHeaders( final PeerTaskResult> headersResult) { return executeWorkerSubTask( ethContext.getScheduler(), () -> { - final CompletableFuture> future = new CompletableFuture<>(); - BlockHeader child = null; - boolean firstSkipped = false; - final int previousHeaderIndex = lastFilledHeaderIndex; - for (final BlockHeader header : headersResult.getResult()) { - final int headerIndex = - Ints.checkedCast( - segmentLength - (referenceHeader.getNumber() - header.getNumber())); - if (!firstSkipped) { - // Skip over reference header - firstSkipped = true; - continue; - } - if (child == null) { - child = - (headerIndex == segmentLength - 1) ? referenceHeader : headers[headerIndex + 1]; - } + return processHeaders(headersResult.getResult(), headersResult.getPeer()); + }); + } - final boolean foundChild = child != null; - final boolean headerInRange = checkHeaderInRange(header); - final boolean headerInvalid = foundChild && !validateHeader(child, header); - if (!headerInRange || !foundChild || headerInvalid) { - final BlockHeader invalidHeader = child; - final CompletableFuture badBlockHandled = - headerInvalid - ? markBadBlock(invalidHeader, headersResult.getPeer()) - : CompletableFuture.completedFuture(null); - badBlockHandled.whenComplete( - (res, err) -> { - LOG.debug( - "Received invalid headers from peer (BREACH_OF_PROTOCOL), disconnecting from: {}", - headersResult.getPeer()); - headersResult - .getPeer() - .disconnect(DisconnectReason.BREACH_OF_PROTOCOL_INVALID_HEADERS); - final InvalidBlockException exception; - if (invalidHeader == null) { - final String msg = - String.format( - "Received misordered blocks. Missing child of %s", - header.toLogString()); - exception = InvalidBlockException.create(msg); - } else { - final String errorMsg = - headerInvalid - ? "Header failed validation" - : "Out-of-range header received from peer"; - exception = InvalidBlockException.fromInvalidBlock(errorMsg, invalidHeader); - } - future.completeExceptionally(exception); - }); + private CompletableFuture> processHeadersUsingPeerTask( + final PeerTaskExecutorResult> headersResult) { + final List blockHeaders = + headersResult + .result() + .orElseThrow( + () -> new RuntimeException("Expected blockHeaders in PeerTaskExecutorResult")); + final EthPeer ethPeer = + headersResult + .ethPeer() + .orElseThrow(() -> new RuntimeException("Expected a peer in PeerTaskExecutorResult")); + return processHeaders(blockHeaders, ethPeer); + } - return future; - } - headers[headerIndex] = header; - lastFilledHeaderIndex = headerIndex; - child = header; - } - future.complete(asList(headers).subList(lastFilledHeaderIndex, previousHeaderIndex)); - return future; - }); + private CompletableFuture> processHeaders( + final List blockHeaders, final EthPeer ethPeer) { + final CompletableFuture> future = new CompletableFuture<>(); + BlockHeader child = null; + boolean firstSkipped = false; + final int previousHeaderIndex = lastFilledHeaderIndex; + for (final BlockHeader header : blockHeaders) { + final int headerIndex = + Ints.checkedCast(segmentLength - (referenceHeader.getNumber() - header.getNumber())); + if (!firstSkipped) { + // Skip over reference header + firstSkipped = true; + continue; + } + if (child == null) { + child = (headerIndex == segmentLength - 1) ? referenceHeader : headers[headerIndex + 1]; + } + + final boolean foundChild = child != null; + final boolean headerInRange = checkHeaderInRange(header); + final boolean headerInvalid = foundChild && !validateHeader(child, header); + if (!headerInRange || !foundChild || headerInvalid) { + final BlockHeader invalidHeader = child; + final CompletableFuture badBlockHandled = + headerInvalid + ? markBadBlock(invalidHeader, ethPeer) + : CompletableFuture.completedFuture(null); + badBlockHandled.whenComplete( + (res, err) -> { + LOG.debug( + "Received invalid headers from peer (BREACH_OF_PROTOCOL), disconnecting from: {}", + ethPeer); + ethPeer.disconnect(DisconnectReason.BREACH_OF_PROTOCOL_INVALID_HEADERS); + final InvalidBlockException exception; + if (invalidHeader == null) { + final String msg = + String.format( + "Received misordered blocks. Missing child of %s", header.toLogString()); + exception = InvalidBlockException.create(msg); + } else { + final String errorMsg = + headerInvalid + ? "Header failed validation" + : "Out-of-range header received from peer"; + exception = InvalidBlockException.fromInvalidBlock(errorMsg, invalidHeader); + } + future.completeExceptionally(exception); + }); + + return future; + } + headers[headerIndex] = header; + lastFilledHeaderIndex = headerIndex; + child = header; + } + future.complete(asList(headers).subList(lastFilledHeaderIndex, previousHeaderIndex)); + return future; } private CompletableFuture markBadBlock(final BlockHeader badHeader, final EthPeer badPeer) { diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java index 91b4efd7b21..e6a84f69fa4 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransaction.java @@ -14,6 +14,24 @@ */ package org.hyperledger.besu.ethereum.eth.transactions; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.ACCESS_LIST_ENTRY_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.ACCESS_LIST_STORAGE_KEY_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOBS_WITH_COMMITMENTS_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOB_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.CODE_DELEGATION_ENTRY_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.EIP1559_AND_EIP4844_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.KZG_COMMITMENT_OR_PROOF_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_ACCESS_LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_CHAIN_ID_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_CODE_DELEGATION_LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_TO_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.PAYLOAD_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.PENDING_TRANSACTION_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.VERSIONED_HASH_SIZE; + import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; @@ -31,21 +49,6 @@ public abstract class PendingTransaction implements org.hyperledger.besu.datatypes.PendingTransaction { static final int NOT_INITIALIZED = -1; - static final int FRONTIER_AND_ACCESS_LIST_SHALLOW_MEMORY_SIZE = 904; - static final int EIP1559_AND_EIP4844_SHALLOW_MEMORY_SIZE = 1016; - static final int OPTIONAL_TO_MEMORY_SIZE = 112; - static final int OPTIONAL_CHAIN_ID_MEMORY_SIZE = 80; - static final int PAYLOAD_BASE_MEMORY_SIZE = 32; - static final int ACCESS_LIST_STORAGE_KEY_MEMORY_SIZE = 32; - static final int ACCESS_LIST_ENTRY_BASE_MEMORY_SIZE = 248; - static final int OPTIONAL_ACCESS_LIST_MEMORY_SIZE = 24; - static final int VERSIONED_HASH_SIZE = 96; - static final int BASE_LIST_SIZE = 48; - static final int BASE_OPTIONAL_SIZE = 16; - static final int KZG_COMMITMENT_OR_PROOF_SIZE = 112; - static final int BLOB_SIZE = 131136; - static final int BLOBS_WITH_COMMITMENTS_SIZE = 40; - static final int PENDING_TRANSACTION_MEMORY_SIZE = 40; private static final AtomicLong TRANSACTIONS_ADDED = new AtomicLong(); private final Transaction transaction; private final long addedAt; @@ -147,20 +150,20 @@ private int computeMemorySize() { case ACCESS_LIST -> computeAccessListMemorySize(); case EIP1559 -> computeEIP1559MemorySize(); case BLOB -> computeBlobMemorySize(); - case DELEGATE_CODE -> computeSetCodeMemorySize(); + case DELEGATE_CODE -> computeDelegateCodeMemorySize(); } - + PENDING_TRANSACTION_MEMORY_SIZE; + + PENDING_TRANSACTION_SHALLOW_SIZE; } private int computeFrontierMemorySize() { - return FRONTIER_AND_ACCESS_LIST_SHALLOW_MEMORY_SIZE + return FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE + computePayloadMemorySize() + computeToMemorySize() + computeChainIdMemorySize(); } private int computeAccessListMemorySize() { - return FRONTIER_AND_ACCESS_LIST_SHALLOW_MEMORY_SIZE + return FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE + computePayloadMemorySize() + computeToMemorySize() + computeChainIdMemorySize() @@ -168,7 +171,7 @@ private int computeAccessListMemorySize() { } private int computeEIP1559MemorySize() { - return EIP1559_AND_EIP4844_SHALLOW_MEMORY_SIZE + return EIP1559_AND_EIP4844_SHALLOW_SIZE + computePayloadMemorySize() + computeToMemorySize() + computeChainIdMemorySize() @@ -177,41 +180,41 @@ private int computeEIP1559MemorySize() { private int computeBlobMemorySize() { return computeEIP1559MemorySize() - + BASE_OPTIONAL_SIZE // for the versionedHashes field + + OPTIONAL_SHALLOW_SIZE // for the versionedHashes field + computeBlobWithCommitmentsMemorySize(); } - private int computeSetCodeMemorySize() { - return 0; + private int computeDelegateCodeMemorySize() { + return computeEIP1559MemorySize() + computeCodeDelegationListMemorySize(); } private int computeBlobWithCommitmentsMemorySize() { final int blobCount = transaction.getBlobCount(); - return BASE_OPTIONAL_SIZE + return OPTIONAL_SHALLOW_SIZE + BLOBS_WITH_COMMITMENTS_SIZE - + (BASE_LIST_SIZE * 4) + + (LIST_SHALLOW_SIZE * 4) + (KZG_COMMITMENT_OR_PROOF_SIZE * blobCount * 2) + (VERSIONED_HASH_SIZE * blobCount) + (BLOB_SIZE * blobCount); } private int computePayloadMemorySize() { - return transaction.getPayload().size() > 0 - ? PAYLOAD_BASE_MEMORY_SIZE + transaction.getPayload().size() + return !transaction.getPayload().isEmpty() + ? PAYLOAD_SHALLOW_SIZE + transaction.getPayload().size() : 0; } private int computeToMemorySize() { if (transaction.getTo().isPresent()) { - return OPTIONAL_TO_MEMORY_SIZE; + return OPTIONAL_TO_SIZE; } return 0; } private int computeChainIdMemorySize() { if (transaction.getChainId().isPresent()) { - return OPTIONAL_CHAIN_ID_MEMORY_SIZE; + return OPTIONAL_CHAIN_ID_SIZE; } return 0; } @@ -221,11 +224,23 @@ private int computeAccessListEntriesMemorySize() { .getAccessList() .map( al -> { - int totalSize = OPTIONAL_ACCESS_LIST_MEMORY_SIZE; - totalSize += al.size() * ACCESS_LIST_ENTRY_BASE_MEMORY_SIZE; + int totalSize = OPTIONAL_ACCESS_LIST_SHALLOW_SIZE; + totalSize += al.size() * ACCESS_LIST_ENTRY_SHALLOW_SIZE; totalSize += al.stream().map(AccessListEntry::storageKeys).mapToInt(List::size).sum() - * ACCESS_LIST_STORAGE_KEY_MEMORY_SIZE; + * ACCESS_LIST_STORAGE_KEY_SIZE; + return totalSize; + }) + .orElse(0); + } + + private int computeCodeDelegationListMemorySize() { + return transaction + .getCodeDelegationList() + .map( + cd -> { + int totalSize = OPTIONAL_CODE_DELEGATION_LIST_SHALLOW_SIZE; + totalSize += cd.size() * CODE_DELEGATION_ENTRY_SIZE; return totalSize; }) .orElse(0); @@ -252,7 +267,7 @@ public boolean equals(final Object o) { @Override public int hashCode() { - return 31 * (int) (sequence ^ (sequence >>> 32)); + return 31 * Long.hashCode(sequence); } @Override @@ -399,4 +414,29 @@ public boolean hasPriority() { } } } + + /** + * The memory size of an object is calculated using the PendingTransactionEstimatedMemorySizeTest + * look there for the details of the calculation and to adapt the code when any of the related + * class changes its structure. + */ + public interface MemorySize { + int FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE = 904; + int EIP1559_AND_EIP4844_SHALLOW_SIZE = 1016; + int OPTIONAL_TO_SIZE = 112; + int OPTIONAL_CHAIN_ID_SIZE = 80; + int PAYLOAD_SHALLOW_SIZE = 32; + int ACCESS_LIST_STORAGE_KEY_SIZE = 32; + int ACCESS_LIST_ENTRY_SHALLOW_SIZE = 248; + int OPTIONAL_ACCESS_LIST_SHALLOW_SIZE = 40; + int OPTIONAL_CODE_DELEGATION_LIST_SHALLOW_SIZE = 40; + int CODE_DELEGATION_ENTRY_SIZE = 472; + int VERSIONED_HASH_SIZE = 96; + int LIST_SHALLOW_SIZE = 48; + int OPTIONAL_SHALLOW_SIZE = 16; + int KZG_COMMITMENT_OR_PROOF_SIZE = 112; + int BLOB_SIZE = 131136; + int BLOBS_WITH_COMMITMENTS_SIZE = 40; + int PENDING_TRANSACTION_SHALLOW_SIZE = 40; + } } diff --git a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java index 3acf49894a3..1adc5977bb6 100644 --- a/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java +++ b/ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPool.java @@ -54,11 +54,11 @@ import java.io.IOException; import java.math.BigInteger; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; -import java.util.IntSummaryStatistics; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -73,6 +73,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -645,15 +646,16 @@ public CompletableFuture setDisabled() { isPoolEnabled.set(false); subscribeConnectId.ifPresent(ethContext.getEthPeers()::unsubscribeConnect); pendingTransactionsListenersProxy.unsubscribe(); - final PendingTransactions pendingTransactionsToSave = pendingTransactions; + final CompletableFuture saveOperation = + saveRestoreManager + .saveToDisk(pendingTransactions) + .exceptionally( + t -> { + LOG.error("Error while saving transaction pool to disk", t); + return null; + }); pendingTransactions = new DisabledPendingTransactions(); - return saveRestoreManager - .saveToDisk(pendingTransactionsToSave) - .exceptionally( - t -> { - LOG.error("Error while saving transaction pool to disk", t); - return null; - }); + return saveOperation; } return CompletableFuture.completedFuture(null); } @@ -750,6 +752,7 @@ class SaveRestoreManager { private final AtomicBoolean isCancelled = new AtomicBoolean(false); CompletableFuture saveToDisk(final PendingTransactions pendingTransactionsToSave) { + cancelInProgressReadOperation(); return serializeAndDedupOperation( () -> executeSaveToDisk(pendingTransactionsToSave), writeInProgress); } @@ -758,20 +761,31 @@ CompletableFuture loadFromDisk() { return serializeAndDedupOperation(this::executeLoadFromDisk, readInProgress); } + private void cancelInProgressReadOperation() { + if (!readInProgress.get().isDone()) { + LOG.debug("Cancelling in progress read operation"); + isCancelled.set(true); + try { + waitUntilReadOperationIsCancelled(); + LOG.debug("In progress read operation cancelled"); + } catch (InterruptedException | ExecutionException e) { + LOG.warn("Error while cancelling in progress read operation", e); + throw new RuntimeException(e); + } + } + } + + private void waitUntilReadOperationIsCancelled() + throws InterruptedException, ExecutionException { + readInProgress.get().get(); + } + private CompletableFuture serializeAndDedupOperation( final Runnable operation, final AtomicReference> operationInProgress) { if (configuration.getEnableSaveRestore()) { try { if (diskAccessLock.tryAcquire(1, TimeUnit.MINUTES)) { - if (!operationInProgress.get().isDone()) { - isCancelled.set(true); - try { - operationInProgress.get().get(); - } catch (ExecutionException ee) { - // nothing to do - } - } isCancelled.set(false); operationInProgress.set( @@ -791,12 +805,17 @@ private CompletableFuture serializeAndDedupOperation( private void executeSaveToDisk(final PendingTransactions pendingTransactionsToSave) { final File saveFile = configuration.getSaveFile(); + final boolean appending = saveFile.exists(); try (final BufferedWriter bw = - new BufferedWriter(new FileWriter(saveFile, StandardCharsets.US_ASCII))) { + new BufferedWriter(new FileWriter(saveFile, StandardCharsets.US_ASCII, appending))) { final var allTxs = pendingTransactionsToSave.getPendingTransactions(); - LOG.info("Saving {} transactions to file {}", allTxs.size(), saveFile); + LOG.info( + "{} {} transactions to file {}", + appending ? "Appending" : "Saving", + allTxs.size(), + saveFile); - final long savedTxs = + final long processedTxCount = allTxs.parallelStream() .takeWhile(unused -> !isCancelled.get()) .map( @@ -819,13 +838,19 @@ private void executeSaveToDisk(final PendingTransactions pendingTransactionsToSa return 1; }) .sum(); + if (isCancelled.get()) { LOG.info( - "Saved {} transactions to file {}, before operation was cancelled", - savedTxs, + "{} {} transactions to file {}, before operation was cancelled", + appending ? "Appended" : "Saved", + processedTxCount, saveFile); } else { - LOG.info("Saved {} transactions to file {}", savedTxs, saveFile); + LOG.info( + "{} {} transactions to file {}", + appending ? "Appended" : "Saved", + processedTxCount, + saveFile); } } catch (IOException e) { LOG.error("Error while saving txpool content to disk", e); @@ -839,10 +864,10 @@ private void executeLoadFromDisk() { LOG.info("Loading transaction pool content from file {}", saveFile); try (final BufferedReader br = new BufferedReader(new FileReader(saveFile, StandardCharsets.US_ASCII))) { - final IntSummaryStatistics stats = + final Map stats = br.lines() .takeWhile(unused -> !isCancelled.get()) - .mapToInt( + .map( line -> { final boolean isLocal = line.charAt(0) == 'l'; final Transaction tx = @@ -850,30 +875,66 @@ private void executeLoadFromDisk() { final ValidationResult result = addTransaction(tx, isLocal); - - return result.isValid() ? 1 : 0; + return result.isValid() ? "OK" : result.getInvalidReason().name(); }) - .summaryStatistics(); + .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + + br.close(); + + final var added = stats.getOrDefault("OK", 0L); + final var processedLines = stats.values().stream().mapToLong(Long::longValue).sum(); + + LOG.debug("Restored transactions stats {}", stats); if (isCancelled.get()) { LOG.info( "Added {} transactions of {} loaded from file {}, before operation was cancelled", - stats.getSum(), - stats.getCount(), + added, + processedLines, saveFile); + removeProcessedLines(saveFile, processedLines); } else { LOG.info( - "Added {} transactions of {} loaded from file {}", - stats.getSum(), - stats.getCount(), + "Added {} transactions of {} loaded from file {}, deleting file", + added, + processedLines, saveFile); + saveFile.delete(); } } catch (IOException e) { LOG.error("Error while saving txpool content to disk", e); } } - saveFile.delete(); } } + + private void removeProcessedLines(final File saveFile, final long processedLines) + throws IOException { + + LOG.debug("Removing processed lines from save file"); + + final var tmp = File.createTempFile(saveFile.getName(), ".tmp"); + + try (final BufferedReader reader = + Files.newBufferedReader(saveFile.toPath(), StandardCharsets.US_ASCII); + final BufferedWriter writer = + Files.newBufferedWriter(tmp.toPath(), StandardCharsets.US_ASCII)) { + reader + .lines() + .skip(processedLines) + .forEach( + line -> { + try { + writer.write(line); + writer.newLine(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + + saveFile.delete(); + Files.move(tmp.toPath(), saveFile.toPath()); + } } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeerTest.java index 99de00e6003..b5495e7636f 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeerTest.java @@ -477,7 +477,6 @@ private EthPeer createPeerWithPeerInfo(final Bytes nodeId) { final Consumer onPeerReady = (peer) -> {}; return new EthPeer( peerConnection, - "foo", onPeerReady, Collections.emptyList(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, @@ -513,7 +512,6 @@ private EthPeer createPeer( // that extend the sub-protocol work correctly return new EthPeer( peerConnection, - "foo", onPeerReady, peerValidators, EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeersTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeersTest.java index f6c635aa51f..2cd50269043 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeersTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthPeersTest.java @@ -58,7 +58,7 @@ public class EthPeersTest { @BeforeEach public void setup() throws Exception { when(peerRequest.sendRequest(any())).thenReturn(responseStream); - ethProtocolManager = EthProtocolManagerTestUtil.create(); + ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); ethPeers = ethProtocolManager.ethContext().getEthPeers(); final ChainHeadTracker mock = mock(ChainHeadTracker.class); final BlockHeader blockHeader = mock(BlockHeader.class); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java index b7c346af693..52fcf322c52 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTest.java @@ -77,6 +77,7 @@ import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; import org.hyperledger.besu.testutil.TestClock; import java.math.BigInteger; @@ -132,13 +133,14 @@ public static void setup() { @Test public void handleMalformedRequestIdMessage() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // this is a non-request id message, but we'll be processing it with eth66, make sure we // disconnect the peer gracefully final MessageData messageData = GetBlockHeadersMessage.create(1, 1, 0, false); @@ -151,13 +153,14 @@ public void handleMalformedRequestIdMessage() { @Test public void disconnectOnUnsolicitedMessage() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = setupPeer(ethManager, (cap, msg, conn) -> {}); @@ -169,13 +172,14 @@ public void disconnectOnUnsolicitedMessage() { @Test public void disconnectOnFailureToSendStatusMessage() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = @@ -188,13 +192,14 @@ public void disconnectOnFailureToSendStatusMessage() { @Test public void disconnectOnWrongChainId() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = @@ -219,13 +224,14 @@ public void disconnectOnWrongChainId() { public void disconnectNewPoWPeers() { final MergePeerFilter mergePeerFilter = new MergePeerFilter(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig(), - Optional.of(mergePeerFilter))) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setMergePeerFilter(Optional.of(mergePeerFilter)) + .build()) { final MockPeerConnection workPeer = setupPeer(ethManager, (cap, msg, conn) -> {}); final MockPeerConnection stakePeer = setupPeer(ethManager, (cap, msg, conn) -> {}); @@ -267,13 +273,14 @@ public void disconnectNewPoWPeers() { @Test public void doNotDisconnectOnLargeMessageWithinLimits() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final MessageData messageData = mock(MessageData.class); when(messageData.getSize()).thenReturn(EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE); when(messageData.getCode()).thenReturn(EthPV62.TRANSACTIONS); @@ -287,13 +294,14 @@ public void doNotDisconnectOnLargeMessageWithinLimits() { @Test public void disconnectOnWrongGenesisHash() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final MessageData messageData = BlockHeadersMessage.create(Collections.singletonList(blockchain.getBlockHeader(1).get())); final MockPeerConnection peer = @@ -317,13 +325,14 @@ public void disconnectOnWrongGenesisHash() { @Test public void doNotDisconnectOnValidMessage() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final MessageData messageData = GetBlockBodiesMessage.create(Collections.singletonList(gen.hash())); final MockPeerConnection peer = setupPeer(ethManager, (cap, msg, conn) -> {}); @@ -339,13 +348,14 @@ public void doNotDisconnectOnValidMessage() { public void respondToGetHeaders() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long startBlock = 5L; final int blockCount = 5; final MessageData messageData = @@ -379,13 +389,14 @@ public void respondToGetHeadersWithinLimits() throws ExecutionException, Interru final EthProtocolConfiguration config = EthProtocolConfiguration.builder().maxGetBlockHeaders(limit).build(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - config)) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(config) + .build()) { final long startBlock = 5L; final int blockCount = 10; final MessageData messageData = @@ -416,13 +427,14 @@ public void respondToGetHeadersWithinLimits() throws ExecutionException, Interru public void respondToGetHeadersReversed() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long endBlock = 10L; final int blockCount = 5; @@ -453,13 +465,14 @@ public void respondToGetHeadersReversed() throws ExecutionException, Interrupted public void respondToGetHeadersWithSkip() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long startBlock = 5L; final int blockCount = 5; @@ -493,13 +506,14 @@ public void respondToGetHeadersReversedWithSkip() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long endBlock = 10L; final int blockCount = 5; @@ -557,13 +571,14 @@ private MockPeerConnection setupPeerWithoutStatusExchange( public void respondToGetHeadersPartial() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long startBlock = blockchain.getChainHeadBlockNumber() - 1L; final int blockCount = 5; @@ -595,13 +610,14 @@ public void respondToGetHeadersPartial() throws ExecutionException, InterruptedE public void respondToGetHeadersEmpty() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long startBlock = blockchain.getChainHeadBlockNumber() + 1; final int blockCount = 5; @@ -630,13 +646,14 @@ public void respondToGetHeadersEmpty() throws ExecutionException, InterruptedExc public void respondToGetBodies() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Setup blocks query final long startBlock = blockchain.getChainHeadBlockNumber() - 5; @@ -683,13 +700,14 @@ public void respondToGetBodiesWithinLimits() throws ExecutionException, Interrup final EthProtocolConfiguration config = EthProtocolConfiguration.builder().maxGetBlockBodies(limit).build(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - config)) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(config) + .build()) { // Setup blocks query final int blockCount = 10; final long startBlock = blockchain.getChainHeadBlockNumber() - blockCount; @@ -732,13 +750,14 @@ public void respondToGetBodiesWithinLimits() throws ExecutionException, Interrup public void respondToGetBodiesPartial() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Setup blocks query final long expectedBlockNumber = blockchain.getChainHeadBlockNumber() - 1; final BlockHeader header = blockchain.getBlockHeader(expectedBlockNumber).get(); @@ -775,13 +794,14 @@ public void respondToGetBodiesPartial() throws ExecutionException, InterruptedEx public void respondToGetReceipts() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Setup blocks query final long startBlock = blockchain.getChainHeadBlockNumber() - 5; final int blockCount = 2; @@ -826,13 +846,14 @@ public void respondToGetReceiptsWithinLimits() throws ExecutionException, Interr final EthProtocolConfiguration config = EthProtocolConfiguration.builder().maxGetReceipts(limit).build(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - config)) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(config) + .build()) { // Setup blocks query final int blockCount = 10; final long startBlock = blockchain.getChainHeadBlockNumber() - blockCount; @@ -874,13 +895,14 @@ public void respondToGetReceiptsWithinLimits() throws ExecutionException, Interr public void respondToGetReceiptsPartial() throws ExecutionException, InterruptedException { final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Setup blocks query final long blockNumber = blockchain.getChainHeadBlockNumber() - 5; final BlockHeader header = blockchain.getBlockHeader(blockNumber).get(); @@ -919,13 +941,14 @@ public void respondToGetNodeData() throws Exception { final WorldStateArchive worldStateArchive = protocolContext.getWorldStateArchive(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Setup node data query final List expectedResults = new ArrayList<>(); @@ -967,13 +990,14 @@ public void respondToGetNodeData() throws Exception { @Test public void newBlockMinedSendsNewBlockMessageToAllPeers() { try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Define handler to validate response final PeerSendHandler onSend = mock(PeerSendHandler.class); final List peers = Lists.newArrayList(); @@ -1038,13 +1062,14 @@ public void shouldSuccessfullyRespondToGetHeadersRequestLessThanZero() final CompletableFuture done = new CompletableFuture<>(); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { final long startBlock = 1L; final int requestedBlockCount = 13; @@ -1105,13 +1130,14 @@ public void transactionMessagesGoToTheCorrectExecutor() { final TransactionsMessage transactionMessage = TransactionsMessage.readFrom(raw); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - ethScheduler, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig())) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(ethScheduler) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build()) { // Create a transaction pool. This has a side effect of registering a listener for the // transactions message. TransactionPoolFactory.createTransactionPool( @@ -1141,15 +1167,17 @@ public void transactionMessagesGoToTheCorrectExecutor() { public void forkIdForChainHeadLegacyNoForksNotEmpty() { final EthScheduler ethScheduler = mock(EthScheduler.class); try (final EthProtocolManager ethManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - ethScheduler, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig(), - new ForkIdManager( - blockchain, Collections.emptyList(), Collections.emptyList(), true))) { + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(ethScheduler) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setForkIdManager( + new ForkIdManager( + blockchain, Collections.emptyList(), Collections.emptyList(), true)) + .build()) { assertThat(ethManager.getForkIdAsBytesList()).isNotEmpty(); final CRC32 genesisHashCRC = new CRC32(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestBuilder.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestBuilder.java new file mode 100644 index 00000000000..3bd629db1e6 --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestBuilder.java @@ -0,0 +1,256 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth.manager; + +import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain; +import static org.mockito.Mockito.mock; + +import org.hyperledger.besu.config.GenesisConfig; +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.chain.GenesisState; +import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; +import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; +import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; +import org.hyperledger.besu.ethereum.eth.sync.SyncMode; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.forkid.ForkIdManager; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; +import org.hyperledger.besu.testutil.TestClock; + +import java.math.BigInteger; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.tuweni.bytes.Bytes; + +public class EthProtocolManagerTestBuilder { + private static final BigInteger DEFAULT_NETWORK_ID = BigInteger.ONE; + private static final ProtocolSchedule DEFAULT_PROTOCOL_SCHEDULE = ProtocolScheduleFixture.MAINNET; + + private ProtocolSchedule protocolSchedule; + private GenesisConfig genesisConfig; + private GenesisState genesisState; + private Blockchain blockchain; + private BigInteger networkId; + private WorldStateArchive worldStateArchive; + private TransactionPool transactionPool; + private EthProtocolConfiguration ethereumWireProtocolConfiguration; + private ForkIdManager forkIdManager; + private EthPeers ethPeers; + private EthMessages ethMessages; + private EthMessages snapMessages; + private EthScheduler ethScheduler; + private EthContext ethContext; + private List peerValidators; + private Optional mergePeerFilter; + private SynchronizerConfiguration synchronizerConfiguration; + private PeerTaskExecutor peerTaskExecutor; + + public static EthProtocolManagerTestBuilder builder() { + return new EthProtocolManagerTestBuilder(); + } + + public EthProtocolManagerTestBuilder setProtocolSchedule( + final ProtocolSchedule protocolSchedule) { + this.protocolSchedule = protocolSchedule; + return this; + } + + public EthProtocolManagerTestBuilder setGenesisConfigFile(final GenesisConfig genesisConfig) { + this.genesisConfig = genesisConfig; + return this; + } + + public EthProtocolManagerTestBuilder setGenesisState(final GenesisState genesisState) { + this.genesisState = genesisState; + return this; + } + + public EthProtocolManagerTestBuilder setBlockchain(final Blockchain blockchain) { + this.blockchain = blockchain; + return this; + } + + public EthProtocolManagerTestBuilder setNetworkId(final BigInteger networkId) { + this.networkId = networkId; + return this; + } + + public EthProtocolManagerTestBuilder setWorldStateArchive( + final WorldStateArchive worldStateArchive) { + this.worldStateArchive = worldStateArchive; + return this; + } + + public EthProtocolManagerTestBuilder setTransactionPool(final TransactionPool transactionPool) { + this.transactionPool = transactionPool; + return this; + } + + public EthProtocolManagerTestBuilder setEthereumWireProtocolConfiguration( + final EthProtocolConfiguration ethereumWireProtocolConfiguration) { + this.ethereumWireProtocolConfiguration = ethereumWireProtocolConfiguration; + return this; + } + + public EthProtocolManagerTestBuilder setForkIdManager(final ForkIdManager forkIdManager) { + this.forkIdManager = forkIdManager; + return this; + } + + public EthProtocolManagerTestBuilder setEthPeers(final EthPeers ethPeers) { + this.ethPeers = ethPeers; + return this; + } + + public EthProtocolManagerTestBuilder setEthMessages(final EthMessages ethMessages) { + this.ethMessages = ethMessages; + return this; + } + + public EthProtocolManagerTestBuilder setSnapMessages(final EthMessages snapMessages) { + this.snapMessages = snapMessages; + return this; + } + + public EthProtocolManagerTestBuilder setEthContext(final EthContext ethContext) { + this.ethContext = ethContext; + return this; + } + + public EthProtocolManagerTestBuilder setPeerValidators(final List peerValidators) { + this.peerValidators = peerValidators; + return this; + } + + public EthProtocolManagerTestBuilder setMergePeerFilter( + final Optional mergePeerFilter) { + this.mergePeerFilter = mergePeerFilter; + return this; + } + + public EthProtocolManagerTestBuilder setSynchronizerConfiguration( + final SynchronizerConfiguration synchronizerConfiguration) { + this.synchronizerConfiguration = synchronizerConfiguration; + return this; + } + + public EthProtocolManagerTestBuilder setEthScheduler(final EthScheduler ethScheduler) { + this.ethScheduler = ethScheduler; + return this; + } + + public EthProtocolManagerTestBuilder setPeerTaskExecutor( + final PeerTaskExecutor peerTaskExecutor) { + this.peerTaskExecutor = peerTaskExecutor; + return this; + } + + public EthProtocolManager build() { + if (protocolSchedule == null) { + protocolSchedule = DEFAULT_PROTOCOL_SCHEDULE; + } + if (genesisConfig == null) { + genesisConfig = GenesisConfig.mainnet(); + } + if (genesisState == null) { + genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); + } + if (blockchain == null) { + blockchain = createInMemoryBlockchain(genesisState.getBlock()); + } + if (networkId == null) { + networkId = DEFAULT_NETWORK_ID; + } + if (worldStateArchive == null) { + worldStateArchive = + BlockchainSetupUtil.forTesting(DataStorageFormat.FOREST).getWorldArchive(); + } + if (transactionPool == null) { + transactionPool = mock(TransactionPool.class); + } + if (ethereumWireProtocolConfiguration == null) { + ethereumWireProtocolConfiguration = EthProtocolConfiguration.defaultConfig(); + } + if (forkIdManager == null) { + forkIdManager = + new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false); + } + if (ethPeers == null) { + ethPeers = + new EthPeers( + () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), + TestClock.fixed(), + new NoOpMetricsSystem(), + EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, + Collections.emptyList(), + Bytes.random(64), + 25, + 25, + false, + SyncMode.FAST, + forkIdManager); + } + ethPeers.setChainHeadTracker(EthProtocolManagerTestUtil.getChainHeadTrackerMock()); + if (ethMessages == null) { + ethMessages = new EthMessages(); + } + if (snapMessages == null) { + snapMessages = new EthMessages(); + } + if (ethScheduler == null) { + ethScheduler = + new DeterministicEthScheduler(DeterministicEthScheduler.TimeoutPolicy.NEVER_TIMEOUT); + } + if (peerTaskExecutor == null) { + peerTaskExecutor = mock(PeerTaskExecutor.class); + } + if (ethContext == null) { + ethContext = + new EthContext(ethPeers, ethMessages, snapMessages, ethScheduler, peerTaskExecutor); + } + if (peerValidators == null) { + peerValidators = Collections.emptyList(); + } + if (mergePeerFilter == null) { + mergePeerFilter = Optional.of(new MergePeerFilter()); + } + if (synchronizerConfiguration == null) { + synchronizerConfiguration = SynchronizerConfiguration.builder().build(); + } + return new EthProtocolManager( + blockchain, + networkId, + worldStateArchive, + transactionPool, + ethereumWireProtocolConfiguration, + ethPeers, + ethMessages, + ethContext, + peerValidators, + mergePeerFilter, + synchronizerConfiguration, + ethScheduler, + forkIdManager); + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java index 0b0bd1e3eb7..a91dd17a531 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/EthProtocolManagerTestUtil.java @@ -15,231 +15,29 @@ package org.hyperledger.besu.ethereum.eth.manager; import static com.google.common.base.Preconditions.checkArgument; -import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; -import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.chain.ChainHead; -import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.core.BlockHeader; -import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.Difficulty; -import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.eth.EthProtocol; -import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.snap.SnapProtocolManager; import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; import org.hyperledger.besu.ethereum.eth.sync.ChainHeadTracker; -import org.hyperledger.besu.ethereum.eth.sync.SyncMode; -import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; -import org.hyperledger.besu.ethereum.forkid.ForkIdManager; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.DefaultMessage; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; -import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; import org.hyperledger.besu.testutil.DeterministicEthScheduler; -import org.hyperledger.besu.testutil.DeterministicEthScheduler.TimeoutPolicy; -import org.hyperledger.besu.testutil.TestClock; -import java.math.BigInteger; -import java.util.Collections; -import java.util.Optional; import java.util.OptionalLong; import java.util.concurrent.CompletableFuture; -import org.apache.tuweni.bytes.Bytes; import org.mockito.Mockito; public class EthProtocolManagerTestUtil { - public static EthProtocolManager create( - final ProtocolSchedule protocolSchedule, - final Blockchain blockchain, - final TimeoutPolicy timeoutPolicy, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration ethereumWireProtocolConfiguration) { - return create( - protocolSchedule, - blockchain, - new DeterministicEthScheduler(timeoutPolicy), - worldStateArchive, - transactionPool, - ethereumWireProtocolConfiguration); - } - - public static EthProtocolManager create( - final ProtocolSchedule protocolSchedule, - final Blockchain blockchain, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration ethereumWireProtocolConfiguration, - final Optional mergePeerFilter) { - - final EthPeers peers = - new EthPeers( - EthProtocol.NAME, - () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), - TestClock.fixed(), - new NoOpMetricsSystem(), - EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, - Collections.emptyList(), - Bytes.random(64), - 25, - 25, - false, - SyncMode.FAST, - new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false)); - - final ChainHeadTracker chainHeadTrackerMock = getChainHeadTrackerMock(); - peers.setChainHeadTracker(chainHeadTrackerMock); - - final EthMessages messages = new EthMessages(); - final EthScheduler ethScheduler = new DeterministicEthScheduler(TimeoutPolicy.NEVER_TIMEOUT); - final EthContext ethContext = new EthContext(peers, messages, ethScheduler); - - return new EthProtocolManager( - blockchain, - BigInteger.ONE, - worldStateArchive, - transactionPool, - ethereumWireProtocolConfiguration, - peers, - messages, - ethContext, - Collections.emptyList(), - mergePeerFilter, - mock(SynchronizerConfiguration.class), - ethScheduler, - new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false)); - } - - public static EthProtocolManager create( - final Blockchain blockchain, - final EthScheduler ethScheduler, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration ethereumWireProtocolConfiguration, - final EthPeers ethPeers, - final EthMessages ethMessages, - final EthContext ethContext) { - return create( - blockchain, - ethScheduler, - worldStateArchive, - transactionPool, - ethereumWireProtocolConfiguration, - ethPeers, - ethMessages, - ethContext, - new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false)); - } - - public static EthProtocolManager create( - final Blockchain blockchain, - final EthScheduler ethScheduler, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration ethereumWireProtocolConfiguration, - final EthPeers ethPeers, - final EthMessages ethMessages, - final EthContext ethContext, - final ForkIdManager forkIdManager) { - - ethPeers.setChainHeadTracker(getChainHeadTrackerMock()); - - final BigInteger networkId = BigInteger.ONE; - return new EthProtocolManager( - blockchain, - networkId, - worldStateArchive, - transactionPool, - ethereumWireProtocolConfiguration, - ethPeers, - ethMessages, - ethContext, - Collections.emptyList(), - Optional.empty(), - mock(SynchronizerConfiguration.class), - ethScheduler, - forkIdManager); - } - - public static EthProtocolManager create(final Blockchain blockchain) { - return create( - ProtocolScheduleFixture.MAINNET, - blockchain, - new DeterministicEthScheduler(TimeoutPolicy.NEVER_TIMEOUT)); - } - - public static EthProtocolManager create( - final ProtocolSchedule protocolSchedule, - final Blockchain blockchain, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration ethProtocolConfiguration) { - return create( - protocolSchedule, - blockchain, - new DeterministicEthScheduler(TimeoutPolicy.NEVER_TIMEOUT), - worldStateArchive, - transactionPool, - ethProtocolConfiguration); - } - - public static EthProtocolManager create(final EthScheduler ethScheduler) { - final ProtocolSchedule protocolSchedule = ProtocolScheduleFixture.MAINNET; - final GenesisConfigFile config = GenesisConfigFile.mainnet(); - final GenesisState genesisState = GenesisState.fromConfig(config, protocolSchedule); - final Blockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); - return create(protocolSchedule, blockchain, ethScheduler); - } - - public static EthProtocolManager create( - final ProtocolSchedule protocolSchedule, - final Blockchain blockchain, - final EthScheduler ethScheduler, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration configuration) { - - final EthPeers peers = - new EthPeers( - EthProtocol.NAME, - () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), - TestClock.fixed(), - new NoOpMetricsSystem(), - EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, - Collections.emptyList(), - Bytes.random(64), - 25, - 25, - false, - SyncMode.FAST, - new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false)); - final EthMessages messages = new EthMessages(); - - final ChainHeadTracker chtMock = getChainHeadTrackerMock(); - - peers.setChainHeadTracker(chtMock); - - return create( - blockchain, - ethScheduler, - worldStateArchive, - transactionPool, - configuration, - peers, - messages, - new EthContext(peers, messages, ethScheduler)); - } - public static ChainHeadTracker getChainHeadTrackerMock() { final ChainHeadTracker chtMock = mock(ChainHeadTracker.class); final BlockHeader blockHeaderMock = mock(BlockHeader.class); @@ -251,86 +49,6 @@ public static ChainHeadTracker getChainHeadTrackerMock() { return chtMock; } - public static EthProtocolManager create( - final ProtocolSchedule protocolSchedule, - final Blockchain blockchain, - final EthScheduler ethScheduler, - final WorldStateArchive worldStateArchive, - final TransactionPool transactionPool, - final EthProtocolConfiguration configuration, - final ForkIdManager forkIdManager) { - - final EthPeers peers = - new EthPeers( - EthProtocol.NAME, - () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), - TestClock.fixed(), - new NoOpMetricsSystem(), - EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, - Collections.emptyList(), - Bytes.random(64), - 25, - 25, - false, - SyncMode.FAST, - new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false)); - final EthMessages messages = new EthMessages(); - - return create( - blockchain, - ethScheduler, - worldStateArchive, - transactionPool, - configuration, - peers, - messages, - new EthContext(peers, messages, ethScheduler), - forkIdManager); - } - - public static EthProtocolManager create( - final ProtocolSchedule protocolSchedule, - final Blockchain blockchain, - final EthScheduler ethScheduler) { - final EthPeers ethPeers = - new EthPeers( - EthProtocol.NAME, - () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), - TestClock.fixed(), - new NoOpMetricsSystem(), - EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, - Collections.emptyList(), - Bytes.random(64), - 25, - 25, - false, - SyncMode.FAST, - new ForkIdManager(blockchain, Collections.emptyList(), Collections.emptyList(), false)); - - final ChainHeadTracker chainHeadTrackerMock = getChainHeadTrackerMock(); - ethPeers.setChainHeadTracker(chainHeadTrackerMock); - - final EthMessages messages = new EthMessages(); - - return create( - blockchain, - ethScheduler, - BlockchainSetupUtil.forTesting(DataStorageFormat.FOREST).getWorldArchive(), - mock(TransactionPool.class), - EthProtocolConfiguration.defaultConfig(), - ethPeers, - messages, - new EthContext(ethPeers, messages, ethScheduler)); - } - - public static EthProtocolManager create() { - return create(TimeoutPolicy.NEVER_TIMEOUT); - } - - public static EthProtocolManager create(final TimeoutPolicy timeoutPolicy) { - return create(new DeterministicEthScheduler(timeoutPolicy)); - } - // Utility to prevent scheduler from automatically running submitted tasks public static void disableEthSchedulerAutoRun(final EthProtocolManager ethProtocolManager) { final EthScheduler scheduler = ethProtocolManager.ethContext().getScheduler(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RequestManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RequestManagerTest.java index a00a08a7378..292aef78420 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RequestManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/RequestManagerTest.java @@ -303,7 +303,6 @@ private EthPeer createPeer() { final Consumer onPeerReady = (peer) -> {}; return new EthPeer( peerConnection, - EthProtocol.NAME, onPeerReady, Collections.emptyList(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java index b1691d0af54..79638fee41e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/AbstractMessageTaskTest.java @@ -27,16 +27,17 @@ import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.core.MiningConfiguration; -import org.hyperledger.besu.ethereum.eth.EthProtocol; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthMessages; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; @@ -64,6 +65,7 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; /** * @param The type of data being requested from the network @@ -92,6 +94,7 @@ public abstract class AbstractMessageTaskTest { protected EthContext ethContext; protected EthPeers ethPeers; protected TransactionPool transactionPool; + protected PeerTaskExecutor peerTaskExecutor; protected AtomicBoolean peersDoTimeout; protected AtomicInteger peerCountToTimeout; @@ -114,7 +117,6 @@ public void setupTest() { ethPeers = spy( new EthPeers( - EthProtocol.NAME, () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), TestClock.fixed(), metricsSystem, @@ -132,7 +134,8 @@ public void setupTest() { final EthScheduler ethScheduler = new DeterministicEthScheduler( () -> peerCountToTimeout.getAndDecrement() > 0 || peersDoTimeout.get()); - ethContext = new EthContext(ethPeers, ethMessages, ethScheduler); + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); + ethContext = new EthContext(ethPeers, ethMessages, ethScheduler, peerTaskExecutor); final SyncState syncState = new SyncState(blockchain, ethContext.getEthPeers()); transactionPool = TransactionPoolFactory.createTransactionPool( @@ -148,15 +151,16 @@ public void setupTest() { transactionPool.setEnabled(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - blockchain, - ethScheduler, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig(), - ethPeers, - ethMessages, - ethContext); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(ethScheduler) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setEthPeers(ethPeers) + .setEthMessages(ethMessages) + .setEthContext(ethContext) + .build(); } protected abstract T generateDataToBeRequested(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/PeerMessageTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/PeerMessageTaskTest.java index 0ed6569387b..3def10fb8c9 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/PeerMessageTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/ethtaskutils/PeerMessageTaskTest.java @@ -162,7 +162,6 @@ protected EthPeer createPeer() { final Consumer onPeerReady = (peer) -> {}; return new EthPeer( peerConnection, - EthProtocol.NAME, onPeerReady, Collections.emptyList(), EthProtocolConfiguration.DEFAULT_MAX_MESSAGE_SIZE, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorTest.java index 9639de154d7..d0ee3f163ec 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/PeerTaskExecutorTest.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol; +import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.util.Optional; @@ -73,7 +74,8 @@ public void testExecuteAgainstPeerWithNoRetriesAndSuccessfulFlow() Mockito.when(requestSender.sendRequest(subprotocol, requestMessageData, ethPeer)) .thenReturn(responseMessageData); Mockito.when(peerTask.processResponse(responseMessageData)).thenReturn(responseObject); - Mockito.when(peerTask.isSuccess(responseObject)).thenReturn(true); + Mockito.when(peerTask.validateResult(responseObject)) + .thenReturn(PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD); PeerTaskExecutorResult result = peerTaskExecutor.executeAgainstPeer(peerTask, ethPeer); @@ -85,6 +87,37 @@ public void testExecuteAgainstPeerWithNoRetriesAndSuccessfulFlow() Assertions.assertEquals(PeerTaskExecutorResponseCode.SUCCESS, result.responseCode()); } + @Test + public void testExecuteAgainstPeerWithNoRetriesAndPeerShouldBeDisconnected() + throws PeerConnection.PeerNotConnected, + ExecutionException, + InterruptedException, + TimeoutException, + InvalidPeerTaskResponseException { + + Object responseObject = new Object(); + + Mockito.when(peerTask.getRequestMessage()).thenReturn(requestMessageData); + Mockito.when(peerTask.getRetriesWithSamePeer()).thenReturn(0); + Mockito.when(peerTask.getSubProtocol()).thenReturn(subprotocol); + Mockito.when(subprotocol.getName()).thenReturn("subprotocol"); + Mockito.when(requestSender.sendRequest(subprotocol, requestMessageData, ethPeer)) + .thenReturn(responseMessageData); + Mockito.when(peerTask.processResponse(responseMessageData)).thenReturn(responseObject); + Mockito.when(peerTask.validateResult(responseObject)) + .thenReturn(PeerTaskValidationResponse.NON_SEQUENTIAL_HEADERS_RETURNED); + + PeerTaskExecutorResult result = peerTaskExecutor.executeAgainstPeer(peerTask, ethPeer); + + Mockito.verify(ethPeer) + .disconnect(DisconnectMessage.DisconnectReason.BREACH_OF_PROTOCOL_NON_SEQUENTIAL_HEADERS); + + Assertions.assertNotNull(result); + Assertions.assertTrue(result.result().isPresent()); + Assertions.assertSame(responseObject, result.result().get()); + Assertions.assertEquals(PeerTaskExecutorResponseCode.INVALID_RESPONSE, result.responseCode()); + } + @Test public void testExecuteAgainstPeerWithNoRetriesAndPartialSuccessfulFlow() throws PeerConnection.PeerNotConnected, @@ -102,7 +135,8 @@ public void testExecuteAgainstPeerWithNoRetriesAndPartialSuccessfulFlow() Mockito.when(requestSender.sendRequest(subprotocol, requestMessageData, ethPeer)) .thenReturn(responseMessageData); Mockito.when(peerTask.processResponse(responseMessageData)).thenReturn(responseObject); - Mockito.when(peerTask.isSuccess(responseObject)).thenReturn(false); + Mockito.when(peerTask.validateResult(responseObject)) + .thenReturn(PeerTaskValidationResponse.NO_RESULTS_RETURNED); PeerTaskExecutorResult result = peerTaskExecutor.executeAgainstPeer(peerTask, ethPeer); @@ -131,7 +165,8 @@ public void testExecuteAgainstPeerWithRetriesAndSuccessfulFlowAfterFirstFailure( .thenReturn(responseMessageData); Mockito.when(requestMessageData.getCode()).thenReturn(requestMessageDataCode); Mockito.when(peerTask.processResponse(responseMessageData)).thenReturn(responseObject); - Mockito.when(peerTask.isSuccess(responseObject)).thenReturn(true); + Mockito.when(peerTask.validateResult(responseObject)) + .thenReturn(PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD); PeerTaskExecutorResult result = peerTaskExecutor.executeAgainstPeer(peerTask, ethPeer); @@ -237,7 +272,8 @@ public void testExecuteWithNoRetriesAndSuccessFlow() Mockito.when(requestSender.sendRequest(subprotocol, requestMessageData, ethPeer)) .thenReturn(responseMessageData); Mockito.when(peerTask.processResponse(responseMessageData)).thenReturn(responseObject); - Mockito.when(peerTask.isSuccess(responseObject)).thenReturn(true); + Mockito.when(peerTask.validateResult(responseObject)) + .thenReturn(PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD); PeerTaskExecutorResult result = peerTaskExecutor.executeAgainstPeer(peerTask, ethPeer); @@ -275,7 +311,8 @@ public void testExecuteWithPeerSwitchingAndSuccessFlow() Mockito.when(requestSender.sendRequest(subprotocol, requestMessageData, peer2)) .thenReturn(responseMessageData); Mockito.when(peerTask.processResponse(responseMessageData)).thenReturn(responseObject); - Mockito.when(peerTask.isSuccess(responseObject)).thenReturn(true); + Mockito.when(peerTask.validateResult(responseObject)) + .thenReturn(PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD); PeerTaskExecutorResult result = peerTaskExecutor.execute(peerTask); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskExecutorAnswer.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskExecutorAnswer.java new file mode 100644 index 00000000000..9437265efba --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskExecutorAnswer.java @@ -0,0 +1,88 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth.manager.peertask.task; + +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.eth.manager.EthPeers; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +public class GetHeadersFromPeerTaskExecutorAnswer + implements Answer>> { + private final Blockchain otherBlockchain; + private final EthPeers ethPeers; + + public GetHeadersFromPeerTaskExecutorAnswer( + final Blockchain otherBlockchain, final EthPeers ethPeers) { + this.otherBlockchain = otherBlockchain; + this.ethPeers = ethPeers; + } + + @Override + public PeerTaskExecutorResult> answer(final InvocationOnMock invocationOnMock) + throws Throwable { + GetHeadersFromPeerTask task = invocationOnMock.getArgument(0, GetHeadersFromPeerTask.class); + List getHeadersFromPeerTaskResult = new ArrayList<>(); + BlockHeader initialHeader; + if (task.getBlockHash() != null) { + initialHeader = otherBlockchain.getBlockHeader(task.getBlockHash()).orElse(null); + } else { + initialHeader = otherBlockchain.getBlockHeader(task.getBlockNumber()).orElse(null); + } + getHeadersFromPeerTaskResult.add(initialHeader); + + if (initialHeader != null && task.getMaxHeaders() > 1) { + if (task.getDirection() == GetHeadersFromPeerTask.Direction.FORWARD) { + int skip = task.getSkip() + 1; + long nextHeaderNumber = initialHeader.getNumber() + skip; + long getLimit = nextHeaderNumber + ((task.getMaxHeaders() - 1) * skip); + for (long i = nextHeaderNumber; i < getLimit; i += skip) { + Optional header = otherBlockchain.getBlockHeader(i); + if (header.isPresent()) { + getHeadersFromPeerTaskResult.add(header.get()); + } else { + break; + } + } + + } else { + int skip = task.getSkip() + 1; + long nextHeaderNumber = initialHeader.getNumber() - skip; + long getLimit = nextHeaderNumber - ((task.getMaxHeaders() - 1) * skip); + for (long i = initialHeader.getNumber() - 1; i > getLimit; i -= skip) { + Optional header = otherBlockchain.getBlockHeader(i); + if (header.isPresent()) { + getHeadersFromPeerTaskResult.add(header.get()); + } else { + break; + } + } + } + } + + return new PeerTaskExecutorResult<>( + Optional.of(getHeadersFromPeerTaskResult), + PeerTaskExecutorResponseCode.SUCCESS, + ethPeers.bestPeer()); + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskTest.java new file mode 100644 index 00000000000..4fd66a8dd88 --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetHeadersFromPeerTaskTest.java @@ -0,0 +1,172 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth.manager.peertask.task; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; +import org.hyperledger.besu.ethereum.eth.EthProtocol; +import org.hyperledger.besu.ethereum.eth.manager.ChainState; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.InvalidPeerTaskResponseException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskValidationResponse; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask.Direction; +import org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData; +import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; + +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +public class GetHeadersFromPeerTaskTest { + + @Test + public void testGetSubProtocol() { + GetHeadersFromPeerTask task = new GetHeadersFromPeerTask(0, 1, 0, Direction.FORWARD, null); + Assertions.assertEquals(EthProtocol.get(), task.getSubProtocol()); + } + + @Test + public void testGetRequestMessageForHash() { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask(Hash.ZERO, 0, 1, 0, Direction.FORWARD, null); + MessageData requestMessageData = task.getRequestMessage(); + Assertions.assertEquals( + "0xe4a00000000000000000000000000000000000000000000000000000000000000000018080", + requestMessageData.getData().toHexString()); + } + + @Test + public void testGetRequestMessageForBlockNumber() { + GetHeadersFromPeerTask task = new GetHeadersFromPeerTask(123, 1, 0, Direction.FORWARD, null); + MessageData requestMessageData = task.getRequestMessage(); + Assertions.assertEquals("0xc47b018080", requestMessageData.getData().toHexString()); + } + + @Test + public void testGetRequestMessageForHashWhenBlockNumberAlsoProvided() { + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask(Hash.ZERO, 123, 1, 0, Direction.FORWARD, null); + MessageData requestMessageData = task.getRequestMessage(); + Assertions.assertEquals( + "0xe4a00000000000000000000000000000000000000000000000000000000000000000018080", + requestMessageData.getData().toHexString()); + } + + @Test + public void testProcessResponseWithNullMessageData() { + GetHeadersFromPeerTask task = new GetHeadersFromPeerTask(0, 1, 0, Direction.FORWARD, null); + Assertions.assertThrows( + InvalidPeerTaskResponseException.class, + () -> task.processResponse(null), + "Response MessageData is null"); + } + + @Test + public void testProcessResponse() throws InvalidPeerTaskResponseException { + final BlockchainSetupUtil blockchainSetupUtil = + BlockchainSetupUtil.forTesting(DataStorageFormat.FOREST); + blockchainSetupUtil.importAllBlocks(); + Blockchain blockchain = blockchainSetupUtil.getBlockchain(); + BlockHeader blockHeader = blockchain.getChainHeadHeader(); + BlockHeadersMessage responseMessage = BlockHeadersMessage.create(blockHeader); + + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask( + blockHeader.getBlockHash(), + 0, + 1, + 0, + Direction.FORWARD, + blockchainSetupUtil.getProtocolSchedule()); + + Assertions.assertEquals( + List.of(blockchain.getChainHeadHeader()), task.processResponse(responseMessage)); + } + + @Test + public void testGetPeerRequirementFilter() { + ProtocolSchedule protocolSchedule = Mockito.mock(ProtocolSchedule.class); + Mockito.when(protocolSchedule.anyMatch(Mockito.any())).thenReturn(false); + + GetHeadersFromPeerTask task = + new GetHeadersFromPeerTask(5, 1, 0, Direction.FORWARD, protocolSchedule); + + EthPeer failForShortChainHeight = mockPeer(1); + EthPeer successfulCandidate = mockPeer(5); + + Assertions.assertFalse(task.getPeerRequirementFilter().test(failForShortChainHeight)); + Assertions.assertTrue(task.getPeerRequirementFilter().test(successfulCandidate)); + } + + @Test + public void testValidateResultForEmptyResult() { + GetHeadersFromPeerTask task = new GetHeadersFromPeerTask(5, 1, 0, Direction.FORWARD, null); + Assertions.assertEquals( + PeerTaskValidationResponse.NO_RESULTS_RETURNED, + task.validateResult(Collections.emptyList())); + } + + @Test + public void testShouldDisconnectPeerForTooManyHeadersReturned() { + GetHeadersFromPeerTask task = new GetHeadersFromPeerTask(5, 1, 1, Direction.FORWARD, null); + + BlockHeader header1 = Mockito.mock(BlockHeader.class); + BlockHeader header2 = Mockito.mock(BlockHeader.class); + BlockHeader header3 = Mockito.mock(BlockHeader.class); + + Assertions.assertEquals( + PeerTaskValidationResponse.TOO_MANY_RESULTS_RETURNED, + task.validateResult(List.of(header1, header2, header3))); + } + + @Test + public void testValidateResultForNonSequentialHeaders() { + GetHeadersFromPeerTask task = new GetHeadersFromPeerTask(1, 3, 0, Direction.FORWARD, null); + + Hash block1Hash = Hash.fromHexStringLenient("01"); + Hash block2Hash = Hash.fromHexStringLenient("02"); + BlockHeader header1 = Mockito.mock(BlockHeader.class); + Mockito.when(header1.getNumber()).thenReturn(1L); + Mockito.when(header1.getHash()).thenReturn(block1Hash); + BlockHeader header2 = Mockito.mock(BlockHeader.class); + Mockito.when(header2.getNumber()).thenReturn(2L); + Mockito.when(header2.getHash()).thenReturn(block2Hash); + Mockito.when(header2.getParentHash()).thenReturn(block1Hash); + BlockHeader header3 = Mockito.mock(BlockHeader.class); + Mockito.when(header3.getNumber()).thenReturn(3L); + Mockito.when(header3.getParentHash()).thenReturn(Hash.ZERO); + + Assertions.assertEquals( + PeerTaskValidationResponse.NON_SEQUENTIAL_HEADERS_RETURNED, + task.validateResult(List.of(header1, header2, header3))); + } + + private EthPeer mockPeer(final long chainHeight) { + EthPeer ethPeer = Mockito.mock(EthPeer.class); + ChainState chainState = Mockito.mock(ChainState.class); + + Mockito.when(ethPeer.chainState()).thenReturn(chainState); + Mockito.when(chainState.getEstimatedHeight()).thenReturn(chainHeight); + + return ethPeer; + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTaskTest.java index 90e6f738fcd..8b8530aa02e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/peertask/task/GetReceiptsFromPeerTaskTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.eth.manager.ChainState; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.peertask.InvalidPeerTaskResponseException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskValidationResponse; import org.hyperledger.besu.ethereum.eth.messages.EthPV63; import org.hyperledger.besu.ethereum.eth.messages.GetReceiptsMessage; import org.hyperledger.besu.ethereum.eth.messages.ReceiptsMessage; @@ -214,30 +215,31 @@ public void testGetPeerRequirementFilter() { new GetReceiptsFromPeerTask( List.of(blockHeader1, blockHeader2, blockHeader3), protocolSchedule); - EthPeer failForIncorrectProtocol = mockPeer("incorrectProtocol", 5); - EthPeer failForShortChainHeight = mockPeer("incorrectProtocol", 1); - EthPeer successfulCandidate = mockPeer(EthProtocol.NAME, 5); + EthPeer failForShortChainHeight = mockPeer(1); + EthPeer successfulCandidate = mockPeer(5); - Assertions.assertFalse(task.getPeerRequirementFilter().test(failForIncorrectProtocol)); Assertions.assertFalse(task.getPeerRequirementFilter().test(failForShortChainHeight)); Assertions.assertTrue(task.getPeerRequirementFilter().test(successfulCandidate)); } @Test - public void testIsSuccessForPartialSuccess() { + public void testValidateResultForPartialSuccess() { GetReceiptsFromPeerTask task = new GetReceiptsFromPeerTask(Collections.emptyList(), null); - Assertions.assertFalse(task.isSuccess(Collections.emptyMap())); + Assertions.assertEquals( + PeerTaskValidationResponse.NO_RESULTS_RETURNED, + task.validateResult(Collections.emptyMap())); } @Test - public void testIsSuccessForFullSuccess() { + public void testValidateResultForFullSuccess() { GetReceiptsFromPeerTask task = new GetReceiptsFromPeerTask(Collections.emptyList(), null); Map> map = new HashMap<>(); map.put(mockBlockHeader(1), null); - Assertions.assertTrue(task.isSuccess(map)); + Assertions.assertEquals( + PeerTaskValidationResponse.RESULTS_VALID_AND_GOOD, task.validateResult(map)); } private BlockHeader mockBlockHeader(final long blockNumber) { @@ -251,11 +253,10 @@ private BlockHeader mockBlockHeader(final long blockNumber) { return blockHeader; } - private EthPeer mockPeer(final String protocol, final long chainHeight) { + private EthPeer mockPeer(final long chainHeight) { EthPeer ethPeer = Mockito.mock(EthPeer.class); ChainState chainState = Mockito.mock(ChainState.class); - Mockito.when(ethPeer.getProtocolName()).thenReturn(protocol); Mockito.when(ethPeer.chainState()).thenReturn(chainState); Mockito.when(chainState.getEstimatedHeight()).thenReturn(chainHeight); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTaskTest.java index 99ea4ad06cb..ff2aeee2ba4 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetBlockFromPeerTaskTest.java @@ -24,6 +24,8 @@ import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.ethtaskutils.AbstractMessageTaskTest; import org.hyperledger.besu.ethereum.eth.manager.exceptions.EthTaskException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.util.ExceptionUtils; import java.util.Optional; @@ -32,6 +34,7 @@ import java.util.concurrent.atomic.AtomicReference; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class GetBlockFromPeerTaskTest extends AbstractMessageTaskTest> { @@ -47,9 +50,11 @@ protected Block generateDataToBeRequested() { @Override protected EthTask> createTask(final Block requestedData) { + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); return GetBlockFromPeerTask.create( protocolSchedule, ethContext, + SynchronizerConfiguration.builder().build(), Optional.of(requestedData.getHash()), BLOCK_NUMBER, metricsSystem); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTaskTest.java index d1594d46f07..3d8734c4a5c 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/RetryingGetBlockFromPeersTaskTest.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.ethtaskutils.RetryingSwitchingPeerMessageTaskTest; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask.PeerTaskResult; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import java.util.Optional; import java.util.concurrent.ExecutionException; @@ -51,6 +52,7 @@ protected RetryingGetBlockFromPeersTask createTask(final PeerTaskResult r return RetryingGetBlockFromPeersTask.create( protocolSchedule, ethContext, + SynchronizerConfiguration.builder().build(), metricsSystem, maxRetries, Optional.of(requestedData.getResult().getHash()), diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTaskTest.java deleted file mode 100644 index 906b0ca7aaa..00000000000 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeerTaskTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.ethereum.eth.manager.task; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.services.MetricsSystem; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class WaitForPeerTaskTest { - private EthProtocolManager ethProtocolManager; - private EthContext ethContext; - private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); - - @BeforeEach - public void setupTest() { - ethProtocolManager = EthProtocolManagerTestUtil.create(); - ethContext = ethProtocolManager.ethContext(); - } - - @Test - public void completesWhenPeerConnects() throws ExecutionException, InterruptedException { - // Execute task and wait for response - final AtomicBoolean successful = new AtomicBoolean(false); - final EthTask task = WaitForPeerTask.create(ethContext, metricsSystem); - final CompletableFuture future = task.run(); - future.whenComplete( - (result, error) -> { - if (error == null) { - successful.compareAndSet(false, true); - } - }); - EthProtocolManagerTestUtil.createPeer(ethProtocolManager); - assertThat(successful).isTrue(); - } - - @Test - public void doesNotCompleteWhenNoPeerConnects() throws ExecutionException, InterruptedException { - final AtomicBoolean successful = new AtomicBoolean(false); - final EthTask task = WaitForPeerTask.create(ethContext, metricsSystem); - final CompletableFuture future = task.run(); - future.whenComplete( - (result, error) -> { - if (error == null) { - successful.compareAndSet(false, true); - } - }); - - assertThat(successful).isFalse(); - } - - @Test - public void cancel() throws ExecutionException, InterruptedException { - // Execute task - final EthTask task = WaitForPeerTask.create(ethContext, metricsSystem); - final CompletableFuture future = task.run(); - - assertThat(future.isDone()).isFalse(); - task.cancel(); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isTrue(); - assertThat(task.run().isCancelled()).isTrue(); - } -} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTaskTest.java deleted file mode 100644 index 283a1b5894c..00000000000 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/WaitForPeersTaskTest.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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.ethereum.eth.manager.task; - -import static org.assertj.core.api.Assertions.assertThat; - -import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.services.MetricsSystem; - -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicBoolean; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class WaitForPeersTaskTest { - private EthProtocolManager ethProtocolManager; - private EthContext ethContext; - private final MetricsSystem metricsSystem = new NoOpMetricsSystem(); - - @BeforeEach - public void setupTest() { - ethProtocolManager = EthProtocolManagerTestUtil.create(); - ethContext = ethProtocolManager.ethContext(); - } - - @Test - public void completesWhenPeersConnects() throws ExecutionException, InterruptedException { - // Execute task and wait for response - final AtomicBoolean successful = new AtomicBoolean(false); - final EthTask task = WaitForPeersTask.create(ethContext, 2, metricsSystem); - final CompletableFuture future = task.run(); - future.whenComplete( - (result, error) -> { - if (error == null) { - successful.compareAndSet(false, true); - } - }); - EthProtocolManagerTestUtil.createPeer(ethProtocolManager); - EthProtocolManagerTestUtil.createPeer(ethProtocolManager); - assertThat(successful).isTrue(); - } - - @Test - public void doesNotCompleteWhenNoPeerConnects() throws ExecutionException, InterruptedException { - final AtomicBoolean successful = new AtomicBoolean(false); - final EthTask task = WaitForPeersTask.create(ethContext, 2, metricsSystem); - final CompletableFuture future = task.run(); - future.whenComplete( - (result, error) -> { - if (error == null) { - successful.compareAndSet(false, true); - } - }); - - assertThat(successful).isFalse(); - } - - @Test - public void doesNotCompleteWhenSomePeersConnects() - throws ExecutionException, InterruptedException { - final AtomicBoolean successful = new AtomicBoolean(false); - final EthTask task = WaitForPeersTask.create(ethContext, 2, metricsSystem); - final CompletableFuture future = task.run(); - future.whenComplete( - (result, error) -> { - if (error == null) { - successful.compareAndSet(false, true); - } - }); - EthProtocolManagerTestUtil.createPeer(ethProtocolManager); - - assertThat(successful).isFalse(); - } - - @Test - public void cancel() throws ExecutionException, InterruptedException { - // Execute task - final EthTask task = WaitForPeersTask.create(ethContext, 2, metricsSystem); - final CompletableFuture future = task.run(); - - assertThat(future.isDone()).isFalse(); - task.cancel(); - assertThat(future.isDone()).isTrue(); - assertThat(future.isCancelled()).isTrue(); - assertThat(task.run().isCancelled()).isTrue(); - } -} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockBodiesMessageTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockBodiesMessageTest.java index 2bb1394a1d3..536f74aba68 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockBodiesMessageTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockBodiesMessageTest.java @@ -16,7 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.core.BlockBody; import org.hyperledger.besu.ethereum.core.BlockHeader; @@ -57,7 +57,7 @@ public final class BlockBodiesMessageTest { public void setup() { protocolSchedule = FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), false, EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockHeadersMessageTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockHeadersMessageTest.java index 9173a7af48b..ab42e404431 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockHeadersMessageTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/messages/BlockHeadersMessageTest.java @@ -14,7 +14,7 @@ */ package org.hyperledger.besu.ethereum.eth.messages; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MiningConfiguration; @@ -64,7 +64,7 @@ public void blockHeadersRoundTrip() throws IOException { final List readHeaders = message.getHeaders( FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), false, EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidatorTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidatorTest.java index b7258de5b7e..3e6ee32c418 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidatorTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/AbstractPeerBlockValidatorTest.java @@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage; @@ -43,7 +44,11 @@ public abstract class AbstractPeerBlockValidatorTest { @Test public void validatePeer_unresponsivePeer() { final EthProtocolManager ethProtocolManager = - EthProtocolManagerTestUtil.create(DeterministicEthScheduler.TimeoutPolicy.ALWAYS_TIMEOUT); + EthProtocolManagerTestBuilder.builder() + .setEthScheduler( + new DeterministicEthScheduler( + DeterministicEthScheduler.TimeoutPolicy.ALWAYS_TIMEOUT)) + .build(); final long blockNumber = 500; final PeerValidator validator = createValidator(blockNumber, 0); @@ -61,7 +66,7 @@ public void validatePeer_unresponsivePeer() { @Test public void validatePeer_requestBlockFromPeerBeingTested() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); final BlockDataGenerator gen = new BlockDataGenerator(1); final long blockNumber = 500; final Block block = gen.block(BlockOptions.create().setBlockNumber(blockNumber)); @@ -97,7 +102,11 @@ public void validatePeer_requestBlockFromPeerBeingTested() { public void canBeValidated() { final BlockDataGenerator gen = new BlockDataGenerator(1); final EthProtocolManager ethProtocolManager = - EthProtocolManagerTestUtil.create(DeterministicEthScheduler.TimeoutPolicy.ALWAYS_TIMEOUT); + EthProtocolManagerTestBuilder.builder() + .setEthScheduler( + new DeterministicEthScheduler( + DeterministicEthScheduler.TimeoutPolicy.ALWAYS_TIMEOUT)) + .build(); final long blockNumber = 500; final long buffer = 10; diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java index 042ca8f9605..27b4a7b4597 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/DaoForkPeerValidatorTest.java @@ -21,8 +21,10 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderValidator; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -37,12 +39,17 @@ public class DaoForkPeerValidatorTest extends AbstractPeerBlockValidatorTest { @Override AbstractPeerBlockValidator createValidator(final long blockNumber, final long buffer) { return new DaoForkPeerValidator( - ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), blockNumber, buffer); + ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), + new NoOpMetricsSystem(), + blockNumber, + buffer); } @Test public void validatePeer_responsivePeerOnRightSideOfFork() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); final BlockDataGenerator gen = new BlockDataGenerator(1); final long daoBlockNumber = 500; final Block daoBlock = @@ -53,7 +60,12 @@ public void validatePeer_responsivePeerOnRightSideOfFork() { final PeerValidator validator = new DaoForkPeerValidator( - ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), daoBlockNumber, 0); + ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), + new NoOpMetricsSystem(), + daoBlockNumber, + 0); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, daoBlockNumber); @@ -73,7 +85,7 @@ public void validatePeer_responsivePeerOnRightSideOfFork() { @Test public void validatePeer_responsivePeerOnWrongSideOfFork() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); final BlockDataGenerator gen = new BlockDataGenerator(1); final long daoBlockNumber = 500; final Block daoBlock = @@ -81,7 +93,12 @@ public void validatePeer_responsivePeerOnWrongSideOfFork() { final PeerValidator validator = new DaoForkPeerValidator( - ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), daoBlockNumber, 0); + ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), + new NoOpMetricsSystem(), + daoBlockNumber, + 0); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, daoBlockNumber); @@ -101,12 +118,17 @@ public void validatePeer_responsivePeerOnWrongSideOfFork() { @Test public void validatePeer_responsivePeerDoesNotHaveBlockWhenPastForkHeight() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); final long daoBlockNumber = 500; final PeerValidator validator = new DaoForkPeerValidator( - ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), daoBlockNumber, 0); + ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), + new NoOpMetricsSystem(), + daoBlockNumber, + 0); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, daoBlockNumber); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/PeerValidatorRunnerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/PeerValidatorRunnerTest.java index 4663ac3ee92..591927bd83b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/PeerValidatorRunnerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/PeerValidatorRunnerTest.java @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; @@ -39,7 +40,7 @@ public class PeerValidatorRunnerTest { public void checkPeer_schedulesFutureCheckWhenPeerNotReady() { final PeerValidator validator = mock(PeerValidator.class); - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); final EthPeer peer = EthProtocolManagerTestUtil.peerBuilder() @@ -78,7 +79,7 @@ public void checkPeer_schedulesFutureCheckWhenPeerNotReady() { public void checkPeer_doesNotScheduleFutureCheckWhenPeerNotReadyAndDisconnected() { final PeerValidator validator = mock(PeerValidator.class); - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); final EthPeer peer = EthProtocolManagerTestUtil.peerBuilder() @@ -105,7 +106,7 @@ public void checkPeer_doesNotScheduleFutureCheckWhenPeerNotReadyAndDisconnected( public void checkPeer_handlesInvalidPeer() { final PeerValidator validator = mock(PeerValidator.class); - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); final EthPeer peer = EthProtocolManagerTestUtil.peerBuilder() @@ -138,7 +139,7 @@ public void checkPeer_handlesInvalidPeer() { public void checkPeer_handlesValidPeer() { final PeerValidator validator = mock(PeerValidator.class); - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); final EthPeer peer = EthProtocolManagerTestUtil.peerBuilder() diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidatorTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidatorTest.java index 4fdb679880b..198ee990b2a 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidatorTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/peervalidation/RequiredBlocksPeerValidatorTest.java @@ -22,8 +22,10 @@ import org.hyperledger.besu.ethereum.core.BlockDataGenerator.BlockOptions; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import java.util.concurrent.CompletableFuture; @@ -36,12 +38,21 @@ public class RequiredBlocksPeerValidatorTest extends AbstractPeerBlockValidatorT @Override AbstractPeerBlockValidator createValidator(final long blockNumber, final long buffer) { return new RequiredBlocksPeerValidator( - ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), blockNumber, Hash.ZERO, buffer); + ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), + new NoOpMetricsSystem(), + blockNumber, + Hash.ZERO, + buffer); } @Test public void validatePeer_responsivePeerWithRequiredBlock() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(ProtocolScheduleFixture.MAINNET) + .build(); final BlockDataGenerator gen = new BlockDataGenerator(1); final long requiredBlockNumber = 500; final Block requiredBlock = @@ -50,6 +61,8 @@ public void validatePeer_responsivePeerWithRequiredBlock() { final PeerValidator validator = new RequiredBlocksPeerValidator( ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), new NoOpMetricsSystem(), requiredBlockNumber, requiredBlock.getHash(), @@ -73,7 +86,7 @@ public void validatePeer_responsivePeerWithRequiredBlock() { @Test public void validatePeer_responsivePeerWithBadRequiredBlock() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); final BlockDataGenerator gen = new BlockDataGenerator(1); final long requiredBlockNumber = 500; final Block requiredBlock = @@ -82,6 +95,8 @@ public void validatePeer_responsivePeerWithBadRequiredBlock() { final PeerValidator validator = new RequiredBlocksPeerValidator( ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), new NoOpMetricsSystem(), requiredBlockNumber, Hash.ZERO, @@ -105,11 +120,16 @@ public void validatePeer_responsivePeerWithBadRequiredBlock() { @Test public void validatePeer_responsivePeerDoesNotHaveBlockWhenPastForkHeight() { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); final PeerValidator validator = new RequiredBlocksPeerValidator( - ProtocolScheduleFixture.MAINNET, new NoOpMetricsSystem(), 1, Hash.ZERO); + ProtocolScheduleFixture.MAINNET, + null, + SynchronizerConfiguration.builder().build(), + new NoOpMetricsSystem(), + 1, + Hash.ZERO); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java index c576b7f8e26..8a6f4c4ecc0 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/AbstractBlockPropagationManagerTest.java @@ -45,6 +45,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthMessages; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -110,12 +111,13 @@ protected void setup(final DataStorageFormat dataStorageFormat) { tempProtocolContext.getConsensusContext(ConsensusContext.class), new BadBlockManager()); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - blockchainUtil.getWorldArchive(), - blockchainUtil.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setWorldStateArchive(blockchainUtil.getWorldArchive()) + .setTransactionPool(blockchainUtil.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); syncConfig = SynchronizerConfiguration.builder().blockPropagationRange(-3, 5).build(); syncState = new SyncState(blockchain, ethProtocolManager.ethContext().getEthPeers()); blockBroadcaster = mock(BlockBroadcaster.class); @@ -641,7 +643,6 @@ public void shouldNotImportBlocksThatAreAlreadyBeingImported() { final EthContext ethContext = new EthContext( new EthPeers( - "eth", () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), TestClock.fixed(), metricsSystem, @@ -655,7 +656,8 @@ public void shouldNotImportBlocksThatAreAlreadyBeingImported() { new ForkIdManager( blockchain, Collections.emptyList(), Collections.emptyList(), false)), new EthMessages(), - ethScheduler); + ethScheduler, + null); final BlockPropagationManager blockPropagationManager = new BlockPropagationManager( syncConfig, @@ -783,7 +785,6 @@ public Object answer(final InvocationOnMock invocation) throws Throwable { final EthContext ethContext = new EthContext( new EthPeers( - "eth", () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), TestClock.fixed(), metricsSystem, @@ -797,7 +798,8 @@ public Object answer(final InvocationOnMock invocation) throws Throwable { new ForkIdManager( blockchain, Collections.emptyList(), Collections.emptyList(), false)), new EthMessages(), - ethScheduler); + ethScheduler, + null); final BlockPropagationManager blockPropagationManager = new BlockPropagationManager( syncConfig, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTrackerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTrackerTest.java index f97fe91c6f5..aa47fd09a34 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTrackerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/ChainHeadTrackerTest.java @@ -15,9 +15,8 @@ package org.hyperledger.besu.ethereum.eth.sync; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.ethereum.chain.BadBlockManager; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; @@ -26,10 +25,14 @@ import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.difficulty.fixed.FixedDifficultyProtocolSchedule; import org.hyperledger.besu.ethereum.eth.manager.ChainState; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTaskExecutorAnswer; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -44,6 +47,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; +import org.mockito.Mockito; public class ChainHeadTrackerTest { @@ -51,11 +55,15 @@ public class ChainHeadTrackerTest { private MutableBlockchain blockchain; private EthProtocolManager ethProtocolManager; private RespondingEthPeer respondingPeer; + + private PeerTaskExecutor peerTaskExecutor; + private SynchronizerConfiguration synchronizerConfiguration; + private ChainHeadTracker chainHeadTracker; private final ProtocolSchedule protocolSchedule = FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), false, EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, @@ -63,8 +71,6 @@ public class ChainHeadTrackerTest { false, new NoOpMetricsSystem()); - private final TrailingPeerLimiter trailingPeerLimiter = mock(TrailingPeerLimiter.class); - static class ChainHeadTrackerTestArguments implements ArgumentsProvider { @Override public Stream provideArguments(final ExtensionContext context) { @@ -73,10 +79,15 @@ public Stream provideArguments(final ExtensionContext conte } } - public void setup(final DataStorageFormat storageFormat) { + public void setup(final DataStorageFormat storageFormat, final boolean isPeerTaskSystemEnabled) { blockchainSetupUtil = BlockchainSetupUtil.forTesting(storageFormat); blockchain = blockchainSetupUtil.getBlockchain(); - ethProtocolManager = EthProtocolManagerTestUtil.create(blockchain); + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); + ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setBlockchain(blockchain) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); respondingPeer = RespondingEthPeer.builder() .ethProtocolManager(ethProtocolManager) @@ -84,11 +95,24 @@ public void setup(final DataStorageFormat storageFormat) { .totalDifficulty(blockchain.getChainHead().getTotalDifficulty()) .estimatedHeight(0) .build(); + GetHeadersFromPeerTaskExecutorAnswer getHeadersAnswer = + new GetHeadersFromPeerTaskExecutorAnswer( + blockchain, ethProtocolManager.ethContext().getEthPeers()); + Mockito.when(peerTaskExecutor.execute(Mockito.any(GetHeadersFromPeerTask.class))) + .thenAnswer(getHeadersAnswer); + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.any(EthPeer.class))) + .thenAnswer(getHeadersAnswer); + synchronizerConfiguration = + SynchronizerConfiguration.builder() + .isPeerTaskSystemEnabled(isPeerTaskSystemEnabled) + .build(); chainHeadTracker = new ChainHeadTracker( ethProtocolManager.ethContext(), protocolSchedule, - trailingPeerLimiter, + synchronizerConfiguration, new NoOpMetricsSystem()); } @@ -96,7 +120,7 @@ public void setup(final DataStorageFormat storageFormat) { @ArgumentsSource(ChainHeadTrackerTestArguments.class) public void shouldRequestHeaderChainHeadWhenNewPeerConnects( final DataStorageFormat storageFormat) { - setup(storageFormat); + setup(storageFormat, false); final Responder responder = RespondingEthPeer.blockchainResponder( blockchainSetupUtil.getBlockchain(), @@ -112,11 +136,23 @@ public void shouldRequestHeaderChainHeadWhenNewPeerConnects( .isEqualTo(blockchain.getChainHeadBlockNumber()); } + @ParameterizedTest + @ArgumentsSource(ChainHeadTrackerTestArguments.class) + public void shouldRequestHeaderChainHeadWhenNewPeerConnectsUsingPeerTaskSystem( + final DataStorageFormat storageFormat) { + setup(storageFormat, true); + chainHeadTracker.getBestHeaderFromPeer(respondingPeer.getEthPeer()); + + Assertions.assertThat(chainHeadState().getEstimatedHeight()).isZero(); + Assertions.assertThat(chainHeadState().getEstimatedHeight()) + .isEqualTo(blockchain.getChainHeadBlockNumber()); + } + @ParameterizedTest @ArgumentsSource(ChainHeadTrackerTestArguments.class) public void shouldIgnoreHeadersIfChainHeadHasAlreadyBeenUpdatedWhileWaiting( final DataStorageFormat storageFormat) { - setup(storageFormat); + setup(storageFormat, false); final Responder responder = RespondingEthPeer.blockchainResponder( blockchainSetupUtil.getBlockchain(), @@ -132,10 +168,23 @@ public void shouldIgnoreHeadersIfChainHeadHasAlreadyBeenUpdatedWhileWaiting( Assertions.assertThat(chainHeadState().getEstimatedHeight()).isZero(); } + @ParameterizedTest + @ArgumentsSource(ChainHeadTrackerTestArguments.class) + public void shouldIgnoreHeadersIfChainHeadHasAlreadyBeenUpdatedWhileWaitingUsingPeerTaskSystem( + final DataStorageFormat storageFormat) { + setup(storageFormat, true); + chainHeadTracker.getBestHeaderFromPeer(respondingPeer.getEthPeer()); + + // Change the hash of the current known head + respondingPeer.getEthPeer().chainState().statusReceived(Hash.EMPTY_TRIE_HASH, Difficulty.ONE); + + Assertions.assertThat(chainHeadState().getEstimatedHeight()).isZero(); + } + @ParameterizedTest @ArgumentsSource(ChainHeadTrackerTestArguments.class) public void shouldCheckTrialingPeerLimits(final DataStorageFormat storageFormat) { - setup(storageFormat); + setup(storageFormat, false); final Responder responder = RespondingEthPeer.blockchainResponder( blockchainSetupUtil.getBlockchain(), @@ -151,6 +200,18 @@ public void shouldCheckTrialingPeerLimits(final DataStorageFormat storageFormat) .isEqualTo(blockchain.getChainHeadBlockNumber()); } + @ParameterizedTest + @ArgumentsSource(ChainHeadTrackerTestArguments.class) + public void shouldCheckTrialingPeerLimitsUsingPeerTaskSystem( + final DataStorageFormat storageFormat) { + setup(storageFormat, true); + chainHeadTracker.getBestHeaderFromPeer(respondingPeer.getEthPeer()); + + Assertions.assertThat(chainHeadState().getEstimatedHeight()).isZero(); + Assertions.assertThat(chainHeadState().getEstimatedHeight()) + .isEqualTo(blockchain.getChainHeadBlockNumber()); + } + private ChainState chainHeadState() { return respondingPeer.getEthPeer().chainState(); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStepTest.java index 3dba7d1cf10..e2dee4c2c53 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/DownloadHeadersStepTest.java @@ -24,8 +24,13 @@ import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.sync.range.RangeHeaders; import org.hyperledger.besu.ethereum.eth.sync.range.SyncTargetRange; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; @@ -36,11 +41,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class DownloadHeadersStepTest { @@ -51,6 +58,7 @@ public class DownloadHeadersStepTest { private final EthPeer syncTarget = mock(EthPeer.class); private EthProtocolManager ethProtocolManager; + private PeerTaskExecutor peerTaskExecutor; private DownloadHeadersStep downloader; private SyncTargetRange checkpointRange; @@ -65,15 +73,12 @@ public static void setUpClass() { @BeforeEach public void setUp() { - ethProtocolManager = EthProtocolManagerTestUtil.create(blockchain); - downloader = - new DownloadHeadersStep( - protocolSchedule, - protocolContext, - ethProtocolManager.ethContext(), - () -> HeaderValidationMode.DETACHED_ONLY, - HEADER_REQUEST_SIZE, - new NoOpMetricsSystem()); + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); + ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setBlockchain(blockchain) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); checkpointRange = new SyncTargetRange( @@ -82,6 +87,15 @@ public void setUp() { @Test public void shouldRetrieveHeadersForCheckpointRange() { + downloader = + new DownloadHeadersStep( + protocolSchedule, + protocolContext, + ethProtocolManager.ethContext(), + () -> HeaderValidationMode.DETACHED_ONLY, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), + HEADER_REQUEST_SIZE, + new NoOpMetricsSystem()); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CompletableFuture result = downloader.apply(checkpointRange); @@ -94,6 +108,15 @@ public void shouldRetrieveHeadersForCheckpointRange() { @Test public void shouldCancelRequestToPeerWhenReturnedFutureIsCancelled() { + downloader = + new DownloadHeadersStep( + protocolSchedule, + protocolContext, + ethProtocolManager.ethContext(), + () -> HeaderValidationMode.DETACHED_ONLY, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), + HEADER_REQUEST_SIZE, + new NoOpMetricsSystem()); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final CompletableFuture result = this.downloader.apply(checkpointRange); @@ -109,6 +132,15 @@ public void shouldCancelRequestToPeerWhenReturnedFutureIsCancelled() { @Test public void shouldReturnOnlyEndHeaderWhenCheckpointRangeHasLengthOfOne() { + downloader = + new DownloadHeadersStep( + protocolSchedule, + protocolContext, + ethProtocolManager.ethContext(), + () -> HeaderValidationMode.DETACHED_ONLY, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), + HEADER_REQUEST_SIZE, + new NoOpMetricsSystem()); final SyncTargetRange checkpointRange = new SyncTargetRange( syncTarget, blockchain.getBlockHeader(3).get(), blockchain.getBlockHeader(4).get()); @@ -121,6 +153,15 @@ public void shouldReturnOnlyEndHeaderWhenCheckpointRangeHasLengthOfOne() { @Test public void shouldGetRemainingHeadersWhenRangeHasNoEnd() { + downloader = + new DownloadHeadersStep( + protocolSchedule, + protocolContext, + ethProtocolManager.ethContext(), + () -> HeaderValidationMode.DETACHED_ONLY, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), + HEADER_REQUEST_SIZE, + new NoOpMetricsSystem()); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); final SyncTargetRange checkpointRange = new SyncTargetRange(peer.getEthPeer(), blockchain.getBlockHeader(3).get()); @@ -133,6 +174,48 @@ public void shouldGetRemainingHeadersWhenRangeHasNoEnd() { .isCompletedWithValue(new RangeHeaders(checkpointRange, headersFromChain(4, 19))); } + @Test + public void shouldGetRemainingHeadersWhenRangeHasNoEndUsingPeerTaskSystem() { + downloader = + new DownloadHeadersStep( + protocolSchedule, + protocolContext, + ethProtocolManager.ethContext(), + () -> HeaderValidationMode.DETACHED_ONLY, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + HEADER_REQUEST_SIZE, + new NoOpMetricsSystem()); + final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + final SyncTargetRange checkpointRange = + new SyncTargetRange(peer.getEthPeer(), blockchain.getBlockHeader(3).get()); + + Mockito.when(peerTaskExecutor.execute(Mockito.any(GetHeadersFromPeerTask.class))) + .thenAnswer( + (invocationOnMock) -> { + GetHeadersFromPeerTask task = + invocationOnMock.getArgument(0, GetHeadersFromPeerTask.class); + List result = new ArrayList<>(); + for (long i = task.getBlockNumber() + 1; i < task.getMaxHeaders(); i++) { + Optional blockHeader = blockchain.getBlockHeader(i); + if (blockHeader.isPresent()) { + result.add(blockHeader.get()); + } else { + // we have reached the end of the blockchain, do nothing and break out of the loop + break; + } + } + return new PeerTaskExecutorResult>( + Optional.of(result), PeerTaskExecutorResponseCode.SUCCESS, Optional.empty()); + }); + + final CompletableFuture result = this.downloader.apply(checkpointRange); + + peer.respond(blockchainResponder(blockchain)); + + assertThat(result) + .isCompletedWithValue(new RangeHeaders(checkpointRange, headersFromChain(4, 19))); + } + private List headersFromChain(final long startNumber, final long endNumber) { final List headers = new ArrayList<>(); for (long i = startNumber; i <= endNumber; i++) { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/RangeHeadersFetcherTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/RangeHeadersFetcherTest.java index 39cad8407e7..c255fb7b241 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/RangeHeadersFetcherTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/RangeHeadersFetcherTest.java @@ -26,9 +26,14 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.sync.fastsync.FastSyncState; import org.hyperledger.besu.ethereum.eth.sync.range.RangeHeadersFetcher; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; @@ -36,15 +41,20 @@ import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.stubbing.Answer; @ExtendWith(MockitoExtension.class) public class RangeHeadersFetcherTest { @@ -55,7 +65,27 @@ public class RangeHeadersFetcherTest { private static ProtocolContext protocolContext; private static final MetricsSystem metricsSystem = new NoOpMetricsSystem(); private static TransactionPool transactionPool; + + private static final Answer>> executeAgainstPeerAnswer = + (invocationOnMock) -> { + List resultList = new ArrayList<>(); + GetHeadersFromPeerTask task = invocationOnMock.getArgument(0, GetHeadersFromPeerTask.class); + for (long i = task.getBlockNumber(); + i < task.getBlockNumber() + task.getMaxHeaders() * (task.getSkip() + 1); + i += task.getSkip() + 1) { + Optional blockHeader = blockchain.getBlockHeader(i); + if (blockHeader.isPresent()) { + resultList.add(blockHeader.get()); + } else { + break; + } + } + return new PeerTaskExecutorResult>( + Optional.of(resultList), PeerTaskExecutorResponseCode.SUCCESS, Optional.empty()); + }; + private EthProtocolManager ethProtocolManager; + private PeerTaskExecutor peerTaskExecutor; private Responder responder; private RespondingEthPeer respondingPeer; @@ -72,14 +102,17 @@ public static void setUpClass() { @BeforeEach public void setUpTest() { + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); responder = RespondingEthPeer.blockchainResponder( blockchain, protocolContext.getWorldStateArchive(), transactionPool); @@ -90,7 +123,7 @@ public void setUpTest() { @Test public void shouldRequestHeadersFromPeerAndExcludeExistingHeader() { - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(false); final CompletableFuture> result = rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(1)); @@ -102,9 +135,44 @@ public void shouldRequestHeadersFromPeerAndExcludeExistingHeader() { assertThat(result).isCompletedWithValue(asList(header(6), header(11), header(16))); } + @Test + public void shouldRequestHeadersFromPeerAndExcludeExistingHeaderUsingPeerTaskSystem() { + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(true); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.eq(respondingPeer.getEthPeer()))) + .thenAnswer(executeAgainstPeerAnswer); + + final CompletableFuture> result = + rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(1)); + + respondingPeer.respond(responder); + + assertThat(result).isCompletedWithValue(asList(header(6), header(11), header(16))); + } + @Test public void shouldNotRequestHeadersBeyondTargetWhenTargetIsMultipleOfSegmentSize() { - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(11)); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(11), false); + + final CompletableFuture> result = + rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(1)); + + respondingPeer.respond(responder); + + assertThat(result).isCompletedWithValue(asList(header(6), header(11))); + } + + @Test + public void + shouldNotRequestHeadersBeyondTargetWhenTargetIsMultipleOfSegmentSizeWithPeerTaskSystem() { + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(11), true); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.eq(respondingPeer.getEthPeer()))) + .thenAnswer(executeAgainstPeerAnswer); final CompletableFuture> result = rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(1)); @@ -116,7 +184,25 @@ public void shouldNotRequestHeadersBeyondTargetWhenTargetIsMultipleOfSegmentSize @Test public void shouldNotRequestHeadersBeyondTargetWhenTargetIsNotAMultipleOfSegmentSize() { - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15)); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15), false); + + final CompletableFuture> result = + rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(1)); + + respondingPeer.respond(responder); + + assertThat(result).isCompletedWithValue(asList(header(6), header(11))); + } + + @Test + public void + shouldNotRequestHeadersBeyondTargetWhenTargetIsNotAMultipleOfSegmentSizeWithPeerTaskSystem() { + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15), true); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.eq(respondingPeer.getEthPeer()))) + .thenAnswer(executeAgainstPeerAnswer); final CompletableFuture> result = rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(1)); @@ -128,7 +214,7 @@ public void shouldNotRequestHeadersBeyondTargetWhenTargetIsNotAMultipleOfSegment @Test public void shouldReturnOnlyTargetHeaderWhenLastHeaderIsTheRangeBeforeTarget() { - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15)); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15), false); final CompletableFuture> result = rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(11)); @@ -138,7 +224,7 @@ public void shouldReturnOnlyTargetHeaderWhenLastHeaderIsTheRangeBeforeTarget() { @Test public void shouldReturnEmptyListWhenLastHeaderIsTarget() { - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15)); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15), false); final CompletableFuture> result = rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(15)); @@ -147,7 +233,7 @@ public void shouldReturnEmptyListWhenLastHeaderIsTarget() { @Test public void shouldReturnEmptyListWhenLastHeaderIsAfterTarget() { - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15)); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(header(15), false); final CompletableFuture> result = rangeHeaderFetcher.getNextRangeHeaders(respondingPeer.getEthPeer(), header(16)); @@ -157,7 +243,7 @@ public void shouldReturnEmptyListWhenLastHeaderIsAfterTarget() { @Test public void nextRangeShouldEndAtChainHeadWhenNextRangeHeaderIsAfterHead() { final long remoteChainHeight = blockchain.getChainHeadBlockNumber(); - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(false); assertThat( rangeHeaderFetcher.nextRangeEndsAtChainHead( @@ -169,7 +255,7 @@ public void nextRangeShouldEndAtChainHeadWhenNextRangeHeaderIsAfterHead() { public void nextRangeShouldNotEndAtChainHeadWhenAFinalRangeHeaderIsSpecified() { final long remoteChainHeight = blockchain.getChainHeadBlockNumber(); final RangeHeadersFetcher rangeHeaderFetcher = - createRangeHeaderFetcher(header(remoteChainHeight)); + createRangeHeaderFetcher(header(remoteChainHeight), false); assertThat( rangeHeaderFetcher.nextRangeEndsAtChainHead( @@ -180,7 +266,31 @@ public void nextRangeShouldNotEndAtChainHeadWhenAFinalRangeHeaderIsSpecified() { @Test public void shouldReturnRemoteChainHeadWhenNextRangeHeaderIsTheRemoteHead() { final long remoteChainHeight = blockchain.getChainHeadBlockNumber(); - final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(false); + + assertThat( + rangeHeaderFetcher.nextRangeEndsAtChainHead( + respondingPeer.getEthPeer(), header(remoteChainHeight - SEGMENT_SIZE))) + .isFalse(); + + final CompletableFuture> result = + rangeHeaderFetcher.getNextRangeHeaders( + respondingPeer.getEthPeer(), header(remoteChainHeight - SEGMENT_SIZE)); + + respondingPeer.respond(responder); + + assertThat(result).isCompletedWithValue(singletonList(header(remoteChainHeight))); + } + + @Test + public void shouldReturnRemoteChainHeadWhenNextRangeHeaderIsTheRemoteHeadWithPeerTaskSystem() { + final long remoteChainHeight = blockchain.getChainHeadBlockNumber(); + final RangeHeadersFetcher rangeHeaderFetcher = createRangeHeaderFetcher(true); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.eq(respondingPeer.getEthPeer()))) + .thenAnswer(executeAgainstPeerAnswer); assertThat( rangeHeaderFetcher.nextRangeEndsAtChainHead( @@ -196,24 +306,27 @@ public void shouldReturnRemoteChainHeadWhenNextRangeHeaderIsTheRemoteHead() { assertThat(result).isCompletedWithValue(singletonList(header(remoteChainHeight))); } - private RangeHeadersFetcher createRangeHeaderFetcher() { + private RangeHeadersFetcher createRangeHeaderFetcher(final boolean isPeerTaskSystemEnabled) { final EthContext ethContext = ethProtocolManager.ethContext(); return new RangeHeadersFetcher( SynchronizerConfiguration.builder() .downloaderChainSegmentSize(SEGMENT_SIZE) .downloaderHeadersRequestSize(3) + .isPeerTaskSystemEnabled(isPeerTaskSystemEnabled) .build(), protocolSchedule, ethContext, metricsSystem); } - private RangeHeadersFetcher createRangeHeaderFetcher(final BlockHeader targetHeader) { + private RangeHeadersFetcher createRangeHeaderFetcher( + final BlockHeader targetHeader, final boolean isPeerTaskSystemEnabled) { final EthContext ethContext = ethProtocolManager.ethContext(); return new RangeHeadersFetcher( SynchronizerConfiguration.builder() .downloaderChainSegmentSize(SEGMENT_SIZE) .downloaderHeadersRequestSize(3) + .isPeerTaskSystemEnabled(isPeerTaskSystemEnabled) .build(), protocolSchedule, ethContext, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java index 4cd4d1c6745..fdb3102af0c 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncContextTest.java @@ -40,8 +40,11 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; @@ -112,6 +115,7 @@ public class BackwardSyncContextTest { @Mock private BlockValidator blockValidator; @Mock private SyncState syncState; + @Mock private PeerTaskExecutor peerTaskExecutor; private BackwardChain backwardChain; private Block uncle; private Block genesisBlock; @@ -144,7 +148,12 @@ public void setup() { } } when(protocolContext.getBlockchain()).thenReturn(localBlockchain); - EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + EthProtocolManager ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager); EthContext ethContext = ethProtocolManager.ethContext(); @@ -178,6 +187,7 @@ public void setup() { new BackwardSyncContext( protocolContext, protocolSchedule, + SynchronizerConfiguration.builder().build(), metricsSystem, ethContext, syncState, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStepTest.java index 696856c0761..8a07a9647da 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/BackwardSyncStepTest.java @@ -17,6 +17,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; import static org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider.createInMemoryBlockchain; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -32,10 +33,17 @@ import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.exceptions.MaxRetriesReachedException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTaskExecutorAnswer; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -45,6 +53,7 @@ import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import javax.annotation.Nonnull; @@ -57,6 +66,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoSettings; import org.mockito.quality.Strictness; +import org.mockito.stubbing.Answer; @ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.LENIENT) @@ -82,6 +92,7 @@ public class BackwardSyncStepTest { private MutableBlockchain localBlockchain; private MutableBlockchain remoteBlockchain; private RespondingEthPeer peer; + @Mock private PeerTaskExecutor peerTaskExecutor; GenericKeyValueStorageFacade headersStorage; GenericKeyValueStorageFacade blocksStorage; GenericKeyValueStorageFacade chainStorage; @@ -130,7 +141,11 @@ public void setup() { when(context.getProtocolSchedule()).thenReturn(protocolSchedule); when(context.getBatchSize()).thenReturn(5); - EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(ethScheduler); + EthProtocolManager ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setEthScheduler(ethScheduler) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); peer = RespondingEthPeer.builder() @@ -139,6 +154,12 @@ public void setup() { .build(); EthContext ethContext = ethProtocolManager.ethContext(); when(context.getEthContext()).thenReturn(ethContext); + + Answer>> getHeadersAnswer = + new GetHeadersFromPeerTaskExecutorAnswer(remoteBlockchain, ethContext.getEthPeers()); + when(peerTaskExecutor.execute(any(GetHeadersFromPeerTask.class))).thenAnswer(getHeadersAnswer); + when(peerTaskExecutor.executeAgainstPeer(any(GetHeadersFromPeerTask.class), any(EthPeer.class))) + .thenAnswer(getHeadersAnswer); } @Test @@ -156,6 +177,23 @@ public void shouldFindHeaderWhenRequested() throws Exception { future.get(); } + @Test + public void shouldFindHeaderWhenRequestedUsingPeerTaskSystem() throws Exception { + final BackwardChain backwardChain = createBackwardChain(LOCAL_HEIGHT + 3); + when(context.getBatchSize()).thenReturn(5); + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + BackwardSyncStep step = spy(new BackwardSyncStep(context, backwardChain)); + + final RespondingEthPeer.Responder responder = + RespondingEthPeer.blockchainResponder(remoteBlockchain); + + final CompletableFuture future = + step.executeAsync(backwardChain.getFirstAncestorHeader().orElseThrow()); + peer.respondWhileOtherThreadsWork(responder, () -> !future.isDone()); + future.get(); + } + @Test public void shouldFindHashToSync() { @@ -166,6 +204,17 @@ public void shouldFindHashToSync() { assertThat(hash).isEqualTo(getBlockByNumber(REMOTE_HEIGHT - 4).getHeader().getParentHash()); } + @Test + public void shouldFindHashToSyncUsingPeerTaskSystem() { + final BackwardChain backwardChain = createBackwardChain(REMOTE_HEIGHT - 4, REMOTE_HEIGHT); + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + BackwardSyncStep step = new BackwardSyncStep(context, backwardChain); + final Hash hash = + step.possibleRestoreOldNodes(backwardChain.getFirstAncestorHeader().orElseThrow()); + assertThat(hash).isEqualTo(getBlockByNumber(REMOTE_HEIGHT - 4).getHeader().getParentHash()); + } + @Test public void shouldRequestHeaderWhenAsked() throws Exception { BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); @@ -182,6 +231,24 @@ public void shouldRequestHeaderWhenAsked() throws Exception { assertThat(blockHeader).isEqualTo(lookingForBlock.getHeader()); } + @Test + public void shouldRequestHeaderWhenAskedUsingPeerTaskSystem() throws Exception { + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); + final Block lookingForBlock = getBlockByNumber(REMOTE_HEIGHT - 2); + + final RespondingEthPeer.Responder responder = + RespondingEthPeer.blockchainResponder(remoteBlockchain); + + final CompletableFuture> future = + step.requestHeaders(lookingForBlock.getHeader().getHash()); + peer.respondWhileOtherThreadsWork(responder, () -> !future.isDone()); + + final BlockHeader blockHeader = future.get().get(0); + assertThat(blockHeader).isEqualTo(lookingForBlock.getHeader()); + } + @Test public void shouldNotRequestHeaderIfAlreadyPresent() throws Exception { BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); @@ -196,6 +263,22 @@ public void shouldNotRequestHeaderIfAlreadyPresent() throws Exception { assertThat(blockHeader).isEqualTo(lookingForBlock.getHeader()); } + @Test + public void shouldNotRequestHeaderIfAlreadyPresentUsingPeerTaskSystem() throws Exception { + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); + final Block lookingForBlock = getBlockByNumber(LOCAL_HEIGHT); + + final CompletableFuture> future = + step.requestHeaders(lookingForBlock.getHeader().getHash()); + + verify(localBlockchain).getBlockHeader(lookingForBlock.getHash()); + verify(context, never()).getEthContext(); + final BlockHeader blockHeader = future.get().get(0); + assertThat(blockHeader).isEqualTo(lookingForBlock.getHeader()); + } + @Test public void shouldRequestHeaderBeforeCurrentHeight() throws Exception { extendBlockchain(REMOTE_HEIGHT + 1, context.getProtocolContext().getBlockchain()); @@ -214,6 +297,26 @@ public void shouldRequestHeaderBeforeCurrentHeight() throws Exception { assertThat(blockHeader).isEqualTo(lookingForBlock.getHeader()); } + @Test + public void shouldRequestHeaderBeforeCurrentHeightUsingPeerTaskSystem() throws Exception { + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + extendBlockchain(REMOTE_HEIGHT + 1, context.getProtocolContext().getBlockchain()); + + BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); + final Block lookingForBlock = getBlockByNumber(REMOTE_HEIGHT - 2); + + final RespondingEthPeer.Responder responder = + RespondingEthPeer.blockchainResponder(remoteBlockchain); + + final CompletableFuture> future = + step.requestHeaders(lookingForBlock.getHeader().getHash()); + peer.respondWhileOtherThreadsWork(responder, () -> !future.isDone()); + + final BlockHeader blockHeader = future.get().get(0); + assertThat(blockHeader).isEqualTo(lookingForBlock.getHeader()); + } + @Test public void shouldThrowWhenResponseIsEmptyWhenRequestingHeader() { BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); @@ -228,6 +331,31 @@ public void shouldThrowWhenResponseIsEmptyWhenRequestingHeader() { assertThatThrownBy(future::get).cause().isInstanceOf(MaxRetriesReachedException.class); } + @Test + public void shouldThrowWhenResponseIsEmptyWhenRequestingHeaderUsingPeerTaskSystem() { + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + Mockito.reset(peerTaskExecutor); + when(peerTaskExecutor.execute(any(GetHeadersFromPeerTask.class))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.empty(), PeerTaskExecutorResponseCode.SUCCESS, Optional.empty())); + when(peerTaskExecutor.executeAgainstPeer(any(GetHeadersFromPeerTask.class), any(EthPeer.class))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.empty(), PeerTaskExecutorResponseCode.SUCCESS, Optional.empty())); + BackwardSyncStep step = new BackwardSyncStep(context, createBackwardChain(REMOTE_HEIGHT - 1)); + final Block lookingForBlock = getBlockByNumber(REMOTE_HEIGHT - 2); + + final RespondingEthPeer.Responder responder = RespondingEthPeer.emptyResponder(); + + final CompletableFuture> future = + step.requestHeaders(lookingForBlock.getHeader().getHash()); + peer.respondWhileOtherThreadsWork(responder, () -> !future.isDone()); + + assertThatThrownBy(future::get).cause().isInstanceOf(RuntimeException.class); + } + @Test public void shouldSaveHeaderDelegatesProperly() { final BackwardChain chain = Mockito.mock(BackwardChain.class); @@ -240,6 +368,20 @@ public void shouldSaveHeaderDelegatesProperly() { verify(chain).prependAncestorsHeader(header); } + @Test + public void shouldSaveHeaderDelegatesProperlyUsingPeerTaskSystem() { + when(context.getSynchronizerConfiguration()) + .thenReturn(SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build()); + final BackwardChain chain = Mockito.mock(BackwardChain.class); + final BlockHeader header = Mockito.mock(BlockHeader.class); + + BackwardSyncStep step = new BackwardSyncStep(context, chain); + + step.saveHeader(header); + + verify(chain).prependAncestorsHeader(header); + } + private BackwardChain createBackwardChain(final int from, final int until) { BackwardChain chain = createBackwardChain(until); for (int i = until; i > from; --i) { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java index de398f68f32..d412e1f2ee9 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ChainForTestCreator.java @@ -91,7 +91,7 @@ public static BlockHeader prepareWrongParentHash(final BlockHeader blockHeader) blockHeader.getExcessBlobGas().orElse(null), blockHeader.getParentBeaconBlockRoot().orElse(null), blockHeader.getRequestsHash().orElse(null), - blockHeader.getTargetBlobCount().orElse(null), + blockHeader.getTargetBlobsPerBlock().orElse(null), blockHeader.getExecutionWitness().orElse(null), new MainnetBlockHeaderFunctions()); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java index 34479bf11fd..7104ae31730 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/backwardsync/ForwardSyncStepTest.java @@ -32,6 +32,7 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; @@ -127,7 +128,7 @@ public void setup() { when(context.getProtocolContext().getBlockchain()).thenReturn(localBlockchain); when(context.getProtocolSchedule()).thenReturn(protocolSchedule); when(context.getBatchSize()).thenReturn(2); - EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager); EthContext ethContext = ethProtocolManager.ethContext(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointSyncChainDownloaderTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointSyncChainDownloaderTest.java index 56e0461f706..e73d286fb0b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointSyncChainDownloaderTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/checkpointsync/CheckPointSyncChainDownloaderTest.java @@ -27,13 +27,17 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTaskExecutorAnswer; import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetReceiptsFromPeerTask; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -50,15 +54,11 @@ import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; -import java.lang.reflect.Field; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; @@ -68,8 +68,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; -import org.junit.platform.commons.util.ReflectionUtils; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; public class CheckPointSyncChainDownloaderTest { @@ -120,11 +118,14 @@ public void setup(final DataStorageFormat dataStorageFormat) { otherBlockchainSetup.importFirstBlocks(30); protocolSchedule = localBlockchainSetup.getProtocolSchedule(); protocolContext = localBlockchainSetup.getProtocolContext(); + peerTaskExecutor = mock(PeerTaskExecutor.class); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); ethContext = ethProtocolManager.ethContext(); final int blockNumber = 10; @@ -142,40 +143,30 @@ public void setup(final DataStorageFormat dataStorageFormat) { true, Optional.of(checkpoint)); - peerTaskExecutor = mock(PeerTaskExecutor.class); - when(peerTaskExecutor.execute(any(GetReceiptsFromPeerTask.class))) .thenAnswer( - new Answer>>>() { - @Override - public PeerTaskExecutorResult>> answer( - final InvocationOnMock invocationOnMock) throws Throwable { - GetReceiptsFromPeerTask task = - invocationOnMock.getArgument(0, GetReceiptsFromPeerTask.class); - - return processTask(task); - } + (invocationOnMock) -> { + GetReceiptsFromPeerTask task = + invocationOnMock.getArgument(0, GetReceiptsFromPeerTask.class); + Map> getReceiptsFromPeerTaskResult = + new HashMap<>(); + task.getBlockHeaders() + .forEach( + (bh) -> + getReceiptsFromPeerTaskResult.put( + bh, otherBlockchain.getTxReceipts(bh.getHash()).get())); + + return new PeerTaskExecutorResult<>( + Optional.of(getReceiptsFromPeerTaskResult), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.empty()); }); - } - @SuppressWarnings("unchecked") - private PeerTaskExecutorResult>> processTask( - final GetReceiptsFromPeerTask task) throws IllegalAccessException { - Map> getReceiptsFromPeerTaskResult = new HashMap<>(); - List fields = - ReflectionUtils.findFields( - task.getClass(), - (field) -> field.getName().equals("blockHeaders"), - ReflectionUtils.HierarchyTraversalMode.TOP_DOWN); - fields.forEach((f) -> f.setAccessible(true)); - Collection blockHeaders = (Collection) fields.getFirst().get(task); - blockHeaders.forEach( - (bh) -> - getReceiptsFromPeerTaskResult.put( - bh, otherBlockchain.getTxReceipts(bh.getHash()).get())); - - return new PeerTaskExecutorResult<>( - Optional.of(getReceiptsFromPeerTaskResult), PeerTaskExecutorResponseCode.SUCCESS); + final Answer>> getHeadersAnswer = + new GetHeadersFromPeerTaskExecutorAnswer(otherBlockchain, ethContext.getEthPeers()); + when(peerTaskExecutor.execute(any(GetHeadersFromPeerTask.class))).thenAnswer(getHeadersAnswer); + when(peerTaskExecutor.executeAgainstPeer(any(GetHeadersFromPeerTask.class), any(EthPeer.class))) + .thenAnswer(getHeadersAnswer); } @AfterEach @@ -193,7 +184,6 @@ private ChainDownloader downloader( protocolSchedule, protocolContext, ethContext, - peerTaskExecutor, syncState, new NoOpMetricsSystem(), new FastSyncState(otherBlockchain.getBlockHeader(pivotBlockNumber).get()), @@ -202,8 +192,7 @@ private ChainDownloader downloader( @ParameterizedTest @ArgumentsSource(CheckPointSyncChainDownloaderTestArguments.class) - public void shouldSyncToPivotBlockInMultipleSegments(final DataStorageFormat storageFormat) - throws IllegalAccessException { + public void shouldSyncToPivotBlockInMultipleSegments(final DataStorageFormat storageFormat) { setup(storageFormat); final RespondingEthPeer peer = @@ -239,8 +228,7 @@ public void shouldSyncToPivotBlockInMultipleSegments(final DataStorageFormat sto @ParameterizedTest @ArgumentsSource(CheckPointSyncChainDownloaderTestArguments.class) - public void shouldSyncToPivotBlockInSingleSegment(final DataStorageFormat storageFormat) - throws IllegalAccessException { + public void shouldSyncToPivotBlockInSingleSegment(final DataStorageFormat storageFormat) { setup(storageFormat); final RespondingEthPeer peer = @@ -273,8 +261,7 @@ public void shouldSyncToPivotBlockInSingleSegment(final DataStorageFormat storag @ParameterizedTest @ArgumentsSource(CheckPointSyncChainDownloaderTestArguments.class) public void shouldSyncToPivotBlockInMultipleSegmentsWithPeerTaskSystem( - final DataStorageFormat storageFormat) - throws IllegalAccessException, ExecutionException, InterruptedException, TimeoutException { + final DataStorageFormat storageFormat) { setup(storageFormat); final RespondingEthPeer peer = @@ -311,7 +298,7 @@ public void shouldSyncToPivotBlockInMultipleSegmentsWithPeerTaskSystem( @ParameterizedTest @ArgumentsSource(CheckPointSyncChainDownloaderTestArguments.class) public void shouldSyncToPivotBlockInSingleSegmentWithPeerTaskSystem( - final DataStorageFormat storageFormat) throws IllegalAccessException { + final DataStorageFormat storageFormat) { setup(storageFormat); final RespondingEthPeer peer = diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStepTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStepTest.java index 4559b211e6e..597ccea8e04 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStepTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/DownloadReceiptsStepTest.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.core.TransactionReceipt; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; @@ -42,6 +43,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; import java.util.HashMap; import java.util.List; @@ -78,13 +80,15 @@ public void setUp() { peerTaskExecutor = mock(PeerTaskExecutor.class); TransactionPool transactionPool = mock(TransactionPool.class); ethProtocolManager = - EthProtocolManagerTestUtil.create( - ProtocolScheduleFixture.MAINNET, - blockchain, - () -> false, - protocolContext.getWorldStateArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(ProtocolScheduleFixture.MAINNET) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(() -> false)) + .setWorldStateArchive(protocolContext.getWorldStateArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); } @Test @@ -93,7 +97,6 @@ public void shouldDownloadReceiptsForBlocks() { new DownloadReceiptsStep( protocolSchedule, ethProtocolManager.ethContext(), - peerTaskExecutor, SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), new NoOpMetricsSystem()); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); @@ -119,7 +122,6 @@ public void shouldDownloadReceiptsForBlocksUsingPeerTaskSystem() new DownloadReceiptsStep( protocolSchedule, ethProtocolManager.ethContext(), - peerTaskExecutor, SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), new NoOpMetricsSystem()); @@ -129,7 +131,7 @@ public void shouldDownloadReceiptsForBlocksUsingPeerTaskSystem() (b) -> receiptsMap.put(b.getHeader(), List.of(Mockito.mock(TransactionReceipt.class)))); PeerTaskExecutorResult>> peerTaskResult = new PeerTaskExecutorResult<>( - Optional.of(receiptsMap), PeerTaskExecutorResponseCode.SUCCESS); + Optional.of(receiptsMap), PeerTaskExecutorResponseCode.SUCCESS, Optional.empty()); Mockito.when(peerTaskExecutor.execute(Mockito.any(GetReceiptsFromPeerTask.class))) .thenReturn(peerTaskResult); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastDownloaderFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastDownloaderFactoryTest.java index bc493ebd036..37ca5be2e99 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastDownloaderFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastDownloaderFactoryTest.java @@ -25,7 +25,6 @@ import org.hyperledger.besu.ethereum.ProtocolContext; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; @@ -72,7 +71,6 @@ public class FastDownloaderFactoryTest { @Mock private ProtocolContext protocolContext; @Mock private MetricsSystem metricsSystem; @Mock private EthContext ethContext; - @Mock private PeerTaskExecutor peerTaskExecutor; @Mock private SyncState syncState; @Mock private Clock clock; @Mock private Path dataDirectory; @@ -116,7 +114,6 @@ public void shouldThrowIfSyncModeChangedWhileFastSyncIncomplete( protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, @@ -142,7 +139,6 @@ public void shouldNotThrowIfSyncModeChangedWhileFastSyncComplete( protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, @@ -171,7 +167,6 @@ public void shouldNotThrowWhenFastSyncModeRequested(final DataStorageFormat data protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, @@ -207,7 +202,6 @@ public void shouldClearWorldStateDuringFastSyncWhenStateQueDirectoryExists( protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, @@ -245,7 +239,6 @@ public void shouldCrashWhenStateQueueIsNotDirectory(final DataStorageFormat data protocolContext, metricsSystem, ethContext, - peerTaskExecutor, worldStateStorageCoordinator, syncState, clock, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActionsTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActionsTest.java index 7af807c1c7b..fe9683059f4 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActionsTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActionsTest.java @@ -16,6 +16,8 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import org.hyperledger.besu.config.GenesisConfigOptions; @@ -29,12 +31,11 @@ import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; -import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; @@ -45,6 +46,7 @@ import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; import java.util.ArrayList; import java.util.List; @@ -62,14 +64,10 @@ import org.junit.jupiter.params.provider.ArgumentsSource; public class FastSyncActionsTest { - - private final SynchronizerConfiguration.Builder syncConfigBuilder = - new SynchronizerConfiguration.Builder().syncMode(SyncMode.FAST).syncPivotDistance(1000); - private final WorldStateStorageCoordinator worldStateStorageCoordinator = mock(WorldStateStorageCoordinator.class); private final AtomicInteger timeoutCount = new AtomicInteger(0); - private SynchronizerConfiguration syncConfig = syncConfigBuilder.build(); + private SynchronizerConfiguration syncConfig; private FastSyncActions fastSyncActions; private EthProtocolManager ethProtocolManager; private EthContext ethContext; @@ -87,34 +85,49 @@ public Stream provideArguments(final ExtensionContext conte } } - public void setUp(final DataStorageFormat storageFormat) { + public void setUp(final DataStorageFormat storageFormat, final boolean isPeerTaskSystemEnabled) { + setUp(storageFormat, isPeerTaskSystemEnabled, Optional.empty()); + } + + public void setUp( + final DataStorageFormat storageFormat, + final boolean isPeerTaskSystemEnabled, + final Optional syncMinimumPeers) { + SynchronizerConfiguration.Builder syncConfigBuilder = + new SynchronizerConfiguration.Builder() + .syncMode(SyncMode.FAST) + .syncPivotDistance(1000) + .isPeerTaskSystemEnabled(isPeerTaskSystemEnabled); + syncMinimumPeers.ifPresent(syncConfigBuilder::syncMinimumPeerCount); + syncConfig = syncConfigBuilder.build(); when(worldStateStorageCoordinator.getDataStorageFormat()).thenReturn(storageFormat); blockchainSetupUtil = BlockchainSetupUtil.forTesting(storageFormat); blockchainSetupUtil.importAllBlocks(); blockchain = blockchainSetupUtil.getBlockchain(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - ProtocolScheduleFixture.MAINNET, - blockchain, - () -> timeoutCount.getAndDecrement() > 0, - blockchainSetupUtil.getWorldArchive(), - blockchainSetupUtil.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(ProtocolScheduleFixture.MAINNET) + .setBlockchain(blockchain) + .setEthScheduler( + new DeterministicEthScheduler(() -> timeoutCount.getAndDecrement() > 0)) + .setWorldStateArchive(blockchainSetupUtil.getWorldArchive()) + .setTransactionPool(blockchainSetupUtil.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); ethContext = ethProtocolManager.ethContext(); ethPeers = ethContext.getEthPeers(); syncState = new SyncState(blockchain, ethPeers); metricsSystem = new NoOpMetricsSystem(); fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); } @ParameterizedTest @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void waitForPeersShouldSucceedIfEnoughPeersAreFound( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false); for (int i = 0; i < syncConfig.getSyncMinimumPeerCount(); i++) { EthProtocolManagerTestUtil.createPeer( ethProtocolManager, syncConfig.getSyncPivotDistance() + i + 1); @@ -127,7 +140,7 @@ public void waitForPeersShouldSucceedIfEnoughPeersAreFound( @ParameterizedTest @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void returnTheSamePivotBlockIfAlreadySelected(final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false); final BlockHeader pivotHeader = new BlockHeaderTestFixture().number(1024).buildHeader(); final FastSyncState fastSyncState = new FastSyncState(pivotHeader); final CompletableFuture result = fastSyncActions.selectPivotBlock(fastSyncState); @@ -139,7 +152,7 @@ public void returnTheSamePivotBlockIfAlreadySelected(final DataStorageFormat sto @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockShouldUseExistingPivotBlockIfAvailable( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false); final BlockHeader pivotHeader = new BlockHeaderTestFixture().number(1024).buildHeader(); EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 5000); @@ -153,14 +166,11 @@ public void selectPivotBlockShouldUseExistingPivotBlockIfAvailable( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockShouldSelectBlockPivotDistanceFromBestPeer( final DataStorageFormat storageFormat) { - setUp(storageFormat); - final int minPeers = 1; - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); + setUp(storageFormat, false, Optional.of(1)); + fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 5000); @@ -174,14 +184,10 @@ public void selectPivotBlockShouldSelectBlockPivotDistanceFromBestPeer( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockShouldConsiderTotalDifficultyWhenSelectingBestPeer( final DataStorageFormat storageFormat) { - setUp(storageFormat); - final int minPeers = 1; - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); + setUp(storageFormat, false, Optional.of(1)); fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); EthProtocolManagerTestUtil.createPeer(ethProtocolManager, Difficulty.of(1000), 5500); EthProtocolManagerTestUtil.createPeer(ethProtocolManager, Difficulty.of(2000), 4000); @@ -196,15 +202,11 @@ public void selectPivotBlockShouldConsiderTotalDifficultyWhenSelectingBestPeer( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockShouldWaitAndRetryUntilMinHeightEstimatesAreAvailable( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false, Optional.of(2)); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); - final int minPeers = 2; - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); final CompletableFuture result = fastSyncActions.selectPivotBlock(FastSyncState.EMPTY_SYNC_STATE); @@ -226,118 +228,41 @@ public void selectPivotBlockShouldWaitAndRetryUntilMinHeightEstimatesAreAvailabl @ParameterizedTest @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) - public void selectPivotBlockShouldWaitAndRetryIfSufficientChainHeightEstimatesAreUnavailable( + public void selectPivotBlockShouldRetryIfPivotBlockSelectorReturnsEmptyOptional( final DataStorageFormat storageFormat) { - setUp(storageFormat); - final int minPeers = 3; - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); - fastSyncActions = - createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); - final long minPivotHeight = syncConfig.getSyncPivotDistance() + 1L; - EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); - - // Create peers without chain height estimates - List peers = new ArrayList<>(); - for (int i = 0; i < minPeers; i++) { - final Difficulty td = Difficulty.of(i); - final OptionalLong height = OptionalLong.empty(); - final RespondingEthPeer peer = - EthProtocolManagerTestUtil.createPeer(ethProtocolManager, td, height); - peers.add(peer); - } - - // No pivot should be selected while peers do not have height estimates - final CompletableFuture result = - fastSyncActions.selectPivotBlock(FastSyncState.EMPTY_SYNC_STATE); - assertThat(result).isNotDone(); - EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); - assertThat(result).isNotDone(); - - // Set subset of heights - peers - .subList(0, minPeers - 1) - .forEach(p -> p.getEthPeer().chainState().updateHeightEstimate(minPivotHeight + 10)); - - // No pivot should be selected while only a subset of peers have height estimates - EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); - assertThat(result).isNotDone(); + setUp(storageFormat, false, Optional.of(3)); - // Set final height - final long bestPeerHeight = minPivotHeight + 1; - peers.get(minPeers - 1).getEthPeer().chainState().updateHeightEstimate(bestPeerHeight); - final FastSyncState expected = - new FastSyncState(bestPeerHeight - syncConfig.getSyncPivotDistance()); - EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); - assertThat(result).isCompletedWithValue(expected); - } + PivotBlockSelector pivotBlockSelector = mock(PivotBlockSelector.class); + fastSyncActions = createFastSyncActions(syncConfig, pivotBlockSelector); - @ParameterizedTest - @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) - public void selectPivotBlockShouldWaitAndRetryIfSufficientValidatedPeersUnavailable( - final DataStorageFormat storageFormat) { - setUp(storageFormat); - final int minPeers = 3; - final PeerValidator validator = mock(PeerValidator.class); - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); - fastSyncActions = - createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); - final long minPivotHeight = syncConfig.getSyncPivotDistance() + 1L; - EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); + FastSyncState expectedResult = new FastSyncState(123); - // Create peers that are not validated - final OptionalLong height = OptionalLong.of(minPivotHeight + 10); - List peers = new ArrayList<>(); - for (int i = 0; i < minPeers; i++) { - final Difficulty td = Difficulty.of(i); + when(pivotBlockSelector.selectNewPivotBlock()) + .thenReturn(Optional.empty()) + .thenReturn(Optional.of(expectedResult)); + when(pivotBlockSelector.prepareRetry()).thenReturn(CompletableFuture.runAsync(() -> {})); - final RespondingEthPeer peer = - EthProtocolManagerTestUtil.createPeer(ethProtocolManager, td, height, validator); - peers.add(peer); - } - - // No pivot should be selected while peers are not fully validated - final CompletableFuture result = + CompletableFuture resultFuture = fastSyncActions.selectPivotBlock(FastSyncState.EMPTY_SYNC_STATE); - assertThat(result).isNotDone(); - EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); - assertThat(result).isNotDone(); - - // Validate a subset of peers - peers.subList(0, minPeers - 1).forEach(p -> p.getEthPeer().markValidated(validator)); - // No pivot should be selected while only a subset of peers has height estimates - EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); - assertThat(result).isNotDone(); + verify(pivotBlockSelector, times(2)).selectNewPivotBlock(); + verify(pivotBlockSelector).prepareRetry(); - // Set best height and mark best peer validated - final long bestPeerHeight = minPivotHeight + 11; - final EthPeer bestPeer = peers.get(minPeers - 1).getEthPeer(); - bestPeer.chainState().updateHeightEstimate(bestPeerHeight); - bestPeer.markValidated(validator); - final FastSyncState expected = - new FastSyncState(bestPeerHeight - syncConfig.getSyncPivotDistance()); - EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); - assertThat(result).isCompletedWithValue(expected); + assertThat(resultFuture).isCompletedWithValue(expectedResult); } @ParameterizedTest @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockUsesBestPeerWithHeightEstimate( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false, Optional.of(3)); selectPivotBlockUsesBestPeerMatchingRequiredCriteria(true, false); } @ParameterizedTest @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockUsesBestPeerThatIsValidated(final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false, Optional.of(3)); selectPivotBlockUsesBestPeerMatchingRequiredCriteria(false, true); } @@ -345,20 +270,16 @@ public void selectPivotBlockUsesBestPeerThatIsValidated(final DataStorageFormat @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockUsesBestPeerThatIsValidatedAndHasHeightEstimate( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false, Optional.of(3)); selectPivotBlockUsesBestPeerMatchingRequiredCriteria(true, true); } private void selectPivotBlockUsesBestPeerMatchingRequiredCriteria( final boolean bestMissingHeight, final boolean bestNotValidated) { - final int minPeers = 3; - final int peerCount = minPeers + 1; - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); + final int peerCount = 4; fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); final long minPivotHeight = syncConfig.getSyncPivotDistance() + 1L; EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); @@ -403,14 +324,10 @@ private void selectPivotBlockUsesBestPeerMatchingRequiredCriteria( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockShouldWaitAndRetryIfBestPeerChainIsShorterThanPivotDistance( final DataStorageFormat storageFormat) { - setUp(storageFormat); - final int minPeers = 1; - syncConfigBuilder.syncMinimumPeerCount(minPeers); - syncConfig = syncConfigBuilder.build(); + setUp(storageFormat, false, Optional.of(1)); fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); final long pivotDistance = syncConfig.getSyncPivotDistance(); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); @@ -433,7 +350,7 @@ public void selectPivotBlockShouldWaitAndRetryIfBestPeerChainIsShorterThanPivotD @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void selectPivotBlockShouldRetryIfBestPeerChainIsEqualToPivotDistance( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false); final long pivotDistance = syncConfig.getSyncPivotDistance(); EthProtocolManagerTestUtil.disableEthSchedulerAutoRun(ethProtocolManager); // Create peers with chains that are too short @@ -458,7 +375,7 @@ public void selectPivotBlockShouldRetryIfBestPeerChainIsEqualToPivotDistance( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void downloadPivotBlockHeaderShouldUseExistingPivotBlockHeaderIfPresent( final DataStorageFormat storageFormat) { - setUp(storageFormat); + setUp(storageFormat, false); final BlockHeader pivotHeader = new BlockHeaderTestFixture().number(1024).buildHeader(); final FastSyncState expected = new FastSyncState(pivotHeader); assertThat(fastSyncActions.downloadPivotBlockHeader(expected)).isCompletedWithValue(expected); @@ -468,12 +385,10 @@ public void downloadPivotBlockHeaderShouldUseExistingPivotBlockHeaderIfPresent( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void downloadPivotBlockHeaderShouldRetrievePivotBlockHeader( final DataStorageFormat storageFormat) { - setUp(storageFormat); - syncConfig = SynchronizerConfiguration.builder().syncMinimumPeerCount(1).build(); + setUp(storageFormat, false, Optional.of(1)); fastSyncActions = createFastSyncActions( - syncConfig, - new PivotSelectorFromPeers(ethContext, syncConfig, syncState, metricsSystem)); + syncConfig, new PivotSelectorFromPeers(ethContext, syncConfig, syncState)); final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1001); final CompletableFuture result = @@ -490,8 +405,7 @@ public void downloadPivotBlockHeaderShouldRetrievePivotBlockHeader( @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) public void downloadPivotBlockHeaderShouldRetrievePivotBlockHash( final DataStorageFormat storageFormat) { - setUp(storageFormat); - syncConfig = SynchronizerConfiguration.builder().syncMinimumPeerCount(1).build(); + setUp(storageFormat, false, Optional.of(1)); GenesisConfigOptions genesisConfig = mock(GenesisConfigOptions.class); when(genesisConfig.getTerminalBlockNumber()).thenReturn(OptionalLong.of(10L)); @@ -511,6 +425,7 @@ public void downloadPivotBlockHeaderShouldRetrievePivotBlockHash( ethContext, metricsSystem, genesisConfig, + syncConfig, () -> finalizedEvent, () -> {})); @@ -537,7 +452,6 @@ private FastSyncActions createFastSyncActions( protocolSchedule, protocolContext, ethContext, - new PeerTaskExecutor(null, null, new NoOpMetricsSystem()), new SyncState(blockchain, ethContext.getEthPeers(), true, Optional.empty()), pivotBlockSelector, new NoOpMetricsSystem()); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloaderTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloaderTest.java index 0e5b5ec2c7c..911a9234d4c 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloaderTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncChainDownloaderTest.java @@ -26,10 +26,10 @@ import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; -import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; import org.hyperledger.besu.ethereum.eth.messages.EthPV62; import org.hyperledger.besu.ethereum.eth.messages.GetBlockHeadersMessage; import org.hyperledger.besu.ethereum.eth.sync.ChainDownloader; @@ -87,10 +87,11 @@ public void setup(final DataStorageFormat storageFormat) { protocolSchedule = localBlockchainSetup.getProtocolSchedule(); protocolContext = localBlockchainSetup.getProtocolContext(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .build(); ethContext = ethProtocolManager.ethContext(); syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); @@ -111,7 +112,6 @@ private ChainDownloader downloader( protocolSchedule, protocolContext, ethContext, - new PeerTaskExecutor(null, null, new NoOpMetricsSystem()), syncState, new NoOpMetricsSystem(), new FastSyncState(otherBlockchain.getBlockHeader(pivotBlockNumber).get()), diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmerTest.java index 2a8a3110840..eb60398589e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockConfirmerTest.java @@ -25,17 +25,26 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotBlockConfirmer.ContestedPivotBlockException; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; +import java.util.List; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; @@ -48,6 +57,7 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ArgumentsProvider; import org.junit.jupiter.params.provider.ArgumentsSource; +import org.mockito.Mockito; public class PivotBlockConfirmerTest { @@ -60,8 +70,8 @@ public class PivotBlockConfirmerTest { private EthProtocolManager ethProtocolManager; private MutableBlockchain blockchain; private TransactionPool transactionPool; - private PivotBlockConfirmer pivotBlockConfirmer; private ProtocolSchedule protocolSchedule; + private PeerTaskExecutor peerTaskExecutor; static class PivotBlockConfirmerTestArguments implements ArgumentsProvider { @Override @@ -78,35 +88,39 @@ public void setUp(final DataStorageFormat storageFormat) { transactionPool = blockchainSetupUtil.getTransactionPool(); protocolSchedule = blockchainSetupUtil.getProtocolSchedule(); protocolContext = blockchainSetupUtil.getProtocolContext(); + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - timeout::get, - blockchainSetupUtil.getWorldArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig()); - pivotBlockConfirmer = createPivotBlockConfirmer(3, 2); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(timeout::get)) + .setWorldStateArchive(blockchainSetupUtil.getWorldArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); } private PivotBlockConfirmer createPivotBlockConfirmer( - final int peersToQuery, final int maxRetries) { - return pivotBlockConfirmer = - spy( - new PivotBlockConfirmer( - protocolSchedule, - ethProtocolManager.ethContext(), - metricsSystem, - PIVOT_BLOCK_NUMBER, - peersToQuery, - maxRetries)); + final int peersToQuery, final int maxRetries, final boolean isPeerTaskSystemEnabled) { + return spy( + new PivotBlockConfirmer( + protocolSchedule, + ethProtocolManager.ethContext(), + metricsSystem, + SynchronizerConfiguration.builder() + .isPeerTaskSystemEnabled(isPeerTaskSystemEnabled) + .build(), + PIVOT_BLOCK_NUMBER, + peersToQuery, + maxRetries)); } @ParameterizedTest @ArgumentsSource(PivotBlockConfirmerTestArguments.class) public void completeSuccessfully(final DataStorageFormat storageFormat) { setUp(storageFormat); - pivotBlockConfirmer = createPivotBlockConfirmer(2, 2); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, false); final Responder responder = RespondingEthPeer.blockchainResponder( @@ -133,11 +147,51 @@ public void completeSuccessfully(final DataStorageFormat storageFormat) { new FastSyncState(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())); } + @ParameterizedTest + @ArgumentsSource(PivotBlockConfirmerTestArguments.class) + public void completeSuccessfullyWithPeerTask(final DataStorageFormat storageFormat) { + setUp(storageFormat); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, true); + + final RespondingEthPeer respondingPeerA = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + + final RespondingEthPeer respondingPeerB = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingPeerA.getEthPeer()))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of(List.of(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingPeerA.getEthPeer()))); + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingPeerB.getEthPeer()))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of(List.of(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingPeerB.getEthPeer()))); + + // Execute task + final CompletableFuture future = pivotBlockConfirmer.confirmPivotBlock(); + + future.join(); + assertThat(future) + .isCompletedWithValue( + new FastSyncState(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())); + } + @ParameterizedTest @ArgumentsSource(PivotBlockConfirmerTestArguments.class) public void delayedResponse(final DataStorageFormat storageFormat) { setUp(storageFormat); - pivotBlockConfirmer = createPivotBlockConfirmer(2, 2); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, false); final Responder responder = RespondingEthPeer.blockchainResponder( @@ -172,7 +226,7 @@ public void delayedResponse(final DataStorageFormat storageFormat) { @ArgumentsSource(PivotBlockConfirmerTestArguments.class) public void peerTimesOutThenIsUnresponsive(final DataStorageFormat storageFormat) { setUp(storageFormat); - pivotBlockConfirmer = createPivotBlockConfirmer(2, 2); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, false); final Responder responder = RespondingEthPeer.blockchainResponder( @@ -214,7 +268,7 @@ public void peerTimesOutThenIsUnresponsive(final DataStorageFormat storageFormat @ArgumentsSource(PivotBlockConfirmerTestArguments.class) public void peerTimesOut(final DataStorageFormat storageFormat) { setUp(storageFormat); - pivotBlockConfirmer = createPivotBlockConfirmer(2, 2); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, false); final Responder responder = RespondingEthPeer.blockchainResponder( @@ -252,11 +306,45 @@ public void peerTimesOut(final DataStorageFormat storageFormat) { new FastSyncState(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())); } + @ParameterizedTest + @ArgumentsSource(PivotBlockConfirmerTestArguments.class) + public void peerTimesOutUsingPeerTaskSystem(final DataStorageFormat storageFormat) { + setUp(storageFormat); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, true); + + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + + when(peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.any(EthPeer.class))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of(List.of(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.empty())) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.empty(), PeerTaskExecutorResponseCode.TIMEOUT, Optional.empty())) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of(List.of(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.empty())); + + // Execute task + final CompletableFuture future = pivotBlockConfirmer.confirmPivotBlock(); + + assertThat(future) + .isCompletedWithValue( + new FastSyncState(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())); + } + @ParameterizedTest @ArgumentsSource(PivotBlockConfirmerTestArguments.class) public void peerUnresponsive(final DataStorageFormat storageFormat) { setUp(storageFormat); - pivotBlockConfirmer = createPivotBlockConfirmer(2, 2); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(2, 2, false); final Responder responder = RespondingEthPeer.blockchainResponder( @@ -300,7 +388,7 @@ public void peerUnresponsive(final DataStorageFormat storageFormat) { @ArgumentsSource(PivotBlockConfirmerTestArguments.class) public void headerMismatch(final DataStorageFormat storageFormat) { setUp(storageFormat); - pivotBlockConfirmer = createPivotBlockConfirmer(3, 2); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(3, 2, false); final Responder responderA = RespondingEthPeer.blockchainResponder( @@ -328,6 +416,49 @@ public void headerMismatch(final DataStorageFormat storageFormat) { assertThat(extraPeer.hasOutstandingRequests()).isFalse(); } + @ParameterizedTest + @ArgumentsSource(PivotBlockConfirmerTestArguments.class) + public void headerMismatchUsingPeerTaskSystem(final DataStorageFormat storageFormat) { + setUp(storageFormat); + PivotBlockConfirmer pivotBlockConfirmer = createPivotBlockConfirmer(3, 2, true); + + final RespondingEthPeer respondingPeerA = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + + final RespondingEthPeer respondingPeerB = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingPeerA.getEthPeer()))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of(List.of(blockchain.getBlockHeader(PIVOT_BLOCK_NUMBER).get())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingPeerA.getEthPeer()))); + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingPeerB.getEthPeer()))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of( + List.of( + new BlockHeaderTestFixture() + .number(PIVOT_BLOCK_NUMBER) + .extraData(Bytes.of(1)) + .buildHeader())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingPeerB.getEthPeer()))); + + // Execute task and wait for response + final CompletableFuture future = pivotBlockConfirmer.confirmPivotBlock(); + + assertThat(future).isCompletedExceptionally(); + assertThatThrownBy(future::get).hasRootCauseInstanceOf(ContestedPivotBlockException.class); + } + private Responder responderForFakeBlocks(final long... blockNumbers) { final Blockchain mockBlockchain = spy(blockchain); for (long blockNumber : blockNumbers) { diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetrieverTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetrieverTest.java index a377ee78278..9cd23a54bdf 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetrieverTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotBlockRetrieverTest.java @@ -28,15 +28,18 @@ import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer.Responder; import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.storage.DataStorageFormat; +import org.hyperledger.besu.testutil.DeterministicEthScheduler; import org.hyperledger.besu.util.ExceptionUtils; import java.util.Optional; @@ -82,13 +85,14 @@ public void setUp(final DataStorageFormat storageFormat) { protocolContext = blockchainSetupUtil.getProtocolContext(); transactionPool = blockchainSetupUtil.getTransactionPool(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - blockchain, - timeout::get, - blockchainSetupUtil.getWorldArchive(), - transactionPool, - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .setEthScheduler(new DeterministicEthScheduler(timeout::get)) + .setWorldStateArchive(blockchainSetupUtil.getWorldArchive()) + .setTransactionPool(transactionPool) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); pivotBlockRetriever = createPivotBlockRetriever(3, 1, 1); } @@ -101,6 +105,7 @@ private PivotBlockRetriever createPivotBlockRetriever( protocolSchedule, ethProtocolManager.ethContext(), metricsSystem, + SynchronizerConfiguration.builder().build(), PIVOT_BLOCK_NUMBER, peersToQuery, pivotBlockDelta, @@ -159,6 +164,7 @@ public void shouldIgnorePeersThatDoNotHaveThePivotBlock(final DataStorageFormat // Add new peer that we can query final RespondingEthPeer respondingPeerB = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); respondingPeerB.respond(responder); // We need one more responsive peer before we're done @@ -169,6 +175,7 @@ public void shouldIgnorePeersThatDoNotHaveThePivotBlock(final DataStorageFormat // Add new peer that we can query final RespondingEthPeer respondingPeerC = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000); + EthProtocolManagerTestUtil.runPendingFutures(ethProtocolManager); respondingPeerC.respond(responder); assertThat(badPeerA.hasOutstandingRequests()).isFalse(); assertThat(badPeerB.hasOutstandingRequests()).isFalse(); @@ -210,11 +217,9 @@ public void shouldIgnorePeersThatAreNotFullyValidated(final DataStorageFormat st final RespondingEthPeer respondingPeerB = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000, peerValidator); respondingPeerB.getEthPeer().markValidated(peerValidator); - // When our new peer "connects", it is not yet valid, so we need to expire our retry timeout - // so that the peer will get re-processed - EthProtocolManagerTestUtil.expirePendingTimeouts(ethProtocolManager); + // add another peer to ensure we get past the waitForPeer call + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000, peerValidator); - assertThat(respondingPeerB.hasOutstandingRequests()).isTrue(); respondingPeerB.respond(responder); // We need one more responsive peer before we're done @@ -226,9 +231,9 @@ public void shouldIgnorePeersThatAreNotFullyValidated(final DataStorageFormat st final RespondingEthPeer respondingPeerC = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000, peerValidator); respondingPeerC.getEthPeer().markValidated(peerValidator); - EthProtocolManagerTestUtil.expirePendingTimeouts(ethProtocolManager); + // add another peer to ensure we get past the waitForPeer call + EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1000, peerValidator); - assertThat(respondingPeerC.hasOutstandingRequests()).isTrue(); respondingPeerC.respond(responder); assertThat(badPeerA.hasOutstandingRequests()).isFalse(); assertThat(badPeerB.hasOutstandingRequests()).isFalse(); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeersTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeersTest.java new file mode 100644 index 00000000000..0d48d6ea26a --- /dev/null +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromPeersTest.java @@ -0,0 +1,91 @@ +/* + * Copyright contributors to Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.ethereum.eth.sync.fastsync; + +import org.hyperledger.besu.ethereum.eth.manager.ChainState; +import org.hyperledger.besu.ethereum.eth.manager.EthContext; +import org.hyperledger.besu.ethereum.eth.manager.EthPeer; +import org.hyperledger.besu.ethereum.eth.manager.EthPeers; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; + +import java.util.Optional; +import java.util.stream.Stream; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import org.mockito.junit.jupiter.MockitoSettings; +import org.mockito.quality.Strictness; + +@ExtendWith(MockitoExtension.class) +@MockitoSettings(strictness = Strictness.LENIENT) +public class PivotSelectorFromPeersTest { + private @Mock EthContext ethContext; + private @Mock EthPeers ethPeers; + private @Mock SyncState syncState; + + private PivotSelectorFromPeers selector; + + @BeforeEach + public void beforeTest() { + SynchronizerConfiguration syncConfig = + SynchronizerConfiguration.builder().syncMinimumPeerCount(2).syncPivotDistance(1).build(); + + selector = new PivotSelectorFromPeers(ethContext, syncConfig, syncState); + } + + @Test + public void testSelectNewPivotBlock() { + EthPeer peer1 = mockPeer(true, 10, true); + EthPeer peer2 = mockPeer(true, 8, true); + + Mockito.when(ethContext.getEthPeers()).thenReturn(ethPeers); + Mockito.when(ethPeers.streamAvailablePeers()).thenReturn(Stream.of(peer1, peer2)); + Mockito.when(ethPeers.getBestPeerComparator()) + .thenReturn((p1, ignored) -> p1 == peer1 ? 1 : -1); + + Optional result = selector.selectNewPivotBlock(); + + Assertions.assertTrue(result.isPresent()); + Assertions.assertEquals(9, result.get().getPivotBlockNumber().getAsLong()); + } + + @Test + public void testSelectNewPivotBlockWithInsufficientPeers() { + Mockito.when(ethContext.getEthPeers()).thenReturn(ethPeers); + Mockito.when(ethPeers.streamAvailablePeers()).thenReturn(Stream.empty()); + + Optional result = selector.selectNewPivotBlock(); + + Assertions.assertTrue(result.isEmpty()); + } + + private EthPeer mockPeer( + final boolean hasEstimatedHeight, final long chainHeight, final boolean isFullyValidated) { + EthPeer ethPeer = Mockito.mock(EthPeer.class); + ChainState chainState = Mockito.mock(ChainState.class); + Mockito.when(ethPeer.chainState()).thenReturn(chainState); + Mockito.when(chainState.hasEstimatedHeight()).thenReturn(hasEstimatedHeight); + Mockito.when(chainState.getEstimatedHeight()).thenReturn(chainHeight); + Mockito.when(ethPeer.isFullyValidated()).thenReturn(isFullyValidated); + + return ethPeer; + } +} diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java index 323f0ae9f10..431c044cbbf 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/worldstate/FastWorldStateDownloaderTest.java @@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -114,7 +115,9 @@ class FastWorldStateDownloaderTest { .build()); final EthProtocolManager ethProtocolManager = - EthProtocolManagerTestUtil.create(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())); + EthProtocolManagerTestBuilder.builder() + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .build(); @AfterEach public void tearDown() throws Exception { @@ -238,7 +241,10 @@ void downloadAlreadyAvailableWorldState() { void canRecoverFromTimeouts() { final DeterministicEthScheduler.TimeoutPolicy timeoutPolicy = DeterministicEthScheduler.TimeoutPolicy.timeoutXTimes(2); - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(timeoutPolicy); + final EthProtocolManager ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setEthScheduler(new DeterministicEthScheduler(timeoutPolicy)) + .build(); final MockExecutorService serviceExecutor = ((DeterministicEthScheduler) ethProtocolManager.ethContext().getScheduler()) .mockServiceExecutor(); @@ -382,7 +388,7 @@ void cancelDownloaderFuture() { @SuppressWarnings("unchecked") private void testCancellation(final boolean shouldCancelFuture) { - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = EthProtocolManagerTestBuilder.builder().build(); // Prevent the persistence service from running final MockExecutorService serviceExecutor = ((DeterministicEthScheduler) ethProtocolManager.ethContext().getScheduler()) @@ -661,7 +667,9 @@ void doesNotRequestKnownStorageTrieNodesFromNetwork() { @Timeout(value = 60) void stalledDownloader() { final EthProtocolManager ethProtocolManager = - EthProtocolManagerTestUtil.create(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())); + EthProtocolManagerTestBuilder.builder() + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .build(); // Setup "remote" state final ForestWorldStateKeyValueStorage remoteStorage = diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderForkTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderForkTest.java index d7b5970098e..fb518c305f7 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderForkTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderForkTest.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -66,13 +67,14 @@ public void setupTest() throws IOException { protocolSchedule = localBlockchainSetup.getProtocolSchedule(); protocolContext = localBlockchainSetup.getProtocolContext(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem()), - localBlockchainSetup.getWorldArchive(), - localBlockchainSetup.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .setWorldStateArchive(localBlockchainSetup.getWorldArchive()) + .setTransactionPool(localBlockchainSetup.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); ethContext = ethProtocolManager.ethContext(); syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTest.java index ac7f0fb8257..2c3c1ecdc8b 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTest.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -96,13 +97,14 @@ public void setupTest(final DataStorageFormat storageFormat) { protocolSchedule = localBlockchainSetup.getProtocolSchedule(); protocolContext = localBlockchainSetup.getProtocolContext(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem()), - localBlockchainSetup.getWorldArchive(), - localBlockchainSetup.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .setWorldStateArchive(localBlockchainSetup.getWorldArchive()) + .setTransactionPool(localBlockchainSetup.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); ethContext = ethProtocolManager.ethContext(); syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTotalTerminalDifficultyTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTotalTerminalDifficultyTest.java index 311ccf5de30..d79a2209241 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTotalTerminalDifficultyTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncChainDownloaderTotalTerminalDifficultyTest.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -80,13 +81,14 @@ public void setupTest(final DataStorageFormat storageFormat) { protocolSchedule = localBlockchainSetup.getProtocolSchedule(); protocolContext = localBlockchainSetup.getProtocolContext(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem()), - localBlockchainSetup.getWorldArchive(), - localBlockchainSetup.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .setWorldStateArchive(localBlockchainSetup.getWorldArchive()) + .setTransactionPool(localBlockchainSetup.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); ethContext = ethProtocolManager.ethContext(); syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloaderTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloaderTest.java index 63e41f6d25c..f50b7edfcff 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloaderTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncDownloaderTest.java @@ -22,6 +22,7 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -71,13 +72,14 @@ public void setupTest(final DataStorageFormat storageFormat) { protocolSchedule = localBlockchainSetup.getProtocolSchedule(); protocolContext = localBlockchainSetup.getProtocolContext(); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem()), - localBlockchainSetup.getWorldArchive(), - localBlockchainSetup.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .setWorldStateArchive(localBlockchainSetup.getWorldArchive()) + .setTransactionPool(localBlockchainSetup.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); ethContext = ethProtocolManager.ethContext(); syncState = new SyncState(protocolContext.getBlockchain(), ethContext.getEthPeers()); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java index 9132842ccbf..66314ddddd6 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fullsync/FullSyncTargetManagerTest.java @@ -30,6 +30,7 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; @@ -81,13 +82,14 @@ public void setup(final DataStorageFormat storageFormat) { new ProtocolContext( localBlockchain, localWorldState, mock(ConsensusContext.class), new BadBlockManager()); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem()), - localWorldState, - localBlockchainSetup.getTransactionPool(), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setEthScheduler(new EthScheduler(1, 1, 1, 1, new NoOpMetricsSystem())) + .setWorldStateArchive(localBlockchainSetup.getWorldArchive()) + .setTransactionPool(localBlockchainSetup.getTransactionPool()) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .build(); final EthContext ethContext = ethProtocolManager.ethContext(); localBlockchainSetup.importFirstBlocks(5); otherBlockchainSetup.importFirstBlocks(20); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java index d3dcb855990..88653f8af37 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/state/SyncStateTest.java @@ -42,6 +42,7 @@ import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthPeers; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; @@ -90,7 +91,7 @@ public class SyncStateTest { @BeforeEach public void setUp() { - ethProtocolManager = EthProtocolManagerTestUtil.create(blockchain); + ethProtocolManager = EthProtocolManagerTestBuilder.builder().setBlockchain(blockchain).build(); ethPeers = spy(ethProtocolManager.ethContext().getEthPeers()); syncTargetPeer = createPeer(TARGET_DIFFICULTY, TARGET_CHAIN_HEIGHT); otherPeer = createPeer(Difficulty.ZERO, 0); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java index 5686b4ae90d..138106c5b6e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskParameterizedTest.java @@ -33,9 +33,15 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -44,7 +50,9 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import java.io.IOException; +import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; @@ -56,6 +64,7 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +import org.mockito.Mockito; public class DetermineCommonAncestorTaskParameterizedTest { private final ProtocolSchedule protocolSchedule = ProtocolScheduleFixture.MAINNET; @@ -67,6 +76,7 @@ public class DetermineCommonAncestorTaskParameterizedTest { private static final int chainHeight = 50; private MutableBlockchain remoteBlockchain; + private PeerTaskExecutor peerTaskExecutor; @BeforeAll public static void setupClass() { @@ -88,6 +98,7 @@ public static void setupClass() { @BeforeEach public void setup() { remoteBlockchain = createInMemoryBlockchain(genesisBlock); + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); } public static Stream parameters() throws IOException { @@ -95,15 +106,19 @@ public static Stream parameters() throws IOException { final Stream.Builder builder = Stream.builder(); for (final int requestSize : requestSizes) { for (int i = 0; i <= chainHeight; i++) { - builder.add(Arguments.of(requestSize, i)); + builder.add(Arguments.of(requestSize, i, true)); + builder.add(Arguments.of(requestSize, i, false)); } } return builder.build(); } - @ParameterizedTest(name = "requestSize={0}, commonAncestor={1}") + @ParameterizedTest(name = "requestSize={0}, commonAncestor={1}, isPeerTaskSystemEnabled={2}") @MethodSource("parameters") - public void searchesAgainstNetwork(final int headerRequestSize, final int commonAncestorHeight) { + public void searchesAgainstNetwork( + final int headerRequestSize, + final int commonAncestorHeight, + final boolean isPeerTaskSystemEnabled) { BlockHeader commonHeader = genesisBlock.getHeader(); for (long i = 1; i <= commonAncestorHeight; i++) { commonHeader = localBlockchain.getBlockHeader(i).get(); @@ -135,12 +150,14 @@ public void searchesAgainstNetwork(final int headerRequestSize, final int common final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); final EthProtocolManager ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - worldStateArchive, - mock(TransactionPool.class), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setWorldStateArchive(worldStateArchive) + .setTransactionPool(mock(TransactionPool.class)) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); final RespondingEthPeer.Responder responder = RespondingEthPeer.blockchainResponder(remoteBlockchain); final RespondingEthPeer respondingEthPeer = @@ -165,8 +182,35 @@ public void searchesAgainstNetwork(final int headerRequestSize, final int common ethContext, respondingEthPeer.getEthPeer(), headerRequestSize, + SynchronizerConfiguration.builder() + .isPeerTaskSystemEnabled(isPeerTaskSystemEnabled) + .build(), metricsSystem); + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingEthPeer.getEthPeer()))) + .thenAnswer( + (invocationOnMock) -> { + GetHeadersFromPeerTask getHeadersTask = + invocationOnMock.getArgument(0, GetHeadersFromPeerTask.class); + long blockNumber = getHeadersTask.getBlockNumber(); + int maxHeaders = getHeadersTask.getMaxHeaders(); + int skip = getHeadersTask.getSkip(); + + List headers = new ArrayList<>(); + long lowerBound = Math.max(0, blockNumber - (maxHeaders - 1) * (skip + 1)); + for (long i = blockNumber; i > lowerBound; i -= skip + 1) { + headers.add(remoteBlockchain.getBlockHeader(i).get()); + } + + return new PeerTaskExecutorResult>( + Optional.of(headers), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingEthPeer.getEthPeer())); + }); + final CompletableFuture future = task.run(); respondingEthPeer.respondWhile(responder, () -> !future.isDone()); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java index f85e4dd31c1..0a1bce7a6c5 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DetermineCommonAncestorTaskTest.java @@ -41,11 +41,17 @@ import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthPeer; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.exceptions.EthTaskException; import org.hyperledger.besu.ethereum.eth.manager.exceptions.EthTaskException.FailureReason; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutor; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -55,13 +61,19 @@ import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.util.ExceptionUtils; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicReference; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; public class DetermineCommonAncestorTaskTest { @@ -74,19 +86,23 @@ public class DetermineCommonAncestorTaskTest { private EthProtocolManager ethProtocolManager; private EthContext ethContext; private ProtocolContext protocolContext; + private PeerTaskExecutor peerTaskExecutor; @BeforeEach public void setup() { localGenesisBlock = blockDataGenerator.genesisBlock(); localBlockchain = createInMemoryBlockchain(localGenesisBlock); final WorldStateArchive worldStateArchive = createInMemoryWorldStateArchive(); + peerTaskExecutor = Mockito.mock(PeerTaskExecutor.class); ethProtocolManager = - EthProtocolManagerTestUtil.create( - protocolSchedule, - localBlockchain, - worldStateArchive, - mock(TransactionPool.class), - EthProtocolConfiguration.defaultConfig()); + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(localBlockchain) + .setWorldStateArchive(worldStateArchive) + .setTransactionPool(mock(TransactionPool.class)) + .setEthereumWireProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .setPeerTaskExecutor(peerTaskExecutor) + .build(); ethContext = ethProtocolManager.ethContext(); protocolContext = new ProtocolContext( @@ -111,6 +127,7 @@ public void shouldFailIfPeerDisconnects() { ethContext, respondingEthPeer.getEthPeer(), defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), metricsSystem); final AtomicReference failure = new AtomicReference<>(); @@ -129,6 +146,51 @@ public void shouldFailIfPeerDisconnects() { assertThat(((EthTaskException) error).reason()).isEqualTo(FailureReason.NO_AVAILABLE_PEERS); } + @Test + public void shouldFailIfPeerDisconnectsUsingPeerTaskSystem() { + final Block block = blockDataGenerator.nextBlock(localBlockchain.getChainHeadBlock()); + localBlockchain.appendBlock(block, blockDataGenerator.receipts(block)); + + final RespondingEthPeer respondingEthPeer = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager); + + final EthTask task = + DetermineCommonAncestorTask.create( + protocolSchedule, + protocolContext, + ethContext, + respondingEthPeer.getEthPeer(), + defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + metricsSystem); + + PeerTaskExecutorResult> taskResult = + new PeerTaskExecutorResult<>( + Optional.of(Collections.emptyList()), + PeerTaskExecutorResponseCode.PEER_DISCONNECTED, + Optional.of(respondingEthPeer.getEthPeer())); + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingEthPeer.getEthPeer()))) + .thenReturn(taskResult); + + final AtomicReference failure = new AtomicReference<>(); + final CompletableFuture future = task.run(); + future.whenComplete( + (response, error) -> { + failure.set(error); + }); + + // Disconnect the target peer + respondingEthPeer.disconnect(DisconnectReason.CLIENT_QUITTING); + + assertThat(failure.get()).isNotNull(); + final Throwable error = ExceptionUtils.rootCause(failure.get()); + assertThat(error).isInstanceOf(EthTaskException.class); + assertThat(((EthTaskException) error).reason()).isEqualTo(FailureReason.PEER_DISCONNECTED); + } + @Test public void shouldHandleEmptyResponses() { final Blockchain remoteBlockchain = setupLocalAndRemoteChains(11, 11, 5); @@ -146,6 +208,7 @@ public void shouldHandleEmptyResponses() { ethContext, respondingEthPeer.getEthPeer(), defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), metricsSystem); // Empty response should be handled without any error @@ -194,6 +257,7 @@ public void shouldIssueConsistentNumberOfRequestsToPeer() { ethContext, respondingEthPeer.getEthPeer(), defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), metricsSystem); final DetermineCommonAncestorTask spy = spy(task); @@ -213,6 +277,44 @@ public void shouldIssueConsistentNumberOfRequestsToPeer() { verify(spy, times(3)).requestHeaders(); } + @Test + public void shouldIssueConsistentNumberOfRequestsToPeerUsingPeerTaskSystem() { + final Blockchain remoteBlockchain = setupLocalAndRemoteChains(101, 101, 1); + + final RespondingEthPeer respondingEthPeer = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager); + + final EthTask task = + DetermineCommonAncestorTask.create( + protocolSchedule, + protocolContext, + ethContext, + respondingEthPeer.getEthPeer(), + defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + metricsSystem); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingEthPeer.getEthPeer()))) + .thenAnswer(peerTaskExecutorResultAnswer(remoteBlockchain)); + + final AtomicReference result = new AtomicReference<>(); + final CompletableFuture future = task.run(); + future.whenComplete( + (response, error) -> { + result.set(response); + }); + + Assertions.assertThat(result.get().getHash()) + .isEqualTo(MainnetBlockHeaderFunctions.createHash(localGenesisBlock.getHeader())); + + Mockito.verify(peerTaskExecutor, Mockito.times(2)) + .executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.eq(respondingEthPeer.getEthPeer())); + } + @Test public void shouldShortCircuitOnHeaderInInitialRequest() { final Blockchain remoteBlockchain = setupLocalAndRemoteChains(100, 100, 96); @@ -230,6 +332,7 @@ public void shouldShortCircuitOnHeaderInInitialRequest() { ethContext, respondingEthPeer.getEthPeer(), 10, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), metricsSystem); final DetermineCommonAncestorTask spy = spy(task); @@ -249,6 +352,51 @@ public void shouldShortCircuitOnHeaderInInitialRequest() { verify(spy, times(1)).requestHeaders(); } + @Test + public void shouldShortCircuitOnHeaderInInitialRequestUsingPeerTaskSystem() { + final Blockchain remoteBlockchain = setupLocalAndRemoteChains(100, 100, 96); + final BlockHeader commonHeader = localBlockchain.getBlockHeader(95).get(); + + final RespondingEthPeer.Responder responder = + RespondingEthPeer.blockchainResponder(remoteBlockchain); + final RespondingEthPeer respondingEthPeer = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager); + + final DetermineCommonAncestorTask task = + DetermineCommonAncestorTask.create( + protocolSchedule, + protocolContext, + ethContext, + respondingEthPeer.getEthPeer(), + 10, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + metricsSystem); + final DetermineCommonAncestorTask spy = spy(task); + + Mockito.when( + peerTaskExecutor.executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), + Mockito.eq(respondingEthPeer.getEthPeer()))) + .thenAnswer(peerTaskExecutorResultAnswer(remoteBlockchain)); + + // Execute task + final CompletableFuture future = spy.run(); + respondingEthPeer.respondWhile(responder, () -> !future.isDone()); + + final AtomicReference result = new AtomicReference<>(); + future.whenComplete( + (response, error) -> { + result.set(response); + }); + + Assertions.assertThat(result.get().getHash()) + .isEqualTo(MainnetBlockHeaderFunctions.createHash(commonHeader)); + + Mockito.verify(peerTaskExecutor) + .executeAgainstPeer( + Mockito.any(GetHeadersFromPeerTask.class), Mockito.eq(respondingEthPeer.getEthPeer())); + } + @Test public void returnsImmediatelyWhenThereIsNoWorkToDo() throws Exception { final RespondingEthPeer respondingEthPeer = @@ -262,6 +410,32 @@ public void returnsImmediatelyWhenThereIsNoWorkToDo() throws Exception { ethContext, peer, defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), + metricsSystem); + + final CompletableFuture result = task.run(); + assertThat(result).isCompletedWithValue(localGenesisBlock.getHeader()); + + // Make sure we didn't ask for any headers + verify(peer, times(0)).getHeadersByHash(any(), anyInt(), anyInt(), anyBoolean()); + verify(peer, times(0)).getHeadersByNumber(anyLong(), anyInt(), anyInt(), anyBoolean()); + verify(peer, times(0)).send(any()); + } + + @Test + public void returnsImmediatelyWhenThereIsNoWorkToDoUsingPeerTaskSystem() throws Exception { + final RespondingEthPeer respondingEthPeer = + spy(EthProtocolManagerTestUtil.createPeer(ethProtocolManager)); + final EthPeer peer = spy(respondingEthPeer.getEthPeer()); + + final EthTask task = + DetermineCommonAncestorTask.create( + protocolSchedule, + protocolContext, + ethContext, + peer, + defaultHeaderRequestSize, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), metricsSystem); final CompletableFuture result = task.run(); @@ -334,4 +508,27 @@ private Blockchain setupLocalAndRemoteChains( return remoteChain; } + + private Answer>> peerTaskExecutorResultAnswer( + final Blockchain remoteBlockchain) { + return new Answer>>() { + @Override + public PeerTaskExecutorResult> answer( + final InvocationOnMock invocationOnMock) throws Throwable { + GetHeadersFromPeerTask getHeadersTask = + invocationOnMock.getArgument(0, GetHeadersFromPeerTask.class); + long blockNumber = getHeadersTask.getBlockNumber(); + int maxHeaders = getHeadersTask.getMaxHeaders(); + int skip = getHeadersTask.getSkip(); + + List headers = new ArrayList<>(); + for (long i = blockNumber; i > blockNumber - (maxHeaders - 1) * (skip + 1); i -= skip + 1) { + headers.add(remoteBlockchain.getBlockHeader(i).get()); + } + + return new PeerTaskExecutorResult>( + Optional.of(headers), PeerTaskExecutorResponseCode.SUCCESS, Optional.empty()); + } + }; + } } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTaskTest.java index c168594d0c1..f594942afac 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/DownloadHeaderSequenceTaskTest.java @@ -30,10 +30,14 @@ import org.hyperledger.besu.ethereum.eth.manager.RespondingEthPeer; import org.hyperledger.besu.ethereum.eth.manager.ethtaskutils.RetryingMessageTaskTest; import org.hyperledger.besu.ethereum.eth.manager.exceptions.MaxRetriesReachedException; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResponseCode; +import org.hyperledger.besu.ethereum.eth.manager.peertask.PeerTaskExecutorResult; +import org.hyperledger.besu.ethereum.eth.manager.peertask.task.GetHeadersFromPeerTask; import org.hyperledger.besu.ethereum.eth.manager.task.AbstractPeerTask.PeerTaskResult; import org.hyperledger.besu.ethereum.eth.manager.task.EthTask; import org.hyperledger.besu.ethereum.eth.messages.BlockHeadersMessage; import org.hyperledger.besu.ethereum.eth.messages.EthPV62; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.ValidationPolicy; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; import org.hyperledger.besu.ethereum.mainnet.BlockHeaderValidator; @@ -51,6 +55,7 @@ import java.util.stream.Collectors; import org.junit.jupiter.api.Test; +import org.mockito.Mockito; public class DownloadHeaderSequenceTaskTest extends RetryingMessageTaskTest> { @@ -75,6 +80,7 @@ protected EthTask> createTask(final List requeste protocolSchedule, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, requestedData.size(), maxRetries, @@ -94,6 +100,7 @@ public void failsWhenPeerReturnsOnlyReferenceHeader() { protocolSchedule, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, 10, maxRetries, @@ -113,6 +120,37 @@ public void failsWhenPeerReturnsOnlyReferenceHeader() { assertNoBadBlocks(); } + @Test + public void failsWhenPeerReturnsOnlyReferenceHeaderUsingPeerTaskSystem() { + RespondingEthPeer respondingEthPeer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager); + + // Execute task and wait for response + final BlockHeader referenceHeader = blockchain.getChainHeadHeader(); + Mockito.when(peerTaskExecutor.execute(Mockito.any(GetHeadersFromPeerTask.class))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of(List.of(referenceHeader)), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingEthPeer.getEthPeer()))); + final EthTask> task = + DownloadHeaderSequenceTask.endingAtHeader( + protocolSchedule, + protocolContext, + ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + referenceHeader, + 10, + maxRetries, + validationPolicy, + metricsSystem); + final CompletableFuture> future = task.run(); + + assertThat(future.isDone()).isTrue(); + assertThat(future.isCompletedExceptionally()).isTrue(); + assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class); + assertNoBadBlocks(); + } + @Test public void failsWhenPeerReturnsOnlySubsetOfHeaders() { final RespondingEthPeer respondingPeer = @@ -125,6 +163,7 @@ public void failsWhenPeerReturnsOnlySubsetOfHeaders() { protocolSchedule, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, 10, maxRetries, @@ -157,6 +196,42 @@ public void failsWhenPeerReturnsOnlySubsetOfHeaders() { assertNoBadBlocks(); } + @Test + public void failsWhenPeerReturnsOnlySubsetOfHeadersUsingPeerTaskSystem() { + final RespondingEthPeer respondingPeer = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager); + + // Execute task and wait for response + final BlockHeader referenceHeader = blockchain.getChainHeadHeader(); + Mockito.when(peerTaskExecutor.execute(Mockito.any(GetHeadersFromPeerTask.class))) + .thenReturn( + new PeerTaskExecutorResult<>( + Optional.of( + List.of( + referenceHeader, + blockchain.getBlockHeader(referenceHeader.getNumber() - 1).get())), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingPeer.getEthPeer()))); + + final EthTask> task = + DownloadHeaderSequenceTask.endingAtHeader( + protocolSchedule, + protocolContext, + ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + referenceHeader, + 10, + maxRetries, + validationPolicy, + metricsSystem); + final CompletableFuture> future = task.run(); + + assertThat(future.isDone()).isTrue(); + assertThat(future.isCompletedExceptionally()).isTrue(); + assertThatThrownBy(future::get).hasCauseInstanceOf(MaxRetriesReachedException.class); + assertNoBadBlocks(); + } + @Test public void marksBadBlockWhenHeaderValidationFails() { final RespondingEthPeer respondingPeer = @@ -175,6 +250,7 @@ public void marksBadBlockWhenHeaderValidationFails() { protocolScheduleSpy, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, blockCount - 1, // The reference header is not included in this count maxRetries, @@ -194,6 +270,67 @@ public void marksBadBlockWhenHeaderValidationFails() { assertBadBlock(badBlock); } + @Test + public void marksBadBlockWhenHeaderValidationFailsUsingPeerTaskSystem() { + final RespondingEthPeer respondingPeer = + EthProtocolManagerTestUtil.createPeer(ethProtocolManager); + // Set up a chain with an invalid block + final int blockCount = 5; + final long startBlock = blockchain.getChainHeadBlockNumber() - blockCount; + final List chain = getBlockSequence(startBlock, blockCount); + final Block badBlock = chain.get(2); + ProtocolSchedule protocolScheduleSpy = setupHeaderValidationToFail(badBlock.getHeader()); + + Mockito.when(peerTaskExecutor.execute(Mockito.any(GetHeadersFromPeerTask.class))) + .then( + (invocationOnMock) -> { + GetHeadersFromPeerTask task = + invocationOnMock.getArgument(0, GetHeadersFromPeerTask.class); + List headers = new ArrayList<>(); + for (long i = task.getBlockNumber(); + i > task.getBlockNumber() - task.getMaxHeaders() * (task.getSkip() + 1); + i -= task.getSkip() + 1) { + Optional header = blockchain.getBlockHeader(i); + if (header.isPresent()) { + headers.add(header.get()); + } else { + break; + } + } + return new PeerTaskExecutorResult>( + Optional.of(headers), + PeerTaskExecutorResponseCode.SUCCESS, + Optional.of(respondingPeer.getEthPeer())); + }); + + // Execute the task + final BlockHeader referenceHeader = chain.get(blockCount - 1).getHeader(); + final EthTask> task = + DownloadHeaderSequenceTask.endingAtHeader( + protocolScheduleSpy, + protocolContext, + ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(true).build(), + referenceHeader, + blockCount - 1, // The reference header is not included in this count + maxRetries, + validationPolicy, + metricsSystem); + final CompletableFuture> future = task.run(); + + final RespondingEthPeer.Responder fullResponder = getFullResponder(); + respondingPeer.respondWhile(fullResponder, () -> !future.isDone()); + + // Check that the future completed exceptionally + assertThat(future.isCompletedExceptionally()).isTrue(); + assertThatThrownBy(future::get) + .hasCauseInstanceOf(InvalidBlockException.class) + .hasMessageContaining("Header failed validation"); + + // Check bad blocks + assertBadBlock(badBlock); + } + @Test public void processHeaders_markBadBlockWhenHeaderValidationFails() { final RespondingEthPeer respondingPeer = @@ -212,6 +349,7 @@ public void processHeaders_markBadBlockWhenHeaderValidationFails() { protocolScheduleSpy, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, blockCount - 1, // The reference header is not included in this count maxRetries, @@ -257,6 +395,7 @@ public void processHeaders_markBadBlockHashWhenHeaderValidationFailsAndBodyUnava protocolScheduleSpy, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, blockCount - 1, // The reference header is not included in this count maxRetries, @@ -301,6 +440,7 @@ public void processHeaders_doesNotMarkBadBlockForOutOfRangeResponse() { protocolSchedule, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, segmentLength, maxRetries, @@ -347,6 +487,7 @@ public void processHeaders_doesNotMarkBadBlockForMisorderedBlocks() { protocolSchedule, protocolContext, ethContext, + SynchronizerConfiguration.builder().isPeerTaskSystemEnabled(false).build(), referenceHeader, segmentLength, maxRetries, diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTaskTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTaskTest.java index dd5d79b6670..a39d3658bfe 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTaskTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/PersistBlockTaskTest.java @@ -25,7 +25,7 @@ import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.sync.tasks.exceptions.InvalidBlockException; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -70,7 +70,11 @@ public void setup(final DataStorageFormat storageFormat) { protocolSchedule = blockchainUtil.getProtocolSchedule(); protocolContext = blockchainUtil.getProtocolContext(); blockchain = blockchainUtil.getBlockchain(); - final EthProtocolManager ethProtocolManager = EthProtocolManagerTestUtil.create(); + final EthProtocolManager ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .build(); ethContext = ethProtocolManager.ethContext(); } diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java index e3e8046ba87..f69232eec4e 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/AbstractTransactionPoolTestBase.java @@ -32,7 +32,7 @@ import static org.mockito.Mockito.when; import static org.mockito.quality.Strictness.LENIENT; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.datatypes.BlobsWithCommitments; @@ -56,7 +56,7 @@ import org.hyperledger.besu.ethereum.core.TransactionTestFixture; import org.hyperledger.besu.ethereum.eth.manager.EthContext; import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager; -import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestUtil; +import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManagerTestBuilder; import org.hyperledger.besu.ethereum.eth.manager.EthScheduler; import org.hyperledger.besu.ethereum.eth.transactions.layered.LayeredTransactionPoolBaseFeeTest; import org.hyperledger.besu.ethereum.eth.transactions.sorter.LegacyTransactionPoolBaseFeeTest; @@ -174,7 +174,7 @@ protected TransactionTestFixture createBaseTransactionBaseFeeMarket(final int no protected abstract ExecutionContextTestFixture createExecutionContextTestFixture(); protected static ExecutionContextTestFixture createExecutionContextTestFixtureBaseFeeMarket() { - final var genesisConfigFile = GenesisConfigFile.fromResource("/txpool-test-genesis.json"); + final var genesisConfigFile = GenesisConfig.fromResource("/txpool-test-genesis.json"); final ProtocolSchedule protocolSchedule = new ProtocolScheduleBuilder( genesisConfigFile.getConfigOptions(), @@ -225,7 +225,11 @@ public void setUp() { protocolSchedule = spy(executionContext.getProtocolSchedule()); doReturn(protocolSpec).when(protocolSchedule).getByBlockHeader(any()); blockGasLimit = blockchain.getChainHeadBlock().getHeader().getGasLimit(); - ethProtocolManager = EthProtocolManagerTestUtil.create(); + ethProtocolManager = + EthProtocolManagerTestBuilder.builder() + .setProtocolSchedule(protocolSchedule) + .setBlockchain(blockchain) + .build(); ethContext = spy(ethProtocolManager.ethContext()); final EthScheduler ethScheduler = spy(ethContext.getScheduler()); diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java index af54f668fe8..393e97608e5 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/PendingTransactionEstimatedMemorySizeTest.java @@ -15,11 +15,28 @@ package org.hyperledger.besu.ethereum.eth.transactions; import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.ACCESS_LIST_ENTRY_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.ACCESS_LIST_STORAGE_KEY_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOBS_WITH_COMMITMENTS_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.BLOB_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.CODE_DELEGATION_ENTRY_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.EIP1559_AND_EIP4844_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.KZG_COMMITMENT_OR_PROOF_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_ACCESS_LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_CHAIN_ID_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_CODE_DELEGATION_LIST_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.OPTIONAL_TO_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.PAYLOAD_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.PENDING_TRANSACTION_SHALLOW_SIZE; +import static org.hyperledger.besu.ethereum.eth.transactions.PendingTransaction.MemorySize.VERSIONED_HASH_SIZE; import org.hyperledger.besu.crypto.SignatureAlgorithm; import org.hyperledger.besu.datatypes.AccessListEntry; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.BlobsWithCommitments; +import org.hyperledger.besu.datatypes.CodeDelegation; import org.hyperledger.besu.datatypes.TransactionType; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.ethereum.core.Transaction; @@ -31,6 +48,8 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import java.io.IOException; +import java.lang.management.ManagementFactory; import java.math.BigInteger; import java.util.Arrays; import java.util.HashSet; @@ -41,8 +60,10 @@ import java.util.TreeSet; import java.util.concurrent.atomic.LongAdder; import java.util.function.Function; +import javax.management.MBeanServer; import com.google.common.collect.Sets; +import com.sun.management.HotSpotDiagnosticMXBean; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.Test; @@ -53,18 +74,68 @@ import org.openjdk.jol.info.GraphVisitor; import org.openjdk.jol.info.GraphWalker; -@EnabledOnOs(OS.LINUX) +/** + * This test class has a double utility, first it is used to verify that the current memory size of + * a pending transaction object correspond to the calculated values, so if any of the tests in this + * file fails, it probably means that one of the related classes has changed its format, and a new + * calculation needs to be done. + * + *

The second utility is to help with the calculation of the memory size of a class, using the JOL Tool, to navigate the class layout and collect the + * reported memory sizes. + * + *

For a correct calculation there are some things to consider, first exclude from the + * calculation any reference to a constant object, for example if a field is always a + * reference to {@code Optional.empty()} then just count the reference size, but not the size of the + * Optional since it is always the same instance for every pending transaction. + * + *

To study the layout of a class it is usually useful to create a test method with one or more + * instance of it, then programmatically save a heap dump using the {@link #dumpHeap(String, + * boolean)} method, then analyze the heap dump with a tool to identify which are the dynamic and + * constant fields, then use the JOL Tool to print the class layout and walk in the object tree, + * then complete the writing of the test that will verify the current amount of memory used by that + * class. + */ +@EnabledOnOs({OS.LINUX, OS.MAC}) public class PendingTransactionEstimatedMemorySizeTest extends BaseTransactionPoolTest { + /** + * Classes that represent constant instances, across all pending transaction types, and are + * ignored during the calculation + */ private static final Set> SHARED_CLASSES = Set.of(SignatureAlgorithm.class, TransactionType.class); + + /** + * Field that points to constant values, across all pending transaction types, and are ignored + * during the calculation + */ private static final Set COMMON_CONSTANT_FIELD_PATHS = Set.of(".value.ctor", ".hashNoSignature", ".signature.encoded.delegate"); + + /** + * Field that points to constant values, for EIP-1559 and EIP-4844 pending transactions, and are + * ignored during the calculation + */ private static final Set EIP1559_EIP4844_CONSTANT_FIELD_PATHS = Sets.union(COMMON_CONSTANT_FIELD_PATHS, Set.of(".gasPrice")); + + /** + * Field that points to constant values, for Frontier and Access List pending transactions, and + * are ignored during the calculation + */ private static final Set FRONTIER_ACCESS_LIST_CONSTANT_FIELD_PATHS = Sets.union(COMMON_CONSTANT_FIELD_PATHS, Set.of(".maxFeePerGas", ".maxPriorityFeePerGas")); + + /** Field which value is dynamic and can only be calculated at runtime */ private static final Set VARIABLE_SIZE_PATHS = - Set.of(".chainId", ".to", ".payload", ".maybeAccessList"); + Set.of( + ".chainId", + ".to", + ".payload", + ".maybeAccessList", + ".versionedHashes", + ".blobsWithCommitments", + ".maybeCodeDelegationList"); @Test public void toSize() { @@ -100,6 +171,7 @@ public void toSize() { + ", " + gpr.klass().toString() + "]"); + System.out.println(ClassLayout.parseClass(gpr.klass()).toPrintable()); }; GraphWalker gw = new GraphWalker(gv); @@ -108,7 +180,7 @@ public void toSize() { System.out.println("Optional To size: " + size); - assertThat(size.sum()).isEqualTo(PendingTransaction.OPTIONAL_TO_MEMORY_SIZE); + assertThat(size.sum()).isEqualTo(OPTIONAL_TO_SIZE); } @Test @@ -133,7 +205,7 @@ public void payloadSize() { size.add(cl.instanceSize()); System.out.println("Base payload size: " + size); - assertThat(size.sum()).isEqualTo(PendingTransaction.PAYLOAD_BASE_MEMORY_SIZE); + assertThat(size.sum()).isEqualTo(PAYLOAD_SHALLOW_SIZE); } @Test @@ -167,39 +239,37 @@ public void chainIdSize() { gw.walk(maybeChainId); - assertThat(size.sum()).isEqualTo(PendingTransaction.OPTIONAL_CHAIN_ID_MEMORY_SIZE); + assertThat(size.sum()).isEqualTo(OPTIONAL_CHAIN_ID_SIZE); } @Test public void kgzCommitmentsSize() { blobsWithCommitmentsFieldSize( t -> t.getBlobsWithCommitments().get().getKzgCommitments(), - PendingTransaction.BASE_LIST_SIZE, - PendingTransaction.KZG_COMMITMENT_OR_PROOF_SIZE); + LIST_SHALLOW_SIZE, + KZG_COMMITMENT_OR_PROOF_SIZE); } @Test public void kgzProofsSize() { blobsWithCommitmentsFieldSize( t -> t.getBlobsWithCommitments().get().getKzgProofs(), - PendingTransaction.BASE_LIST_SIZE, - PendingTransaction.KZG_COMMITMENT_OR_PROOF_SIZE); + LIST_SHALLOW_SIZE, + KZG_COMMITMENT_OR_PROOF_SIZE); } @Test public void blobsSize() { blobsWithCommitmentsFieldSize( - t -> t.getBlobsWithCommitments().get().getBlobs(), - PendingTransaction.BASE_LIST_SIZE, - PendingTransaction.BLOB_SIZE); + t -> t.getBlobsWithCommitments().get().getBlobs(), LIST_SHALLOW_SIZE, BLOB_SIZE); } @Test public void versionedHashesSize() { blobsWithCommitmentsFieldSize( t -> t.getBlobsWithCommitments().get().getVersionedHashes(), - PendingTransaction.BASE_LIST_SIZE, - PendingTransaction.VERSIONED_HASH_SIZE); + LIST_SHALLOW_SIZE, + VERSIONED_HASH_SIZE); } private void blobsWithCommitmentsFieldSize( @@ -260,8 +330,7 @@ public void blobsWithCommitmentsSize() { System.out.println(rl.toPrintable()); System.out.println("BlobQuad size:" + rl.instanceSize()); - assertThat(cl.instanceSize() + rl.instanceSize()) - .isEqualTo(PendingTransaction.BLOBS_WITH_COMMITMENTS_SIZE); + assertThat(cl.instanceSize() + rl.instanceSize()).isEqualTo(BLOBS_WITH_COMMITMENTS_SIZE); } @Test @@ -287,7 +356,7 @@ public void pendingTransactionSize() { size.add(cl.instanceSize()); System.out.println("PendingTransaction size: " + size); - assertThat(size.sum()).isEqualTo(PendingTransaction.PENDING_TRANSACTION_MEMORY_SIZE); + assertThat(size.sum()).isEqualTo(PENDING_TRANSACTION_SHALLOW_SIZE); } @Test @@ -313,15 +382,18 @@ public void accessListSize() { final var optAL = txAccessList.getAccessList(); - final ClassLayout cl1 = ClassLayout.parseInstance(optAL); - System.out.println(cl1.toPrintable()); - System.out.println("Optional size: " + cl1.instanceSize()); + final ClassLayout optionalClassLayout = ClassLayout.parseInstance(optAL); + System.out.println(optionalClassLayout.toPrintable()); + System.out.println("Optional size: " + optionalClassLayout.instanceSize()); - final ClassLayout cl2 = ClassLayout.parseInstance(optAL.get()); - System.out.println(cl2.toPrintable()); - System.out.println("Optional + list size: " + cl2.instanceSize()); + final ClassLayout listClassLayout = ClassLayout.parseInstance(optAL.get()); + System.out.println(listClassLayout.toPrintable()); + System.out.println( + "Optional + list size: " + + (optionalClassLayout.instanceSize() + listClassLayout.instanceSize())); - assertThat(cl2.instanceSize()).isEqualTo(PendingTransaction.OPTIONAL_ACCESS_LIST_MEMORY_SIZE); + assertThat(optionalClassLayout.instanceSize() + listClassLayout.instanceSize()) + .isEqualTo(OPTIONAL_ACCESS_LIST_SHALLOW_SIZE); final AccessListEntry ale = optAL.get().get(0); @@ -329,92 +401,100 @@ public void accessListSize() { System.out.println("AccessListEntry container size: " + aleSize); - assertThat(aleSize).isEqualTo(PendingTransaction.ACCESS_LIST_ENTRY_BASE_MEMORY_SIZE); + assertThat(aleSize).isEqualTo(ACCESS_LIST_ENTRY_SHALLOW_SIZE); final Bytes32 storageKey = ale.storageKeys().get(0); final ClassLayout cl4 = ClassLayout.parseInstance(storageKey); System.out.println(cl4.toPrintable()); System.out.println("Single storage key size: " + cl4.instanceSize()); - assertThat(cl4.instanceSize()) - .isEqualTo(PendingTransaction.ACCESS_LIST_STORAGE_KEY_MEMORY_SIZE); + assertThat(cl4.instanceSize()).isEqualTo(ACCESS_LIST_STORAGE_KEY_SIZE); } @Test - public void baseEIP1559AndEIP4844TransactionMemorySize() { + public void codeDelegationListSize() { System.setProperty("jol.magicFieldOffset", "true"); - Transaction txEip1559 = createEIP1559Transaction(1, KEYS1, 10); + + TransactionTestFixture preparedTx = + prepareTransaction(TransactionType.DELEGATE_CODE, 0, Wei.of(500), Wei.ZERO, 0, 0); + Transaction txDelegateCode = preparedTx.createTransaction(KEYS1); BytesValueRLPOutput rlpOut = new BytesValueRLPOutput(); - txEip1559.writeTo(rlpOut); + txDelegateCode.writeTo(rlpOut); - txEip1559 = + txDelegateCode = Transaction.readFrom(new BytesValueRLPInput(rlpOut.encoded(), false)).detachedCopy(); - System.out.println(txEip1559.getSender()); - System.out.println(txEip1559.getHash()); - System.out.println(txEip1559.getSize()); + System.out.println(txDelegateCode.getSender()); + System.out.println(txDelegateCode.getHash()); + System.out.println(txDelegateCode.getSize()); - final ClassLayout cl = ClassLayout.parseInstance(txEip1559); - System.out.println(cl.toPrintable()); - LongAdder eip1559size = new LongAdder(); - eip1559size.add(cl.instanceSize()); - System.out.println(eip1559size); + final var optCD = txDelegateCode.getCodeDelegationList(); - final SortedSet fieldSizes = new TreeSet<>(); - GraphWalker gw = getGraphWalker(EIP1559_EIP4844_CONSTANT_FIELD_PATHS, fieldSizes); + final ClassLayout optionalClassLayout = ClassLayout.parseInstance(optCD); + System.out.println(optionalClassLayout.toPrintable()); + System.out.println("Optional size: " + optionalClassLayout.instanceSize()); - gw.walk(txEip1559); + final ClassLayout listClassLayout = ClassLayout.parseInstance(optCD.get()); + System.out.println(listClassLayout.toPrintable()); + System.out.println( + "Optional + list size: " + + (optionalClassLayout.instanceSize() + listClassLayout.instanceSize())); - fieldSizes.forEach( - fieldSize -> { - eip1559size.add(fieldSize.size()); - System.out.println( - "(" - + eip1559size - + ")[" - + fieldSize.size() - + ", " - + fieldSize.path() - + ", " - + fieldSize - + "]"); - }); + assertThat(optionalClassLayout.instanceSize() + listClassLayout.instanceSize()) + .isEqualTo(OPTIONAL_CODE_DELEGATION_LIST_SHALLOW_SIZE); + + final CodeDelegation codeDelegation = optCD.get().get(0); + + long cdSize = sizeOfField(codeDelegation, "storageKeys.elementData["); - System.out.println("Base EIP1559 size: " + eip1559size); - assertThat(eip1559size.sum()) - .isEqualTo(PendingTransaction.EIP1559_AND_EIP4844_SHALLOW_MEMORY_SIZE); + System.out.println("CodeDelegation container size: " + cdSize); + + assertThat(cdSize).isEqualTo(CODE_DELEGATION_ENTRY_SIZE); + } + + @Test + public void baseEIP1559AndEIP4844TransactionMemorySize() { + Transaction txEip1559 = createEIP1559Transaction(1, KEYS1, 10); + assertThat(baseTransactionMemorySize(txEip1559, EIP1559_EIP4844_CONSTANT_FIELD_PATHS)) + .isEqualTo(EIP1559_AND_EIP4844_SHALLOW_SIZE); } @Test public void baseFrontierAndAccessListTransactionMemorySize() { + final Transaction txFrontier = + createTransaction(TransactionType.FRONTIER, 1, Wei.of(500), 0, KEYS1); + assertThat(baseTransactionMemorySize(txFrontier, FRONTIER_ACCESS_LIST_CONSTANT_FIELD_PATHS)) + .isEqualTo(FRONTIER_AND_ACCESS_LIST_SHALLOW_SIZE); + } + + private long baseTransactionMemorySize(final Transaction tx, final Set constantFields) { System.setProperty("jol.magicFieldOffset", "true"); - Transaction txFrontier = createTransaction(TransactionType.FRONTIER, 1, Wei.of(500), 0, KEYS1); BytesValueRLPOutput rlpOut = new BytesValueRLPOutput(); - txFrontier.writeTo(rlpOut); + tx.writeTo(rlpOut); - txFrontier = + final var baseTx = Transaction.readFrom(new BytesValueRLPInput(rlpOut.encoded(), false)).detachedCopy(); - System.out.println(txFrontier.getSender()); - System.out.println(txFrontier.getHash()); - System.out.println(txFrontier.getSize()); + System.out.println(baseTx.getSender()); + System.out.println(baseTx.getHash()); + System.out.println(baseTx.getSize()); - final ClassLayout cl = ClassLayout.parseInstance(txFrontier); + final ClassLayout cl = ClassLayout.parseInstance(baseTx); System.out.println(cl.toPrintable()); - LongAdder frontierSize = new LongAdder(); - frontierSize.add(cl.instanceSize()); - System.out.println(frontierSize); + LongAdder baseTxSize = new LongAdder(); + baseTxSize.add(cl.instanceSize()); + System.out.println(baseTxSize); final SortedSet fieldSizes = new TreeSet<>(); - GraphWalker gw = getGraphWalker(FRONTIER_ACCESS_LIST_CONSTANT_FIELD_PATHS, fieldSizes); + GraphWalker gw = getGraphWalker(constantFields, fieldSizes); - gw.walk(txFrontier); + gw.walk(baseTx); fieldSizes.forEach( fieldSize -> { - frontierSize.add(fieldSize.size()); + baseTxSize.add(fieldSize.size()); System.out.println( "(" - + frontierSize + + baseTxSize + ")[" + fieldSize.size() + ", " @@ -423,10 +503,8 @@ public void baseFrontierAndAccessListTransactionMemorySize() { + fieldSize + "]"); }); - - System.out.println("Base Frontier size: " + frontierSize); - assertThat(frontierSize.sum()) - .isEqualTo(PendingTransaction.FRONTIER_AND_ACCESS_LIST_SHALLOW_MEMORY_SIZE); + System.out.println("Base tx size: " + baseTxSize); + return baseTxSize.sum(); } private GraphWalker getGraphWalker( @@ -478,6 +556,7 @@ private long sizeOfField(final Object container, final String... excludePaths) { + ", " + gpr.klass().toString() + "]"); + System.out.println(ClassLayout.parseClass(gpr.klass()).toPrintable()); } }; @@ -489,6 +568,24 @@ private long sizeOfField(final Object container, final String... excludePaths) { return size.sum(); } + /** + * Utility method useful for producing a heap dump when calculating the memory size of a new + * object. Note that the file is not overwritten, so you need to remove it to create a new heap + * dump. + * + * @param filePath where to save the heap dump + * @param live true to only include live objects + * @throws IOException if any errors happen during the saving + */ + @SuppressWarnings("unused") + private static void dumpHeap(final String filePath, final boolean live) throws IOException { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + HotSpotDiagnosticMXBean mxBean = + ManagementFactory.newPlatformMXBeanProxy( + server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); + mxBean.dumpHeap(filePath, live); + } + record FieldSize(String path, Class clazz, long size) implements Comparable { @Override diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java index d042996ce7a..e29b8285c9c 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TestNode.java @@ -23,7 +23,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.crypto.KeyPair; import org.hyperledger.besu.cryptoservices.NodeKey; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; @@ -117,10 +117,10 @@ public TestNode( .setBindPort(listenPort) .setSupportedProtocols(EthProtocol.get())); - final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromResource("/dev.json"); + final GenesisConfig genesisConfig = GenesisConfig.fromResource("/dev.json"); final ProtocolSchedule protocolSchedule = FixedDifficultyProtocolSchedule.create( - GenesisConfigFile.fromResource("/dev.json").getConfigOptions(), + GenesisConfig.fromResource("/dev.json").getConfigOptions(), false, EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, @@ -128,7 +128,7 @@ public TestNode( false, new NoOpMetricsSystem()); - final GenesisState genesisState = GenesisState.fromConfig(genesisConfigFile, protocolSchedule); + final GenesisState genesisState = GenesisState.fromConfig(genesisConfig, protocolSchedule); final BlockHeaderFunctions blockHeaderFunctions = ScheduleBasedBlockHeaderFunctions.create(protocolSchedule); final MutableBlockchain blockchain = @@ -154,7 +154,6 @@ public boolean isMessagePermitted(final EnodeURL destinationEnode, final int cod }; final EthPeers ethPeers = new EthPeers( - EthProtocol.NAME, () -> protocolSchedule.getByBlockHeader(blockchain.getChainHeadHeader()), TestClock.fixed(), metricsSystem, @@ -171,7 +170,7 @@ public boolean isMessagePermitted(final EnodeURL destinationEnode, final int cod ethPeers.setChainHeadTracker(mockCHT); final EthScheduler scheduler = new EthScheduler(1, 1, 1, metricsSystem); - final EthContext ethContext = new EthContext(ethPeers, ethMessages, scheduler); + final EthContext ethContext = new EthContext(ethPeers, ethMessages, scheduler, null); transactionPool = TransactionPoolFactory.createTransactionPool( diff --git a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java index 612a1de9dfb..11b0f59f690 100644 --- a/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java +++ b/ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/transactions/TransactionPoolFactoryTest.java @@ -112,7 +112,6 @@ public void setup() { final NodeMessagePermissioningProvider nmpp = (destinationEnode, code) -> true; ethPeers = new EthPeers( - "ETH", () -> protocolSpec, TestClock.fixed(), new NoOpMetricsSystem(), diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index 2574d4b8e39..0ff6a21da83 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -30,7 +30,6 @@ import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.EvmSpecVersion; @@ -464,9 +463,9 @@ public void run() { .coinbase(coinbase) .difficulty( Difficulty.fromHexString( - genesisFileModule.providesGenesisConfigFile().getDifficulty())) + genesisFileModule.providesGenesisConfig().getDifficulty())) .number(0) - .gasLimit(genesisFileModule.providesGenesisConfigFile().getGasLimit()) + .gasLimit(genesisFileModule.providesGenesisConfig().getGasLimit()) .timestamp(0) .ommersHash(Hash.EMPTY_LIST_HASH) .stateRoot(Hash.EMPTY_TRIE_HASH) @@ -483,7 +482,7 @@ public void run() { .getBlockchain() .getChainHeadHeader() .getBaseFee() - .or(() -> genesisFileModule.providesGenesisConfigFile().getBaseFeePerGas()) + .or(() -> genesisFileModule.providesGenesisConfig().getBaseFeePerGas()) .orElse( protocolSpec.getFeeMarket().implementsBaseFee() ? Wei.of(0xa) : null)) .buildBlockHeader(); @@ -511,7 +510,10 @@ public void run() { .blockValues(blockHeader) .completer(c -> {}) .miningBeneficiary(blockHeader.getCoinbase()) - .blockHashLookup(new CachingBlockHashLookup(blockHeader, component.getBlockchain())) + .blockHashLookup( + protocolSpec + .getBlockHashProcessor() + .createBlockHashLookup(component.getBlockchain(), blockHeader)) .accessListWarmAddresses(addressList) .build(); Deque messageFrameStack = initialMessageFrame.getMessageFrameStack(); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java index 8512b5537e0..7af024bf18b 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java @@ -16,7 +16,7 @@ import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.GenesisConfigOptions; import org.hyperledger.besu.datatypes.HardforkId.MainnetHardforkId; import org.hyperledger.besu.ethereum.chain.GenesisState; @@ -64,14 +64,14 @@ protected GenesisFileModule(final String genesisConfig) { @Singleton @Provides - GenesisConfigFile providesGenesisConfigFile() { - return GenesisConfigFile.fromConfig(genesisConfig); + GenesisConfig providesGenesisConfig() { + return GenesisConfig.fromConfig(genesisConfig); } @Singleton @Provides - GenesisConfigOptions provideGenesisConfigOptions(final GenesisConfigFile genesisConfigFile) { - return genesisConfigFile.getConfigOptions(); + GenesisConfigOptions provideGenesisConfigOptions(final GenesisConfig genesisConfig) { + return genesisConfig.getConfigOptions(); } @Singleton @@ -88,8 +88,8 @@ ProtocolSchedule provideProtocolSchedule( @Singleton @Provides GenesisState provideGenesisState( - final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) { - return GenesisState.fromConfig(genesisConfigFile, protocolSchedule); + final GenesisConfig genesisConfig, final ProtocolSchedule protocolSchedule) { + return GenesisState.fromConfig(genesisConfig, protocolSchedule); } @Singleton diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java index f6e05b5a498..b15aec6b9d0 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java @@ -270,7 +270,10 @@ private void traceTestSpecs(final String test, final List Hash.hash(Bytes.wrap(Long.toString(blockNumber).getBytes(UTF_8))), + (__, blockNumber) -> + blockNumber >= blockHeader.getNumber() + ? Hash.ZERO + : Hash.hash(Bytes.wrap(Long.toString(blockNumber).getBytes(UTF_8))), false, TransactionValidationParams.processingBlock(), tracer, diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java index ba55fdf29ea..14f1cce978c 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/T8nExecutor.java @@ -52,8 +52,9 @@ import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.trie.diffbased.common.DiffBasedAccount; -import org.hyperledger.besu.ethereum.vm.CachingBlockHashLookup; +import org.hyperledger.besu.ethereum.vm.BlockchainBasedBlockHashLookup; import org.hyperledger.besu.evm.account.Account; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.log.Log; import org.hyperledger.besu.evm.tracing.OperationTracer; @@ -231,10 +232,14 @@ protected static List extractTransactions( final long authorizationNonce = Bytes.fromHexStringLenient(entryAsJson.get("nonce").textValue()).toLong(); - final byte authorizationV = + final BigInteger authorizationV = Bytes.fromHexStringLenient(entryAsJson.get("v").textValue()) - .toUnsignedBigInteger() - .byteValueExact(); + .toUnsignedBigInteger(); + if (authorizationV.compareTo(BigInteger.valueOf(256)) >= 0) { + throw new IllegalArgumentException( + "Invalid authorizationV value. Must be less than 256"); + } + final BigInteger authorizationR = Bytes.fromHexStringLenient(entryAsJson.get("r").textValue()) .toUnsignedBigInteger(); @@ -243,7 +248,7 @@ protected static List extractTransactions( .toUnsignedBigInteger(); final SECPSignature authorizationSignature = - new SECPSignature(authorizationR, authorizationS, authorizationV); + new SECPSignature(authorizationR, authorizationS, authorizationV.byteValue()); authorizations.add( new org.hyperledger.besu.ethereum.core.CodeDelegation( @@ -349,9 +354,7 @@ static T8nResult runTest( long blobGasLimit = protocolSpec.getGasLimitCalculator().currentBlobGasLimit(); if (!referenceTestEnv.isStateTest()) { - protocolSpec - .getBlockHashProcessor() - .processBlockHashes(blockchain, worldState, referenceTestEnv); + protocolSpec.getBlockHashProcessor().processBlockHashes(worldState, referenceTestEnv); } final WorldUpdater rootWorldStateUpdater = worldState.updater(); @@ -385,13 +388,28 @@ static T8nResult runTest( tracer = tracerManager.getManagedTracer(transactionIndex, transaction.getHash()); tracer.tracePrepareTransaction(worldStateUpdater, transaction); tracer.traceStartTransaction(worldStateUpdater, transaction); + BlockHashLookup blockHashLookup = + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader); + if (blockHashLookup instanceof BlockchainBasedBlockHashLookup) { + // basically t8n test cases for blockhash are broken and one cannot create a blockchain + // from them so need to + // add in a manual BlockHashLookup + blockHashLookup = + (__, blockNumber) -> { + if (referenceTestEnv.getNumber() - blockNumber > 256L + || blockNumber >= referenceTestEnv.getNumber()) { + return Hash.ZERO; + } + return referenceTestEnv.getBlockhashByNumber(blockNumber).orElse(Hash.ZERO); + }; + } result = processor.processTransaction( worldStateUpdater, blockHeader, transaction, blockHeader.getCoinbase(), - number -> referenceTestEnv.getBlockhashByNumber(number).orElse(Hash.ZERO), + blockHashLookup, false, TransactionValidationParams.processingBlock(), tracer, @@ -524,7 +542,7 @@ static T8nResult runTest( worldState, protocolSpec, receipts, - new CachingBlockHashLookup(blockHeader, blockchain), + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader), OperationTracer.NO_TRACING); Optional> maybeRequests = Optional.of(rpc.process(context)); Hash requestsHash = BodyValidation.requestsHash(maybeRequests.orElse(List.of())); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java index 35d5de5d666..c3eb1ea307a 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java @@ -63,7 +63,7 @@ public abstract class BenchmarkExecutor { .code(CodeV0.EMPTY_CODE) .completer(__ -> {}) .address(Address.ZERO) - .blockHashLookup(n -> null) + .blockHashLookup((__, ___) -> null) .blockValues(new SimpleBlockValues()) .gasPrice(Wei.ZERO) .miningBeneficiary(Address.ZERO) diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal-request.json similarity index 88% rename from ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json rename to ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal-request.json index 35f9843231d..615161c88d8 100644 --- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal.json +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/t8n/prague-withdrawal-request.json @@ -51,16 +51,18 @@ "0x40": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7" } }, - "0x09fc772d0857550724b07b850a4323f39112aaaa": { + "0x0c15f14308530b7cdb8460094bbb9cc28b9aaaaa": { + "comment": "This is the runtime bytecode for the Withdrawal Request Smart Contract.", "nonce": "0x01", "balance": "0x00", - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460c7573615156028575f545f5260205ff35b36603814156101f05760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f057600182026001905f5b5f821115608057810190830284830290049160010191906065565b9093900434106101f057600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160db575060105b5f5b81811461017f5780604c02838201600302600401805490600101805490600101549160601b83528260140152807fffffffffffffffffffffffffffffffff0000000000000000000000000000000016826034015260401c906044018160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160dd565b9101809214610191579060025561019c565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101c957505f5b6001546002828201116101de5750505f6101e4565b01600290035b5f555f600155604c025ff35b5f5ffd", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd", "storage": {} }, - "0x01abea29659e5e97c95107f20bb753cd3e09bbbb": { + "0x00431f263ce400f4455c2dcf564e53007ca4bbbb": { + "comment": "Increase the MAX_EFFECTIVE_BALANCE", "nonce": "0x01", "balance": "0x00", - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cf573615156028575f545f5260205ff35b366060141561019a5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f821115608057810190830284830290049160010191906065565b90939004341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060011160e3575060015b5f5b8181146101295780607402838201600402600401805490600101805490600101805490600101549260601b84529083601401528260340152906054015260010160e5565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd", + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd", "storage": {} }, "0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": { @@ -82,9 +84,10 @@ "storage": {} }, "0x0000000000000000000000000000000000001000": { + "comment": "This is a proxy contract that calls 0c15f14308530b7cdb8460094bbb9cc28b9aaaaa ie Withdrawal Request", "nonce": "0x01", "balance": "0xad78ebc5ac62000000", - "code": "0x60386000600037600060006038600060017309fc772d0857550724b07b850a4323f39112aaaa620f4240f150", + "code": "0x6038600060003760006000603860006001730c15f14308530b7cdb8460094bbb9cc28b9aaaaa620f4240f150", "storage": {} } }, @@ -131,7 +134,7 @@ "stdout": { "alloc": { "0x0000000000000000000000000000000000001000": { - "code": "0x60386000600037600060006038600060017309fc772d0857550724b07b850a4323f39112aaaa620f4240f150", + "code": "0x6038600060003760006000603860006001730c15f14308530b7cdb8460094bbb9cc28b9aaaaa620f4240f150", "balance": "0xad78ebc5ac61ffffff", "nonce": "0x1" }, @@ -181,13 +184,21 @@ "balance": "0x0", "nonce": "0x1" }, - "0x01abea29659e5e97c95107f20bb753cd3e09bbbb": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cf573615156028575f545f5260205ff35b366060141561019a5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f821115608057810190830284830290049160010191906065565b90939004341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060011160e3575060015b5f5b8181146101295780607402838201600402600401805490600101805490600101805490600101549260601b84529083601401528260340152906054015260010160e5565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd", + "0x00431f263ce400f4455c2dcf564e53007ca4bbbb": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460d35760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1461019a57600182026001905f5b5f82111560685781019083028483029004916001019190604d565b9093900492505050366060146088573661019a573461019a575f5260205ff35b341061019a57600154600101600155600354806004026004013381556001015f358155600101602035815560010160403590553360601b5f5260605f60143760745fa0600101600355005b6003546002548082038060021160e7575060025b5f5b8181146101295782810160040260040181607402815460601b815260140181600101548152602001816002015481526020019060030154905260010160e9565b910180921461013b5790600255610146565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff141561017357505f5b6001546001828201116101885750505f61018e565b01600190035b5f555f6001556074025ff35b5f5ffd", "balance": "0x0", "nonce": "0x1" }, - "0x09fc772d0857550724b07b850a4323f39112aaaa": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460c7573615156028575f545f5260205ff35b36603814156101f05760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f057600182026001905f5b5f821115608057810190830284830290049160010191906065565b9093900434106101f057600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160db575060105b5f5b81811461017f5780604c02838201600302600401805490600101805490600101549160601b83528260140152807fffffffffffffffffffffffffffffffff0000000000000000000000000000000016826034015260401c906044018160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160dd565b9101809214610191579060025561019c565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101c957505f5b6001546002828201116101de5750505f6101e4565b01600290035b5f555f600155604c025ff35b5f5ffd", + "0x0aae40965e6800cd9b1f4b05ff21581047e3f91e":{ + "code":"0x3373fffffffffffffffffffffffffffffffffffffffe1460575767ffffffffffffffff5f3511605357600143035f3511604b575f35612000014311604b57611fff5f3516545f5260205ff35b5f5f5260205ff35b5f5ffd5b5f35611fff60014303165500", + "storage":{ + "0x0000000000000000000000000000000000000000000000000000000000000000":"0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb" + }, + "balance":"0x0", + "nonce":"0x1" + }, + "0x0c15f14308530b7cdb8460094bbb9cc28b9aaaaa": { + "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460cb5760115f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146101f457600182026001905f5b5f82111560685781019083028483029004916001019190604d565b909390049250505036603814608857366101f457346101f4575f5260205ff35b34106101f457600154600101600155600354806003026004013381556001015f35815560010160203590553360601b5f5260385f601437604c5fa0600101600355005b6003546002548082038060101160df575060105b5f5b8181146101835782810160030260040181604c02815460601b8152601401816001015481526020019060020154807fffffffffffffffffffffffffffffffff00000000000000000000000000000000168252906010019060401c908160381c81600701538160301c81600601538160281c81600501538160201c81600401538160181c81600301538160101c81600201538160081c81600101535360010160e1565b910180921461019557906002556101a0565b90505f6002555f6003555b5f54807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14156101cd57505f5b6001546002828201116101e25750505f6101e8565b01600290035b5f555f600155604c025ff35b5f5ffd", "storage": { "0x0000000000000000000000000000000000000000000000000000000000000004": "0x0000000000000000000000000000000000000000000000000000000000001000", "0x0000000000000000000000000000000000000000000000000000000000000006": "0x0000000000000000000000000000000100000000000000000000000000000000" @@ -195,16 +206,8 @@ "balance": "0x1", "nonce": "0x1" }, - "0x0aae40965e6800cd9b1f4b05ff21581047e3f91e": { - "code": "0x3373fffffffffffffffffffffffffffffffffffffffe1460575767ffffffffffffffff5f3511605357600143035f3511604b575f35612000014311604b57611fff5f3516545f5260205ff35b5f5f5260205ff35b5f5ffd5b5f35611fff60014303165500", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x10715cfbefdb8a0cb2f7d7ca5ee6d1ea65515ecb41cff0a22d1e11716a9d27fb" - }, - "balance": "0x0", - "nonce": "0x1" - }, "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b": { - "balance": "0xad78ebc5ac61f2afcb", + "balance": "0xad78ebc5ac61f2b034", "nonce": "0x1" } }, @@ -216,20 +219,20 @@ "0x00000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000", "0x" ], - "stateRoot": "0x23d988164325beeeea1044c9f104ff4fe108038369f26a3327198ce40f827430", + "stateRoot": "0x575019750f84d65daf5469b26d05ad8e4335c63011dbca71ca97420cbd80d579", "txRoot": "0x0d36638e52999b7beafa00eb94f7ca23139774cd14229c011d0edc1fc66125c9", - "receiptsRoot": "0x3d22e243cbebced1fafba149bce09285797af6c66ce901ff3ab1caf073fca791", - "logsHash": "0xf69b003be75aaafefa35aa30e6367f732dd9b31a6c97196febc285ee9289bb60", - "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "receiptsRoot": "0x2af83312a6aa55bd8f169e65eec48f92d6d6dc3398bc038d7ccfab5d9aa26b3f", + "logsHash": "0xac344ad50aad544ec284bf76ac9b939f93e00f8fe16097a151df14bde2065f83", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000", "receipts": [ { "root": "0x", "status": "0x1", - "cumulativeGasUsed": "0x1e6e3", - "logsBloom": "0x00000000000000000000000008000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "cumulativeGasUsed": "0x1e6d4", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000", "logs": [ { - "address": "0x09fc772d0857550724b07b850a4323f39112aaaa", + "address": "0x0c15f14308530b7cdb8460094bbb9cc28b9aaaaa", "topics": [], "data": "0x00000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000", "blockNumber": 1, @@ -242,13 +245,13 @@ ], "transactionHash": "0xa888ec4587b7ba70d0127004a96fbb0a83ccb611e61405094e6514b970bf37f6", "contractAddress": "0x0000000000000000000000000000000000000000", - "gasUsed": "0x1e6e3", + "gasUsed": "0x1e6d4", "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "transactionIndex": "0x0" } ], "currentDifficulty": null, - "gasUsed": "0x1e6e3", + "gasUsed": "0x1e6d4", "currentBaseFee": "0x7", "withdrawalsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", "currentExcessBlobGas": "0x0", diff --git a/ethereum/p2p/build.gradle b/ethereum/p2p/build.gradle index 7cfcf2f8d58..6ed42425e0a 100644 --- a/ethereum/p2p/build.gradle +++ b/ethereum/p2p/build.gradle @@ -35,7 +35,6 @@ dependencies { implementation project(':datatypes') implementation project(':ethereum:core') implementation project(':ethereum:rlp') - implementation project(':pki') implementation project(':metrics:core') implementation project(':nat') implementation project(':util') diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java index 55a536976fe..610ebd39d8a 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetwork.java @@ -44,7 +44,6 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.MessageCallback; import org.hyperledger.besu.ethereum.p2p.rlpx.RlpxAgent; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.ShouldConnectCallback; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; @@ -520,7 +519,6 @@ public static class Builder { private NatService natService = new NatService(Optional.empty()); private MetricsSystem metricsSystem; private StorageProvider storageProvider; - private Optional p2pTLSConfiguration = Optional.empty(); private Blockchain blockchain; private List blockNumberForks; private List timestampForks; @@ -605,7 +603,6 @@ private RlpxAgent createRlpxAgent( .peerPrivileges(peerPrivileges) .localNode(localNode) .metricsSystem(metricsSystem) - .p2pTLSConfiguration(p2pTLSConfiguration) .allConnectionsSupplier(allConnectionsSupplier) .allActiveConnectionsSupplier(allActiveConnectionsSupplier) .maxPeers(maxPeers) @@ -684,12 +681,6 @@ public Builder storageProvider(final StorageProvider storageProvider) { return this; } - public Builder p2pTLSConfiguration(final Optional p2pTLSConfiguration) { - checkNotNull(p2pTLSConfiguration); - this.p2pTLSConfiguration = p2pTLSConfiguration; - return this; - } - public Builder blockchain(final MutableBlockchain blockchain) { checkNotNull(blockchain); this.blockchain = blockchain; diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/RlpxAgent.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/RlpxAgent.java index 7363b765d4d..48c417fda44 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/RlpxAgent.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/RlpxAgent.java @@ -30,8 +30,6 @@ import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnectionEvents; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerRlpxPermissions; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.NettyConnectionInitializer; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.NettyTLSConnectionInitializer; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.ShouldConnectCallback; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.messages.DisconnectMessage.DisconnectReason; @@ -371,7 +369,6 @@ public static class Builder { private ConnectionInitializer connectionInitializer; private PeerConnectionEvents connectionEvents; private MetricsSystem metricsSystem; - private Optional p2pTLSConfiguration; private Supplier> allConnectionsSupplier; private Supplier> allActiveConnectionsSupplier; private int maxPeers; @@ -386,23 +383,10 @@ public RlpxAgent build() { connectionEvents = new PeerConnectionEvents(metricsSystem); } if (connectionInitializer == null) { - if (p2pTLSConfiguration.isPresent()) { - LOG.debug("TLS Configuration found using NettyTLSConnectionInitializer"); - connectionInitializer = - new NettyTLSConnectionInitializer( - nodeKey, - config, - localNode, - connectionEvents, - metricsSystem, - p2pTLSConfiguration.get(), - peerTable); - } else { - LOG.debug("Using default NettyConnectionInitializer"); - connectionInitializer = - new NettyConnectionInitializer( - nodeKey, config, localNode, connectionEvents, metricsSystem, peerTable); - } + LOG.debug("Using default NettyConnectionInitializer"); + connectionInitializer = + new NettyConnectionInitializer( + nodeKey, config, localNode, connectionEvents, metricsSystem, peerTable); } final PeerRlpxPermissions rlpxPermissions = @@ -475,11 +459,6 @@ public Builder metricsSystem(final MetricsSystem metricsSystem) { return this; } - public Builder p2pTLSConfiguration(final Optional p2pTLSConfiguration) { - this.p2pTLSConfiguration = p2pTLSConfiguration; - return this; - } - public Builder allConnectionsSupplier( final Supplier> allConnectionsSupplier) { this.allConnectionsSupplier = allConnectionsSupplier; diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializer.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializer.java deleted file mode 100644 index db41c1574c7..00000000000 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializer.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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.ethereum.p2p.rlpx.connections.netty; - -import static org.hyperledger.besu.ethereum.p2p.rlpx.RlpxFrameConstants.LENGTH_FRAME_SIZE; -import static org.hyperledger.besu.ethereum.p2p.rlpx.RlpxFrameConstants.LENGTH_MAX_MESSAGE_FRAME; - -import org.hyperledger.besu.cryptoservices.NodeKey; -import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; -import org.hyperledger.besu.ethereum.p2p.discovery.internal.PeerTable; -import org.hyperledger.besu.ethereum.p2p.peers.LocalNode; -import org.hyperledger.besu.ethereum.p2p.peers.Peer; -import org.hyperledger.besu.ethereum.p2p.plain.PlainFramer; -import org.hyperledger.besu.ethereum.p2p.plain.PlainHandshaker; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnectionEventDispatcher; -import org.hyperledger.besu.ethereum.p2p.rlpx.framing.Framer; -import org.hyperledger.besu.ethereum.p2p.rlpx.handshake.HandshakeSecrets; -import org.hyperledger.besu.ethereum.p2p.rlpx.handshake.Handshaker; -import org.hyperledger.besu.plugin.data.EnodeURL; -import org.hyperledger.besu.plugin.services.MetricsSystem; - -import java.security.GeneralSecurityException; -import java.util.Optional; -import java.util.function.Supplier; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Suppliers; -import io.netty.channel.Channel; -import io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import io.netty.handler.codec.LengthFieldPrepender; -import io.netty.handler.codec.compression.SnappyFrameDecoder; -import io.netty.handler.codec.compression.SnappyFrameEncoder; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslHandler; - -public class NettyTLSConnectionInitializer extends NettyConnectionInitializer { - - private final Optional> tlsContextFactorySupplier; - private final Boolean clientHelloSniHeaderEnabled; - - public NettyTLSConnectionInitializer( - final NodeKey nodeKey, - final RlpxConfiguration config, - final LocalNode localNode, - final PeerConnectionEventDispatcher eventDispatcher, - final MetricsSystem metricsSystem, - final TLSConfiguration p2pTLSConfiguration, - final PeerTable peerTable) { - this( - nodeKey, - config, - localNode, - eventDispatcher, - metricsSystem, - defaultTlsContextFactorySupplier(p2pTLSConfiguration), - p2pTLSConfiguration.getClientHelloSniHeaderEnabled(), - peerTable); - } - - @VisibleForTesting - NettyTLSConnectionInitializer( - final NodeKey nodeKey, - final RlpxConfiguration config, - final LocalNode localNode, - final PeerConnectionEventDispatcher eventDispatcher, - final MetricsSystem metricsSystem, - final Supplier tlsContextFactorySupplier, - final Boolean clientHelloSniHeaderEnabled, - final PeerTable peerTable) { - super(nodeKey, config, localNode, eventDispatcher, metricsSystem, peerTable); - if (tlsContextFactorySupplier != null) { - this.tlsContextFactorySupplier = - Optional.of(Suppliers.memoize(tlsContextFactorySupplier::get)); - } else { - this.tlsContextFactorySupplier = Optional.empty(); - } - this.clientHelloSniHeaderEnabled = clientHelloSniHeaderEnabled; - } - - @Override - void addAdditionalOutboundHandlers(final Channel ch, final Peer peer) - throws GeneralSecurityException { - if (tlsContextFactorySupplier.isPresent()) { - final SslContext clientSslContext = - tlsContextFactorySupplier.get().get().createNettyClientSslContext(); - final EnodeURL enode = peer.getEnodeURL(); - final SslHandler sslHandler = createClientSslHandler(ch, clientSslContext, enode); - addHandlersToChannelPipeline(ch, sslHandler); - } - } - - private SslHandler createClientSslHandler( - final Channel ch, final SslContext sslContext, final EnodeURL enode) { - if (this.clientHelloSniHeaderEnabled) { - return sslContext.newHandler( - ch.alloc(), enode.getHost(), enode.getListeningPort().orElseThrow()); - } else { - return sslContext.newHandler(ch.alloc()); - } - } - - @Override - void addAdditionalInboundHandlers(final Channel ch) throws GeneralSecurityException { - if (tlsContextFactorySupplier.isPresent()) { - final SslContext serverSslContext = - tlsContextFactorySupplier.get().get().createNettyServerSslContext(); - addHandlersToChannelPipeline(ch, serverSslContext.newHandler(ch.alloc())); - } - } - - private void addHandlersToChannelPipeline(final Channel ch, final SslHandler sslHandler) { - ch.pipeline().addLast(sslHandler); - ch.pipeline().addLast(new SnappyFrameDecoder()); - ch.pipeline().addLast(new SnappyFrameEncoder()); - ch.pipeline() - .addLast( - new LengthFieldBasedFrameDecoder( - LENGTH_MAX_MESSAGE_FRAME, 0, LENGTH_FRAME_SIZE, 0, LENGTH_FRAME_SIZE)); - ch.pipeline().addLast(new LengthFieldPrepender(LENGTH_FRAME_SIZE)); - } - - @Override - public Handshaker buildInstance() { - return new PlainHandshaker(); - } - - @Override - public Framer buildFramer(final HandshakeSecrets secrets) { - return new PlainFramer(); - } - - @VisibleForTesting - static Supplier defaultTlsContextFactorySupplier( - final TLSConfiguration tlsConfiguration) { - if (tlsConfiguration == null) { - throw new IllegalStateException("TLSConfiguration cannot be null when using TLS"); - } - - return () -> { - try { - return TLSContextFactory.buildFrom(tlsConfiguration); - } catch (final Exception e) { - throw new IllegalStateException("Error creating TLSContextFactory", e); - } - }; - } -} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSConfiguration.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSConfiguration.java deleted file mode 100644 index 2bcb6ddbc65..00000000000 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSConfiguration.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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.ethereum.p2p.rlpx.connections.netty; - -import static java.util.Objects.requireNonNull; - -import java.nio.file.Path; -import java.util.function.Supplier; - -public class TLSConfiguration { - - private final String keyStoreType; - private final Path keyStorePath; - private final Supplier keyStorePasswordSupplier; - private final Path keyStorePasswordPath; - private final String trustStoreType; - private final Path trustStorePath; - private final Supplier trustStorePasswordSupplier; - private final Path trustStorePasswordPath; - private final Path crlPath; - private final String[] allowedProtocols; - private final Boolean clientHelloSniHeaderEnabled; - - private TLSConfiguration( - final String keyStoreType, - final Path keyStorePath, - final Supplier keyStorePasswordSupplier, - final Path keyStorePasswordPath, - final String trustStoreType, - final Path trustStorePath, - final Supplier trustStorePasswordSupplier, - final Path trustStorePasswordPath, - final Path crlPath, - final String[] allowedProtocols, - final Boolean clientHelloSniHeaderEnabled) { - this.keyStoreType = keyStoreType; - this.keyStorePath = keyStorePath; - this.keyStorePasswordSupplier = keyStorePasswordSupplier; - this.keyStorePasswordPath = keyStorePasswordPath; - this.trustStoreType = trustStoreType; - this.trustStorePath = trustStorePath; - this.trustStorePasswordSupplier = trustStorePasswordSupplier; - this.trustStorePasswordPath = trustStorePasswordPath; - this.crlPath = crlPath; - this.allowedProtocols = allowedProtocols; - this.clientHelloSniHeaderEnabled = clientHelloSniHeaderEnabled; - } - - public String getKeyStoreType() { - return keyStoreType; - } - - public Path getKeyStorePath() { - return keyStorePath; - } - - public String getKeyStorePassword() { - return null == keyStorePasswordSupplier ? null : keyStorePasswordSupplier.get(); - } - - public Path getKeyStorePasswordPath() { - return keyStorePasswordPath; - } - - public String getTrustStoreType() { - return trustStoreType; - } - - public Path getTrustStorePath() { - return trustStorePath; - } - - public String getTrustStorePassword() { - return null == trustStorePasswordSupplier ? null : trustStorePasswordSupplier.get(); - } - - public Path getTrustStorePasswordPath() { - return trustStorePasswordPath; - } - - public Path getCrlPath() { - return crlPath; - } - - public String[] getAllowedProtocols() { - return allowedProtocols; - } - - public Boolean getClientHelloSniHeaderEnabled() { - return clientHelloSniHeaderEnabled; - } - - public static final class Builder { - private String keyStoreType; - private Path keyStorePath; - private Supplier keyStorePasswordSupplier; - private Path keyStorePasswordPath; - private String trustStoreType; - private Path trustStorePath; - private Supplier trustStorePasswordSupplier; - private Path trustStorePasswordPath; - private Path crlPath; - private String[] allowedProtocols; - private Boolean clientHelloSniHeaderEnabled; - - private Builder() {} - - public static Builder tlsConfiguration() { - return new Builder(); - } - - public Builder withKeyStoreType(final String keyStoreType) { - this.keyStoreType = keyStoreType; - return this; - } - - public Builder withKeyStorePath(final Path keyStorePath) { - this.keyStorePath = keyStorePath; - return this; - } - - public Builder withKeyStorePasswordPath(final Path keyStorePasswordPath) { - this.keyStorePasswordPath = keyStorePasswordPath; - return this; - } - - public Builder withKeyStorePasswordSupplier(final Supplier keyStorePasswordSupplier) { - this.keyStorePasswordSupplier = keyStorePasswordSupplier; - return this; - } - - public Builder withTrustStoreType(final String trustStoreType) { - this.trustStoreType = trustStoreType; - return this; - } - - public Builder withTrustStorePath(final Path trustStorePath) { - this.trustStorePath = trustStorePath; - return this; - } - - public Builder withTrustStorePasswordSupplier( - final Supplier trustStorePasswordSupplier) { - this.trustStorePasswordSupplier = trustStorePasswordSupplier; - return this; - } - - public Builder withTrustStorePasswordPath(final Path trustStorePasswordPath) { - this.trustStorePasswordPath = trustStorePasswordPath; - return this; - } - - public Builder withCrlPath(final Path crlPath) { - this.crlPath = crlPath; - return this; - } - - public Builder withAllowedProtocols(final String[] allowedProtocols) { - this.allowedProtocols = allowedProtocols; - return this; - } - - public Builder withClientHelloSniEnabled(final Boolean clientHelloSniHeaderEnabled) { - this.clientHelloSniHeaderEnabled = clientHelloSniHeaderEnabled; - return this; - } - - public TLSConfiguration build() { - requireNonNull(keyStoreType, "Key Store Type must not be null"); - requireNonNull(keyStorePasswordSupplier, "Key Store password supplier must not be null"); - return new TLSConfiguration( - keyStoreType, - keyStorePath, - keyStorePasswordSupplier, - keyStorePasswordPath, - trustStoreType, - trustStorePath, - trustStorePasswordSupplier, - trustStorePasswordPath, - crlPath, - allowedProtocols, - clientHelloSniHeaderEnabled); - } - } -} diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactory.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactory.java deleted file mode 100644 index d3d6c6e280a..00000000000 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactory.java +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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.ethereum.p2p.rlpx.connections.netty; - -import org.hyperledger.besu.pki.keystore.HardwareKeyStoreWrapper; -import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; -import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; - -import io.netty.handler.ssl.ClientAuth; -import io.netty.handler.ssl.IdentityCipherSuiteFilter; -import io.netty.handler.ssl.JdkSslContext; -import io.netty.handler.ssl.SslContext; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class TLSContextFactory { - - private static final Logger LOG = LoggerFactory.getLogger(TLSContextFactory.class); - - private static final String[] ALLOWED_PROTOCOLS = {"TLSv1.3"}; - private static final String KEYMANAGER_FACTORY_ALGORITHM = "PKIX"; - private static final String TRUSTMANAGER_FACTORY_ALGORITHM = "PKIX"; - - private List enabledCipherSuites = null; - private KeyManagerFactory kmf; - private TrustManagerFactory tmf; - private Collection crls; - private String[] allowedProtocols; - - protected TLSContextFactory() {} - - protected TLSContextFactory( - final String keystorePass, - final KeyStoreWrapper keystoreWrapper, - final List configuredCipherSuites, - final String[] allowedProtocols) - throws GeneralSecurityException, IOException { - kmf = getKeyManagerFactory(keystoreWrapper.getKeyStore(), keystorePass); - tmf = getTrustManagerFactory(keystoreWrapper.getTrustStore()); - crls = keystoreWrapper.getCRLs(); - if (configuredCipherSuites != null && !configuredCipherSuites.isEmpty()) { - enabledCipherSuites = configuredCipherSuites; - } - this.allowedProtocols = null == allowedProtocols ? ALLOWED_PROTOCOLS : allowedProtocols; - } - - public static TLSContextFactory getInstance( - final String keyStorePassword, final KeyStoreWrapper wrapper, final String[] allowedProtocols) - throws GeneralSecurityException, IOException { - return new TLSContextFactory(keyStorePassword, wrapper, null, allowedProtocols); - } - - public static TLSContextFactory getInstance( - final String keyStorePassword, final KeyStoreWrapper wrapper) - throws GeneralSecurityException, IOException { - return new TLSContextFactory(keyStorePassword, wrapper, null, null); - } - - public SslContext createNettyServerSslContext() - throws NoSuchAlgorithmException, KeyManagementException { - final List enabledCipherSuites = getEnabledCipherSuites(); - - return new JdkSslContext( - createJavaSslContext(), - false, - enabledCipherSuites, - IdentityCipherSuiteFilter.INSTANCE, - null, - ClientAuth.REQUIRE, - null, - false); - } - - public SslContext createNettyClientSslContext() - throws NoSuchAlgorithmException, KeyManagementException { - final List enabledCipherSuites = getEnabledCipherSuites(); - - return new JdkSslContext( - createJavaSslContext(), - true, - enabledCipherSuites, - IdentityCipherSuiteFilter.INSTANCE, - null, - ClientAuth.NONE, - null, - false); - } - - public SSLContext createJavaSslContext() throws NoSuchAlgorithmException, KeyManagementException { - final SSLContext context = SSLContext.getInstance(getTlsProtocol()); - context.init( - kmf.getKeyManagers(), - null == crls || crls.isEmpty() ? tmf.getTrustManagers() : wrap(tmf.getTrustManagers()), - null); - return context; - } - - protected TrustManager[] wrap(final TrustManager[] trustMgrs) { - final TrustManager[] ret = trustMgrs.clone(); - for (int i = 0; i < ret.length; i++) { - TrustManager trustMgr = ret[i]; - if (trustMgr instanceof X509TrustManager) { - X509TrustManager x509TrustManager = (X509TrustManager) trustMgr; - ret[i] = - new X509TrustManager() { - @Override - public void checkClientTrusted( - final X509Certificate[] x509Certificates, final String s) - throws CertificateException { - checkRevoked(x509Certificates); - x509TrustManager.checkClientTrusted(x509Certificates, s); - } - - @Override - public void checkServerTrusted( - final X509Certificate[] x509Certificates, final String s) - throws CertificateException { - checkRevoked(x509Certificates); - x509TrustManager.checkServerTrusted(x509Certificates, s); - } - - private void checkRevoked(final X509Certificate[] x509Certificates) - throws CertificateException { - for (X509CRL crl : crls) { - for (X509Certificate cert : x509Certificates) { - if (crl.isRevoked(cert)) { - throw new CertificateException("Certificate revoked"); - } - } - } - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return x509TrustManager.getAcceptedIssuers(); - } - }; - } - } - return ret; - } - - protected TrustManagerFactory getTrustManagerFactory(final KeyStore truststore) - throws GeneralSecurityException { - final TrustManagerFactory tmf = TrustManagerFactory.getInstance(TRUSTMANAGER_FACTORY_ALGORITHM); - tmf.init(truststore); - return tmf; - } - - protected KeyManagerFactory getKeyManagerFactory( - final KeyStore keystore, final String keystorePassword) throws GeneralSecurityException { - final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KEYMANAGER_FACTORY_ALGORITHM); - kmf.init(keystore, keystorePassword.toCharArray()); - return kmf; - } - - private List getEnabledCipherSuites() { - final String protocol = getTlsProtocol(); - try { - if (enabledCipherSuites == null || enabledCipherSuites.isEmpty()) { - final SSLContext sslcontext = SSLContext.getInstance(protocol); - sslcontext.init(null, null, null); - enabledCipherSuites = Arrays.asList(sslcontext.createSSLEngine().getEnabledCipherSuites()); - } - } catch (final NoSuchAlgorithmException | KeyManagementException e) { - LOG.warn( - "Could not get list of enabled (JDK) cipher suites for protocol:{}, reverting to Netty's default ones.", - protocol); - } - return enabledCipherSuites; - } - - private String getTlsProtocol() { - return Arrays.stream(allowedProtocols).max(Comparator.naturalOrder()).orElse(null); - } - - public static TLSContextFactory buildFrom(final TLSConfiguration config) - throws GeneralSecurityException, IOException { - TLSContextFactory ret = null; - if (null != config) { - LOG.info("Initializing SSL Context using {} keystore.", config.getKeyStoreType()); - KeyStoreWrapper wrapper = - KeyStoreWrapper.KEYSTORE_TYPE_PKCS11.equalsIgnoreCase(config.getKeyStoreType()) - ? new HardwareKeyStoreWrapper( - config.getKeyStorePassword(), config.getKeyStorePath(), config.getCrlPath()) - : new SoftwareKeyStoreWrapper( - config.getKeyStoreType(), - config.getKeyStorePath(), - config.getKeyStorePassword(), - config.getTrustStoreType(), - config.getTrustStorePath(), - config.getTrustStorePassword(), - config.getCrlPath()); - ret = - TLSContextFactory.getInstance( - config.getKeyStorePassword(), wrapper, config.getAllowedProtocols()); - } - return ret; - } -} diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java index 88b9197262a..327edbaf47c 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/DefaultP2PNetworkTest.java @@ -97,7 +97,7 @@ public void before() { lenient().when(discoveryAgent.checkForkId(any())).thenReturn(true); lenient() .when(discoveryAgent.start(anyInt())) - .thenReturn(CompletableFuture.completedFuture(Integer.valueOf(30301))); + .thenReturn(CompletableFuture.completedFuture(30301)); } @Test diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/P2PPlainNetworkTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/P2PPlainNetworkTest.java index d02cb1ff83f..5a5d40907d2 100644 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/P2PPlainNetworkTest.java +++ b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/network/P2PPlainNetworkTest.java @@ -16,8 +16,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.assertj.core.api.Fail.fail; -import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS12; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -39,10 +37,7 @@ import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissions; import org.hyperledger.besu.ethereum.p2p.permissions.PeerPermissionsDenylist; import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnection; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration; -import org.hyperledger.besu.ethereum.p2p.rlpx.wire.AbstractMessageData; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Capability; -import org.hyperledger.besu.ethereum.p2p.rlpx.wire.Message; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MockSubProtocol; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.ShouldConnectCallback; import org.hyperledger.besu.ethereum.p2p.rlpx.wire.SubProtocol; @@ -51,12 +46,8 @@ import org.hyperledger.besu.plugin.data.EnodeURL; import java.net.InetAddress; -import java.net.URISyntaxException; -import java.nio.file.Path; import java.util.Arrays; import java.util.Collections; -import java.util.Objects; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @@ -89,8 +80,8 @@ public void closeVertx() { @Test public void handshaking() throws Exception { final NodeKey nodeKey = NodeKeyUtils.generate(); - try (final P2PNetwork listener = builder("partner1client1").nodeKey(nodeKey).build(); - final P2PNetwork connector = builder("partner2client1").build()) { + try (final P2PNetwork listener = builder().nodeKey(nodeKey).build(); + final P2PNetwork connector = builder().build()) { listener.getRlpxAgent().subscribeConnectRequest(testCallback); connector.getRlpxAgent().subscribeConnectRequest(testCallback); @@ -113,8 +104,8 @@ public void handshaking() throws Exception { @Test public void preventMultipleConnections() throws Exception { final NodeKey listenNodeKey = NodeKeyUtils.generate(); - try (final P2PNetwork listener = builder("partner1client1").nodeKey(listenNodeKey).build(); - final P2PNetwork connector = builder("partner2client1").build()) { + try (final P2PNetwork listener = builder().nodeKey(listenNodeKey).build(); + final P2PNetwork connector = builder().build()) { listener.getRlpxAgent().subscribeConnectRequest(testCallback); connector.getRlpxAgent().subscribeConnectRequest(testCallback); @@ -155,10 +146,9 @@ public void limitMaxPeers() throws Exception { RlpxConfiguration.create() .setBindPort(0) .setSupportedProtocols(MockSubProtocol.create())); - try (final P2PNetwork listener = - builder("partner1client1").nodeKey(nodeKey).config(listenerConfig).build(); - final P2PNetwork connector1 = builder("partner1client1").build(); - final P2PNetwork connector2 = builder("partner2client1").build()) { + try (final P2PNetwork listener = builder().nodeKey(nodeKey).config(listenerConfig).build(); + final P2PNetwork connector1 = builder().build(); + final P2PNetwork connector2 = builder().build()) { listener.getRlpxAgent().subscribeConnectRequest(testCallback); connector1.getRlpxAgent().subscribeConnectRequest(testCallback); connector2.getRlpxAgent().subscribeConnectRequest((p, d) -> false); @@ -202,15 +192,9 @@ public void rejectPeerWithNoSharedCaps() throws Exception { final SubProtocol subprotocol2 = MockSubProtocol.create("oth"); final Capability cap2 = Capability.create(subprotocol2.getName(), 63); try (final P2PNetwork listener = - builder("partner1client1") - .nodeKey(listenerNodeKey) - .supportedCapabilities(cap1) - .build(); + builder().nodeKey(listenerNodeKey).supportedCapabilities(cap1).build(); final P2PNetwork connector = - builder("partner2client1") - .nodeKey(connectorNodeKey) - .supportedCapabilities(cap2) - .build()) { + builder().nodeKey(connectorNodeKey).supportedCapabilities(cap2).build()) { listener.getRlpxAgent().subscribeConnectRequest(testCallback); connector.getRlpxAgent().subscribeConnectRequest(testCallback); @@ -230,9 +214,8 @@ public void rejectPeerWithNoSharedCaps() throws Exception { public void rejectIncomingConnectionFromDenylistedPeer() throws Exception { final PeerPermissionsDenylist localDenylist = PeerPermissionsDenylist.create(); - try (final P2PNetwork localNetwork = - builder("partner1client1").peerPermissions(localDenylist).build(); - final P2PNetwork remoteNetwork = builder("partner2client1").build()) { + try (final P2PNetwork localNetwork = builder().peerPermissions(localDenylist).build(); + final P2PNetwork remoteNetwork = builder().build()) { localNetwork.getRlpxAgent().subscribeConnectRequest(testCallback); remoteNetwork.getRlpxAgent().subscribeConnectRequest(testCallback); @@ -280,9 +263,8 @@ public void rejectIncomingConnectionFromDisallowedPeer() throws Exception { final PeerPermissions peerPermissions = mock(PeerPermissions.class); when(peerPermissions.isPermitted(any(), any(), any())).thenReturn(true); - try (final P2PNetwork localNetwork = - builder("partner1client1").peerPermissions(peerPermissions).build(); - final P2PNetwork remoteNetwork = builder("partner2client1").build()) { + try (final P2PNetwork localNetwork = builder().peerPermissions(peerPermissions).build(); + final P2PNetwork remoteNetwork = builder().build()) { localNetwork.getRlpxAgent().subscribeConnectRequest(testCallback); remoteNetwork.getRlpxAgent().subscribeConnectRequest(testCallback); @@ -323,89 +305,8 @@ public void rejectIncomingConnectionFromDisallowedPeer() throws Exception { } } - @Test - public void p2pOverTlsCanHandleRecordFragmentation() throws Exception { - // Given - final int tlsRecordSize = 16 * 1024; - final int threeTlsRecords = 2 * tlsRecordSize + 1; - final LargeMessageData largeMessageData = - new LargeMessageData(Bytes.of(buildPaddedMessage(threeTlsRecords))); - - final NodeKey nodeKey = NodeKeyUtils.generate(); - try (final P2PNetwork listener = builder("partner1client1").nodeKey(nodeKey).build(); - final P2PNetwork connector = builder("partner2client1").build()) { - listener.getRlpxAgent().subscribeConnectRequest(testCallback); - connector.getRlpxAgent().subscribeConnectRequest(testCallback); - - final CompletableFuture disconnectReasonFuture = new CompletableFuture<>(); - listener.subscribeDisconnect( - (peerConnection, reason, initiatedByPeer) -> { - if (!DisconnectReason.CLIENT_QUITTING.equals( - reason)) { // client quitting is the valid end state - disconnectReasonFuture.complete(reason); - } - }); - final CompletableFuture successfulMessageFuture = new CompletableFuture<>(); - listener.subscribe( - Capability.create("eth", 63), - (capability, message) -> { - if (message.getData().getCode() == LargeMessageData.VALID_ETH_MESSAGE_CODE) { - successfulMessageFuture.complete(message); - } - }); - - listener.start(); - connector.start(); - - final EnodeURL listenerEnode = listener.getLocalEnode().get(); - final Bytes listenId = listenerEnode.getNodeId(); - final int listenPort = listenerEnode.getListeningPort().get(); - final PeerConnection peerConnection = - connector.connect(createPeer(listenId, listenPort)).get(30000L, TimeUnit.SECONDS); - - // When - peerConnection.sendForProtocol("eth", largeMessageData); - - // Then - CompletableFuture.anyOf(disconnectReasonFuture, successfulMessageFuture) - .thenAccept( - successOrFailure -> { - if (successOrFailure instanceof DisconnectReason) { - fail( - "listener disconnected due to " - + ((DisconnectReason) successOrFailure).name()); - } else { - final Message receivedMessage = (Message) successOrFailure; - assertThat(receivedMessage.getData().getData()) - .isEqualTo(largeMessageData.getData()); - } - }) - .get(30L, TimeUnit.SECONDS); - } - } - private final ShouldConnectCallback testCallback = (p, d) -> true; - private static class LargeMessageData extends AbstractMessageData { - - public static final int VALID_ETH_MESSAGE_CODE = 0x07; - - private LargeMessageData(final Bytes data) { - super(data); - } - - @Override - public int getCode() { - return VALID_ETH_MESSAGE_CODE; - } - } - - private byte[] buildPaddedMessage(final int messageSize) { - final byte[] bytes = new byte[messageSize]; - Arrays.fill(bytes, (byte) 9); - return bytes; - } - private Peer createPeer(final Bytes nodeId, final int listenPort) { return DefaultPeer.fromEnodeURL( EnodeURLImpl.builder() @@ -415,35 +316,7 @@ private Peer createPeer(final Bytes nodeId, final int listenPort) { .build()); } - private static Path toPath(final String path) { - try { - return Path.of(Objects.requireNonNull(P2PPlainNetworkTest.class.getResource(path)).toURI()); - } catch (final URISyntaxException e) { - throw new RuntimeException("Error converting to URI.", e); - } - } - - public Optional p2pTLSEnabled(final String clientDirName) { - final String parentPath = "/keys"; - final String keystorePath = parentPath + "/%s/client1.p12"; - final String truststorePath = parentPath + "/%s/truststore.p12"; - final String crl = parentPath + "/crl/crl.pem"; - final TLSConfiguration.Builder builder = TLSConfiguration.Builder.tlsConfiguration(); - builder - .withKeyStoreType(KEYSTORE_TYPE_PKCS12) - .withKeyStorePath(toPath(String.format(keystorePath, clientDirName))) - .withKeyStorePasswordSupplier(() -> "test123") - // .withKeyStorePasswordPath(toPath(String.format(nsspin, name))) - .withTrustStoreType(KEYSTORE_TYPE_PKCS12) - .withTrustStorePath(toPath(String.format(truststorePath, clientDirName))) - .withTrustStorePasswordSupplier(() -> "test123") - .withCrlPath(toPath(crl)) - .withClientHelloSniEnabled(false); - - return Optional.of(builder.build()); - } - - private DefaultP2PNetwork.Builder builder(final String clientDirName) { + private DefaultP2PNetwork.Builder builder() { final MutableBlockchain blockchainMock = mock(MutableBlockchain.class); final Block blockMock = mock(Block.class); when(blockMock.getHash()).thenReturn(Hash.ZERO); @@ -452,7 +325,6 @@ private DefaultP2PNetwork.Builder builder(final String clientDirName) { .vertx(vertx) .config(config) .nodeKey(NodeKeyUtils.generate()) - .p2pTLSConfiguration(p2pTLSEnabled(clientDirName)) .metricsSystem(new NoOpMetricsSystem()) .supportedCapabilities(Arrays.asList(Capability.create("eth", 63))) .storageProvider(new InMemoryKeyValueStorageProvider()) diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializerTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializerTest.java deleted file mode 100644 index ac39d81bb07..00000000000 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/NettyTLSConnectionInitializerTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright contributors to Hyperledger Besu. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - */ -package org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty; - -import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import org.hyperledger.besu.cryptoservices.NodeKey; -import org.hyperledger.besu.ethereum.p2p.config.RlpxConfiguration; -import org.hyperledger.besu.ethereum.p2p.discovery.internal.PeerTable; -import org.hyperledger.besu.ethereum.p2p.peers.LocalNode; -import org.hyperledger.besu.ethereum.p2p.peers.Peer; -import org.hyperledger.besu.ethereum.p2p.rlpx.connections.PeerConnectionEventDispatcher; -import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.data.EnodeURL; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import com.google.common.collect.ImmutableList; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.embedded.EmbeddedChannel; -import io.netty.handler.codec.LengthFieldBasedFrameDecoder; -import io.netty.handler.codec.LengthFieldPrepender; -import io.netty.handler.codec.compression.SnappyFrameDecoder; -import io.netty.handler.codec.compression.SnappyFrameEncoder; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslHandler; -import org.apache.tuweni.bytes.Bytes; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; -import org.mockito.quality.Strictness; - -@ExtendWith(MockitoExtension.class) -@MockitoSettings(strictness = Strictness.LENIENT) -public class NettyTLSConnectionInitializerTest { - - private static final String PEER_HOST = "hyperledger.org"; - private static final int PEER_PORT = 30303; - @Mock private NodeKey nodeKey; - @Mock private RlpxConfiguration rlpxConfiguration; - @Mock private LocalNode localNode; - @Mock private PeerConnectionEventDispatcher eventDispatcher; - @Mock private TLSContextFactory tlsContextFactory; - @Mock private SslContext clientSslContext; - @Mock private SslContext serverSslContext; - @Mock private SslHandler clientSslHandler; - @Mock private SslHandler serverSslHandler; - @Mock private Peer peer; - @Mock private EnodeURL enodeURL; - - private NettyTLSConnectionInitializer nettyTLSConnectionInitializer; - - @BeforeEach - public void before() throws Exception { - nettyTLSConnectionInitializer = createNettyTLSConnectionInitializer(false); - - when(tlsContextFactory.createNettyServerSslContext()).thenReturn(serverSslContext); - when(serverSslContext.newHandler(any())).thenReturn(serverSslHandler); - - when(tlsContextFactory.createNettyClientSslContext()).thenReturn(clientSslContext); - when(clientSslContext.newHandler(any())).thenReturn(clientSslHandler); - when(peer.getEnodeURL()).thenReturn(enodeURL); - when(enodeURL.getHost()).thenReturn(PEER_HOST); - when(enodeURL.getListeningPort()).thenReturn(Optional.of(PEER_PORT)); - } - - private NettyTLSConnectionInitializer createNettyTLSConnectionInitializer( - final boolean clientHelloSniHeaderEnabled) { - return new NettyTLSConnectionInitializer( - nodeKey, - rlpxConfiguration, - localNode, - eventDispatcher, - new NoOpMetricsSystem(), - () -> tlsContextFactory, - clientHelloSniHeaderEnabled, - new PeerTable(Bytes.random(64))); - } - - @Test - public void addAdditionalOutboundHandlersIncludesAllExpectedHandlersToChannelPipeline() - throws Exception { - final EmbeddedChannel embeddedChannel = new EmbeddedChannel(); - nettyTLSConnectionInitializer.addAdditionalOutboundHandlers(embeddedChannel, peer); - - // TLS - assertThat(embeddedChannel.pipeline().get(SslHandler.class)).isEqualTo(clientSslHandler); - - // Snappy compression - assertThat(embeddedChannel.pipeline().get(SnappyFrameDecoder.class)).isNotNull(); - assertThat(embeddedChannel.pipeline().get(SnappyFrameEncoder.class)).isNotNull(); - - // Message Framing - assertThat(embeddedChannel.pipeline().get(LengthFieldBasedFrameDecoder.class)).isNotNull(); - assertThat(embeddedChannel.pipeline().get(LengthFieldPrepender.class)).isNotNull(); - - assertHandlersOrderInPipeline(embeddedChannel.pipeline()); - } - - @Test - public void addAdditionalOutboundHandlersUsesSslHandlerWithSniHeaderEnabledIfConfigured() - throws Exception { - nettyTLSConnectionInitializer = createNettyTLSConnectionInitializer(true); - when(clientSslContext.newHandler(any(), eq(PEER_HOST), eq(PEER_PORT))) - .thenReturn(clientSslHandler); - - final EmbeddedChannel embeddedChannel = new EmbeddedChannel(); - nettyTLSConnectionInitializer.addAdditionalOutboundHandlers(embeddedChannel, peer); - - // Handler with SNI params was created - verify(clientSslContext).newHandler(any(), eq(PEER_HOST), eq(PEER_PORT)); - - // Other handlers are still present as expected - assertHandlersOrderInPipeline(embeddedChannel.pipeline()); - } - - @Test - public void addAdditionalInboundHandlersIncludesAllExpectedHandlersToChannelPipeline() - throws Exception { - final EmbeddedChannel embeddedChannel = new EmbeddedChannel(); - nettyTLSConnectionInitializer.addAdditionalInboundHandlers(embeddedChannel); - - // TLS - assertThat(embeddedChannel.pipeline().get(SslHandler.class)).isEqualTo(serverSslHandler); - - // Snappy compression - assertThat(embeddedChannel.pipeline().get(SnappyFrameDecoder.class)).isNotNull(); - assertThat(embeddedChannel.pipeline().get(SnappyFrameEncoder.class)).isNotNull(); - - // Message Framing - assertThat(embeddedChannel.pipeline().get(LengthFieldBasedFrameDecoder.class)).isNotNull(); - assertThat(embeddedChannel.pipeline().get(LengthFieldPrepender.class)).isNotNull(); - - assertHandlersOrderInPipeline(embeddedChannel.pipeline()); - } - - private void assertHandlersOrderInPipeline(final ChannelPipeline pipeline) { - // Appending '#0' because Netty adds it to the handler's names - final ArrayList expectedHandlerNamesInOrder = - new ArrayList<>( - ImmutableList.of( - "SslHandler#0", - "SnappyFrameDecoder#0", - "SnappyFrameEncoder#0", - "LengthFieldBasedFrameDecoder#0", - "LengthFieldPrepender#0", - "DefaultChannelPipeline$TailContext#0")); // This final handler is Netty's default - - final List actualHandlerNamesInOrder = pipeline.names(); - assertThat(actualHandlerNamesInOrder).isEqualTo(expectedHandlerNamesInOrder); - } - - @Test - public void defaultTlsContextFactorySupplierThrowsErrorWithNullTLSConfiguration() { - assertThatThrownBy(() -> NettyTLSConnectionInitializer.defaultTlsContextFactorySupplier(null)) - .isInstanceOf(IllegalStateException.class) - .hasMessage("TLSConfiguration cannot be null when using TLS"); - } - - @Test - public void defaultTlsContextFactorySupplierCapturesInternalError() { - final TLSConfiguration tlsConfiguration = mock(TLSConfiguration.class); - when(tlsConfiguration.getKeyStoreType()).thenThrow(new RuntimeException()); - - assertThatThrownBy( - () -> - NettyTLSConnectionInitializer.defaultTlsContextFactorySupplier(tlsConfiguration) - .get()) - .isInstanceOf(IllegalStateException.class) - .hasMessage("Error creating TLSContextFactory"); - } -} diff --git a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactoryTest.java b/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactoryTest.java deleted file mode 100644 index d7763892c5d..00000000000 --- a/ethereum/p2p/src/test/java/org/hyperledger/besu/ethereum/p2p/rlpx/connections/netty/TLSContextFactoryTest.java +++ /dev/null @@ -1,504 +0,0 @@ -/* - * 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.ethereum.p2p.rlpx.connections.netty; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.pki.keystore.KeyStoreWrapper.KEYSTORE_TYPE_PKCS12; - -import org.hyperledger.besu.pki.PkiException; -import org.hyperledger.besu.pki.keystore.HardwareKeyStoreWrapper; -import org.hyperledger.besu.pki.keystore.KeyStoreWrapper; -import org.hyperledger.besu.pki.keystore.SoftwareKeyStoreWrapper; - -import java.net.InetSocketAddress; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collection; -import java.util.Optional; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import io.netty.bootstrap.Bootstrap; -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslHandler; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -class TLSContextFactoryTest { - - // see resources/keys/README.md for setup details. - private static final String keystorePassword = "test123"; - - private static final Logger LOG = LoggerFactory.getLogger(TLSContextFactoryTest.class); - - private static final int MAX_NUMBER_MESSAGES = 10; - private static final String CRL_PEM = "/keys/crl/crl.pem"; - private static final String PARTNER1_CLIENT1_PKCS11 = "/keys/partner1client1/nss.cfg"; - private static final String PARTNER1_CLIENT1_KEYSTORE = "/keys/partner1client1/client1.p12"; - private static final String PARTNET1_CLIENT2_KEYSTORE = "/keys/partner1client2rvk/client2.p12"; - private static final String PARTNER2_CLIENT1_KEYSTORE = "/keys/partner2client1/client1.p12"; - private static final String PARTNER2_CLIENT2_KEYSTORE = "/keys/partner2client2rvk/client2.p12"; - private static final String INVALIDPARTNER1_CLIENT1_KEYSTORE = - "/keys/invalidpartner1client1/client1.p12"; - - private static final String PARTNER1_CLIENT1_TRUSTSTORE = "/keys/partner1client1/truststore.p12"; - private static final String PARTNET1_CLIENT2_TRUSTSTORE = - "/keys/partner1client2rvk/truststore.p12"; - private static final String PARTNER2_CLIENT1_TRUSTSTORE = "/keys/partner2client1/truststore.p12"; - private static final String PARTNER2_CLIENT2_TRUSTSTORE = - "/keys/partner2client2rvk/truststore.p12"; - private static final String INVALIDPARTNER1_CLIENT1_TRUSTSTORE = - "/keys/invalidpartner1client1/truststore.p12"; - - private Server server; - private Client client; - - static Collection hardwareKeysData() { - return Arrays.asList( - new Object[][] { - { - "PKCS11 server Partner1 Client1 -> PKCS12 client Partner2 Client1 SuccessfulConnection", - true, - getHardwareKeyStoreWrapper(PARTNER1_CLIENT1_PKCS11, CRL_PEM), - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), - Optional.empty(), - Optional.empty() - }, - { - "PKCS11 server Partner1 Client1 -> PKCS12 client InvalidPartner1 Client1 FailedConnection", - false, - getHardwareKeyStoreWrapper(PARTNER1_CLIENT1_PKCS11, CRL_PEM), - getSoftwareKeyStoreWrapper( - INVALIDPARTNER1_CLIENT1_KEYSTORE, INVALIDPARTNER1_CLIENT1_TRUSTSTORE, null), - Optional.empty(), - Optional.of("certificate_unknown") - }, - { - "PKCS11 server Partner1 Client1 -> PKCS12 client Partner2 Client2 revoked FailedConnection", - false, - getHardwareKeyStoreWrapper(PARTNER1_CLIENT1_PKCS11, CRL_PEM), - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT2_KEYSTORE, PARTNER2_CLIENT2_TRUSTSTORE, null), - Optional.of("Certificate revoked"), - Optional.of("certificate_unknown") - }, - }); - } - - static Collection softwareKeysData() { - return Arrays.asList( - new Object[][] { - { - "PKCS12 server Partner1 Client1 -> PKCS12 client Partner2 Client1 SuccessfulConnection", - true, - getSoftwareKeyStoreWrapper( - PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), - Optional.empty(), - Optional.empty() - }, - { - "PKCS12 server Partner2 Client1 -> PKCS12 client Partner1 Client1 SuccessfulConnection", - true, - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), - getSoftwareKeyStoreWrapper( - PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), - Optional.empty(), - Optional.empty() - }, - { - "PKCS12 server Partner1 Client1 -> PKCS12 client InvalidPartner1 Client1 FailedConnection", - false, - getSoftwareKeyStoreWrapper( - PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), - getSoftwareKeyStoreWrapper( - INVALIDPARTNER1_CLIENT1_KEYSTORE, INVALIDPARTNER1_CLIENT1_TRUSTSTORE, null), - Optional.empty(), - Optional.of("certificate_unknown") - }, - { - "PKCS12 server InvalidPartner1 Client1 -> PKCS12 client Partner1 Client1 FailedConnection", - false, - getSoftwareKeyStoreWrapper( - INVALIDPARTNER1_CLIENT1_KEYSTORE, INVALIDPARTNER1_CLIENT1_TRUSTSTORE, null), - getSoftwareKeyStoreWrapper( - PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), - Optional.of("certificate_unknown"), - Optional.empty() - }, - { - "PKCS12 server Partner1 Client2 (revoked) -> PKCS12 client Partner2 Client1 FailedConnection", - false, - getSoftwareKeyStoreWrapper( - PARTNET1_CLIENT2_KEYSTORE, PARTNET1_CLIENT2_TRUSTSTORE, null), - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), - Optional.empty(), - Optional.of("Certificate revoked") - }, - { - "PKCS12 server Partner2 Client1 -> PKCS12 client Partner1 Client2 (revoked) FailedConnection", - false, - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT1_KEYSTORE, PARTNER2_CLIENT1_TRUSTSTORE, CRL_PEM), - getSoftwareKeyStoreWrapper( - PARTNET1_CLIENT2_KEYSTORE, PARTNET1_CLIENT2_TRUSTSTORE, null), - Optional.of("Certificate revoked"), - Optional.of("certificate_unknown") - }, - { - "PKCS12 server Partner2 Client2 (revoked) -> PKCS12 client Partner1 Client1 FailedConnection", - false, - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT2_KEYSTORE, PARTNER2_CLIENT2_TRUSTSTORE, null), - getSoftwareKeyStoreWrapper( - PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), - Optional.empty(), - Optional.of("Certificate revoked"), - }, - { - "PKCS12 server Partner1 Client1 -> PKCS12 client Partner2 Client2 (revoked) FailedConnection", - false, - getSoftwareKeyStoreWrapper( - PARTNER1_CLIENT1_KEYSTORE, PARTNER1_CLIENT1_TRUSTSTORE, CRL_PEM), - getSoftwareKeyStoreWrapper( - PARTNER2_CLIENT2_KEYSTORE, PARTNER2_CLIENT2_TRUSTSTORE, null), - Optional.of("Certificate revoked"), - Optional.of("certificate_unknown") - } - }); - } - - @BeforeEach - void init() {} - - @AfterEach - void tearDown() { - if (client != null) { - client.stop(); - } - if (server != null) { - server.stop(); - } - } - - private static Path toPath(final String path) throws Exception { - return null == path ? null : Path.of(TLSContextFactoryTest.class.getResource(path).toURI()); - } - - private static KeyStoreWrapper getHardwareKeyStoreWrapper( - final String config, final String crlLocation) { - try { - return new HardwareKeyStoreWrapper(keystorePassword, toPath(config), toPath(crlLocation)); - } catch (final Exception e) { - // Not a mac, probably a production build. Full failure. - throw new PkiException("Failed to initialize hardware keystore", e); - } - } - - private static KeyStoreWrapper getSoftwareKeyStoreWrapper( - final String jksKeyStore, final String trustStore, final String crl) { - try { - return new SoftwareKeyStoreWrapper( - KEYSTORE_TYPE_PKCS12, - toPath(jksKeyStore), - keystorePassword, - KEYSTORE_TYPE_PKCS12, - toPath(trustStore), - keystorePassword, - toPath(crl)); - } catch (final Exception e) { - throw new PkiException("Failed to initialize software keystore", e); - } - } - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("softwareKeysData") - @DisabledOnOs(OS.MAC) - void testConnectionSoftwareKeys( - final String ignoredTestDescription, - final boolean testSuccess, - final KeyStoreWrapper serverKeyStoreWrapper, - final KeyStoreWrapper clientKeyStoreWrapper, - final Optional serverFailureMessage, - final Optional clientFailureMessage) - throws Exception { - testConnection( - testSuccess, - serverKeyStoreWrapper, - clientKeyStoreWrapper, - serverFailureMessage, - clientFailureMessage); - } - - @ParameterizedTest(name = "{index}: {0}") - @MethodSource("hardwareKeysData") - @DisabledOnOs(OS.MAC) - void testConnectionHardwareKeys( - final String ignoredTestDescription, - final boolean testSuccess, - final KeyStoreWrapper serverKeyStoreWrapper, - final KeyStoreWrapper clientKeyStoreWrapper, - final Optional serverFailureMessage, - final Optional clientFailureMessage) - throws Exception { - testConnection( - testSuccess, - serverKeyStoreWrapper, - clientKeyStoreWrapper, - serverFailureMessage, - clientFailureMessage); - } - - private void testConnection( - final boolean testSuccess, - final KeyStoreWrapper serverKeyStoreWrapper, - final KeyStoreWrapper clientKeyStoreWrapper, - final Optional serverFailureMessage, - final Optional clientFailureMessage) - throws Exception { - final CountDownLatch serverLatch = new CountDownLatch(MAX_NUMBER_MESSAGES); - final CountDownLatch clientLatch = new CountDownLatch(MAX_NUMBER_MESSAGES); - server = startServer(serverKeyStoreWrapper, serverLatch); - client = startClient(server.port, clientKeyStoreWrapper, clientLatch); - - if (testSuccess) { - client.getChannelFuture().channel().writeAndFlush(Unpooled.copyInt(0)); - final boolean allMessagesServerExchanged = serverLatch.await(10, TimeUnit.SECONDS); - final boolean allMessagesClientExchanged = clientLatch.await(10, TimeUnit.SECONDS); - assertThat(allMessagesClientExchanged && allMessagesServerExchanged).isTrue(); - } else { - try { - client.getChannelFuture().channel().writeAndFlush(Unpooled.copyInt(0)).sync(); - serverLatch.await(2, TimeUnit.SECONDS); - assertThat(client.getChannelFuture().channel().isActive()).isFalse(); - - if (serverFailureMessage.isPresent()) { - assertThat(server.getCause()).isNotEmpty(); - assertThat(server.getCause().get()).hasMessageContaining(serverFailureMessage.get()); - } else { - assertThat(server.getCause()).isEmpty(); - } - - if (clientFailureMessage.isPresent()) { - assertThat(client.getCause()).isNotEmpty(); - assertThat(client.getCause().get()).hasMessageContaining(clientFailureMessage.get()); - } else { - assertThat(client.getCause()).isEmpty(); - } - } catch (final Exception e) { - // NOOP - } - } - } - - private Server startServer(final KeyStoreWrapper keyStoreWrapper, final CountDownLatch latch) - throws Exception { - - final Server nettyServer = new Server(keystorePassword, keyStoreWrapper, latch); - nettyServer.start(); - return nettyServer; - } - - private Client startClient( - final int port, final KeyStoreWrapper keyStoreWrapper, final CountDownLatch latch) - throws Exception { - - final Client nettyClient = new Client(port, keystorePassword, keyStoreWrapper, latch); - nettyClient.start(); - return nettyClient; - } - - static class MessageHandler extends ChannelInboundHandlerAdapter { - private final String id; - private final CountDownLatch latch; - - private Throwable cause; - - MessageHandler(final String id, final CountDownLatch latch) { - this.id = id; - this.latch = latch; - } - - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) - throws InterruptedException { - final int message = ((ByteBuf) msg).readInt(); - LOG.info("[" + id + "] Received message: " + message); - - if (message < 2 * MAX_NUMBER_MESSAGES) { - final int replyMessage = message + 1; - ctx.writeAndFlush(Unpooled.copyInt(replyMessage)).sync(); - LOG.info("[" + id + "] Sent message: " + replyMessage); - this.latch.countDown(); - LOG.info("Remaining {}", this.latch.getCount()); - } - } - - @Override - public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) - throws Exception { - this.cause = cause; - } - - public Optional getCause() { - return Optional.ofNullable(cause); - } - } - - static class Client { - int port; - private final String keystorePassword; - private final KeyStoreWrapper keyStoreWrapper; - private final CountDownLatch latch; - - private ChannelFuture channelFuture; - private final EventLoopGroup group = new NioEventLoopGroup(); - private MessageHandler messageHandler; - - ChannelFuture getChannelFuture() { - return channelFuture; - } - - Client( - final int port, - final String keystorePassword, - final KeyStoreWrapper keyStoreWrapper, - final CountDownLatch latch) { - this.port = port; - this.keystorePassword = keystorePassword; - this.keyStoreWrapper = keyStoreWrapper; - this.latch = latch; - } - - void start() throws Exception { - final Bootstrap b = new Bootstrap(); - b.group(group); - b.channel(NioSocketChannel.class); - b.handler( - new ChannelInitializer() { - @Override - protected void initChannel(final SocketChannel socketChannel) throws Exception { - final SslContext sslContext = - TLSContextFactory.getInstance(keystorePassword, keyStoreWrapper) - .createNettyClientSslContext(); - - final SslHandler sslHandler = sslContext.newHandler(socketChannel.alloc()); - socketChannel.pipeline().addFirst("ssl", sslHandler); - messageHandler = new MessageHandler("Client", latch); - socketChannel.pipeline().addLast(messageHandler); - } - }); - - this.channelFuture = b.connect("127.0.0.1", this.port).sync(); - } - - void stop() { - group.shutdownGracefully(); - messageHandler = null; - } - - Optional getCause() { - return messageHandler != null ? messageHandler.getCause() : Optional.empty(); - } - } - - static class Server { - private int port; - private final String keystorePassword; - private final KeyStoreWrapper keyStoreWrapper; - private final CountDownLatch latch; - - private Channel channel; - - private final EventLoopGroup parentGroup = new NioEventLoopGroup(); - private final EventLoopGroup childGroup = new NioEventLoopGroup(); - - private MessageHandler messageHandler; - - Server( - final String keystorePassword, - final KeyStoreWrapper keyStoreWrapper, - final CountDownLatch latch) { - this.keystorePassword = keystorePassword; - this.keyStoreWrapper = keyStoreWrapper; - this.latch = latch; - } - - void start() throws Exception { - final ServerBootstrap sb = new ServerBootstrap(); - sb.group(parentGroup, childGroup) - .channel(NioServerSocketChannel.class) - .childHandler( - new ChannelInitializer() { - @Override - public void initChannel(final SocketChannel socketChannel) throws Exception { - final SslContext sslContext = - TLSContextFactory.getInstance(keystorePassword, keyStoreWrapper) - .createNettyServerSslContext(); - final SslHandler sslHandler = sslContext.newHandler(channel.alloc()); - socketChannel.pipeline().addFirst("ssl", sslHandler); - - socketChannel - .pipeline() - .addLast(messageHandler = new MessageHandler("Server", latch)); - } - }); - - final ChannelFuture cf = sb.bind(0).sync(); - this.channel = cf.channel(); - this.port = ((InetSocketAddress) channel.localAddress()).getPort(); - } - - void stop() { - childGroup.shutdownGracefully(); - parentGroup.shutdownGracefully(); - } - - Optional getCause() { - return messageHandler != null ? messageHandler.getCause() : Optional.empty(); - } - } - - @Test - void dryRunDetector() { - assertThat(true) - .withFailMessage("This test is here so gradle --dry-run executes this class") - .isTrue(); - } -} diff --git a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningController.java b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningController.java index ec66ea51eff..b5878d14de3 100644 --- a/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningController.java +++ b/ethereum/permissioning/src/main/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningController.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -48,7 +49,7 @@ public class NodeLocalConfigPermissioningController implements NodeConnectionPer private LocalPermissioningConfiguration configuration; private final List fixedNodes; private final Bytes localNodeId; - private final List nodesAllowlist = new ArrayList<>(); + private final List nodesAllowlist = new CopyOnWriteArrayList<>(); private final AllowlistPersistor allowlistPersistor; private final Subscribers> nodeAllowlistUpdatedObservers = Subscribers.create(); diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java index 106f9c36100..5db372b63ac 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java @@ -46,6 +46,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import com.google.common.collect.Lists; @@ -316,6 +317,56 @@ public void whenCheckingIfNodeIsPermittedOrderDoesNotMatter() { .isTrue(); } + @Test + public void whenCallingIsPermittedAndRemovingEntryInAnotherThreadShouldNotThrowException() + throws InterruptedException { + // Add a node to the allowlist + controller.addNodes(Lists.newArrayList(enode1)); + + // Atomic flag to detect exceptions + AtomicBoolean exceptionOccurred = new AtomicBoolean(false); + + // Create a thread to call isPermitted + Thread isPermittedThread = + new Thread( + () -> { + try { + for (int i = 0; i < 1000; i++) { + controller.isPermitted(enode1); + } + } catch (Exception e) { + exceptionOccurred.set(true); + e.printStackTrace(); + } + }); + + // Create a thread to modify the allowlist + Thread modifyAllowlistThread = + new Thread( + () -> { + try { + for (int i = 0; i < 1000; i++) { + controller.removeNodes(Lists.newArrayList(enode1)); + controller.addNodes(Lists.newArrayList(enode1)); + } + } catch (Exception e) { + exceptionOccurred.set(true); + e.printStackTrace(); + } + }); + + // Start both threads + isPermittedThread.start(); + modifyAllowlistThread.start(); + + // Wait for both threads to complete + isPermittedThread.join(); + modifyAllowlistThread.join(); + + // Assert no exceptions were thrown + assert (!exceptionOccurred.get()); + } + @Test public void stateShouldRevertIfAllowlistPersistFails() throws IOException, AllowlistFileSyncException { diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java index a9c97b1cc4e..487874d8e3d 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/NodeSmartContractPermissioningControllerTest.java @@ -23,11 +23,12 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; @@ -62,7 +63,7 @@ private NodeSmartContractPermissioningController setupController( final ObjectNode jsonData = JsonUtil.objectNodeFromString(emptyContractFile, true); final GenesisState genesisState = - GenesisState.fromConfig(GenesisConfigFile.fromConfig(jsonData), protocolSchedule); + GenesisState.fromConfig(GenesisConfig.fromConfig(jsonData), protocolSchedule); final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final WorldStateArchive worldArchive = createInMemoryWorldStateArchive(); @@ -70,7 +71,8 @@ private NodeSmartContractPermissioningController setupController( genesisState.writeStateTo(worldArchive.getMutable()); final TransactionSimulator ts = - new TransactionSimulator(blockchain, worldArchive, protocolSchedule, 0L); + new TransactionSimulator( + blockchain, worldArchive, protocolSchedule, MiningConfiguration.newDefault(), 0L); final Address contractAddress = Address.fromHexString(contractAddressString); when(metricsSystem.createCounter( diff --git a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java index 1fd4f58a4bd..daea4a6d210 100644 --- a/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/org/hyperledger/besu/ethereum/permissioning/TransactionSmartContractPermissioningControllerTest.java @@ -22,13 +22,14 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; 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.chain.GenesisState; import org.hyperledger.besu.ethereum.chain.MutableBlockchain; +import org.hyperledger.besu.ethereum.core.MiningConfiguration; import org.hyperledger.besu.ethereum.core.ProtocolScheduleFixture; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; @@ -60,8 +61,7 @@ private TransactionSmartContractPermissioningController setupController( final GenesisState genesisState = GenesisState.fromConfig( - GenesisConfigFile.fromSource(this.getClass().getResource(resourceName)), - protocolSchedule); + GenesisConfig.fromSource(this.getClass().getResource(resourceName)), protocolSchedule); final MutableBlockchain blockchain = createInMemoryBlockchain(genesisState.getBlock()); final WorldStateArchive worldArchive = createInMemoryWorldStateArchive(); @@ -69,7 +69,8 @@ private TransactionSmartContractPermissioningController setupController( genesisState.writeStateTo(worldArchive.getMutable()); final TransactionSimulator ts = - new TransactionSimulator(blockchain, worldArchive, protocolSchedule, 0L); + new TransactionSimulator( + blockchain, worldArchive, protocolSchedule, MiningConfiguration.newDefault(), 0L); final Address contractAddress = Address.fromHexString(contractAddressString); when(metricsSystem.createCounter( diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java index 329f87260ac..799abd04386 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java @@ -202,7 +202,7 @@ public ReferenceTestBlockHeader( excessBlobGas != null ? BlobGas.fromHexString(excessBlobGas) : null, parentBeaconBlockRoot != null ? Bytes32.fromHexString(parentBeaconBlockRoot) : null, requestsHash != null ? Hash.fromHexString(requestsHash) : null, - null, // TODO SLD EIP-7742 use targetBlobCount when reference tests are updated + null, // TODO SLD EIP-7742 use targetBlobsPerBlock when reference tests are updated null, // TODO MANAGE WITNESS FROM VERKLE new BlockHeaderFunctions() { @Override diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java index 865fff0e668..37a9ea971c0 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestEnv.java @@ -146,7 +146,7 @@ public ReferenceTestEnv( currentExcessBlobGas == null ? null : BlobGas.of(Long.decode(currentExcessBlobGas)), beaconRoot == null ? null : Bytes32.fromHexString(beaconRoot), null, // requestsHash - null, // TODO SLD EIP-7742 use targetBlobCount when reference tests are updated + null, // TODO SLD EIP-7742 use targetBlobsPerBlock when reference tests are updated null, // execution witnesses new MainnetBlockHeaderFunctions()); this.parentDifficulty = parentDifficulty; diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java index 8549a2dd150..36b4f8e9376 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestWorldState.java @@ -35,6 +35,7 @@ @JsonIgnoreProperties(ignoreUnknown = true) public interface ReferenceTestWorldState extends MutableWorldState { + @JsonIgnoreProperties(ignoreUnknown = true) class AccountMock { private final long nonce; private final Wei balance; diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java index ea09a1eb983..a5e3d364fc2 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/mainnet/DifficultyCalculatorTests.java @@ -18,7 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.config.GenesisConfig; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.config.StubGenesisConfigOptions; import org.hyperledger.besu.datatypes.Address; @@ -57,7 +57,7 @@ public static Stream getTestParametersForConfig() throws IOException Arguments.of( "/BasicTests/difficultyMainNetwork.json", MainnetProtocolSchedule.fromConfig( - GenesisConfigFile.mainnet() + GenesisConfig.mainnet() .withOverrides(postMergeOverrides).getConfigOptions(), EvmConfiguration.DEFAULT, MiningConfiguration.MINING_DISABLED, new BadBlockManager(), false, new NoOpMetricsSystem())), Arguments.of( diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java index 354642f1ad7..8e1ac386a79 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/vm/GeneralStateReferenceTestTools.java @@ -155,7 +155,7 @@ public static void executeTest(final GeneralStateTestCaseEipSpec spec) { blockHeader, transaction, blockHeader.getCoinbase(), - new CachingBlockHashLookup(blockHeader, blockchain), + protocolSpec.getBlockHashProcessor().createBlockHashLookup(blockchain, blockHeader), false, TransactionValidationParams.processingBlock(), blobGasPrice); diff --git a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/GetWorkProtocol.java b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/GetWorkProtocol.java index 262956c32f9..1cff4db180c 100644 --- a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/GetWorkProtocol.java +++ b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/GetWorkProtocol.java @@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory; /** Protocol using JSON-RPC HTTP methods to provide getWork/submitWork methods. */ +@Deprecated(since = "24.12.0") public class GetWorkProtocol implements StratumProtocol { private static final Logger LOG = LoggerFactory.getLogger(GetWorkProtocol.class); private static final ObjectMapper mapper = new ObjectMapper(); diff --git a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1EthProxyProtocol.java b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1EthProxyProtocol.java index 0506fa1e25b..1b7b9332854 100644 --- a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1EthProxyProtocol.java +++ b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1EthProxyProtocol.java @@ -43,6 +43,7 @@ * *

This protocol allows miners to submit EthHash solutions over a persistent TCP connection. */ +@Deprecated(since = "24.12.0") public class Stratum1EthProxyProtocol implements StratumProtocol { private static final Logger LOG = LoggerFactory.getLogger(Stratum1EthProxyProtocol.class); private static final JsonMapper mapper = new JsonMapper(); diff --git a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1Protocol.java b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1Protocol.java index 4311647948d..795bfbacd41 100644 --- a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1Protocol.java +++ b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/Stratum1Protocol.java @@ -50,6 +50,7 @@ * *

This protocol allows miners to submit EthHash solutions over a persistent TCP connection. */ +@Deprecated(since = "24.12.0") public class Stratum1Protocol implements StratumProtocol { private static final Logger LOG = LoggerFactory.getLogger(Stratum1Protocol.class); private static final JsonMapper mapper = new JsonMapper(); diff --git a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumConnection.java b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumConnection.java index 5db1957bfd0..af47b4d0fe4 100644 --- a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumConnection.java +++ b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumConnection.java @@ -24,6 +24,7 @@ * Persistent TCP connection using a variant of the Stratum protocol, connecting the client to * miners. */ +@Deprecated(since = "24.12.0") final class StratumConnection { private static final Logger LOG = LoggerFactory.getLogger(StratumConnection.class); diff --git a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumProtocol.java b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumProtocol.java index a6a8ac88071..3eda87b047b 100644 --- a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumProtocol.java +++ b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumProtocol.java @@ -37,6 +37,7 @@ *

Manages the lifecycle of a TCP connection according to a particular variant of the Stratum * protocol. */ +@Deprecated(since = "24.12.0") public interface StratumProtocol { /** diff --git a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumServer.java b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumServer.java index 7990b883905..4669e47c7b8 100644 --- a/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumServer.java +++ b/ethereum/stratum/src/main/java/org/hyperledger/besu/ethereum/stratum/StratumServer.java @@ -65,6 +65,7 @@ * TCP server allowing miners to connect to the client over persistent TCP connections, using the * various Stratum protocols. */ +@Deprecated(since = "24.12.0") public class StratumServer implements PoWObserver { private static final Logger logger = LoggerFactory.getLogger(StratumServer.class); diff --git a/evm/build.gradle b/evm/build.gradle index 1ca6f3da424..44c572bdfe0 100644 --- a/evm/build.gradle +++ b/evm/build.gradle @@ -44,7 +44,6 @@ dependencies { implementation 'io.tmio:tuweni-bytes' implementation 'io.tmio:tuweni-units' implementation 'org.hyperledger.besu:arithmetic' - implementation 'org.hyperledger.besu:bls12-381' implementation 'org.hyperledger.besu:besu-verkle-trie' implementation'org.hyperledger.besu:gnark' implementation 'tech.pegasys:jc-kzg-4844' diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java index 0e5219d8355..4ee28145def 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/account/BaseDelegatedCodeAccount.java @@ -17,6 +17,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.Optional; @@ -25,13 +26,17 @@ class BaseDelegatedCodeAccount { private final WorldUpdater worldUpdater; + private final GasCalculator gasCalculator; /** The address of the account that has delegated code to be loaded into it. */ protected final Address delegatedCodeAddress; protected BaseDelegatedCodeAccount( - final WorldUpdater worldUpdater, final Address delegatedCodeAddress) { + final WorldUpdater worldUpdater, + final Address delegatedCodeAddress, + final GasCalculator gasCalculator) { this.worldUpdater = worldUpdater; + this.gasCalculator = gasCalculator; this.delegatedCodeAddress = delegatedCodeAddress; } @@ -86,6 +91,9 @@ private Optional getDelegatedAccount() { } private Bytes resolveDelegatedCode() { + if (gasCalculator.isPrecompile(delegatedCodeAddress)) { + return Bytes.EMPTY; + } return getDelegatedAccount().map(Account::getUnprocessedCode).orElse(Bytes.EMPTY); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java index 1eba364c194..0ac969abade 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/account/DelegatedCodeAccount.java @@ -17,6 +17,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.NavigableMap; @@ -37,12 +38,14 @@ public class DelegatedCodeAccount extends BaseDelegatedCodeAccount implements Ac * @param worldUpdater the world updater. * @param wrappedAccount the account that has delegated code to be loaded into it. * @param codeDelegationAddress the address of the delegated code. + * @param gasCalculator the gas calculator to check for precompiles. */ public DelegatedCodeAccount( final WorldUpdater worldUpdater, final Account wrappedAccount, - final Address codeDelegationAddress) { - super(worldUpdater, codeDelegationAddress); + final Address codeDelegationAddress, + final GasCalculator gasCalculator) { + super(worldUpdater, codeDelegationAddress, gasCalculator); this.wrappedAccount = wrappedAccount; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java b/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java index 62b45338ebc..2246230179e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/account/MutableDelegatedCodeAccount.java @@ -17,6 +17,7 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.gascalculator.GasCalculator; import org.hyperledger.besu.evm.worldstate.WorldUpdater; import java.util.Map; @@ -39,12 +40,14 @@ public class MutableDelegatedCodeAccount extends BaseDelegatedCodeAccount * @param worldUpdater the world updater. * @param wrappedAccount the account that has delegated code to be loaded into it. * @param codeDelegationAddress the address of the delegated code. + * @param gasCalculator the gas calculator to check for precompiles. */ public MutableDelegatedCodeAccount( final WorldUpdater worldUpdater, final MutableAccount wrappedAccount, - final Address codeDelegationAddress) { - super(worldUpdater, codeDelegationAddress); + final Address codeDelegationAddress, + final GasCalculator gasCalculator) { + super(worldUpdater, codeDelegationAddress, gasCalculator); this.wrappedAccount = wrappedAccount; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/blockhash/BlockHashLookup.java b/evm/src/main/java/org/hyperledger/besu/evm/blockhash/BlockHashLookup.java new file mode 100644 index 00000000000..47f9414a4a9 --- /dev/null +++ b/evm/src/main/java/org/hyperledger/besu/evm/blockhash/BlockHashLookup.java @@ -0,0 +1,28 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.evm.blockhash; + +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.evm.frame.MessageFrame; + +import java.util.function.BiFunction; + +/** + * Function that gets the block hash, passed in as part of TxValues. + * + *

Arg is the current executing message frame. The Result is the Hash, which may be zero based on + * lookup rules. + */ +public interface BlockHashLookup extends BiFunction {} diff --git a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java index 36218c0e3c4..06b033d2735 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java @@ -15,7 +15,6 @@ package org.hyperledger.besu.evm.fluent; import static com.google.common.base.Preconditions.checkNotNull; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.collections.trie.BytesTrieSet; import org.hyperledger.besu.datatypes.AccessWitness; @@ -27,6 +26,7 @@ import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.EvmSpecVersion; import org.hyperledger.besu.evm.MainnetEVMs; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.code.CodeV0; import org.hyperledger.besu.evm.contractvalidation.ContractValidationRule; import org.hyperledger.besu.evm.contractvalidation.MaxCodeSizeRule; @@ -75,7 +75,7 @@ public class EVMExecutor { private Wei ethValue = Wei.ZERO; private Code code = CodeV0.EMPTY_CODE; private BlockValues blockValues = new SimpleBlockValues(); - private BlockHashLookup blockHashLookup = n -> null; + private BlockHashLookup blockHashLookup = (__, ___) -> null; private Optional> versionedHashes = Optional.empty(); private OperationTracer tracer = OperationTracer.NO_TRACING; private boolean requireDeposit = true; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java index c16e9aa932a..4ea478afde8 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/MessageFrame.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.Code; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import org.hyperledger.besu.evm.gascalculator.stateless.NoopAccessWitness; import org.hyperledger.besu.evm.internal.MemoryEntry; import org.hyperledger.besu.evm.internal.OperandStack; @@ -33,7 +34,6 @@ import org.hyperledger.besu.evm.internal.StorageEntry; import org.hyperledger.besu.evm.internal.UnderflowException; import org.hyperledger.besu.evm.log.Log; -import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.worldstate.WorldUpdater; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java b/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java index 81ebbdb767a..58110080459 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/frame/TxValues.java @@ -14,14 +14,13 @@ */ package org.hyperledger.besu.evm.frame; -import static org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup; - import org.hyperledger.besu.collections.undo.UndoScalar; import org.hyperledger.besu.collections.undo.UndoSet; import org.hyperledger.besu.collections.undo.UndoTable; import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.VersionedHash; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.blockhash.BlockHashLookup; import java.util.Deque; import java.util.List; diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/CancunGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/CancunGasCalculator.java index 79165e5c210..6a44bbc1d0e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/CancunGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/CancunGasCalculator.java @@ -26,31 +26,45 @@ */ public class CancunGasCalculator extends ShanghaiGasCalculator { + /** The default mainnet target blobs per block for Cancun */ + private static final int DEFAULT_TARGET_BLOBS_PER_BLOCK_CANCUN = 3; + + /** this.getBlobGasPerBlob() * 3 blobs = 131072 * 6 = 393216 = 0x60000 */ + private final long targetBlobGasPerBlock; + /** Instantiates a new Cancun Gas Calculator. */ public CancunGasCalculator() { - this(KZG_POINT_EVAL.toArrayUnsafe()[19]); + this(KZG_POINT_EVAL.toArrayUnsafe()[19], DEFAULT_TARGET_BLOBS_PER_BLOCK_CANCUN); + } + + /** + * Instantiates a new Cancun Gas Calculator + * + * @param targetBlobsPerBlock the target blobs per block + */ + public CancunGasCalculator(final int targetBlobsPerBlock) { + this(KZG_POINT_EVAL.toArrayUnsafe()[19], targetBlobsPerBlock); } /** * Instantiates a new Cancun Gas Calculator * * @param maxPrecompile the max precompile + * @param targetBlobsPerBlock the target blobs per block */ - protected CancunGasCalculator(final int maxPrecompile) { + protected CancunGasCalculator(final int maxPrecompile, final int targetBlobsPerBlock) { super(maxPrecompile); + this.targetBlobGasPerBlock = getBlobGasPerBlob() * targetBlobsPerBlock; } private static final long TLOAD_GAS = WARM_STORAGE_READ_COST; private static final long TSTORE_GAS = WARM_STORAGE_READ_COST; /** - * The blob gas cost per blob. This is the gas cost for each blob of blob that is added to the + * The blob gas cost per blob. This is the gas cost for each blob of data that is added to the * block. */ - public static final long BLOB_GAS_PER_BLOB = 1 << 17; - - /** The target blob gas per block. */ - public static final long TARGET_BLOB_GAS_PER_BLOCK = 0x60000; + private static final long BLOB_GAS_PER_BLOB = 1 << 17; // EIP-1153 @Override @@ -64,8 +78,13 @@ public long getTransientStoreOperationGasCost() { } @Override - public long blobGasCost(final int blobCount) { - return BLOB_GAS_PER_BLOB * blobCount; + public long blobGasCost(final long blobCount) { + return getBlobGasPerBlob() * blobCount; + } + + @Override + public long getBlobGasPerBlob() { + return BLOB_GAS_PER_BLOB; } /** @@ -74,37 +93,15 @@ public long blobGasCost(final int blobCount) { * @return The target blob gas per block. */ public long getTargetBlobGasPerBlock() { - return TARGET_BLOB_GAS_PER_BLOCK; - } - - /** - * Computes the excess blob gas for a given block based on the parent's excess blob gas and blob - * gas used. If the sum of parent's excess blob gas and parent's blob gas used is less than the - * target blob gas per block, the excess blob gas is calculated as 0. Otherwise, it is computed as - * the difference between the sum and the target blob gas per block. - * - * @param parentExcessBlobGas The excess blob gas of the parent block. - * @param newBlobs blob gas incurred by current block - * @return The excess blob gas for the current block. - */ - @Override - public long computeExcessBlobGas(final long parentExcessBlobGas, final int newBlobs) { - final long consumedBlobGas = blobGasCost(newBlobs); - final long currentExcessBlobGas = parentExcessBlobGas + consumedBlobGas; - - if (currentExcessBlobGas < TARGET_BLOB_GAS_PER_BLOCK) { - return 0L; - } - return currentExcessBlobGas - TARGET_BLOB_GAS_PER_BLOCK; + return targetBlobGasPerBlock; } @Override public long computeExcessBlobGas(final long parentExcessBlobGas, final long parentBlobGasUsed) { final long currentExcessBlobGas = parentExcessBlobGas + parentBlobGasUsed; - - if (currentExcessBlobGas < TARGET_BLOB_GAS_PER_BLOCK) { + if (currentExcessBlobGas < targetBlobGasPerBlock) { return 0L; } - return currentExcessBlobGas - TARGET_BLOB_GAS_PER_BLOCK; + return currentExcessBlobGas - targetBlobGasPerBlock; } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java index 91306d978d8..8ae4132d043 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/GasCalculator.java @@ -712,24 +712,22 @@ default long getTransientStoreOperationGasCost() { } /** - * Return the gas cost given the number of blobs + * Returns the blob gas cost per blob. This is the gas cost for each blob of data that is added to + * the block. * - * @param blobCount the number of blobs - * @return the total gas cost + * @return the blob gas cost per blob */ - default long blobGasCost(final int blobCount) { + default long getBlobGasPerBlob() { return 0L; } /** - * Compute the new value for the excess blob gas, given the parent value and the count of new - * blobs + * Return the gas cost given the number of blobs * - * @param parentExcessBlobGas excess blob gas from the parent - * @param newBlobs count of new blobs - * @return the new excess blob gas value + * @param blobCount the number of blobs + * @return the total gas cost */ - default long computeExcessBlobGas(final long parentExcessBlobGas, final int newBlobs) { + default long blobGasCost(final long blobCount) { return 0L; } @@ -755,8 +753,8 @@ default long delegateCodeGasCost(final int delegateCodeListLength) { } /** - * Calculates the refund for proessing the 7702 code delegation list if an delegater account - * already exist in the trie. + * Calculates the refund for processing the 7702 code delegation list if a delegator account + * already exists in the trie. * * @param alreadyExistingAccountSize The number of accounts already in the trie * @return the gas refund @@ -765,16 +763,6 @@ default long calculateDelegateCodeGasRefund(final long alreadyExistingAccountSiz return 0L; } - /** - * Returns the gas cost for resolving the code of a delegate account. - * - * @param isWarm whether the account is warm - * @return the gas cost - */ - default long delegatedCodeResolutionGasCost(final boolean isWarm) { - return 0L; - } - default AccessWitness newAccessWitness() { return NoopAccessWitness.get(); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/OsakaGasCalculator.java b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/OsakaGasCalculator.java index b4155dac52a..de56430f00f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/OsakaGasCalculator.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/gascalculator/OsakaGasCalculator.java @@ -17,10 +17,9 @@ import static org.hyperledger.besu.datatypes.Address.BLS12_MAP_FP2_TO_G2; /** - * Gas Calculator for Prague + * Gas Calculator for Osaka * - *

Placeholder for new gas schedule items. If Prague finalzies without changes this can be - * removed + *

Placeholder for new gas schedule items. If Osaka finalzies without changes this can be removed * *