Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods;

import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcRequestException;
Expand Down Expand Up @@ -74,7 +76,8 @@ public JsonRpcResponse validateAndExecute(
final String privacyGroupId,
final Supplier<JsonRpcResponse> successfulJsonRpcResponse) {
return privacyController
.validatePrivateTransaction(privateTransaction, privacyGroupId)
.validatePrivateTransaction(
privateTransaction, privacyGroupId, enclavePublicKey(request.getUser()))
.either(
successfulJsonRpcResponse,
(errorReason) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea;

import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
Expand Down Expand Up @@ -59,7 +61,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {

final SendTransactionResponse sendTransactionResponse;
try {
sendTransactionResponse = privacyController.sendTransaction(privateTransaction);
sendTransactionResponse =
privacyController.sendTransaction(
privateTransaction, enclavePublicKey(requestContext.getUser()));
} catch (final Exception e) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter;
Expand Down Expand Up @@ -59,7 +60,10 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
try {
response =
privacyController.createPrivacyGroup(
parameter.getAddresses(), parameter.getName(), parameter.getDescription());
parameter.getAddresses(),
parameter.getName(),
parameter.getDescription(),
enclavePublicKey(requestContext.getUser()));
} catch (Exception e) {
LOG.error("Failed to create privacy group", e);
return new JsonRpcErrorResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

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.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;
Expand Down Expand Up @@ -48,10 +50,12 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {

final String response;
try {
response = privacyController.deletePrivacyGroup(privacyGroupId);
response =
privacyController.deletePrivacyGroup(
privacyGroupId, enclavePublicKey(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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

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;
Expand Down Expand Up @@ -57,7 +59,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {

final SendTransactionResponse sendTransactionResponse;
try {
sendTransactionResponse = privacyController.sendTransaction(privateTransaction);
sendTransactionResponse =
privacyController.sendTransaction(
privateTransaction, enclavePublicKey(requestContext.getUser()));
} catch (final Exception e) {
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
Expand Down Expand Up @@ -54,7 +55,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {

PrivacyGroup[] response;
try {
response = privacyController.findPrivacyGroup(Arrays.asList(addresses));
response =
privacyController.findPrivacyGroup(
Arrays.asList(addresses), enclavePublicKey(requestContext.getUser()));
} catch (Exception e) {
LOG.error("Failed to fetch privacy group", e);
return new JsonRpcErrorResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
Expand Down Expand Up @@ -56,7 +57,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
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, enclavePublicKey(requestContext.getUser()));
return new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), Quantity.create(nonce));
} catch (final Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
Expand Down Expand Up @@ -68,7 +69,8 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
LOG.trace("Fetching transaction information");
final ReceiveResponse receiveResponse =
privacyController.retrieveTransaction(
resultTransaction.getTransaction().getPayloadBytes().toBase64String());
resultTransaction.getTransaction().getPayloadBytes().toBase64String(),
enclavePublicKey(requestContext.getUser()));
LOG.trace("Received transaction information");

final BytesValueRLPInput input =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;

import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

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;
Expand Down Expand Up @@ -48,7 +50,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
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, enclavePublicKey(requestContext.getUser()));
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), Quantity.create(nonce));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiTenancyUserUtil.enclavePublicKey;

import org.hyperledger.besu.enclave.EnclaveClientException;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
Expand Down Expand Up @@ -92,7 +93,9 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final String privacyGroupId;
try {
final ReceiveResponse receiveResponse =
privacyController.retrieveTransaction(transaction.getPayloadBytes().toBase64String());
privacyController.retrieveTransaction(
transaction.getPayloadBytes().toBase64String(),
enclavePublicKey(requestContext.getUser()));
LOG.trace("Received transaction information");

final BytesValueRLPInput input =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;

import java.util.Optional;

import org.junit.Before;
import org.junit.Test;

Expand Down Expand Up @@ -56,7 +58,7 @@ public void validRequestProducesExpectedNonce() {
final long reportedNonce = 8L;
final PrivGetEeaTransactionCount method = new PrivGetEeaTransactionCount(privacyController);

when(privacyController.determineNonce(privateFrom, privateFor, address))
when(privacyController.determineNonce(privateFrom, privateFor, address, Optional.empty()))
.thenReturn(reportedNonce);

final JsonRpcResponse response = method.response(request);
Expand All @@ -71,7 +73,7 @@ public void validRequestProducesExpectedNonce() {
public void nonceProviderThrowsRuntimeExceptionProducesErrorResponse() {
final PrivGetEeaTransactionCount method = new PrivGetEeaTransactionCount(privacyController);

when(privacyController.determineNonce(privateFrom, privateFor, address))
when(privacyController.determineNonce(privateFrom, privateFor, address, Optional.empty()))
.thenThrow(RuntimeException.class);

final JsonRpcResponse response = method.response(request);
Expand All @@ -86,7 +88,7 @@ public void nonceProviderThrowsRuntimeExceptionProducesErrorResponse() {
public void nonceProviderThrowsAnExceptionProducesErrorResponse() {
final PrivGetEeaTransactionCount method = new PrivGetEeaTransactionCount(privacyController);

when(privacyController.determineNonce(privateFrom, privateFor, address))
when(privacyController.determineNonce(privateFrom, privateFor, address, Optional.empty()))
.thenThrow(RuntimeException.class);

final JsonRpcResponse response = method.response(request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

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;
Expand All @@ -42,6 +43,9 @@
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;
Expand Down Expand Up @@ -106,9 +110,12 @@ 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), "");

@Mock private TransactionPool transactionPool;

Expand Down Expand Up @@ -195,10 +202,10 @@ public void valueNonZeroTransaction() {

@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)))
Expand All @@ -208,7 +215,8 @@ public void validTransactionIsSentToTransactionPool() {
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(
Expand All @@ -218,20 +226,22 @@ public void validTransactionIsSentToTransactionPool() {
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(Optional.of(ENCLAVE_PUBLIC_KEY)));
verify(privacyController)
.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class), eq(Optional.of(ENCLAVE_PUBLIC_KEY)));
verify(privacyController)
.createPrivacyMarkerTransaction(any(String.class), any(PrivateTransaction.class));
verify(transactionPool).addLocalTransaction(any(Transaction.class));
}

@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)))
Expand All @@ -254,9 +264,9 @@ public void validTransactionPrivacyGroupIsSentToTransactionPool() {
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));
Expand All @@ -282,7 +292,7 @@ public void invalidTransactionWithoutPrivateFromFieldFailsWithDecodeError() {

@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 =
Expand Down Expand Up @@ -346,10 +356,10 @@ public void transactionWithNotWhitelistedSenderAccountIsRejected() {
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)))
Expand All @@ -367,9 +377,9 @@ private void verifyErrorForInvalidTransaction(
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));
Expand Down