refactor: EeaSendRawTransaction isolate send raw on/off chain (#2283)

* refactor: isolate send raw on/off chain

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* Move responsibility of checking restriction type into JsonRpcMethod

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* Refactor: Make use of privacy vs private consistent

Rename s/privacyMarkerTransaction/privateMarkerTransaction/g


Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>
pull/2392/head
Antony Denyer 4 years ago committed by GitHub
parent b81a481a42
commit 51287459ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/GetAllPrivateMarkerTransactionHashes.java
  2. 6
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  3. 4
      besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java
  4. 2
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  5. 4
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivGetPrivateTransactionIntegrationTest.java
  6. 90
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java
  7. 85
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransaction.java
  8. 74
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransaction.java
  9. 8
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java
  10. 4
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueries.java
  11. 146
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java
  12. 288
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java
  13. 140
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/OnChainEeaSendRawTransactionTest.java
  14. 132
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransactionTest.java
  15. 175
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransactionTest.java
  16. 2
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java
  17. 8
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java
  18. 4
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/query/PrivacyQueriesTest.java
  19. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessor.java
  20. 6
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyController.java
  21. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/MultiTenancyPrivacyController.java
  22. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java
  23. 6
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateStateRehydration.java
  24. 6
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocator.java
  25. 5
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidator.java
  26. 16
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/PrivateTransactionMetadata.java
  27. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigration.java
  28. 14
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionDataFixture.java
  29. 6
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/PrivacyBlockProcessorTest.java
  30. 22
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/DefaultPrivacyControllerTest.java
  31. 12
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionLocatorTest.java
  32. 31
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/PrivateTransactionValidatorTest.java
  33. 26
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java

@ -27,7 +27,7 @@ import org.web3j.protocol.besu.Besu;
import org.web3j.protocol.core.DefaultBlockParameter; import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.methods.response.EthBlock; import org.web3j.protocol.core.methods.response.EthBlock;
public class GetAllPrivacyMarkerTransactionHashes implements Transaction<List<String>> { public class GetAllPrivateMarkerTransactionHashes implements Transaction<List<String>> {
@Override @Override
public List<String> execute(final NodeRequests node) { public List<String> execute(final NodeRequests node) {
final Besu besu = node.privacy().getBesuClient(); final Besu besu = node.privacy().getBesuClient();

@ -954,7 +954,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
names = {"--privacy-marker-transaction-signing-key-file"}, names = {"--privacy-marker-transaction-signing-key-file"},
description = 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.") "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( @Option(
names = {"--privacy-enable-database-migration"}, names = {"--privacy-enable-database-migration"},
@ -2130,7 +2130,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0) { if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0) {
// if gas is required, cannot use random keys to sign private tx // if gas is required, cannot use random keys to sign private tx
// ie --privacy-marker-transaction-signing-key-file must be set // ie --privacy-marker-transaction-signing-key-file must be set
if (privacyMarkerTransactionSigningKeyPath == null) { if (privateMarkerTransactionSigningKeyPath == null) {
throw new ParameterException( throw new ParameterException(
commandLine, 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"); "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."); "--privacy-precompiled-address option is deprecated. This address is derived, based on --privacy-onchain-groups-enabled.");
} }
privacyParametersBuilder.setPrivateKeyPath(privacyMarkerTransactionSigningKeyPath); privacyParametersBuilder.setPrivateKeyPath(privateMarkerTransactionSigningKeyPath);
privacyParametersBuilder.setStorageProvider( privacyParametersBuilder.setStorageProvider(
privacyKeyStorageProvider(keyValueStorageName + "-privacy")); privacyKeyStorageProvider(keyValueStorageName + "-privacy"));
if (isPrivacyTlsEnabled) { if (isPrivacyTlsEnabled) {

@ -198,13 +198,13 @@ public class PrivacyReorgTest {
final DefaultBlockchain blockchain = (DefaultBlockchain) protocolContext.getBlockchain(); final DefaultBlockchain blockchain = (DefaultBlockchain) protocolContext.getBlockchain();
final PrivateStateStorage privateStateStorage = privacyParameters.getPrivateStateStorage(); final PrivateStateStorage privateStateStorage = privacyParameters.getPrivateStateStorage();
final Transaction privacyMarkerTransaction = final Transaction privateMarkerTransaction =
buildMarkerTransaction(getEnclaveKey(enclave.clientUrl())); buildMarkerTransaction(getEnclaveKey(enclave.clientUrl()));
final Block firstBlock = final Block firstBlock =
gen.block( gen.block(
getBlockOptionsWithTransaction( getBlockOptionsWithTransaction(
blockchain.getGenesisBlock(), blockchain.getGenesisBlock(),
privacyMarkerTransaction, privateMarkerTransaction,
FIRST_BLOCK_WITH_SINGLE_TRANSACTION_STATE_ROOT)); FIRST_BLOCK_WITH_SINGLE_TRANSACTION_STATE_ROOT));
appendBlock(besuController, blockchain, protocolContext, firstBlock); appendBlock(besuController, blockchain, protocolContext, firstBlock);

@ -3484,7 +3484,7 @@ public class BesuCommandTest extends CommandTestAbstract {
} }
@Test @Test
public void privacyMarkerTransactionSigningKeyFileRequiredIfMinGasPriceNonZero() { public void privateMarkerTransactionSigningKeyFileRequiredIfMinGasPriceNonZero() {
parseCommand("--privacy-enabled", "--privacy-public-key-file", ENCLAVE_PUBLIC_KEY_PATH); parseCommand("--privacy-enabled", "--privacy-public-key-file", ENCLAVE_PUBLIC_KEY_PATH);
assertThat(commandErrorOutput.toString()) assertThat(commandErrorOutput.toString())

@ -16,7 +16,7 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat; 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.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
@ -152,7 +152,7 @@ public class PrivGetPrivateTransactionIntegrationTest {
new PrivGetPrivateTransaction(privacyController, enclavePublicKeyProvider); new PrivGetPrivateTransaction(privacyController, enclavePublicKeyProvider);
final Hash blockHash = Hash.ZERO; 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.getTransactionByHash(eq(pmt.getHash()))).thenReturn(Optional.of(pmt));
when(blockchain.getTransactionLocation(eq(pmt.getHash()))) when(blockchain.getTransactionLocation(eq(pmt.getHash())))
.thenReturn(Optional.of(new TransactionLocation(blockHash, 0))); .thenReturn(Optional.of(new TransactionLocation(blockHash, 0)));

@ -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.JsonRpcEnclaveErrorConverter.convertEnclaveInvalidReason;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcErrorConverter.convertTransactionInvalidReason; 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.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.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; 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.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.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; 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.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; 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.Transaction;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult; 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.PrivateTransaction;
import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPException; import org.hyperledger.besu.ethereum.rlp.RLPException;
@ -42,23 +36,16 @@ import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import java.util.Optional; import java.util.Optional;
import io.vertx.ext.auth.User;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
public class EeaSendRawTransaction implements JsonRpcMethod { public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod {
private static final Logger LOG = getLogger(); private static final Logger LOG = getLogger();
final TransactionPool transactionPool; private final TransactionPool transactionPool;
final PrivacyController privacyController;
private final EnclavePublicKeyProvider enclavePublicKeyProvider; protected AbstractEeaSendRawTransaction(final TransactionPool transactionPool) {
public EeaSendRawTransaction(
final TransactionPool transactionPool,
final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) {
this.transactionPool = transactionPool; this.transactionPool = transactionPool;
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
} }
@Override @Override
@ -75,36 +62,22 @@ public class EeaSendRawTransaction implements JsonRpcMethod {
final PrivateTransaction privateTransaction = final PrivateTransaction privateTransaction =
PrivateTransaction.readFrom(RLP.input(Bytes.fromHexString(rawPrivateTransaction))); 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<Bytes> maybePrivacyGroupId = privateTransaction.getPrivacyGroupId();
final Optional<PrivacyGroup> maybePrivacyGroup =
findPrivacyGroup(
privacyController, maybePrivacyGroupId, enclavePublicKey, privateTransaction);
final ValidationResult<TransactionInvalidReason> validationResult = final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(privateTransaction, enclavePublicKey); validatePrivateTransaction(privateTransaction, requestContext.getUser());
if (!validationResult.isValid()) { if (!validationResult.isValid()) {
return new JsonRpcErrorResponse( return new JsonRpcErrorResponse(
id, convertTransactionInvalidReason(validationResult.getInvalidReason())); id, convertTransactionInvalidReason(validationResult.getInvalidReason()));
} }
final JsonRpcResponse ret = final Transaction privateMarkerTransaction =
createPMTAndAddToTxPool( createPrivateMarkerTransaction(privateTransaction, requestContext.getUser());
id,
privateTransaction, return transactionPool
maybePrivacyGroup, .addLocalTransaction(privateMarkerTransaction)
maybePrivacyGroupId, .either(
enclavePublicKey, () -> new JsonRpcSuccessResponse(id, privateMarkerTransaction.getHash().toString()),
Address.DEFAULT_PRIVACY); errorReason -> getJsonRpcErrorResponse(id, errorReason));
return ret;
} catch (final JsonRpcErrorResponseException e) { } catch (final JsonRpcErrorResponseException e) {
return new JsonRpcErrorResponse(id, e.getJsonRpcError()); return new JsonRpcErrorResponse(id, e.getJsonRpcError());
@ -116,35 +89,6 @@ public class EeaSendRawTransaction implements JsonRpcMethod {
} }
} }
Optional<PrivacyGroup> findPrivacyGroup(
final PrivacyController privacyController,
final Optional<Bytes> maybePrivacyGroupId,
final String enclavePublicKey,
final PrivateTransaction privateTransaction) {
final Optional<PrivacyGroup> maybePrivacyGroup =
findOffchainPrivacyGroup(privacyController, maybePrivacyGroupId, enclavePublicKey);
return maybePrivacyGroup;
}
JsonRpcResponse createPMTAndAddToTxPool(
final Object id,
final PrivateTransaction privateTransaction,
final Optional<PrivacyGroup> maybePrivacyGroup,
final Optional<Bytes> 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( JsonRpcErrorResponse getJsonRpcErrorResponse(
final Object id, final TransactionInvalidReason errorReason) { final Object id, final TransactionInvalidReason errorReason) {
if (errorReason.equals(TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT)) { if (errorReason.equals(TransactionInvalidReason.INTRINSIC_GAS_EXCEEDS_GAS_LIMIT)) {
@ -152,4 +96,10 @@ public class EeaSendRawTransaction implements JsonRpcMethod {
} }
return new JsonRpcErrorResponse(id, convertTransactionInvalidReason(errorReason)); return new JsonRpcErrorResponse(id, convertTransactionInvalidReason(errorReason));
} }
protected abstract ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final Optional<User> user);
protected abstract Transaction createPrivateMarkerTransaction(
final PrivateTransaction privateTransaction, final Optional<User> user);
} }

@ -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<TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final Optional<User> 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> user) {
final Optional<PrivacyGroup> 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);
}
}

@ -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 static org.hyperledger.besu.ethereum.privacy.PrivacyGroupUtil.findOnchainPrivacyGroup;
import org.hyperledger.besu.enclave.types.PrivacyGroup; 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.privacy.methods.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; 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.Address;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool; 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.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; 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 java.util.Optional;
import io.vertx.ext.auth.User;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32; 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 TransactionPool transactionPool,
final PrivacyController privacyController, final PrivacyController privacyController,
final EnclavePublicKeyProvider enclavePublicKeyProvider) { final EnclavePublicKeyProvider enclavePublicKeyProvider) {
super(transactionPool, privacyController, enclavePublicKeyProvider); super(transactionPool);
this.privacyController = privacyController;
this.enclavePublicKeyProvider = enclavePublicKeyProvider;
} }
@Override @Override
public String getName() { protected ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
return RpcMethod.EEA_SEND_RAW_TRANSACTION.getMethodName(); final PrivateTransaction privateTransaction, final Optional<User> user) {
if (!privateTransaction.getRestriction().equals(Restriction.RESTRICTED)) {
return ValidationResult.invalid(
TransactionInvalidReason.PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE);
}
return privacyController.validatePrivateTransaction(
privateTransaction, enclavePublicKeyProvider.getEnclaveKey(user));
} }
@Override @Override
Optional<PrivacyGroup> findPrivacyGroup( protected Transaction createPrivateMarkerTransaction(
final PrivacyController privacyController, final PrivateTransaction privateTransaction, final Optional<User> user) {
final Optional<Bytes> maybePrivacyGroupId, if (privateTransaction.getPrivacyGroupId().isEmpty()) {
final String enclavePublicKey,
final PrivateTransaction privateTransaction) {
if (maybePrivacyGroupId.isEmpty()) {
throw new JsonRpcErrorResponseException(JsonRpcError.ONCHAIN_PRIVACY_GROUP_ID_NOT_AVAILABLE); throw new JsonRpcErrorResponseException(JsonRpcError.ONCHAIN_PRIVACY_GROUP_ID_NOT_AVAILABLE);
} }
final Optional<PrivacyGroup> maybePrivacyGroup =
final String enclavePublicKey = enclavePublicKeyProvider.getEnclaveKey(user);
final Optional<PrivacyGroup> privacyGroup =
findOnchainPrivacyGroup( findOnchainPrivacyGroup(
privacyController, maybePrivacyGroupId, enclavePublicKey, privateTransaction); privacyController,
if (maybePrivacyGroup.isEmpty()) { privateTransaction.getPrivacyGroupId(),
enclavePublicKey,
privateTransaction);
if (privacyGroup.isEmpty()) {
throw new JsonRpcErrorResponseException(JsonRpcError.ONCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST); throw new JsonRpcErrorResponseException(JsonRpcError.ONCHAIN_PRIVACY_GROUP_DOES_NOT_EXIST);
} }
return maybePrivacyGroup;
}
@Override final Bytes privacyGroupId = privateTransaction.getPrivacyGroupId().get();
JsonRpcResponse createPMTAndAddToTxPool(
final Object id,
final PrivateTransaction privateTransaction,
final Optional<PrivacyGroup> maybePrivacyGroup,
final Optional<Bytes> maybePrivacyGroupId,
final String enclavePublicKey,
final Address privacyPrecompiledAddress) {
final Bytes privacyGroupId = maybePrivacyGroupId.get();
final String privateTransactionLookupId = final String privateTransactionLookupId =
privacyController.sendTransaction(privateTransaction, enclavePublicKey, maybePrivacyGroup); privacyController.sendTransaction(privateTransaction, enclavePublicKey, privacyGroup);
final Optional<String> addPayloadPrivateTransactionLookupId = final Optional<String> addPayloadPrivateTransactionLookupId =
privacyController.buildAndSendAddPayload( privacyController.buildAndSendAddPayload(
privateTransaction, Bytes32.wrap(privacyGroupId), enclavePublicKey); privateTransaction, Bytes32.wrap(privacyGroupId), enclavePublicKey);
final Transaction privacyMarkerTransaction =
privacyController.createPrivacyMarkerTransaction( return privacyController.createPrivateMarkerTransaction(
buildCompoundLookupId(privateTransactionLookupId, addPayloadPrivateTransactionLookupId), buildCompoundLookupId(privateTransactionLookupId, addPayloadPrivateTransactionLookupId),
privateTransaction, privateTransaction,
Address.ONCHAIN_PRIVACY); Address.ONCHAIN_PRIVACY);
return transactionPool
.addLocalTransaction(privacyMarkerTransaction)
.either(
() -> new JsonRpcSuccessResponse(id, privacyMarkerTransaction.getHash().toString()),
errorReason -> getJsonRpcErrorResponse(id, errorReason));
} }
private String buildCompoundLookupId( private String buildCompoundLookupId(

@ -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.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod; 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.EnclavePublicKeyProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.EeaSendRawTransaction; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.RestrictedOffChainEeaSendRawTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea.OnChainEeaSendRawTransaction; 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.jsonrpc.internal.privacy.methods.priv.PrivGetEeaTransactionCount;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
@ -45,12 +45,12 @@ public class EeaJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
final EnclavePublicKeyProvider enclavePublicKeyProvider) { final EnclavePublicKeyProvider enclavePublicKeyProvider) {
if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) { if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) {
return mapOf( return mapOf(
new OnChainEeaSendRawTransaction( new RestrictedOnChainEeaSendRawTransaction(
getTransactionPool(), privacyController, enclavePublicKeyProvider), getTransactionPool(), privacyController, enclavePublicKeyProvider),
new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider)); new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider));
} else { // off chain privacy } else { // off chain privacy
return mapOf( return mapOf(
new EeaSendRawTransaction( new RestrictedOffChainEeaSendRawTransaction(
getTransactionPool(), privacyController, enclavePublicKeyProvider), getTransactionPool(), privacyController, enclavePublicKeyProvider),
new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider)); new PrivGetEeaTransactionCount(privacyController, enclavePublicKeyProvider));
} }

@ -70,7 +70,7 @@ public class PrivacyQueries {
final List<Hash> pmtHashList = final List<Hash> pmtHashList =
privateTransactionMetadataList.stream() privateTransactionMetadataList.stream()
.map(PrivateTransactionMetadata::getPrivacyMarkerTransactionHash) .map(PrivateTransactionMetadata::getPrivateMarkerTransactionHash)
.collect(Collectors.toList()); .collect(Collectors.toList());
final List<PrivateTransactionReceipt> privateTransactionReceiptList = final List<PrivateTransactionReceipt> privateTransactionReceiptList =
@ -90,7 +90,7 @@ public class PrivacyQueries {
privateTransactionReceiptList.get(i), privateTransactionReceiptList.get(i),
blockNumber, blockNumber,
blockHash, blockHash,
privateTransactionMetadataList.get(i).getPrivacyMarkerTransactionHash(), privateTransactionMetadataList.get(i).getPrivateMarkerTransactionHash(),
findPMTIndex(pmtHashList.get(i)), findPMTIndex(pmtHashList.get(i)),
removed)) removed))
.flatMap(Collection::stream) .flatMap(Collection::stream)

@ -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<SignatureAlgorithm> 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();
}
}

