remove container tests (#4999)

* remove container tests

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

* print error message in event of AT failure

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

Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
Co-authored-by: Stefan Pingel <16143240+pinges@users.noreply.github.com>
pull/5014/head
Sally MacFarlane 2 years ago committed by GitHub
parent 6b9c1ce40d
commit 37ffa1f8bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/AcceptanceTestBase.java
  2. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/account/TransferTransaction.java
  3. 17
      container-tests/build.gradle
  4. 40
      container-tests/tests/build.gradle
  5. 301
      container-tests/tests/src/test/java/org/hyperledger/besu/tests/container/ContainerTestBase.java
  6. 312
      container-tests/tests/src/test/java/org/hyperledger/besu/tests/container/ContainerTests.java
  7. 186
      container-tests/tests/src/test/java/org/hyperledger/besu/tests/container/helpers/ContractOperations.java
  8. 1
      container-tests/tests/src/test/resources/besu/config/besuAddress
  9. 1
      container-tests/tests/src/test/resources/besu/data/key
  10. 45
      container-tests/tests/src/test/resources/genesis.json
  11. 1
      container-tests/tests/src/test/resources/goQuorum/qdata/nodeKey
  12. 0
      container-tests/tests/src/test/resources/ipc/.empty
  13. 6
      container-tests/tests/src/test/resources/keys/key1.key
  14. 1
      container-tests/tests/src/test/resources/keys/key1.pub
  15. 6
      container-tests/tests/src/test/resources/keys/key2.key
  16. 1
      container-tests/tests/src/test/resources/keys/key2.pub
  17. 47
      container-tests/tests/src/test/resources/tessera/tesseraConfig.json
  18. 9
      container-tests/tests/src/test/solidity/TestContract.sol
  19. 1
      settings.gradle

@ -201,6 +201,7 @@ public class AcceptanceTestBase {
LOG.error(
"==========================================================================================");
LOG.error("Test failed. Reported Throwable at the point of failure:", e);
LOG.error(e.getMessage());
}
@Override

@ -35,7 +35,7 @@ import org.web3j.utils.Numeric;
public class TransferTransaction implements Transaction<Hash> {
/** Price for each for each GAS units in this transaction (wei). */
/** Price for each GAS units in this transaction (wei). */
private static final BigInteger MINIMUM_GAS_PRICE = BigInteger.valueOf(1000);
/** Number of GAS units that the transaction will cost. */

@ -1,17 +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
*/
jar { enabled = false }

@ -1,40 +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
*/
jar { enabled = false }
dependencies {
testImplementation 'junit:junit'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.awaitility:awaitility'
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.testcontainers:testcontainers'
testImplementation 'org.web3j:core'
testImplementation 'org.web3j:quorum'
testRuntimeOnly 'org.junit.vintage:junit-vintage-engine'
}
test.enabled = false
// TODO make this run only on nightly
task containerTests(type: Test) {
description = 'Runs GoQuorum <> Besu container tests.'
dependsOn(rootProject.distDocker)
def dockerBuildVersion = project.hasProperty('release.releaseVersion') ? project.property('release.releaseVersion') : "${rootProject.version}"
def imageName = "hyperledger/besu"
def image = "${imageName}:${dockerBuildVersion}"
systemProperty 'containertest.imagename', image
}

@ -1,301 +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.tests.container;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import com.github.dockerjava.api.command.CreateContainerCmd;
import org.awaitility.Awaitility;
import org.awaitility.core.ThrowingRunnable;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.testcontainers.containers.BindMode;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.EthBlockNumber;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.quorum.Quorum;
@SuppressWarnings({"rawtypes", "unchecked"})
public class ContainerTestBase {
// A docker image can be built using `./gradlew clean distDocker`
// check the status of local images with `docker images`
// To use that local image, change besuImage below eg
// private final String besuImage = "hyperledger/besu:21.7.0-SNAPSHOT";
private final String besuImage = System.getProperty("containertest.imagename");
public static final String GOQUORUM_VERSION = "22.4.4";
public static final String TESSERA_VERSION = "22.1.7";
protected final String goQuorumTesseraPubKey = "3XGBIf+x8IdVQOVfIsbRnHwTYOJP/Fx84G8gMmy8qDM=";
protected final String besuTesseraPubKey = "8JJLEAbq6o9m4Kqm++v0Y1n9Z2ryAFtZTyhnxSKWgws=";
private final Network containerNetwork = Network.SHARED;
protected Quorum besuWeb3j;
protected Quorum goQuorumWeb3j;
// General config
private final String hostGenesisPath = "/genesis.json";
private final String hostKeyPath = "/keys/";
private final String containerKeyPath = "/tmp/keys/";
private final Integer networkId = 2020;
// Besu config
private final Integer besuP2pPort = 30303;
private final Integer besuRpcPort = 8545;
private final String besuContainerGenesisPath = "/opt/besu/genesis.json";
private final String besuNetworkAlias = "besuNode";
private final String hostBesuKeyPath = "/besu/data/key";
private final String containerBesuKeyPath = "/opt/besu/key";
// GoQuorum + Tessera shared config
private final String ipcBindDir = "/tmp/ipc/";
private final String ipcDirPath = "/ipc/";
private final String ipcFilePath = "test.ipc";
private final String containerIpcPath = ipcBindDir + ipcFilePath;
// Tessera config
private final String tesseraContainerPrivKey1Path = "/tmp/keys/key1.key";
private final String tesseraContainerPubKey1Path = "/tmp/keys/key1.pub";
private final String tesseraContainerPrivKey2Path = "/tmp/keys/key2.key";
private final String tesseraContainerPubKey2Path = "/tmp/keys/key2.pub";
private final String tesseraContainerConfigFilePath = "/tmp/tessera/tesseraConfig.json";
protected final int tesseraRestPort = 9081;
private final int tesseraQ2TRestPort = 9003;
private final String hostTesseraResources = "/tessera/";
private final String containerTesseraResources = "/tmp/tessera/";
private final int tesseraP2pPort = 9001;
// GoQuorum config
private final String goQuorumContainerDatadir = "/tmp/qdata/";
private final String goQuorumContainerGenesis = "/tmp/qdata/genesis.json";
private final String goQuorumContainerGethIpcPath = goQuorumContainerDatadir + "/geth.ipc";
private final Integer goQuorumP2pPort = 30303;
private final Integer goQuorumRpcPort = 8545;
@Rule public final GenericContainer besuContainer = buildBesuContainer();
@Rule
public final GenericContainer tesseraGoQuorumContainer =
buildGoQuorumTesseraContainer(
ipcDirPath,
ipcBindDir,
containerIpcPath,
tesseraContainerPrivKey1Path,
tesseraContainerPubKey1Path);
@Rule
public final GenericContainer tesseraBesuContainer =
buildBesuTesseraContainer(tesseraContainerPrivKey2Path, tesseraContainerPubKey2Path);
@Rule
public final GenericContainer goQuorumContainer =
buildGoQuorumContainer(ipcDirPath, ipcBindDir, containerIpcPath);
@Before
public void setUp() throws IOException, InterruptedException {
besuWeb3j =
buildWeb3JQuorum(
besuContainer.getContainerIpAddress(), besuContainer.getMappedPort(besuRpcPort));
goQuorumWeb3j =
buildWeb3JQuorum(
goQuorumContainer.getContainerIpAddress(),
goQuorumContainer.getMappedPort(goQuorumRpcPort));
waitFor(10, () -> assertClientVersion(besuWeb3j, "besu"));
waitFor(10, () -> assertClientVersion(goQuorumWeb3j, GOQUORUM_VERSION));
// Tell GoQuorum to peer to Besu
goQuorumContainer.execInContainer(
"geth",
"--exec",
"admin.addPeer(\"enode://11b72d1e2fdde254a493047d4061f3b62cc2ba59f4c1b0cf41dda4ba0d77f0bfe4f932ccf9f60203b1d47753f69edf1c80e755e3159e596b1f6aa03cb0c275c4@"
+ besuNetworkAlias
+ ":"
+ besuP2pPort
+ "\")",
"attach",
goQuorumContainerGethIpcPath);
waitFor(30, () -> assertBlockHeight(besuWeb3j, 5));
waitFor(30, () -> assertBlockHeight(goQuorumWeb3j, 5));
}
@After
public void tearDown() throws IOException {
boolean fileExists = Files.deleteIfExists(Path.of(getResourcePath(ipcDirPath + ipcFilePath)));
if (!fileExists) {
System.out.println("Unable to delete tx IPC file.");
}
}
private GenericContainer buildBesuContainer() {
return new GenericContainer(besuImage)
.withNetwork(containerNetwork)
.withNetworkAliases(besuNetworkAlias)
.withExposedPorts(besuRpcPort, besuP2pPort)
.withClasspathResourceMapping(hostBesuKeyPath, containerBesuKeyPath, BindMode.READ_ONLY)
.withClasspathResourceMapping(hostGenesisPath, besuContainerGenesisPath, BindMode.READ_ONLY)
.withClasspathResourceMapping(hostKeyPath, containerKeyPath, BindMode.READ_ONLY)
.withCommand(
"--genesis-file",
besuContainerGenesisPath,
"--network-id",
networkId.toString(),
"--p2p-port",
besuP2pPort.toString(),
"--rpc-http-enabled",
"--rpc-http-port",
besuRpcPort.toString(),
"--rpc-http-api",
"ADMIN,ETH,NET,WEB3,GOQUORUM",
"--min-gas-price",
"0",
"--privacy-public-key-file",
"/tmp/keys/key2.pub",
"--privacy-url",
"http://" + "besuTessera" + ':' + tesseraQ2TRestPort);
}
private GenericContainer buildGoQuorumTesseraContainer(
final String ipcPath,
final String ipcBindDir,
final String containerIpcPath,
final String privKeyPath,
final String pubKeyPath) {
return new GenericContainer("quorumengineering/tessera:" + TESSERA_VERSION)
.withNetwork(containerNetwork)
.withNetworkAliases("goQuorumTessera")
.withClasspathResourceMapping(
hostTesseraResources, containerTesseraResources, BindMode.READ_ONLY)
.withClasspathResourceMapping(ipcPath, ipcBindDir, BindMode.READ_WRITE)
.withClasspathResourceMapping(hostKeyPath, containerKeyPath, BindMode.READ_ONLY)
.withCommand(
"--configfile " + tesseraContainerConfigFilePath,
"-o serverConfigs[0].serverAddress=http://localhost:" + tesseraRestPort,
"-o serverConfigs[1].serverAddress=unix:" + containerIpcPath,
"-o serverConfigs[2].serverAddress=http://" + "goQuorumTessera" + ":" + tesseraP2pPort,
"-o keys.keyData[0].privateKeyPath=" + privKeyPath,
"-o keys.keyData[0].publicKeyPath=" + pubKeyPath,
"-o peer[0].url=http://" + "goQuorumTessera" + ":" + tesseraP2pPort + "/",
"-o peer[1].url=http://" + "besuTessera" + ":" + tesseraP2pPort + "/")
.withExposedPorts(tesseraP2pPort, tesseraRestPort)
.waitingFor(Wait.forHttp("/upcheck"));
}
private GenericContainer buildBesuTesseraContainer(
final String privKeyPath, final String pubKeyPath) {
return new GenericContainer("quorumengineering/tessera:" + TESSERA_VERSION)
.withNetwork(containerNetwork)
.withNetworkAliases("besuTessera")
.withClasspathResourceMapping(
hostTesseraResources, containerTesseraResources, BindMode.READ_ONLY)
.withClasspathResourceMapping(hostKeyPath, containerKeyPath, BindMode.READ_ONLY)
.withCommand(
"--configfile " + tesseraContainerConfigFilePath,
"-o serverConfigs[0].serverAddress=http://localhost:" + tesseraRestPort,
"-o serverConfigs[1].serverAddress=http://localhost:" + tesseraQ2TRestPort,
"-o serverConfigs[2].serverAddress=http://" + "besuTessera" + ":" + tesseraP2pPort,
"-o keys.keyData[0].privateKeyPath=" + privKeyPath,
"-o keys.keyData[0].publicKeyPath=" + pubKeyPath,
"-o peer[0].url=http://" + "besuTessera" + ":" + tesseraP2pPort + "/",
"-o peer[1].url=http://" + "goQuorumTessera" + ":" + tesseraP2pPort + "/")
.withExposedPorts(tesseraP2pPort, tesseraRestPort)
.waitingFor(Wait.forHttp("/upcheck"));
}
private GenericContainer buildGoQuorumContainer(
final String ipcPath, final String ipcBindDir, final String containerIpcPath) {
return new GenericContainer("quorumengineering/quorum:" + GOQUORUM_VERSION)
.withNetwork(containerNetwork)
.dependsOn(tesseraGoQuorumContainer)
.withExposedPorts(goQuorumRpcPort, goQuorumP2pPort)
.withClasspathResourceMapping(
"/goQuorum/qdata/", goQuorumContainerDatadir, BindMode.READ_ONLY)
.withClasspathResourceMapping(hostGenesisPath, goQuorumContainerGenesis, BindMode.READ_ONLY)
.withClasspathResourceMapping(ipcPath, ipcBindDir, BindMode.READ_WRITE)
.withEnv("PRIVATE_CONFIG", containerIpcPath)
.withCreateContainerCmdModifier(
(Consumer<CreateContainerCmd>)
cmd ->
cmd.withEntrypoint(
"/bin/ash",
"-c",
"geth init "
+ goQuorumContainerGenesis
+ " --datadir "
+ goQuorumContainerDatadir
+ " && geth --datadir "
+ goQuorumContainerDatadir
+ " --networkid "
+ networkId.toString()
+ " --rpc"
+ " --rpcaddr 0.0.0.0"
+ " --rpcport "
+ goQuorumRpcPort.toString()
+ " --rpcapi admin,eth,debug,miner,net,shh,txpool,personal,web3,quorum,quorumExtension,clique"
+ " --emitcheckpoints"
+ " --port "
+ goQuorumP2pPort.toString()
+ " --verbosity"
+ " 3"
+ " --nousb"
+ " --nodekey "
+ goQuorumContainerDatadir
+ "/nodeKey"));
}
private Quorum buildWeb3JQuorum(final String containerIpAddress, final Integer mappedPort) {
return Quorum.build(new HttpService("http://" + containerIpAddress + ":" + mappedPort));
}
private void assertClientVersion(final Web3j web3, final String clientString) throws IOException {
final Web3ClientVersion clientVersionResult = web3.web3ClientVersion().send();
assertThat(clientVersionResult.getWeb3ClientVersion()).contains(clientString);
}
private void assertBlockHeight(final Web3j web3j, final int blockHeight) throws IOException {
final EthBlockNumber blockNumberResult = web3j.ethBlockNumber().send();
assertThat(blockNumberResult.getBlockNumber().intValueExact())
.isGreaterThanOrEqualTo(blockHeight);
}
public static void waitFor(final int timeout, final ThrowingRunnable condition) {
Awaitility.await()
.ignoreExceptions()
.atMost(timeout, TimeUnit.SECONDS)
.untilAsserted(condition);
}
private String getResourcePath(final String resourceName) {
return getClass().getResource(resourceName).getPath();
}
protected Credentials loadCredentials() throws IOException, CipherException {
return Credentials.create("8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63");
}
}

@ -1,312 +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.tests.container;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.fail;
import static org.hyperledger.besu.tests.container.helpers.ContractOperations.deployContractAndReturnAddress;
import static org.hyperledger.besu.tests.container.helpers.ContractOperations.generate64BytesHexString;
import static org.hyperledger.besu.tests.container.helpers.ContractOperations.getCode;
import static org.hyperledger.besu.tests.container.helpers.ContractOperations.getTransactionLog;
import static org.hyperledger.besu.tests.container.helpers.ContractOperations.sendLogEventAndReturnTransactionHash;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import io.reactivex.disposables.Disposable;
import okhttp3.OkHttpClient;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
import org.web3j.abi.EventEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.generated.Int256;
import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.EthLog;
import org.web3j.protocol.core.methods.response.EthTransaction;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.quorum.enclave.Enclave;
import org.web3j.quorum.enclave.Tessera;
import org.web3j.quorum.enclave.protocol.EnclaveService;
import org.web3j.quorum.methods.response.PrivatePayload;
import org.web3j.quorum.tx.QuorumTransactionManager;
import org.web3j.tx.response.PollingTransactionReceiptProcessor;
public class ContainerTests extends ContainerTestBase {
public static final String CONTRACT_PREFIX = "0x6080604052348015600f57600080fd5b5060";
private Credentials credentials;
private Enclave besuEnclave;
private EnclaveService besuEnclaveService;
private Enclave goQuorumEnclave;
private EnclaveService goQuorumEnclaveService;
private PollingTransactionReceiptProcessor besuPollingTransactionReceiptProcessor;
private PollingTransactionReceiptProcessor goQuorumPollingTransactionReceiptProcessor;
@Before
public void testSetUp() throws IOException, CipherException {
besuEnclaveService =
new EnclaveService(
"http://" + tesseraBesuContainer.getHost(),
tesseraBesuContainer.getMappedPort(tesseraRestPort),
new OkHttpClient());
besuEnclave = new Tessera(besuEnclaveService, besuWeb3j);
besuPollingTransactionReceiptProcessor =
new PollingTransactionReceiptProcessor(besuWeb3j, 1000, 10);
goQuorumEnclaveService =
new EnclaveService(
"http://" + tesseraGoQuorumContainer.getHost(),
tesseraGoQuorumContainer.getMappedPort(tesseraRestPort),
new OkHttpClient());
goQuorumEnclave = new Tessera(goQuorumEnclaveService, goQuorumWeb3j);
goQuorumPollingTransactionReceiptProcessor =
new PollingTransactionReceiptProcessor(goQuorumWeb3j, 1000, 10);
credentials = loadCredentials();
}
@Test
public void contractShouldBeDeployedToBothNodes() throws IOException, TransactionException {
// create a GoQuorum transaction manager
final QuorumTransactionManager qtm =
new QuorumTransactionManager(
goQuorumWeb3j,
goQuorumEnclave,
credentials,
goQuorumTesseraPubKey,
Arrays.asList(goQuorumTesseraPubKey, besuTesseraPubKey));
// Get the deployed contract address
final String contractAddress =
deployContractAndReturnAddress(
goQuorumWeb3j,
credentials,
qtm,
besuPollingTransactionReceiptProcessor,
goQuorumPollingTransactionReceiptProcessor);
// Generate a random value to insert into the log
final String logValue = generate64BytesHexString(98765L);
// Send the transaction and get the transaction hash
final String transactionHash =
sendLogEventAndReturnTransactionHash(
goQuorumWeb3j,
credentials,
contractAddress,
qtm,
besuPollingTransactionReceiptProcessor,
goQuorumPollingTransactionReceiptProcessor,
logValue);
// Get the transaction logs
final String goQuorumResult = getTransactionLog(goQuorumWeb3j, transactionHash);
final String besuResult = getTransactionLog(besuWeb3j, transactionHash);
assertThat(besuResult).isEqualTo(logValue);
assertThat(goQuorumResult).isEqualTo(logValue);
// Assert the Besu node gets value for eth_getCode
final String codeValueBesu = getCode(besuWeb3j, contractAddress);
assertThat(codeValueBesu).startsWith(CONTRACT_PREFIX);
// Assert the GoQuorum node gets value for eth_getCode
final String codeValueGoQuorum = getCode(goQuorumWeb3j, contractAddress);
assertThat(codeValueGoQuorum).startsWith(CONTRACT_PREFIX);
assertThat(codeValueBesu).isEqualTo(codeValueGoQuorum);
// Assert that the private payloads returned are the same
final String enclaveKey = getEnclaveKey(transactionHash);
final PrivatePayload goQuorumPayload = goQuorumWeb3j.quorumGetPrivatePayload(enclaveKey).send();
final PrivatePayload besuPayload = besuWeb3j.quorumGetPrivatePayload(enclaveKey).send();
assertThat(goQuorumPayload.getPrivatePayload()).isEqualTo(besuPayload.getPrivatePayload());
}
@NotNull
private String getEnclaveKey(final String transactionHash) throws IOException {
final EthTransaction send = besuWeb3j.ethGetTransactionByHash(transactionHash).send();
return send.getTransaction().get().getInput();
}
@Test
public void contractShouldBeDeployedOnlyToGoQuorumNode()
throws IOException, TransactionException {
// create a quorum transaction manager
final QuorumTransactionManager qtm =
new QuorumTransactionManager(
goQuorumWeb3j,
goQuorumEnclave,
credentials,
goQuorumTesseraPubKey,
List.of(goQuorumTesseraPubKey));
// Get the deployed contract address
final String contractAddress =
deployContractAndReturnAddress(
goQuorumWeb3j,
credentials,
qtm,
goQuorumPollingTransactionReceiptProcessor,
besuPollingTransactionReceiptProcessor);
// Generate a random value to insert into the log
final String logValue = generate64BytesHexString(192837L);
// Send the transaction and get the transaction hash
final String transactionHash =
sendLogEventAndReturnTransactionHash(
goQuorumWeb3j,
credentials,
contractAddress,
qtm,
goQuorumPollingTransactionReceiptProcessor,
besuPollingTransactionReceiptProcessor,
logValue);
// Assert the GoQuorum node has received the log
final String quorumResult = getTransactionLog(goQuorumWeb3j, transactionHash);
assertThat(quorumResult).isEqualTo(logValue);
// Assert the Besu node has not received the log
assertThatThrownBy(() -> getTransactionLog(besuWeb3j, transactionHash))
.hasMessageContaining("No log found");
// Assert the GoQuorum node gets value for eth_getCode
final String codeValueGoQuorum = getCode(goQuorumWeb3j, contractAddress);
assertThat(codeValueGoQuorum).startsWith(CONTRACT_PREFIX);
// Assert the Besu node gets NO value for eth_getCode
final String codeValueBesu = getCode(besuWeb3j, contractAddress);
assertThat(codeValueBesu).isEqualTo("0x");
}
@Test
public void contractShouldBeDeployedOnlyToBesuNode()
throws IOException, TransactionException, InterruptedException {
// create a GoQuorum transaction manager
final QuorumTransactionManager qtm =
new QuorumTransactionManager(
besuWeb3j, besuEnclave, credentials, besuTesseraPubKey, List.of(besuTesseraPubKey));
// Get the deployed contract address
final String contractAddress =
deployContractAndReturnAddress(
besuWeb3j,
credentials,
qtm,
besuPollingTransactionReceiptProcessor,
goQuorumPollingTransactionReceiptProcessor);
// Subscribe to the event
final Event testEvent =
new Event(
"TestEvent",
Arrays.<TypeReference<?>>asList(
new TypeReference<Address>(true) {}, new TypeReference<Int256>() {}));
final String eventEncoded = EventEncoder.encode(testEvent);
final EthFilter ethFilterSubscription =
new EthFilter(
DefaultBlockParameterName.LATEST, DefaultBlockParameterName.LATEST, contractAddress);
ethFilterSubscription.addSingleTopic(eventEncoded);
// Generate a value to insert into the log
final String logValue = generate64BytesHexString(1234567L);
final AtomicBoolean checked = new AtomicBoolean(false);
final Disposable subscribe =
besuWeb3j
.ethLogFlowable(ethFilterSubscription)
.subscribe(
log -> {
final String eventHash =
log.getTopics().get(0); // Index 0 is the event definition hash
if (eventHash.equals(eventEncoded)) {
// address indexed _arg1
final Address arg1 =
(Address)
FunctionReturnDecoder.decodeIndexedValue(
log.getTopics().get(1), new TypeReference<Address>() {});
assertThat(arg1.toString()).isEqualTo(credentials.getAddress());
final String data = log.getData();
assertThat(data.substring(2)).isEqualTo(logValue);
checked.set(true);
}
});
// Send the transaction and get the transaction hash
final String transactionHash =
sendLogEventAndReturnTransactionHash(
besuWeb3j,
credentials,
contractAddress,
qtm,
besuPollingTransactionReceiptProcessor,
goQuorumPollingTransactionReceiptProcessor,
logValue);
// Assert the GoQuorum node gets NO value for eth_getCode
final String codeValueGoQuorum = getCode(goQuorumWeb3j, contractAddress);
assertThat(codeValueGoQuorum).isEqualTo("0x");
// Assert the Besu node gets a value for eth_getCode
final String codeValueBesu = getCode(besuWeb3j, contractAddress);
assertThat(codeValueBesu).startsWith(CONTRACT_PREFIX);
int secondsWaited = 0;
while (!checked.get()) {
Thread.sleep(1000);
secondsWaited++;
if (secondsWaited > 30) {
fail("Waited more than 30 seconds for log.");
}
}
subscribe.dispose();
// Assert the Besu node has received the log
final String besuResult = getTransactionLog(besuWeb3j, transactionHash);
assertThat(besuResult).isEqualTo(logValue);
// Assert the GoQuorum node has not received the log
assertThatThrownBy(() -> getTransactionLog(goQuorumWeb3j, transactionHash))
.hasMessageContaining("No log found");
// Get transaction log using a filter
final EthFilter ethFilter =
new EthFilter(
DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST, contractAddress);
ethFilter.addSingleTopic(eventEncoded);
@SuppressWarnings("rawtypes")
final List<EthLog.LogResult> logs = besuWeb3j.ethGetLogs(ethFilter).send().getLogs();
assertThat(logs.size()).isEqualTo(1);
assertThat(logs.toString()).contains(transactionHash);
assertThat(logs.toString()).contains(logValue);
}
}

@ -1,186 +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.tests.container.helpers;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import org.jetbrains.annotations.NotNull;
import org.web3j.abi.FunctionEncoder;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGetCode;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.quorum.Quorum;
import org.web3j.quorum.tx.QuorumTransactionManager;
import org.web3j.tx.response.PollingTransactionReceiptProcessor;
public class ContractOperations {
public static final String SIMPLE_STORAGE_CONTRACT_BYTECODE =
"6080604052348015600f57600080fd5b5060de8061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060275760003560e01c8062f88abf14602c575b600080fd5b605560048036036020811015604057600080fd5b81019080803590602001909291905050506057565b005b3373ffffffffffffffffffffffffffffffffffffffff167f748aa07c80b05bd067e3688dbb79d9f9583cd018be6a589a7c364cacd770e0a2826040518082815260200191505060405180910390a25056fea26469706673582212207df0d3ad8bced04b7bd476cc81a6233c0b575966c29b4af96450313628ee623964736f6c63430007040033";
public static String SIMPLE_STORAGE_CONTRACT_WITH_CONSTRUCTOR;
public static String deployContractAndReturnAddress(
final Quorum quorumWeb3j,
final Credentials credentials,
final QuorumTransactionManager qtm,
final PollingTransactionReceiptProcessor pollingTransactionReceiptProcessorReturn,
final PollingTransactionReceiptProcessor pollingTransactionReceiptProcessorIgnore)
throws IOException, TransactionException {
// Build smart contract transaction
final String encodedConstructor = FunctionEncoder.encodeConstructor(Collections.emptyList());
SIMPLE_STORAGE_CONTRACT_WITH_CONSTRUCTOR =
SIMPLE_STORAGE_CONTRACT_BYTECODE + encodedConstructor;
final RawTransaction contractTransaction =
RawTransaction.createTransaction(
BigInteger.valueOf(getNonce(quorumWeb3j, credentials)),
BigInteger.ZERO,
BigInteger.valueOf(4300000),
"",
BigInteger.ZERO,
SIMPLE_STORAGE_CONTRACT_WITH_CONSTRUCTOR);
// Send the signed transaction to quorum
final EthSendTransaction sendContractTransactionResult = qtm.signAndSend(contractTransaction);
assertThat(sendContractTransactionResult.hasError()).isFalse();
pollNodeForTransactionReceipt(
pollingTransactionReceiptProcessorIgnore,
sendContractTransactionResult.getTransactionHash());
// Poll for the transaction receipt
final TransactionReceipt transactionReceiptResult =
pollNodeForTransactionReceiptResult(
pollingTransactionReceiptProcessorReturn,
sendContractTransactionResult.getTransactionHash());
return transactionReceiptResult.getContractAddress();
}
public static String getCode(final Quorum web3j, final String contractAddress)
throws IOException {
final DefaultBlockParameter blockParam =
DefaultBlockParameter.valueOf(DefaultBlockParameterName.LATEST.toString());
final EthGetCode codeResult = web3j.ethGetCode(contractAddress, blockParam).send();
assertThat(codeResult.getCode())
.withFailMessage("Code for contractAddress not found.")
.isNotEmpty();
return codeResult.getCode();
}
public static String getTransactionLog(final Quorum web3j, final String transactionHash)
throws IOException {
final EthGetTransactionReceipt transactionReceiptResult =
web3j.ethGetTransactionReceipt(transactionHash).send();
assertThat(transactionReceiptResult.getTransactionReceipt())
.withFailMessage("Transaction for log not found.")
.isNotEmpty();
final List<Log> logs = transactionReceiptResult.getTransactionReceipt().get().getLogs();
assertThat(logs.size()).withFailMessage("No log found.").isEqualTo(1);
// Remove the 0x prefix
return logs.get(0).getData().substring(2);
}
public static String sendLogEventAndReturnTransactionHash(
final Quorum quorum,
final Credentials credentials,
final String contractAddress,
final QuorumTransactionManager qtm,
final PollingTransactionReceiptProcessor pollingTransactionReceiptProcessorReturn,
final PollingTransactionReceiptProcessor pollingTransactionReceiptProcessorIgnore,
final String param)
throws IOException, TransactionException {
final String functionSig = "0x00f88abf";
final String data = functionSig + param;
final RawTransaction logEventTransaction =
RawTransaction.createTransaction(
BigInteger.valueOf(getNonce(quorum, credentials)),
BigInteger.ZERO,
BigInteger.valueOf(4300000),
contractAddress,
BigInteger.ZERO,
data);
final EthSendTransaction sendTransactionResult = qtm.signAndSend(logEventTransaction);
assertThat(sendTransactionResult.hasError()).isFalse();
pollNodeForTransactionReceipt(
pollingTransactionReceiptProcessorIgnore, sendTransactionResult.getTransactionHash());
final TransactionReceipt logReceiptResult =
pollNodeForTransactionReceiptResult(
pollingTransactionReceiptProcessorReturn, sendTransactionResult.getTransactionHash());
return logReceiptResult.getTransactionHash();
}
public static String generate64BytesHexString(final long number) {
final String str = Long.toHexString(number);
return prependZeroesToPadHexStringToGivenLength(str, 64);
}
@NotNull
public static String prependZeroesToPadHexStringToGivenLength(
final String hexString, final int lenRequested) {
final StringBuilder sb = new StringBuilder(hexString);
while (sb.length() < lenRequested) {
sb.insert(0, '0');
}
return sb.toString();
}
public static int getNonce(final Quorum quorum, final Credentials credentials)
throws IOException {
final EthGetTransactionCount transactionCountResult =
quorum
.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.LATEST)
.send();
assertThat(transactionCountResult.hasError()).isFalse();
return transactionCountResult.getTransactionCount().intValueExact();
}
public static TransactionReceipt pollNodeForTransactionReceiptResult(
final PollingTransactionReceiptProcessor pollingTransactionReceiptProcessor,
final String transactionHash)
throws IOException, TransactionException {
final TransactionReceipt transactionReceiptResult =
pollingTransactionReceiptProcessor.waitForTransactionReceipt(transactionHash);
assertThat(transactionReceiptResult.isStatusOK()).isTrue();
return transactionReceiptResult;
}
public static void pollNodeForTransactionReceipt(
final PollingTransactionReceiptProcessor pollingTransactionReceiptProcessor,
final String transactionHash)
throws IOException, TransactionException {
final TransactionReceipt transactionReceiptResult =
pollingTransactionReceiptProcessor.waitForTransactionReceipt(transactionHash);
assertThat(transactionReceiptResult.isStatusOK()).isTrue();
}
}

@ -1 +0,0 @@
0x8a15eaa6e526e9b8ebdea0bfc6d4399b0ae7ba1c

@ -1 +0,0 @@
0xc86c0030a86bb894c1e10c25d48d4949a288df9c6ff736b32d977f39893fd0dc

@ -1,45 +0,0 @@
{
"config":{
"homesteadBlock": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"chainId":2020,
"eip150Block": 0,
"eip155Block": 0,
"eip150Hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"eip158Block": 0,
"clique":{
"blockperiodseconds":2,
"epochlength":30000,
"period": 2,
"epoch": 30000
},
"isQuorum": true
},
"coinbase":"0x0000000000000000000000000000000000000000",
"extraData":"0x00000000000000000000000000000000000000000000000000000000000000008a15eaa6e526e9b8ebdea0bfc6d4399b0ae7ba1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
},
"difficulty": "0x0",
"gasLimit": "0xE0000000",
"mixhash": "0x00000000000000000000000000000000000000647572616c65787365646c6578",
"nonce": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x00"
}

