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

Commit

Permalink
[PAN-2672] Return specific and useful error for enclave issues (#1455)
Browse files Browse the repository at this point in the history
* Return specific error for enclave

* Serialize into error object instead of regex to find the error.

* Return EnclaveException for errors in Enclave

* Fix enclave error response after rebase
  • Loading branch information
Puneetha17 authored and ekellstrand committed Jun 11, 2019
1 parent 15fb741 commit 3d7a93f
Show file tree
Hide file tree
Showing 22 changed files with 394 additions and 97 deletions.
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))))));
}
}

0 comments on commit 3d7a93f

Please sign in to comment.