chore: Removed Privacy ATs (#7530)

* chore: Removed privacy acceptance classes

Signed-off-by: Preeti <35308865+pr9t@users.noreply.github.com>

* Chore: removed classes that extends PrivateLogFilterAcceptanceTest and FlexiblePrivacyAcceptanceTestBase

Signed-off-by: Preeti <35308865+pr9t@users.noreply.github.com>

---------

Signed-off-by: Preeti <35308865+pr9t@users.noreply.github.com>
Co-authored-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
Preeti
2024-09-02 04:56:11 +05:30
committed by GitHub
parent fa73102097
commit c915e057cf
22 changed files with 0 additions and 4753 deletions

View File

@@ -1,74 +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.acceptance.dsl.privacy;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.NOOP;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import static org.web3j.utils.Restriction.RESTRICTED;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.PluginCreateRandomPrivacyGroupIdTransaction;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.RestrictedCreatePrivacyGroupTransaction;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.util.Arrays;
import java.util.Collection;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.web3j.utils.Restriction;
@RunWith(Parameterized.class)
public abstract class ParameterizedEnclaveTestBase extends PrivacyAcceptanceTestBase {
protected final Restriction restriction;
protected final EnclaveType enclaveType;
protected final EnclaveEncryptorType enclaveEncryptorType;
protected ParameterizedEnclaveTestBase(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType) {
this.restriction = restriction;
this.enclaveType = enclaveType;
this.enclaveEncryptorType = enclaveEncryptorType;
}
@Parameters(name = "{0} tx with {1} enclave and {2} encryptor type")
public static Collection<Object[]> params() {
return Arrays.asList(
new Object[][] {
{RESTRICTED, TESSERA, NACL},
{RESTRICTED, TESSERA, EC},
{UNRESTRICTED, NOOP, EnclaveEncryptorType.NOOP}
});
}
public Transaction<String> createPrivacyGroup(
final String name, final String description, final PrivacyNode... nodes) {
if (restriction == RESTRICTED) {
return new RestrictedCreatePrivacyGroupTransaction(name, description, nodes);
} else if (restriction == UNRESTRICTED) {
return new PluginCreateRandomPrivacyGroupIdTransaction();
} else {
throw new RuntimeException("Do not know how to handle " + restriction);
}
}
}

View File

@@ -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.tests.acceptance.dsl.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.tests.acceptance.dsl.WaitUtils;
import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions;
import org.hyperledger.besu.tests.acceptance.dsl.condition.net.NetConditions;
import org.hyperledger.besu.tests.acceptance.dsl.condition.priv.PrivConditions;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeFactory;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivateContractVerifier;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivateTransactionVerifier;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.contract.PrivateContractTransactions;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.PrivacyTransactions;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.contract.ContractTransactions;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.eth.EthTransactions;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.net.NetTransactions;
import java.math.BigInteger;
import io.vertx.core.Vertx;
import org.junit.After;
import org.junit.ClassRule;
import org.junit.rules.TemporaryFolder;
public class PrivacyAcceptanceTestBase {
@ClassRule public static final TemporaryFolder privacy = new TemporaryFolder();
protected final PrivacyTransactions privacyTransactions;
protected final PrivateContractVerifier privateContractVerifier;
protected final PrivateTransactionVerifier privateTransactionVerifier;
protected final PrivacyNodeFactory privacyBesu;
protected final PrivateContractTransactions privateContractTransactions;
protected final PrivConditions priv;
protected final PrivacyCluster privacyCluster;
protected final ContractTransactions contractTransactions;
protected final NetConditions net;
protected final EthTransactions ethTransactions;
protected final EthConditions eth;
private final Vertx vertx = Vertx.vertx();
public PrivacyAcceptanceTestBase() {
ethTransactions = new EthTransactions();
net = new NetConditions(new NetTransactions());
privacyTransactions = new PrivacyTransactions();
privateContractVerifier = new PrivateContractVerifier();
privateTransactionVerifier = new PrivateTransactionVerifier(privacyTransactions);
privacyBesu = new PrivacyNodeFactory(vertx);
privateContractTransactions = new PrivateContractTransactions();
privacyCluster = new PrivacyCluster(net);
priv =
new PrivConditions(
new org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy
.PrivacyTransactions());
contractTransactions = new ContractTransactions();
eth = new EthConditions(ethTransactions);
}
protected void waitForBlockHeight(final PrivacyNode node, final long blockchainHeight) {
WaitUtils.waitFor(
120,
() ->
assertThat(node.execute(ethTransactions.blockNumber()))
.isGreaterThanOrEqualTo(BigInteger.valueOf(blockchainHeight)));
}
@After
public void tearDownAcceptanceTestBase() {
privacyCluster.close();
vertx.close();
}
}

View File

@@ -1,318 +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.acceptance.privacy;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.bft.ConsensusType;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.containers.Network;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.utils.Restriction;
@RunWith(Parameterized.class)
public class BftPrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase {
private final BftPrivacyType bftPrivacyType;
public static class BftPrivacyType {
private final EnclaveType enclaveType;
private final EnclaveEncryptorType enclaveEncryptorType;
private final ConsensusType consensusType;
private final Restriction restriction;
public BftPrivacyType(
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType,
final ConsensusType consensusType,
final Restriction restriction) {
this.enclaveType = enclaveType;
this.enclaveEncryptorType = enclaveEncryptorType;
this.consensusType = consensusType;
this.restriction = restriction;
}
@Override
public String toString() {
return String.join(
",",
enclaveType.toString(),
enclaveEncryptorType.toString(),
consensusType.toString(),
restriction.toString());
}
}
public BftPrivacyClusterAcceptanceTest(final BftPrivacyType bftPrivacyType) {
this.bftPrivacyType = bftPrivacyType;
}
@Parameterized.Parameters(name = "{0}")
public static Collection<BftPrivacyType> bftPrivacyTypes() {
final List<BftPrivacyType> bftPrivacyTypes = new ArrayList<>();
for (EnclaveType x : EnclaveType.valuesForTests()) {
for (ConsensusType consensusType : ConsensusType.values()) {
bftPrivacyTypes.add(
new BftPrivacyType(
x, EnclaveEncryptorType.NACL, consensusType, Restriction.RESTRICTED));
bftPrivacyTypes.add(
new BftPrivacyType(x, EnclaveEncryptorType.EC, consensusType, Restriction.RESTRICTED));
}
}
for (ConsensusType consensusType : ConsensusType.values()) {
bftPrivacyTypes.add(
new BftPrivacyType(
EnclaveType.NOOP,
EnclaveEncryptorType.NOOP,
consensusType,
Restriction.UNRESTRICTED));
}
return bftPrivacyTypes;
}
private PrivacyNode alice;
private PrivacyNode bob;
private PrivacyNode charlie;
@Before
public void setUp() throws Exception {
final Network containerNetwork = Network.newNetwork();
alice = createNode(containerNetwork, "node1", 0);
bob = createNode(containerNetwork, "node2", 1);
charlie = createNode(containerNetwork, "node3", 2);
privacyCluster.start(alice, bob, charlie);
alice.verify(priv.syncingStatus(false));
bob.verify(priv.syncingStatus(false));
charlie.verify(priv.syncingStatus(false));
}
private PrivacyNode createNode(
final Network containerNetwork, final String nodeName, final int privacyAccount)
throws IOException {
if (bftPrivacyType.consensusType == ConsensusType.IBFT2) {
return privacyBesu.createIbft2NodePrivacyEnabled(
nodeName,
PrivacyAccountResolver.values()[privacyAccount].resolve(
bftPrivacyType.enclaveEncryptorType),
true,
bftPrivacyType.enclaveType,
Optional.of(containerNetwork),
false,
false,
bftPrivacyType.restriction == Restriction.UNRESTRICTED,
"0xAA");
} else if (bftPrivacyType.consensusType == ConsensusType.QBFT) {
return privacyBesu.createQbftNodePrivacyEnabled(
nodeName,
PrivacyAccountResolver.values()[privacyAccount].resolve(
bftPrivacyType.enclaveEncryptorType),
bftPrivacyType.enclaveType,
Optional.of(containerNetwork),
false,
false,
bftPrivacyType.restriction == Restriction.UNRESTRICTED,
"0xAA");
} else {
throw new IllegalStateException("Unknown consensus type " + bftPrivacyType.consensusType);
}
}
@Test
public void onlyAliceAndBobCanExecuteContract() {
// Contract address is generated from sender address and transaction nonce
final String contractAddress =
EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, alice.getAddress().toString())
.verify(eventEmitter);
final String transactionHash =
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
alice.getTransactionSigningKey(),
bftPrivacyType.restriction,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
final PrivateTransactionReceipt expectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, expectedReceipt));
if (bftPrivacyType.restriction != Restriction.UNRESTRICTED) {
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash));
}
}
@Test
public void aliceCanDeployMultipleTimesInSingleGroup() {
final String firstDeployedAddress =
EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
privacyCluster.stopNode(charlie);
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
final String secondDeployedAddress =
EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType)
? "0x5194e214fae257530710d18c868df7a295d9d53b"
: "0x10f807f8a905da5bd319196da7523c6bd768690f";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
}
@Test
public void canInteractWithMultiplePrivacyGroups() {
// alice deploys contract
final String firstDeployedAddress =
EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType)
? "0x760359bc605b3848f5199829bde6b382d90fb8eb"
: "0xff206d21150a8da5b83629d8a722f3135ed532b1";
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey(),
charlie.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
// charlie interacts with contract
final String firstTransactionHash =
charlie.execute(
privateContractTransactions.callSmartContract(
firstEventEmitter.getContractAddress(),
firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
charlie.getTransactionSigningKey(),
bftPrivacyType.restriction,
charlie.getEnclaveKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
// alice gets receipt from charlie's interaction
final PrivateTransactionReceipt aliceReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash));
// verify bob and charlie have access to the same receipt
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, aliceReceipt));
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, aliceReceipt));
// alice deploys second contract
final String secondDeployedAddress =
EnclaveEncryptorType.EC.equals(bftPrivacyType.enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
// bob interacts with contract
final String secondTransactionHash =
bob.execute(
privateContractTransactions.callSmartContract(
secondEventEmitter.getContractAddress(),
secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
bob.getTransactionSigningKey(),
bftPrivacyType.restriction,
bob.getEnclaveKey(),
alice.getEnclaveKey()));
// alice gets receipt from bob's interaction
final PrivateTransactionReceipt secondExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
secondTransactionHash, secondExpectedReceipt));
// charlie cannot see the receipt
if (bftPrivacyType.restriction != Restriction.UNRESTRICTED) {
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash));
}
}
}

View File

@@ -1,77 +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.acceptance.privacy;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.util.Optional;
import org.junit.Test;
import org.web3j.utils.Restriction;
public class DeployPrivateSmartContractAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode minerNode;
public DeployPrivateSmartContractAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
minerNode =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(minerNode);
minerNode.verify(priv.syncingStatus(false));
}
@Test
public void deployingMustGiveValidReceiptAndCode() throws Exception {
final String contractAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0xfeeb2367e77e28f75fc3bcc55b70a535752db058"
: "0x89ce396d0f9f937ddfa71113e29b2081c4869555";
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
minerNode.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString())
.verify(eventEmitter);
privateContractVerifier.validContractCodeProvided().verify(eventEmitter);
}
}

View File

@@ -1,240 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.catchThrowable;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.security.KeyPairGenerator;
import java.security.spec.ECGenParameterSpec;
import java.util.Arrays;
import java.util.Base64;
import java.util.Collection;
import java.util.Optional;
import org.apache.tuweni.crypto.sodium.Box;
import org.assertj.core.api.Condition;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.testcontainers.containers.Network;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.utils.Restriction;
@RunWith(Parameterized.class)
public class EnclaveErrorAcceptanceTest extends PrivacyAcceptanceTestBase {
private final PrivacyNode alice;
private final PrivacyNode bob;
private final String wrongPublicKey;
@Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}
public EnclaveErrorAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
final Network containerNetwork = Network.newNetwork();
alice =
privacyBesu.createIbft2NodePrivacyEnabled(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork),
false,
false,
false,
"0xAA");
bob =
privacyBesu.createIbft2NodePrivacyEnabled(
"node2",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork),
false,
false,
false,
"0xBB");
privacyCluster.start(alice, bob);
alice.verify(priv.syncingStatus(false));
bob.verify(priv.syncingStatus(false));
final byte[] wrongPublicKeyBytes =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? getSECP256r1PublicKeyByteArray()
: Box.KeyPair.random().publicKey().bytesArray();
wrongPublicKey = Base64.getEncoder().encodeToString(wrongPublicKeyBytes);
}
@Test
public void aliceCannotSendTransactionFromBobNode() {
final Throwable throwable =
catchThrowable(
() ->
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
wrongPublicKey,
bob.getEnclaveKey())));
assertThat(throwable)
.hasMessageContaining(
RpcErrorType.PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY.getMessage());
}
@Test
public void enclaveNoPeerUrlError() {
final Throwable throwable =
catchThrowable(
() ->
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
wrongPublicKey)));
final String tesseraMessage = RpcErrorType.TESSERA_NODE_MISSING_PEER_URL.getMessage();
assertThat(throwable.getMessage()).has(matchTesseraEnclaveMessage(tesseraMessage));
}
@Test
public void whenEnclaveIsDisconnectedGetReceiptReturnsInternalError() {
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), alice.getAddress().toString())
.verify(eventEmitter);
final String transactionHash =
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
alice.getTransactionSigningKey(),
Restriction.RESTRICTED,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
final PrivateTransactionReceipt receiptBeforeEnclaveLosesConnection =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
alice.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, receiptBeforeEnclaveLosesConnection));
alice.getEnclave().stop();
alice.verify(
privateTransactionVerifier.internalErrorPrivateTransactionReceipt(transactionHash));
}
@Test
@Ignore("Web3J is broken by PR #1426")
public void transactionFailsIfPartyIsOffline() {
// Contract address is generated from sender address and transaction nonce
final String contractAddress = "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, alice.getAddress().toString())
.verify(eventEmitter);
bob.getEnclave().stop();
final Throwable throwable =
catchThrowable(
() ->
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
alice.getTransactionSigningKey(),
Restriction.RESTRICTED,
alice.getEnclaveKey(),
bob.getEnclaveKey())));
assertThat(throwable).hasMessageContaining("NodePropagatingToAllPeers");
}
@Test
public void createPrivacyGroupReturnsCorrectError() {
final Throwable throwable =
catchThrowable(() -> alice.execute(privacyTransactions.createPrivacyGroup(null, null)));
final String tesseraMessage = RpcErrorType.TESSERA_CREATE_GROUP_INCLUDE_SELF.getMessage();
assertThat(throwable.getMessage()).has(matchTesseraEnclaveMessage(tesseraMessage));
}
private Condition<String> matchTesseraEnclaveMessage(final String enclaveMessage) {
return new Condition<>(
message -> message.contains(enclaveMessage),
"Message did not match Tessera expected output");
}
private byte[] getSECP256r1PublicKeyByteArray() {
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
final ECGenParameterSpec spec = new ECGenParameterSpec("secp256r1");
keyGen.initialize(spec);
return keyGen.generateKeyPair().getPublic().getEncoded();
} catch (Exception exception) {
return new byte[0];
}
}
}

