Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add genesis configuration isPoa() convenience function, and use it in validation of --miner-enabled option #5669

Merged
merged 8 commits into from
Jul 11, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Use the node's configuration to determine if DNS enode URLs are allowed in calls to `admin_addPeer` and `admin_removePeer` [#5584](https://github.com/hyperledger/besu/pull/5584)
- Align the implementation of Eth/68 `NewPooledTransactionHashes` to other clients, using unsigned int for encoding size. [#5640](https://github.com/hyperledger/besu/pull/5640)
- Failure at startup when enabling layered txpool before initial sync done [#5636](https://github.com/hyperledger/besu/issues/5636)
- Remove miner-related option warnings if the change isn't using Ethash consensus algorithm [#5669](https://github.com/hyperledger/besu/pull/5669)

### Download Links

Expand Down
23 changes: 12 additions & 11 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2133,7 +2133,7 @@ private void issueOptionWarnings() {
"--remote-connections-max-percentage"));

// Check that block producer options work
if (!isMergeEnabled()) {
if (!isMergeEnabled() && getActualGenesisConfigOptions().isEthHash()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! Didn't know about this one.

CommandLineUtils.checkOptionDependencies(
logger,
commandLine,
Expand All @@ -2144,17 +2144,18 @@ private void issueOptionWarnings() {
"--min-gas-price",
"--min-block-occupancy-ratio",
"--miner-extra-data"));

// Check that mining options are able to work
CommandLineUtils.checkOptionDependencies(
logger,
commandLine,
"--miner-enabled",
!minerOptionGroup.isMiningEnabled,
asList(
"--miner-stratum-enabled",
"--Xminer-remote-sealers-limit",
"--Xminer-remote-sealers-hashrate-ttl"));
}
// Check that mining options are able to work
CommandLineUtils.checkOptionDependencies(
logger,
commandLine,
"--miner-enabled",
!minerOptionGroup.isMiningEnabled,
asList(
"--miner-stratum-enabled",
"--Xminer-remote-sealers-limit",
"--Xminer-remote-sealers-hashrate-ttl"));

CommandLineUtils.failIfOptionDoesntMeetRequirement(
commandLine,
Expand Down
85 changes: 83 additions & 2 deletions besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,20 @@ public class BesuCommandTest extends CommandTestAbstract {
(new JsonObject()).put("config", new JsonObject().put("ecCurve", "secp256k1"));
private static final String ENCLAVE_PUBLIC_KEY_PATH =
BesuCommand.class.getResource("/orion_publickey.pub").getPath();
private static final JsonObject VALID_GENESIS_QBFT_POST_LONDON =
(new JsonObject())
.put(
"config",
new JsonObject()
.put("londonBlock", 0)
.put("qbft", new JsonObject().put("blockperiodseconds", 5)));
private static final JsonObject VALID_GENESIS_IBFT2_POST_LONDON =
(new JsonObject())
.put(
"config",
new JsonObject()
.put("londonBlock", 0)
.put("ibft2", new JsonObject().put("blockperiodseconds", 5)));

private static final String[] VALID_ENODE_STRINGS = {
"enode://" + VALID_NODE_ID + "@192.168.0.1:4567",
Expand Down Expand Up @@ -3684,7 +3698,7 @@ public void stratumMiningIsEnabledWhenSpecified() throws Exception {
@Test
public void stratumMiningOptionsRequiresServiceToBeEnabled() {

parseCommand("--miner-stratum-enabled");
parseCommand("--network", "dev", "--miner-stratum-enabled");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I needed to modify the test in a way that would ensure it was being run with a) merge enabled and b) ethash enabled, so that the warning message it was testing for would be produced. The default network is mainnet.json which doesn't have ethash enabled but dev.json does so I ended up going with that.


verifyOptionsConstraintLoggerCall("--miner-enabled", "--miner-stratum-enabled");

Expand All @@ -3698,7 +3712,7 @@ public void stratumMiningOptionsRequiresServiceToBeEnabled() {
public void stratumMiningOptionsRequiresServiceToBeEnabledToml() throws IOException {
final Path toml = createTempFile("toml", "miner-stratum-enabled=true\n");

parseCommand("--config-file", toml.toString());
parseCommand("--network", "dev", "--config-file", toml.toString());

verifyOptionsConstraintLoggerCall("--miner-enabled", "--miner-stratum-enabled");

Expand Down Expand Up @@ -3753,6 +3767,46 @@ public void blockProducingOptionsWarnsMinerShouldBeEnabledToml() throws IOExcept
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void blockProducingOptionsDoNotWarnWhenPoA() throws IOException {

final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON);
parseCommand(
"--genesis-file",
genesisFileQBFT.toString(),
"--min-gas-price",
"42",
"--miner-extra-data",
"0x1122334455667788990011223344556677889900112233445566778899001122");

verify(mockLogger, atMost(0))
.warn(
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture());

assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();

final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON);
parseCommand(
"--genesis-file",
genesisFileIBFT2.toString(),
"--min-gas-price",
"42",
"--miner-extra-data",
"0x1122334455667788990011223344556677889900112233445566778899001122");

verify(mockLogger, atMost(0))
.warn(
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture());

assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void blockProducingOptionsDoNotWarnWhenMergeEnabled() {

Expand Down Expand Up @@ -3801,6 +3855,33 @@ public void minGasPriceRequiresMainOptionToml() throws IOException {
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void minGasPriceDoesNotRequireMainOptionWhenPoA() throws IOException {
final Path genesisFileQBFT = createFakeGenesisFile(VALID_GENESIS_QBFT_POST_LONDON);
parseCommand("--genesis-file", genesisFileQBFT.toString(), "--min-gas-price", "0");

verify(mockLogger, atMost(0))
.warn(
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture());

assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();

final Path genesisFileIBFT2 = createFakeGenesisFile(VALID_GENESIS_IBFT2_POST_LONDON);
parseCommand("--genesis-file", genesisFileIBFT2.toString(), "--min-gas-price", "0");

verify(mockLogger, atMost(0))
.warn(
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture(),
stringArgumentCaptor.capture());

assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}

@Test
public void miningParametersAreCaptured() {
final Address requestedCoinbase = Address.fromHexString("0000011111222223333344444");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ public interface GenesisConfigOptions {
*/
boolean isClique();

/**
* Is a Proof of Authority network.
*
* @return the boolean
*/
boolean isPoa();

/**
* Is consensus migration boolean.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ public boolean isQbft() {
return configRoot.has(QBFT_CONFIG_KEY);
}

@Override
public boolean isPoa() {
return isQbft() || isClique() || isIbft2() || isIbftLegacy();
}

@Override
public BftConfigOptions getBftConfigOptions() {
final String fieldKey = isIbft2() ? IBFT2_CONFIG_KEY : QBFT_CONFIG_KEY;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ public boolean isQbft() {
return false;
}

@Override
public boolean isPoa() {
return false;
}

@Override
public CheckpointConfigOptions getCheckpointOptions() {
return CheckpointConfigOptions.DEFAULT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,22 @@ public void shouldNotUseEthHashIfEthHashNotPresent() {
public void shouldUseIbft2WhenIbft2InConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("ibft2", emptyMap()));
assertThat(config.isIbft2()).isTrue();
assertThat(config.isPoa()).isTrue();
assertThat(config.getConsensusEngine()).isEqualTo("ibft2");
}

public void shouldUseQbftWhenQbftInConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("qbft", emptyMap()));
assertThat(config.isQbft()).isTrue();
assertThat(config.isPoa()).isTrue();
assertThat(config.getConsensusEngine()).isEqualTo("qbft");
}

@Test
public void shouldUseCliqueWhenCliqueInConfig() {
final GenesisConfigOptions config = fromConfigOptions(singletonMap("clique", emptyMap()));
assertThat(config.isClique()).isTrue();
assertThat(config.isPoa()).isTrue();
assertThat(config.getCliqueConfigOptions()).isNotSameAs(CliqueConfigOptions.DEFAULT);
assertThat(config.getConsensusEngine()).isEqualTo("clique");
}
Expand All @@ -63,6 +72,7 @@ public void shouldUseCliqueWhenCliqueInConfig() {
public void shouldNotUseCliqueIfCliqueNotPresent() {
final GenesisConfigOptions config = fromConfigOptions(emptyMap());
assertThat(config.isClique()).isFalse();
assertThat(config.isPoa()).isFalse();
assertThat(config.getCliqueConfigOptions()).isSameAs(CliqueConfigOptions.DEFAULT);
}

Expand Down Expand Up @@ -230,6 +240,7 @@ public void shouldSupportEmptyGenesisConfig() {
final GenesisConfigOptions config = GenesisConfigFile.fromConfig("{}").getConfigOptions();
assertThat(config.isEthHash()).isFalse();
assertThat(config.isClique()).isFalse();
assertThat(config.isPoa()).isFalse();
assertThat(config.getHomesteadBlockNumber()).isEmpty();
}

Expand Down