[PAN-2852] privacy group id consistent (#1667)

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Ivaylo Kirilov 5 years ago committed by Lucas Saldanha
parent ef47ffe050
commit 2c64a9ceba
  1. 3
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/privacy/PrivacyNode.java
  2. 10
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EnclaveErrorAcceptanceTest.java
  3. 15
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/EventEmitterHarness.java
  4. 7
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/web3j/privacy/PrivacyGroup.java
  5. 11
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContract.java
  6. 26
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionHandler.java
  7. 9
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetPrivateTransaction.java
  8. 8
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetTransactionReceipt.java
  9. 9
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetTransactionCountTest.java
  10. 13
      util/src/main/java/tech/pegasys/pantheon/util/bytes/BytesValues.java

@ -30,6 +30,7 @@ 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 tech.pegasys.pantheon.util.bytes.BytesValues;
import java.io.IOException;
import java.util.Arrays;
@ -113,7 +114,7 @@ public class PrivacyNode extends PantheonNode {
public long nextNonce(final BytesValue privacyGroupId) {
return execute(
new EeaGetTransactionCountTransaction(
getAddress().toString(), privacyGroupId.toString()))
getAddress().toString(), BytesValues.asBase64String(privacyGroupId)))
.longValue();
}
}

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.tests.web3j.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
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;
@ -23,6 +22,7 @@ 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 java.util.Base64;
@ -32,7 +32,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class PrivateTxEnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBase {
public class EnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBase {
protected static final String CONTRACT_NAME = "Event Emitter";
private EventEmitterHarness eventEmitterHarness;
@ -54,7 +54,8 @@ public class PrivateTxEnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBa
privateTransactionVerifier,
eea);
wrongPublicKey =
BytesValue.wrap(Base64.getEncoder().encode(Box.KeyPair.random().publicKey().bytesArray()));
BytesValues.fromBase64(
Base64.getEncoder().encode(Box.KeyPair.random().publicKey().bytesArray()));
}
@Test
@ -91,8 +92,7 @@ public class PrivateTxEnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBa
.nonce(privacyNet.getNode("Alice").nextNonce(privacyGroup))
.from(privacyNet.getNode("Alice").getAddress())
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave("Alice").getPublicKeys().get(0).getBytes(UTF_8)))
BytesValues.fromBase64(privacyNet.getEnclave("Alice").getPublicKeys().get(0)))
.privateFor(Lists.newArrayList(wrongPublicKey))
.keyPair(privacyNet.getNode("Alice").keyPair())
.build(TransactionType.CREATE_CONTRACT);

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.tests.web3j.privacy;
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;
@ -24,6 +23,7 @@ import tech.pegasys.pantheon.tests.acceptance.dsl.privacy.PrivateTransactionVeri
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;
@ -118,8 +118,7 @@ public class EventEmitterHarness {
.from(privacyNet.getNode(sender).getAddress())
.to(Address.fromHexString(contractAddress))
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave(sender).getPublicKeys().get(0).getBytes(UTF_8)))
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.STORE);
@ -159,8 +158,7 @@ public class EventEmitterHarness {
.from(privacyNet.getNode(sender).getAddress())
.to(Address.fromHexString(contractAddress))
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave(sender).getPublicKeys().get(0).getBytes(UTF_8)))
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.GET);
@ -190,8 +188,7 @@ public class EventEmitterHarness {
.from(privacyNet.getNode(sender).getAddress())
.to(null)
.privateFrom(
BytesValue.wrap(
privacyNet.getEnclave(sender).getPublicKeys().get(0).getBytes(UTF_8)))
BytesValues.fromBase64(privacyNet.getEnclave(sender).getPublicKeys().get(0)))
.privateFor(convertNamesToOrionPublicKeys(receivers))
.keyPair(privacyNet.getNode(sender).keyPair())
.build(PrivateTransactionBuilder.TransactionType.CREATE_CONTRACT);
@ -229,9 +226,7 @@ public class EventEmitterHarness {
private List<BytesValue> convertNamesToOrionPublicKeys(final String... toNodeNames) {
return Arrays.stream(toNodeNames)
.map(
name ->
BytesValue.wrap(privacyNet.getEnclave(name).getPublicKeys().get(0).getBytes(UTF_8)))
.map(name -> BytesValues.fromBase64(privacyNet.getEnclave(name).getPublicKeys().get(0)))
.collect(Collectors.toList());
}

@ -14,6 +14,7 @@ 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;
@ -27,7 +28,6 @@ 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(
@ -47,8 +47,7 @@ public class PrivacyGroup {
.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))))));
return BytesValues.fromBase64(
Base64.getEncoder().encode(Hash.sha3(RlpEncoder.encode(new RlpList(rlpList)))));
}
}