View File

@@ -1,642 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import static org.junit.runners.Parameterized.Parameters;
import org.hyperledger.besu.tests.acceptance.dsl.condition.eth.EthConditions;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import com.google.common.collect.Lists;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.testcontainers.containers.Network;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
@RunWith(Parameterized.class)
public class FlexiblePrivacyAcceptanceTest extends FlexiblePrivacyAcceptanceTestBase {
private final EnclaveType enclaveType;
private final EnclaveEncryptorType enclaveEncryptorType;
public FlexiblePrivacyAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) {
this.enclaveType = enclaveType;
this.enclaveEncryptorType = enclaveEncryptorType;
}
@Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}
private PrivacyNode alice;
private PrivacyNode bob;
private PrivacyNode charlie;
private final MinerTransactions minerTransactions = new MinerTransactions();
private final EthConditions ethConditions = new EthConditions(ethTransactions);
private static final String EXPECTED_STORE_OUTPUT_DATA =
"0x000000000000000000000000f17f52151ebef6c7334fad080c5704d77216b7320000000000000000000000000000000000000000000000000000000000000539";
private static final String EXPECTED_STORE_EVENT_TOPIC =
"0xc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5";
@Before
public void setUp() throws Exception {
final Network containerNetwork = Network.newNetwork();
alice =
privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork));
bob =
privacyBesu.createFlexiblePrivacyGroupEnabledNode(
"node2",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork));
charlie =
privacyBesu.createFlexiblePrivacyGroupEnabledNode(
"node3",
PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork));
privacyCluster.start(alice, bob, charlie);
alice.verify(priv.syncingStatus(false));
bob.verify(priv.syncingStatus(false));
charlie.verify(priv.syncingStatus(false));
}
@Test
public void nodeCanCreatePrivacyGroup() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice);
}
@Test
public void deployingMustGiveValidReceipt() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob);
final Contract eventEmitter = deployPrivateContract(EventEmitter.class, privacyGroupId, alice);
final String commitmentHash = getContractDeploymentCommitmentHash(eventEmitter);
alice.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash));
bob.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash));
}
@Test
public void canAddParticipantToGroup() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob);
final Contract eventEmitter = deployPrivateContract(EventEmitter.class, privacyGroupId, alice);
final String commitmentHash = getContractDeploymentCommitmentHash(eventEmitter);
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(commitmentHash));
final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey());
lockPrivacyGroup(privacyGroupId, alice, aliceCredentials);
addMembersToPrivacyGroup(privacyGroupId, alice, aliceCredentials, charlie);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob, charlie);
charlie.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(commitmentHash));
}
@Test
public void removedMemberCannotSendTransactionToGroup() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob);
final String removeHash =
removeFromPrivacyGroup(
privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob);
bob.verify(privateTransactionVerifier.existingPrivateTransactionReceipt(removeHash));
assertThatThrownBy(() -> deployPrivateContract(EventEmitter.class, privacyGroupId, bob))
.isInstanceOf(RuntimeException.class)
.hasMessageContaining("Flexible Privacy group does not exist.");
}
@Test
public void canInteractWithPrivateGenesisPreCompile() throws Exception {
final String privacyGroupId = createFlexiblePrivacyGroup(alice, bob);
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.loadSmartContractWithPrivacyGroupId(
"0x1000000000000000000000000000000000000001",
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupId));
privateTransactionVerifier.existingPrivateTransactionReceipt(
eventEmitter.store(BigInteger.valueOf(42)).send().getTransactionHash());
final String aliceResponse =
alice
.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))
.getValue();
assertThat(new BigInteger(aliceResponse.substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(42));
final String bobResponse =
bob.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))
.getValue();
assertThat(new BigInteger(bobResponse.substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(42));
final String charlieResponse =
charlie
.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))
.getValue();
assertThat(charlieResponse).isEqualTo("0x");
}
@Test
public void memberCanBeAddedAfterBeingRemoved() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice);
lockPrivacyGroup(privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()));
addMembersToPrivacyGroup(
privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob);
final EventEmitter eventEmitter =
deployPrivateContract(EventEmitter.class, privacyGroupId, alice);
final int valueSetWhileBobWasMember = 17;
final PrivateTransactionReceipt receiptWhileBobMember =
setEventEmitterValueAndCheck(
Lists.newArrayList(alice, bob),
privacyGroupId,
eventEmitter,
valueSetWhileBobWasMember);
removeFromPrivacyGroup(
privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice);
final int valueSetWhileBobWas_NOT_aMember = 1337;
final PrivateTransactionReceipt receiptWhileBobRemoved =
setEventEmitterValueAndCheck(
Lists.newArrayList(alice),
privacyGroupId,
eventEmitter,
valueSetWhileBobWas_NOT_aMember);
checkEmitterValue(
Lists.newArrayList(bob),
privacyGroupId,
eventEmitter,
valueSetWhileBobWasMember); // bob did not get the last transaction
lockPrivacyGroup(privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()));
addMembersToPrivacyGroup(
privacyGroupId, alice, Credentials.create(alice.getTransactionSigningKey()), bob);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob);
checkEmitterValue(
Lists.newArrayList(alice, bob),
privacyGroupId,
eventEmitter,
valueSetWhileBobWas_NOT_aMember);
PrivateTransactionReceipt receipt =
bob.execute(
privacyTransactions.getPrivateTransactionReceipt(
receiptWhileBobRemoved.getcommitmentHash()));
assertThat(receipt.getStatus()).isEqualTo("0x1");
receipt =
bob.execute(
privacyTransactions.getPrivateTransactionReceipt(
receiptWhileBobMember.getcommitmentHash()));
assertThat(receipt.getStatus()).isEqualTo("0x1");
}
PrivateTransactionReceipt setEventEmitterValueAndCheck(
final List<PrivacyNode> nodes,
final String privacyGroupId,
final EventEmitter eventEmitter,
final int value) {
final PrivateTransactionReceipt receiptWhileBobMember =
setEventEmitterValue(nodes, privacyGroupId, eventEmitter, value);
checkEmitterValue(nodes, privacyGroupId, eventEmitter, value);
return receiptWhileBobMember;
}
private PrivateTransactionReceipt setEventEmitterValue(
final List<PrivacyNode> nodes,
final String privacyGroupId,
final EventEmitter eventEmitter,
final int value) {
final PrivacyNode firstNode = nodes.get(0);
final String txHash =
firstNode.execute(
privateContractTransactions.callOnchainPermissioningSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.valueOf(value)).encodeFunctionCall(),
firstNode.getTransactionSigningKey(),
firstNode.getEnclaveKey(),
privacyGroupId));
PrivateTransactionReceipt receipt = null;
for (final PrivacyNode node : nodes) {
receipt = node.execute(privacyTransactions.getPrivateTransactionReceipt(txHash));
assertThat(receipt.getStatus()).isEqualTo("0x1");
}
return receipt;
}
private void checkEmitterValue(
final List<PrivacyNode> nodes,
final String privacyGroupId,
final EventEmitter eventEmitter,
final int expectedValue) {
for (final PrivacyNode node : nodes) {
final EthCall response =
node.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()));
assertThat(new BigInteger(response.getValue().substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(expectedValue));
}
}
@Test
public void bobCanAddCharlieAfterBeingAddedByAlice() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice);
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), alice.getAddress().toString())
.verify(eventEmitter);
final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey());
final String aliceLockHash =
alice.execute(
privacyTransactions.privxLockPrivacyGroupAndCheck(
privacyGroupId, alice, aliceCredentials));
alice.execute(
privacyTransactions.addToPrivacyGroup(privacyGroupId, alice, aliceCredentials, bob));
checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob);
bob.execute(
privacyTransactions.privxLockPrivacyGroupAndCheck(privacyGroupId, bob, aliceCredentials));
alice.execute(minerTransactions.minerStop());
alice.getBesu().verify(ethConditions.miningStatus(false));
final BigInteger pendingTransactionFilterId =
alice.execute(ethTransactions.newPendingTransactionsFilter());
final String callHash =
alice.execute(
privateContractTransactions.callOnchainPermissioningSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.value().encodeFunctionCall(),
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupId));
final String bobAddHash =
addMembersToPrivacyGroup(privacyGroupId, bob, aliceCredentials, charlie);
alice
.getBesu()
.verify(
ethConditions.expectNewPendingTransactions(
pendingTransactionFilterId, Arrays.asList(callHash, bobAddHash)));
alice.execute(minerTransactions.minerStart());
alice.getBesu().verify(ethConditions.miningStatus(true));
checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob, charlie);
final Optional<TransactionReceipt> aliceAddReceipt =
alice.execute(ethTransactions.getTransactionReceipt(bobAddHash));
assertThat(aliceAddReceipt.get().getStatus())
.isEqualTo("0x1"); // this means the PMT for the "add" succeeded which is what we expect
final Optional<TransactionReceipt> alicePublicReceipt =
alice.execute(ethTransactions.getTransactionReceipt(callHash));
if (alicePublicReceipt.isPresent()) {
assertThat(alicePublicReceipt.get().getBlockHash())
.isEqualTo(
aliceAddReceipt
.get()
.getBlockHash()); // ensure that "add" and "call" are in the same block
assertThat(alicePublicReceipt.get().getStatus())
.isEqualTo(
"0x1"); // this means the PMT for the "call" succeeded which is what we expect because
// it is in the same block as the "add" and there is no way to tell that this
// will happen before the block is mined
}
final PrivateTransactionReceipt aliceReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(callHash));
assertThat(aliceReceipt.getStatus())
.isEqualTo(
"0x0"); // this means the "call" failed which is what we expect because the group was
// locked!
final PrivateTransactionReceipt bobReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(callHash));
assertThat(bobReceipt.getStatus())
.isEqualTo(
"0x0"); // this means the "call" failed which is what we expect because the group was
// locked!
// assert charlie can access private transaction information from before he was added
final PrivateTransactionReceipt expectedAliceLockReceipt =
new PrivateTransactionReceipt(
null,
alice.getAddress().toHexString(),
FLEXIBLE_PRIVACY_PROXY.toHexString(),
"0x",
Collections.emptyList(),
null,
null,
alice.getEnclaveKey(),
null,
privacyGroupId,
"0x1",
null);
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
aliceLockHash, expectedAliceLockReceipt));
final String aliceStoreHash =
charlie.execute(
privateContractTransactions.callOnchainPermissioningSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.valueOf(1337)).encodeFunctionCall(),
charlie.getTransactionSigningKey(),
charlie.getEnclaveKey(),
privacyGroupId));
final PrivateTransactionReceipt expectedStoreReceipt =
new PrivateTransactionReceipt(
null,
charlie.getAddress().toHexString(),
eventEmitter.getContractAddress(),
"0x",
Collections.singletonList(
new Log(
false,
"0x0",
"0x0",
aliceStoreHash,
null,
null,
eventEmitter.getContractAddress(),
EXPECTED_STORE_OUTPUT_DATA,
null,
Collections.singletonList(EXPECTED_STORE_EVENT_TOPIC))),
null,
null,
charlie.getEnclaveKey(),
null,
privacyGroupId,
"0x1",
null);
alice.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
aliceStoreHash, expectedStoreReceipt));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
aliceStoreHash, expectedStoreReceipt));
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
aliceStoreHash, expectedStoreReceipt));
removeFromPrivacyGroup(privacyGroupId, bob, aliceCredentials, charlie);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice, bob);
}
@Test
public void canOnlyCallProxyContractWhenGroupLocked() {
final String privacyGroupId = createFlexiblePrivacyGroup(alice);
checkFlexiblePrivacyGroupExists(privacyGroupId, alice);
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), alice.getAddress().toString())
.verify(eventEmitter);
final Credentials aliceCredentials = Credentials.create(alice.getTransactionSigningKey());
final Supplier<String> callContract =
() -> {
return alice.execute(
privateContractTransactions.callOnchainPermissioningSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.value().encodeFunctionCall(),
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupId));
};
final String lockHash =
alice.execute(
privacyTransactions.privxLockPrivacyGroupAndCheck(
privacyGroupId, alice, aliceCredentials));
final String callWhileLockedHash = callContract.get();
final String unlockHash =
alice.execute(
privacyTransactions.privxUnlockPrivacyGroupAndCheck(
privacyGroupId, alice, aliceCredentials));
final String callAfterUnlockedHash = callContract.get();
alice.execute(minerTransactions.minerStart());
alice.getBesu().verify(ethConditions.miningStatus(true));
final BiConsumer<String, String> assertThatTransactionReceiptIs =
(String hash, String expectedResult) -> {
final PrivateTransactionReceipt receipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(hash));
assertThat(receipt.getStatus()).isEqualTo(expectedResult);
};
// when locking a group succeeds ...
assertThatTransactionReceiptIs.accept(lockHash, "0x1");
// ... calls to contracts fail ...
assertThatTransactionReceiptIs.accept(callWhileLockedHash, "0x0");
// ... but unlock the group works ...
assertThatTransactionReceiptIs.accept(unlockHash, "0x1");
// ... and afterwards we can call contracts again
assertThatTransactionReceiptIs.accept(callAfterUnlockedHash, "0x1");
}
@Test
public void addMembersToTwoGroupsInTheSameBlock() {
final String privacyGroupId1 = createFlexiblePrivacyGroup(alice);
final String privacyGroupId2 = createFlexiblePrivacyGroup(bob);
checkFlexiblePrivacyGroupExists(privacyGroupId1, alice);
checkFlexiblePrivacyGroupExists(privacyGroupId2, bob);
lockPrivacyGroup(privacyGroupId1, alice, Credentials.create(alice.getTransactionSigningKey()));
lockPrivacyGroup(privacyGroupId2, bob, Credentials.create(bob.getTransactionSigningKey()));
final BigInteger pendingTransactionFilterId =
alice.execute(ethTransactions.newPendingTransactionsFilter());
alice.execute(minerTransactions.minerStop());
alice.getBesu().verify(ethConditions.miningStatus(false));
final String aliceAddHash =
addMembersToPrivacyGroup(
privacyGroupId1, alice, Credentials.create(alice.getTransactionSigningKey()), charlie);
final String bobAddHash =
addMembersToPrivacyGroup(
privacyGroupId2, bob, Credentials.create(bob.getTransactionSigningKey()), alice);
alice
.getBesu()
.verify(
ethConditions.expectNewPendingTransactions(
pendingTransactionFilterId, Arrays.asList(aliceAddHash, bobAddHash)));
alice.execute(minerTransactions.minerStart());
checkFlexiblePrivacyGroupExists(privacyGroupId1, alice, charlie);
checkFlexiblePrivacyGroupExists(privacyGroupId2, bob, alice);
}
private <T extends Contract> T deployPrivateContract(
final Class<T> clazz, final String privacyGroupId, final PrivacyNode sender) {
final T contract =
sender.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
clazz, sender.getTransactionSigningKey(), sender.getEnclaveKey(), privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(contract.getContractAddress(), sender.getAddress().toString())
.verify(contract);
return contract;
}
private String addMembersToPrivacyGroup(
final String privacyGroupId,
final PrivacyNode nodeAddingMember,
final Credentials signer,
final PrivacyNode... newMembers) {
return nodeAddingMember.execute(
privacyTransactions.addToPrivacyGroup(
privacyGroupId, nodeAddingMember, signer, newMembers));
}
private String removeFromPrivacyGroup(
final String privacyGroupId,
final PrivacyNode nodeRemovingMember,
final Credentials signer,
final PrivacyNode memberBeingRemoved) {
return nodeRemovingMember.execute(
privacyTransactions.removeFromPrivacyGroup(
privacyGroupId,
nodeRemovingMember.getEnclaveKey(),
signer,
memberBeingRemoved.getEnclaveKey()));
}
/**
* This method will send a transaction to lock the privacy group identified by the specified id.
* This also checks if the lock transaction was successful.
*
* @return the hash of the lock privacy group transaction
*/
private String lockPrivacyGroup(
final String privacyGroupId, final PrivacyNode member, final Credentials signer) {
return member.execute(
privacyTransactions.privxLockPrivacyGroupAndCheck(privacyGroupId, member, signer));
}
}

