[PAN-2941] Refactor privacy acceptance tests (#1864)

* update web3j 4.5.0 + use pantheon module in favour of core
* remove custom eea/privacy rpc calls -> use web3j instead
* overhaul the conditions -> web3j does the polling for receipts for us
* re-define a PrivacyNode - it is an object that holds a PantheonNode and an OrionTestHarness
* do not start OrionTestHarness prematurely - calling PrivacyNode.start() will start an Orion node followed by it's accompanying Pantheon node
* stop and close resources properly -> clean-up removes the created temporary directories correctly

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Ivaylo Kirilov 5 years ago committed by Trent Mohay
parent 402937a459
commit c691f488e2
  1. 2
      acceptance-tests/build.gradle
  2. 30
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/EeaConditions.java
  3. 35
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectNoPrivateContractDeployedReceipt.java
  4. 37
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectNoValidPrivateContractEventsEmitted.java
  5. 37
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectNoValidPrivateContractValuesReturned.java
  6. 40
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectSuccessfulEeaGetTransactionReceipt.java
  7. 40
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectValidPrivateContractDeployedReceipt.java
  8. 44
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectValidPrivateContractEventsEmitted.java
  9. 44
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectValidPrivateContractValuesReturned.java
  10. 36
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/ExpectValidPrivateTransactionReceipt.java
  11. 37
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/condition/eea/GetValidPrivateTransactionReceipt.java
  12. 2
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/ethsigner/EthSignerClientTest.java
  13. 15
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java
  14. 12
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/PantheonNodeConfiguration.java
  15. 57
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/PantheonNodeConfigurationBuilder.java
  16. 45
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/PantheonNodeFactory.java
  17. 7
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/genesis/GenesisConfigurationFactory.java
  18. 4
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/permissioning/PermissionedNodeBuilder.java
  19. 36
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeConfiguration.java
  20. 81
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java
  21. 78
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/privacy/PrivacyPantheonFactoryConfiguration.java
  22. 55
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/privacy/PrivacyPantheonFactoryConfigurationBuilder.java
  23. 115
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/configuration/privacy/PrivacyPantheonNodeFactory.java
  24. 46
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivacyAcceptanceTestBase.java
  25. 141
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivacyCluster.java
  26. 278
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivacyNet.java
  27. 227
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivacyNode.java
  28. 63
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivateTransactionVerifier.java
  29. 67
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivateTransactions.java
  30. 51
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/account/PrivacyAccount.java
  31. 56
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/account/PrivacyAccountResolver.java
  32. 27
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/EeaGetTransactionReceiptTransaction.java
  33. 34
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/ExpectNoPrivateTransactionReceipt.java
  34. 49
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/ExpectValidPrivacyGroupCreated.java
  35. 53
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/ExpectValidPrivateContractDeployedReceipt.java
  36. 42
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/ExpectValidPrivateTransactionReceipt.java
  37. 8
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/PrivateCondition.java
  38. 19
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/PrivateContractCondition.java
  39. 23
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/PrivateContractVerifier.java
  40. 41
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/condition/PrivateTransactionVerifier.java
  41. 77
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java
  42. 90
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractTransaction.java
  43. 90
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/contract/DeployPrivateSmartContractWithPrivacyGroupIdTransaction.java
  44. 91
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/contract/LoadPrivateSmartContractTransaction.java
  45. 107
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java
  46. 35
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/transaction/CreatePrivacyGroupTransaction.java
  47. 25
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/transaction/FindPrivacyGroupTransaction.java
  48. 57
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java
  49. 23
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java
  50. 20
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/NodeRequests.java
  51. 101
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/EeaRequestFactory.java
  52. 42
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/EeaSendRawTransactionTransaction.java
  53. 149
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/PrivateTransactionBuilder.java
  54. 44
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/priv/PrivCreatePrivacyGroupTransactionWithoutDescription.java
  55. 44
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/priv/PrivCreatePrivacyGroupTransactionWithoutName.java
  56. 43
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/priv/PrivCreatePrivacyGroupWithoutOptionalParamsTransaction.java
  57. 47
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/priv/PrivGetTransactionCountTransaction.java
  58. 96
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/priv/PrivRequestFactory.java
  59. 28
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java
  60. 39
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/generated/EventEmitter.java
  61. 55
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/DeployPrivateSmartContractAcceptanceTest.java
  62. 104
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EnclaveErrorAcceptanceTest.java
  63. 43
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EthSignerAcceptanceTest.java
  64. 305
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EventEmitterHarness.java
  65. 260
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/Ibft2PrivacyClusterAcceptanceTest.java
  66. 262
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyClusterAcceptanceTest.java
  67. 53
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyGroup.java
  68. 233
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyGroupAcceptanceTest.java
  69. 38
      acceptance-tests/src/test/resources/ibft/privacy-ibft.json
  70. 20
      enclave/src/integration-test/java/tech/pegasys/pantheon/enclave/EnclaveTest.java
  71. 6
      ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java
  72. 33
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/MainnetProtocolSpecs.java
  73. 16
      ethereum/jsonrpc/src/integration-test/java/tech/pegasys/pantheon/ethereum/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java
  74. 3
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroupTest.java
  75. 14
      gradle/versions.gradle
  76. 57
      testutil/src/main/java/tech/pegasys/orion/testutil/OrionConfiguration.java
  77. 31
      testutil/src/main/java/tech/pegasys/orion/testutil/OrionKeyConfiguration.java
  78. 117
      testutil/src/main/java/tech/pegasys/orion/testutil/OrionTestHarness.java
  79. 131
      testutil/src/main/java/tech/pegasys/orion/testutil/OrionTestHarnessFactory.java

@ -50,7 +50,7 @@ dependencies {
testImplementation 'org.awaitility:awaitility'
testImplementation 'org.java-websocket:Java-WebSocket'
testImplementation 'org.web3j:abi'
testImplementation 'org.web3j:eea'
testImplementation 'org.web3j:pantheon'
testImplementation 'org.web3j:crypto'
testImplementation 'tech.pegasys.ethsigner.internal:core'
testImplementation 'tech.pegasys.ethsigner.internal:file-based'

@ -1,30 +0,0 @@
/*
* Copyright 2019 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.eea;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class EeaConditions {
private final EeaTransactions transactions;
public EeaConditions(final EeaTransactions transactions) {
this.transactions = transactions;
}
public Condition expectSuccessfulTransactionReceipt(final String transactionHash) {
return new ExpectSuccessfulEeaGetTransactionReceipt(
transactions.getTransactionReceipt(transactionHash));
}
}

@ -1,35 +0,0 @@
/*
* Copyright 2019 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.eea;
import static org.junit.Assert.assertNull;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class ExpectNoPrivateContractDeployedReceipt extends GetValidPrivateTransactionReceipt {
public ExpectNoPrivateContractDeployedReceipt(
final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
final PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
assertNull(privateTxReceipt.getContractAddress());
}
}

@ -1,37 +0,0 @@
/*
* Copyright 2019 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.eea;
import static junit.framework.TestCase.assertTrue;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class ExpectNoValidPrivateContractEventsEmitted extends GetValidPrivateTransactionReceipt {
public ExpectNoValidPrivateContractEventsEmitted(
final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
final PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
if (privateTxReceipt.getLogs() != null) {
assertTrue(privateTxReceipt.getLogs().isEmpty());
}
}
}

@ -1,37 +0,0 @@
/*
* Copyright 2019 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.eea;
import static org.junit.Assert.assertEquals;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class ExpectNoValidPrivateContractValuesReturned extends GetValidPrivateTransactionReceipt {
public ExpectNoValidPrivateContractValuesReturned(
final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
final PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
if (privateTxReceipt.getOutput() != null) {
assertEquals("0x", privateTxReceipt.getOutput());
}
}
}

@ -1,40 +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.eea;
import static org.assertj.core.api.Assertions.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.eea.EeaGetTransactionReceiptTransaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
public class ExpectSuccessfulEeaGetTransactionReceipt implements Condition {
private final EeaGetTransactionReceiptTransaction transaction;
public ExpectSuccessfulEeaGetTransactionReceipt(
final EeaGetTransactionReceiptTransaction transaction) {
this.transaction = transaction;
}
@Override
public void verify(final Node node) {
waitFor(
() -> {
final PrivateTransactionReceipt response = node.execute(transaction);
assertThat(response.getContractAddress()).isNotEqualTo("0x");
});
}
}

@ -1,40 +0,0 @@
/*
* Copyright 2019 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.eea;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class ExpectValidPrivateContractDeployedReceipt extends GetValidPrivateTransactionReceipt {
private final String contractAddress;
public ExpectValidPrivateContractDeployedReceipt(
final String contractAddress, final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
this.contractAddress = contractAddress;
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
final PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
assertEquals(contractAddress, privateTxReceipt.getContractAddress());
assertNotEquals("0x", privateTxReceipt.getOutput());
}
}

@ -1,44 +0,0 @@
/*
* Copyright 2019 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.eea;
import static org.junit.Assert.assertEquals;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
import java.math.BigInteger;
import org.web3j.utils.Numeric;
public class ExpectValidPrivateContractEventsEmitted extends GetValidPrivateTransactionReceipt {
private final String eventValue;
public ExpectValidPrivateContractEventsEmitted(
final String eventValue, final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
this.eventValue = eventValue;
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
String event = privateTxReceipt.getLogs().get(0).getData().substring(66, 130);
assertEquals(
new BigInteger(eventValue), Numeric.decodeQuantity(Numeric.prependHexPrefix(event)));
}
}

@ -1,44 +0,0 @@
/*
* Copyright 2019 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.eea;
import static org.junit.Assert.assertEquals;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
import org.web3j.utils.Numeric;
public class ExpectValidPrivateContractValuesReturned extends GetValidPrivateTransactionReceipt {
private final String returnValue;
public ExpectValidPrivateContractValuesReturned(
final String returnValue, final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
this.returnValue = returnValue;
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
final PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
BytesValue output = BytesValue.fromHexString(privateTxReceipt.getOutput());
assertEquals(new BigInteger(returnValue), Numeric.decodeQuantity(output.toString()));
}
}

@ -1,36 +0,0 @@
/*
* Copyright 2019 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.eea;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertNotNull;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class ExpectValidPrivateTransactionReceipt extends GetValidPrivateTransactionReceipt {
public ExpectValidPrivateTransactionReceipt(
final EeaConditions eea, final EeaTransactions transactions) {
super(eea, transactions);
}
@Override
public void verify(final PantheonNode node, final String transactionHash) {
final PrivateTransactionReceipt privateTxReceipt =
getPrivateTransactionReceipt(node, transactionHash);
assertNotNull(privateTxReceipt);
assertThat(privateTxReceipt.getFrom()).isNotBlank();
}
}

@ -1,37 +0,0 @@
/*
* Copyright 2019 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.eea;
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public abstract class GetValidPrivateTransactionReceipt implements EeaCondition {
private EeaConditions eea;
private EeaTransactions transactions;
GetValidPrivateTransactionReceipt(final EeaConditions eea, final EeaTransactions transactions) {
this.eea = eea;
this.transactions = transactions;
}
PrivateTransactionReceipt getPrivateTransactionReceipt(
final PantheonNode node, final String transactionHash) {
waitFor(() -> node.verify(eea.expectSuccessfulTransactionReceipt(transactionHash)));
return node.execute(transactions.getPrivateTransactionReceipt(transactionHash));
}
}

@ -102,7 +102,7 @@ public class EthSignerClientTest {
BigInteger.ZERO,
ENCLAVE_PUBLIC_KEY,
Collections.emptyList(),
"");
"restricted");
assertEquals(MOCK_RESPONSE, response);
}

@ -34,13 +34,12 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.admin.AdminRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft2.Ibft2RequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.login.LoginRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.miner.MinerRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.CustomRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.perm.PermissioningJsonRpcRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory;
import java.io.File;
import java.io.FileInputStream;
@ -86,7 +85,7 @@ public class PantheonNode implements NodeConfiguration, RunnableNode, AutoClosea
private final String name;
private final MiningParameters miningParameters;
private final PrivacyParameters privacyParameters;
private PrivacyParameters privacyParameters = PrivacyParameters.DEFAULT;
private final JsonRpcConfiguration jsonRpcConfiguration;
private final WebSocketConfiguration webSocketConfiguration;
private final MetricsConfiguration metricsConfiguration;
@ -108,7 +107,6 @@ public class PantheonNode implements NodeConfiguration, RunnableNode, AutoClosea
public PantheonNode(
final String name,
final MiningParameters miningParameters,
final PrivacyParameters privacyParameters,
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final MetricsConfiguration metricsConfiguration,
@ -139,8 +137,6 @@ public class PantheonNode implements NodeConfiguration, RunnableNode, AutoClosea
this.keyPair = KeyPairUtil.loadKeyPair(homeDirectory);
this.name = name;
this.miningParameters = miningParameters;
this.privacyParameters = privacyParameters;
this.privacyParameters.setSigningKeyPair(keyPair);
this.jsonRpcConfiguration = jsonRpcConfiguration;
this.webSocketConfiguration = webSocketConfiguration;
this.metricsConfiguration = metricsConfiguration;
@ -301,8 +297,7 @@ public class PantheonNode implements NodeConfiguration, RunnableNode, AutoClosea
new Ibft2RequestFactory(web3jService),
new PermissioningJsonRpcRequestFactory(web3jService),
new AdminRequestFactory(web3jService),
new EeaRequestFactory(web3jService),
new PrivRequestFactory(web3jService),
new PrivacyRequestFactory(web3jService),
new CustomRequestFactory(web3jService),
new MinerRequestFactory(web3jService),
websocketService,
@ -516,6 +511,10 @@ public class PantheonNode implements NodeConfiguration, RunnableNode, AutoClosea
return privacyParameters;
}
public void setPrivacyParameters(final PrivacyParameters privacyParameters) {
this.privacyParameters = privacyParameters;
}
public boolean isDevMode() {
return devMode;
}

@ -13,7 +13,6 @@
package tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.config.NetworkingConfiguration;
@ -24,11 +23,10 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.genesis.Gen
import java.util.List;
import java.util.Optional;
public class PantheonFactoryConfiguration {
public class PantheonNodeConfiguration {
private final String name;
private final MiningParameters miningParameters;
private final PrivacyParameters privacyParameters;
private final JsonRpcConfiguration jsonRpcConfiguration;
private final WebSocketConfiguration webSocketConfiguration;
private final MetricsConfiguration metricsConfiguration;
@ -45,10 +43,9 @@ public class PantheonFactoryConfiguration {
private final List<String> extraCLIOptions;
private final List<String> staticNodes;
public PantheonFactoryConfiguration(
public PantheonNodeConfiguration(
final String name,
final MiningParameters miningParameters,
final PrivacyParameters privacyParameters,
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final MetricsConfiguration metricsConfiguration,
@ -66,7 +63,6 @@ public class PantheonFactoryConfiguration {
final List<String> staticNodes) {
this.name = name;
this.miningParameters = miningParameters;
this.privacyParameters = privacyParameters;
this.jsonRpcConfiguration = jsonRpcConfiguration;
this.webSocketConfiguration = webSocketConfiguration;
this.metricsConfiguration = metricsConfiguration;
@ -92,10 +88,6 @@ public class PantheonFactoryConfiguration {
return miningParameters;
}
public PrivacyParameters getPrivacyParameters() {
return privacyParameters;
}
public JsonRpcConfiguration getJsonRpcConfiguration() {
return jsonRpcConfiguration;
}

@ -16,7 +16,6 @@ import static java.util.Collections.singletonList;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.MiningParametersTestBuilder;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.RpcApis;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
@ -32,12 +31,11 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class PantheonFactoryConfigurationBuilder {
public class PantheonNodeConfigurationBuilder {
private String name;
private MiningParameters miningParameters =
new MiningParametersTestBuilder().enabled(false).build();
private PrivacyParameters privacyParameters = PrivacyParameters.DEFAULT;
private JsonRpcConfiguration jsonRpcConfiguration = JsonRpcConfiguration.createDefault();
private WebSocketConfiguration webSocketConfiguration = WebSocketConfiguration.createDefault();
private MetricsConfiguration metricsConfiguration = MetricsConfiguration.builder().build();
@ -54,30 +52,30 @@ public class PantheonFactoryConfigurationBuilder {
private List<String> extraCLIOptions = new ArrayList<>();
private List<String> staticNodes = new ArrayList<>();
public PantheonFactoryConfigurationBuilder() {
public PantheonNodeConfigurationBuilder() {
// Check connections more frequently during acceptance tests to cut down on
// intermittent failures due to the fact that we're running over a real network
networkingConfiguration.setInitiateConnectionsFrequency(5);
}
public PantheonFactoryConfigurationBuilder name(final String name) {
public PantheonNodeConfigurationBuilder name(final String name) {
this.name = name;
return this;
}
public PantheonFactoryConfigurationBuilder miningEnabled() {
public PantheonNodeConfigurationBuilder miningEnabled() {
this.miningParameters = new MiningParametersTestBuilder().enabled(true).build();
this.jsonRpcConfiguration.addRpcApi(RpcApis.MINER);
return this;
}
public PantheonFactoryConfigurationBuilder jsonRpcConfiguration(
public PantheonNodeConfigurationBuilder jsonRpcConfiguration(
final JsonRpcConfiguration jsonRpcConfiguration) {
this.jsonRpcConfiguration = jsonRpcConfiguration;
return this;
}
public PantheonFactoryConfigurationBuilder jsonRpcEnabled() {
public PantheonNodeConfigurationBuilder jsonRpcEnabled() {
this.jsonRpcConfiguration.setEnabled(true);
this.jsonRpcConfiguration.setPort(0);
this.jsonRpcConfiguration.setHostsWhitelist(singletonList("*"));
@ -85,17 +83,13 @@ public class PantheonFactoryConfigurationBuilder {
return this;
}
public PantheonFactoryConfigurationBuilder enablePrivateTransactions(
final PrivacyParameters privacyParameters) {
public PantheonNodeConfigurationBuilder enablePrivateTransactions() {
this.jsonRpcConfiguration.addRpcApi(RpcApis.EEA);
this.jsonRpcConfiguration.addRpcApi(RpcApis.PRIV);
this.privacyParameters = privacyParameters;
this.privacyParameters.setEnabled(true);
return this;
}
public PantheonFactoryConfigurationBuilder jsonRpcAuthenticationEnabled()
throws URISyntaxException {
public PantheonNodeConfigurationBuilder jsonRpcAuthenticationEnabled() throws URISyntaxException {
final String authTomlPath =
Paths.get(ClassLoader.getSystemResource("authentication/auth.toml").toURI())
.toAbsolutePath()
@ -107,19 +101,19 @@ public class PantheonFactoryConfigurationBuilder {
return this;
}
public PantheonFactoryConfigurationBuilder webSocketConfiguration(
public PantheonNodeConfigurationBuilder webSocketConfiguration(
final WebSocketConfiguration webSocketConfiguration) {
this.webSocketConfiguration = webSocketConfiguration;
return this;
}
public PantheonFactoryConfigurationBuilder metricsConfiguration(
public PantheonNodeConfigurationBuilder metricsConfiguration(
final MetricsConfiguration metricsConfiguration) {
this.metricsConfiguration = metricsConfiguration;
return this;
}
public PantheonFactoryConfigurationBuilder webSocketEnabled() {
public PantheonNodeConfigurationBuilder webSocketEnabled() {
final WebSocketConfiguration config = WebSocketConfiguration.createDefault();
config.setEnabled(true);
config.setPort(0);
@ -129,12 +123,12 @@ public class PantheonFactoryConfigurationBuilder {
return this;
}
public PantheonFactoryConfigurationBuilder bootnodeEligible(final boolean bootnodeEligible) {
public PantheonNodeConfigurationBuilder bootnodeEligible(final boolean bootnodeEligible) {
this.bootnodeEligible = bootnodeEligible;
return this;
}
public PantheonFactoryConfigurationBuilder webSocketAuthenticationEnabled()
public PantheonNodeConfigurationBuilder webSocketAuthenticationEnabled()
throws URISyntaxException {
final String authTomlPath =
Paths.get(ClassLoader.getSystemResource("authentication/auth.toml").toURI())
@ -147,65 +141,64 @@ public class PantheonFactoryConfigurationBuilder {
return this;
}
public PantheonFactoryConfigurationBuilder permissioningConfiguration(
public PantheonNodeConfigurationBuilder permissioningConfiguration(
final PermissioningConfiguration permissioningConfiguration) {
this.permissioningConfiguration = Optional.of(permissioningConfiguration);
return this;
}
public PantheonFactoryConfigurationBuilder keyFilePath(final String keyFilePath) {
public PantheonNodeConfigurationBuilder keyFilePath(final String keyFilePath) {
this.keyFilePath = Optional.of(keyFilePath);
return this;
}
public PantheonFactoryConfigurationBuilder devMode(final boolean devMode) {
public PantheonNodeConfigurationBuilder devMode(final boolean devMode) {
this.devMode = devMode;
return this;
}
public PantheonFactoryConfigurationBuilder genesisConfigProvider(
public PantheonNodeConfigurationBuilder genesisConfigProvider(
final GenesisConfigurationProvider genesisConfigProvider) {
this.genesisConfigProvider = genesisConfigProvider;
return this;
}
public PantheonFactoryConfigurationBuilder p2pEnabled(final Boolean p2pEnabled) {
public PantheonNodeConfigurationBuilder p2pEnabled(final Boolean p2pEnabled) {
this.p2pEnabled = p2pEnabled;
return this;
}
public PantheonFactoryConfigurationBuilder discoveryEnabled(final boolean discoveryEnabled) {
public PantheonNodeConfigurationBuilder discoveryEnabled(final boolean discoveryEnabled) {
this.discoveryEnabled = discoveryEnabled;
return this;
}
public PantheonFactoryConfigurationBuilder plugins(final List<String> plugins) {
public PantheonNodeConfigurationBuilder plugins(final List<String> plugins) {
this.plugins.clear();
this.plugins.addAll(plugins);
return this;
}
public PantheonFactoryConfigurationBuilder extraCLIOptions(final List<String> extraCLIOptions) {
public PantheonNodeConfigurationBuilder extraCLIOptions(final List<String> extraCLIOptions) {
this.extraCLIOptions.clear();
this.extraCLIOptions.addAll(extraCLIOptions);
return this;
}
public PantheonFactoryConfigurationBuilder revertReasonEnabled() {
public PantheonNodeConfigurationBuilder revertReasonEnabled() {
this.revertReasonEnabled = true;
return this;
}
public PantheonFactoryConfigurationBuilder staticNodes(final List<String> staticNodes) {
public PantheonNodeConfigurationBuilder staticNodes(final List<String> staticNodes) {
this.staticNodes = staticNodes;
return this;
}
public PantheonFactoryConfiguration build() {
return new PantheonFactoryConfiguration(
public PantheonNodeConfiguration build() {
return new PantheonNodeConfiguration(
name,
miningParameters,
privacyParameters,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration,

@ -34,11 +34,10 @@ public class PantheonNodeFactory {
private final GenesisConfigurationFactory genesis = new GenesisConfigurationFactory();
private final NodeConfigurationFactory node = new NodeConfigurationFactory();
public PantheonNode create(final PantheonFactoryConfiguration config) throws IOException {
public PantheonNode create(final PantheonNodeConfiguration config) throws IOException {
return new PantheonNode(
config.getName(),
config.getMiningParameters(),
config.getPrivacyParameters(),
config.getJsonRpcConfiguration(),
config.getWebSocketConfiguration(),
config.getMetricsConfiguration(),
@ -58,7 +57,7 @@ public class PantheonNodeFactory {
public PantheonNode createMinerNode(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcEnabled()
@ -68,7 +67,7 @@ public class PantheonNodeFactory {
public PantheonNode createMinerNodeWithRevertReasonEnabled(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcEnabled()
@ -79,7 +78,7 @@ public class PantheonNodeFactory {
public PantheonNode createArchiveNode(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.webSocketEnabled()
@ -88,7 +87,7 @@ public class PantheonNodeFactory {
public Node createArchiveNodeThatMustNotBeTheBootnode(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.webSocketEnabled()
@ -99,7 +98,7 @@ public class PantheonNodeFactory {
public PantheonNode createArchiveNodeWithDiscoveryDisabledAndAdmin(final String name)
throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcConfiguration(node.jsonRpcConfigWithAdmin())
.webSocketEnabled()
@ -113,7 +112,7 @@ public class PantheonNodeFactory {
// metricsConfiguration.setEnabled(true);
// metricsConfiguration.setPort(0);
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
// .setMetricsConfiguration(metricsConfiguration)
.jsonRpcConfiguration(node.jsonRpcConfigWithAdmin())
@ -124,7 +123,7 @@ public class PantheonNodeFactory {
public PantheonNode createArchiveNodeNetServicesDisabled(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcConfiguration(node.jsonRpcConfigWithAdmin())
.p2pEnabled(false)
@ -134,7 +133,7 @@ public class PantheonNodeFactory {
public PantheonNode createArchiveNodeWithAuthentication(final String name)
throws IOException, URISyntaxException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.jsonRpcAuthenticationEnabled()
@ -145,7 +144,7 @@ public class PantheonNodeFactory {
public PantheonNode createArchiveNodeWithAuthenticationOverWebSocket(final String name)
throws IOException, URISyntaxException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.webSocketEnabled()
.webSocketAuthenticationEnabled()
@ -154,7 +153,7 @@ public class PantheonNodeFactory {
public PantheonNode createNodeWithP2pDisabled(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.p2pEnabled(false)
.jsonRpcConfiguration(node.createJsonRpcEnabledConfig())
@ -162,14 +161,14 @@ public class PantheonNodeFactory {
}
public PantheonNode createArchiveNodeWithRpcDisabled(final String name) throws IOException {
return create(new PantheonFactoryConfigurationBuilder().name(name).build());
return create(new PantheonNodeConfigurationBuilder().name(name).build());
}
public PantheonNode createPluginsNode(
final String name, final List<String> plugins, final List<String> extraCLIOptions)
throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.plugins(plugins)
.extraCLIOptions(extraCLIOptions)
@ -184,7 +183,7 @@ public class PantheonNodeFactory {
webSocketConfig.setRpcApis(asList(enabledRpcApis));
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcConfiguration(jsonRpcConfig)
.webSocketConfiguration(webSocketConfig)
@ -193,12 +192,12 @@ public class PantheonNodeFactory {
public PantheonNode createNodeWithNoDiscovery(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder().name(name).discoveryEnabled(false).build());
new PantheonNodeConfigurationBuilder().name(name).discoveryEnabled(false).build());
}
public PantheonNode createCliqueNode(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig())
@ -210,7 +209,7 @@ public class PantheonNodeFactory {
public PantheonNode createIbft2Node(final String name) throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig())
@ -232,8 +231,8 @@ public class PantheonNodeFactory {
final boolean mining)
throws IOException {
final String genesisFile = genesis.readGenesisFile(genesisPath);
final PantheonFactoryConfigurationBuilder builder =
new PantheonFactoryConfigurationBuilder()
final PantheonNodeConfigurationBuilder builder =
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.webSocketEnabled()
@ -252,7 +251,7 @@ public class PantheonNodeFactory {
throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithCliqueEnabledConfig())
@ -269,7 +268,7 @@ public class PantheonNodeFactory {
throws IOException {
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig())
@ -293,7 +292,7 @@ public class PantheonNodeFactory {
.collect(toList());
return create(
new PantheonFactoryConfigurationBuilder()
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.webSocketEnabled()

@ -46,6 +46,13 @@ public class GenesisConfigurationFactory {
validators, template, IbftExtraData::createGenesisExtraDataString);
}
public Optional<String> createPrivacyIbft2GenesisConfig(
final Collection<? extends RunnableNode> validators) {
final String template = readGenesisFile("/ibft/privacy-ibft.json");
return updateGenesisExtraData(
validators, template, IbftExtraData::createGenesisExtraDataString);
}
private Optional<String> updateGenesisExtraData(
final Collection<? extends RunnableNode> validators,
final String genesisTemplate,

@ -27,7 +27,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.WhitelistPersistor.WHITELIST
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.node.RunnableNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonFactoryConfigurationBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonNodeConfigurationBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonNodeFactory;
import java.io.File;
@ -171,7 +171,7 @@ public class PermissionedNodeBuilder {
final PermissioningConfiguration permissioningConfiguration =
new PermissioningConfiguration(localPermConfig, smartContractPermConfig);
final PantheonFactoryConfigurationBuilder builder = new PantheonFactoryConfigurationBuilder();
final PantheonNodeConfigurationBuilder builder = new PantheonNodeConfigurationBuilder();
builder
.name(name)
.jsonRpcConfiguration(jsonRpcConfigWithPermApiEnabled())

@ -0,0 +1,36 @@
/*
* Copyright 2019 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.configuration.privacy;
import tech.pegasys.orion.testutil.OrionKeyConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonNodeConfiguration;
public class PrivacyNodeConfiguration {
private final PantheonNodeConfiguration pantheonConfig;
private final OrionKeyConfiguration orionConfig;
PrivacyNodeConfiguration(
final PantheonNodeConfiguration pantheonConfig, final OrionKeyConfiguration orionConfig) {
this.pantheonConfig = pantheonConfig;
this.orionConfig = orionConfig;
}
public PantheonNodeConfiguration getPantheonConfig() {
return pantheonConfig;
}
public OrionKeyConfiguration getOrionKeyConfig() {
return orionConfig;
}
}

@ -0,0 +1,81 @@
/*
* Copyright 2019 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.configuration.privacy;
import tech.pegasys.orion.testutil.OrionKeyConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.NodeConfigurationFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonNodeConfigurationBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.account.PrivacyAccount;
import java.io.IOException;
public class PrivacyNodeFactory {
private final GenesisConfigurationFactory genesis = new GenesisConfigurationFactory();
private final NodeConfigurationFactory node = new NodeConfigurationFactory();
private PrivacyNode create(final PrivacyNodeConfiguration privacyNodeConfig) throws IOException {
return new PrivacyNode(privacyNodeConfig);
}
public PrivacyNode createPrivateTransactionEnabledMinerNode(
final String name, final PrivacyAccount privacyAccount) throws IOException {
return create(
new PrivacyNodeConfiguration(
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcEnabled()
.webSocketEnabled()
.enablePrivateTransactions()
.keyFilePath(privacyAccount.getPrivateKeyPath())
.build(),
new OrionKeyConfiguration(
privacyAccount.getEnclaveKeyPath(), privacyAccount.getEnclavePrivateKeyPath())));
}
public PrivacyNode createPrivateTransactionEnabledNode(
final String name, final PrivacyAccount privacyAccount) throws IOException {
return create(
new PrivacyNodeConfiguration(
new PantheonNodeConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.keyFilePath(privacyAccount.getPrivateKeyPath())
.enablePrivateTransactions()
.webSocketEnabled()
.build(),
new OrionKeyConfiguration(
privacyAccount.getEnclaveKeyPath(), privacyAccount.getEnclavePrivateKeyPath())));
}
public PrivacyNode createIbft2NodePrivacyEnabled(
final String name, final PrivacyAccount privacyAccount) throws IOException {
return create(
new PrivacyNodeConfiguration(
new PantheonNodeConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig())
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.genesisConfigProvider(genesis::createPrivacyIbft2GenesisConfig)
.keyFilePath(privacyAccount.getPrivateKeyPath())
.enablePrivateTransactions()
.build(),
new OrionKeyConfiguration(
privacyAccount.getEnclaveKeyPath(), privacyAccount.getEnclavePrivateKeyPath())));
}
}

@ -1,78 +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.node.configuration.privacy;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.config.NetworkingConfiguration;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonFactoryConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class PrivacyPantheonFactoryConfiguration extends PantheonFactoryConfiguration {
private final OrionTestHarness orion;
PrivacyPantheonFactoryConfiguration(
final String name,
final MiningParameters miningParameters,
final PrivacyParameters privacyParameters,
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyFilePath,
final boolean devMode,
final GenesisConfigurationProvider genesisConfigProvider,
final boolean p2pEnabled,
final NetworkingConfiguration networkingConfiguration,
final boolean discoveryEnabled,
final boolean bootnodeEligible,
final boolean revertReasonEnabled,
final List<String> plugins,
final List<String> extraCLIOptions,
final OrionTestHarness orion) {
super(
name,
miningParameters,
privacyParameters,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration,
permissioningConfiguration,
keyFilePath,
devMode,
genesisConfigProvider,
p2pEnabled,
networkingConfiguration,
discoveryEnabled,
bootnodeEligible,
revertReasonEnabled,
plugins,
extraCLIOptions,
new ArrayList<>());
this.orion = orion;
}
public OrionTestHarness getOrion() {
return orion;
}
}

@ -1,55 +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.node.configuration.privacy;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonFactoryConfiguration;
public class PrivacyPantheonFactoryConfigurationBuilder {
protected PantheonFactoryConfiguration config;
protected OrionTestHarness orion;
public PrivacyPantheonFactoryConfigurationBuilder setConfig(
final PantheonFactoryConfiguration config) {
this.config = config;
return this;
}
public PrivacyPantheonFactoryConfigurationBuilder setOrion(final OrionTestHarness orion) {
this.orion = orion;
return this;
}
public PrivacyPantheonFactoryConfiguration build() {
return new PrivacyPantheonFactoryConfiguration(
config.getName(),
config.getMiningParameters(),
config.getPrivacyParameters(),
config.getJsonRpcConfiguration(),
config.getWebSocketConfiguration(),
config.getMetricsConfiguration(),
config.getPermissioningConfiguration(),
config.getKeyFilePath(),
config.isDevMode(),
config.getGenesisConfigProvider(),
config.isP2pEnabled(),
config.getNetworkingConfiguration(),
config.isDiscoveryEnabled(),
config.isBootnodeEligible(),
config.isRevertReasonEnabled(),
config.getPlugins(),
config.getExtraCLIOptions(),
orion);
}
}

@ -1,115 +0,0 @@
/*
* Copyright 2019 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.configuration.privacy;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.NodeConfigurationFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonFactoryConfigurationBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import java.io.IOException;
public class PrivacyPantheonNodeFactory {
private final GenesisConfigurationFactory genesis = new GenesisConfigurationFactory();
private final NodeConfigurationFactory node = new NodeConfigurationFactory();
private static PrivacyNode create(final PrivacyPantheonFactoryConfiguration config)
throws IOException {
return new PrivacyNode(
config.getName(),
config.getMiningParameters(),
config.getPrivacyParameters(),
config.getJsonRpcConfiguration(),
config.getWebSocketConfiguration(),
config.getMetricsConfiguration(),
config.getPermissioningConfiguration(),
config.getKeyFilePath(),
config.isDevMode(),
config.getGenesisConfigProvider(),
config.isP2pEnabled(),
config.getNetworkingConfiguration(),
config.isDiscoveryEnabled(),
config.isBootnodeEligible(),
config.isRevertReasonEnabled(),
config.getPlugins(),
config.getExtraCLIOptions(),
config.getOrion());
}
public PrivacyNode createPrivateTransactionEnabledMinerNode(
final String name,
final PrivacyParameters privacyParameters,
final String keyFilePath,
final OrionTestHarness orionTestHarness)
throws IOException {
return create(
new PrivacyPantheonFactoryConfigurationBuilder()
.setConfig(
new PantheonFactoryConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcEnabled()
.keyFilePath(keyFilePath)
.enablePrivateTransactions(privacyParameters)
.webSocketEnabled()
.build())
.setOrion(orionTestHarness)
.build());
}
public PrivacyNode createPrivateTransactionEnabledNode(
final String name,
final PrivacyParameters privacyParameters,
final String keyFilePath,
final OrionTestHarness orionTestHarness)
throws IOException {
return create(
new PrivacyPantheonFactoryConfigurationBuilder()
.setConfig(
new PantheonFactoryConfigurationBuilder()
.name(name)
.jsonRpcEnabled()
.keyFilePath(keyFilePath)
.enablePrivateTransactions(privacyParameters)
.webSocketEnabled()
.build())
.setOrion(orionTestHarness)
.build());
}
public PrivacyNode createIbft2NodePrivacyEnabled(
final String name,
final PrivacyParameters privacyParameters,
final String keyFilePath,
final OrionTestHarness orionTestHarness)
throws IOException {
return create(
new PrivacyPantheonFactoryConfigurationBuilder()
.setConfig(
new PantheonFactoryConfigurationBuilder()
.name(name)
.miningEnabled()
.jsonRpcConfiguration(node.createJsonRpcWithIbft2EnabledConfig())
.webSocketConfiguration(node.createWebSocketEnabledConfig())
.devMode(false)
.genesisConfigProvider(genesis::createIbft2GenesisConfig)
.keyFilePath(keyFilePath)
.enablePrivateTransactions(privacyParameters)
.build())
.setOrion(orionTestHarness)
.build());
}
}

@ -12,31 +12,45 @@
*/
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy;
import tech.pegasys.pantheon.tests.acceptance.dsl.AcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.EeaConditions;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.privacy.PrivacyPantheonNodeFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.net.NetConditions;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.condition.PrivateContractVerifier;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.condition.PrivateTransactionVerifier;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.contract.PrivateContractTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.NetTransactions;
import org.junit.After;
import org.junit.ClassRule;
import org.junit.rules.TemporaryFolder;
public class PrivacyAcceptanceTestBase extends AcceptanceTestBase {
public class PrivacyAcceptanceTestBase {
@ClassRule public static final TemporaryFolder privacy = new TemporaryFolder();
protected final EeaConditions eea;
protected final PrivateTransactions privateTransactions;
protected final PrivateTransactionBuilder.Builder privateTransactionBuilder;
protected final PrivacyTransactions privacyTransactions;
protected final PrivateContractVerifier privateContractVerifier;
protected final PrivateTransactionVerifier privateTransactionVerifier;
protected final PrivacyPantheonNodeFactory privacyPantheon;
protected final PrivacyNodeFactory privacyPantheon;
protected final PrivateContractTransactions privateContractTransactions;
protected final PrivacyCluster privacyCluster;
protected final PrivacyAccountResolver privacyAccountResolver;
protected final NetConditions net;
public PrivacyAcceptanceTestBase() {
final EeaTransactions eeaTransactions = new EeaTransactions();
net = new NetConditions(new NetTransactions());
privacyTransactions = new PrivacyTransactions();
privateContractVerifier = new PrivateContractVerifier();
privateTransactionVerifier = new PrivateTransactionVerifier(privacyTransactions);
privacyPantheon = new PrivacyNodeFactory();
privateContractTransactions = new PrivateContractTransactions();
privacyCluster = new PrivacyCluster(net);
privacyAccountResolver = new PrivacyAccountResolver();
}
privateTransactions = new PrivateTransactions();
eea = new EeaConditions(eeaTransactions);
privateTransactionBuilder = PrivateTransactionBuilder.builder();
privateTransactionVerifier = new PrivateTransactionVerifier(eea, eeaTransactions);
privacyPantheon = new PrivacyPantheonNodeFactory();
@After
public void tearDownAcceptanceTestBase() {
privacyCluster.close();
}
}

@ -0,0 +1,141 @@
/*
* Copyright 2019 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.privacy;
import static java.util.Collections.emptyList;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.net.NetConditions;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNodeRunner;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.RunnableNode;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class PrivacyCluster {
private static final Logger LOG = LogManager.getLogger();
private final NetConditions net;
private final PantheonNodeRunner pantheonNodeRunner;
private List<PrivacyNode> nodes = emptyList();
private List<RunnableNode> runnableNodes = emptyList();
private PrivacyNode bootNode;
public PrivacyCluster(final NetConditions net) {
this.net = net;
this.pantheonNodeRunner = PantheonNodeRunner.instance();
}
public void start(final PrivacyNode... nodes) {
start(Arrays.asList(nodes));
}
public void start(final List<PrivacyNode> nodes) {
if (nodes.isEmpty()) {
throw new IllegalArgumentException("Can't start a cluster with no nodes");
}
this.nodes = nodes;
this.runnableNodes = nodes.stream().map(n -> n.getPantheon()).collect(Collectors.toList());
final Optional<PrivacyNode> bootNode = selectAndStartBootnode(nodes);
nodes.stream()
.filter(node -> bootNode.map(boot -> boot != node).orElse(true))
.forEach(this::startNode);
for (final PrivacyNode node : nodes) {
LOG.info("Awaiting peer discovery for node {}", node.getName());
node.awaitPeerDiscovery(net.awaitPeerCount(nodes.size() - 1));
}
verifyAllOrionNetworkConnections();
}
public List<PrivacyNode> getNodes() {
return nodes;
}
/** Verify that each Orion node has connected to every other Orion */
public void verifyAllOrionNetworkConnections() {
for (int i = 0; i < nodes.size() - 1; i++) {
nodes.get(i).testOrionConnection(nodes.subList(i + 1, nodes.size()));
}
}
public void stop() {
for (final PrivacyNode node : nodes) {
pantheonNodeRunner.stopNode(node.getPantheon());
}
}
public void stopNode(final PrivacyNode node) {
node.getOrion().stop();
pantheonNodeRunner.stopNode(node.getPantheon());
}
public void close() {
stop();
for (final PrivacyNode node : nodes) {
node.close();
}
pantheonNodeRunner.shutdown();
}
private Optional<PrivacyNode> selectAndStartBootnode(final List<PrivacyNode> nodes) {
final Optional<PrivacyNode> bootNode =
nodes.stream()
.filter(node -> node.getConfiguration().isBootnodeEligible())
.filter(node -> node.getConfiguration().isP2pEnabled())
.filter(node -> node.getConfiguration().isDiscoveryEnabled())
.findFirst();
bootNode.ifPresent(
b -> {
LOG.info("Selected node {} as bootnode", b.getName());
startNode(b, true);
this.bootNode = b;
});
return bootNode;
}
private void startNode(final PrivacyNode node) {
startNode(node, false);
}
private void startNode(final PrivacyNode node, final boolean isBootNode) {
node.getConfiguration()
.setBootnodes(isBootNode ? emptyList() : Collections.singletonList(bootNode.enodeUrl()));
node.getConfiguration()
.getGenesisConfigProvider()
.create(runnableNodes)
.ifPresent(node.getConfiguration()::setGenesisConfig);
if (!isBootNode) {
node.addOtherEnclaveNode(bootNode.getOrion().nodeUrl());
}
LOG.info(
"Starting node {} (id = {}...{})",
node.getName(),
node.getNodeId().substring(0, 4),
node.getNodeId().substring(124));
node.start(pantheonNodeRunner);
}
}

@ -1,278 +0,0 @@
/*
* Copyright 2019 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.privacy;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.orion.testutil.OrionTestHarnessFactory;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.cluster.Cluster;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.privacy.PrivacyPantheonNodeFactory;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import com.google.common.base.Preconditions;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.rules.TemporaryFolder;
public class PrivacyNet {
private static final Logger LOG = LogManager.getLogger();
private static final String PANTHEON_KEYPAIR_NODE_1 = "key";
private static final String PANTHEON_KEYPAIR_NODE_2 = "key1";
private static final String PANTHEON_KEYPAIR_NODE_3 = "key2";
private static final Map<String, String> KNOWN_PANTHEON_KEYPAIRS = new HashMap<>();
private final TemporaryFolder temporaryFolder;
private Cluster cluster;
private Map<String, PrivacyNode> nodes;
static {
KNOWN_PANTHEON_KEYPAIRS.put("Alice", PANTHEON_KEYPAIR_NODE_1);
KNOWN_PANTHEON_KEYPAIRS.put("Bob", PANTHEON_KEYPAIR_NODE_2);
KNOWN_PANTHEON_KEYPAIRS.put("Charlie", PANTHEON_KEYPAIR_NODE_3);
}
private PrivacyNet(
final TemporaryFolder temporaryFolder,
final Map<String, PrivacyNode> privacyNodes,
final Cluster cluster) {
this.temporaryFolder = temporaryFolder;
this.nodes = privacyNodes;
this.cluster = cluster;
}
public static PrivacyNet.Builder builder(
final TemporaryFolder temporaryFolder,
final PrivacyPantheonNodeFactory pantheonNodeFactory,
final Cluster cluster,
final boolean ibft) {
return new Builder(temporaryFolder, pantheonNodeFactory, cluster, ibft);
}
public Map<String, PrivacyNode> getNodes() {
return nodes;
}
public PrivacyNode getNode(final String name) {
return nodes.get(name);
}
public OrionTestHarness getEnclave(final String name) {
return nodes.get(name).orion;
}
public void startPrivacyNet() {
if (nodes == null)
throw new IllegalStateException(
"Cannot start network nodes. init method was never called to initialize the nodes");
cluster.start(nodes.values().toArray(new PrivacyNode[0]));
verifyAllOrionNetworkConnections();
}
public void stopPrivacyNet() {
try {
cluster.stop();
} catch (RuntimeException e) {
LOG.error("Error stopping Pantheon nodes. Logging and continuing.", e);
}
try {
stopOrionNodes();
} catch (RuntimeException e) {
LOG.error("Error stopping Orion nodes. Logging and continuing.", e);
}
}
private void stopOrionNodes() {
if (nodes == null) return; // Never started
for (PrivacyNode node : nodes.values()) {
try {
node.orion.getOrion().stop();
} catch (RuntimeException e) {
LOG.error(
String.format(
"Error stopping Orion node %s. Logging and continuing to shutdown other nodes.",
node.orion.nodeUrl()),
e);
}
}
}
/** Verify that each Orion node has connected to every other Orion */
public void verifyAllOrionNetworkConnections() {
PrivacyNode[] nodeList = nodes.values().toArray(new PrivacyNode[0]);
for (int i = 0; i < nodeList.length; i++) {
for (int j = i + 1; j < nodeList.length; j++) {
nodeList[i].testOrionConnection(nodeList[j]);
}
for (int j = i + 2; j < nodeList.length; j = j + 2) {
nodeList[i].testOrionConnection(nodeList[j]);
}
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(String.format("temporaryFolder = %s\n", temporaryFolder.getRoot()));
for (PrivacyNode privacyNode : nodes.values()) {
sb.append(String.format("Pantheon Node Name = %s\n", privacyNode.getName()));
sb.append(String.format("Pantheon Address = %s\n", privacyNode.getAddress()));
sb.append(
String.format("Pantheon Private Key = %s\n", privacyNode.keyPair().getPrivateKey()));
sb.append(String.format("Pantheon Public Key = %s\n", privacyNode.keyPair().getPublicKey()));
sb.append(String.format("Orion Pub Key = %s\n", privacyNode.getOrionPubKeyBytes()));
sb.append(
String.format(
"Orion Pub Key Base64 = %s\n",
Base64.getEncoder()
.encodeToString(privacyNode.getOrionPubKeyBytes().extractArray())));
sb.append(String.format("Pantheon = %s\n", privacyNode));
sb.append(String.format("Orion Config = %s\n", privacyNode.orion.getConfig()));
sb.append(String.format("Orion Pub Key = %s\n", privacyNode.getOrionPubKeyBytes()));
}
return sb.toString();
}
public static class Builder {
private TemporaryFolder temporaryFolder;
private PrivacyPantheonNodeFactory pantheonNodeFactory;
private Cluster cluster;
private final boolean ibft;
private String otherOrionNode = null;
private Map<String, PrivacyNode> nodes;
private Builder(
final TemporaryFolder temporaryFolder,
final PrivacyPantheonNodeFactory pantheonNodeFactory,
final Cluster cluster,
final boolean ibft) {
this.temporaryFolder = temporaryFolder;
this.pantheonNodeFactory = pantheonNodeFactory;
this.cluster = cluster;
this.ibft = ibft;
}
public Builder addMinerNode(final String name) throws IOException {
return addNode(name, true);
}
public Builder addNode(final String name) throws IOException {
return addNode(name, false);
}
public Builder addNode(final String name, final Optional<String> keyPath) throws IOException {
return addNode(name, false, keyPath);
}
public Builder addNode(final String name, final boolean isMiningEnabled) throws IOException {
return addNode(name, isMiningEnabled, Optional.empty());
}
public Builder addNode(
final String name, final boolean isMiningEnabled, final Optional<String> keyPath)
throws IOException {
final PrivacyNode node = makeNode(name, isMiningEnabled, otherOrionNode, keyPath);
if (nodes == null) {
nodes = new HashMap<>();
otherOrionNode = node.orion.nodeUrl(); // All nodes use first added node for discovery
}
nodes.put(name, node);
return this;
}
public PrivacyNode makeNode(
final String name,
final boolean isMiningEnabled,
final String otherOrionNodes,
final Optional<String> orionKeyPath)
throws IOException {
final OrionTestHarness orion;
if (otherOrionNodes == null) {
// Need conditional because createEnclave will choke if passing in null
orion = createEnclave(temporaryFolder, orionKeyPath);
} else {
orion = createEnclave(temporaryFolder, orionKeyPath, otherOrionNodes);
}
final PrivacyNode node;
final String keyFilePath = KNOWN_PANTHEON_KEYPAIRS.get(name);
if (isMiningEnabled && !ibft) {
node =
pantheonNodeFactory.createPrivateTransactionEnabledMinerNode(
name, generatePrivacyParameters(orion), keyFilePath, orion);
} else if (!isMiningEnabled && !ibft) {
node =
pantheonNodeFactory.createPrivateTransactionEnabledNode(
name, generatePrivacyParameters(orion), keyFilePath, orion);
} else {
node =
pantheonNodeFactory.createIbft2NodePrivacyEnabled(
name, generatePrivacyParameters(orion), keyFilePath, orion);
}
return node;
}
protected OrionTestHarness createEnclave(
final TemporaryFolder temporaryFolder,
final Optional<String> pubKeyPath,
final String... othernode)
throws IOException {
final Path tmpPath = temporaryFolder.newFolder().toPath();
final String orionPublicKeyFileName = pubKeyPath.orElse(provideNextKnownOrionKey());
final String orionPrivateKeyFileName = privaKeyPathFromPubKeyPath(orionPublicKeyFileName);
return OrionTestHarnessFactory.create(
tmpPath, orionPublicKeyFileName, orionPrivateKeyFileName, othernode);
}
private String privaKeyPathFromPubKeyPath(final String orionPublicKeyFileName) {
return orionPublicKeyFileName.substring(0, orionPublicKeyFileName.length() - 3) + "key";
}
private Integer nextKnownOrionKey = 0;
private String provideNextKnownOrionKey() {
if (nextKnownOrionKey < 4) {
return String.format("orion_key_%d.pub", nextKnownOrionKey++);
}
throw new RuntimeException("Limit of known nodes reached");
}
private PrivacyParameters generatePrivacyParameters(final OrionTestHarness testHarness)
throws IOException {
return new PrivacyParameters.Builder()
.setEnabled(true)
.setEnclaveUrl(testHarness.clientUrl())
.setEnclavePublicKeyUsingFile(testHarness.getConfig().publicKeys().get(0).toFile())
.setDataDir(temporaryFolder.newFolder().toPath())
.build();
}
public PrivacyNet build() {
Preconditions.checkNotNull(nodes);
return new PrivacyNet(temporaryFolder, nodes, cluster);
}
}
}

@ -12,111 +12,180 @@
*/
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.orion.testutil.OrionTestHarnessFactory;
import tech.pegasys.pantheon.controller.KeyPairUtil;
import tech.pegasys.pantheon.enclave.Enclave;
import tech.pegasys.pantheon.enclave.EnclaveException;
import tech.pegasys.pantheon.enclave.types.SendRequest;
import tech.pegasys.pantheon.enclave.types.SendRequestLegacy;
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.config.NetworkingConfiguration;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.Condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.genesis.GenesisConfigurationProvider;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivGetTransactionCountTransaction;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNodeRunner;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.NodeConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.PantheonNodeConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeConfiguration;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.condition.PrivateCondition;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.awaitility.Awaitility;
public class PrivacyNode extends PantheonNode {
public class PrivacyNode implements AutoCloseable {
private static final Logger LOG = LogManager.getLogger();
public OrionTestHarness orion;
public PrivacyNode(
final String name,
final MiningParameters miningParameters,
final PrivacyParameters privacyParameters,
final JsonRpcConfiguration jsonRpcConfiguration,
final WebSocketConfiguration webSocketConfiguration,
final MetricsConfiguration metricsConfiguration,
final Optional<PermissioningConfiguration> permissioningConfiguration,
final Optional<String> keyfilePath,
final boolean devMode,
final GenesisConfigurationProvider genesisConfigProvider,
final boolean p2pEnabled,
final NetworkingConfiguration networkingConfiguration,
final boolean discoveryEnabled,
final boolean bootnodeEligible,
final boolean revertReasonEnabled,
final List<String> plugins,
final List<String> extraCLIOptions,
final OrionTestHarness orion)
throws IOException {
super(
name,
miningParameters,
privacyParameters,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration,
permissioningConfiguration,
keyfilePath,
devMode,
genesisConfigProvider,
p2pEnabled,
networkingConfiguration,
discoveryEnabled,
bootnodeEligible,
revertReasonEnabled,
plugins,
extraCLIOptions,
new ArrayList<>());
this.orion = orion;
}
public BytesValue getOrionPubKeyBytes() {
return BytesValue.wrap(orion.getPublicKeys().get(0).getBytes(UTF_8));
}
public void testOrionConnection(final PrivacyNode... otherNodes) {
private final OrionTestHarness orion;
private final PantheonNode pantheon;
public PrivacyNode(final PrivacyNodeConfiguration privacyConfiguration) throws IOException {
final Path orionDir = Files.createTempDirectory("acctest-orion");
this.orion = OrionTestHarnessFactory.create(orionDir, privacyConfiguration.getOrionKeyConfig());
final PantheonNodeConfiguration pantheonConfig = privacyConfiguration.getPantheonConfig();
this.pantheon =
new PantheonNode(
pantheonConfig.getName(),
pantheonConfig.getMiningParameters(),
pantheonConfig.getJsonRpcConfiguration(),
pantheonConfig.getWebSocketConfiguration(),
pantheonConfig.getMetricsConfiguration(),
pantheonConfig.getPermissioningConfiguration(),
pantheonConfig.getKeyFilePath(),
pantheonConfig.isDevMode(),
pantheonConfig.getGenesisConfigProvider(),
pantheonConfig.isP2pEnabled(),
pantheonConfig.getNetworkingConfiguration(),
pantheonConfig.isDiscoveryEnabled(),
pantheonConfig.isBootnodeEligible(),
pantheonConfig.isRevertReasonEnabled(),
pantheonConfig.getPlugins(),
pantheonConfig.getExtraCLIOptions(),
new ArrayList<>());
}
public void testOrionConnection(final List<PrivacyNode> otherNodes) {
LOG.info(
String.format(
"Testing Orion connectivity between %s (%s) and %s (%s)",
getName(),
"Testing Enclave connectivity between %s (%s) and %s (%s)",
pantheon.getName(),
orion.nodeUrl(),
Arrays.toString(Arrays.stream(otherNodes).map(PrivacyNode::getName).toArray()),
Arrays.toString(
Arrays.stream(otherNodes).map(node -> node.orion.nodeUrl()).toArray())));
Enclave orionEnclave = new Enclave(orion.clientUrl());
Arrays.toString(otherNodes.stream().map(node -> node.pantheon.getName()).toArray()),
Arrays.toString(otherNodes.stream().map(node -> node.orion.nodeUrl()).toArray())));
Enclave enclaveClient = new Enclave(orion.clientUrl());
SendRequest sendRequest1 =
new SendRequestLegacy(
"SGVsbG8sIFdvcmxkIQ==",
orion.getPublicKeys().get(0),
Arrays.stream(otherNodes)
.map(node -> node.orion.getPublicKeys().get(0))
orion.getDefaultPublicKey(),
otherNodes.stream()
.map(node -> node.orion.getDefaultPublicKey())
.collect(Collectors.toList()));
waitFor(() -> orionEnclave.send(sendRequest1));
Awaitility.await()
.until(
() -> {
try {
enclaveClient.send(sendRequest1);
return true;
} catch (final EnclaveException e) {
LOG.info("Waiting for enclave connectivity");
return false;
}
});
}
public OrionTestHarness getOrion() {
return orion;
}
public PantheonNode getPantheon() {
return pantheon;
}
public void stop() {
pantheon.stop();
orion.stop();
}
@Override
public void close() {
pantheon.close();
orion.close();
}
public void start(final PantheonNodeRunner runner) {
orion.start();
final PrivacyParameters privacyParameters;
try {
privacyParameters =
new PrivacyParameters.Builder()
.setEnabled(true)
.setEnclaveUrl(orion.clientUrl())
.setEnclavePublicKeyUsingFile(orion.getConfig().publicKeys().get(0).toFile())
.setDataDir(Files.createTempDirectory("acctest-privacy"))
.setPrivateKeyPath(KeyPairUtil.getDefaultKeyFile(pantheon.homeDirectory()).toPath())
.build();
} catch (IOException e) {
throw new RuntimeException();
}
pantheon.setPrivacyParameters(privacyParameters);
pantheon.start(runner);
}
public void awaitPeerDiscovery(final Condition condition) {
pantheon.awaitPeerDiscovery(condition);
}
public String getName() {
return pantheon.getName();
}
public Address getAddress() {
return pantheon.getAddress();
}
public URI enodeUrl() {
return pantheon.enodeUrl();
}
public String getNodeId() {
return pantheon.getNodeId();
}
public <T> T execute(final Transaction<T> transaction) {
return pantheon.execute(transaction);
}
public void verify(final PrivateCondition expected) {
expected.verify(this);
}
public String getEnclaveKey() {
return orion.getDefaultPublicKey();
}
public String getTransactionSigningKey() {
return pantheon.keyPair().getPrivateKey().toString();
}
public void addOtherEnclaveNode(final URI otherNode) {
orion.addOtherNode(otherNode);
}
public long nextNonce(final BytesValue privacyGroupId) {
return execute(
new PrivGetTransactionCountTransaction(
getAddress().toString(), BytesValues.asBase64String(privacyGroupId)))
.longValue();
public NodeConfiguration getConfiguration() {
return pantheon.getConfiguration();
}
}

@ -1,63 +0,0 @@
/*
* Copyright 2019 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.privacy;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.EeaConditions;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectNoPrivateContractDeployedReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectNoValidPrivateContractEventsEmitted;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectNoValidPrivateContractValuesReturned;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectValidPrivateContractDeployedReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectValidPrivateContractEventsEmitted;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectValidPrivateContractValuesReturned;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.ExpectValidPrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaTransactions;
public class PrivateTransactionVerifier {
private final EeaTransactions transactions;
private final EeaConditions eea;
public PrivateTransactionVerifier(final EeaConditions eea, final EeaTransactions transactions) {
this.eea = eea;
this.transactions = transactions;
}
public ExpectValidPrivateTransactionReceipt validPrivateTransactionReceipt() {
return new ExpectValidPrivateTransactionReceipt(eea, transactions);
}
public ExpectValidPrivateContractDeployedReceipt validPrivateContractDeployed(
final String contractAddress) {
return new ExpectValidPrivateContractDeployedReceipt(contractAddress, eea, transactions);
}
public ExpectNoPrivateContractDeployedReceipt noPrivateContractDeployed() {
return new ExpectNoPrivateContractDeployedReceipt(eea, transactions);
}
public ExpectValidPrivateContractEventsEmitted validEventReturned(final String eventValue) {
return new ExpectValidPrivateContractEventsEmitted(eventValue, eea, transactions);
}
public ExpectNoValidPrivateContractEventsEmitted noValidEventReturned() {
return new ExpectNoValidPrivateContractEventsEmitted(eea, transactions);
}
public ExpectValidPrivateContractValuesReturned validOutputReturned(final String returnValue) {
return new ExpectValidPrivateContractValuesReturned(returnValue, eea, transactions);
}
public ExpectNoValidPrivateContractValuesReturned noValidOutputReturned() {
return new ExpectNoValidPrivateContractValuesReturned(eea, transactions);
}
}

@ -1,67 +0,0 @@
/*
* Copyright 2019 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.privacy;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaSendRawTransactionTransaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivCreatePrivacyGroupTransaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivCreatePrivacyGroupTransactionWithoutDescription;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivCreatePrivacyGroupTransactionWithoutName;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivCreatePrivacyGroupWithoutOptionalParamsTransaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivFindPrivacyGroupTransaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivGetTransactionCountTransaction;
import java.util.List;
public class PrivateTransactions {
public PrivateTransactions() {}
public EeaSendRawTransactionTransaction deployPrivateSmartContract(
final String signedRawPrivateTransaction) {
return new EeaSendRawTransactionTransaction(signedRawPrivateTransaction);
}
public EeaSendRawTransactionTransaction createPrivateRawTransaction(
final String signedRawPrivateTransaction) {
return new EeaSendRawTransactionTransaction(signedRawPrivateTransaction);
}
public PrivGetTransactionCountTransaction getTransactionCount(
final String address, final String privacyGroupId) {
return new PrivGetTransactionCountTransaction(address, privacyGroupId);
}
public PrivCreatePrivacyGroupTransaction createPrivacyGroup(
final List<String> addresses, final String name, final String description) {
return new PrivCreatePrivacyGroupTransaction(addresses, name, description);
}
public PrivCreatePrivacyGroupTransactionWithoutName createPrivacyGroupWithoutName(
final List<String> addresses, final String description) {
return new PrivCreatePrivacyGroupTransactionWithoutName(addresses, description);
}
public PrivCreatePrivacyGroupTransactionWithoutDescription createPrivacyGroupWithoutDescription(
final List<String> addresses, final String name) {
return new PrivCreatePrivacyGroupTransactionWithoutDescription(addresses, name);
}
public PrivCreatePrivacyGroupWithoutOptionalParamsTransaction
createPrivacyGroupWithoutOptionalParams(final List<String> addresses) {
return new PrivCreatePrivacyGroupWithoutOptionalParamsTransaction(addresses);
}
public PrivFindPrivacyGroupTransaction findPrivacyGroup(final List<String> addresses) {
return new PrivFindPrivacyGroupTransaction(addresses);
}
}

@ -0,0 +1,51 @@
/*
* Copyright 2019 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.privacy.account;
import java.io.File;
import java.net.URL;
public class PrivacyAccount {
private final URL privateKeyPath;
private final URL enclaveKeyPath;
private final URL enclavePrivateKeyPath;
private PrivacyAccount(
final URL privateKeyPath, final URL enclavePublicKeyPath, final URL enclavePrivateKeyPath) {
this.privateKeyPath = privateKeyPath;
this.enclaveKeyPath = enclavePublicKeyPath;
this.enclavePrivateKeyPath = enclavePrivateKeyPath;
}
public static PrivacyAccount create(
final URL privateKeyPath, final URL enclavePublicKeyPath, final URL enclavePrivateKeyPath) {
return new PrivacyAccount(privateKeyPath, enclavePublicKeyPath, enclavePrivateKeyPath);
}
public String getPrivateKeyPath() {
return toStringResource(privateKeyPath);
}
public String getEnclaveKeyPath() {
return toStringResource(enclaveKeyPath);
}
public String getEnclavePrivateKeyPath() {
return toStringResource(enclavePrivateKeyPath);
}
private String toStringResource(final URL path) {
return path.getPath().substring(path.getPath().lastIndexOf(File.separator) + 1);
}
}

@ -0,0 +1,56 @@
/*
* 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.privacy.account;
import java.net.URL;
/** Supplier of known funded accounts defined in dev.json */
public class PrivacyAccountResolver {
public static final PrivacyAccount ALICE =
PrivacyAccount.create(
resolveResource("key"),
resolveResource("orion_key_0.pub"),
resolveResource("orion_key_0.key"));
public static final PrivacyAccount BOB =
PrivacyAccount.create(
resolveResource("key1"),
resolveResource("orion_key_1.pub"),
resolveResource("orion_key_1.key"));
public static final PrivacyAccount CHARLIE =
PrivacyAccount.create(
resolveResource("key2"),
resolveResource("orion_key_2.pub"),
resolveResource("orion_key_2.key"));
private static URL resolveResource(final String resource) {
return PrivacyAccountResolver.class.getClassLoader().getResource(resource);
}
public PrivacyAccountResolver() {}
public PrivacyAccount resolve(final Integer account) {
switch (account) {
case 0:
return ALICE;
case 1:
return BOB;
case 2:
return CHARLIE;
default:
throw new RuntimeException("Unknown privacy account");
}
}
}

@ -10,34 +10,39 @@
* 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.eea;
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy.condition;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceipt;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory.PrivateTransactionReceiptResponse;
import java.io.IOException;
import org.web3j.protocol.eea.response.PrivateTransactionReceipt;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.protocol.pantheon.Pantheon;
import org.web3j.tx.response.PollingPrivateTransactionReceiptProcessor;
public class EeaGetTransactionReceiptTransaction implements Transaction<PrivateTransactionReceipt> {
private final String txHash;
private final String transactionHash;
public EeaGetTransactionReceiptTransaction(final String txHash) {
this.txHash = txHash;
public EeaGetTransactionReceiptTransaction(final String transactionHash) {
this.transactionHash = transactionHash;
}
@Override
public PrivateTransactionReceipt execute(final NodeRequests node) {
final Pantheon pantheon = node.privacy().getPantheonClient();
final PollingPrivateTransactionReceiptProcessor receiptProcessor =
new PollingPrivateTransactionReceiptProcessor(pantheon, 3, 3);
try {
final PrivateTransactionReceiptResponse result =
node.eea().eeaGetTransactionReceipt(txHash).send();
final PrivateTransactionReceipt result =
receiptProcessor.waitForTransactionReceipt(transactionHash);
assertThat(result).isNotNull();
assertThat(result.hasError()).isFalse();
return result.getResult();
} catch (IOException e) {
return result;
} catch (IOException | TransactionException e) {
return null;
}
}

@ -0,0 +1,34 @@
/*
* Copyright 2019 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.privacy.condition;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions;
public class ExpectNoPrivateTransactionReceipt implements PrivateCondition {
private final PrivacyTransactions transactions;
private final String transactionHash;
public ExpectNoPrivateTransactionReceipt(
final PrivacyTransactions transactions, final String transactionHash) {
this.transactions = transactions;
this.transactionHash = transactionHash;
}
@Override
public void verify(final PrivacyNode node) {
assertThat(node.execute(transactions.getPrivateTransactionReceipt(transactionHash))).isNull();
}
}

@ -0,0 +1,49 @@
/*
* Copyright 2019 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.privacy.condition;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions;
import java.util.List;
import org.awaitility.Awaitility;
import org.web3j.protocol.pantheon.response.privacy.PrivacyGroup;
import org.web3j.utils.Base64String;
public class ExpectValidPrivacyGroupCreated implements PrivateCondition {
private final PrivacyTransactions transactions;
private final PrivacyGroup expected;
public ExpectValidPrivacyGroupCreated(
final PrivacyTransactions transactions, final PrivacyGroup expected) {
this.transactions = transactions;
this.expected = expected;
}
@Override
public void verify(final PrivacyNode node) {
Awaitility.await()
.untilAsserted(
() -> {
final List<PrivacyGroup> groups =
node.execute(
transactions.findPrivacyGroup(
Base64String.unwrapList(expected.getMembers())));
assertThat(groups).contains(expected);
});
}
}

@ -0,0 +1,53 @@
/*
* Copyright 2019 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.privacy.condition;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Optional;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
public class ExpectValidPrivateContractDeployedReceipt implements PrivateContractCondition {
private final String contractAddress;
private final String senderAddress;
public ExpectValidPrivateContractDeployedReceipt(
final String contractAddress, final String senderAddress) {
this.contractAddress = contractAddress;
this.senderAddress = senderAddress;
}
@Override
public void verify(final Contract contract) {
assertThat(contract).isNotNull();
final Optional<TransactionReceipt> 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();
// Address generation is deterministic, based on the sender address and the transaction nonce
assertThat(transactionReceipt.getContractAddress()).isEqualTo(contractAddress);
// Address for the account that signed (and paid) for the contract deployment transaction
assertThat(transactionReceipt.getFrom()).isEqualTo(senderAddress);
}
}

@ -0,0 +1,42 @@
/*
* Copyright 2019 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.privacy.condition;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions;
import org.web3j.protocol.eea.response.PrivateTransactionReceipt;
public class ExpectValidPrivateTransactionReceipt implements PrivateCondition {
private final PrivacyTransactions transactions;
private final String transactionHash;
private final PrivateTransactionReceipt receipt;
public ExpectValidPrivateTransactionReceipt(
final PrivacyTransactions transactions,
final String transactionHash,
final PrivateTransactionReceipt receipt) {
this.transactions = transactions;
this.transactionHash = transactionHash;
this.receipt = receipt;
}
@Override
public void verify(final PrivacyNode node) {
assertThat(node.execute(transactions.getPrivateTransactionReceipt(transactionHash)))
.isEqualTo(receipt);
}
}

@ -10,10 +10,10 @@
* 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.eea;
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy.condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
public interface EeaCondition {
void verify(PantheonNode node, String transactionHash);
public interface PrivateCondition {
void verify(PrivacyNode node);
}

@ -0,0 +1,19 @@
/*
* Copyright 2019 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.privacy.condition;
import org.web3j.tx.Contract;
public interface PrivateContractCondition {
void verify(final Contract contract);
}

@ -0,0 +1,23 @@
/*
* 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.privacy.condition;
public class PrivateContractVerifier {
public PrivateContractVerifier() {}
public ExpectValidPrivateContractDeployedReceipt validPrivateContractDeployed(
final String contractAddress, final String senderAddress) {
return new ExpectValidPrivateContractDeployedReceipt(contractAddress, senderAddress);
}
}

@ -0,0 +1,41 @@
/*
* Copyright 2019 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.privacy.condition;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions;
import org.web3j.protocol.eea.response.PrivateTransactionReceipt;
import org.web3j.protocol.pantheon.response.privacy.PrivacyGroup;
public class PrivateTransactionVerifier {
private final PrivacyTransactions transactions;
public PrivateTransactionVerifier(final PrivacyTransactions transactions) {
this.transactions = transactions;
}
public ExpectValidPrivateTransactionReceipt validPrivateTransactionReceipt(
final String transactionHash, final PrivateTransactionReceipt receipt) {
return new ExpectValidPrivateTransactionReceipt(transactions, transactionHash, receipt);
}
public ExpectNoPrivateTransactionReceipt noPrivateTransactionReceipt(
final String transactionHash) {
return new ExpectNoPrivateTransactionReceipt(transactions, transactionHash);
}
public ExpectValidPrivacyGroupCreated validPrivacyGroupCreated(final PrivacyGroup expected) {
return new ExpectValidPrivacyGroupCreated(transactions, expected);
}
}

@ -0,0 +1,77 @@
/*
* Copyright 2019 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.privacy.contract;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.pantheon.Pantheon;
import org.web3j.tx.LegacyPrivateTransactionManager;
import org.web3j.tx.PrivateTransactionManager;
import org.web3j.tx.gas.PantheonPrivacyGasProvider;
import org.web3j.utils.Base64String;
public class CallPrivateSmartContractFunction implements Transaction<String> {
private static final PantheonPrivacyGasProvider GAS_PROVIDER =
new PantheonPrivacyGasProvider(BigInteger.valueOf(1000));
private final String contractAddress;
private final String encodedFunction;
private final Credentials senderCredentials;
private final long chainId;
private final Base64String privateFrom;
private final List<Base64String> privateFor;
public CallPrivateSmartContractFunction(
final String contractAddress,
final String encodedFunction,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final List<String> privateFor) {
this.contractAddress = contractAddress;
this.encodedFunction = encodedFunction;
this.senderCredentials = Credentials.create(transactionSigningKey);
this.chainId = chainId;
this.privateFrom = Base64String.wrap(privateFrom);
this.privateFor = Base64String.wrapList(privateFor);
}
@Override
public String execute(final NodeRequests node) {
final Pantheon pantheon = node.privacy().getPantheonClient();
final PrivateTransactionManager privateTransactionManager =
new LegacyPrivateTransactionManager(
pantheon, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privateFor);
try {
return privateTransactionManager
.sendTransaction(
GAS_PROVIDER.getGasPrice(),
GAS_PROVIDER.getGasLimit(),
contractAddress,
encodedFunction,
null)
.getTransactionHash();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,90 @@
/*
* Copyright 2019 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.privacy.contract;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.List;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.tx.Contract;
import org.web3j.tx.LegacyPrivateTransactionManager;
import org.web3j.tx.PrivateTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.PantheonPrivacyGasProvider;
import org.web3j.utils.Base64String;
public class DeployPrivateSmartContractTransaction<T extends Contract> implements Transaction<T> {
private static final PantheonPrivacyGasProvider GAS_PROVIDER =
new PantheonPrivacyGasProvider(BigInteger.valueOf(1000));
private static final Object METHOD_IS_STATIC = null;
private final Class<T> clazz;
private final Credentials senderCredentials;
private final long chainId;
private final Base64String privateFrom;
private final List<Base64String> privateFor;
public DeployPrivateSmartContractTransaction(
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final List<String> privateFor) {
this.clazz = clazz;
this.senderCredentials = Credentials.create(transactionSigningKey);
this.chainId = chainId;
this.privateFrom = Base64String.wrap(privateFrom);
this.privateFor = Base64String.wrapList(privateFor);
}
@Override
public T execute(final NodeRequests node) {
final PrivateTransactionManager privateTransactionManager =
new LegacyPrivateTransactionManager(
node.privacy().getPantheonClient(),
GAS_PROVIDER,
senderCredentials,
chainId,
privateFrom,
privateFor);
try {
final Method method =
clazz.getMethod(
"deploy", Web3j.class, TransactionManager.class, ContractGasProvider.class);
final Object invoked =
method.invoke(
METHOD_IS_STATIC,
node.privacy().getPantheonClient(),
privateTransactionManager,
GAS_PROVIDER);
return cast(invoked).send();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
private RemoteCall<T> cast(final Object invokedMethod) {
return (RemoteCall<T>) invokedMethod;
}
}

@ -0,0 +1,90 @@
/*
* Copyright 2019 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.privacy.contract;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.lang.reflect.Method;
import java.math.BigInteger;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.tx.Contract;
import org.web3j.tx.PantheonPrivateTransactionManager;
import org.web3j.tx.PrivateTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.PantheonPrivacyGasProvider;
import org.web3j.utils.Base64String;
public class DeployPrivateSmartContractWithPrivacyGroupIdTransaction<T extends Contract>
implements Transaction<T> {
private static final PantheonPrivacyGasProvider GAS_PROVIDER =
new PantheonPrivacyGasProvider(BigInteger.valueOf(1000));
private static final Object METHOD_IS_STATIC = null;
private final Class<T> clazz;
private final Credentials senderCredentials;
private final long chainId;
private final Base64String privateFrom;
private final Base64String privacyGroupId;
public DeployPrivateSmartContractWithPrivacyGroupIdTransaction(
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final String privacyGroupId) {
this.clazz = clazz;
this.senderCredentials = Credentials.create(transactionSigningKey);
this.chainId = chainId;
this.privateFrom = Base64String.wrap(privateFrom);
this.privacyGroupId = Base64String.wrap(privacyGroupId);
}
@Override
public T execute(final NodeRequests node) {
final PrivateTransactionManager privateTransactionManager =
new PantheonPrivateTransactionManager(
node.privacy().getPantheonClient(),
GAS_PROVIDER,
senderCredentials,
chainId,
privateFrom,
privacyGroupId);
try {
final Method method =
clazz.getMethod(
"deploy", Web3j.class, TransactionManager.class, ContractGasProvider.class);
final Object invoked =
method.invoke(
METHOD_IS_STATIC,
node.privacy().getPantheonClient(),
privateTransactionManager,
GAS_PROVIDER);
return cast(invoked).send();
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
@SuppressWarnings("unchecked")
private RemoteCall<T> cast(final Object invokedMethod) {
return (RemoteCall<T>) invokedMethod;
}
}

@ -0,0 +1,91 @@
/*
* Copyright 2019 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.privacy.contract;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.List;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.tx.Contract;
import org.web3j.tx.LegacyPrivateTransactionManager;
import org.web3j.tx.PrivateTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.PantheonPrivacyGasProvider;
import org.web3j.utils.Base64String;
public class LoadPrivateSmartContractTransaction<T extends Contract> implements Transaction<T> {
private static final PantheonPrivacyGasProvider GAS_PROVIDER =
new PantheonPrivacyGasProvider(BigInteger.valueOf(1000));
private static final Object METHOD_IS_STATIC = null;
private final Class<T> clazz;
private final Credentials senderCredentials;
private final long chainId;
private final Base64String privateFrom;
private final List<Base64String> privateFor;
private String contractAddress;
public LoadPrivateSmartContractTransaction(
final String contractAddress,
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final List<String> privateFor) {
this.contractAddress = contractAddress;
this.clazz = clazz;
this.senderCredentials = Credentials.create(transactionSigningKey);
this.chainId = chainId;
this.privateFrom = Base64String.wrap(privateFrom);
this.privateFor = Base64String.wrapList(privateFor);
}
@SuppressWarnings("unchecked")
@Override
public T execute(final NodeRequests node) {
final PrivateTransactionManager privateTransactionManager =
new LegacyPrivateTransactionManager(
node.privacy().getPantheonClient(),
GAS_PROVIDER,
senderCredentials,
chainId,
privateFrom,
privateFor);
try {
final Method method =
clazz.getMethod(
"load",
String.class,
Web3j.class,
TransactionManager.class,
ContractGasProvider.class);
return (T)
method.invoke(
METHOD_IS_STATIC,
contractAddress,
node.privacy().getPantheonClient(),
privateTransactionManager,
GAS_PROVIDER);
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}

@ -0,0 +1,107 @@
/*
* Copyright 2019 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.privacy.contract;
import java.util.Arrays;
import java.util.List;
import org.web3j.tx.Contract;
public class PrivateContractTransactions {
public <T extends Contract>
DeployPrivateSmartContractWithPrivacyGroupIdTransaction<T>
createSmartContractWithPrivacyGroupId(
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final String privacyGroupId) {
return new DeployPrivateSmartContractWithPrivacyGroupIdTransaction<>(
clazz, transactionSigningKey, chainId, privateFrom, privacyGroupId);
}
public <T extends Contract> DeployPrivateSmartContractTransaction<T> createSmartContract(
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final String... privateFor) {
return createSmartContract(
clazz, transactionSigningKey, chainId, privateFrom, Arrays.asList(privateFor));
}
public <T extends Contract> DeployPrivateSmartContractTransaction<T> createSmartContract(
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final List<String> privateFor) {
return new DeployPrivateSmartContractTransaction<>(
clazz, transactionSigningKey, chainId, privateFrom, privateFor);
}
public CallPrivateSmartContractFunction callSmartContract(
final String contractAddress,
final String encodedFunction,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final String... privateFor) {
return callSmartContract(
contractAddress,
encodedFunction,
transactionSigningKey,
chainId,
privateFrom,
Arrays.asList(privateFor));
}
public CallPrivateSmartContractFunction callSmartContract(
final String contractAddress,
final String encodedFunction,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final List<String> privateFor) {
return new CallPrivateSmartContractFunction(
contractAddress, encodedFunction, transactionSigningKey, chainId, privateFrom, privateFor);
}
public <T extends Contract> LoadPrivateSmartContractTransaction<T> loadSmartContract(
final String contractAddress,
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final String... privateFor) {
return loadSmartContract(
contractAddress,
clazz,
transactionSigningKey,
chainId,
privateFrom,
Arrays.asList(privateFor));
}
private <T extends Contract> LoadPrivateSmartContractTransaction<T> loadSmartContract(
final String contractAddress,
final Class<T> clazz,
final String transactionSigningKey,
final long chainId,
final String privateFrom,
final List<String> privateFor) {
return new LoadPrivateSmartContractTransaction<>(
contractAddress, clazz, transactionSigningKey, chainId, privateFrom, privateFor);
}
}

@ -10,38 +10,45 @@
* 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.priv;
import static org.assertj.core.api.Assertions.assertThat;
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PrivCreatePrivacyGroupTransaction implements Transaction<String> {
import org.web3j.protocol.pantheon.Pantheon;
import org.web3j.utils.Base64String;
private final List<String> addresses;
public class CreatePrivacyGroupTransaction implements Transaction<String> {
private final String name;
private final String description;
private final List<Base64String> addresses;
public PrivCreatePrivacyGroupTransaction(
final List<String> addresses, final String name, final String description) {
this.addresses = addresses;
public CreatePrivacyGroupTransaction(
final String name, final String description, final PrivacyNode... nodes) {
this.name = name;
this.description = description;
this.addresses =
Arrays.stream(nodes)
.map(n -> Base64String.wrap(n.getOrion().getDefaultPublicKey()))
.collect(Collectors.toList());
}
@Override
public String execute(final NodeRequests node) {
final Pantheon pantheon = node.privacy().getPantheonClient();
try {
PrivRequestFactory.PrivCreatePrivacyGroupResponse result =
node.priv().privCreatePrivacyGroup(addresses, name, description).send();
assertThat(result).isNotNull();
return result.getResult();
} catch (final IOException e) {
return pantheon
.privCreatePrivacyGroup(addresses, name, description)
.send()
.getPrivacyGroupId()
.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@ -10,34 +10,33 @@
* 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.priv;
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.enclave.types.PrivacyGroup;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
public class PrivFindPrivacyGroupTransaction implements Transaction<List<PrivacyGroup>> {
import org.web3j.protocol.pantheon.Pantheon;
import org.web3j.protocol.pantheon.response.privacy.PrivacyGroup;
import org.web3j.utils.Base64String;
private final List<String> addresses;
public class FindPrivacyGroupTransaction implements Transaction<List<PrivacyGroup>> {
private List<Base64String> nodes;
public PrivFindPrivacyGroupTransaction(final List<String> addresses) {
public FindPrivacyGroupTransaction(final List<String> nodeEnclaveKeys) {
this.addresses = addresses;
this.nodes = nodeEnclaveKeys.stream().map(Base64String::wrap).collect(Collectors.toList());
}
@Override
public List<PrivacyGroup> execute(final NodeRequests node) {
final Pantheon pantheon = node.privacy().getPantheonClient();
try {
PrivRequestFactory.PrivFindPrivacyGroupResponse result =
node.priv().privFindPrivacyGroup(addresses).send();
assertThat(result).isNotNull();
return result.getResult();
} catch (final IOException e) {
return pantheon.privFindPrivacyGroup(nodes).send().getGroups();
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@ -0,0 +1,57 @@
/*
* Copyright 2019 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.privacy.transaction;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.methods.response.EthBlock;
import org.web3j.protocol.pantheon.Pantheon;
public class GetAllPrivacyMarkerTransactionHashes implements Transaction<List<String>> {
@Override
public List<String> execute(final NodeRequests node) {
final Pantheon pantheon = node.privacy().getPantheonClient();
final List<String> toReturn = new ArrayList<>();
try {
final long blockchainHeight =
pantheon.ethBlockNumber().send().getBlockNumber().longValueExact();
for (int i = 0; i <= blockchainHeight; i++) {
pantheon
.ethGetBlockByNumber(DefaultBlockParameter.valueOf(BigInteger.valueOf(i)), true)
.send()
.getBlock()
.getTransactions()
.forEach(
t -> {
if (((EthBlock.TransactionObject) t)
.getTo()
.equals(Address.DEFAULT_PRIVACY.toString())) {
toReturn.add(((EthBlock.TransactionObject) t).getHash());
}
});
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return toReturn;
}
}

@ -10,23 +10,26 @@
* 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.eea;
package tech.pegasys.pantheon.tests.acceptance.dsl.privacy.transaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivGetTransactionCountTransaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.condition.EeaGetTransactionReceiptTransaction;
public class EeaTransactions {
import java.util.List;
public EeaGetTransactionReceiptTransaction getTransactionReceipt(final String transactionHash) {
public class PrivacyTransactions {
public EeaGetTransactionReceiptTransaction getPrivateTransactionReceipt(
final String transactionHash) {
return new EeaGetTransactionReceiptTransaction(transactionHash);
}
public PrivGetTransactionCountTransaction getTransactionCount(
final String address, final String privacyGroupId) {
return new PrivGetTransactionCountTransaction(address, privacyGroupId);
public CreatePrivacyGroupTransaction createPrivacyGroup(
final String name, final String description, final PrivacyNode... nodes) {
return new CreatePrivacyGroupTransaction(name, description, nodes);
}
public EeaGetTransactionReceiptTransaction getPrivateTransactionReceipt(
final String transactionHash) {
return new EeaGetTransactionReceiptTransaction(transactionHash);
public FindPrivacyGroupTransaction findPrivacyGroup(final List<String> nodes) {
return new FindPrivacyGroupTransaction(nodes);
}
}

@ -14,13 +14,12 @@ package tech.pegasys.pantheon.tests.acceptance.dsl.transaction;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.admin.AdminRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.clique.CliqueRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.EeaRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.ibft2.Ibft2RequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.login.LoginRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.miner.MinerRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.net.CustomRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.perm.PermissioningJsonRpcRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.priv.PrivRequestFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory;
import java.util.Optional;
@ -34,8 +33,7 @@ public class NodeRequests {
private final Ibft2RequestFactory ibft;
private final PermissioningJsonRpcRequestFactory perm;
private final AdminRequestFactory admin;
private final EeaRequestFactory eea;
private final PrivRequestFactory priv;
private final PrivacyRequestFactory privacy;
private final CustomRequestFactory custom;
private final Optional<WebSocketService> websocketService;
private final LoginRequestFactory login;
@ -47,8 +45,7 @@ public class NodeRequests {
final Ibft2RequestFactory ibft,
final PermissioningJsonRpcRequestFactory perm,
final AdminRequestFactory admin,
final EeaRequestFactory eea,
final PrivRequestFactory priv,
final PrivacyRequestFactory privacy,
final CustomRequestFactory custom,
final MinerRequestFactory miner,
final Optional<WebSocketService> websocketService,
@ -58,8 +55,7 @@ public class NodeRequests {
this.ibft = ibft;
this.perm = perm;
this.admin = admin;
this.eea = eea;
this.priv = priv;
this.privacy = privacy;
this.custom = custom;
this.miner = miner;
this.websocketService = websocketService;
@ -94,12 +90,8 @@ public class NodeRequests {
return custom;
}
public EeaRequestFactory eea() {
return eea;
}
public PrivRequestFactory priv() {
return priv;
public PrivacyRequestFactory privacy() {
return privacy;
}
public LoginRequestFactory login() {

@ -1,101 +0,0 @@
/*
* Copyright 2019 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.eea;
import java.util.Collections;
import java.util.List;
import org.assertj.core.util.Lists;
import org.web3j.protocol.Web3jService;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.Response;
import org.web3j.protocol.core.methods.response.Log;
public class EeaRequestFactory {
public static class PrivateTransactionReceiptResponse
extends Response<PrivateTransactionReceipt> {}
public static class PrivateTransactionReceipt {
private String contractAddress;
private String from;
private String to;
private String output;
private List<Log> logs;
public PrivateTransactionReceipt() {}
public String getContractAddress() {
return contractAddress;
}
public void setContractAddress(final String contractAddress) {
this.contractAddress = contractAddress;
}
public String getFrom() {
return from;
}
public void setFrom(final String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(final String to) {
this.to = to;
}
public List<Log> getLogs() {
return logs;
}
public void setLogs(final List<Log> logs) {
this.logs = logs;
}
public String getOutput() {
return output;
}
public void setOutput(final String output) {
this.output = output;
}
}
private final Web3jService web3jService;
public EeaRequestFactory(final Web3jService web3jService) {
this.web3jService = web3jService;
}
Request<?, org.web3j.protocol.core.methods.response.EthSendTransaction> eeaSendRawTransaction(
final String signedTransactionData) {
return new Request<>(
"eea_sendRawTransaction",
Collections.singletonList(signedTransactionData),
web3jService,
org.web3j.protocol.core.methods.response.EthSendTransaction.class);
}
Request<?, PrivateTransactionReceiptResponse> eeaGetTransactionReceipt(final String txHash) {
return new Request<>(
"eea_getTransactionReceipt",
Lists.newArrayList(txHash),
web3jService,
PrivateTransactionReceiptResponse.class);
}
}

@ -1,42 +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.transaction.eea;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
public class EeaSendRawTransactionTransaction implements Transaction<String> {
private final String transactionData;
public EeaSendRawTransactionTransaction(final String transactionData) {
this.transactionData = transactionData;
}
@Override
public String execute(final NodeRequests node) {
try {
EthSendTransaction response = node.eea().eeaSendRawTransaction(transactionData).send();
assertThat(response.getTransactionHash()).isNotNull();
return response.getTransactionHash();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -1,149 +0,0 @@
/*
* Copyright 2019 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.eea;
import tech.pegasys.pantheon.crypto.SECP256K1;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.ethereum.privacy.Restriction;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class PrivateTransactionBuilder {
public static BytesValue EVENT_EMITTER_CONSTRUCTOR =
BytesValue.fromHexString(
"0x608060405234801561001057600080fd5b5060008054600160a06"
+ "0020a03191633179055610199806100326000396000f3fe6080"
+ "604052600436106100565763ffffffff7c01000000000000000"
+ "000000000000000000000000000000000000000006000350416"
+ "633fa4f245811461005b5780636057361d1461008257806367e"
+ "404ce146100ae575b600080fd5b34801561006757600080fd5b"
+ "506100706100ec565b60408051918252519081900360200190f"
+ "35b34801561008e57600080fd5b506100ac6004803603602081"
+ "10156100a557600080fd5b50356100f2565b005b3480156100b"
+ "a57600080fd5b506100c3610151565b6040805173ffffffffff"
+ "ffffffffffffffffffffffffffffff909216825251908190036"
+ "0200190f35b60025490565b6040805133815260208101839052"
+ "81517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb1"
+ "2b753f3d1aaa2d8f9f5929181900390910190a1600255600180"
+ "5473ffffffffffffffffffffffffffffffffffffffff1916331"
+ "79055565b60015473ffffffffffffffffffffffffffffffffff"
+ "ffffff169056fea165627a7a72305820c7f729cb24e05c221f5"
+ "aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029");
private static BytesValue SET_FUNCTION_CALL =
BytesValue.fromHexString(
"0x6057361d00000000000000000000000000000000000000000000000000000000000003e8");
private static BytesValue GET_FUNCTION_CALL = BytesValue.fromHexString("0x3fa4f245");
public enum TransactionType {
CREATE_CONTRACT,
STORE,
GET
}
public static PrivateTransactionBuilder.Builder builder() {
return new PrivateTransactionBuilder.Builder();
}
public static class Builder {
long nonce;
Address from;
Address to;
BytesValue privateFrom;
Optional<BytesValue> privacyGroupId = Optional.empty();
Optional<List<BytesValue>> privateFor = Optional.of(new ArrayList<>());
SECP256K1.KeyPair keyPair;
public Builder nonce(final long nonce) {
this.nonce = nonce;
return this;
}
public Builder from(final Address from) {
this.from = from;
return this;
}
public Builder to(final Address to) {
this.to = to;
return this;
}
public Builder privateFrom(final BytesValue privateFrom) {
this.privateFrom = privateFrom;
return this;
}
public Builder privacyGroupId(final BytesValue privacyGroupId) {
this.privacyGroupId = Optional.of(privacyGroupId);
return this;
}
public Builder privateFor(final List<BytesValue> privateFor) {
this.privateFor = Optional.of(privateFor);
return this;
}
public Builder keyPair(final SECP256K1.KeyPair keyPair) {
this.keyPair = keyPair;
return this;
}
public String build(final TransactionType type) {
BytesValue payload;
switch (type) {
case CREATE_CONTRACT:
payload = EVENT_EMITTER_CONSTRUCTOR;
break;
case STORE:
payload = SET_FUNCTION_CALL;
break;
case GET:
payload = GET_FUNCTION_CALL;
break;
default:
throw new IllegalStateException("Unexpected value: " + type);
}
var builder =
PrivateTransaction.builder()
.nonce(nonce)
.gasPrice(Wei.of(1000))
.gasLimit(63992)
.to(to)
.value(Wei.ZERO)
.payload(payload)
.sender(from)
.chainId(BigInteger.valueOf(2018))
.privateFrom(privateFrom)
.restriction(Restriction.RESTRICTED);
if (privacyGroupId.isPresent()) {
builder = builder.privacyGroupId(privacyGroupId.get());
} else {
builder = builder.privateFor(privateFor.get());
}
return RLP.encode(builder.signAndBuild(keyPair)::writeTo).toString();
}
}
}

@ -1,44 +0,0 @@
/*
* Copyright 2019 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.priv;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.List;
public class PrivCreatePrivacyGroupTransactionWithoutDescription implements Transaction<String> {
private final List<String> addresses;
private final String name;
public PrivCreatePrivacyGroupTransactionWithoutDescription(
final List<String> addresses, final String name) {
this.addresses = addresses;
this.name = name;
}
@Override
public String execute(final NodeRequests node) {
try {
final PrivRequestFactory.PrivCreatePrivacyGroupResponse result =
node.priv().privCreatePrivacyGroupWithoutDescription(addresses, name).send();
assertThat(result).isNotNull();
return result.getResult();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -1,44 +0,0 @@
/*
* Copyright 2019 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.priv;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.List;
public class PrivCreatePrivacyGroupTransactionWithoutName implements Transaction<String> {
private final List<String> addresses;
private final String description;
public PrivCreatePrivacyGroupTransactionWithoutName(
final List<String> addresses, final String description) {
this.addresses = addresses;
this.description = description;
}
@Override
public String execute(final NodeRequests node) {
try {
final PrivRequestFactory.PrivCreatePrivacyGroupResponse result =
node.priv().privCreatePrivacyGroupWithoutName(addresses, description).send();
assertThat(result).isNotNull();
return result.getResult();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -1,43 +0,0 @@
/*
* Copyright 2019 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.priv;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.util.List;
public class PrivCreatePrivacyGroupWithoutOptionalParamsTransaction implements Transaction<String> {
private final List<String> addresses;
public PrivCreatePrivacyGroupWithoutOptionalParamsTransaction(final List<String> addresses) {
this.addresses = addresses;
}
@Override
public String execute(final NodeRequests node) {
try {
PrivRequestFactory.PrivCreatePrivacyGroupResponse result =
node.priv().privCreatePrivacyGroupWithoutOptionalParams(addresses).send();
assertThat(result).isNotNull();
return result.getResult();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -1,47 +0,0 @@
/*
* Copyright 2019 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.priv;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.NodeRequests;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.Transaction;
import java.io.IOException;
import java.math.BigInteger;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
public class PrivGetTransactionCountTransaction implements Transaction<BigInteger> {
private final String accountAddress;
private String privacyGroupId;
public PrivGetTransactionCountTransaction(
final String accountAddress, final String privacyGroupId) {
this.accountAddress = accountAddress;
this.privacyGroupId = privacyGroupId;
}
@Override
public BigInteger execute(final NodeRequests node) {
try {
EthGetTransactionCount result =
node.priv().privGetTransactionCount(accountAddress, privacyGroupId).send();
assertThat(result).isNotNull();
return result.getTransactionCount();
} catch (final IOException e) {
throw new RuntimeException(e);
}
}
}

@ -1,96 +0,0 @@
/*
* Copyright 2019 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.priv;
import tech.pegasys.pantheon.enclave.types.PrivacyGroup;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.privacy.parameters.CreatePrivacyGroupParameter;
import java.util.Collections;
import java.util.List;
import org.assertj.core.util.Lists;
import org.web3j.protocol.Web3jService;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.Response;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
public class PrivRequestFactory {
public static class PrivCreatePrivacyGroupResponse extends Response<String> {}
public static class PrivFindPrivacyGroupResponse extends Response<List<PrivacyGroup>> {}
private final Web3jService web3jService;
public PrivRequestFactory(final Web3jService web3jService) {
this.web3jService = web3jService;
}
public Request<?, EthGetTransactionCount> privGetTransactionCount(
final String accountAddress, final String privacyGroupId) {
return new Request<>(
"priv_getTransactionCount",
Lists.newArrayList(accountAddress, privacyGroupId),
web3jService,
EthGetTransactionCount.class);
}
public Request<?, PrivCreatePrivacyGroupResponse> privCreatePrivacyGroup(
final List<String> addresses, final String name, final String description) {
return new Request<>(
"priv_createPrivacyGroup",
Lists.newArrayList(
new CreatePrivacyGroupParameter(addresses.toArray(new String[] {}), name, description)),
web3jService,
PrivCreatePrivacyGroupResponse.class);
}
public Request<?, PrivCreatePrivacyGroupResponse> privCreatePrivacyGroupWithoutName(
final List<String> addresses, final String description) {
return new Request<>(
"priv_createPrivacyGroup",
Collections.singletonList(
new CreatePrivacyGroupParameter(addresses.toArray(new String[] {}), null, description)),
web3jService,
PrivCreatePrivacyGroupResponse.class);
}
public Request<?, PrivCreatePrivacyGroupResponse> privCreatePrivacyGroupWithoutDescription(
final List<String> addresses, final String name) {
return new Request<>(
"priv_createPrivacyGroup",
Collections.singletonList(
new CreatePrivacyGroupParameter(addresses.toArray(new String[] {}), name, null)),
web3jService,
PrivCreatePrivacyGroupResponse.class);
}
public Request<?, PrivCreatePrivacyGroupResponse> privCreatePrivacyGroupWithoutOptionalParams(
final List<String> addresses) {
return new Request<>(
"priv_createPrivacyGroup",
Collections.singletonList(
new CreatePrivacyGroupParameter(addresses.toArray(new String[] {}), null, null)),
web3jService,
PrivCreatePrivacyGroupResponse.class);
}
public Request<?, PrivFindPrivacyGroupResponse> privFindPrivacyGroup(
final List<String> addresses) {
return new Request<>(
"priv_findPrivacyGroup",
Collections.singletonList(addresses),
web3jService,
PrivFindPrivacyGroupResponse.class);
}
}

@ -0,0 +1,28 @@
/*
* Copyright 2019 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.privacy;
import org.web3j.protocol.Web3jService;
import org.web3j.protocol.pantheon.Pantheon;
public class PrivacyRequestFactory {
private final Pantheon pantheonClient;
public PrivacyRequestFactory(final Web3jService web3jService) {
this.pantheonClient = Pantheon.build(web3jService);
}
public Pantheon getPantheonClient() {
return pantheonClient;
}
}

@ -1,5 +1,5 @@
/*
* Copyright 2018 ConsenSys AG.
* Copyright 2019 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
@ -30,7 +30,9 @@ import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.BaseEventResponse;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
@ -46,11 +48,11 @@ import org.web3j.tx.gas.ContractGasProvider;
* or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the <a
* href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 4.0.1.
* <p>Generated with web3j version 4.4.1.
*/
@SuppressWarnings("rawtypes")
public class EventEmitter extends Contract {
private static final String BINARY =
public static final String BINARY =
"608060405234801561001057600080fd5b5060008054600160a060020a03191633179055610199806100326000396000f3fe6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f245811461005b5780636057361d1461008257806367e404ce146100ae575b600080fd5b34801561006757600080fd5b506100706100ec565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100ac600480360360208110156100a557600080fd5b50356100f2565b005b3480156100ba57600080fd5b506100c3610151565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a16002556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b60015473ffffffffffffffffffffffffffffffffffffffff169056fea165627a7a72305820c7f729cb24e05c221f5aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029";
public static final String FUNC_VALUE = "value";
@ -101,7 +103,7 @@ public class EventEmitter extends Contract {
super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
}
public RemoteCall<BigInteger> value() {
public RemoteFunctionCall<BigInteger> value() {
final Function function =
new Function(
FUNC_VALUE,
@ -110,7 +112,7 @@ public class EventEmitter extends Contract {
return executeRemoteCallSingleValueReturn(function, BigInteger.class);
}
public RemoteCall<TransactionReceipt> store(BigInteger _amount) {
public RemoteFunctionCall<TransactionReceipt> store(BigInteger _amount) {
final Function function =
new Function(
FUNC_STORE,
@ -119,7 +121,7 @@ public class EventEmitter extends Contract {
return executeRemoteCallTransaction(function);
}
public RemoteCall<String> sender() {
public RemoteFunctionCall<String> sender() {
final Function function =
new Function(
FUNC_SENDER,
@ -146,15 +148,18 @@ public class EventEmitter extends Contract {
return web3j
.ethLogFlowable(filter)
.map(
log -> {
Contract.EventValuesWithLog eventValues =
extractEventParametersWithLog(STORED_EVENT, log);
StoredEventResponse typedResponse = new StoredEventResponse();
typedResponse.log = log;
typedResponse._to = (String) eventValues.getNonIndexedValues().get(0).getValue();
typedResponse._amount =
(BigInteger) eventValues.getNonIndexedValues().get(1).getValue();
return typedResponse;
new io.reactivex.functions.Function<Log, StoredEventResponse>() {
@Override
public StoredEventResponse apply(Log log) {
Contract.EventValuesWithLog eventValues =
extractEventParametersWithLog(STORED_EVENT, log);
StoredEventResponse typedResponse = new StoredEventResponse();
typedResponse.log = log;
typedResponse._to = (String) eventValues.getNonIndexedValues().get(0).getValue();
typedResponse._amount =
(BigInteger) eventValues.getNonIndexedValues().get(1).getValue();
return typedResponse;
}
});
}
@ -229,9 +234,7 @@ public class EventEmitter extends Contract {
EventEmitter.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "");
}
public static class StoredEventResponse {
public Log log;
public static class StoredEventResponse extends BaseEventResponse {
public String _to;
public BigInteger _amount;

@ -13,53 +13,40 @@
package tech.pegasys.pantheon.tests.web3j.privacy;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.web3j.generated.EventEmitter;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class DeployPrivateSmartContractAcceptanceTest extends PrivacyAcceptanceTestBase {
protected static final String CONTRACT_NAME = "Event Emitter";
private static final long POW_CHAIN_ID = 2018;
private EventEmitterHarness eventEmitterHarness;
private PrivacyNet privacyNet;
private PrivacyNode minerNode;
@Before
public void setUp() throws Exception {
privacyNet =
PrivacyNet.builder(privacy, privacyPantheon, cluster, false).addMinerNode("Alice").build();
privacyNet.startPrivacyNet();
eventEmitterHarness =
new EventEmitterHarness(
privateTransactionBuilder,
privacyNet,
privateTransactions,
privateTransactionVerifier,
eea);
minerNode =
privacyPantheon.createPrivateTransactionEnabledMinerNode(
"miner-node", privacyAccountResolver.resolve(0));
privacyCluster.start(minerNode);
}
@Test
public void deployingMustGiveValidReceipt() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice");
}
@Test
public void privateSmartContractMustEmitEvents() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice");
eventEmitterHarness.store(CONTRACT_NAME, "Alice");
}
@Test
public void privateSmartContractMustReturnValues() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice");
eventEmitterHarness.store(CONTRACT_NAME, "Alice");
eventEmitterHarness.get(CONTRACT_NAME, "Alice");
}
@After
public void tearDown() {
privacyNet.stopPrivacyNet();
final String contractAddress = "0x89ce396d0f9f937ddfa71113e29b2081c4869555";
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
POW_CHAIN_ID,
minerNode.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString())
.verify(eventEmitter);
}
}

@ -12,103 +12,69 @@
*/
package tech.pegasys.pantheon.tests.web3j.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static tech.pegasys.pantheon.tests.web3j.privacy.PrivacyGroup.generatePrivacyGroup;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcError;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder.TransactionType;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.web3j.generated.EventEmitter;
import java.util.Base64;
import com.google.common.collect.Lists;
import net.consensys.cava.crypto.sodium.Box;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class EnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBase {
protected static final String CONTRACT_NAME = "Event Emitter";
private EventEmitterHarness eventEmitterHarness;
private PrivacyNet privacyNet;
private BytesValue wrongPublicKey;
private BytesValue privacyGroup;
private static final long IBFT2_CHAIN_ID = 4;
private PrivacyNode alice;
private PrivacyNode bob;
private String wrongPublicKey;
@Before
public void setUp() throws Exception {
privacyNet =
PrivacyNet.builder(privacy, privacyPantheon, cluster, false).addMinerNode("Alice").build();
privacyNet.startPrivacyNet();
privacyGroup = generatePrivacyGroup(privacyNet, "Alice");
eventEmitterHarness =
new EventEmitterHarness(
privateTransactionBuilder,
privacyNet,
privateTransactions,
privateTransactionVerifier,
eea);
alice =
privacyPantheon.createIbft2NodePrivacyEnabled("node1", privacyAccountResolver.resolve(0));
bob = privacyPantheon.createIbft2NodePrivacyEnabled("node2", privacyAccountResolver.resolve(1));
privacyCluster.start(alice, bob);
wrongPublicKey =
BytesValues.fromBase64(
Base64.getEncoder().encode(Box.KeyPair.random().publicKey().bytesArray()));
Base64.getEncoder().encodeToString(Box.KeyPair.random().publicKey().bytesArray());
}
@Test
@SuppressWarnings("MissingFail")
public void enclaveNoMatchingPrivateKeyError() {
final String invalidDeploy =
PrivateTransactionBuilder.builder()
.nonce(privacyNet.getNode("Alice").nextNonce(privacyGroup))
.from(privacyNet.getNode("Alice").getAddress())
.privateFrom(wrongPublicKey)
.keyPair(privacyNet.getNode("Alice").keyPair())
.build(TransactionType.CREATE_CONTRACT);
final Throwable thrown =
public void aliceCannotSendTransactionFromBobNode() {
final Throwable throwable =
catchThrowable(
() ->
privacyNet
.getNode("Alice")
.execute(privateTransactions.createPrivateRawTransaction(invalidDeploy)));
assertThat(thrown)
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
wrongPublicKey,
bob.getEnclaveKey())));
assertThat(throwable)
.hasMessageContaining(JsonRpcError.ENCLAVE_NO_MATCHING_PRIVATE_KEY.getMessage());
}
@Test
@SuppressWarnings("MissingFail")
public void enclaveNoPeerUrlError() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice");
final String invalidStore =
PrivateTransactionBuilder.builder()
.nonce(privacyNet.getNode("Alice").nextNonce(privacyGroup))
.from(privacyNet.getNode("Alice").getAddress())
.privateFrom(
BytesValues.fromBase64(privacyNet.getEnclave("Alice").getPublicKeys().get(0)))
.privateFor(Lists.newArrayList(wrongPublicKey))
.keyPair(privacyNet.getNode("Alice").keyPair())
.build(TransactionType.CREATE_CONTRACT);
final Throwable thrown =
final Throwable throwable =
catchThrowable(
() ->
privacyNet
.getNode("Alice")
.execute(privateTransactions.createPrivateRawTransaction(invalidStore)));
assertThat(thrown).hasMessageContaining(JsonRpcError.NODE_MISSING_PEER_URL.getMessage());
}
@After
public void tearDown() {
privacyNet.stopPrivacyNet();
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
wrongPublicKey)));
assertThat(throwable).hasMessageContaining(JsonRpcError.NODE_MISSING_PEER_URL.getMessage());
}
}

@ -12,16 +12,12 @@
*/
package tech.pegasys.pantheon.tests.web3j.privacy;
import static tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder.EVENT_EMITTER_CONSTRUCTOR;
import static tech.pegasys.pantheon.tests.web3j.privacy.PrivacyGroup.generatePrivacyGroup;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.EthSignerClient;
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarness;
import tech.pegasys.pantheon.tests.acceptance.dsl.ethsigner.testutil.EthSignerTestHarnessFactory;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.web3j.generated.EventEmitter;
import java.io.IOException;
import java.math.BigInteger;
@ -29,52 +25,47 @@ import java.util.Collections;
import org.junit.Before;
import org.junit.Test;
import org.web3j.protocol.eea.response.PrivateTransactionReceipt;
public class EthSignerAcceptanceTest extends PrivacyAcceptanceTestBase {
private PrivacyNet privacyNet;
private PrivacyNode minerNode;
private EthSignerClient ethSignerClient;
@Before
public void setUp() throws Exception {
privacyNet =
PrivacyNet.builder(privacy, privacyPantheon, cluster, false).addMinerNode("Alice").build();
privacyNet.startPrivacyNet();
minerNode =
privacyPantheon.createPrivateTransactionEnabledMinerNode(
"miner-node", privacyAccountResolver.resolve(0));
privacyCluster.start(minerNode);
final EthSignerTestHarness ethSigner =
EthSignerTestHarnessFactory.create(
privacy.newFolder().toPath(),
"ethSignerKey--fe3b557e8fb62b89f4916b721be55ceb828dbd73.json",
privacyNet.getNode("Alice").getJsonRpcSocketPort().orElseThrow(),
minerNode.getPantheon().getJsonRpcSocketPort().orElseThrow(),
2018);
ethSignerClient = new EthSignerClient(ethSigner.getHttpListeningUrl());
}
@Test
public void privateSmartContractMustDeploy() throws IOException {
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, "Alice");
final long nonce = privacyNet.getNode("Alice").nextNonce(privacyGroupId);
final String transactionHash =
ethSignerClient.eeaSendTransaction(
null,
BigInteger.valueOf(63992),
BigInteger.valueOf(1000),
EVENT_EMITTER_CONSTRUCTOR.toString(),
BigInteger.valueOf(nonce),
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
EventEmitter.BINARY,
BigInteger.valueOf(0),
minerNode.getEnclaveKey(),
Collections.emptyList(),
"restricted");
privacyNet.getNode("Alice").verify(eea.expectSuccessfulTransactionReceipt(transactionHash));
final String expectedContractAddress =
Address.privateContractAddress(
privacyNet.getNode("Alice").getAddress(), nonce, privacyGroupId)
.toString();
final PrivateTransactionReceipt receipt =
minerNode.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
privateTransactionVerifier
.validPrivateContractDeployed(expectedContractAddress)
.verify(privacyNet.getNode("Alice"), transactionHash);
minerNode.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(transactionHash, receipt));
}
}

@ -1,305 +0,0 @@
/*
* Copyright 2019 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.web3j.privacy;
import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
import static tech.pegasys.pantheon.tests.web3j.privacy.PrivacyGroup.generatePrivacyGroup;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.EeaCondition;
import tech.pegasys.pantheon.tests.acceptance.dsl.condition.eea.EeaConditions;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivateTransactionVerifier;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivateTransactions;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class EventEmitterHarness {
private PrivateTransactionBuilder.Builder privateTransactionBuilder;
private PrivacyNet privacyNet;
private PrivateTransactions privateTransactions;
private PrivateTransactionVerifier privateTransactionVerifier;
private EeaConditions eea;
private Map<String, String> contracts;
public EventEmitterHarness(
final PrivateTransactionBuilder.Builder privateTransactionBuilder,
final PrivacyNet privacyNet,
final PrivateTransactions privateTransactions,
final PrivateTransactionVerifier privateTransactionVerifier,
final EeaConditions eea) {
this.privateTransactionBuilder = privateTransactionBuilder;
this.privacyNet = privacyNet;
this.privateTransactions = privateTransactions;
this.privateTransactionVerifier = privateTransactionVerifier;
this.eea = eea;
this.contracts = new HashMap<>();
}
public String resolveContractAddress(final String contractName) {
return contracts.get(contractName);
}
public void deploy(final String contractName, final String sender, final String... receivers) {
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String contractAddress =
generateContractAddress(sender, nonce, privacyGroupId).toString();
deploy(
contractName,
privateTransactionVerifier.validPrivateContractDeployed(contractAddress),
privateTransactionVerifier.noPrivateContractDeployed(),
sender,
receivers);
}
public void deployWithPrivacyGroup(
final String contractName,
final String sender,
final String mPrivacyGroupId,
final String... groupMembers) {
deployWithPrivacyGroup(
contractName,
"Test",
nextNonce(sender, BytesValues.fromBase64(mPrivacyGroupId)),
sender,
mPrivacyGroupId,
groupMembers);
}
public void deploy(
final String contractName,
final EeaCondition forParticipants,
final EeaCondition forNonParticipants,
final String sender,
final String... receivers) {
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String contractAddress =
generateContractAddress(sender, nonce, privacyGroupId).toString();
deploy(
contractAddress,
contractName,
nonce,
forParticipants,
forNonParticipants,
sender,
receivers);
}
public void store(final String contractName, final String sender, final String... receivers) {
store(
contractName,
privateTransactionVerifier.validEventReturned("1000"),
privateTransactionVerifier.noValidEventReturned(),
sender,
receivers);
}
public void store(
final String contractName,
final EeaCondition forParticipants,
final EeaCondition forNonParticipants,
final String sender,
final String... receivers) {
final String contractAddress = resolveContractAddress(contractName);
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String storeValue =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getNode(sender).getAddress())
.to(Address.fromHexString(contractAddress))
.privateFrom(
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.STORE);
final String transactionHash =
privacyNet
.getNode(sender)
.execute(privateTransactions.createPrivateRawTransaction(storeValue));
waitForTransactionToBeMined(transactionHash);
verifyForParticipants(forParticipants, transactionHash, sender, receivers);
verifyForNonParticipants(forNonParticipants, transactionHash, sender, receivers);
}
public void get(final String contractName, final String sender, final String... receivers) {
get(
contractName,
privateTransactionVerifier.validOutputReturned("1000"),
privateTransactionVerifier.noValidOutputReturned(),
sender,
receivers);
}
public void get(
final String contractName,
final EeaCondition forParticipants,
final EeaCondition forNonParticipants,
final String sender,
final String... receivers) {
final String contractAddress = resolveContractAddress(contractName);
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String getValue =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getNode(sender).getAddress())
.to(Address.fromHexString(contractAddress))
.privateFrom(
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.GET);
final String transactionHash =
privacyNet
.getNode(sender)
.execute(privateTransactions.createPrivateRawTransaction(getValue));
waitForTransactionToBeMined(transactionHash);
verifyForParticipants(forParticipants, transactionHash, sender, receivers);
verifyForNonParticipants(forNonParticipants, transactionHash, sender, receivers);
}
private void deployWithPrivacyGroup(
final String contractAddress,
final String contractName,
final long nonce,
final String sender,
final String privacyGroupId,
final String... groupMembers) {
final String deployContract =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getNode(sender).getAddress())
.to(null)
.privateFrom(
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privacyGroupId(BytesValues.fromBase64(privacyGroupId))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.CREATE_CONTRACT);
final String transactionHash =
privacyNet
.getNode(sender)
.execute(privateTransactions.deployPrivateSmartContract(deployContract));
waitForTransactionToBeMined(transactionHash);
verifyForParticipants(
privateTransactionVerifier.validPrivateTransactionReceipt(),
transactionHash,
sender,
groupMembers);
contracts.put(contractName, contractAddress);
}
private void deploy(
final String contractAddress,
final String contractName,
final long nonce,
final EeaCondition forParticipants,
final EeaCondition forNonParticipants,
final String sender,
final String... receivers) {
final String deployContract =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getNode(sender).getAddress())
.to(null)
.privateFrom(
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.CREATE_CONTRACT);
final String transactionHash =
privacyNet
.getNode(sender)
.execute(privateTransactions.deployPrivateSmartContract(deployContract));
waitForTransactionToBeMined(transactionHash);
verifyForParticipants(forParticipants, transactionHash, sender, receivers);
verifyForNonParticipants(forNonParticipants, transactionHash, sender, receivers);
contracts.put(contractName, contractAddress);
}
private Address generateContractAddress(
final String sender, final long nonce, final BytesValue privacyGroupId) {
return Address.privateContractAddress(
privacyNet.getNode(sender).getAddress(), nonce, privacyGroupId);
}
private long nextNonce(final String sender, final BytesValue privacyGroupId) {
return privacyNet.getNode(sender).nextNonce(privacyGroupId);
}
private void waitForTransactionToBeMined(final String transactionHash) {
waitFor(
() ->
privacyNet
.getNode("Alice")
.verify(eea.expectSuccessfulTransactionReceipt(transactionHash)));
}
private List<BytesValue> convertNamesToOrionPublicKeys(final String... toNodeNames) {
return Arrays.stream(toNodeNames)
.map(name -> BytesValues.fromBase64(privacyNet.getEnclave(name).getPublicKeys().get(0)))
.collect(Collectors.toList());
}
private void verifyForNonParticipants(
final EeaCondition condition,
final String transactionHash,
final String sender,
final String[] receivers) {
privacyNet.getNodes().keySet().stream()
.filter(key -> !sender.equals(key) && !Arrays.asList(receivers).contains(key))
.forEach(node -> verifyForParticipant(condition, transactionHash, node));
}
private void verifyForParticipants(
final EeaCondition condition,
final String transactionHash,
final String fromNodeName,
final String[] toNodeNames) {
verifyForParticipant(condition, transactionHash, fromNodeName);
Arrays.stream(toNodeNames)
.forEach(node -> verifyForParticipant(condition, transactionHash, node));
}
private void verifyForParticipant(
final EeaCondition condition, final String transactionHash, final String nodeName) {
condition.verify(privacyNet.getNode(nodeName), transactionHash);
}
}

@ -12,123 +12,185 @@
*/
package tech.pegasys.pantheon.tests.web3j.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder.TransactionType;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.web3j.generated.EventEmitter;
import java.math.BigInteger;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.web3j.protocol.eea.response.PrivateTransactionReceipt;
public class Ibft2PrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase {
private static final String CONTRACT_NAME = "Event Emmiter";
private EventEmitterHarness eventEmitterHarness;
private PrivacyNet privacyNet;
private static final long IBFT2_CHAIN_ID = 4;
private PrivacyNode alice;
private PrivacyNode bob;
private PrivacyNode charlie;
@Before
public void setUp() throws Exception {
privacyNet =
PrivacyNet.builder(privacy, privacyPantheon, cluster, false)
.addMinerNode("Alice")
.addMinerNode("Bob")
.addMinerNode("Charlie")
.build();
privacyNet.startPrivacyNet();
eventEmitterHarness =
new EventEmitterHarness(
privateTransactionBuilder,
privacyNet,
privateTransactions,
privateTransactionVerifier,
eea);
}
@Test
public void node2CanSeeContract() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
}
@Test
public void node2CanExecuteContract() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
eventEmitterHarness.store(CONTRACT_NAME, "Bob", "Alice");
alice =
privacyPantheon.createIbft2NodePrivacyEnabled("node1", privacyAccountResolver.resolve(0));
bob = privacyPantheon.createIbft2NodePrivacyEnabled("node2", privacyAccountResolver.resolve(1));
charlie =
privacyPantheon.createIbft2NodePrivacyEnabled("node3", privacyAccountResolver.resolve(2));
privacyCluster.start(alice, bob, charlie);
}
@Test
public void node2CanSeePrivateTransactionReceipt() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
eventEmitterHarness.store(CONTRACT_NAME, "Bob", "Alice");
eventEmitterHarness.get(CONTRACT_NAME, "Bob", "Alice");
}
@Test(expected = RuntimeException.class)
public void node2ExpectError() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
String invalidStoreValueFromNode2 =
PrivateTransactionBuilder.builder()
.nonce(0)
.from(privacyNet.getNode("Bob").getAddress())
.to(Address.fromHexString(eventEmitterHarness.resolveContractAddress(CONTRACT_NAME)))
.privateFrom(
BytesValue.wrap(
privacyNet
.getEnclave("Alice")
.getPublicKeys()
.get(0)
.getBytes(UTF_8))) // wrong public key
.privateFor(
Lists.newArrayList(
BytesValue.wrap(
privacyNet.getEnclave("Bob").getPublicKeys().get(0).getBytes(UTF_8))))
.keyPair(privacyNet.getNode("Bob").keyPair())
.build(TransactionType.STORE);
privacyNet
.getNode("Bob")
.execute(privateTransactions.createPrivateRawTransaction(invalidStoreValueFromNode2));
public void onlyAliceAndBobCanExecuteContract() {
// Contract address is generated from sender address and transaction nonce
final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, alice.getAddress().toString())
.verify(eventEmitter);
final String transactionHash =
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
final PrivateTransactionReceipt expectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, expectedReceipt));
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash));
}
@Test
public void node1CanDeployMultipleTimes() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
eventEmitterHarness.store(CONTRACT_NAME, "Bob", "Alice");
final String secondContract = "Event Emitter 2";
eventEmitterHarness.deploy(secondContract, "Alice", "Bob");
eventEmitterHarness.store(secondContract, "Bob", "Alice");
public void aliceCanDeployMultipleTimesInSingleGroup() {
final String firstDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838";
privacyCluster.stopNode(charlie);
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
final String secondDeployedAddress = "0x10f807f8a905da5bd319196da7523c6bd768690f";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
}
@Test
public void node1CanInteractWithMultiplePrivacyGroups() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob", "Charlie");
eventEmitterHarness.store(CONTRACT_NAME, "Alice", "Bob", "Charlie");
final String secondContract = "Event Emitter 2";
eventEmitterHarness.store(
secondContract,
privateTransactionVerifier.noValidEventReturned(),
privateTransactionVerifier.noValidEventReturned(),
"Alice",
"Bob");
eventEmitterHarness.deploy(secondContract, "Alice", "Bob");
eventEmitterHarness.store(secondContract, "Alice", "Bob");
eventEmitterHarness.get(secondContract, "Alice", "Bob");
}
@After
public void tearDown() {
privacyNet.stopPrivacyNet();
public void canInteractWithMultiplePrivacyGroups() {
// alice deploys contract
final String firstDeployedAddress = "0xff206d21150a8da5b83629d8a722f3135ed532b1";
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey(),
charlie.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
// charlie interacts with contract
final String firstTransactionHash =
charlie.execute(
privateContractTransactions.callSmartContract(
firstEventEmitter.getContractAddress(),
firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
charlie.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
charlie.getEnclaveKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
// alice gets receipt from charlie's interaction
final PrivateTransactionReceipt firstExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash));
// verify bob and charlie have access to the same receipt
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
// alice deploys second contract
final String secondDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
// bob interacts with contract
final String secondTransactionHash =
bob.execute(
privateContractTransactions.callSmartContract(
secondEventEmitter.getContractAddress(),
secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
bob.getTransactionSigningKey(),
IBFT2_CHAIN_ID,
bob.getEnclaveKey(),
alice.getEnclaveKey()));
// alice gets receipt from bob's interaction
final PrivateTransactionReceipt secondExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
secondTransactionHash, secondExpectedReceipt));
// charlie cannot see the receipt
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash));
}
}

