From 51287459ab1b766754d7fca8b174ac9a78e13e8e Mon Sep 17 00:00:00 2001 From: Antony Denyer Date: Wed, 9 Jun 2021 12:13:03 +0100 Subject: [PATCH] refactor: EeaSendRawTransaction isolate send raw on/off chain (#2283) * refactor: isolate send raw on/off chain Signed-off-by: Antony Denyer * Move responsibility of checking restriction type into JsonRpcMethod Signed-off-by: Antony Denyer * Refactor: Make use of privacy vs private consistent Rename s/privacyMarkerTransaction/privateMarkerTransaction/g Signed-off-by: Antony Denyer --- ...GetAllPrivateMarkerTransactionHashes.java} | 2 +- .../org/hyperledger/besu/cli/BesuCommand.java | 6 +- .../hyperledger/besu/PrivacyReorgTest.java | 4 +- .../hyperledger/besu/cli/BesuCommandTest.java | 2 +- ...vGetPrivateTransactionIntegrationTest.java | 4 +- ...ava => AbstractEeaSendRawTransaction.java} | 90 ++---- ...strictedOffChainEeaSendRawTransaction.java | 85 ++++++ ...strictedOnChainEeaSendRawTransaction.java} | 80 ++--- .../jsonrpc/methods/EeaJsonRpcMethods.java | 8 +- .../ethereum/api/query/PrivacyQueries.java | 4 +- .../eea/BaseEeaSendRawTransaction.java | 146 +++++++++ .../eea/EeaSendRawTransactionTest.java | 288 ++---------------- .../eea/OnChainEeaSendRawTransactionTest.java | 140 --------- ...ctedOffChainEeaSendRawTransactionTest.java | 132 ++++++++ ...ictedOnChainEeaSendRawTransactionTest.java | 175 +++++++++++ .../priv/PrivGetPrivateTransactionTest.java | 2 +- .../priv/PrivGetTransactionReceiptTest.java | 8 +- .../api/query/PrivacyQueriesTest.java | 4 +- .../mainnet/PrivacyBlockProcessor.java | 8 +- .../privacy/DefaultPrivacyController.java | 6 +- .../MultiTenancyPrivacyController.java | 9 +- .../ethereum/privacy/PrivacyController.java | 4 +- .../privacy/PrivateStateRehydration.java | 6 +- .../privacy/PrivateTransactionLocator.java | 6 +- .../privacy/PrivateTransactionValidator.java | 5 - .../storage/PrivateTransactionMetadata.java | 16 +- .../migration/PrivateStorageMigration.java | 4 +- .../core/PrivateTransactionDataFixture.java | 14 +- .../mainnet/PrivacyBlockProcessorTest.java | 6 +- .../privacy/DefaultPrivacyControllerTest.java | 22 +- .../PrivateTransactionLocatorTest.java | 12 +- .../PrivateTransactionValidatorTest.java | 31 -- .../PrivateStorageMigrationTest.java | 26 +- 33 files changed, 715 insertions(+), 640 deletions(-) rename acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/{GetAllPrivacyMarkerTransactionHashes.java => GetAllPrivateMarkerTransactionHashes.java} (97%) rename ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/{EeaSendRawTransaction.java => AbstractEeaSendRawTransaction.java} (53%) create mode 100644 ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransaction.java rename ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/{OnChainEeaSendRawTransaction.java => RestrictedOnChainEeaSendRawTransaction.java} (57%) create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java delete mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransactionTest.java create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransactionTest.java create mode 100644 ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransactionTest.java diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java similarity index 97% rename from acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java rename to acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java index ef7e8d9544..bf30cfaa68 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivacyMarkerTransactionHashes.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java @@ -27,7 +27,7 @@ import org.web3j.protocol.besu.Besu; import org.web3j.protocol.core.DefaultBlockParameter; import org.web3j.protocol.core.methods.response.EthBlock; -public class GetAllPrivacyMarkerTransactionHashes implements Transaction> { +public class GetAllPrivateMarkerTransactionHashes implements Transaction> { @Override public List execute(final NodeRequests node) { final Besu besu = node.privacy().getBesuClient(); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 505f4cb6b0..cac2d092e1 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -954,7 +954,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { names = {"--privacy-marker-transaction-signing-key-file"}, description = "The name of a file containing the private key used to sign privacy marker transactions. If unset, each will be signed with a random key.") - private final Path privacyMarkerTransactionSigningKeyPath = null; + private final Path privateMarkerTransactionSigningKeyPath = null; @Option( names = {"--privacy-enable-database-migration"}, @@ -2130,7 +2130,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0) { // if gas is required, cannot use random keys to sign private tx // ie --privacy-marker-transaction-signing-key-file must be set - if (privacyMarkerTransactionSigningKeyPath == null) { + if (privateMarkerTransactionSigningKeyPath == null) { throw new ParameterException( commandLine, "Not a free gas network. --privacy-marker-transaction-signing-key-file must be specified and must be a funded account. Private transactions cannot be signed by random (non-funded) accounts in paid gas networks"); @@ -2142,7 +2142,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { "--privacy-precompiled-address option is deprecated. This address is derived, based on --privacy-onchain-groups-enabled."); } - privacyParametersBuilder.setPrivateKeyPath(privacyMarkerTransactionSigningKeyPath); + privacyParametersBuilder.setPrivateKeyPath(privateMarkerTransactionSigningKeyPath); privacyParametersBuilder.setStorageProvider( privacyKeyStorageProvider(keyValueStorageName + "-privacy")); if (isPrivacyTlsEnabled) { diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java index 121f03fc5d..f8e557d776 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java @@ -198,13 +198,13 @@ public class PrivacyReorgTest { final DefaultBlockchain blockchain = (DefaultBlockchain) protocolContext.getBlockchain(); final PrivateStateStorage privateStateStorage = privacyParameters.getPrivateStateStorage(); - final Transaction privacyMarkerTransaction = + final Transaction privateMarkerTransaction = buildMarkerTransaction(getEnclaveKey(enclave.clientUrl())); final Block firstBlock = gen.block( getBlockOptionsWithTransaction( blockchain.getGenesisBlock(), - privacyMarkerTransaction, + privateMarkerTransaction, FIRST_BLOCK_WITH_SINGLE_TRANSACTION_STATE_ROOT)); appendBlock(besuController, blockchain, protocolContext, firstBlock); diff --git a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java index 835d05d4ea..848bac93a7 100644 --- a/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java +++ b/besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java @@ -3484,7 +3484,7 @@ public class BesuCommandTest extends CommandTestAbstract { } @Test - public void privacyMarkerTransactionSigningKeyFileRequiredIfMinGasPriceNonZero() { + public void privateMarkerTransactionSigningKeyFileRequiredIfMinGasPriceNonZero() { parseCommand("--privacy-enabled", "--privacy-public-key-file", ENCLAVE_PUBLIC_KEY_PATH); assertThat(commandErrorOutput.toString()) diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java index 7fa492cfd8..e9cb893368 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java @@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods; import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; -import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privacyMarkerTransaction; +import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateMarkerTransaction; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -152,7 +152,7 @@ public class PrivGetPrivateTransactionIntegrationTest { new PrivGetPrivateTransaction(privacyController, enclavePublicKeyProvider); final Hash blockHash = Hash.ZERO; - final Transaction pmt = spy(privacyMarkerTransaction()); + final Transaction pmt = spy(privateMarkerTransaction()); when(blockchain.getTransactionByHash(eq(pmt.getHash()))).thenReturn(Optional.of(pmt)); when(blockchain.getTransactionLocation(eq(pmt.getHash()))) .thenReturn(Optional.of(new TransactionLocation(blockHash, 0))); diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java similarity index 53% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransaction.java rename to ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java index 6dc8172433..1d4deb21a1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java @@ -18,23 +18,17 @@ import static org.apache.logging.log4j.LogManager.getLogger; import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcEnclaveErrorConverter.convertEnclaveInvalidReason; import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter.convertTransactionInvalidReason; import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.DECODE_ERROR; -import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY; -import static org.hyperledger.besu.ethereum.privacy.PrivacyGroupUtil.findOffchainPrivacyGroup; -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; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; -import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; -import org.hyperledger.besu.ethereum.privacy.PrivacyController; import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLPException; @@ -42,23 +36,16 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import java.util.Optional; +import io.vertx.ext.auth.User; import org.apache.logging.log4j.Logger; import org.apache.tuweni.bytes.Bytes; -public class EeaSendRawTransaction implements JsonRpcMethod { - +public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod { private static final Logger LOG = getLogger(); - final TransactionPool transactionPool; - final PrivacyController privacyController; - private final EnclavePublicKeyProvider enclavePublicKeyProvider; - - public EeaSendRawTransaction( - final TransactionPool transactionPool, - final PrivacyController privacyController, - final EnclavePublicKeyProvider enclavePublicKeyProvider) { + private final TransactionPool transactionPool; + + protected AbstractEeaSendRawTransaction(final TransactionPool transactionPool) { this.transactionPool = transactionPool; - this.privacyController = privacyController; - this.enclavePublicKeyProvider = enclavePublicKeyProvider; } @Override @@ -75,36 +62,22 @@ public class EeaSendRawTransaction implements JsonRpcMethod { final PrivateTransaction privateTransaction = PrivateTransaction.readFrom(RLP.input(Bytes.fromHexString(rawPrivateTransaction))); - final String enclavePublicKey = - enclavePublicKeyProvider.getEnclaveKey(requestContext.getUser()); - - if (!privateTransaction.getPrivateFrom().equals(Bytes.fromBase64String(enclavePublicKey))) { - return new JsonRpcErrorResponse(id, PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY); - } - - final Optional maybePrivacyGroupId = privateTransaction.getPrivacyGroupId(); - - final Optional maybePrivacyGroup = - findPrivacyGroup( - privacyController, maybePrivacyGroupId, enclavePublicKey, privateTransaction); - final ValidationResult validationResult = - privacyController.validatePrivateTransaction(privateTransaction, enclavePublicKey); + validatePrivateTransaction(privateTransaction, requestContext.getUser()); if (!validationResult.isValid()) { return new JsonRpcErrorResponse( id, convertTransactionInvalidReason(validationResult.getInvalidReason())); } - final JsonRpcResponse ret = - createPMTAndAddToTxPool( - id, - privateTransaction, - maybePrivacyGroup, - maybePrivacyGroupId, - enclavePublicKey, - Address.DEFAULT_PRIVACY); - return ret; + final Transaction privateMarkerTransaction = + createPrivateMarkerTransaction(privateTransaction, requestContext.getUser()); + + return transactionPool + .addLocalTransaction(privateMarkerTransaction) + .either( + () -> new JsonRpcSuccessResponse(id, privateMarkerTransaction.getHash().toString()), + errorReason -> getJsonRpcErrorResponse(id, errorReason)); } catch (final JsonRpcErrorResponseException e) { return new JsonRpcErrorResponse(id, e.getJsonRpcError()); @@ -116,35 +89,6 @@ public class EeaSendRawTransaction implements JsonRpcMethod { } } - Optional findPrivacyGroup( - final PrivacyController privacyController, - final Optional maybePrivacyGroupId, - final String enclavePublicKey, - final PrivateTransaction privateTransaction) { - final Optional maybePrivacyGroup = - findOffchainPrivacyGroup(privacyController, maybePrivacyGroupId, enclavePublicKey); - return maybePrivacyGroup; - } - - JsonRpcResponse createPMTAndAddToTxPool( - final Object id, - final PrivateTransaction privateTransaction, - final Optional maybePrivacyGroup, - final Optional maybePrivacyGroupId, - final String enclavePublicKey, - final Address privacyPrecompileAddress) { - final String privateTransactionLookupId = - privacyController.sendTransaction(privateTransaction, enclavePublicKey, maybePrivacyGroup); - final Transaction privacyMarkerTransaction = - privacyController.createPrivacyMarkerTransaction( - privateTransactionLookupId, privateTransaction, privacyPrecompileAddress); - return transactionPool - .addLocalTransaction(privacyMarkerTransaction) - .either( - () -> new JsonRpcSuccessResponse(id, privacyMarkerTransaction.getHash().toString()), - errorReason -> getJsonRpcErrorResponse(id, errorReason)); - } - JsonRpcErrorResponse getJsonRpcErrorResponse( final Object id, final TransactionInvalidReason errorReason) { if (errorReason.equals(TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT)) { @@ -152,4 +96,10 @@ public class EeaSendRawTransaction implements JsonRpcMethod { } return new JsonRpcErrorResponse(id, convertTransactionInvalidReason(errorReason)); } + + protected abstract ValidationResult validatePrivateTransaction( + final PrivateTransaction privateTransaction, final Optional user); + + protected abstract Transaction createPrivateMarkerTransaction( + final PrivateTransaction privateTransaction, final Optional user); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransaction.java new file mode 100644 index 0000000000..ab0b79fda2 --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransaction.java @@ -0,0 +1,85 @@ +/* + * 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.eea; + +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY; +import static org.hyperledger.besu.ethereum.privacy.PrivacyGroupUtil.findOffchainPrivacyGroup; + +import org.hyperledger.besu.enclave.types.PrivacyGroup; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider; +import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; +import org.hyperledger.besu.ethereum.privacy.PrivacyController; +import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; +import org.hyperledger.besu.ethereum.privacy.Restriction; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; + +import java.util.Optional; + +import io.vertx.ext.auth.User; +import org.apache.tuweni.bytes.Bytes; + +public class RestrictedOffChainEeaSendRawTransaction extends AbstractEeaSendRawTransaction { + + final PrivacyController privacyController; + private final EnclavePublicKeyProvider enclavePublicKeyProvider; + + public RestrictedOffChainEeaSendRawTransaction( + final TransactionPool transactionPool, + final PrivacyController privacyController, + final EnclavePublicKeyProvider enclavePublicKeyProvider) { + super(transactionPool); + this.privacyController = privacyController; + this.enclavePublicKeyProvider = enclavePublicKeyProvider; + } + + @Override + protected ValidationResult validatePrivateTransaction( + final PrivateTransaction privateTransaction, final Optional user) { + + if (!privateTransaction.getRestriction().equals(Restriction.RESTRICTED)) { + return ValidationResult.invalid( + TransactionInvalidReason.PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE); + } + + final String enclavePublicKey = enclavePublicKeyProvider.getEnclaveKey(user); + + if (!privateTransaction.getPrivateFrom().equals(Bytes.fromBase64String(enclavePublicKey))) { + throw new JsonRpcErrorResponseException(PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY); + } + + return privacyController.validatePrivateTransaction( + privateTransaction, enclavePublicKeyProvider.getEnclaveKey(user)); + } + + @Override + protected Transaction createPrivateMarkerTransaction( + final PrivateTransaction privateTransaction, final Optional user) { + + final Optional maybePrivacyGroup = + findOffchainPrivacyGroup( + privacyController, + privateTransaction.getPrivacyGroupId(), + enclavePublicKeyProvider.getEnclaveKey(user)); + + final String privateTransactionLookupId = + privacyController.sendTransaction( + privateTransaction, enclavePublicKeyProvider.getEnclaveKey(user), maybePrivacyGroup); + return privacyController.createPrivateMarkerTransaction( + privateTransactionLookupId, privateTransaction, Address.DEFAULT_PRIVACY); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransaction.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransaction.java similarity index 57% rename from ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransaction.java rename to ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransaction.java index d7a366047b..e8de6cf4e1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransaction.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransaction.java @@ -17,78 +17,80 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea; import static org.hyperledger.besu.ethereum.privacy.PrivacyGroupUtil.findOnchainPrivacyGroup; import org.hyperledger.besu.enclave.types.PrivacyGroup; -import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; 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; import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.privacy.PrivacyController; import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; +import org.hyperledger.besu.ethereum.privacy.Restriction; +import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; import java.util.Optional; +import io.vertx.ext.auth.User; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; -public class OnChainEeaSendRawTransaction extends EeaSendRawTransaction { +public class RestrictedOnChainEeaSendRawTransaction extends AbstractEeaSendRawTransaction { - public OnChainEeaSendRawTransaction( + private final PrivacyController privacyController; + private final EnclavePublicKeyProvider enclavePublicKeyProvider; + + public RestrictedOnChainEeaSendRawTransaction( final TransactionPool transactionPool, final PrivacyController privacyController, final EnclavePublicKeyProvider enclavePublicKeyProvider) { - super(transactionPool, privacyController, enclavePublicKeyProvider); + super(transactionPool); + this.privacyController = privacyController; + this.enclavePublicKeyProvider = enclavePublicKeyProvider; } @Override - public String getName() { - return RpcMethod.EEA_SEND_RAW_TRANSACTION.getMethodName(); + protected ValidationResult validatePrivateTransaction( + final PrivateTransaction privateTransaction, final Optional user) { + if (!privateTransaction.getRestriction().equals(Restriction.RESTRICTED)) { + return ValidationResult.invalid( + TransactionInvalidReason.PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE); + } + return privacyController.validatePrivateTransaction( + privateTransaction, enclavePublicKeyProvider.getEnclaveKey(user)); } @Override - Optional findPrivacyGroup( - final PrivacyController privacyController, - final Optional maybePrivacyGroupId, - final String enclavePublicKey, - final PrivateTransaction privateTransaction) { - if (maybePrivacyGroupId.isEmpty()) { + protected Transaction createPrivateMarkerTransaction( + final PrivateTransaction privateTransaction, final Optional user) { + if (privateTransaction.getPrivacyGroupId().isEmpty()) { throw new JsonRpcErrorResponseException(JsonRpcError.ONCHAIN_PRIVACY_GROUP_ID_NOT_AVAILABLE); } - final Optional maybePrivacyGroup = + + final String enclavePublicKey = enclavePublicKeyProvider.getEnclaveKey(user); + + final Optional privacyGroup = findOnchainPrivacyGroup( - privacyController, maybePrivacyGroupId, enclavePublicKey, privateTransaction); - if (maybePrivacyGroup.isEmpty()) { + privacyController, + privateTransaction.getPrivacyGroupId(), + enclavePublicKey, + privateTransaction); + + if (privacyGroup.isEmpty()) { throw new JsonRpcErrorResponseException(JsonRpcError.ONCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST); } - return maybePrivacyGroup; - } - @Override - JsonRpcResponse createPMTAndAddToTxPool( - final Object id, - final PrivateTransaction privateTransaction, - final Optional maybePrivacyGroup, - final Optional maybePrivacyGroupId, - final String enclavePublicKey, - final Address privacyPrecompiledAddress) { - final Bytes privacyGroupId = maybePrivacyGroupId.get(); + final Bytes privacyGroupId = privateTransaction.getPrivacyGroupId().get(); + final String privateTransactionLookupId = - privacyController.sendTransaction(privateTransaction, enclavePublicKey, maybePrivacyGroup); + privacyController.sendTransaction(privateTransaction, enclavePublicKey, privacyGroup); final Optional addPayloadPrivateTransactionLookupId = privacyController.buildAndSendAddPayload( privateTransaction, Bytes32.wrap(privacyGroupId), enclavePublicKey); - final Transaction privacyMarkerTransaction = - privacyController.createPrivacyMarkerTransaction( - buildCompoundLookupId(privateTransactionLookupId, addPayloadPrivateTransactionLookupId), - privateTransaction, - Address.ONCHAIN_PRIVACY); - return transactionPool - .addLocalTransaction(privacyMarkerTransaction) - .either( - () -> new JsonRpcSuccessResponse(id, privacyMarkerTransaction.getHash().toString()), - errorReason -> getJsonRpcErrorResponse(id, errorReason)); + + return privacyController.createPrivateMarkerTransaction( + buildCompoundLookupId(privateTransactionLookupId, addPayloadPrivateTransactionLookupId), + privateTransaction, + Address.ONCHAIN_PRIVACY); } private String buildCompoundLookupId( diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java index 18cd943a88..9fa70cd174 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java @@ -18,8 +18,8 @@ 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.eea.OnChainEeaSendRawTransaction; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.RestrictedOffChainEeaSendRawTransaction; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.RestrictedOnChainEeaSendRawTransaction; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetEeaTransactionCount; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.core.PrivacyParameters; @@ -45,12 +45,12 @@ public class EeaJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods { final EnclavePublicKeyProvider enclavePublicKeyProvider) { if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) { return mapOf( - new OnChainEeaSendRawTransaction( + new RestrictedOnChainEeaSendRawTransaction( getTransactionPool(), privacyController, enclavePublicKeyProvider), new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider)); } else { // off chain privacy return mapOf( - new EeaSendRawTransaction( + new RestrictedOffChainEeaSendRawTransaction( getTransactionPool(), privacyController, enclavePublicKeyProvider), new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider)); } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueries.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueries.java index 697e3efbfa..4dd6b64527 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueries.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueries.java @@ -70,7 +70,7 @@ public class PrivacyQueries { final List pmtHashList = privateTransactionMetadataList.stream() - .map(PrivateTransactionMetadata::getPrivacyMarkerTransactionHash) + .map(PrivateTransactionMetadata::getPrivateMarkerTransactionHash) .collect(Collectors.toList()); final List privateTransactionReceiptList = @@ -90,7 +90,7 @@ public class PrivacyQueries { privateTransactionReceiptList.get(i), blockNumber, blockHash, - privateTransactionMetadataList.get(i).getPrivacyMarkerTransactionHash(), + privateTransactionMetadataList.get(i).getPrivateMarkerTransactionHash(), findPMTIndex(pmtHashList.get(i)), removed)) .flatMap(Collection::stream) diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java new file mode 100644 index 0000000000..109e8343bf --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java @@ -0,0 +1,146 @@ +/* + * 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.eea; + +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.core.Address; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.core.Wei; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; +import org.hyperledger.besu.ethereum.privacy.PrivacyController; +import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; +import org.hyperledger.besu.ethereum.privacy.Restriction; +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; + +import java.math.BigInteger; +import java.util.List; +import java.util.Optional; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import org.apache.tuweni.bytes.Bytes; +import org.mockito.Mock; + +public class BaseEeaSendRawTransaction { + + final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + + final Transaction PUBLIC_TRANSACTION = + new Transaction( + 0L, + Wei.of(1), + 21000L, + Optional.of( + Address.wrap(Bytes.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"))), + Wei.ZERO, + SIGNATURE_ALGORITHM + .get() + .createSignature( + new BigInteger( + "32886959230931919120748662916110619501838190146643992583529828535682419954515"), + new BigInteger( + "14473701025599600909210599917245952381483216609124029382871721729679842002948"), + Byte.parseByte("0")), + Bytes.fromHexString("0x"), + Address.wrap(Bytes.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")), + Optional.empty()); + + final JsonRpcRequestContext validPrivateForTransactionRequest = + new JsonRpcRequestContext( + new JsonRpcRequest( + "2.0", "eea_sendRawTransaction", new String[] {validPrivateForTransaction()})); + + final JsonRpcRequestContext validPrivacyGroupTransactionRequest = + new JsonRpcRequestContext( + new JsonRpcRequest( + "2.0", + "eea_sendRawTransaction", + new String[] {validPrivatePrivacyGroupTransaction(Restriction.RESTRICTED)})); + + final JsonRpcRequestContext validUnrestrictedPrivacyGroupTransactionRequest = + new JsonRpcRequestContext( + new JsonRpcRequest( + "2.0", + "eea_sendRawTransaction", + new String[] {validPrivatePrivacyGroupTransaction(Restriction.UNRESTRICTED)})); + + final JsonRpcRequestContext validUnsuportedPrivacyGroupTransactionRequest = + new JsonRpcRequestContext( + new JsonRpcRequest( + "2.0", + "eea_sendRawTransaction", + new String[] {validPrivatePrivacyGroupTransaction(Restriction.UNSUPPORTED)})); + + @Mock TransactionPool transactionPool; + @Mock PrivacyController privacyController; + + private String validPrivateForTransaction() { + final PrivateTransaction.Builder privateTransactionBuilder = + PrivateTransaction.builder() + .nonce(0) + .gasPrice(Wei.of(1)) + .gasLimit(21000) + .value(Wei.ZERO) + .payload(Bytes.EMPTY) + .to(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87")) + .chainId(BigInteger.ONE) + .privateFrom(Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp=")) + .privateFor( + List.of( + Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp="), + Bytes.fromBase64String("QTFhVnRNeExDVUhtQlZIWG9aenpCZ1BiVy93ajVheER="))) + .restriction(Restriction.RESTRICTED); + return rlpEncodeTransaction(privateTransactionBuilder); + } + + private String validPrivatePrivacyGroupTransaction(final Restriction restriction) { + final PrivateTransaction.Builder privateTransactionBuilder = + PrivateTransaction.builder() + .nonce(0) + .gasPrice(Wei.of(1)) + .gasLimit(21000) + .value(Wei.ZERO) + .payload(Bytes.EMPTY) + .to(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87")) + .chainId(BigInteger.ONE) + .privateFrom(Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp=")) + .privacyGroupId(Bytes.fromBase64String("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=")) + .restriction(restriction); + return rlpEncodeTransaction(privateTransactionBuilder); + } + + private String rlpEncodeTransaction(final PrivateTransaction.Builder privateTransactionBuilder) { + final KeyPair keyPair = + SIGNATURE_ALGORITHM + .get() + .createKeyPair( + SIGNATURE_ALGORITHM + .get() + .createPrivateKey( + new BigInteger( + "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", + 16))); + + final PrivateTransaction privateTransaction = privateTransactionBuilder.signAndBuild(keyPair); + final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput(); + privateTransaction.writeTo(bvrlp); + return bvrlp.encoded().toHexString(); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java index d3349617cf..e9ccbeb0af 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java @@ -14,22 +14,16 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea; -import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.PRIVATE_TRANSACTION_FAILED; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; -import org.hyperledger.besu.crypto.KeyPair; -import org.hyperledger.besu.crypto.SignatureAlgorithm; -import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; -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; @@ -37,43 +31,18 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.Enclav 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.core.Address; -import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.core.Wei; -import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.mainnet.ValidationResult; import org.hyperledger.besu.ethereum.privacy.MultiTenancyValidationException; -import org.hyperledger.besu.ethereum.privacy.PrivacyController; import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; -import org.hyperledger.besu.ethereum.privacy.Restriction; -import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; -import java.math.BigInteger; -import java.util.List; -import java.util.Optional; - -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -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; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) -public class EeaSendRawTransactionTest { - - static final Supplier SIGNATURE_ALGORITHM = - Suppliers.memoize(SignatureAlgorithmFactory::getInstance); - static final String VALID_LEGACY_PRIVATE_TRANSACTION_RLP = validPrivateTransactionRlp(); - static final String VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP = - validPrivateTransactionRlpPrivacyGroup(); +public class EeaSendRawTransactionTest extends BaseEeaSendRawTransaction { // RLP encode fails creating a transaction without privateFrom so must be manually encoded private static final String PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP_NO_PRIVATE_FROM = @@ -84,39 +53,17 @@ public class EeaSendRawTransactionTest { + "885ff29e973e2576b6600181d1b0a2b5294e30d9be4a1981ff" + "b33a0b8c8a72657374726963746564"; - static final Transaction PUBLIC_TRANSACTION = - new Transaction( - 0L, - Wei.of(1), - 21000L, - Optional.of( - Address.wrap(Bytes.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"))), - Wei.ZERO, - SIGNATURE_ALGORITHM - .get() - .createSignature( - new BigInteger( - "32886959230931919120748662916110619501838190146643992583529828535682419954515"), - new BigInteger( - "14473701025599600909210599917245952381483216609124029382871721729679842002948"), - Byte.parseByte("0")), - Bytes.fromHexString("0x"), - Address.wrap(Bytes.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")), - Optional.empty()); static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo="; - - final String MOCK_ORION_KEY = ""; - final User user = new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), ""); final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY; + final String MOCK_ORION_KEY = ""; - @Mock TransactionPool transactionPool; - @Mock EeaSendRawTransaction method; - @Mock PrivacyController privacyController; + RestrictedOffChainEeaSendRawTransaction method; @Before public void before() { method = - new EeaSendRawTransaction(transactionPool, privacyController, enclavePublicKeyProvider); + new RestrictedOffChainEeaSendRawTransaction( + transactionPool, privacyController, enclavePublicKeyProvider); } @Test @@ -164,129 +111,7 @@ public class EeaSendRawTransactionTest { final JsonRpcResponse actualResponse = method.response(request); - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } - - @Test - public void validTransactionIsSentToTransactionPool() { - when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) - .thenReturn(MOCK_ORION_KEY); - when(privacyController.validatePrivateTransaction( - any(PrivateTransaction.class), any(String.class))) - .thenReturn(ValidationResult.valid()); - when(privacyController.createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class))) - .thenReturn(PUBLIC_TRANSACTION); - when(transactionPool.addLocalTransaction(any(Transaction.class))) - .thenReturn(ValidationResult.valid()); - final JsonRpcRequestContext request = getJsonRpcRequestContext(); - - final JsonRpcResponse expectedResponse = - new JsonRpcSuccessResponse( - request.getRequest().getId(), - "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15"); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - verify(privacyController) - .sendTransaction(any(PrivateTransaction.class), eq(ENCLAVE_PUBLIC_KEY), any()); - verify(privacyController) - .validatePrivateTransaction(any(PrivateTransaction.class), eq(ENCLAVE_PUBLIC_KEY)); - verify(privacyController) - .createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class)); - verify(transactionPool).addLocalTransaction(any(Transaction.class)); - } - - @Test - public void validTransactionPrivacyGroupIsSentToTransactionPool() { - when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) - .thenReturn(MOCK_ORION_KEY); - when(privacyController.validatePrivateTransaction(any(PrivateTransaction.class), anyString())) - .thenReturn(ValidationResult.valid()); - when(privacyController.findOffChainPrivacyGroupByGroupId(any(String.class), any(String.class))) - .thenReturn( - Optional.of( - new PrivacyGroup( - "", PrivacyGroup.Type.PANTHEON, "", "", singletonList(ENCLAVE_PUBLIC_KEY)))); - when(privacyController.createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class))) - .thenReturn(PUBLIC_TRANSACTION); - when(transactionPool.addLocalTransaction(any(Transaction.class))) - .thenReturn(ValidationResult.valid()); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", - "eea_sendRawTransaction", - new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP})); - - final JsonRpcResponse expectedResponse = - new JsonRpcSuccessResponse( - request.getRequest().getId(), - "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15"); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - verify(privacyController).sendTransaction(any(PrivateTransaction.class), any(), any()); - verify(privacyController) - .validatePrivateTransaction(any(PrivateTransaction.class), anyString()); - verify(privacyController) - .createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class)); - verify(transactionPool).addLocalTransaction(any(Transaction.class)); - } - - @Test - public void eeaTransactionFailsWhenOnchainPrivacyGroupFeatureIsEnabled() { - method = - new OnChainEeaSendRawTransaction( - transactionPool, privacyController, enclavePublicKeyProvider); - - final JsonRpcRequestContext request = getJsonRpcRequestContext(); - - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse( - request.getRequest().getId(), JsonRpcError.ONCHAIN_PRIVACY_GROUP_ID_NOT_AVAILABLE); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } - - private JsonRpcRequestContext getJsonRpcRequestContext() { - return new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", "eea_sendRawTransaction", new String[] {VALID_LEGACY_PRIVATE_TRANSACTION_RLP}), - user); - } - - @Test - public void onChainPrivacyGroupTransactionFailsWhenFeatureIsNotEnabled() { - method = - new EeaSendRawTransaction(transactionPool, privacyController, enclavePublicKeyProvider); - - when(privacyController.findOffChainPrivacyGroupByGroupId(any(String.class), any(String.class))) - .thenThrow( - new RuntimeException(JsonRpcError.OFFCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST.getMessage())); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", - "eea_sendRawTransaction", - new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP})); - - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse( - request.getRequest().getId(), JsonRpcError.OFFCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); } @Test @@ -303,23 +128,22 @@ public class EeaSendRawTransactionTest { final JsonRpcResponse actualResponse = method.response(request); - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); verifyNoInteractions(privacyController); } @Test public void invalidTransactionIsNotSentToEnclaveAndIsNotAddedToTransactionPool() { - when(privacyController.validatePrivateTransaction(any(PrivateTransaction.class), anyString())) + when(privacyController.validatePrivateTransaction(any(), anyString())) .thenReturn(ValidationResult.invalid(PRIVATE_TRANSACTION_FAILED)); - final JsonRpcRequestContext request = getJsonRpcRequestContext(); - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + new JsonRpcErrorResponse( + validPrivateForTransactionRequest.getRequest().getId(), JsonRpcError.INVALID_PARAMS); - final JsonRpcResponse actualResponse = method.response(request); + final JsonRpcResponse actualResponse = method.response(validPrivateForTransactionRequest); - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); verify(privacyController, never()).sendTransaction(any(), any(), any()); verifyNoInteractions(transactionPool); } @@ -331,14 +155,13 @@ public class EeaSendRawTransactionTest { when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) .thenThrow(new MultiTenancyValidationException("validation failed")); - final JsonRpcRequestContext request = getJsonRpcRequestContext(); - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.ENCLAVE_ERROR); + new JsonRpcErrorResponse( + validPrivateForTransactionRequest.getRequest().getId(), JsonRpcError.ENCLAVE_ERROR); - final JsonRpcResponse actualResponse = method.response(request); + final JsonRpcResponse actualResponse = method.response(validPrivateForTransactionRequest); - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); verifyNoInteractions(transactionPool); } @@ -389,88 +212,25 @@ public class EeaSendRawTransactionTest { private void verifyErrorForInvalidTransaction( final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) { - when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) - .thenReturn(MOCK_ORION_KEY); - when(privacyController.validatePrivateTransaction(any(PrivateTransaction.class), anyString())) + when(privacyController.sendTransaction(any(), any(), any())).thenReturn(MOCK_ORION_KEY); + when(privacyController.validatePrivateTransaction(any(), anyString())) .thenReturn(ValidationResult.valid()); - when(privacyController.createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class))) + when(privacyController.createPrivateMarkerTransaction(any(), any(), any())) .thenReturn(PUBLIC_TRANSACTION); - when(transactionPool.addLocalTransaction(any(Transaction.class))) + when(transactionPool.addLocalTransaction(any())) .thenReturn(ValidationResult.invalid(transactionInvalidReason)); - final JsonRpcRequestContext request = getJsonRpcRequestContext(); final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(request.getRequest().getId(), expectedError); + new JsonRpcErrorResponse( + validPrivateForTransactionRequest.getRequest().getId(), expectedError); - final JsonRpcResponse actualResponse = method.response(request); + final JsonRpcResponse actualResponse = method.response(validPrivateForTransactionRequest); - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - verify(privacyController).sendTransaction(any(PrivateTransaction.class), any(), any()); - verify(privacyController) - .validatePrivateTransaction(any(PrivateTransaction.class), anyString()); - verify(privacyController) - .createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class)); - verify(transactionPool).addLocalTransaction(any(Transaction.class)); + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); } @Test public void getMethodReturnsExpectedName() { assertThat(method.getName()).matches("eea_sendRawTransaction"); } - - private static String validPrivateTransactionRlp() { - final PrivateTransaction.Builder privateTransactionBuilder = - PrivateTransaction.builder() - .nonce(0) - .gasPrice(Wei.of(1)) - .gasLimit(21000) - .value(Wei.ZERO) - .payload(Bytes.EMPTY) - .to(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87")) - .chainId(BigInteger.ONE) - .privateFrom(Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp=")) - .privateFor( - List.of( - Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp="), - Bytes.fromBase64String("QTFhVnRNeExDVUhtQlZIWG9aenpCZ1BiVy93ajVheER="))) - .restriction(Restriction.RESTRICTED); - return rlpEncodeTransaction(privateTransactionBuilder); - } - - private static String validPrivateTransactionRlpPrivacyGroup() { - final PrivateTransaction.Builder privateTransactionBuilder = - PrivateTransaction.builder() - .nonce(0) - .gasPrice(Wei.of(1)) - .gasLimit(21000) - .value(Wei.ZERO) - .payload(Bytes.EMPTY) - .to(Address.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87")) - .chainId(BigInteger.ONE) - .privateFrom(Bytes.fromBase64String("S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXp=")) - .privacyGroupId(Bytes.fromBase64String("DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=")) - .restriction(Restriction.RESTRICTED); - return rlpEncodeTransaction(privateTransactionBuilder); - } - - private static String rlpEncodeTransaction( - final PrivateTransaction.Builder privateTransactionBuilder) { - final KeyPair keyPair = - SIGNATURE_ALGORITHM - .get() - .createKeyPair( - SIGNATURE_ALGORITHM - .get() - .createPrivateKey( - new BigInteger( - "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", - 16))); - - final PrivateTransaction privateTransaction = privateTransactionBuilder.signAndBuild(keyPair); - final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput(); - privateTransaction.writeTo(bvrlp); - return bvrlp.encoded().toHexString(); - } } diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransactionTest.java deleted file mode 100644 index 5311f68e52..0000000000 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransactionTest.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.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.when; - -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.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.core.Address; -import org.hyperledger.besu.ethereum.core.Transaction; -import org.hyperledger.besu.ethereum.mainnet.ValidationResult; -import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; - -import java.util.Arrays; -import java.util.Optional; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class OnChainEeaSendRawTransactionTest extends EeaSendRawTransactionTest { - - @Test - public void validOnChainTransactionPrivacyGroupIsSentToTransactionPool() { - method = - new OnChainEeaSendRawTransaction( - transactionPool, privacyController, enclavePublicKeyProvider); - - when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) - .thenReturn(MOCK_ORION_KEY); - when(privacyController.validatePrivateTransaction( - any(PrivateTransaction.class), any(String.class))) - .thenReturn(ValidationResult.valid()); - final Optional optionalPrivacyGroup = - Optional.of( - new PrivacyGroup( - "", PrivacyGroup.Type.ONCHAIN, "", "", Arrays.asList(ENCLAVE_PUBLIC_KEY))); - when(privacyController.findOnChainPrivacyGroupAndAddNewMembers(any(), any(), any())) - .thenReturn(optionalPrivacyGroup); - when(privacyController.createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), any(Address.class))) - .thenReturn(PUBLIC_TRANSACTION); - when(transactionPool.addLocalTransaction(any(Transaction.class))) - .thenReturn(ValidationResult.valid()); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", - "eea_sendRawTransaction", - new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP})); - - final JsonRpcResponse expectedResponse = - new JsonRpcSuccessResponse( - request.getRequest().getId(), - "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15"); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - verify(privacyController).sendTransaction(any(PrivateTransaction.class), any(), any()); - verify(privacyController) - .validatePrivateTransaction(any(PrivateTransaction.class), any(String.class)); - verify(privacyController) - .createPrivacyMarkerTransaction( - any(String.class), any(PrivateTransaction.class), eq(Address.ONCHAIN_PRIVACY)); - verify(transactionPool).addLocalTransaction(any(Transaction.class)); - } - - @Test - public void transactionFailsForLegacyPrivateTransaction() { - method = - new OnChainEeaSendRawTransaction( - transactionPool, privacyController, enclavePublicKeyProvider); - - final JsonRpcRequestContext request = getJsonRpcRequestContext(); - - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse( - request.getRequest().getId(), JsonRpcError.ONCHAIN_PRIVACY_GROUP_ID_NOT_AVAILABLE); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } - - private JsonRpcRequestContext getJsonRpcRequestContext() { - return new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", "eea_sendRawTransaction", new String[] {VALID_LEGACY_PRIVATE_TRANSACTION_RLP}), - user); - } - - @Test - public void offChainPrivacyGroupTransactionFailsWhenOnchainPrivacyGroupFeatureIsEnabled() { - method = - new OnChainEeaSendRawTransaction( - transactionPool, privacyController, enclavePublicKeyProvider); - - when(privacyController.findOnChainPrivacyGroupAndAddNewMembers(any(), any(), any())) - .thenReturn(Optional.empty()); - - final JsonRpcRequestContext request = - new JsonRpcRequestContext( - new JsonRpcRequest( - "2.0", - "eea_sendRawTransaction", - new String[] {VALID_PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP})); - - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse( - request.getRequest().getId(), JsonRpcError.ONCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST); - - final JsonRpcResponse actualResponse = method.response(request); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } -} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransactionTest.java new file mode 100644 index 0000000000..05e38035fa --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransactionTest.java @@ -0,0 +1,132 @@ +/* + * 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.eea; + +import static java.util.Collections.singletonList; +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.enclave.types.PrivacyGroup; +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.core.Address; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; + +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class RestrictedOffChainEeaSendRawTransactionTest extends BaseEeaSendRawTransaction { + static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo="; + final String MOCK_ORION_KEY = ""; + + final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY; + + RestrictedOffChainEeaSendRawTransaction method; + + @Before + public void before() { + method = + new RestrictedOffChainEeaSendRawTransaction( + transactionPool, privacyController, enclavePublicKeyProvider); + } + + @Test + public void validLegacyTransactionIsSentToTransactionPool() { + when(privacyController.sendTransaction(any(), any(), any())).thenReturn(MOCK_ORION_KEY); + when(privacyController.validatePrivateTransaction(any(), any())) + .thenReturn(ValidationResult.valid()); + when(privacyController.createPrivateMarkerTransaction(any(), any(), any())) + .thenReturn(PUBLIC_TRANSACTION); + when(transactionPool.addLocalTransaction(any())).thenReturn(ValidationResult.valid()); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse( + validPrivateForTransactionRequest.getRequest().getId(), + "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15"); + + final JsonRpcResponse actualResponse = method.response(validPrivateForTransactionRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION); + verify(privacyController) + .createPrivateMarkerTransaction(any(), any(), eq(Address.DEFAULT_PRIVACY)); + } + + @Test + public void validPantheonPrivacyGroupTransactionIsSentToTransactionPool() { + when(privacyController.validatePrivateTransaction(any(), any())) + .thenReturn(ValidationResult.valid()); + + Optional pantheonPrivacyGroup = + Optional.of( + new PrivacyGroup( + "", PrivacyGroup.Type.PANTHEON, "", "", singletonList(ENCLAVE_PUBLIC_KEY))); + + when(privacyController.findOffChainPrivacyGroupByGroupId(any(), any())) + .thenReturn(pantheonPrivacyGroup); + when(privacyController.createPrivateMarkerTransaction(any(), any(), any())) + .thenReturn(PUBLIC_TRANSACTION); + when(transactionPool.addLocalTransaction(any())).thenReturn(ValidationResult.valid()); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), + "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15"); + + final JsonRpcResponse actualResponse = method.response(validPrivacyGroupTransactionRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION); + verify(privacyController) + .createPrivateMarkerTransaction(any(), any(), eq(Address.DEFAULT_PRIVACY)); + } + + @Test + public void + transactionWithUnrestrictedTransactionTypeShouldReturnUnimplementedTransactionTypeError() { + final JsonRpcResponse actualResponse = + method.response(validUnrestrictedPrivacyGroupTransactionRequest); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void + transactionWithUnsupportedTransactionTypeShouldReturnUnimplementedTransactionTypeError() { + final JsonRpcResponse actualResponse = + method.response(validUnsuportedPrivacyGroupTransactionRequest); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransactionTest.java new file mode 100644 index 0000000000..1f49c0a00c --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransactionTest.java @@ -0,0 +1,175 @@ +/* + * 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.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.when; + +import org.hyperledger.besu.enclave.types.PrivacyGroup; +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.core.Address; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.mainnet.ValidationResult; +import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; + +import java.util.Arrays; +import java.util.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTransaction { + static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo="; + final String MOCK_ORION_KEY = ""; + + final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY; + + RestrictedOnChainEeaSendRawTransaction method; + + @Before + public void before() { + method = + new RestrictedOnChainEeaSendRawTransaction( + transactionPool, privacyController, enclavePublicKeyProvider); + } + + @Test + public void validOnChainTransactionPrivacyGroupIsSentToTransactionPool() { + when(privacyController.sendTransaction(any(), any(), any())).thenReturn(MOCK_ORION_KEY); + when(privacyController.validatePrivateTransaction(any(), any())) + .thenReturn(ValidationResult.valid()); + when(privacyController.createPrivateMarkerTransaction( + any(String.class), any(PrivateTransaction.class), any(Address.class))) + .thenReturn(PUBLIC_TRANSACTION); + when(transactionPool.addLocalTransaction(any(Transaction.class))) + .thenReturn(ValidationResult.valid()); + + final Optional onChainPrivacyGroup = + Optional.of( + new PrivacyGroup( + "", PrivacyGroup.Type.ONCHAIN, "", "", Arrays.asList(ENCLAVE_PUBLIC_KEY))); + + when(privacyController.findOnChainPrivacyGroupAndAddNewMembers(any(), any(), any())) + .thenReturn(onChainPrivacyGroup); + + final JsonRpcResponse expectedResponse = + new JsonRpcSuccessResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), + "0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15"); + + final JsonRpcResponse actualResponse = method.response(validPrivacyGroupTransactionRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION); + verify(privacyController) + .createPrivateMarkerTransaction(any(), any(), eq(Address.ONCHAIN_PRIVACY)); + } + + @Test + public void transactionFailsForLegacyPrivateTransaction() { + when(privacyController.validatePrivateTransaction(any(), any())) + .thenReturn(ValidationResult.valid()); + + method = + new RestrictedOnChainEeaSendRawTransaction( + transactionPool, privacyController, enclavePublicKeyProvider); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivateForTransactionRequest.getRequest().getId(), + JsonRpcError.ONCHAIN_PRIVACY_GROUP_ID_NOT_AVAILABLE); + + final JsonRpcResponse actualResponse = method.response(validPrivateForTransactionRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void offChainPrivacyGroupTransactionFailsWhenOnchainPrivacyGroupFeatureIsEnabled() { + when(privacyController.validatePrivateTransaction(any(), any())) + .thenReturn(ValidationResult.valid()); + + method = + new RestrictedOnChainEeaSendRawTransaction( + transactionPool, privacyController, enclavePublicKeyProvider); + + when(privacyController.findOnChainPrivacyGroupAndAddNewMembers(any(), any(), any())) + .thenReturn(Optional.empty()); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), + JsonRpcError.ONCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST); + + final JsonRpcResponse actualResponse = method.response(validPrivacyGroupTransactionRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void onChainPrivacyGroupTransactionFailsWhenGroupDoesNotExist() { + when(privacyController.validatePrivateTransaction(any(), any())) + .thenReturn(ValidationResult.valid()); + + method = + new RestrictedOnChainEeaSendRawTransaction( + transactionPool, privacyController, enclavePublicKeyProvider); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), + JsonRpcError.ONCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST); + + final JsonRpcResponse actualResponse = method.response(validPrivacyGroupTransactionRequest); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void + transactionWithUnrestrictedTransactionTypeShouldReturnUnimplementedTransactionTypeError() { + final JsonRpcResponse actualResponse = + method.response(validUnrestrictedPrivacyGroupTransactionRequest); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } + + @Test + public void + transactionWithUnsupportedTransactionTypeShouldReturnUnimplementedTransactionTypeError() { + final JsonRpcResponse actualResponse = + method.response(validUnsuportedPrivacyGroupTransactionRequest); + + final JsonRpcResponse expectedResponse = + new JsonRpcErrorResponse( + validPrivacyGroupTransactionRequest.getRequest().getId(), JsonRpcError.INVALID_PARAMS); + + assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java index 32e71f8760..bc6c911daf 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java @@ -67,7 +67,7 @@ public class PrivGetPrivateTransactionTest { privGetPrivateTransaction = new PrivGetPrivateTransaction(privacyController, enclavePublicKeyProvider); - markerTransaction = PrivateTransactionDataFixture.privacyMarkerTransaction(); + markerTransaction = PrivateTransactionDataFixture.privateMarkerTransaction(); } @Test diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java index 43f8cede15..b610f6e1bb 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java @@ -17,7 +17,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.VALID_BASE64_ENCLAVE_KEY; -import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privacyMarkerTransaction; +import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateMarkerTransaction; import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateTransactionBesu; import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateTransactionLegacy; import static org.mockito.ArgumentMatchers.any; @@ -85,7 +85,7 @@ public class PrivGetTransactionReceiptTest { @Test public void returnReceiptIfLegacyTransactionExists() { - final Transaction pmt = privacyMarkerTransaction(); + final Transaction pmt = privateMarkerTransaction(); final PrivateTransaction legacyPrivateTransaction = privateTransactionLegacy(); final ExecutedPrivateTransaction executedPrivateTransaction = createExecutedPrivateTransaction(pmt, legacyPrivateTransaction); @@ -106,7 +106,7 @@ public class PrivGetTransactionReceiptTest { @Test public void returnReceiptIfBesuTransactionExists() { - final Transaction pmt = privacyMarkerTransaction(); + final Transaction pmt = privateMarkerTransaction(); final PrivateTransaction privateTransaction = privateTransactionBesu(); final ExecutedPrivateTransaction executedPrivateTransaction = createExecutedPrivateTransaction(pmt, privateTransaction); @@ -152,7 +152,7 @@ public class PrivGetTransactionReceiptTest { @Test public void transactionReceiptContainsRevertReasonWhenInvalidTransactionOccurs() { - final Transaction pmt = privacyMarkerTransaction(); + final Transaction pmt = privateMarkerTransaction(); final PrivateTransaction privateTransaction = privateTransactionBesu(); final ExecutedPrivateTransaction executedPrivateTransaction = createExecutedPrivateTransaction(pmt, privateTransaction); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java index a1a77cc8dc..a426346154 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java @@ -211,7 +211,7 @@ public class PrivacyQueriesTest { new PrivateTransactionReceiptTestFixture().logs(List.of(log)).create(); when(privateWorldStateReader.getPrivateTransactionReceipt( - blockHash, metadata.getPrivacyMarkerTransactionHash())) + blockHash, metadata.getPrivateMarkerTransactionHash())) .thenReturn(Optional.of(receipt)); }); } @@ -222,7 +222,7 @@ public class PrivacyQueriesTest { for (int i = 0; i < transactionMetadataList.size(); i++) { final PrivateTransactionMetadata privateTransactionMetadata = transactionMetadataList.get(i); - final Hash pmtHash = privateTransactionMetadata.getPrivacyMarkerTransactionHash(); + final Hash pmtHash = privateTransactionMetadata.getPrivateMarkerTransactionHash(); final TransactionLocation pmtLocation = new TransactionLocation(blockHeader.getHash(), i); when(blockchainQueries.transactionLocationByHash(pmtHash)) .thenReturn(Optional.of(pmtLocation)); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessor.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessor.java index 11abefde05..3e0af2b61b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessor.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessor.java @@ -191,16 +191,16 @@ public class PrivacyBlockProcessor implements BlockProcessor { actualList = Collections.emptyList(); } else { // we are being added, but do not have to rehydrate all private transactions - final Hash nodeLatestPrivacyMarkerTransactionHash = + final Hash nodeLatestPrivateMarkerTransactionHash = nodeLatestPrivateTxMetadataList .get(nodeLatestPrivateTxMetadataList.size() - 1) - .getPrivacyMarkerTransactionHash(); + .getPrivateMarkerTransactionHash(); for (int i = 0; i < privateTransactionWithMetadataList.size(); i++) { if (!privateTransactionWithMetadataList .get(i) .getPrivateTransactionMetadata() - .getPrivacyMarkerTransactionHash() - .equals(nodeLatestPrivacyMarkerTransactionHash)) { + .getPrivateMarkerTransactionHash() + .equals(nodeLatestPrivateMarkerTransactionHash)) { continue; } if (privateTransactionWithMetadataList.size() - 1 == i) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyController.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyController.java index ef36e0030f..e9f82e9e7f 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyController.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyController.java @@ -165,13 +165,13 @@ public class DefaultPrivacyController implements PrivacyController { } @Override - public Transaction createPrivacyMarkerTransaction( + public Transaction createPrivateMarkerTransaction( final String privateTransactionLookupId, final PrivateTransaction privateTransaction) { return privateMarkerTransactionFactory.create(privateTransactionLookupId, privateTransaction); } @Override - public Transaction createPrivacyMarkerTransaction( + public Transaction createPrivateMarkerTransaction( final String privateTransactionLookupId, final PrivateTransaction privateTransaction, final Address privacyPrecompileAddress) { @@ -431,7 +431,7 @@ public class DefaultPrivacyController implements PrivacyController { privateTransactionMetadataList.get(i); final Transaction privateMarkerTransaction = blockchain - .getTransactionByHash(privateTransactionMetadata.getPrivacyMarkerTransactionHash()) + .getTransactionByHash(privateTransactionMetadata.getPrivateMarkerTransactionHash()) .orElseThrow(); final ReceiveResponse receiveResponse = retrieveTransaction( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/MultiTenancyPrivacyController.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/MultiTenancyPrivacyController.java index 1b11ef773f..4dc9656a5d 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/MultiTenancyPrivacyController.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/MultiTenancyPrivacyController.java @@ -129,24 +129,25 @@ public class MultiTenancyPrivacyController implements PrivacyController { } @Override - public Transaction createPrivacyMarkerTransaction( + public Transaction createPrivateMarkerTransaction( final String privateTransactionLookupId, final PrivateTransaction privateTransaction) { - return privacyController.createPrivacyMarkerTransaction( + return privacyController.createPrivateMarkerTransaction( privateTransactionLookupId, privateTransaction); } @Override - public Transaction createPrivacyMarkerTransaction( + public Transaction createPrivateMarkerTransaction( final String privateTransactionLookupId, final PrivateTransaction privateTransaction, final Address privacyPrecompileAddress) { - return privacyController.createPrivacyMarkerTransaction( + return privacyController.createPrivateMarkerTransaction( privateTransactionLookupId, privateTransaction, privacyPrecompileAddress); } @Override public ValidationResult validatePrivateTransaction( final PrivateTransaction privateTransaction, final String enclavePublicKey) { + final String privacyGroupId = privateTransaction.determinePrivacyGroupId().toBase64String(); verifyPrivacyGroupContainsEnclavePublicKey(privacyGroupId, enclavePublicKey); return privateTransactionValidator.validate( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java index 3d6b0cb7d3..60b0d7b16b 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java @@ -49,10 +49,10 @@ public interface PrivacyController { PrivacyGroup[] findOffChainPrivacyGroupByMembers(List addresses, String enclavePublicKey); - Transaction createPrivacyMarkerTransaction( + Transaction createPrivateMarkerTransaction( String privateTransactionLookupId, PrivateTransaction privateTransaction); - Transaction createPrivacyMarkerTransaction( + Transaction createPrivateMarkerTransaction( String privateTransactionLookupId, PrivateTransaction privateTransaction, Address privacyPrecompileAddress); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java index cdbde34506..983f2ee2e5 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java @@ -98,7 +98,7 @@ public class PrivateStateRehydration { final PrivateTransactionWithMetadata transactionWithMetadata = privateTransactionWithMetadataList.get(j); pmtHashToPrivateTransactionMap.put( - transactionWithMetadata.getPrivateTransactionMetadata().getPrivacyMarkerTransactionHash(), + transactionWithMetadata.getPrivateTransactionMetadata().getPrivateMarkerTransactionHash(), transactionWithMetadata.getPrivateTransaction()); } @@ -117,7 +117,7 @@ public class PrivateStateRehydration { privateTransactionWithMetadataList .get(i) .getPrivateTransactionMetadata() - .getPrivacyMarkerTransactionHash(); + .getPrivateMarkerTransactionHash(); final Optional transactionLocationOfLastPmtInBlock = blockchain.getTransactionLocation(lastPmtHash); @@ -241,7 +241,7 @@ public class PrivateStateRehydration { privateTransactionWithMetadataList .get(index) .getPrivateTransactionMetadata() - .getPrivacyMarkerTransactionHash()) + .getPrivateMarkerTransactionHash()) .orElseThrow() .getBlockHash(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocator.java index ca569e9750..c25550fa81 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocator.java @@ -192,10 +192,10 @@ public class PrivateTransactionLocator { for (final PrivateTransactionWithMetadata privateTx : privateTransactionWithMetadataList) { - final Hash actualPrivacyMarkerTransactionHash = - privateTx.getPrivateTransactionMetadata().getPrivacyMarkerTransactionHash(); + final Hash actualPrivateMarkerTransactionHash = + privateTx.getPrivateTransactionMetadata().getPrivateMarkerTransactionHash(); - if (expectedPmtHash.equals(actualPrivacyMarkerTransactionHash)) { + if (expectedPmtHash.equals(actualPrivateMarkerTransactionHash)) { return Optional.of( new TransactionFromEnclave( privateTx.getPrivateTransaction(), diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidator.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidator.java index 65db76fbf6..70d5120f7c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidator.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidator.java @@ -88,11 +88,6 @@ public class PrivateTransactionValidator { if (!privateTransaction.getValue().isZero()) { return ValidationResult.invalid(TransactionInvalidReason.PRIVATE_VALUE_NOT_ZERO); } - if (!privateTransaction.getRestriction().equals(Restriction.RESTRICTED)) { - return ValidationResult.invalid( - TransactionInvalidReason.PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE); - } - return ValidationResult.valid(); } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/PrivateTransactionMetadata.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/PrivateTransactionMetadata.java index a99ee5efe1..83e5777fd2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/PrivateTransactionMetadata.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/PrivateTransactionMetadata.java @@ -22,11 +22,11 @@ import java.util.Objects; /** Mined private transaction metadata. */ public class PrivateTransactionMetadata { - private final Hash privacyMarkerTransactionHash; + private final Hash privateMarkerTransactionHash; private final Hash stateRoot; - public PrivateTransactionMetadata(final Hash privacyMarkerTransactionHash, final Hash stateRoot) { - this.privacyMarkerTransactionHash = privacyMarkerTransactionHash; + public PrivateTransactionMetadata(final Hash privateMarkerTransactionHash, final Hash stateRoot) { + this.privateMarkerTransactionHash = privateMarkerTransactionHash; this.stateRoot = stateRoot; } @@ -34,14 +34,14 @@ public class PrivateTransactionMetadata { return stateRoot; } - public Hash getPrivacyMarkerTransactionHash() { - return privacyMarkerTransactionHash; + public Hash getPrivateMarkerTransactionHash() { + return privateMarkerTransactionHash; } public void writeTo(final RLPOutput out) { out.startList(); - out.writeBytes(privacyMarkerTransactionHash); + out.writeBytes(privateMarkerTransactionHash); out.writeBytes(stateRoot); out.endList(); @@ -63,12 +63,12 @@ public class PrivateTransactionMetadata { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final PrivateTransactionMetadata that = (PrivateTransactionMetadata) o; - return privacyMarkerTransactionHash.equals(that.privacyMarkerTransactionHash) + return privateMarkerTransactionHash.equals(that.privateMarkerTransactionHash) && stateRoot.equals(that.stateRoot); } @Override public int hashCode() { - return Objects.hash(privacyMarkerTransactionHash, stateRoot); + return Objects.hash(privateMarkerTransactionHash, stateRoot); } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java index d0d5b9afb1..5d66ac5ca2 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java @@ -131,14 +131,14 @@ public class PrivateStorageMigration { final List txs = block.getBody().getTransactions(); int lastPmtIndex = -1; for (int i = 0; i < txs.size(); i++) { - if (isPrivacyMarkerTransaction(txs.get(i))) { + if (isPrivateMarkerTransaction(txs.get(i))) { lastPmtIndex = i; } } return lastPmtIndex; } - private boolean isPrivacyMarkerTransaction(final Transaction tx) { + private boolean isPrivateMarkerTransaction(final Transaction tx) { return tx.getTo().isPresent() && tx.getTo().get().equals(privacyPrecompileAddress); } diff --git a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionDataFixture.java b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionDataFixture.java index 8261eaa5ee..e5d23045c9 100644 --- a/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionDataFixture.java +++ b/ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionDataFixture.java @@ -80,21 +80,21 @@ public class PrivateTransactionDataFixture { public static final Address VALID_CONTRACT_DEPLOYMENT_ADDRESS = Address.fromHexString("0x0bac79b78b9866ef11c989ad21a7fcf15f7a18d7"); - public static Transaction privacyMarkerTransaction() { - return privacyMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.DEFAULT_PRIVACY); + public static Transaction privateMarkerTransaction() { + return privateMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.DEFAULT_PRIVACY); } - public static Transaction privacyMarkerTransactionOnChain() { - return privacyMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.ONCHAIN_PRIVACY); + public static Transaction privateMarkerTransactionOnChain() { + return privateMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.ONCHAIN_PRIVACY); } - public static Transaction privacyMarkerTransactionOnChainAdd() { - return privacyMarkerTransaction( + public static Transaction privateMarkerTransactionOnChainAdd() { + return privateMarkerTransaction( Bytes.concatenate(VALID_BASE64_ENCLAVE_KEY, VALID_BASE64_ENCLAVE_KEY), Address.ONCHAIN_PRIVACY); } - private static Transaction privacyMarkerTransaction( + private static Transaction privateMarkerTransaction( final Bytes transactionKey, final Address precompiledContractAddress) { return Transaction.builder() .type(TransactionType.FRONTIER) diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java index 601100df7f..b47d544d17 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java @@ -131,18 +131,18 @@ public class PrivacyBlockProcessorTest { final Block firstBlock = blockDataGenerator.block( BlockDataGenerator.BlockOptions.create() - .addTransaction(PrivateTransactionDataFixture.privacyMarkerTransactionOnChain())); + .addTransaction(PrivateTransactionDataFixture.privateMarkerTransactionOnChain())); final Block secondBlock = blockDataGenerator.block( BlockDataGenerator.BlockOptions.create() .addTransaction( - PrivateTransactionDataFixture.privacyMarkerTransactionOnChainAdd())); + PrivateTransactionDataFixture.privateMarkerTransactionOnChainAdd())); when(enclave.receive(any())) .thenReturn( PrivateTransactionDataFixture.generateAddToGroupReceiveResponse( PrivateTransactionDataFixture.privateTransactionBesu(), - PrivateTransactionDataFixture.privacyMarkerTransactionOnChain())); + PrivateTransactionDataFixture.privateMarkerTransactionOnChain())); when(blockchain.getTransactionLocation(any())) .thenReturn(Optional.of(new TransactionLocation(firstBlock.getHash(), 0))); when(blockchain.getBlockByHash(any())).thenReturn(Optional.of(firstBlock)); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyControllerTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyControllerTest.java index 16bfce220f..66aa0a5515 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyControllerTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyControllerTest.java @@ -203,7 +203,7 @@ public class DefaultPrivacyControllerTest { privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY); final Transaction markerTransaction = - privacyController.createPrivacyMarkerTransaction(privateTransactionLookupId, transaction); + privacyController.createPrivateMarkerTransaction(privateTransactionLookupId, transaction); assertThat(validationResult).isEqualTo(ValidationResult.valid()); assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress()); @@ -227,7 +227,7 @@ public class DefaultPrivacyControllerTest { privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY); final Transaction markerTransaction = - privacyController.createPrivacyMarkerTransaction(privateTransactionLookupId, transaction); + privacyController.createPrivateMarkerTransaction(privateTransactionLookupId, transaction); assertThat(validationResult).isEqualTo(ValidationResult.valid()); assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress()); @@ -459,26 +459,26 @@ public class DefaultPrivacyControllerTest { } @Test - public void canCreatePrivacyMarkerTransactionForOnChainPrivacy() { + public void canCreatePrivateMarkerTransactionForOnChainPrivacy() { final PrivateTransaction transaction = buildBesuPrivateTransaction(0); final String privateTransactionLookupId = privacyController.sendTransaction( transaction, ENCLAVE_PUBLIC_KEY, Optional.of(ONCHAIN_PRIVACY_GROUP)); - final Transaction onChainPrivacyMarkerTransaction = - privacyController.createPrivacyMarkerTransaction( + final Transaction onChainPrivateMarkerTransaction = + privacyController.createPrivateMarkerTransaction( privateTransactionLookupId, transaction, Address.ONCHAIN_PRIVACY); - assertThat(onChainPrivacyMarkerTransaction.contractAddress()) + assertThat(onChainPrivateMarkerTransaction.contractAddress()) .isEqualTo(PUBLIC_TRANSACTION.contractAddress()); - assertThat(onChainPrivacyMarkerTransaction.getPayload()) + assertThat(onChainPrivateMarkerTransaction.getPayload()) .isEqualTo(PUBLIC_TRANSACTION.getPayload()); - assertThat(onChainPrivacyMarkerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce()); - assertThat(onChainPrivacyMarkerTransaction.getSender()) + assertThat(onChainPrivateMarkerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce()); + assertThat(onChainPrivateMarkerTransaction.getSender()) .isEqualTo(PUBLIC_TRANSACTION.getSender()); - assertThat(onChainPrivacyMarkerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue()); - assertThat(onChainPrivacyMarkerTransaction.getTo().get()).isEqualTo(Address.ONCHAIN_PRIVACY); + assertThat(onChainPrivateMarkerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue()); + assertThat(onChainPrivateMarkerTransaction.getTo().get()).isEqualTo(Address.ONCHAIN_PRIVACY); verify(enclave) .send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(singletonList(ENCLAVE_PUBLIC_KEY))); } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocatorTest.java index 295c699df4..8d7d204479 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocatorTest.java @@ -77,7 +77,7 @@ public class PrivateTransactionLocatorTest { @Test public void locateLegacyPrivateTransactionSentToOffchainPrivacyGroup() { - final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransaction(); + final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransaction(); final PrivateTransaction privateTransaction = privateTransactionLegacy(); final ExecutedPrivateTransaction expectedPrivateTx = @@ -91,7 +91,7 @@ public class PrivateTransactionLocatorTest { @Test public void locateBesuPrivateTransactionSentToOffchainPrivacyGroup() { - final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransaction(); + final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransaction(); final PrivateTransaction privateTransaction = privateTransactionBesu(); final ExecutedPrivateTransaction expectedPrivateTx = @@ -126,7 +126,7 @@ public class PrivateTransactionLocatorTest { @Test public void locateBesuPrivateTransactionSentToOnchainPrivacyGroup() { - final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); + final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain(); final PrivateTransaction privateTransaction = privateTransactionBesu(); final ExecutedPrivateTransaction expectedPrivateTx = @@ -160,7 +160,7 @@ public class PrivateTransactionLocatorTest { @Test public void locateBesuPrivateTransactionFromAddBlobSentToOnchainPrivacyGroup() { - final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); + final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain(); final PrivateTransaction privateTransaction = privateTransactionBesu(); final ExecutedPrivateTransaction expectedPrivateTx = @@ -174,7 +174,7 @@ public class PrivateTransactionLocatorTest { @Test public void locatePrivateTransactionWithNoEntryOnPGHeadBlockMap() { - final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); + final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain(); final PrivateTransaction privateTransaction = privateTransactionBesu(); createExecutedPrivateTransactionFromAddBlob(pmt, privateTransaction); @@ -190,7 +190,7 @@ public class PrivateTransactionLocatorTest { @Test public void locateBesuPrivateTransactionNotFoundInAddBlob() { - final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); + final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain(); final PrivateTransaction privateTransaction = privateTransactionBesu(); createExecutedPrivateTransactionFromAddBlob(pmt, privateTransaction); diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidatorTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidatorTest.java index fad325da72..13c679e6a7 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidatorTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidatorTest.java @@ -18,7 +18,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INCORRECT_PRIVATE_NONCE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INVALID_SIGNATURE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.PRIVATE_NONCE_TOO_LOW; -import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.PRIVATE_VALUE_NOT_ZERO; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.WRONG_CHAIN_ID; @@ -137,30 +136,6 @@ public class PrivateTransactionValidatorTest { assertThat(validationResult).isEqualTo(ValidationResult.invalid(PRIVATE_VALUE_NOT_ZERO)); } - @Test - public void - transactionWithUnrestrictedTransactionTypeShouldReturnUnimplementedTransactionTypeError() { - validator = new PrivateTransactionValidator(Optional.of(BigInteger.ONE)); - - final ValidationResult validationResult = - validator.validate(privateTransactionWithRestriction(Restriction.UNRESTRICTED), 0L, false); - - assertThat(validationResult) - .isEqualTo(ValidationResult.invalid(PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE)); - } - - @Test - public void - transactionWithUnsupportedTransactionTypeShouldReturnUnimplementedTransactionTypeError() { - validator = new PrivateTransactionValidator(Optional.of(BigInteger.ONE)); - - final ValidationResult validationResult = - validator.validate(privateTransactionWithRestriction(Restriction.UNSUPPORTED), 0L, false); - - assertThat(validationResult) - .isEqualTo(ValidationResult.invalid(PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE)); - } - private PrivateTransaction privateTransactionWithNonce(final long nonce) { return new PrivateTransactionTestFixture() .nonce(nonce) @@ -177,10 +152,4 @@ public class PrivateTransactionValidatorTest { private PrivateTransaction privateTransactionWithValue(final long value) { return new PrivateTransactionTestFixture().value(Wei.of(value)).createTransaction(senderKeys); } - - private PrivateTransaction privateTransactionWithRestriction(final Restriction restriction) { - return new PrivateTransactionTestFixture() - .restriction(restriction) - .createTransaction(senderKeys); - } } diff --git a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java index 25ced4a571..3d4976d9fd 100644 --- a/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java +++ b/ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java @@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.privacy.storage.migration; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privacyMarkerTransaction; +import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateMarkerTransaction; import static org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver.EMPTY_ROOT_HASH; import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_0_0; import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_4_0; @@ -147,8 +147,8 @@ public class PrivateStorageMigrationTest { @Test public void successfulMigrationBumpsSchemaVersion() { - final Transaction privacyMarkerTransaction = createPrivacyMarkerTransaction(); - mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); + final Transaction privateMarkerTransaction = createPrivateMarkerTransaction(); + mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction); assertThat(privateStateStorage.getSchemaVersion()).isEqualTo(SCHEMA_VERSION_1_0_0); migration.migratePrivateStorage(); @@ -158,8 +158,8 @@ public class PrivateStorageMigrationTest { @Test public void failedMigrationThrowsErrorAndDoesNotBumpSchemaVersion() { - final Transaction privacyMarkerTransaction = createPrivacyMarkerTransaction(); - mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); + final Transaction privateMarkerTransaction = createPrivateMarkerTransaction(); + mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction); final Hash rootHashOtherThanZero = Hash.wrap(Bytes32.fromHexStringLenient("1")); createPrivacyGroupHeadBlockInitialMapAndMetadata(PRIVACY_GROUP_BYTES, rootHashOtherThanZero); @@ -186,8 +186,8 @@ public class PrivateStorageMigrationTest { @Test public void migrationReprocessBlocksWithPMT() { - final Transaction privacyMarkerTransaction = createPrivacyMarkerTransaction(); - mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); + final Transaction privateMarkerTransaction = createPrivateMarkerTransaction(); + mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction); final Block blockWithPMT = blockchain.getBlockByNumber(1L).orElseThrow(); migration.migratePrivateStorage(); @@ -208,7 +208,7 @@ public class PrivateStorageMigrationTest { public void migrationOnlyProcessRequiredTransactions() { final List transactions = new ArrayList<>(); transactions.add(publicTransaction()); - transactions.add(createPrivacyMarkerTransaction()); + transactions.add(createPrivateMarkerTransaction()); transactions.add(publicTransaction()); mockBlockchainWithTransactionsInABlock(transactions); @@ -240,10 +240,10 @@ public class PrivateStorageMigrationTest { return existingPgHeadMap; } - private Transaction createPrivacyMarkerTransaction() { - final Transaction privacyMarkerTransaction = privacyMarkerTransaction(); - mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); - return privacyMarkerTransaction; + private Transaction createPrivateMarkerTransaction() { + final Transaction privateMarkerTransaction = privateMarkerTransaction(); + mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction); + return privateMarkerTransaction; } private void mockBlockchainWithZeroTransactions() { @@ -265,7 +265,7 @@ public class PrivateStorageMigrationTest { .thenReturn(Optional.of(EMPTY_ROOT_HASH)); } - private void mockBlockchainWithPrivacyMarkerTransaction(final Transaction transaction) { + private void mockBlockchainWithPrivateMarkerTransaction(final Transaction transaction) { final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); final Block genesis = blockDataGenerator.genesisBlock();