Fix and re-enable CliqueProposeRpcAcceptanceTest (#8324)

Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
Fabio Di Fabio
2025-02-20 06:36:21 +01:00
committed by GitHub
parent 0e54416026
commit f54e4555bb
2 changed files with 76 additions and 48 deletions

View File

@@ -539,6 +539,12 @@ public class BesuNodeFactory {
public BesuNode createCliqueNodeWithValidators(final String name, final String... validators)
throws IOException {
return createCliqueNodeWithValidators(name, CliqueOptions.DEFAULT, validators);
}
public BesuNode createCliqueNodeWithValidators(
final String name, final CliqueOptions cliqueOptions, final String... validators)
throws IOException {
return create(
new BesuNodeConfigurationBuilder()
@@ -553,7 +559,9 @@ public class BesuNodeFactory {
node.createGenesisConfigForValidators(
asList(validators),
nodes,
GenesisConfigurationFactory::createCliqueGenesisConfig))
vs ->
GenesisConfigurationFactory.createCliqueGenesisConfig(
vs, cliqueOptions)))
.build());
}

View File

@@ -18,61 +18,60 @@ import org.hyperledger.besu.tests.acceptance.dsl.AcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.condition.Condition;
import org.hyperledger.besu.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import java.io.IOException;
import java.util.Arrays;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
@Disabled("flaky see https://github.com/hyperledger/besu/issues/7973")
public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBase {
private static final GenesisConfigurationFactory.CliqueOptions CLIQUE_OPTIONS =
new GenesisConfigurationFactory.CliqueOptions(5, 30000, true);
@Test
public void shouldAddValidators() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final BesuNode minerNode1 = besu.createCliqueNodeWithValidators("miner1", initialValidators);
final BesuNode minerNode2 = besu.createCliqueNodeWithValidators("miner2", initialValidators);
final BesuNode minerNode3 = besu.createCliqueNodeWithValidators("miner3", initialValidators);
public void shouldAddAndRemoveValidators() throws IOException {
final String[] initialValidators = {"miner1"};
final BesuNode minerNode1 =
besu.createCliqueNodeWithValidators("miner1", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode2 =
besu.createCliqueNodeWithValidators("miner2", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode3 =
besu.createCliqueNodeWithValidators("miner3", CLIQUE_OPTIONS, initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);
waitForNodesConnectedAndInSync(minerNode1, minerNode2, minerNode3);
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode2));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
}
@Test
public void shouldRemoveValidators() throws IOException {
final String[] initialValidators = {"miner1", "miner2", "miner3"};
final BesuNode minerNode1 = besu.createCliqueNodeWithValidators("miner1", initialValidators);
final BesuNode minerNode2 = besu.createCliqueNodeWithValidators("miner2", initialValidators);
final BesuNode minerNode3 = besu.createCliqueNodeWithValidators("miner3", initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);
waitForNodesConnectedAndInSync(minerNode1, minerNode2, minerNode3);
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
final Condition cliqueValidatorsChanged = clique.awaitSignerSetChange(minerNode1);
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode3));
final Condition cliqueValidatorsChanged = clique.awaitSignerSetChange(minerNode2);
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode1));
minerNode3.execute(cliqueTransactions.createRemoveProposal(minerNode1));
cluster.verify(clique.validatorsEqual(minerNode2, minerNode3));
cluster.verify(cliqueValidatorsChanged);
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
}
@Disabled
@Test
public void shouldNotAddValidatorWhenInsufficientVotes() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final BesuNode minerNode1 = besu.createCliqueNodeWithValidators("miner1", initialValidators);
final BesuNode minerNode2 = besu.createCliqueNodeWithValidators("miner2", initialValidators);
final BesuNode minerNode3 = besu.createCliqueNodeWithValidators("miner3", initialValidators);
final String[] initialValidators = {"miner1"};
final BesuNode minerNode1 =
besu.createCliqueNodeWithValidators("miner1", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode2 =
besu.createCliqueNodeWithValidators("miner2", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode3 =
besu.createCliqueNodeWithValidators("miner3", CLIQUE_OPTIONS, initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);
waitForNodesConnectedAndInSync(minerNode1, minerNode2, minerNode3);
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode2));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.verify(blockchain.reachesHeight(minerNode1, 1));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
@@ -80,34 +79,57 @@ public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBase {
@Test
public void shouldNotRemoveValidatorWhenInsufficientVotes() throws IOException {
final BesuNode minerNode1 = besu.createCliqueNode("miner1");
final BesuNode minerNode2 = besu.createCliqueNode("miner2");
final BesuNode minerNode3 = besu.createCliqueNode("miner3");
final String[] initialValidators = {"miner1"};
final BesuNode minerNode1 =
besu.createCliqueNodeWithValidators("miner1", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode2 =
besu.createCliqueNodeWithValidators("miner2", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode3 =
besu.createCliqueNodeWithValidators("miner3", CLIQUE_OPTIONS, initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);
waitForNodesConnectedAndInSync(minerNode1, minerNode2, minerNode3);
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode2));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode3));
minerNode1.verify(blockchain.reachesHeight(minerNode1, 1));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
}
@Disabled
@Test
public void shouldIncludeVoteInBlockHeader() throws IOException {
final String[] initialValidators = {"miner1", "miner2"};
final BesuNode minerNode1 = besu.createCliqueNodeWithValidators("miner1", initialValidators);
final BesuNode minerNode2 = besu.createCliqueNodeWithValidators("miner2", initialValidators);
final BesuNode minerNode3 = besu.createCliqueNodeWithValidators("miner3", initialValidators);
final String[] initialValidators = {"miner1"};
final BesuNode minerNode1 =
besu.createCliqueNodeWithValidators("miner1", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode2 =
besu.createCliqueNodeWithValidators("miner2", CLIQUE_OPTIONS, initialValidators);
final BesuNode minerNode3 =
besu.createCliqueNodeWithValidators("miner3", CLIQUE_OPTIONS, initialValidators);
cluster.start(minerNode1, minerNode2, minerNode3);
waitForNodesConnectedAndInSync(minerNode1, minerNode2, minerNode3);
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode2));
minerNode1.verify(blockchain.reachesHeight(minerNode1, 1));
minerNode1.verify(blockchain.beneficiaryEquals(minerNode3));
minerNode1.verify(blockchain.beneficiaryEquals(minerNode2));
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.AUTH));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2));
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3));
minerNode1.verify(blockchain.reachesHeight(minerNode1, 1));
minerNode2.verify(blockchain.reachesHeight(minerNode1, 1));
minerNode1.verify(blockchain.beneficiaryEquals(minerNode3));
minerNode2.verify(blockchain.beneficiaryEquals(minerNode3));
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.AUTH));
minerNode2.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.AUTH));
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3));
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2));
minerNode1.verify(blockchain.reachesHeight(minerNode1, 1));
@@ -115,17 +137,15 @@ public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBase {
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.DROP));
}
private void waitForNodesConnectedAndInSync(
final BesuNode minerNode1, final BesuNode minerNode2, final BesuNode minerNode3) {
private void waitForNodesConnectedAndInSync(final BesuNode... nodes) {
// verify nodes are fully connected otherwise blocks could not be propagated
minerNode1.verify(net.awaitPeerCount(2));
minerNode2.verify(net.awaitPeerCount(2));
minerNode3.verify(net.awaitPeerCount(2));
Arrays.stream(nodes).forEach(node -> node.verify(net.awaitPeerCount(nodes.length - 1)));
// verify that the miner started producing blocks and all other nodes are syncing from it
waitForBlockHeight(minerNode1, 1);
final var minerChainHead = minerNode1.execute(ethTransactions.block());
minerNode2.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
minerNode3.verify(blockchain.minimumHeight(minerChainHead.getNumber().longValue()));
waitForBlockHeight(nodes[0], 1);
final var firstNodeChainHead = nodes[0].execute(ethTransactions.block());
Arrays.stream(nodes)
.skip(1)
.forEach(node -> waitForBlockHeight(node, firstNodeChainHead.getNumber().longValue()));
}
}