mirror of https://github.com/hyperledger/besu
Clique acceptance tests (#290)
parent
24b8d730e4
commit
ab744a916c
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.clique; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class CliqueDiscardRpcAcceptanceTest extends AcceptanceTestBase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldDiscardVotes() throws IOException { |
||||||
|
final String[] initialValidators = {"miner1", "miner2"}; |
||||||
|
final PantheonNode minerNode1 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner1", initialValidators); |
||||||
|
final PantheonNode minerNode2 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner2", initialValidators); |
||||||
|
final PantheonNode minerNode3 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner3", initialValidators); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2)); |
||||||
|
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode2)); |
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode1.execute(cliqueTransactions.createDiscardProposal(minerNode2)); |
||||||
|
minerNode1.execute(cliqueTransactions.createDiscardProposal(minerNode3)); |
||||||
|
|
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 2)); |
||||||
|
|
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2)); |
||||||
|
minerNode1.verify(clique.noProposals()); |
||||||
|
minerNode2.verify( |
||||||
|
clique.proposalsEqual().removeProposal(minerNode2).addProposal(minerNode3).build()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,68 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.clique; |
||||||
|
|
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
|
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class CliqueGetSignersRpcTest extends AcceptanceTestBase { |
||||||
|
private PantheonNode minerNode1; |
||||||
|
private PantheonNode minerNode2; |
||||||
|
private PantheonNode minerNode3; |
||||||
|
private PantheonNode[] allNodes; |
||||||
|
private PantheonNode[] initialNodes; |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() throws Exception { |
||||||
|
final String[] validators = {"miner1", "miner2"}; |
||||||
|
minerNode1 = pantheon.createCliqueNodeWithValidators("miner1", validators); |
||||||
|
minerNode2 = pantheon.createCliqueNodeWithValidators("miner2", validators); |
||||||
|
minerNode3 = pantheon.createCliqueNodeWithValidators("miner3", validators); |
||||||
|
initialNodes = new PantheonNode[] {minerNode1, minerNode2}; |
||||||
|
allNodes = new PantheonNode[] {minerNode1, minerNode2, minerNode3}; |
||||||
|
cluster.start(allNodes); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldBeAbleToGetValidatorsForBlockNumber() { |
||||||
|
cluster.verify(clique.validatorsAtBlockEqual("0x0", initialNodes)); |
||||||
|
cluster.waitUntil(wait.chainHeadIsAt(1)); |
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
|
||||||
|
cluster.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
cluster.verify(clique.validatorsAtBlockEqual("0x2", initialNodes)); |
||||||
|
|
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
cluster.verify(clique.validatorsAtBlockEqual("0x3", allNodes)); |
||||||
|
cluster.verify(clique.validatorsAtBlockEqual(LATEST, allNodes)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldBeAbleToGetValidatorsForBlockHash() { |
||||||
|
cluster.verify(clique.validatorsAtBlockHashFromBlockNumberEqual(minerNode1, 0, initialNodes)); |
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
|
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
cluster.verify(clique.validatorsAtBlockHashFromBlockNumberEqual(minerNode1, 1, initialNodes)); |
||||||
|
|
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
cluster.verify(clique.validatorsAtBlockHashFromBlockNumberEqual(minerNode1, 3, allNodes)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,75 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.clique; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class CliqueMiningAcceptanceTest extends AcceptanceTestBase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldMineTransactionsOnSingleNode() throws IOException { |
||||||
|
final PantheonNode minerNode = pantheon.createCliqueNode("miner1"); |
||||||
|
cluster.start(minerNode); |
||||||
|
|
||||||
|
final Account sender = accounts.createAccount("account1"); |
||||||
|
final Account receiver = accounts.createAccount("account2"); |
||||||
|
|
||||||
|
minerNode.execute(transactions.createTransfer(sender, 50)); |
||||||
|
cluster.verify(sender.balanceEquals(50)); |
||||||
|
|
||||||
|
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 1)); |
||||||
|
cluster.verify(receiver.balanceEquals(1)); |
||||||
|
|
||||||
|
minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 2)); |
||||||
|
cluster.verify(receiver.balanceEquals(3)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldMineTransactionsOnMultipleNodes() throws IOException { |
||||||
|
final PantheonNode minerNode1 = pantheon.createCliqueNode("miner1"); |
||||||
|
final PantheonNode minerNode2 = pantheon.createCliqueNode("miner2"); |
||||||
|
final PantheonNode minerNode3 = pantheon.createCliqueNode("miner3"); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
final Account sender = accounts.createAccount("account1"); |
||||||
|
final Account receiver = accounts.createAccount("account2"); |
||||||
|
|
||||||
|
minerNode1.execute(transactions.createTransfer(sender, 50)); |
||||||
|
cluster.verify(sender.balanceEquals(50)); |
||||||
|
|
||||||
|
minerNode2.execute(transactions.createIncrementalTransfers(sender, receiver, 1)); |
||||||
|
cluster.verify(receiver.balanceEquals(1)); |
||||||
|
|
||||||
|
minerNode3.execute(transactions.createIncrementalTransfers(sender, receiver, 2)); |
||||||
|
cluster.verify(receiver.balanceEquals(3)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldStallMiningWhenInsufficientValidators() throws IOException { |
||||||
|
final PantheonNode minerNode1 = pantheon.createCliqueNode("miner1"); |
||||||
|
final PantheonNode minerNode2 = pantheon.createCliqueNode("miner2"); |
||||||
|
final PantheonNode minerNode3 = pantheon.createCliqueNode("miner3"); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
cluster.stopNode(minerNode2); |
||||||
|
cluster.stopNode(minerNode3); |
||||||
|
minerNode1.verify(net.awaitPeerCount(0)); |
||||||
|
minerNode1.verify(clique.noNewBlockCreated(minerNode1)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.clique; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class CliqueProposalRpcAcceptanceTest extends AcceptanceTestBase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldReturnProposals() throws IOException { |
||||||
|
final String[] initialValidators = {"miner1", "miner2"}; |
||||||
|
final PantheonNode minerNode1 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner1", initialValidators); |
||||||
|
final PantheonNode minerNode2 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner2", initialValidators); |
||||||
|
final PantheonNode minerNode3 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner3", initialValidators); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
cluster.verify(clique.noProposals()); |
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2)); |
||||||
|
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode3)); |
||||||
|
|
||||||
|
minerNode1.verify( |
||||||
|
clique.proposalsEqual().addProposal(minerNode3).removeProposal(minerNode2).build()); |
||||||
|
minerNode2.verify(clique.proposalsEqual().removeProposal(minerNode3).build()); |
||||||
|
minerNode3.verify(clique.noProposals()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,115 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.clique; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.waitcondition.WaitCondition; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
public class CliqueProposeRpcAcceptanceTest extends AcceptanceTestBase { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldAddValidators() throws IOException { |
||||||
|
final String[] initialValidators = {"miner1", "miner2"}; |
||||||
|
final PantheonNode minerNode1 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner1", initialValidators); |
||||||
|
final PantheonNode minerNode2 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner2", initialValidators); |
||||||
|
final PantheonNode minerNode3 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner3", initialValidators); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2)); |
||||||
|
final WaitCondition cliqueValidatorsChanged = wait.cliqueValidatorsChanged(minerNode1); |
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode2.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
cluster.waitUntil(cliqueValidatorsChanged); |
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldRemoveValidators() throws IOException { |
||||||
|
final String[] initialValidators = {"miner1", "miner2", "miner3"}; |
||||||
|
final PantheonNode minerNode1 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner1", initialValidators); |
||||||
|
final PantheonNode minerNode2 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner2", initialValidators); |
||||||
|
final PantheonNode minerNode3 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner3", initialValidators); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3)); |
||||||
|
final WaitCondition cliqueValidatorsChanged = wait.cliqueValidatorsChanged(minerNode1); |
||||||
|
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode3)); |
||||||
|
minerNode2.execute(cliqueTransactions.createRemoveProposal(minerNode3)); |
||||||
|
cluster.waitUntil(cliqueValidatorsChanged); |
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldNotAddValidatorWhenInsufficientVotes() throws IOException { |
||||||
|
final String[] initialValidators = {"miner1", "miner2"}; |
||||||
|
final PantheonNode minerNode1 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner1", initialValidators); |
||||||
|
final PantheonNode minerNode2 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner2", initialValidators); |
||||||
|
final PantheonNode minerNode3 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner3", initialValidators); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2)); |
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldNotRemoveValidatorWhenInsufficientVotes() throws IOException { |
||||||
|
final PantheonNode minerNode1 = pantheon.createCliqueNode("miner1"); |
||||||
|
final PantheonNode minerNode2 = pantheon.createCliqueNode("miner2"); |
||||||
|
final PantheonNode minerNode3 = pantheon.createCliqueNode("miner3"); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3)); |
||||||
|
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode3)); |
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
cluster.verify(clique.validatorsEqual(minerNode1, minerNode2, minerNode3)); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void shouldIncludeVoteInBlockHeader() throws IOException { |
||||||
|
final String[] initialValidators = {"miner1", "miner2"}; |
||||||
|
final PantheonNode minerNode1 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner1", initialValidators); |
||||||
|
final PantheonNode minerNode2 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner2", initialValidators); |
||||||
|
final PantheonNode minerNode3 = |
||||||
|
pantheon.createCliqueNodeWithValidators("miner3", initialValidators); |
||||||
|
cluster.start(minerNode1, minerNode2, minerNode3); |
||||||
|
|
||||||
|
minerNode1.execute(cliqueTransactions.createAddProposal(minerNode3)); |
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
minerNode1.verify(blockchain.beneficiaryEquals(minerNode3)); |
||||||
|
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.AUTH)); |
||||||
|
|
||||||
|
minerNode1.execute(cliqueTransactions.createRemoveProposal(minerNode2)); |
||||||
|
minerNode1.waitUntil(wait.chainHeadHasProgressed(minerNode1, 1)); |
||||||
|
minerNode1.verify(blockchain.beneficiaryEquals(minerNode2)); |
||||||
|
minerNode1.verify(clique.nonceVoteEquals(CLIQUE_NONCE_VOTE.DROP)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,36 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.blockchain; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Java6Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; |
||||||
|
|
||||||
|
public class ExpectBeneficiary implements Condition { |
||||||
|
private final EthTransactions eth; |
||||||
|
private final String beneficiary; |
||||||
|
|
||||||
|
public ExpectBeneficiary(final EthTransactions eth, final PantheonNode node) { |
||||||
|
this.eth = eth; |
||||||
|
this.beneficiary = node.getAddress().toString(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor(() -> assertThat(node.execute(eth.block()).getMiner()).isEqualTo(beneficiary)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.blockchain; |
||||||
|
|
||||||
|
import static junit.framework.TestCase.fail; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; |
||||||
|
|
||||||
|
import java.math.BigInteger; |
||||||
|
import java.util.concurrent.TimeUnit; |
||||||
|
import java.util.concurrent.atomic.AtomicInteger; |
||||||
|
|
||||||
|
import org.awaitility.Awaitility; |
||||||
|
|
||||||
|
public class ExpectBlockNotCreated implements Condition { |
||||||
|
private final EthTransactions eth; |
||||||
|
private final int initialWait; |
||||||
|
private final int blockPeriodWait; |
||||||
|
|
||||||
|
public ExpectBlockNotCreated( |
||||||
|
final EthTransactions eth, final int initialWait, final int blockPeriodWait) { |
||||||
|
this.eth = eth; |
||||||
|
this.initialWait = initialWait; |
||||||
|
this.blockPeriodWait = blockPeriodWait; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
final AtomicInteger tries = new AtomicInteger(); |
||||||
|
final int triesRequired = blockPeriodWait / 1000; |
||||||
|
final BigInteger initialBlock = initialBlock(node); |
||||||
|
Awaitility.await() |
||||||
|
.pollInterval(1, TimeUnit.SECONDS) |
||||||
|
.atMost(30, TimeUnit.SECONDS) |
||||||
|
.until(() -> isNewBlock(node, tries, triesRequired, initialBlock)); |
||||||
|
} |
||||||
|
|
||||||
|
private Boolean isNewBlock( |
||||||
|
final Node node, |
||||||
|
final AtomicInteger tries, |
||||||
|
final int triesRequired, |
||||||
|
final BigInteger lastBlock) { |
||||||
|
final BigInteger currentBlock = node.execute(eth.blockNumber()); |
||||||
|
final int currentTries = tries.getAndIncrement(); |
||||||
|
if (!currentBlock.equals(lastBlock)) { |
||||||
|
final String failMsg = |
||||||
|
String.format( |
||||||
|
"New block created. Expected block=%s got block=%s", lastBlock, currentBlock); |
||||||
|
fail(failMsg); |
||||||
|
} |
||||||
|
// Only consider that the block is really the same after a period of time or number tries as a
|
||||||
|
// block could be currently be in the process of being mined
|
||||||
|
return currentTries > triesRequired; |
||||||
|
} |
||||||
|
|
||||||
|
private BigInteger initialBlock(final Node node) { |
||||||
|
try { |
||||||
|
Thread.sleep(initialWait); |
||||||
|
return node.execute(eth.blockNumber()); |
||||||
|
} catch (InterruptedException e) { |
||||||
|
throw new IllegalStateException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.blockchain; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Java6Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; |
||||||
|
|
||||||
|
import java.math.BigInteger; |
||||||
|
|
||||||
|
public class ExpectBlockNumber implements Condition { |
||||||
|
private final EthTransactions eth; |
||||||
|
private final BigInteger blockNumber; |
||||||
|
|
||||||
|
public ExpectBlockNumber(final EthTransactions eth, final BigInteger blockNumber) { |
||||||
|
this.eth = eth; |
||||||
|
this.blockNumber = blockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor(() -> assertThat(node.execute(eth.blockNumber())).isEqualTo(blockNumber)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,123 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique; |
||||||
|
|
||||||
|
import static java.util.Collections.emptyList; |
||||||
|
import static tech.pegasys.pantheon.ethereum.core.Hash.fromHexString; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.config.CliqueConfigOptions; |
||||||
|
import tech.pegasys.pantheon.config.GenesisConfigFile; |
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.blockchain.ExpectBlockNotCreated; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; |
||||||
|
|
||||||
|
import java.math.BigInteger; |
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.HashMap; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.Map.Entry; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap; |
||||||
|
import org.web3j.protocol.core.DefaultBlockParameter; |
||||||
|
|
||||||
|
public class CliqueConditions { |
||||||
|
private final EthTransactions eth; |
||||||
|
private final CliqueTransactions clique; |
||||||
|
|
||||||
|
public CliqueConditions(final EthTransactions eth, final CliqueTransactions clique) { |
||||||
|
this.eth = eth; |
||||||
|
this.clique = clique; |
||||||
|
} |
||||||
|
|
||||||
|
public ExpectValidators validatorsEqual(final PantheonNode... validators) { |
||||||
|
return new ExpectValidators(clique, validatorAddresses(validators)); |
||||||
|
} |
||||||
|
|
||||||
|
public Condition validatorsAtBlockEqual( |
||||||
|
final String blockNumber, final PantheonNode... validators) { |
||||||
|
return new ExpectValidatorsAtBlock(clique, blockNumber, validatorAddresses(validators)); |
||||||
|
} |
||||||
|
|
||||||
|
public Condition validatorsAtBlockHashFromBlockNumberEqual( |
||||||
|
final Node node, final long blockNumber, final PantheonNode... validators) { |
||||||
|
final DefaultBlockParameter blockParameter = |
||||||
|
DefaultBlockParameter.valueOf(BigInteger.valueOf(blockNumber)); |
||||||
|
final String blockHash = node.execute(eth.block(blockParameter)).getHash(); |
||||||
|
return new ExpectValidatorsAtBlockHash( |
||||||
|
clique, fromHexString(blockHash), validatorAddresses(validators)); |
||||||
|
} |
||||||
|
|
||||||
|
public ProposalsConfig proposalsEqual() { |
||||||
|
return new ProposalsConfig(clique); |
||||||
|
} |
||||||
|
|
||||||
|
public Condition noProposals() { |
||||||
|
return new ExpectProposals(clique, ImmutableMap.of()); |
||||||
|
} |
||||||
|
|
||||||
|
public Condition nonceVoteEquals(final CLIQUE_NONCE_VOTE clique_nonce_vote) { |
||||||
|
return new ExpectNonceVote(eth, clique_nonce_vote); |
||||||
|
} |
||||||
|
|
||||||
|
public Condition noNewBlockCreated(final PantheonNode node) { |
||||||
|
final int blockPeriodSeconds = cliqueBlockPeriod(node); |
||||||
|
final int blockPeriodWait = blockPeriodSeconds * 1000; |
||||||
|
return new ExpectBlockNotCreated(eth, blockPeriodWait, blockPeriodWait); |
||||||
|
} |
||||||
|
|
||||||
|
private int cliqueBlockPeriod(final PantheonNode node) { |
||||||
|
final String config = node.genesisConfigProvider().createGenesisConfig(emptyList()).get(); |
||||||
|
final GenesisConfigFile genesisConfigFile = GenesisConfigFile.fromConfig(config); |
||||||
|
final CliqueConfigOptions cliqueConfigOptions = |
||||||
|
genesisConfigFile.getConfigOptions().getCliqueConfigOptions(); |
||||||
|
return cliqueConfigOptions.getBlockPeriodSeconds(); |
||||||
|
} |
||||||
|
|
||||||
|
private Address[] validatorAddresses(final PantheonNode[] validators) { |
||||||
|
return Arrays.stream(validators).map(PantheonNode::getAddress).sorted().toArray(Address[]::new); |
||||||
|
} |
||||||
|
|
||||||
|
public static class ProposalsConfig { |
||||||
|
private final Map<PantheonNode, Boolean> proposals = new HashMap<>(); |
||||||
|
private final CliqueTransactions clique; |
||||||
|
|
||||||
|
public ProposalsConfig(final CliqueTransactions clique) { |
||||||
|
this.clique = clique; |
||||||
|
} |
||||||
|
|
||||||
|
public ProposalsConfig addProposal(final PantheonNode node) { |
||||||
|
proposals.put(node, true); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public ProposalsConfig removeProposal(final PantheonNode node) { |
||||||
|
proposals.put(node, false); |
||||||
|
return this; |
||||||
|
} |
||||||
|
|
||||||
|
public Condition build() { |
||||||
|
final Map<Address, Boolean> proposalsAsAddress = |
||||||
|
this.proposals |
||||||
|
.entrySet() |
||||||
|
.stream() |
||||||
|
.collect(Collectors.toMap(p -> p.getKey().getAddress(), Entry::getValue)); |
||||||
|
return new ExpectProposals(clique, proposalsAsAddress); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Java6Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique.ExpectNonceVote.CLIQUE_NONCE_VOTE.AUTH; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; |
||||||
|
|
||||||
|
public class ExpectNonceVote implements Condition { |
||||||
|
private static final String NONCE_AUTH = "0xffffffffffffffff"; |
||||||
|
private static final String NONCE_DROP = "0x0000000000000000"; |
||||||
|
private final EthTransactions eth; |
||||||
|
private final String expectedNonce; |
||||||
|
|
||||||
|
public enum CLIQUE_NONCE_VOTE { |
||||||
|
AUTH, |
||||||
|
DROP |
||||||
|
} |
||||||
|
|
||||||
|
public ExpectNonceVote(final EthTransactions eth, final CLIQUE_NONCE_VOTE vote) { |
||||||
|
this.eth = eth; |
||||||
|
this.expectedNonce = vote == AUTH ? NONCE_AUTH : NONCE_DROP; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor(() -> assertThat(node.execute(eth.block()).getNonceRaw()).isEqualTo(expectedNonce)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class ExpectProposals implements Condition { |
||||||
|
private final CliqueTransactions clique; |
||||||
|
private final Map<Address, Boolean> proposers; |
||||||
|
|
||||||
|
public ExpectProposals(final CliqueTransactions clique, final Map<Address, Boolean> proposers) { |
||||||
|
this.clique = clique; |
||||||
|
this.proposers = proposers; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor(() -> assertThat(node.execute(clique.createProposals())).isEqualTo(proposers)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
|
||||||
|
public class ExpectValidators implements Condition { |
||||||
|
private final CliqueTransactions clique; |
||||||
|
private final Address[] validators; |
||||||
|
|
||||||
|
public ExpectValidators(final CliqueTransactions clique, final Address... validators) { |
||||||
|
this.clique = clique; |
||||||
|
this.validators = validators; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor( |
||||||
|
() -> |
||||||
|
assertThat(node.execute(clique.createGetSigners(LATEST))).containsExactly(validators)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
|
||||||
|
public class ExpectValidatorsAtBlock implements Condition { |
||||||
|
private final CliqueTransactions clique; |
||||||
|
private final String blockParameter; |
||||||
|
private final Address[] validators; |
||||||
|
|
||||||
|
public ExpectValidatorsAtBlock( |
||||||
|
final CliqueTransactions clique, final String blockNumber, final Address... validators) { |
||||||
|
this.clique = clique; |
||||||
|
this.blockParameter = blockNumber; |
||||||
|
this.validators = validators; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor( |
||||||
|
() -> |
||||||
|
assertThat(node.execute(clique.createGetSigners(blockParameter))) |
||||||
|
.containsExactly(validators)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.condition.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.ethereum.core.Hash; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
|
||||||
|
public class ExpectValidatorsAtBlockHash implements Condition { |
||||||
|
private final CliqueTransactions clique; |
||||||
|
private final Hash blockHash; |
||||||
|
private final Address[] validators; |
||||||
|
|
||||||
|
public ExpectValidatorsAtBlockHash( |
||||||
|
final CliqueTransactions clique, final Hash blockHash, final Address... validators) { |
||||||
|
this.clique = clique; |
||||||
|
this.blockHash = blockHash; |
||||||
|
this.validators = validators; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void verify(final Node node) { |
||||||
|
waitFor( |
||||||
|
() -> |
||||||
|
assertThat(node.execute(clique.createGetSignersAtHash(blockHash))) |
||||||
|
.containsExactly(validators)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.node; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.Optional; |
||||||
|
|
||||||
|
@FunctionalInterface |
||||||
|
public interface GenesisConfigProvider { |
||||||
|
Optional<String> createGenesisConfig(final List<RunnableNode> validators); |
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction; |
||||||
|
|
||||||
|
import static java.util.Collections.emptyList; |
||||||
|
import static java.util.Collections.singletonList; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.ethereum.core.Hash; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Map; |
||||||
|
import java.util.concurrent.ScheduledExecutorService; |
||||||
|
|
||||||
|
import org.web3j.protocol.Web3jService; |
||||||
|
import org.web3j.protocol.core.JsonRpc2_0Web3j; |
||||||
|
import org.web3j.protocol.core.Request; |
||||||
|
import org.web3j.protocol.core.Response; |
||||||
|
|
||||||
|
public class PantheonWeb3j extends JsonRpc2_0Web3j { |
||||||
|
|
||||||
|
public PantheonWeb3j(final Web3jService web3jService) { |
||||||
|
super(web3jService); |
||||||
|
} |
||||||
|
|
||||||
|
public PantheonWeb3j( |
||||||
|
final Web3jService web3jService, |
||||||
|
final long pollingInterval, |
||||||
|
final ScheduledExecutorService scheduledExecutorService) { |
||||||
|
super(web3jService, pollingInterval, scheduledExecutorService); |
||||||
|
} |
||||||
|
|
||||||
|
public Request<?, ProposeResponse> cliquePropose(final String address, final Boolean auth) { |
||||||
|
return new Request<>( |
||||||
|
"clique_propose", |
||||||
|
Arrays.asList(address, auth.toString()), |
||||||
|
web3jService, |
||||||
|
ProposeResponse.class); |
||||||
|
} |
||||||
|
|
||||||
|
public Request<?, DiscardResponse> cliqueDiscard(final String address) { |
||||||
|
return new Request<>( |
||||||
|
"clique_discard", singletonList(address), web3jService, DiscardResponse.class); |
||||||
|
} |
||||||
|
|
||||||
|
public Request<?, ProposalsResponse> cliqueProposals() { |
||||||
|
return new Request<>("clique_proposals", emptyList(), web3jService, ProposalsResponse.class); |
||||||
|
} |
||||||
|
|
||||||
|
public Request<?, SignersBlockResponse> cliqueGetSigners(final String blockNumber) { |
||||||
|
return new Request<>( |
||||||
|
"clique_getSigners", singletonList(blockNumber), web3jService, SignersBlockResponse.class); |
||||||
|
} |
||||||
|
|
||||||
|
public Request<?, SignersBlockResponse> cliqueGetSignersAtHash(final Hash hash) { |
||||||
|
return new Request<>( |
||||||
|
"clique_getSignersAtHash", |
||||||
|
singletonList(hash.toString()), |
||||||
|
web3jService, |
||||||
|
SignersBlockResponse.class); |
||||||
|
} |
||||||
|
|
||||||
|
public static class ProposeResponse extends Response<Boolean> {} |
||||||
|
|
||||||
|
public static class DiscardResponse extends Response<Boolean> {} |
||||||
|
|
||||||
|
public static class SignersBlockResponse extends Response<List<Address>> {} |
||||||
|
|
||||||
|
public static class ProposalsResponse extends Response<Map<Address, Boolean>> {} |
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j.DiscardResponse; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class CliqueDiscard implements Transaction<Boolean> { |
||||||
|
private final String address; |
||||||
|
|
||||||
|
public CliqueDiscard(final String address) { |
||||||
|
this.address = address; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean execute(final PantheonWeb3j node) { |
||||||
|
try { |
||||||
|
final DiscardResponse result = node.cliqueDiscard(address).send(); |
||||||
|
assertThat(result).isNotNull(); |
||||||
|
assertThat(result.hasError()).isFalse(); |
||||||
|
return result.getResult(); |
||||||
|
} catch (final IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j.SignersBlockResponse; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class CliqueGetSigners implements Transaction<List<Address>> { |
||||||
|
private final String blockNumber; |
||||||
|
|
||||||
|
public CliqueGetSigners(final String blockNumber) { |
||||||
|
this.blockNumber = blockNumber; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Address> execute(final PantheonWeb3j node) { |
||||||
|
try { |
||||||
|
final SignersBlockResponse result = node.cliqueGetSigners(blockNumber).send(); |
||||||
|
assertThat(result).isNotNull(); |
||||||
|
assertThat(result.hasError()).isFalse(); |
||||||
|
return result.getResult(); |
||||||
|
} catch (final IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.ethereum.core.Hash; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j.SignersBlockResponse; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class CliqueGetSignersAtHash implements Transaction<List<Address>> { |
||||||
|
private final Hash hash; |
||||||
|
|
||||||
|
public CliqueGetSignersAtHash(final Hash hash) { |
||||||
|
this.hash = hash; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public List<Address> execute(final PantheonWeb3j node) { |
||||||
|
try { |
||||||
|
final SignersBlockResponse result = node.cliqueGetSignersAtHash(hash).send(); |
||||||
|
assertThat(result).isNotNull(); |
||||||
|
assertThat(result.hasError()).isFalse(); |
||||||
|
return result.getResult(); |
||||||
|
} catch (final IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j.ProposalsResponse; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
public class CliqueProposals implements Transaction<Map<Address, Boolean>> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Map<Address, Boolean> execute(final PantheonWeb3j node) { |
||||||
|
try { |
||||||
|
final ProposalsResponse result = node.cliqueProposals().send(); |
||||||
|
assertThat(result).isNotNull(); |
||||||
|
assertThat(result.hasError()).isFalse(); |
||||||
|
return result.getResult(); |
||||||
|
} catch (final IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j.ProposeResponse; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
public class CliquePropose implements Transaction<Boolean> { |
||||||
|
private final String address; |
||||||
|
private final boolean auth; |
||||||
|
|
||||||
|
public CliquePropose(final String address, final boolean auth) { |
||||||
|
this.address = address; |
||||||
|
this.auth = auth; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean execute(final PantheonWeb3j node) { |
||||||
|
try { |
||||||
|
final ProposeResponse result = node.cliquePropose(address, auth).send(); |
||||||
|
assertThat(result).isNotNull(); |
||||||
|
assertThat(result.hasError()).isFalse(); |
||||||
|
return result.getResult(); |
||||||
|
} catch (final IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Hash; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
|
||||||
|
public class CliqueTransactions { |
||||||
|
public static final String LATEST = "latest"; |
||||||
|
|
||||||
|
public CliquePropose createRemoveProposal(final PantheonNode node) { |
||||||
|
return propose(node.getAddress().toString(), false); |
||||||
|
} |
||||||
|
|
||||||
|
public CliquePropose createAddProposal(final PantheonNode node) { |
||||||
|
return propose(node.getAddress().toString(), true); |
||||||
|
} |
||||||
|
|
||||||
|
private CliquePropose propose(final String address, final boolean auth) { |
||||||
|
return new CliquePropose(address, auth); |
||||||
|
} |
||||||
|
|
||||||
|
public CliqueProposals createProposals() { |
||||||
|
return new CliqueProposals(); |
||||||
|
} |
||||||
|
|
||||||
|
public CliqueGetSigners createGetSigners(final String blockNumber) { |
||||||
|
return new CliqueGetSigners(blockNumber); |
||||||
|
} |
||||||
|
|
||||||
|
public CliqueGetSignersAtHash createGetSignersAtHash(final Hash blockHash) { |
||||||
|
return new CliqueGetSignersAtHash(blockHash); |
||||||
|
} |
||||||
|
|
||||||
|
public CliqueDiscard createDiscardProposal(final PantheonNode node) { |
||||||
|
return new CliqueDiscard(node.getAddress().toString()); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.PantheonWeb3j; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import org.web3j.protocol.core.DefaultBlockParameter; |
||||||
|
import org.web3j.protocol.core.methods.response.EthBlock; |
||||||
|
import org.web3j.protocol.core.methods.response.EthBlock.Block; |
||||||
|
|
||||||
|
public class EthGetBlockTransaction implements Transaction<Block> { |
||||||
|
private final DefaultBlockParameter blockParameter; |
||||||
|
private final boolean fullTransactionObjects; |
||||||
|
|
||||||
|
EthGetBlockTransaction( |
||||||
|
final DefaultBlockParameter blockParameter, final boolean fullTransactionObjects) { |
||||||
|
this.blockParameter = blockParameter; |
||||||
|
this.fullTransactionObjects = fullTransactionObjects; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Block execute(final PantheonWeb3j node) { |
||||||
|
try { |
||||||
|
final EthBlock result = |
||||||
|
node.ethGetBlockByNumber(blockParameter, fullTransactionObjects).send(); |
||||||
|
assertThat(result).isNotNull(); |
||||||
|
assertThat(result.hasError()).isFalse(); |
||||||
|
return result.getBlock(); |
||||||
|
} catch (final IOException e) { |
||||||
|
throw new RuntimeException(e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.waitcondition; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
|
||||||
|
@FunctionalInterface |
||||||
|
public interface WaitCondition { |
||||||
|
void waitUntil(Node node); |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.waitcondition; |
||||||
|
|
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.blockchain.ExpectBlockNumber; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; |
||||||
|
|
||||||
|
import java.math.BigInteger; |
||||||
|
|
||||||
|
public class WaitConditions { |
||||||
|
private final EthTransactions eth; |
||||||
|
private final CliqueTransactions clique; |
||||||
|
|
||||||
|
public WaitConditions(final EthTransactions eth, final CliqueTransactions clique) { |
||||||
|
this.eth = eth; |
||||||
|
this.clique = clique; |
||||||
|
} |
||||||
|
|
||||||
|
public WaitCondition chainHeadHasProgressed( |
||||||
|
final PantheonNode node, final int blocksAheadOfLatest) { |
||||||
|
final BigInteger futureBlock = |
||||||
|
node.execute(eth.blockNumber()).add(BigInteger.valueOf(blocksAheadOfLatest)); |
||||||
|
return new ExpectBlockNumber(eth, futureBlock)::verify; |
||||||
|
} |
||||||
|
|
||||||
|
public WaitCondition cliqueValidatorsChanged(final Node node) { |
||||||
|
return new WaitUntilSignersChanged(node.execute(clique.createGetSigners(LATEST)), clique); |
||||||
|
} |
||||||
|
|
||||||
|
public WaitCondition chainHeadIsAt(final long blockNumber) { |
||||||
|
return new ExpectBlockNumber(eth, BigInteger.valueOf(blockNumber))::verify; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 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. |
||||||
|
*/ |
||||||
|
package tech.pegasys.pantheon.tests.acceptance.dsl.waitcondition; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; |
||||||
|
import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions.LATEST; |
||||||
|
|
||||||
|
import tech.pegasys.pantheon.ethereum.core.Address; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; |
||||||
|
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class WaitUntilSignersChanged implements WaitCondition { |
||||||
|
private final CliqueTransactions clique; |
||||||
|
private final List<Address> initialSigners; |
||||||
|
|
||||||
|
public WaitUntilSignersChanged( |
||||||
|
final List<Address> initialSigners, final CliqueTransactions clique) { |
||||||
|
this.initialSigners = initialSigners; |
||||||
|
this.clique = clique; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void waitUntil(final Node node) { |
||||||
|
waitFor( |
||||||
|
60, |
||||||
|
() -> |
||||||
|
assertThat(node.execute(clique.createGetSigners(LATEST))).isNotEqualTo(initialSigners)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
{ |
||||||
|
"config": { |
||||||
|
"chainId": 4, |
||||||
|
"homesteadBlock": 1, |
||||||
|
"eip150Block": 2, |
||||||
|
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000", |
||||||
|
"eip155Block": 0, |
||||||
|
"eip158Block": 0, |
||||||
|
"byzantiumBlock": 0, |
||||||
|
"clique": { |
||||||
|
"period": 5, |
||||||
|
"epoch": 30000 |
||||||
|
} |
||||||
|
}, |
||||||
|
"nonce": "0x0", |
||||||
|
"timestamp": "0x58ee40ba", |
||||||
|
"extraData": "%cliqueExtraData%", |
||||||
|
"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" |
||||||
|
} |
Loading…
Reference in new issue