Privacy plugin pmt factory (#2557)

* Refactor: clarify intent of arg when testing permissioning plugin

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* Refactor: remove duplicate createPrivateMarkerTransaction

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* PrivateMarkerTransactionFactory: add option to delegate to plugin

if defined the plugin will be responsible for creating the pmt

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* Implement locking strategy for eea_sendRawTransaction

- this will lock per address being sent to prevent nonce
too low errors

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* Refactor plugin integration to use a more explicit poco

- the plugin will need to sign the transaction with the data it's given
- it will not need to query anything e.g nonce etc

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* refactor: update naming and tidy up based on comments

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>

* Isolate code for calculating gas limit when using privacy plugin

Signed-off-by: Antony Denyer <git@antonydenyer.co.uk>
Co-authored-by: Vijay Michalik <vijay.michalik@consensys.net>
pull/2584/head
Antony Denyer 3 years ago committed by GitHub
parent bdb9c1ad85
commit 41521b6c03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeConfiguration.java
  2. 2
      acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/configuration/privacy/PrivacyNodeFactory.java
  3. 1
      acceptance-tests/test-plugins/build.gradle
  4. 2
      acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestPermissioningPlugin.java
  5. 22
      acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestPrivacyServicePlugin.java
  6. 87
      acceptance-tests/test-plugins/src/main/java/org/hyperledger/besu/plugins/TestSigningPrivateMarkerTransactionFactory.java
  7. 2
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/plugins/PermissioningPluginTest.java
  8. 99
      acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/privacy/PluginPrivacySigningAcceptanceTest.java
  9. 12
      besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java
  10. 29
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  11. 15
      besu/src/main/java/org/hyperledger/besu/services/PrivacyPluginServiceImpl.java
  12. 14
      besu/src/test/java/org/hyperledger/besu/cli/CommandTestAbstract.java
  13. 2
      ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/fork/frontier/PrivGetPrivateTransactionIntegrationTest.java
  14. 91
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/AbstractEeaSendRawTransaction.java
  15. 34
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransaction.java
  16. 33
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransaction.java
  17. 24
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransaction.java
  18. 36
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/EeaJsonRpcMethods.java
  19. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/GoQuorumJsonRpcPrivacyMethods.java
  20. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivJsonRpcMethods.java
  21. 48
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethods.java
  22. 5
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivxJsonRpcMethods.java
  23. 26
      ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/websocket/methods/PrivateWebSocketMethodsFactory.java
  24. 85
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/BaseEeaSendRawTransaction.java
  25. 10
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/EeaSendRawTransactionTest.java
  26. 22
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/PluginEeaSendRawTransactionTest.java
  27. 26
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOffChainEeaSendRawTransactionTest.java
  28. 38
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/privacy/methods/eea/RestrictedOnChainEeaSendRawTransactionTest.java
  29. 6
      ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/PrivacyApiGroupJsonRpcMethodsTest.java
  30. 8
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Transaction.java
  31. 4
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/core/Wei.java
  32. 20
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PluginPrivacyController.java
  33. 9
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/PrivacyController.java
  34. 21
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/RestrictedDefaultPrivacyController.java
  35. 17
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/RestrictedMultiTenancyPrivacyController.java
  36. 39
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/markertransaction/FixedKeySigningPrivateMarkerTransactionFactory.java
  37. 59
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/markertransaction/PrivateMarkerTransactionFactory.java
  38. 38
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/markertransaction/RandomSigningPrivateMarkerTransactionFactory.java
  39. 49
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/privacy/markertransaction/SigningPrivateMarkerTransactionFactory.java
  40. 10
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/mainnet/precompiles/privacy/PrivacyPluginPrecompiledContractTest.java
  41. 110
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/RestrictedDefaultPrivacyControllerTest.java
  42. 55
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/markertransaction/FixedKeySigningPrivateMarkerTransactionFactoryTest.java
  43. 52
      ethereum/core/src/test/java/org/hyperledger/besu/ethereum/privacy/markertransaction/RandomSigningPrivateMarkerTransactionFactoryTest.java
  44. 2
      plugin-api/build.gradle
  45. 36
      plugin-api/src/main/java/org/hyperledger/besu/plugin/data/UnsignedPrivateMarkerTransaction.java
  46. 6
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/PrivacyPluginService.java
  47. 31
      plugin-api/src/main/java/org/hyperledger/besu/plugin/services/privacy/PrivateMarkerTransactionFactory.java

@ -30,7 +30,7 @@ public class PrivacyNodeConfiguration {
this(false, false, false, besuConfig, keyConfig);
}
PrivacyNodeConfiguration(
public PrivacyNodeConfiguration(
final boolean isOnchainPrivacyGroupEnabled,
final boolean isMultitenancyEnabled,
final boolean isPrivacyPluginEnabled,

@ -41,7 +41,7 @@ public class PrivacyNodeFactory {
this.vertx = vertx;
}
private PrivacyNode create(
public PrivacyNode create(
final PrivacyNodeConfiguration privacyNodeConfig,
final EnclaveType enclaveType,
final Optional<Network> containerNetwork)

@ -3,6 +3,7 @@ dependencies {
implementation project(':plugin-api')
implementation project(':besu')
implementation project(':ethereum:core')
implementation project(':crypto')
implementation project(':ethereum:rlp')
implementation 'com.google.auto.service:auto-service'
implementation 'info.picocli:picocli'

@ -86,6 +86,6 @@ public class TestPermissioningPlugin implements BesuPlugin {
@Override
public void stop() {}
@Option(names = "--plugin-permissioning-enabled")
@Option(names = "--plugin-permissioning-test-enabled")
boolean enabled = false;
}

@ -38,14 +38,17 @@ import picocli.CommandLine.Option;
public class TestPrivacyServicePlugin implements BesuPlugin {
private static final Logger LOG = LogManager.getLogger();
private PrivacyPluginService service;
PrivacyPluginService pluginService;
BesuContext context;
@Override
public void register(final BesuContext context) {
this.context = context;
context.getService(PicoCLIOptions.class).get().addPicoCLIOptions("privacy-service", this);
service = context.getService(PrivacyPluginService.class).get();
pluginService = context.getService(PrivacyPluginService.class).get();
service.setPayloadProvider(
pluginService.setPayloadProvider(
new PrivacyPluginPayloadProvider() {
@Override
public Bytes generateMarkerPayload(
@ -74,11 +77,22 @@ public class TestPrivacyServicePlugin implements BesuPlugin {
}
@Override
public void start() {}
public void start() {
if (signingEnabled) {
pluginService.setPrivateMarkerTransactionFactory(
new TestSigningPrivateMarkerTransactionFactory(signingKey));
}
}
@Override
public void stop() {}
@Option(names = "--plugin-privacy-service-encryption-prefix")
String prefix;
@Option(names = "--plugin-privacy-service-signing-enabled")
boolean signingEnabled = false;
@Option(names = "--plugin-privacy-service-signing-key")
String signingKey;
}

@ -0,0 +1,87 @@
/*
* 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.plugins;
import static org.apache.logging.log4j.LogManager.getLogger;
import static org.hyperledger.besu.ethereum.core.Address.extract;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SECPPrivateKey;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.plugin.data.Address;
import org.hyperledger.besu.plugin.data.PrivateTransaction;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
public class TestSigningPrivateMarkerTransactionFactory implements PrivateMarkerTransactionFactory {
private static final Logger LOG = getLogger();
final KeyPair aliceFixedSigningKey;
final Address sender;
public TestSigningPrivateMarkerTransactionFactory(
final String privateMarkerTransactionSigningKey) {
final SignatureAlgorithm algorithm = SignatureAlgorithmFactory.getInstance();
final SECPPrivateKey privateKey =
algorithm.createPrivateKey(Bytes32.fromHexString(privateMarkerTransactionSigningKey));
aliceFixedSigningKey = algorithm.createKeyPair(privateKey);
sender = extract(Hash.hash(aliceFixedSigningKey.getPublicKey().getEncodedBytes()));
}
@Override
public Bytes create(
final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction,
final PrivateTransaction privateTransaction,
final String privacyUserId) {
final Transaction transaction =
Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(unsignedPrivateMarkerTransaction.getNonce())
.gasPrice(
unsignedPrivateMarkerTransaction.getGasPrice().map(Wei::fromQuantity).orElse(null))
.gasLimit(unsignedPrivateMarkerTransaction.getGasLimit())
.to(
org.hyperledger.besu.ethereum.core.Address.fromPlugin(
unsignedPrivateMarkerTransaction.getTo().get()))
.value(Wei.fromQuantity(unsignedPrivateMarkerTransaction.getValue()))
.payload(unsignedPrivateMarkerTransaction.getPayload())
.signAndBuild(aliceFixedSigningKey);
LOG.info("Signing PMT from " + sender);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
transaction.writeTo(out);
return out.encoded();
}
@Override
public Address getSender(
final PrivateTransaction privateTransaction, final String privacyUserId) {
return sender;
}
}

@ -41,7 +41,7 @@ public class PermissioningPluginTest extends AcceptanceTestBase {
new BesuNodeConfigurationBuilder()
.miningEnabled(false)
.plugins(List.of("testPlugins"))
.extraCLIOptions(List.of("--plugin-permissioning-enabled=true"))
.extraCLIOptions(List.of("--plugin-permissioning-test-enabled=true"))
.jsonRpcEnabled()
.jsonRpcTxPool()
.jsonRpcAdmin();

@ -0,0 +1,99 @@
/*
* 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.acceptance.dsl.privacy.account.PrivacyAccountResolver.BOB;
import static org.web3j.utils.Restriction.UNRESTRICTED;
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.web3j.generated.EventEmitter;
import org.hyperledger.enclave.testutil.EnclaveKeyConfiguration;
import org.hyperledger.enclave.testutil.EnclaveType;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
public class PluginPrivacySigningAcceptanceTest extends PrivacyAcceptanceTestBase {
private PrivacyNode minerNode;
@Before
public void setup() throws IOException {
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())),
EnclaveType.NOOP,
Optional.empty());
privacyCluster.start(minerNode);
}
@Test
public void canDeployContractSignedByPlugin() throws Exception {
final String contractAddress = "0xd0152772c54cecfa7684f09f7616dcc825545dff";
final EventEmitter eventEmitter =
minerNode.execute(
privateContractTransactions.createSmartContract(
EventEmitter.class,
minerNode.getTransactionSigningKey(),
UNRESTRICTED,
minerNode.getEnclaveKey()));
privateContractVerifier
.validPrivateContractDeployed(contractAddress, minerNode.getAddress().toString())
.verify(eventEmitter);
privateContractVerifier.validContractCodeProvided().verify(eventEmitter);
final TransactionReceipt pmtReceipt =
minerNode
.execute(
ethTransactions.getTransactionReceipt(
"0x5586b8321e26cdabd68e0139955b90f97c0fc082519d07e1c0b9db26862ff2ff"))
.get();
assertThat(pmtReceipt.getStatus()).isEqualTo("0x1");
assertThat(pmtReceipt.getFrom()).isEqualTo("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73");
}
}

@ -659,8 +659,7 @@ public class RunnerBuilder {
webSocketsJsonRpcMethods,
privacyParameters,
protocolSchedule,
blockchainQueries,
transactionPool));
blockchainQueries));
createPrivateTransactionObserver(subscriptionManager, privacyParameters);
}
@ -943,8 +942,7 @@ public class RunnerBuilder {
final Map<String, JsonRpcMethod> jsonRpcMethods,
final PrivacyParameters privacyParameters,
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final TransactionPool transactionPool) {
final BlockchainQueries blockchainQueries) {
final WebSocketMethodsFactory websocketMethodsFactory =
new WebSocketMethodsFactory(subscriptionManager, jsonRpcMethods);
@ -952,11 +950,7 @@ public class RunnerBuilder {
if (privacyParameters.isEnabled()) {
final PrivateWebSocketMethodsFactory privateWebSocketMethodsFactory =
new PrivateWebSocketMethodsFactory(
privacyParameters,
subscriptionManager,
protocolSchedule,
blockchainQueries,
transactionPool);
privacyParameters, subscriptionManager, protocolSchedule, blockchainQueries);
privateWebSocketMethodsFactory.methods().forEach(websocketMethodsFactory::addMethods);
}

@ -160,7 +160,7 @@ import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.PermissioningServiceImpl;
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.PrivacyPluginPluginServiceImpl;
import org.hyperledger.besu.services.PrivacyPluginServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin;
@ -273,7 +273,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final StorageServiceImpl storageService;
private final SecurityModuleServiceImpl securityModuleService;
private final PermissioningServiceImpl permissioningService;
private final PrivacyPluginPluginServiceImpl privacyService;
private final PrivacyPluginServiceImpl privacyPluginPluginService;
private final Map<String, String> environment;
private final MetricCategoryRegistryImpl metricCategoryRegistry =
@ -1144,7 +1144,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
new StorageServiceImpl(),
new SecurityModuleServiceImpl(),
new PermissioningServiceImpl(),
new PrivacyPluginPluginServiceImpl());
new PrivacyPluginServiceImpl());
}
@VisibleForTesting
@ -1160,7 +1160,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
final StorageServiceImpl storageService,
final SecurityModuleServiceImpl securityModuleService,
final PermissioningServiceImpl permissioningService,
final PrivacyPluginPluginServiceImpl privacyService) {
final PrivacyPluginServiceImpl privacyPluginPluginService) {
this.logger = logger;
this.rlpBlockImporter = rlpBlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
@ -1172,7 +1172,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
this.storageService = storageService;
this.securityModuleService = securityModuleService;
this.permissioningService = permissioningService;
this.privacyService = privacyService;
this.privacyPluginPluginService = privacyPluginPluginService;
pluginCommonConfiguration = new BesuCommandConfigurationService();
besuPluginContext.addService(BesuConfiguration.class, pluginCommonConfiguration);
}
@ -1312,7 +1312,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuPluginContext.addService(StorageService.class, storageService);
besuPluginContext.addService(MetricCategoryRegistry.class, metricCategoryRegistry);
besuPluginContext.addService(PermissioningService.class, permissioningService);
besuPluginContext.addService(PrivacyPluginService.class, privacyService);
besuPluginContext.addService(PrivacyPluginService.class, privacyPluginPluginService);
// register built-in plugins
new RocksDBPlugin().register(besuPluginContext);
@ -1408,6 +1408,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
besuController.getTransactionPool(),
besuController.getSyncState()));
besuPluginContext.addService(MetricsSystem.class, getMetricsSystem());
besuController.getAdditionalPluginServices().appendPluginServices(besuPluginContext);
besuPluginContext.startPlugins();
}
@ -2137,7 +2138,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
if (unstablePrivacyPluginOptions.isPrivacyPluginEnabled()
&& privacyService.getPayloadProvider() == null) {
&& privacyPluginPluginService.getPayloadProvider() == null) {
throw new ParameterException(
commandLine, "Privacy Plugin must be registered when enabling privacy plugin!");
}
@ -2181,13 +2182,23 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
if (Wei.ZERO.compareTo(minTransactionGasPrice) < 0) {
// if gas is required, cannot use random keys to sign private tx
// ie --privacy-marker-transaction-signing-key-file must be set
if (privateMarkerTransactionSigningKeyPath == null) {
if (privateMarkerTransactionSigningKeyPath == null
&& (privacyPluginPluginService == null
|| privacyPluginPluginService.getPrivateMarkerTransactionFactory() == null)) {
throw new ParameterException(
commandLine,
"Not a free gas network. --privacy-marker-transaction-signing-key-file must be specified and must be a funded account. Private transactions cannot be signed by random (non-funded) accounts in paid gas networks");
}
}
if (privateMarkerTransactionSigningKeyPath != null
&& privacyPluginPluginService != null
&& privacyPluginPluginService.getPrivateMarkerTransactionFactory() != null) {
throw new ParameterException(
commandLine,
"--privacy-marker-transaction-signing-key-file can not be used in conjunction with a plugin that specifies a PrivateMarkerTransactionFactory");
}
if (!Address.PRIVACY.equals(privacyPrecompiledAddress)) {
logger.warn(
"--privacy-precompiled-address option is deprecated. This address is derived, based on --privacy-onchain-groups-enabled.");
@ -2215,7 +2226,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
&& (rpcHttpApis.contains(RpcApis.GOQUORUM) || rpcWsApis.contains(RpcApis.GOQUORUM))) {
logger.warn("Cannot use GOQUORUM API methods when not in GoQuorum mode.");
}
privacyParametersBuilder.setPrivacyService(privacyService);
privacyParametersBuilder.setPrivacyService(privacyPluginPluginService);
final PrivacyParameters privacyParameters = privacyParametersBuilder.build();
if (isPrivacyEnabled) {

@ -17,14 +17,16 @@ package org.hyperledger.besu.services;
import org.hyperledger.besu.plugin.services.PrivacyPluginService;
import org.hyperledger.besu.plugin.services.privacy.PrivacyGroupAuthProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivacyPluginPayloadProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class PrivacyPluginPluginServiceImpl implements PrivacyPluginService {
public class PrivacyPluginServiceImpl implements PrivacyPluginService {
private static final Logger LOG = LogManager.getLogger();
private PrivacyPluginPayloadProvider privacyPluginPayloadProvider;
private PrivateMarkerTransactionFactory privateMarkerTransactionFactory;
private PrivacyGroupAuthProvider privacyGroupAuthProvider =
(privacyGroupId, privacyUserId, blockNumber) -> true;
@ -52,4 +54,15 @@ public class PrivacyPluginPluginServiceImpl implements PrivacyPluginService {
public PrivacyGroupAuthProvider getPrivacyGroupAuthProvider() {
return privacyGroupAuthProvider;
}
@Override
public PrivateMarkerTransactionFactory getPrivateMarkerTransactionFactory() {
return privateMarkerTransactionFactory;
}
@Override
public void setPrivateMarkerTransactionFactory(
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
this.privateMarkerTransactionFactory = privateMarkerTransactionFactory;
}
}

@ -49,15 +49,18 @@ import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.WebSocketConfiguration;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.chain.MutableBlockchain;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
import org.hyperledger.besu.ethereum.eth.manager.EthProtocolManager;
import org.hyperledger.besu.ethereum.eth.sync.BlockBroadcaster;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.permissioning.PermissioningConfiguration;
import org.hyperledger.besu.ethereum.storage.StorageProvider;
import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration;
import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive;
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration;
import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
@ -66,7 +69,7 @@ import org.hyperledger.besu.plugin.services.storage.KeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.PermissioningServiceImpl;
import org.hyperledger.besu.services.PrivacyPluginPluginServiceImpl;
import org.hyperledger.besu.services.PrivacyPluginServiceImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
@ -145,6 +148,9 @@ public abstract class CommandTestAbstract {
@Mock protected PicoCLIOptions cliOptions;
@Mock protected NodeKey nodeKey;
@Mock protected BesuPluginContextImpl mockBesuPluginContext;
@Mock protected MutableBlockchain mockMutableBlockchain;
@Mock protected WorldStateArchive mockWorldStateArchive;
@Mock protected TransactionPool mockTransactionPool;
@SuppressWarnings("PrivateStaticFinalLoggers") // @Mocks are inited by JUnit
@Mock
@ -213,6 +219,10 @@ public abstract class CommandTestAbstract {
when(mockEthProtocolManager.getBlockBroadcaster()).thenReturn(mockBlockBroadcaster);
when(mockProtocolContext.getBlockchain()).thenReturn(mockMutableBlockchain);
lenient().when(mockProtocolContext.getWorldStateArchive()).thenReturn(mockWorldStateArchive);
when(mockController.getTransactionPool()).thenReturn(mockTransactionPool);
when(mockRunnerBuilder.vertx(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.besuController(any())).thenReturn(mockRunnerBuilder);
when(mockRunnerBuilder.discovery(anyBoolean())).thenReturn(mockRunnerBuilder);
@ -372,7 +382,7 @@ public abstract class CommandTestAbstract {
storageService,
securityModuleService,
new PermissioningServiceImpl(),
new PrivacyPluginPluginServiceImpl());
new PrivacyPluginServiceImpl());
this.mockNodeKey = mockNodeKey;
this.keyPair = keyPair;
}

@ -137,7 +137,7 @@ public class PrivGetPrivateTransactionIntegrationTest {
privacyController =
new RestrictedDefaultPrivacyController(
blockchain, privateStateStorage, enclave, null, null, null, null, null, null);
blockchain, privateStateStorage, enclave, null, null, null, null, null);
}
@After

@ -22,20 +22,28 @@ import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRp
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.rlp.RLP;
import org.hyperledger.besu.ethereum.rlp.RLPException;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import com.google.common.util.concurrent.Striped;
import io.vertx.ext.auth.User;
import org.apache.logging.log4j.Logger;
import org.apache.tuweni.bytes.Bytes;
@ -43,9 +51,22 @@ import org.apache.tuweni.bytes.Bytes;
public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod {
private static final Logger LOG = getLogger();
private final TransactionPool transactionPool;
protected AbstractEeaSendRawTransaction(final TransactionPool transactionPool) {
private final PrivacyIdProvider privacyIdProvider;
private final PrivateMarkerTransactionFactory privateMarkerTransactionFactory;
private final NonceProvider publicNonceProvider;
private static final int MAX_CONCURRENT_PMT_SIGNATURE_REQUESTS = 10;
private final Striped<Lock> stripedLock =
Striped.lazyWeakLock(MAX_CONCURRENT_PMT_SIGNATURE_REQUESTS);
protected AbstractEeaSendRawTransaction(
final TransactionPool transactionPool,
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final NonceProvider publicNonceProvider) {
this.transactionPool = transactionPool;
this.privacyIdProvider = privacyIdProvider;
this.privateMarkerTransactionFactory = privateMarkerTransactionFactory;
this.publicNonceProvider = publicNonceProvider;
}
@Override
@ -56,6 +77,7 @@ public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod {
@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
final Object id = requestContext.getRequest().getId();
final Optional<User> user = requestContext.getUser();
final String rawPrivateTransaction = requestContext.getRequiredParameter(0, String.class);
try {
@ -63,22 +85,40 @@ public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod {
PrivateTransaction.readFrom(RLP.input(Bytes.fromHexString(rawPrivateTransaction)));
final ValidationResult<TransactionInvalidReason> validationResult =
validatePrivateTransaction(privateTransaction, requestContext.getUser());
validatePrivateTransaction(privateTransaction, user);
if (!validationResult.isValid()) {
return new JsonRpcErrorResponse(
id, convertTransactionInvalidReason(validationResult.getInvalidReason()));
}
final Transaction privateMarkerTransaction =
createPrivateMarkerTransaction(privateTransaction, requestContext.getUser());
final org.hyperledger.besu.plugin.data.Address sender =
privateMarkerTransactionFactory.getSender(
privateTransaction, privacyIdProvider.getPrivacyUserId(user));
// We lock by sender address so that we can send multiple requests from the same address
// the request will be blocked until the nonce for that sender has been calculated and the
// transaction
// has completed submission to the transaction pool
final Lock lock = stripedLock.get(sender.toShortHexString());
lock.lock();
try {
final Transaction privateMarkerTransaction =
createPrivateMarkerTransaction(privateTransaction, user);
return transactionPool
.addLocalTransaction(privateMarkerTransaction)
.either(
() -> new JsonRpcSuccessResponse(id, privateMarkerTransaction.getHash().toString()),
errorReason -> getJsonRpcErrorResponse(id, errorReason));
LOG.error("CHEESE");
LOG.error(privateMarkerTransaction.getHash());
return transactionPool
.addLocalTransaction(privateMarkerTransaction)
.either(
() -> new JsonRpcSuccessResponse(id, privateMarkerTransaction.getHash().toString()),
errorReason -> getJsonRpcErrorResponse(id, errorReason));
} finally {
lock.unlock();
}
} catch (final JsonRpcErrorResponseException e) {
return new JsonRpcErrorResponse(id, e.getJsonRpcError());
} catch (final IllegalArgumentException | RLPException e) {
@ -102,4 +142,35 @@ public abstract class AbstractEeaSendRawTransaction implements JsonRpcMethod {
protected abstract Transaction createPrivateMarkerTransaction(
final PrivateTransaction privateTransaction, final Optional<User> user);
protected Transaction createPrivateMarkerTransaction(
final Address privacyPrecompileAddress,
final String pmtPayload,
final PrivateTransaction privateTransaction,
final String privacyUserId) {
final Address sender =
Address.fromPlugin(
privateMarkerTransactionFactory.getSender(privateTransaction, privacyUserId));
final long nonce = publicNonceProvider.getNonce(sender);
final Transaction unsignedPrivateMarkerTransaction =
new Transaction.Builder()
.type(TransactionType.FRONTIER)
.nonce(nonce)
.gasPrice(privateTransaction.getGasPrice())
.gasLimit(getGasLimit(privateTransaction, pmtPayload))
.to(privacyPrecompileAddress)
.value(Wei.ZERO)
.payload(Bytes.fromBase64String(pmtPayload))
.build();
final Bytes rlpBytes =
privateMarkerTransactionFactory.create(
unsignedPrivateMarkerTransaction, privateTransaction, privacyUserId);
return Transaction.readFrom(rlpBytes);
}
protected abstract long getGasLimit(PrivateTransaction privateTransaction, String pmtPayload);
}

@ -22,22 +22,31 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Optional;
import io.vertx.ext.auth.User;
import org.apache.tuweni.bytes.Bytes;
public class PluginEeaSendRawTransaction extends AbstractEeaSendRawTransaction {
private final PrivacyController privacyController;
private final PrivacyIdProvider privacyIdProvider;
private final GasCalculator gasCalculator;
public PluginEeaSendRawTransaction(
final TransactionPool transactionPool,
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final NonceProvider publicNonceProvider,
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider) {
super(transactionPool);
final GasCalculator gasCalculator) {
super(transactionPool, privacyIdProvider, privateMarkerTransactionFactory, publicNonceProvider);
this.privacyController = privacyController;
this.privacyIdProvider = privacyIdProvider;
this.gasCalculator = gasCalculator;
}
@Override
@ -59,7 +68,24 @@ public class PluginEeaSendRawTransaction extends AbstractEeaSendRawTransaction {
privacyController.createPrivateMarkerTransactionPayload(
privateTransaction, privacyUserId, Optional.empty());
return privacyController.createPrivateMarkerTransaction(
payloadFromPlugin, privateTransaction, Address.PLUGIN_PRIVACY);
return createPrivateMarkerTransaction(
Address.PLUGIN_PRIVACY, payloadFromPlugin, privateTransaction, privacyUserId);
}
@Override
protected long getGasLimit(final PrivateTransaction privateTransaction, final String pmtPayload) {
// The gas limit can not be determined by the sender because the payload could be changed by the
// plugin
// choose the highest of the two options
return Math.max(
privateTransaction.getGasLimit(),
gasCalculator
.transactionIntrinsicGasCostAndAccessedState(
new Transaction.Builder()
.to(Address.PLUGIN_PRIVACY)
.payload(Bytes.fromBase64String(pmtPayload))
.build())
.getGas()
.toLong());
}
}

@ -26,7 +26,9 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.plugin.data.Restriction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Optional;
@ -40,11 +42,13 @@ public class RestrictedOffChainEeaSendRawTransaction extends AbstractEeaSendRawT
public RestrictedOffChainEeaSendRawTransaction(
final TransactionPool transactionPool,
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider) {
super(transactionPool);
this.privacyController = privacyController;
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final NonceProvider publicNonceProvider,
final PrivacyController privacyController) {
super(transactionPool, privacyIdProvider, privateMarkerTransactionFactory, publicNonceProvider);
this.privacyIdProvider = privacyIdProvider;
this.privacyController = privacyController;
}
@Override
@ -62,24 +66,29 @@ public class RestrictedOffChainEeaSendRawTransaction extends AbstractEeaSendRawT
throw new JsonRpcErrorResponseException(PRIVATE_FROM_DOES_NOT_MATCH_ENCLAVE_PUBLIC_KEY);
}
return privacyController.validatePrivateTransaction(
privateTransaction, privacyIdProvider.getPrivacyUserId(user));
return privacyController.validatePrivateTransaction(privateTransaction, privacyUserId);
}
@Override
protected Transaction createPrivateMarkerTransaction(
final PrivateTransaction privateTransaction, final Optional<User> user) {
final String privacyUserId = privacyIdProvider.getPrivacyUserId(user);
final Optional<PrivacyGroup> maybePrivacyGroup =
findOffchainPrivacyGroup(
privacyController,
privateTransaction.getPrivacyGroupId(),
privacyIdProvider.getPrivacyUserId(user));
privacyController, privateTransaction.getPrivacyGroupId(), privacyUserId);
final String privateTransactionLookupId =
privacyController.createPrivateMarkerTransactionPayload(
privateTransaction, privacyIdProvider.getPrivacyUserId(user), maybePrivacyGroup);
return privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, privateTransaction, Address.DEFAULT_PRIVACY);
privateTransaction, privacyUserId, maybePrivacyGroup);
return createPrivateMarkerTransaction(
Address.DEFAULT_PRIVACY, privateTransactionLookupId, privateTransaction, privacyUserId);
}
@Override
protected long getGasLimit(final PrivateTransaction privateTransaction, final String pmtPayload) {
return privateTransaction.getGasLimit();
}
}

@ -26,7 +26,9 @@ import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.plugin.data.Restriction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Optional;
@ -41,9 +43,11 @@ public class RestrictedOnChainEeaSendRawTransaction extends AbstractEeaSendRawTr
public RestrictedOnChainEeaSendRawTransaction(
final TransactionPool transactionPool,
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider) {
super(transactionPool);
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final NonceProvider publicNonceProvider,
final PrivacyController privacyController) {
super(transactionPool, privacyIdProvider, privateMarkerTransactionFactory, publicNonceProvider);
this.privacyController = privacyController;
this.privacyIdProvider = privacyIdProvider;
}
@ -88,10 +92,16 @@ public class RestrictedOnChainEeaSendRawTransaction extends AbstractEeaSendRawTr
privacyController.buildAndSendAddPayload(
privateTransaction, Bytes32.wrap(privacyGroupId), privacyUserId);
return privacyController.createPrivateMarkerTransaction(
buildCompoundLookupId(privateTransactionLookupId, addPayloadPrivateTransactionLookupId),
privateTransaction,
Address.ONCHAIN_PRIVACY);
final String pmtPayload =
buildCompoundLookupId(privateTransactionLookupId, addPayloadPrivateTransactionLookupId);
return createPrivateMarkerTransaction(
Address.ONCHAIN_PRIVACY, pmtPayload, privateTransaction, privacyUserId);
}
@Override
protected long getGasLimit(final PrivateTransaction privateTransaction, final String pmtPayload) {
return privateTransaction.getGasLimit();
}
private String buildCompoundLookupId(

@ -14,6 +14,7 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.LatestNonceProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApi;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcApis;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
@ -27,37 +28,62 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Map;
public class EeaJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
private final TransactionPool transactionPool;
private final PrivacyParameters privacyParameters;
private final NonceProvider nonceProvider;
public EeaJsonRpcMethods(
final BlockchainQueries blockchainQueries,
final ProtocolSchedule protocolSchedule,
final TransactionPool transactionPool,
final PrivacyParameters privacyParameters) {
super(blockchainQueries, protocolSchedule, transactionPool, privacyParameters);
this.transactionPool = transactionPool;
this.privacyParameters = privacyParameters;
this.nonceProvider =
new LatestNonceProvider(blockchainQueries, transactionPool.getPendingTransactions());
}
@Override
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController, final PrivacyIdProvider privacyIdProvider) {
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
if (getPrivacyParameters().isPrivacyPluginEnabled()) {
if (privacyParameters.isPrivacyPluginEnabled()) {
return mapOf(
new PluginEeaSendRawTransaction(
getTransactionPool(), privacyController, privacyIdProvider),
transactionPool,
privacyIdProvider,
privateMarkerTransactionFactory,
nonceProvider,
privacyController,
getGasCalculator()),
new PrivGetEeaTransactionCount(privacyController, privacyIdProvider));
} else if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) {
return mapOf(
new RestrictedOnChainEeaSendRawTransaction(
getTransactionPool(), privacyController, privacyIdProvider),
transactionPool,
privacyIdProvider,
privateMarkerTransactionFactory,
nonceProvider,
privacyController),
new PrivGetEeaTransactionCount(privacyController, privacyIdProvider));
} else { // off chain privacy
return mapOf(
new RestrictedOffChainEeaSendRawTransaction(
getTransactionPool(), privacyController, privacyIdProvider),
transactionPool,
privacyIdProvider,
privateMarkerTransactionFactory,
nonceProvider,
privacyController),
new PrivGetEeaTransactionCount(privacyController, privacyIdProvider));
}
}

@ -28,6 +28,7 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Collections;
import java.util.Map;
@ -48,7 +49,9 @@ public class GoQuorumJsonRpcPrivacyMethods extends PrivacyApiGroupJsonRpcMethods
@Override
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController, final PrivacyIdProvider enclavePublicKeyProvider) {
final PrivacyController privacyController,
final PrivacyIdProvider enclavePublicKeyProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
if (goQuorumParameters.isPresent()) {
final GoQuorumEnclave enclave = goQuorumParameters.get().enclave();

@ -40,6 +40,7 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Map;
@ -64,7 +65,9 @@ public class PrivJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
@Override
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController, final PrivacyIdProvider privacyIdProvider) {
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
final Map<String, JsonRpcMethod> RPC_METHODS =
mapOf(

@ -14,7 +14,6 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.LatestNonceProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.DisabledPrivacyRpcMethod;
@ -22,9 +21,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.MultiT
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.PrivacyQueries;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.PendingTransactions;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.ChainHeadPrivateNonceProvider;
@ -35,8 +32,9 @@ import org.hyperledger.besu.ethereum.privacy.PrivateTransactionSimulator;
import org.hyperledger.besu.ethereum.privacy.RestrictedDefaultPrivacyController;
import org.hyperledger.besu.ethereum.privacy.RestrictedMultiTenancyPrivacyController;
import org.hyperledger.besu.ethereum.privacy.markertransaction.FixedKeySigningPrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.privacy.markertransaction.PrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.privacy.markertransaction.RandomSigningPrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.math.BigInteger;
import java.util.Map;
@ -88,14 +86,20 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
return privacyParameters;
}
public GasCalculator getGasCalculator() {
return protocolSchedule
.getByBlockNumber(blockchainQueries.headBlockNumber())
.getGasCalculator();
}
@Override
protected Map<String, JsonRpcMethod> create() {
final PrivateMarkerTransactionFactory markerTransactionFactory =
createPrivateMarkerTransactionFactory(
privacyParameters, blockchainQueries, transactionPool.getPendingTransactions());
createPrivateMarkerTransactionFactory();
final PrivacyIdProvider enclavePublicProvider = PrivacyIdProvider.build(privacyParameters);
final PrivacyController privacyController = createPrivacyController(markerTransactionFactory);
return create(privacyController, enclavePublicProvider).entrySet().stream()
final PrivacyController privacyController = createPrivacyController();
return create(privacyController, enclavePublicProvider, markerTransactionFactory).entrySet()
.stream()
.collect(
Collectors.toMap(
Map.Entry::getKey,
@ -103,26 +107,22 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
}
protected abstract Map<String, JsonRpcMethod> create(
final PrivacyController privacyController, final PrivacyIdProvider privacyIdProvider);
private PrivateMarkerTransactionFactory createPrivateMarkerTransactionFactory(
final PrivacyParameters privacyParameters,
final BlockchainQueries blockchainQueries,
final PendingTransactions pendingTransactions) {
final Address privateContractAddress = privacyParameters.getPrivacyAddress();
if (privacyParameters.getSigningKeyPair().isPresent()) {
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider,
PrivateMarkerTransactionFactory markerTransactionFactory);
private PrivateMarkerTransactionFactory createPrivateMarkerTransactionFactory() {
if (privacyParameters.getPrivacyService() != null
&& privacyParameters.getPrivacyService().getPrivateMarkerTransactionFactory() != null) {
return privacyParameters.getPrivacyService().getPrivateMarkerTransactionFactory();
} else if (privacyParameters.getSigningKeyPair().isPresent()) {
return new FixedKeySigningPrivateMarkerTransactionFactory(
privateContractAddress,
new LatestNonceProvider(blockchainQueries, pendingTransactions),
privacyParameters.getSigningKeyPair().get());
}
return new RandomSigningPrivateMarkerTransactionFactory(privateContractAddress);
return new RandomSigningPrivateMarkerTransactionFactory();
}
private PrivacyController createPrivacyController(
final PrivateMarkerTransactionFactory markerTransactionFactory) {
private PrivacyController createPrivacyController() {
final Optional<BigInteger> chainId = protocolSchedule.getChainId();
if (privacyParameters.isPrivacyPluginEnabled()) {
@ -130,7 +130,6 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
getBlockchainQueries().getBlockchain(),
privacyParameters,
chainId,
markerTransactionFactory,
createPrivateTransactionSimulator(),
privateNonceProvider,
privacyParameters.getPrivateWorldStateReader());
@ -140,7 +139,6 @@ public abstract class PrivacyApiGroupJsonRpcMethods extends ApiGroupJsonRpcMetho
getBlockchainQueries().getBlockchain(),
privacyParameters,
chainId,
markerTransactionFactory,
createPrivateTransactionSimulator(),
privateNonceProvider,
privacyParameters.getPrivateWorldStateReader());

@ -24,6 +24,7 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Map;
@ -44,7 +45,9 @@ public class PrivxJsonRpcMethods extends PrivacyApiGroupJsonRpcMethods {
@Override
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController, final PrivacyIdProvider privacyIdProvider) {
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
if (getPrivacyParameters().isOnchainPrivacyGroupsEnabled()) {
return mapOf(new PrivxFindOnChainPrivacyGroup(privacyController, privacyIdProvider));
} else {

@ -14,15 +14,12 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.websocket.methods;
import org.hyperledger.besu.ethereum.api.jsonrpc.LatestNonceProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.PrivacyIdProvider;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.SubscriptionManager;
import org.hyperledger.besu.ethereum.api.jsonrpc.websocket.subscription.request.SubscriptionRequestMapper;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.ChainHeadPrivateNonceProvider;
import org.hyperledger.besu.ethereum.privacy.PluginPrivacyController;
@ -31,9 +28,6 @@ import org.hyperledger.besu.ethereum.privacy.PrivateNonceProvider;
import org.hyperledger.besu.ethereum.privacy.PrivateTransactionSimulator;
import org.hyperledger.besu.ethereum.privacy.RestrictedDefaultPrivacyController;
import org.hyperledger.besu.ethereum.privacy.RestrictedMultiTenancyPrivacyController;
import org.hyperledger.besu.ethereum.privacy.markertransaction.FixedKeySigningPrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.privacy.markertransaction.PrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.privacy.markertransaction.RandomSigningPrivateMarkerTransactionFactory;
import java.math.BigInteger;
import java.util.Collection;
@ -46,19 +40,16 @@ public class PrivateWebSocketMethodsFactory {
private final SubscriptionManager subscriptionManager;
private final ProtocolSchedule protocolSchedule;
private final BlockchainQueries blockchainQueries;
private final TransactionPool transactionPool;
public PrivateWebSocketMethodsFactory(
final PrivacyParameters privacyParameters,
final SubscriptionManager subscriptionManager,
final ProtocolSchedule protocolSchedule,
final BlockchainQueries blockchainQueries,
final TransactionPool transactionPool) {
final BlockchainQueries blockchainQueries) {
this.privacyParameters = privacyParameters;
this.subscriptionManager = subscriptionManager;
this.protocolSchedule = protocolSchedule;
this.blockchainQueries = blockchainQueries;
this.transactionPool = transactionPool;
}
public Collection<JsonRpcMethod> methods() {
@ -73,19 +64,6 @@ public class PrivateWebSocketMethodsFactory {
subscriptionManager, subscriptionRequestMapper, privacyController, privacyIdProvider));
}
private PrivateMarkerTransactionFactory createPrivateMarkerTransactionFactory() {
final Address privateContractAddress = privacyParameters.getPrivacyAddress();
if (privacyParameters.getSigningKeyPair().isPresent()) {
return new FixedKeySigningPrivateMarkerTransactionFactory(
privateContractAddress,
new LatestNonceProvider(blockchainQueries, transactionPool.getPendingTransactions()),
privacyParameters.getSigningKeyPair().get());
}
return new RandomSigningPrivateMarkerTransactionFactory(privateContractAddress);
}
private PrivacyController createPrivacyController() {
final Optional<BigInteger> chainId = protocolSchedule.getChainId();
if (privacyParameters.isPrivacyPluginEnabled()) {
@ -93,7 +71,6 @@ public class PrivateWebSocketMethodsFactory {
blockchainQueries.getBlockchain(),
privacyParameters,
chainId,
createPrivateMarkerTransactionFactory(),
createPrivateTransactionSimulator(),
createPrivateNonceProvider(),
privacyParameters.getPrivateWorldStateReader());
@ -103,7 +80,6 @@ public class PrivateWebSocketMethodsFactory {
blockchainQueries.getBlockchain(),
privacyParameters,
chainId,
createPrivateMarkerTransactionFactory(),
createPrivateTransactionSimulator(),
createPrivateNonceProvider(),
privacyParameters.getPrivateWorldStateReader());

@ -23,10 +23,14 @@ import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.BerlinGasCalculator;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.privacy.markertransaction.FixedKeySigningPrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.ethereum.vm.GasCalculator;
import org.hyperledger.besu.plugin.data.Restriction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.math.BigInteger;
import java.util.List;
@ -39,26 +43,80 @@ import org.mockito.Mock;
public class BaseEeaSendRawTransaction {
final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM =
final String MOCK_ORION_KEY = "bW9ja2tleQ==";
final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM_SUPPLIER =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
final Transaction PUBLIC_TRANSACTION =
final KeyPair keyPair =
SIGNATURE_ALGORITHM_SUPPLIER
.get()
.createKeyPair(
SIGNATURE_ALGORITHM_SUPPLIER
.get()
.createPrivateKey(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16)));
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory =
new FixedKeySigningPrivateMarkerTransactionFactory(keyPair);
final GasCalculator gasCalculator = new BerlinGasCalculator();
final Transaction PUBLIC_ONCHAIN_TRANSACTION =
new Transaction(
0L,
Wei.of(1),
21000L,
Optional.of(
Address.wrap(Bytes.fromHexString("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"))),
Optional.of(Address.ONCHAIN_PRIVACY),
Wei.ZERO,
SIGNATURE_ALGORITHM_SUPPLIER
.get()
.createSignature(
new BigInteger(
"104310573331543561412661001400556426894275857431274618344686100036716947434951"),
new BigInteger(
"33080506591748900530090726168809539464160321639149722208454899701475015405641"),
Byte.parseByte("1")),
Bytes.fromBase64String(MOCK_ORION_KEY),
Address.wrap(Bytes.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
Optional.empty());
final Transaction PUBLIC_PLUGIN_TRANSACTION =
new Transaction(
0L,
Wei.of(1),
21112L,
Optional.of(Address.PLUGIN_PRIVACY),
Wei.ZERO,
SIGNATURE_ALGORITHM
SIGNATURE_ALGORITHM_SUPPLIER
.get()
.createSignature(
new BigInteger(
"32886959230931919120748662916110619501838190146643992583529828535682419954515"),
"111331907905663242841915789134040957461022579868467291368609335839524284474080"),
new BigInteger(
"14473701025599600909210599917245952381483216609124029382871721729679842002948"),
"16338460226177675602590882211136457396059831699034102939076916361204709826919"),
Byte.parseByte("0")),
Bytes.fromHexString("0x"),
Bytes.fromBase64String(MOCK_ORION_KEY),
Address.wrap(Bytes.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
Optional.empty());
final Transaction PUBLIC_OFF_CHAIN_TRANSACTION =
new Transaction(
0L,
Wei.of(1),
21000L,
Optional.of(Address.DEFAULT_PRIVACY),
Wei.ZERO,
SIGNATURE_ALGORITHM_SUPPLIER
.get()
.createSignature(
new BigInteger(
"45331864585825234947874751069766983839005678711670143534492294352090223768785"),
new BigInteger(
"32813839561238589140263096892921088101761344639911577803805398248765156383629"),
Byte.parseByte("1")),
Bytes.fromBase64String(MOCK_ORION_KEY),
Address.wrap(Bytes.fromHexString("0x8411b12666f68ef74cace3615c9d5a377729d03f")),
Optional.empty());
@ -127,17 +185,6 @@ public class BaseEeaSendRawTransaction {
}
private String rlpEncodeTransaction(final PrivateTransaction.Builder privateTransactionBuilder) {
final KeyPair keyPair =
SIGNATURE_ALGORITHM
.get()
.createKeyPair(
SIGNATURE_ALGORITHM
.get()
.createPrivateKey(
new BigInteger(
"8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
16)));
final PrivateTransaction privateTransaction = privateTransactionBuilder.signAndBuild(keyPair);
final BytesValueRLPOutput bvrlp = new BytesValueRLPOutput();
privateTransaction.writeTo(bvrlp);

@ -55,15 +55,19 @@ public class EeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo=";
final PrivacyIdProvider privacyIdProvider = (user) -> ENCLAVE_PUBLIC_KEY;
final String MOCK_ORION_KEY = "";
RestrictedOffChainEeaSendRawTransaction method;
@Before
public void before() {
method =
new RestrictedOffChainEeaSendRawTransaction(
transactionPool, privacyController, privacyIdProvider);
transactionPool,
privacyIdProvider,
privateMarkerTransactionFactory,
address -> 0,
privacyController);
}
@Test
@ -217,8 +221,6 @@ public class EeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
.thenReturn(MOCK_ORION_KEY);
when(privacyController.validatePrivateTransaction(any(), anyString()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivateMarkerTransaction(any(), any(), any()))
.thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any()))
.thenReturn(ValidationResult.invalid(transactionInvalidReason));

@ -16,13 +16,11 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.junit.Before;
@ -37,31 +35,35 @@ public class PluginEeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
@Before
public void before() {
method = new PluginEeaSendRawTransaction(transactionPool, privacyController, (user) -> "");
method =
new PluginEeaSendRawTransaction(
transactionPool,
user -> "",
privateMarkerTransactionFactory,
address -> 0,
privacyController,
gasCalculator);
}
@Test
public void validUnrestrictedTransactionIsSentToTransactionPool() {
when(privacyController.createPrivateMarkerTransactionPayload(any(), any(), any()))
.thenReturn("");
.thenReturn(MOCK_ORION_KEY);
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivateMarkerTransaction(any(), any(), any()))
.thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any())).thenReturn(ValidationResult.valid());
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
validPrivacyGroupTransactionRequest.getRequest().getId(),
"0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15");
"0x8d84a2d2158c9be3c18a8e6d064fd085e440d117294ba2e7f909e36bf192ffbd");
final JsonRpcResponse actualResponse =
method.response(validUnrestrictedPrivacyGroupTransactionRequest);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION);
verify(privacyController)
.createPrivateMarkerTransaction(any(), any(), eq(Address.PLUGIN_PRIVACY));
verify(transactionPool).addLocalTransaction(PUBLIC_PLUGIN_TRANSACTION);
}
}

@ -17,7 +17,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -27,7 +26,6 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import java.util.Optional;
@ -40,7 +38,6 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class RestrictedOffChainEeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo=";
final String MOCK_ORION_KEY = "";
final PrivacyIdProvider privacyIdProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@ -50,7 +47,11 @@ public class RestrictedOffChainEeaSendRawTransactionTest extends BaseEeaSendRawT
public void before() {
method =
new RestrictedOffChainEeaSendRawTransaction(
transactionPool, privacyController, privacyIdProvider);
transactionPool,
privacyIdProvider,
privateMarkerTransactionFactory,
address -> 0,
privacyController);
}
@Test
@ -59,27 +60,25 @@ public class RestrictedOffChainEeaSendRawTransactionTest extends BaseEeaSendRawT
.thenReturn(MOCK_ORION_KEY);
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivateMarkerTransaction(any(), any(), any()))
.thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any())).thenReturn(ValidationResult.valid());
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
validPrivateForTransactionRequest.getRequest().getId(),
"0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15");
"0x7f14b1aaa2fdddf918350d99801bf00a0eb1a1441b21b8c147f42db5ea675590");
final JsonRpcResponse actualResponse = method.response(validPrivateForTransactionRequest);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION);
verify(privacyController)
.createPrivateMarkerTransaction(any(), any(), eq(Address.DEFAULT_PRIVACY));
verify(transactionPool).addLocalTransaction(PUBLIC_OFF_CHAIN_TRANSACTION);
}
@Test
public void validPantheonPrivacyGroupTransactionIsSentToTransactionPool() {
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivateMarkerTransactionPayload(any(), any(), any()))
.thenReturn(MOCK_ORION_KEY);
Optional<PrivacyGroup> pantheonPrivacyGroup =
Optional.of(
@ -88,21 +87,16 @@ public class RestrictedOffChainEeaSendRawTransactionTest extends BaseEeaSendRawT
when(privacyController.findOffChainPrivacyGroupByGroupId(any(), any()))
.thenReturn(pantheonPrivacyGroup);
when(privacyController.createPrivateMarkerTransaction(any(), any(), any()))
.thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any())).thenReturn(ValidationResult.valid());
final JsonRpcResponse expectedResponse =
new JsonRpcSuccessResponse(
validPrivacyGroupTransactionRequest.getRequest().getId(),
"0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15");
"0x7f14b1aaa2fdddf918350d99801bf00a0eb1a1441b21b8c147f42db5ea675590");
final JsonRpcResponse actualResponse = method.response(validPrivacyGroupTransactionRequest);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION);
verify(privacyController)
.createPrivateMarkerTransaction(any(), any(), eq(Address.DEFAULT_PRIVACY));
}
@Test

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.privacy.methods.eea;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ -26,10 +25,8 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import java.util.Arrays;
import java.util.Optional;
@ -42,7 +39,6 @@ import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTransaction {
static final String ENCLAVE_PUBLIC_KEY = "S28yYlZxRCtuTmxOWUw1RUU3eTNJZE9udmlmdGppaXo=";
final String MOCK_ORION_KEY = "";
final PrivacyIdProvider privacyIdProvider = (user) -> ENCLAVE_PUBLIC_KEY;
@ -52,21 +48,23 @@ public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTr
public void before() {
method =
new RestrictedOnChainEeaSendRawTransaction(
transactionPool, privacyController, privacyIdProvider);
transactionPool,
privacyIdProvider,
privateMarkerTransactionFactory,
address -> 0,
privacyController);
}
@Test
public void validOnChainTransactionPrivacyGroupIsSentToTransactionPool() {
when(privacyController.createPrivateMarkerTransactionPayload(any(), any(), any()))
.thenReturn(MOCK_ORION_KEY);
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivateMarkerTransaction(
any(String.class), any(PrivateTransaction.class), any(Address.class)))
.thenReturn(PUBLIC_TRANSACTION);
when(transactionPool.addLocalTransaction(any(Transaction.class)))
.thenReturn(ValidationResult.valid());
when(privacyController.createPrivateMarkerTransactionPayload(any(), any(), any()))
.thenReturn(MOCK_ORION_KEY);
final Optional<PrivacyGroup> onChainPrivacyGroup =
Optional.of(
new PrivacyGroup(
@ -75,17 +73,15 @@ public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTr
when(privacyController.findOnChainPrivacyGroupAndAddNewMembers(any(), any(), any()))
.thenReturn(onChainPrivacyGroup);
final JsonRpcResponse expectedResponse =
final JsonRpcSuccessResponse expectedResponse =
new JsonRpcSuccessResponse(
validPrivacyGroupTransactionRequest.getRequest().getId(),
"0x221e930a2c18d91fca4d509eaa3512f3e01fef266f660e32473de67474b36c15");
"0x5af919ad2926e1cf98292dc0f3f8f74dbc446dd96debdd97e224e4695e662ff0");
final JsonRpcResponse actualResponse = method.response(validPrivacyGroupTransactionRequest);
assertThat(actualResponse).usingRecursiveComparison().isEqualTo(expectedResponse);
verify(transactionPool).addLocalTransaction(PUBLIC_TRANSACTION);
verify(privacyController)
.createPrivateMarkerTransaction(any(), any(), eq(Address.ONCHAIN_PRIVACY));
verify(transactionPool).addLocalTransaction(PUBLIC_ONCHAIN_TRANSACTION);
}
@Test
@ -93,10 +89,6 @@ public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTr
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
method =
new RestrictedOnChainEeaSendRawTransaction(
transactionPool, privacyController, privacyIdProvider);
final JsonRpcResponse expectedResponse =
new JsonRpcErrorResponse(
validPrivateForTransactionRequest.getRequest().getId(),
@ -112,10 +104,6 @@ public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTr
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
method =
new RestrictedOnChainEeaSendRawTransaction(
transactionPool, privacyController, privacyIdProvider);
when(privacyController.findOnChainPrivacyGroupAndAddNewMembers(any(), any(), any()))
.thenReturn(Optional.empty());
@ -134,10 +122,6 @@ public class RestrictedOnChainEeaSendRawTransactionTest extends BaseEeaSendRawTr
when(privacyController.validatePrivateTransaction(any(), any()))
.thenReturn(ValidationResult.valid());
method =
new RestrictedOnChainEeaSendRawTransaction(
transactionPool, privacyController, privacyIdProvider);
final JsonRpcResponse expectedResponse =
new JsonRpcErrorResponse(
validPrivacyGroupTransactionRequest.getRequest().getId(),

@ -35,6 +35,7 @@ import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.privacy.PrivacyController;
import org.hyperledger.besu.ethereum.privacy.RestrictedMultiTenancyPrivacyController;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.Map;
import java.util.Optional;
@ -64,6 +65,7 @@ public class PrivacyApiGroupJsonRpcMethodsTest {
@Before
public void setup() {
when(rpcMethod.getName()).thenReturn("priv_method");
privacyApiGroupJsonRpcMethods =
new TestPrivacyApiGroupJsonRpcMethods(
blockchainQueries, protocolSchedule, transactionPool, privacyParameters, rpcMethod);
@ -178,7 +180,9 @@ public class PrivacyApiGroupJsonRpcMethodsTest {
@Override
protected Map<String, JsonRpcMethod> create(
final PrivacyController privacyController, final PrivacyIdProvider privacyIdProvider) {
final PrivacyController privacyController,
final PrivacyIdProvider privacyIdProvider,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {
this.privacyController = privacyController;
this.privacyIdProvider = privacyIdProvider;
return mapOf(rpcMethod);

@ -43,7 +43,9 @@ import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
/** An operation submitted by an external actor to be applied to the system. */
public class Transaction implements org.hyperledger.besu.plugin.data.Transaction {
public class Transaction
implements org.hyperledger.besu.plugin.data.Transaction,
org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction {
// Used for transactions that are not tied to a specific chain
// (e.g. does not have a chain id associated with it).
@ -104,6 +106,10 @@ public class Transaction implements org.hyperledger.besu.plugin.data.Transaction
return new Builder();
}
public static Transaction readFrom(final Bytes rlpBytes) {
return readFrom(RLP.input(rlpBytes));
}
public static Transaction readFrom(final RLPInput rlpInput) {
return TransactionDecoder.decodeForWire(rlpInput);
}

@ -92,4 +92,8 @@ public final class Wei extends BaseUInt256Value<Wei> implements Quantity {
public String toShortHexString() {
return super.isZero() ? "0x0" : super.toShortHexString();
}
public static Wei fromQuantity(final Quantity quantity) {
return Wei.of(quantity.getAsBigInteger());
}
}

@ -26,7 +26,6 @@ import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.markertransaction.PrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
@ -43,7 +42,6 @@ import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
public class PluginPrivacyController implements PrivacyController {
private final PrivateMarkerTransactionFactory privateMarkerTransactionFactory;
private final PrivateTransactionValidator privateTransactionValidator;
private final PrivateStateRootResolver privateStateRootResolver;
private final Blockchain blockchain;
@ -56,11 +54,9 @@ public class PluginPrivacyController implements PrivacyController {
final Blockchain blockchain,
final PrivacyParameters privacyParameters,
final Optional<BigInteger> chainId,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final PrivateTransactionSimulator privateTransactionSimulator,
final PrivateNonceProvider privateNonceProvider,
final PrivateWorldStateReader privateWorldStateReader) {
this.privateMarkerTransactionFactory = privateMarkerTransactionFactory;
this.privateTransactionValidator = new PrivateTransactionValidator(chainId);
this.blockchain = blockchain;
this.privateTransactionSimulator = privateTransactionSimulator;
@ -82,22 +78,6 @@ public class PluginPrivacyController implements PrivacyController {
.toBase64String();
}
@Override
public Transaction createPrivateMarkerTransaction(
final String unrestrictedTransactionPayload, final PrivateTransaction privateTransaction) {
return privateMarkerTransactionFactory.create(
unrestrictedTransactionPayload, privateTransaction);
}
@Override
public Transaction createPrivateMarkerTransaction(
final String unrestrictedTransactionPayload,
final PrivateTransaction privateTransaction,
final Address privacyPrecompileAddress) {
return privateMarkerTransactionFactory.create(
unrestrictedTransactionPayload, privateTransaction, privacyPrecompileAddress);
}
@Override
public ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final String privacyUserId) {

@ -18,7 +18,6 @@ import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
@ -49,14 +48,6 @@ public interface PrivacyController {
PrivacyGroup[] findOffChainPrivacyGroupByMembers(List<String> addresses, String privacyUserId);
Transaction createPrivateMarkerTransaction(
String privateMarkerTransactionPayload, PrivateTransaction privateTransaction);
Transaction createPrivateMarkerTransaction(
String privateMarkerTransactionPayload,
PrivateTransaction privateTransaction,
Address privacyPrecompileAddress);
ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
PrivateTransaction privateTransaction, String privacyUserId);

@ -31,7 +31,6 @@ import org.hyperledger.besu.ethereum.core.PrivacyParameters;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.markertransaction.PrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateTransactionMetadata;
@ -66,7 +65,6 @@ public class RestrictedDefaultPrivacyController implements PrivacyController {
private final PrivateStateStorage privateStateStorage;
private final Enclave enclave;
private final PrivateTransactionValidator privateTransactionValidator;
private final PrivateMarkerTransactionFactory privateMarkerTransactionFactory;
private final PrivateTransactionSimulator privateTransactionSimulator;
private final PrivateNonceProvider privateNonceProvider;
private final PrivateWorldStateReader privateWorldStateReader;
@ -77,7 +75,6 @@ public class RestrictedDefaultPrivacyController implements PrivacyController {
final Blockchain blockchain,
final PrivacyParameters privacyParameters,
final Optional<BigInteger> chainId,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final PrivateTransactionSimulator privateTransactionSimulator,
final PrivateNonceProvider privateNonceProvider,
final PrivateWorldStateReader privateWorldStateReader) {
@ -86,7 +83,6 @@ public class RestrictedDefaultPrivacyController implements PrivacyController {
privacyParameters.getPrivateStateStorage(),
privacyParameters.getEnclave(),
new PrivateTransactionValidator(chainId),
privateMarkerTransactionFactory,
privateTransactionSimulator,
privateNonceProvider,
privateWorldStateReader,
@ -98,7 +94,6 @@ public class RestrictedDefaultPrivacyController implements PrivacyController {
final PrivateStateStorage privateStateStorage,
final Enclave enclave,
final PrivateTransactionValidator privateTransactionValidator,
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory,
final PrivateTransactionSimulator privateTransactionSimulator,
final PrivateNonceProvider privateNonceProvider,
final PrivateWorldStateReader privateWorldStateReader,
@ -107,7 +102,6 @@ public class RestrictedDefaultPrivacyController implements PrivacyController {
this.privateStateStorage = privateStateStorage;
this.enclave = enclave;
this.privateTransactionValidator = privateTransactionValidator;
this.privateMarkerTransactionFactory = privateMarkerTransactionFactory;
this.privateTransactionSimulator = privateTransactionSimulator;
this.privateNonceProvider = privateNonceProvider;
this.privateWorldStateReader = privateWorldStateReader;
@ -163,21 +157,6 @@ public class RestrictedDefaultPrivacyController implements PrivacyController {
return enclave.findPrivacyGroup(addresses);
}
@Override
public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId, final PrivateTransaction privateTransaction) {
return privateMarkerTransactionFactory.create(privateTransactionLookupId, privateTransaction);
}
@Override
public Transaction createPrivateMarkerTransaction(
final String transactionPayload,
final PrivateTransaction privateTransaction,
final Address privacyPrecompileAddress) {
return privateMarkerTransactionFactory.create(
transactionPayload, privateTransaction, privacyPrecompileAddress);
}
@Override
public ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final String privacyUserId) {

@ -19,7 +19,6 @@ import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
@ -127,22 +126,6 @@ public class RestrictedMultiTenancyPrivacyController implements PrivacyControlle
.toArray(PrivacyGroup[]::new);
}
@Override
public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId, final PrivateTransaction privateTransaction) {
return privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, privateTransaction);
}
@Override
public Transaction createPrivateMarkerTransaction(
final String privateTransactionLookupId,
final PrivateTransaction privateTransaction,
final Address privacyPrecompileAddress) {
return privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, privateTransaction, privacyPrecompileAddress);
}
@Override
public ValidationResult<TransactionInvalidReason> validatePrivateTransaction(
final PrivateTransaction privateTransaction, final String privacyUserId) {

@ -15,39 +15,36 @@
package org.hyperledger.besu.ethereum.privacy.markertransaction;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.ethereum.util.NonceProvider;
import org.hyperledger.besu.plugin.data.Address;
import org.hyperledger.besu.plugin.data.PrivateTransaction;
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import org.apache.tuweni.bytes.Bytes;
public class FixedKeySigningPrivateMarkerTransactionFactory
extends PrivateMarkerTransactionFactory {
extends SigningPrivateMarkerTransactionFactory implements PrivateMarkerTransactionFactory {
private final NonceProvider nonceProvider;
private final KeyPair signingKey;
private final Address sender;
public FixedKeySigningPrivateMarkerTransactionFactory(
final Address privacyPrecompileAddress,
final NonceProvider nonceProvider,
final KeyPair signingKey) {
super(privacyPrecompileAddress);
this.nonceProvider = nonceProvider;
public FixedKeySigningPrivateMarkerTransactionFactory(final KeyPair signingKey) {
this.signingKey = signingKey;
this.sender = Util.publicKeyToAddress(signingKey.getPublicKey());
}
@Override
public Transaction create(
final String privateMarkerTransactionPayload,
public Address getSender(
final PrivateTransaction privateTransaction, final String privacyUserId) {
return this.sender;
}
@Override
public Bytes create(
final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction,
final PrivateTransaction privateTransaction,
final Address precompileAddress) {
return create(
privateMarkerTransactionPayload,
privateTransaction,
nonceProvider.getNonce(sender),
signingKey,
precompileAddress);
final String privacyUserId) {
return signAndBuild(unsignedPrivateMarkerTransaction, signingKey);
}
}

@ -1,59 +0,0 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.privacy.markertransaction;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.apache.tuweni.bytes.Bytes;
public abstract class PrivateMarkerTransactionFactory {
private final Address privacyPrecompileAddress;
protected PrivateMarkerTransactionFactory(final Address privacyPrecompileAddress) {
this.privacyPrecompileAddress = privacyPrecompileAddress;
}
public Transaction create(
final String privateMarkerTransactionPayload, final PrivateTransaction privateTransaction) {
return create(privateMarkerTransactionPayload, privateTransaction, privacyPrecompileAddress);
}
public abstract Transaction create(
final String privateMarkerTransactionPayload,
final PrivateTransaction privateTransaction,
final Address precompileAddress);
protected Transaction create(
final String privateMarkerTransactionPayload,
final PrivateTransaction privateTransaction,
final long nonce,
final KeyPair signingKey,
final Address precompileAddress) {
return Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(nonce)
.gasPrice(privateTransaction.getGasPrice())
.gasLimit(privateTransaction.getGasLimit())
.to(precompileAddress)
.value(privateTransaction.getValue())
.payload(Bytes.fromBase64String(privateMarkerTransactionPayload))
.signAndBuild(signingKey);
}
}

@ -15,24 +15,38 @@
package org.hyperledger.besu.ethereum.privacy.markertransaction;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithm;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.plugin.data.Address;
import org.hyperledger.besu.plugin.data.PrivateTransaction;
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
public class RandomSigningPrivateMarkerTransactionFactory extends PrivateMarkerTransactionFactory {
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import org.apache.tuweni.bytes.Bytes;
public RandomSigningPrivateMarkerTransactionFactory(final Address privacyPrecompileAddress) {
super(privacyPrecompileAddress);
public class RandomSigningPrivateMarkerTransactionFactory
extends SigningPrivateMarkerTransactionFactory implements PrivateMarkerTransactionFactory {
private static final Supplier<SignatureAlgorithm> SIGNATURE_ALGORITHM_SUPPLIER =
Suppliers.memoize(SignatureAlgorithmFactory::getInstance);
@Override
public Address getSender(
final PrivateTransaction privateTransaction, final String privacyUserId) {
// Note the address here is only used as a key to lock nonce generation for the same address
final KeyPair signingKey = SIGNATURE_ALGORITHM_SUPPLIER.get().generateKeyPair();
return org.hyperledger.besu.ethereum.core.Address.extract(signingKey.getPublicKey());
}
@Override
public Transaction create(
final String privateMarkerTransactionPayload,
public Bytes create(
final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction,
final PrivateTransaction privateTransaction,
final Address precompileAddress) {
final KeyPair signingKey = SignatureAlgorithmFactory.getInstance().generateKeyPair();
return create(
privateMarkerTransactionPayload, privateTransaction, 0, signingKey, precompileAddress);
final String privacyUserId) {
final KeyPair signingKey = SIGNATURE_ALGORITHM_SUPPLIER.get().generateKeyPair();
return signAndBuild(unsignedPrivateMarkerTransaction, signingKey);
}
}

@ -0,0 +1,49 @@
/*
* Copyright ConsenSys AG.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.privacy.markertransaction;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction;
import org.apache.tuweni.bytes.Bytes;
public class SigningPrivateMarkerTransactionFactory {
protected Bytes signAndBuild(
final UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction,
final KeyPair signingKey) {
final Transaction transaction =
Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(unsignedPrivateMarkerTransaction.getNonce())
.gasPrice(
unsignedPrivateMarkerTransaction.getGasPrice().map(Wei::fromQuantity).orElse(null))
.gasLimit(unsignedPrivateMarkerTransaction.getGasLimit())
.to(
org.hyperledger.besu.ethereum.core.Address.fromPlugin(
unsignedPrivateMarkerTransaction.getTo().get()))
.value(Wei.fromQuantity(unsignedPrivateMarkerTransaction.getValue()))
.payload(unsignedPrivateMarkerTransaction.getPayload())
.signAndBuild(signingKey);
final BytesValueRLPOutput out = new BytesValueRLPOutput();
transaction.writeTo(out);
return out.encoded();
}
}

@ -50,6 +50,7 @@ import org.hyperledger.besu.ethereum.vm.OperationTracer;
import org.hyperledger.besu.plugin.services.PrivacyPluginService;
import org.hyperledger.besu.plugin.services.privacy.PrivacyGroupAuthProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivacyPluginPayloadProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
import java.util.ArrayList;
import java.util.List;
@ -133,6 +134,15 @@ public class PrivacyPluginPrecompiledContractTest {
public PrivacyGroupAuthProvider getPrivacyGroupAuthProvider() {
return (privacyGroupId, privacyUserId, blockNumber) -> true;
}
@Override
public PrivateMarkerTransactionFactory getPrivateMarkerTransactionFactory() {
return null;
}
@Override
public void setPrivateMarkerTransactionFactory(
final PrivateMarkerTransactionFactory privateMarkerTransactionFactory) {}
})
.setEnclaveFactory(mock(EnclaveFactory.class))
.build());

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.privacy;
import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason.INCORRECT_PRIVATE_NONCE;
@ -38,27 +37,22 @@ import org.hyperledger.besu.enclave.Enclave;
import org.hyperledger.besu.enclave.EnclaveServerException;
import org.hyperledger.besu.enclave.types.PrivacyGroup;
import org.hyperledger.besu.enclave.types.ReceiveResponse;
import org.hyperledger.besu.enclave.types.SendResponse;
import org.hyperledger.besu.ethereum.chain.Blockchain;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.Log;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.mainnet.ValidationResult;
import org.hyperledger.besu.ethereum.privacy.markertransaction.FixedKeySigningPrivateMarkerTransactionFactory;
import org.hyperledger.besu.ethereum.privacy.storage.PrivacyGroupHeadBlockMap;
import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage;
import org.hyperledger.besu.ethereum.processing.TransactionProcessingResult;
import org.hyperledger.besu.ethereum.transaction.CallParameter;
import org.hyperledger.besu.ethereum.transaction.TransactionInvalidReason;
import org.hyperledger.besu.plugin.data.Restriction;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.enclave.testutil.EnclaveKeyUtils;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ -98,10 +92,6 @@ public class RestrictedDefaultPrivacyControllerTest {
private static final ArrayList<Log> LOGS = new ArrayList<>();
private static final String MOCK_TRANSACTION_SIMULATOR_RESULT_OUTPUT_BYTES_PREFIX =
"0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002";
private static final PrivacyGroup PANTHEON_PRIVACY_GROUP =
new PrivacyGroup("", PrivacyGroup.Type.PANTHEON, "", "", emptyList());
private static final PrivacyGroup ONCHAIN_PRIVACY_GROUP =
new PrivacyGroup("", PrivacyGroup.Type.ONCHAIN, "", "", Arrays.asList(ENCLAVE_PUBLIC_KEY));
private PrivacyController privacyController;
private PrivacyController brokenPrivacyController;
@ -115,26 +105,10 @@ public class RestrictedDefaultPrivacyControllerTest {
private Blockchain blockchain;
private PrivateStateStorage privateStateStorage;
private static final Transaction PUBLIC_TRANSACTION =
Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(0)
.gasPrice(Wei.of(1000))
.gasLimit(3000000)
.to(Address.fromHexString("0x627306090abab3a6e1400e9345bc60c78a8bef57"))
.value(Wei.ZERO)
.payload(Base64.decode(TRANSACTION_KEY))
.sender(Address.fromHexString("0xfe3b557e8fb62b89f4916b721be55ceb828dbd73"))
.chainId(BigInteger.valueOf(1337))
.signAndBuild(KEY_PAIR);
private Enclave mockEnclave() {
final Enclave mockEnclave = mock(Enclave.class);
final SendResponse response = new SendResponse(TRANSACTION_KEY);
final ReceiveResponse receiveResponse =
new ReceiveResponse(new byte[0], PRIVACY_GROUP_ID, null);
when(mockEnclave.send(anyString(), anyString(), anyList())).thenReturn(response);
when(mockEnclave.send(anyString(), anyString(), anyString())).thenReturn(response);
when(mockEnclave.receive(any(), any())).thenReturn(receiveResponse);
return mockEnclave;
}
@ -173,8 +147,6 @@ public class RestrictedDefaultPrivacyControllerTest {
privateStateStorage,
enclave,
privateTransactionValidator,
new FixedKeySigningPrivateMarkerTransactionFactory(
Address.DEFAULT_PRIVACY, (address) -> 0, KEY_PAIR),
privateTransactionSimulator,
privateNonceProvider,
privateWorldStateReader,
@ -185,61 +157,12 @@ public class RestrictedDefaultPrivacyControllerTest {
privateStateStorage,
brokenMockEnclave(),
privateTransactionValidator,
new FixedKeySigningPrivateMarkerTransactionFactory(
Address.DEFAULT_PRIVACY, (address) -> 0, KEY_PAIR),
privateTransactionSimulator,
privateNonceProvider,
privateWorldStateReader,
privateStateRootResolver);
}
@Test
public void sendsValidLegacyTransaction() {
final PrivateTransaction transaction = buildLegacyPrivateTransaction(1);
final String privateTransactionLookupId =
privacyController.createPrivateMarkerTransactionPayload(
transaction, ENCLAVE_PUBLIC_KEY, Optional.empty());
final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final Transaction markerTransaction =
privacyController.createPrivateMarkerTransaction(privateTransactionLookupId, transaction);
assertThat(validationResult).isEqualTo(ValidationResult.valid());
assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress());
assertThat(markerTransaction.getPayload()).isEqualTo(PUBLIC_TRANSACTION.getPayload());
assertThat(markerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
assertThat(markerTransaction.getSender()).isEqualTo(PUBLIC_TRANSACTION.getSender());
assertThat(markerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
verify(enclave)
.send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(List.of(ENCLAVE_PUBLIC_KEY, ENCLAVE_KEY2)));
}
@Test
public void sendValidBesuTransaction() {
final PrivateTransaction transaction = buildBesuPrivateTransaction(1);
final String privateTransactionLookupId =
privacyController.createPrivateMarkerTransactionPayload(
transaction, ENCLAVE_PUBLIC_KEY, Optional.of(PANTHEON_PRIVACY_GROUP));
final ValidationResult<TransactionInvalidReason> validationResult =
privacyController.validatePrivateTransaction(transaction, ENCLAVE_PUBLIC_KEY);
final Transaction markerTransaction =
privacyController.createPrivateMarkerTransaction(privateTransactionLookupId, transaction);
assertThat(validationResult).isEqualTo(ValidationResult.valid());
assertThat(markerTransaction.contractAddress()).isEqualTo(PUBLIC_TRANSACTION.contractAddress());
assertThat(markerTransaction.getPayload()).isEqualTo(PUBLIC_TRANSACTION.getPayload());
assertThat(markerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
assertThat(markerTransaction.getSender()).isEqualTo(PUBLIC_TRANSACTION.getSender());
assertThat(markerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
verify(enclave).send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(PRIVACY_GROUP_ID));
}
@Test
public void findOnChainPrivacyGroups() {
final List<String> privacyGroupAddresses = newArrayList(ENCLAVE_PUBLIC_KEY, ENCLAVE_KEY2);
@ -460,31 +383,6 @@ public class RestrictedDefaultPrivacyControllerTest {
assertThat(result.isPresent()).isTrue();
}
@Test
public void canCreatePrivateMarkerTransactionForOnChainPrivacy() {
final PrivateTransaction transaction = buildBesuPrivateTransaction(0);
final String privateTransactionLookupId =
privacyController.createPrivateMarkerTransactionPayload(
transaction, ENCLAVE_PUBLIC_KEY, Optional.of(ONCHAIN_PRIVACY_GROUP));
final Transaction onChainPrivateMarkerTransaction =
privacyController.createPrivateMarkerTransaction(
privateTransactionLookupId, transaction, Address.ONCHAIN_PRIVACY);
assertThat(onChainPrivateMarkerTransaction.contractAddress())
.isEqualTo(PUBLIC_TRANSACTION.contractAddress());
assertThat(onChainPrivateMarkerTransaction.getPayload())
.isEqualTo(PUBLIC_TRANSACTION.getPayload());
assertThat(onChainPrivateMarkerTransaction.getNonce()).isEqualTo(PUBLIC_TRANSACTION.getNonce());
assertThat(onChainPrivateMarkerTransaction.getSender())
.isEqualTo(PUBLIC_TRANSACTION.getSender());
assertThat(onChainPrivateMarkerTransaction.getValue()).isEqualTo(PUBLIC_TRANSACTION.getValue());
assertThat(onChainPrivateMarkerTransaction.getTo().get()).isEqualTo(Address.ONCHAIN_PRIVACY);
verify(enclave)
.send(anyString(), eq(ENCLAVE_PUBLIC_KEY), eq(singletonList(ENCLAVE_PUBLIC_KEY)));
}
@Test
public void getContractCodeCallsPrivateWorldStateReader() {
final Hash blockHash = Hash.ZERO;
@ -513,14 +411,6 @@ public class RestrictedDefaultPrivacyControllerTest {
.signAndBuild(KEY_PAIR);
}
private static PrivateTransaction buildBesuPrivateTransaction(final long nonce) {
return buildPrivateTransaction(nonce)
.privateFrom(Bytes.fromBase64String(ENCLAVE_PUBLIC_KEY))
.privacyGroupId(Bytes.fromBase64String(PRIVACY_GROUP_ID))
.signAndBuild(KEY_PAIR);
}
private static PrivateTransaction.Builder buildPrivateTransaction(final long nonce) {
return PrivateTransaction.builder()
.nonce(nonce)

@ -16,7 +16,6 @@ package org.hyperledger.besu.ethereum.privacy.markertransaction;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.crypto.KeyPair;
import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;
@ -25,54 +24,56 @@ import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Util;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.plugin.data.TransactionType;
import java.util.Base64;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
import org.junit.Test;
public class FixedKeySigningPrivateMarkerTransactionFactoryTest {
private final PrivateTransaction privTransaction = mock(PrivateTransaction.class);
private final Wei gasPrice = Wei.of(100);
private final long gasLimit = 500;
private final Wei value = Wei.ZERO;
private final long providedNonce = 100;
private final String enclaveKey = "enclaveKey";
@Before
public void setup() {
when(privTransaction.getGasPrice()).thenReturn(gasPrice);
when(privTransaction.getGasLimit()).thenReturn(gasLimit);
when(privTransaction.getValue()).thenReturn(value);
}
@Test
public void createsFullyPopulatedPrivateMarkerTransactionUsingProvidedNonce() {
final PrivateTransaction privTransaction = mock(PrivateTransaction.class);
final Wei gasPrice = Wei.of(100);
final long gasLimit = 500;
final long providedNonce = 100;
final String enclaveKey = "pmtLookupKey";
final KeyPair signingKeys = SignatureAlgorithmFactory.getInstance().generateKeyPair();
final Address precompiledAddress = Address.fromHexString("1");
final FixedKeySigningPrivateMarkerTransactionFactory factory =
new FixedKeySigningPrivateMarkerTransactionFactory(
precompiledAddress, (address) -> providedNonce, signingKeys);
new FixedKeySigningPrivateMarkerTransactionFactory(signingKeys);
final Transaction unsignedPrivateMarkerTransaction =
new Transaction.Builder()
.type(TransactionType.FRONTIER)
.nonce(providedNonce)
.gasPrice(gasPrice)
.gasLimit(gasLimit)
.to(precompiledAddress)
.value(Wei.ZERO)
.payload(Bytes.fromBase64String(enclaveKey))
.build();
final Transaction transaction = factory.create(enclaveKey, privTransaction);
final Transaction transaction =
Transaction.readFrom(factory.create(unsignedPrivateMarkerTransaction, privTransaction, ""));
assertThat(transaction.getNonce()).isEqualTo(providedNonce);
assertThat(transaction.getGasLimit()).isEqualTo(privTransaction.getGasLimit());
assertThat(transaction.getGasPrice().get()).isEqualTo(privTransaction.getGasPrice());
assertThat(transaction.getValue()).isEqualTo(privTransaction.getValue());
assertThat(transaction.getGasLimit()).isEqualTo(gasLimit);
assertThat(transaction.getGasPrice().get()).isEqualTo(gasPrice);
assertThat(transaction.getValue()).isEqualTo(Wei.ZERO);
assertThat(transaction.getSender())
.isEqualTo(Util.publicKeyToAddress(signingKeys.getPublicKey()));
assertThat(transaction.getTo()).isEqualTo(Optional.of(precompiledAddress));
assertThat(transaction.getPayload())
.isEqualTo(Bytes.wrap(Base64.getDecoder().decode(enclaveKey)));
assertThat(transaction.getPayload()).isEqualTo(Bytes.fromBase64String(enclaveKey));
final Transaction nextTransaction = factory.create("enclaveKey", privTransaction);
final Transaction nextTransaction =
Transaction.readFrom(factory.create(unsignedPrivateMarkerTransaction, privTransaction, ""));
assertThat(nextTransaction.getSender()).isEqualTo(transaction.getSender());
}
}

@ -16,54 +16,58 @@ package org.hyperledger.besu.ethereum.privacy.markertransaction;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
import org.hyperledger.besu.ethereum.privacy.PrivateTransaction;
import org.hyperledger.besu.plugin.data.TransactionType;
import java.util.Base64;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
import org.junit.Before;
import org.junit.Test;
public class RandomSigningPrivateMarkerTransactionFactoryTest {
private final PrivateTransaction privTransaction = mock(PrivateTransaction.class);
@Test
public void producedTransactionHasZeroNonceAndDifferentSendThanPrior() {
private final Wei gasPrice = Wei.of(100);
private final long gasLimit = 500;
private final Wei value = Wei.ZERO;
private final String enclaveKey = "enclaveKey";
final PrivateTransaction privTransaction = mock(PrivateTransaction.class);
@Before
public void setup() {
when(privTransaction.getGasPrice()).thenReturn(gasPrice);
when(privTransaction.getGasLimit()).thenReturn(gasLimit);
when(privTransaction.getValue()).thenReturn(value);
}
final Wei gasPrice = Wei.of(100);
final long gasLimit = 500;
final String enclaveKey = "enclaveKey";
final long providedNonce = 0;
@Test
public void producedTransactionHasZeroNonceAndDifferentSendThanPrior() {
final Address precompiledAddress = Address.fromHexString("1");
final Transaction unsignedPrivateMarkerTransaction =
new Transaction.Builder()
.type(TransactionType.FRONTIER)
.nonce(providedNonce)
.gasPrice(gasPrice)
.gasLimit(gasLimit)
.to(precompiledAddress)
.value(Wei.ZERO)
.payload(Bytes.fromBase64String(enclaveKey))
.build();
final RandomSigningPrivateMarkerTransactionFactory factory =
new RandomSigningPrivateMarkerTransactionFactory(precompiledAddress);
new RandomSigningPrivateMarkerTransactionFactory();
final Transaction transaction = factory.create(enclaveKey, privTransaction);
final Transaction transaction =
Transaction.readFrom(factory.create(unsignedPrivateMarkerTransaction, privTransaction, ""));
assertThat(transaction.getNonce()).isEqualTo(0);
assertThat(transaction.getGasLimit()).isEqualTo(privTransaction.getGasLimit());
assertThat(transaction.getGasPrice().get()).isEqualTo(privTransaction.getGasPrice());
assertThat(transaction.getValue()).isEqualTo(privTransaction.getValue());
assertThat(transaction.getGasLimit()).isEqualTo(gasLimit);
assertThat(transaction.getGasPrice().get()).isEqualTo(gasPrice);
assertThat(transaction.getValue()).isEqualTo(Wei.ZERO);
assertThat(transaction.getTo()).isEqualTo(Optional.of(precompiledAddress));
assertThat(transaction.getPayload())
.isEqualTo(Bytes.wrap(Base64.getDecoder().decode(enclaveKey)));
assertThat(transaction.getPayload()).isEqualTo(Bytes.fromBase64String(enclaveKey));
final Transaction nextTransaction = factory.create("enclaveKey", privTransaction);
final Transaction nextTransaction =
Transaction.readFrom(factory.create(unsignedPrivateMarkerTransaction, privTransaction, ""));
assertThat(nextTransaction.getSender()).isNotEqualTo(transaction.getSender());
}
}

@ -64,7 +64,7 @@ Calculated : ${currentHash}
tasks.register('checkAPIChanges', FileStateChecker) {
description = "Checks that the API for the Plugin-API project does not change without deliberate thought"
files = sourceSets.main.allJava.files
knownHash = '7A9tIejAyYgizfaMXMD5Q9QYqzMvK32w1JOWkqXIpDI='
knownHash = 'HVhl+xNOt6THTZvQNZ9NnOIQB6AkN+wq+1stbnqe6ig='
}
check.dependsOn('checkAPIChanges')

@ -0,0 +1,36 @@
/*
* 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.plugin.data;
import java.util.Optional;
import org.apache.tuweni.bytes.Bytes;
public interface UnsignedPrivateMarkerTransaction {
TransactionType getType();
long getNonce();
Optional<? extends Quantity> getGasPrice();
long getGasLimit();
Optional<? extends Address> getTo();
Quantity getValue();
Bytes getPayload();
}

@ -16,6 +16,7 @@ package org.hyperledger.besu.plugin.services;
import org.hyperledger.besu.plugin.services.privacy.PrivacyGroupAuthProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivacyPluginPayloadProvider;
import org.hyperledger.besu.plugin.services.privacy.PrivateMarkerTransactionFactory;
public interface PrivacyPluginService extends BesuService {
void setPayloadProvider(PrivacyPluginPayloadProvider privacyPluginPayloadProvider);
@ -25,4 +26,9 @@ public interface PrivacyPluginService extends BesuService {
void setPrivacyGroupAuthProvider(PrivacyGroupAuthProvider privacyGroupAuthProvider);
PrivacyGroupAuthProvider getPrivacyGroupAuthProvider();
PrivateMarkerTransactionFactory getPrivateMarkerTransactionFactory();
void setPrivateMarkerTransactionFactory(
PrivateMarkerTransactionFactory privateMarkerTransactionFactory);
}

@ -0,0 +1,31 @@
/*
* 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.plugin.services.privacy;
import org.hyperledger.besu.plugin.data.Address;
import org.hyperledger.besu.plugin.data.PrivateTransaction;
import org.hyperledger.besu.plugin.data.UnsignedPrivateMarkerTransaction;
import org.apache.tuweni.bytes.Bytes;
public interface PrivateMarkerTransactionFactory {
Address getSender(PrivateTransaction privateTransaction, String privacyUserId);
Bytes create(
UnsignedPrivateMarkerTransaction unsignedPrivateMarkerTransaction,
PrivateTransaction privateTransaction,
String privacyUserId);
}
Loading…
Cancel
Save