mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 21:17:54 -05:00
Merge branch 'main' into zkbesu
This commit is contained in:
2
.github/workflows/acceptance-tests.yml
vendored
2
.github/workflows/acceptance-tests.yml
vendored
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/**'
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -462,7 +462,6 @@ public final class RunnerTest {
|
||||
.networkConfiguration(NetworkingConfiguration.create())
|
||||
.randomPeerPriority(Boolean.FALSE)
|
||||
.maxPeers(25)
|
||||
.lowerBoundPeers(25)
|
||||
.maxRemotelyInitiatedPeers(15)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
1
config/src/main/resources/profiles/staker.toml
Normal file
1
config/src/main/resources/profiles/staker.toml
Normal file
@@ -0,0 +1 @@
|
||||
network="MAINNET"
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"init" : "0x600160015560015460025560ff60005360016000f3",
|
||||
"value" : "0x0"
|
||||
},
|
||||
"error" : "Out of gas",
|
||||
"error" : "Illegal state change",
|
||||
"subtraces" : 0,
|
||||
"traceAddress" : [ 0 ],
|
||||
"type" : "create"
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"init" : "0x600160015560015460025560ff60005360016000f3",
|
||||
"value" : "0x0"
|
||||
},
|
||||
"error" : "Out of gas",
|
||||
"error" : "Illegal state change",
|
||||
"subtraces" : 0,
|
||||
"traceAddress" : [ 0 ],
|
||||
"type" : "create"
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"init" : "0x600160015560015460025560ff60005360016000f3",
|
||||
"value" : "0x0"
|
||||
},
|
||||
"error" : "Out of gas",
|
||||
"error" : "Illegal state change",
|
||||
"subtraces" : 0,
|
||||
"traceAddress" : [ 0 ],
|
||||
"type" : "create"
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -110,7 +110,6 @@ public class TransactionPoolFactoryTest {
|
||||
Bytes.random(64),
|
||||
25,
|
||||
25,
|
||||
25,
|
||||
false);
|
||||
when(ethContext.getEthMessages()).thenReturn(ethMessages);
|
||||
when(ethContext.getEthPeers()).thenReturn(ethPeers);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -231,7 +231,6 @@ public class RetestethContext {
|
||||
localNodeKey,
|
||||
MAX_PEERS,
|
||||
MAX_PEERS,
|
||||
MAX_PEERS,
|
||||
false);
|
||||
final SyncState syncState = new SyncState(blockchain, ethPeers);
|
||||
|
||||
|
||||
66
evm/src/main/java/org/hyperledger/besu/evm/ClassicEVMs.java
Normal file
66
evm/src/main/java/org/hyperledger/besu/evm/ClassicEVMs.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user