Skip to content

Commit

Permalink
Merge branch 'main' into zkbesu
Browse files Browse the repository at this point in the history
# Conflicts:
#	acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java
  • Loading branch information
fab-10 committed Feb 29, 2024
2 parents 9730676 + e3e512d commit 730cd0b
Show file tree
Hide file tree
Showing 35 changed files with 659 additions and 152 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

### Breaking Changes
- RocksDB database metadata format has changed to be more expressive, the migration of an existing metadata file to the new format is automatic at startup. Before performing a downgrade to a previous version it is mandatory to revert to the original format using the subcommand `besu --data-path=/path/to/besu/datadir storage revert-metadata v2-to-v1`.
- PoA networks won't start with SNAP or CHECKPOINT sync (previously Besu would start with this config but quietly fail to sync, so it's now more obvious that it won't work) [#6625](https://github.com/hyperledger/besu/pull/6625)

### Upcoming Breaking Changes

### Deprecations

### Additions and Improvements
- Extend `Blockchain` service [#6592](https://github.com/hyperledger/besu/pull/6592)
- Add bft-style blockperiodseconds transitions to Clique [#6596](https://github.com/hyperledger/besu/pull/6596)
- RocksDB database metadata refactoring [#6555](https://github.com/hyperledger/besu/pull/6555)
- Make layered txpool aware of minGasPrice and minPriorityFeePerGas dynamic options [#6611](https://github.com/hyperledger/besu/pull/6611)

Expand All @@ -36,7 +38,6 @@

### 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` is deprecated. [#6501](https://github.com/hyperledger/besu/pull/6501)

### Upcoming Breaking Changes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.hyperledger.besu.ethereum.p2p.rlpx.connections.netty.TLSConfiguration;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.ImmutableDataStorageConfiguration;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
import org.hyperledger.besu.tests.acceptance.dsl.StaticNodesUtils;
Expand Down Expand Up @@ -114,9 +113,9 @@ public void startNode(final BesuNode node) {

params.addAll(
DataStorageOptions.fromConfig(
ImmutableDataStorageConfiguration.builder()
.from(DataStorageConfiguration.DEFAULT_FOREST_CONFIG)
.build())
node.getDataStorageConfiguration() == null
? DataStorageConfiguration.DEFAULT_BONSAI_CONFIG
: node.getDataStorageConfiguration())
.getCLIOptions());

if (node.getMiningParameters().isMiningEnabled()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ public void startNode(final BesuNode node) {

final PluginTransactionValidatorService pluginTransactionValidatorService =
getPluginTransactionValidatorService(besuPluginContext);

final DataStorageConfiguration dataStorageConfiguration =
node.getDataStorageConfiguration() == null
? DataStorageConfiguration.DEFAULT_BONSAI_CONFIG
: node.getDataStorageConfiguration();

builder
.synchronizerConfiguration(new SynchronizerConfiguration.Builder().build())
.dataDirectory(node.homeDirectory())
Expand All @@ -235,7 +241,7 @@ public void startNode(final BesuNode node) {
.nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir))))
.metricsSystem(metricsSystem)
.transactionPoolConfiguration(txPoolConfig)
.dataStorageConfiguration(DataStorageConfiguration.DEFAULT_FOREST_CONFIG)
.dataStorageConfiguration(dataStorageConfiguration)
.ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig())
.clock(Clock.systemUTC())
.isRevertReasonEnabled(node.isRevertReasonEnabled())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public class BesuNodeConfigurationBuilder {
private Optional<PermissioningConfiguration> permissioningConfiguration = Optional.empty();
private ApiConfiguration apiConfiguration = ImmutableApiConfiguration.builder().build();
private DataStorageConfiguration dataStorageConfiguration =
DataStorageConfiguration.DEFAULT_FOREST_CONFIG;
DataStorageConfiguration.DEFAULT_BONSAI_CONFIG;
private String keyFilePath = null;
private boolean devMode = true;
private GenesisConfigurationProvider genesisConfigProvider = ignore -> Optional.empty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;

import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder;

Expand Down Expand Up @@ -70,6 +71,8 @@ protected BesuNodeConfigurationBuilder configureNode(
return nodeBuilder
.devMode(false)
.dataPath(hostDataPath)
.dataStorageConfiguration(
DataStorageConfiguration.DEFAULT_FOREST_CONFIG) // existing db is forest
.genesisConfigProvider((nodes) -> Optional.of(genesisData))
.jsonRpcEnabled();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,23 @@
*/
package org.hyperledger.besu.tests.acceptance.clique;

import static java.util.stream.Collectors.joining;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.assertj.core.data.Percentage.withPercentage;

import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBaseJunit5;
import org.hyperledger.besu.tests.acceptance.dsl.account.Account;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory.CliqueOptions;

import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.junit.jupiter.api.Test;
import org.web3j.protocol.core.DefaultBlockParameter;

public class CliqueMiningAcceptanceTest extends AcceptanceTestBaseJunit5 {

Expand Down Expand Up @@ -123,4 +132,117 @@ public void shouldStillMineWhenANodeFailsAndHasSufficientValidators() throws IOE
cluster.verifyOnActiveNodes(clique.blockIsCreatedByProposer(minerNode1));
cluster.verifyOnActiveNodes(clique.blockIsCreatedByProposer(minerNode2));
}

@Test
public void shouldMineBlocksWithBlockPeriodAccordingToTransitions() throws IOException {

final var cliqueOptions = new CliqueOptions(3, CliqueOptions.DEFAULT.epochLength(), true);
final BesuNode minerNode = besu.createCliqueNode("miner1", cliqueOptions);

// setup transitions
final Map<String, Object> decreasePeriodTo2_Transition =
Map.of("block", 3, "blockperiodseconds", 2);
final Map<String, Object> decreasePeriodTo1_Transition =
Map.of("block", 4, "blockperiodseconds", 1);
final Map<String, Object> increasePeriodTo2_Transition =
Map.of("block", 6, "blockperiodseconds", 2);

final Optional<String> initialGenesis =
minerNode.getGenesisConfigProvider().create(List.of(minerNode));
final String genesisWithTransitions =
prependTransitionsToCliqueOptions(
initialGenesis.orElseThrow(),
List.of(
decreasePeriodTo2_Transition,
decreasePeriodTo1_Transition,
increasePeriodTo2_Transition));
minerNode.setGenesisConfig(genesisWithTransitions);

// Mine 6 blocks
cluster.start(minerNode);
minerNode.verify(blockchain.reachesHeight(minerNode, 5));

// Assert the block period decreased/increased after each transition
final long block1Timestamp = getTimestampForBlock(minerNode, 1);
final long block2Timestamp = getTimestampForBlock(minerNode, 2);
final long block3Timestamp = getTimestampForBlock(minerNode, 3);
final long block4Timestamp = getTimestampForBlock(minerNode, 4);
final long block5Timestamp = getTimestampForBlock(minerNode, 5);
final long block6Timestamp = getTimestampForBlock(minerNode, 6);
assertThat(block2Timestamp - block1Timestamp).isCloseTo(3, withPercentage(20));
assertThat(block3Timestamp - block2Timestamp).isCloseTo(2, withPercentage(20));
assertThat(block4Timestamp - block3Timestamp).isCloseTo(1, withPercentage(20));
assertThat(block5Timestamp - block4Timestamp).isCloseTo(1, withPercentage(20));
assertThat(block6Timestamp - block5Timestamp).isCloseTo(2, withPercentage(20));
}

private long getTimestampForBlock(final BesuNode minerNode, final int blockNumber) {
return minerNode
.execute(
ethTransactions.block(DefaultBlockParameter.valueOf(BigInteger.valueOf(blockNumber))))
.getTimestamp()
.longValue();
}

private String prependTransitionsToCliqueOptions(
final String originalOptions, final List<Map<String, Object>> transitions) {
final StringBuilder stringBuilder =
new StringBuilder()
.append(formatCliqueTransitionsOptions(transitions))
.append(",\n")
.append(quote("clique"))
.append(": {");

return originalOptions.replace(quote("clique") + ": {", stringBuilder.toString());
}

private String formatCliqueTransitionsOptions(final List<Map<String, Object>> transitions) {
final StringBuilder stringBuilder = new StringBuilder();

stringBuilder.append(quote("transitions"));
stringBuilder.append(": {\n");
stringBuilder.append(quote("clique"));
stringBuilder.append(": [");
final String formattedTransitions =
transitions.stream().map(this::formatTransition).collect(joining(",\n"));
stringBuilder.append(formattedTransitions);
stringBuilder.append("\n]");
stringBuilder.append("}\n");

return stringBuilder.toString();
}

private String quote(final Object value) {
return '"' + value.toString() + '"';
}

private String formatTransition(final Map<String, Object> transition) {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("{");
String formattedTransition =
transition.keySet().stream()
.map(key -> formatKeyValues(key, transition.get(key)))
.collect(joining(","));
stringBuilder.append(formattedTransition);
stringBuilder.append("}");
return stringBuilder.toString();
}

private String formatKeyValues(final Object... keyOrValue) {
if (keyOrValue.length % 2 == 1) {
// An odd number of strings cannot form a set of key-value pairs
throw new IllegalArgumentException("Must supply key-value pairs");
}
final StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < keyOrValue.length; i += 2) {
if (i > 0) {
stringBuilder.append(", ");
}
final String key = keyOrValue[i].toString();
final Object value = keyOrValue[i + 1];
final String valueStr = value instanceof String ? quote(value) : value.toString();
stringBuilder.append(String.format("\n%s: %s", quote(key), valueStr));
}
return stringBuilder.toString();
}
}
22 changes: 20 additions & 2 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -1622,6 +1622,16 @@ private GenesisConfigOptions readGenesisConfigOptions() {
throw new ParameterException(
this.commandLine, "Unable to load genesis file. " + e.getCause());
}
if (genesisConfigOptions.isPoa()) {
final String errorSuffix = "can't be used with PoA networks";
if (SyncMode.CHECKPOINT.equals(syncMode) || SyncMode.X_CHECKPOINT.equals(syncMode)) {
throw new ParameterException(
commandLine, String.format("%s %s", "Checkpoint sync", errorSuffix));
}
if (syncMode == SyncMode.SNAP || syncMode == SyncMode.X_SNAP) {
throw new ParameterException(commandLine, String.format("%s %s", "Snap sync", errorSuffix));
}
}
return genesisConfigOptions;
}

Expand Down Expand Up @@ -1655,6 +1665,14 @@ && isOptionSet(commandLine, "--sync-min-peers")) {
SyncMode.isCheckpointSync(getDefaultSyncModeIfNotSet()),
singletonList("--Xcheckpoint-post-merge-enabled"));