@ -12,123 +12,187 @@
*/
package tech.pegasys.pantheon.tests.web3j.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder;
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder.TransactionType;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import tech.pegasys.pantheon.tests.web3j.generated.EventEmitter;
import java.math.BigInteger;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.web3j.protocol.eea.response.PrivateTransactionReceipt;
public class PrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase {
private static final String CONTRACT_NAME = "Event Emmiter";
private EventEmitterHarness eventEmitterHarness;
private PrivacyNet privacyNet;
private static final long POW_CHAIN_ID = 2018;
private PrivacyNode alice;
private PrivacyNode bob;
private PrivacyNode charlie;
@Before
public void setUp() throws Exception {
privacyNet =
PrivacyNet.builder(privacy, privacyPantheon, cluster, false)
.addMinerNode("Alice")
.addMinerNode("Bob")
.addMinerNode("Charlie")
.build();
privacyNet.startPrivacyNet();
eventEmitterHarness =
new EventEmitterHarness(
privateTransactionBuilder,
privacyNet,
privateTransactions,
privateTransactionVerifier,
eea);
}
@Test
public void node2CanSeeContract() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
}
@Test
public void node2CanExecuteContract() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
eventEmitterHarness.store(CONTRACT_NAME, "Bob", "Alice");
alice =
privacyPantheon.createPrivateTransactionEnabledMinerNode(
"node1", privacyAccountResolver.resolve(0));
bob =
privacyPantheon.createPrivateTransactionEnabledNode(
"node2", privacyAccountResolver.resolve(1));
charlie =
privacyPantheon.createPrivateTransactionEnabledNode(
"node3", privacyAccountResolver.resolve(2));
privacyCluster.start(alice, bob, charlie);
}
@Test
public void node2CanSeePrivateTransactionReceipt() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
eventEmitterHarness.store(CONTRACT_NAME, "Bob", "Alice");
eventEmitterHarness.get(CONTRACT_NAME, "Bob", "Alice");
}
@Test(expected = RuntimeException.class)
public void node2ExpectError() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
String invalidStoreValueFromNode2 =
PrivateTransactionBuilder.builder()
.nonce(0)
.from(privacyNet.getNode("Bob").getAddress())
.to(Address.fromHexString(eventEmitterHarness.resolveContractAddress(CONTRACT_NAME)))
.privateFrom(
BytesValue.wrap(
privacyNet
.getEnclave("Alice")
.getPublicKeys()
.get(0)
.getBytes(UTF_8))) // wrong public key
.privateFor(
Lists.newArrayList(
BytesValue.wrap(
privacyNet.getEnclave("Bob").getPublicKeys().get(0).getBytes(UTF_8))))
.keyPair(privacyNet.getNode("Bob").keyPair())
.build(TransactionType.STORE);
privacyNet
.getNode("Bob")
.execute(privateTransactions.createPrivateRawTransaction(invalidStoreValueFromNode2));
public void onlyAliceAndBobCanExecuteContract() {
// Contract address is generated from sender address and transaction nonce
final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
POW_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, alice.getAddress().toString())
.verify(eventEmitter);
final String transactionHash =
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
alice.getTransactionSigningKey(),
POW_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
final PrivateTransactionReceipt expectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, expectedReceipt));
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash));
}
@Test
public void node1CanDeployMultipleTimes() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob");
eventEmitterHarness.store(CONTRACT_NAME, "Bob", "Alice");
final String secondContract = "Event Emitter 2";
eventEmitterHarness.deploy(secondContract, "Alice", "Bob");
eventEmitterHarness.store(secondContract, "Bob", "Alice");
public void aliceCanDeployMultipleTimesInSingleGroup() {
final String firstDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
POW_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
final String secondDeployedAddress = "0x10f807f8a905da5bd319196da7523c6bd768690f";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
POW_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
}
@Test
public void node1CanInteractWithMultiplePrivacyGroups() {
eventEmitterHarness.deploy(CONTRACT_NAME, "Alice", "Bob", "Charlie");
eventEmitterHarness.store(CONTRACT_NAME, "Alice", "Bob", "Charlie");
final String secondContract = "Event Emitter 2";
eventEmitterHarness.store(
secondContract,
privateTransactionVerifier.noValidEventReturned(),
privateTransactionVerifier.noValidEventReturned(),
"Alice",
"Bob");
eventEmitterHarness.deploy(secondContract, "Alice", "Bob");
eventEmitterHarness.store(secondContract, "Alice", "Bob");
eventEmitterHarness.get(secondContract, "Alice", "Bob");
}
@After
public void tearDown() {
privacyNet.stopPrivacyNet();
public void canInteractWithMultiplePrivacyGroups() {
// alice deploys contract
final String firstDeployedAddress = "0xff206d21150a8da5b83629d8a722f3135ed532b1";
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
POW_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey(),
charlie.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
// charlie interacts with contract
final String firstTransactionHash =
charlie.execute(
privateContractTransactions.callSmartContract(
firstEventEmitter.getContractAddress(),
firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
charlie.getTransactionSigningKey(),
POW_CHAIN_ID,
charlie.getEnclaveKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
// alice gets receipt from charlie's interaction
final PrivateTransactionReceipt firstExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash));
// verify bob and charlie have access to the same receipt
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
// alice deploys second contract
final String secondDeployedAddress = "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
POW_CHAIN_ID,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
// bob interacts with contract
final String secondTransactionHash =
bob.execute(
privateContractTransactions.callSmartContract(
secondEventEmitter.getContractAddress(),
secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
bob.getTransactionSigningKey(),
POW_CHAIN_ID,
bob.getEnclaveKey(),
alice.getEnclaveKey()));
// alice gets receipt from bob's interaction
final PrivateTransactionReceipt secondExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
secondTransactionHash, secondExpectedReceipt));
// charlie cannot see the receipt
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash));
}
}

