diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java index 7b299fb7483..58c0fedc01f 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/CallPrivateSmartContractFunction.java @@ -23,6 +23,7 @@ import org.web3j.crypto.Credentials; import org.web3j.protocol.besu.Besu; +import org.web3j.tx.BesuPrivateTransactionManager; import org.web3j.tx.LegacyPrivateTransactionManager; import org.web3j.tx.PrivateTransactionManager; import org.web3j.tx.gas.BesuPrivacyGasProvider; @@ -38,6 +39,7 @@ public class CallPrivateSmartContractFunction implements Transaction { private final long chainId; private final Base64String privateFrom; private final List privateFor; + private final Base64String privacyGroupId; public CallPrivateSmartContractFunction( final String contractAddress, @@ -46,22 +48,65 @@ public CallPrivateSmartContractFunction( final long chainId, final String privateFrom, final List privateFor) { + this( + contractAddress, + encodedFunction, + transactionSigningKey, + chainId, + privateFrom, + privateFor, + null); + } + + public CallPrivateSmartContractFunction( + final String contractAddress, + final String encodedFunction, + final String transactionSigningKey, + final long chainId, + final String privateFrom, + final String privacyGroupId) { + this( + contractAddress, + encodedFunction, + transactionSigningKey, + chainId, + privateFrom, + null, + privacyGroupId); + } + + private CallPrivateSmartContractFunction( + final String contractAddress, + final String encodedFunction, + final String transactionSigningKey, + final long chainId, + final String privateFrom, + final List privateFor, + final String privacyGroupId) { this.contractAddress = contractAddress; this.encodedFunction = encodedFunction; this.senderCredentials = Credentials.create(transactionSigningKey); this.chainId = chainId; this.privateFrom = Base64String.wrap(privateFrom); - this.privateFor = Base64String.wrapList(privateFor); + this.privateFor = privateFor != null ? Base64String.wrapList(privateFor) : null; + this.privacyGroupId = privacyGroupId != null ? Base64String.wrap(privacyGroupId) : null; } @Override public String execute(final NodeRequests node) { final Besu besu = node.privacy().getBesuClient(); - final PrivateTransactionManager privateTransactionManager = - new LegacyPrivateTransactionManager( - besu, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privateFor); + PrivateTransactionManager privateTransactionManager; + if (privacyGroupId != null) { + privateTransactionManager = + new BesuPrivateTransactionManager( + besu, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privacyGroupId); + } else { + privateTransactionManager = + new LegacyPrivateTransactionManager( + besu, GAS_PROVIDER, senderCredentials, chainId, privateFrom, privateFor); + } try { return privateTransactionManager diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java index 426b69e5dd3..f820118d136 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/contract/PrivateContractTransactions.java @@ -80,6 +80,22 @@ public CallPrivateSmartContractFunction callSmartContract( contractAddress, encodedFunction, transactionSigningKey, chainId, privateFrom, privateFor); } + public CallPrivateSmartContractFunction callSmartContract( + final String contractAddress, + final String encodedFunction, + final String transactionSigningKey, + final long chainId, + final String privateFrom, + final String privacyGroupId) { + return new CallPrivateSmartContractFunction( + contractAddress, + encodedFunction, + transactionSigningKey, + chainId, + privateFrom, + privacyGroupId); + } + public LoadPrivateSmartContractTransaction loadSmartContract( final String contractAddress, final Class clazz, diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java index ac5a4ec61a3..52a6531cee9 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/transaction/PrivacyTransactions.java @@ -17,9 +17,11 @@ import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.condition.PrivGetTransactionReceiptTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.EeaSendRawTransactionTransaction; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivCallTransaction; import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivGetCodeTransaction; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.privacy.PrivGetLogsTransaction; import java.util.List; @@ -75,6 +77,11 @@ public PrivGetCodeTransaction privGetCode( return new PrivGetCodeTransaction(privacyGroupId, contractAddress, blockParameter); } + public PrivGetLogsTransaction privGetLogs( + final String privacyGroupId, final LogFilterJsonParameter filterParameter) { + return new PrivGetLogsTransaction(privacyGroupId, filterParameter); + } + public RemoveFromOnChainPrivacyGroupTransaction removeFromPrivacyGroup( final String privacyGroupId, final PrivacyNode remover, final PrivacyNode nodeToRemove) { return new RemoveFromOnChainPrivacyGroupTransaction(privacyGroupId, remover, nodeToRemove); diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/util/LogFilterJsonParameter.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/util/LogFilterJsonParameter.java new file mode 100644 index 00000000000..0ef7c51dc00 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/util/LogFilterJsonParameter.java @@ -0,0 +1,59 @@ +/* + * 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.util; + +import java.util.List; + +public class LogFilterJsonParameter { + + private final String fromBlock; + private final String toBlock; + private final List addresses; + private final List> topics; + private final String blockhash; + + public LogFilterJsonParameter( + final String fromBlock, + final String toBlock, + final List addresses, + final List> topics, + final String blockhash) { + this.fromBlock = fromBlock; + this.toBlock = toBlock; + this.addresses = addresses; + this.topics = topics; + this.blockhash = blockhash; + } + + public String getFromBlock() { + return fromBlock; + } + + public String getToBlock() { + return toBlock; + } + + public List getAddresses() { + return addresses; + } + + public List> getTopics() { + return topics; + } + + public String getBlockhash() { + return blockhash; + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetLogsTransaction.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetLogsTransaction.java new file mode 100644 index 00000000000..5a20e301483 --- /dev/null +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivGetLogsTransaction.java @@ -0,0 +1,51 @@ +/* + * 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.transaction.privacy; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.NodeRequests; +import org.hyperledger.besu.tests.acceptance.dsl.transaction.Transaction; + +import java.io.IOException; + +import org.web3j.protocol.core.methods.response.EthLog; + +public class PrivGetLogsTransaction implements Transaction { + + private final String privacyGroupId; + private final LogFilterJsonParameter filterParameter; + + public PrivGetLogsTransaction( + final String privacyGroupId, final LogFilterJsonParameter filterParameter) { + this.privacyGroupId = privacyGroupId; + this.filterParameter = filterParameter; + } + + @Override + public EthLog execute(final NodeRequests node) { + try { + final EthLog response = node.privacy().privGetLogs(privacyGroupId, filterParameter).send(); + + assertThat(response).as("check response is not null").isNotNull(); + assertThat(response.getResult()).as("check result in response isn't null").isNotNull(); + + return response; + } catch (final IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java index 4fc8a903666..b97f677f338 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/transaction/privacy/PrivacyRequestFactory.java @@ -26,6 +26,7 @@ import org.hyperledger.besu.ethereum.privacy.group.OnChainGroupManagement; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivacyNode; import org.hyperledger.besu.tests.acceptance.dsl.privacy.PrivateTransactionGroupResponse; +import org.hyperledger.besu.tests.acceptance.dsl.privacy.util.LogFilterJsonParameter; import java.io.IOException; import java.math.BigInteger; @@ -39,7 +40,6 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.apache.tuweni.bytes.Bytes; -import org.web3j.abi.datatypes.Type; import org.web3j.crypto.Credentials; import org.web3j.protocol.Web3jService; import org.web3j.protocol.besu.Besu; @@ -47,6 +47,7 @@ import org.web3j.protocol.core.Request; import org.web3j.protocol.core.Response; import org.web3j.protocol.core.methods.response.EthCall; +import org.web3j.protocol.core.methods.response.EthLog; import org.web3j.protocol.eea.crypto.PrivateTransactionEncoder; import org.web3j.protocol.eea.crypto.RawPrivateTransaction; import org.web3j.protocol.exceptions.TransactionException; @@ -387,6 +388,13 @@ public Request privCall( EthCall.class); } + public Request privGetLogs( + final String privacyGroupId, final LogFilterJsonParameter filterParameter) { + + return new Request<>( + "priv_getLogs", Arrays.asList(privacyGroupId, filterParameter), web3jService, EthLog.class); + } + public static class PrivxFindPrivacyGroupResponse extends Response> { public List getGroups() { diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetLogsAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetLogsAcceptanceTest.java new file mode 100644 index 00000000000..dff020b4fb8 --- /dev/null +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/web3j/privacy/PrivGetLogsAcceptanceTest.java @@ -0,0 +1,150 @@ +/* + * Copyright ConsenSys AG. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.tests.web3j.privacy; + +import static org.assertj.core.api.Assertions.assertThat; + +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.util.LogFilterJsonParameter; +import org.hyperledger.besu.tests.web3j.generated.EventEmitter; + +import java.math.BigInteger; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.web3j.protocol.besu.response.privacy.PrivateTransactionReceipt; +import org.web3j.protocol.core.methods.response.EthLog; + +public class PrivGetLogsAcceptanceTest extends PrivacyAcceptanceTestBase { + + /* + This value is derived from the contract event signature + */ + private static final String EVENT_EMITTER_EVENT_TOPIC = + "0xc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5"; + private static final long POW_CHAIN_ID = 2018; + + private PrivacyNode node; + + @Before + public void setUp() throws Exception { + node = + privacyBesu.createPrivateTransactionEnabledMinerNode( + "miner-node", privacyAccountResolver.resolve(0)); + privacyCluster.start(node); + } + + @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 EthLog response = node.execute(privacyTransactions.privGetLogs(privacyGroupId, filter)); + + /* + We expect one log entry per tx changing the contract value + */ + assertThat(response.getLogs()).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 EthLog response = node.execute(privacyTransactions.privGetLogs(privacyGroupId, filter)); + + assertThat(response.getLogs()).hasSize(1); + } + + private LogFilterJsonParameter blockRangeLogFilter( + final String fromBlock, final String toBlock, 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, 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( + privacyTransactions.createPrivacyGroup("myGroupName", "my group description", node)); + } + + private EventEmitter deployEventEmitterContract(final String privacyGroupId) { + final EventEmitter eventEmitter = + node.execute( + privateContractTransactions.createSmartContractWithPrivacyGroupId( + EventEmitter.class, + node.getTransactionSigningKey(), + POW_CHAIN_ID, + 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.callSmartContract( + eventEmitterContract.getContractAddress(), + eventEmitterContract.store(BigInteger.valueOf(value)).encodeFunctionCall(), + node.getTransactionSigningKey(), + POW_CHAIN_ID, + node.getEnclaveKey(), + privacyGroupId)); + + return node.execute(privacyTransactions.getPrivateTransactionReceipt(transactionHash)); + } +}