Use token enclave public key when in privacy multi-tenancy mode (#272)

Signed-off-by: Jason Frame <jasonwframe@gmail.com>
pull/282/head
Jason Frame 5 years ago committed by GitHub
parent 665101345a
commit 8f61ff33bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java
  2. 24
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/EnclavePublicKeyProvider.java
  3. 11
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/PrivacySendTransaction.java
  4. 14
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransaction.java
  5. 12
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroup.java
  6. 14
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDeletePrivacyGroup.java
  7. 14
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDistributeRawTransaction.java
  8. 12
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivFindPrivacyGroup.java
  9. 14
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetEeaTransactionCount.java
  10. 10
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransaction.java
  11. 13
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionCount.java
  12. 10
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceipt.java
  13. 16
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java
  14. 23
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java
  15. 19
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java
  16. 18
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/privacy/eea/PrivGetEeaTransactionCountTest.java
  17. 47
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java
  18. 38
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivCreatePrivacyGroupTest.java
  19. 88
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDeletePrivacyGroupTest.java
  20. 25
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivDistributeRawTransactionTest.java
  21. 101
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivFindPrivacyGroupTest.java
  22. 35
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java
  23. 17
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionCountTest.java
  24. 40
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java
  25. 94
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethodsTest.java
  26. 42
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java
  27. 71
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivacyControllerTest.java

@ -26,6 +26,7 @@ import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.enclave.types.SendResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetPrivateTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionLegacyResult;
@ -76,6 +77,8 @@ public class PrivGetPrivateTransactionIntegrationTest {
private static Vertx vertx = Vertx.vertx();
private EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@BeforeClass
public static void setUpOnce() throws Exception {
folder.create();
@ -89,7 +92,7 @@ public class PrivGetPrivateTransactionIntegrationTest {
final EnclaveFactory factory = new EnclaveFactory(vertx);
enclave = factory.createVertxEnclave(testHarness.clientUrl());
privacyController = new PrivacyController(enclave, ENCLAVE_PUBLIC_KEY, null, null, null, null);
privacyController = new PrivacyController(enclave, null, null, null, null);
}
@AfterClass
@ -148,7 +151,7 @@ public class PrivGetPrivateTransactionIntegrationTest {
public void returnsStoredPrivateTransaction() {
final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction(blockchain, privacyController);
new PrivGetPrivateTransaction(blockchain, privacyController, enclavePublicKeyProvider);
when(blockchain.transactionByHash(any(Hash.class)))
.thenReturn(Optional.of(returnedTransaction));

@ -0,0 +1,24 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods;
import java.util.Optional;
import io.vertx.ext.auth.User;
@FunctionalInterface
public interface EnclavePublicKeyProvider {
String getEnclaveKey(Optional<User> user);
}

@ -37,9 +37,13 @@ public class PrivacySendTransaction {
private static final Logger LOG = LogManager.getLogger();
protected final PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivacySendTransaction(final PrivacyController privacyController) {
public PrivacySendTransaction(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
public PrivateTransaction validateAndDecodeRequest(final JsonRpcRequestContext request)
@ -74,7 +78,10 @@ public class PrivacySendTransaction {
final String privacyGroupId,
final Supplier<JsonRpcResponse> successfulJsonRpcResponse) {
return privacyController
.validatePrivateTransaction(privateTransaction, privacyGroupId)
.validatePrivateTransaction(
privateTransaction,
privacyGroupId,
enclavePublicKeyProvider.getEnclaveKey(request.getUser()))
.either(
successfulJsonRpcResponse,
(errorReason) ->

@ -19,6 +19,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacySendTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacySendTransaction.ErrorResponseException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
@ -33,14 +34,19 @@ import org.hyperledger.besu.ethereum.privacy.SendTransactionResponse;
public class EeaSendRawTransaction implements JsonRpcMethod {
private final PrivacySendTransaction privacySendTransaction;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
private TransactionPool transactionPool;
private PrivacyController privacyController;
public EeaSendRawTransaction(
final TransactionPool transactionPool, final PrivacyController privacyController) {
final TransactionPool transactionPool,
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.transactionPool = transactionPool;
this.privacyController = privacyController;
this.privacySendTransaction = new PrivacySendTransaction(privacyController);
this.privacySendTransaction =
new PrivacySendTransaction(privacyController, enclavePublicKeyProvider);
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -59,7 +65,9 @@ public class EeaSendRawTransaction implements JsonRpcMethod {
final SendTransactionResponse sendTransactionResponse;
try {
sendTransactionResponse = privacyController.sendTransaction(privateTransaction);
sendTransactionResponse =
privacyController.sendTransaction(
privateTransaction, enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
} catch (final Exception e) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),

@ -21,6 +21,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.parameters.CreatePrivacyGroupParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
@ -33,9 +34,13 @@ public class PrivCreatePrivacyGroup implements JsonRpcMethod {
private static final Logger LOG = getLogger();
private PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivCreatePrivacyGroup(final PrivacyController privacyController) {
public PrivCreatePrivacyGroup(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -59,7 +64,10 @@ public class PrivCreatePrivacyGroup implements JsonRpcMethod {
try {
response =
privacyController.createPrivacyGroup(
parameter.getAddresses(), parameter.getName(), parameter.getDescription());
parameter.getAddresses(),
parameter.getName(),
parameter.getDescription(),
enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
} catch (Exception e) {
LOG.error("Failed to create privacy group", e);
return new JsonRpcErrorResponse(

@ -19,7 +19,9 @@ import static org.apache.logging.log4j.LogManager.getLogger;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
@ -30,9 +32,13 @@ public class PrivDeletePrivacyGroup implements JsonRpcMethod {
private static final Logger LOG = getLogger();
private PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivDeletePrivacyGroup(final PrivacyController privacyController) {
public PrivDeletePrivacyGroup(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -48,10 +54,12 @@ public class PrivDeletePrivacyGroup implements JsonRpcMethod {
final String response;
try {
response = privacyController.deletePrivacyGroup(privacyGroupId);
response =
privacyController.deletePrivacyGroup(
privacyGroupId, enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
} catch (Exception e) {
LOG.error("Failed to fetch transaction", e);
return new JsonRpcSuccessResponse(
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), JsonRpcError.DELETE_PRIVACY_GROUP_ERROR);
}
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), response);

@ -18,6 +18,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacySendTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacySendTransaction.ErrorResponseException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
@ -35,10 +36,15 @@ public class PrivDistributeRawTransaction implements JsonRpcMethod {
private final PrivacyController privacyController;
private final PrivacySendTransaction privacySendTransaction;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivDistributeRawTransaction(final PrivacyController privacyController) {
public PrivDistributeRawTransaction(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.privacySendTransaction = new PrivacySendTransaction(privacyController);
this.privacySendTransaction =
new PrivacySendTransaction(privacyController, enclavePublicKeyProvider);
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -57,7 +63,9 @@ public class PrivDistributeRawTransaction implements JsonRpcMethod {
final SendTransactionResponse sendTransactionResponse;
try {
sendTransactionResponse = privacyController.sendTransaction(privateTransaction);
sendTransactionResponse =
privacyController.sendTransaction(
privateTransaction, enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
} catch (final Exception e) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),

@ -20,6 +20,7 @@ import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
@ -34,9 +35,13 @@ public class PrivFindPrivacyGroup implements JsonRpcMethod {
private static final Logger LOG = getLogger();
private PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivFindPrivacyGroup(final PrivacyController privacyController) {
public PrivFindPrivacyGroup(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -54,7 +59,10 @@ public class PrivFindPrivacyGroup implements JsonRpcMethod {
PrivacyGroup[] response;
try {
response = privacyController.findPrivacyGroup(Arrays.asList(addresses));
response =
privacyController.findPrivacyGroup(
Arrays.asList(addresses),
enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
} catch (Exception e) {
LOG.error("Failed to fetch privacy group", e);
return new JsonRpcErrorResponse(

@ -19,6 +19,7 @@ import static org.apache.logging.log4j.LogManager.getLogger;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
@ -34,9 +35,13 @@ public class PrivGetEeaTransactionCount implements JsonRpcMethod {
private static final Logger LOG = getLogger();
private PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivGetEeaTransactionCount(final PrivacyController privacyController) {
public PrivGetEeaTransactionCount(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -56,7 +61,12 @@ public class PrivGetEeaTransactionCount implements JsonRpcMethod {
final String[] privateFor = requestContext.getRequiredParameter(2, String[].class);
try {
final long nonce = privacyController.determineNonce(privateFrom, privateFor, address);
final long nonce =
privacyController.determineNonce(
privateFrom,
privateFor,
address,
enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
return new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), Quantity.create(nonce));
} catch (final Exception e) {

@ -21,6 +21,7 @@ import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionGroupResult;
@ -41,11 +42,15 @@ public class PrivGetPrivateTransaction implements JsonRpcMethod {
private final BlockchainQueries blockchain;
private final PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivGetPrivateTransaction(
final BlockchainQueries blockchain, final PrivacyController privacyController) {
final BlockchainQueries blockchain,
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.blockchain = blockchain;
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -68,7 +73,8 @@ public class PrivGetPrivateTransaction implements JsonRpcMethod {
LOG.trace("Fetching transaction information");
final ReceiveResponse receiveResponse =
privacyController.retrieveTransaction(
resultTransaction.getTransaction().getPayload().toBase64String());
resultTransaction.getTransaction().getPayload().toBase64String(),
enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
LOG.trace("Received transaction information");
final BytesValueRLPInput input =

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
@ -28,9 +29,13 @@ import org.hyperledger.besu.ethereum.privacy.PrivacyController;
public class PrivGetTransactionCount implements JsonRpcMethod {
private final PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivGetTransactionCount(final PrivacyController privacyController) {
public PrivGetTransactionCount(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -48,7 +53,11 @@ public class PrivGetTransactionCount implements JsonRpcMethod {
final Address address = requestContext.getRequiredParameter(0, Address.class);
final String privacyGroupId = requestContext.getRequiredParameter(1, String.class);
final long nonce = privacyController.determineNonce(address, privacyGroupId);
final long nonce =
privacyController.determineNonce(
address,
privacyGroupId,
enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), Quantity.create(nonce));
}
}

@ -23,6 +23,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
@ -56,14 +57,17 @@ public class PrivGetTransactionReceipt implements JsonRpcMethod {
private final BlockchainQueries blockchain;
private PrivacyParameters privacyParameters;
private PrivacyController privacyController;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public PrivGetTransactionReceipt(
final BlockchainQueries blockchain,
final PrivacyParameters privacyParameters,
final PrivacyController privacyController) {
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.blockchain = blockchain;
this.privacyParameters = privacyParameters;
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
}
@Override
@ -92,7 +96,9 @@ public class PrivGetTransactionReceipt implements JsonRpcMethod {
final String privacyGroupId;
try {
final ReceiveResponse receiveResponse =
privacyController.retrieveTransaction(transaction.getPayload().toBase64String());
privacyController.retrieveTransaction(
transaction.getPayload().toBase64String(),
enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()));
LOG.trace("Received transaction information");
final BytesValueRLPInput input =

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.EeaSendRawTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetEeaTransactionCount;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
@ -38,14 +39,17 @@ public class EeaJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
}
@Override
protected RpcApi getApiGroup() {
return RpcApis.EEA;
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
return mapOf(
new EeaSendRawTransaction(
getTransactionPool(), privacyController, enclavePublicKeyProvider),
new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider));
}
@Override
protected Map<String, JsonRpcMethod> create(final PrivacyController privacyController) {
return mapOf(
new EeaSendRawTransaction(getTransactionPool(), privacyController),
new PrivGetEeaTransactionCount(privacyController));
protected RpcApi getApiGroup() {
return RpcApis.EEA;
}
}

@ -17,6 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivCreatePrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivDeletePrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivDistributeRawTransaction;
@ -49,16 +50,22 @@ public class PrivJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
}
@Override
protected Map<String, JsonRpcMethod> create(final PrivacyController privacyController) {
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
return mapOf(
new PrivGetTransactionReceipt(
getBlockchainQueries(), getPrivacyParameters(), privacyController),
new PrivCreatePrivacyGroup(privacyController),
new PrivDeletePrivacyGroup(privacyController),
new PrivFindPrivacyGroup(privacyController),
getBlockchainQueries(),
getPrivacyParameters(),
privacyController,
enclavePublicKeyProvider),
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider),
new PrivDeletePrivacyGroup(privacyController, enclavePublicKeyProvider),
new PrivFindPrivacyGroup(privacyController, enclavePublicKeyProvider),
new PrivGetPrivacyPrecompileAddress(getPrivacyParameters()),
new PrivGetTransactionCount(privacyController),
new PrivGetPrivateTransaction(getBlockchainQueries(), privacyController),
new PrivDistributeRawTransaction(privacyController));
new PrivGetTransactionCount(privacyController, enclavePublicKeyProvider),
new PrivGetPrivateTransaction(
getBlockchainQueries(), privacyController, enclavePublicKeyProvider),
new PrivDistributeRawTransaction(privacyController, enclavePublicKeyProvider));
}
}

@ -14,9 +14,12 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;
import org.hyperledger.besu.ethereum.api.jsonrpc.LatestNonceProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.DisabledPrivacyRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyRpcMethodDecorator;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Address;
@ -77,13 +80,25 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
new PrivacyController(
privacyParameters, protocolSchedule.getChainId(), markerTransactionFactory);
return create(privacyController).entrySet().stream()
final EnclavePublicKeyProvider enclavePublicProvider =
privacyParameters.isMultiTenancyEnabled()
? user ->
enclavePublicKey(user)
.orElseThrow(
() ->
new IllegalStateException(
"Request does not contain an authorization token"))
: user -> privacyParameters.getEnclavePublicKey();
return create(privacyController, enclavePublicProvider).entrySet().stream()
.collect(
Collectors.toMap(
Entry::getKey, entry -> createPrivacyMethod(privacyParameters, entry.getValue())));
}
protected abstract Map<String, JsonRpcMethod> create(final PrivacyController privacyController);
protected abstract Map<String, JsonRpcMethod> create(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider);
private PrivateMarkerTransactionFactory createPrivateMarkerTransactionFactory(
final PrivacyParameters privacyParameters,

@ -20,6 +20,7 @@ import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetEeaTransactionCount;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
@ -33,6 +34,7 @@ import org.junit.Before;
import org.junit.Test;
public class PrivGetEeaTransactionCountTest {
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final PrivacyController privacyController = mock(PrivacyController.class);
@ -41,6 +43,7 @@ public class PrivGetEeaTransactionCountTest {
private final String privateFrom = "thePrivateFromKey";
private final String[] privateFor = new String[] {"first", "second", "third"};
private final Address address = Address.fromHexString("55");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@Before
public void setup() {
@ -54,9 +57,10 @@ public class PrivGetEeaTransactionCountTest {
@Test
public void validRequestProducesExpectedNonce() {
final long reportedNonce = 8L;
final PrivGetEeaTransactionCount method = new PrivGetEeaTransactionCount(privacyController);
final PrivGetEeaTransactionCount method =
new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider);
when(privacyController.determineNonce(privateFrom, privateFor, address))
when(privacyController.determineNonce(privateFrom, privateFor, address, ENCLAVE_PUBLIC_KEY))
.thenReturn(reportedNonce);
final JsonRpcResponse response = method.response(request);
@ -69,9 +73,10 @@ public class PrivGetEeaTransactionCountTest {
@Test
public void nonceProviderThrowsRuntimeExceptionProducesErrorResponse() {
final PrivGetEeaTransactionCount method = new PrivGetEeaTransactionCount(privacyController);
final PrivGetEeaTransactionCount method =
new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider);
when(privacyController.determineNonce(privateFrom, privateFor, address))
when(privacyController.determineNonce(privateFrom, privateFor, address, ENCLAVE_PUBLIC_KEY))
.thenThrow(RuntimeException.class);
final JsonRpcResponse response = method.response(request);
@ -84,9 +89,10 @@ public class PrivGetEeaTransactionCountTest {
@Test
public void nonceProviderThrowsAnExceptionProducesErrorResponse() {
final PrivGetEeaTransactionCount method = new PrivGetEeaTransactionCount(privacyController);
final PrivGetEeaTransactionCount method =
new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider);
when(privacyController.determineNonce(privateFrom, privateFor, address))
when(privacyController.determineNonce(privateFrom, privateFor, address, ENCLAVE_PUBLIC_KEY))
.thenThrow(RuntimeException.class);
final JsonRpcResponse response = method.response(request);

@ -16,6 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
@ -25,6 +26,7 @@ import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.enclave.EnclaveServerException;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
@ -42,6 +44,9 @@ import org.hyperledger.besu.ethereum.privacy.SendTransactionResponse;
import java.math.BigInteger;
import java.util.Optional;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
import org.junit.Test;
@ -106,9 +111,13 @@ public class EeaSendRawTransactionTest {
Bytes.fromHexString("0x"),
Address.wrap(Bytes.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
Optional.empty());
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
final String MOCK_ORION_KEY = "";
final String MOCK_PRIVACY_GROUP = "";
private final String MOCK_ORION_KEY = "";
private final String MOCK_PRIVACY_GROUP = "";
private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@Mock private TransactionPool transactionPool;
@ -118,7 +127,8 @@ public class EeaSendRawTransactionTest {
@Before
public void before() {
method = new EeaSendRawTransaction(transactionPool, privacyController);
method =
new EeaSendRawTransaction(transactionPool, privacyController, enclavePublicKeyProvider);
}
@Test
@ -195,10 +205,10 @@ public class EeaSendRawTransactionTest {
@Test
public void validTransactionIsSentToTransactionPool() {
when(privacyController.sendTransaction(any(PrivateTransaction.class)))
when(privacyController.sendTransaction(any(PrivateTransaction.class), any()))
.thenReturn(new SendTransactionResponse(MOCK_ORION_KEY, MOCK_PRIVACY_GROUP));
when(privacyController.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class)))
any(PrivateTransaction.class), any(String.class), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivacyMarkerTransaction(
any(String.class), any(PrivateTransaction.class)))
@ -208,7 +218,8 @@ public class EeaSendRawTransactionTest {
final JsonRpcRequestContext request =
new JsonRpcRequestContext(
new JsonRpcRequest(
"2.0", "eea_sendRawTransaction", new String[] {VALID_PRIVATE_TRANSACTION_RLP}));
"2.0", "eea_sendRawTransaction", new String[] {VALID_PRIVATE_TRANSACTION_RLP}),
user);
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
@ -218,9 +229,11 @@ public class EeaSendRawTransactionTest {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
verify(privacyController).sendTransaction(any(PrivateTransaction.class));
verify(privacyController)
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class));
.sendTransaction(any(PrivateTransaction.class), eq(ENCLAVE_PUBLIC_KEY));
verify(privacyController)
.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class), eq(ENCLAVE_PUBLIC_KEY));
verify(privacyController)
.createPrivacyMarkerTransaction(any(String.class), any(PrivateTransaction.class));
verify(transactionPool).addLocalTransaction(any(Transaction.class));
@ -228,10 +241,10 @@ public class EeaSendRawTransactionTest {
@Test
public void validTransactionPrivacyGroupIsSentToTransactionPool() {
when(privacyController.sendTransaction(any(PrivateTransaction.class)))
when(privacyController.sendTransaction(any(PrivateTransaction.class), any()))
.thenReturn(new SendTransactionResponse(MOCK_ORION_KEY, MOCK_PRIVACY_GROUP));
when(privacyController.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class)))
any(PrivateTransaction.class), any(String.class), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivacyMarkerTransaction(
any(String.class), any(PrivateTransaction.class)))
@ -254,9 +267,9 @@ public class EeaSendRawTransactionTest {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
verify(privacyController).sendTransaction(any(PrivateTransaction.class));
verify(privacyController).sendTransaction(any(PrivateTransaction.class), any());
verify(privacyController)
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class));
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class), any());
verify(privacyController)
.createPrivacyMarkerTransaction(any(String.class), any(PrivateTransaction.class));
verify(transactionPool).addLocalTransaction(any(Transaction.class));
@ -282,7 +295,7 @@ public class EeaSendRawTransactionTest {
@Test
public void invalidTransactionIsNotSentToTransactionPool() {
when(privacyController.sendTransaction(any(PrivateTransaction.class)))
when(privacyController.sendTransaction(any(PrivateTransaction.class), any()))
.thenThrow(new EnclaveServerException(500, "enclave failed to execute"));
final JsonRpcRequestContext request =
@ -346,10 +359,10 @@ public class EeaSendRawTransactionTest {
private void verifyErrorForInvalidTransaction(
final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) {
when(privacyController.sendTransaction(any(PrivateTransaction.class)))
when(privacyController.sendTransaction(any(PrivateTransaction.class), any()))
.thenReturn(new SendTransactionResponse(MOCK_ORION_KEY, MOCK_PRIVACY_GROUP));
when(privacyController.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class)))
any(PrivateTransaction.class), any(String.class), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivacyMarkerTransaction(
any(String.class), any(PrivateTransaction.class)))
@ -367,9 +380,9 @@ public class EeaSendRawTransactionTest {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
verify(privacyController).sendTransaction(any(PrivateTransaction.class));
verify(privacyController).sendTransaction(any(PrivateTransaction.class), any());
verify(privacyController)
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class));
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class), any());
verify(privacyController)
.createPrivacyMarkerTransaction(any(String.class), any(PrivateTransaction.class));
verify(transactionPool).addLocalTransaction(any(Transaction.class));

@ -18,6 +18,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowableOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.enclave.Enclave;
@ -26,6 +27,7 @@ import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.parameters.CreatePrivacyGroupParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
@ -35,6 +37,9 @@ import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import java.util.List;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Test;
@ -45,10 +50,14 @@ public class PrivCreatePrivacyGroupTest {
private static final String NAME = "testName";
private static final String DESCRIPTION = "testDesc";
private static final List<String> ADDRESSES = Lists.newArrayList(FROM, "second participant");
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private final Enclave enclave = mock(Enclave.class);
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final PrivacyController privacyController = mock(PrivacyController.class);
private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@Before
public void setUp() {
@ -61,12 +70,12 @@ public class PrivCreatePrivacyGroupTest {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);
when(privacyController.createPrivacyGroup(ADDRESSES, NAME, DESCRIPTION))
when(privacyController.createPrivacyGroup(ADDRESSES, NAME, DESCRIPTION, ENCLAVE_PUBLIC_KEY))
.thenReturn(privacyGroup);
when(privacyParameters.getEnclavePublicKey()).thenReturn(FROM);
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final CreatePrivacyGroupParameter param =
new CreatePrivacyGroupParameter(ADDRESSES, NAME, DESCRIPTION);
@ -74,7 +83,7 @@ public class PrivCreatePrivacyGroupTest {
final Object[] params = new Object[] {param};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_createPrivacyGroup", params));
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_createPrivacyGroup", params), user);
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privCreatePrivacyGroup.response(request);
@ -82,6 +91,7 @@ public class PrivCreatePrivacyGroupTest {
final String result = (String) response.getResult();
assertThat(result).isEqualTo(expected);
verify(privacyController).createPrivacyGroup(ADDRESSES, NAME, DESCRIPTION, ENCLAVE_PUBLIC_KEY);
}
@Test
@ -89,11 +99,12 @@ public class PrivCreatePrivacyGroupTest {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);
when(privacyController.createPrivacyGroup(ADDRESSES, NAME, null)).thenReturn(privacyGroup);
when(privacyController.createPrivacyGroup(ADDRESSES, NAME, null, ENCLAVE_PUBLIC_KEY))
.thenReturn(privacyGroup);
when(privacyParameters.getEnclavePublicKey()).thenReturn(FROM);
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final Object[] params =
new Object[] {
@ -124,12 +135,12 @@ public class PrivCreatePrivacyGroupTest {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);
when(privacyController.createPrivacyGroup(ADDRESSES, null, DESCRIPTION))
when(privacyController.createPrivacyGroup(ADDRESSES, null, DESCRIPTION, ENCLAVE_PUBLIC_KEY))
.thenReturn(privacyGroup);
when(privacyParameters.getEnclavePublicKey()).thenReturn(FROM);
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final Object[] params =
new Object[] {
@ -160,11 +171,12 @@ public class PrivCreatePrivacyGroupTest {
final String expected = "a wonderful group";
final PrivacyGroup privacyGroup =
new PrivacyGroup(expected, PrivacyGroup.Type.PANTHEON, NAME, DESCRIPTION, ADDRESSES);
when(privacyController.createPrivacyGroup(ADDRESSES, null, null)).thenReturn(privacyGroup);
when(privacyController.createPrivacyGroup(ADDRESSES, null, null, ENCLAVE_PUBLIC_KEY))
.thenReturn(privacyGroup);
when(privacyParameters.getEnclavePublicKey()).thenReturn(FROM);
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final Object[] params =
new Object[] {
@ -196,7 +208,7 @@ public class PrivCreatePrivacyGroupTest {
when(privacyParameters.getEnclavePublicKey()).thenReturn(FROM);
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final Object[] params =
new Object[] {
@ -225,7 +237,7 @@ public class PrivCreatePrivacyGroupTest {
public void returnsCorrectExceptionMissingParam() {
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {};
@ -241,10 +253,10 @@ public class PrivCreatePrivacyGroupTest {
@Test
public void returnsCorrectErrorEnclaveError() {
when(privacyController.createPrivacyGroup(ADDRESSES, NAME, DESCRIPTION))
when(privacyController.createPrivacyGroup(ADDRESSES, NAME, DESCRIPTION, ENCLAVE_PUBLIC_KEY))
.thenThrow(new EnclaveServerException(500, ""));
final PrivCreatePrivacyGroup privCreatePrivacyGroup =
new PrivCreatePrivacyGroup(privacyController);
new PrivCreatePrivacyGroup(privacyController, enclavePublicKeyProvider);
final CreatePrivacyGroupParameter param =
new CreatePrivacyGroupParameter(ADDRESSES, NAME, DESCRIPTION);

@ -0,0 +1,88 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.junit.Before;
import org.junit.Test;
public class PrivDeletePrivacyGroupTest {
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final String PRIVACY_GROUP_ID = "privacyGroupId";
private final Enclave enclave = mock(Enclave.class);
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final PrivacyController privacyController = mock(PrivacyController.class);
private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
private JsonRpcRequestContext request;
@Before
public void setUp() {
when(privacyParameters.getEnclave()).thenReturn(enclave);
when(privacyParameters.isEnabled()).thenReturn(true);
request =
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_deletePrivacyGroup", new Object[] {PRIVACY_GROUP_ID}),
user);
}
@Test
public void deletesPrivacyGroupWithValidGroupId() {
when(privacyController.deletePrivacyGroup(PRIVACY_GROUP_ID, ENCLAVE_PUBLIC_KEY))
.thenReturn(PRIVACY_GROUP_ID);
final PrivDeletePrivacyGroup privDeletePrivacyGroup =
new PrivDeletePrivacyGroup(privacyController, enclavePublicKeyProvider);
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privDeletePrivacyGroup.response(request);
final String result = (String) response.getResult();
assertThat(result).isEqualTo(PRIVACY_GROUP_ID);
verify(privacyController).deletePrivacyGroup(PRIVACY_GROUP_ID, ENCLAVE_PUBLIC_KEY);
}
@Test
public void failsWithDeletePrivacyGroupErrorIfEnclaveFails() {
when(privacyController.deletePrivacyGroup(PRIVACY_GROUP_ID, ENCLAVE_PUBLIC_KEY))
.thenThrow(new IllegalStateException("some failure"));
final PrivDeletePrivacyGroup privDeletePrivacyGroup =
new PrivDeletePrivacyGroup(privacyController, enclavePublicKeyProvider);
final JsonRpcErrorResponse response =
(JsonRpcErrorResponse) privDeletePrivacyGroup.response(request);
assertThat(response.getError()).isEqualTo(JsonRpcError.DELETE_PRIVACY_GROUP_ERROR);
verify(privacyController).deletePrivacyGroup(PRIVACY_GROUP_ID, ENCLAVE_PUBLIC_KEY);
}
}

@ -16,11 +16,13 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
@ -30,6 +32,9 @@ import org.hyperledger.besu.ethereum.privacy.SendTransactionResponse;
import java.util.Base64;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
import org.junit.Test;
@ -48,22 +53,27 @@ public class PrivDistributeRawTransactionTest {
+ "e60551d7a19cf30603db5bfc23e5ac43a56f57f25f75486aa00f"
+ "200e885ff29e973e2576b6600181d1b0a2b5294e30d9be4a1981"
+ "ffb33a0b8c8a72657374726963746564";
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@Mock private PrivDistributeRawTransaction method;
@Mock private PrivacyController privacyController;
@Before
public void before() {
method = new PrivDistributeRawTransaction(privacyController);
method = new PrivDistributeRawTransaction(privacyController, enclavePublicKeyProvider);
}
@Test
public void validTransactionHashReturnedAfterDistribute() {
final String enclavePublicKey = "93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=";
when(privacyController.sendTransaction(any(PrivateTransaction.class)))
when(privacyController.sendTransaction(any(PrivateTransaction.class), any()))
.thenReturn(new SendTransactionResponse(enclavePublicKey, ""));
when(privacyController.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class)))
any(PrivateTransaction.class), any(String.class), any()))
.thenReturn(ValidationResult.valid());
final JsonRpcRequestContext request =
@ -71,7 +81,8 @@ public class PrivDistributeRawTransactionTest {
new JsonRpcRequest(
"2.0",
"priv_distributeRawTransaction",
new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP}));
new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP}),
user);
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
@ -81,8 +92,10 @@ public class PrivDistributeRawTransactionTest {
final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse);
verify(privacyController).sendTransaction(any(PrivateTransaction.class));
verify(privacyController)
.validatePrivateTransaction(any(PrivateTransaction.class), any(String.class));
.sendTransaction(any(PrivateTransaction.class), eq(ENCLAVE_PUBLIC_KEY));
verify(privacyController)
.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class), eq(ENCLAVE_PUBLIC_KEY));
}
}

@ -0,0 +1,101 @@
/*
* Copyright 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import java.util.List;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.assertj.core.util.Lists;
import org.junit.Before;
import org.junit.Test;
public class PrivFindPrivacyGroupTest {
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final List<String> ADDRESSES =
List.of(
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
"0x627306090abab3a6e1400e9345bc60c78a8bef57");
private final Enclave enclave = mock(Enclave.class);
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final PrivacyController privacyController = mock(PrivacyController.class);
private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
private JsonRpcRequestContext request;
private PrivacyGroup privacyGroup;
@Before
public void setUp() {
when(privacyParameters.getEnclave()).thenReturn(enclave);
when(privacyParameters.isEnabled()).thenReturn(true);
request =
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_deletePrivacyGroup", new Object[] {ADDRESSES}), user);
privacyGroup = new PrivacyGroup();
privacyGroup.setName("privacyGroup");
privacyGroup.setDescription("privacyGroup desc");
privacyGroup.setPrivacyGroupId("privacy group id");
privacyGroup.setMembers(Lists.list("member1"));
}
@Test
public void findsPrivacyGroupWithValidAddresses() {
when(privacyController.findPrivacyGroup(ADDRESSES, ENCLAVE_PUBLIC_KEY))
.thenReturn(new PrivacyGroup[] {privacyGroup});
final PrivFindPrivacyGroup privFindPrivacyGroup =
new PrivFindPrivacyGroup(privacyController, enclavePublicKeyProvider);
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privFindPrivacyGroup.response(request);
final PrivacyGroup[] result = (PrivacyGroup[]) response.getResult();
assertThat(result).hasSize(1);
assertThat(result[0]).isEqualToComparingFieldByField(privacyGroup);
verify(privacyController).findPrivacyGroup(ADDRESSES, ENCLAVE_PUBLIC_KEY);
}
@Test
public void failsWithFindPrivacyGroupErrorIfEnclaveFails() {
when(privacyController.findPrivacyGroup(ADDRESSES, ENCLAVE_PUBLIC_KEY))
.thenThrow(new IllegalStateException("some failure"));
final PrivFindPrivacyGroup privFindPrivacyGroup =
new PrivFindPrivacyGroup(privacyController, enclavePublicKeyProvider);
final JsonRpcErrorResponse response =
(JsonRpcErrorResponse) privFindPrivacyGroup.response(request);
assertThat(response.getError()).isEqualTo(JsonRpcError.FIND_PRIVACY_GROUP_ERROR);
verify(privacyController).findPrivacyGroup(ADDRESSES, ENCLAVE_PUBLIC_KEY);
}
}

@ -19,6 +19,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1;
@ -26,6 +27,7 @@ import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionGroupResult;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionLegacyResult;
@ -48,6 +50,9 @@ import java.util.Base64;
import java.util.Optional;
import com.google.common.collect.Lists;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
import org.junit.Rule;
@ -65,6 +70,11 @@ public class PrivGetPrivateTransactionTest {
SECP256K1.PrivateKey.create(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final String TRANSACTION_HASH =
Bytes.fromBase64String("5bpr9tz4zhmWmk9RlNng93Ky7lXwFkMc7+ckoFgUMku=").toString();
private static final Bytes ENCLAVE_KEY =
Bytes.fromBase64String("93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=");
private final PrivateTransaction.Builder privateTransactionBuilder =
PrivateTransaction.builder()
@ -90,15 +100,15 @@ public class PrivGetPrivateTransactionTest {
.privateFrom(Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.restriction(Restriction.RESTRICTED);
private final String enclaveKey =
Bytes.fromBase64String("93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=").toString();
private final Enclave enclave = mock(Enclave.class);
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final BlockchainQueries blockchain = mock(BlockchainQueries.class);
private final TransactionWithMetadata returnedTransaction = mock(TransactionWithMetadata.class);
private final Transaction justTransaction = mock(Transaction.class);
private final PrivacyController privacyController = mock(PrivacyController.class);
private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@Before
public void before() {
@ -111,8 +121,7 @@ public class PrivGetPrivateTransactionTest {
when(blockchain.transactionByHash(any(Hash.class)))
.thenReturn(Optional.of(returnedTransaction));
when(returnedTransaction.getTransaction()).thenReturn(justTransaction);
when(justTransaction.getPayload())
.thenReturn(new UnformattedDataImpl(Bytes.fromBase64String("")));
when(justTransaction.getPayload()).thenReturn(new UnformattedDataImpl(ENCLAVE_KEY));
final PrivateTransaction privateTransaction =
privateTransactionBuilder
@ -124,14 +133,15 @@ public class PrivGetPrivateTransactionTest {
new PrivateTransactionLegacyResult(privateTransaction);
final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction(blockchain, privacyController);
final Object[] params = new Object[] {enclaveKey};
new PrivGetPrivateTransaction(blockchain, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {TRANSACTION_HASH};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getPrivateTransaction", params));
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getPrivateTransaction", params), user);
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
when(privacyController.retrieveTransaction(anyString()))
when(privacyController.retrieveTransaction(anyString(), any()))
.thenReturn(
new ReceiveResponse(
Base64.getEncoder().encodeToString(bvrlp.encoded().toArray()).getBytes(UTF_8), ""));
@ -140,6 +150,7 @@ public class PrivGetPrivateTransactionTest {
final PrivateTransactionResult result = (PrivateTransactionResult) response.getResult();
assertThat(result).isEqualToComparingFieldByField(privateTransactionLegacyResult);
verify(privacyController).retrieveTransaction(ENCLAVE_KEY.toBase64String(), ENCLAVE_PUBLIC_KEY);
}
@Test
@ -158,15 +169,15 @@ public class PrivGetPrivateTransactionTest {
new PrivateTransactionGroupResult(privateTransaction);
final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction(blockchain, privacyController);
new PrivGetPrivateTransaction(blockchain, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {enclaveKey};
final Object[] params = new Object[] {TRANSACTION_HASH};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getPrivateTransaction", params));
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
when(privacyController.retrieveTransaction(anyString()))
when(privacyController.retrieveTransaction(anyString(), any()))
.thenReturn(
new ReceiveResponse(
Base64.getEncoder().encodeToString(bvrlp.encoded().toArrayUnsafe()).getBytes(UTF_8),

@ -17,21 +17,27 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
import org.junit.Test;
public class PrivGetTransactionCountTest {
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final PrivacyController privacyController = mock(PrivacyController.class);
@ -40,25 +46,30 @@ public class PrivGetTransactionCountTest {
private final Address senderAddress =
Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57");
private final long NONCE = 5;
private User user = new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@Before
public void before() {
when(privacyParameters.isEnabled()).thenReturn(true);
when(privacyController.determineNonce(senderAddress, privacyGroupId)).thenReturn(NONCE);
when(privacyController.determineNonce(senderAddress, privacyGroupId, ENCLAVE_PUBLIC_KEY))
.thenReturn(NONCE);
}
@Test
public void verifyTransactionCount() {
final PrivGetTransactionCount privGetTransactionCount =
new PrivGetTransactionCount(privacyController);
new PrivGetTransactionCount(privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {senderAddress, privacyGroupId};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionCount", params));
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getTransactionCount", params), user);
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetTransactionCount.response(request);
assertThat(response.getResult()).isEqualTo(String.format("0x%X", NONCE));
verify(privacyController).determineNonce(senderAddress, privacyGroupId, ENCLAVE_PUBLIC_KEY);
}
}

@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1;
@ -29,6 +30,7 @@ import org.hyperledger.besu.enclave.EnclaveServerException;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.Quantity;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionReceiptResult;
@ -54,6 +56,9 @@ import java.util.Collections;
import java.util.Optional;
import com.google.common.collect.Lists;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.Before;
@ -65,6 +70,8 @@ public class PrivGetTransactionReceiptTest {
@Rule public final TemporaryFolder temp = new TemporaryFolder();
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final Bytes ENCLAVE_KEY = Bytes.wrap("EnclaveKey".getBytes(UTF_8));
private static final Address SENDER =
Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73");
@ -135,6 +142,9 @@ public class PrivGetTransactionReceiptTest {
null,
Quantity.create(Bytes.of(1).toUnsignedBigInteger()));
private User user = new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
private final BlockchainQueries blockchainQueries = mock(BlockchainQueries.class);
private final Blockchain blockchain = mock(Blockchain.class);
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
@ -143,7 +153,7 @@ public class PrivGetTransactionReceiptTest {
@Before
public void setUp() {
when(privacyController.retrieveTransaction(anyString()))
when(privacyController.retrieveTransaction(anyString(), any()))
.thenReturn(
new ReceiveResponse(
Base64.getEncoder().encode(RLP.encode(privateTransaction::writeTo).toArray()), ""));
@ -170,10 +180,12 @@ public class PrivGetTransactionReceiptTest {
public void returnReceiptIfTransactionExists() {
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(blockchainQueries, privacyParameters, privacyController);
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getTransactionReceipt", params), user);
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetTransactionReceipt.response(request);
@ -181,15 +193,17 @@ public class PrivGetTransactionReceiptTest {
(PrivateTransactionReceiptResult) response.getResult();
assertThat(result).isEqualToComparingFieldByField(expectedResult);
verify(privacyController).retrieveTransaction(ENCLAVE_KEY.toBase64String(), ENCLAVE_PUBLIC_KEY);
}
@Test
public void enclavePayloadNotFoundResultsInSuccessButNullResponse() {
when(privacyController.retrieveTransaction(anyString()))
when(privacyController.retrieveTransaction(anyString(), any()))
.thenThrow(new EnclaveClientException(404, "EnclavePayloadNotFound"));
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(blockchainQueries, privacyParameters, privacyController);
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
@ -207,7 +221,8 @@ public class PrivGetTransactionReceiptTest {
when(blockchain.getTransactionLocation(nullable(Hash.class))).thenReturn(Optional.empty());
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(blockchainQueries, privacyParameters, privacyController);
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
@ -222,10 +237,11 @@ public class PrivGetTransactionReceiptTest {
@Test
public void enclaveConnectionIssueThrowsRuntimeException() {
when(privacyController.retrieveTransaction(anyString()))
when(privacyController.retrieveTransaction(anyString(), any()))
.thenThrow(EnclaveServerException.class);
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(blockchainQueries, privacyParameters, privacyController);
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
@ -240,7 +256,8 @@ public class PrivGetTransactionReceiptTest {
.thenReturn(Optional.of(Bytes.fromHexString("0x01")));
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(blockchainQueries, privacyParameters, privacyController);
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequest request = new JsonRpcRequest("1", "priv_getTransactionReceipt", params);
@ -256,11 +273,12 @@ public class PrivGetTransactionReceiptTest {
@Test
public void enclaveKeysCannotDecryptPayloadThrowsRuntimeException() {
final String keysCannotDecryptPayloadMsg = "EnclaveKeysCannotDecryptPayload";
when(privacyController.retrieveTransaction(any()))
when(privacyController.retrieveTransaction(any(), any()))
.thenThrow(new EnclaveClientException(400, keysCannotDecryptPayloadMsg));
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(blockchainQueries, privacyParameters, privacyController);
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));

@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.PRIVACY_NOT_ENABLED;
import static org.mockito.Mockito.when;
@ -23,6 +24,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyRpcMethodDecorator;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
@ -34,7 +36,11 @@ import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import java.util.Map;
import java.util.Optional;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -43,18 +49,23 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class PrivacyApiGroupJsonRpcMethodsTest {
private static final String DEFAULT_ENCLAVE_PUBLIC_KEY =
"A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
@Mock private JsonRpcMethod rpcMethod;
@Mock private BlockchainQueries blockchainQueries;
@Mock private ProtocolSchedule<?> protocolSchedule;
@Mock private TransactionPool transactionPool;
@Mock private PrivacyParameters privacyParameters;
private PrivacyApiGroupJsonRpcMethods privacyApiGroupJsonRpcMethods;
private TestPrivacyApiGroupJsonRpcMethods privacyApiGroupJsonRpcMethods;
@Before
public void setup() {
when(rpcMethod.getName()).thenReturn("priv_method");
privacyApiGroupJsonRpcMethods = createPrivacyApiGroupJsonRpcMethods();
privacyApiGroupJsonRpcMethods =
new TestPrivacyApiGroupJsonRpcMethods(
blockchainQueries, protocolSchedule, transactionPool, privacyParameters, rpcMethod);
}
@Test
@ -75,6 +86,52 @@ public class PrivacyApiGroupJsonRpcMethodsTest {
assertThat(privMethod).isSameAs(rpcMethod);
}
@Test
public void rpcsCreatedWithoutMultiTenancyUseFixedEnclavePublicKey() {
when(privacyParameters.isEnabled()).thenReturn(true);
when(privacyParameters.getEnclavePublicKey()).thenReturn(DEFAULT_ENCLAVE_PUBLIC_KEY);
final User user = createUser(DEFAULT_ENCLAVE_PUBLIC_KEY);
privacyApiGroupJsonRpcMethods.create();
final EnclavePublicKeyProvider enclavePublicKeyProvider =
privacyApiGroupJsonRpcMethods.enclavePublicKeyProvider;
assertThat(enclavePublicKeyProvider.getEnclaveKey(Optional.of(user)))
.isEqualTo(DEFAULT_ENCLAVE_PUBLIC_KEY);
assertThat(enclavePublicKeyProvider.getEnclaveKey(Optional.empty()))
.isEqualTo(DEFAULT_ENCLAVE_PUBLIC_KEY);
}
@Test
public void rpcsCreatedWithMultiTenancyUseEnclavePublicKeyFromRequest() {
when(privacyParameters.isEnabled()).thenReturn(true);
when(privacyParameters.isMultiTenancyEnabled()).thenReturn(true);
final User user1 = createUser("key1");
final User user2 = createUser("key2");
privacyApiGroupJsonRpcMethods.create();
final EnclavePublicKeyProvider enclavePublicKeyProvider =
privacyApiGroupJsonRpcMethods.enclavePublicKeyProvider;
assertThat(enclavePublicKeyProvider.getEnclaveKey(Optional.of(user1))).isEqualTo("key1");
assertThat(enclavePublicKeyProvider.getEnclaveKey(Optional.of(user2))).isEqualTo("key2");
}
@Test
public void rpcsCreatedWithMultiTenancyAndWithoutUserFail() {
when(privacyParameters.isEnabled()).thenReturn(true);
when(privacyParameters.isMultiTenancyEnabled()).thenReturn(true);
privacyApiGroupJsonRpcMethods.create();
final EnclavePublicKeyProvider enclavePublicKeyProvider =
privacyApiGroupJsonRpcMethods.enclavePublicKeyProvider;
assertThatThrownBy(() -> enclavePublicKeyProvider.getEnclaveKey(Optional.empty()))
.isInstanceOf(IllegalStateException.class)
.hasMessage("Request does not contain an authorization token");
}
@Test
public void rpcMethodsCreatedWhenPrivacyIsNotEnabledAreDisabled() {
final Map<String, JsonRpcMethod> rpcMethods = privacyApiGroupJsonRpcMethods.create();
@ -90,19 +147,36 @@ public class PrivacyApiGroupJsonRpcMethodsTest {
assertThat(errorResponse.getError()).isEqualTo(PRIVACY_NOT_ENABLED);
}
private PrivacyApiGroupJsonRpcMethods createPrivacyApiGroupJsonRpcMethods() {
return new PrivacyApiGroupJsonRpcMethods(
blockchainQueries, protocolSchedule, transactionPool, privacyParameters) {
private User createUser(final String enclavePublicKey) {
return new JWTUser(new JsonObject().put("privacyPublicKey", enclavePublicKey), "");
}
@Override
protected RpcApi getApiGroup() {
return RpcApis.PRIV;
private static class TestPrivacyApiGroupJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
private final JsonRpcMethod rpcMethod;
private EnclavePublicKeyProvider enclavePublicKeyProvider;
public TestPrivacyApiGroupJsonRpcMethods(
final BlockchainQueries blockchainQueries,
final ProtocolSchedule<?> protocolSchedule,
final TransactionPool transactionPool,
final PrivacyParameters privacyParameters,
final JsonRpcMethod rpcMethod) {
super(blockchainQueries, protocolSchedule, transactionPool, privacyParameters);
this.rpcMethod = rpcMethod;
}
@Override
protected Map<String, JsonRpcMethod> create(final PrivacyController privacyController) {
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
return mapOf(rpcMethod);
}
};
@Override
protected RpcApi getApiGroup() {
return RpcApis.PRIV;
}
}
}

@ -46,7 +46,6 @@ public class PrivacyController {
private static final Logger LOG = LogManager.getLogger();
private final Enclave enclave;
private final String enclavePublicKey;
private final PrivateStateStorage privateStateStorage;
private final WorldStateArchive privateWorldStateArchive;
private final PrivateTransactionValidator privateTransactionValidator;
@ -58,7 +57,6 @@ public class PrivacyController {
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
this(
privacyParameters.getEnclave(),
privacyParameters.getEnclavePublicKey(),
privacyParameters.getPrivateStateStorage(),
privacyParameters.getPrivateWorldStateArchive(),
new PrivateTransactionValidator(chainId),
@ -67,23 +65,22 @@ public class PrivacyController {
public PrivacyController(
final Enclave enclave,
final String enclavePublicKey,
final PrivateStateStorage privateStateStorage,
final WorldStateArchive privateWorldStateArchive,
final PrivateTransactionValidator privateTransactionValidator,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
this.enclave = enclave;
this.enclavePublicKey = enclavePublicKey;
this.privateStateStorage = privateStateStorage;
this.privateWorldStateArchive = privateWorldStateArchive;
this.privateTransactionValidator = privateTransactionValidator;
this.privateMarkerTransactionFactory = privateMarkerTransactionFactory;
}
public SendTransactionResponse sendTransaction(final PrivateTransaction privateTransaction) {
public SendTransactionResponse sendTransaction(
final PrivateTransaction privateTransaction, final String enclavePublicKey) {
try {
LOG.trace("Storing private transaction in enclave");
final SendResponse sendResponse = sendRequest(privateTransaction);
final SendResponse sendResponse = sendRequest(privateTransaction, enclavePublicKey);
final String enclaveKey = sendResponse.getKey();
if (privateTransaction.getPrivacyGroupId().isPresent()) {
final String privacyGroupId = privateTransaction.getPrivacyGroupId().get().toBase64String();
@ -99,20 +96,25 @@ public class PrivacyController {
}
}
public ReceiveResponse retrieveTransaction(final String enclaveKey) {
public ReceiveResponse retrieveTransaction(
final String enclaveKey, final String enclavePublicKey) {
return enclave.receive(enclaveKey, enclavePublicKey);
}
public PrivacyGroup createPrivacyGroup(
final List<String> addresses, final String name, final String description) {
final List<String> addresses,
final String name,
final String description,
final String enclavePublicKey) {
return enclave.createPrivacyGroup(addresses, enclavePublicKey, name, description);
}
public String deletePrivacyGroup(final String privacyGroupId) {
public String deletePrivacyGroup(final String privacyGroupId, final String enclavePublicKey) {
return enclave.deletePrivacyGroup(privacyGroupId, enclavePublicKey);
}
public PrivacyGroup[] findPrivacyGroup(final List<String> addresses) {
public PrivacyGroup[] findPrivacyGroup(
final List<String> addresses, final String enclavePublicKey) {
return enclave.findPrivacyGroup(addresses);
}
@ -122,13 +124,19 @@ public class PrivacyController {
}
public ValidationResult<TransactionValidator.TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final String privacyGroupId) {
final PrivateTransaction privateTransaction,
final String privacyGroupId,
final String enclavePublicKey) {
return privateTransactionValidator.validate(
privateTransaction, determineNonce(privateTransaction.getSender(), privacyGroupId));
privateTransaction,
determineNonce(privateTransaction.getSender(), privacyGroupId, enclavePublicKey));
}
public long determineNonce(
final String privateFrom, final String[] privateFor, final Address address) {
final String privateFrom,
final String[] privateFor,
final Address address,
final String enclavePublicKey) {
final List<String> groupMembers = Lists.asList(privateFrom, privateFor);
final List<PrivacyGroup> matchingGroups =
@ -150,10 +158,11 @@ public class PrivacyController {
final String privacyGroupId = legacyGroups.get(0).getPrivacyGroupId();
return determineNonce(address, privacyGroupId);
return determineNonce(address, privacyGroupId, enclavePublicKey);
}
public long determineNonce(final Address sender, final String privacyGroupId) {
public long determineNonce(
final Address sender, final String privacyGroupId, final String enclavePublicKey) {
return privateStateStorage
.getLatestStateRoot(Bytes.fromBase64String(privacyGroupId))
.map(
@ -177,7 +186,8 @@ public class PrivacyController {
Account.DEFAULT_NONCE);
}
private SendResponse sendRequest(final PrivateTransaction privateTransaction) {
private SendResponse sendRequest(
final PrivateTransaction privateTransaction, final String enclavePublicKey) {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
privateTransaction.writeTo(rlpOutput);
final String payload = rlpOutput.encoded().toBase64String();

@ -24,6 +24,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
@ -71,10 +72,12 @@ public class PrivacyControllerTest {
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private static final byte[] PAYLOAD = new byte[0];
private static final String PRIVACY_GROUP_ID = "pg_id";
private static final List<String> PRIVACY_GROUP_ADDRESSES = newArrayList("8f2a", "fb23");
private static final String PRIVACY_GROUP_NAME = "pg_name";
private static final String PRIVACY_GROUP_DESCRIPTION = "pg_desc";
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final String ENCLAVE_KEY2 = "Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=";
private static final String PRIVACY_GROUP_ID = "DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=";
private PrivacyController privacyController;
private PrivacyController brokenPrivacyController;
@ -140,7 +143,6 @@ public class PrivacyControllerTest {
privacyController =
new PrivacyController(
enclave,
enclavePublicKey,
privateStateStorage,
worldStateArchive,
privateTransactionValidator,
@ -149,7 +151,6 @@ public class PrivacyControllerTest {
brokenPrivacyController =
new PrivacyController(
brokenMockEnclave(),
enclavePublicKey,
privateStateStorage,
worldStateArchive,
privateTransactionValidator,
@ -163,11 +164,11 @@ public class PrivacyControllerTest {
final PrivateTransaction transaction = buildLegacyPrivateTransaction(1);
final SendTransactionResponse sendTransactionResponse =
privacyController.sendTransaction(transaction);
privacyController.sendTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(
transaction, sendTransactionResponse.getPrivacyGroupId());
transaction, sendTransactionResponse.getPrivacyGroupId(), ENCLAVE_PUBLIC_KEY);
final Transaction markerTransaction =
privacyController.createPrivacyMarkerTransaction(
@ -179,6 +180,8 @@ public class PrivacyControllerTest {
assertThat(markerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
assertThat(markerTransaction.getSender()).isEqualTo(PUBLIC_TRANSACTION.getSender());
assertThat(markerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
verify(enclave)
.send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(List.of(ENCLAVE_PUBLIC_KEY, ENCLAVE_KEY2)));
}
@Test
@ -187,11 +190,11 @@ public class PrivacyControllerTest {
final PrivateTransaction transaction = buildBesuPrivateTransaction(1);
final SendTransactionResponse sendTransactionResponse =
privacyController.sendTransaction(transaction);
privacyController.sendTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(
transaction, transaction.getPrivacyGroupId().get().toString());
transaction, transaction.getPrivacyGroupId().get().toString(), ENCLAVE_PUBLIC_KEY);
final Transaction markerTransaction =
privacyController.createPrivacyMarkerTransaction(
@ -203,12 +206,16 @@ public class PrivacyControllerTest {
assertThat(markerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
assertThat(markerTransaction.getSender()).isEqualTo(PUBLIC_TRANSACTION.getSender());
assertThat(markerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
verify(enclave).send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(PRIVACY_GROUP_ID));
}
@Test
public void sendTransactionWhenEnclaveFailsThrowsEnclaveError() {
assertThatExceptionOfType(EnclaveServerException.class)
.isThrownBy(() -> brokenPrivacyController.sendTransaction(buildLegacyPrivateTransaction()));
.isThrownBy(
() ->
brokenPrivacyController.sendTransaction(
buildLegacyPrivateTransaction(), ENCLAVE_PUBLIC_KEY));
}
@Test
@ -218,10 +225,10 @@ public class PrivacyControllerTest {
final PrivateTransaction transaction = buildLegacyPrivateTransaction(0);
final SendTransactionResponse sendTransactionResponse =
privacyController.sendTransaction(transaction);
privacyController.sendTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(
transaction, sendTransactionResponse.getPrivacyGroupId());
transaction, sendTransactionResponse.getPrivacyGroupId(), ENCLAVE_PUBLIC_KEY);
assertThat(validationResult).isEqualTo(ValidationResult.invalid(PRIVATE_NONCE_TOO_LOW));
}
@ -233,10 +240,10 @@ public class PrivacyControllerTest {
final PrivateTransaction transaction = buildLegacyPrivateTransaction(2);
final SendTransactionResponse sendTransactionResponse =
privacyController.sendTransaction(transaction);
privacyController.sendTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(
transaction, sendTransactionResponse.getPrivacyGroupId());
transaction, sendTransactionResponse.getPrivacyGroupId(), ENCLAVE_PUBLIC_KEY);
assertThat(validationResult).isEqualTo(ValidationResult.invalid(INCORRECT_PRIVATE_NONCE));
}
@ -245,7 +252,8 @@ public class PrivacyControllerTest {
when(enclave.receive(anyString(), anyString()))
.thenReturn(new ReceiveResponse(PAYLOAD, PRIVACY_GROUP_ID));
final ReceiveResponse receiveResponse = privacyController.retrieveTransaction(TRANSACTION_KEY);
final ReceiveResponse receiveResponse =
privacyController.retrieveTransaction(TRANSACTION_KEY, ENCLAVE_PUBLIC_KEY);
assertThat(receiveResponse.getPayload()).isEqualTo(PAYLOAD);
assertThat(receiveResponse.getPrivacyGroupId()).isEqualTo(PRIVACY_GROUP_ID);
@ -266,7 +274,10 @@ public class PrivacyControllerTest {
final PrivacyGroup privacyGroup =
privacyController.createPrivacyGroup(
PRIVACY_GROUP_ADDRESSES, PRIVACY_GROUP_NAME, PRIVACY_GROUP_DESCRIPTION);
PRIVACY_GROUP_ADDRESSES,
PRIVACY_GROUP_NAME,
PRIVACY_GROUP_DESCRIPTION,
ENCLAVE_PUBLIC_KEY);
assertThat(privacyGroup).isEqualToComparingFieldByField(enclavePrivacyGroupResponse);
verify(enclave)
@ -281,7 +292,8 @@ public class PrivacyControllerTest {
public void deletesPrivacyGroup() {
when(enclave.deletePrivacyGroup(anyString(), anyString())).thenReturn(PRIVACY_GROUP_ID);
final String deletedPrivacyGroupId = privacyController.deletePrivacyGroup(PRIVACY_GROUP_ID);
final String deletedPrivacyGroupId =
privacyController.deletePrivacyGroup(PRIVACY_GROUP_ID, ENCLAVE_PUBLIC_KEY);
assertThat(deletedPrivacyGroupId).isEqualTo(PRIVACY_GROUP_ID);
verify(enclave).deletePrivacyGroup(PRIVACY_GROUP_ID, enclavePublicKey);
@ -299,7 +311,7 @@ public class PrivacyControllerTest {
when(enclave.findPrivacyGroup(any())).thenReturn(new PrivacyGroup[] {privacyGroup});
final PrivacyGroup[] privacyGroups =
privacyController.findPrivacyGroup(PRIVACY_GROUP_ADDRESSES);
privacyController.findPrivacyGroup(PRIVACY_GROUP_ADDRESSES, ENCLAVE_PUBLIC_KEY);
assertThat(privacyGroups).hasSize(1);
assertThat(privacyGroups[0]).isEqualToComparingFieldByField(privacyGroup);
verify(enclave).findPrivacyGroup(PRIVACY_GROUP_ADDRESSES);
@ -318,7 +330,8 @@ public class PrivacyControllerTest {
when(account.getNonce()).thenReturn(8L);
final long nonce =
privacyController.determineNonce("privateFrom", new String[] {"first", "second"}, address);
privacyController.determineNonce(
"privateFrom", new String[] {"first", "second"}, address, ENCLAVE_PUBLIC_KEY);
assertThat(nonce).isEqualTo(reportedNonce);
verify(enclave)
@ -335,7 +348,8 @@ public class PrivacyControllerTest {
when(enclave.findPrivacyGroup(any())).thenReturn(returnedGroups);
final long nonce =
privacyController.determineNonce("privateFrom", new String[] {"first", "second"}, address);
privacyController.determineNonce(
"privateFrom", new String[] {"first", "second"}, address, ENCLAVE_PUBLIC_KEY);
assertThat(nonce).isEqualTo(reportedNonce);
verify(enclave)
@ -358,7 +372,7 @@ public class PrivacyControllerTest {
.isThrownBy(
() ->
privacyController.determineNonce(
"privateFrom", new String[] {"first", "second"}, address));
"privateFrom", new String[] {"first", "second"}, address, ENCLAVE_PUBLIC_KEY));
}
@Test
@ -367,7 +381,7 @@ public class PrivacyControllerTest {
when(account.getNonce()).thenReturn(4L);
final long nonce = privacyController.determineNonce(address, "Group1");
final long nonce = privacyController.determineNonce(address, "Group1", ENCLAVE_PUBLIC_KEY);
assertThat(nonce).isEqualTo(4L);
verify(privateStateStorage).getLatestStateRoot(Base64.decode("Group1"));
@ -382,7 +396,7 @@ public class PrivacyControllerTest {
when(privateStateStorage.getLatestStateRoot(Base64.decode("Group1")))
.thenReturn(Optional.empty());
final long nonce = privacyController.determineNonce(address, "Group1");
final long nonce = privacyController.determineNonce(address, "Group1", ENCLAVE_PUBLIC_KEY);
assertThat(nonce).isEqualTo(Account.DEFAULT_NONCE);
verifyNoInteractions(worldStateArchive, mutableWorldState, account);
@ -396,7 +410,7 @@ public class PrivacyControllerTest {
.thenReturn(Optional.of(hash));
when(worldStateArchive.getMutable(hash)).thenReturn(Optional.empty());
final long nonce = privacyController.determineNonce(address, "Group1");
final long nonce = privacyController.determineNonce(address, "Group1", ENCLAVE_PUBLIC_KEY);
assertThat(nonce).isEqualTo(Account.DEFAULT_NONCE);
verifyNoInteractions(mutableWorldState, account);
@ -411,7 +425,7 @@ public class PrivacyControllerTest {
when(worldStateArchive.getMutable(hash)).thenReturn(Optional.of(mutableWorldState));
when(mutableWorldState.get(address)).thenReturn(null);
final long nonce = privacyController.determineNonce(address, "Group1");
final long nonce = privacyController.determineNonce(address, "Group1", ENCLAVE_PUBLIC_KEY);
assertThat(nonce).isEqualTo(Account.DEFAULT_NONCE);
verifyNoInteractions(account);
@ -423,19 +437,16 @@ public class PrivacyControllerTest {
private static PrivateTransaction buildLegacyPrivateTransaction(final long nonce) {
return buildPrivateTransaction(nonce)
.privateFrom(Base64.decode("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privateFor(
newArrayList(
Base64.decode("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="),
Base64.decode("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=")))
.privateFrom(Base64.decode(ENCLAVE_PUBLIC_KEY))
.privateFor(newArrayList(Base64.decode(ENCLAVE_PUBLIC_KEY), Base64.decode(ENCLAVE_KEY2)))
.signAndBuild(KEY_PAIR);
}
private static PrivateTransaction buildBesuPrivateTransaction(final long nonce) {
return buildPrivateTransaction(nonce)
.privateFrom(Base64.decode("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privacyGroupId(Base64.decode("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w="))
.privateFrom(Base64.decode(ENCLAVE_PUBLIC_KEY))
.privacyGroupId(Base64.decode(PRIVACY_GROUP_ID))
.signAndBuild(KEY_PAIR);
}

Loading…
Cancel
Save