iterative merge: Initial plumbing for merge subproject (#2968)

Signed-off-by: garyschulte <garyschulte@gmail.com>
pull/2979/head
garyschulte 3 years ago committed by GitHub
parent 1959043af8
commit 65cb5f6a9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  2. 57
      besu/src/main/java/org/hyperledger/besu/cli/options/unstable/MergeOptions.java
  3. 60
      besu/src/test/java/org/hyperledger/besu/cli/options/unstable/MergeOptionsTest.java
  4. 1
      config/build.gradle
  5. 4
      config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java
  6. 6
      config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java
  7. 14
      config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java
  8. 40
      config/src/main/java/org/hyperledger/besu/config/experimental/MergeOptions.java
  9. 18
      config/src/test/java/org/hyperledger/besu/config/GenesisConfigFileTest.java
  10. 23
      config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java
  11. 48
      consensus/merge/build.gradle
  12. 19
      consensus/merge/src/main/java/org/hyperledger/besu/consensus/merge/blockcreation/MergeMiningCoordinator.java
  13. 1
      settings.gradle

@ -55,6 +55,7 @@ import org.hyperledger.besu.cli.options.unstable.DnsOptions;
import org.hyperledger.besu.cli.options.unstable.EthProtocolOptions;
import org.hyperledger.besu.cli.options.unstable.EvmOptions;
import org.hyperledger.besu.cli.options.unstable.LauncherOptions;
import org.hyperledger.besu.cli.options.unstable.MergeOptions;
import org.hyperledger.besu.cli.options.unstable.MetricsCLIOptions;
import org.hyperledger.besu.cli.options.unstable.MiningOptions;
import org.hyperledger.besu.cli.options.unstable.NatOptions;
@ -268,6 +269,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final NatOptions unstableNatOptions = NatOptions.create();
private final NativeLibraryOptions unstableNativeLibraryOptions = NativeLibraryOptions.create();
private final RPCOptions unstableRPCOptions = RPCOptions.create();
private final MergeOptions mergeOptions = MergeOptions.create();
final LauncherOptions unstableLauncherOptions = LauncherOptions.create();
private final PrivacyPluginOptions unstablePrivacyPluginOptions = PrivacyPluginOptions.create();
private final EvmOptions unstableEvmOptions = EvmOptions.create();
@ -1302,6 +1304,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
.put("Native Library", unstableNativeLibraryOptions)
.put("Data Storage Options", unstableDataStorageOptions)
.put("Launcher", unstableLauncherOptions)
.put("Merge", mergeOptions)
.put("EVM Options", unstableEvmOptions)
.build();

@ -0,0 +1,57 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options.unstable;
import static org.hyperledger.besu.config.experimental.MergeOptions.setMergeEnabled;
import java.util.Stack;
import net.consensys.quorum.mainnet.launcher.options.Options;
import picocli.CommandLine;
import picocli.CommandLine.Option;
/** Unstable support for eth1/2 merge */
public class MergeOptions implements Options {
// To make it easier for tests to reset the value to default
public static final boolean MERGE_ENABLED_DEFAULT_VALUE = false;
@Option(
hidden = true,
names = {"--Xmerge-support"},
description = "Enable experimental support for eth1/eth2 merge (default: ${DEFAULT-VALUE})",
arity = "1",
parameterConsumer = MergeConfigConsumer.class)
@SuppressWarnings({"FieldCanBeFinal"})
private static boolean mergeEnabled = MERGE_ENABLED_DEFAULT_VALUE;
public static MergeOptions create() {
return new MergeOptions();
}
public Boolean isMergeEnabled() {
return mergeEnabled;
}
@SuppressWarnings({"JdkObsolete"})
static class MergeConfigConsumer implements CommandLine.IParameterConsumer {
@Override
public void consumeParameters(
final Stack<String> args,
final CommandLine.Model.ArgSpec argSpec,
final CommandLine.Model.CommandSpec commandSpec) {
setMergeEnabled(Boolean.parseBoolean(args.pop()));
}
}
}

@ -0,0 +1,60 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options.unstable;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy;
import java.util.Stack;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
@SuppressWarnings({"JdkObsolete"})
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class MergeOptionsTest {
@Test
public void shouldBeDisabledByDefault() {
// disabledByDefault
assertThat(MergeOptions.create().isMergeEnabled()).isFalse();
}
@Test
public void shouldBeEnabledFromCliConsumer() {
// enable
var mockStack = new Stack<String>();
mockStack.push("true");
new MergeOptions.MergeConfigConsumer().consumeParameters(mockStack, null, null);
assertThat(org.hyperledger.besu.config.experimental.MergeOptions.isMergeEnabled()).isTrue();
}
@Test
public void shouldDoWithMergeEnabled() {
final AtomicBoolean check = new AtomicBoolean(false);
org.hyperledger.besu.config.experimental.MergeOptions.doIfMergeEnabled((() -> check.set(true)));
assertThat(check.get()).isTrue();
}
@Test
public void shouldThrowOnReconfigure() {
assertThatThrownBy(
() -> org.hyperledger.besu.config.experimental.MergeOptions.setMergeEnabled(false))
.isInstanceOf(RuntimeException.class);
}
}

@ -33,6 +33,7 @@ dependencies {
implementation 'org.apache.logging.log4j:log4j-api'
implementation 'info.picocli:picocli'
implementation 'org.apache.tuweni:tuweni-bytes'
implementation 'org.apache.tuweni:tuweni-units'
runtimeOnly 'org.apache.logging.log4j:log4j-core'
testImplementation project(':testutil')

@ -21,6 +21,8 @@ import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import org.apache.tuweni.units.bigints.UInt256;
public interface GenesisConfigOptions {
boolean isEthHash();
@ -73,6 +75,8 @@ public interface GenesisConfigOptions {
OptionalLong getBaseFeePerGas();
Optional<UInt256> getTerminalTotalDifficulty();
List<Long> getForks();
/**

@ -31,6 +31,7 @@ import java.util.stream.Stream;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
import org.apache.tuweni.units.bigints.UInt256;
public class JsonGenesisConfigOptions implements GenesisConfigOptions {
@ -263,6 +264,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions {
.orElse(OptionalLong.empty());
}
@Override
public Optional<UInt256> getTerminalTotalDifficulty() {
return getOptionalBigInteger("terminaltotaldifficulty").map(UInt256::valueOf);
}
@Override
public OptionalLong getClassicForkBlock() {
return getOptionalLong("classicforkblock");

@ -23,6 +23,7 @@ import java.util.OptionalInt;
import java.util.OptionalLong;
import com.google.common.collect.ImmutableMap;
import org.apache.tuweni.units.bigints.UInt256;
public class StubGenesisConfigOptions implements GenesisConfigOptions {
@ -37,6 +38,8 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
private OptionalLong muirGlacierBlockNumber = OptionalLong.empty();
private OptionalLong berlinBlockNumber = OptionalLong.empty();
private OptionalLong londonBlockNumber = OptionalLong.empty();
private Optional<UInt256> terminalTotalDifficulty = Optional.empty();
private OptionalLong baseFeePerGas = OptionalLong.empty();
private OptionalLong classicForkBlock = OptionalLong.empty();
private OptionalLong ecip1015BlockNumber = OptionalLong.empty();
@ -183,6 +186,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return baseFeePerGas;
}
@Override
public Optional<UInt256> getTerminalTotalDifficulty() {
return terminalTotalDifficulty;
}
@Override
public OptionalLong getClassicForkBlock() {
return classicForkBlock;
@ -403,6 +411,12 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions {
return this;
}
public StubGenesisConfigOptions terminalTotalDifficulty(
final UInt256 updatedTerminalTotalDifficulty) {
terminalTotalDifficulty = Optional.of(updatedTerminalTotalDifficulty);
return this;
}
public StubGenesisConfigOptions baseFeePerGas(final long baseFeeOverride) {
baseFeePerGas = OptionalLong.of(baseFeeOverride);
return this;

@ -0,0 +1,40 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.config.experimental;
import java.util.Optional;
/** For now there is a static config that is driven by a command line option. */
public class MergeOptions {
private static Optional<Boolean> mergeEnabled = Optional.empty();
public static void setMergeEnabled(final boolean bool) {
if (!mergeEnabled.isPresent()) {
mergeEnabled = Optional.of(bool);
} else if (mergeEnabled.get() != bool) {
throw new RuntimeException("Refusing to re-configure already configured merge feature");
}
}
public static boolean isMergeEnabled() {
return mergeEnabled.orElse(false);
}
public static void doIfMergeEnabled(final Runnable mergeDo) {
if (isMergeEnabled()) {
mergeDo.run();
}
}
}

@ -32,6 +32,7 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.io.Resources;
import org.apache.tuweni.units.bigints.UInt256;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.Test;
@ -178,6 +179,23 @@ public class GenesisConfigFileTest {
assertThat(withOverrides.getBaseFeePerGas().getAsLong()).isEqualTo(8L);
}
@Test
public void shouldGetTerminalTotalDifficultyAtGenesis() {
GenesisConfigFile withTerminalTotalDifficultyAtGenesis =
fromConfig("{\"config\":{\"terminalTotalDifficulty\":1000}}");
assertThat(
withTerminalTotalDifficultyAtGenesis
.getConfigOptions()
.getTerminalTotalDifficulty()
.get())
.isEqualTo(UInt256.valueOf(1000L));
}
@Test
public void shouldGetEmptyTerminalTotalDifficultyAtGenesis() {
assertThat(EMPTY_CONFIG.getConfigOptions().getTerminalTotalDifficulty()).isNotPresent();
}
@Test
public void shouldDefaultTimestampToZero() {
assertThat(EMPTY_CONFIG.getTimestamp()).isZero();

@ -24,6 +24,7 @@ import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.tuweni.units.bigints.UInt256;
import org.junit.Test;
public class GenesisConfigOptionsTest {
@ -224,6 +225,28 @@ public class GenesisConfigOptionsTest {
assertThat(config.getHomesteadBlockNumber()).isEmpty();
}
@Test
public void shouldGetTerminalTotalDifficultyWhenSpecified() {
final GenesisConfigOptions config =
fromConfigOptions(singletonMap("terminalTotalDifficulty", BigInteger.valueOf(1000)));
assertThat(config.getTerminalTotalDifficulty()).isPresent();
assertThat(config.getTerminalTotalDifficulty().get()).isEqualTo(UInt256.valueOf(1000));
// stubJsonGenesis
final GenesisConfigOptions stub =
new StubGenesisConfigOptions().terminalTotalDifficulty(UInt256.valueOf(500));
assertThat(stub.getTerminalTotalDifficulty()).isPresent();
assertThat(stub.getTerminalTotalDifficulty().get()).isEqualTo(UInt256.valueOf(500));
}
@Test
public void shouldNotReturnTerminalTotalDifficultyWhenNotSpecified() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.getTerminalTotalDifficulty()).isNotPresent();
// stubJsonGenesis
assertThat(new StubGenesisConfigOptions().getTerminalTotalDifficulty()).isNotPresent();
}
@Test
public void isQuorumShouldDefaultToFalse() {
final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions();

@ -0,0 +1,48 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
apply plugin: 'java-library'
jar {
archiveBaseName = 'besu-merge'
manifest {
attributes(
'Specification-Title': archiveBaseName,
'Specification-Version': project.version,
'Implementation-Title': archiveBaseName,
'Implementation-Version': calculateVersion()
)
}
}
repositories { mavenCentral() }
dependencies {
implementation project(':config')
implementation project(':datatypes')
implementation project(':ethereum:blockcreation')
implementation project(':ethereum:core')
implementation project(':ethereum:eth')
implementation project(':evm')
implementation project(':util')
implementation 'com.google.guava:guava'
implementation 'io.vertx:vertx-core'
implementation 'org.apache.tuweni:tuweni-bytes'
implementation 'org.apache.tuweni:tuweni-units'
testImplementation 'junit:junit'
testImplementation 'org.assertj:assertj-core'
}

@ -0,0 +1,19 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.consensus.merge.blockcreation;
import org.hyperledger.besu.ethereum.blockcreation.MiningCoordinator;
public interface MergeMiningCoordinator extends MiningCoordinator {}

@ -23,6 +23,7 @@ include 'consensus:clique'
include 'consensus:common'
include 'consensus:ibft'
include 'consensus:ibftlegacy'
include 'consensus:merge'
include 'consensus:qbft'
include 'container-tests:tests'
include 'datatypes'

Loading…
Cancel
Save