@ -1,53 +0,0 @@
/*
* Copyright 2019 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.web3j.privacy;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import org.web3j.crypto.Hash;
import org.web3j.rlp.RlpEncoder;
import org.web3j.rlp.RlpList;
import org.web3j.rlp.RlpString;
import org.web3j.rlp.RlpType;
public class PrivacyGroup {
public static BytesValue generatePrivacyGroup(
final PrivacyNet privacyNet, final String sender, final String... receivers) {
final List<byte[]> stringList = new ArrayList<>();
stringList.add(
Base64.getDecoder().decode(privacyNet.getEnclave(sender).getPublicKeys().get(0)));
Arrays.stream(receivers)
.forEach(
(receiver) ->
stringList.add(
Base64.getDecoder()
.decode(privacyNet.getEnclave(receiver).getPublicKeys().get(0))));
List<RlpType> rlpList =
stringList.stream()
.distinct()
.sorted(Comparator.comparing(Arrays::hashCode))
.map(RlpString::create)
.collect(Collectors.toList());
return BytesValues.fromBase64(
Base64.getEncoder().encode(Hash.sha3(RlpEncoder.encode(new RlpList(rlpList)))));
}
}

@ -14,205 +14,114 @@ package tech.pegasys.pantheon.tests.web3j.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import tech.pegasys.pantheon.enclave.Enclave;
import tech.pegasys.pantheon.enclave.types.CreatePrivacyGroupRequest;
import tech.pegasys.pantheon.enclave.types.PrivacyGroup;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNet;
import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivacyNode;
import java.util.List;
import org.awaitility.Awaitility;
import org.junit.Before;
import org.junit.Test;
import org.web3j.protocol.pantheon.response.privacy.PrivacyGroup;
import org.web3j.utils.Base64String;
public class PrivacyGroupAcceptanceTest extends PrivacyAcceptanceTestBase {
private static final String CONTRACT_NAME = "Event Emmiter";
private EventEmitterHarness eventEmitterHarness;
private PrivacyGroup privacyGroup;
private PrivacyNet privacyNet;
private PrivacyNode alice;
private PrivacyNode bob;
private PrivacyNode charlie;
@Before
public void setUp() throws Exception {
privacyNet =
PrivacyNet.builder(privacy, privacyPantheon, cluster, false)
.addMinerNode("Alice")
.addMinerNode("Bob")
.addMinerNode("Charlie")
.build();
privacyNet.startPrivacyNet();
final Enclave enclave =
new Enclave(privacyNet.getNode("Alice").getPrivacyParameters().getEnclaveUri());
final String[] addresses =
privacyNet.getNodes().values().stream()
.map(privacyNode -> privacyNode.orion.getPublicKeys())
.flatMap(List::stream)
.toArray(String[]::new);
this.privacyGroup =
enclave.createPrivacyGroup(
new CreatePrivacyGroupRequest(
addresses,
privacyNet.getNode("Alice").orion.getPublicKeys().get(0),
"testName",
"testDesc"));
eventEmitterHarness =
new EventEmitterHarness(
privateTransactionBuilder,
privacyNet,
privateTransactions,
privateTransactionVerifier,
eea);
}
@Test
public void nodeCanDeployWithPrivacyGroupId() {
eventEmitterHarness.deployWithPrivacyGroup(
CONTRACT_NAME, "Alice", privacyGroup.getPrivacyGroupId(), "Alice", "Bob", "Charlie");
alice =
privacyPantheon.createPrivateTransactionEnabledMinerNode(
"node1", privacyAccountResolver.resolve(0));
bob =
privacyPantheon.createPrivateTransactionEnabledNode(
"node2", privacyAccountResolver.resolve(1));
charlie =
privacyPantheon.createPrivateTransactionEnabledNode(
"node3", privacyAccountResolver.resolve(2));
privacyCluster.start(alice, bob, charlie);
}
@Test
public void nodeCanCreatePrivacyGroup() {
final String privacyGroupId =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.createPrivacyGroup(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0)),
"myGroupName",
"my group description"));
alice.execute(
privacyTransactions.createPrivacyGroup(
"myGroupName", "my group description", alice, bob));
assertThat(privacyGroupId).isNotNull();
verifyGroupWasCreated();
final List<PrivacyGroup> privacyGroups =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.findPrivacyGroup(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0))));
assertThat(privacyGroups.size()).isEqualTo(1);
assertThat(privacyGroups.get(0).getPrivacyGroupId()).isEqualTo(privacyGroupId);
assertThat(privacyGroups.get(0).getName()).isEqualTo("myGroupName");
assertThat(privacyGroups.get(0).getDescription()).isEqualTo("my group description");
assertThat(privacyGroups.get(0).getMembers().length).isEqualTo(2);
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"myGroupName",
"my group description",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void nodeCanCreatePrivacyGroupWithoutName() {
final String privacyGroupId =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.createPrivacyGroupWithoutName(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0)),
"my group description"));
alice.execute(
privacyTransactions.createPrivacyGroup(null, "my group description", alice, bob));
assertThat(privacyGroupId).isNotNull();
verifyGroupWasCreated();
final List<PrivacyGroup> privacyGroups =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.findPrivacyGroup(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0))));
assertThat(privacyGroups.size()).isEqualTo(1);
assertThat(privacyGroups.get(0).getPrivacyGroupId()).isEqualTo(privacyGroupId);
assertThat(privacyGroups.get(0).getName()).isEqualTo("Default Name");
assertThat(privacyGroups.get(0).getDescription()).isEqualTo("my group description");
assertThat(privacyGroups.get(0).getMembers().length).isEqualTo(2);
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"Default Name",
"my group description",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void nodeCanCreatePrivacyGroupWithoutDescription() {
final String privacyGroupId =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.createPrivacyGroupWithoutDescription(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0)),
"myGroupName"));
alice.execute(privacyTransactions.createPrivacyGroup("myGroupName", null, alice, bob));
assertThat(privacyGroupId).isNotNull();
verifyGroupWasCreated();
final List<PrivacyGroup> privacyGroups =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.findPrivacyGroup(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0))));
assertThat(privacyGroups.size()).isEqualTo(1);
assertThat(privacyGroups.get(0).getPrivacyGroupId()).isEqualTo(privacyGroupId);
assertThat(privacyGroups.get(0).getName()).isEqualTo("myGroupName");
assertThat(privacyGroups.get(0).getDescription()).isEqualTo("Default Description");
assertThat(privacyGroups.get(0).getMembers().length).isEqualTo(2);
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"myGroupName",
"Default Description",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void nodeCanCreatePrivacyGroupWithoutOptionalParams() {
final String privacyGroupId =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.createPrivacyGroupWithoutOptionalParams(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0))));
alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob));
assertThat(privacyGroupId).isNotNull();
verifyGroupWasCreated();
final List<PrivacyGroup> privacyGroups =
privacyNet
.getNode("Alice")
.execute(
privateTransactions.findPrivacyGroup(
List.of(
privacyNet.getEnclave("Alice").getPublicKeys().get(0),
privacyNet.getEnclave("Bob").getPublicKeys().get(0))));
assertThat(privacyGroups.size()).isEqualTo(1);
assertThat(privacyGroups.get(0).getPrivacyGroupId()).isEqualTo(privacyGroupId);
assertThat(privacyGroups.get(0).getName()).isEqualTo("Default Name");
assertThat(privacyGroups.get(0).getDescription()).isEqualTo("Default Description");
assertThat(privacyGroups.get(0).getMembers().length).isEqualTo(2);
}
private void verifyGroupWasCreated() {
privacyNet
.getNode("Alice")
.verify(
node ->
Awaitility.await()
.until(
() ->
node.execute(
privateTransactions.findPrivacyGroup(
List.of(
privacyNet
.getEnclave("Alice")
.getPublicKeys()
.get(0),
privacyNet
.getEnclave("Bob")
.getPublicKeys()
.get(0))))
.size()
> 0));
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"Default Name",
"Default Description",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
}

@ -0,0 +1,38 @@
{
"config": {
"chainId": 4,
"byzantiumBlock": 0,
"ibft2": {
"blockperiodseconds": 1,
"epochlength": 30000,
"requesttimeoutseconds": 5
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "%extraData%",
"gasLimit": "0x47b760",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"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"
}

@ -17,6 +17,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.junit.Assert.assertTrue;
import tech.pegasys.orion.testutil.OrionKeyConfiguration;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.orion.testutil.OrionTestHarnessFactory;
import tech.pegasys.pantheon.enclave.types.CreatePrivacyGroupRequest;
@ -50,19 +51,22 @@ public class EnclaveTest {
private static OrionTestHarness testHarness;
@Before
public void setUpOnce() throws Exception {
public void setUp() throws Exception {
folder.create();
testHarness =
OrionTestHarnessFactory.create(
folder.newFolder().toPath(), "orion_key_0.pub", "orion_key_0.key");
folder.newFolder().toPath(),
new OrionKeyConfiguration("orion_key_0.pub", "orion_key_0.key"));
testHarness.start();
enclave = new Enclave(testHarness.clientUrl());
}
@After
public void tearDownOnce() {
testHarness.getOrion().stop();
public void tearDown() {
testHarness.close();
}
@Test
@ -71,7 +75,7 @@ public class EnclaveTest {
}
@Test
public void testSendAndReceive() throws Exception {
public void testSendAndReceive() {
final List<String> publicKeys = testHarness.getPublicKeys();
final SendResponse sr =
@ -85,7 +89,7 @@ public class EnclaveTest {
}
@Test
public void testSendWithPrivacyGroupAndReceive() throws Exception {
public void testSendWithPrivacyGroupAndReceive() {
final List<String> publicKeys = testHarness.getPublicKeys();
final CreatePrivacyGroupRequest privacyGroupRequest =
@ -104,7 +108,7 @@ public class EnclaveTest {
}
@Test
public void testCreateAndDeletePrivacyGroup() throws Exception {
public void testCreateAndDeletePrivacyGroup() {
final List<String> publicKeys = testHarness.getPublicKeys();
final String name = "testName";
final String description = "testDesc";
@ -128,7 +132,7 @@ public class EnclaveTest {
}
@Test
public void testCreateFindDeleteFindPrivacyGroup() throws Exception {
public void testCreateFindDeleteFindPrivacyGroup() {
List<String> publicKeys = testHarness.getPublicKeys();
String name = "name";
String description = "desc";

@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import tech.pegasys.orion.testutil.OrionKeyConfiguration;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.orion.testutil.OrionTestHarnessFactory;
import tech.pegasys.pantheon.enclave.Enclave;
@ -115,7 +116,10 @@ public class PrivacyPrecompiledContractIntegrationTest {
testHarness =
OrionTestHarnessFactory.create(
folder.newFolder().toPath(), "orion_key_0.pub", "orion_key_1.key");
folder.newFolder().toPath(),
new OrionKeyConfiguration("orion_key_0.pub", "orion_key_1.key"));
testHarness.start();
enclave = new Enclave(testHarness.clientUrl());
messageFrame = mock(MessageFrame.class);

@ -226,22 +226,6 @@ public abstract class MainnetProtocolSpecs {
true,
stackSizeLimit,
Account.DEFAULT_VERSION))
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(chainId))
.privateTransactionProcessorBuilder(
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
false,
stackSizeLimit,
Account.DEFAULT_VERSION,
privateTransactionValidator))
.name("SpuriousDragon");
}
@ -250,6 +234,7 @@ public abstract class MainnetProtocolSpecs {
final OptionalInt contractSizeLimit,
final OptionalInt configStackSizeLimit,
final boolean enableRevertReason) {
final int stackSizeLimit = configStackSizeLimit.orElse(DEFAULT_MAX_STACK_SIZE);
return spuriousDragonDefinition(chainId, contractSizeLimit, configStackSizeLimit)
.evmBuilder(MainnetEvmRegistries::byzantium)
.precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::byzantium)
@ -259,6 +244,22 @@ public abstract class MainnetProtocolSpecs {
? MainnetProtocolSpecs::byzantiumTransactionReceiptFactoryWithReasonEnabled
: MainnetProtocolSpecs::byzantiumTransactionReceiptFactory)
.blockReward(BYZANTIUM_BLOCK_REWARD)
.privateTransactionValidatorBuilder(() -> new PrivateTransactionValidator(chainId))
.privateTransactionProcessorBuilder(
(gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
privateTransactionValidator) ->
new PrivateTransactionProcessor(
gasCalculator,
transactionValidator,
contractCreationProcessor,
messageCallProcessor,
false,
stackSizeLimit,
Account.DEFAULT_VERSION,
privateTransactionValidator))
.name("Byzantium");
}

@ -18,6 +18,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import tech.pegasys.orion.testutil.OrionKeyConfiguration;
import tech.pegasys.orion.testutil.OrionTestHarness;
import tech.pegasys.orion.testutil.OrionTestHarnessFactory;
import tech.pegasys.pantheon.crypto.SECP256K1;
@ -43,7 +44,6 @@ import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Base64;
import java.util.Optional;
@ -73,19 +73,17 @@ public class PrivGetPrivateTransactionIntegrationTest {
testHarness =
OrionTestHarnessFactory.create(
folder.newFolder().toPath(), "orion_key_0.pub", "orion_key_0.key");
folder.newFolder().toPath(),
new OrionKeyConfiguration("orion_key_0.pub", "orion_key_0.key"));
testHarness.start();
enclave = new Enclave(testHarness.clientUrl());
}
@AfterClass
public static void tearDownOnce() {
testHarness.stopOrion();
}
@Test
public void testUpCheck() throws IOException {
assertThat(enclave.upCheck()).isTrue();
testHarness.close();
}
private final Address sender =
@ -132,7 +130,7 @@ public class PrivGetPrivateTransactionIntegrationTest {
private final BlockchainQueries blockchain = mock(BlockchainQueries.class);
@Test
public void returnsStoredPrivateTransaction() throws Exception {
public void returnsStoredPrivateTransaction() {
final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction(blockchain, enclave, parameters, privacyParameters);

@ -80,7 +80,6 @@ public class PrivCreatePrivacyGroupTest {
@Test
public void verifyCreatePrivacyGroupWithoutDescription() {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);
@ -115,7 +114,6 @@ public class PrivCreatePrivacyGroupTest {
@Test
public void verifyCreatePrivacyGroupWithoutName() {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);
@ -150,7 +148,6 @@ public class PrivCreatePrivacyGroupTest {
@Test
public void verifyCreatePrivacyGroupWithoutOptionalParams() {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);

@ -85,16 +85,16 @@ dependencyManagement {
dependency 'org.springframework.security:spring-security-crypto:5.1.5.RELEASE'
dependency 'org.web3j:abi:4.3.1'
dependency 'org.web3j:core:4.3.1'
dependency 'org.web3j:crypto:4.3.1'
dependency 'org.web3j:eea:4.3.1'
dependency 'org.web3j:abi:4.5.0'
dependency 'org.web3j:core:4.5.0'
dependency 'org.web3j:crypto:4.5.0'
dependency 'org.web3j:pantheon:4.5.0'
dependency 'org.xerial.snappy:snappy-java:1.1.7.3'
dependency "tech.pegasys.ethsigner.internal:core:0.2.0"
dependency "tech.pegasys.ethsigner.internal:file-based:0.2.0"
dependency "tech.pegasys.ethsigner.internal:signing-api:0.2.0"
dependency "tech.pegasys.ethsigner.internal:core:0.3.0"
dependency "tech.pegasys.ethsigner.internal:file-based:0.3.0"
dependency "tech.pegasys.ethsigner.internal:signing-api:0.3.0"
dependency "tech.pegasys.pantheon:plugin-api:1.2.3"
}

@ -0,0 +1,57 @@
/*
* Copyright 2019 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.orion.testutil;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
public class OrionConfiguration {
private final Path publicKey;
private final Path privateKey;
private final Path tempDir;
private final List<String> otherNodes = new ArrayList<>();
public OrionConfiguration(
final Path publicKey,
final Path privateKey,
final Path tempDir,
final List<String> otherNodes) {
this.publicKey = publicKey;
this.privateKey = privateKey;
this.tempDir = tempDir;
this.otherNodes.addAll(otherNodes);
}
public Path getPublicKey() {
return publicKey;
}
public Path getPrivateKey() {
return privateKey;
}
public Path getTempDir() {
return tempDir;
}
public List<String> getOtherNodes() {
return otherNodes;
}
public void addOtherNode(final String otherNode) {
otherNodes.add(otherNode);
}
}

@ -0,0 +1,31 @@
/*
* Copyright 2019 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.orion.testutil;
public class OrionKeyConfiguration {
private final String pubKeyPath;
private final String privKeyPath;
public OrionKeyConfiguration(final String pubKeyPath, final String privKeyPath) {
this.pubKeyPath = pubKeyPath;
this.privKeyPath = privKeyPath;
}
public String getPubKeyPath() {
return pubKeyPath;
}
public String getPrivKeyPath() {
return privKeyPath;
}
}

@ -17,39 +17,74 @@ import static com.google.common.io.Files.readLines;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import com.google.common.base.Charsets;
import com.google.common.io.MoreFiles;
import com.google.common.io.RecursiveDeleteOption;
import net.consensys.orion.cmd.Orion;
import net.consensys.orion.config.Config;
import okhttp3.HttpUrl;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class OrionTestHarness {
private static final Logger LOG = LogManager.getLogger();
private final Orion orion;
private final Config config;
private final OrionConfiguration orionConfiguration;
protected static final String HOST = "127.0.0.1";
private Config config;
private boolean isRunning;
protected OrionTestHarness(final Orion orion, final Config config) {
protected static final String HOST = "127.0.0.1";
this.orion = orion;
this.config = config;
protected OrionTestHarness(final OrionConfiguration orionConfiguration) {
this.orionConfiguration = orionConfiguration;
this.orion = new Orion();
}
public Orion getOrion() {
return orion;
}
public void stopOrion() {
orion.stop();
public void start() {
if (!isRunning) {
config = buildConfig();
orion.run(System.out, System.err, config);
isRunning = true;
LOG.info("Orion node port: {}", orion.nodePort());
LOG.info("Orion client port: {}", orion.clientPort());
}
}
public void stop() {
if (isRunning) {
orion.stop();
isRunning = false;
}
}
public void close() {
stop();
try {
MoreFiles.deleteRecursively(config.workDir(), RecursiveDeleteOption.ALLOW_INSECURE);
} catch (final IOException e) {
LOG.info("Failed to clean up temporary file: {}", config.workDir(), e);
}
}
public Config getConfig() {
return config;
}
public String getDefaultPublicKey() {
return config.publicKeys().stream().map(OrionTestHarness::readFile).findFirst().orElseThrow();
}
public List<String> getPublicKeys() {
return config.publicKeys().stream()
.map(OrionTestHarness::readFile)
@ -72,12 +107,66 @@ public class OrionTestHarness {
return URI.create(httpUrl.toString());
}
public String nodeUrl() {
return new HttpUrl.Builder()
.scheme("http")
.host(HOST)
.port(orion.nodePort())
.build()
.toString();
public URI nodeUrl() {
HttpUrl httpUrl =
new HttpUrl.Builder().scheme("http").host(HOST).port(orion.nodePort()).build();
return URI.create(httpUrl.toString());
}
public void addOtherNode(final URI otherNode) {
orionConfiguration.addOtherNode(otherNode.toString());
}
private Config buildConfig() {
// @formatter:off
String confString =
"tls=\"off\"\n"
+ "tlsservertrust=\"tofu\"\n"
+ "tlsclienttrust=\"tofu\"\n"
+ "nodeport=0\n"
+ "nodenetworkinterface = \""
+ HOST
+ "\"\n"
+ "clientport=0\n"
+ "clientnetworkinterface = \""
+ HOST
+ "\"\n"
+ "storage = \"leveldb:database/orion_node\"\n"
+ "publickeys = ["
+ joinPathsAsTomlListEntry(orionConfiguration.getPublicKey())
+ "]\n"
+ "privatekeys = ["
+ joinPathsAsTomlListEntry(orionConfiguration.getPrivateKey())
+ "]\n"
+ "workdir= \""
+ orionConfiguration.getTempDir().toString()
+ "\"\n";
if (orionConfiguration.getOtherNodes().size() != 0) {
confString +=
"othernodes = [" + joinStringsAsTomlListEntry(orionConfiguration.getOtherNodes()) + "]\n";
}
// @formatter:on
return Config.load(confString);
}
private static String joinPathsAsTomlListEntry(final Path... paths) {
return joinStringsAsTomlListEntry(
Arrays.stream(paths).map(p -> p.toAbsolutePath().toString()).collect(Collectors.toList()));
}
private static String joinStringsAsTomlListEntry(final List<String> strings) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (String string : strings) {
if (!first) {
builder.append(",");
}
first = false;
builder.append("\"").append(string).append("\"");
}
return builder.toString();
}
}

@ -12,76 +12,29 @@
*/
package tech.pegasys.orion.testutil;
import static java.nio.charset.StandardCharsets.UTF_8;
import static net.consensys.cava.io.file.Files.copyResource;
import java.io.IOException;
import java.nio.file.Path;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.Base64;
import com.google.common.io.CharSink;
import com.google.common.io.Files;
import net.consensys.orion.cmd.Orion;
import net.consensys.orion.config.Config;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.params.Ed25519PublicKeyParameters;
import java.util.Collections;
import java.util.List;
public class OrionTestHarnessFactory {
private static final Logger LOG = LogManager.getLogger();
protected static final String HOST = "127.0.0.1";
public static OrionTestHarness create(
final Path tempDir,
final Ed25519PublicKeyParameters pubKey,
final String pubKeyPath,
final Ed25519PrivateKeyParameters privKey,
final String privKeyPath,
final String... othernodes)
public static OrionTestHarness create(final Path tempDir, final OrionKeyConfiguration orionConfig)
throws IOException {
return create(
tempDir, pubKeyPath, privKeyPath, pubKey.getEncoded(), privKey.getEncoded(), othernodes);
tempDir,
orionConfig.getPubKeyPath(),
orionConfig.getPrivKeyPath(),
Collections.emptyList());
}
public static OrionTestHarness create(
final Path tempDir,
final PublicKey pubKey,
final String pubKeyPath,
final PrivateKey privKey,
final String privKeyPath,
final String... othernodes)
throws IOException {
return create(
tempDir, pubKeyPath, privKeyPath, pubKey.getEncoded(), privKey.getEncoded(), othernodes);
}
private static OrionTestHarness create(
final Path tempDir,
final String pubKeyPath,
final String privKeyPath,
final byte[] encodedPubKey,
final byte[] encodedPrivKey,
final String[] othernodes)
throws IOException {
final Path pubKeyFile = tempDir.resolve(pubKeyPath);
final CharSink pubKeySink = Files.asCharSink(pubKeyFile.toFile(), UTF_8);
pubKeySink.write(Base64.getEncoder().encodeToString(encodedPubKey));
final Path privKeyFile = tempDir.resolve(privKeyPath);
final CharSink privKeySink = Files.asCharSink(privKeyFile.toFile(), UTF_8);
privKeySink.write(Base64.getEncoder().encodeToString(encodedPrivKey));
return create(tempDir, pubKeyFile, privKeyFile, othernodes);
}
public static OrionTestHarness create(
final Path tempDir,
final String pubKeyPath,
final String privKeyPath,
final String... othernodes)
final List<String> othernodes)
throws IOException {
Path key1pub = copyResource(pubKeyPath, tempDir.resolve(pubKeyPath));
Path key1key = copyResource(privKeyPath, tempDir.resolve(privKeyPath));
@ -90,72 +43,8 @@ public class OrionTestHarnessFactory {
}
public static OrionTestHarness create(
final Path tempDir, final Path key1pub, final Path key1key, final String... othernodes) {
// @formatter:off
String confString =
"tls=\"off\"\n"
+ "tlsservertrust=\"tofu\"\n"
+ "tlsclienttrust=\"tofu\"\n"
+ "nodeport=0\n"
+ "nodenetworkinterface = \""
+ HOST
+ "\"\n"
+ "clientport=0\n"
+ "clientnetworkinterface = \""
+ HOST
+ "\"\n"
+ "storage = \"leveldb:database/orion_node\"\n"
+ "publickeys = ["
+ joinPathsAsTomlListEntry(key1pub)
+ "]\n"
+ "privatekeys = ["
+ joinPathsAsTomlListEntry(key1key)
+ "]\n"
+ "workdir= \""
+ tempDir.toString()
+ "\"\n";
if (othernodes.length != 0) {
confString += "othernodes = [" + joinStringsAsTomlListEntry(othernodes) + "]\n";
}
// @formatter:on
Config config = Config.load(confString);
final Orion orion = new Orion();
orion.run(System.out, System.err, config);
LOG.info("Orion node port: {}", orion.nodePort());
LOG.info("Orion client port: {}", orion.clientPort());
return new OrionTestHarness(orion, config);
}
private static String joinPathsAsTomlListEntry(final Path... paths) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (Path path : paths) {
if (!first) {
builder.append(",");
}
first = false;
builder.append("\"").append(path.toAbsolutePath().toString()).append("\"");
}
return builder.toString();
}
final Path tempDir, final Path key1pub, final Path key1key, final List<String> othernodes) {
private static String joinStringsAsTomlListEntry(final String... strings) {
StringBuilder builder = new StringBuilder();
boolean first = true;
for (String string : strings) {
if (!first) {
builder.append(",");
}
first = false;
builder.append("\"").append(string).append("\"");
}
return builder.toString();
return new OrionTestHarness(new OrionConfiguration(key1pub, key1key, tempDir, othernodes));
}
}

Loading…
Cancel
Save