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

[PAN-2672] Return specific and useful error for enclave issues #1455

Merged
merged 5 commits into from
Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
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.PantheonNode;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.cluster.Cluster;
import tech.pegasys.pantheon.tests.acceptance.dsl.node.configuration.privacy.PrivacyPantheonNodeFactory;

Expand Down Expand Up @@ -72,7 +71,7 @@ public Map<String, PrivacyNode> getNodes() {
return nodes;
}

public PantheonNode getPantheon(final String name) {
public PrivacyNode getNode(final String name) {
return nodes.get(name);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import tech.pegasys.pantheon.metrics.prometheus.MetricsConfiguration;
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.eea.EeaGetTransactionCountTransaction;
import tech.pegasys.pantheon.util.bytes.BytesValue;

import java.io.IOException;
Expand Down Expand Up @@ -102,4 +103,11 @@ public void testOrionConnection(final PrivacyNode... otherNodes) {
.collect(Collectors.toList()));
waitFor(() -> orionEnclave.send(sendRequest1));
}

public long nextNonce(final BytesValue privacyGroupId) {
return execute(
new EeaGetTransactionCountTransaction(
getAddress().toString(), privacyGroupId.toString()))
.longValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import tech.pegasys.pantheon.util.bytes.BytesValue;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class PrivateTransactionBuilder {
Expand Down Expand Up @@ -67,7 +68,7 @@ public static class Builder {
Address from;
Address to;
BytesValue privateFrom;
List<BytesValue> privateFor;
List<BytesValue> privateFor = new ArrayList<>();
SECP256K1.KeyPair keyPair;

public Builder nonce(final long nonce) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import static java.nio.charset.StandardCharsets.UTF_8;
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;
Expand All @@ -24,22 +25,12 @@
import tech.pegasys.pantheon.tests.acceptance.dsl.transaction.eea.PrivateTransactionBuilder;
import tech.pegasys.pantheon.util.bytes.BytesValue;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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;
import org.web3j.utils.Numeric;

public class EventEmitterHarness {

private PrivateTransactionBuilder.Builder privateTransactionBuilder;
Expand Down Expand Up @@ -71,7 +62,7 @@ public String resolveContractAddress(final String contractName) {
}

public void deploy(final String contractName, final String sender, final String... receivers) {
final BytesValue privacyGroupId = generatePrivaycGroup(sender, receivers);
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String contractAddress =
generateContractAddress(sender, nonce, privacyGroupId).toString();
Expand All @@ -89,7 +80,7 @@ public void deploy(
final EeaCondition forNonParticipants,
final String sender,
final String... receivers) {
final BytesValue privacyGroupId = generatePrivaycGroup(sender, receivers);
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String contractAddress =
generateContractAddress(sender, nonce, privacyGroupId).toString();
Expand Down Expand Up @@ -119,22 +110,22 @@ public void store(
final String sender,
final String... receivers) {
final String contractAddress = resolveContractAddress(contractName);
final BytesValue privacyGroupId = generatePrivaycGroup(sender, receivers);
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String storeValue =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getPantheon(sender).getAddress())
.from(privacyNet.getNode(sender).getAddress())
.to(Address.fromHexString(contractAddress))
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave(sender).getPublicKeys().get(0).getBytes(UTF_8)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getPantheon(sender).keyPair())
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.STORE);
final String transactionHash =
privacyNet
.getPantheon(sender)
.getNode(sender)
.execute(privateTransactions.createPrivateRawTransaction(storeValue));

waitForTransactionToBeMined(transactionHash);
Expand All @@ -160,22 +151,22 @@ public void get(
final String sender,
final String... receivers) {
final String contractAddress = resolveContractAddress(contractName);
final BytesValue privacyGroupId = generatePrivaycGroup(sender, receivers);
final BytesValue privacyGroupId = generatePrivacyGroup(privacyNet, sender, receivers);
final long nonce = nextNonce(sender, privacyGroupId);
final String getValue =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getPantheon(sender).getAddress())
.from(privacyNet.getNode(sender).getAddress())
.to(Address.fromHexString(contractAddress))
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave(sender).getPublicKeys().get(0).getBytes(UTF_8)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getPantheon(sender).keyPair())
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.GET);
final String transactionHash =
privacyNet
.getPantheon(sender)
.getNode(sender)
.execute(privateTransactions.createPrivateRawTransaction(getValue));

waitForTransactionToBeMined(transactionHash);
Expand All @@ -196,17 +187,17 @@ private void deploy(
final String deployContract =
privateTransactionBuilder
.nonce(nonce)
.from(privacyNet.getPantheon(sender).getAddress())
.from(privacyNet.getNode(sender).getAddress())
.to(null)
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave(sender).getPublicKeys().get(0).getBytes(UTF_8)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getPantheon(sender).keyPair())
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.CREATE_CONTRACT);
final String transactionHash =
privacyNet
.getPantheon(sender)
.getNode(sender)
.execute(privateTransactions.deployPrivateSmartContract(deployContract));

waitForTransactionToBeMined(transactionHash);
Expand All @@ -221,44 +212,18 @@ private void deploy(
private Address generateContractAddress(
final String sender, final long nonce, final BytesValue privacyGroupId) {
return Address.privateContractAddress(
privacyNet.getPantheon(sender).getAddress(), nonce, privacyGroupId);
}

private BytesValue generatePrivaycGroup(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 BytesValue.fromHexString(
Numeric.toHexString(
Base64.getEncoder().encode(Hash.sha3(RlpEncoder.encode(new RlpList(rlpList))))));
privacyNet.getNode(sender).getAddress(), nonce, privacyGroupId);
}

private long nextNonce(final String sender, final BytesValue privacyGroupId) {
return privacyNet
.getPantheon(sender)
.execute(
privateTransactions.getTransactionCount(
privacyNet.getPantheon(sender).getAddress().toString(), privacyGroupId.toString()))
.longValue();
return privacyNet.getNode(sender).nextNonce(privacyGroupId);
}

private void waitForTransactionToBeMined(final String transactionHash) {
waitFor(
() ->
privacyNet
.getPantheon("Alice")
.getNode("Alice")
.verify(eea.expectSuccessfulTransactionReceipt(transactionHash)));
}

Expand Down Expand Up @@ -292,6 +257,6 @@ private void verifyForParticipants(

private void verifyForParticipant(
final EeaCondition condition, final String transactionHash, final String nodeName) {
condition.verify(privacyNet.getPantheon(nodeName), transactionHash);
condition.verify(privacyNet.getNode(nodeName), transactionHash);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void node2ExpectError() {
String invalidStoreValueFromNode2 =
PrivateTransactionBuilder.builder()
.nonce(0)
.from(privacyNet.getPantheon("Bob").getAddress())
.from(privacyNet.getNode("Bob").getAddress())
.to(Address.fromHexString(eventEmitterHarness.resolveContractAddress(CONTRACT_NAME)))
.privateFrom(
BytesValue.wrap(
Expand All @@ -88,11 +88,11 @@ public void node2ExpectError() {
Lists.newArrayList(
BytesValue.wrap(
privacyNet.getEnclave("Bob").getPublicKeys().get(0).getBytes(UTF_8))))
.keyPair(privacyNet.getPantheon("Bob").keyPair())
.keyPair(privacyNet.getNode("Bob").keyPair())
.build(TransactionType.STORE);

privacyNet
.getPantheon("Bob")
.getNode("Bob")
.execute(privateTransactions.createPrivateRawTransaction(invalidStoreValueFromNode2));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public void node2ExpectError() {
String invalidStoreValueFromNode2 =
PrivateTransactionBuilder.builder()
.nonce(0)
.from(privacyNet.getPantheon("Bob").getAddress())
.from(privacyNet.getNode("Bob").getAddress())
.to(Address.fromHexString(eventEmitterHarness.resolveContractAddress(CONTRACT_NAME)))
.privateFrom(
BytesValue.wrap(
Expand All @@ -88,11 +88,11 @@ public void node2ExpectError() {
Lists.newArrayList(
BytesValue.wrap(
privacyNet.getEnclave("Bob").getPublicKeys().get(0).getBytes(UTF_8))))
.keyPair(privacyNet.getPantheon("Bob").keyPair())
.keyPair(privacyNet.getNode("Bob").keyPair())
.build(TransactionType.STORE);

privacyNet
.getPantheon("Bob")
.getNode("Bob")
.execute(privateTransactions.createPrivateRawTransaction(invalidStoreValueFromNode2));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* 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 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;
import org.web3j.utils.Numeric;

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 BytesValue.fromHexString(
Numeric.toHexString(
Base64.getEncoder().encode(Hash.sha3(RlpEncoder.encode(new RlpList(rlpList))))));
}
}