View File

@@ -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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY_PROXY;
import static org.hyperledger.besu.ethereum.privacy.group.FlexibleGroupManagement.GET_PARTICIPANTS_METHOD_SIGNATURE;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.ExpectValidFlexiblePrivacyGroupCreated;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreateFlexiblePrivacyGroupTransaction;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.tuweni.bytes.Bytes;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.Utils;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.DynamicBytes;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.utils.Base64String;
public class FlexiblePrivacyAcceptanceTestBase extends PrivacyAcceptanceTestBase {
protected String createFlexiblePrivacyGroup(final PrivacyNode... members) {
final List<String> addresses =
Arrays.stream(members).map(PrivacyNode::getEnclaveKey).collect(Collectors.toList());
return createFlexiblePrivacyGroup(members[0].getEnclaveKey(), addresses, members);
}
/**
* Create an flexible privacy group. The privacy group id will be randomly generated.
*
* <p>This method also checks that each node member has successfully processed the transaction and
* has the expected list of member for the group.
*
* @param members the list of members of the privacy group. The first member of the list will be
* the creator of the group.
* @return the id of the privacy group
*/
protected String createFlexiblePrivacyGroup(
final String privateFrom, final List<String> addresses, final PrivacyNode... members) {
final PrivacyNode groupCreator = members[0];
final CreateFlexiblePrivacyGroupTransaction createTx =
privacyTransactions.createFlexiblePrivacyGroup(groupCreator, privateFrom, addresses);
final PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse createResponse =
groupCreator.execute(createTx);
final String privacyGroupId = createResponse.getPrivacyGroupId();
final List<Base64String> membersEnclaveKeys =
Arrays.stream(members)
.map(m -> Base64String.wrap(m.getEnclaveKey()))
.collect(Collectors.toList());
for (final PrivacyNode member : members) {
member.verify(flexiblePrivacyGroupExists(privacyGroupId, membersEnclaveKeys));
}
final String commitmentHash =
callGetParticipantsMethodAndReturnCommitmentHash(privacyGroupId, groupCreator, privateFrom);
final PrivateTransactionReceipt expectedReceipt =
buildExpectedAddMemberTransactionReceipt(privacyGroupId, groupCreator, addresses);
for (final PrivacyNode member : members) {
member.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
commitmentHash, expectedReceipt));
}
return privacyGroupId;
}
protected String callGetParticipantsMethodAndReturnCommitmentHash(
final String privacyGroupId, final PrivacyNode groupCreator, final String privateFrom) {
return groupCreator.execute(
privateContractTransactions.callOnchainPermissioningSmartContract(
FLEXIBLE_PRIVACY_PROXY.toHexString(),
GET_PARTICIPANTS_METHOD_SIGNATURE.toString(),
groupCreator.getTransactionSigningKey(),
privateFrom,
privacyGroupId));
}
protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt(
final String privacyGroupId, final PrivacyNode groupCreator, final List<String> members) {
return buildExpectedAddMemberTransactionReceipt(
privacyGroupId, groupCreator, groupCreator.getEnclaveKey(), members);
}
protected PrivateTransactionReceipt buildExpectedAddMemberTransactionReceipt(
final String privacyGroupId,
final PrivacyNode groupCreator,
final String privateFrom,
final List<String> members) {
final StringBuilder output = new StringBuilder();
// hex prefix
output.append("0x");
final String encodedParameters =
FunctionEncoder.encode(
"",
Arrays.asList(
new DynamicArray<>(
DynamicBytes.class,
Utils.typeMap(
members.stream()
.map(Bytes::fromBase64String)
.map(Bytes::toArrayUnsafe)
.collect(Collectors.toList()),
DynamicBytes.class))));
output.append(encodedParameters);
return new PrivateTransactionReceipt(
null,
groupCreator.getAddress().toHexString(),
FLEXIBLE_PRIVACY_PROXY.toHexString(),
output.toString(),
Collections.emptyList(),
null,
null,
privateFrom,
null,
privacyGroupId,
"0x1",
null);
}
protected ExpectValidFlexiblePrivacyGroupCreated flexiblePrivacyGroupExists(
final String privacyGroupId, final List<Base64String> members) {
return privateTransactionVerifier.flexiblePrivacyGroupExists(privacyGroupId, members);
}
protected String getContractDeploymentCommitmentHash(final Contract contract) {
final Optional<TransactionReceipt> transactionReceipt = contract.getTransactionReceipt();
assertThat(transactionReceipt).isPresent();
final PrivateTransactionReceipt privateTransactionReceipt =
(PrivateTransactionReceipt) transactionReceipt.get();
return privateTransactionReceipt.getcommitmentHash();
}
/**
* This method will check if a privacy group with the specified id and list of members exists.
* Each one of the members node will be queried to ensure that they all have the same privacy
* group in their private state.
*
* @param privacyGroupId the id of the privacy group
* @param members the list of member in the privacy group
*/
protected void checkFlexiblePrivacyGroupExists(
final String privacyGroupId, final PrivacyNode... members) {
final List<Base64String> membersEnclaveKeys =
Arrays.stream(members)
.map(PrivacyNode::getEnclaveKey)
.map(Base64String::wrap)
.collect(Collectors.toList());
for (final PrivacyNode member : members) {
member.verify(flexiblePrivacyGroupExists(privacyGroupId, membersEnclaveKeys));
}
}
}

View File

@@ -1,137 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.BesuNodeConfigurationBuilder;
import org.hyperledger.besu.tests.acceptance.dsl.node.configuration.privacy.PrivacyNodeConfiguration;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccount;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.methods.response.EthBlock.Block;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
@RunWith(Parameterized.class)
public class PluginPrivacySigningAcceptanceTest extends PrivacyAcceptanceTestBase {
private PrivacyNode minerNode;
private final EnclaveEncryptorType enclaveEncryptorType;
public PluginPrivacySigningAcceptanceTest(final EnclaveEncryptorType enclaveEncryptorType) {
this.enclaveEncryptorType = enclaveEncryptorType;
}
@Parameterized.Parameters(name = "{0}")
public static Collection<EnclaveEncryptorType> enclaveEncryptorTypes() {
return Arrays.stream(EnclaveEncryptorType.values())
.filter(encryptorType -> !EnclaveEncryptorType.NOOP.equals(encryptorType))
.collect(Collectors.toList());
}
@Before
public void setup() throws IOException {
final PrivacyAccount BOB = PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType);
minerNode =
privacyBesu.create(
new PrivacyNodeConfiguration(
false,
false,
true,
new BesuNodeConfigurationBuilder()
.name("miner")
.miningEnabled()
.jsonRpcEnabled()
.webSocketEnabled()
.enablePrivateTransactions()
.keyFilePath(BOB.getPrivateKeyPath())
.plugins(Collections.singletonList("testPlugins"))
.extraCLIOptions(
List.of(
"--plugin-privacy-service-encryption-prefix=0xAA",
"--plugin-privacy-service-signing-enabled=true",
"--plugin-privacy-service-signing-key=8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"))
.build(),
new EnclaveKeyConfiguration(
BOB.getEnclaveKeyPaths(),
BOB.getEnclavePrivateKeyPaths(),
BOB.getEnclaveEncryptorType())),
EnclaveType.NOOP,
Optional.empty());
privacyCluster.start(minerNode);
minerNode.verify(priv.syncingStatus(false));
}
@Test
public void canDeployContractSignedByPlugin() throws Exception {
final String contractAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0xf01ec73d91fdeb8bb9388ec74e6a3981da86e021"
: "0xd0152772c54cecfa7684f09f7616dcc825545dff";
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
minerNode.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString())
.verify(eventEmitter);
privateContractVerifier.validContractCodeProvided().verify(eventEmitter);
final BigInteger blockNumberContractDeployed =
eventEmitter.getTransactionReceipt().get().getBlockNumber();
final Block blockContractDeployed =
minerNode.execute(
ethTransactions.block(DefaultBlockParameter.valueOf(blockNumberContractDeployed)));
assertThat(blockContractDeployed.getTransactions().size()).isEqualTo(1);
final String transactionHashContractDeployed =
(String) blockContractDeployed.getTransactions().get(0).get();
final TransactionReceipt pmtReceipt =
minerNode
.execute(ethTransactions.getTransactionReceipt(transactionHashContractDeployed))
.get();
assertThat(pmtReceipt.getStatus()).isEqualTo("0x1");
assertThat(pmtReceipt.getFrom()).isEqualTo("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73");
}
}

View File

