mirror of
https://github.com/vacp2p/linea-besu.git
synced 2026-01-09 21:17:54 -05:00
[PAN-2825] eea send raw transaction with privacy group id (#1611)
* Add privacy group id to private transaction * Update enclave send methods to accept privacy group id * Update eea sendRawTransaction endpoint * extract privacy group id from private transaction if present * extract privateFor/privateFrom if privacy group id is not present * Fix tests * Change abstract class invocation to concrete class. * Utility method to load enclave public key Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
This commit is contained in:
committed by
Eric Kellstrand
parent
7cf7e2b4c4
commit
d2d338b797
@@ -18,6 +18,7 @@ import static tech.pegasys.pantheon.tests.acceptance.dsl.WaitUtils.waitFor;
|
||||
import tech.pegasys.orion.testutil.OrionTestHarness;
|
||||
import tech.pegasys.pantheon.enclave.Enclave;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequest;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequestLegacy;
|
||||
import tech.pegasys.pantheon.ethereum.core.MiningParameters;
|
||||
import tech.pegasys.pantheon.ethereum.core.PrivacyParameters;
|
||||
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcConfiguration;
|
||||
@@ -100,7 +101,7 @@ public class PrivacyNode extends PantheonNode {
|
||||
Arrays.stream(otherNodes).map(node -> node.orion.nodeUrl()).toArray())));
|
||||
Enclave orionEnclave = new Enclave(orion.clientUrl());
|
||||
SendRequest sendRequest1 =
|
||||
new SendRequest(
|
||||
new SendRequestLegacy(
|
||||
"SGVsbG8sIFdvcmxkIQ==",
|
||||
orion.getPublicKeys().get(0),
|
||||
Arrays.stream(otherNodes)
|
||||
|
||||
@@ -25,6 +25,8 @@ import tech.pegasys.pantheon.enclave.types.PrivacyGroup;
|
||||
import tech.pegasys.pantheon.enclave.types.ReceiveRequest;
|
||||
import tech.pegasys.pantheon.enclave.types.ReceiveResponse;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequest;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequestLegacy;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequestPantheon;
|
||||
import tech.pegasys.pantheon.enclave.types.SendResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -73,7 +75,28 @@ public class EnclaveTest {
|
||||
List<String> publicKeys = testHarness.getPublicKeys();
|
||||
|
||||
SendRequest sc =
|
||||
new SendRequest(PAYLOAD, publicKeys.get(0), Lists.newArrayList(publicKeys.get(0)));
|
||||
new SendRequestLegacy(PAYLOAD, publicKeys.get(0), Lists.newArrayList(publicKeys.get(0)));
|
||||
SendResponse sr = enclave.send(sc);
|
||||
|
||||
ReceiveRequest rc = new ReceiveRequest(sr.getKey(), publicKeys.get(0));
|
||||
ReceiveResponse rr = enclave.receive(rc);
|
||||
|
||||
assertEquals(PAYLOAD, new String(rr.getPayload(), UTF_8));
|
||||
assertNotNull(rr.getPrivacyGroupId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSendWithPrivacyGroupAndReceive() throws Exception {
|
||||
List<String> publicKeys = testHarness.getPublicKeys();
|
||||
|
||||
CreatePrivacyGroupRequest privacyGroupRequest =
|
||||
new CreatePrivacyGroupRequest(publicKeys.toArray(new String[0]), publicKeys.get(0), "", "");
|
||||
|
||||
PrivacyGroup privacyGroupResponse = enclave.createPrivacyGroup(privacyGroupRequest);
|
||||
|
||||
SendRequest sc =
|
||||
new SendRequestPantheon(
|
||||
PAYLOAD, publicKeys.get(0), privacyGroupResponse.getPrivacyGroupId());
|
||||
SendResponse sr = enclave.send(sc);
|
||||
|
||||
ReceiveRequest rc = new ReceiveRequest(sr.getKey(), publicKeys.get(0));
|
||||
|
||||
@@ -14,24 +14,13 @@ package tech.pegasys.pantheon.enclave.types;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
@JsonPropertyOrder({"payload", "from", "to"})
|
||||
public class SendRequest {
|
||||
public abstract class SendRequest {
|
||||
private byte[] payload;
|
||||
private String from;
|
||||
private List<String> to;
|
||||
|
||||
public SendRequest(
|
||||
@JsonProperty(value = "payload") final String payload,
|
||||
@JsonProperty(value = "from") final String from,
|
||||
@JsonProperty(value = "to") final List<String> to) {
|
||||
public SendRequest(final String payload, final String from) {
|
||||
this.payload = payload.getBytes(UTF_8);
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
@@ -41,8 +30,4 @@ public class SendRequest {
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public List<String> getTo() {
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.enclave.types;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
@JsonPropertyOrder({"payload", "from", "to"})
|
||||
public class SendRequestLegacy extends SendRequest {
|
||||
private List<String> to;
|
||||
|
||||
public SendRequestLegacy(
|
||||
@JsonProperty(value = "payload") final String payload,
|
||||
@JsonProperty(value = "from") final String from,
|
||||
@JsonProperty(value = "to") final List<String> to) {
|
||||
super(payload, from);
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
public List<String> getTo() {
|
||||
return to;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.enclave.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
|
||||
@JsonPropertyOrder({"payload", "from", "privacyGroupId"})
|
||||
public class SendRequestPantheon extends SendRequest {
|
||||
private String privacyGroupId;
|
||||
|
||||
public SendRequestPantheon(
|
||||
@JsonProperty(value = "payload") final String payload,
|
||||
@JsonProperty(value = "from") final String from,
|
||||
@JsonProperty(value = "to") final String privacyGroupId) {
|
||||
super(payload, from);
|
||||
|
||||
this.privacyGroupId = privacyGroupId;
|
||||
}
|
||||
|
||||
public String getPrivacyGroupId() {
|
||||
return privacyGroupId;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import tech.pegasys.orion.testutil.OrionTestHarness;
|
||||
import tech.pegasys.orion.testutil.OrionTestHarnessFactory;
|
||||
import tech.pegasys.pantheon.enclave.Enclave;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequest;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequestLegacy;
|
||||
import tech.pegasys.pantheon.enclave.types.SendResponse;
|
||||
import tech.pegasys.pantheon.ethereum.chain.Blockchain;
|
||||
import tech.pegasys.pantheon.ethereum.core.Address;
|
||||
@@ -151,7 +152,8 @@ public class PrivacyPrecompiledContractIntegrationTest {
|
||||
List<String> publicKeys = testHarness.getPublicKeys();
|
||||
|
||||
String s = new String(VALID_PRIVATE_TRANSACTION_RLP_BASE64, UTF_8);
|
||||
SendRequest sc = new SendRequest(s, publicKeys.get(0), Lists.newArrayList(publicKeys.get(0)));
|
||||
SendRequest sc =
|
||||
new SendRequestLegacy(s, publicKeys.get(0), Lists.newArrayList(publicKeys.get(0)));
|
||||
SendResponse sr = enclave.send(sc);
|
||||
|
||||
PrivacyPrecompiledContract privacyPrecompiledContract =
|
||||
@@ -178,7 +180,7 @@ public class PrivacyPrecompiledContractIntegrationTest {
|
||||
publicKeys.add("noPrivateKey");
|
||||
|
||||
String s = new String(VALID_PRIVATE_TRANSACTION_RLP_BASE64, UTF_8);
|
||||
SendRequest sc = new SendRequest(s, publicKeys.get(0), publicKeys);
|
||||
SendRequest sc = new SendRequestLegacy(s, publicKeys.get(0), publicKeys);
|
||||
|
||||
final Throwable thrown = catchThrowable(() -> enclave.send(sc));
|
||||
|
||||
@@ -191,7 +193,7 @@ public class PrivacyPrecompiledContractIntegrationTest {
|
||||
publicKeys.add("noPrivateKenoPrivateKenoPrivateKenoPrivateK");
|
||||
|
||||
String s = new String(VALID_PRIVATE_TRANSACTION_RLP_BASE64, UTF_8);
|
||||
SendRequest sc = new SendRequest(s, publicKeys.get(0), publicKeys);
|
||||
SendRequest sc = new SendRequestLegacy(s, publicKeys.get(0), publicKeys);
|
||||
|
||||
final Throwable thrown = catchThrowable(() -> enclave.send(sc));
|
||||
|
||||
|
||||
@@ -66,9 +66,11 @@ public class PrivateTransaction {
|
||||
|
||||
private final Optional<BigInteger> chainId;
|
||||
|
||||
private final BytesValue privateFrom;
|
||||
private final Optional<BytesValue> privacyGroupId;
|
||||
|
||||
private final List<BytesValue> privateFor;
|
||||
private final Optional<BytesValue> privateFrom;
|
||||
|
||||
private final Optional<List<BytesValue>> privateFor;
|
||||
|
||||
private final Restriction restriction;
|
||||
|
||||
@@ -115,19 +117,32 @@ 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 privateFrom = input.readBytesValue();
|
||||
final List<BytesValue> privateFor = input.readList(RLPInput::readBytesValue);
|
||||
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());
|
||||
|
||||
input.leaveList();
|
||||
|
||||
chainId.ifPresent(builder::chainId);
|
||||
return builder
|
||||
.signature(signature)
|
||||
.privateFrom(privateFrom)
|
||||
.privateFor(privateFor)
|
||||
.restriction(restriction)
|
||||
.build();
|
||||
|
||||
if (privateFor.isPresent()) {
|
||||
return builder
|
||||
.signature(signature)
|
||||
.privateFrom(tempValue)
|
||||
.privateFor(privateFor.get())
|
||||
.restriction(restriction)
|
||||
.build();
|
||||
} else {
|
||||
return builder
|
||||
.signature(signature)
|
||||
.privacyGroupId(tempValue)
|
||||
.restriction(restriction)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static Restriction convertToEnum(final BytesValue readBytesValue) {
|
||||
@@ -155,6 +170,7 @@ public class PrivateTransaction {
|
||||
* otherwise it should contain an address.
|
||||
* <p>The {@code chainId} must be greater than 0 to be applied to a specific chain; otherwise
|
||||
* it will default to any chain.
|
||||
* @param privacyGroupId The privacy group id of this private transaction
|
||||
* @param privateFrom The public key of the sender of this private transaction
|
||||
* @param privateFor An array of the public keys of the intended recipients of this private
|
||||
* transaction
|
||||
@@ -170,8 +186,9 @@ public class PrivateTransaction {
|
||||
final BytesValue payload,
|
||||
final Address sender,
|
||||
final Optional<BigInteger> chainId,
|
||||
final BytesValue privateFrom,
|
||||
final List<BytesValue> privateFor,
|
||||
final Optional<BytesValue> privacyGroupId,
|
||||
final Optional<BytesValue> privateFrom,
|
||||
final Optional<List<BytesValue>> privateFor,
|
||||
final Restriction restriction) {
|
||||
this.nonce = nonce;
|
||||
this.gasPrice = gasPrice;
|
||||
@@ -182,6 +199,7 @@ public class PrivateTransaction {
|
||||
this.payload = payload;
|
||||
this.sender = sender;
|
||||
this.chainId = chainId;
|
||||
this.privacyGroupId = privacyGroupId;
|
||||
this.privateFrom = privateFrom;
|
||||
this.privateFor = privateFor;
|
||||
this.restriction = restriction;
|
||||
@@ -265,12 +283,21 @@ 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 BytesValue getPrivateFrom() {
|
||||
public Optional<BytesValue> getPrivateFrom() {
|
||||
return privateFrom;
|
||||
}
|
||||
|
||||
@@ -279,7 +306,7 @@ public class PrivateTransaction {
|
||||
*
|
||||
* @return the enclave public keys of the receivers
|
||||
*/
|
||||
public List<BytesValue> getPrivateFor() {
|
||||
public Optional<List<BytesValue>> getPrivateFor() {
|
||||
return privateFor;
|
||||
}
|
||||
|
||||
@@ -321,6 +348,7 @@ public class PrivateTransaction {
|
||||
value,
|
||||
payload,
|
||||
chainId,
|
||||
privacyGroupId,
|
||||
privateFrom,
|
||||
privateFor,
|
||||
restriction.getBytes());
|
||||
@@ -343,8 +371,10 @@ public class PrivateTransaction {
|
||||
out.writeUInt256Scalar(getValue());
|
||||
out.writeBytesValue(getPayload());
|
||||
writeSignature(out);
|
||||
out.writeBytesValue(getPrivateFrom());
|
||||
out.writeList(getPrivateFor(), (bv, rlpO) -> rlpO.writeBytesValue(bv));
|
||||
getPrivacyGroupId().ifPresent(out::writeBytesValue);
|
||||
getPrivateFrom().ifPresent(out::writeBytesValue);
|
||||
getPrivateFor()
|
||||
.ifPresent(privateFor -> out.writeList(privateFor, (bv, rlpO) -> rlpO.writeBytesValue(bv)));
|
||||
out.writeBytesValue(getRestriction().getBytes());
|
||||
|
||||
out.endList();
|
||||
@@ -427,8 +457,9 @@ public class PrivateTransaction {
|
||||
final Wei value,
|
||||
final BytesValue payload,
|
||||
final Optional<BigInteger> chainId,
|
||||
final BytesValue privateFrom,
|
||||
final List<BytesValue> privateFor,
|
||||
final Optional<BytesValue> privacyGroupId,
|
||||
final Optional<BytesValue> privateFrom,
|
||||
final Optional<List<BytesValue>> privateFor,
|
||||
final BytesValue restriction) {
|
||||
return keccak256(
|
||||
RLP.encode(
|
||||
@@ -445,8 +476,9 @@ public class PrivateTransaction {
|
||||
out.writeUInt256Scalar(UInt256.ZERO);
|
||||
out.writeUInt256Scalar(UInt256.ZERO);
|
||||
}
|
||||
out.writeBytesValue(privateFrom);
|
||||
out.writeList(privateFor, (bv, rlpO) -> rlpO.writeBytesValue(bv));
|
||||
privacyGroupId.ifPresent(out::writeBytesValue);
|
||||
privateFrom.ifPresent(out::writeBytesValue);
|
||||
privateFor.ifPresent(pF -> out.writeList(pF, (bv, rlpO) -> rlpO.writeBytesValue(bv)));
|
||||
out.writeBytesValue(restriction);
|
||||
out.endList();
|
||||
}));
|
||||
@@ -499,8 +531,14 @@ public class PrivateTransaction {
|
||||
sb.append("sig=").append(getSignature()).append(", ");
|
||||
if (chainId.isPresent()) sb.append("chainId=").append(getChainId().get()).append(", ");
|
||||
sb.append("payload=").append(getPayload());
|
||||
sb.append("privateFrom=").append(getPrivateFrom());
|
||||
sb.append("privateFor=").append(Arrays.toString(getPrivateFor().toArray()));
|
||||
if (getPrivacyGroupId().isPresent())
|
||||
sb.append("privacyGroupId=").append(getPrivacyGroupId().get()).append(", ");
|
||||
if (getPrivateFrom().isPresent())
|
||||
sb.append("privateFrom=").append(getPrivateFrom().get()).append(", ");
|
||||
if (getPrivateFor().isPresent())
|
||||
sb.append("privateFor=")
|
||||
.append(Arrays.toString(getPrivateFor().get().toArray()))
|
||||
.append(", ");
|
||||
sb.append("restriction=").append(getRestriction());
|
||||
return sb.append("}").toString();
|
||||
}
|
||||
@@ -532,9 +570,11 @@ public class PrivateTransaction {
|
||||
|
||||
protected Optional<BigInteger> chainId = Optional.empty();
|
||||
|
||||
protected BytesValue privateFrom;
|
||||
protected Optional<BytesValue> privacyGroupId = Optional.empty();
|
||||
|
||||
protected List<BytesValue> privateFor;
|
||||
protected Optional<BytesValue> privateFrom = Optional.empty();
|
||||
|
||||
protected Optional<List<BytesValue>> privateFor = Optional.empty();
|
||||
|
||||
protected Restriction restriction;
|
||||
|
||||
@@ -583,13 +623,18 @@ public class PrivateTransaction {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder privacyGroupId(final BytesValue privacyGroupId) {
|
||||
this.privacyGroupId = Optional.of(privacyGroupId);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder privateFrom(final BytesValue privateFrom) {
|
||||
this.privateFrom = privateFrom;
|
||||
this.privateFrom = Optional.of(privateFrom);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder privateFor(final List<BytesValue> privateFor) {
|
||||
this.privateFor = privateFor;
|
||||
this.privateFor = Optional.of(privateFor);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -599,6 +644,10 @@ public class PrivateTransaction {
|
||||
}
|
||||
|
||||
public PrivateTransaction build() {
|
||||
if (privacyGroupId.isPresent() && (privateFrom.isPresent() || privateFor.isPresent())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Private transaction should contain either privacyGroup by itself or privateFrom and privateFor together, but not both");
|
||||
}
|
||||
return new PrivateTransaction(
|
||||
nonce,
|
||||
gasPrice,
|
||||
@@ -609,6 +658,7 @@ public class PrivateTransaction {
|
||||
payload,
|
||||
sender,
|
||||
chainId,
|
||||
privacyGroupId,
|
||||
privateFrom,
|
||||
privateFor,
|
||||
restriction);
|
||||
@@ -632,6 +682,7 @@ public class PrivateTransaction {
|
||||
value,
|
||||
payload,
|
||||
chainId,
|
||||
privacyGroupId,
|
||||
privateFrom,
|
||||
privateFor,
|
||||
restriction.getBytes());
|
||||
|
||||
@@ -20,6 +20,8 @@ import tech.pegasys.pantheon.enclave.Enclave;
|
||||
import tech.pegasys.pantheon.enclave.types.ReceiveRequest;
|
||||
import tech.pegasys.pantheon.enclave.types.ReceiveResponse;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequest;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequestLegacy;
|
||||
import tech.pegasys.pantheon.enclave.types.SendRequestPantheon;
|
||||
import tech.pegasys.pantheon.enclave.types.SendResponse;
|
||||
import tech.pegasys.pantheon.ethereum.core.Account;
|
||||
import tech.pegasys.pantheon.ethereum.core.Address;
|
||||
@@ -49,6 +51,7 @@ public class PrivateTransactionHandler {
|
||||
private final Address privacyPrecompileAddress;
|
||||
private final SECP256K1.KeyPair nodeKeyPair;
|
||||
private final Address signerAddress;
|
||||
private final String enclavePublicKey;
|
||||
private final PrivateStateStorage privateStateStorage;
|
||||
private final WorldStateArchive privateWorldStateArchive;
|
||||
|
||||
@@ -57,6 +60,7 @@ public class PrivateTransactionHandler {
|
||||
new Enclave(privacyParameters.getEnclaveUri()),
|
||||
Address.privacyPrecompiled(privacyParameters.getPrivacyAddress()),
|
||||
privacyParameters.getSigningKeyPair(),
|
||||
privacyParameters.getEnclavePublicKey(),
|
||||
privacyParameters.getPrivateStateStorage(),
|
||||
privacyParameters.getPrivateWorldStateArchive());
|
||||
}
|
||||
@@ -65,12 +69,14 @@ public class PrivateTransactionHandler {
|
||||
final Enclave enclave,
|
||||
final Address privacyPrecompileAddress,
|
||||
final SECP256K1.KeyPair nodeKeyPair,
|
||||
final String enclavePublicKey,
|
||||
final PrivateStateStorage privateStateStorage,
|
||||
final WorldStateArchive privateWorldStateArchive) {
|
||||
this.enclave = enclave;
|
||||
this.privacyPrecompileAddress = privacyPrecompileAddress;
|
||||
this.nodeKeyPair = nodeKeyPair;
|
||||
this.signerAddress = Util.publicKeyToAddress(nodeKeyPair.getPublicKey());
|
||||
this.enclavePublicKey = enclavePublicKey;
|
||||
this.privateStateStorage = privateStateStorage;
|
||||
this.privateWorldStateArchive = privateWorldStateArchive;
|
||||
}
|
||||
@@ -89,9 +95,16 @@ public class PrivateTransactionHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public String getPrivacyGroup(final String key, final BytesValue from) throws Exception {
|
||||
final ReceiveRequest receiveRequest = new ReceiveRequest(key, BytesValues.asString(from));
|
||||
LOG.debug("Getting privacy group for {}", BytesValues.asString(from));
|
||||
public String getPrivacyGroup(final String key, final PrivateTransaction privateTransaction)
|
||||
throws Exception {
|
||||
if (privateTransaction.getPrivacyGroupId().isPresent()) {
|
||||
return privateTransaction.getPrivacyGroupId().get().toString();
|
||||
}
|
||||
final ReceiveRequest receiveRequest =
|
||||
new ReceiveRequest(key, BytesValues.asString(privateTransaction.getPrivateFrom().get()));
|
||||
LOG.debug(
|
||||
"Getting privacy group for {}",
|
||||
BytesValues.asString(privateTransaction.getPrivateFrom().get()));
|
||||
final ReceiveResponse receiveResponse;
|
||||
try {
|
||||
receiveResponse = enclave.receive(receiveRequest);
|
||||
@@ -144,23 +157,30 @@ public class PrivateTransactionHandler {
|
||||
}
|
||||
|
||||
private SendRequest createSendRequest(final PrivateTransaction privateTransaction) {
|
||||
final List<String> privateFor =
|
||||
privateTransaction.getPrivateFor().stream()
|
||||
.map(BytesValues::asString)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// FIXME: Orion should concatenate to and from - not it pantheon
|
||||
if (privateFor.isEmpty()) {
|
||||
privateFor.add(BytesValues.asString(privateTransaction.getPrivateFrom()));
|
||||
}
|
||||
|
||||
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
|
||||
privateTransaction.writeTo(bvrlp);
|
||||
|
||||
return new SendRequest(
|
||||
Base64.getEncoder().encodeToString(bvrlp.encoded().extractArray()),
|
||||
BytesValues.asString(privateTransaction.getPrivateFrom()),
|
||||
privateFor);
|
||||
if (privateTransaction.getPrivacyGroupId().isPresent()) {
|
||||
return new SendRequestPantheon(
|
||||
Base64.getEncoder().encodeToString(bvrlp.encoded().extractArray()),
|
||||
enclavePublicKey,
|
||||
BytesValues.asString(privateTransaction.getPrivacyGroupId().get()));
|
||||
} else {
|
||||
final List<String> privateFor =
|
||||
privateTransaction.getPrivateFor().get().stream()
|
||||
.map(BytesValues::asString)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// FIXME: orion should accept empty privateFor
|
||||
if (privateFor.isEmpty()) {
|
||||
privateFor.add(BytesValues.asString(privateTransaction.getPrivateFrom().get()));
|
||||
}
|
||||
|
||||
return new SendRequestLegacy(
|
||||
Base64.getEncoder().encodeToString(bvrlp.encoded().extractArray()),
|
||||
BytesValues.asString(privateTransaction.getPrivateFrom().get()),
|
||||
privateFor);
|
||||
}
|
||||
}
|
||||
|
||||
public long getSenderNonce(final Address sender, final String privacyGroupId) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import static org.mockito.Mockito.when;
|
||||
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.INCORRECT_PRIVATE_NONCE;
|
||||
import static tech.pegasys.pantheon.ethereum.mainnet.TransactionValidator.TransactionInvalidReason.PRIVATE_NONCE_TOO_LOW;
|
||||
|
||||
import tech.pegasys.orion.testutil.OrionKeyUtils;
|
||||
import tech.pegasys.pantheon.crypto.SECP256K1;
|
||||
import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair;
|
||||
import tech.pegasys.pantheon.enclave.Enclave;
|
||||
@@ -107,6 +108,7 @@ public class PrivateTransactionHandlerTest {
|
||||
mockEnclave(),
|
||||
Address.DEFAULT_PRIVACY,
|
||||
KEY_PAIR,
|
||||
OrionKeyUtils.loadKey("orion_key_0.pub"),
|
||||
privateStateStorage,
|
||||
worldStateArchive);
|
||||
brokenPrivateTransactionHandler =
|
||||
@@ -114,19 +116,20 @@ public class PrivateTransactionHandlerTest {
|
||||
brokenMockEnclave(),
|
||||
Address.DEFAULT_PRIVACY,
|
||||
KEY_PAIR,
|
||||
OrionKeyUtils.loadKey("orion_key_0.pub"),
|
||||
privateStateStorage,
|
||||
worldStateArchive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validTransactionThroughHandler() throws Exception {
|
||||
public void validLegacyTransactionThroughHandler() throws Exception {
|
||||
|
||||
final PrivateTransaction transaction = buildPrivateTransaction(1);
|
||||
final PrivateTransaction transaction = buildLegacyPrivateTransaction(1);
|
||||
|
||||
final String enclaveKey = privateTransactionHandler.sendToOrion(transaction);
|
||||
|
||||
final String privacyGroupId =
|
||||
privateTransactionHandler.getPrivacyGroup(enclaveKey, transaction.getPrivateFrom());
|
||||
privateTransactionHandler.getPrivacyGroup(enclaveKey, transaction);
|
||||
|
||||
final ValidationResult<TransactionInvalidReason> validationResult =
|
||||
privateTransactionHandler.validatePrivateTransaction(transaction, privacyGroupId);
|
||||
@@ -142,18 +145,40 @@ public class PrivateTransactionHandlerTest {
|
||||
assertThat(markerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validPantheonTransactionThroughHandler() throws Exception {
|
||||
|
||||
final PrivateTransaction transaction = buildPantheonPrivateTransaction(1);
|
||||
|
||||
final String enclaveKey = privateTransactionHandler.sendToOrion(transaction);
|
||||
|
||||
final ValidationResult<TransactionInvalidReason> validationResult =
|
||||
privateTransactionHandler.validatePrivateTransaction(
|
||||
transaction, transaction.getPrivacyGroupId().get().toString());
|
||||
|
||||
final Transaction markerTransaction =
|
||||
privateTransactionHandler.createPrivacyMarkerTransaction(enclaveKey, transaction, 0L);
|
||||
|
||||
assertThat(validationResult).isEqualTo(ValidationResult.valid());
|
||||
assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress());
|
||||
assertThat(markerTransaction.getPayload()).isEqualTo(PUBLIC_TRANSACTION.getPayload());
|
||||
assertThat(markerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
|
||||
assertThat(markerTransaction.getSender()).isEqualTo(PUBLIC_TRANSACTION.getSender());
|
||||
assertThat(markerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void enclaveIsDownWhileHandling() throws Exception {
|
||||
brokenPrivateTransactionHandler.sendToOrion(buildPrivateTransaction());
|
||||
brokenPrivateTransactionHandler.sendToOrion(buildLegacyPrivateTransaction());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonceTooLowError() throws Exception {
|
||||
final PrivateTransaction transaction = buildPrivateTransaction(0);
|
||||
final PrivateTransaction transaction = buildLegacyPrivateTransaction(0);
|
||||
|
||||
final String enclaveKey = privateTransactionHandler.sendToOrion(transaction);
|
||||
final String privacyGroupId =
|
||||
privateTransactionHandler.getPrivacyGroup(enclaveKey, transaction.getPrivateFrom());
|
||||
privateTransactionHandler.getPrivacyGroup(enclaveKey, transaction);
|
||||
final ValidationResult<TransactionInvalidReason> validationResult =
|
||||
privateTransactionHandler.validatePrivateTransaction(transaction, privacyGroupId);
|
||||
assertThat(validationResult).isEqualTo(ValidationResult.invalid(PRIVATE_NONCE_TOO_LOW));
|
||||
@@ -161,21 +186,40 @@ public class PrivateTransactionHandlerTest {
|
||||
|
||||
@Test
|
||||
public void incorrectNonceError() throws Exception {
|
||||
final PrivateTransaction transaction = buildPrivateTransaction(2);
|
||||
final PrivateTransaction transaction = buildLegacyPrivateTransaction(2);
|
||||
|
||||
final String enclaveKey = privateTransactionHandler.sendToOrion(transaction);
|
||||
final String privacyGroupId =
|
||||
privateTransactionHandler.getPrivacyGroup(enclaveKey, transaction.getPrivateFrom());
|
||||
privateTransactionHandler.getPrivacyGroup(enclaveKey, transaction);
|
||||
final ValidationResult<TransactionInvalidReason> validationResult =
|
||||
privateTransactionHandler.validatePrivateTransaction(transaction, privacyGroupId);
|
||||
assertThat(validationResult).isEqualTo(ValidationResult.invalid(INCORRECT_PRIVATE_NONCE));
|
||||
}
|
||||
|
||||
private static PrivateTransaction buildPrivateTransaction() {
|
||||
return buildPrivateTransaction(0);
|
||||
private static PrivateTransaction buildLegacyPrivateTransaction() {
|
||||
return buildLegacyPrivateTransaction(0);
|
||||
}
|
||||
|
||||
private static PrivateTransaction buildPrivateTransaction(final long nonce) {
|
||||
private static PrivateTransaction buildLegacyPrivateTransaction(final long nonce) {
|
||||
return buildPrivateTransaction(nonce)
|
||||
.privateFrom(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
|
||||
.privateFor(
|
||||
Lists.newArrayList(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
|
||||
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
|
||||
.signAndBuild(KEY_PAIR);
|
||||
}
|
||||
|
||||
private static PrivateTransaction buildPantheonPrivateTransaction(final long nonce) {
|
||||
|
||||
return buildPrivateTransaction(nonce)
|
||||
.privacyGroupId(
|
||||
BytesValue.wrap("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=".getBytes(UTF_8)))
|
||||
.signAndBuild(KEY_PAIR);
|
||||
}
|
||||
|
||||
private static PrivateTransaction.Builder buildPrivateTransaction(final long nonce) {
|
||||
return PrivateTransaction.builder()
|
||||
.nonce(nonce)
|
||||
.gasPrice(Wei.of(1000))
|
||||
@@ -185,13 +229,6 @@ public class PrivateTransactionHandlerTest {
|
||||
.payload(BytesValue.fromHexString("0x"))
|
||||
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
|
||||
.chainId(BigInteger.valueOf(2018))
|
||||
.privateFrom(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)))
|
||||
.privateFor(
|
||||
Lists.newArrayList(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
|
||||
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
|
||||
.restriction(Restriction.RESTRICTED)
|
||||
.signAndBuild(KEY_PAIR);
|
||||
.restriction(Restriction.RESTRICTED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,14 @@ public class PrivateTransactionTest {
|
||||
+ "6e766966746a69697a706a52742b4854754642733d8a726573747269637465"
|
||||
+ "64";
|
||||
|
||||
private static final String VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP =
|
||||
"0xf8b7800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87a0f"
|
||||
+ "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
|
||||
+ "801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3"
|
||||
+ "6649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab949f53fa"
|
||||
+ "a07bd2c804ac4479414f69462f796e70632b4a5861325941474230624369745"
|
||||
+ "36c4f4d4e6d2b53686d422f374d364334773d8a72657374726963746564";
|
||||
|
||||
private static final String VALID_SIGNED_PRIVATE_TRANSACTION_RLP =
|
||||
"0xf901a4808203e8832dc6c08080b8ef60806040523480156100105760008"
|
||||
+ "0fd5b5060d08061001f6000396000f3fe60806040526004361060485763f"
|
||||
@@ -103,10 +111,38 @@ public class PrivateTransactionTest {
|
||||
BytesValue.fromHexString("0x"),
|
||||
Address.wrap(BytesValue.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
|
||||
Optional.empty(),
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
|
||||
Lists.newArrayList(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
|
||||
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))),
|
||||
Optional.empty(),
|
||||
Optional.of(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8))),
|
||||
Optional.of(
|
||||
Lists.newArrayList(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
|
||||
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8)))),
|
||||
Restriction.RESTRICTED);
|
||||
|
||||
private static final PrivateTransaction VALID_PRIVATE_TRANSACTION_PRIVACY_GROUP =
|
||||
new PrivateTransaction(
|
||||
0L,
|
||||
Wei.of(1),
|
||||
21000L,
|
||||
Optional.of(
|
||||
Address.wrap(BytesValue.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"))),
|
||||
Wei.of(
|
||||
new BigInteger(
|
||||
"115792089237316195423570985008687907853269984665640564039457584007913129639935")),
|
||||
SECP256K1.Signature.create(
|
||||
new BigInteger(
|
||||
"32886959230931919120748662916110619501838190146643992583529828535682419954515"),
|
||||
new BigInteger(
|
||||
"14473701025599600909210599917245952381483216609124029382871721729679842002948"),
|
||||
Byte.valueOf("0")),
|
||||
BytesValue.fromHexString("0x"),
|
||||
Address.wrap(BytesValue.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
|
||||
Optional.empty(),
|
||||
Optional.of(
|
||||
BytesValue.wrap("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=".getBytes(UTF_8))),
|
||||
Optional.empty(),
|
||||
Optional.empty(),
|
||||
Restriction.RESTRICTED);
|
||||
|
||||
private static final PrivateTransaction VALID_SIGNED_PRIVATE_TRANSACTION =
|
||||
@@ -186,6 +222,20 @@ public class PrivateTransactionTest {
|
||||
assertEquals(VALID_PRIVATE_TRANSACTION_RLP, bvrlpo.encoded().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteTo_privacyGroup() {
|
||||
BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput();
|
||||
VALID_PRIVATE_TRANSACTION_PRIVACY_GROUP.writeTo(bvrlpo);
|
||||
assertEquals(VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP, bvrlpo.encoded().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteToWithLargeChainId() {
|
||||
BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput();
|
||||
VALID_SIGNED_PRIVATE_TRANSACTION_LARGE_CHAINID.writeTo(bvrlpo);
|
||||
assertEquals(VALID_SIGNED_PRIVATE_TRANSACTION_LARGE_CHAINID_RLP, bvrlpo.encoded().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignedWriteTo() {
|
||||
BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput();
|
||||
@@ -202,6 +252,16 @@ public class PrivateTransactionTest {
|
||||
assertEquals(VALID_PRIVATE_TRANSACTION, p);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadFrom_privacyGroup() {
|
||||
PrivateTransaction p =
|
||||
PrivateTransaction.readFrom(
|
||||
new BytesValueRLPInput(
|
||||
BytesValue.fromHexString(VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP), false));
|
||||
|
||||
assertEquals(VALID_PRIVATE_TRANSACTION_PRIVACY_GROUP, p);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignedReadFrom() {
|
||||
PrivateTransaction p =
|
||||
@@ -218,13 +278,6 @@ public class PrivateTransactionTest {
|
||||
new BytesValueRLPInput(BytesValue.fromHexString(INVALID_RLP), false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWriteToWithLargeChainId() {
|
||||
BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput();
|
||||
VALID_SIGNED_PRIVATE_TRANSACTION_LARGE_CHAINID.writeTo(bvrlpo);
|
||||
assertEquals(VALID_SIGNED_PRIVATE_TRANSACTION_LARGE_CHAINID_RLP, bvrlpo.encoded().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadFromWithLargeChainId() {
|
||||
PrivateTransaction p =
|
||||
@@ -235,4 +288,27 @@ public class PrivateTransactionTest {
|
||||
|
||||
assertEquals(VALID_SIGNED_PRIVATE_TRANSACTION_LARGE_CHAINID, p);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testBuildInvalidPrivateTransactionThrowsException() {
|
||||
PrivateTransaction.builder()
|
||||
.nonce(0)
|
||||
.gasPrice(Wei.of(1000))
|
||||
.gasLimit(3000000)
|
||||
.to(Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57"))
|
||||
.value(Wei.ZERO)
|
||||
.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)))
|
||||
.privateFor(
|
||||
Lists.newArrayList(
|
||||
BytesValue.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8)),
|
||||
BytesValue.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8))))
|
||||
.restriction(Restriction.RESTRICTED)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,9 +95,8 @@ public class EeaSendRawTransaction implements JsonRpcMethod {
|
||||
|
||||
final String privacyGroupId;
|
||||
try {
|
||||
privacyGroupId =
|
||||
privateTransactionHandler.getPrivacyGroup(
|
||||
enclaveKey, privateTransaction.getPrivateFrom());
|
||||
privacyGroupId = privateTransactionHandler.getPrivacyGroup(enclaveKey, privateTransaction);
|
||||
|
||||
} catch (final Exception e) {
|
||||
return new JsonRpcErrorResponse(request.getId(), convertEnclaveInvalidReason(e.getMessage()));
|
||||
}
|
||||
|
||||
@@ -69,6 +69,14 @@ public class EeaSendRawTransactionTest {
|
||||
+ "49644f6e766966746a69697a706a52742b4854754642733d8a72"
|
||||
+ "657374726963746564";
|
||||
|
||||
private static final String VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP =
|
||||
"0xf897800182520894095e7baea6a6c7c4c2dfeb977efac326af552d878"
|
||||
+ "0801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff75"
|
||||
+ "9b307d495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b"
|
||||
+ "28ad43601b4ab949f53faa07bd2c804ac4479414f69462f796e70"
|
||||
+ "632b4a586132594147423062436974536c4f4d4e6d2b53686d422"
|
||||
+ "f374d364334773d8a72657374726963746564";
|
||||
|
||||
private static final Transaction PUBLIC_TRANSACTION =
|
||||
new Transaction(
|
||||
0L,
|
||||
@@ -182,7 +190,7 @@ public class EeaSendRawTransactionTest {
|
||||
when(parameter.required(any(Object[].class), anyInt(), any()))
|
||||
.thenReturn(VALID_PRIVATE_TRANSACTION_RLP);
|
||||
when(privateTxHandler.sendToOrion(any(PrivateTransaction.class))).thenReturn(MOCK_ORION_KEY);
|
||||
when(privateTxHandler.getPrivacyGroup(any(String.class), any(BytesValue.class)))
|
||||
when(privateTxHandler.getPrivacyGroup(any(String.class), any(PrivateTransaction.class)))
|
||||
.thenReturn(MOCK_PRIVACY_GROUP);
|
||||
when(privateTxHandler.validatePrivateTransaction(
|
||||
any(PrivateTransaction.class), any(String.class)))
|
||||
@@ -205,7 +213,46 @@ public class EeaSendRawTransactionTest {
|
||||
|
||||
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
|
||||
verify(privateTxHandler).sendToOrion(any(PrivateTransaction.class));
|
||||
verify(privateTxHandler).getPrivacyGroup(any(String.class), any(BytesValue.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 validTransactionPrivayGroupIsSentToTransactionPool() 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);
|
||||
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});
|
||||
|
||||
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)
|
||||
@@ -283,7 +330,7 @@ public class EeaSendRawTransactionTest {
|
||||
when(parameter.required(any(Object[].class), anyInt(), any()))
|
||||
.thenReturn(VALID_PRIVATE_TRANSACTION_RLP);
|
||||
when(privateTxHandler.sendToOrion(any(PrivateTransaction.class))).thenReturn(MOCK_ORION_KEY);
|
||||
when(privateTxHandler.getPrivacyGroup(any(String.class), any(BytesValue.class)))
|
||||
when(privateTxHandler.getPrivacyGroup(any(String.class), any(PrivateTransaction.class)))
|
||||
.thenReturn(MOCK_PRIVACY_GROUP);
|
||||
when(privateTxHandler.validatePrivateTransaction(
|
||||
any(PrivateTransaction.class), any(String.class)))
|
||||
@@ -305,7 +352,7 @@ public class EeaSendRawTransactionTest {
|
||||
|
||||
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
|
||||
verify(privateTxHandler).sendToOrion(any(PrivateTransaction.class));
|
||||
verify(privateTxHandler).getPrivacyGroup(any(String.class), any(BytesValue.class));
|
||||
verify(privateTxHandler).getPrivacyGroup(any(String.class), any(PrivateTransaction.class));
|
||||
verify(privateTxHandler)
|
||||
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class));
|
||||
verify(privateTxHandler)
|
||||
|
||||
@@ -12,6 +12,11 @@
|
||||
*/
|
||||
package tech.pegasys.orion.testutil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
@@ -23,9 +28,25 @@ import net.consensys.cava.bytes.Bytes;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class OrionKeyGenerator {
|
||||
public class OrionKeyUtils {
|
||||
private static final Logger LOG = LogManager.getLogger();
|
||||
|
||||
/**
|
||||
* Utility method to load the enclave public key. Possible input values are the names of the *.pub
|
||||
* files in the resources folder.
|
||||
*
|
||||
* @param keyFileName the name of the file containing the enclave public key
|
||||
* @return the enclave public key stored in that file
|
||||
* @throws IOException throws if key not found
|
||||
*/
|
||||
public static String loadKey(final String keyFileName) throws IOException {
|
||||
InputStream is = OrionKeyUtils.class.getResourceAsStream("/" + keyFileName);
|
||||
InputStreamReader streamReader = new InputStreamReader(is, StandardCharsets.UTF_8);
|
||||
try (BufferedReader reader = new BufferedReader(streamReader)) {
|
||||
return reader.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
public static KeyPair generateKeys() throws NoSuchAlgorithmException {
|
||||
final KeyPair keyPair = KeyPairGenerator.getInstance("Ed25519").generateKeyPair();
|
||||
final PublicKey pubKey = keyPair.getPublic();
|
||||
Reference in New Issue
Block a user