@ -14,22 +14,16 @@
*/ */
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea; 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.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.PRIVATE_TRANSACTION_FAILED; import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.PRIVATE_TRANSACTION_FAILED;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when; 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.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.exception.InvalidJsonRpcParameters; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.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.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; 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.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.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.MultiTenancyValidationException; 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.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.Restriction;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason; 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.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class) @RunWith(MockitoJUnitRunner.class)
public class EeaSendRawTransactionTest { public class EeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
static final Supplier<SignatureAlgorithm> 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();
// RLP encode fails creating a transaction without privateFrom so must be manually encoded // 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 = private static final String PRIVATE_TRANSACTION_RLP_PRIVACY_GROUP_NO_PRIVATE_FROM =
@ -84,39 +53,17 @@ public class EeaSendRawTransactionTest {
+ "885ff29e973e2576b6600181d1b0a2b5294e30d9be4a1981ff" + "885ff29e973e2576b6600181d1b0a2b5294e30d9be4a1981ff"
+ "b33a0b8c8a72657374726963746564"; + "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="; 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 EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY;
final String MOCK_ORION_KEY = "";
@Mock TransactionPool transactionPool; RestrictedOffChainEeaSendRawTransaction method;
@Mock EeaSendRawTransaction method;
@Mock PrivacyController privacyController;
@Before @Before
public void before() { public void before() {
method = method =
new EeaSendRawTransaction(transactionPool, privacyController, enclavePublicKeyProvider); new RestrictedOffChainEeaSendRawTransaction(
transactionPool, privacyController, enclavePublicKeyProvider);
} }
@Test @Test
@ -164,129 +111,7 @@ public class EeaSendRawTransactionTest {
final JsonRpcResponse actualResponse = method.response(request); final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(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);
} }
@Test @Test
@ -303,23 +128,22 @@ public class EeaSendRawTransactionTest {
final JsonRpcResponse actualResponse = method.response(request); final JsonRpcResponse actualResponse = method.response(request);
assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verifyNoInteractions(privacyController); verifyNoInteractions(privacyController);
} }
@Test @Test
public void invalidTransactionIsNotSentToEnclaveAndIsNotAddedToTransactionPool() { public void invalidTransactionIsNotSentToEnclaveAndIsNotAddedToTransactionPool() {
when(privacyController.validatePrivateTransaction(any(PrivateTransaction.class), anyString())) when(privacyController.validatePrivateTransaction(any(), anyString()))
.thenReturn(ValidationResult.invalid(PRIVATE_TRANSACTION_FAILED)); .thenReturn(ValidationResult.invalid(PRIVATE_TRANSACTION_FAILED));
final JsonRpcRequestContext request = getJsonRpcRequestContext();
final JsonRpcResponse expectedResponse = 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()); verify(privacyController, never()).sendTransaction(any(), any(), any());
verifyNoInteractions(transactionPool); verifyNoInteractions(transactionPool);
} }
@ -331,14 +155,13 @@ public class EeaSendRawTransactionTest {
when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any()))
.thenThrow(new MultiTenancyValidationException("validation failed")); .thenThrow(new MultiTenancyValidationException("validation failed"));
final JsonRpcRequestContext request = getJsonRpcRequestContext();
final JsonRpcResponse expectedResponse = 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); verifyNoInteractions(transactionPool);
} }
@ -389,88 +212,25 @@ public class EeaSendRawTransactionTest {
private void verifyErrorForInvalidTransaction( private void verifyErrorForInvalidTransaction(
final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) { final TransactionInvalidReason transactionInvalidReason, final JsonRpcError expectedError) {
when(privacyController.sendTransaction(any(PrivateTransaction.class), any(), any())) when(privacyController.sendTransaction(any(), any(), any())).thenReturn(MOCK_ORION_KEY);
.thenReturn(MOCK_ORION_KEY); when(privacyController.validatePrivateTransaction(any(), anyString()))
when(privacyController.validatePrivateTransaction(any(PrivateTransaction.class), anyString()))
.thenReturn(ValidationResult.valid()); .thenReturn(ValidationResult.valid());
when(privacyController.createPrivacyMarkerTransaction( when(privacyController.createPrivateMarkerTransaction(any(), any(), any()))
any(String.class), any(PrivateTransaction.class), any(Address.class)))
.thenReturn(PUBLIC_TRANSACTION); .thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any(Transaction.class))) when(transactionPool.addLocalTransaction(any()))
.thenReturn(ValidationResult.invalid(transactionInvalidReason)); .thenReturn(ValidationResult.invalid(transactionInvalidReason));
final JsonRpcRequestContext request = getJsonRpcRequestContext();
final JsonRpcResponse expectedResponse = 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); assertThat(actualResponse).usingRecursiveComparison().isEqualTo(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 @Test
public void getMethodReturnsExpectedName() { public void getMethodReturnsExpectedName() {
assertThat(method.getName()).matches("eea_sendRawTransaction"); 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();
}
} }