@@ -1,295 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.tests.web3j.generated.RevertReason.FUNC_REVERTWITHREVERTREASON;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.besu.tests.web3j.generated.RevertReason;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.bouncycastle.util.encoders.Hex;
import org.junit.Test;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Bool;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.protocol.core.Request;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Contract;
import org.web3j.utils.Restriction;
public class PrivCallAcceptanceTest extends ParameterizedEnclaveTestBase {
private static final int VALUE = 1024;
private final PrivacyNode minerNode;
public PrivCallAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
minerNode =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(minerNode);
minerNode.verify(priv.syncingStatus(false));
}
@Test
public void mustReturnCorrectValue() throws Exception {
final String privacyGroupId =
minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode));
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
restriction,
minerNode.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), minerNode.getAddress().toString())
.verify(eventEmitter);
final Request<Object, EthCall> priv_call =
privCall(privacyGroupId, eventEmitter, false, false, false);
EthCall resp = priv_call.send();
String value = resp.getValue();
assertThat(new BigInteger(value.substring(2), 16)).isEqualByComparingTo(BigInteger.ZERO);
final TransactionReceipt receipt = eventEmitter.store(BigInteger.valueOf(VALUE)).send();
assertThat(receipt).isNotNull();
resp = priv_call.send();
value = resp.getValue();
assertThat(new BigInteger(value.substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(VALUE));
}
@Test
public void mustRevertWithRevertReason() throws Exception {
final String privacyGroupId =
minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode));
final RevertReason revertReasonContract =
minerNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
RevertReason.class,
minerNode.getTransactionSigningKey(),
restriction,
minerNode.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
revertReasonContract.getContractAddress(), minerNode.getAddress().toString())
.verify(revertReasonContract);
final Request<Object, EthCall> priv_call =
privCall(privacyGroupId, revertReasonContract, false, false, true);
EthCall resp = priv_call.send();
assertThat(resp.getRevertReason()).isEqualTo("Execution reverted: RevertReason");
byte[] bytes = Hex.decode(resp.getError().getData().substring(3, 203));
String revertMessage =
new String(Arrays.copyOfRange(bytes, 4, bytes.length), Charset.defaultCharset()).trim();
assertThat(revertMessage).isEqualTo("RevertReason");
}
@Test
public void shouldReturnEmptyResultWithNonExistingPrivacyGroup() throws IOException {
final String privacyGroupId =
minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode));
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
restriction,
minerNode.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), minerNode.getAddress().toString())
.verify(eventEmitter);
final String invalidPrivacyGroup = constructInvalidString(privacyGroupId);
final Request<Object, EthCall> privCall =
privCall(invalidPrivacyGroup, eventEmitter, false, false, false);
final EthCall result = privCall.send();
assertThat(result.getResult()).isEqualTo("0x");
}
@Test
public void mustNotSucceedWithWronglyEncodedFunction() throws IOException {
final String privacyGroupId =
minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode));
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
restriction,
minerNode.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), minerNode.getAddress().toString())
.verify(eventEmitter);
final Request<Object, EthCall> priv_call =
privCall(privacyGroupId, eventEmitter, true, false, false);
final String errorMessage = priv_call.send().getError().getMessage();
assertThat(errorMessage).isEqualTo("Private transaction failed");
}
@Test
public void mustReturn0xUsingInvalidContractAddress() throws IOException {
final String privacyGroupId =
minerNode.execute(createPrivacyGroup("myGroupName", "my group description", minerNode));
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
restriction,
minerNode.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), minerNode.getAddress().toString())
.verify(eventEmitter);
final Request<Object, EthCall> priv_call =
privCall(privacyGroupId, eventEmitter, false, true, false);
final EthCall result = priv_call.send();
assertThat(result).isNotNull();
assertThat(result.getResult()).isEqualTo("0x");
}
@Nonnull
private String constructInvalidString(final String privacyGroupId) {
final char[] chars = privacyGroupId.toCharArray();
if (chars[3] == '0') {
chars[3] = '1';
} else {
chars[3] = '0';
}
return String.valueOf(chars);
}
@Nonnull
private Request<Object, EthCall> privCall(
final String privacyGroupId,
final Contract contract,
final boolean useInvalidParameters,
final boolean useInvalidContractAddress,
final boolean useRevertFunction) {
final Uint256 invalid = new Uint256(BigInteger.TEN);
@SuppressWarnings("rawtypes")
final List<Type> inputParameters =
useInvalidParameters ? Arrays.asList(invalid) : Collections.emptyList();
final Function function =
useRevertFunction
? new Function(
FUNC_REVERTWITHREVERTREASON,
inputParameters,
Arrays.<TypeReference<?>>asList(new TypeReference<Bool>() {}))
: new Function(
"value",
inputParameters,
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
final String encoded = FunctionEncoder.encode(function);
final HttpService httpService =
new HttpService(
"http://"
+ minerNode.getBesu().getHostName()
+ ":"
+ minerNode.getBesu().getJsonRpcPort().get());
final String validContractAddress = contract.getContractAddress();
final String invalidContractAddress = constructInvalidString(validContractAddress);
final String contractAddress =
useInvalidContractAddress ? invalidContractAddress : validContractAddress;
final Transaction transaction =
Transaction.createEthCallTransaction(null, contractAddress, encoded);
return new Request<>(
"priv_call",
Arrays.asList(privacyGroupId, transaction, "latest"),
httpService,
EthCall.class);
}
}

View File

@@ -1,181 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.util.Collection;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.testcontainers.containers.Network;
@RunWith(Parameterized.class)
public class PrivDebugGetStateRootFlexibleGroupAcceptanceTest
extends FlexiblePrivacyAcceptanceTestBase {
private final EnclaveType enclaveType;
public PrivDebugGetStateRootFlexibleGroupAcceptanceTest(final EnclaveType enclaveType) {
this.enclaveType = enclaveType;
}
@Parameters(name = "{0}")
public static Collection<EnclaveType> enclaveTypes() {
return EnclaveType.valuesForTests();
}
private PrivacyNode aliceNode;
private PrivacyNode bobNode;
@Before
public void setUp() throws IOException, URISyntaxException {
final Network containerNetwork = Network.newNetwork();
aliceNode =
privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode(
"alice-node",
PrivacyAccountResolver.ALICE.resolve(EnclaveEncryptorType.NACL),
false,
enclaveType,
Optional.of(containerNetwork));
bobNode =
privacyBesu.createFlexiblePrivacyGroupEnabledNode(
"bob-node",
PrivacyAccountResolver.BOB.resolve(EnclaveEncryptorType.NACL),
false,
enclaveType,
Optional.of(containerNetwork));
privacyCluster.start(aliceNode, bobNode);
aliceNode.verify(priv.syncingStatus(false));
bobNode.verify(priv.syncingStatus(false));
}
@Test
public void nodesInGroupShouldHaveSameStateRoot() {
final String privacyGroupId = createFlexiblePrivacyGroup(aliceNode, bobNode);
final Hash aliceStateRootId =
aliceNode
.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest"))
.getResult();
final Hash bobStateRootId =
bobNode
.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest"))
.getResult();
assertThat(aliceStateRootId).isEqualTo(bobStateRootId);
}
@Test
public void unknownGroupShouldReturnError() {
final PrivacyRequestFactory.DebugGetStateRoot aliceResult =
aliceNode.execute(
privacyTransactions.debugGetStateRoot(
Hash.wrap(Bytes32.random()).toBase64String(), "latest"));
assertThat(aliceResult.getResult()).isNull();
assertThat(aliceResult.hasError()).isTrue();
assertThat(aliceResult.getError()).isNotNull();
assertThat(aliceResult.getError().getMessage()).contains("Error finding privacy group");
}
@Test
public void blockParamShouldBeApplied() {
waitForBlockHeight(aliceNode, 2);
waitForBlockHeight(bobNode, 2);
final String privacyGroupId = createFlexiblePrivacyGroup(aliceNode, bobNode);
waitForBlockHeight(aliceNode, 10);
waitForBlockHeight(bobNode, 10);
final Hash aliceResult1 =
aliceNode.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "1")).getResult();
final Hash bobResultInt1 =
bobNode.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "1")).getResult();
assertThat(aliceResult1).isEqualTo(bobResultInt1);
final Hash aliceResultLatest =
aliceNode
.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest"))
.getResult();
final Hash bobResultLatest =
bobNode
.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest"))
.getResult();
assertThat(aliceResultLatest).isEqualTo(bobResultLatest);
assertThat(aliceResult1).isNotEqualTo(aliceResultLatest);
}
@Test
public void canInteractWithPrivateGenesisPreCompile() throws Exception {
final String privacyGroupId = createFlexiblePrivacyGroup(aliceNode, bobNode);
final EventEmitter eventEmitter =
aliceNode.execute(
privateContractTransactions.loadSmartContractWithPrivacyGroupId(
"0x1000000000000000000000000000000000000001",
EventEmitter.class,
aliceNode.getTransactionSigningKey(),
aliceNode.getEnclaveKey(),
privacyGroupId));
privateTransactionVerifier.existingPrivateTransactionReceipt(
eventEmitter.store(BigInteger.valueOf(42)).send().getTransactionHash());
final String aliceResponse =
aliceNode
.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))
.getValue();
assertThat(new BigInteger(aliceResponse.substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(42));
final String bobResponse =
bobNode
.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()))
.getValue();
assertThat(new BigInteger(bobResponse.substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(42));
}
}

View File

@@ -1,113 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes32;
import org.junit.Test;
import org.testcontainers.containers.Network;
import org.web3j.utils.Restriction;
public class PrivDebugGetStateRootOffchainGroupAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode aliceNode;
private final PrivacyNode bobNode;
public PrivDebugGetStateRootOffchainGroupAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
final Network containerNetwork = Network.newNetwork();
aliceNode =
privacyBesu.createIbft2NodePrivacyEnabled(
"alice-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork),
false,
false,
restriction == UNRESTRICTED,
"0xAA");
bobNode =
privacyBesu.createIbft2NodePrivacyEnabled(
"bob-node",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork),
false,
false,
restriction == UNRESTRICTED,
"0xBB");
privacyCluster.start(aliceNode, bobNode);
aliceNode.verify(priv.syncingStatus(false));
bobNode.verify(priv.syncingStatus(false));
}
@Test
public void nodesInGroupShouldHaveSameStateRoot() {
final String privacyGroupId =
aliceNode.execute(
createPrivacyGroup("testGroup", "A group for everyone", aliceNode, bobNode));
final Hash aliceStateRootId =
aliceNode
.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest"))
.getResult();
final Hash bobStateRootId =
bobNode
.execute(privacyTransactions.debugGetStateRoot(privacyGroupId, "latest"))
.getResult();
assertThat(aliceStateRootId).isEqualTo(bobStateRootId);
}
@Test
public void unknownGroupShouldReturnError() {
if (restriction != UNRESTRICTED) {
final PrivacyRequestFactory.DebugGetStateRoot aliceResult =
aliceNode.execute(
privacyTransactions.debugGetStateRoot(
Hash.wrap(Bytes32.random()).toBase64String(), "latest"));
assertThat(aliceResult.getResult()).isNull();
assertThat(aliceResult.hasError()).isTrue();
assertThat(aliceResult.getError()).isNotNull();
assertThat(aliceResult.getError().getMessage()).contains("Error finding privacy group");
}
}
}

View File

@@ -1,102 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.web3j.utils.Restriction;
public class PrivGetCodeAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode alice;
public PrivGetCodeAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
alice =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(alice);
alice.verify(priv.syncingStatus(false));
}
@Test
public void privGetCodeReturnsDeployedContractBytecode() {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitterContract = deployPrivateContract(privacyGroupId);
final Bytes deployedContractCode =
alice.execute(
privacyTransactions.privGetCode(
privacyGroupId,
Address.fromHexString(eventEmitterContract.getContractAddress()),
"latest"));
assertThat(eventEmitterContract.getContractBinary())
.contains(deployedContractCode.toUnprefixedHexString());
}
private EventEmitter deployPrivateContract(final String privacyGroupId) {
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
alice.getTransactionSigningKey(),
restriction,
alice.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), alice.getAddress().toString())
.verify(eventEmitter);
return eventEmitter;
}
private String createPrivacyGroup() {
final String privacyGroupId =
alice.execute(createPrivacyGroup("myGroupName", "my group description", alice));
assertThat(privacyGroupId).isNotNull();
return privacyGroupId;
}
}

View File