CommandLineUtils.failIfOptionDoesntMeetRequirement(
commandLine,
"--Xsnapsync-synchronizer-flat option can only be used when -Xsnapsync-synchronizer-flat-db-healing-enabled is true",
unstableSynchronizerOptions.isSnapsyncFlatDbHealingEnabled(),
asList(
"--Xsnapsync-synchronizer-flat-account-healed-count-per-request",
"--Xsnapsync-synchronizer-flat-slot-healed-count-per-request"));

if (!securityModuleName.equals(DEFAULT_SECURITY_MODULE)
&& nodePrivateKeyFileOption.getNodePrivateKeyFile() != null) {
logger.warn(
Expand Down Expand Up @@ -1956,10 +1974,10 @@ private PrivacyParameters privacyParameters() {
if (syncMode == SyncMode.FAST) {
throw new ParameterException(commandLine, String.format("%s %s", "Fast sync", errorSuffix));
}
if (syncMode == SyncMode.SNAP) {
if (syncMode == SyncMode.SNAP || syncMode == SyncMode.X_SNAP) {
throw new ParameterException(commandLine, String.format("%s %s", "Snap sync", errorSuffix));
}
if (syncMode == SyncMode.CHECKPOINT) {
if (syncMode == SyncMode.CHECKPOINT || syncMode == SyncMode.X_CHECKPOINT) {
throw new ParameterException(
commandLine, String.format("%s %s", "Checkpoint sync", errorSuffix));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,7 @@ public void parseBlockPropagationRange(final String arg) {
names = SNAP_FLAT_DB_HEALING_ENABLED_FLAG,
hidden = true,
paramLabel = "<Boolean>",
description =
"(Deprecated) Always enabled: Snap sync flat db healing enabled (default: ${DEFAULT-VALUE})")
description = "Snap sync flat db healing enabled (default: ${DEFAULT-VALUE})")
private Boolean snapsyncFlatDbHealingEnabled =
SnapSyncConfiguration.DEFAULT_IS_FLAT_DB_HEALING_ENABLED;

Expand All @@ -306,6 +305,15 @@ public void parseBlockPropagationRange(final String arg) {

private SynchronizerOptions() {}

/**
* Flag to know whether the flat db healing feature is enabled or disabled.
*
* @return true is the flat db healing is enabled
*/
public boolean isSnapsyncFlatDbHealingEnabled() {
return snapsyncFlatDbHealingEnabled;
}

/**
* Create synchronizer options.
*
Expand Down Expand Up @@ -441,11 +449,15 @@ public List<String> getCLIOptions() {
SNAP_BYTECODE_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncBytecodeCountPerRequest),
SNAP_TRIENODE_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncTrieNodeCountPerRequest),
SNAP_FLAT_ACCOUNT_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatAccountHealedCountPerRequest),
SNAP_FLAT_STORAGE_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatStorageHealedCountPerRequest));
OptionParser.format(snapsyncTrieNodeCountPerRequest));
if (isSnapsyncFlatDbHealingEnabled()) {
value.addAll(
Arrays.asList(
SNAP_FLAT_ACCOUNT_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatAccountHealedCountPerRequest),
SNAP_FLAT_STORAGE_HEALED_COUNT_PER_REQUEST_FLAG,
OptionParser.format(snapsyncFlatStorageHealedCountPerRequest)));
}
return value;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.hyperledger.besu.config.CliqueConfigOptions;
import org.hyperledger.besu.consensus.clique.CliqueBlockInterface;
import org.hyperledger.besu.consensus.clique.CliqueContext;
import org.hyperledger.besu.consensus.clique.CliqueForksSchedulesFactory;
import org.hyperledger.besu.consensus.clique.CliqueMiningTracker;
import org.hyperledger.besu.consensus.clique.CliqueProtocolSchedule;
import org.hyperledger.besu.consensus.clique.blockcreation.CliqueBlockScheduler;
Expand All @@ -27,6 +28,7 @@
import org.hyperledger.besu.consensus.clique.jsonrpc.CliqueJsonRpcMethods;
import org.hyperledger.besu.consensus.common.BlockInterface;
import org.hyperledger.besu.consensus.common.EpochManager;
import org.hyperledger.besu.consensus.common.ForksSchedule;
import org.hyperledger.besu.consensus.common.validator.blockbased.BlockValidatorProvider;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.ethereum.ProtocolContext;
Expand All @@ -52,19 +54,19 @@ public class CliqueBesuControllerBuilder extends BesuControllerBuilder {

private Address localAddress;
private EpochManager epochManager;
private long secondsBetweenBlocks;
private boolean createEmptyBlocks = true;
private final BlockInterface blockInterface = new CliqueBlockInterface();
private ForksSchedule<CliqueConfigOptions> forksSchedule;

@Override
protected void prepForBuild() {
localAddress = Util.publicKeyToAddress(nodeKey.getPublicKey());
final CliqueConfigOptions cliqueConfig = configOptionsSupplier.get().getCliqueConfigOptions();
final long blocksPerEpoch = cliqueConfig.getEpochLength();
secondsBetweenBlocks = cliqueConfig.getBlockPeriodSeconds();
createEmptyBlocks = cliqueConfig.getCreateEmptyBlocks();

epochManager = new EpochManager(blocksPerEpoch);
forksSchedule = CliqueForksSchedulesFactory.create(configOptionsSupplier.get());
}

@Override
Expand Down Expand Up @@ -92,7 +94,7 @@ protected MiningCoordinator createMiningCoordinator(
clock,
protocolContext.getConsensusContext(CliqueContext.class).getValidatorProvider(),
localAddress,
secondsBetweenBlocks),
forksSchedule),
epochManager,
createEmptyBlocks,
ethProtocolManager.ethContext().getScheduler());
Expand All @@ -113,6 +115,7 @@ protected MiningCoordinator createMiningCoordinator(
protected ProtocolSchedule createProtocolSchedule() {
return CliqueProtocolSchedule.create(
configOptionsSupplier.get(),
forksSchedule,
nodeKey,
privacyParameters,
isRevertReasonEnabled,
Expand Down
Loading

0 comments on commit 730cd0b

Please sign in to comment.