[PAN-2910] Eea get private transaction fix (#1707)

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Ivaylo Kirilov 5 years ago committed by Lucas Saldanha
parent 405405e4e6
commit 26c7e05948
  1. 4
      ethereum/core/src/integration-test/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java
  2. 3
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContract.java
  3. 112
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransaction.java
  4. 19
      ethereum/core/src/main/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionHandler.java
  5. 22
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionHandlerTest.java
  6. 117
      ethereum/core/src/test/java/tech/pegasys/pantheon/ethereum/privacy/PrivateTransactionTest.java
  7. 12
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetPrivateTransaction.java
  8. 3
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetTransactionReceipt.java
  9. 5
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransaction.java
  10. 53
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/results/privacy/PrivateTransactionGroupResult.java
  11. 59
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/results/privacy/PrivateTransactionLegacyResult.java
  12. 117
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/results/privacy/PrivateTransactionResult.java
  13. 75
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaGetPrivateTransactionTest.java
  14. 64
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/privacy/EeaSendRawTransactionTest.java

@ -43,6 +43,7 @@ import tech.pegasys.pantheon.ethereum.vm.OperationTracer;
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.io.IOException;
import java.util.Base64;
@ -168,8 +169,7 @@ public class PrivacyPrecompiledContractIntegrationTest {
privacyPrecompiledContract.setPrivateTransactionProcessor(mockPrivateTxProcessor());
BytesValue actual =
privacyPrecompiledContract.compute(
BytesValue.wrap(sr.getKey().getBytes(UTF_8)), messageFrame);
privacyPrecompiledContract.compute(BytesValues.fromBase64(sr.getKey()), messageFrame);
assertThat(actual).isEqualTo(BytesValue.fromHexString(DEFAULT_OUTPUT));
}

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.ethereum.mainnet.precompiles.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static tech.pegasys.pantheon.crypto.Hash.keccak256;
import tech.pegasys.pantheon.enclave.Enclave;
@ -93,7 +92,7 @@ public class PrivacyPrecompiledContract extends AbstractPrecompiledContract {
@Override
public BytesValue compute(final BytesValue input, final MessageFrame messageFrame) {
final String key = new String(input.extractArray(), UTF_8);
final String key = BytesValues.asBase64String(input);
final ReceiveRequest receiveRequest = new ReceiveRequest(key, enclavePublicKey);
ReceiveResponse receiveResponse;

@ -66,12 +66,12 @@ public class PrivateTransaction {
private final Optional<BigInteger> chainId;
private final Optional<BytesValue> privacyGroupId;
private final Optional<BytesValue> privateFrom;
private final BytesValue privateFrom;
private final Optional<List<BytesValue>> privateFor;
private final Optional<BytesValue> privacyGroupId;
private final Restriction restriction;
// Caches a "hash" of a portion of the transaction used for sender recovery.
@ -91,6 +91,12 @@ public class PrivateTransaction {
}
public static PrivateTransaction readFrom(final RLPInput input) throws RLPException {
return readFrom(input, null);
}
@SuppressWarnings({"unchecked"})
public static PrivateTransaction readFrom(final RLPInput input, final BytesValue enclavePublicKey)
throws RLPException {
input.enterList();
final Builder builder =
@ -117,34 +123,49 @@ public class PrivateTransaction {
final BigInteger r = BytesValues.asUnsignedBigInteger(input.readUInt256Scalar().getBytes());
final BigInteger s = BytesValues.asUnsignedBigInteger(input.readUInt256Scalar().getBytes());
final SECP256K1.Signature signature = SECP256K1.Signature.create(r, s, recId);
final BytesValue tempValue = input.readBytesValue();
Optional<List<BytesValue>> privateFor = Optional.empty();
if (input.nextIsList()) {
privateFor = Optional.of(input.readList(RLPInput::readBytesValue));
}
final Restriction restriction = convertToEnum(input.readBytesValue());
final RLPInput item1 = input.readAsRlp(); // privateFrom or privateFor/PrivacyGroupId
final RLPInput item2 = input.readAsRlp(); // privateFor/PrivacyGroupId or restriction
final BytesValue privateFrom;
final Object privateForOrPrivacyGroupId;
final Restriction restriction;
if (input.isEndOfCurrentList()) {
privateFrom = enclavePublicKey;
privateForOrPrivacyGroupId = resolvePrivateForOrPrivacyGroupId(item1);
restriction = convertToEnum(item2.readBytesValue());
} else {
privateFrom = item1.readBytesValue();
privateForOrPrivacyGroupId = resolvePrivateForOrPrivacyGroupId(item2);
restriction = convertToEnum(input.readBytesValue());
}
input.leaveList();
chainId.ifPresent(builder::chainId);
if (privateFor.isPresent()) {
if (privateForOrPrivacyGroupId instanceof List) {
return builder
.signature(signature)
.privateFrom(tempValue)
.privateFor(privateFor.get())
.privateFrom(privateFrom)
.privateFor((List<BytesValue>) privateForOrPrivacyGroupId)
.restriction(restriction)
.build();
} else {
return builder
.signature(signature)
.privacyGroupId(tempValue)
.privateFrom(privateFrom)
.privacyGroupId((BytesValue) privateForOrPrivacyGroupId)
.restriction(restriction)
.build();
}
}
private static Object resolvePrivateForOrPrivacyGroupId(final RLPInput item) {
return item.nextIsList() ? item.readList(RLPInput::readBytesValue) : item.readBytesValue();
}
private static Restriction convertToEnum(final BytesValue readBytesValue) {
if (readBytesValue.equals(Restriction.RESTRICTED.getBytes())) {
return Restriction.RESTRICTED;
@ -186,9 +207,9 @@ public class PrivateTransaction {
final BytesValue payload,
final Address sender,
final Optional<BigInteger> chainId,
final Optional<BytesValue> privacyGroupId,
final Optional<BytesValue> privateFrom,
final BytesValue privateFrom,
final Optional<List<BytesValue>> privateFor,
final Optional<BytesValue> privacyGroupId,
final Restriction restriction) {
this.nonce = nonce;
this.gasPrice = gasPrice;
@ -199,9 +220,9 @@ public class PrivateTransaction {
this.payload = payload;
this.sender = sender;
this.chainId = chainId;
this.privacyGroupId = privacyGroupId;
this.privateFrom = privateFrom;
this.privateFor = privateFor;
this.privacyGroupId = privacyGroupId;
this.restriction = restriction;
}
@ -283,21 +304,12 @@ public class PrivateTransaction {
return chainId;
}
/**
* Returns the enclave privacy group id.
*
* @return the enclave privacy group id.
*/
public Optional<BytesValue> getPrivacyGroupId() {
return privacyGroupId;
}
/**
* Returns the enclave public key of the sender.
*
* @return the enclave public key of the sender.
*/
public Optional<BytesValue> getPrivateFrom() {
public BytesValue getPrivateFrom() {
return privateFrom;
}
@ -310,6 +322,15 @@ public class PrivateTransaction {
return privateFor;
}
/**
* Returns the enclave privacy group id.
*
* @return the enclave privacy group id.
*/
public Optional<BytesValue> getPrivacyGroupId() {
return privacyGroupId;
}
/**
* Returns the restriction of this private transaction.
*
@ -348,9 +369,9 @@ public class PrivateTransaction {
value,
payload,
chainId,
privacyGroupId,
privateFrom,
privateFor,
privacyGroupId,
restriction.getBytes());
}
return hashNoSignature;
@ -371,10 +392,10 @@ public class PrivateTransaction {
out.writeUInt256Scalar(getValue());
out.writeBytesValue(getPayload());
writeSignature(out);
getPrivacyGroupId().ifPresent(out::writeBytesValue);
getPrivateFrom().ifPresent(out::writeBytesValue);
out.writeBytesValue(getPrivateFrom());
getPrivateFor()
.ifPresent(privateFor -> out.writeList(privateFor, (bv, rlpO) -> rlpO.writeBytesValue(bv)));
getPrivacyGroupId().ifPresent(out::writeBytesValue);
out.writeBytesValue(getRestriction().getBytes());
out.endList();
@ -457,9 +478,9 @@ public class PrivateTransaction {
final Wei value,
final BytesValue payload,
final Optional<BigInteger> chainId,
final Optional<BytesValue> privacyGroupId,
final Optional<BytesValue> privateFrom,
final BytesValue privateFrom,
final Optional<List<BytesValue>> privateFor,
final Optional<BytesValue> privacyGroupId,
final BytesValue restriction) {
return keccak256(
RLP.encode(
@ -476,9 +497,9 @@ public class PrivateTransaction {
out.writeUInt256Scalar(UInt256.ZERO);
out.writeUInt256Scalar(UInt256.ZERO);
}
privacyGroupId.ifPresent(out::writeBytesValue);
privateFrom.ifPresent(out::writeBytesValue);
out.writeBytesValue(privateFrom);
privateFor.ifPresent(pF -> out.writeList(pF, (bv, rlpO) -> rlpO.writeBytesValue(bv)));
privacyGroupId.ifPresent(out::writeBytesValue);
out.writeBytesValue(restriction);
out.endList();
}));
@ -530,15 +551,14 @@ public class PrivateTransaction {
sb.append("value=").append(getValue()).append(", ");
sb.append("sig=").append(getSignature()).append(", ");
if (chainId.isPresent()) sb.append("chainId=").append(getChainId().get()).append(", ");
sb.append("payload=").append(getPayload());
if (getPrivacyGroupId().isPresent())
sb.append("privacyGroupId=").append(getPrivacyGroupId().get()).append(", ");
if (getPrivateFrom().isPresent())
sb.append("privateFrom=").append(getPrivateFrom().get()).append(", ");
sb.append("payload=").append(getPayload()).append(", ");
sb.append("privateFrom=").append(getPrivateFrom()).append(", ");
if (getPrivateFor().isPresent())
sb.append("privateFor=")
.append(Arrays.toString(getPrivateFor().get().toArray()))
.append(", ");
if (getPrivacyGroupId().isPresent())
sb.append("privacyGroupId=").append(getPrivacyGroupId().get()).append(", ");
sb.append("restriction=").append(getRestriction());
return sb.append("}").toString();
}
@ -570,12 +590,12 @@ public class PrivateTransaction {
protected Optional<BigInteger> chainId = Optional.empty();
protected Optional<BytesValue> privacyGroupId = Optional.empty();
protected Optional<BytesValue> privateFrom = Optional.empty();
protected BytesValue privateFrom;
protected Optional<List<BytesValue>> privateFor = Optional.empty();
protected Optional<BytesValue> privacyGroupId = Optional.empty();
protected Restriction restriction;
public Builder chainId(final BigInteger chainId) {
@ -629,7 +649,7 @@ public class PrivateTransaction {
}
public Builder privateFrom(final BytesValue privateFrom) {
this.privateFrom = Optional.of(privateFrom);
this.privateFrom = privateFrom;
return this;
}
@ -644,9 +664,9 @@ public class PrivateTransaction {
}
public PrivateTransaction build() {
if (privacyGroupId.isPresent() && (privateFrom.isPresent() || privateFor.isPresent())) {
if (privacyGroupId.isPresent() && privateFor.isPresent()) {
throw new IllegalArgumentException(
"Private transaction should contain either privacyGroup by itself or privateFrom and privateFor together, but not both");
"Private transaction should contain either privacyGroup or privateFor, but not both");
}
return new PrivateTransaction(
nonce,
@ -658,9 +678,9 @@ public class PrivateTransaction {
payload,
sender,
chainId,
privacyGroupId,
privateFrom,
privateFor,
privacyGroupId,
restriction);
}
@ -682,9 +702,9 @@ public class PrivateTransaction {
value,
payload,
chainId,
privacyGroupId,
privateFrom,
privateFor,
privacyGroupId,
restriction.getBytes());
return SECP256K1.sign(hash, keys);
}

@ -32,13 +32,11 @@ import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionIn
import tech.pegasys.pantheon.ethereum.mainnet.ValidationResult;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.List;
import java.util.stream.Collectors;
import com.google.common.base.Charsets;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -100,11 +98,10 @@ public class PrivateTransactionHandler {
return BytesValues.asBase64String(privateTransaction.getPrivacyGroupId().get());
}
final ReceiveRequest receiveRequest =
new ReceiveRequest(
key, BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()));
new ReceiveRequest(key, BytesValues.asBase64String(privateTransaction.getPrivateFrom()));
LOG.debug(
"Getting privacy group for {}",
BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()));
BytesValues.asBase64String(privateTransaction.getPrivateFrom()));
final ReceiveResponse receiveResponse;
try {
receiveResponse = enclave.receive(receiveRequest);
@ -126,7 +123,7 @@ public class PrivateTransactionHandler {
.gasLimit(privateTransaction.getGasLimit())
.to(privacyPrecompileAddress)
.value(privateTransaction.getValue())
.payload(BytesValue.wrap(transactionEnclaveKey.getBytes(Charsets.UTF_8)))
.payload(BytesValues.fromBase64(transactionEnclaveKey))
.sender(signerAddress)
.signAndBuild(nodeKeyPair);
}
@ -173,13 +170,11 @@ public class PrivateTransactionHandler {
// FIXME: orion should accept empty privateFor
if (privateFor.isEmpty()) {
privateFor.add(BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()));
privateFor.add(BytesValues.asBase64String(privateTransaction.getPrivateFrom()));
}
return new SendRequestLegacy(
payload,
BytesValues.asBase64String(privateTransaction.getPrivateFrom().get()),
privateFor);
payload, BytesValues.asBase64String(privateTransaction.getPrivateFrom()), privateFor);
}
}
@ -210,4 +205,8 @@ public class PrivateTransactionHandler {
public Address getSignerAddress() {
return signerAddress;
}
public String getEnclaveKey() {
return enclavePublicKey;
}
}

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.ethereum.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
@ -38,12 +37,12 @@ import tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionIn
import tech.pegasys.pantheon.ethereum.mainnet.ValidationResult;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Optional;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
@ -53,15 +52,15 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class PrivateTransactionHandlerTest {
private static final String TRANSACTION_KEY = "My Transaction Key";
private static final String TRANSACTION_KEY = "93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=";
private static final KeyPair KEY_PAIR =
KeyPair.create(
SECP256K1.PrivateKey.create(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
PrivateTransactionHandler privateTransactionHandler;
PrivateTransactionHandler brokenPrivateTransactionHandler;
private PrivateTransactionHandler privateTransactionHandler;
private PrivateTransactionHandler brokenPrivateTransactionHandler;
private static final Transaction PUBLIC_TRANSACTION =
Transaction.builder()
@ -70,7 +69,7 @@ public class PrivateTransactionHandlerTest {
.gasLimit(3000000)
.to(Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57"))
.value(Wei.ZERO)
.payload(BytesValue.wrap(TRANSACTION_KEY.getBytes(Charsets.UTF_8)))
.payload(BytesValues.fromBase64(TRANSACTION_KEY))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(BigInteger.valueOf(2018))
.signAndBuild(KEY_PAIR);
@ -202,20 +201,19 @@ public class PrivateTransactionHandlerTest {
private static PrivateTransaction buildLegacyPrivateTransaction(final long nonce) {
return buildPrivateTransaction(nonce)
.privateFrom(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
.privateFrom(BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privateFor(
Lists.newArrayList(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="),
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")))
.signAndBuild(KEY_PAIR);
}
private static PrivateTransaction buildPantheonPrivateTransaction(final long nonce) {
return buildPrivateTransaction(nonce)
.privacyGroupId(
BytesValue.wrap("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=".getBytes(UTF_8)))
.privateFrom(BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privacyGroupId(BytesValues.fromBase64("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w="))
.signAndBuild(KEY_PAIR);
}

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.ethereum.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import tech.pegasys.pantheon.crypto.SECP256K1;
@ -22,6 +21,7 @@ import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.ethereum.rlp.RLPException;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.math.BigInteger;
import java.util.Optional;
@ -39,58 +39,53 @@ public class PrivateTransactionTest {
+ "601b4ab949f53faa07bd2c804";
private static final String VALID_PRIVATE_TRANSACTION_RLP =
"0xf90113800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87"
+ "a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "ffff801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d"
+ "495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab94"
+ "9f53faa07bd2c804ac41316156744d784c4355486d425648586f5a7a7a4267"
+ "5062572f776a3561784470573958386c393153476f3df85aac41316156744d"
+ "784c4355486d425648586f5a7a7a42675062572f776a356178447057395838"
+ "6c393153476f3dac4b6f32625671442b6e4e6c4e594c35454537793349644f"
+ "6e766966746a69697a706a52742b4854754642733d8a726573747269637465"
+ "64";
"0xf8ef800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87a0f"
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3"
+ "6649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53fa"
+ "a07bd2c804a0035695b4cc4b0941e60551d7a19cf30603db5bfc23e5ac43a56"
+ "f57f25f75486af842a0035695b4cc4b0941e60551d7a19cf30603db5bfc23e5"
+ "ac43a56f57f25f75486aa02a8d9b56a0fe9cd94d60be4413bcb721d3a7be27e"
+ "d8e28b3a6346df874ee141b8a72657374726963746564";
private static final String VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP =
"0xf8b7800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87a0f"
"0xf8cc800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87a0f"
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3"
+ "6649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53fa"
+ "a07bd2c804ac4479414f69462f796e70632b4a5861325941474230624369745"
+ "36c4f4d4e6d2b53686d422f374d364334773d8a72657374726963746564";
+ "a07bd2c804a0035695b4cc4b0941e60551d7a19cf30603db5bfc23e5ac43a56"
+ "f57f25f75486aa00f200e885ff29e973e2576b6600181d1b0a2b5294e30d9be"
+ "4a1981ffb33a0b8c8a72657374726963746564";
private static final String VALID_SIGNED_PRIVATE_TRANSACTION_RLP =
"0xf901a4808203e8832dc6c08080b8ef60806040523480156100105760008"
+ "0fd5b5060d08061001f6000396000f3fe60806040526004361060485763f"
+ "fffffff7c010000000000000000000000000000000000000000000000000"
+ "000000060003504166360fe47b18114604d5780636d4ce63c146075575b6"
+ "00080fd5b348015605857600080fd5b50607360048036036020811015606"
+ "d57600080fd5b50356099565b005b348015608057600080fd5b506087609"
+ "e565b60408051918252519081900360200190f35b600055565b600054905"
+ "6fea165627a7a72305820cb1d0935d14b589300b12fcd0ab849a7e9019c8"
+ "1da24d6daa4f6b2f003d1b01800292ca0a6dc7319bd355ce9d8e0928d29d"
+ "9b8110bcba9168fad68498e49526420fe65dea06c4c12c2ae518c5130353"
+ "eb6c2893b1c36b7fd1497c156b1e158b716f482601fac41316156744d784"
+ "c4355486d425648586f5a7a7a42675062572f776a3561784470573958386"
+ "c393153476f3dedac4b6f32625671442b6e4e6c4e594c354545377933496"
+ "44f6e766966746a69697a706a52742b4854754642733d8a7265737472696"
+ "3746564";
"0xf9018c808203e8832dc6c08080b8ef60806040523480156100105760008"
+ "0fd5b5060d08061001f6000396000f3fe60806040526004361060485763ffff"
+ "ffff7c010000000000000000000000000000000000000000000000000000000"
+ "060003504166360fe47b18114604d5780636d4ce63c146075575b600080fd5b"
+ "348015605857600080fd5b50607360048036036020811015606d57600080fd5"
+ "b50356099565b005b348015608057600080fd5b506087609e565b6040805191"
+ "8252519081900360200190f35b600055565b6000549056fea165627a7a72305"
+ "820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6daa4f6b2f003d1"
+ "b01800292ca0bab7ae7f68afad5ade9e26177e044079bbcfd7857cf911b7a4c"
+ "97027dd92e41ba06e92e391ced52de53725e3054af3908a9f2f36374d727ebc"
+ "616a96a1ed2ca548a0035695b4cc4b0941e60551d7a19cf30603db5bfc23e5a"
+ "c43a56f57f25f75486ae1a02a8d9b56a0fe9cd94d60be4413bcb721d3a7be27"
+ "ed8e28b3a6346df874ee141b8a72657374726963746564";
private static final String VALID_SIGNED_PRIVATE_TRANSACTION_LARGE_CHAINID_RLP =
"0xf901a9808203e8832dc6c08080b8ef608060405234801561001057600080"
+ "fd5b5060d08061001f6000396000f3fe60806040526004361060485763ff"
+ "ffffff7c0100000000000000000000000000000000000000000000000000"
+ "00000060003504166360fe47b18114604d5780636d4ce63c146075575b60"
+ "0080fd5b348015605857600080fd5b50607360048036036020811015606d"
+ "57600080fd5b50356099565b005b348015608057600080fd5b506087609e"
+ "565b60408051918252519081900360200190f35b600055565b6000549056"
+ "fea165627a7a72305820cb1d0935d14b589300b12fcd0ab849a7e9019c81"
+ "da24d6daa4f6b2f003d1b0180029850100000022a0ebccb6952d7ad4eb5c"
+ "1d4da2f67a833f66c1b9127e0c592224dd24210104a095a07d35a1bbc54f"
+ "fa5b2dc9f315b545238575c8960108076036c6ffcafedddf4d22ac413161"
+ "56744d784c4355486d425648586f5a7a7a42675062572f776a3561784470"
+ "573958386c393153476f3dedac4b6f32625671442b6e4e6c4e594c354545"
+ "37793349644f6e766966746a69697a706a52742b4854754642733d8a7265"
+ "7374726963746564";
"0xf90191808203e8832dc6c08080b8ef60806040523480156100105760008"
+ "0fd5b5060d08061001f6000396000f3fe60806040526004361060485763ffff"
+ "ffff7c010000000000000000000000000000000000000000000000000000000"
+ "060003504166360fe47b18114604d5780636d4ce63c146075575b600080fd5b"
+ "348015605857600080fd5b50607360048036036020811015606d57600080fd5"
+ "b50356099565b005b348015608057600080fd5b506087609e565b6040805191"
+ "8252519081900360200190f35b600055565b6000549056fea165627a7a72305"
+ "820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6daa4f6b2f003d1"
+ "b0180029850100000021a0bfa05529e85cdaadda498b6ab4ded157a70356ad7"
+ "6df24c18fa12b9d49be6ef4a03a54b8bc0c4e41e08d4cf0e94da98c5e02ef57"
+ "524cf2b53deecd56e3ba184927a0035695b4cc4b0941e60551d7a19cf30603d"
+ "b5bfc23e5ac43a56f57f25f75486ae1a02a8d9b56a0fe9cd94d60be4413bcb7"
+ "21d3a7be27ed8e28b3a6346df874ee141b8a72657374726963746564";
private static final PrivateTransaction VALID_PRIVATE_TRANSACTION =
new PrivateTransaction(
@ -111,13 +106,12 @@ public class PrivateTransactionTest {
BytesValue.fromHexString("0x"),
Address.wrap(BytesValue.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
Optional.empty(),
Optional.empty(),
Optional.of(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8))),
BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="),
Optional.of(
Lists.newArrayList(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8)))),
BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="),
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="))),
Optional.empty(),
Restriction.RESTRICTED);
private static final PrivateTransaction VALID_PRIVATE_TRANSACTION_PRIVACY_GROUP =
@ -139,10 +133,9 @@ public class PrivateTransactionTest {
BytesValue.fromHexString("0x"),
Address.wrap(BytesValue.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
Optional.empty(),
Optional.of(
BytesValue.wrap("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=".getBytes(UTF_8))),
Optional.empty(),
BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="),
Optional.empty(),
Optional.of(BytesValues.fromBase64("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=")),
Restriction.RESTRICTED);
private static final PrivateTransaction VALID_SIGNED_PRIVATE_TRANSACTION =
@ -167,11 +160,10 @@ public class PrivateTransactionTest {
.sender(
Address.wrap(BytesValue.fromHexString("0x1c9a6e1ee3b7ac6028e786d9519ae3d24ee31e79")))
.chainId(BigInteger.valueOf(4))
.privateFrom(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
.privateFrom(BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privateFor(
Lists.newArrayList(
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")))
.restriction(Restriction.RESTRICTED)
.signAndBuild(
SECP256K1.KeyPair.create(
@ -202,11 +194,10 @@ public class PrivateTransactionTest {
.sender(
Address.wrap(BytesValue.fromHexString("0x1c9a6e1ee3b7ac6028e786d9519ae3d24ee31e79")))
.chainId(BigInteger.valueOf(2147483647))
.privateFrom(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
.privateFrom(BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privateFor(
Lists.newArrayList(
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")))
.restriction(Restriction.RESTRICTED)
.signAndBuild(
SECP256K1.KeyPair.create(
@ -300,14 +291,12 @@ public class PrivateTransactionTest {
.payload(BytesValue.fromHexString("0x"))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(BigInteger.valueOf(2018))
.privacyGroupId(
BytesValue.wrap("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=".getBytes(UTF_8)))
.privateFrom(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
.privacyGroupId(BytesValues.fromBase64("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w="))
.privateFrom(BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privateFor(
Lists.newArrayList(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="),
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")))
.restriction(Restriction.RESTRICTED)
.build();
}

@ -24,6 +24,8 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.JsonRpcMethod;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.privacy.PrivateTransactionGroupResult;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.privacy.PrivateTransactionLegacyResult;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPInput;
import tech.pegasys.pantheon.util.bytes.BytesValues;
@ -65,9 +67,15 @@ public class EeaGetPrivateTransaction implements JsonRpcMethod {
new BytesValueRLPInput(BytesValues.fromBase64(receiveResponse.getPayload()), false);
final PrivateTransaction privateTransaction = PrivateTransaction.readFrom(bytesValueRLPInput);
return new JsonRpcSuccessResponse(request.getId(), privateTransaction);
if (privateTransaction.getPrivacyGroupId().isPresent()) {
return new JsonRpcSuccessResponse(
request.getId(), new PrivateTransactionGroupResult(privateTransaction));
} else {
return new JsonRpcSuccessResponse(
request.getId(), new PrivateTransactionLegacyResult(privateTransaction));
}
} catch (Exception e) {
LOG.error("Failed to fetch transaction from Enclave with error " + e.getMessage());
LOG.error("Failed to fetch private transaction with error " + e.getMessage());
return new JsonRpcSuccessResponse(request.getId(), null);
}
}

@ -12,7 +12,6 @@
*/
package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.logging.log4j.LogManager.getLogger;
import tech.pegasys.pantheon.enclave.Enclave;
@ -160,7 +159,7 @@ public class EeaGetTransactionReceipt implements JsonRpcMethod {
final Transaction transaction, final String publicKey) throws Exception {
LOG.trace("Fetching transaction information from Enclave");
final ReceiveRequest enclaveRequest =
new ReceiveRequest(new String(transaction.getPayload().extractArray(), UTF_8), publicKey);
new ReceiveRequest(BytesValues.asBase64String(transaction.getPayload()), publicKey);
ReceiveResponse enclaveResponse = enclave.receive(enclaveRequest);
LOG.trace("Received transaction information from Enclave");
return enclaveResponse;

@ -35,6 +35,7 @@ import tech.pegasys.pantheon.ethereum.privacy.Restriction;
import tech.pegasys.pantheon.ethereum.rlp.RLP;
import tech.pegasys.pantheon.ethereum.rlp.RLPException;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.OptionalLong;
@ -133,7 +134,9 @@ public class EeaSendRawTransaction implements JsonRpcMethod {
private PrivateTransaction decodeRawTransaction(final String hash)
throws InvalidJsonRpcRequestException {
try {
return PrivateTransaction.readFrom(RLP.input(BytesValue.fromHexString(hash)));
return PrivateTransaction.readFrom(
RLP.input(BytesValue.fromHexString(hash)),
BytesValues.fromBase64(privateTransactionHandler.getEnclaveKey()));
} catch (final IllegalArgumentException | RLPException e) {
LOG.debug(e);
throw new InvalidJsonRpcRequestException("Invalid raw private transaction hex", e);

@ -0,0 +1,53 @@
/*
* 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.ethereum.jsonrpc.internal.results.privacy;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonPropertyOrder({
"from",
"gas",
"gasPrice",
"hash",
"input",
"nonce",
"to",
"value",
"v",
"r",
"s",
"privateFrom",
"privacyGroupId",
"restriction"
})
/*
The original deserialised private transaction sent via eea_sendRawTransaction
This class is used if the original request was sent with privateFrom and privateFor
*/
public class PrivateTransactionGroupResult extends PrivateTransactionResult {
private final String privacyGroupId;
public PrivateTransactionGroupResult(final PrivateTransaction tx) {
super(tx);
this.privacyGroupId = BytesValues.asBase64String(tx.getPrivacyGroupId().get());
}
@JsonGetter(value = "privateFor")
public String getPrivacyGroupId() {
return privacyGroupId;
}
}

@ -0,0 +1,59 @@
/*
* 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.ethereum.jsonrpc.internal.results.privacy;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.util.List;
import java.util.stream.Collectors;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
@JsonPropertyOrder({
"from",
"gas",
"gasPrice",
"hash",
"input",
"nonce",
"to",
"value",
"v",
"r",
"s",
"privateFrom",
"privateFor",
"restriction"
})
/*
The original deserialised private transaction sent via eea_sendRawTransaction
This class is used if the original request was sent with privateFrom and privateFor
*/
public class PrivateTransactionLegacyResult extends PrivateTransactionResult {
private final List<String> privateFor;
public PrivateTransactionLegacyResult(final PrivateTransaction tx) {
super(tx);
this.privateFor =
tx.getPrivateFor().get().stream()
.map(BytesValues::asBase64String)
.collect(Collectors.toList());
}
@JsonGetter(value = "privateFor")
public List<String> getPrivateFor() {
return privateFor;
}
}

@ -0,0 +1,117 @@
/*
* 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.ethereum.jsonrpc.internal.results.privacy;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.Quantity;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import com.fasterxml.jackson.annotation.JsonGetter;
public abstract class PrivateTransactionResult {
private final String from;
private final String gas;
private final String gasPrice;
private final String hash;
private final String input;
private final String nonce;
private final String to;
private final String value;
private final String v;
private final String r;
private final String s;
private final String privateFrom;
private final String restriction;
public PrivateTransactionResult(final PrivateTransaction tx) {
this.from = tx.getSender().toString();
this.gas = Quantity.create(tx.getGasLimit());
this.gasPrice = Quantity.create(tx.getGasPrice());
this.hash = tx.hash().toString();
this.input = tx.getPayload().toString();
this.nonce = Quantity.create(tx.getNonce());
this.to = tx.getTo().map(BytesValue::toString).orElse(null);
this.value = Quantity.create(tx.getValue());
this.v = Quantity.create(tx.getV());
this.r = Quantity.create(tx.getR());
this.s = Quantity.create(tx.getS());
this.privateFrom = BytesValues.asBase64String(tx.getPrivateFrom());
this.restriction = BytesValues.asString(tx.getRestriction().getBytes());
}
@JsonGetter(value = "from")
public String getFrom() {
return from;
}
@JsonGetter(value = "gas")
public String getGas() {
return gas;
}
@JsonGetter(value = "gasPrice")
public String getGasPrice() {
return gasPrice;
}
@JsonGetter(value = "hash")
public String getHash() {
return hash;
}
@JsonGetter(value = "input")
public String getInput() {
return input;
}
@JsonGetter(value = "nonce")
public String getNonce() {
return nonce;
}
@JsonGetter(value = "to")
public String getTo() {
return to;
}
@JsonGetter(value = "value")
public String getValue() {
return value;
}
@JsonGetter(value = "v")
public String getV() {
return v;
}
@JsonGetter(value = "r")
public String getR() {
return r;
}
@JsonGetter(value = "s")
public String getS() {
return s;
}
@JsonGetter(value = "privateFrom")
public String getPrivateFrom() {
return privateFrom;
}
@JsonGetter(value = "restriction")
public String getRestriction() {
return restriction;
}
}

@ -13,7 +13,7 @@
package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods.privacy;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -24,15 +24,18 @@ import tech.pegasys.pantheon.enclave.types.ReceiveRequest;
import tech.pegasys.pantheon.enclave.types.ReceiveResponse;
import tech.pegasys.pantheon.ethereum.core.Address;
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
import tech.pegasys.pantheon.ethereum.core.Transaction;
import tech.pegasys.pantheon.ethereum.core.Wei;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.privacy.PrivateTransactionGroupResult;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.privacy.PrivateTransactionLegacyResult;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.results.privacy.PrivateTransactionResult;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransaction;
import tech.pegasys.pantheon.ethereum.privacy.Restriction;
import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.BytesValues;
import java.math.BigInteger;
import java.util.Base64;
@ -54,7 +57,7 @@ public class EeaGetPrivateTransactionTest {
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private final PrivateTransaction privateTransaction =
private final PrivateTransaction.Builder privateTransactionBuilder =
PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
@ -75,25 +78,10 @@ public class EeaGetPrivateTransactionTest {
+ "daa4f6b2f003d1b0180029"))
.sender(sender)
.chainId(BigInteger.valueOf(2018))
.privateFrom(
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
.privateFor(
Lists.newArrayList(
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
.restriction(Restriction.RESTRICTED)
.signAndBuild(KEY_PAIR);
.privateFrom(BytesValues.fromBase64("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.restriction(Restriction.RESTRICTED);
private final Transaction transaction =
Transaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57"))
.value(Wei.ZERO)
.payload(BytesValue.wrap("EnclaveKey".getBytes(UTF_8)))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(BigInteger.valueOf(2018))
.signAndBuild(KEY_PAIR);
private final String enclaveKey = "93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=";
private final JsonRpcParameter parameters = new JsonRpcParameter();
private final Enclave enclave = mock(Enclave.class);
@ -101,10 +89,47 @@ public class EeaGetPrivateTransactionTest {
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
@Test
public void returnsPrivateTransaction() throws Exception {
public void returnsPrivateTransactionLegacy() throws Exception {
final PrivateTransaction privateTransaction =
privateTransactionBuilder
.privateFor(
Lists.newArrayList(
BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")))
.signAndBuild(KEY_PAIR);
final PrivateTransactionLegacyResult privateTransactionLegacyResult =
new PrivateTransactionLegacyResult(privateTransaction);
final EeaGetPrivateTransaction eeaGetPrivateTransaction =
new EeaGetPrivateTransaction(enclave, parameters, privacyParameters);
final Object[] params = new Object[] {enclaveKey};
final JsonRpcRequest request = new JsonRpcRequest("1", "eea_getPrivateTransaction", params);
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
when(enclave.receive(any(ReceiveRequest.class)))
.thenReturn(
new ReceiveResponse(
Base64.getEncoder().encodeToString(bvrlp.encoded().extractArray()).getBytes(UTF_8),
""));
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) eeaGetPrivateTransaction.response(request);
final PrivateTransactionResult result = (PrivateTransactionResult) response.getResult();
assertThat(result).isEqualToComparingFieldByField(privateTransactionLegacyResult);
}
@Test
public void returnsPrivateTransactionGroup() throws Exception {
final PrivateTransaction privateTransaction =
privateTransactionBuilder
.privacyGroupId(BytesValues.fromBase64("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="))
.signAndBuild(KEY_PAIR);
final PrivateTransactionGroupResult privateTransactionGroupResult =
new PrivateTransactionGroupResult(privateTransaction);
final EeaGetPrivateTransaction eeaGetPrivateTransaction =
new EeaGetPrivateTransaction(enclave, parameters, privacyParameters);
final Object[] params = new Object[] {transaction.getPayload().toString()};
final Object[] params = new Object[] {enclaveKey};
final JsonRpcRequest request = new JsonRpcRequest("1", "eea_getPrivateTransaction", params);
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
@ -116,8 +141,8 @@ public class EeaGetPrivateTransactionTest {
""));
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) eeaGetPrivateTransaction.response(request);
final PrivateTransaction result = (PrivateTransaction) response.getResult();
final PrivateTransactionResult result = (PrivateTransactionResult) response.getResult();
assertEquals(privateTransaction, result);
assertThat(result).isEqualToComparingFieldByField(privateTransactionGroupResult);
}
}

@ -72,12 +72,21 @@ public class EeaSendRawTransactionTest {
+ "657374726963746564";
private static final String VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP =
"0xf897800182520894095e7baea6a6c7c4c2dfeb977efac326af552d878"
+ "0801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff75"
+ "9b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b"
+ "28ad43601b4ab949f53faa07bd2c804ac4479414f69462f796e70"
+ "632b4a586132594147423062436974536c4f4d4e6d2b53686d422"
+ "f374d364334773d8a72657374726963746564";
"0xf8ac800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87"
+ "80801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff"
+ "759b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56"
+ "c0b28ad43601b4ab949f53faa07bd2c804a0035695b4cc4b0941"
+ "e60551d7a19cf30603db5bfc23e5ac43a56f57f25f75486aa00f"
+ "200e885ff29e973e2576b6600181d1b0a2b5294e30d9be4a1981"
+ "ffb33a0b8c8a72657374726963746564";
private static final String VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP_NO_PRIVATE_FROM =
"0xf88b800182520894095e7baea6a6c7c4c2dfeb977efac326af55"
+ "2d8780801ba048b55bfa915ac795c431978d8a6a992b628d55"
+ "7da5ff759b307d495a36649353a01fffd310ac743f371de3b9"
+ "f7f9cb56c0b28ad43601b4ab949f53faa07bd2c804a00f200e"
+ "885ff29e973e2576b6600181d1b0a2b5294e30d9be4a1981ff"
+ "b33a0b8c8a72657374726963746564";
private static final Transaction PUBLIC_TRANSACTION =
new Transaction(
@ -115,6 +124,8 @@ public class EeaSendRawTransactionTest {
@Before
public void before() {
when(transactionPool.getPendingTransactions()).thenReturn(pendingTransactions);
when(privateTxHandler.getEnclaveKey())
.thenReturn("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=");
method =
new EeaSendRawTransaction(blockchainQueries, privateTxHandler, transactionPool, parameter);
@ -228,7 +239,7 @@ public class EeaSendRawTransactionTest {
}
@Test
public void validTransactionPrivayGroupIsSentToTransactionPool() throws Exception {
public void validTransactionPrivacyGroupIsSentToTransactionPool() throws Exception {
when(parameter.required(any(Object[].class), anyInt(), any()))
.thenReturn(VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP);
when(privateTxHandler.sendToOrion(any(PrivateTransaction.class))).thenReturn(MOCK_ORION_KEY);
@ -266,6 +277,45 @@ public class EeaSendRawTransactionTest {
verify(transactionPool).addLocalTransaction(any(Transaction.class));
}
@Test
public void validTransactionPrivacyGroupNoPrivateFromIsSentToTransactionPool() throws Exception {
when(parameter.required(any(Object[].class), anyInt(), any()))
.thenReturn(VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP_NO_PRIVATE_FROM);
when(privateTxHandler.sendToOrion(any(PrivateTransaction.class))).thenReturn(MOCK_ORION_KEY);
when(privateTxHandler.getPrivacyGroup(any(String.class), any(PrivateTransaction.class)))
.thenReturn(MOCK_PRIVACY_GROUP);
when(privateTxHandler.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class)))
.thenReturn(ValidationResult.valid());
when(privateTxHandler.createPrivacyMarkerTransaction(
any(String.class), any(PrivateTransaction.class), any(Long.class)))
.thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any(Transaction.class)))
.thenReturn(ValidationResult.valid());
final JsonRpcRequest request =
new JsonRpcRequest(
"2.0",
"eea_sendRawTransaction",
new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP_NO_PRIVATE_FROM});
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
request.getId(), "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15");
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
verify(privateTxHandler).sendToOrion(any(PrivateTransaction.class));
verify(privateTxHandler).getPrivacyGroup(any(String.class), any(PrivateTransaction.class));
verify(privateTxHandler)
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class));
verify(privateTxHandler)
.createPrivacyMarkerTransaction(
any(String.class), any(PrivateTransaction.class), any(Long.class));
verify(transactionPool).addLocalTransaction(any(Transaction.class));
}
@Test
public void invalidTransactionIsSentToTransactionPool() throws Exception {
when(parameter.required(any(Object[].class), anyInt(), any()))

Loading…
Cancel
Save