remove integration tests related to privacy (#7645)

* remove integration tests related to privacy

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>

---------

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
pull/7664/head
Sally MacFarlane 2 months ago committed by GitHub
parent 1751a77f98
commit 9d689b9401
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 215
      enclave/src/integration-test/java/org/hyperledger/besu/enclave/EnclaveTest.java
  2. 52
      enclave/src/integration-test/java/org/hyperledger/besu/enclave/TlsCertificateDefinition.java
  3. 144
      enclave/src/integration-test/java/org/hyperledger/besu/enclave/TlsEnabledEnclaveTest.java
  4. 109
      enclave/src/integration-test/java/org/hyperledger/besu/enclave/TlsEnabledHttpServerFactory.java
  5. 98
      enclave/src/integration-test/java/org/hyperledger/besu/enclave/TlsHelpers.java
  6. 192
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/PrivGetPrivateTransactionIntegrationTest.java
  7. 244
      ethereum/core/src/integration-test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPrecompiledContractIntegrationTest.java
  8. 1
      testutil/src/main/resources/enclave_key_0.key

@ -1,215 +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.enclave;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.enclave.types.SendResponse;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration;
import org.hyperledger.enclave.testutil.TesseraTestHarness;
import org.hyperledger.enclave.testutil.TesseraTestHarnessFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import com.google.common.collect.Lists;
import io.vertx.core.Vertx;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class EnclaveTest {
@TempDir private static Path folder;
private static final String PAYLOAD = "a wonderful transaction";
private static final String MOCK_KEY = "iOCzoGo5kwtZU0J41Z9xnGXHN6ZNukIa9MspvHtu3Jk=";
private Enclave enclave;
private Vertx vertx;
private EnclaveFactory factory;
private TesseraTestHarness testHarness;
@BeforeEach
public void setUp() throws Exception {
vertx = Vertx.vertx();
factory = new EnclaveFactory(vertx);
testHarness =
TesseraTestHarnessFactory.create(
"enclave",
Files.createTempDirectory(folder, "enclave"),
new EnclaveKeyConfiguration(
new String[] {"enclave_key_0.pub"},
new String[] {"enclave_key_0.key"},
EnclaveEncryptorType.NOOP),
Optional.empty());
testHarness.start();
enclave = factory.createVertxEnclave(testHarness.clientUrl());
}
@AfterEach
public void tearDown() {
testHarness.close();
vertx.close();
}
@Test
public void testUpCheck() {
assertThat(enclave.upCheck()).isTrue();
}
@Test
public void testReceiveThrowsWhenPayloadDoesNotExist() {
final String publicKey = testHarness.getDefaultPublicKey();
final Throwable t = catchThrowable(() -> enclave.receive(MOCK_KEY, publicKey));
assertThat(t.getMessage()).isEqualTo("Message with hash was not found");
}
@Test
public void testSendAndReceive() {
final List<String> publicKeys = testHarness.getPublicKeys();
final SendResponse sr =
enclave.send(PAYLOAD, publicKeys.get(0), Lists.newArrayList(publicKeys.get(0)));
final ReceiveResponse rr = enclave.receive(sr.getKey(), publicKeys.get(0));
assertThat(rr).isNotNull();
assertThat(new String(rr.getPayload(), UTF_8)).isEqualTo(PAYLOAD);
assertThat(rr.getPrivacyGroupId()).isNotNull();
}
@Test
public void testSendWithPrivacyGroupAndReceive() {
final List<String> publicKeys = testHarness.getPublicKeys();
final PrivacyGroup privacyGroupResponse =
enclave.createPrivacyGroup(publicKeys, publicKeys.get(0), "", "");
final SendResponse sr =
enclave.send(PAYLOAD, publicKeys.get(0), privacyGroupResponse.getPrivacyGroupId());
final ReceiveResponse rr = enclave.receive(sr.getKey(), publicKeys.get(0));
assertThat(rr).isNotNull();
assertThat(new String(rr.getPayload(), UTF_8)).isEqualTo(PAYLOAD);
assertThat(rr.getPrivacyGroupId()).isNotNull();
}
@Test
public void testCreateAndDeletePrivacyGroup() {
final List<String> publicKeys = testHarness.getPublicKeys();
final String name = "testName";
final String description = "testDesc";
final PrivacyGroup privacyGroupResponse =
enclave.createPrivacyGroup(publicKeys, publicKeys.get(0), name, description);
assertThat(privacyGroupResponse.getPrivacyGroupId()).isNotNull();
assertThat(privacyGroupResponse.getName()).isEqualTo(name);
assertThat(privacyGroupResponse.getDescription()).isEqualTo(description);
assertThat(privacyGroupResponse.getType()).isEqualByComparingTo(PrivacyGroup.Type.PANTHEON);
final String response =
enclave.deletePrivacyGroup(privacyGroupResponse.getPrivacyGroupId(), publicKeys.get(0));
assertThat(privacyGroupResponse.getPrivacyGroupId()).isEqualTo(response);
}
@Test
public void testCreateFindDeleteFindPrivacyGroup() {
final List<String> publicKeys = testHarness.getPublicKeys();
final String name = "name";
final String description = "desc";
final PrivacyGroup privacyGroupResponse =
enclave.createPrivacyGroup(publicKeys, publicKeys.get(0), name, description);
assertThat(privacyGroupResponse.getPrivacyGroupId()).isNotNull();
assertThat(privacyGroupResponse.getName()).isEqualTo(name);
assertThat(privacyGroupResponse.getDescription()).isEqualTo(description);
assertThat(privacyGroupResponse.getType()).isEqualTo(PrivacyGroup.Type.PANTHEON);
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.untilAsserted(
() -> {
final PrivacyGroup[] findPrivacyGroupResponse = enclave.findPrivacyGroup(publicKeys);
assertThat(findPrivacyGroupResponse.length).isEqualTo(1);
assertThat(findPrivacyGroupResponse[0].getPrivacyGroupId())
.isEqualTo(privacyGroupResponse.getPrivacyGroupId());
});
final String response =
enclave.deletePrivacyGroup(privacyGroupResponse.getPrivacyGroupId(), publicKeys.get(0));
assertThat(privacyGroupResponse.getPrivacyGroupId()).isEqualTo(response);
Awaitility.await()
.atMost(5, TimeUnit.SECONDS)
.untilAsserted(
() -> {
final PrivacyGroup[] findPrivacyGroupResponse = enclave.findPrivacyGroup(publicKeys);
assertThat(findPrivacyGroupResponse.length).isEqualTo(0);
});
}
@Test
public void testCreateDeleteRetrievePrivacyGroup() {
final List<String> publicKeys = testHarness.getPublicKeys();
final String name = "name";
final String description = "desc";
final PrivacyGroup privacyGroupResponse =
enclave.createPrivacyGroup(publicKeys, publicKeys.get(0), name, description);
assertThat(privacyGroupResponse.getPrivacyGroupId()).isNotNull();
assertThat(privacyGroupResponse.getName()).isEqualTo(name);
assertThat(privacyGroupResponse.getDescription()).isEqualTo(description);
assertThat(privacyGroupResponse.getType()).isEqualTo(PrivacyGroup.Type.PANTHEON);
final PrivacyGroup retrievePrivacyGroup =
enclave.retrievePrivacyGroup(privacyGroupResponse.getPrivacyGroupId());
assertThat(retrievePrivacyGroup).usingRecursiveComparison().isEqualTo(privacyGroupResponse);
final String response =
enclave.deletePrivacyGroup(privacyGroupResponse.getPrivacyGroupId(), publicKeys.get(0));
assertThat(privacyGroupResponse.getPrivacyGroupId()).isEqualTo(response);
}
@Test
public void upcheckReturnsFalseIfNoResponseReceived() throws URISyntaxException {
assertThat(factory.createVertxEnclave(new URI("http://8.8.8.8:65535")).upCheck()).isFalse();
}
}

@ -1,52 +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.enclave;
import java.io.File;
import java.net.URL;
import java.nio.file.Path;
import com.google.common.io.Resources;
public class TlsCertificateDefinition {
private final File pkcs12File;
private final String password;
public static TlsCertificateDefinition loadFromResource(
final String resourcePath, final String password) {
try {
final URL sslCertificate = Resources.getResource(resourcePath);
final Path keystorePath = Path.of(sslCertificate.getPath());
return new TlsCertificateDefinition(keystorePath.toFile(), password);
} catch (final Exception e) {
throw new RuntimeException("Failed to load TLS certificates", e);
}
}
public TlsCertificateDefinition(final File pkcs12File, final String password) {
this.pkcs12File = pkcs12File;
this.password = password;
}
public File getPkcs12File() {
return pkcs12File;
}
public String getPassword() {
return password;
}
}

@ -1,144 +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.enclave;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
import static org.hyperledger.besu.enclave.TlsHelpers.populateFingerprintFile;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Optional;
import io.vertx.core.Vertx;
import io.vertx.core.http.HttpServer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TlsEnabledEnclaveTest {
private TlsEnabledHttpServerFactory serverFactory;
private Vertx vertx;
final TlsCertificateDefinition httpServerCert =
TlsCertificateDefinition.loadFromResource("tls/cert1.pfx", "password");
final TlsCertificateDefinition besuCert =
TlsCertificateDefinition.loadFromResource("tls/cert2.pfx", "password2");
public void shutdown() {
vertx.close();
}
@BeforeEach
public void setup() {
serverFactory = new TlsEnabledHttpServerFactory();
this.vertx = Vertx.vertx();
}
@AfterEach
public void cleanup() {
serverFactory.shutdown();
this.shutdown();
}
private Enclave createEnclave(
final int httpServerPort, final Path workDir, final boolean tlsEnabled) throws IOException {
final Path serverFingerprintFile = workDir.resolve("server_known_clients");
final Path besuCertPasswordFile = workDir.resolve("password_file");
try {
populateFingerprintFile(serverFingerprintFile, httpServerCert, Optional.of(httpServerPort));
Files.write(besuCertPasswordFile, besuCert.getPassword().getBytes(Charset.defaultCharset()));
final EnclaveFactory factory = new EnclaveFactory(vertx);
if (tlsEnabled) {
final URI httpServerUri = new URI("https://localhost:" + httpServerPort);
return factory.createVertxEnclave(
httpServerUri,
besuCert.getPkcs12File().toPath(),
besuCertPasswordFile,
serverFingerprintFile);
} else {
return factory.createVertxEnclave(new URI("http://localhost:" + httpServerPort));
}
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException e) {
fail("unable to populate fingerprint file");
return null;
} catch (URISyntaxException e) {
fail("unable to create URI");
return null;
}
}
@Test
public void nonTlsEnclaveCannotConnectToTlsServer() throws IOException {
Path workDir = Files.createTempDirectory("test-certs");
// Note: the HttpServer always responds with a JsonRpcSuccess, result="I'm up".
final HttpServer httpServer = serverFactory.create(httpServerCert, besuCert, workDir, true);
final Enclave enclave = createEnclave(httpServer.actualPort(), workDir, false);
assertThat(enclave.upCheck()).isEqualTo(false);
}
@Test
public void nonTlsEnclaveCanConnectToNonTlsServer() throws IOException {
Path workDir = Files.createTempDirectory("test-certs");
// Note: the HttpServer always responds with a JsonRpcSuccess, result="I'm up".
final HttpServer httpServer = serverFactory.create(httpServerCert, besuCert, workDir, false);
final Enclave enclave = createEnclave(httpServer.actualPort(), workDir, false);
assertThat(enclave.upCheck()).isEqualTo(true);
}
@Test
public void tlsEnclaveCannotConnectToNonTlsServer() throws IOException {
Path workDir = Files.createTempDirectory("test-certs");
// Note: the HttpServer always responds with a JsonRpcSuccess, result="I'm up!".
final HttpServer httpServer = serverFactory.create(httpServerCert, besuCert, workDir, false);
final Enclave enclave = createEnclave(httpServer.actualPort(), workDir, true);
assertThat(enclave.upCheck()).isEqualTo(false);
}
@Test
public void tlsEnclaveCanConnectToTlsServer() throws IOException {
Path workDir = Files.createTempDirectory("test-certs");
// Note: the HttpServer always responds with a JsonRpcSuccess, result="I'm up".
final HttpServer httpServer = serverFactory.create(httpServerCert, besuCert, workDir, true);
final Enclave enclave = createEnclave(httpServer.actualPort(), workDir, true);
assertThat(enclave.upCheck()).isEqualTo(true);
}
}

@ -1,109 +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.enclave;
import static org.hyperledger.besu.enclave.TlsHelpers.populateFingerprintFile;
import java.io.IOException;
import java.nio.file.Path;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import com.google.common.collect.Lists;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.vertx.core.Vertx;
import io.vertx.core.http.ClientAuth;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.net.PfxOptions;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import org.apache.tuweni.net.tls.VertxTrustOptions;
class TlsEnabledHttpServerFactory {
private final Vertx vertx;
private final List<HttpServer> serversCreated = Lists.newArrayList();
TlsEnabledHttpServerFactory() {
this.vertx = Vertx.vertx();
}
void shutdown() {
serversCreated.forEach(HttpServer::close);
vertx.close();
}
HttpServer create(
final TlsCertificateDefinition serverCert,
final TlsCertificateDefinition acceptedClientCerts,
final Path workDir,
final boolean tlsEnabled) {
try {
final Path serverFingerprintFile = workDir.resolve("server_known_clients");
populateFingerprintFile(serverFingerprintFile, acceptedClientCerts, Optional.empty());
final HttpServerOptions web3HttpServerOptions = new HttpServerOptions();
web3HttpServerOptions.setPort(0);
if (tlsEnabled) {
web3HttpServerOptions.setSsl(true);
web3HttpServerOptions.setClientAuth(ClientAuth.REQUIRED);
web3HttpServerOptions.setTrustOptions(
VertxTrustOptions.allowlistClients(serverFingerprintFile));
web3HttpServerOptions.setPfxKeyCertOptions(
new PfxOptions()
.setPath(serverCert.getPkcs12File().toString())
.setPassword(serverCert.getPassword()));
}
final Router router = Router.router(vertx);
router
.route(HttpMethod.GET, "/upcheck")
.produces(HttpHeaderValues.APPLICATION_JSON.toString())
.handler(TlsEnabledHttpServerFactory::handleRequest);
final HttpServer mockOrionHttpServer = vertx.createHttpServer(web3HttpServerOptions);
final CompletableFuture<Boolean> serverConfigured = new CompletableFuture<>();
mockOrionHttpServer.requestHandler(router).listen(result -> serverConfigured.complete(true));
serverConfigured.get();
serversCreated.add(mockOrionHttpServer);
return mockOrionHttpServer;
} catch (final KeyStoreException
| NoSuchAlgorithmException
| CertificateException
| IOException
| ExecutionException
| InterruptedException e) {
throw new RuntimeException("Failed to construct a TLS Enabled Server", e);
}
}
private static void handleRequest(final RoutingContext context) {
final HttpServerResponse response = context.response();
if (!response.closed()) {
response.end("I'm up!");
}
}
}

@ -1,98 +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.enclave;
import org.hyperledger.besu.crypto.MessageDigestFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.StringJoiner;
import com.google.common.collect.Lists;
public class TlsHelpers {
private TlsHelpers() {}
private static KeyStore loadP12KeyStore(final File pkcsFile, final String password)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException {
final KeyStore store = KeyStore.getInstance("pkcs12");
try (final InputStream keystoreStream = new FileInputStream(pkcsFile)) {
store.load(keystoreStream, password.toCharArray());
} catch (IOException e) {
throw new RuntimeException("Unable to load keystore.", e);
}
return store;
}
public static void populateFingerprintFile(
final Path knownClientsPath,
final TlsCertificateDefinition certDef,
final Optional<Integer> serverPortToAppendToHostname)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
final List<X509Certificate> certs = getCertsFromPkcs12(certDef);
final StringBuilder fingerprintsToAdd = new StringBuilder();
final String portFragment = serverPortToAppendToHostname.map(port -> ":" + port).orElse("");
for (final X509Certificate cert : certs) {
final String fingerprint = generateFingerprint(cert);
fingerprintsToAdd.append(String.format("localhost%s %s%n", portFragment, fingerprint));
fingerprintsToAdd.append(String.format("127.0.0.1%s %s%n", portFragment, fingerprint));
}
Files.writeString(knownClientsPath, fingerprintsToAdd.toString());
}
@SuppressWarnings("JdkObsolete") // java.util.Enumeration is baked into the Keystore API
public static List<X509Certificate> getCertsFromPkcs12(final TlsCertificateDefinition certDef)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException {
final List<X509Certificate> results = Lists.newArrayList();
final KeyStore p12 = loadP12KeyStore(certDef.getPkcs12File(), certDef.getPassword());
final Enumeration<String> aliases = p12.aliases();
while (aliases.hasMoreElements()) {
results.add((X509Certificate) p12.getCertificate(aliases.nextElement()));
}
return results;
}
private static String generateFingerprint(final X509Certificate cert)
throws NoSuchAlgorithmException, CertificateEncodingException {
final MessageDigest md = MessageDigestFactory.create(MessageDigestFactory.SHA256_ALG);
md.update(cert.getEncoded());
final byte[] digest = md.digest();
final StringJoiner joiner = new StringJoiner(":");
for (final byte b : digest) {
joiner.add(String.format("%02X", b));
}
return joiner.toString().toLowerCase(Locale.ROOT);
}
}

