From ef8c4f028427e10c58ad6e20760a17f31f27109f Mon Sep 17 00:00:00 2001 From: CJ Hare Date: Wed, 17 Oct 2018 16:38:17 +1000 Subject: [PATCH] Restructuring the DSL (#78) * Restructuring the DSL --- .../CreateAccountAcceptanceTest.java | 6 +- .../acceptance/dsl/AcceptanceTestBase.java | 17 +++- .../tests/acceptance/dsl/account/Account.java | 11 +++ .../acceptance/dsl/account/Accounts.java | 88 ++----------------- .../acceptance/dsl/condition/Condition.java | 20 +++++ .../dsl/condition/ExpectAccountBalance.java | 44 ++++++++++ .../tests/acceptance/dsl/node/Cluster.java | 32 +------ .../tests/acceptance/dsl/node/Node.java | 25 ++++++ .../acceptance/dsl/node/PantheonNode.java | 40 +++------ .../dsl/transaction/Transaction.java | 20 +++++ .../dsl/transaction/Transactions.java | 50 +++++++++++ .../dsl/transaction/TransferTransaction.java | 65 ++++++++++++++ .../transaction/TransferTransactionSet.java | 40 +++++++++ .../mining/MiningAcceptanceTest.java | 28 +++--- .../NewPendingTransactionAcceptanceTest.java | 68 +++++++------- 15 files changed, 359 insertions(+), 195 deletions(-) create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/Condition.java create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/ExpectAccountBalance.java create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Node.java create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transaction.java create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transactions.java create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransaction.java create mode 100644 acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransactionSet.java diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/CreateAccountAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/CreateAccountAcceptanceTest.java index 23459ca5f6..0b109dec2c 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/CreateAccountAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/CreateAccountAcceptanceTest.java @@ -39,8 +39,8 @@ public class CreateAccountAcceptanceTest extends AcceptanceTestBase { @Test public void shouldCreateAnAccount() { - final Account account = accounts.createAccount("account1", "20", ETHER, fullNode); - accounts.waitForAccountBalance(account, "20", ETHER, minerNode); - accounts.waitForAccountBalance(account, "20", ETHER, fullNode); + final Account account = accounts.createAccount("a-new-account"); + minerNode.execute(transactions.createTransfer(account, 20)); + cluster.verify(account.balanceEquals("20", ETHER)); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/AcceptanceTestBase.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/AcceptanceTestBase.java index e27e72891c..8ebbb1aa70 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/AcceptanceTestBase.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/AcceptanceTestBase.java @@ -14,17 +14,26 @@ package tech.pegasys.pantheon.tests.acceptance.dsl; import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts; import tech.pegasys.pantheon.tests.acceptance.dsl.node.Cluster; +import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transactions; import org.junit.After; public class AcceptanceTestBase { - protected Cluster cluster = new Cluster(); - protected Accounts accounts = new Accounts(); - protected JsonRpc jsonRpc = new JsonRpc(cluster); + protected final Accounts accounts; + protected final Cluster cluster; + protected final Transactions transactions; + protected final JsonRpc jsonRpc; + + protected AcceptanceTestBase() { + accounts = new Accounts(); + cluster = new Cluster(); + transactions = new Transactions(accounts); + jsonRpc = new JsonRpc(cluster); + } @After - public void tearDownAcceptanceTestBase() throws Exception { + public void tearDownAcceptanceTestBase() { cluster.close(); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Account.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Account.java index 026d6844ff..0b3433f5ab 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Account.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Account.java @@ -16,11 +16,14 @@ import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.crypto.SECP256K1.PrivateKey; 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.condition.ExpectAccountBalance; import tech.pegasys.pantheon.util.bytes.Bytes32; import java.math.BigInteger; import org.web3j.crypto.Credentials; +import org.web3j.utils.Convert.Unit; public class Account { @@ -61,4 +64,12 @@ public class Account { public String getName() { return name; } + + public Condition balanceEquals(final String expectedBalance, final Unit balanceUnit) { + return new ExpectAccountBalance(this, expectedBalance, balanceUnit); + } + + public Condition balanceEquals(final int expectedBalance) { + return balanceEquals(String.valueOf(expectedBalance), Unit.ETHER); + } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Accounts.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Accounts.java index 407479d287..a002c02c64 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Accounts.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/account/Accounts.java @@ -12,25 +12,8 @@ */ package tech.pegasys.pantheon.tests.acceptance.dsl.account; -import static org.apache.logging.log4j.LogManager.getLogger; -import static org.assertj.core.api.Assertions.assertThat; -import static org.web3j.utils.Convert.Unit.ETHER; -import static org.web3j.utils.Convert.toWei; -import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; - -import tech.pegasys.pantheon.ethereum.core.Hash; -import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.logging.log4j.Logger; -import org.web3j.utils.Convert.Unit; - public class Accounts { - private static final Logger LOG = getLogger(); - private final Account richBenefactorOne; private final Account richBenefactorTwo; @@ -45,76 +28,15 @@ public class Accounts { "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3"); } - public Account createAccount( - final String accountName, - final String initialBalance, - final Unit initialBalanceUnit, - final PantheonNode createOnNode) { - final Account account = Account.create(accountName); - createOnNode.transferFunds(richBenefactorOne, account, initialBalance, initialBalanceUnit); + public Account getSecondaryBenefactor() { + return richBenefactorTwo; + } - return account; + public Account getPrimaryBenefactor() { + return richBenefactorOne; } public Account createAccount(final String accountName) { return Account.create(accountName); } - - public void waitForAccountBalance( - final Account account, - final String expectedBalance, - final Unit balanceUnit, - final PantheonNode node) { - LOG.info( - "Waiting for {} to have a balance of {} {} on node {}", - account.getName(), - expectedBalance, - balanceUnit, - node.getName()); - - waitFor( - () -> - assertThat(node.getAccountBalance(account)) - .isEqualTo(toWei(expectedBalance, balanceUnit).toBigIntegerExact())); - } - - public void waitForAccountBalance( - final Account account, final int etherAmount, final PantheonNode node) { - waitForAccountBalance(account, String.valueOf(etherAmount), ETHER, node); - } - - public Hash transfer(final Account recipient, final int amount, final PantheonNode node) { - return transfer(richBenefactorOne, recipient, amount, node); - } - - public Hash transfer( - final Account sender, final Account recipient, final int amount, final PantheonNode node) { - return node.transferFunds(sender, recipient, String.valueOf(amount), Unit.ETHER); - } - - /** - * Transfer funds in separate transactions (1 eth increments). This is a strategy to increase the - * total of transactions. - * - * @param fromAccount account sending the ether value - * @param toAccount account receiving the ether value - * @param etherAmount amount of ether to transfer - * @return a list with the hashes of each transaction - */ - public List incrementalTransfer( - final Account fromAccount, - final Account toAccount, - final int etherAmount, - final PantheonNode node) { - final List txHashes = new ArrayList<>(); - for (int i = 1; i <= etherAmount; i++) { - final Hash hash = node.transferFunds(fromAccount, toAccount, String.valueOf(1), Unit.ETHER); - txHashes.add(hash); - } - return txHashes; - } - - public Account getSecondaryBenefactor() { - return richBenefactorTwo; - } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/Condition.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/Condition.java new file mode 100644 index 0000000000..df5b4a49c6 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/Condition.java @@ -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.condition; + +import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; + +public interface Condition { + + void verify(Node node); +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/ExpectAccountBalance.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/ExpectAccountBalance.java new file mode 100644 index 0000000000..b92246df8e --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/ExpectAccountBalance.java @@ -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.condition; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.web3j.utils.Convert.toWei; +import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; + +import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; +import tech.pegasys.pantheon.tests.acceptance.dsl.node.Node; + +import org.web3j.utils.Convert.Unit; + +public class ExpectAccountBalance implements Condition { + + private final Account account; + private final String expectedBalance; + private final Unit balanceUnit; + + public ExpectAccountBalance( + final Account account, final String expectedBalance, final Unit balanceUnit) { + this.expectedBalance = expectedBalance; + this.balanceUnit = balanceUnit; + this.account = account; + } + + @Override + public void verify(final Node node) { + waitFor( + () -> + assertThat(node.getAccountBalance(account)) + .isEqualTo(toWei(expectedBalance, balanceUnit).toBigIntegerExact())); + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Cluster.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Cluster.java index e9ed5110fe..942ca1b081 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Cluster.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Cluster.java @@ -13,11 +13,9 @@ package tech.pegasys.pantheon.tests.acceptance.dsl.node; import static org.assertj.core.api.Assertions.assertThat; -import static org.web3j.utils.Convert.toWei; -import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor; import tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils; -import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; +import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; import java.io.IOException; import java.util.ArrayList; @@ -25,14 +23,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.web3j.utils.Convert.Unit; - public class Cluster implements AutoCloseable { - private static final Logger LOG = LogManager.getLogger(Cluster.class); - private final Map nodes = new HashMap<>(); private final PantheonNodeRunner pantheonNodeRunner = PantheonNodeRunner.instance(); @@ -90,25 +82,9 @@ public class Cluster implements AutoCloseable { } } - public void awaitPropagation(final Account account, final int expectedBalance) { - awaitPropagation(account, String.valueOf(expectedBalance), Unit.ETHER); - } - - public void awaitPropagation( - final Account account, final String expectedBalance, final Unit balanceUnit) { - - for (final PantheonNode node : nodes.values()) { - LOG.info( - "Waiting for {} to have a balance of {} {} on node {}", - account.getName(), - expectedBalance, - balanceUnit, - node.getName()); - - waitFor( - () -> - assertThat(node.getAccountBalance(account)) - .isEqualTo(toWei(expectedBalance, balanceUnit).toBigIntegerExact())); + public void verify(final Condition expected) { + for (final Node node : nodes.values()) { + expected.verify(node); } } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Node.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Node.java new file mode 100644 index 0000000000..bbccde6966 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/Node.java @@ -0,0 +1,25 @@ +/* + * 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 tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; +import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; + +import java.math.BigInteger; + +public interface Node { + + T execute(Transaction transaction); + + BigInteger getAccountBalance(Account account); +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java index 2859472343..8aa7a484ed 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java @@ -16,15 +16,14 @@ import static org.apache.logging.log4j.LogManager.getLogger; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import static org.web3j.protocol.core.DefaultBlockParameterName.LATEST; -import static org.web3j.utils.Numeric.toHexString; import tech.pegasys.pantheon.controller.KeyPairUtil; import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.blockcreation.MiningParameters; -import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration; import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration; import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; +import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction; import java.io.File; import java.io.FileInputStream; @@ -44,23 +43,17 @@ import com.google.common.io.MoreFiles; import com.google.common.io.RecursiveDeleteOption; import org.apache.logging.log4j.Logger; import org.java_websocket.exceptions.WebsocketNotConnectedException; -import org.web3j.crypto.RawTransaction; -import org.web3j.crypto.TransactionEncoder; import org.web3j.protocol.Web3j; import org.web3j.protocol.Web3jService; import org.web3j.protocol.core.methods.response.EthGetBalance; import org.web3j.protocol.http.HttpService; import org.web3j.protocol.websocket.WebSocketService; import org.web3j.utils.Async; -import org.web3j.utils.Convert; -import org.web3j.utils.Convert.Unit; -public class PantheonNode implements AutoCloseable { +public class PantheonNode implements Node, AutoCloseable { private static final String LOCALHOST = "127.0.0.1"; private static final Logger LOG = getLogger(); - private static final BigInteger MINIMUM_GAS_PRICE = BigInteger.valueOf(1000); - private static final BigInteger TRANSFER_GAS_COST = BigInteger.valueOf(21000); private final String name; private final Path homeDirectory; @@ -161,25 +154,7 @@ public class PantheonNode implements AutoCloseable { return web3j; } - public Hash transferFunds( - final Account from, final Account to, final String amount, final Unit unit) { - final RawTransaction transaction = - RawTransaction.createEtherTransaction( - from.getNextNonce(), - MINIMUM_GAS_PRICE, - TRANSFER_GAS_COST, - to.getAddress(), - Convert.toWei(amount, unit).toBigIntegerExact()); - final String signedTransactionData = - toHexString(TransactionEncoder.signMessage(transaction, from.web3jCredentials())); - try { - return Hash.fromHexString( - web3j().ethSendRawTransaction(signedTransactionData).send().getTransactionHash()); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - + @Override public BigInteger getAccountBalance(final Account account) { try { final EthGetBalance balanceResponse = @@ -310,7 +285,7 @@ public class PantheonNode implements AutoCloseable { this.bootnodes = bootnodes; } - public MiningParameters getMiningParameters() { + MiningParameters getMiningParameters() { return miningParameters; } @@ -324,7 +299,7 @@ public class PantheonNode implements AutoCloseable { .toString(); } - public void stop() { + void stop() { if (web3j != null) { web3j.shutdown(); web3j = null; @@ -359,4 +334,9 @@ public class PantheonNode implements AutoCloseable { return eth; } + + @Override + public T execute(final Transaction transaction) { + return transaction.execute(web3j()); + } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transaction.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transaction.java new file mode 100644 index 0000000000..e038d694da --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transaction.java @@ -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.transaction; + +import org.web3j.protocol.Web3j; + +public interface Transaction { + + T execute(final Web3j node); +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transactions.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transactions.java new file mode 100644 index 0000000000..af77ed219e --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/Transactions.java @@ -0,0 +1,50 @@ +/* + * 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 tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; +import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts; + +import java.util.ArrayList; +import java.util.List; + +import org.web3j.utils.Convert.Unit; + +public class Transactions { + + private final Accounts accounts; + + public Transactions(final Accounts accounts) { + this.accounts = accounts; + } + + public TransferTransaction createTransfer(final Account recipient, final int amount) { + return createTransfer(accounts.getPrimaryBenefactor(), recipient, amount); + } + + public TransferTransaction createTransfer( + final Account sender, final Account recipient, final int amount) { + return new TransferTransaction(sender, recipient, String.valueOf(amount), Unit.ETHER); + } + + public TransferTransactionSet createIncrementalTransfers( + final Account sender, final Account recipient, final int etherAmount) { + final List transfers = new ArrayList<>(); + + for (int i = 1; i <= etherAmount; i++) { + transfers.add(new TransferTransaction(sender, recipient, "1", Unit.ETHER)); + } + + return new TransferTransactionSet(transfers); + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransaction.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransaction.java new file mode 100644 index 0000000000..195ccfdc01 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransaction.java @@ -0,0 +1,65 @@ +/* + * 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 org.web3j.utils.Numeric.toHexString; + +import tech.pegasys.pantheon.ethereum.core.Hash; +import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; + +import java.io.IOException; +import java.math.BigInteger; + +import org.web3j.crypto.RawTransaction; +import org.web3j.crypto.TransactionEncoder; +import org.web3j.protocol.Web3j; +import org.web3j.utils.Convert; +import org.web3j.utils.Convert.Unit; + +public class TransferTransaction implements Transaction { + + private static final BigInteger MINIMUM_GAS_PRICE = BigInteger.valueOf(1000); + private static final BigInteger TRANSFER_GAS_COST = BigInteger.valueOf(21000); + + private final Account sender; + private final Account recipient; + private final String amount; + private final Unit unit; + + public TransferTransaction( + final Account sender, final Account recipient, final String amount, final Unit unit) { + this.sender = sender; + this.recipient = recipient; + this.amount = amount; + this.unit = unit; + } + + @Override + public Hash execute(final Web3j node) { + final RawTransaction transaction = + RawTransaction.createEtherTransaction( + sender.getNextNonce(), + MINIMUM_GAS_PRICE, + TRANSFER_GAS_COST, + recipient.getAddress(), + Convert.toWei(amount, unit).toBigIntegerExact()); + final String signedTransactionData = + toHexString(TransactionEncoder.signMessage(transaction, sender.web3jCredentials())); + try { + return Hash.fromHexString( + node.ethSendRawTransaction(signedTransactionData).send().getTransactionHash()); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransactionSet.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransactionSet.java new file mode 100644 index 0000000000..58ea93a917 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/TransferTransactionSet.java @@ -0,0 +1,40 @@ +/* + * 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 tech.pegasys.pantheon.ethereum.core.Hash; + +import java.util.ArrayList; +import java.util.List; + +import org.web3j.protocol.Web3j; + +public class TransferTransactionSet implements Transaction> { + + private final List transactions; + + public TransferTransactionSet(final List transactions) { + this.transactions = transactions; + } + + @Override + public List execute(final Web3j node) { + final List hashes = new ArrayList<>(); + + for (final TransferTransaction transaction : transactions) { + hashes.add(transaction.execute(node)); + } + + return hashes; + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/mining/MiningAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/mining/MiningAcceptanceTest.java index 0bc59bdaaf..53a229ca67 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/mining/MiningAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/mining/MiningAcceptanceTest.java @@ -12,7 +12,6 @@ */ package tech.pegasys.pantheon.tests.acceptance.mining; -import static org.web3j.utils.Convert.Unit.ETHER; import static tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNodeConfig.pantheonMinerNode; import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; @@ -36,23 +35,24 @@ public class MiningAcceptanceTest extends AcceptanceTestBase { @Test public void shouldMineTransactions() { - final Account fromAccount = accounts.createAccount("account1", "50", ETHER, minerNode); - final Account toAccount = accounts.createAccount("account2", "0", ETHER, minerNode); - accounts.waitForAccountBalance(fromAccount, 50, minerNode); + final Account sender = accounts.createAccount("account1"); + final Account receiver = accounts.createAccount("account2"); + minerNode.execute(transactions.createTransfer(sender, 50)); + cluster.verify(sender.balanceEquals(50)); - accounts.incrementalTransfer(fromAccount, toAccount, 1, minerNode); - accounts.waitForAccountBalance(toAccount, 1, minerNode); + minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 1)); + cluster.verify(receiver.balanceEquals(1)); - accounts.incrementalTransfer(fromAccount, toAccount, 2, minerNode); - accounts.waitForAccountBalance(toAccount, 3, minerNode); + minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 2)); + cluster.verify(receiver.balanceEquals(3)); - accounts.incrementalTransfer(fromAccount, toAccount, 3, minerNode); - accounts.waitForAccountBalance(toAccount, 6, minerNode); + minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 3)); + cluster.verify(receiver.balanceEquals(6)); - accounts.incrementalTransfer(fromAccount, toAccount, 4, minerNode); - accounts.waitForAccountBalance(toAccount, 10, minerNode); + minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 4)); + cluster.verify(receiver.balanceEquals(10)); - accounts.incrementalTransfer(fromAccount, toAccount, 5, minerNode); - accounts.waitForAccountBalance(toAccount, 15, minerNode); + minerNode.execute(transactions.createIncrementalTransfers(sender, receiver, 5)); + cluster.verify(receiver.balanceEquals(15)); } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java index 8d8c589fd3..d676d8f0f1 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/pubsub/NewPendingTransactionAcceptanceTest.java @@ -63,8 +63,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { // Create the light fork final Subscription lightForkSubscription = minerWebSocket.subscribe(); - final Hash lightForkEvent = accounts.transfer(accountOne, 5, minerNode); - cluster.awaitPropagation(accountOne, 5); + final Hash lightForkEvent = minerNode.execute(transactions.createTransfer(accountOne, 5)); + cluster.verify(accountOne.balanceEquals(5)); minerWebSocket.verifyTotalEventsReceived(1); lightForkSubscription.verifyEventReceived(lightForkEvent); @@ -86,14 +86,14 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { final Account heavyForkBenefactor = accounts.getSecondaryBenefactor(); final Hash heavyForkEventOne = - accounts.transfer(heavyForkBenefactor, accountTwo, 1, minerNodeTwo); - cluster.awaitPropagation(accountTwo, 1); + minerNodeTwo.execute(transactions.createTransfer(heavyForkBenefactor, accountTwo, 1)); + cluster.verify(accountTwo.balanceEquals(1)); final Hash heavyForkEventTwo = - accounts.transfer(heavyForkBenefactor, accountTwo, 2, minerNodeTwo); - cluster.awaitPropagation(accountTwo, 1 + 2); + minerNodeTwo.execute(transactions.createTransfer(heavyForkBenefactor, accountTwo, 2)); + cluster.verify(accountTwo.balanceEquals(1 + 2)); final Hash heavyForkEventThree = - accounts.transfer(heavyForkBenefactor, accountTwo, 3, minerNodeTwo); - cluster.awaitPropagation(accountTwo, 1 + 2 + 3); + minerNodeTwo.execute(transactions.createTransfer(heavyForkBenefactor, accountTwo, 3)); + cluster.verify(accountTwo.balanceEquals(1 + 2 + 3)); heavyForkWebSocket.verifyTotalEventsReceived(3); heavyForkSubscription.verifyEventReceived(heavyForkEventOne); @@ -121,8 +121,9 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { // This publish give time needed for heavy fork to be chosen final Hash mergedForksEventOne = - accounts.transfer(accounts.getSecondaryBenefactor(), accountTwo, 3, minerNodeTwo); - cluster.awaitPropagation(accountTwo, 9); + minerNodeTwo.execute( + transactions.createTransfer(accounts.getSecondaryBenefactor(), accountTwo, 3)); + cluster.verify(accountTwo.balanceEquals(9)); minerMergedForksWebSocket.verifyTotalEventsReceived(1); minerMergedForksSubscription.verifyEventReceived(lightForkEvent); @@ -134,13 +135,14 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { // Check that account two (funded in heavier chain) can be mined on miner one (from lighter // chain) - final Hash mergedForksEventTwo = accounts.transfer(accountTwo, 3, minerNode); - cluster.awaitPropagation(accountTwo, 9 + 3); + final Hash mergedForksEventTwo = minerNode.execute(transactions.createTransfer(accountTwo, 3)); + cluster.verify(accountTwo.balanceEquals(9 + 3)); // Check that account one (funded in lighter chain) can be mined on miner two (from heavier // chain) - final Hash mergedForksEventThree = accounts.transfer(accountOne, 2, minerNodeTwo); - cluster.awaitPropagation(accountOne, 5 + 2); + final Hash mergedForksEventThree = + minerNodeTwo.execute(transactions.createTransfer(accountOne, 2)); + cluster.verify(accountOne.balanceEquals(5 + 2)); minerMergedForksWebSocket.verifyTotalEventsReceived(1 + 1 + 1); minerMergedForksSubscription.verifyEventReceived(mergedForksEventTwo); @@ -157,8 +159,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { public void subscriptionToMinerNodeMustReceivePublishEvent() { final Subscription minerSubscription = minerWebSocket.subscribe(); - final Hash event = accounts.transfer(accountOne, 4, minerNode); - cluster.awaitPropagation(accountOne, 4); + final Hash event = minerNode.execute(transactions.createTransfer(accountOne, 4)); + cluster.verify(accountOne.balanceEquals(4)); minerWebSocket.verifyTotalEventsReceived(1); minerSubscription.verifyEventReceived(event); @@ -170,8 +172,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { public void subscriptionToArchiveNodeMustReceivePublishEvent() { final Subscription archiveSubscription = archiveWebSocket.subscribe(); - final Hash event = accounts.transfer(accountOne, 23, minerNode); - cluster.awaitPropagation(accountOne, 23); + final Hash event = minerNode.execute(transactions.createTransfer(accountOne, 23)); + cluster.verify(accountOne.balanceEquals(23)); archiveWebSocket.verifyTotalEventsReceived(1); archiveSubscription.verifyEventReceived(event); @@ -187,8 +189,8 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { final Subscription archiveSubscriptionTwo = archiveWebSocket.subscribe(); final Subscription archiveSubscriptionThree = archiveWebSocket.subscribe(); - final Hash event = accounts.transfer(accountOne, 30, minerNode); - cluster.awaitPropagation(accountOne, 30); + final Hash event = minerNode.execute(transactions.createTransfer(accountOne, 30)); + cluster.verify(accountOne.balanceEquals(30)); minerWebSocket.verifyTotalEventsReceived(2); minerSubscriptionOne.verifyEventReceived(event); @@ -210,15 +212,15 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { public void subscriptionToMinerNodeMustReceiveEveryPublishEvent() { final Subscription minerSubscription = minerWebSocket.subscribe(); - final Hash eventOne = accounts.transfer(accountOne, 1, minerNode); - cluster.awaitPropagation(accountOne, 1); + final Hash eventOne = minerNode.execute(transactions.createTransfer(accountOne, 1)); + cluster.verify(accountOne.balanceEquals(1)); minerWebSocket.verifyTotalEventsReceived(1); minerSubscription.verifyEventReceived(eventOne); - final Hash eventTwo = accounts.transfer(accountOne, 4, minerNode); - final Hash eventThree = accounts.transfer(accountOne, 5, minerNode); - cluster.awaitPropagation(accountOne, 1 + 4 + 5); + final Hash eventTwo = minerNode.execute(transactions.createTransfer(accountOne, 4)); + final Hash eventThree = minerNode.execute(transactions.createTransfer(accountOne, 5)); + cluster.verify(accountOne.balanceEquals(1 + 4 + 5)); minerWebSocket.verifyTotalEventsReceived(3); minerSubscription.verifyEventReceived(eventTwo); @@ -231,16 +233,16 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { public void subscriptionToArchiveNodeMustReceiveEveryPublishEvent() { final Subscription archiveSubscription = archiveWebSocket.subscribe(); - final Hash eventOne = accounts.transfer(accountOne, 2, minerNode); - final Hash eventTwo = accounts.transfer(accountOne, 5, minerNode); - cluster.awaitPropagation(accountOne, 2 + 5); + final Hash eventOne = minerNode.execute(transactions.createTransfer(accountOne, 2)); + final Hash eventTwo = minerNode.execute(transactions.createTransfer(accountOne, 5)); + cluster.verify(accountOne.balanceEquals(2 + 5)); archiveWebSocket.verifyTotalEventsReceived(2); archiveSubscription.verifyEventReceived(eventOne); archiveSubscription.verifyEventReceived(eventTwo); - final Hash eventThree = accounts.transfer(accountOne, 8, minerNode); - cluster.awaitPropagation(accountOne, 2 + 5 + 8); + final Hash eventThree = minerNode.execute(transactions.createTransfer(accountOne, 8)); + cluster.verify(accountOne.balanceEquals(2 + 5 + 8)); archiveWebSocket.verifyTotalEventsReceived(3); archiveSubscription.verifyEventReceived(eventThree); @@ -256,9 +258,9 @@ public class NewPendingTransactionAcceptanceTest extends AcceptanceTestBase { final Subscription archiveSubscriptionTwo = archiveWebSocket.subscribe(); final Subscription archiveSubscriptionThree = archiveWebSocket.subscribe(); - final Hash eventOne = accounts.transfer(accountOne, 10, minerNode); - final Hash eventTwo = accounts.transfer(accountOne, 5, minerNode); - cluster.awaitPropagation(accountOne, 10 + 5); + final Hash eventOne = minerNode.execute(transactions.createTransfer(accountOne, 10)); + final Hash eventTwo = minerNode.execute(transactions.createTransfer(accountOne, 5)); + cluster.verify(accountOne.balanceEquals(10 + 5)); minerWebSocket.verifyTotalEventsReceived(4); minerSubscriptionOne.verifyEventReceived(eventOne);