Merge branch 'refs/heads/7311-add-peertask-foundation-code' into 7311-add-GetReceiptsFromPeerTask

pull/7638/head
Matilda Clerke 1 month ago
commit c4e685d2c6
  1. 2
      .github/workflows/BesuContainerVerify.sh
  2. 2
      .github/workflows/splitList.sh
  3. 2
      .github/workflows/splitTestsByTime.sh
  4. 5
      CHANGELOG.md
  5. 3
      MAINTAINERS.md
  6. 1
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  7. 17
      besu/src/main/java/org/hyperledger/besu/cli/ConfigurationOverviewBuilder.java
  8. 26
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/SynchronizerOptions.java
  9. 30
      besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java
  10. 2
      besu/src/main/scripts/besu-entry.sh
  11. 46
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  12. 39
      besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java
  13. 4
      build.gradle
  14. 2
      docker/test.sh
  15. 14
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/manager/task/GetHeadersFromPeerByNumberTask.java
  16. 167
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromBlock.java
  17. 58
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromHeadBlock.java
  18. 138
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/PivotSelectorFromSafeBlock.java
  19. 7
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapSyncConfiguration.java
  20. 4
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/snapsync/SnapSyncMetricsManager.java
  21. 10
      ethereum/eth/src/main/java/org/hyperledger/besu/ethereum/eth/sync/tasks/GetReceiptsForHeadersTask.java
  22. 12
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/manager/task/GetHeadersFromPeerByNumberTaskTest.java
  23. 52
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/fastsync/FastSyncActionsTest.java
  24. 20
      ethereum/eth/src/test/java/org/hyperledger/besu/ethereum/eth/sync/tasks/GetReceiptsForHeadersTaskTest.java
  25. 2
      ethereum/evmtool/src/test/benchmarks/bench-caliper.sh
  26. 2
      ethereum/evmtool/src/test/benchmarks/bench-loop.sh
  27. 2
      ethereum/evmtool/src/test/benchmarks/bench-mainnet.sh
  28. 2
      ethereum/evmtool/src/test/benchmarks/bench-static.sh
  29. 22
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpec.java
  30. 22
      ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/TransactionSequence.java
  31. 310
      ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/referencetests/BlockchainReferenceTestCaseSpecTest.java
  32. 2
      gradle/spotless/java.current.license
  33. 2
      gradle/spotless/sh.license
  34. 8
      gradle/verification-metadata.xml
  35. 2
      gradle/versions.gradle
  36. 2
      privacy-contracts/src/main/solidity/generateWrappers.sh
  37. 2
      scripts/dco_check.sh
  38. 9
      testutil/src/main/java/org/hyperledger/besu/testutil/JsonTestParameters.java

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -3,13 +3,13 @@
## [Unreleased] ## [Unreleased]
### Breaking Changes ### Breaking Changes
- Added isLabelsObserved to LabelledGauge in plugin-api. Implementing classes will need to also implement this method
### Upcoming Breaking Changes ### Upcoming Breaking Changes
### Additions and Improvements ### Additions and Improvements
### Bug fixes ### Bug fixes
- Fix eth_feeHistory rewards when bounded by configuration [#7750](https://github.com/hyperledger/besu/pull/7750)
## 24.10.0 ## 24.10.0
@ -18,6 +18,7 @@
### Upcoming Breaking Changes ### Upcoming Breaking Changes
- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release - k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release
- `--host-whitelist` has been deprecated in favor of `--host-allowlist` since 2020 and will be removed in a future release
### Additions and Improvements ### Additions and Improvements
- Remove privacy test classes support [#7569](https://github.com/hyperledger/besu/pull/7569) - Remove privacy test classes support [#7569](https://github.com/hyperledger/besu/pull/7569)
@ -28,7 +29,6 @@
- Interrupt pending transaction processing on block creation timeout [#7673](https://github.com/hyperledger/besu/pull/7673) - Interrupt pending transaction processing on block creation timeout [#7673](https://github.com/hyperledger/besu/pull/7673)
- Align gas cap calculation for transaction simulation to Geth approach [#7703](https://github.com/hyperledger/besu/pull/7703) - Align gas cap calculation for transaction simulation to Geth approach [#7703](https://github.com/hyperledger/besu/pull/7703)
- Expose chainId in the `BlockchainService` [7702](https://github.com/hyperledger/besu/pull/7702) - Expose chainId in the `BlockchainService` [7702](https://github.com/hyperledger/besu/pull/7702)
- Use head block instead of safe block for snap sync [7536](https://github.com/hyperledger/besu/issues/7536)
- Add support for `chainId` in `CallParameters` [#7720](https://github.com/hyperledger/besu/pull/7720) - Add support for `chainId` in `CallParameters` [#7720](https://github.com/hyperledger/besu/pull/7720)
- Add `--ephemery` network support for Ephemery Testnet [#7563](https://github.com/hyperledger/besu/pull/7563) thanks to [@gconnect](https://github.com/gconnect) - Add `--ephemery` network support for Ephemery Testnet [#7563](https://github.com/hyperledger/besu/pull/7563) thanks to [@gconnect](https://github.com/gconnect)
- Add configuration of Consolidation Request Contract Address via genesis configuration [#7647](https://github.com/hyperledger/besu/pull/7647) - Add configuration of Consolidation Request Contract Address via genesis configuration [#7647](https://github.com/hyperledger/besu/pull/7647)
@ -42,6 +42,7 @@
- Fix an unhandled PeerTable exception [#7733](https://github.com/hyperledger/besu/issues/7733) - Fix an unhandled PeerTable exception [#7733](https://github.com/hyperledger/besu/issues/7733)
- Fix RocksDBException: Busy leading to MerkleTrieException: Unable to load trie node value [#7745](https://github.com/hyperledger/besu/pull/7745) - Fix RocksDBException: Busy leading to MerkleTrieException: Unable to load trie node value [#7745](https://github.com/hyperledger/besu/pull/7745)
- If a BFT validator node is syncing, pause block production until sync has completed [#7657](https://github.com/hyperledger/besu/pull/7657) - If a BFT validator node is syncing, pause block production until sync has completed [#7657](https://github.com/hyperledger/besu/pull/7657)
- Fix eth_feeHistory rewards when bounded by configuration [#7750](https://github.com/hyperledger/besu/pull/7750)
## 24.9.1 ## 24.9.1

@ -9,6 +9,7 @@
| Name | Github | LFID | | Name | Github | LFID |
| ---------------- | ---------------- | ---------------- | | ---------------- | ---------------- | ---------------- |
| Ameziane Hamlat | ahamlat | ahamlat | | Ameziane Hamlat | ahamlat | ahamlat |
| Chaminda Divitotawela | cdivitotawela | cdivitotawela |
| Daniel Lehrner | daniellehrner | daniellehrner | | Daniel Lehrner | daniellehrner | daniellehrner |
| Diego López León | diega | diega | | Diego López León | diega | diega |
| Fabio Di Fabio | fab-10 | fab-10 | | Fabio Di Fabio | fab-10 | fab-10 |
@ -18,7 +19,7 @@
| Justin Florentine| jflo | RoboCopsGoneMad | | Justin Florentine| jflo | RoboCopsGoneMad |
| Jason Frame | jframe | jframe | | Jason Frame | jframe | jframe |
| Joshua Fernandes | joshuafernandes | joshuafernandes | | Joshua Fernandes | joshuafernandes | joshuafernandes |
| Luis Pinto | lu-pinto | lu-pinto | Luis Pinto | lu-pinto | lu-pinto |
| Lucas Saldanha | lucassaldanha | lucassaldanha | | Lucas Saldanha | lucassaldanha | lucassaldanha |
| Sally MacFarlane | macfarla | macfarla | | Sally MacFarlane | macfarla | macfarla |
| Karim Taam | matkt | matkt | | Karim Taam | matkt | matkt |

@ -2739,7 +2739,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
builder.setSnapServerEnabled(this.unstableSynchronizerOptions.isSnapsyncServerEnabled()); builder.setSnapServerEnabled(this.unstableSynchronizerOptions.isSnapsyncServerEnabled());
builder.setSnapSyncBftEnabled(this.unstableSynchronizerOptions.isSnapSyncBftEnabled()); builder.setSnapSyncBftEnabled(this.unstableSynchronizerOptions.isSnapSyncBftEnabled());
builder.setSnapSyncToHeadEnabled(this.unstableSynchronizerOptions.isSnapSyncToHeadEnabled());
builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation()); builder.setTxPoolImplementation(buildTransactionPoolConfiguration().getTxPoolImplementation());
builder.setWorldStateUpdateMode(unstableEvmOptions.toDomainObject().worldUpdaterMode()); builder.setWorldStateUpdateMode(unstableEvmOptions.toDomainObject().worldUpdaterMode());

@ -58,7 +58,6 @@ public class ConfigurationOverviewBuilder {
private Integer trieLogsPruningWindowSize = null; private Integer trieLogsPruningWindowSize = null;
private boolean isSnapServerEnabled = false; private boolean isSnapServerEnabled = false;
private boolean isSnapSyncBftEnabled = false; private boolean isSnapSyncBftEnabled = false;
private boolean isSnapSyncToHeadEnabled = true;
private TransactionPoolConfiguration.Implementation txPoolImplementation; private TransactionPoolConfiguration.Implementation txPoolImplementation;
private EvmConfiguration.WorldUpdaterMode worldStateUpdateMode; private EvmConfiguration.WorldUpdaterMode worldStateUpdateMode;
private Map<String, String> environment; private Map<String, String> environment;
@ -258,18 +257,6 @@ public class ConfigurationOverviewBuilder {
return this; return this;
} }
/**
* Sets snap sync to head enabled/disabled
*
* @param snapSyncToHeadEnabled bool to indicate if snap sync to head is enabled
* @return the builder
*/
public ConfigurationOverviewBuilder setSnapSyncToHeadEnabled(
final boolean snapSyncToHeadEnabled) {
isSnapSyncToHeadEnabled = snapSyncToHeadEnabled;
return this;
}
/** /**
* Sets trie logs pruning window size * Sets trie logs pruning window size
* *
@ -402,10 +389,6 @@ public class ConfigurationOverviewBuilder {
lines.add("Experimental Snap Sync for BFT enabled"); lines.add("Experimental Snap Sync for BFT enabled");
} }
if (isSnapSyncToHeadEnabled) {
lines.add("Snap Sync to Head enabled");
}
if (isBonsaiLimitTrieLogsEnabled) { if (isBonsaiLimitTrieLogsEnabled) {
final StringBuilder trieLogPruningString = new StringBuilder(); final StringBuilder trieLogPruningString = new StringBuilder();
trieLogPruningString trieLogPruningString

@ -87,8 +87,6 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
private static final String SNAP_SYNC_BFT_ENABLED_FLAG = "--Xsnapsync-bft-enabled"; private static final String SNAP_SYNC_BFT_ENABLED_FLAG = "--Xsnapsync-bft-enabled";
private static final String SNAP_SYNC_TO_HEAD_ENABLED_FLAG = "--Xsnapsync-to-head-enabled";
/** /**
* Parse block propagation range. * Parse block propagation range.
* *
@ -316,15 +314,6 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
description = "Snap sync enabled for BFT chains (default: ${DEFAULT-VALUE})") description = "Snap sync enabled for BFT chains (default: ${DEFAULT-VALUE})")
private Boolean snapsyncBftEnabled = SnapSyncConfiguration.DEFAULT_SNAP_SYNC_BFT_ENABLED; private Boolean snapsyncBftEnabled = SnapSyncConfiguration.DEFAULT_SNAP_SYNC_BFT_ENABLED;
@CommandLine.Option(
names = SNAP_SYNC_TO_HEAD_ENABLED_FLAG,
hidden = true,
paramLabel = "<Boolean>",
arity = "0..1",
description = "Snap sync to head enabled (default: ${DEFAULT-VALUE})")
private Boolean snapsyncToHeadEnabled =
SnapSyncConfiguration.DEFAULT_SNAP_SYNC_TO_HEAD_ENABLED_FLAG;
@CommandLine.Option( @CommandLine.Option(
names = {"--Xpeertask-system-enabled"}, names = {"--Xpeertask-system-enabled"},
hidden = true, hidden = true,
@ -352,15 +341,6 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
return snapsyncBftEnabled; return snapsyncBftEnabled;
} }
/**
* Flag to know if Snap sync should sync to head instead of safe block
*
* @return true if snap sync should sync to head
*/
public boolean isSnapSyncToHeadEnabled() {
return snapsyncToHeadEnabled;
}
/** /**
* Flag to indicate whether the peer task system should be used where available * Flag to indicate whether the peer task system should be used where available
* *
@ -421,7 +401,6 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
options.checkpointPostMergeSyncEnabled = config.isCheckpointPostMergeEnabled(); options.checkpointPostMergeSyncEnabled = config.isCheckpointPostMergeEnabled();
options.snapsyncServerEnabled = config.getSnapSyncConfiguration().isSnapServerEnabled(); options.snapsyncServerEnabled = config.getSnapSyncConfiguration().isSnapServerEnabled();
options.snapsyncBftEnabled = config.getSnapSyncConfiguration().isSnapSyncBftEnabled(); options.snapsyncBftEnabled = config.getSnapSyncConfiguration().isSnapSyncBftEnabled();
options.snapsyncToHeadEnabled = config.getSnapSyncConfiguration().isSnapSyncToHeadEnabled();
return options; return options;
} }
@ -455,7 +434,6 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
.localFlatStorageCountToHealPerRequest(snapsyncFlatStorageHealedCountPerRequest) .localFlatStorageCountToHealPerRequest(snapsyncFlatStorageHealedCountPerRequest)
.isSnapServerEnabled(snapsyncServerEnabled) .isSnapServerEnabled(snapsyncServerEnabled)
.isSnapSyncBftEnabled(snapsyncBftEnabled) .isSnapSyncBftEnabled(snapsyncBftEnabled)
.isSnapSyncToHeadEnabled(snapsyncToHeadEnabled)
.build()); .build());
builder.checkpointPostMergeEnabled(checkpointPostMergeSyncEnabled); builder.checkpointPostMergeEnabled(checkpointPostMergeSyncEnabled);
builder.isPeerTaskSystemEnabled(isPeerTaskSystemEnabled); builder.isPeerTaskSystemEnabled(isPeerTaskSystemEnabled);
@ -515,9 +493,7 @@ public class SynchronizerOptions implements CLIOptions<SynchronizerConfiguration
SNAP_SERVER_ENABLED_FLAG, SNAP_SERVER_ENABLED_FLAG,
OptionParser.format(snapsyncServerEnabled), OptionParser.format(snapsyncServerEnabled),
SNAP_SYNC_BFT_ENABLED_FLAG, SNAP_SYNC_BFT_ENABLED_FLAG,
OptionParser.format(snapsyncBftEnabled), OptionParser.format(snapsyncBftEnabled));
SNAP_SYNC_TO_HEAD_ENABLED_FLAG,
OptionParser.format(snapsyncToHeadEnabled));
return value; return value;
} }
} }

@ -67,7 +67,6 @@ import org.hyperledger.besu.ethereum.eth.sync.DefaultSynchronizer;
import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector;
import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SyncMode;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromHeadBlock;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromPeers; import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromPeers;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromSafeBlock; import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromSafeBlock;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint; import org.hyperledger.besu.ethereum.eth.sync.fastsync.checkpoint.Checkpoint;
@ -903,27 +902,14 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
LOG.info("Initial sync done, unsubscribe forkchoice supplier"); LOG.info("Initial sync done, unsubscribe forkchoice supplier");
}; };
if (syncConfig.getSnapSyncConfiguration().isSnapSyncToHeadEnabled()) { return new PivotSelectorFromSafeBlock(
LOG.info("Using head block for sync."); protocolContext,
return new PivotSelectorFromHeadBlock( protocolSchedule,
protocolContext, ethContext,
protocolSchedule, metricsSystem,
ethContext, genesisConfigOptions,
metricsSystem, unverifiedForkchoiceSupplier,
genesisConfigOptions, unsubscribeForkchoiceListener);
unverifiedForkchoiceSupplier,
unsubscribeForkchoiceListener);
} else {
LOG.info("Using safe block for sync.");
return new PivotSelectorFromSafeBlock(
protocolContext,
protocolSchedule,
ethContext,
metricsSystem,
genesisConfigOptions,
unverifiedForkchoiceSupplier,
unsubscribeForkchoiceListener);
}
} else { } else {
LOG.info("TTD difficulty is not present, creating initial sync phase for PoW"); 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, metricsSystem);

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1014,7 +1014,7 @@ public class BesuCommandTest extends CommandTestAbstract {
} }
@Test @Test
public void p2pHostAndPortOptionsAreRespected() { public void p2pHostAndPortOptionsAreRespectedAndNotLeaked() {
final String host = "1.2.3.4"; final String host = "1.2.3.4";
final int port = 1234; final int port = 1234;
@ -1022,6 +1022,8 @@ public class BesuCommandTest extends CommandTestAbstract {
verify(mockRunnerBuilder).p2pAdvertisedHost(stringArgumentCaptor.capture()); verify(mockRunnerBuilder).p2pAdvertisedHost(stringArgumentCaptor.capture());
verify(mockRunnerBuilder).p2pListenPort(intArgumentCaptor.capture()); verify(mockRunnerBuilder).p2pListenPort(intArgumentCaptor.capture());
verify(mockRunnerBuilder).metricsConfiguration(metricsConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build(); verify(mockRunnerBuilder).build();
assertThat(stringArgumentCaptor.getValue()).isEqualTo(host); assertThat(stringArgumentCaptor.getValue()).isEqualTo(host);
@ -1030,11 +1032,47 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(commandOutput.toString(UTF_8)).isEmpty(); assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty(); assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
// rpc host should remain default ie 127.0.0.1 // all other port values remain default
assertThat(metricsConfigArgumentCaptor.getValue().getPort()).isEqualTo(9545);
assertThat(metricsConfigArgumentCaptor.getValue().getPushPort()).isEqualTo(9001);
assertThat(jsonRpcConfigArgumentCaptor.getValue().getPort()).isEqualTo(8545);
// all other host values remain default
final String defaultHost = "127.0.0.1";
assertThat(metricsConfigArgumentCaptor.getValue().getHost()).isEqualTo(defaultHost);
assertThat(metricsConfigArgumentCaptor.getValue().getPushHost()).isEqualTo(defaultHost);
assertThat(jsonRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo(defaultHost);
}
@Test
public void p2pHostAndPortOptionsAreRespectedAndNotLeakedWithMetricsEnabled() {
final String host = "1.2.3.4";
final int port = 1234;
parseCommand("--p2p-host", host, "--p2p-port", String.valueOf(port), "--metrics-enabled");
verify(mockRunnerBuilder).p2pAdvertisedHost(stringArgumentCaptor.capture());
verify(mockRunnerBuilder).p2pListenPort(intArgumentCaptor.capture());
verify(mockRunnerBuilder).metricsConfiguration(metricsConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture()); verify(mockRunnerBuilder).jsonRpcConfiguration(jsonRpcConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build(); verify(mockRunnerBuilder).build();
assertThat(jsonRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo("127.0.0.1"); assertThat(stringArgumentCaptor.getValue()).isEqualTo(host);
assertThat(intArgumentCaptor.getValue()).isEqualTo(port);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
// all other port values remain default
assertThat(metricsConfigArgumentCaptor.getValue().getPort()).isEqualTo(9545);
assertThat(metricsConfigArgumentCaptor.getValue().getPushPort()).isEqualTo(9001);
assertThat(jsonRpcConfigArgumentCaptor.getValue().getPort()).isEqualTo(8545);
// all other host values remain default
final String defaultHost = "127.0.0.1";
assertThat(metricsConfigArgumentCaptor.getValue().getHost()).isEqualTo(defaultHost);
assertThat(metricsConfigArgumentCaptor.getValue().getPushHost()).isEqualTo(defaultHost);
assertThat(jsonRpcConfigArgumentCaptor.getValue().getHost()).isEqualTo(defaultHost);
} }
@Test @Test
@ -2285,7 +2323,7 @@ public class BesuCommandTest extends CommandTestAbstract {
} }
@Test @Test
public void staticNodesFileOptionValidParamenter() throws IOException { public void staticNodesFileOptionValidParameter() throws IOException {
final Path staticNodeTempFile = final Path staticNodeTempFile =
createTempFile( createTempFile(
"static-nodes-goodformat.json", "static-nodes-goodformat.json",

@ -45,8 +45,6 @@ import org.hyperledger.besu.ethereum.core.MiningParameters;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromHeadBlock;
import org.hyperledger.besu.ethereum.eth.sync.fastsync.PivotSelectorFromSafeBlock;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket; import org.hyperledger.besu.ethereum.mainnet.feemarket.BaseFeeMarket;
@ -76,15 +74,12 @@ import com.google.common.collect.Range;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256; import org.apache.tuweni.units.bigints.UInt256;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDir;
import org.mockito.Answers; import org.mockito.Answers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockedConstruction;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
@ -95,10 +90,7 @@ public class MergeBesuControllerBuilderTest {
@Mock GenesisConfigFile genesisConfigFile; @Mock GenesisConfigFile genesisConfigFile;
@Mock GenesisConfigOptions genesisConfigOptions; @Mock GenesisConfigOptions genesisConfigOptions;
@Mock SynchronizerConfiguration synchronizerConfiguration;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
SynchronizerConfiguration synchronizerConfiguration;
@Mock EthProtocolConfiguration ethProtocolConfiguration; @Mock EthProtocolConfiguration ethProtocolConfiguration;
@Mock CheckpointConfigOptions checkpointConfigOptions; @Mock CheckpointConfigOptions checkpointConfigOptions;
@ -154,9 +146,6 @@ public class MergeBesuControllerBuilderTest {
lenient().when(synchronizerConfiguration.getDownloaderParallelism()).thenReturn(1); lenient().when(synchronizerConfiguration.getDownloaderParallelism()).thenReturn(1);
lenient().when(synchronizerConfiguration.getTransactionsParallelism()).thenReturn(1); lenient().when(synchronizerConfiguration.getTransactionsParallelism()).thenReturn(1);
lenient().when(synchronizerConfiguration.getComputationParallelism()).thenReturn(1); lenient().when(synchronizerConfiguration.getComputationParallelism()).thenReturn(1);
lenient()
.when(synchronizerConfiguration.getSnapSyncConfiguration().isSnapSyncToHeadEnabled())
.thenReturn(false);
lenient() lenient()
.when(synchronizerConfiguration.getBlockPropagationRange()) .when(synchronizerConfiguration.getBlockPropagationRange())
@ -302,32 +291,6 @@ public class MergeBesuControllerBuilderTest {
assertThat(mergeContext.getFinalized().get()).isEqualTo(finalizedHeader); assertThat(mergeContext.getFinalized().get()).isEqualTo(finalizedHeader);
} }
@Test
public void assertPivotSelectorFromSafeBlockIsCreated() {
MockedConstruction<PivotSelectorFromSafeBlock> mocked =
Mockito.mockConstruction(PivotSelectorFromSafeBlock.class);
lenient()
.when(synchronizerConfiguration.getSnapSyncConfiguration().isSnapSyncToHeadEnabled())
.thenReturn(false);
visitWithMockConfigs(new MergeBesuControllerBuilder()).build();
Assertions.assertEquals(1, mocked.constructed().size());
}
@Test
public void assertPivotSelectorFromHeadBlockIsCreated() {
MockedConstruction<PivotSelectorFromHeadBlock> mocked =
Mockito.mockConstruction(PivotSelectorFromHeadBlock.class);
lenient()
.when(synchronizerConfiguration.getSnapSyncConfiguration().isSnapSyncToHeadEnabled())
.thenReturn(true);
visitWithMockConfigs(new MergeBesuControllerBuilder()).build();
Assertions.assertEquals(1, mocked.constructed().size());
}
private BlockHeader finalizedBlockHeader() { private BlockHeader finalizedBlockHeader() {
final long blockNumber = 42; final long blockNumber = 42;
final Hash magicHash = Hash.wrap(Bytes32.leftPad(Bytes.ofUnsignedInt(42))); final Hash magicHash = Hash.wrap(Bytes32.leftPad(Bytes.ofUnsignedInt(42)));

@ -215,7 +215,7 @@ allprojects {
// apply appropriate license header files. // apply appropriate license header files.
licenseHeaderFile("${rootDir}/gradle/spotless/java.former.license").named("older").onlyIfContentMatches("^/\\*\\r?\\n.*Copyright ConsenSys AG\\.") licenseHeaderFile("${rootDir}/gradle/spotless/java.former.license").named("older").onlyIfContentMatches("^/\\*\\r?\\n.*Copyright ConsenSys AG\\.")
licenseHeaderFile("${rootDir}/gradle/spotless/java.former.date.license").named("older.year").onlyIfContentMatches("^/\\*\\r?\\n.* Copyright \\d{4} ConsenSys AG\\.") licenseHeaderFile("${rootDir}/gradle/spotless/java.former.date.license").named("older.year").onlyIfContentMatches("^/\\*\\r?\\n.* Copyright \\d{4} ConsenSys AG\\.")
licenseHeaderFile("${rootDir}/gradle/spotless/java.current.license").named("current").onlyIfContentMatches("^(?!/\\*\\r?\\n \\*.*ConsenSys AG\\.)") licenseHeaderFile("${rootDir}/gradle/spotless/java.current.license").named("current").onlyIfContentMatches("^(?!/\\*\\r?\\n \\*.*(ConsenSys AG|Hyperledger Besu)\\.)")
} }
// spotless check applied to build.gradle (groovy) files // spotless check applied to build.gradle (groovy) files
groovyGradle { groovyGradle {
@ -240,7 +240,7 @@ allprojects {
licenseHeaderFile("${rootDir}/gradle/spotless/java.former.license","^pragma solidity.+?").named("former").onlyIfContentMatches("^/\\*\\r?\\n.*Copyright ConsenSys AG\\.") licenseHeaderFile("${rootDir}/gradle/spotless/java.former.license","^pragma solidity.+?").named("former").onlyIfContentMatches("^/\\*\\r?\\n.*Copyright ConsenSys AG\\.")
licenseHeaderFile("${rootDir}/gradle/spotless/java.former.date.license","^pragma solidity.+?").named("former.date").onlyIfContentMatches("^/\\*\\r?\\n.* Copyright \\d{4} ConsenSys AG\\.") licenseHeaderFile("${rootDir}/gradle/spotless/java.former.date.license","^pragma solidity.+?").named("former.date").onlyIfContentMatches("^/\\*\\r?\\n.* Copyright \\d{4} ConsenSys AG\\.")
licenseHeaderFile("${rootDir}/gradle/spotless/java.current.license","^pragma solidity.+?").named("current").onlyIfContentMatches("^(?!/\\*\\r?\\n \\*.*ConsenSys AG\\.)") licenseHeaderFile("${rootDir}/gradle/spotless/java.current.license","^pragma solidity.+?").named("current").onlyIfContentMatches("^(?!/\\*\\r?\\n \\*.*(ConsenSys AG|Hyperledger Besu)\\.)")
} }
} }

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -43,25 +43,15 @@ public class GetHeadersFromPeerByNumberTask extends AbstractGetHeadersFromPeerTa
this.blockNumber = blockNumber; this.blockNumber = blockNumber;
} }
public static AbstractGetHeadersFromPeerTask startingAtNumber(
final ProtocolSchedule protocolSchedule,
final EthContext ethContext,
final long firstBlockNumber,
final int segmentLength,
final MetricsSystem metricsSystem) {
return new GetHeadersFromPeerByNumberTask(
protocolSchedule, ethContext, firstBlockNumber, segmentLength, 0, false, metricsSystem);
}
public static AbstractGetHeadersFromPeerTask endingAtNumber( public static AbstractGetHeadersFromPeerTask endingAtNumber(
final ProtocolSchedule protocolSchedule, final ProtocolSchedule protocolSchedule,
final EthContext ethContext, final EthContext ethContext,
final long lastlockNumber, final long lastBlockNumber,
final int segmentLength, final int segmentLength,
final int skip, final int skip,
final MetricsSystem metricsSystem) { final MetricsSystem metricsSystem) {
return new GetHeadersFromPeerByNumberTask( return new GetHeadersFromPeerByNumberTask(
protocolSchedule, ethContext, lastlockNumber, segmentLength, skip, true, metricsSystem); protocolSchedule, ethContext, lastBlockNumber, segmentLength, skip, true, metricsSystem);
} }
public static AbstractGetHeadersFromPeerTask forSingleNumber( public static AbstractGetHeadersFromPeerTask forSingleNumber(

@ -1,167 +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.eth.sync.fastsync;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.consensus.merge.ForkchoiceEvent;
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.task.WaitForPeersTask;
import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector;
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.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class PivotSelectorFromBlock implements PivotBlockSelector {
private static final Logger LOG = LoggerFactory.getLogger(PivotSelectorFromBlock.class);
private final ProtocolContext protocolContext;
private final ProtocolSchedule protocolSchedule;
private final EthContext ethContext;
private final MetricsSystem metricsSystem;
private final GenesisConfigOptions genesisConfig;
private final Supplier<Optional<ForkchoiceEvent>> forkchoiceStateSupplier;
private final Runnable cleanupAction;
private long lastNoFcuReceivedInfoLog = System.currentTimeMillis();
private static final long NO_FCU_RECEIVED_LOGGING_THRESHOLD = 60000L;
private volatile Optional<BlockHeader> maybeCachedHeadBlockHeader = Optional.empty();
public PivotSelectorFromBlock(
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final EthContext ethContext,
final MetricsSystem metricsSystem,
final GenesisConfigOptions genesisConfig,
final Supplier<Optional<ForkchoiceEvent>> forkchoiceStateSupplier,
final Runnable cleanupAction) {
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
this.ethContext = ethContext;
this.metricsSystem = metricsSystem;
this.genesisConfig = genesisConfig;
this.forkchoiceStateSupplier = forkchoiceStateSupplier;
this.cleanupAction = cleanupAction;
}
@Override
public CompletableFuture<Void> prepareRetry() {
// nothing to do
return CompletableFuture.completedFuture(null);
}
@Override
public void close() {
cleanupAction.run();
}
@Override
public long getMinRequiredBlockNumber() {
return genesisConfig.getTerminalBlockNumber().orElse(0L);
}
@Override
public long getBestChainHeight() {
final long localChainHeight = protocolContext.getBlockchain().getChainHeadBlockNumber();
return Math.max(
forkchoiceStateSupplier
.get()
.map(ForkchoiceEvent::getHeadBlockHash)
.map(
headBlockHash ->
maybeCachedHeadBlockHeader
.filter(
cachedBlockHeader -> cachedBlockHeader.getHash().equals(headBlockHash))
.map(BlockHeader::getNumber)
.orElseGet(
() -> {
LOG.debug(
"Downloading chain head block header by hash {}", headBlockHash);
try {
return waitForPeers(1)
.thenCompose(unused -> downloadBlockHeader(headBlockHash))
.thenApply(
blockHeader -> {
maybeCachedHeadBlockHeader = Optional.of(blockHeader);
return blockHeader.getNumber();
})
.get(20, TimeUnit.SECONDS);
} catch (Throwable t) {
LOG.debug(
"Error trying to download chain head block header by hash {}",
headBlockHash,
t);
}
return null;
}))
.orElse(0L),
localChainHeight);
}
@Override
public Optional<FastSyncState> selectNewPivotBlock() {
final Optional<ForkchoiceEvent> maybeForkchoice = forkchoiceStateSupplier.get();
if (maybeForkchoice.isPresent()) {
Optional<Hash> pivotHash = getPivotHash(maybeForkchoice.get());
if (pivotHash.isPresent()) {
LOG.info("Selecting new pivot block: {}", pivotHash);
return Optional.of(new FastSyncState(pivotHash.get()));
}
}
if (lastNoFcuReceivedInfoLog + NO_FCU_RECEIVED_LOGGING_THRESHOLD < System.currentTimeMillis()) {
lastNoFcuReceivedInfoLog = System.currentTimeMillis();
LOG.info(
"Waiting for consensus client, this may be because your consensus client is still syncing");
}
LOG.debug("No finalized block hash announced yet");
return Optional.empty();
}
private CompletableFuture<BlockHeader> 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<Void> waitForPeers(final int count) {
final WaitForPeersTask waitForPeersTask =
WaitForPeersTask.create(ethContext, count, metricsSystem);
return waitForPeersTask.run();
}
protected abstract Optional<Hash> getPivotHash(final ForkchoiceEvent forkchoiceEvent);
}

@ -1,58 +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.eth.sync.fastsync;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.consensus.merge.ForkchoiceEvent;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.eth.manager.EthContext;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.Optional;
import java.util.function.Supplier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PivotSelectorFromHeadBlock extends PivotSelectorFromBlock {
private static final Logger LOG = LoggerFactory.getLogger(PivotSelectorFromHeadBlock.class);
public PivotSelectorFromHeadBlock(
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final EthContext ethContext,
final MetricsSystem metricsSystem,
final GenesisConfigOptions genesisConfig,
final Supplier<Optional<ForkchoiceEvent>> forkchoiceStateSupplier,
final Runnable cleanupAction) {
super(
protocolContext,
protocolSchedule,
ethContext,
metricsSystem,
genesisConfig,
forkchoiceStateSupplier,
cleanupAction);
}
@Override
protected Optional<Hash> getPivotHash(final ForkchoiceEvent forkchoiceEvent) {
Hash hash = forkchoiceEvent.getHeadBlockHash();
LOG.info("Returning head block hash {} as pivot", hash);
return Optional.of(hash);
}
}

@ -18,18 +18,36 @@ import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.consensus.merge.ForkchoiceEvent; import org.hyperledger.besu.consensus.merge.ForkchoiceEvent;
import org.hyperledger.besu.datatypes.Hash; import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext; 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.EthContext;
import org.hyperledger.besu.ethereum.eth.manager.task.WaitForPeersTask;
import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector;
import org.hyperledger.besu.ethereum.eth.sync.tasks.RetryingGetHeaderFromPeerByHashTask;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.MetricsSystem;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
public class PivotSelectorFromSafeBlock extends PivotSelectorFromBlock { public class PivotSelectorFromSafeBlock implements PivotBlockSelector {
private static final Logger LOG = LoggerFactory.getLogger(PivotSelectorFromSafeBlock.class); private static final Logger LOG = LoggerFactory.getLogger(PivotSelectorFromSafeBlock.class);
private final ProtocolContext protocolContext;
private final ProtocolSchedule protocolSchedule;
private final EthContext ethContext;
private final MetricsSystem metricsSystem;
private final GenesisConfigOptions genesisConfig;
private final Supplier<Optional<ForkchoiceEvent>> forkchoiceStateSupplier;
private final Runnable cleanupAction;
private long lastNoFcuReceivedInfoLog = System.currentTimeMillis();
private static final long NO_FCU_RECEIVED_LOGGING_THRESHOLD = 60000L;
private volatile Optional<BlockHeader> maybeCachedHeadBlockHeader = Optional.empty();
public PivotSelectorFromSafeBlock( public PivotSelectorFromSafeBlock(
final ProtocolContext protocolContext, final ProtocolContext protocolContext,
@ -39,25 +57,111 @@ public class PivotSelectorFromSafeBlock extends PivotSelectorFromBlock {
final GenesisConfigOptions genesisConfig, final GenesisConfigOptions genesisConfig,
final Supplier<Optional<ForkchoiceEvent>> forkchoiceStateSupplier, final Supplier<Optional<ForkchoiceEvent>> forkchoiceStateSupplier,
final Runnable cleanupAction) { final Runnable cleanupAction) {
super( this.protocolContext = protocolContext;
protocolContext, this.protocolSchedule = protocolSchedule;
protocolSchedule, this.ethContext = ethContext;
ethContext, this.metricsSystem = metricsSystem;
metricsSystem, this.genesisConfig = genesisConfig;
genesisConfig, this.forkchoiceStateSupplier = forkchoiceStateSupplier;
forkchoiceStateSupplier, this.cleanupAction = cleanupAction;
cleanupAction);
} }
@Override @Override
protected Optional<Hash> getPivotHash(final ForkchoiceEvent forkchoiceEvent) { public Optional<FastSyncState> selectNewPivotBlock() {
if (forkchoiceEvent.hasValidSafeBlockHash()) { final Optional<ForkchoiceEvent> maybeForkchoice = forkchoiceStateSupplier.get();
Hash hash = forkchoiceEvent.getSafeBlockHash(); if (maybeForkchoice.isPresent() && maybeForkchoice.get().hasValidSafeBlockHash()) {
LOG.debug("Returning safe block hash {} as pivot.", hash); return Optional.of(selectLastSafeBlockAsPivot(maybeForkchoice.get().getSafeBlockHash()));
return Optional.of(hash); }
} else { if (lastNoFcuReceivedInfoLog + NO_FCU_RECEIVED_LOGGING_THRESHOLD < System.currentTimeMillis()) {
LOG.debug("No safe block hash found."); lastNoFcuReceivedInfoLog = System.currentTimeMillis();
return Optional.empty(); LOG.info(
"Waiting for consensus client, this may be because your consensus client is still syncing");
} }
LOG.debug("No finalized block hash announced yet");
return Optional.empty();
}
@Override
public CompletableFuture<Void> prepareRetry() {
// nothing to do
return CompletableFuture.completedFuture(null);
}
private FastSyncState selectLastSafeBlockAsPivot(final Hash safeHash) {
LOG.debug("Returning safe block hash {} as pivot", safeHash);
return new FastSyncState(safeHash);
}
@Override
public void close() {
cleanupAction.run();
}
@Override
public long getMinRequiredBlockNumber() {
return genesisConfig.getTerminalBlockNumber().orElse(0L);
}
@Override
public long getBestChainHeight() {
final long localChainHeight = protocolContext.getBlockchain().getChainHeadBlockNumber();
return Math.max(
forkchoiceStateSupplier
.get()
.map(ForkchoiceEvent::getHeadBlockHash)
.map(
headBlockHash ->
maybeCachedHeadBlockHeader
.filter(
cachedBlockHeader -> cachedBlockHeader.getHash().equals(headBlockHash))
.map(BlockHeader::getNumber)
.orElseGet(
() -> {
LOG.debug(
"Downloading chain head block header by hash {}", headBlockHash);
try {
return waitForPeers(1)
.thenCompose(unused -> downloadBlockHeader(headBlockHash))
.thenApply(
blockHeader -> {
maybeCachedHeadBlockHeader = Optional.of(blockHeader);
return blockHeader.getNumber();
})
.get(20, TimeUnit.SECONDS);
} catch (Throwable t) {
LOG.debug(
"Error trying to download chain head block header by hash {}",
headBlockHash,
t);
}
return null;
}))
.orElse(0L),
localChainHeight);
}
private CompletableFuture<BlockHeader> 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<Void> waitForPeers(final int count) {
final WaitForPeersTask waitForPeersTask =
WaitForPeersTask.create(ethContext, count, metricsSystem);
return waitForPeersTask.run();
} }
} }

@ -40,8 +40,6 @@ public class SnapSyncConfiguration {
public static final Boolean DEFAULT_SNAP_SYNC_BFT_ENABLED = Boolean.FALSE; public static final Boolean DEFAULT_SNAP_SYNC_BFT_ENABLED = Boolean.FALSE;
public static final Boolean DEFAULT_SNAP_SYNC_TO_HEAD_ENABLED_FLAG = Boolean.TRUE;
public static SnapSyncConfiguration getDefault() { public static SnapSyncConfiguration getDefault() {
return ImmutableSnapSyncConfiguration.builder().build(); return ImmutableSnapSyncConfiguration.builder().build();
} }
@ -90,9 +88,4 @@ public class SnapSyncConfiguration {
public Boolean isSnapSyncBftEnabled() { public Boolean isSnapSyncBftEnabled() {
return DEFAULT_SNAP_SYNC_BFT_ENABLED; return DEFAULT_SNAP_SYNC_BFT_ENABLED;
} }
@Value.Default
public Boolean isSnapSyncToHeadEnabled() {
return DEFAULT_SNAP_SYNC_TO_HEAD_ENABLED_FLAG;
}
} }

@ -218,13 +218,11 @@ public class SnapSyncMetricsManager {
public void notifySnapSyncCompleted() { public void notifySnapSyncCompleted() {
final Duration duration = Duration.ofMillis(System.currentTimeMillis() - startSyncTime); final Duration duration = Duration.ofMillis(System.currentTimeMillis() - startSyncTime);
final long hours = (duration.toDaysPart() * 24) + duration.toHoursPart();
LOG.info( LOG.info(
"Finished worldstate snapsync with nodes {} (healed={}) duration {}{}:{},{}.", "Finished worldstate snapsync with nodes {} (healed={}) duration {}{}:{},{}.",
nbTrieNodesGenerated.addAndGet(nbTrieNodesHealed.get()), nbTrieNodesGenerated.addAndGet(nbTrieNodesHealed.get()),
nbTrieNodesHealed, nbTrieNodesHealed,
hours > 0 ? (hours + ":") : "", duration.toHoursPart() > 0 ? (duration.toHoursPart() + ":") : "",
duration.toMinutesPart(), duration.toMinutesPart(),
duration.toSecondsPart(), duration.toSecondsPart(),
duration.toMillisPart()); duration.toMillisPart());

@ -42,7 +42,7 @@ import org.slf4j.LoggerFactory;
public class GetReceiptsForHeadersTask public class GetReceiptsForHeadersTask
extends AbstractRetryingPeerTask<Map<BlockHeader, List<TransactionReceipt>>> { extends AbstractRetryingPeerTask<Map<BlockHeader, List<TransactionReceipt>>> {
private static final Logger LOG = LoggerFactory.getLogger(GetReceiptsForHeadersTask.class); private static final Logger LOG = LoggerFactory.getLogger(GetReceiptsForHeadersTask.class);
private static final int DEFAULT_RETRIES = 5; protected static final int DEFAULT_RETRIES = 5;
private final EthContext ethContext; private final EthContext ethContext;
@ -66,14 +66,6 @@ public class GetReceiptsForHeadersTask
} }
// TODO: This is only used in test code and should be removed // TODO: This is only used in test code and should be removed
public static GetReceiptsForHeadersTask forHeaders(
final EthContext ethContext,
final List<BlockHeader> headers,
final int maxRetries,
final MetricsSystem metricsSystem) {
return new GetReceiptsForHeadersTask(ethContext, headers, maxRetries, metricsSystem);
}
public static GetReceiptsForHeadersTask forHeaders( public static GetReceiptsForHeadersTask forHeaders(
final EthContext ethContext, final EthContext ethContext,
final List<BlockHeader> headers, final List<BlockHeader> headers,

@ -57,7 +57,7 @@ public class GetHeadersFromPeerByNumberTaskTest extends PeerMessageTaskTest<List
protected List<BlockHeader> generateDataToBeRequested() { protected List<BlockHeader> generateDataToBeRequested() {
final int count = 3; final int count = 3;
final List<BlockHeader> requestedHeaders = new ArrayList<>(count); final List<BlockHeader> requestedHeaders = new ArrayList<>(count);
for (long i = 0; i < count; i++) { for (long i = count - 1; i >= 0; i--) {
requestedHeaders.add(blockchain.getBlockHeader(5 + i).get()); requestedHeaders.add(blockchain.getBlockHeader(5 + i).get());
} }
return requestedHeaders; return requestedHeaders;
@ -66,9 +66,13 @@ public class GetHeadersFromPeerByNumberTaskTest extends PeerMessageTaskTest<List
@Override @Override
protected EthTask<AbstractPeerTask.PeerTaskResult<List<BlockHeader>>> createTask( protected EthTask<AbstractPeerTask.PeerTaskResult<List<BlockHeader>>> createTask(
final List<BlockHeader> requestedData) { final List<BlockHeader> requestedData) {
final BlockHeader firstHeader = requestedData.get(0); return GetHeadersFromPeerByNumberTask.endingAtNumber(
return GetHeadersFromPeerByNumberTask.startingAtNumber( protocolSchedule,
protocolSchedule, ethContext, firstHeader.getNumber(), requestedData.size(), metricsSystem); ethContext,
requestedData.getFirst().getNumber(),
requestedData.size(),
0,
metricsSystem);
} }
@Test @Test

@ -39,7 +39,6 @@ import org.hyperledger.besu.ethereum.eth.peervalidation.PeerValidator;
import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector; import org.hyperledger.besu.ethereum.eth.sync.PivotBlockSelector;
import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SyncMode;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.snapsync.ImmutableSnapSyncConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.state.SyncState; import org.hyperledger.besu.ethereum.eth.sync.state.SyncState;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator; import org.hyperledger.besu.ethereum.worldstate.WorldStateStorageCoordinator;
@ -489,7 +488,7 @@ public class FastSyncActionsTest {
@ParameterizedTest @ParameterizedTest
@ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class) @ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class)
public void downloadPivotBlockHeaderShouldRetrieveSafePivotBlockHash( public void downloadPivotBlockHeaderShouldRetrievePivotBlockHash(
final DataStorageFormat storageFormat) { final DataStorageFormat storageFormat) {
setUp(storageFormat); setUp(storageFormat);
syncConfig = SynchronizerConfiguration.builder().syncMinimumPeerCount(1).build(); syncConfig = SynchronizerConfiguration.builder().syncMinimumPeerCount(1).build();
@ -527,55 +526,6 @@ public class FastSyncActionsTest {
assertThat(result).isCompletedWithValue(new FastSyncState(blockchain.getBlockHeader(3).get())); assertThat(result).isCompletedWithValue(new FastSyncState(blockchain.getBlockHeader(3).get()));
} }
@ParameterizedTest
@ArgumentsSource(FastSyncActionsTest.FastSyncActionsTestArguments.class)
public void downloadPivotBlockHeaderShouldRetrieveHeadPivotBlockHash(
final DataStorageFormat storageFormat) {
setUp(storageFormat);
syncConfig =
SynchronizerConfiguration.builder()
.syncMinimumPeerCount(1)
.snapSyncConfiguration(
ImmutableSnapSyncConfiguration.builder().isSnapSyncToHeadEnabled(true).build())
.build();
GenesisConfigOptions genesisConfig = mock(GenesisConfigOptions.class);
when(genesisConfig.getTerminalBlockNumber()).thenReturn(OptionalLong.of(10L));
final Optional<ForkchoiceEvent> finalizedEvent =
Optional.of(
new ForkchoiceEvent(
blockchain.getChainHeadHash(),
blockchain.getBlockHashByNumber(3L).get(),
blockchain.getBlockHashByNumber(2L).get()));
fastSyncActions =
createFastSyncActions(
syncConfig,
new PivotSelectorFromHeadBlock(
blockchainSetupUtil.getProtocolContext(),
blockchainSetupUtil.getProtocolSchedule(),
ethContext,
metricsSystem,
genesisConfig,
() -> finalizedEvent,
() -> {}));
final RespondingEthPeer peer = EthProtocolManagerTestUtil.createPeer(ethProtocolManager, 1001);
final CompletableFuture<FastSyncState> result =
fastSyncActions.downloadPivotBlockHeader(
new FastSyncState(finalizedEvent.get().getHeadBlockHash()));
assertThat(result).isNotCompleted();
final RespondingEthPeer.Responder responder = RespondingEthPeer.blockchainResponder(blockchain);
peer.respond(responder);
assertThat(result)
.isCompletedWithValue(
new FastSyncState(
blockchain.getBlockHeader(blockchain.getChainHeadBlockNumber()).get()));
}
private FastSyncActions createFastSyncActions( private FastSyncActions createFastSyncActions(
final SynchronizerConfiguration syncConfig, final PivotBlockSelector pivotBlockSelector) { final SynchronizerConfiguration syncConfig, final PivotBlockSelector pivotBlockSelector) {
final ProtocolSchedule protocolSchedule = blockchainSetupUtil.getProtocolSchedule(); final ProtocolSchedule protocolSchedule = blockchainSetupUtil.getProtocolSchedule();

@ -30,11 +30,19 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
public class GetReceiptsForHeadersTaskTest public class GetReceiptsForHeadersTaskTest
extends RetryingMessageTaskTest<Map<BlockHeader, List<TransactionReceipt>>> { extends RetryingMessageTaskTest<Map<BlockHeader, List<TransactionReceipt>>> {
@BeforeEach
@Override
public void resetMaxRetries() {
maxRetries = GetReceiptsForHeadersTask.DEFAULT_RETRIES;
}
@Override @Override
protected Map<BlockHeader, List<TransactionReceipt>> generateDataToBeRequested() { protected Map<BlockHeader, List<TransactionReceipt>> generateDataToBeRequested() {
// Setup data to be requested and expected response // Setup data to be requested and expected response
@ -50,8 +58,7 @@ public class GetReceiptsForHeadersTaskTest
protected EthTask<Map<BlockHeader, List<TransactionReceipt>>> createTask( protected EthTask<Map<BlockHeader, List<TransactionReceipt>>> createTask(
final Map<BlockHeader, List<TransactionReceipt>> requestedData) { final Map<BlockHeader, List<TransactionReceipt>> requestedData) {
final List<BlockHeader> headersToComplete = new ArrayList<>(requestedData.keySet()); final List<BlockHeader> headersToComplete = new ArrayList<>(requestedData.keySet());
return GetReceiptsForHeadersTask.forHeaders( return GetReceiptsForHeadersTask.forHeaders(ethContext, headersToComplete, metricsSystem);
ethContext, headersToComplete, maxRetries, metricsSystem);
} }
@Test @Test
@ -68,4 +75,13 @@ public class GetReceiptsForHeadersTaskTest
assertThat(createTask(expected).run()).isCompletedWithValue(expected); assertThat(createTask(expected).run()).isCompletedWithValue(expected);
} }
@Override
@Test
@Disabled
public void failsWhenPeerReturnsPartialResultThenStops() {
// Test is not valid when more than 4 retries are allowed, as is always the case with
// GetReceiptsForHeadersTask, because the peer is forcefully disconnected after failing
// too many times
}
} }

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -41,6 +41,7 @@ import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.evm.log.LogsBloomFilter;
import org.hyperledger.besu.evm.worldstate.WorldUpdater; import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
@ -224,14 +225,14 @@ public class BlockchainReferenceTestCaseSpec {
"expectExceptionHomestead", "expectExceptionHomestead",
"expectExceptionALL", "expectExceptionALL",
"hasBigInt", "hasBigInt",
"rlp_decoded", "rlp_decoded"
"transactionSequence"
}) })
public static class CandidateBlock { public static class CandidateBlock {
private final Bytes rlp; private final Bytes rlp;
private final Boolean valid; private final Boolean valid;
private final List<TransactionSequence> transactionSequence;
@JsonCreator @JsonCreator
public CandidateBlock( public CandidateBlock(
@ -242,14 +243,15 @@ public class BlockchainReferenceTestCaseSpec {
@JsonProperty("withdrawals") final Object withdrawals, @JsonProperty("withdrawals") final Object withdrawals,
@JsonProperty("depositRequests") final Object depositRequests, @JsonProperty("depositRequests") final Object depositRequests,
@JsonProperty("withdrawalRequests") final Object withdrawalRequests, @JsonProperty("withdrawalRequests") final Object withdrawalRequests,
@JsonProperty("consolidationRequests") final Object consolidationRequests) { @JsonProperty("consolidationRequests") final Object consolidationRequests,
boolean blockVaid = true; @JsonProperty("transactionSequence") final List<TransactionSequence> transactionSequence) {
boolean blockValid = true;
// The BLOCK__WrongCharAtRLP_0 test has an invalid character in its rlp string. // The BLOCK__WrongCharAtRLP_0 test has an invalid character in its rlp string.
Bytes rlpAttempt = null; Bytes rlpAttempt = null;
try { try {
rlpAttempt = Bytes.fromHexString(rlp); rlpAttempt = Bytes.fromHexString(rlp);
} catch (final IllegalArgumentException e) { } catch (final IllegalArgumentException e) {
blockVaid = false; blockValid = false;
} }
this.rlp = rlpAttempt; this.rlp = rlpAttempt;
@ -257,16 +259,22 @@ public class BlockchainReferenceTestCaseSpec {
&& transactions == null && transactions == null
&& uncleHeaders == null && uncleHeaders == null
&& withdrawals == null) { && withdrawals == null) {
blockVaid = false; blockValid = false;
} }
this.valid = blockVaid; this.valid = blockValid;
this.transactionSequence = transactionSequence;
} }
public boolean isValid() { public boolean isValid() {
return valid; return valid;
} }
public boolean areAllTransactionsValid() {
return transactionSequence == null
|| transactionSequence.stream().filter(t -> !t.valid()).count() == 0;
}
public boolean isExecutable() { public boolean isExecutable() {
return rlp != null; return rlp != null;
} }

@ -0,0 +1,22 @@
/*
* 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.referencetests;
import com.fasterxml.jackson.annotation.JsonProperty;
public record TransactionSequence(
@JsonProperty("exception") String exception,
@JsonProperty("rawBytes") String rawBytes,
@JsonProperty("valid") boolean valid) {}

@ -0,0 +1,310 @@
/*
* 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.referencetests;
import org.hyperledger.besu.testutil.JsonTestParameters;
import java.io.IOException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class BlockchainReferenceTestCaseSpecTest {
String jsonValid =
"""
{
"Call1MB1024Calldepth_d0g0v0_London" : {
"_info" : {
"comment" : "",
"filling-rpc-server" : "evm version 1.13.5-unstable-cd295356-20231019",
"filling-tool-version" : "retesteth-0.3.1-cancun+commit.1e18e0b3.Linux.g++",
"generatedTestHash" : "faf65f5956de8021ec3bddb63cb503e48fb2c89c8596bbc2ad793e6f3b39e1dc",
"lllcversion" : "Version: 0.5.14-develop.2023.7.11+commit.c58ab2c6.mod.Linux.g++",
"solidity" : "Version: 0.8.21+commit.d9974bed.Linux.g++",
"source" : "src/GeneralStateTestsFiller/stQuadraticComplexityTest/Call1MB1024CalldepthFiller.json",
"sourceHash" : "d88ac245b033cfc6159f6201b10b65796ba183dfe25c5f5e6d19d6f50a31daec"
},
"blocks" : [
{
"blockHeader" : {
"baseFeePerGas" : "0x0a",
"bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "0x020000",
"extraData" : "0x00",
"gasLimit" : "0xcd79195900",
"gasUsed" : "0x0249f0",
"hash" : "0xfa70e84a600031d217fae4106b80155ff4af8970a97c8f9bf35efaf6929390a5",
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce" : "0x0000000000000000",
"number" : "0x01",
"parentHash" : "0xefe355079be4a8cb49404abe2162ac9513c33d657d8f3cefe1ebadb91b1cd0cc",
"receiptTrie" : "0xa0e10907f175886de9bd8cd4ac2c21d1db4109a3a9fecf60f54015ee102803fd",
"stateRoot" : "0x33a1c7342e4b786c8fd736fc7d5c1b2fb3563abab428b356600e6f526de5518a",
"timestamp" : "0x03e8",
"transactionsTrie" : "0x09612e25490525613f1024d5f9a39a220234a3865309a68dee5f2f13eaac5fc1",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"rlp" : "0xf90263f901fba0efe355079be4a8cb49404abe2162ac9513c33d657d8f3cefe1ebadb91b1cd0cca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b94f5374fce5edbc8e2a8697c15331677e6ebf0ba033a1c7342e4b786c8fd736fc7d5c1b2fb3563abab428b356600e6f526de5518aa009612e25490525613f1024d5f9a39a220234a3865309a68dee5f2f13eaac5fc1a0a0e10907f175886de9bd8cd4ac2c21d1db4109a3a9fecf60f54015ee102803fdb9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200000185cd79195900830249f08203e800a000000000000000000000000000000000000000000000000000000000000000008800000000000000000af862f860800a830249f094bbbf5374fce5edbc8e2a8697c15331677e6ebf0b0a801ba06843bbbe573744c46cf47f1c126c11a53cffa1bcc3eeb0e0d328e6a73ecc5447a02062c2fbb34bfea606f3cf268b5a94a81d68e748d4d896c514061c03e8acb774c0",
"transactions" : [
{
"data" : "0x",
"gasLimit" : "0x0249f0",
"gasPrice" : "0x0a",
"nonce" : "0x00",
"r" : "0x6843bbbe573744c46cf47f1c126c11a53cffa1bcc3eeb0e0d328e6a73ecc5447",
"s" : "0x2062c2fbb34bfea606f3cf268b5a94a81d68e748d4d896c514061c03e8acb774",
"sender" : "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"to" : "0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b",
"v" : "0x1b",
"value" : "0x0a"
}
],
"uncleHeaders" : [
]
}
],
"genesisBlockHeader" : {
"baseFeePerGas" : "0x0b",
"bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"difficulty" : "0x020000",
"extraData" : "0x00",
"gasLimit" : "0xcd79195900",
"gasUsed" : "0x00",
"hash" : "0xefe355079be4a8cb49404abe2162ac9513c33d657d8f3cefe1ebadb91b1cd0cc",
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce" : "0x0000000000000000",
"number" : "0x00",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0x16d6ea0e1b8d4eb9d1bfd2a1031ea72a255d9af13a88b4cfb8253d2f756d57e1",
"timestamp" : "0x00",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901fbf901f6a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794b94f5374fce5edbc8e2a8697c15331677e6ebf0ba016d6ea0e1b8d4eb9d1bfd2a1031ea72a255d9af13a88b4cfb8253d2f756d57e1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000830200008085cd79195900808000a000000000000000000000000000000000000000000000000000000000000000008800000000000000000bc0c0",
"lastblockhash" : "0xfa70e84a600031d217fae4106b80155ff4af8970a97c8f9bf35efaf6929390a5",
"network" : "London",
"postState" : {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0xffffffffffffffffffffffffffe91c9f",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
},
"0xaaa50000fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0fffffffffffff",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x1bc16d674ec80000",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0fffffffffffff",
"code" : "0x60016000540160005561040060005410601b5760016002556047565b60006000620f42406000600073bbbf5374fce5edbc8e2a8697c15331677e6ebf0b620f55c85a03f16001555b00",
"nonce" : "0x00",
"storage" : {
}
}
},
"pre" : {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0xffffffffffffffffffffffffffffffff",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xaaa50000fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0fffffffffffff",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xbbbf5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0fffffffffffff",
"code" : "0x60016000540160005561040060005410601b5760016002556047565b60006000620f42406000600073bbbf5374fce5edbc8e2a8697c15331677e6ebf0b620f55c85a03f16001555b00",
"nonce" : "0x00",
"storage" : {
}
}
},
"sealEngine" : "NoProof"
}
}
""";
String jsonInvalid =
"""
{ "ValueOverflow_d0g0v0_EIP150" : {
"_info" : {
"comment" : "",
"filling-rpc-server" : "evm version 1.13.5-unstable-cd295356-20231019",
"filling-tool-version" : "retesteth-0.3.1-cancun+commit.1e18e0b3.Linux.g++",
"generatedTestHash" : "3e97036f37b30c4b22f7816fb9f8321623ec4dd8646b0ab9c76fcf87371a36e3",
"lllcversion" : "Version: 0.5.14-develop.2023.7.11+commit.c58ab2c6.mod.Linux.g++",
"solidity" : "Version: 0.8.21+commit.d9974bed.Linux.g++",
"source" : "src/GeneralStateTestsFiller/stTransactionTest/ValueOverflowFiller.yml",
"sourceHash" : "fa6acc202e029dc360fd6d105ac578d91f184f692359decbfe4f9f50af7fbb67"
},
"blocks" : [
{
"expectException" : "TR_RLP_WRONGVALUE",
"rlp" : "0xf9027ef901f6a0a96bbebc0b60fd343eead12143896f9331f436013c0f28cfd13698f0348f4b03a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa0fd1aa19de23712bad2af7f5e2a01afd6f92273527d501b20bb35e1e42b52f1d0a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000018405500000808203e800a00000000000000000000000000000000000000000000000000000000000000000880000000000000000f882f880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28c0",
"transactionSequence" : [
{
"exception" : "TR_RLP_WRONGVALUE",
"rawBytes" : "0xf880806482520894d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0a1010000000000000000000000000000000000000000000000000000000000000001801ba0c16787a8e25e941d67691954642876c08f00996163ae7dfadbbfd6cd436f549da06180e5626cae31590f40641fe8f63734316c4bfeb4cdfab6714198c1044d2e28",
"valid" : "false"
}
]
}
],
"genesisBlockHeader" : {
"bloom" : "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"coinbase" : "0x2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"difficulty" : "0x020000",
"extraData" : "0x00",
"gasLimit" : "0x05500000",
"gasUsed" : "0x00",
"hash" : "0xa96bbebc0b60fd343eead12143896f9331f436013c0f28cfd13698f0348f4b03",
"mixHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce" : "0x0000000000000000",
"number" : "0x00",
"parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"stateRoot" : "0x1751725d1aad5298768fbcf64069b2c1b85aeaffcc561146067d6beedd08052a",
"timestamp" : "0x00",
"transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
},
"genesisRLP" : "0xf901f9f901f4a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347942adc25665018aa1fe0e6bc666dac8fc2697ff9baa01751725d1aad5298768fbcf64069b2c1b85aeaffcc561146067d6beedd08052aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000083020000808405500000808000a00000000000000000000000000000000000000000000000000000000000000000880000000000000000c0c0",
"lastblockhash" : "0xa96bbebc0b60fd343eead12143896f9331f436013c0f28cfd13698f0348f4b03",
"network" : "EIP150",
"postState" : {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x3b9aca00",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xd0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0" : {
"balance" : "0x00",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"pre" : {
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x3b9aca00",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"0xd0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0" : {
"balance" : "0x00",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"sealEngine" : "NoProof"
}
}""";
@Test
void getValidTxs() {
ObjectMapper objectMapper = new ObjectMapper();
final JavaType javaType =
objectMapper
.getTypeFactory()
.constructParametricType(
JsonTestParameters.JsonTestCaseReader.class, BlockchainReferenceTestCaseSpec.class);
JsonTestParameters.JsonTestCaseReader<BlockchainReferenceTestCaseSpec>
blockchainReferenceTestCaseSpec;
try {
blockchainReferenceTestCaseSpec = objectMapper.readValue(jsonValid, javaType);
} catch (final IOException e) {
throw new RuntimeException("Error parsing test case json.", e);
}
Assertions.assertEquals(1, blockchainReferenceTestCaseSpec.testCaseSpecs.size());
Assertions.assertEquals(
1,
blockchainReferenceTestCaseSpec
.testCaseSpecs
.get("Call1MB1024Calldepth_d0g0v0_London")
.getCandidateBlocks()
.length);
Assertions.assertEquals(
true,
blockchainReferenceTestCaseSpec
.testCaseSpecs
.get("Call1MB1024Calldepth_d0g0v0_London")
.getCandidateBlocks()[0]
.areAllTransactionsValid());
}
@Test
void getInValidTxs() {
ObjectMapper objectMapper = new ObjectMapper();
final JavaType javaType =
objectMapper
.getTypeFactory()
.constructParametricType(
JsonTestParameters.JsonTestCaseReader.class, BlockchainReferenceTestCaseSpec.class);
JsonTestParameters.JsonTestCaseReader<BlockchainReferenceTestCaseSpec>
blockchainReferenceTestCaseSpec;
try {
blockchainReferenceTestCaseSpec = objectMapper.readValue(jsonInvalid, javaType);
} catch (final IOException e) {
throw new RuntimeException("Error parsing test case json.", e);
}
Assertions.assertEquals(1, blockchainReferenceTestCaseSpec.testCaseSpecs.size());
Assertions.assertEquals(
1,
blockchainReferenceTestCaseSpec
.testCaseSpecs
.get("ValueOverflow_d0g0v0_EIP150")
.getCandidateBlocks()
.length);
Assertions.assertEquals(
false,
blockchainReferenceTestCaseSpec
.testCaseSpecs
.get("ValueOverflow_d0g0v0_EIP150")
.getCandidateBlocks()[0]
.areAllTransactionsValid());
}
}

@ -1,5 +1,5 @@
/* /*
* Copyright contributors to Hyperledger Besu. * Copyright contributors to Besu.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * 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 * the License. You may obtain a copy of the License at

@ -1,5 +1,5 @@
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -3601,6 +3601,14 @@
<sha256 value="b579ab836863ad48e578bae9961e1b004bd140afc43e7c3335646b7fb3daf9da" origin="Generated by Gradle"/> <sha256 value="b579ab836863ad48e578bae9961e1b004bd140afc43e7c3335646b7fb3daf9da" origin="Generated by Gradle"/>
</artifact> </artifact>
</component> </component>
<component group="org.bitbucket.b_c" name="jose4j" version="0.9.4">
<artifact name="jose4j-0.9.4.jar">
<sha256 value="9012aa4c20319d35159030c3bdecade66863030a98338bfdf73a5238849fb9d9" origin="Generated by Gradle"/>
</artifact>
<artifact name="jose4j-0.9.4.pom">
<sha256 value="e2b9549357f8fb11909b7cb07af339f8dbfe156d84c1ddebb92c81458a9e25b5" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="org.bouncycastle" name="bcpg-jdk18on" version="1.77"> <component group="org.bouncycastle" name="bcpg-jdk18on" version="1.77">
<artifact name="bcpg-jdk18on-1.77.jar"> <artifact name="bcpg-jdk18on-1.77.jar">
<sha256 value="07ae5704f3b729284b646643c798db0984af0126e646233fbd577b34de69fdf2" origin="Generated by Gradle"/> <sha256 value="07ae5704f3b729284b646643c798db0984af0126e646233fbd577b34de69fdf2" origin="Generated by Gradle"/>

@ -27,6 +27,8 @@ dependencyManagement {
dependency 'com.google.protobuf:protobuf-java:3.25.5' dependency 'com.google.protobuf:protobuf-java:3.25.5'
dependency 'org.bitbucket.b_c:jose4j:0.9.4'
dependency 'com.github.oshi:oshi-core:6.6.3' dependency 'com.github.oshi:oshi-core:6.6.3'
dependency 'com.google.auto.service:auto-service:1.1.1' dependency 'com.google.auto.service:auto-service:1.1.1'

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
## ##
## Copyright contributors to Hyperledger Besu. ## Copyright contributors to Besu.
## ##
## Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with ## 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 ## the License. You may obtain a copy of the License at

@ -341,10 +341,15 @@ public class JsonTestParameters<S, T> {
} }
} }
private static class JsonTestCaseReader<T> { /**
* Parameterized wrapper for deserialization.
*
* @param <T> the type parameter
*/
public static class JsonTestCaseReader<T> {
/** The Test case specs. */ /** The Test case specs. */
final Map<String, T> testCaseSpecs; public final Map<String, T> testCaseSpecs;
/** /**
* Public constructor. * Public constructor.

Loading…
Cancel
Save