Merge branch 'main' into zkbesu

This commit is contained in:
Fabio Di Fabio
2024-02-06 11:47:03 +01:00
70 changed files with 745 additions and 398 deletions

View File

@@ -90,7 +90,7 @@ jobs:
#then drop file extension, then insert --tests option between each.
run: cat testList.txt | sed -e 's@acceptance-tests/tests/src/test/java/@--tests\ @g;s@/@.@g;s/\.java//g' > gradleArgs.txt
- name: run acceptance tests
run: ./gradlew acceptanceTest `cat gradleArgs.txt` -Dorg.gradle.parallel=true -Dorg.gradle.caching=true
run: ./gradlew acceptanceTestNotPrivacy `cat gradleArgs.txt` -Dorg.gradle.parallel=true -Dorg.gradle.caching=true
- name: cleanup tempfiles
run: rm testList.txt gradleArgs.txt
- name: Upload Acceptance Test Results

View File

@@ -11,7 +11,9 @@
### Deprecations
- X_SNAP and X_CHECKPOINT are marked for deprecation and will be removed in 24.4.0 in favor of SNAP and CHECKPOINT [#6405](https://github.com/hyperledger/besu/pull/6405)
- `--Xsnapsync-synchronizer-flat-db-healing-enabled` is deprecated (always enabled). [#6499](https://github.com/hyperledger/besu/pull/6499)
- `--Xp2p-peer-lower-bound` [#6501](https://github.com/hyperledger/besu/pull/6501)
### Additions and Improvements
- Upgrade Prometheus and Opentelemetry dependencies [#6422](https://github.com/hyperledger/besu/pull/6422)
@@ -20,14 +22,19 @@
- Log blob count when importing a block via Engine API [#6466](https://github.com/hyperledger/besu/pull/6466)
- Introduce `--Xbonsai-limit-trie-logs-enabled` experimental feature which by default will only retain the latest 512 trie logs, saving about 3GB per week in database growth [#5390](https://github.com/hyperledger/besu/issues/5390)
- Introduce `besu storage x-trie-log prune` experimental offline subcommand which will prune all redundant trie logs except the latest 512 [#6303](https://github.com/hyperledger/besu/pull/6303)
- SNAP and CHECKPOINT sync - early access flag removed so now simply SNAP and CHECKPOINT [#6405](https://github.com/hyperledger/besu/pull/6405)
- X_SNAP and X_CHECKPOINT are marked for deprecation and will be removed in 24.4.0
- Github Actions based build.
- Introduce caching mechanism to optimize Keccak hash calculations for account storage slots during block processing [#6452](https://github.com/hyperledger/besu/pull/6452)
- Added configuration options for `pragueTime` to genesis file for Prague fork development [#6473](https://github.com/hyperledger/besu/pull/6473)
- Moving trielog storage to RocksDB's blobdb to improve write amplications [#6289](https://github.com/hyperledger/besu/pull/6289)
- Support for `shanghaiTime` fork and Shanghai EVM smart contracts in QBFT/IBFT chains [#6353](https://github.com/hyperledger/besu/pull/6353)
- Change ExecutionHaltReason for contract creation collision case to return ILLEGAL_STATE_CHANGE [#6518](https://github.com/hyperledger/besu/pull/6518)
### Bug fixes
- Fix the way an advertised host configured with `--p2p-host` is treated when communicating with the originator of a PING packet [#6225](https://github.com/hyperledger/besu/pull/6225)
- Fix `poa-block-txs-selection-max-time` option that was inadvertently reset to its default after being configured [#6444](https://github.com/hyperledger/besu/pull/6444)
- Fix ETC Spiral upgrade breach of consensus [#6524](https://github.com/hyperledger/besu/pull/6524)
### Download Links

View File

@@ -211,7 +211,6 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
.map(pkiConfig -> new PkiBlockCreationConfigurationProvider().load(pkiConfig)))
.evmConfiguration(EvmConfiguration.DEFAULT)
.maxPeers(maxPeers)
.lowerBoundPeers(maxPeers)
.maxRemotelyInitiatedPeers(15)
.networkConfiguration(node.getNetworkingConfiguration())
.randomPeerPriority(false)

View File

@@ -53,6 +53,6 @@ public class WebSocket {
public void verifyTotalEventsReceived(final int expectedTotalEventCount) {
WaitUtils.waitFor(
() -> assertThat(connection.getSubscriptionEvents()).hasSize(expectedTotalEventCount));
60, () -> assertThat(connection.getSubscriptionEvents()).hasSize(expectedTotalEventCount));
}
}

View File

@@ -155,6 +155,33 @@ task acceptanceTestMainnet(type: Test) {
doFirst { mkdir "${buildDir}/jvmErrorLogs" }
}
task acceptanceTestNotPrivacy(type: Test) {
inputs.property "integration.date", LocalTime.now() // so it runs at every invocation
exclude '**/privacy/**'
useJUnitPlatform {}
dependsOn(rootProject.installDist)
setSystemProperties(test.getSystemProperties())
systemProperty 'acctests.runBesuAsProcess', 'true'
systemProperty 'java.security.properties', "${buildDir}/resources/test/acceptanceTesting.security"
mustRunAfter rootProject.subprojects*.test
description = 'Runs MAINNET Besu acceptance tests (excluding privacy since they run nightly, and are being refactored).'
group = 'verification'
jvmArgs "-XX:ErrorFile=${buildDir}/jvmErrorLogs/java_err_pid%p.log"
testLogging {
exceptionFormat = 'full'
showStackTraces = true
showStandardStreams = Boolean.getBoolean('acctests.showStandardStreams')
showExceptions = true
showCauses = true
}
doFirst { mkdir "${buildDir}/jvmErrorLogs" }
}
task acceptanceTestCliqueBft(type: Test) {
inputs.property "integration.date", LocalTime.now() // so it runs at every invocation
include '**/bft/**'

View File

@@ -150,6 +150,36 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
cluster.verify(receiver.balanceEquals(3));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("factoryFunctions")
public void shouldMineOnSingleNodeWithFreeGas_Shanghai(
final String testName, final BftAcceptanceTestParameterization nodeFactory) throws Exception {
setUp(testName, nodeFactory);
final BesuNode minerNode = nodeFactory.createNode(besu, "miner1");
updateGenesisConfigToShanghai(minerNode, true);
cluster.start(minerNode);
cluster.verify(blockchain.reachesHeight(minerNode, 1));
final Account sender = accounts.createAccount("account1");
final Account receiver = accounts.createAccount("account2");
minerNode.execute(accountTransactions.createTransfer(sender, 50, Amount.ZERO));
cluster.verify(sender.balanceEquals(50));
minerNode.execute(accountTransactions.create1559Transfer(sender, 50, 4, Amount.ZERO));
cluster.verify(sender.balanceEquals(100));
minerNode.execute(
accountTransactions.createIncrementalTransfers(sender, receiver, 1, Amount.ZERO));
cluster.verify(receiver.balanceEquals(1));
minerNode.execute(
accountTransactions.create1559IncrementalTransfers(sender, receiver, 2, 4, Amount.ZERO));
cluster.verify(receiver.balanceEquals(3));
}
@ParameterizedTest(name = "{index}: {0}")
@MethodSource("factoryFunctions")
public void shouldMineOnMultipleNodes(
@@ -245,4 +275,16 @@ public class BftMiningAcceptanceTest extends ParameterizedBftTestBase {
config.put("zeroBaseFee", zeroBaseFeeEnabled);
minerNode.setGenesisConfig(genesisConfigNode.toString());
}
private static void updateGenesisConfigToShanghai(
final BesuNode minerNode, final boolean zeroBaseFeeEnabled) {
final Optional<String> genesisConfig =
minerNode.getGenesisConfigProvider().create(List.of(minerNode));
final ObjectNode genesisConfigNode = JsonUtil.objectNodeFromString(genesisConfig.orElseThrow());
final ObjectNode config = (ObjectNode) genesisConfigNode.get("config");
config.remove("berlinBlock");
config.put("shanghaiTime", 100);
config.put("zeroBaseFee", zeroBaseFeeEnabled);
minerNode.setGenesisConfig(genesisConfigNode.toString());
}
}

View File

@@ -21,6 +21,7 @@ import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.hyperledger.besu.cli.DefaultCommandValues.getDefaultBesuDataPath;
import static org.hyperledger.besu.cli.config.NetworkName.MAINNET;
import static org.hyperledger.besu.cli.options.unstable.NetworkingOptions.PEER_LOWER_BOUND_FLAG;
import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG;
import static org.hyperledger.besu.cli.util.CommandLineUtils.isOptionSet;
import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
@@ -320,7 +321,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private int maxPeers;
private int maxRemoteInitiatedPeers;
private int peersLowerBound;
// CLI options defined by user at runtime.
// Options parsing is done with CLI library Picocli https://picocli.info/
@@ -1523,18 +1523,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private void ensureValidPeerBoundParams() {
maxPeers = p2PDiscoveryOptionGroup.maxPeers;
peersLowerBound = unstableNetworkingOptions.toDomainObject().getPeerLowerBound();
if (peersLowerBound > maxPeers) {
logger.warn(
"`--Xp2p-peer-lower-bound` "
+ peersLowerBound
+ " must not exceed --max-peers "
+ maxPeers);
logger.warn("setting --Xp2p-peer-lower-bound=" + maxPeers);
peersLowerBound = maxPeers;
}
final Boolean isLimitRemoteWireConnectionsEnabled =
p2PDiscoveryOptionGroup.isLimitRemoteWireConnectionsEnabled;
if (isOptionSet(commandLine, PEER_LOWER_BOUND_FLAG)) {
logger.warn(PEER_LOWER_BOUND_FLAG + " is deprecated and will be removed soon.");
}
if (isLimitRemoteWireConnectionsEnabled) {
final float fraction =
Fraction.fromPercentage(p2PDiscoveryOptionGroup.maxRemoteConnectionsPercentage)
@@ -1615,8 +1608,8 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
CommandLineUtils.failIfOptionDoesntMeetRequirement(
commandLine,
"--Xcheckpoint-post-merge-enabled can only be used with X_CHECKPOINT sync-mode",
SyncMode.X_CHECKPOINT.equals(getDefaultSyncModeIfNotSet()),
"--Xcheckpoint-post-merge-enabled can only be used with CHECKPOINT sync-mode",
SyncMode.isCheckpointSync(getDefaultSyncModeIfNotSet()),
singletonList("--Xcheckpoint-post-merge-enabled"));
if (!securityModuleName.equals(DEFAULT_SECURITY_MODULE)
@@ -1794,7 +1787,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.evmConfiguration(unstableEvmOptions.toDomainObject())
.dataStorageConfiguration(dataStorageOptions.toDomainObject())
.maxPeers(p2PDiscoveryOptionGroup.maxPeers)
.lowerBoundPeers(peersLowerBound)
.maxRemotelyInitiatedPeers(maxRemoteInitiatedPeers)
.randomPeerPriority(p2PDiscoveryOptionGroup.randomPeerPriority)
.chainPruningConfiguration(unstableChainPruningOptions.toDomainObject())
@@ -1928,6 +1920,13 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
if (syncMode == SyncMode.FAST) {
throw new ParameterException(commandLine, String.format("%s %s", "Fast sync", errorSuffix));
}
if (syncMode == SyncMode.SNAP) {
throw new ParameterException(commandLine, String.format("%s %s", "Snap sync", errorSuffix));
}
if (syncMode == SyncMode.CHECKPOINT) {
throw new ParameterException(
commandLine, String.format("%s %s", "Checkpoint sync", errorSuffix));
}
if (isPruningEnabled()) {
throw new ParameterException(commandLine, String.format("%s %s", "Pruning", errorSuffix));
}
@@ -2471,11 +2470,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.forEach(
port -> {
if (port.equals(p2PDiscoveryOptionGroup.p2pPort)
&& !NetworkUtility.isPortAvailable(port)) {
&& (NetworkUtility.isPortUnavailableForTcp(port)
|| NetworkUtility.isPortUnavailableForUdp(port))) {
unavailablePorts.add(port);
}
if (!port.equals(p2PDiscoveryOptionGroup.p2pPort)
&& !NetworkUtility.isPortAvailableForTcp(port)) {
&& NetworkUtility.isPortUnavailableForTcp(port)) {
unavailablePorts.add(port);
}
});

View File

@@ -74,8 +74,6 @@ public interface DefaultCommandValues {
int SYNC_MIN_PEER_COUNT = 5;
/** The constant DEFAULT_MAX_PEERS. */
int DEFAULT_MAX_PEERS = 25;
/** The constant DEFAULT_P2P_PEER_LOWER_BOUND. */
int DEFAULT_P2P_PEER_LOWER_BOUND = 25;
/** The constant DEFAULT_HTTP_MAX_CONNECTIONS. */
int DEFAULT_HTTP_MAX_CONNECTIONS = 80;
/** The constant DEFAULT_HTTP_MAX_BATCH_SIZE. */

View File

@@ -18,7 +18,8 @@ import org.apache.commons.lang3.StringUtils;
/** Enum for profile names. Each profile corresponds to a configuration file. */
public enum ProfileName {
/** The 'STAKER' profile */
STAKER("profiles/staker.toml"),
/** The 'MINIMALIST_STAKER' profile */
MINIMALIST_STAKER("profiles/minimalist-staker.toml"),
/** The 'DEV' profile. Corresponds to the 'profiles/dev.toml' configuration file. */

View File

@@ -80,8 +80,8 @@ public class NetworkingOptions implements CLIOptions<NetworkingConfiguration> {
hidden = true,
names = PEER_LOWER_BOUND_FLAG,
description =
"Lower bound on the target number of P2P connections (default: ${DEFAULT-VALUE})")
private Integer peerLowerBoundConfig = DefaultCommandValues.DEFAULT_P2P_PEER_LOWER_BOUND;
"(Deprecated) Lower bound on the target number of P2P connections (default: ${DEFAULT-VALUE})")
private final Integer peerLowerBoundConfig = DefaultCommandValues.DEFAULT_MAX_PEERS;
private NetworkingOptions() {}
@@ -107,7 +107,6 @@ public class NetworkingOptions implements CLIOptions<NetworkingConfiguration> {
cliOptions.initiateConnectionsFrequencySec =
networkingConfig.getInitiateConnectionsFrequencySec();
cliOptions.dnsDiscoveryServerOverride = networkingConfig.getDnsDiscoveryServerOverride();
cliOptions.peerLowerBoundConfig = networkingConfig.getPeerLowerBound();
return cliOptions;
}
@@ -120,7 +119,6 @@ public class NetworkingOptions implements CLIOptions<NetworkingConfiguration> {
config.setDnsDiscoveryServerOverride(dnsDiscoveryServerOverride);
config.getDiscovery().setDiscoveryV5Enabled(isPeerDiscoveryV5Enabled);
config.getDiscovery().setFilterOnEnrForkId(filterOnEnrForkId);
config.setPeerLowerBound(peerLowerBoundConfig);
return config;
}

View File

@@ -87,10 +87,7 @@ public class TrieLogHelper {
}
final long numberOfBatches = calculateNumberOfBatches(layersToRetain);
LOG.info(
"Starting pruning: retain {} trie logs, processing in {} batches...",
layersToRetain,
numberOfBatches);
LOG.info("Retain {} trie logs, processing in {} batches", layersToRetain, numberOfBatches);
processTrieLogBatches(
rootWorldStateStorage,

View File

@@ -137,7 +137,7 @@ public class TrieLogSubCommand implements Runnable {
LOG.info("Estimating trie logs size before pruning...");
long sizeBefore = estimatedSizeOfTrieLogs();
LOG.info("Estimated trie logs size before pruning: {}", formatOutputSize(sizeBefore));
LOG.info("Starting pruning...");
final TrieLogHelper trieLogHelper = new TrieLogHelper();
boolean success =
trieLogHelper.prune(

View File

@@ -178,7 +178,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
/** The Max peers. */
protected int maxPeers;
private int peerLowerBound;
private int maxRemotelyInitiatedPeers;
/** The Chain pruner configuration. */
protected ChainPrunerConfiguration chainPrunerConfiguration = ChainPrunerConfiguration.DEFAULT;
@@ -475,22 +474,10 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
return this;
}
/**
* Lower bound of peers where we stop actively trying to initiate new outgoing connections
*
* @param peerLowerBound lower bound of peers where we stop actively trying to initiate new
* outgoing connections
* @return the besu controller builder
*/
public BesuControllerBuilder lowerBoundPeers(final int peerLowerBound) {
this.peerLowerBound = peerLowerBound;
return this;
}
/**
* Maximum number of remotely initiated peer connections
*
* @param maxRemotelyInitiatedPeers aximum number of remotely initiated peer connections
* @param maxRemotelyInitiatedPeers maximum number of remotely initiated peer connections
* @return the besu controller builder
*/
public BesuControllerBuilder maxRemotelyInitiatedPeers(final int maxRemotelyInitiatedPeers) {
@@ -511,7 +498,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
}
/**
* Chain pruning configuration besu controller builder.
* Sets the number of blocks to cache.
*
* @param numberOfBlocksToCache the number of blocks to cache
* @return the besu controller builder
@@ -681,7 +668,6 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
maxMessageSize,
messagePermissioningProviders,
nodeKey.getPublicKey().getEncodedBytes(),
peerLowerBound,
maxPeers,
maxRemotelyInitiatedPeers,
randomPeerPriority);
@@ -1161,8 +1147,7 @@ public abstract class BesuControllerBuilder implements MiningParameterOverrides
final CheckpointConfigOptions checkpointConfigOptions =
genesisConfig.getConfigOptions(genesisConfigOverrides).getCheckpointOptions();
if (SyncMode.X_CHECKPOINT.equals(syncConfig.getSyncMode())
&& checkpointConfigOptions.isValid()) {
if (SyncMode.isCheckpointSync(syncConfig.getSyncMode()) && checkpointConfigOptions.isValid()) {
validators.add(
new CheckpointBlocksPeerValidator(
protocolSchedule,

View File

@@ -462,7 +462,6 @@ public final class RunnerTest {
.networkConfiguration(NetworkingConfiguration.create())
.randomPeerPriority(Boolean.FALSE)
.maxPeers(25)
.lowerBoundPeers(25)
.maxRemotelyInitiatedPeers(15)
.build();
}

View File

@@ -253,7 +253,6 @@ public class BesuCommandTest extends CommandTestAbstract {
verify(mockControllerBuilder).storageProvider(storageProviderArgumentCaptor.capture());
verify(mockControllerBuilder).gasLimitCalculator(eq(GasLimitCalculator.constant()));
verify(mockControllerBuilder).maxPeers(eq(maxPeers));
verify(mockControllerBuilder).lowerBoundPeers(eq(maxPeers));
verify(mockControllerBuilder).maxRemotelyInitiatedPeers(eq((int) Math.floor(0.6 * maxPeers)));
verify(mockControllerBuilder).build();
@@ -1040,7 +1039,7 @@ public class BesuCommandTest extends CommandTestAbstract {
}
@Test
public void p2pPeerUpperBound_without_p2pPeerLowerBound_shouldSetLowerBoundEqualToUpperBound() {
public void p2pPeerUpperBound_without_p2pPeerLowerBound_shouldSetMaxPeers() {
final int maxPeers = 23;
parseCommand("--p2p-peer-upper-bound", String.valueOf(maxPeers));
@@ -1051,29 +1050,6 @@ public class BesuCommandTest extends CommandTestAbstract {
verify(mockControllerBuilder).maxPeers(intArgumentCaptor.capture());
assertThat(intArgumentCaptor.getValue()).isEqualTo(maxPeers);
verify(mockControllerBuilder).lowerBoundPeers(intArgumentCaptor.capture());
assertThat(intArgumentCaptor.getValue()).isEqualTo(maxPeers);
verify(mockRunnerBuilder).build();
}
@Test
public void maxpeersSet_p2pPeerLowerBoundSet() {
final int maxPeers = 123;
final int minPeers = 66;
parseCommand(
"--max-peers",
String.valueOf(maxPeers),
"--Xp2p-peer-lower-bound",
String.valueOf(minPeers));
verify(mockControllerBuilder).maxPeers(intArgumentCaptor.capture());
assertThat(intArgumentCaptor.getValue()).isEqualTo(maxPeers);
verify(mockControllerBuilder).lowerBoundPeers(intArgumentCaptor.capture());
assertThat(intArgumentCaptor.getValue()).isEqualTo(minPeers);
verify(mockRunnerBuilder).build();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
@@ -1158,7 +1134,7 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
.contains(
"Invalid value for option '--sync-mode': expected one of [FULL, FAST, X_SNAP, X_CHECKPOINT] (case-insensitive) but was 'bogus'");
"Invalid value for option '--sync-mode': expected one of [FULL, FAST, SNAP, CHECKPOINT, X_SNAP, X_CHECKPOINT] (case-insensitive) but was 'bogus'");
}
@Test
@@ -1211,11 +1187,11 @@ public class BesuCommandTest extends CommandTestAbstract {
@Test
public void parsesValidSnapSyncMinPeersOption() {
parseCommand("--sync-mode", "X_SNAP", "--sync-min-peers", "11");
parseCommand("--sync-mode", "SNAP", "--sync-min-peers", "11");
verify(mockControllerBuilder).synchronizerConfiguration(syncConfigurationCaptor.capture());
final SynchronizerConfiguration syncConfig = syncConfigurationCaptor.getValue();
assertThat(syncConfig.getSyncMode()).isEqualTo(SyncMode.X_SNAP);
assertThat(syncConfig.getSyncMode()).isEqualTo(SyncMode.SNAP);
assertThat(syncConfig.getFastSyncMinimumPeerCount()).isEqualTo(11);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
@@ -2614,6 +2590,24 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(commandOutput.toString(UTF_8)).isEmpty();
}
@Test
public void privacyWithSnapSyncMustError() {
parseCommand("--sync-mode=SNAP", "--privacy-enabled");
assertThat(commandErrorOutput.toString(UTF_8))
.contains("Snap sync cannot be enabled with privacy.");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
}
@Test
public void privacyWithCheckpointSyncMustError() {
parseCommand("--sync-mode=CHECKPOINT", "--privacy-enabled");
assertThat(commandErrorOutput.toString(UTF_8))
.contains("Checkpoint sync cannot be enabled with privacy.");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
}
@Test
public void privacyWithPruningMustError() {
parseCommand("--pruning-enabled", "--privacy-enabled");
@@ -3216,7 +3210,7 @@ public class BesuCommandTest extends CommandTestAbstract {
"--genesis-file",
genesisFile.toString(),
"--sync-mode",
"X_CHECKPOINT",
"CHECKPOINT",
"--Xcheckpoint-post-merge-enabled");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
@@ -3227,7 +3221,7 @@ public class BesuCommandTest extends CommandTestAbstract {
@Test
public void checkpointPostMergeShouldFailWhenGenesisUsesCheckpointFromPreMerge() {
// using the default genesis which has a checkpoint sync block prior to the merge
parseCommand("--sync-mode", "X_CHECKPOINT", "--Xcheckpoint-post-merge-enabled");
parseCommand("--sync-mode", "CHECKPOINT", "--Xcheckpoint-post-merge-enabled");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8))
@@ -3238,9 +3232,9 @@ public class BesuCommandTest extends CommandTestAbstract {
@Test
public void checkpointPostMergeShouldFailWhenSyncModeIsNotCheckpoint() {
parseCommand("--sync-mode", "X_SNAP", "--Xcheckpoint-post-merge-enabled");
parseCommand("--sync-mode", "SNAP", "--Xcheckpoint-post-merge-enabled");
assertThat(commandErrorOutput.toString(UTF_8))
.contains("--Xcheckpoint-post-merge-enabled can only be used with X_CHECKPOINT sync-mode");
.contains("--Xcheckpoint-post-merge-enabled can only be used with CHECKPOINT sync-mode");
}
@Test
@@ -3255,7 +3249,7 @@ public class BesuCommandTest extends CommandTestAbstract {
"--genesis-file",
genesisFile.toString(),
"--sync-mode",
"X_CHECKPOINT",
"CHECKPOINT",
"--Xcheckpoint-post-merge-enabled");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
@@ -3274,7 +3268,7 @@ public class BesuCommandTest extends CommandTestAbstract {
"--genesis-file",
genesisFile.toString(),
"--sync-mode",
"X_CHECKPOINT",
"CHECKPOINT",
"--Xcheckpoint-post-merge-enabled");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
@@ -3293,7 +3287,7 @@ public class BesuCommandTest extends CommandTestAbstract {
"--genesis-file",
genesisFile.toString(),
"--sync-mode",
"X_CHECKPOINT",
"CHECKPOINT",
"--Xcheckpoint-post-merge-enabled");
assertThat(commandOutput.toString(UTF_8)).isEmpty();
@@ -3302,20 +3296,6 @@ public class BesuCommandTest extends CommandTestAbstract {
"PoS checkpoint sync can't be used with TTD = 0 and checkpoint totalDifficulty = 0");
}
@Test
public void checkP2pPeerLowerBound_isSet() {
final int lowerBound = 13;
parseCommand("--Xp2p-peer-lower-bound", String.valueOf(lowerBound));
verify(mockControllerBuilder).lowerBoundPeers(intArgumentCaptor.capture());
verify(mockControllerBuilder).build();
assertThat(intArgumentCaptor.getValue()).isEqualTo(lowerBound);
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
}
@Test
public void kzgTrustedSetupFileRequiresDataBlobEnabledNetwork() throws IOException {
final Path genesisFileWithoutBlobs =

View File

@@ -288,7 +288,6 @@ public abstract class CommandTestAbstract {
when(mockControllerBuilder.maxPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.chainPruningConfiguration(any())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.lowerBoundPeers(anyInt())).thenReturn(mockControllerBuilder);
when(mockControllerBuilder.maxRemotelyInitiatedPeers(anyInt()))
.thenReturn(mockControllerBuilder);
when(mockControllerBuilder.transactionSelectorFactory(any())).thenReturn(mockControllerBuilder);

View File

@@ -176,7 +176,6 @@ public class NetworkingOptionsTest
NetworkingConfiguration.DEFAULT_INITIATE_CONNECTIONS_FREQUENCY_SEC + 10);
config.setCheckMaintainedConnectionsFrequency(
NetworkingConfiguration.DEFAULT_CHECK_MAINTAINED_CONNECTIONS_FREQUENCY_SEC + 10);
config.setPeerLowerBound(NetworkingConfiguration.DEFAULT_PEER_LOWER_BOUND - 10);
return config;
}

View File

@@ -130,7 +130,7 @@ public class BesuControllerTest {
final BesuControllerBuilder besuControllerBuilder =
new BesuController.Builder()
.fromGenesisConfig(postMergeGenesisFile, Collections.emptyMap(), SyncMode.X_CHECKPOINT);
.fromGenesisConfig(postMergeGenesisFile, Collections.emptyMap(), SyncMode.CHECKPOINT);
assertThat(besuControllerBuilder).isInstanceOf(MergeBesuControllerBuilder.class);
}
@@ -147,7 +147,7 @@ public class BesuControllerTest {
final BesuControllerBuilder besuControllerBuilder =
new BesuController.Builder()
.fromGenesisConfig(mergeAtGenesisFile, Collections.emptyMap(), SyncMode.X_CHECKPOINT);
.fromGenesisConfig(mergeAtGenesisFile, Collections.emptyMap(), SyncMode.CHECKPOINT);
assertThat(besuControllerBuilder).isInstanceOf(TransitionBesuControllerBuilder.class);
}
@@ -156,7 +156,7 @@ public class BesuControllerTest {
public void preMergeCheckpointSyncUsesTransitionControllerBuilder() {
final BesuControllerBuilder besuControllerBuilder =
new BesuController.Builder()
.fromGenesisConfig(genesisConfigFile, Collections.emptyMap(), SyncMode.X_CHECKPOINT);
.fromGenesisConfig(genesisConfigFile, Collections.emptyMap(), SyncMode.CHECKPOINT);
assertThat(besuControllerBuilder).isInstanceOf(TransitionBesuControllerBuilder.class);
}
@@ -165,7 +165,7 @@ public class BesuControllerTest {
public void nonCheckpointSyncUsesTransitionControllerBuild() {
final BesuControllerBuilder besuControllerBuilder =
new BesuController.Builder()
.fromGenesisConfig(genesisConfigFile, Collections.emptyMap(), SyncMode.X_SNAP);
.fromGenesisConfig(genesisConfigFile, Collections.emptyMap(), SyncMode.SNAP);
assertThat(besuControllerBuilder).isInstanceOf(TransitionBesuControllerBuilder.class);
}

View File

@@ -0,0 +1 @@
network="MAINNET"

View File

@@ -53,14 +53,22 @@ public class CombinedProtocolScheduleFactory {
protocolSchedule.getScheduledProtocolSpecs().stream()
.filter(protocolSpecMatchesConsensusBlockRange(spec.getBlock(), endBlock))
.forEach(
s ->
combinedProtocolSchedule.putBlockNumberMilestone(s.fork().milestone(), s.spec()));
s -> {
if (s instanceof ScheduledProtocolSpec.TimestampProtocolSpec) {
combinedProtocolSchedule.putTimestampMilestone(s.fork().milestone(), s.spec());
} else if (s instanceof ScheduledProtocolSpec.BlockNumberProtocolSpec) {
combinedProtocolSchedule.putBlockNumberMilestone(s.fork().milestone(), s.spec());
} else {
throw new IllegalStateException(
"Unexpected milestone: " + s + " for milestone: " + s.fork().milestone());
}
});
// When moving to a new consensus mechanism we want to use the last milestone but created by
// our consensus mechanism's BesuControllerBuilder so any additional rules are applied
if (spec.getBlock() > 0) {
combinedProtocolSchedule.putBlockNumberMilestone(
spec.getBlock(), protocolSchedule.getByBlockNumber(spec.getBlock()));
spec.getBlock(), protocolSchedule.getByBlockNumberOrTimestamp(spec.getBlock(), 0L));
}
}
return combinedProtocolSchedule;

View File

@@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecBuilder;
import org.hyperledger.besu.ethereum.mainnet.WithdrawalsValidator;
import org.hyperledger.besu.ethereum.mainnet.feemarket.FeeMarket;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
@@ -116,6 +117,9 @@ public abstract class BaseBftProtocolScheduleBuilder {
.skipZeroBlockRewards(true)
.blockHeaderFunctions(BftBlockHeaderFunctions.forOnchainBlock(bftExtraDataCodec))
.blockReward(Wei.of(configOptions.getBlockRewardWei()))
.withdrawalsValidator(
new WithdrawalsValidator
.ProhibitedWithdrawals()) // QBFT/IBFT doesn't support withdrawals
.miningBeneficiaryCalculator(
header -> configOptions.getMiningBeneficiary().orElseGet(header::getCoinbase));
}

View File

@@ -39,12 +39,13 @@ public class BftProtocolSchedule extends DefaultProtocolSchedule {
}
/**
* Look up ProtocolSpec by block number
* Look up ProtocolSpec by block number or timestamp
*
* @param number block number
* @return the protocol spec for that block number
* @param timestamp block timestamp
* @return the protocol spec for that block number or timestamp
*/
public ProtocolSpec getByBlockNumber(final long number) {
public ProtocolSpec getByBlockNumberOrTimestamp(final long number, final long timestamp) {
checkArgument(number >= 0, "number must be non-negative");
checkArgument(
!protocolSpecs.isEmpty(), "At least 1 milestone must be provided to the protocol schedule");
@@ -53,12 +54,19 @@ public class BftProtocolSchedule extends DefaultProtocolSchedule {
"There must be a milestone starting from block 0");
// protocolSpecs is sorted in descending block order, so the first one we find that's lower than
// the requested level will be the most appropriate spec
ProtocolSpec theSpec = null;
for (final ScheduledProtocolSpec s : protocolSpecs) {
if (number >= s.fork().milestone()) {
return s.spec();
if ((s instanceof ScheduledProtocolSpec.BlockNumberProtocolSpec)
&& (number >= s.fork().milestone())) {
theSpec = s.spec();
break;
} else if ((s instanceof ScheduledProtocolSpec.TimestampProtocolSpec)
&& (timestamp >= s.fork().milestone())) {
theSpec = s.spec();
break;
}
}
return null;
return theSpec;
}
/**

View File

@@ -60,18 +60,20 @@ public class CombinedProtocolScheduleFactoryTest {
final BftProtocolSchedule combinedProtocolSchedule =
combinedProtocolScheduleFactory.create(consensusSchedule, Optional.of(BigInteger.TEN));
assertThat(combinedProtocolSchedule.getByBlockNumber(0L).getName()).isEqualTo("Frontier");
assertThat(combinedProtocolSchedule.getByBlockNumber(0L))
.isSameAs(protocolSchedule.getByBlockNumber(0L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L).getName())
.isEqualTo("Frontier");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L))
.isSameAs(protocolSchedule.getByBlockNumberOrTimestamp(0L, 0L));
assertThat(combinedProtocolSchedule.getByBlockNumber(5L).getName()).isEqualTo("Homestead");
assertThat(combinedProtocolSchedule.getByBlockNumber(5L))
.isSameAs(protocolSchedule.getByBlockNumber(5L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L).getName())
.isEqualTo("Homestead");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L))
.isSameAs(protocolSchedule.getByBlockNumberOrTimestamp(5L, 0L));
assertThat(combinedProtocolSchedule.getByBlockNumber(10L).getName())
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L).getName())
.isEqualTo("Constantinople");
assertThat(combinedProtocolSchedule.getByBlockNumber(10L))
.isSameAs(protocolSchedule.getByBlockNumber(10L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L))
.isSameAs(protocolSchedule.getByBlockNumberOrTimestamp(10L, 0L));
assertThat(
new MilestoneStreamingProtocolSchedule(combinedProtocolSchedule)
@@ -88,63 +90,78 @@ public class CombinedProtocolScheduleFactoryTest {
genesisConfigOptions.byzantiumBlock(105L);
genesisConfigOptions.berlinBlock(110L);
genesisConfigOptions.londonBlock(220L);
genesisConfigOptions.shanghaiTime(1000000050L);
genesisConfigOptions.chainId(BigInteger.TEN);
final BftProtocolSchedule protocolSchedule1 = createProtocolSchedule(genesisConfigOptions);
final BftProtocolSchedule protocolSchedule2 = createProtocolSchedule(genesisConfigOptions);
final BftProtocolSchedule protocolSchedule3 = createProtocolSchedule(genesisConfigOptions);
final BftProtocolSchedule protocolSchedule4 = createProtocolSchedule(genesisConfigOptions);
final NavigableSet<ForkSpec<ProtocolSchedule>> consensusSchedule =
new TreeSet<>(ForkSpec.COMPARATOR);
consensusSchedule.add(new ForkSpec<>(0, protocolSchedule1));
consensusSchedule.add(new ForkSpec<>(100L, protocolSchedule2));
consensusSchedule.add(new ForkSpec<>(200L, protocolSchedule3));
consensusSchedule.add(new ForkSpec<>(1000000000L, protocolSchedule4));
final BftProtocolSchedule combinedProtocolSchedule =
combinedProtocolScheduleFactory.create(consensusSchedule, Optional.of(BigInteger.TEN));
// consensus schedule 1
assertThat(combinedProtocolSchedule.getByBlockNumber(0L).getName()).isEqualTo("Frontier");
assertThat(combinedProtocolSchedule.getByBlockNumber(0L))
.isSameAs(protocolSchedule1.getByBlockNumber(0L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L).getName())
.isEqualTo("Frontier");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 0L))
.isSameAs(protocolSchedule1.getByBlockNumberOrTimestamp(0L, 0L));
assertThat(combinedProtocolSchedule.getByBlockNumber(5L).getName()).isEqualTo("Homestead");
assertThat(combinedProtocolSchedule.getByBlockNumber(5L))
.isSameAs(protocolSchedule1.getByBlockNumber(5L));
assertThat(combinedProtocolSchedule.getByBlockNumber(10L).getName())
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L).getName())
.isEqualTo("Homestead");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(5L, 0L))
.isSameAs(protocolSchedule1.getByBlockNumberOrTimestamp(5L, 0L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L).getName())
.isEqualTo("Constantinople");
assertThat(combinedProtocolSchedule.getByBlockNumber(10L))
.isSameAs(protocolSchedule1.getByBlockNumber(10L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(10L, 0L))
.isSameAs(protocolSchedule1.getByBlockNumberOrTimestamp(10L, 0L));
// consensus schedule 2 migration block
assertThat(combinedProtocolSchedule.getByBlockNumber(100L).getName())
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(100L, 0L).getName())
.isEqualTo("Constantinople");
assertThat(combinedProtocolSchedule.getByBlockNumber(100L))
.isSameAs(protocolSchedule2.getByBlockNumber(10L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(100L, 0L))
.isSameAs(protocolSchedule2.getByBlockNumberOrTimestamp(10L, 0L));
// consensus schedule 2
assertThat(combinedProtocolSchedule.getByBlockNumber(105L).getName()).isEqualTo("Byzantium");
assertThat(combinedProtocolSchedule.getByBlockNumber(105L))
.isSameAs(protocolSchedule2.getByBlockNumber(105L));
assertThat(combinedProtocolSchedule.getByBlockNumber(110L).getName()).isEqualTo("Berlin");
assertThat(combinedProtocolSchedule.getByBlockNumber(110L))
.isSameAs(protocolSchedule2.getByBlockNumber(110L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(105L, 0L).getName())
.isEqualTo("Byzantium");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(105L, 0L))
.isSameAs(protocolSchedule2.getByBlockNumberOrTimestamp(105L, 0L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(110L, 0L).getName())
.isEqualTo("Berlin");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(110L, 0L))
.isSameAs(protocolSchedule2.getByBlockNumberOrTimestamp(110L, 0L));
// consensus schedule 3 migration block
assertThat(combinedProtocolSchedule.getByBlockNumber(200L).getName()).isEqualTo("Berlin");
assertThat(combinedProtocolSchedule.getByBlockNumber(200L))
.isSameAs(protocolSchedule3.getByBlockNumber(110L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(200L, 0L).getName())
.isEqualTo("Berlin");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(200L, 0L))
.isSameAs(protocolSchedule3.getByBlockNumberOrTimestamp(110L, 0L));
// consensus schedule 3
assertThat(combinedProtocolSchedule.getByBlockNumber(220L).getName()).isEqualTo("London");
assertThat(combinedProtocolSchedule.getByBlockNumber(220L))
.isSameAs(protocolSchedule3.getByBlockNumber(220L));
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(220L, 0L).getName())
.isEqualTo("London");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(220L, 0L))
.isSameAs(protocolSchedule3.getByBlockNumberOrTimestamp(220L, 0L));
// consensus schedule 4
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(0L, 1000000050L).getName())
.isEqualTo("Shanghai");
assertThat(combinedProtocolSchedule.getByBlockNumberOrTimestamp(220L, 1000000050L))
.isSameAs(protocolSchedule4.getByBlockNumberOrTimestamp(220L, 1000000050L));
assertThat(
new MilestoneStreamingProtocolSchedule(combinedProtocolSchedule)
.streamMilestoneBlocks()
.collect(Collectors.toList()))
.isEqualTo(List.of(0L, 5L, 10L, 100L, 105L, 110L, 200L, 220L));
.isEqualTo(List.of(0L, 5L, 10L, 100L, 105L, 110L, 200L, 220L, 1000000000L, 1000000050L));
}
private BftProtocolSchedule createProtocolSchedule(

View File

@@ -24,6 +24,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
@@ -48,6 +49,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -74,6 +76,8 @@ public class IbftRoundIntegrationTest {
private final Subscribers<MinedBlockObserver> subscribers = Subscribers.create();
private ProtocolContext protocolContext;
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private ProtocolSpec protocolSpec;
@Mock private MutableBlockchain blockChain;
@Mock private WorldStateArchive worldStateArchive;
@Mock private BlockImporter blockImporter;
@@ -112,6 +116,9 @@ public class IbftRoundIntegrationTest {
final BlockHeader header = headerTestFixture.buildHeader();
proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList()));
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true));
protocolContext =
@@ -131,7 +138,7 @@ public class IbftRoundIntegrationTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
throwingMessageFactory,
@@ -158,7 +165,7 @@ public class IbftRoundIntegrationTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
throwingMessageFactory,

View File

@@ -40,6 +40,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -57,7 +58,7 @@ public class IbftRound {
private final RoundState roundState;
private final BlockCreator blockCreator;
private final ProtocolContext protocolContext;
private final BlockImporter blockImporter;
private final ProtocolSchedule protocolSchedule;
private final NodeKey nodeKey;
private final MessageFactory messageFactory; // used only to create stored local msgs
private final IbftMessageTransmitter transmitter;
@@ -69,7 +70,7 @@ public class IbftRound {
* @param roundState the round state
* @param blockCreator the block creator
* @param protocolContext the protocol context
* @param blockImporter the block importer
* @param protocolSchedule the protocol schedule
* @param observers the observers
* @param nodeKey the node key
* @param messageFactory the message factory
@@ -81,7 +82,7 @@ public class IbftRound {
final RoundState roundState,
final BlockCreator blockCreator,
final ProtocolContext protocolContext,
final BlockImporter blockImporter,
final ProtocolSchedule protocolSchedule,
final Subscribers<MinedBlockObserver> observers,
final NodeKey nodeKey,
final MessageFactory messageFactory,
@@ -91,7 +92,7 @@ public class IbftRound {
this.roundState = roundState;
this.blockCreator = blockCreator;
this.protocolContext = protocolContext;
this.blockImporter = blockImporter;
this.protocolSchedule = protocolSchedule;
this.observers = observers;
this.nodeKey = nodeKey;
this.messageFactory = messageFactory;
@@ -312,6 +313,8 @@ public class IbftRound {
blockToImport.getHash());
}
LOG.trace("Importing block with extraData={}", extraData);
final BlockImporter blockImporter =
protocolSchedule.getByBlockHeader(blockToImport.getHeader()).getBlockImporter();
final BlockImportResult result =
blockImporter.importBlock(protocolContext, blockToImport, HeaderValidationMode.FULL);
if (!result.isImported()) {

View File

@@ -99,9 +99,8 @@ public class IbftRoundFactory {
*/
public IbftRound createNewRoundWithState(
final BlockHeader parentHeader, final RoundState roundState) {
final ConsensusRoundIdentifier roundIdentifier = roundState.getRoundIdentifier();
final BlockCreator blockCreator =
blockCreatorFactory.create(parentHeader, roundIdentifier.getRoundNumber());
blockCreatorFactory.create(parentHeader, roundState.getRoundIdentifier().getRoundNumber());
final IbftMessageTransmitter messageTransmitter =
new IbftMessageTransmitter(messageFactory, finalState.getValidatorMulticaster());
@@ -110,7 +109,7 @@ public class IbftRoundFactory {
roundState,
blockCreator,
protocolContext,
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockImporter(),
protocolSchedule,
minedBlockObservers,
finalState.getNodeKey(),
messageFactory,

View File

@@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.util.Optional;
@@ -38,7 +39,7 @@ public class MessageValidator {
private final SignedDataValidator signedDataValidator;
private final ProposalBlockConsistencyValidator proposalConsistencyValidator;
private final BlockValidator blockValidator;
private final ProtocolSchedule protocolSchedule;
private final ProtocolContext protocolContext;
private final RoundChangeCertificateValidator roundChangeCertificateValidator;
@@ -47,19 +48,19 @@ public class MessageValidator {
*
* @param signedDataValidator the signed data validator
* @param proposalConsistencyValidator the proposal consistency validator
* @param blockValidator the block validator
* @param protocolSchedule the protocol schedule
* @param protocolContext the protocol context
* @param roundChangeCertificateValidator the round change certificate validator
*/
public MessageValidator(
final SignedDataValidator signedDataValidator,
final ProposalBlockConsistencyValidator proposalConsistencyValidator,
final BlockValidator blockValidator,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final RoundChangeCertificateValidator roundChangeCertificateValidator) {
this.signedDataValidator = signedDataValidator;
this.proposalConsistencyValidator = proposalConsistencyValidator;
this.blockValidator = blockValidator;
this.protocolSchedule = protocolSchedule;
this.protocolContext = protocolContext;
this.roundChangeCertificateValidator = roundChangeCertificateValidator;
}
@@ -93,6 +94,10 @@ public class MessageValidator {
}
private boolean validateBlock(final Block block) {
final BlockValidator blockValidator =
protocolSchedule.getByBlockHeader(block.getHeader()).getBlockValidator();
final var validationResult =
blockValidator.validateAndProcessBlock(
protocolContext, block, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);

View File

@@ -22,7 +22,6 @@ 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.datatypes.Address;
import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -80,8 +79,6 @@ public class MessageValidatorFactory {
*/
public MessageValidator createMessageValidator(
final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) {
final BlockValidator blockValidator =
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockValidator();
final Collection<Address> validators = getValidatorsAfterBlock(parentHeader);
final BftBlockInterface bftBlockInterface =
@@ -90,8 +87,8 @@ public class MessageValidatorFactory {
return new MessageValidator(
createSignedDataValidator(roundIdentifier, parentHeader),
new ProposalBlockConsistencyValidator(),
blockValidator,
protocolContext,
protocolSchedule,
new RoundChangeCertificateValidator(
validators,
(ri) -> createSignedDataValidator(ri, parentHeader),

View File

@@ -110,7 +110,7 @@ public class IbftProtocolScheduleTest {
final BlockHeader blockHeader,
final int block) {
return schedule
.getByBlockNumber(block)
.getByBlockNumberOrTimestamp(block, blockHeader.getTimestamp())
.getBlockHeaderValidator()
.validateHeader(
blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.LIGHT);

View File

@@ -31,8 +31,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.StubGenesisConfigOptions;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
import org.hyperledger.besu.consensus.common.bft.BlockTimer;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
@@ -61,13 +63,19 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult;
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults;
import org.hyperledger.besu.ethereum.chain.DefaultBlockchain;
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.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.mainnet.DefaultProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.util.Subscribers;
import java.math.BigInteger;
@@ -75,6 +83,7 @@ import java.time.Clock;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
@@ -101,8 +110,8 @@ public class IbftBlockHeightManagerTest {
@Mock private Clock clock;
@Mock private MessageValidatorFactory messageValidatorFactory;
@Mock private BftBlockCreator blockCreator;
@Mock private BlockImporter blockImporter;
@Mock private BlockTimer blockTimer;
@Mock private DefaultBlockchain blockchain;
@Mock private RoundTimer roundTimer;
@Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator;
@Mock private ValidatorMulticaster validatorMulticaster;
@@ -158,7 +167,21 @@ public class IbftBlockHeightManagerTest {
.thenReturn(messageValidator);
protocolContext =
new ProtocolContext(null, null, setupContextWithValidators(validators), Optional.empty());
new ProtocolContext(
blockchain, null, setupContextWithValidators(validators), Optional.empty());
final ProtocolScheduleBuilder protocolScheduleBuilder =
new ProtocolScheduleBuilder(
new StubGenesisConfigOptions(),
BigInteger.ONE,
ProtocolSpecAdapters.create(0, Function.identity()),
new PrivacyParameters(),
false,
EvmConfiguration.DEFAULT);
ProtocolSchedule protocolSchedule =
new BftProtocolSchedule(
(DefaultProtocolSchedule) protocolScheduleBuilder.createProtocolSchedule());
// Ensure the created IbftRound has the valid ConsensusRoundIdentifier;
when(roundFactory.createNewRound(any(), anyInt()))
@@ -171,7 +194,7 @@ public class IbftBlockHeightManagerTest {
createdRoundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
Subscribers.create(),
nodeKey,
messageFactory,
@@ -189,7 +212,7 @@ public class IbftBlockHeightManagerTest {
providedRoundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
Subscribers.create(),
nodeKey,
messageFactory,

View File

@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
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.RoundTimer;
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
@@ -56,6 +57,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -83,14 +85,16 @@ public class IbftRoundTest {
private final BftExtraDataCodec bftExtraDataCodec = new IbftExtraDataCodec();
private ProtocolContext protocolContext;
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private MutableBlockchain blockChain;
@Mock private WorldStateArchive worldStateArchive;
@Mock private BlockImporter blockImporter;
@Mock private IbftMessageTransmitter transmitter;
@Mock private MinedBlockObserver minedBlockObserver;
@Mock private BftBlockCreator blockCreator;
@Mock private MessageValidator messageValidator;
@Mock private RoundTimer roundTimer;
@Mock private ProtocolSpec protocolSpec;
@Mock private BlockImporter blockImporter;
@Captor private ArgumentCaptor<Block> blockCaptor;
@@ -127,9 +131,12 @@ public class IbftRoundTest {
.when(blockCreator.createBlock(anyLong()))
.thenReturn(new BlockCreationResult(proposedBlock, new TransactionSelectionResults()));
lenient().when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
lenient()
.when(blockImporter.importBlock(any(), any(), any()))
.thenReturn(new BlockImportResult(true));
.thenReturn(new BlockImportResult(BlockImportResult.BlockImportStatus.IMPORTED));
subscribers.subscribe(minedBlockObserver);
}
@@ -141,7 +148,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -159,7 +166,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -181,7 +188,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -204,7 +211,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -227,7 +234,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -271,7 +278,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -308,7 +315,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -332,7 +339,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -379,7 +386,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -413,7 +420,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -434,7 +441,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -460,7 +467,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -490,7 +497,7 @@ public class IbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
throwingNodeKey,
throwingMessageFactory,

View File

@@ -17,6 +17,7 @@ package org.hyperledger.besu.consensus.ibft.validation;
import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
@@ -26,6 +27,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.BftContext;
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.ProposedBlockHelpers;
import org.hyperledger.besu.consensus.ibft.messagewrappers.Commit;
@@ -42,6 +44,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.AddressHelpers;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.List;
@@ -66,6 +69,8 @@ public class MessageValidatorTest {
private final ProposalBlockConsistencyValidator proposalBlockConsistencyValidator =
mock(ProposalBlockConsistencyValidator.class);
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private ProtocolSpec protocolSpec;
@Mock private BlockValidator blockValidator;
private ProtocolContext protocolContext;
private final RoundChangeCertificateValidator roundChangeCertificateValidator =
@@ -101,6 +106,12 @@ public class MessageValidatorTest {
mockBftCtx,
Optional.empty());
lenient()
.when(protocolSchedule.getByBlockNumberOrTimestamp(anyLong(), anyLong()))
.thenReturn(protocolSpec);
when(protocolSpec.getBlockValidator()).thenReturn(blockValidator);
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
@@ -115,8 +126,8 @@ public class MessageValidatorTest {
new MessageValidator(
signedDataValidator,
proposalBlockConsistencyValidator,
blockValidator,
protocolContext,
protocolSchedule,
roundChangeCertificateValidator);
}

View File

@@ -147,6 +147,7 @@ public class TestContextBuilder {
private static final MetricsSystem metricsSystem = new NoOpMetricsSystem();
private boolean useValidatorContract;
private boolean useLondonMilestone = false;
private boolean useShanghaiMilestone = false;
private boolean useZeroBaseFee = false;
public static final int EPOCH_LENGTH = 10_000;
public static final int BLOCK_TIMER_SEC = 3;
@@ -215,6 +216,11 @@ public class TestContextBuilder {
return this;
}
public TestContextBuilder useShanghaiMilestone(final boolean useShanghaiMilestone) {
this.useShanghaiMilestone = useShanghaiMilestone;
return this;
}
public TestContextBuilder useZeroBaseFee(final boolean useZeroBaseFee) {
this.useZeroBaseFee = useZeroBaseFee;
return this;
@@ -285,6 +291,7 @@ public class TestContextBuilder {
synchronizerUpdater,
useValidatorContract,
useLondonMilestone,
useShanghaiMilestone,
useZeroBaseFee,
qbftForks);
@@ -365,6 +372,7 @@ public class TestContextBuilder {
final SynchronizerUpdater synchronizerUpdater,
final boolean useValidatorContract,
final boolean useLondonMilestone,
final boolean useShanghaiMilestone,
final boolean useZeroBaseFee,
final List<QbftFork> qbftForks) {
@@ -390,6 +398,8 @@ public class TestContextBuilder {
if (useLondonMilestone) {
genesisConfigOptions.londonBlock(0);
} else if (useShanghaiMilestone) {
genesisConfigOptions.shanghaiTime(10);
} else {
genesisConfigOptions.berlinBlock(0);
}

View File

@@ -140,6 +140,33 @@ public class ValidatorContractTest {
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@Test
public void retrievesValidatorsFromValidatorContract_ShanghaiFork_ZeroBaseFee() {
// Using Shanghai on a free gas network
final TestContext context =
new TestContextBuilder()
.indexOfFirstLocallyProposedBlock(0)
.nodeParams(
List.of(new NodeParams(NODE_ADDRESS, NodeKeyUtils.createFrom(NODE_PRIVATE_KEY))))
.clock(TestClock.fixed())
.genesisFile(
Resources.getResource("genesis_validator_contract_shanghai.json").getFile())
.useValidatorContract(true)
.useShanghaiMilestone(true)
.useZeroBaseFee(true)
.buildAndStart();
createNewBlockAsProposerFixedTime(
context, 1,
266L); // 10s ahead of genesis timestamp in genesis_validator_contract_shanghai.json
final ValidatorProvider validatorProvider = context.getValidatorProvider();
final BlockHeader genesisBlock = context.getBlockchain().getBlockHeader(0).get();
final BlockHeader block1 = context.getBlockchain().getBlockHeader(1).get();
assertThat(validatorProvider.getValidatorsForBlock(genesisBlock)).containsExactly(NODE_ADDRESS);
assertThat(validatorProvider.getValidatorsForBlock(block1)).containsExactly(NODE_ADDRESS);
}
@Test
public void transitionsFromBlockHeaderModeToValidatorContractMode() {
final List<QbftFork> qbftForks =
@@ -397,6 +424,24 @@ public class ValidatorContractTest {
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
}
private void createNewBlockAsProposerFixedTime(
final TestContext context, final long blockNumber, final long timestamp) {
ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(blockNumber, 0);
// trigger proposal
context.getController().handleBlockTimerExpiry(new BlockTimerExpiry(roundId));
// peers commit proposed block
Block proposedBlock = context.createBlockForProposalFromChainHead(timestamp);
RoundSpecificPeers peers = context.roundSpecificPeers(roundId);
peers.commitForNonProposing(roundId, proposedBlock);
assertThat(context.getCurrentChainHeight()).isEqualTo(blockNumber);
context
.getController()
.handleNewBlockEvent(new NewChainHead(context.getBlockchain().getChainHeadHeader()));
}
private void remotePeerProposesNewBlock(final TestContext context, final long blockNumber) {
ConsensusRoundIdentifier roundId = new ConsensusRoundIdentifier(blockNumber, 0);

View File

@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
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.RoundTimer;
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
@@ -50,6 +51,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -77,6 +79,8 @@ public class QbftRoundIntegrationTest {
private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec();
private ProtocolContext protocolContext;
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private ProtocolSpec protocolSpec;
@Mock private MutableBlockchain blockChain;
@Mock private WorldStateArchive worldStateArchive;
@Mock private BlockImporter blockImporter;
@@ -115,6 +119,9 @@ public class QbftRoundIntegrationTest {
final BlockHeader header = headerTestFixture.buildHeader();
proposedBlock = new Block(header, new BlockBody(emptyList(), emptyList()));
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true));
protocolContext =
@@ -135,7 +142,7 @@ public class QbftRoundIntegrationTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
throwingMessageFactory,
@@ -163,7 +170,7 @@ public class QbftRoundIntegrationTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
throwingMessageFactory,

View File

@@ -0,0 +1,46 @@
{
"nonce": "0x0",
"timestamp": "0x100",
"extraData": "0xe5a00000000000000000000000000000000000000000000000000000000000000000c0c080c0",
"gasLimit": "0x29b92700",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"64d9be4177f418bcf4e56adad85f33e3a64efe22": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"9f66f8a0f0a6537e4a36aa1799673ea7ae97a166": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"a7f25969fb6f3d5ac09a88862c90b5ff664557a7": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"f4bbfd32c11c9d63e9b4c77bb225810f840342df": {
"balance": "0x446c3b15f9926687d2c40534fdb564000000000000"
},
"0x0000000000000000000000000000000000008888": {
"comment": "validator smart contract. This is compiled from validator_contract.sol using solc --evm-version shanghai --bin-runtime validator_contract.sol",
"balance": "0",
"code": "608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063b7ab4db51461002d575b5f80fd5b61003561004b565b60405161004291906101bc565b60405180910390f35b60605f8054806020026020016040519081016040528092919081815260200182805480156100cb57602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610082575b5050505050905090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610127826100fe565b9050919050565b6101378161011d565b82525050565b5f610148838361012e565b60208301905092915050565b5f602082019050919050565b5f61016a826100d5565b61017481856100df565b935061017f836100ef565b805f5b838110156101af578151610196888261013d565b97506101a183610154565b925050600181019050610182565b5085935050505092915050565b5f6020820190508181035f8301526101d48184610160565b90509291505056fea2646970667358221220b52fc648d3af2856c13132ebd193317528087a330aea868fcf843abcf9d9dc6d64736f6c63430008140033",
"storage": {
"0000000000000000000000000000000000000000000000000000000000000000": "0000000000000000000000000000000000000000000000000000000000000001",
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": "000000000000000000000000eac51e3fe1afc9894f0dfeab8ceb471899b932df"
}
},
"0x0000000000000000000000000000000000009999": {
"comment": "validator smart contract. This is compiled from validator_contract.sol using solc --evm-version shanghai --bin-runtime validator_contract.sol",
"balance": "0",
"code": "608060405234801561000f575f80fd5b5060043610610029575f3560e01c8063b7ab4db51461002d575b5f80fd5b61003561004b565b60405161004291906101bc565b60405180910390f35b60605f8054806020026020016040519081016040528092919081815260200182805480156100cb57602002820191905f5260205f20905b815f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610082575b5050505050905090565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610127826100fe565b9050919050565b6101378161011d565b82525050565b5f610148838361012e565b60208301905092915050565b5f602082019050919050565b5f61016a826100d5565b61017481856100df565b935061017f836100ef565b805f5b838110156101af578151610196888261013d565b97506101a183610154565b925050600181019050610182565b5085935050505092915050565b5f6020820190508181035f8301526101d48184610160565b90509291505056fea2646970667358221220b52fc648d3af2856c13132ebd193317528087a330aea868fcf843abcf9d9dc6d64736f6c63430008140033",
"storage": {
"0000000000000000000000000000000000000000000000000000000000000000": "0000000000000000000000000000000000000000000000000000000000000002",
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563": "000000000000000000000000e98d92560fac3069ccff53ef348ded26a51d4b68",
"290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564": "000000000000000000000000eac51e3fe1afc9894f0dfeab8ceb471899b932df"
}
}
},
"number": "0x0",
"gasUsed": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas": "0x7"
}

View File

@@ -44,6 +44,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -65,8 +66,9 @@ public class QbftRound {
protected final BlockCreator blockCreator;
/** The Protocol context. */
protected final ProtocolContext protocolContext;
/** The Protocol schedule. */
protected final ProtocolSchedule protocolSchedule;
private final BlockImporter blockImporter;
private final NodeKey nodeKey;
private final MessageFactory messageFactory; // used only to create stored local msgs
private final QbftMessageTransmitter transmitter;
@@ -79,7 +81,7 @@ public class QbftRound {
* @param roundState the round state
* @param blockCreator the block creator
* @param protocolContext the protocol context
* @param blockImporter the block importer
* @param protocolSchedule the protocol schedule
* @param observers the observers
* @param nodeKey the node key
* @param messageFactory the message factory
@@ -91,7 +93,7 @@ public class QbftRound {
final RoundState roundState,
final BlockCreator blockCreator,
final ProtocolContext protocolContext,
final BlockImporter blockImporter,
final ProtocolSchedule protocolSchedule,
final Subscribers<MinedBlockObserver> observers,
final NodeKey nodeKey,
final MessageFactory messageFactory,
@@ -101,7 +103,7 @@ public class QbftRound {
this.roundState = roundState;
this.blockCreator = blockCreator;
this.protocolContext = protocolContext;
this.blockImporter = blockImporter;
this.protocolSchedule = protocolSchedule;
this.observers = observers;
this.nodeKey = nodeKey;
this.messageFactory = messageFactory;
@@ -341,7 +343,10 @@ public class QbftRound {
getRoundIdentifier(),
blockToImport.getHash());
}
LOG.trace("Importing proposed block with extraData={}", extraData);
final BlockImporter blockImporter =
protocolSchedule.getByBlockHeader(blockToImport.getHeader()).getBlockImporter();
final BlockImportResult result =
blockImporter.importBlock(protocolContext, blockToImport, HeaderValidationMode.FULL);
if (!result.isImported()) {

View File

@@ -99,7 +99,6 @@ public class QbftRoundFactory {
*/
public QbftRound createNewRoundWithState(
final BlockHeader parentHeader, final RoundState roundState) {
final ConsensusRoundIdentifier roundIdentifier = roundState.getRoundIdentifier();
final BlockCreator blockCreator = blockCreatorFactory.create(parentHeader, 0);
// TODO(tmm): Why is this created everytime?!
@@ -110,7 +109,7 @@ public class QbftRoundFactory {
roundState,
blockCreator,
protocolContext,
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockImporter(),
protocolSchedule,
minedBlockObservers,
finalState.getNodeKey(),
messageFactory,

View File

@@ -23,7 +23,6 @@ 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.datatypes.Address;
import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.BlockHeader;
@@ -78,16 +77,13 @@ public class MessageValidatorFactory {
final RoundChangePayloadValidator roundChangePayloadValidator =
new RoundChangePayloadValidator(validatorsForHeight, chainHeight);
final BlockValidator blockValidator =
protocolSchedule.getByBlockNumber(chainHeight).getBlockValidator();
return new RoundChangeMessageValidator(
roundChangePayloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(validatorsForHeight.size()),
chainHeight,
validatorsForHeight,
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
}
/**
@@ -101,13 +97,11 @@ public class MessageValidatorFactory {
final ConsensusRoundIdentifier roundIdentifier, final BlockHeader parentHeader) {
final Collection<Address> validatorsForHeight = getValidatorsAfterBlock(parentHeader);
final BlockValidator blockValidator =
protocolSchedule.getByBlockNumber(roundIdentifier.getSequenceNumber()).getBlockValidator();
final ProposalValidator proposalValidator =
new ProposalValidator(
blockValidator,
protocolContext,
protocolSchedule,
BftHelpers.calculateRequiredValidatorQuorum(validatorsForHeight.size()),
validatorsForHeight,
roundIdentifier,

View File

@@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.consensus.qbft.validation;
import static com.google.common.base.Preconditions.checkState;
import org.hyperledger.besu.consensus.common.bft.BftBlockInterface;
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
@@ -144,6 +146,8 @@ public class ProposalPayloadValidator {
}
private boolean validateBlock(final Block block) {
checkState(blockValidator != null, "block validation not possible, no block validator.");
final var validationResult =
blockValidator.validateAndProcessBlock(
protocolContext, block, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);

View File

@@ -33,6 +33,7 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.util.Collection;
import java.util.Comparator;
@@ -49,8 +50,8 @@ public class ProposalValidator {
private static final Logger LOG = LoggerFactory.getLogger(ProposalValidator.class);
private static final String ERROR_PREFIX = "Invalid Proposal Payload";
private final BlockValidator blockValidator;
private final ProtocolContext protocolContext;
private final ProtocolSchedule protocolSchedule;
private final int quorumMessageCount;
private final Collection<Address> validators;
private final ConsensusRoundIdentifier roundIdentifier;
@@ -60,8 +61,8 @@ public class ProposalValidator {
/**
* Instantiates a new Proposal validator.
*
* @param blockValidator the block validator
* @param protocolContext the protocol context
* @param protocolSchedule the protocol schedule
* @param quorumMessageCount the quorum message count
* @param validators the validators
* @param roundIdentifier the round identifier
@@ -69,15 +70,15 @@ public class ProposalValidator {
* @param bftExtraDataCodec the bft extra data codec
*/
public ProposalValidator(
final BlockValidator blockValidator,
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule,
final int quorumMessageCount,
final Collection<Address> validators,
final ConsensusRoundIdentifier roundIdentifier,
final Address expectedProposer,
final BftExtraDataCodec bftExtraDataCodec) {
this.blockValidator = blockValidator;
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
this.quorumMessageCount = quorumMessageCount;
this.validators = validators;
this.roundIdentifier = roundIdentifier;
@@ -92,6 +93,8 @@ public class ProposalValidator {
* @return the boolean
*/
public boolean validate(final Proposal msg) {
final BlockValidator blockValidator =
protocolSchedule.getByBlockHeader(msg.getBlock().getHeader()).getBlockValidator();
final ProposalPayloadValidator payloadValidator =
new ProposalPayloadValidator(

View File

@@ -27,6 +27,7 @@ import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import java.util.Collection;
import java.util.List;
@@ -45,8 +46,8 @@ public class RoundChangeMessageValidator {
private final long quorumMessageCount;
private final long chainHeight;
private final Collection<Address> validators;
private final BlockValidator blockValidator;
private final ProtocolContext protocolContext;
private final ProtocolSchedule protocolSchedule;
/**
* Instantiates a new Round change message validator.
@@ -55,22 +56,22 @@ public class RoundChangeMessageValidator {
* @param quorumMessageCount the quorum message count
* @param chainHeight the chain height
* @param validators the validators
* @param blockValidator the block validator
* @param protocolContext the protocol context
* @param protocolSchedule the protocol context
*/
public RoundChangeMessageValidator(
final RoundChangePayloadValidator roundChangePayloadValidator,
final long quorumMessageCount,
final long chainHeight,
final Collection<Address> validators,
final BlockValidator blockValidator,
final ProtocolContext protocolContext) {
final ProtocolContext protocolContext,
final ProtocolSchedule protocolSchedule) {
this.roundChangePayloadValidator = roundChangePayloadValidator;
this.quorumMessageCount = quorumMessageCount;
this.chainHeight = chainHeight;
this.validators = validators;
this.blockValidator = blockValidator;
this.protocolContext = protocolContext;
this.protocolSchedule = protocolSchedule;
}
/**
@@ -94,6 +95,10 @@ public class RoundChangeMessageValidator {
}
private boolean validateBlock(final Block block) {
final BlockValidator blockValidator =
protocolSchedule.getByBlockHeader(block.getHeader()).getBlockValidator();
final var validationResult =
blockValidator.validateAndProcessBlock(
protocolContext, block, HeaderValidationMode.LIGHT, HeaderValidationMode.FULL);

View File

@@ -144,7 +144,7 @@ public class QbftProtocolScheduleTest {
final BlockHeader blockHeader,
final int block) {
return schedule
.getByBlockNumber(block)
.getByBlockNumberOrTimestamp(block, blockHeader.getTimestamp())
.getBlockHeaderValidator()
.validateHeader(
blockHeader, parentHeader, protocolContext(validators), HeaderValidationMode.LIGHT);

View File

@@ -31,8 +31,10 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.config.StubGenesisConfigOptions;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
import org.hyperledger.besu.consensus.common.bft.BftExtraDataCodec;
import org.hyperledger.besu.consensus.common.bft.BftProtocolSchedule;
import org.hyperledger.besu.consensus.common.bft.BlockTimer;
import org.hyperledger.besu.consensus.common.bft.ConsensusRoundIdentifier;
import org.hyperledger.besu.consensus.common.bft.RoundTimer;
@@ -60,20 +62,26 @@ import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.blockcreation.BlockCreator.BlockCreationResult;
import org.hyperledger.besu.ethereum.blockcreation.txselection.TransactionSelectionResults;
import org.hyperledger.besu.ethereum.chain.DefaultBlockchain;
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.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.DefaultProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters;
import org.hyperledger.besu.ethereum.p2p.rlpx.wire.MessageData;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.util.Subscribers;
import java.math.BigInteger;
import java.time.Clock;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
import com.google.common.collect.Lists;
import org.apache.tuweni.bytes.Bytes;
@@ -104,9 +112,9 @@ public class QbftBlockHeightManagerTest {
@Mock private Clock clock;
@Mock private MessageValidatorFactory messageValidatorFactory;
@Mock private BftBlockCreator blockCreator;
@Mock private BlockImporter blockImporter;
@Mock private BlockTimer blockTimer;
@Mock private RoundTimer roundTimer;
@Mock private DefaultBlockchain blockchain;
@Mock private FutureRoundProposalMessageValidator futureRoundProposalMessageValidator;
@Mock private ValidatorMulticaster validatorMulticaster;
@@ -153,16 +161,28 @@ public class QbftBlockHeightManagerTest {
when(messageValidatorFactory.createFutureRoundProposalMessageValidator(anyLong(), any()))
.thenReturn(futureRoundProposalMessageValidator);
when(messageValidatorFactory.createMessageValidator(any(), any())).thenReturn(messageValidator);
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(false));
protocolContext =
new ProtocolContext(
null,
blockchain,
null,
setupContextWithBftExtraDataEncoder(
QbftContext.class, validators, new QbftExtraDataCodec()),
Optional.empty());
final ProtocolScheduleBuilder protocolScheduleBuilder =
new ProtocolScheduleBuilder(
new StubGenesisConfigOptions(),
BigInteger.ONE,
ProtocolSpecAdapters.create(0, Function.identity()),
new PrivacyParameters(),
false,
EvmConfiguration.DEFAULT);
ProtocolSchedule protocolSchedule =
new BftProtocolSchedule(
(DefaultProtocolSchedule) protocolScheduleBuilder.createProtocolSchedule());
// Ensure the created QbftRound has the valid ConsensusRoundIdentifier;
when(roundFactory.createNewRound(any(), anyInt()))
.thenAnswer(
@@ -174,7 +194,7 @@ public class QbftBlockHeightManagerTest {
createdRoundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
Subscribers.create(),
nodeKey,
messageFactory,
@@ -191,7 +211,7 @@ public class QbftBlockHeightManagerTest {
providedRoundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
Subscribers.create(),
nodeKey,
messageFactory,

View File

@@ -32,6 +32,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.consensus.common.bft.BftBlockHashing;
import org.hyperledger.besu.consensus.common.bft.BftExtraData;
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.RoundTimer;
import org.hyperledger.besu.consensus.common.bft.blockcreation.BftBlockCreator;
@@ -59,6 +60,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture;
import org.hyperledger.besu.ethereum.core.BlockImporter;
import org.hyperledger.besu.ethereum.mainnet.BlockImportResult;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModuleException;
import org.hyperledger.besu.util.Subscribers;
@@ -92,14 +94,16 @@ public class QbftRoundTest {
private final BftExtraDataCodec bftExtraDataCodec = new QbftExtraDataCodec();
private ProtocolContext protocolContext;
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private MutableBlockchain blockChain;
@Mock private WorldStateArchive worldStateArchive;
@Mock private BlockImporter blockImporter;
@Mock private QbftMessageTransmitter transmitter;
@Mock private MinedBlockObserver minedBlockObserver;
@Mock private BftBlockCreator blockCreator;
@Mock private MessageValidator messageValidator;
@Mock private RoundTimer roundTimer;
@Mock private ProtocolSpec protocolSpec;
@Mock private BlockImporter blockImporter;
@Captor private ArgumentCaptor<Block> blockCaptor;
@@ -136,7 +140,11 @@ public class QbftRoundTest {
when(blockCreator.createBlock(anyLong()))
.thenReturn(new BlockCreationResult(proposedBlock, new TransactionSelectionResults()));
when(blockImporter.importBlock(any(), any(), any())).thenReturn(new BlockImportResult(true));
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockImporter()).thenReturn(blockImporter);
when(blockImporter.importBlock(any(), any(), any()))
.thenReturn(new BlockImportResult(BlockImportResult.BlockImportStatus.IMPORTED));
subscribers.subscribe(minedBlockObserver);
}
@@ -148,7 +156,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -166,7 +174,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -189,7 +197,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -213,7 +221,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -226,7 +234,6 @@ public class QbftRoundTest {
roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList());
verify(transmitter, times(1)).multicastPrepare(roundIdentifier, proposedBlock.getHash());
verify(transmitter, times(1)).multicastCommit(any(), any(), any());
verify(blockImporter, times(1)).importBlock(any(), any(), any());
}
@Test
@@ -237,7 +244,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -252,18 +259,15 @@ public class QbftRoundTest {
round.createAndSendProposalMessage(15);
verify(transmitter, never()).multicastCommit(any(), any(), any());
verify(blockImporter, never()).importBlock(any(), any(), any());
round.handlePrepareMessage(
messageFactory2.createPrepare(roundIdentifier, proposedBlock.getHash()));
verify(transmitter, times(1))
.multicastCommit(roundIdentifier, proposedBlock.getHash(), localCommitSeal);
verify(blockImporter, never()).importBlock(any(), any(), any());
round.handleCommitMessage(
messageFactory.createCommit(roundIdentifier, proposedBlock.getHash(), remoteCommitSeal));
verify(blockImporter, times(1)).importBlock(any(), any(), any());
}
@Test
@@ -274,7 +278,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -297,7 +301,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -345,7 +349,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -384,7 +388,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -405,7 +409,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -419,8 +423,6 @@ public class QbftRoundTest {
round.handleProposalMessage(
messageFactory.createProposal(
roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList()));
verify(blockImporter, times(1)).importBlock(any(), any(), any());
}
@Test
@@ -432,7 +434,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
nodeKey,
messageFactory,
@@ -446,8 +448,6 @@ public class QbftRoundTest {
round.handleProposalMessage(
messageFactory.createProposal(
roundIdentifier, proposedBlock, Collections.emptyList(), Collections.emptyList()));
verify(blockImporter, times(1)).importBlock(any(), any(), any());
}
@Test
@@ -463,7 +463,7 @@ public class QbftRoundTest {
roundState,
blockCreator,
protocolContext,
blockImporter,
protocolSchedule,
subscribers,
throwingNodeKey,
throwingMessageFactory,

View File

@@ -25,6 +25,7 @@ import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
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;
@@ -44,6 +45,7 @@ import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.HashMap;
@@ -86,6 +88,8 @@ public class ProposalValidatorTest {
@Mock private BlockValidator blockValidator;
@Mock private MutableBlockchain blockChain;
@Mock private WorldStateArchive worldStateArchive;
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private ProtocolSpec protocolSpec;
private ProtocolContext protocolContext;
private final Map<ROUND_ID, RoundSpecificItems> roundItems = new HashMap<>();
@@ -109,6 +113,10 @@ public class ProposalValidatorTest {
eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
when(protocolSpec.getBlockValidator()).thenReturn(blockValidator);
roundItems.put(ROUND_ID.ZERO, createRoundSpecificItems(0));
roundItems.put(ROUND_ID.ONE, createRoundSpecificItems(1));
}
@@ -121,8 +129,8 @@ public class ProposalValidatorTest {
validators.getNodeAddresses(), roundIdentifier, bftExtraDataEncoder),
roundIdentifier,
new ProposalValidator(
blockValidator,
protocolContext,
protocolSchedule,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
validators.getNodeAddresses(),
roundIdentifier,

View File

@@ -20,11 +20,12 @@ 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.mockito.ArgumentMatchers.eq;
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.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;
@@ -42,7 +43,7 @@ import org.hyperledger.besu.ethereum.BlockValidator;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import java.util.Collections;
@@ -59,9 +60,11 @@ import org.mockito.junit.jupiter.MockitoExtension;
public class RoundChangeMessageValidatorTest {
@Mock private RoundChangePayloadValidator payloadValidator;
@Mock private BlockValidator blockValidator;
@Mock private MutableBlockchain blockChain;
@Mock private WorldStateArchive worldStateArchive;
@Mock private BftProtocolSchedule protocolSchedule;
@Mock private BlockValidator blockValidator;
@Mock private ProtocolSpec protocolSpec;
private ProtocolContext protocolContext;
private RoundChangeMessageValidator messageValidator;
@@ -83,6 +86,10 @@ public class RoundChangeMessageValidatorTest {
setupContextWithBftExtraDataEncoder(
QbftContext.class, emptyList(), bftExtraDataEncoder),
Optional.empty());
lenient().when(protocolSchedule.getByBlockHeader(any())).thenReturn(protocolSpec);
lenient().when(protocolSpec.getBlockValidator()).thenReturn(blockValidator);
}
@Test
@@ -94,8 +101,8 @@ public class RoundChangeMessageValidatorTest {
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
for (int i = 0; i < VALIDATOR_COUNT; i++) {
final RoundChange message =
@@ -106,18 +113,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void roundChangeWithValidPiggyBackDataIsValid() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -133,18 +139,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void roundChangeWithBlockRoundMismatchingPreparesIsValid() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -162,18 +167,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void blockIsInvalidFailsValidation() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult("Failed"));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(BlockProcessingResult.FAILED);
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);
@@ -195,8 +199,8 @@ public class RoundChangeMessageValidatorTest {
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final RoundChange message =
validators.getMessageFactory(0).createRoundChange(targetRound, Optional.empty());
@@ -205,18 +209,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void insufficientPiggyBackedPrepareMessagesIsInvalid() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -232,18 +235,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void prepareFromNonValidatorFails() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final QbftNode nonValidator = QbftNode.create();
@@ -261,18 +263,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void validationFailsIfPreparedMetadataContainsDifferentRoundToBlock() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -296,18 +297,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void validationFailsIfPreparesContainsDifferentRoundToBlock() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -333,18 +333,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void validationFailsIfPreparesContainsWrongHeight() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -370,18 +369,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void validationFailsIfPreparesHaveDuplicateAuthors() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(
@@ -402,18 +400,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void validationFailsIfBlockExistsButNotPreparedMetadata() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);
@@ -430,18 +427,17 @@ public class RoundChangeMessageValidatorTest {
@Test
public void validationFailsIfBlockHashDoesNotMatchPreparedMetadata() {
when(blockValidator.validateAndProcessBlock(
any(), any(), eq(HeaderValidationMode.LIGHT), eq(HeaderValidationMode.FULL)))
.thenReturn(new BlockProcessingResult(Optional.empty()));
when(payloadValidator.validate(any())).thenReturn(true);
when(blockValidator.validateAndProcessBlock(any(), any(), any(), any()))
.thenReturn(new BlockProcessingResult(Optional.empty()));
messageValidator =
new RoundChangeMessageValidator(
payloadValidator,
BftHelpers.calculateRequiredValidatorQuorum(VALIDATOR_COUNT),
CHAIN_HEIGHT,
validators.getNodeAddresses(),
blockValidator,
protocolContext);
protocolContext,
protocolSchedule);
final Block block =
ProposedBlockHelpers.createProposalBlock(Collections.emptyList(), roundIdentifier);

View File

@@ -107,7 +107,8 @@ public class VmTraceGenerator {
} else if (frame.getExceptionalHaltReason().isPresent()) {
final Optional<ExceptionalHaltReason> haltReason = frame.getExceptionalHaltReason();
return haltReason.get() != ExceptionalHaltReason.INVALID_JUMP_DESTINATION
&& haltReason.get() != ExceptionalHaltReason.INSUFFICIENT_GAS;
&& haltReason.get() != ExceptionalHaltReason.INSUFFICIENT_GAS
&& haltReason.get() != ExceptionalHaltReason.ILLEGAL_STATE_CHANGE;
} else {
return frame.isVirtualOperation();
}

View File

@@ -41,7 +41,7 @@
"init" : "0x600160015560015460025560ff60005360016000f3",
"value" : "0x0"
},
"error" : "Out of gas",
"error" : "Illegal state change",
"subtraces" : 0,
"traceAddress" : [ 0 ],
"type" : "create"

View File

@@ -82,7 +82,7 @@
"init" : "0x600160015560015460025560ff60005360016000f3",
"value" : "0x0"
},
"error" : "Out of gas",
"error" : "Illegal state change",
"subtraces" : 0,
"traceAddress" : [ 0 ],
"type" : "create"

View File

@@ -34,7 +34,7 @@
"init" : "0x600160015560015460025560ff60005360016000f3",
"value" : "0x0"
},
"error" : "Out of gas",
"error" : "Illegal state change",
"subtraces" : 0,
"traceAddress" : [ 0 ],
"type" : "create"

View File

@@ -22,6 +22,7 @@ import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.core.TransactionReceipt;
import org.hyperledger.besu.ethereum.core.feemarket.CoinbaseFeePriceCalculator;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.evm.ClassicEVMs;
import org.hyperledger.besu.evm.MainnetEVMs;
import org.hyperledger.besu.evm.contractvalidation.MaxCodeSizeRule;
import org.hyperledger.besu.evm.contractvalidation.PrefixCodeRule;
@@ -355,7 +356,7 @@ public class ClassicProtocolSpecs {
// EIP-3855
.evmBuilder(
(gasCalculator, jdCacheConfig) ->
MainnetEVMs.shanghai(
ClassicEVMs.spiral(
gasCalculator, chainId.orElse(BigInteger.ZERO), evmConfiguration))
// EIP-3651
.transactionProcessorBuilder(

View File

@@ -87,7 +87,6 @@ public class EthPeers {
private final Subscribers<ConnectCallback> connectCallbacks = Subscribers.create();
private final Subscribers<DisconnectCallback> disconnectCallbacks = Subscribers.create();
private final Collection<PendingPeerRequest> pendingRequests = new CopyOnWriteArrayList<>();
private final int peerLowerBound;
private final int peerUpperBound;
private final int maxRemotelyInitiatedConnections;
private final Boolean randomPeerPriority;
@@ -108,7 +107,6 @@ public class EthPeers {
final int maxMessageSize,
final List<NodeMessagePermissioningProvider> permissioningProviders,
final Bytes localNodeId,
final int peerLowerBound,
final int peerUpperBound,
final int maxRemotelyInitiatedConnections,
final Boolean randomPeerPriority) {
@@ -119,15 +117,10 @@ public class EthPeers {
this.maxMessageSize = maxMessageSize;
this.bestPeerComparator = HEAVIEST_CHAIN;
this.localNodeId = localNodeId;
this.peerLowerBound = peerLowerBound;
this.peerUpperBound = peerUpperBound;
this.maxRemotelyInitiatedConnections = maxRemotelyInitiatedConnections;
this.randomPeerPriority = randomPeerPriority;
LOG.trace(
"MaxPeers: {}, Lower Bound: {}, Max Remote: {}",
peerUpperBound,
peerLowerBound,
maxRemotelyInitiatedConnections);
LOG.trace("MaxPeers: {}, Max Remote: {}", peerUpperBound, maxRemotelyInitiatedConnections);
metricsSystem.createIntegerGauge(
BesuMetricCategory.ETHEREUM,
"peer_count",
@@ -175,10 +168,6 @@ public class EthPeers {
}
}
public int getPeerLowerBound() {
return peerLowerBound;
}
@NotNull
private List<PeerConnection> getIncompleteConnections(final Bytes id) {
return incompleteConnections.asMap().keySet().stream()

View File

@@ -142,7 +142,7 @@ public class DefaultSynchronizer implements Synchronizer, UnverifiedForkchoiceLi
worldStateStorage,
syncState,
clock);
} else if (SyncMode.X_CHECKPOINT.equals(syncConfig.getSyncMode())) {
} else if (SyncMode.isCheckpointSync(syncConfig.getSyncMode())) {
this.fastSyncFactory =
() ->
CheckpointDownloaderFactory.createCheckpointDownloader(

View File

@@ -24,8 +24,11 @@ public enum SyncMode {
// Perform light validation on older blocks, and switch to full validation for more recent blocks
FAST,
// Perform snapsync
X_SNAP,
SNAP,
// Perform snapsync but starting from a checkpoint instead of starting from genesis
CHECKPOINT,
// Deprecated and will be removed in 24.4.0 (X_SNAP and X_CHECKPOINT)
X_SNAP,
X_CHECKPOINT;
public String normalize() {
@@ -38,10 +41,16 @@ public enum SyncMode {
}
public static boolean isFullSync(final SyncMode syncMode) {
return !EnumSet.of(SyncMode.FAST, SyncMode.X_SNAP, SyncMode.X_CHECKPOINT).contains(syncMode);
return !EnumSet.of(
SyncMode.FAST,
SyncMode.SNAP,
SyncMode.X_SNAP,
SyncMode.CHECKPOINT,
SyncMode.X_CHECKPOINT)
.contains(syncMode);
}
public static boolean isCheckpointSync(final SyncMode syncMode) {
return syncMode.equals(X_CHECKPOINT);
return X_CHECKPOINT.equals(syncMode) || CHECKPOINT.equals(syncMode);
}
}

View File

@@ -1152,9 +1152,9 @@ public final class EthProtocolManagerTest {
@Test
public void shouldUseRightCapabilityDependingOnSyncMode() {
assertHighestCapability(SyncMode.X_SNAP, EthProtocol.ETH68);
assertHighestCapability(SyncMode.SNAP, EthProtocol.ETH68);
assertHighestCapability(SyncMode.FULL, EthProtocol.ETH68);
assertHighestCapability(SyncMode.X_CHECKPOINT, EthProtocol.ETH68);
assertHighestCapability(SyncMode.CHECKPOINT, EthProtocol.ETH68);
/* Eth67 does not support fast sync, see EIP-4938 */
assertHighestCapability(SyncMode.FAST, EthProtocol.ETH66);
}
@@ -1166,9 +1166,9 @@ public final class EthProtocolManagerTest {
final EthProtocolConfiguration configuration =
EthProtocolConfiguration.builder().maxEthCapability(EthProtocolVersion.V65).build();
assertHighestCapability(SyncMode.X_SNAP, EthProtocol.ETH65, configuration);
assertHighestCapability(SyncMode.SNAP, EthProtocol.ETH65, configuration);
assertHighestCapability(SyncMode.FULL, EthProtocol.ETH65, configuration);
assertHighestCapability(SyncMode.X_CHECKPOINT, EthProtocol.ETH65, configuration);
assertHighestCapability(SyncMode.CHECKPOINT, EthProtocol.ETH65, configuration);
/* Eth67 does not support fast sync, see EIP-4938 */
assertHighestCapability(SyncMode.FAST, EthProtocol.ETH65, configuration);
}
@@ -1180,7 +1180,7 @@ public final class EthProtocolManagerTest {
final EthProtocolConfiguration configuration =
EthProtocolConfiguration.builder().minEthCapability(EthProtocolVersion.V64).build();
final EthProtocolManager ethManager = createEthManager(SyncMode.X_SNAP, configuration);
final EthProtocolManager ethManager = createEthManager(SyncMode.SNAP, configuration);
assertThat(ethManager.getSupportedCapabilities()).contains(EthProtocol.ETH64);
assertThat(ethManager.getSupportedCapabilities()).doesNotContain(EthProtocol.ETH63);
@@ -1193,9 +1193,9 @@ public final class EthProtocolManagerTest {
final EthProtocolConfiguration configuration =
EthProtocolConfiguration.builder().maxEthCapability(EthProtocolVersion.V67).build();
assertHighestCapability(SyncMode.X_SNAP, EthProtocol.ETH67, configuration);
assertHighestCapability(SyncMode.SNAP, EthProtocol.ETH67, configuration);
assertHighestCapability(SyncMode.FULL, EthProtocol.ETH67, configuration);
assertHighestCapability(SyncMode.X_CHECKPOINT, EthProtocol.ETH67, configuration);
assertHighestCapability(SyncMode.CHECKPOINT, EthProtocol.ETH67, configuration);
/* Eth67 does not support fast sync, see EIP-4938 */
assertHighestCapability(SyncMode.FAST, EthProtocol.ETH66, configuration);
}

View File

@@ -86,7 +86,6 @@ public class EthProtocolManagerTestUtil {
Bytes.random(64),
25,
25,
25,
false);
final EthMessages messages = new EthMessages();
final EthScheduler ethScheduler = new DeterministicEthScheduler(TimeoutPolicy.NEVER_TIMEOUT);
@@ -206,7 +205,6 @@ public class EthProtocolManagerTestUtil {
Bytes.random(64),
25,
25,
25,
false);
final EthMessages messages = new EthMessages();
@@ -241,7 +239,6 @@ public class EthProtocolManagerTestUtil {
Bytes.random(64),
25,
25,
25,
false);
final EthMessages messages = new EthMessages();
@@ -272,7 +269,6 @@ public class EthProtocolManagerTestUtil {
Bytes.random(64),
25,
25,
25,
false);
final EthMessages messages = new EthMessages();

View File

@@ -118,7 +118,6 @@ public abstract class AbstractMessageTaskTest<T, R> {
Bytes.random(64),
MAX_PEERS,
MAX_PEERS,
MAX_PEERS,
false));
final EthMessages ethMessages = new EthMessages();

View File

@@ -630,7 +630,6 @@ public abstract class AbstractBlockPropagationManagerTest {
Bytes.random(64),
25,
25,
25,
false),
new EthMessages(),
ethScheduler);
@@ -769,7 +768,6 @@ public abstract class AbstractBlockPropagationManagerTest {
Bytes.random(64),
25,
25,
25,
false),
new EthMessages(),
ethScheduler);

View File

@@ -147,7 +147,6 @@ public class TestNode implements Closeable {
Bytes.random(64),
25,
25,
25,
false);
final EthScheduler scheduler = new EthScheduler(1, 1, 1, metricsSystem);

View File

@@ -110,7 +110,6 @@ public class TransactionPoolFactoryTest {
Bytes.random(64),
25,
25,
25,
false);
when(ethContext.getEthMessages()).thenReturn(ethMessages);
when(ethContext.getEthPeers()).thenReturn(ethPeers);

View File

@@ -30,7 +30,6 @@ public class NetworkingConfiguration {
private int initiateConnectionsFrequencySec = DEFAULT_INITIATE_CONNECTIONS_FREQUENCY_SEC;
private int checkMaintainedConnectionsFrequencySec =
DEFAULT_CHECK_MAINTAINED_CONNECTIONS_FREQUENCY_SEC;
private Integer peerLowerBound = DEFAULT_PEER_LOWER_BOUND;
private Optional<String> dnsDiscoveryServerOverride = Optional.empty();
public static NetworkingConfiguration create() {
@@ -87,16 +86,6 @@ public class NetworkingConfiguration {
return this;
}
public Integer getPeerLowerBound() {
return peerLowerBound;
}
public NetworkingConfiguration setPeerLowerBound(final Integer peerLowerBoundConfig) {
checkArgument(peerLowerBoundConfig > 0);
this.peerLowerBound = peerLowerBoundConfig;
return this;
}
@Override
public boolean equals(final Object o) {
if (o == this) {

View File

@@ -231,7 +231,6 @@ public class RetestethContext {
localNodeKey,
MAX_PEERS,
MAX_PEERS,
MAX_PEERS,
false);
final SyncState syncState = new SyncState(blockchain, ethPeers);

View File

@@ -0,0 +1,66 @@
/*
* 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;
import static org.hyperledger.besu.evm.MainnetEVMs.SHANGHAI_INIT_CODE_SIZE_LIMIT;
import static org.hyperledger.besu.evm.MainnetEVMs.registerIstanbulOperations;
import org.hyperledger.besu.evm.gascalculator.GasCalculator;
import org.hyperledger.besu.evm.internal.EvmConfiguration;
import org.hyperledger.besu.evm.operation.Create2Operation;
import org.hyperledger.besu.evm.operation.CreateOperation;
import org.hyperledger.besu.evm.operation.OperationRegistry;
import org.hyperledger.besu.evm.operation.Push0Operation;
import java.math.BigInteger;
public class ClassicEVMs {
/**
* spiral evm.
*
* @param gasCalculator the gas calculator
* @param chainId the chain id
* @param evmConfiguration the evm configuration
* @return the evm
*/
public static EVM spiral(
final GasCalculator gasCalculator,
final BigInteger chainId,
final EvmConfiguration evmConfiguration) {
return new EVM(
spiralOperations(gasCalculator, chainId),
gasCalculator,
evmConfiguration,
EvmSpecVersion.SHANGHAI);
}
/**
* spiral operations' registry.
*
* @param gasCalculator the gas calculator
* @param chainId the chain id
* @return the operation registry
*/
public static OperationRegistry spiralOperations(
final GasCalculator gasCalculator, final BigInteger chainId) {
OperationRegistry registry = new OperationRegistry();
registerIstanbulOperations(registry, gasCalculator, chainId);
registry.put(new Push0Operation(gasCalculator));
registry.put(new CreateOperation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
registry.put(new Create2Operation(gasCalculator, SHANGHAI_INIT_CODE_SIZE_LIMIT));
return registry;
}
}

View File

@@ -117,10 +117,10 @@ public class ContractCreationProcessor extends AbstractMessageProcessor {
LOG.trace(
"Contract creation error: account has already been created for address {}",
contractAddress);
frame.setExceptionalHaltReason(Optional.of(ExceptionalHaltReason.INSUFFICIENT_GAS));
frame.setExceptionalHaltReason(Optional.of(ExceptionalHaltReason.ILLEGAL_STATE_CHANGE));
frame.setState(MessageFrame.State.EXCEPTIONAL_HALT);
operationTracer.traceAccountCreationResult(
frame, Optional.of(ExceptionalHaltReason.INSUFFICIENT_GAS));
frame, Optional.of(ExceptionalHaltReason.ILLEGAL_STATE_CHANGE));
} else {
frame.addCreate(contractAddress);
contract.incrementBalance(frame.getValue());

View File

@@ -258,6 +258,13 @@ public class RocksDBKeyValueStorageFactory implements KeyValueStorageFactory {
final int databaseVersion;
if (databaseExists) {
databaseVersion = DatabaseMetadata.lookUpFrom(dataDir).getVersion();
if (databaseVersion != commonConfiguration.getDatabaseVersion()) {
String error =
String.format(
"Mismatch detected: Database at %s is version '%s', but configuration expects version '%s'.",
dataDir, databaseVersion, commonConfiguration.getDatabaseVersion());
throw new StorageException(error);
}
LOG.info(
"Existing database detected at {}. Version {}. Compacting database...",
dataDir,

View File

@@ -56,6 +56,7 @@ public class RocksDBKeyValuePrivacyStorageFactoryTest {
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
final RocksDBKeyValuePrivacyStorageFactory storageFactory =
new RocksDBKeyValuePrivacyStorageFactory(

View File

@@ -56,9 +56,7 @@ public class RocksDBKeyValueStorageFactoryTest {
public void shouldCreateCorrectMetadataFileForLatestVersion() throws Exception {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@@ -70,14 +68,19 @@ public class RocksDBKeyValueStorageFactoryTest {
assertThat(DatabaseMetadata.lookUpFrom(tempDataDir).getVersion()).isEqualTo(DEFAULT_VERSION);
}
private void mockCommonConfiguration(final Path tempDataDir, final Path tempDatabaseDir) {
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
}
@Test
public void shouldDetectVersion1DatabaseIfNoMetadataFileFound() throws Exception {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@@ -93,9 +96,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@@ -113,8 +114,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@@ -135,8 +135,8 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
new DatabaseMetadata(-1).writeToDirectory(tempDataDir);
assertThatThrownBy(
() ->
@@ -148,14 +148,42 @@ public class RocksDBKeyValueStorageFactoryTest {
.isInstanceOf(StorageException.class);
}
@Test
public void shouldThrowExceptionWhenExistingDatabaseVersionDifferentFromConfig()
throws Exception {
final int actualDatabaseVersion = 1;
final int expectedDatabaseVersion = 2;
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(expectedDatabaseVersion);
new DatabaseMetadata(actualDatabaseVersion).writeToDirectory(tempDataDir);
assertThatThrownBy(
() ->
new RocksDBKeyValueStorageFactory(
() -> rocksDbConfiguration,
segments,
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS)
.create(segment, commonConfiguration, metricsSystem))
.isInstanceOf(StorageException.class)
.hasMessage(
String.format(
"Mismatch detected: Database at %s is version '%s', but configuration expects version '%s'.",
tempDataDir.toAbsolutePath(), actualDatabaseVersion, expectedDatabaseVersion));
}
@Test
public void shouldSetSegmentationFieldDuringCreation() throws Exception {
final Path tempDataDir = temporaryFolder.resolve("data");
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(
@@ -170,8 +198,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempDatabaseDir = temporaryFolder.resolve("db");
Files.createDirectories(tempDatabaseDir);
Files.createDirectories(tempDataDir);
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempDataDir);
mockCommonConfiguration(tempDataDir, tempDatabaseDir);
final String badVersion = "{\"🦄\":1}";
Files.write(
@@ -206,9 +233,7 @@ public class RocksDBKeyValueStorageFactoryTest {
final Path tempSymLinkDataDir =
Files.createSymbolicLink(temporaryFolder.resolve("symlink-data-dir"), tempRealDataDir);
final Path tempDatabaseDir = temporaryFolder.resolve("db");
when(commonConfiguration.getStoragePath()).thenReturn(tempDatabaseDir);
when(commonConfiguration.getDataPath()).thenReturn(tempSymLinkDataDir);
when(commonConfiguration.getDatabaseVersion()).thenReturn(DEFAULT_VERSION);
mockCommonConfiguration(tempSymLinkDataDir, tempDatabaseDir);
final RocksDBKeyValueStorageFactory storageFactory =
new RocksDBKeyValueStorageFactory(

View File

@@ -160,41 +160,39 @@ public class NetworkUtility {
}
/**
* Is port available for tcp.
* Is port unavailable for tcp.
*
* @param port the port
* @return the boolean
* @return true if the port is unavailable for TCP
*/
public static boolean isPortAvailableForTcp(final int port) {
public static boolean isPortUnavailableForTcp(final int port) {
try (final ServerSocket serverSocket = new ServerSocket()) {
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(port));
return true;
serverSocket.close();
return false;
} catch (IOException ex) {
LOG.trace(String.format("Failed to open port %d for TCP", port), ex);
}
return false;
}
private static boolean isPortAvailableForUdp(final int port) {
try (final DatagramSocket datagramSocket = new DatagramSocket(null)) {
datagramSocket.setReuseAddress(true);
datagramSocket.bind(new InetSocketAddress(port));
return true;
} catch (IOException ex) {
LOG.trace(String.format("failed to open port %d for UDP", port), ex);
}
return false;
return true;
}
/**
* Is port available.
* Is port unavailable for udp.
*
* @param port the port
* @return the boolean
* @return true if the port is unavailable for UDP
*/
public static boolean isPortAvailable(final int port) {
return isPortAvailableForTcp(port) && isPortAvailableForUdp(port);
public static boolean isPortUnavailableForUdp(final int port) {
try (final DatagramSocket datagramSocket = new DatagramSocket(null)) {
datagramSocket.setReuseAddress(true);
datagramSocket.bind(new InetSocketAddress(port));
datagramSocket.close();
return false;
} catch (IOException ex) {
LOG.trace(String.format("failed to open port %d for UDP", port), ex);
}
return true;
}
/**

View File

@@ -17,6 +17,7 @@ package org.hyperledger.besu.util;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
@@ -35,12 +36,19 @@ public class NetworkUtilityTest {
}
@Test
public void assertPortIsNotAvailable() throws IOException {
public void assertPortIsNotAvailableForTcp() throws IOException {
final ServerSocket serverSocket = new ServerSocket(8541);
assertThat(!NetworkUtility.isPortAvailable(8541)).isEqualTo(true);
assertThat(NetworkUtility.isPortUnavailableForTcp(8541)).isEqualTo(true);
serverSocket.close();
}
@Test
public void assertPortIsNotAvailableForUdp() throws IOException {
final DatagramSocket datagramSocket = new DatagramSocket(8541);
assertThat(NetworkUtility.isPortUnavailableForUdp(8541)).isEqualTo(true);
datagramSocket.close();
}
@Test
public void assertLocalhostIdentification() {
assertThat(NetworkUtility.isLocalhostAddress("127.0.0.1")).isTrue();