diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/PrivateTransactionBuilder.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/PrivateTransactionBuilder.java index 816deaf242..91c521a085 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/PrivateTransactionBuilder.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/transaction/eea/PrivateTransactionBuilder.java @@ -23,6 +23,7 @@ import java.math.BigInteger; import java.util.ArrayList; import java.util.List; +import java.util.Optional; public class PrivateTransactionBuilder { @@ -68,7 +69,8 @@ public static class Builder { Address from; Address to; BytesValue privateFrom; - List privateFor = new ArrayList<>(); + Optional privacyGroupId = Optional.empty(); + Optional> privateFor = Optional.of(new ArrayList<>()); SECP256K1.KeyPair keyPair; public Builder nonce(final long nonce) { @@ -91,8 +93,13 @@ public Builder privateFrom(final BytesValue privateFrom) { return this; } + public Builder privacyGroupId(final BytesValue privacyGroupId) { + this.privacyGroupId = Optional.of(privacyGroupId); + return this; + } + public Builder privateFor(final List privateFor) { - this.privateFor = privateFor; + this.privateFor = Optional.of(privateFor); return this; } @@ -116,22 +123,27 @@ public String build(final TransactionType type) { default: throw new IllegalStateException("Unexpected value: " + type); } - return RLP.encode( - 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) - .privateFor(privateFor) - .restriction(Restriction.RESTRICTED) - .signAndBuild(keyPair) - ::writeTo) - .toString(); + + 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(); } } } diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EventEmitterHarness.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EventEmitterHarness.java index 07715f8e58..04708663e2 100644 --- a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EventEmitterHarness.java +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EventEmitterHarness.java @@ -74,6 +74,20 @@ public void deploy(final String contractName, final String sender, final String. 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, @@ -174,6 +188,40 @@ public void get( 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, @@ -247,7 +295,7 @@ private void verifyForParticipants( final String[] toNodeNames) { verifyForParticipant(condition, transactionHash, fromNodeName); Arrays.stream(toNodeNames) - .forEach(node -> verifyForParticipant(condition, transactionHash, fromNodeName)); + .forEach(node -> verifyForParticipant(condition, transactionHash, node)); } private void verifyForParticipant( diff --git a/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyGroupIdAcceptanceTest.java b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyGroupIdAcceptanceTest.java new file mode 100644 index 0000000000..9234896e21 --- /dev/null +++ b/acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyGroupIdAcceptanceTest.java @@ -0,0 +1,71 @@ +/* + * 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.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 java.util.List; + +import org.junit.Before; +import org.junit.Test; + +public class PrivacyGroupIdAcceptanceTest extends PrivacyAcceptanceTestBase { + private static final String CONTRACT_NAME = "Event Emmiter"; + private EventEmitterHarness eventEmitterHarness; + private PrivacyGroup privacyGroup; + + @Before + public void setUp() throws Exception { + PrivacyNet privacyNet = + PrivacyNet.builder(privacy, privacyPantheon, cluster, false) + .addMinerNode("Alice") + .addMinerNode("Bob") + .addMinerNode("Charlie") + .build(); + + privacyNet.startPrivacyNet(); + + Enclave enclave = + new Enclave(privacyNet.getNode("Alice").getPrivacyParameters().getEnclaveUri()); + 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"); + } +}