diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java index 62a637de5c1..676af532d56 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/BesuNodeFactory.java @@ -379,7 +379,9 @@ public BesuNode createCliqueNode(final String name) throws IOException { .build()); } - public BesuNode createCliqueNoEmptyBlockNode(final String name) throws IOException { + public BesuNode createCliqueNode( + final String name, final GenesisConfigurationFactory.CliqueOptions cliqueOptions) + throws IOException { return create( new BesuNodeConfigurationBuilder() .name(name) @@ -388,7 +390,9 @@ public BesuNode createCliqueNoEmptyBlockNode(final String name) throws IOExcepti .webSocketConfiguration(node.createWebSocketEnabledConfig()) .devMode(false) .genesisConfigProvider( - GenesisConfigurationFactory::createCliqueNoEmptyBlocksGenesisConfig) + validators -> + GenesisConfigurationFactory.createCliqueGenesisConfig( + validators, cliqueOptions)) .build()); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java index dcacc487a82..80bbf4c9206 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java @@ -46,16 +46,17 @@ private GenesisConfigurationFactory() { public static Optional createCliqueGenesisConfig( final Collection validators) { - final String template = readGenesisFile("/clique/clique.json"); - return updateGenesisExtraData( - validators, template, CliqueExtraData::createGenesisExtraDataString); + return createCliqueGenesisConfig(validators, CliqueOptions.DEFAULT); } - public static Optional createCliqueNoEmptyBlocksGenesisConfig( - final Collection validators) { - final String template = readGenesisFile("/clique/clique-no-empty-blocks.json"); + public static Optional createCliqueGenesisConfig( + final Collection 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 createIbft2GenesisConfig( @@ -145,6 +146,14 @@ private static Optional 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 { @@ -154,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); + } } diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java index 36d9fad07b4..c4a6e53c05d 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/clique/CliqueMiningAcceptanceTest.java @@ -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; @@ -44,12 +45,33 @@ public void shouldMineTransactionsOnSingleNode() throws IOException { @Test public void shouldNotMineBlocksIfNoTransactionsOnSingleNode() throws IOException { - final BesuNode minerNode = besu.createCliqueNoEmptyBlockNode("miner1"); + 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)); } + @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"); diff --git a/acceptance-tests/tests/src/test/resources/clique/clique.json b/acceptance-tests/tests/src/test/resources/clique/clique.json deleted file mode 100644 index 8fb3c6dc331..00000000000 --- a/acceptance-tests/tests/src/test/resources/clique/clique.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "config": { - "chainId": 4, - "homesteadBlock": 1, - "eip150Block": 2, - "eip158Block": 4, - "byzantiumBlock": 5, - "constantinopleBlock": 6, - "petersburgBlock": 7, - "clique": { - "blockperiodseconds": 10, - "epochlength": 30000 - } - }, - "nonce": "0x0", - "timestamp": "0x58ee40ba", - "extraData": "%extraData%", - "gasLimit": "0x47b760", - "difficulty": "0x1", - "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "coinbase": "0x0000000000000000000000000000000000000000", - "alloc": { - "fe3b557e8fb62b89f4916b721be55ceb828dbd73": { - "privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", - "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "0xad78ebc5ac6200000" - }, - "627306090abaB3A6e1400e9345bC60c78a8BEf57": { - "privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", - "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "90000000000000000000000" - }, - "f17f52151EbEF6C7334FAD080c5704D77216b732": { - "privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f", - "comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored", - "balance": "90000000000000000000000" - } - }, - "number": "0x0", - "gasUsed": "0x0", - "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" -} diff --git a/acceptance-tests/tests/src/test/resources/clique/clique-no-empty-blocks.json b/acceptance-tests/tests/src/test/resources/clique/clique.json.tpl similarity index 92% rename from acceptance-tests/tests/src/test/resources/clique/clique-no-empty-blocks.json rename to acceptance-tests/tests/src/test/resources/clique/clique.json.tpl index 6521b5a7948..abed233a776 100644 --- a/acceptance-tests/tests/src/test/resources/clique/clique-no-empty-blocks.json +++ b/acceptance-tests/tests/src/test/resources/clique/clique.json.tpl @@ -8,9 +8,9 @@ "constantinopleBlock": 6, "petersburgBlock": 7, "clique": { - "blockperiodseconds": 10, - "epochlength": 30000, - "createemptyblocks": false + "blockperiodseconds": %blockperiodseconds%, + "epochlength": %epochlength%, + "createemptyblocks": %createemptyblocks% } }, "nonce": "0x0",