Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Ibft Json Acceptance tests #634

Merged
merged 16 commits into from
Jan 29, 2019
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft.IbftTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.NetTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.web3.Web3Transactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.waitcondition.WaitConditions;
Expand All @@ -38,6 +39,7 @@ public class AcceptanceTestBase {
protected final Blockchain blockchain;
protected final Cluster cluster;
protected final CliqueTransactions cliqueTransactions;
protected final IbftTransactions ibftTransactions;
protected final Transactions transactions;
protected final Clique clique;
protected final Ibft ibft;
Expand All @@ -55,16 +57,18 @@ protected AcceptanceTestBase() {
blockchain = new Blockchain(ethTransactions);
eth = new Eth(ethTransactions);
cliqueTransactions = new CliqueTransactions();
ibftTransactions = new IbftTransactions();

clique = new Clique(ethTransactions, cliqueTransactions);
ibft = new Ibft();
ibft = new Ibft(ethTransactions, ibftTransactions);
net = new Net(new NetTransactions());
cluster = new Cluster(net);
transactions = new Transactions(accounts);
perm = new Perm(transactions);
web3 = new Web3(new Web3Transactions());
pantheon = new PantheonNodeFactory();
contractVerifier = new ContractVerifier(accounts.getPrimaryBenefactor());
wait = new WaitConditions(ethTransactions, cliqueTransactions);
wait = new WaitConditions(ethTransactions, cliqueTransactions, ibftTransactions);
}

@After
Expand Down
Original file line number Diff line number Diff line change
@@ -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.ibft;

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.ibft.IbftTransactions;

import java.util.Map;

public class ExpectProposals implements Condition {
private final IbftTransactions ibft;
private final Map<Address, Boolean> proposers;

public ExpectProposals(final IbftTransactions ibft, final Map<Address, Boolean> proposers) {
this.ibft = ibft;
this.proposers = proposers;
}

@Override
public void verify(final Node node) {
waitFor(() -> assertThat(node.execute(ibft.createProposals())).isEqualTo(proposers));
}
}
Original file line number Diff line number Diff line change
@@ -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.ibft;

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;
Copy link
Contributor

Choose a reason for hiding this comment

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

we shouldn't be depending on this constant Clique even though it will work. This seems very generic LATEST could probably move somewhere more common.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true.


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.ibft.IbftTransactions;

public class ExpectValidators implements Condition {
private final IbftTransactions ibft;
private final Address[] validators;

public ExpectValidators(final IbftTransactions ibft, final Address... validators) {
this.ibft = ibft;
this.validators = validators;
}

@Override
public void verify(final Node node) {
waitFor(
() ->
assertThat(node.execute(ibft.createGetValidators(LATEST))).containsExactly(validators));
}
}
Original file line number Diff line number Diff line change
@@ -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.ibft;

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.ibft.IbftTransactions;

public class ExpectValidatorsAtBlock implements Condition {
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't look like this is being used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

private final IbftTransactions ibft;
private final String blockParameter;
private final Address[] validators;

public ExpectValidatorsAtBlock(
final IbftTransactions ibft, final String blockNumber, final Address... validators) {
this.ibft = ibft;
this.blockParameter = blockNumber;
this.validators = validators;
}

@Override
public void verify(final Node node) {
waitFor(
() ->
assertThat(node.execute(ibft.createGetValidators(blockParameter)))
.containsExactly(validators));
}
}
Original file line number Diff line number Diff line change
@@ -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.ibft;

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.ibft.IbftTransactions;

public class ExpectValidatorsAtBlockHash implements Condition {
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't look like this is being used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed.

private final IbftTransactions ibft;
private final Hash blockHash;
private final Address[] validators;

public ExpectValidatorsAtBlockHash(
final IbftTransactions ibft, final Hash blockHash, final Address... validators) {
this.ibft = ibft;
this.blockHash = blockHash;
this.validators = validators;
}

@Override
public void verify(final Node node) {
waitFor(
() ->
assertThat(node.execute(ibft.createGetValidatorsAtHash(blockHash)))
.containsExactly(validators));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,84 @@
*/
package tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc;

import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.ibft.ExpectProposals;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.ibft.ExpectValidators;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft.IbftTransactions;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableMap;

public class Ibft {

private final EthTransactions eth;
private final IbftTransactions ibft;

public Ibft(final EthTransactions eth, final IbftTransactions ibft) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't look like EthTransactions is used

this.eth = eth;
this.ibft = ibft;
}

public List<PantheonNode> validators(final PantheonNode[] nodes) {
final Comparator<PantheonNode> compareByAddress =
Comparator.comparing(PantheonNode::getAddress);
List<PantheonNode> pantheonNodes = Arrays.asList(nodes);
pantheonNodes.sort(compareByAddress);
return pantheonNodes;
}

public ExpectValidators validatorsEqual(final PantheonNode... validators) {
return new ExpectValidators(ibft, validatorAddresses(validators));
}

private Address[] validatorAddresses(final PantheonNode[] validators) {
return Arrays.stream(validators).map(PantheonNode::getAddress).sorted().toArray(Address[]::new);
}

public Condition noProposals() {
return new ExpectProposals(ibft, ImmutableMap.of());
}

public ProposalsConfig proposalsEqual() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Ibft is using pending votes instead of proposals for this concept, so I think it would be clearer in the ibft tests if we used the term pending votes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done.

return new ProposalsConfig(ibft);
}

public static class ProposalsConfig {
private final Map<PantheonNode, Boolean> proposals = new HashMap<>();
private final IbftTransactions ibft;

public ProposalsConfig(final IbftTransactions ibft) {
this.ibft = ibft;
}

public Ibft.ProposalsConfig addProposal(final PantheonNode node) {
proposals.put(node, true);
return this;
}

public Ibft.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 tech.pegasys.pantheon.tests.acceptance.dsl.condition.ibft.ExpectProposals(
ibft, proposalsAsAddress);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,40 @@ public Request<?, SignersBlockResponse> cliqueGetSignersAtHash(final Hash hash)
SignersBlockResponse.class);
}

CjHare marked this conversation as resolved.
Show resolved Hide resolved
public Request<?, ProposeResponse> ibftPropose(final String address, final Boolean auth) {
return new Request<>(
"ibft_proposeValidatorVote",
Arrays.asList(address, auth.toString()),
web3jService,
ProposeResponse.class);
}

public Request<?, DiscardResponse> ibftDiscard(final String address) {
return new Request<>(
"ibft_discardValidatorVote", singletonList(address), web3jService, DiscardResponse.class);
}

public Request<?, ProposalsResponse> ibftProposals() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't really match up with the rpc method name. Original intent for the clique rpcs was that these method names corresponded to the underlying rpc method.

return new Request<>(
"ibft_getPendingVotes", emptyList(), web3jService, ProposalsResponse.class);
}

public Request<?, SignersBlockResponse> ibftGetValidators(final String blockNumber) {
return new Request<>(
"ibft_getValidatorsByBlockNumber",
singletonList(blockNumber),
web3jService,
SignersBlockResponse.class);
}

public Request<?, SignersBlockResponse> ibftGetSignersAtHash(final Hash hash) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Doesn't look this is being used. But we I think we should have a test to verify this rpc is working.

return new Request<>(
"ibft_getValidatorsByBlockHash",
singletonList(hash.toString()),
web3jService,
SignersBlockResponse.class);
}

public static class ProposeResponse extends Response<Boolean> {}

public static class DiscardResponse extends Response<Boolean> {}
Expand Down
Original file line number Diff line number Diff line change
@@ -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.ibft;

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 IbftDiscard implements Transaction<Boolean> {
private final String address;

public IbftDiscard(final String address) {
this.address = address;
}

@Override
public Boolean execute(final PantheonWeb3j node) {
try {
final DiscardResponse result = node.ibftDiscard(address).send();
assertThat(result).isNotNull();
assertThat(result.hasError()).isFalse();
return result.getResult();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}
Loading