Skip to content

Commit

Permalink
Handle base64 <-> BytesValue in uniform way throughout
Browse files Browse the repository at this point in the history
  • Loading branch information
iikirilov committed Jul 11, 2019
1 parent 4080774 commit 242f895
Show file tree
Hide file tree
Showing 11 changed files with 61 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ public class PrivacyAcceptanceTestBase extends AcceptanceTestBase {
@ClassRule public static final TemporaryFolder privacy = new TemporaryFolder();

protected final EeaConditions eea;
protected final PrivateTransactions privateTransactions;
protected final PrivateTransactions
privateTransactions;
protected final PrivateTransactionBuilder.Builder privateTransactionBuilder;
protected final PrivateTransactionVerifier privateTransactionVerifier;
protected final PrivacyPantheonNodeFactory privacyPantheon;

public PrivacyAcceptanceTestBase() {
final EeaTransactions eeaTransactions = new EeaTransactions();

privateTransactions = new PrivateTransactions();
privateTransactions =
new PrivateTransactions();
eea = new EeaConditions(eeaTransactions);
privateTransactionBuilder = PrivateTransactionBuilder.builder();
privateTransactionVerifier = new PrivateTransactionVerifier(eea, eeaTransactions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;
Expand Down Expand Up @@ -113,7 +114,7 @@ public void testOrionConnection(final PrivacyNode... otherNodes) {
public long nextNonce(final BytesValue privacyGroupId) {
return execute(
new EeaGetTransactionCountTransaction(
getAddress().toString(), privacyGroupId.toString()))
getAddress().toString(), BytesValues.asBase64String(privacyGroupId)))
.longValue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -24,6 +23,7 @@
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;
Expand Down Expand Up @@ -118,8 +118,7 @@ public void store(
.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);
Expand Down Expand Up @@ -159,8 +158,7 @@ public void get(
.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);
Expand Down Expand Up @@ -190,8 +188,7 @@ private void deploy(
.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);
Expand Down Expand Up @@ -229,9 +226,7 @@ private void waitForTransactionToBeMined(final String transactionHash) {

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());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

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;
Expand All @@ -27,7 +28,6 @@
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(
Expand All @@ -47,8 +47,7 @@ public static BytesValue generatePrivacyGroup(
.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)))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@
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;

Expand Down Expand Up @@ -107,15 +105,14 @@ public BytesValue compute(final BytesValue input, final MessageFrame messageFram
}

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);
Expand Down Expand Up @@ -144,7 +141,7 @@ public BytesValue compute(final BytesValue input, final MessageFrame messageFram
}

if (messageFrame.isPersistingState()) {
LOG.trace(
LOG.debug(
"Persisting private state {} for privacyGroup {}",
disposablePrivateState.rootHash(),
privacyGroupId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
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;

Expand Down Expand Up @@ -98,18 +97,18 @@ public String sendToOrion(final PrivateTransaction privateTransaction) throws Ex
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;
Expand Down Expand Up @@ -159,33 +158,34 @@ public ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.util.Base64;

import org.apache.logging.log4j.Logger;
import tech.pegasys.pantheon.util.bytes.BytesValues;

public class EeaGetPrivateTransaction implements JsonRpcMethod {

Expand All @@ -56,7 +57,7 @@ public String getName() {

@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 =
Expand All @@ -65,7 +66,7 @@ public JsonRpcResponse response(final JsonRpcRequest request) {

final BytesValueRLPInput bytesValueRLPInput =
new BytesValueRLPInput(
BytesValue.wrap(Base64.getDecoder().decode(receiveResponse.getPayload())), false);
BytesValues.fromBase64(receiveResponse.getPayload()), false);

final PrivateTransaction privateTransaction = PrivateTransaction.readFrom(bytesValueRLPInput);
return new JsonRpcSuccessResponse(request.getId(), privateTransaction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.Quantity;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionHandler;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class EeaGetTransactionCount implements JsonRpcMethod {
private static final Logger LOG = LogManager.getLogger();

private final JsonRpcParameter parameters;
private final PrivateTransactionHandler privateTransactionHandler;
Expand All @@ -51,6 +55,7 @@ public JsonRpcResponse response(final JsonRpcRequest request) {
final String privacyGroupId = parameters.required(request.getParams(), 1, String.class);

final long nonce = privateTransactionHandler.getSenderNonce(address, privacyGroupId);

return new JsonRpcSuccessResponse(request.getId(), Quantity.create(nonce));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,12 @@
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 {
Expand Down Expand Up @@ -98,8 +97,7 @@ public JsonRpcResponse response(final JsonRpcRequest request) {
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();
Expand All @@ -114,7 +112,7 @@ public JsonRpcResponse response(final JsonRpcRequest request) {
? Address.privateContractAddress(
privateTransaction.getSender(),
privateTransaction.getNonce(),
BytesValue.wrap(privacyGroupId.getBytes(Charsets.UTF_8)))
BytesValues.fromBase64(privacyGroupId))
.toString()
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@
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");
Expand All @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

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 {
Expand Down Expand Up @@ -254,6 +255,18 @@ public static BigInteger asSignedBigInteger(final BytesValue bytes) {
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));
Expand Down

0 comments on commit 242f895

Please sign in to comment.