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

Acceptance test for Clique when configured to not create empty blocks #6191

Merged
merged 3 commits into from
Nov 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.hyperledger.besu.tests.acceptance.dsl.node.Node;
import org.hyperledger.besu.tests.acceptance.dsl.node.RunnableNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory.CliqueOptions;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.pki.PkiKeystoreConfigurationFactory;

import java.io.File;
Expand Down Expand Up @@ -368,14 +369,30 @@ public BesuNode createNodeWithNoDiscovery(final String name) throws IOException
}

public BesuNode createCliqueNode(final String name) throws IOException {
return createCliqueNode(name, CliqueOptions.DEFAULT);
}

public BesuNode createCliqueNode(final String name, final CliqueOptions cliqueOptions)
throws IOException {
return createCliqueNodeWithExtraCliOptions(name, cliqueOptions, List.of());
}

public BesuNode createCliqueNodeWithExtraCliOptions(
final String name, final CliqueOptions cliqueOptions, final List<String> extraCliOptions)
throws IOException {
return create(
new BesuNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig())
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.genesisConfigProvider(GenesisConfigurationFactory::createCliqueGenesisConfig)
.jsonRpcTxPool()
.genesisConfigProvider(
validators ->
GenesisConfigurationFactory.createCliqueGenesisConfig(
validators, cliqueOptions))
.extraCLIOptions(extraCliOptions)
.build());
}

Expand Down Expand Up @@ -567,6 +584,7 @@ public BesuNode createCliqueNodeWithValidators(final String name, final String..
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig())
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.jsonRpcTxPool()
.devMode(false)
.genesisConfigProvider(
nodes ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,17 @@ private GenesisConfigurationFactory() {

public static Optional<String> createCliqueGenesisConfig(
final Collection<? extends RunnableNode> validators) {
final String template = readGenesisFile("/clique/clique.json");
return createCliqueGenesisConfig(validators, CliqueOptions.DEFAULT);
}

public static Optional<String> createCliqueGenesisConfig(
final Collection<? extends RunnableNode> validators, final CliqueOptions cliqueOptions) {
final String template = readGenesisFile("/clique/clique.json.tpl");

return updateGenesisExtraData(
validators, template, CliqueExtraData::createGenesisExtraDataString);
validators,
updateGenesisCliqueOptions(template, cliqueOptions),
CliqueExtraData::createGenesisExtraDataString);
}

public static Optional<String> createIbft2GenesisConfig(
Expand Down Expand Up @@ -138,6 +146,14 @@ private static Optional<String> updateGenesisExtraData(
return Optional.of(genesis);
}

private static String updateGenesisCliqueOptions(
final String template, final CliqueOptions cliqueOptions) {
return template
.replace("%blockperiodseconds%", String.valueOf(cliqueOptions.blockPeriodSeconds))
.replace("%epochlength%", String.valueOf(cliqueOptions.epochLength))
.replace("%createemptyblocks%", String.valueOf(cliqueOptions.createEmptyBlocks));
}

@SuppressWarnings("UnstableApiUsage")
public static String readGenesisFile(final String filepath) {
try {
Expand All @@ -147,4 +163,8 @@ public static String readGenesisFile(final String filepath) {
throw new IllegalStateException("Unable to get test genesis config " + filepath);
}
}

public record CliqueOptions(int blockPeriodSeconds, int epochLength, boolean createEmptyBlocks) {
public static final CliqueOptions DEFAULT = new CliqueOptions(10, 30000, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
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;

Expand All @@ -42,6 +43,35 @@ public void shouldMineTransactionsOnSingleNode() throws IOException {
cluster.verify(receiver.balanceEquals(3));
}

@Test
public void shouldNotMineBlocksIfNoTransactionsWhenCreateEmptyBlockIsFalse() throws IOException {
final var cliqueOptionsNoEmptyBlocks =
new CliqueOptions(
CliqueOptions.DEFAULT.blockPeriodSeconds(), CliqueOptions.DEFAULT.epochLength(), false);
final BesuNode minerNode = besu.createCliqueNode("miner1", cliqueOptionsNoEmptyBlocks);
cluster.start(minerNode);

cluster.verify(clique.noNewBlockCreated(minerNode));
jframe marked this conversation as resolved.
Show resolved Hide resolved
}

@Test
public void shouldMineBlocksOnlyWhenTransactionsArePresentWhenCreateEmptyBlockIsFalse()
throws IOException {
final var cliqueOptionsNoEmptyBlocks =
new CliqueOptions(
CliqueOptions.DEFAULT.blockPeriodSeconds(), CliqueOptions.DEFAULT.epochLength(), false);
final BesuNode minerNode = besu.createCliqueNode("miner1", cliqueOptionsNoEmptyBlocks);
cluster.start(minerNode);

final Account sender = accounts.createAccount("account1");

cluster.verify(clique.noNewBlockCreated(minerNode));

minerNode.execute(accountTransactions.createTransfer(sender, 50));

minerNode.verify(clique.blockIsCreatedByProposer(minerNode));
}

@Test
public void shouldMineTransactionsOnMultipleNodes() throws IOException {
final BesuNode minerNode1 = besu.createCliqueNode("miner1");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
"constantinopleBlock": 6,
"petersburgBlock": 7,
"clique": {
"blockperiodseconds": 10,
"epochlength": 30000
"blockperiodseconds": %blockperiodseconds%,
"epochlength": %epochlength%,
"createemptyblocks": %createemptyblocks%
}
},
"nonce": "0x0",
Expand Down
Loading