@ -39,10 +39,8 @@ import tech.pegasys.pantheon.ethereum.vm.MessageFrame;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.Base64;
import com.google.common.base.Charsets;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -107,15 +105,14 @@ public class PrivacyPrecompiledContract extends AbstractPrecompiledContract {
}
final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(
BytesValue.wrap(Base64.getDecoder().decode(receiveResponse.getPayload())), false);
new BytesValueRLPInput(BytesValues.fromBase64(receiveResponse.getPayload()), false);
final PrivateTransaction privateTransaction = PrivateTransaction.readFrom(bytesValueRLPInput);
final WorldUpdater publicWorldState = messageFrame.getWorldState();
final BytesValue privacyGroupId =
BytesValue.wrap(receiveResponse.getPrivacyGroupId().getBytes(Charsets.UTF_8));
final BytesValue privacyGroupId = BytesValues.fromBase64(receiveResponse.getPrivacyGroupId());
// get the last world state root hash - or create a new one
final Hash lastRootHash =
privateStateStorage.getPrivateAccountState(privacyGroupId).orElse(EMPTY_ROOT_HASH);

@ -35,7 +35,6 @@ import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.Base64;
import java.util.List;
import java.util.stream.Collectors;
@ -98,18 +97,18 @@ public class PrivateTransactionHandler {
public String getPrivacyGroup(final String key, final PrivateTransaction privateTransaction)
throws Exception {
if (privateTransaction.getPrivacyGroupId().isPresent()) {
return privateTransaction.getPrivacyGroupId().get().toString();
return BytesValues.asBase64String(privateTransaction.getPrivacyGroupId().get());
}
final ReceiveRequest receiveRequest =
new ReceiveRequest(key, BytesValues.asString(privateTransaction.getPrivateFrom().get()));
new ReceiveRequest(
key, BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()));
LOG.debug(
"Getting privacy group for {}",
BytesValues.asString(privateTransaction.getPrivateFrom().get()));
BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()));
final ReceiveResponse receiveResponse;
try {
receiveResponse = enclave.receive(receiveRequest);
return BytesValue.wrap(receiveResponse.getPrivacyGroupId().getBytes(Charsets.UTF_8))
.toString();
return receiveResponse.getPrivacyGroupId();
} catch (Exception e) {
LOG.error("Failed to retrieve private transaction in enclave", e);
throw e;
@ -159,33 +158,34 @@ public class PrivateTransactionHandler {
private SendRequest createSendRequest(final PrivateTransaction privateTransaction) {
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
final String payload = BytesValues.asBase64String(bvrlp.encoded());
if (privateTransaction.getPrivacyGroupId().isPresent()) {
return new SendRequestPantheon(
Base64.getEncoder().encodeToString(bvrlp.encoded().extractArray()),
payload,
enclavePublicKey,
BytesValues.asString(privateTransaction.getPrivacyGroupId().get()));
BytesValues.asBase64String(privateTransaction.getPrivacyGroupId().get()));
} else {
final List<String> privateFor =
privateTransaction.getPrivateFor().get().stream()
.map(BytesValues::asString)
.map(BytesValues::asBase64String)
.collect(Collectors.toList());
// FIXME: orion should accept empty privateFor
if (privateFor.isEmpty()) {
privateFor.add(BytesValues.asString(privateTransaction.getPrivateFrom().get()));
privateFor.add(BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()));
}
return new SendRequestLegacy(
Base64.getEncoder().encodeToString(bvrlp.encoded().extractArray()),
BytesValues.asString(privateTransaction.getPrivateFrom().get()),
payload,
BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()),
privateFor);
}
}
public long getSenderNonce(final Address sender, final String privacyGroupId) {
return privateStateStorage
.getPrivateAccountState(BytesValue.fromHexString(privacyGroupId))
.getPrivateAccountState(BytesValues.fromBase64(privacyGroupId))
.map(
lastRootHash ->
privateWorldStateArchive

@ -26,9 +26,7 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Base64;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import org.apache.logging.log4j.Logger;
@ -56,7 +54,7 @@ public class EeaGetPrivateTransaction implements JsonRpcMethod {
@Override
public JsonRpcResponse response(final JsonRpcRequest request) {
LOG.trace("Executing {}", RpcMethod.EEA_GET_TRANSACTION_RECEIPT.getMethodName());
LOG.trace("Executing {}", RpcMethod.EEA_GET_PRIVATE_TRANSACTION.getMethodName());
final String enclaveKey = parameters.required(request.getParams(), 0, String.class);
try {
ReceiveResponse receiveResponse =
@ -64,8 +62,7 @@ public class EeaGetPrivateTransaction implements JsonRpcMethod {
LOG.trace("Received transaction information from Enclave");
final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(
BytesValue.wrap(Base64.getDecoder().decode(receiveResponse.getPayload())), false);
new BytesValueRLPInput(BytesValues.fromBase64(receiveResponse.getPayload()), false);
final PrivateTransaction privateTransaction = PrivateTransaction.readFrom(bytesValueRLPInput);
return new JsonRpcSuccessResponse(request.getId(), privateTransaction);

@ -39,13 +39,12 @@ import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.util.bytes.Bytes32;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import com.google.common.base.Charsets;
import org.apache.logging.log4j.Logger;
public class EeaGetTransactionReceipt implements JsonRpcMethod {
@ -98,8 +97,7 @@ public class EeaGetTransactionReceipt implements JsonRpcMethod {
LOG.trace("Received transaction information from Enclave");
final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(
BytesValue.wrap(Base64.getDecoder().decode(receiveResponse.getPayload())), false);
new BytesValueRLPInput(BytesValues.fromBase64(receiveResponse.getPayload()), false);
privateTransaction = PrivateTransaction.readFrom(bytesValueRLPInput);
privacyGroupId = receiveResponse.getPrivacyGroupId();
@ -114,7 +112,7 @@ public class EeaGetTransactionReceipt implements JsonRpcMethod {
? Address.privateContractAddress(
privateTransaction.getSender(),
privateTransaction.getNonce(),
BytesValue.wrap(privacyGroupId.getBytes(Charsets.UTF_8)))
BytesValues.fromBase64(privacyGroupId))
.toString()
: null;

@ -23,13 +23,15 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParamet
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionHandler;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import org.junit.Test;
public class EeaGetTransactionCountTest {
private final JsonRpcParameter parameters = new JsonRpcParameter();
private final BytesValue privacyGroupId = BytesValue.wrap("0x123".getBytes(UTF_8));
private final String privacyGroupId =
BytesValues.asBase64String(BytesValue.wrap("0x123".getBytes(UTF_8)));
private final Address senderAddress =
Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57");
@ -39,13 +41,12 @@ public class EeaGetTransactionCountTest {
public void verifyTransactionCount() {
final PrivateTransactionHandler privateTransactionHandler =
mock(PrivateTransactionHandler.class);
when(privateTransactionHandler.getSenderNonce(senderAddress, privacyGroupId.toString()))
.thenReturn(NONCE);
when(privateTransactionHandler.getSenderNonce(senderAddress, privacyGroupId)).thenReturn(NONCE);
final EeaGetTransactionCount eeaGetTransactionCount =
new EeaGetTransactionCount(parameters, privateTransactionHandler);
final Object[] params = new Object[] {senderAddress, privacyGroupId.toString()};
final Object[] params = new Object[] {senderAddress, privacyGroupId};
final JsonRpcRequest request = new JsonRpcRequest("1", "eea_getTransactionCount", params);
final JsonRpcSuccessResponse response =

@ -16,6 +16,7 @@ import static com.google.common.base.Preconditions.checkArgument;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
/** Static utility methods to work with {@link BytesValue} and {@link MutableBytesValue}. */
public abstract class BytesValues {
@ -254,6 +255,18 @@ public abstract class BytesValues {
return new BigInteger(bytes.getArrayUnsafe());
}
public static String asBase64String(final BytesValue bytesValue) {
return Base64.getEncoder().encodeToString(bytesValue.extractArray());
}
public static BytesValue fromBase64(final byte[] bytes) {
return BytesValue.wrap(Base64.getDecoder().decode(bytes));
}
public static BytesValue fromBase64(final String str) {
return BytesValue.wrap(Base64.getDecoder().decode(str));
}
// In Java9, this could be moved to BytesValue and made private
static BytesValue fromHexString(final String str, final int destSize, final boolean lenient) {
return BytesValue.wrap(fromRawHexString(str, destSize, lenient));

Loading…
Cancel
Save