@ -1 +0,0 @@
c0b7ff2352175d2a43d72eca7c2f806cc7bd74a7a597630d62f5261834348f74

@ -1,6 +0,0 @@
{
"type" : "unlocked",
"data" : {
"bytes" : "srn2w10NWdvWyHkPMWB07W5NjIPmiAHRqESL8vH3Kyw="
}
}

@ -1 +0,0 @@
3XGBIf+x8IdVQOVfIsbRnHwTYOJP/Fx84G8gMmy8qDM=

@ -1,6 +0,0 @@
{
"type" : "unlocked",
"data" : {
"bytes" : "LWjzMnDP/MQIATegt45LTrMh1i9ISX64CFO0EzFDNhg="
}
}

@ -1 +0,0 @@
8JJLEAbq6o9m4Kqm++v0Y1n9Z2ryAFtZTyhnxSKWgws=

@ -1,47 +0,0 @@
{
"useWhiteList": false,
"jdbc": {
"username": "sa",
"password": "",
"url": "jdbc:h2:/tmp/tessera;LOCK_TIMEOUT=20000",
"autoCreateTables": true
},
"serverConfigs":[
{
"app":"ThirdParty",
"enabled": true,
"serverAddress": "http://localhost:9081",
"communicationType" : "REST"
},
{
"app":"Q2T",
"enabled": true,
"serverAddress": "unix:/tmp/test.ipc",
"communicationType" : "REST"
},
{
"app":"P2P",
"enabled": true,
"serverAddress":"http://localhost:9001",
"sslConfig": {
"tls": "OFF"
},
"communicationType" : "REST"
}
],
"peer": [
{
"url": "http://localhost:9001"
}
],
"keys": {
"passwords": [],
"keyData": [
{
"privateKeyPath": "myKey.key",
"publicKeyPath": "myKey.pub"
}
]
},
"alwaysSendTo": []
}

@ -1,9 +0,0 @@
pragma solidity >=0.6.0 < 0.8.0;
contract TestContract {
event TestEvent(address indexed _from, int val);
function logEvent(int randomNum) public {
emit TestEvent(msg.sender, randomNum);
}
}

@ -44,7 +44,6 @@ include 'consensus:ibft'
include 'consensus:ibftlegacy'
include 'consensus:merge'
include 'consensus:qbft'
include 'container-tests:tests'
include 'datatypes'
include 'crypto'
include 'datatypes'

Loading…
Cancel
Save