[PRIV] Unit tests around json rpc (#450)

* fix eea_sendRawTransaction test
* add priv_getPrivateTransaction test

Signed-off-by: Ivaylo Kirilov <iikirilov@gmail.com>
Co-authored-by: Lucas Saldanha <lucas.saldanha@consensys.net>
pull/457/head
Ivaylo Kirilov 5 years ago committed by GitHub
parent 52be1faf9c
commit ad5bfecd3f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java
  2. 215
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetPrivateTransactionTest.java
  3. 259
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/priv/PrivGetTransactionReceiptTest.java
  4. 150
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionDataFixture.java
  5. 5
      ethereum/core/src/test-support/java/org/hyperledger/besu/ethereum/core/PrivateTransactionTestFixture.java
  6. 5
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractTest.java
  7. 5
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateStorageMigrationTest.java
  8. 85
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/storage/migration/PrivateTransactionDataFixture.java

@ -27,6 +27,7 @@ import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1; import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.enclave.EnclaveClientException;
import org.hyperledger.besu.enclave.types.PrivacyGroup; 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;
@ -241,6 +242,10 @@ public class EeaSendRawTransactionTest {
when(privacyController.validatePrivateTransaction( when(privacyController.validatePrivateTransaction(
any(PrivateTransaction.class), any(String.class))) any(PrivateTransaction.class), any(String.class)))
.thenReturn(ValidationResult.valid()); .thenReturn(ValidationResult.valid());
when(privacyController.retrievePrivacyGroup(any(String.class), any(String.class)))
.thenThrow(new EnclaveClientException(0, ""));
when(privacyController.buildAndSendAddPayload(any(PrivateTransaction.class), any(String.class)))
.thenReturn(Optional.of(ENCLAVE_PUBLIC_KEY));
when(privacyController.createPrivacyMarkerTransaction( when(privacyController.createPrivacyMarkerTransaction(
any(String.class), any(PrivateTransaction.class), any(Address.class))) any(String.class), any(PrivateTransaction.class), any(Address.class)))
.thenReturn(PUBLIC_TRANSACTION); .thenReturn(PUBLIC_TRANSACTION);

@ -14,18 +14,16 @@
*/ */
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv; package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.VALID_BASE64_ENCLAVE_KEY;
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.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.enclave.Enclave; import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.EnclaveClientException; import org.hyperledger.besu.enclave.EnclaveClientException;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
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.privacy.methods.EnclavePublicKeyProvider; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
@ -38,27 +36,22 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.Privat
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionResult; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata; import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
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.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.math.BigInteger;
import java.util.Base64;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import io.vertx.core.json.JsonObject; import io.vertx.core.json.JsonObject;
import io.vertx.ext.auth.User; import io.vertx.ext.auth.User;
import io.vertx.ext.auth.jwt.impl.JWTUser; import io.vertx.ext.auth.jwt.impl.JWTUser;
import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
@ -68,162 +61,160 @@ public class PrivGetPrivateTransactionTest {
@Rule public final TemporaryFolder temp = new TemporaryFolder(); @Rule public final TemporaryFolder temp = new TemporaryFolder();
private final Address sender = private final PrivateTransaction privateContractDeploymentTransactionLegacy =
Address.fromHexString("0x0000000000000000000000000000000000000003"); PrivateTransactionDataFixture.privateContractDeploymentTransactionLegacy();
private static final SECP256K1.KeyPair KEY_PAIR = private final PrivateTransaction privateContractDeploymentTransactionBesu =
SECP256K1.KeyPair.create( PrivateTransactionDataFixture.privateContractDeploymentTransactionBesu();
SECP256K1.PrivateKey.create( private final Transaction markerTransaction =
new BigInteger( PrivateTransactionDataFixture.privacyMarkerTransaction();
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private static final String TRANSACTION_HASH =
Bytes.fromBase64String("5bpr9tz4zhmWmk9RlNng93Ky7lXwFkMc7+ckoFgUMku=").toString();
private static final Bytes ENCLAVE_KEY =
Bytes.fromBase64String("93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=");
private static final List<Bytes> TEST_PRIVATE_FOR =
Collections.singletonList(
Bytes.fromBase64String("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="));
private final PrivateTransaction.Builder privateTransactionBuilder =
PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(null)
.value(Wei.ZERO)
.payload(
Bytes.fromHexString(
"0x608060405234801561001057600080fd5b5060d08061001f60003960"
+ "00f3fe60806040526004361060485763ffffffff7c01000000"
+ "00000000000000000000000000000000000000000000000000"
+ "60003504166360fe47b18114604d5780636d4ce63c14607557"
+ "5b600080fd5b348015605857600080fd5b5060736004803603"
+ "6020811015606d57600080fd5b50356099565b005b34801560"
+ "8057600080fd5b506087609e565b6040805191825251908190"
+ "0360200190f35b600055565b6000549056fea165627a7a7230"
+ "5820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6"
+ "daa4f6b2f003d1b0180029"))
.sender(sender)
.chainId(BigInteger.valueOf(2018))
.privateFrom(Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.restriction(Restriction.RESTRICTED);
private final Enclave enclave = mock(Enclave.class); private final Enclave enclave = mock(Enclave.class);
private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class); private final PrivacyParameters privacyParameters = mock(PrivacyParameters.class);
private final PrivateStateStorage privateStateStorage = mock(PrivateStateStorage.class); private final PrivateStateStorage privateStateStorage = mock(PrivateStateStorage.class);
private final BlockchainQueries blockchain = mock(BlockchainQueries.class); private final BlockchainQueries blockchain = mock(BlockchainQueries.class);
private final TransactionWithMetadata returnedTransaction = mock(TransactionWithMetadata.class); private final TransactionWithMetadata returnedTransaction = mock(TransactionWithMetadata.class);
private final Transaction justTransaction = mock(Transaction.class);
private final PrivacyController privacyController = mock(PrivacyController.class); private final PrivacyController privacyController = mock(PrivacyController.class);
private final User user = private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), ""); new JWTUser(
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY; new JsonObject().put("privacyPublicKey", VALID_BASE64_ENCLAVE_KEY.toBase64String()), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider =
(user) -> VALID_BASE64_ENCLAVE_KEY.toBase64String();
@Before @Before
public void before() { public void before() {
when(privacyParameters.getEnclave()).thenReturn(enclave); when(privacyParameters.getEnclave()).thenReturn(enclave);
when(privacyParameters.isEnabled()).thenReturn(true); when(privacyParameters.isEnabled()).thenReturn(true);
when(returnedTransaction.getBlockHash()).thenReturn(Optional.of(Hash.ZERO)); when(returnedTransaction.getBlockHash()).thenReturn(Optional.of(Hash.ZERO));
}
@Test
public void returnsPrivateTransactionLegacy() {
when(blockchain.transactionByHash(any(Hash.class))) when(blockchain.transactionByHash(any(Hash.class)))
.thenReturn(Optional.of(returnedTransaction)); .thenReturn(Optional.of(returnedTransaction));
when(returnedTransaction.getTransaction()).thenReturn(justTransaction); when(returnedTransaction.getTransaction()).thenReturn(markerTransaction);
when(justTransaction.getPayload()).thenReturn(ENCLAVE_KEY); }
final PrivateTransaction privateTransaction = @Test
privateTransactionBuilder.privateFor(TEST_PRIVATE_FOR).signAndBuild(KEY_PAIR); public void returnsPrivateTransactionLegacy() {
final PrivateTransactionLegacyResult privateTransactionLegacyResult = final PrivateTransactionLegacyResult privateTransactionLegacyResult =
new PrivateTransactionLegacyResult(privateTransaction); new PrivateTransactionLegacyResult(privateContractDeploymentTransactionLegacy);
when(privacyController.retrieveTransaction(anyString(), any()))
.thenReturn(
PrivateTransactionDataFixture.generateReceiveResponse(
privateContractDeploymentTransactionLegacy));
final JsonRpcRequestContext request = createRequestContext();
final PrivateTransactionResult result = makeRequest(request);
assertThat(result).isEqualToComparingFieldByField(privateTransactionLegacyResult);
verify(privacyController)
.retrieveTransaction(
markerTransaction.getPayload().toBase64String(),
VALID_BASE64_ENCLAVE_KEY.toBase64String());
}
protected PrivateTransactionResult makeRequest(final JsonRpcRequestContext request) {
final PrivGetPrivateTransaction privGetPrivateTransaction = final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction( new PrivGetPrivateTransaction(
blockchain, privacyController, privateStateStorage, enclavePublicKeyProvider); blockchain, privacyController, privateStateStorage, enclavePublicKeyProvider);
final Object[] params = new Object[] {TRANSACTION_HASH};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getPrivateTransaction", params), user);
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
when(privacyController.retrieveTransaction(anyString(), any()))
.thenReturn(
new ReceiveResponse(
Base64.getEncoder().encodeToString(bvrlp.encoded().toArray()).getBytes(UTF_8),
"",
null));
final JsonRpcSuccessResponse response = final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetPrivateTransaction.response(request); (JsonRpcSuccessResponse) privGetPrivateTransaction.response(request);
final PrivateTransactionResult result = (PrivateTransactionResult) response.getResult(); return (PrivateTransactionResult) response.getResult();
assertThat(result).isEqualToComparingFieldByField(privateTransactionLegacyResult);
verify(privacyController).retrieveTransaction(ENCLAVE_KEY.toBase64String(), ENCLAVE_PUBLIC_KEY);
} }
@Test @Test
public void returnsPrivateTransactionGroup() { public void returnsPrivateTransactionGroup() {
when(blockchain.transactionByHash(any(Hash.class))) final PrivateTransactionGroupResult privateTransactionGroupResult =
.thenReturn(Optional.of(returnedTransaction)); new PrivateTransactionGroupResult(privateContractDeploymentTransactionBesu);
when(returnedTransaction.getTransaction()).thenReturn(justTransaction);
when(justTransaction.getPayload()).thenReturn(ENCLAVE_KEY); final JsonRpcRequestContext request = createRequestContext();
when(privacyController.retrieveTransaction(anyString(), any()))
.thenReturn(
PrivateTransactionDataFixture.generateReceiveResponse(
privateContractDeploymentTransactionBesu));
final PrivateTransactionResult result = makeRequest(request);
assertThat(result).isEqualToComparingFieldByField(privateTransactionGroupResult);
}
final PrivateTransaction privateTransaction = @Test
privateTransactionBuilder.privacyGroupId(ENCLAVE_KEY).signAndBuild(KEY_PAIR); public void returnsPrivateTransactionOnChain() {
final PrivateTransactionGroupResult privateTransactionGroupResult = final PrivateTransactionGroupResult privateTransactionGroupResult =
new PrivateTransactionGroupResult(privateTransaction); new PrivateTransactionGroupResult(privateContractDeploymentTransactionBesu);
final PrivGetPrivateTransaction privGetPrivateTransaction = when(privacyController.retrieveTransaction(anyString(), any()))
new PrivGetPrivateTransaction( .thenReturn(
blockchain, privacyController, privateStateStorage, enclavePublicKeyProvider); PrivateTransactionDataFixture.generateVersionedReceiveResponse(
privateContractDeploymentTransactionBesu));
final JsonRpcRequestContext request = createRequestContext();
final PrivateTransactionResult result = makeRequest(request);
final Object[] params = new Object[] {TRANSACTION_HASH}; assertThat(result).isEqualToComparingFieldByField(privateTransactionGroupResult);
final JsonRpcRequestContext request = }
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getPrivateTransaction", params));
@Test
public void returnsPrivateTransactionOnChainFromBlob() {
final PrivateTransactionGroupResult privateTransactionGroupResult =
new PrivateTransactionGroupResult(privateContractDeploymentTransactionBesu);
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput(); when(privateStateStorage.getPrivacyGroupHeadBlockMap(any(Bytes32.class)))
privateTransaction.writeTo(bvrlp); .thenReturn(
Optional.of(
new PrivacyGroupHeadBlockMap(Collections.singletonMap(Bytes32.ZERO, Hash.ZERO))));
when(privateStateStorage.getAddDataKey(any(Bytes32.class)))
.thenReturn(Optional.of(Bytes32.ZERO));
when(privacyController.retrieveTransaction(anyString(), any())) when(privacyController.retrieveTransaction(anyString(), any()))
.thenThrow(new EnclaveClientException(0, "EnclavePayloadNotFound"));
when(privacyController.retrieveAddBlob(anyString()))
.thenReturn( .thenReturn(
new ReceiveResponse( PrivateTransactionDataFixture.generateAddBlobResponse(
Base64.getEncoder().encodeToString(bvrlp.encoded().toArrayUnsafe()).getBytes(UTF_8), privateContractDeploymentTransactionBesu, markerTransaction));
"",
null));
final JsonRpcSuccessResponse response = final JsonRpcRequestContext request = createRequestContext();
(JsonRpcSuccessResponse) privGetPrivateTransaction.response(request);
final PrivateTransactionResult result = (PrivateTransactionResult) response.getResult(); final PrivateTransactionResult result = makeRequest(request);
assertThat(result).isEqualToComparingFieldByField(privateTransactionGroupResult); assertThat(result).isEqualToComparingFieldByField(privateTransactionGroupResult);
} }
@Test @Test
public void failsWithEnclaveErrorOnEnclaveError() { public void returnNullWhenPrivateMarkerTransactionDoesNotExist() {
when(blockchain.transactionByHash(any(Hash.class))) when(blockchain.transactionByHash(any(Hash.class))).thenReturn(Optional.empty());
.thenReturn(Optional.of(returnedTransaction));
when(returnedTransaction.getTransaction()).thenReturn(justTransaction);
when(justTransaction.getPayload()).thenReturn(ENCLAVE_KEY);
final PrivateTransaction privateTransaction = final JsonRpcRequestContext request = createRequestContext();
privateTransactionBuilder.privacyGroupId(ENCLAVE_KEY).signAndBuild(KEY_PAIR);
final PrivGetPrivateTransaction privGetPrivateTransaction = final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction( new PrivGetPrivateTransaction(
blockchain, privacyController, privateStateStorage, enclavePublicKeyProvider); blockchain, privacyController, privateStateStorage, enclavePublicKeyProvider);
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetPrivateTransaction.response(request);
final Object[] params = new Object[] {TRANSACTION_HASH}; assertThat(response.getResult()).isNull();
final JsonRpcRequestContext request = }
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getPrivateTransaction", params));
@Test
public void failsWithEnclaveErrorOnEnclaveError() {
final JsonRpcRequestContext request = createRequestContext();
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
when(privacyController.retrieveTransaction(anyString(), any())) when(privacyController.retrieveTransaction(anyString(), any()))
.thenThrow(new EnclaveClientException(500, "enclave failure")); .thenThrow(new EnclaveClientException(500, "enclave failure"));
final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction(
blockchain, privacyController, privateStateStorage, enclavePublicKeyProvider);
final JsonRpcResponse response = privGetPrivateTransaction.response(request); final JsonRpcResponse response = privGetPrivateTransaction.response(request);
final JsonRpcResponse expectedResponse = final JsonRpcResponse expectedResponse =
new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.ENCLAVE_ERROR); new JsonRpcErrorResponse(request.getRequest().getId(), JsonRpcError.ENCLAVE_ERROR);
assertThat(response).isEqualTo(expectedResponse); assertThat(response).isEqualTo(expectedResponse);
} }
private JsonRpcRequestContext createRequestContext() {
final Object[] params = new Object[] {markerTransaction.getHash()};
return new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getTransactionReceipt", params), user);
}
} }

@ -14,9 +14,11 @@
*/ */
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv; package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat; import static org.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_CONTRACT_DEPLOYMENT_ADDRESS;
import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.generateReceiveResponse;
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.nullable; import static org.mockito.ArgumentMatchers.nullable;
@ -25,10 +27,8 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.enclave.EnclaveClientException; import org.hyperledger.besu.enclave.EnclaveClientException;
import org.hyperledger.besu.enclave.EnclaveServerException; import org.hyperledger.besu.enclave.EnclaveServerException;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.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.privacy.methods.EnclavePublicKeyProvider; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.EnclavePublicKeyProvider;
@ -43,17 +43,14 @@ import org.hyperledger.besu.ethereum.core.BlockBody;
import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Hash; import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.PrivacyParameters; import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture;
import org.hyperledger.besu.ethereum.core.Transaction; import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
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.PrivateTransactionReceipt; import org.hyperledger.besu.ethereum.privacy.PrivateTransactionReceipt;
import org.hyperledger.besu.ethereum.privacy.Restriction; import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.math.BigInteger;
import java.util.Base64;
import java.util.Collections; import java.util.Collections;
import java.util.Optional; import java.util.Optional;
@ -71,77 +68,18 @@ public class PrivGetTransactionReceiptTest {
@Rule public final TemporaryFolder temp = new TemporaryFolder(); @Rule public final TemporaryFolder temp = new TemporaryFolder();
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="; private final PrivateTransaction privateContractDeploymentTransactionLegacy =
private static final Bytes ENCLAVE_KEY = PrivateTransactionDataFixture.privateContractDeploymentTransactionLegacy();
Bytes.wrap("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs=".getBytes(UTF_8)); private final PrivateTransaction privateContractDeploymentTransactionBesu =
private static final Address SENDER = PrivateTransactionDataFixture.privateContractDeploymentTransactionBesu();
Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"); private final Transaction markerTransaction =
PrivateTransactionDataFixture.privacyMarkerTransaction();
private static final SECP256K1.KeyPair KEY_PAIR =
SECP256K1.KeyPair.create(
SECP256K1.PrivateKey.create(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private final PrivateTransaction privateTransaction =
PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(null)
.value(Wei.ZERO)
.payload(
Bytes.fromHexString(
"0x608060405234801561001057600080fd5b5060d08061001f60003960"
+ "00f3fe60806040526004361060485763ffffffff7c01000000"
+ "00000000000000000000000000000000000000000000000000"
+ "60003504166360fe47b18114604d5780636d4ce63c14607557"
+ "5b600080fd5b348015605857600080fd5b5060736004803603"
+ "6020811015606d57600080fd5b50356099565b005b34801560"
+ "8057600080fd5b506087609e565b6040805191825251908190"
+ "0360200190f35b600055565b6000549056fea165627a7a7230"
+ "5820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6"
+ "daa4f6b2f003d1b0180029"))
.sender(SENDER)
.chainId(BigInteger.valueOf(2018))
.privateFrom(Bytes.fromBase64String(ENCLAVE_PUBLIC_KEY))
.privateFor(Collections.singletonList(ENCLAVE_KEY))
.restriction(Restriction.RESTRICTED)
.signAndBuild(KEY_PAIR);
private final Transaction transaction =
Transaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(Address.DEFAULT_PRIVACY)
.value(Wei.ZERO)
.payload(ENCLAVE_KEY)
.sender(SENDER)
.chainId(BigInteger.valueOf(2018))
.signAndBuild(KEY_PAIR);
private final PrivateTransactionReceiptResult expectedResult =
new PrivateTransactionReceiptResult(
"0x0bac79b78b9866ef11c989ad21a7fcf15f7a18d7",
SENDER.toHexString(),
null,
Collections.emptyList(),
Bytes.EMPTY,
null,
0,
0,
transaction.getHash(),
privateTransaction.getHash(),
Bytes.fromBase64String(ENCLAVE_PUBLIC_KEY),
Collections.singletonList(ENCLAVE_KEY),
null,
null,
Quantity.create(Bytes.of(1).toUnsignedBigInteger()));
private final User user = private final User user =
new JWTUser(new JsonObject().put("privacyPublicKey", ENCLAVE_PUBLIC_KEY), ""); new JWTUser(
private final EnclavePublicKeyProvider enclavePublicKeyProvider = (user) -> ENCLAVE_PUBLIC_KEY; new JsonObject().put("privacyPublicKey", VALID_BASE64_ENCLAVE_KEY.toBase64String()), "");
private final EnclavePublicKeyProvider enclavePublicKeyProvider =
(user) -> VALID_BASE64_ENCLAVE_KEY.toBase64String();
private final BlockchainQueries blockchainQueries = mock(BlockchainQueries.class); private final BlockchainQueries blockchainQueries = mock(BlockchainQueries.class);
private final Blockchain blockchain = mock(Blockchain.class); private final Blockchain blockchain = mock(Blockchain.class);
@ -151,20 +89,12 @@ public class PrivGetTransactionReceiptTest {
@Before @Before
public void setUp() { public void setUp() {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
rlpOutput.startList();
privateTransaction.writeTo(rlpOutput);
rlpOutput.endList();
final byte[] src = rlpOutput.encoded().toArray();
when(privacyController.retrieveTransaction(anyString(), anyString()))
.thenReturn(new ReceiveResponse(Base64.getEncoder().encode(src), "", null));
when(blockchainQueries.getBlockchain()).thenReturn(blockchain); when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
final TransactionLocation transactionLocation = new TransactionLocation(Hash.EMPTY, 0); final TransactionLocation transactionLocation = new TransactionLocation(Hash.EMPTY, 0);
when(blockchain.getTransactionLocation(nullable(Hash.class))) when(blockchain.getTransactionLocation(nullable(Hash.class)))
.thenReturn(Optional.of(transactionLocation)); .thenReturn(Optional.of(transactionLocation));
final BlockBody blockBody = final BlockBody blockBody =
new BlockBody(Collections.singletonList(transaction), Collections.emptyList()); new BlockBody(Collections.singletonList(markerTransaction), Collections.emptyList());
when(blockchain.getBlockBody(any(Hash.class))).thenReturn(Optional.of(blockBody)); when(blockchain.getBlockBody(any(Hash.class))).thenReturn(Optional.of(blockBody));
final BlockHeader mockBlockHeader = mock(BlockHeader.class); final BlockHeader mockBlockHeader = mock(BlockHeader.class);
when(blockchain.getBlockHeader(any(Hash.class))).thenReturn(Optional.of(mockBlockHeader)); when(blockchain.getBlockHeader(any(Hash.class))).thenReturn(Optional.of(mockBlockHeader));
@ -172,34 +102,60 @@ public class PrivGetTransactionReceiptTest {
when(privacyParameters.isEnabled()).thenReturn(true); when(privacyParameters.isEnabled()).thenReturn(true);
when(privacyParameters.getPrivateStateStorage()).thenReturn(privateStateStorage); when(privacyParameters.getPrivateStateStorage()).thenReturn(privateStateStorage);
@SuppressWarnings("unchecked")
final PrivateTransactionReceipt receipt = final PrivateTransactionReceipt receipt =
new PrivateTransactionReceipt( new PrivateTransactionReceipt(1, Collections.emptyList(), Bytes.EMPTY, Optional.empty());
1, Collections.EMPTY_LIST, Bytes.EMPTY, Optional.ofNullable(null));
when(privateStateStorage.getTransactionReceipt(any(Bytes32.class), any(Bytes32.class))) when(privateStateStorage.getTransactionReceipt(any(Bytes32.class), any(Bytes32.class)))
.thenReturn(Optional.of(receipt)); .thenReturn(Optional.of(receipt));
} }
@Test @Test
public void returnReceiptIfTransactionExists() { public void returnReceiptIfTransactionExists() {
final PrivateTransactionReceiptResult expectedResult =
privateTransactionReceiptResultFor(
privateContractDeploymentTransactionLegacy, markerTransaction);
final PrivGetTransactionReceipt privGetTransactionReceipt = when(privacyController.retrieveTransaction(anyString(), anyString()))
new PrivGetTransactionReceipt( .thenReturn(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider); PrivateTransactionDataFixture.generateReceiveResponse(
final Object[] params = new Object[] {transaction.getHash()}; privateContractDeploymentTransactionLegacy));
final JsonRpcRequestContext request =
new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getTransactionReceipt", params), user);
final JsonRpcSuccessResponse response = executeAndVerifyCall(expectedResult, 2);
(JsonRpcSuccessResponse) privGetTransactionReceipt.response(request); }
final PrivateTransactionReceiptResult result =
(PrivateTransactionReceiptResult) response.getResult();
assertThat(result).isEqualToComparingFieldByField(expectedResult); @Test
verify(privacyController, times(2)) public void returnReceiptForVersionedOnChainTransaction() {
.retrieveTransaction( final PrivateTransactionReceiptResult expectedResult =
transaction.getPayload().slice(0, 32).toBase64String(), ENCLAVE_PUBLIC_KEY); privateTransactionReceiptResultFor(
privateContractDeploymentTransactionBesu, markerTransaction);
when(privacyController.retrieveTransaction(anyString(), anyString()))
.thenReturn(
PrivateTransactionDataFixture.generateVersionedReceiveResponse(
privateContractDeploymentTransactionBesu));
executeAndVerifyCall(expectedResult, 1);
}
@Test
public void returnReceiptIfTransactionExistsInBlob() {
final PrivateTransactionReceiptResult expectedResult =
privateTransactionReceiptResultFor(
privateContractDeploymentTransactionBesu, markerTransaction);
when(privacyController.retrieveTransaction(anyString(), anyString()))
.thenThrow(new EnclaveClientException(0, "EnclavePayloadNotFound"));
when(privateStateStorage.getPrivacyGroupHeadBlockMap(any(Bytes32.class)))
.thenReturn(
Optional.of(
new PrivacyGroupHeadBlockMap(Collections.singletonMap(Bytes32.ZERO, Hash.ZERO))));
when(privateStateStorage.getAddDataKey(any(Bytes32.class)))
.thenReturn(Optional.of(Bytes32.ZERO));
when(privacyController.retrieveAddBlob(anyString()))
.thenReturn(
PrivateTransactionDataFixture.generateAddBlobResponse(
privateContractDeploymentTransactionBesu, markerTransaction));
executeAndVerifyCall(expectedResult, 1);
} }
@Test @Test
@ -207,13 +163,11 @@ public class PrivGetTransactionReceiptTest {
when(privacyController.retrieveTransaction(anyString(), any())) when(privacyController.retrieveTransaction(anyString(), any()))
.thenThrow(new EnclaveClientException(404, "EnclavePayloadNotFound")); .thenThrow(new EnclaveClientException(404, "EnclavePayloadNotFound"));
final JsonRpcRequestContext request = createRequestContext();
final PrivGetTransactionReceipt privGetTransactionReceipt = final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt( new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider); blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
final JsonRpcSuccessResponse response = final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetTransactionReceipt.response(request); (JsonRpcSuccessResponse) privGetTransactionReceipt.response(request);
final PrivateTransactionReceiptResult result = final PrivateTransactionReceiptResult result =
@ -226,13 +180,11 @@ public class PrivGetTransactionReceiptTest {
public void markerTransactionNotAvailableResultsInNullResponse() { public void markerTransactionNotAvailableResultsInNullResponse() {
when(blockchain.getTransactionLocation(nullable(Hash.class))).thenReturn(Optional.empty()); when(blockchain.getTransactionLocation(nullable(Hash.class))).thenReturn(Optional.empty());
final JsonRpcRequestContext request = createRequestContext();
final PrivGetTransactionReceipt privGetTransactionReceipt = final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt( new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider); blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
final JsonRpcSuccessResponse response = final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetTransactionReceipt.response(request); (JsonRpcSuccessResponse) privGetTransactionReceipt.response(request);
final PrivateTransactionReceiptResult result = final PrivateTransactionReceiptResult result =
@ -245,38 +197,36 @@ public class PrivGetTransactionReceiptTest {
public void enclaveConnectionIssueThrowsRuntimeException() { public void enclaveConnectionIssueThrowsRuntimeException() {
when(privacyController.retrieveTransaction(anyString(), any())) when(privacyController.retrieveTransaction(anyString(), any()))
.thenThrow(EnclaveServerException.class); .thenThrow(EnclaveServerException.class);
final JsonRpcRequestContext request = createRequestContext();
final PrivGetTransactionReceipt privGetTransactionReceipt = final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt( new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider); blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
final Throwable t = catchThrowable(() -> privGetTransactionReceipt.response(request)); final Throwable t = catchThrowable(() -> privGetTransactionReceipt.response(request));
assertThat(t).isInstanceOf(RuntimeException.class); assertThat(t).isInstanceOf(RuntimeException.class);
} }
@Test @Test
public void transactionReceiptContainsRevertReasonWhenInvalidTransactionOccurs() { public void transactionReceiptContainsRevertReasonWhenInvalidTransactionOccurs() {
@SuppressWarnings("unchecked") when(privacyController.retrieveTransaction(anyString(), anyString()))
.thenReturn(generateReceiveResponse(privateContractDeploymentTransactionLegacy));
final PrivateTransactionReceipt privateTransactionReceipt = final PrivateTransactionReceipt privateTransactionReceipt =
new PrivateTransactionReceipt( new PrivateTransactionReceipt(
1, 1,
Collections.EMPTY_LIST, Collections.emptyList(),
Bytes.EMPTY, Bytes.EMPTY,
Optional.of(Bytes.wrap(new byte[] {(byte) 0x01}))); Optional.of(Bytes.wrap(new byte[] {(byte) 0x01})));
when(privateStateStorage.getTransactionReceipt(any(Bytes32.class), any(Bytes32.class))) when(privateStateStorage.getTransactionReceipt(any(Bytes32.class), any(Bytes32.class)))
.thenReturn(Optional.of(privateTransactionReceipt)); .thenReturn(Optional.of(privateTransactionReceipt));
final JsonRpcRequestContext request = createRequestContext();
final PrivGetTransactionReceipt privGetTransactionReceipt = final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt( new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider); blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequest request = new JsonRpcRequest("1", "priv_getTransactionReceipt", params);
final JsonRpcSuccessResponse response = final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) (JsonRpcSuccessResponse) privGetTransactionReceipt.response(request);
privGetTransactionReceipt.response(new JsonRpcRequestContext(request));
final PrivateTransactionReceiptResult result = final PrivateTransactionReceiptResult result =
(PrivateTransactionReceiptResult) response.getResult(); (PrivateTransactionReceiptResult) response.getResult();
@ -289,15 +239,70 @@ public class PrivGetTransactionReceiptTest {
when(privacyController.retrieveTransaction(any(), any())) when(privacyController.retrieveTransaction(any(), any()))
.thenThrow(new EnclaveClientException(400, keysCannotDecryptPayloadMsg)); .thenThrow(new EnclaveClientException(400, keysCannotDecryptPayloadMsg));
final JsonRpcRequestContext request = createRequestContext();
final PrivGetTransactionReceipt privGetTransactionReceipt = final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt( new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider); blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final Object[] params = new Object[] {transaction.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getTransactionReceipt", params));
final Throwable t = catchThrowable(() -> privGetTransactionReceipt.response(request)); final Throwable t = catchThrowable(() -> privGetTransactionReceipt.response(request));
assertThat(t).isInstanceOf(EnclaveClientException.class); assertThat(t).isInstanceOf(EnclaveClientException.class);
assertThat(t.getMessage()).isEqualTo(keysCannotDecryptPayloadMsg); assertThat(t.getMessage()).isEqualTo(keysCannotDecryptPayloadMsg);
} }
private PrivateTransactionReceiptResult privateTransactionReceiptResultFor(
final PrivateTransaction privateTransaction, final Transaction markerTransaction) {
return new PrivateTransactionReceiptResult(
privateTransaction.getPrivacyGroupId().isPresent()
? Address.privateContractAddress(
privateTransaction.getSender(),
privateTransaction.getNonce(),
privateTransaction.getPrivacyGroupId().get())
.toHexString()
: VALID_CONTRACT_DEPLOYMENT_ADDRESS.toHexString(),
privateTransaction.getSender().toHexString(),
null,
Collections.emptyList(),
Bytes.EMPTY,
null,
0,
0,
markerTransaction.getHash(),
privateTransaction.getHash(),
privateTransaction.getPrivateFrom(),
privateTransaction.getPrivateFor().isPresent()
? privateTransaction.getPrivateFor().get()
: null,
privateTransaction.getPrivacyGroupId().isPresent()
? privateTransaction.getPrivacyGroupId().get()
: null,
null,
Quantity.create(Bytes.of(1).toUnsignedBigInteger()));
}
private void executeAndVerifyCall(
final PrivateTransactionReceiptResult expectedResult, final int i) {
final PrivGetTransactionReceipt privGetTransactionReceipt =
new PrivGetTransactionReceipt(
blockchainQueries, privacyParameters, privacyController, enclavePublicKeyProvider);
final JsonRpcRequestContext request = createRequestContext();
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetTransactionReceipt.response(request);
final PrivateTransactionReceiptResult result =
(PrivateTransactionReceiptResult) response.getResult();
assertThat(result).isEqualToComparingFieldByField(expectedResult);
verify(privacyController, times(i))
.retrieveTransaction(
markerTransaction.getPayload().toBase64String(),
VALID_BASE64_ENCLAVE_KEY.toBase64String());
}
private JsonRpcRequestContext createRequestContext() {
final Object[] params = new Object[] {markerTransaction.getHash()};
return new JsonRpcRequestContext(
new JsonRpcRequest("1", "priv_getTransactionReceipt", params), user);
}
} }

@ -0,0 +1,150 @@
/*
* 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.core;
import static java.nio.charset.StandardCharsets.UTF_8;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionWithMetadata;
import org.hyperledger.besu.ethereum.privacy.VersionedPrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateTransactionMetadata;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
public class PrivateTransactionDataFixture {
public static final long DEFAULT_NONCE = 0;
public static final Wei DEFAULT_GAS_PRICE = Wei.of(1000);
public static final long DEFAULT_GAS_LIMIT = 3000000;
public static final Wei DEFAULT_VALUE = Wei.of(0);
public static final Address DEFAULT_SENDER =
Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73");
public static final BigInteger DEFAULT_CHAIN_ID = BigInteger.valueOf(2018);
public static final SECP256K1.KeyPair KEY_PAIR =
SECP256K1.KeyPair.create(
SECP256K1.PrivateKey.create(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
public static final Bytes VALID_BASE64_ENCLAVE_KEY =
Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=");
public static final Bytes VALID_CONTRACT_DEPLOYMENT_PAYLOAD =
Bytes.fromHexString(
"0x608060405234801561001057600080fd5b5060d08061001f60003960"
+ "00f3fe60806040526004361060485763ffffffff7c01000000"
+ "00000000000000000000000000000000000000000000000000"
+ "60003504166360fe47b18114604d5780636d4ce63c14607557"
+ "5b600080fd5b348015605857600080fd5b5060736004803603"
+ "6020811015606d57600080fd5b50356099565b005b34801560"
+ "8057600080fd5b506087609e565b6040805191825251908190"
+ "0360200190f35b600055565b6000549056fea165627a7a7230"
+ "5820cb1d0935d14b589300b12fcd0ab849a7e9019c81da24d6"
+ "daa4f6b2f003d1b0180029");
public static final Address VALID_CONTRACT_DEPLOYMENT_ADDRESS =
Address.fromHexString("0x0bac79b78b9866ef11c989ad21a7fcf15f7a18d7");
public static Transaction privacyMarkerTransaction() {
return privacyMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.DEFAULT_PRIVACY);
}
public static Transaction privacyMarkerTransactionOnChain() {
return privacyMarkerTransaction(VALID_BASE64_ENCLAVE_KEY, Address.ONCHAIN_PRIVACY);
}
public static Transaction privacyMarkerTransactionOnChainAdd() {
return privacyMarkerTransaction(
Bytes.concatenate(VALID_BASE64_ENCLAVE_KEY, VALID_BASE64_ENCLAVE_KEY),
Address.ONCHAIN_PRIVACY);
}
private static Transaction privacyMarkerTransaction(
final Bytes transactionKey, final Address precompiledContractAddress) {
return Transaction.builder()
.nonce(DEFAULT_NONCE)
.gasPrice(DEFAULT_GAS_PRICE)
.gasLimit(DEFAULT_GAS_LIMIT)
.to(precompiledContractAddress)
.value(DEFAULT_VALUE)
.payload(transactionKey)
.sender(DEFAULT_SENDER)
.chainId(DEFAULT_CHAIN_ID)
.signAndBuild(KEY_PAIR);
}
public static PrivateTransaction privateContractDeploymentTransactionLegacy() {
return new PrivateTransactionTestFixture()
.payload(VALID_CONTRACT_DEPLOYMENT_PAYLOAD)
.privateFor(Collections.singletonList(VALID_BASE64_ENCLAVE_KEY))
.createTransaction(KEY_PAIR);
}
public static PrivateTransaction privateTransactionBesu() {
return new PrivateTransactionTestFixture()
.privacyGroupId(VALID_BASE64_ENCLAVE_KEY)
.createTransaction(KEY_PAIR);
}
public static PrivateTransaction privateContractDeploymentTransactionBesu() {
return new PrivateTransactionTestFixture()
.payload(VALID_CONTRACT_DEPLOYMENT_PAYLOAD)
.privacyGroupId(VALID_BASE64_ENCLAVE_KEY)
.createTransaction(KEY_PAIR);
}
public static ReceiveResponse generateReceiveResponse(
final PrivateTransaction privateTransaction) {
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
privateTransaction.writeTo(rlpOutput);
return new ReceiveResponse(
rlpOutput.encoded().toBase64String().getBytes(UTF_8),
privateTransaction.getPrivacyGroupId().isPresent()
? privateTransaction.getPrivacyGroupId().get().toBase64String()
: "",
null);
}
public static ReceiveResponse generateVersionedReceiveResponse(
final PrivateTransaction privateTransaction) {
final VersionedPrivateTransaction versionedPrivateTransaction =
new VersionedPrivateTransaction(privateTransaction, Bytes32.ZERO);
final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput();
versionedPrivateTransaction.writeTo(rlpOutput);
return new ReceiveResponse(
rlpOutput.encoded().toBase64String().getBytes(UTF_8),
privateTransaction.getPrivacyGroupId().isPresent()
? privateTransaction.getPrivacyGroupId().get().toBase64String()
: "",
null);
}
public static List<PrivateTransactionWithMetadata> generateAddBlobResponse(
final PrivateTransaction privateTransaction, final Transaction markerTransaction) {
final PrivateTransactionWithMetadata privateTransactionWithMetadata =
new PrivateTransactionWithMetadata(
privateTransaction,
new PrivateTransactionMetadata(markerTransaction.getHash(), Hash.ZERO));
return Collections.singletonList(privateTransactionWithMetadata);
}
}

@ -34,7 +34,8 @@ public class PrivateTransactionTestFixture {
private long gasLimit = 5000; private long gasLimit = 5000;
private Optional<Address> to = Optional.empty(); private Optional<Address> to = Optional.empty();
private Address sender = Address.fromHexString(String.format("%020x", 1));
private Address sender = Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73");
private Wei value = Wei.of(0); private Wei value = Wei.of(0);
@ -70,7 +71,7 @@ public class PrivateTransactionTestFixture {
chainId.ifPresent(builder::chainId); chainId.ifPresent(builder::chainId);
if (privacyGroupId.isPresent()) { if (privacyGroupId.isPresent()) {
this.privacyGroupId(privacyGroupId.get()); privacyGroupId.ifPresent(builder::privacyGroupId);
} else { } else {
privateFor.ifPresent(builder::privateFor); privateFor.ifPresent(builder::privateFor);
} }

@ -30,6 +30,7 @@ import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator; import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.Log; import org.hyperledger.besu.ethereum.core.Log;
import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture;
import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader; import org.hyperledger.besu.ethereum.core.ProcessableBlockHeader;
import org.hyperledger.besu.ethereum.core.WorldUpdater; import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.mainnet.SpuriousDragonGasCalculator; import org.hyperledger.besu.ethereum.mainnet.SpuriousDragonGasCalculator;
@ -37,7 +38,6 @@ import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor; import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap; import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.privacy.storage.migration.PrivateTransactionDataFixture;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.BlockHashLookup;
import org.hyperledger.besu.ethereum.vm.MessageFrame; import org.hyperledger.besu.ethereum.vm.MessageFrame;
@ -133,8 +133,7 @@ public class PrivacyPrecompiledContractTest {
contract.setPrivateTransactionProcessor(mockPrivateTxProcessor()); contract.setPrivateTransactionProcessor(mockPrivateTxProcessor());
BytesValueRLPOutput bytesValueRLPOutput = new BytesValueRLPOutput(); BytesValueRLPOutput bytesValueRLPOutput = new BytesValueRLPOutput();
PrivateTransactionDataFixture.privateTransaction(PAYLOAD_TEST_PRIVACY_GROUP_ID) PrivateTransactionDataFixture.privateTransactionBesu().writeTo(bytesValueRLPOutput);
.writeTo(bytesValueRLPOutput);
final ReceiveResponse response = final ReceiveResponse response =
new ReceiveResponse( new ReceiveResponse(

@ -16,10 +16,10 @@ 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.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;
import static org.hyperledger.besu.ethereum.privacy.storage.migration.PrivateTransactionDataFixture.privacyMarkerTransaction;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
@ -73,7 +73,6 @@ public class PrivateStorageMigrationTest {
public static final Bytes32 PRIVACY_GROUP_BYTES = public static final Bytes32 PRIVACY_GROUP_BYTES =
Bytes32.wrap(Bytes.fromBase64String(PRIVACY_GROUP_ID)); Bytes32.wrap(Bytes.fromBase64String(PRIVACY_GROUP_ID));
private static final Address PRIVACY_ADDRESS = Address.DEFAULT_PRIVACY; private static final Address PRIVACY_ADDRESS = Address.DEFAULT_PRIVACY;
private static final String TRANSACTION_KEY = "93Ky7lXwFkMc7+ckoFgUMku5bpr9tz4zhmWmk9RlNng=";
@Mock private Blockchain blockchain; @Mock private Blockchain blockchain;
@Mock private ProtocolSchedule<?> protocolSchedule; @Mock private ProtocolSchedule<?> protocolSchedule;
@ -231,7 +230,7 @@ public class PrivateStorageMigrationTest {
} }
private Transaction createPrivacyMarkerTransaction() { private Transaction createPrivacyMarkerTransaction() {
final Transaction privacyMarkerTransaction = privacyMarkerTransaction(TRANSACTION_KEY); final Transaction privacyMarkerTransaction = privacyMarkerTransaction();
mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction); mockBlockchainWithPrivacyMarkerTransaction(privacyMarkerTransaction);
return privacyMarkerTransaction; return privacyMarkerTransaction;
} }

@ -1,85 +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.privacy.storage.migration;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor.Result;
import org.hyperledger.besu.ethereum.privacy.Restriction;
import java.math.BigInteger;
import org.apache.tuweni.bytes.Bytes;
public class PrivateTransactionDataFixture {
private static final SECP256K1.KeyPair KEY_PAIR =
SECP256K1.KeyPair.create(
SECP256K1.PrivateKey.create(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
private static final BlockDataGenerator blockDataGenerator = new BlockDataGenerator();
public static Transaction privacyMarkerTransaction(final String transactionKey) {
return Transaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(Address.DEFAULT_PRIVACY)
.value(Wei.ZERO)
.payload(Bytes.fromBase64String(transactionKey))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(BigInteger.valueOf(2018))
.signAndBuild(KEY_PAIR);
}
public static PrivateTransaction privateTransaction(final String privacyGroupId) {
return PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(null)
.value(Wei.ZERO)
.payload(
Bytes.fromHexString(
"0x608060405234801561001057600080fd5b5060d08061001f6000396000"
+ "f3fe60806040526004361060485763ffffffff7c010000000000"
+ "0000000000000000000000000000000000000000000000600035"
+ "04166360fe47b18114604d5780636d4ce63c146075575b600080"
+ "fd5b348015605857600080fd5b50607360048036036020811015"
+ "606d57600080fd5b50356099565b005b348015608057600080fd"
+ "5b506087609e565b60408051918252519081900360200190f35b"
+ "600055565b6000549056fea165627a7a72305820cb1d0935d14b"
+ "589300b12fcd0ab849a7e9019c81da24d6daa4f6b2f003d1b018"
+ "0029"))
.sender(Address.wrap(Bytes.fromHexString("0x1c9a6e1ee3b7ac6028e786d9519ae3d24ee31e79")))
.chainId(BigInteger.valueOf(4))
.privateFrom(Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="))
.privacyGroupId(Bytes.fromBase64String(privacyGroupId))
.restriction(Restriction.RESTRICTED)
.signAndBuild(KEY_PAIR);
}
public static Result successfulPrivateTxProcessingResult() {
return Result.successful(
blockDataGenerator.logs(3, 1), 0, Bytes.EMPTY, ValidationResult.valid());
}
}
Loading…
Cancel
Save