@ -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<PrivacyGroup> 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);
}
}

@ -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<PrivacyGroup> 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);
}
}

@ -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<PrivacyGroup> 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);
}
}

@ -67,7 +67,7 @@ public class PrivGetPrivateTransactionTest {
privGetPrivateTransaction = privGetPrivateTransaction =
new PrivGetPrivateTransaction(privacyController, enclavePublicKeyProvider); new PrivGetPrivateTransaction(privacyController, enclavePublicKeyProvider);
markerTransaction = PrivateTransactionDataFixture.privacyMarkerTransaction(); markerTransaction = PrivateTransactionDataFixture.privateMarkerTransaction();
} }
@Test @Test

@ -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.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable; 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.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.privateTransactionBesu;
import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateTransactionLegacy; import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateTransactionLegacy;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@ -85,7 +85,7 @@ public class PrivGetTransactionReceiptTest {
@Test @Test
public void returnReceiptIfLegacyTransactionExists() { public void returnReceiptIfLegacyTransactionExists() {
final Transaction pmt = privacyMarkerTransaction(); final Transaction pmt = privateMarkerTransaction();
final PrivateTransaction legacyPrivateTransaction = privateTransactionLegacy(); final PrivateTransaction legacyPrivateTransaction = privateTransactionLegacy();
final ExecutedPrivateTransaction executedPrivateTransaction = final ExecutedPrivateTransaction executedPrivateTransaction =
createExecutedPrivateTransaction(pmt, legacyPrivateTransaction); createExecutedPrivateTransaction(pmt, legacyPrivateTransaction);
@ -106,7 +106,7 @@ public class PrivGetTransactionReceiptTest {
@Test @Test
public void returnReceiptIfBesuTransactionExists() { public void returnReceiptIfBesuTransactionExists() {
final Transaction pmt = privacyMarkerTransaction(); final Transaction pmt = privateMarkerTransaction();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
final ExecutedPrivateTransaction executedPrivateTransaction = final ExecutedPrivateTransaction executedPrivateTransaction =
createExecutedPrivateTransaction(pmt, privateTransaction); createExecutedPrivateTransaction(pmt, privateTransaction);
@ -152,7 +152,7 @@ public class PrivGetTransactionReceiptTest {
@Test @Test
public void transactionReceiptContainsRevertReasonWhenInvalidTransactionOccurs() { public void transactionReceiptContainsRevertReasonWhenInvalidTransactionOccurs() {
final Transaction pmt = privacyMarkerTransaction(); final Transaction pmt = privateMarkerTransaction();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
final ExecutedPrivateTransaction executedPrivateTransaction = final ExecutedPrivateTransaction executedPrivateTransaction =
createExecutedPrivateTransaction(pmt, privateTransaction); createExecutedPrivateTransaction(pmt, privateTransaction);

@ -211,7 +211,7 @@ public class PrivacyQueriesTest {
new PrivateTransactionReceiptTestFixture().logs(List.of(log)).create(); new PrivateTransactionReceiptTestFixture().logs(List.of(log)).create();
when(privateWorldStateReader.getPrivateTransactionReceipt( when(privateWorldStateReader.getPrivateTransactionReceipt(
blockHash, metadata.getPrivacyMarkerTransactionHash())) blockHash, metadata.getPrivateMarkerTransactionHash()))
.thenReturn(Optional.of(receipt)); .thenReturn(Optional.of(receipt));
}); });
} }
@ -222,7 +222,7 @@ public class PrivacyQueriesTest {
for (int i = 0; i < transactionMetadataList.size(); i++) { for (int i = 0; i < transactionMetadataList.size(); i++) {
final PrivateTransactionMetadata privateTransactionMetadata = transactionMetadataList.get(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); final TransactionLocation pmtLocation = new TransactionLocation(blockHeader.getHash(), i);
when(blockchainQueries.transactionLocationByHash(pmtHash)) when(blockchainQueries.transactionLocationByHash(pmtHash))
.thenReturn(Optional.of(pmtLocation)); .thenReturn(Optional.of(pmtLocation));

@ -191,16 +191,16 @@ public class PrivacyBlockProcessor implements BlockProcessor {
actualList = Collections.emptyList(); actualList = Collections.emptyList();
} else { } else {
// we are being added, but do not have to rehydrate all private transactions // we are being added, but do not have to rehydrate all private transactions
final Hash nodeLatestPrivacyMarkerTransactionHash = final Hash nodeLatestPrivateMarkerTransactionHash =
nodeLatestPrivateTxMetadataList nodeLatestPrivateTxMetadataList
.get(nodeLatestPrivateTxMetadataList.size() - 1) .get(nodeLatestPrivateTxMetadataList.size() - 1)
.getPrivacyMarkerTransactionHash(); .getPrivateMarkerTransactionHash();
for (int i = 0; i < privateTransactionWithMetadataList.size(); i++) { for (int i = 0; i < privateTransactionWithMetadataList.size(); i++) {
if (!privateTransactionWithMetadataList if (!privateTransactionWithMetadataList
.get(i) .get(i)
.getPrivateTransactionMetadata() .getPrivateTransactionMetadata()
.getPrivacyMarkerTransactionHash() .getPrivateMarkerTransactionHash()
.equals(nodeLatestPrivacyMarkerTransactionHash)) { .equals(nodeLatestPrivateMarkerTransactionHash)) {
continue; continue;
} }
if (privateTransactionWithMetadataList.size() - 1 == i) { if (privateTransactionWithMetadataList.size() - 1 == i) {

@ -165,13 +165,13 @@ public class DefaultPrivacyController implements PrivacyController {
} }
@Override @Override
public Transaction createPrivacyMarkerTransaction( public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId, final PrivateTransaction privateTransaction) { final String privateTransactionLookupId, final PrivateTransaction privateTransaction) {
return privateMarkerTransactionFactory.create(privateTransactionLookupId, privateTransaction); return privateMarkerTransactionFactory.create(privateTransactionLookupId, privateTransaction);
} }
@Override @Override
public Transaction createPrivacyMarkerTransaction( public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId, final String privateTransactionLookupId,
final PrivateTransaction privateTransaction, final PrivateTransaction privateTransaction,
final Address privacyPrecompileAddress) { final Address privacyPrecompileAddress) {
@ -431,7 +431,7 @@ public class DefaultPrivacyController implements PrivacyController {
privateTransactionMetadataList.get(i); privateTransactionMetadataList.get(i);
final Transaction privateMarkerTransaction = final Transaction privateMarkerTransaction =
blockchain blockchain
.getTransactionByHash(privateTransactionMetadata.getPrivacyMarkerTransactionHash()) .getTransactionByHash(privateTransactionMetadata.getPrivateMarkerTransactionHash())
.orElseThrow(); .orElseThrow();
final ReceiveResponse receiveResponse = final ReceiveResponse receiveResponse =
retrieveTransaction( retrieveTransaction(

@ -129,24 +129,25 @@ public class MultiTenancyPrivacyController implements PrivacyController {
} }
@Override @Override
public Transaction createPrivacyMarkerTransaction( public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId, final PrivateTransaction privateTransaction) { final String privateTransactionLookupId, final PrivateTransaction privateTransaction) {
return privacyController.createPrivacyMarkerTransaction( return privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, privateTransaction); privateTransactionLookupId, privateTransaction);
} }
@Override @Override
public Transaction createPrivacyMarkerTransaction( public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId, final String privateTransactionLookupId,
final PrivateTransaction privateTransaction, final PrivateTransaction privateTransaction,
final Address privacyPrecompileAddress) { final Address privacyPrecompileAddress) {
return privacyController.createPrivacyMarkerTransaction( return privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, privateTransaction, privacyPrecompileAddress); privateTransactionLookupId, privateTransaction, privacyPrecompileAddress);
} }
@Override @Override
public ValidationResult<TransactionInvalidReason> validatePrivateTransaction( public ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final String enclavePublicKey) { final PrivateTransaction privateTransaction, final String enclavePublicKey) {
final String privacyGroupId = privateTransaction.determinePrivacyGroupId().toBase64String(); final String privacyGroupId = privateTransaction.determinePrivacyGroupId().toBase64String();
verifyPrivacyGroupContainsEnclavePublicKey(privacyGroupId, enclavePublicKey); verifyPrivacyGroupContainsEnclavePublicKey(privacyGroupId, enclavePublicKey);
return privateTransactionValidator.validate( return privateTransactionValidator.validate(

@ -49,10 +49,10 @@ public interface PrivacyController {
PrivacyGroup[] findOffChainPrivacyGroupByMembers(List<String> addresses, String enclavePublicKey); PrivacyGroup[] findOffChainPrivacyGroupByMembers(List<String> addresses, String enclavePublicKey);
Transaction createPrivacyMarkerTransaction( Transaction createPrivateMarkerTransaction(
String privateTransactionLookupId, PrivateTransaction privateTransaction); String privateTransactionLookupId, PrivateTransaction privateTransaction);
Transaction createPrivacyMarkerTransaction( Transaction createPrivateMarkerTransaction(
String privateTransactionLookupId, String privateTransactionLookupId,
PrivateTransaction privateTransaction, PrivateTransaction privateTransaction,
Address privacyPrecompileAddress); Address privacyPrecompileAddress);

@ -98,7 +98,7 @@ public class PrivateStateRehydration {
final PrivateTransactionWithMetadata transactionWithMetadata = final PrivateTransactionWithMetadata transactionWithMetadata =
privateTransactionWithMetadataList.get(j); privateTransactionWithMetadataList.get(j);
pmtHashToPrivateTransactionMap.put( pmtHashToPrivateTransactionMap.put(
transactionWithMetadata.getPrivateTransactionMetadata().getPrivacyMarkerTransactionHash(), transactionWithMetadata.getPrivateTransactionMetadata().getPrivateMarkerTransactionHash(),
transactionWithMetadata.getPrivateTransaction()); transactionWithMetadata.getPrivateTransaction());
} }
@ -117,7 +117,7 @@ public class PrivateStateRehydration {
privateTransactionWithMetadataList privateTransactionWithMetadataList
.get(i) .get(i)
.getPrivateTransactionMetadata() .getPrivateTransactionMetadata()
.getPrivacyMarkerTransactionHash(); .getPrivateMarkerTransactionHash();
final Optional<TransactionLocation> transactionLocationOfLastPmtInBlock = final Optional<TransactionLocation> transactionLocationOfLastPmtInBlock =
blockchain.getTransactionLocation(lastPmtHash); blockchain.getTransactionLocation(lastPmtHash);
@ -241,7 +241,7 @@ public class PrivateStateRehydration {
privateTransactionWithMetadataList privateTransactionWithMetadataList
.get(index) .get(index)
.getPrivateTransactionMetadata() .getPrivateTransactionMetadata()
.getPrivacyMarkerTransactionHash()) .getPrivateMarkerTransactionHash())
.orElseThrow() .orElseThrow()
.getBlockHash(); .getBlockHash();
} }

@ -192,10 +192,10 @@ public class PrivateTransactionLocator {
for (final PrivateTransactionWithMetadata privateTx : for (final PrivateTransactionWithMetadata privateTx :
privateTransactionWithMetadataList) { privateTransactionWithMetadataList) {
final Hash actualPrivacyMarkerTransactionHash = final Hash actualPrivateMarkerTransactionHash =
privateTx.getPrivateTransactionMetadata().getPrivacyMarkerTransactionHash(); privateTx.getPrivateTransactionMetadata().getPrivateMarkerTransactionHash();
if (expectedPmtHash.equals(actualPrivacyMarkerTransactionHash)) { if (expectedPmtHash.equals(actualPrivateMarkerTransactionHash)) {
return Optional.of( return Optional.of(
new TransactionFromEnclave( new TransactionFromEnclave(
privateTx.getPrivateTransaction(), privateTx.getPrivateTransaction(),

@ -88,11 +88,6 @@ public class PrivateTransactionValidator {
if (!privateTransaction.getValue().isZero()) { if (!privateTransaction.getValue().isZero()) {
return ValidationResult.invalid(TransactionInvalidReason.PRIVATE_VALUE_NOT_ZERO); 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(); return ValidationResult.valid();
} }

@ -22,11 +22,11 @@ import java.util.Objects;
/** Mined private transaction metadata. */ /** Mined private transaction metadata. */
public class PrivateTransactionMetadata { public class PrivateTransactionMetadata {
private final Hash privacyMarkerTransactionHash; private final Hash privateMarkerTransactionHash;
private final Hash stateRoot; private final Hash stateRoot;
public PrivateTransactionMetadata(final Hash privacyMarkerTransactionHash, final Hash stateRoot) { public PrivateTransactionMetadata(final Hash privateMarkerTransactionHash, final Hash stateRoot) {
this.privacyMarkerTransactionHash = privacyMarkerTransactionHash; this.privateMarkerTransactionHash = privateMarkerTransactionHash;
this.stateRoot = stateRoot; this.stateRoot = stateRoot;
} }
@ -34,14 +34,14 @@ public class PrivateTransactionMetadata {
return stateRoot; return stateRoot;
} }
public Hash getPrivacyMarkerTransactionHash() { public Hash getPrivateMarkerTransactionHash() {
return privacyMarkerTransactionHash; return privateMarkerTransactionHash;
} }
public void writeTo(final RLPOutput out) { public void writeTo(final RLPOutput out) {
out.startList(); out.startList();
out.writeBytes(privacyMarkerTransactionHash); out.writeBytes(privateMarkerTransactionHash);
out.writeBytes(stateRoot); out.writeBytes(stateRoot);
out.endList(); out.endList();
@ -63,12 +63,12 @@ public class PrivateTransactionMetadata {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
final PrivateTransactionMetadata that = (PrivateTransactionMetadata) o; final PrivateTransactionMetadata that = (PrivateTransactionMetadata) o;
return privacyMarkerTransactionHash.equals(that.privacyMarkerTransactionHash) return privateMarkerTransactionHash.equals(that.privateMarkerTransactionHash)
&& stateRoot.equals(that.stateRoot); && stateRoot.equals(that.stateRoot);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(privacyMarkerTransactionHash, stateRoot); return Objects.hash(privateMarkerTransactionHash, stateRoot);
} }
} }

@ -131,14 +131,14 @@ public class PrivateStorageMigration {
final List<Transaction> txs = block.getBody().getTransactions(); final List<Transaction> txs = block.getBody().getTransactions();
int lastPmtIndex = -1; int lastPmtIndex = -1;
for (int i = 0; i < txs.size(); i++) { for (int i = 0; i < txs.size(); i++) {
if (isPrivacyMarkerTransaction(txs.get(i))) { if (isPrivateMarkerTransaction(txs.get(i))) {
lastPmtIndex = i; lastPmtIndex = i;
} }
} }
return lastPmtIndex; return lastPmtIndex;
} }
private boolean isPrivacyMarkerTransaction(final Transaction tx) { private boolean isPrivateMarkerTransaction(final Transaction tx) {
return tx.getTo().isPresent() && tx.getTo().get().equals(privacyPrecompileAddress); return tx.getTo().isPresent() && tx.getTo().get().equals(privacyPrecompileAddress);
} }

@ -80,21 +80,21 @@ public class PrivateTransactionDataFixture {
public static final Address VALID_CONTRACT_DEPLOYMENT_ADDRESS = public static final Address VALID_CONTRACT_DEPLOYMENT_ADDRESS =
Address.fromHexString("0x0bac79b78b9866ef11c989ad21a7fcf15f7a18d7"); Address.fromHexString("0x0bac79b78b9866ef11c989ad21a7fcf15f7a18d7");
public static Transaction privacyMarkerTransaction() { public static Transaction privateMarkerTransaction() {
return privacyMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.DEFAULT_PRIVACY); return privateMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.DEFAULT_PRIVACY);
} }
public static Transaction privacyMarkerTransactionOnChain() { public static Transaction privateMarkerTransactionOnChain() {
return privacyMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.ONCHAIN_PRIVACY); return privateMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.ONCHAIN_PRIVACY);
} }
public static Transaction privacyMarkerTransactionOnChainAdd() { public static Transaction privateMarkerTransactionOnChainAdd() {
return privacyMarkerTransaction( return privateMarkerTransaction(
Bytes.concatenate(VALID_BASE64_ENCLAVE_KEY, VALID_BASE64_ENCLAVE_KEY), Bytes.concatenate(VALID_BASE64_ENCLAVE_KEY, VALID_BASE64_ENCLAVE_KEY),
Address.ONCHAIN_PRIVACY); Address.ONCHAIN_PRIVACY);
} }
private static Transaction privacyMarkerTransaction( private static Transaction privateMarkerTransaction(
final Bytes transactionKey, final Address precompiledContractAddress) { final Bytes transactionKey, final Address precompiledContractAddress) {
return Transaction.builder() return Transaction.builder()
.type(TransactionType.FRONTIER) .type(TransactionType.FRONTIER)

@ -131,18 +131,18 @@ public class PrivacyBlockProcessorTest {
final Block firstBlock = final Block firstBlock =
blockDataGenerator.block( blockDataGenerator.block(
BlockDataGenerator.BlockOptions.create() BlockDataGenerator.BlockOptions.create()
.addTransaction(PrivateTransactionDataFixture.privacyMarkerTransactionOnChain())); .addTransaction(PrivateTransactionDataFixture.privateMarkerTransactionOnChain()));
final Block secondBlock = final Block secondBlock =
blockDataGenerator.block( blockDataGenerator.block(
BlockDataGenerator.BlockOptions.create() BlockDataGenerator.BlockOptions.create()
.addTransaction( .addTransaction(
PrivateTransactionDataFixture.privacyMarkerTransactionOnChainAdd())); PrivateTransactionDataFixture.privateMarkerTransactionOnChainAdd()));
when(enclave.receive(any())) when(enclave.receive(any()))
.thenReturn( .thenReturn(
PrivateTransactionDataFixture.generateAddToGroupReceiveResponse( PrivateTransactionDataFixture.generateAddToGroupReceiveResponse(
PrivateTransactionDataFixture.privateTransactionBesu(), PrivateTransactionDataFixture.privateTransactionBesu(),
PrivateTransactionDataFixture.privacyMarkerTransactionOnChain())); PrivateTransactionDataFixture.privateMarkerTransactionOnChain()));
when(blockchain.getTransactionLocation(any())) when(blockchain.getTransactionLocation(any()))
.thenReturn(Optional.of(new TransactionLocation(firstBlock.getHash(), 0))); .thenReturn(Optional.of(new TransactionLocation(firstBlock.getHash(), 0)));
when(blockchain.getBlockByHash(any())).thenReturn(Optional.of(firstBlock)); when(blockchain.getBlockByHash(any())).thenReturn(Optional.of(firstBlock));

@ -203,7 +203,7 @@ public class DefaultPrivacyControllerTest {
privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY); privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final Transaction markerTransaction = final Transaction markerTransaction =
privacyController.createPrivacyMarkerTransaction(privateTransactionLookupId, transaction); privacyController.createPrivateMarkerTransaction(privateTransactionLookupId, transaction);
assertThat(validationResult).isEqualTo(ValidationResult.valid()); assertThat(validationResult).isEqualTo(ValidationResult.valid());
assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress()); assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress());
@ -227,7 +227,7 @@ public class DefaultPrivacyControllerTest {
privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY); privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final Transaction markerTransaction = final Transaction markerTransaction =
privacyController.createPrivacyMarkerTransaction(privateTransactionLookupId, transaction); privacyController.createPrivateMarkerTransaction(privateTransactionLookupId, transaction);
assertThat(validationResult).isEqualTo(ValidationResult.valid()); assertThat(validationResult).isEqualTo(ValidationResult.valid());
assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress()); assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress());
@ -459,26 +459,26 @@ public class DefaultPrivacyControllerTest {
} }
@Test @Test
public void canCreatePrivacyMarkerTransactionForOnChainPrivacy() { public void canCreatePrivateMarkerTransactionForOnChainPrivacy() {
final PrivateTransaction transaction = buildBesuPrivateTransaction(0); final PrivateTransaction transaction = buildBesuPrivateTransaction(0);
final String privateTransactionLookupId = final String privateTransactionLookupId =
privacyController.sendTransaction( privacyController.sendTransaction(
transaction, ENCLAVE_PUBLIC_KEY, Optional.of(ONCHAIN_PRIVACY_GROUP)); transaction, ENCLAVE_PUBLIC_KEY, Optional.of(ONCHAIN_PRIVACY_GROUP));
final Transaction onChainPrivacyMarkerTransaction = final Transaction onChainPrivateMarkerTransaction =
privacyController.createPrivacyMarkerTransaction( privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, transaction, Address.ONCHAIN_PRIVACY); privateTransactionLookupId, transaction, Address.ONCHAIN_PRIVACY);
assertThat(onChainPrivacyMarkerTransaction.contractAddress()) assertThat(onChainPrivateMarkerTransaction.contractAddress())
.isEqualTo(PUBLIC_TRANSACTION.contractAddress()); .isEqualTo(PUBLIC_TRANSACTION.contractAddress());
assertThat(onChainPrivacyMarkerTransaction.getPayload()) assertThat(onChainPrivateMarkerTransaction.getPayload())
.isEqualTo(PUBLIC_TRANSACTION.getPayload()); .isEqualTo(PUBLIC_TRANSACTION.getPayload());
assertThat(onChainPrivacyMarkerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce()); assertThat(onChainPrivateMarkerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
assertThat(onChainPrivacyMarkerTransaction.getSender()) assertThat(onChainPrivateMarkerTransaction.getSender())
.isEqualTo(PUBLIC_TRANSACTION.getSender()); .isEqualTo(PUBLIC_TRANSACTION.getSender());
assertThat(onChainPrivacyMarkerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue()); assertThat(onChainPrivateMarkerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
assertThat(onChainPrivacyMarkerTransaction.getTo().get()).isEqualTo(Address.ONCHAIN_PRIVACY); assertThat(onChainPrivateMarkerTransaction.getTo().get()).isEqualTo(Address.ONCHAIN_PRIVACY);
verify(enclave) verify(enclave)
.send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(singletonList(ENCLAVE_PUBLIC_KEY))); .send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(singletonList(ENCLAVE_PUBLIC_KEY)));
} }

@ -77,7 +77,7 @@ public class PrivateTransactionLocatorTest {
@Test @Test
public void locateLegacyPrivateTransactionSentToOffchainPrivacyGroup() { public void locateLegacyPrivateTransactionSentToOffchainPrivacyGroup() {
final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransaction(); final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransaction();
final PrivateTransaction privateTransaction = privateTransactionLegacy(); final PrivateTransaction privateTransaction = privateTransactionLegacy();
final ExecutedPrivateTransaction expectedPrivateTx = final ExecutedPrivateTransaction expectedPrivateTx =
@ -91,7 +91,7 @@ public class PrivateTransactionLocatorTest {
@Test @Test
public void locateBesuPrivateTransactionSentToOffchainPrivacyGroup() { public void locateBesuPrivateTransactionSentToOffchainPrivacyGroup() {
final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransaction(); final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransaction();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
final ExecutedPrivateTransaction expectedPrivateTx = final ExecutedPrivateTransaction expectedPrivateTx =
@ -126,7 +126,7 @@ public class PrivateTransactionLocatorTest {
@Test @Test
public void locateBesuPrivateTransactionSentToOnchainPrivacyGroup() { public void locateBesuPrivateTransactionSentToOnchainPrivacyGroup() {
final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
final ExecutedPrivateTransaction expectedPrivateTx = final ExecutedPrivateTransaction expectedPrivateTx =
@ -160,7 +160,7 @@ public class PrivateTransactionLocatorTest {
@Test @Test
public void locateBesuPrivateTransactionFromAddBlobSentToOnchainPrivacyGroup() { public void locateBesuPrivateTransactionFromAddBlobSentToOnchainPrivacyGroup() {
final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
final ExecutedPrivateTransaction expectedPrivateTx = final ExecutedPrivateTransaction expectedPrivateTx =
@ -174,7 +174,7 @@ public class PrivateTransactionLocatorTest {
@Test @Test
public void locatePrivateTransactionWithNoEntryOnPGHeadBlockMap() { public void locatePrivateTransactionWithNoEntryOnPGHeadBlockMap() {
final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
createExecutedPrivateTransactionFromAddBlob(pmt, privateTransaction); createExecutedPrivateTransactionFromAddBlob(pmt, privateTransaction);
@ -190,7 +190,7 @@ public class PrivateTransactionLocatorTest {
@Test @Test
public void locateBesuPrivateTransactionNotFoundInAddBlob() { public void locateBesuPrivateTransactionNotFoundInAddBlob() {
final Transaction pmt = PrivateTransactionDataFixture.privacyMarkerTransactionOnChain(); final Transaction pmt = PrivateTransactionDataFixture.privateMarkerTransactionOnChain();
final PrivateTransaction privateTransaction = privateTransactionBesu(); final PrivateTransaction privateTransaction = privateTransactionBesu();
createExecutedPrivateTransactionFromAddBlob(pmt, privateTransaction); createExecutedPrivateTransactionFromAddBlob(pmt, privateTransaction);

@ -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.INCORRECT_PRIVATE_NONCE;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INVALID_SIGNATURE; 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_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.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.REPLAY_PROTECTED_SIGNATURES_NOT_SUPPORTED;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.WRONG_CHAIN_ID; 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)); assertThat(validationResult).isEqualTo(ValidationResult.invalid(PRIVATE_VALUE_NOT_ZERO));
} }
@Test
public void
transactionWithUnrestrictedTransactionTypeShouldReturnUnimplementedTransactionTypeError() {
validator = new PrivateTransactionValidator(Optional.of(BigInteger.ONE));
final ValidationResult<TransactionInvalidReason> 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<TransactionInvalidReason> validationResult =
validator.validate(privateTransactionWithRestriction(Restriction.UNSUPPORTED), 0L, false);
assertThat(validationResult)
.isEqualTo(ValidationResult.invalid(PRIVATE_UNIMPLEMENTED_TRANSACTION_TYPE));
}
private PrivateTransaction privateTransactionWithNonce(final long nonce) { private PrivateTransaction privateTransactionWithNonce(final long nonce) {
return new PrivateTransactionTestFixture() return new PrivateTransactionTestFixture()
.nonce(nonce) .nonce(nonce)
@ -177,10 +152,4 @@ public class PrivateTransactionValidatorTest {
private PrivateTransaction privateTransactionWithValue(final long value) { private PrivateTransaction privateTransactionWithValue(final long value) {
return new PrivateTransactionTestFixture().value(Wei.of(value)).createTransaction(senderKeys); return new PrivateTransactionTestFixture().value(Wei.of(value)).createTransaction(senderKeys);
} }
private PrivateTransaction privateTransactionWithRestriction(final Restriction restriction) {
return new PrivateTransactionTestFixture()
.restriction(restriction)
.createTransaction(senderKeys);
}
} }

@ -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.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy; 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.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_0_0;
import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_4_0; import static org.hyperledger.besu.ethereum.privacy.storage.PrivateStateKeyValueStorage.SCHEMA_VERSION_1_4_0;
@ -147,8 +147,8 @@ public class PrivateStorageMigrationTest {
@Test @Test
public void successfulMigrationBumpsSchemaVersion() { public void successfulMigrationBumpsSchemaVersion() {
final Transaction privacyMarkerTransaction = createPrivacyMarkerTransaction(); final Transaction privateMarkerTransaction = createPrivateMarkerTransaction();
mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction);
assertThat(privateStateStorage.getSchemaVersion()).isEqualTo(SCHEMA_VERSION_1_0_0); assertThat(privateStateStorage.getSchemaVersion()).isEqualTo(SCHEMA_VERSION_1_0_0);
migration.migratePrivateStorage(); migration.migratePrivateStorage();
@ -158,8 +158,8 @@ public class PrivateStorageMigrationTest {
@Test @Test
public void failedMigrationThrowsErrorAndDoesNotBumpSchemaVersion() { public void failedMigrationThrowsErrorAndDoesNotBumpSchemaVersion() {
final Transaction privacyMarkerTransaction = createPrivacyMarkerTransaction(); final Transaction privateMarkerTransaction = createPrivateMarkerTransaction();
mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction);
final Hash rootHashOtherThanZero = Hash.wrap(Bytes32.fromHexStringLenient("1")); final Hash rootHashOtherThanZero = Hash.wrap(Bytes32.fromHexStringLenient("1"));
createPrivacyGroupHeadBlockInitialMapAndMetadata(PRIVACY_GROUP_BYTES, rootHashOtherThanZero); createPrivacyGroupHeadBlockInitialMapAndMetadata(PRIVACY_GROUP_BYTES, rootHashOtherThanZero);
@ -186,8 +186,8 @@ public class PrivateStorageMigrationTest {
@Test @Test
public void migrationReprocessBlocksWithPMT() { public void migrationReprocessBlocksWithPMT() {
final Transaction privacyMarkerTransaction = createPrivacyMarkerTransaction(); final Transaction privateMarkerTransaction = createPrivateMarkerTransaction();
mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction);
final Block blockWithPMT = blockchain.getBlockByNumber(1L).orElseThrow(); final Block blockWithPMT = blockchain.getBlockByNumber(1L).orElseThrow();
migration.migratePrivateStorage(); migration.migratePrivateStorage();
@ -208,7 +208,7 @@ public class PrivateStorageMigrationTest {
public void migrationOnlyProcessRequiredTransactions() { public void migrationOnlyProcessRequiredTransactions() {
final List<Transaction> transactions = new ArrayList<>(); final List<Transaction> transactions = new ArrayList<>();
transactions.add(publicTransaction()); transactions.add(publicTransaction());
transactions.add(createPrivacyMarkerTransaction()); transactions.add(createPrivateMarkerTransaction());
transactions.add(publicTransaction()); transactions.add(publicTransaction());
mockBlockchainWithTransactionsInABlock(transactions); mockBlockchainWithTransactionsInABlock(transactions);
@ -240,10 +240,10 @@ public class PrivateStorageMigrationTest {
return existingPgHeadMap; return existingPgHeadMap;
} }
private Transaction createPrivacyMarkerTransaction() { private Transaction createPrivateMarkerTransaction() {
final Transaction privacyMarkerTransaction = privacyMarkerTransaction(); final Transaction privateMarkerTransaction = privateMarkerTransaction();
mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); mockBlockchainWithPrivateMarkerTransaction(privateMarkerTransaction);
return privacyMarkerTransaction; return privateMarkerTransaction;
} }
private void mockBlockchainWithZeroTransactions() { private void mockBlockchainWithZeroTransactions() {
@ -265,7 +265,7 @@ public class PrivateStorageMigrationTest {
.thenReturn(Optional.of(EMPTY_ROOT_HASH)); .thenReturn(Optional.of(EMPTY_ROOT_HASH));
} }
private void mockBlockchainWithPrivacyMarkerTransaction(final Transaction transaction) { private void mockBlockchainWithPrivateMarkerTransaction(final Transaction transaction) {
final BlockDataGenerator blockDataGenerator = new BlockDataGenerator(); final BlockDataGenerator blockDataGenerator = new BlockDataGenerator();
final Block genesis = blockDataGenerator.genesisBlock(); final Block genesis = blockDataGenerator.genesisBlock();

Loading…
Cancel
Save