@@ -1,171 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthLog.LogResult;
import org.web3j.utils.Restriction;
@SuppressWarnings("rawtypes")
public class PrivGetLogsAcceptanceTest extends ParameterizedEnclaveTestBase {
/*
This value is derived from the contract event signature
*/
private static final String EVENT_EMITTER_EVENT_TOPIC =
"0xc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5";
private final PrivacyNode node;
public PrivGetLogsAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
node =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(node);
node.verify(priv.syncingStatus(false));
}
@Test
public void getLogsUsingBlockRangeFilter() {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitterContract = deployEventEmitterContract(privacyGroupId);
/*
Updating the contract value 2 times
*/
updateContractValue(privacyGroupId, eventEmitterContract, 1);
updateContractValue(privacyGroupId, eventEmitterContract, 2);
final LogFilterJsonParameter filter =
blockRangeLogFilter("earliest", "latest", eventEmitterContract.getContractAddress());
final List<LogResult> logs =
node.execute(privacyTransactions.privGetLogs(privacyGroupId, filter));
/*
We expect one log entry per tx changing the contract value
*/
assertThat(logs).hasSize(2);
}
@Test
public void getLogsUsingBlockHashFilter() {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitterContract = deployEventEmitterContract(privacyGroupId);
/*
Updating the contract value 1 times
*/
final PrivateTransactionReceipt updateValueReceipt =
updateContractValue(privacyGroupId, eventEmitterContract, 1);
final String blockHash = updateValueReceipt.getBlockHash();
final LogFilterJsonParameter filter =
blockHashLogFilter(blockHash, eventEmitterContract.getContractAddress());
final List<LogResult> logs =
node.execute(privacyTransactions.privGetLogs(privacyGroupId, filter));
assertThat(logs).hasSize(1);
}
private LogFilterJsonParameter blockRangeLogFilter(
final String fromBlock, final String toBlock, final String contractAddress) {
return new LogFilterJsonParameter(
fromBlock,
toBlock,
List.of(contractAddress),
List.of(List.of(EVENT_EMITTER_EVENT_TOPIC)),
null);
}
private LogFilterJsonParameter blockHashLogFilter(
final String blockHash, final String contractAddress) {
return new LogFilterJsonParameter(
null,
null,
List.of(contractAddress),
List.of(List.of(EVENT_EMITTER_EVENT_TOPIC)),
blockHash);
}
private String createPrivacyGroup() {
return node.execute(createPrivacyGroup("myGroupName", "my group description", node));
}
private EventEmitter deployEventEmitterContract(final String privacyGroupId) {
final EventEmitter eventEmitter =
node.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
node.getTransactionSigningKey(),
restriction,
node.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), node.getAddress().toString())
.verify(eventEmitter);
return eventEmitter;
}
private PrivateTransactionReceipt updateContractValue(
final String privacyGroupId, final EventEmitter eventEmitterContract, final int value) {
final String transactionHash =
node.execute(
privateContractTransactions.callSmartContractWithPrivacyGroupId(
eventEmitterContract.getContractAddress(),
eventEmitterContract.store(BigInteger.valueOf(value)).encodeFunctionCall(),
node.getTransactionSigningKey(),
restriction,
node.getEnclaveKey(),
privacyGroupId));
return node.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
}
}

View File

@@ -1,153 +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.acceptance.privacy;
import static org.web3j.utils.Restriction.RESTRICTED;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.testcontainers.containers.Network;
import org.web3j.utils.Restriction;
public class PrivGetPrivateTransactionAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode alice;
private final PrivacyNode bob;
public PrivGetPrivateTransactionAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
final Network containerNetwork = Network.newNetwork();
alice =
privacyBesu.createIbft2NodePrivacyEnabled(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork),
false,
false,
restriction == UNRESTRICTED,
"0xAA");
bob =
privacyBesu.createIbft2NodePrivacyEnabled(
"node2",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.of(containerNetwork),
false,
false,
restriction == UNRESTRICTED,
"0xBB");
privacyCluster.start(alice, bob);
alice.verify(priv.syncingStatus(false));
bob.verify(priv.syncingStatus(false));
}
@Test
public void returnsTransaction() {
final Transaction<String> onlyAlice = createPrivacyGroup("Only Alice", "", alice);
final String privacyGroupId = alice.execute(onlyAlice);
final PrivateTransaction validSignedPrivateTransaction =
getValidSignedPrivateTransaction(alice, privacyGroupId);
final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction);
final Hash transactionHash =
alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString()));
alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString()));
alice
.getBesu()
.verify(priv.getPrivateTransaction(transactionHash, validSignedPrivateTransaction));
}
@Test
public void nonExistentHashReturnsNull() {
alice.getBesu().verify(priv.getPrivateTransactionReturnsNull(Hash.ZERO));
}
@Test
public void returnsNullTransactionNotInNodesPrivacyGroup() {
final Transaction<String> onlyAlice = createPrivacyGroup("Only Alice", "", alice);
final String privacyGroupId = alice.execute(onlyAlice);
final PrivateTransaction validSignedPrivateTransaction =
getValidSignedPrivateTransaction(alice, privacyGroupId);
final BytesValueRLPOutput rlpOutput = getRLPOutput(validSignedPrivateTransaction);
final Hash transactionHash =
alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString()));
alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString()));
bob.getBesu().verify(priv.getPrivateTransactionReturnsNull(transactionHash));
}
private BytesValueRLPOutput getRLPOutput(final PrivateTransaction privateTransaction) {
final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlpo);
return bvrlpo;
}
private PrivateTransaction getValidSignedPrivateTransaction(
final PrivacyNode node, final String privacyGoupId) {
org.hyperledger.besu.plugin.data.Restriction besuRestriction =
restriction == RESTRICTED
? org.hyperledger.besu.plugin.data.Restriction.RESTRICTED
: org.hyperledger.besu.plugin.data.Restriction.UNRESTRICTED;
return PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.of(999999))
.gasLimit(3000000)
.to(null)
.value(Wei.ZERO)
.payload(Bytes.wrap(new byte[] {}))
.sender(node.getAddress())
.privateFrom(Bytes.fromBase64String(node.getEnclaveKey()))
.restriction(besuRestriction)
.privacyGroupId(Bytes.fromBase64String(privacyGoupId))
.signAndBuild(node.getBesu().getPrivacyParameters().getSigningKeyPair().get());
}
}

View File