@ -1,192 +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.methods.fork.frontier;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.PrivateTransactionDataFixture.privateMarkerTransaction;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
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.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.enclave.types.SendResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.priv.PrivGetPrivateTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.privacy.PrivateTransactionLegacyResult;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.TransactionLocation;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.RestrictedDefaultPrivacyController;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.plugin.data.Restriction;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration;
import org.hyperledger.enclave.testutil.TesseraTestHarness;
import org.hyperledger.enclave.testutil.TesseraTestHarnessFactory;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Optional;
import com.google.common.collect.Lists;
import io.vertx.core.Vertx;
import org.apache.tuweni.bytes.Bytes;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class PrivGetPrivateTransactionIntegrationTest {
@TempDir private static Path folder;
private static final String ENCLAVE_PUBLIC_KEY = "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
private final PrivacyIdProvider privacyIdProvider = (user) -> ENCLAVE_PUBLIC_KEY;
private final PrivateStateStorage privateStateStorage = mock(PrivateStateStorage.class);
private final Blockchain blockchain = mock(Blockchain.class);
private final Address sender =
Address.fromHexString("0x0000000000000000000000000000000000000003");
private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithmFactory.getInstance();
private final KeyPair KEY_PAIR =
signatureAlgorithm.createKeyPair(
signatureAlgorithm.createPrivateKey(
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.wrap(ENCLAVE_PUBLIC_KEY.getBytes(UTF_8)))
.privateFor(
Lists.newArrayList(
Bytes.wrap("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=".getBytes(UTF_8))))
.restriction(Restriction.RESTRICTED)
.signAndBuild(KEY_PAIR);
private Vertx vertx = Vertx.vertx();
private TesseraTestHarness testHarness;
private Enclave enclave;
private PrivacyController privacyController;
@BeforeEach
public void setUp() throws Exception {
vertx = Vertx.vertx();
testHarness =
TesseraTestHarnessFactory.create(
"enclave",
Files.createTempDirectory(folder, "enclave"),
new EnclaveKeyConfiguration(
new String[] {"enclave_key_0.pub"},
new String[] {"enclave_key_0.key"},
EnclaveEncryptorType.NOOP),
Optional.empty());
testHarness.start();
final EnclaveFactory factory = new EnclaveFactory(vertx);
enclave = factory.createVertxEnclave(testHarness.clientUrl());
privacyController =
new RestrictedDefaultPrivacyController(
blockchain, privateStateStorage, enclave, null, null, null, null, null);
}
@AfterEach
public void tearDown() {
testHarness.close();
vertx.close();
}
@Test
public void returnsStoredPrivateTransaction() {
final PrivGetPrivateTransaction privGetPrivateTransaction =
new PrivGetPrivateTransaction(privacyController, privacyIdProvider);
final Hash blockHash = Hash.ZERO;
final Transaction pmt = spy(privateMarkerTransaction());
when(blockchain.getTransactionByHash(eq(pmt.getHash()))).thenReturn(Optional.of(pmt));
when(blockchain.getTransactionLocation(eq(pmt.getHash())))
.thenReturn(Optional.of(new TransactionLocation(blockHash, 0)));
final BlockHeader blockHeader = mock(BlockHeader.class);
when(blockHeader.getHash()).thenReturn(blockHash);
when(blockchain.getBlockHeader(eq(blockHash))).thenReturn(Optional.of(blockHeader));
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);
final String payload = Base64.getEncoder().encodeToString(bvrlp.encoded().toArrayUnsafe());
final ArrayList<String> to = Lists.newArrayList("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=");
final SendResponse sendResponse = enclave.send(payload, ENCLAVE_PUBLIC_KEY, to);
final Bytes hexKey = Bytes.fromBase64String(sendResponse.getKey());
when(pmt.getPayload()).thenReturn(hexKey);
final Object[] params = new Object[] {pmt.getHash()};
final JsonRpcRequestContext request =
new JsonRpcRequestContext(new JsonRpcRequest("1", "priv_getPrivateTransaction", params));
final JsonRpcSuccessResponse response =
(JsonRpcSuccessResponse) privGetPrivateTransaction.response(request);
final PrivateTransactionLegacyResult result =
(PrivateTransactionLegacyResult) response.getResult();
assertThat(new PrivateTransactionLegacyResult(this.privateTransaction))
.usingRecursiveComparison()
.isEqualTo(result);
}
}

