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 9e04a99339..481f980974 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,6 +14,7 @@ package tech.pegasys.pantheon.tests.acceptance.dsl; import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts; import tech.pegasys.pantheon.tests.acceptance.dsl.blockchain.Blockchain; +import tech.pegasys.pantheon.tests.acceptance.dsl.contract.ContractVerifier; import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Eth; import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Net; import tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc.Web3; @@ -36,6 +37,7 @@ public class AcceptanceTestBase { protected final Eth eth; protected final Net net; protected final PantheonNodeFactory pantheon; + protected final ContractVerifier contractVerifier; protected AcceptanceTestBase() { final EthTransactions ethTransactions = new EthTransactions(); @@ -47,6 +49,7 @@ public class AcceptanceTestBase { transactions = new Transactions(accounts); web3 = new Web3(new Web3Transactions()); pantheon = new PantheonNodeFactory(); + contractVerifier = new ContractVerifier(accounts.getPrimaryBenefactor()); } @After 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 ef39d9b0e8..1a98b59b09 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 @@ -16,6 +16,9 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransaction public class Accounts { + public static final String GENESIS_ACCOUNT_ONE_PRIVATE_KEY = + "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"; + private final EthTransactions eth; private final Account richBenefactorOne; private final Account richBenefactorTwo; @@ -23,10 +26,7 @@ public class Accounts { public Accounts(final EthTransactions eth) { this.eth = eth; richBenefactorOne = - Account.fromPrivateKey( - eth, - "Rich Benefactor One", - "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"); + Account.fromPrivateKey(eth, "Rich Benefactor One", GENESIS_ACCOUNT_ONE_PRIVATE_KEY); richBenefactorTwo = Account.fromPrivateKey( eth, diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eth/EthGetTransactionReceiptEquals.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eth/EthGetTransactionReceiptEquals.java deleted file mode 100644 index ca1887a890..0000000000 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eth/EthGetTransactionReceiptEquals.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * 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.eth; - -import static org.assertj.core.api.Assertions.assertThat; - -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.EthGetTransactionReceiptTransaction; - -import java.util.Optional; - -import org.web3j.protocol.core.methods.response.TransactionReceipt; - -public class EthGetTransactionReceiptEquals implements Condition { - - private final EthGetTransactionReceiptTransaction transaction; - private final TransactionReceipt expectedReceipt; - - public EthGetTransactionReceiptEquals( - final EthGetTransactionReceiptTransaction transaction, - final TransactionReceipt expectedReceipt) { - this.transaction = transaction; - this.expectedReceipt = expectedReceipt; - } - - @Override - public void verify(final Node node) { - final Optional response = node.execute(transaction); - - assertThat(response.isPresent()).isTrue(); - assertThat(response.get()).isEqualTo(expectedReceipt); - } -} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/contract/ContractVerifier.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/contract/ContractVerifier.java new file mode 100644 index 0000000000..4b6b20845f --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/contract/ContractVerifier.java @@ -0,0 +1,28 @@ +/* + * 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.contract; + +import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; + +public class ContractVerifier { + + private final Account sender; + + public ContractVerifier(final Account sender) { + this.sender = sender; + } + + public ExpectValidTransactionReceipt validTransactionReceipt(final String contractAddress) { + return new ExpectValidTransactionReceipt(sender, contractAddress); + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/contract/ExpectValidTransactionReceipt.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/contract/ExpectValidTransactionReceipt.java new file mode 100644 index 0000000000..e6dc1ad7b5 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/contract/ExpectValidTransactionReceipt.java @@ -0,0 +1,74 @@ +/* + * 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.contract; + +import static org.assertj.core.api.Assertions.assertThat; + +import tech.pegasys.pantheon.tests.acceptance.dsl.account.Account; + +import java.math.BigInteger; +import java.util.Optional; + +import org.web3j.protocol.core.methods.response.TransactionReceipt; +import org.web3j.tx.Contract; + +public class ExpectValidTransactionReceipt { + + private final String senderAddress; + private final String contractAddress; + + public ExpectValidTransactionReceipt(final Account sender, final String contractAddress) { + this.contractAddress = contractAddress; + this.senderAddress = sender.getAddress(); + } + + public void verify(final Contract contract) { + + assertThat(contract).isNotNull(); + final Optional receipt = contract.getTransactionReceipt(); + + // We're expecting a receipt + assertThat(receipt).isNotNull(); + assertThat(receipt.isPresent()).isTrue(); + final TransactionReceipt transactionReceipt = receipt.get(); + + // Contract transaction has no 'to' address or contract address + assertThat(transactionReceipt.getTo()).isNull(); + assertThat(transactionReceipt.getRoot()).isNull(); + + // Variables outside the control of the test :. just check existence + assertThat(transactionReceipt.getBlockHash()).isNotBlank(); + assertThat(transactionReceipt.getTransactionHash()).isNotBlank(); + assertThat(transactionReceipt.getTransactionIndex()).isNotNull(); + assertThat(transactionReceipt.getTransactionHash()).isNotNull(); + + // Block zero is the genesis, expecting anytime after then + assertThat(transactionReceipt.getBlockNumber()).isGreaterThanOrEqualTo(BigInteger.ONE); + + // Address generation is deterministic, based on the sender address and the transaction nonce + assertThat(transactionReceipt.getContractAddress()).isEqualTo(contractAddress); + + // Expecting successful transaction (status '0x1') + assertThat(transactionReceipt.getStatus()).isEqualTo("0x1"); + + // Address for the account that signed (and paid) for the contract deployment transaction + assertThat(transactionReceipt.getFrom()).isEqualTo(senderAddress); + + // No logs from expected from the contract deployment + assertThat(transactionReceipt.getLogs()).isNotNull(); + assertThat(transactionReceipt.getLogs().size()).isEqualTo(0); + assertThat(transactionReceipt.getLogsBloom()) + .isEqualTo( + "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + } +} diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/jsonrpc/Eth.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/jsonrpc/Eth.java index cb94afe732..10ee67b239 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/jsonrpc/Eth.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/jsonrpc/Eth.java @@ -14,7 +14,6 @@ package tech.pegasys.pantheon.tests.acceptance.dsl.jsonrpc; import tech.pegasys.pantheon.ethereum.core.Hash; import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition; -import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth.EthGetTransactionReceiptEquals; import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth.ExpectEthAccountsException; import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth.ExpectEthGetTransactionReceiptIsAbsent; import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth.ExpectEthGetWorkException; @@ -22,8 +21,6 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth.ExpectSuccessful import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eth.SanityCheckEthGetWorkValues; import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eth.EthTransactions; -import org.web3j.protocol.core.methods.response.TransactionReceipt; - public class Eth { private final EthTransactions transactions; @@ -53,10 +50,4 @@ public class Eth { return new ExpectEthGetTransactionReceiptIsAbsent( transactions.getTransactionReceipt(transactionHash)); } - - public Condition expectTransactionReceipt( - final String transactionHash, final TransactionReceipt receipt) { - return new EthGetTransactionReceiptEquals( - transactions.getTransactionReceipt(transactionHash), receipt); - } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/DeploySmartContractTransaction.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/DeploySmartContractTransaction.java index 665e527112..64ba7ee4dc 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/DeploySmartContractTransaction.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/DeploySmartContractTransaction.java @@ -12,6 +12,8 @@ */ package tech.pegasys.pantheon.tests.acceptance.dsl.transaction; +import tech.pegasys.pantheon.tests.acceptance.dsl.account.Accounts; + import java.lang.reflect.Method; import java.math.BigInteger; @@ -24,9 +26,9 @@ public class DeploySmartContractTransaction implements Trans private static final BigInteger DEFAULT_GAS_PRICE = BigInteger.valueOf(1000); private static final BigInteger DEFAULT_GAS_LIMIT = BigInteger.valueOf(3000000); - private static final Credentials GENESIS_ACCOUNT_ONE_PRIVATE_KEY = - Credentials.create("0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"); private static final Object METHOD_IS_STATIC = null; + private static final Credentials BENEFACTOR_ONE = + Credentials.create(Accounts.GENESIS_ACCOUNT_ONE_PRIVATE_KEY); private final Class clazz; @@ -43,11 +45,7 @@ public class DeploySmartContractTransaction implements Trans final Object invoked = method.invoke( - METHOD_IS_STATIC, - node, - GENESIS_ACCOUNT_ONE_PRIVATE_KEY, - DEFAULT_GAS_PRICE, - DEFAULT_GAS_LIMIT); + METHOD_IS_STATIC, node, BENEFACTOR_ONE, DEFAULT_GAS_PRICE, DEFAULT_GAS_LIMIT); return cast(invoked).send(); } catch (final Exception e) { diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/DeploySmartContractAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/DeploySmartContractAcceptanceTest.java index cc24583cbf..0d5b65ce16 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/DeploySmartContractAcceptanceTest.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/DeploySmartContractAcceptanceTest.java @@ -12,17 +12,12 @@ */ package tech.pegasys.pantheon.tests.web3j; -import static org.assertj.core.api.Assertions.assertThat; - import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase; import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode; import tech.pegasys.pantheon.tests.web3j.generated.SimpleStorage; -import java.util.Optional; - import org.junit.Before; import org.junit.Test; -import org.web3j.protocol.core.methods.response.TransactionReceipt; public class DeploySmartContractAcceptanceTest extends AcceptanceTestBase { @@ -35,23 +30,13 @@ public class DeploySmartContractAcceptanceTest extends AcceptanceTestBase { } @Test - public void deployContractReceiptMustMatchEthGetTransactionReceipt() { - final SimpleStorage contract = - minerNode.execute(transactions.createSmartContract(SimpleStorage.class)); - assertThat(contract).isNotNull(); + public void deployingMustGiveValidReceipt() { + // Contract address is generated from sender address and transaction nonce + final String contractAddress = "0x42699a7612a82f1d9c36148af9c77354759b210b"; - final Optional receipt = contract.getTransactionReceipt(); - assertThat(receipt).isNotNull(); - assertThat(receipt.isPresent()).isTrue(); - - final TransactionReceipt transactionReceipt = receipt.get(); - assertThat(transactionReceipt.getTransactionHash()).isNotNull(); - - // Contract transaction has no 'to' address or contract address - assertThat(transactionReceipt.getTo()).isNull(); - assertThat(transactionReceipt.getContractAddress()).isNotBlank(); + final SimpleStorage simpleStorageContract = + minerNode.execute(transactions.createSmartContract(SimpleStorage.class)); - minerNode.verify( - eth.expectTransactionReceipt(transactionReceipt.getTransactionHash(), transactionReceipt)); + contractVerifier.validTransactionReceipt(contractAddress).verify(simpleStorageContract); } }