@@ -1,174 +0,0 @@
/*
* Copyright contributors to Hyperledger Besu.
*
* 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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.SimpleStorage;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Optional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;
import org.web3j.utils.Restriction;
public class PrivTraceTransactionAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode node;
private final PrivacyNode wrongNode;
public PrivTraceTransactionAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
node =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
wrongNode =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(node);
privacyCluster.start(wrongNode);
}
@Test
public void getTransactionTrace() throws JsonProcessingException {
final String privacyGroupId = createPrivacyGroup();
final SimpleStorage simpleStorageContract = deploySimpleStorageContract(privacyGroupId);
Hash transactionHash =
Hash.fromHexString(doTransaction(privacyGroupId, simpleStorageContract, 0));
final String result =
node.execute(privacyTransactions.privTraceTransaction(privacyGroupId, transactionHash));
assertThat(result).isNotNull();
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(result);
JsonNode resultNode = rootNode.get("result");
assertThat(resultNode).isNotNull();
assertThat(resultNode.isArray()).isTrue();
assertThat(resultNode.size()).isGreaterThan(0);
JsonNode trace = resultNode.get(0);
assertThat(trace.get("action").get("callType").asText()).isEqualTo("call");
assertThat(trace.get("action").get("from").asText()).isEqualTo(node.getAddress().toString());
assertThat(trace.get("action").get("input").asText()).startsWith("0x60fe47b1");
assertThat(trace.get("action").get("to").asText())
.isEqualTo(simpleStorageContract.getContractAddress());
assertThat(trace.get("action").get("value").asText()).isEqualTo("0x0");
assertThat(trace.get("blockHash").asText()).isNotEmpty();
assertThat(trace.get("blockNumber").asInt()).isGreaterThan(0);
assertThat(trace.get("transactionHash").asText()).isEqualTo(transactionHash.toString());
assertThat(trace.get("type").asText()).isEqualTo("call");
final String wrongPrivacyGroupId = createWrongPrivacyGroup();
final String resultEmpty =
wrongNode.execute(
privacyTransactions.privTraceTransaction(wrongPrivacyGroupId, transactionHash));
ObjectMapper mapperEmpty = new ObjectMapper();
JsonNode rootNodeEmpty = mapperEmpty.readTree(resultEmpty);
JsonNode resultNodeEmpty = rootNodeEmpty.get("result");
assertThat(resultNodeEmpty).isNotNull();
assertThat(resultNodeEmpty.isArray()).isTrue();
assertThat(resultNodeEmpty.isEmpty()).isTrue();
final String resultWrongHash =
wrongNode.execute(privacyTransactions.privTraceTransaction(privacyGroupId, Hash.EMPTY));
ObjectMapper mapperWrongHash = new ObjectMapper();
JsonNode rootNodeWrongHash = mapperWrongHash.readTree(resultWrongHash);
JsonNode resultNodeWrongHash = rootNodeWrongHash.get("result");
assertThat(resultNodeWrongHash).isNotNull();
assertThat(resultNodeWrongHash.isArray()).isTrue();
assertThat(resultNodeWrongHash.isEmpty()).isTrue();
}
private String createPrivacyGroup() {
return node.execute(createPrivacyGroup("myGroupName", "my group description", node));
}
private String createWrongPrivacyGroup() {
return wrongNode.execute(createPrivacyGroup("myGroupName", "my group description", wrongNode));
}
private SimpleStorage deploySimpleStorageContract(final String privacyGroupId) {
final SimpleStorage simpleStorage =
node.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
SimpleStorage.class,
node.getTransactionSigningKey(),
restriction,
node.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
simpleStorage.getContractAddress(), node.getAddress().toString())
.verify(simpleStorage);
return simpleStorage;
}
private String doTransaction(
final String privacyGroupId, final SimpleStorage simpleStorageContract, final int value) {
return node.execute(
privateContractTransactions.callSmartContractWithPrivacyGroupId(
simpleStorageContract.getContractAddress(),
simpleStorageContract.set(BigInteger.valueOf(value)).encodeFunctionCall(),
node.getTransactionSigningKey(),
restriction,
node.getEnclaveKey(),
privacyGroupId));
}
}

View File

@@ -1,407 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.besu.ethereum.core.PrivacyParameters.DEFAULT_PRIVACY;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import static org.web3j.utils.Restriction.RESTRICTED;
import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import io.vertx.core.Vertx;
import org.apache.tuweni.bytes.Bytes;
import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.testcontainers.containers.Network;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.eea.crypto.PrivateTransactionEncoder;
import org.web3j.protocol.eea.crypto.RawPrivateTransaction;
import org.web3j.utils.Base64String;
import org.web3j.utils.Numeric;
@RunWith(Parameterized.class)
public class PrivacyClusterAcceptanceTest extends PrivacyAcceptanceTestBase {
private final PrivacyNode alice;
private final PrivacyNode bob;
private final PrivacyNode charlie;
private final EnclaveEncryptorType enclaveEncryptorType;
private final Vertx vertx = Vertx.vertx();
private final EnclaveFactory enclaveFactory = new EnclaveFactory(vertx);
@Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}
public PrivacyClusterAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
this.enclaveEncryptorType = enclaveEncryptorType;
final Network containerNetwork = Network.newNetwork();
alice =
privacyBesu.createPrivateTransactionEnabledMinerNode(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
false);
bob =
privacyBesu.createPrivateTransactionEnabledNode(
"node2",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
false);
charlie =
privacyBesu.createPrivateTransactionEnabledNode(
"node3",
PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
false);
privacyCluster.start(alice, bob, charlie);
alice.verify(priv.syncingStatus(false));
bob.verify(priv.syncingStatus(false));
charlie.verify(priv.syncingStatus(false));
}
@After
public void cleanUp() {
vertx.close();
}
@Test
public void onlyAliceAndBobCanExecuteContract() {
// Contract address is generated from sender address and transaction nonce
final String contractAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, alice.getAddress().toString())
.verify(eventEmitter);
final String transactionHash =
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
alice.getTransactionSigningKey(),
RESTRICTED,
alice.getEnclaveKey(),
bob.getEnclaveKey()));
final PrivateTransactionReceipt expectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, expectedReceipt));
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(transactionHash));
// When Alice executes a contract call in the wrong privacy group the transaction should pass
// but it should NOT return any output
final String transactionHash2 =
alice.execute(
privateContractTransactions.callSmartContract(
eventEmitter.getContractAddress(),
eventEmitter.value().encodeFunctionCall(),
alice.getTransactionSigningKey(),
RESTRICTED,
alice.getEnclaveKey(),
charlie.getEnclaveKey()));
final PrivateTransactionReceipt expectedReceipt2 =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash2));
assertThat(expectedReceipt2.getOutput()).isEqualTo("0x");
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash2, expectedReceipt2));
}
@Test
public void aliceCanUsePrivDistributeTransaction() {
// Contract address is generated from sender address and transaction nonce
final String contractAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
final String receiptPrivacyGroupId =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "MjuFB4b9Hz+f8zvkWWasxZWRjHWXU4t7B2nOHo4mekA="
: "DyAOiF/ynpc+JXa2YAGB0bCitSlOMNm+ShmB/7M6C4w=";
final RawPrivateTransaction rawPrivateTransaction =
RawPrivateTransaction.createContractTransaction(
BigInteger.ZERO,
BigInteger.ZERO,
BigInteger.ZERO,
Numeric.prependHexPrefix(EventEmitter.BINARY),
Base64String.wrap(alice.getEnclaveKey()),
Collections.singletonList(Base64String.wrap(bob.getEnclaveKey())),
Base64String.wrap(receiptPrivacyGroupId),
RESTRICTED);
final String signedPrivateTransaction =
Numeric.toHexString(
PrivateTransactionEncoder.signMessage(
rawPrivateTransaction, Credentials.create(alice.getTransactionSigningKey())));
final String transactionKey =
alice.execute(privacyTransactions.privDistributeTransaction(signedPrivateTransaction));
final Enclave aliceEnclave = enclaveFactory.createVertxEnclave(alice.getEnclave().clientUrl());
final ReceiveResponse aliceRR =
aliceEnclave.receive(
Bytes.fromHexString(transactionKey).toBase64String(), alice.getEnclaveKey());
final Enclave bobEnclave = enclaveFactory.createVertxEnclave(bob.getEnclave().clientUrl());
final ReceiveResponse bobRR =
bobEnclave.receive(
Bytes.fromHexString(transactionKey).toBase64String(), bob.getEnclaveKey());
assertThat(bobRR).usingRecursiveComparison().isEqualTo(aliceRR);
final RawTransaction pmt =
RawTransaction.createTransaction(
BigInteger.ZERO,
BigInteger.valueOf(1000),
BigInteger.valueOf(65000),
DEFAULT_PRIVACY.toString(),
transactionKey);
final String signedPmt =
Numeric.toHexString(
TransactionEncoder.signMessage(
pmt, Credentials.create(alice.getTransactionSigningKey())));
final String transactionHash = alice.execute(ethTransactions.sendRawTransaction(signedPmt));
final String receiptPrivateFrom =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAES8nC4qT/KdoAoTSF3qs/47DUsDihyVbWiRjZAiyvqp9eSDkqV1RzlM+58oOwnpFRwvWNZM+AxMVxT+MvxdsqMA=="
: "A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo=";
final ArrayList<String> receiptPrivateFor =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? new ArrayList<>(
Collections.singletonList(
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXIgZqRA25V+3nN+Do6b5r0jiUunub6ubjPhqwHpPxP44uUYh9RKCQNRnsqCJ9PjeTnC8R3ieJk7HWAlycU1bug=="))
: new ArrayList<>(
Collections.singletonList("Ko2bVqD+nNlNYL5EE7y3IdOnviftjiizpjRt+HTuFBs="));
final PrivateTransactionReceipt expectedReceipt =
new PrivateTransactionReceipt(
contractAddress,
"0xfe3b557e8fb62b89f4916b721be55ceb828dbd73",
null,
null, // ignored in the following call, checked separately below
Collections.emptyList(),
"0x023955c49d6265c579561940287449242704d5fd239ff07ea36a3fc7aface61c",
"0x82e521ee16ff13104c5f81e8354ecaaafd5450b710b07f620204032bfe76041a",
receiptPrivateFrom,
receiptPrivateFor,
receiptPrivacyGroupId,
"0x1",
null);
alice.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, expectedReceipt, true));
final PrivateTransactionReceipt alicePrivateTransactionReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
assertThat(EventEmitter.BINARY)
.contains(alicePrivateTransactionReceipt.getOutput().substring(2));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash, expectedReceipt, true));
final PrivateTransactionReceipt bobPrivateTransactionReceipt =
bob.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
assertThat(EventEmitter.BINARY).contains(bobPrivateTransactionReceipt.getOutput().substring(2));
}
@Test
public void aliceCanDeployMultipleTimesInSingleGroup() {
final String firstDeployedAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
final String secondDeployedAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0x5194e214fae257530710d18c868df7a295d9d53b"
: "0x10f807f8a905da5bd319196da7523c6bd768690f";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
}
@Test
public void canInteractWithMultiplePrivacyGroups() {
// alice deploys contract
final String firstDeployedAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0x760359bc605b3848f5199829bde6b382d90fb8eb"
: "0xff206d21150a8da5b83629d8a722f3135ed532b1";
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey(),
charlie.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(firstDeployedAddress, alice.getAddress().toString())
.verify(firstEventEmitter);
// charlie interacts with contract
final String firstTransactionHash =
charlie.execute(
privateContractTransactions.callSmartContract(
firstEventEmitter.getContractAddress(),
firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
charlie.getTransactionSigningKey(),
RESTRICTED,
charlie.getEnclaveKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
// alice gets receipt from charlie's interaction
final PrivateTransactionReceipt firstExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash));
// verify bob and charlie have access to the same receipt
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
// alice deploys second contract
final String secondDeployedAddress =
EnclaveEncryptorType.EC.equals(enclaveEncryptorType)
? "0x3e5d325a03ad3ce5640502219833d30b89ce3ce1"
: "0xebf56429e6500e84442467292183d4d621359838";
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
bob.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(secondDeployedAddress, alice.getAddress().toString())
.verify(secondEventEmitter);
// bob interacts with contract
final String secondTransactionHash =
bob.execute(
privateContractTransactions.callSmartContract(
secondEventEmitter.getContractAddress(),
secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
bob.getTransactionSigningKey(),
RESTRICTED,
bob.getEnclaveKey(),
alice.getEnclaveKey()));
// alice gets receipt from bob's interaction
final PrivateTransactionReceipt secondExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
secondTransactionHash, secondExpectedReceipt));
// charlie cannot see the receipt
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash));
}
}

View File

@@ -1,255 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import static org.web3j.utils.Restriction.RESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.besu.util.LogConfigurator;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.testcontainers.containers.Network;
import org.web3j.protocol.besu.response.privacy.PrivacyGroup;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.utils.Base64String;
@RunWith(Parameterized.class)
public class PrivacyGroupAcceptanceTest extends PrivacyAcceptanceTestBase {
private final PrivacyNode alice;
private final PrivacyNode bob;
private final PrivacyNode charlie;
@Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}
public PrivacyGroupAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
final Network containerNetwork = Network.newNetwork();
alice =
privacyBesu.createPrivateTransactionEnabledMinerNode(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
false);
bob =
privacyBesu.createPrivateTransactionEnabledNode(
"node2",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
false);
charlie =
privacyBesu.createPrivateTransactionEnabledNode(
"node3",
PrivacyAccountResolver.CHARLIE.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
false);
privacyCluster.start(alice, bob, charlie);
alice.verify(priv.syncingStatus(false));
bob.verify(priv.syncingStatus(false));
charlie.verify(priv.syncingStatus(false));
}
@Test
public void nodeCanCreatePrivacyGroup() {
LogConfigurator.setLevel("", "DEBUG");
final String privacyGroupId =
alice.execute(
privacyTransactions.createPrivacyGroup(
"myGroupName", "my group description", alice, bob));
assertThat(privacyGroupId).isNotNull();
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"myGroupName",
"my group description",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void nodeCanCreatePrivacyGroupWithoutName() {
final String privacyGroupId =
alice.execute(
privacyTransactions.createPrivacyGroup(null, "my group description", alice, bob));
assertThat(privacyGroupId).isNotNull();
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"",
"my group description",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void nodeCanCreatePrivacyGroupWithoutDescription() {
final String privacyGroupId =
alice.execute(privacyTransactions.createPrivacyGroup("myGroupName", null, alice, bob));
assertThat(privacyGroupId).isNotNull();
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"myGroupName",
"",
Base64String.wrapList(alice.getEnclaveKey(), bob.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
bob.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void nodeCanCreatePrivacyGroupWithoutOptionalParams() {
final String privacyGroupId =
alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice));
assertThat(privacyGroupId).isNotNull();
final PrivacyGroup expected =
new PrivacyGroup(
privacyGroupId,
PrivacyGroup.Type.PANTHEON,
"",
"",
Base64String.wrapList(alice.getEnclaveKey()));
alice.verify(privateTransactionVerifier.validPrivacyGroupCreated(expected));
}
@Test
public void canInteractWithMultiplePrivacyGroups() {
final String privacyGroupIdABC =
alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob, charlie));
final EventEmitter firstEventEmitter =
alice.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupIdABC));
// charlie interacts with contract
final String firstTransactionHash =
charlie.execute(
privateContractTransactions.callSmartContractWithPrivacyGroupId(
firstEventEmitter.getContractAddress(),
firstEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
charlie.getTransactionSigningKey(),
RESTRICTED,
charlie.getEnclaveKey(),
privacyGroupIdABC));
// alice gets receipt from charlie's interaction
final PrivateTransactionReceipt firstExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(firstTransactionHash));
// verify bob and charlie have access to the same receipt
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
charlie.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
firstTransactionHash, firstExpectedReceipt));
// alice deploys second contract
final String privacyGroupIdAB =
alice.execute(privacyTransactions.createPrivacyGroup(null, null, alice, bob));
final EventEmitter secondEventEmitter =
alice.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupIdAB));
// bob interacts with contract
final String secondTransactionHash =
bob.execute(
privateContractTransactions.callSmartContractWithPrivacyGroupId(
secondEventEmitter.getContractAddress(),
secondEventEmitter.store(BigInteger.ONE).encodeFunctionCall(),
bob.getTransactionSigningKey(),
RESTRICTED,
bob.getEnclaveKey(),
privacyGroupIdAB));
// alice gets receipt from bob's interaction
final PrivateTransactionReceipt secondExpectedReceipt =
alice.execute(privacyTransactions.getPrivateTransactionReceipt(secondTransactionHash));
bob.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
secondTransactionHash, secondExpectedReceipt));
// charlie cannot see the receipt
charlie.verify(privateTransactionVerifier.noPrivateTransactionReceipt(secondTransactionHash));
}
}

View File

@@ -1,165 +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.acceptance.privacy;
import static java.util.Optional.empty;
import static org.web3j.utils.Restriction.RESTRICTED;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.datatypes.Hash;
import org.hyperledger.besu.datatypes.Wei;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.miner.MinerTransactions;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Test;
import org.web3j.utils.Restriction;
public class PrivacyReceiptAcceptanceTest extends ParameterizedEnclaveTestBase {
final MinerTransactions minerTransactions = new MinerTransactions();
private final PrivacyNode alice;
public PrivacyReceiptAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
alice =
privacyBesu.createIbft2NodePrivacyEnabled(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
false,
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED,
"0xAA");
privacyCluster.start(alice);
alice.verify(priv.syncingStatus(false));
}
@Test
public void createPrivateTransactionReceiptSuccessfulTransaction() {
final Transaction<String> onlyAlice = createPrivacyGroup("Only Alice", "", alice);
final String privacyGroupId = alice.execute(onlyAlice);
final PrivateTransaction validTransaction =
createSignedTransaction(alice, privacyGroupId, empty());
final BytesValueRLPOutput rlpOutput = getRLPOutput(validTransaction);
final Hash transactionHash =
alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString()));
// Successful PMT
alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString()));
// Successful private transaction
alice.getBesu().verify(priv.getSuccessfulTransactionReceipt(transactionHash));
}
@Test
public void createPrivateTransactionReceiptFailedTransaction() {
final Transaction<String> onlyAlice = createPrivacyGroup("Only Alice", "", alice);
final String privacyGroupId = alice.execute(onlyAlice);
final PrivateTransaction invalidPayloadTransaction =
createSignedTransaction(
alice, privacyGroupId, Optional.of(Bytes.fromBase64String("invalidPayload")));
final BytesValueRLPOutput rlpOutput = getRLPOutput(invalidPayloadTransaction);
final Hash transactionHash =
alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString()));
// Successful PMT
alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash.toString()));
// Failed private transaction
alice.getBesu().verify(priv.getFailedTransactionReceipt(transactionHash));
}
@Test
public void createPrivateTransactionReceiptInvalidTransaction() {
final Transaction<String> onlyAlice = createPrivacyGroup("Only Alice", "", alice);
final String privacyGroupId = alice.execute(onlyAlice);
final PrivateTransaction validTransaction =
createSignedTransaction(alice, privacyGroupId, empty());
final BytesValueRLPOutput rlpOutput = getRLPOutput(validTransaction);
// Stop mining, to allow adding duplicate nonce block
alice.getBesu().execute(minerTransactions.minerStop());
final Hash transactionHash1 =
alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString()));
final Hash transactionHash2 =
alice.execute(privacyTransactions.sendRawTransaction(rlpOutput.encoded().toHexString()));
// Start mining again
alice.getBesu().execute(minerTransactions.minerStart());
// Successful PMTs
alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash1.toString()));
alice.getBesu().verify(eth.expectSuccessfulTransactionReceipt(transactionHash2.toString()));
// Successful first private transaction
alice.getBesu().verify(priv.getSuccessfulTransactionReceipt(transactionHash1));
// Invalid second private transaction
alice.getBesu().verify(priv.getInvalidTransactionReceipt(transactionHash2));
}
private BytesValueRLPOutput getRLPOutput(final PrivateTransaction privateTransaction) {
final BytesValueRLPOutput bvrlpo = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlpo);
return bvrlpo;
}
private PrivateTransaction createSignedTransaction(
final PrivacyNode node, final String privacyGoupId, final Optional<Bytes> payload) {
org.hyperledger.besu.plugin.data.Restriction besuRestriction =
restriction == RESTRICTED
? org.hyperledger.besu.plugin.data.Restriction.RESTRICTED
: org.hyperledger.besu.plugin.data.Restriction.UNRESTRICTED;
final Bytes defaultPayload = Bytes.wrap(new byte[] {});
return PrivateTransaction.builder()
.nonce(0)
.gasPrice(Wei.of(999999))
.gasLimit(3000000)
.to(null)
.value(Wei.ZERO)
.payload(payload.orElse(defaultPayload))
.sender(node.getAddress())
.privateFrom(Bytes.fromBase64String(node.getEnclaveKey()))
.restriction(besuRestriction)
.privacyGroupId(Bytes.fromBase64String(privacyGoupId))
.signAndBuild(node.getBesu().getPrivacyParameters().getSigningKeyPair().get());
}
}

View File

@@ -1,225 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.CrossContractReader;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.besu.tests.web3j.generated.RemoteSimpleStorage;
import org.hyperledger.besu.tests.web3j.generated.SimpleStorage;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Test;
import org.testcontainers.containers.Network;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.tx.exceptions.ContractCallException;
import org.web3j.utils.Restriction;
public class PrivateContractPublicStateAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode transactionNode;
public PrivateContractPublicStateAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
final Network containerNetwork = Network.newNetwork();
final PrivacyNode minerNode =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-miner-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
restriction == UNRESTRICTED);
transactionNode =
privacyBesu.createPrivateTransactionEnabledNode(
restriction + "-transaction-node",
PrivacyAccountResolver.BOB.resolve(enclaveEncryptorType),
enclaveType,
Optional.of(containerNetwork),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(minerNode, transactionNode);
minerNode.verify(priv.syncingStatus(false));
transactionNode.verify(priv.syncingStatus(false));
}
@Test
public void mustAllowAccessToPublicStateFromPrivateTx() throws Exception {
final EventEmitter publicEventEmitter =
transactionNode.execute(contractTransactions.createSmartContract(EventEmitter.class));
final TransactionReceipt receipt = publicEventEmitter.store(BigInteger.valueOf(12)).send();
assertThat(receipt).isNotNull();
final CrossContractReader reader =
transactionNode.execute(
privateContractTransactions.createSmartContract(
CrossContractReader.class,
transactionNode.getTransactionSigningKey(),
transactionNode.getEnclaveKey()));
final RemoteFunctionCall<BigInteger> remoteFunctionCall =
reader.read(publicEventEmitter.getContractAddress());
final BigInteger result = remoteFunctionCall.send();
assertThat(result).isEqualTo(BigInteger.valueOf(12));
}
@Test
public void mustNotAllowAccessToPrivateStateFromPublicTx() throws Exception {
final EventEmitter privateEventEmitter =
transactionNode.execute(
(privateContractTransactions.createSmartContract(
EventEmitter.class,
transactionNode.getTransactionSigningKey(),
transactionNode.getEnclaveKey())));
final TransactionReceipt receipt = privateEventEmitter.store(BigInteger.valueOf(12)).send();
assertThat(receipt).isNotNull();
final CrossContractReader publicReader =
transactionNode.execute(
contractTransactions.createSmartContract(CrossContractReader.class));
final RemoteFunctionCall<BigInteger> functionCall =
publicReader.read(privateEventEmitter.getContractAddress());
assertThatThrownBy(functionCall::send).isInstanceOf(ContractCallException.class);
}
@Test
public void privateContractMustNotBeAbleToCallPublicContractWhichChangesState() throws Exception {
final CrossContractReader privateReader =
transactionNode.execute(
privateContractTransactions.createSmartContract(
CrossContractReader.class,
transactionNode.getTransactionSigningKey(),
transactionNode.getEnclaveKey()));
final CrossContractReader publicReader =
transactionNode.execute(
contractTransactions.createSmartContract(CrossContractReader.class));
assertThatExceptionOfType(TransactionException.class)
.isThrownBy(() -> privateReader.incrementRemote(publicReader.getContractAddress()).send())
.returns(
"0x", e -> ((PrivateTransactionReceipt) e.getTransactionReceipt().get()).getOutput());
}
@Test
public void privateContractMustNotBeAbleToCallPublicContractWhichInstantiatesContract()
throws Exception {
final CrossContractReader privateReader =
transactionNode.execute(
privateContractTransactions.createSmartContract(
CrossContractReader.class,
transactionNode.getTransactionSigningKey(),
transactionNode.getEnclaveKey()));
final CrossContractReader publicReader =
transactionNode.execute(
contractTransactions.createSmartContract(CrossContractReader.class));
assertThatExceptionOfType(TransactionException.class)
.isThrownBy(() -> privateReader.deployRemote(publicReader.getContractAddress()).send())
.returns(0, e -> e.getTransactionReceipt().get().getLogs().size());
}
@Test
public void privateContractMustNotBeAbleToCallSelfDestructOnPublicContract() throws Exception {
final CrossContractReader privateReader =
transactionNode.execute(
privateContractTransactions.createSmartContract(
CrossContractReader.class,
transactionNode.getTransactionSigningKey(),
transactionNode.getEnclaveKey()));
final CrossContractReader publicReader =
transactionNode
.getBesu()
.execute(contractTransactions.createSmartContract(CrossContractReader.class));
assertThatExceptionOfType(TransactionException.class)
.isThrownBy(() -> privateReader.remoteDestroy(publicReader.getContractAddress()).send())
.withMessage(
"Transaction null has failed with status: 0x0. Gas used: unknown. Revert reason: '0x'.")
.returns(
"0x", e -> ((PrivateTransactionReceipt) e.getTransactionReceipt().get()).getOutput());
}
@Test
public void privateContractCanCallPublicContractThatCallsPublicContract() throws Exception {
final SimpleStorage simpleStorage =
transactionNode
.getBesu()
.execute(contractTransactions.createSmartContract(SimpleStorage.class));
final RemoteSimpleStorage remoteSimpleStorage =
transactionNode
.getBesu()
.execute(contractTransactions.createSmartContract(RemoteSimpleStorage.class));
remoteSimpleStorage.setRemote(simpleStorage.getContractAddress()).send();
final RemoteSimpleStorage reallyRemoteSimpleStorage =
transactionNode
.getBesu()
.execute(contractTransactions.createSmartContract(RemoteSimpleStorage.class));
reallyRemoteSimpleStorage.setRemote(remoteSimpleStorage.getContractAddress()).send();
simpleStorage.set(BigInteger.valueOf(42)).send();
assertThat(simpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42));
assertThat(remoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42));
assertThat(reallyRemoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42));
final RemoteSimpleStorage privateRemoteSimpleStorage =
transactionNode.execute(
privateContractTransactions.createSmartContract(
RemoteSimpleStorage.class,
transactionNode.getTransactionSigningKey(),
transactionNode.getEnclaveKey()));
privateRemoteSimpleStorage.setRemote(simpleStorage.getContractAddress()).send();
assertThat(privateRemoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42));
privateRemoteSimpleStorage.setRemote(reallyRemoteSimpleStorage.getContractAddress()).send();
assertThat(privateRemoteSimpleStorage.get().send()).isEqualTo(BigInteger.valueOf(42));
}
}

View File

@@ -1,100 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.web3j.utils.Restriction.RESTRICTED;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Optional;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.utils.Restriction;
@RunWith(Parameterized.class)
public class PrivateGenesisAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode alice;
public PrivateGenesisAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
alice =
privacyBesu.createIbft2NodePrivacyEnabledWithGenesis(
"node1",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
true,
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED,
"AA");
privacyCluster.start(alice);
alice.verify(priv.syncingStatus(false));
}
@Test
public void canInteractWithPrivateGenesisPreCompile() throws Exception {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitter =
alice.execute(
privateContractTransactions.loadSmartContractWithPrivacyGroupId(
"0x1000000000000000000000000000000000000001",
EventEmitter.class,
alice.getTransactionSigningKey(),
alice.getEnclaveKey(),
privacyGroupId));
eventEmitter.store(BigInteger.valueOf(42)).send();
final EthCall response =
alice.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()));
final String value = response.getValue();
assertThat(new BigInteger(value.substring(2), 16)).isEqualByComparingTo(BigInteger.valueOf(42));
}
private String createPrivacyGroup() {
if (restriction == RESTRICTED) {
return alice.execute(privacyTransactions.createPrivacyGroup("name", "description", alice));
} else if (restriction == UNRESTRICTED) {
return "gsvwYfGPurL7wgXKmgFtCamXarAl9fA5jaSXi8TLpJw=";
} else {
throw new RuntimeException("Do not know how to handle " + restriction);
}
}
}

View File

@@ -1,162 +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.acceptance.privacy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.web3j.utils.Restriction.UNRESTRICTED;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.ParameterizedEnclaveTestBase;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthLog.LogResult;
import org.web3j.utils.Restriction;
@SuppressWarnings("rawtypes")
public class PrivateLogFilterAcceptanceTest extends ParameterizedEnclaveTestBase {
private final PrivacyNode node;
public PrivateLogFilterAcceptanceTest(
final Restriction restriction,
final EnclaveType enclaveType,
final EnclaveEncryptorType enclaveEncryptorType)
throws IOException {
super(restriction, enclaveType, enclaveEncryptorType);
node =
privacyBesu.createPrivateTransactionEnabledMinerNode(
restriction + "-node",
PrivacyAccountResolver.ALICE.resolve(enclaveEncryptorType),
enclaveType,
Optional.empty(),
false,
false,
restriction == UNRESTRICTED);
privacyCluster.start(node);
node.verify(priv.syncingStatus(false));
}
@Test
public void installAndUninstallFilter() {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitterContract = deployEventEmitterContract(privacyGroupId);
final LogFilterJsonParameter filter =
blockRangeLogFilter("earliest", "latest", eventEmitterContract.getContractAddress());
final String filterId = node.execute(privacyTransactions.newFilter(privacyGroupId, filter));
final boolean filterUninstalled =
node.execute(privacyTransactions.uninstallFilter(privacyGroupId, filterId));
assertThat(filterUninstalled).isTrue();
}
@Test
public void getFilterLogs() {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitterContract = deployEventEmitterContract(privacyGroupId);
final LogFilterJsonParameter filter =
blockRangeLogFilter("earliest", "latest", eventEmitterContract.getContractAddress());
final String filterId = node.execute(privacyTransactions.newFilter(privacyGroupId, filter));
updateContractValue(privacyGroupId, eventEmitterContract, 1);
final List<LogResult> logs =
node.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId));
assertThat(logs).hasSize(1);
}
@Test
public void getFilterChanges() {
final String privacyGroupId = createPrivacyGroup();
final EventEmitter eventEmitterContract = deployEventEmitterContract(privacyGroupId);
final LogFilterJsonParameter filter =
blockRangeLogFilter("earliest", "latest", eventEmitterContract.getContractAddress());
final String filterId = node.execute(privacyTransactions.newFilter(privacyGroupId, filter));
updateContractValue(privacyGroupId, eventEmitterContract, 1);
updateContractValue(privacyGroupId, eventEmitterContract, 2);
assertThat(node.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId)))
.hasSize(2);
updateContractValue(privacyGroupId, eventEmitterContract, 3);
assertThat(node.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId)))
.hasSize(1);
}
private LogFilterJsonParameter blockRangeLogFilter(
final String fromBlock, final String toBlock, final String contractAddress) {
return new LogFilterJsonParameter(
fromBlock, toBlock, List.of(contractAddress), Collections.emptyList(), null);
}
private String createPrivacyGroup() {
return node.execute(createPrivacyGroup("myGroupName", "my group description", node));
}
private EventEmitter deployEventEmitterContract(final String privacyGroupId) {
final EventEmitter eventEmitter =
node.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
node.getTransactionSigningKey(),
restriction,
node.getEnclaveKey(),
privacyGroupId));
privateContractVerifier
.validPrivateContractDeployed(
eventEmitter.getContractAddress(), node.getAddress().toString())
.verify(eventEmitter);
return eventEmitter;
}
private PrivateTransactionReceipt updateContractValue(
final String privacyGroupId, final EventEmitter eventEmitterContract, final int value) {
final String transactionHash =
node.execute(
privateContractTransactions.callSmartContractWithPrivacyGroupId(
eventEmitterContract.getContractAddress(),
eventEmitterContract.store(BigInteger.valueOf(value)).encodeFunctionCall(),
node.getTransactionSigningKey(),
restriction,
node.getEnclaveKey(),
privacyGroupId));
return node.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash));
}
}

View File

@@ -1,491 +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.acceptance.privacy.multitenancy;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.EC;
import static org.hyperledger.enclave.testutil.EnclaveEncryptorType.NACL;
import static org.hyperledger.enclave.testutil.EnclaveType.TESSERA;
import org.hyperledger.besu.datatypes.Address;
import org.hyperledger.besu.tests.acceptance.dsl.node.BesuNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.account.PrivacyAccountResolver;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.contract.CallPrivateSmartContractFunction;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.transaction.CreateFlexiblePrivacyGroupTransaction;
import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.perm.PermissioningTransactions;
import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivacyRequestFactory;
import org.hyperledger.besu.tests.acceptance.privacy.FlexiblePrivacyAcceptanceTestBase;
import org.hyperledger.besu.tests.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveEncryptorType;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.utils.Base64String;
import org.web3j.utils.Restriction;
@RunWith(Parameterized.class)
public class FlexibleMultiTenancyAcceptanceTest extends FlexiblePrivacyAcceptanceTestBase {
private final EnclaveType enclaveType;
private final EnclaveEncryptorType enclaveEncryptorType;
public FlexibleMultiTenancyAcceptanceTest(
final EnclaveType enclaveType, final EnclaveEncryptorType enclaveEncryptorType) {
this.enclaveType = enclaveType;
this.enclaveEncryptorType = enclaveEncryptorType;
}
@Parameterized.Parameters(name = "{0} enclave type with {1} encryptor")
public static Collection<Object[]> enclaveParameters() {
return Arrays.asList(
new Object[][] {
{TESSERA, NACL},
{TESSERA, EC}
});
}
private static final PermissioningTransactions permissioningTransactions =
new PermissioningTransactions();
private static final long VALUE_SET = 10L;
private PrivacyNode alice;
private MultiTenancyPrivacyNode aliceMultiTenancyPrivacyNode;
@Before
public void setUp() throws Exception {
alice =
privacyBesu.createFlexiblePrivacyGroupEnabledMinerNode(
"node1",
PrivacyAccountResolver.MULTI_TENANCY.resolve(enclaveEncryptorType),
true,
enclaveType,
Optional.empty());
final BesuNode aliceBesu = alice.getBesu();
privacyCluster.startNodes(alice);
final String alice1Token =
aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user", "pegasys"));
aliceBesu.useAuthenticationTokenInHeaderForJsonRpc(alice1Token);
final String alice2Token =
aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user2", "Password2"));
final String alice3Token =
aliceBesu.execute(permissioningTransactions.createSuccessfulLogin("user3", "Password3"));
privacyCluster.awaitPeerCount(alice);
final String alice1EnclaveKey = alice.getEnclave().getPublicKeys().get(0);
final String alice2EnclaveKey = alice.getEnclave().getPublicKeys().get(1);
final String alice3EnclaveKey = alice.getEnclave().getPublicKeys().get(2);
aliceMultiTenancyPrivacyNode = new MultiTenancyPrivacyNode(alice);
aliceMultiTenancyPrivacyNode
.addTenantWithToken(alice1EnclaveKey, alice1Token)
.addTenantWithToken(alice2EnclaveKey, alice2Token)
.addTenantWithToken(alice3EnclaveKey, alice3Token);
}
@After
public void tearDown() {
privacyCluster.close();
}
@Test
public void createPrivacyGroup() {
createFlexiblePrivacyGroup(alice);
}
@Test
public void createPrivacyGroupWithAllTenants() {
final MultiTenancyPrivacyGroup privacyGroup = new MultiTenancyPrivacyGroup();
privacyGroup.addNodeWithTenants(
aliceMultiTenancyPrivacyNode, aliceMultiTenancyPrivacyNode.getTenants());
createFlexiblePrivacyGroup(privacyGroup);
}
@Test
public void noAccessWhenNotAMember() {
final MultiTenancyPrivacyGroup twoTenantsFromAlice = new MultiTenancyPrivacyGroup();
final List<String> tenants = aliceMultiTenancyPrivacyNode.getTenants();
final String removedTenant = tenants.remove(tenants.size() - 1);
twoTenantsFromAlice.addNodeWithTenants(aliceMultiTenancyPrivacyNode, tenants);
final String privacyGroupId = createFlexiblePrivacyGroup(twoTenantsFromAlice);
final MultiTenancyPrivacyNode multiTenancyPrivacyNode =
twoTenantsFromAlice.getPrivacyNodes().get(0);
final String tenant = tenants.get(0);
final PrivacyNode privacyNode = multiTenancyPrivacyNode.getPrivacyNode();
final BesuNode privacyNodeBesu = privacyNode.getBesu();
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
final EventEmitter eventEmitter =
privacyNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
privacyNode.getTransactionSigningKey(),
tenant,
privacyGroupId));
final String transactionHash = getContractDeploymentCommitmentHash(eventEmitter);
// check that a member can get the transaction receipt
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
privacyNode.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
transactionHash,
(PrivateTransactionReceipt) eventEmitter.getTransactionReceipt().get()));
final String actual =
privacyNode
.execute(
privacyTransactions.privGetCode(
privacyGroupId,
Address.fromHexString(eventEmitter.getContractAddress()),
"latest"))
.toHexString();
assertThat(EventEmitter.BINARY).contains(actual.substring(2));
// check that getting the transaction receipt does not work if you are not a member
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
privacyNode.verify(
privateTransactionVerifier.noPrivateTransactionReceipt(
transactionHash)); // returning null because the RPC is using the enclave key
// check that getting the code of the event emitter does not work when you are not a member
assertThatThrownBy(
() ->
privacyNode.execute(
privacyTransactions.privGetCode(
privacyGroupId,
Address.fromHexString(eventEmitter.getContractAddress()),
"latest")))
.hasMessageContaining("Unauthorized");
final LogFilterJsonParameter filterParameter =
new LogFilterJsonParameter(
"earliest",
"latest",
List.of(eventEmitter.getContractAddress()),
Collections.emptyList(),
null);
// create a valid filter
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
final String filterId =
privacyNode.execute(privacyTransactions.newFilter(privacyGroupId, filterParameter));
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
final CallPrivateSmartContractFunction storeTransaction =
privateContractTransactions.callSmartContractWithPrivacyGroupId(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(),
privacyNode.getTransactionSigningKey(),
Restriction.RESTRICTED,
tenant,
privacyGroupId);
final String storeTransactionHash = privacyNode.execute(storeTransaction);
privacyNode.execute(privacyTransactions.getPrivateTransactionReceipt(storeTransactionHash));
// check that getting the filter changes works for a member
assertThat(privacyNode.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId)))
.hasSize(1);
// check that getting the filter changes does not work if you are not a member
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
assertThatThrownBy(
() ->
privacyNode.execute(privacyTransactions.getFilterChanges(privacyGroupId, filterId)))
.hasMessageContaining("Unauthorized");
// check that getting the filter logs works for a member
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
assertThat(privacyNode.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId)))
.hasSize(3); // create privacy group, deploy event emitter, store on event emitter
// check that getting the filter logs does not work if you are not a member
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
assertThatThrownBy(
() -> privacyNode.execute(privacyTransactions.getFilterLogs(privacyGroupId, filterId)))
.hasMessageContaining("Unauthorized");
// check that getting the logs works for a member
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
assertThat(
privacyNode.execute(privacyTransactions.privGetLogs(privacyGroupId, filterParameter)))
.hasSize(3); // create privacy group, deploy event emitter, store on event emitter
// check that getting the logs does not work if you are not a member
privacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
assertThatThrownBy(
() ->
privacyNode.execute(
privacyTransactions.privGetLogs(privacyGroupId, filterParameter)))
.hasMessageContaining("Unauthorized");
final List<Base64String> base64StringList =
tenants.stream().map(Base64String::wrap).collect(Collectors.toList());
// check that a member can find the on-chain privacy group
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
final List<PrivacyRequestFactory.FlexiblePrivacyGroup> group =
privacyNode.execute(
privacyTransactions.findFlexiblePrivacyGroup(
Base64String.unwrapList(base64StringList)));
assertThat(group.size()).isEqualTo(1);
assertThat(group.get(0).getMembers()).containsAll(base64StringList).hasSize(2);
// check that when you are not a member you cannot find the privacy group
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
assertThatThrownBy(
() ->
privacyNode.execute(
privacyTransactions.findFlexiblePrivacyGroup(
Base64String.unwrapList(base64StringList))))
.hasMessageContaining("Error finding flexible privacy group");
// check that a member can do a priv_call
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
final EthCall readValue =
privacyNode.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall()));
assertThat(new BigInteger(readValue.getValue().substring(2), 16))
.isEqualByComparingTo(BigInteger.valueOf(VALUE_SET));
// check that when you are not a member you cannot do a priv_call
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
assertThatThrownBy(
() ->
privacyNode.execute(
privacyTransactions.privCall(
privacyGroupId, eventEmitter, eventEmitter.value().encodeFunctionCall())))
.hasMessageContaining("Unauthorized");
// check that a member can do a priv_getTransaction
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenant));
final PrivacyRequestFactory.GetPrivateTransactionResponse privTransaction =
privacyNode.execute(privacyTransactions.privGetTransaction(storeTransactionHash));
assertThat(privTransaction.getResult().getPrivacyGroupId()).isEqualTo(privacyGroupId);
// check that when you are not a member you cannot do a priv_getTransaction
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(removedTenant));
assertThatThrownBy(
() -> privacyNode.execute(privacyTransactions.privGetTransaction(storeTransactionHash)))
.hasMessageContaining(
"Expecting actual not to be null"); // TODO: returning null because the RPC is using the
// enclave key
}
@Test
public void removedMemberCannotGetFilterChanges() {
final MultiTenancyPrivacyGroup allTenantsFromAlice = new MultiTenancyPrivacyGroup();
final List<String> tenants = aliceMultiTenancyPrivacyNode.getTenants();
allTenantsFromAlice.addNodeWithTenants(aliceMultiTenancyPrivacyNode, tenants);
final String privacyGroupId = createFlexiblePrivacyGroup(allTenantsFromAlice);
final MultiTenancyPrivacyNode multiTenancyPrivacyNode =
allTenantsFromAlice.getPrivacyNodes().get(0);
final String groupCreatingTenant = allTenantsFromAlice.getGroupCreatingTenant();
final String tenantToBeRemoved =
tenants.stream().filter(t -> !t.equals(groupCreatingTenant)).findFirst().orElseThrow();
final PrivacyNode groupCreatingPrivacyNode = allTenantsFromAlice.getGroupCreatingPrivacyNode();
final BesuNode groupCreatingPrivacyNodeBesu = groupCreatingPrivacyNode.getBesu();
groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(groupCreatingTenant));
final EventEmitter eventEmitter =
groupCreatingPrivacyNode.execute(
privateContractTransactions.createSmartContractWithPrivacyGroupId(
EventEmitter.class,
groupCreatingPrivacyNode.getTransactionSigningKey(),
groupCreatingTenant,
privacyGroupId));
final LogFilterJsonParameter filterParameter =
new LogFilterJsonParameter(
"earliest",
"latest",
List.of(eventEmitter.getContractAddress()),
Collections.emptyList(),
null);
final String filterId =
groupCreatingPrivacyNode.execute(
privacyTransactions.newFilter(privacyGroupId, filterParameter));
final CallPrivateSmartContractFunction storeTransaction =
privateContractTransactions.callSmartContractWithPrivacyGroupId(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(),
groupCreatingPrivacyNode.getTransactionSigningKey(),
Restriction.RESTRICTED,
groupCreatingTenant,
privacyGroupId);
final String storeTransactionHash = groupCreatingPrivacyNode.execute(storeTransaction);
groupCreatingPrivacyNode.execute(
privacyTransactions.getPrivateTransactionReceipt(storeTransactionHash));
// check that getting the filter changes works for a member
groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenantToBeRemoved));
assertThat(
groupCreatingPrivacyNode.execute(
privacyTransactions.getFilterChanges(privacyGroupId, filterId)))
.hasSize(1);
groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(groupCreatingTenant));
final CallPrivateSmartContractFunction store2Transaction =
privateContractTransactions.callSmartContractWithPrivacyGroupId(
eventEmitter.getContractAddress(),
eventEmitter.store(BigInteger.valueOf(VALUE_SET)).encodeFunctionCall(),
groupCreatingPrivacyNode.getTransactionSigningKey(),
Restriction.RESTRICTED,
groupCreatingTenant,
privacyGroupId);
final String store2TransactionHash = groupCreatingPrivacyNode.execute(store2Transaction);
groupCreatingPrivacyNode.execute(
privacyTransactions.getPrivateTransactionReceipt(store2TransactionHash));
// now remove from privacy group
final String removeTransactionHash =
removeFromPrivacyGroup(
privacyGroupId,
groupCreatingPrivacyNode,
groupCreatingTenant,
Credentials.create(groupCreatingPrivacyNode.getTransactionSigningKey()),
tenantToBeRemoved);
groupCreatingPrivacyNode.execute(
privacyTransactions.getPrivateTransactionReceipt(removeTransactionHash));
// check that it does not work anymore when member has been removed
groupCreatingPrivacyNodeBesu.useAuthenticationTokenInHeaderForJsonRpc(
multiTenancyPrivacyNode.getTokenForTenant(tenantToBeRemoved));
assertThatThrownBy(
() ->
groupCreatingPrivacyNode.execute(
privacyTransactions.getFilterChanges(privacyGroupId, filterId)))
.hasMessageContaining("Unauthorized");
}
private String createFlexiblePrivacyGroup(final MultiTenancyPrivacyGroup group) {
final List<MultiTenancyPrivacyNode> multiTenancyPrivacyNodes = group.getPrivacyNodes();
final MultiTenancyPrivacyNode groupCreatorMultiTenancyPrivacyNode =
multiTenancyPrivacyNodes.get(0);
final PrivacyNode groupCreatorNode = group.getGroupCreatingPrivacyNode();
final String groupCreatorTenant = group.getGroupCreatingTenant();
final List<String> members = group.getTenants();
final String token = groupCreatorMultiTenancyPrivacyNode.getTokenForTenant(groupCreatorTenant);
final CreateFlexiblePrivacyGroupTransaction createTx =
privacyTransactions.createFlexiblePrivacyGroup(
groupCreatorNode, groupCreatorTenant, members, token);
final PrivacyRequestFactory.PrivxCreatePrivacyGroupResponse createResponse =
groupCreatorNode.execute(createTx);
final String privacyGroupId = createResponse.getPrivacyGroupId();
final List<Base64String> base64StringList =
members.stream().map(Base64String::wrap).collect(Collectors.toList());
for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) {
final PrivacyNode privacyNode = mtpn.getPrivacyNode();
for (final String tenant : mtpn.getTenants()) {
if (members.contains(tenant)) {
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(mtpn.getTokenForTenant(tenant));
privacyNode.verify(flexiblePrivacyGroupExists(privacyGroupId, base64StringList));
}
}
}
groupCreatorNode.getBesu().useAuthenticationTokenInHeaderForJsonRpc(token);
final String commitmentHash =
callGetParticipantsMethodAndReturnCommitmentHash(
privacyGroupId, groupCreatorNode, groupCreatorTenant);
final PrivateTransactionReceipt expectedReceipt =
buildExpectedAddMemberTransactionReceipt(
privacyGroupId, groupCreatorNode, groupCreatorTenant, members);
for (final MultiTenancyPrivacyNode mtpn : multiTenancyPrivacyNodes) {
final PrivacyNode privacyNode = mtpn.getPrivacyNode();
for (final String tenant : mtpn.getTenants()) {
if (members.contains(tenant)) {
privacyNode
.getBesu()
.useAuthenticationTokenInHeaderForJsonRpc(mtpn.getTokenForTenant(tenant));
privacyNode.verify(
privateTransactionVerifier.validPrivateTransactionReceipt(
commitmentHash, expectedReceipt));
}
}
}
return privacyGroupId;
}
private String removeFromPrivacyGroup(
final String privacyGroupId,
final PrivacyNode node,
final String nodeRemovingMember,
final Credentials signer,
final String memberBeingRemoved) {
return node.execute(
privacyTransactions.removeFromPrivacyGroup(
privacyGroupId, nodeRemovingMember, signer, memberBeingRemoved));
}
}