@ -1,244 +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.mainnet.precompiles.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.enclave.types.SendResponse;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockDataGenerator;
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.mainnet.PrivateStateUtils;
import org.hyperledger.besu.ethereum.privacy.PrivateStateGenesisAllocator;
import org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionProcessor;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateMetadataUpdater;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.evm.frame.MessageFrame;
import org.hyperledger.besu.evm.gascalculator.SpuriousDragonGasCalculator;
import org.hyperledger.besu.evm.operation.BlockHashOperation.BlockHashLookup;
import org.hyperledger.besu.evm.precompile.PrecompiledContract;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration;
import org.hyperledger.enclave.testutil.TesseraTestHarness;
import org.hyperledger.enclave.testutil.TesseraTestHarnessFactory;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import com.google.common.collect.Lists;
import io.vertx.core.Vertx;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
public class PrivacyPrecompiledContractIntegrationTest {
// this tempDir is deliberately static
@TempDir private static Path folder;
private static final Bytes VALID_PRIVATE_TRANSACTION_RLP =
Bytes.fromHexString(
"0xf90113800182520894095e7baea6a6c7c4c2dfeb977efac326af552d87"
+ "a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
+ "ffff801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d"
+ "495a36649353a01fffd310ac743f371de3b9f7f9cb56c0b28ad43601b4ab94"
+ "9f53faa07bd2c804ac41316156744d784c4355486d425648586f5a7a7a4267"
+ "5062572f776a3561784470573958386c393153476f3df85aac41316156744d"
+ "784c4355486d425648586f5a7a7a42675062572f776a356178447057395838"
+ "6c393153476f3dac4b6f32625671442b6e4e6c4e594c35454537793349644f"
+ "6e766966746a69697a706a52742b4854754642733d8a726573747269637465"
+ "64");
private static final String DEFAULT_OUTPUT = "0x01";
private static Enclave enclave;
private static MessageFrame messageFrame;
private static TesseraTestHarness testHarness;
private static WorldStateArchive worldStateArchive;
private static PrivateStateStorage privateStateStorage;
private static final Vertx vertx = Vertx.vertx();
private PrivateTransactionProcessor mockPrivateTxProcessor() {
final PrivateTransactionProcessor mockPrivateTransactionProcessor =
mock(PrivateTransactionProcessor.class);
final TransactionProcessingResult result =
TransactionProcessingResult.successful(
null, 0, 0, Bytes.fromHexString(DEFAULT_OUTPUT), null);
when(mockPrivateTransactionProcessor.processTransaction(
nullable(WorldUpdater.class),
nullable(WorldUpdater.class),
nullable(ProcessableBlockHeader.class),
nullable(Hash.class),
nullable(PrivateTransaction.class),
nullable(Address.class),
nullable(OperationTracer.class),
nullable(BlockHashLookup.class),
nullable(Bytes.class)))
.thenReturn(result);
return mockPrivateTransactionProcessor;
}
@BeforeAll
public static void setUpOnce() throws Exception {
testHarness =
TesseraTestHarnessFactory.create(
"enclave",
Files.createTempDirectory(folder, "enclave"),
new EnclaveKeyConfiguration(
new String[] {"enclave_key_0.pub"},
new String[] {"enclave_key_1.key"},
EnclaveEncryptorType.NOOP),
Optional.empty());
testHarness.start();
final EnclaveFactory factory = new EnclaveFactory(vertx);
enclave = factory.createVertxEnclave(testHarness.clientUrl());
messageFrame = mock(MessageFrame.class);
final BlockDataGenerator blockGenerator = new BlockDataGenerator();
final Block genesis = blockGenerator.genesisBlock();
final Block block =
blockGenerator.block(
new BlockDataGenerator.BlockOptions().setParentHash(genesis.getHeader().getHash()));
when(messageFrame.getBlockValues()).thenReturn(block.getHeader());
final PrivateMetadataUpdater privateMetadataUpdater = mock(PrivateMetadataUpdater.class);
when(privateMetadataUpdater.getPrivateBlockMetadata(any())).thenReturn(null);
when(privateMetadataUpdater.getPrivacyGroupHeadBlockMap())
.thenReturn(PrivacyGroupHeadBlockMap.empty());
when(messageFrame.getContextVariable(
eq(PrivateStateUtils.KEY_IS_PERSISTING_PRIVATE_STATE), anyBoolean()))
.thenReturn(false);
when(messageFrame.getContextVariable(eq(PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER)))
.thenReturn(privateMetadataUpdater);
when(messageFrame.hasContextVariable(eq(PrivateStateUtils.KEY_PRIVATE_METADATA_UPDATER)))
.thenReturn(true);
worldStateArchive = mock(WorldStateArchive.class);
final MutableWorldState mutableWorldState = mock(MutableWorldState.class);
when(mutableWorldState.updater()).thenReturn(mock(WorldUpdater.class));
when(worldStateArchive.getMutable()).thenReturn(mutableWorldState);
when(worldStateArchive.getMutable(any(), any())).thenReturn(Optional.of(mutableWorldState));
privateStateStorage = mock(PrivateStateStorage.class);
final PrivateStateStorage.Updater storageUpdater = mock(PrivateStateStorage.Updater.class);
when(privateStateStorage.getPrivacyGroupHeadBlockMap(any()))
.thenReturn(Optional.of(PrivacyGroupHeadBlockMap.empty()));
when(storageUpdater.putPrivateBlockMetadata(
nullable(Bytes32.class), nullable(Bytes32.class), any()))
.thenReturn(storageUpdater);
when(storageUpdater.putTransactionReceipt(
nullable(Bytes32.class), nullable(Bytes32.class), any()))
.thenReturn(storageUpdater);
when(privateStateStorage.updater()).thenReturn(storageUpdater);
}
@AfterAll
public static void tearDownOnce() {
testHarness.stop();
vertx.close();
}
@Test
public void testUpCheck() {
assertThat(enclave.upCheck()).isTrue();
}
@Test
public void testSendAndReceive() {
final List<String> publicKeys = testHarness.getPublicKeys();
final PrivateTransaction privateTransaction =
PrivateTransactionDataFixture.privateContractDeploymentTransactionBesu(publicKeys.get(0));
final BytesValueRLPOutput bytesValueRLPOutput = new BytesValueRLPOutput();
privateTransaction.writeTo(bytesValueRLPOutput);
final String s = bytesValueRLPOutput.encoded().toBase64String();
final SendResponse sr =
enclave.send(s, publicKeys.get(0), Lists.newArrayList(publicKeys.get(0)));
final PrivacyPrecompiledContract privacyPrecompiledContract =
new PrivacyPrecompiledContract(
new SpuriousDragonGasCalculator(),
enclave,
worldStateArchive,
new PrivateStateRootResolver(privateStateStorage),
new PrivateStateGenesisAllocator(
false, (privacyGroupId, blockNumber) -> Collections::emptyList),
false,
"IntegrationTest");
privacyPrecompiledContract.setPrivateTransactionProcessor(mockPrivateTxProcessor());
final PrecompiledContract.PrecompileContractResult result =
privacyPrecompiledContract.computePrecompile(
Bytes.fromBase64String(sr.getKey()), messageFrame);
final Bytes actual = result.getOutput();
assertThat(actual).isEqualTo(Bytes.fromHexString(DEFAULT_OUTPUT));
}
@Test
public void testNoPrivateKeyError() throws RuntimeException {
final List<String> publicKeys = testHarness.getPublicKeys();
publicKeys.add("noPrivateKey");
final String s = VALID_PRIVATE_TRANSACTION_RLP.toBase64String();
final Throwable thrown = catchThrowable(() -> enclave.send(s, publicKeys.get(0), publicKeys));
assertThat(thrown).hasMessageContaining("Index 9 out of bounds for length 9");
}
@Test
public void testWrongPrivateKeyError() throws RuntimeException {
final List<String> publicKeys = testHarness.getPublicKeys();
publicKeys.add("noPrivateKenoPrivateKenoPrivateKenoPrivateK");
final String s = VALID_PRIVATE_TRANSACTION_RLP.toBase64String();
final Throwable thrown = catchThrowable(() -> enclave.send(s, publicKeys.get(0), publicKeys));
assertThat(thrown).hasMessageContaining("Recipient not found for key:");
}
}

@ -1 +0,0 @@
{"data":{"bytes":"hBsuQsGJzx4QHmFmBkNoI7YGnTmaZP4P+wBOdu56ljk="},"type":"unlocked"}
Loading…
Cancel
Save