From 38a025b8708f2c8f0daa31db1f30e995d9d15dd8 Mon Sep 17 00:00:00 2001 From: Justin Florentine Date: Fri, 2 Aug 2024 13:01:58 -0400 Subject: [PATCH] Dagger controller tests (#7341) * daggerize PrivacyReorgTest * inline as many dagger bits into tests as possible * refactored to use inner classes * BesuComponent can now be provided --------- Signed-off-by: Justin Florentine Signed-off-by: Sally MacFarlane Co-authored-by: Sally MacFarlane --- .../perm/AllowListContainsKeyAndValue.java | 6 + .../dsl/node/ThreadBesuNodeRunner.java | 376 ++++++++++++------ .../acceptance/dsl/privacy/PrivacyNode.java | 2 +- ...ClusterThreadNodeRunnerAcceptanceTest.java | 2 +- besu/build.gradle | 2 + .../controller/BesuControllerBuilder.java | 1 + .../besu/services/BlockchainServiceImpl.java | 2 + .../services/PermissioningServiceImpl.java | 2 + .../besu/services/RpcEndpointServiceImpl.java | 2 + .../services/SecurityModuleServiceImpl.java | 7 +- .../besu/services/StorageServiceImpl.java | 2 + .../TransactionPoolValidatorServiceImpl.java | 6 +- .../TransactionSelectionServiceImpl.java | 6 +- .../TransactionSimulationServiceImpl.java | 2 + .../besu/FlexGroupPrivacyTest.java | 168 ++++++++ .../hyperledger/besu/PrivacyReorgTest.java | 151 +++++-- .../org/hyperledger/besu/PrivacyTest.java | 171 ++++---- .../java/org/hyperledger/besu/RunnerTest.java | 3 + .../chainexport/RlpBlockExporterTest.java | 3 + .../chainimport/JsonBlockImporterTest.java | 3 + .../chainimport/RlpBlockImporterTest.java | 5 + .../besu/components/EnclaveModule.java | 98 +++++ .../besu/components/GenesisConfigModule.java | 38 ++ .../components/MockBesuCommandModule.java | 50 +++ .../components/NoOpMetricsSystemModule.java | 40 ++ .../components/PrivacyParametersModule.java | 47 +++ .../besu/components/PrivacyTestModule.java | 111 ++++++ .../AbstractBftBesuControllerBuilderTest.java | 2 + .../CliqueBesuControllerBuilderTest.java | 2 + .../MergeBesuControllerBuilderTest.java | 2 + .../besu/ethereum/p2p/peers/EnodeURLImpl.java | 13 +- 31 files changed, 1064 insertions(+), 261 deletions(-) create mode 100644 besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java create mode 100644 besu/src/test/java/org/hyperledger/besu/components/EnclaveModule.java create mode 100644 besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java create mode 100644 besu/src/test/java/org/hyperledger/besu/components/MockBesuCommandModule.java create mode 100644 besu/src/test/java/org/hyperledger/besu/components/NoOpMetricsSystemModule.java create mode 100644 besu/src/test/java/org/hyperledger/besu/components/PrivacyParametersModule.java create mode 100644 besu/src/test/java/org/hyperledger/besu/components/PrivacyTestModule.java diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/AllowListContainsKeyAndValue.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/AllowListContainsKeyAndValue.java index a2ffc9b36da..0913fd227f3 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/AllowListContainsKeyAndValue.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/condition/perm/AllowListContainsKeyAndValue.java @@ -24,11 +24,16 @@ import java.nio.file.Path; import java.util.Collection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class AllowListContainsKeyAndValue implements Condition { private final ALLOWLIST_TYPE allowlistType; private final Collection allowlistValues; private final Path configFilePath; + private static final Logger LOG = LoggerFactory.getLogger(AllowListContainsKeyAndValue.class); + public AllowListContainsKeyAndValue( final ALLOWLIST_TYPE allowlistType, final Collection allowlistValues, @@ -47,6 +52,7 @@ public void verify(final Node node) { allowlistType, allowlistValues, configFilePath); } catch (final Exception e) { result = false; + LOG.error("Error verifying allowlist contains key and value", e); } assertThat(result).isTrue(); } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java index 459fe49efb3..7e8d435c721 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/node/ThreadBesuNodeRunner.java @@ -18,8 +18,13 @@ import org.hyperledger.besu.Runner; import org.hyperledger.besu.RunnerBuilder; +import org.hyperledger.besu.chainexport.RlpBlockExporter; +import org.hyperledger.besu.chainimport.JsonBlockImporter; +import org.hyperledger.besu.chainimport.RlpBlockImporter; +import org.hyperledger.besu.cli.BesuCommand; import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.controller.BesuControllerBuilder; @@ -31,23 +36,28 @@ import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration; import org.hyperledger.besu.ethereum.api.jsonrpc.InProcessRpcConfiguration; import org.hyperledger.besu.ethereum.core.ImmutableMiningParameters; +import org.hyperledger.besu.ethereum.core.MiningParameters; import org.hyperledger.besu.ethereum.core.plugins.PluginConfiguration; import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule; import org.hyperledger.besu.ethereum.eth.transactions.ImmutableTransactionPoolConfiguration; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.peers.EnodeURLImpl; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProvider; import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStorageProviderBuilder; import org.hyperledger.besu.ethereum.transaction.TransactionSimulator; +import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoaderModule; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; -import org.hyperledger.besu.metrics.MetricsSystemFactory; +import org.hyperledger.besu.metrics.MetricsSystemModule; import org.hyperledger.besu.metrics.ObservableMetricsSystem; +import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; import org.hyperledger.besu.plugin.data.EnodeURL; import org.hyperledger.besu.plugin.services.BesuConfiguration; import org.hyperledger.besu.plugin.services.BesuEvents; import org.hyperledger.besu.plugin.services.BlockchainService; +import org.hyperledger.besu.plugin.services.MetricsSystem; import org.hyperledger.besu.plugin.services.PermissioningService; import org.hyperledger.besu.plugin.services.PicoCLIOptions; import org.hyperledger.besu.plugin.services.PrivacyPluginService; @@ -71,17 +81,27 @@ import org.hyperledger.besu.services.TransactionPoolValidatorServiceImpl; import org.hyperledger.besu.services.TransactionSelectionServiceImpl; import org.hyperledger.besu.services.TransactionSimulationServiceImpl; +import org.hyperledger.besu.services.kvstore.InMemoryStoragePlugin; import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.time.Clock; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import dagger.Component; +import dagger.Module; +import dagger.Provides; import io.opentelemetry.api.GlobalOpenTelemetry; import io.vertx.core.Vertx; import org.slf4j.Logger; @@ -97,59 +117,6 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner { private final Map besuPluginContextMap = new ConcurrentHashMap<>(); - private BesuPluginContextImpl buildPluginContext( - final BesuNode node, - final StorageServiceImpl storageService, - final SecurityModuleServiceImpl securityModuleService, - final TransactionSimulationServiceImpl transactionSimulationServiceImpl, - final TransactionSelectionServiceImpl transactionSelectionServiceImpl, - final TransactionPoolValidatorServiceImpl transactionPoolValidatorServiceImpl, - final BlockchainServiceImpl blockchainServiceImpl, - final RpcEndpointServiceImpl rpcEndpointServiceImpl, - final BesuConfiguration commonPluginConfiguration, - final PermissioningServiceImpl permissioningService) { - final CommandLine commandLine = new CommandLine(CommandSpec.create()); - final BesuPluginContextImpl besuPluginContext = new BesuPluginContextImpl(); - besuPluginContext.addService(StorageService.class, storageService); - besuPluginContext.addService(SecurityModuleService.class, securityModuleService); - besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); - besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); - besuPluginContext.addService( - TransactionSelectionService.class, transactionSelectionServiceImpl); - besuPluginContext.addService( - TransactionPoolValidatorService.class, transactionPoolValidatorServiceImpl); - besuPluginContext.addService( - TransactionSimulationService.class, transactionSimulationServiceImpl); - besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl); - besuPluginContext.addService(BesuConfiguration.class, commonPluginConfiguration); - - final Path pluginsPath; - final String pluginDir = System.getProperty("besu.plugins.dir"); - if (pluginDir == null || pluginDir.isEmpty()) { - pluginsPath = node.homeDirectory().resolve("plugins"); - final File pluginsDirFile = pluginsPath.toFile(); - if (!pluginsDirFile.isDirectory()) { - pluginsDirFile.mkdirs(); - pluginsDirFile.deleteOnExit(); - } - System.setProperty("besu.plugins.dir", pluginsPath.toString()); - } else { - pluginsPath = Path.of(pluginDir); - } - - besuPluginContext.addService(BesuConfiguration.class, commonPluginConfiguration); - besuPluginContext.addService(PermissioningService.class, permissioningService); - besuPluginContext.addService(PrivacyPluginService.class, new PrivacyPluginServiceImpl()); - - besuPluginContext.registerPlugins(new PluginConfiguration(pluginsPath)); - - commandLine.parseArgs(node.getConfiguration().getExtraCLIOptions().toArray(new String[0])); - - // register built-in plugins - new RocksDBPlugin().register(besuPluginContext); - return besuPluginContext; - } - @Override public void startNode(final BesuNode node) { @@ -162,8 +129,9 @@ public void startNode(final BesuNode node) { throw new UnsupportedOperationException("commands are not supported with thread runner"); } - final StorageServiceImpl storageService = new StorageServiceImpl(); - final SecurityModuleServiceImpl securityModuleService = new SecurityModuleServiceImpl(); + AcceptanceTestBesuComponent component = + DaggerThreadBesuNodeRunner_AcceptanceTestBesuComponent.create(); + final TransactionSimulationServiceImpl transactionSimulationServiceImpl = new TransactionSimulationServiceImpl(); final TransactionSelectionServiceImpl transactionSelectionServiceImpl = @@ -186,49 +154,22 @@ public void startNode(final BesuNode node) { .withMiningParameters(miningParameters); final BesuPluginContextImpl besuPluginContext = - besuPluginContextMap.computeIfAbsent( - node, - n -> - buildPluginContext( - node, - storageService, - securityModuleService, - transactionSimulationServiceImpl, - transactionSelectionServiceImpl, - transactionPoolValidatorServiceImpl, - blockchainServiceImpl, - rpcEndpointServiceImpl, - commonPluginConfiguration, - permissioningService)); + besuPluginContextMap.computeIfAbsent(node, n -> component.getBesuPluginContext()); GlobalOpenTelemetry.resetForTest(); - final ObservableMetricsSystem metricsSystem = - MetricsSystemFactory.create(node.getMetricsConfiguration()); + final ObservableMetricsSystem metricsSystem = component.getObservableMetricsSystem(); final List bootnodes = node.getConfiguration().getBootnodes().stream() .map(EnodeURLImpl::fromURI) .collect(Collectors.toList()); - final NetworkName network = node.getNetwork() == null ? NetworkName.DEV : node.getNetwork(); - final EthNetworkConfig.Builder networkConfigBuilder = - new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(network)) - .setBootNodes(bootnodes); + + final EthNetworkConfig.Builder networkConfigBuilder = component.ethNetworkConfigBuilder(); + networkConfigBuilder.setBootNodes(bootnodes); node.getConfiguration() .getGenesisConfig() .map(GenesisConfigFile::fromConfig) .ifPresent(networkConfigBuilder::setGenesisConfigFile); final EthNetworkConfig ethNetworkConfig = networkConfigBuilder.build(); - final SynchronizerConfiguration synchronizerConfiguration = - new SynchronizerConfiguration.Builder().build(); - final BesuControllerBuilder builder = - new BesuController.Builder() - .fromEthNetworkConfig(ethNetworkConfig, synchronizerConfiguration.getSyncMode()); - - final KeyValueStorageProvider storageProvider = - new KeyValueStorageProviderBuilder() - .withStorageFactory(storageService.getByName("rocksdb").get()) - .withCommonConfiguration(commonPluginConfiguration) - .withMetricsSystem(metricsSystem) - .build(); final TransactionPoolConfiguration txPoolConfig = ImmutableTransactionPoolConfiguration.builder() @@ -237,35 +178,20 @@ public void startNode(final BesuNode node) { .transactionPoolValidatorService(transactionPoolValidatorServiceImpl) .build(); + final BesuControllerBuilder builder = component.besuControllerBuilder(); + builder.isRevertReasonEnabled(node.isRevertReasonEnabled()); + builder.networkConfiguration(node.getNetworkingConfiguration()); + builder.transactionPoolConfiguration(txPoolConfig); + builder.dataDirectory(dataDir); + builder.nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir)))); + builder.privacyParameters(node.getPrivacyParameters()); final InProcessRpcConfiguration inProcessRpcConfiguration = node.inProcessRpcConfiguration(); - final int maxPeers = 25; - - builder - .synchronizerConfiguration(new SynchronizerConfiguration.Builder().build()) - .dataDirectory(node.homeDirectory()) - .miningParameters(miningParameters) - .privacyParameters(node.getPrivacyParameters()) - .nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir)))) - .metricsSystem(metricsSystem) - .transactionPoolConfiguration(txPoolConfig) - .dataStorageConfiguration(DataStorageConfiguration.DEFAULT_FOREST_CONFIG) - .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) - .clock(Clock.systemUTC()) - .isRevertReasonEnabled(node.isRevertReasonEnabled()) - .storageProvider(storageProvider) - .gasLimitCalculator(GasLimitCalculator.constant()) - .evmConfiguration(EvmConfiguration.DEFAULT) - .maxPeers(maxPeers) - .maxRemotelyInitiatedPeers(15) - .networkConfiguration(node.getNetworkingConfiguration()) - .randomPeerPriority(false); - node.getGenesisConfig() .map(GenesisConfigFile::fromConfig) .ifPresent(builder::genesisConfigFile); - final BesuController besuController = builder.build(); + final BesuController besuController = component.besuController(); initTransactionSimulationService( transactionSimulationServiceImpl, besuController, node.getApiConfiguration()); @@ -299,11 +225,10 @@ public void startNode(final BesuNode node) { .collect(Collectors.toList())) .besuPluginContext(besuPluginContext) .autoLogBloomCaching(false) - .storageProvider(storageProvider) + .storageProvider(besuController.getStorageProvider()) .rpcEndpointService(rpcEndpointServiceImpl) .inProcessRpcConfiguration(inProcessRpcConfiguration); node.engineRpcConfiguration().ifPresent(runnerBuilder::engineJsonRpcConfiguration); - besuPluginContext.beforeExternalServices(); final Runner runner = runnerBuilder.build(); @@ -396,4 +321,229 @@ public void startConsoleCapture() { public String getConsoleContents() { throw new RuntimeException("Console contents can only be captured in process execution"); } + + @Module + @SuppressWarnings("CloseableProvides") + static class BesuControllerModule { + @Provides + @Singleton + public SynchronizerConfiguration provideSynchronizationConfiguration() { + final SynchronizerConfiguration synchronizerConfiguration = + SynchronizerConfiguration.builder().build(); + return synchronizerConfiguration; + } + + @Singleton + @Provides + public BesuControllerBuilder provideBesuControllerBuilder( + final EthNetworkConfig ethNetworkConfig, + final SynchronizerConfiguration synchronizerConfiguration) { + + final BesuControllerBuilder builder = + new BesuController.Builder() + .fromEthNetworkConfig(ethNetworkConfig, synchronizerConfiguration.getSyncMode()); + return builder; + } + + @Provides + public BesuController provideBesuController( + final SynchronizerConfiguration synchronizerConfiguration, + final BesuControllerBuilder builder, + final ObservableMetricsSystem metricsSystem, + final KeyValueStorageProvider storageProvider, + final MiningParameters miningParameters) { + + builder + .synchronizerConfiguration(synchronizerConfiguration) + .metricsSystem(metricsSystem) + .dataStorageConfiguration(DataStorageConfiguration.DEFAULT_FOREST_CONFIG) + .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .clock(Clock.systemUTC()) + .storageProvider(storageProvider) + .gasLimitCalculator(GasLimitCalculator.constant()) + .evmConfiguration(EvmConfiguration.DEFAULT) + .maxPeers(25) + .maxRemotelyInitiatedPeers(15) + .miningParameters(miningParameters) + .randomPeerPriority(false) + .besuComponent(null); + return builder.build(); + } + + @Provides + @Singleton + public EthNetworkConfig.Builder provideEthNetworkConfigBuilder() { + final EthNetworkConfig.Builder networkConfigBuilder = + new EthNetworkConfig.Builder(EthNetworkConfig.getNetworkConfig(NetworkName.DEV)); + return networkConfigBuilder; + } + + @Provides + public EthNetworkConfig provideEthNetworkConfig( + final EthNetworkConfig.Builder networkConfigBuilder) { + + final EthNetworkConfig ethNetworkConfig = networkConfigBuilder.build(); + return ethNetworkConfig; + } + + @Provides + @Named("besuPluginContext") + public BesuPluginContextImpl providePluginContext( + final StorageServiceImpl storageService, + final SecurityModuleServiceImpl securityModuleService, + final TransactionSimulationServiceImpl transactionSimulationServiceImpl, + final TransactionSelectionServiceImpl transactionSelectionServiceImpl, + final TransactionPoolValidatorServiceImpl transactionPoolValidatorServiceImpl, + final BlockchainServiceImpl blockchainServiceImpl, + final RpcEndpointServiceImpl rpcEndpointServiceImpl, + final BesuConfiguration commonPluginConfiguration, + final PermissioningServiceImpl permissioningService) { + final CommandLine commandLine = new CommandLine(CommandSpec.create()); + final BesuPluginContextImpl besuPluginContext = new BesuPluginContextImpl(); + besuPluginContext.addService(StorageService.class, storageService); + besuPluginContext.addService(SecurityModuleService.class, securityModuleService); + besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine)); + besuPluginContext.addService(RpcEndpointService.class, rpcEndpointServiceImpl); + besuPluginContext.addService( + TransactionSelectionService.class, transactionSelectionServiceImpl); + besuPluginContext.addService( + TransactionPoolValidatorService.class, transactionPoolValidatorServiceImpl); + besuPluginContext.addService( + TransactionSimulationService.class, transactionSimulationServiceImpl); + besuPluginContext.addService(BlockchainService.class, blockchainServiceImpl); + besuPluginContext.addService(BesuConfiguration.class, commonPluginConfiguration); + + final Path pluginsPath; + final String pluginDir = System.getProperty("besu.plugins.dir"); + if (pluginDir == null || pluginDir.isEmpty()) { + // pluginsPath = node.homeDirectory().resolve("plugins"); + pluginsPath = commonPluginConfiguration.getDataPath().resolve("plugins"); + final File pluginsDirFile = pluginsPath.toFile(); + if (!pluginsDirFile.isDirectory()) { + pluginsDirFile.mkdirs(); + pluginsDirFile.deleteOnExit(); + } + System.setProperty("besu.plugins.dir", pluginsPath.toString()); + } else { + pluginsPath = Path.of(pluginDir); + } + + besuPluginContext.addService(BesuConfiguration.class, commonPluginConfiguration); + besuPluginContext.addService(PermissioningService.class, permissioningService); + besuPluginContext.addService(PrivacyPluginService.class, new PrivacyPluginServiceImpl()); + + besuPluginContext.registerPlugins(new PluginConfiguration(pluginsPath)); + + // register built-in plugins + new RocksDBPlugin().register(besuPluginContext); + return besuPluginContext; + } + + @Provides + public KeyValueStorageProvider provideKeyValueStorageProvider( + final BesuConfiguration commonPluginConfiguration, final MetricsSystem metricsSystem) { + + final StorageServiceImpl storageService = new StorageServiceImpl(); + storageService.registerKeyValueStorage( + new InMemoryStoragePlugin.InMemoryKeyValueStorageFactory("memory")); + final KeyValueStorageProvider storageProvider = + new KeyValueStorageProviderBuilder() + .withStorageFactory(storageService.getByName("memory").get()) + .withCommonConfiguration(commonPluginConfiguration) + .withMetricsSystem(metricsSystem) + .build(); + + return storageProvider; + } + + @Provides + public MiningParameters provideMiningParameters( + final TransactionSelectionServiceImpl transactionSelectionServiceImpl) { + final var miningParameters = + ImmutableMiningParameters.builder() + .transactionSelectionService(transactionSelectionServiceImpl) + .build(); + + return miningParameters; + } + + @Provides + Path provideDataDir() { + try { + return Files.createTempDirectory("acctest"); + } catch (final IOException e) { + throw new RuntimeException("Unable to create temporary data directory", e); + } + } + + @Provides + @Inject + BesuConfiguration provideBesuConfiguration(final Path dataDir) { + final BesuConfigurationImpl commonPluginConfiguration = new BesuConfigurationImpl(); + commonPluginConfiguration.init( + dataDir, dataDir.resolve(DATABASE_PATH), DataStorageConfiguration.DEFAULT_FOREST_CONFIG); + return commonPluginConfiguration; + } + + @Provides + TransactionPoolConfiguration provideTransactionPoolConfiguration( + final BesuNode node, + final TransactionPoolValidatorServiceImpl transactionPoolValidatorServiceImpl) { + return ImmutableTransactionPoolConfiguration.builder() + .from(node.getTransactionPoolConfiguration()) + .strictTransactionReplayProtectionEnabled(node.isStrictTxReplayProtectionEnabled()) + .transactionPoolValidatorService(transactionPoolValidatorServiceImpl) + .build(); + } + } + + @Module + static class MockBesuCommandModule { + + @Provides + BesuCommand provideBesuCommand(final AcceptanceTestBesuComponent component) { + final BesuCommand besuCommand = + new BesuCommand( + component, + RlpBlockImporter::new, + JsonBlockImporter::new, + RlpBlockExporter::new, + new RunnerBuilder(), + new BesuController.Builder(), + Optional.ofNullable(component.getBesuPluginContext()).orElse(null), + System.getenv()); + besuCommand.toCommandLine(); + return besuCommand; + } + + @Provides + @Singleton + MetricsConfiguration provideMetricsConfiguration() { + return MetricsConfiguration.builder().build(); + } + + @Provides + @Named("besuCommandLogger") + @Singleton + Logger provideBesuCommandLogger() { + return LoggerFactory.getLogger(MockBesuCommandModule.class); + } + } + + @Singleton + @Component( + modules = { + ThreadBesuNodeRunner.BesuControllerModule.class, + ThreadBesuNodeRunner.MockBesuCommandModule.class, + BonsaiCachedMerkleTrieLoaderModule.class, + MetricsSystemModule.class, + BlobCacheModule.class + }) + public interface AcceptanceTestBesuComponent extends BesuComponent { + BesuController besuController(); + + BesuControllerBuilder besuControllerBuilder(); // TODO: needing this sucks + + EthNetworkConfig.Builder ethNetworkConfigBuilder(); + } } diff --git a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java index 520cd7d5741..d54bf908726 100644 --- a/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java +++ b/acceptance-tests/dsl/src/main/java/org/hyperledger/besu/tests/acceptance/dsl/privacy/PrivacyNode.java @@ -276,7 +276,7 @@ private PrivacyStorageProvider createKeyValueStorageProvider( final Path dataLocation, final Path dbLocation) { final var besuConfiguration = new BesuConfigurationImpl(); besuConfiguration - .init(dataLocation, dbLocation, null) + .init(dataLocation, dbLocation, besuConfig.getDataStorageConfiguration()) .withMiningParameters(besuConfig.getMiningParameters()); return new PrivacyKeyValueStorageProviderBuilder() .withStorageFactory( diff --git a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java index 8fbd0d3d625..39cc5ad26fc 100644 --- a/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java +++ b/acceptance-tests/tests/src/test/java/org/hyperledger/besu/tests/acceptance/bootstrap/ClusterThreadNodeRunnerAcceptanceTest.java @@ -38,7 +38,7 @@ public void setUp() throws Exception { final BesuNodeRunner besuNodeRunner = new ThreadBesuNodeRunner(); noDiscoveryCluster = new Cluster(clusterConfiguration, net, besuNodeRunner); final BesuNode noDiscoveryNode = besu.createNodeWithNoDiscovery("noDiscovery"); - fullNode = besu.createArchiveNode("node2"); + fullNode = besu.createArchiveNode("archive"); noDiscoveryCluster.start(noDiscoveryNode, fullNode); } diff --git a/besu/build.gradle b/besu/build.gradle index 286ca7a30fc..7eef4a216c2 100644 --- a/besu/build.gradle +++ b/besu/build.gradle @@ -104,6 +104,8 @@ dependencies { testImplementation 'org.mockito:mockito-core' testImplementation 'org.testcontainers:testcontainers' testImplementation 'tech.pegasys.discovery:discovery' + testImplementation 'com.google.dagger:dagger' annotationProcessor 'com.google.dagger:dagger-compiler' + testAnnotationProcessor 'com.google.dagger:dagger-compiler' } diff --git a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java index ddb75fcdedc..6bb3fb117c1 100644 --- a/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/controller/BesuControllerBuilder.java @@ -552,6 +552,7 @@ public BesuController build() { checkNotNull(evmConfiguration, "Missing evm config"); checkNotNull(networkingConfiguration, "Missing network configuration"); checkNotNull(dataStorageConfiguration, "Missing data storage configuration"); + prepForBuild(); final ProtocolSchedule protocolSchedule = createProtocolSchedule(); diff --git a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java index 1f014ee0610..f10ebcce474 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/BlockchainServiceImpl.java @@ -34,6 +34,7 @@ import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Collectors; +import javax.inject.Inject; /** The Blockchain service implementation. */ @Unstable @@ -44,6 +45,7 @@ public class BlockchainServiceImpl implements BlockchainService { private MutableBlockchain blockchain; /** Instantiates a new Blockchain service implementation. */ + @Inject public BlockchainServiceImpl() {} /** diff --git a/besu/src/main/java/org/hyperledger/besu/services/PermissioningServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/PermissioningServiceImpl.java index eda202f6d4d..e43bf1c054e 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/PermissioningServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/PermissioningServiceImpl.java @@ -19,6 +19,7 @@ import org.hyperledger.besu.plugin.services.permissioning.NodeMessagePermissioningProvider; import java.util.List; +import javax.inject.Inject; import com.google.common.collect.Lists; @@ -29,6 +30,7 @@ public class PermissioningServiceImpl implements PermissioningService { Lists.newArrayList(); /** Default Constructor. */ + @Inject public PermissioningServiceImpl() {} @Override diff --git a/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java index dcfe29146e7..5d7df73b2ef 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/RpcEndpointServiceImpl.java @@ -36,6 +36,7 @@ import java.util.NoSuchElementException; import java.util.function.Function; import java.util.stream.Collectors; +import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,6 +49,7 @@ public class RpcEndpointServiceImpl implements RpcEndpointService { private Map inProcessRpcMethods; /** Default Constructor. */ + @Inject public RpcEndpointServiceImpl() {} /** diff --git a/besu/src/main/java/org/hyperledger/besu/services/SecurityModuleServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/SecurityModuleServiceImpl.java index c3905c304bc..5605fe49b5f 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/SecurityModuleServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/SecurityModuleServiceImpl.java @@ -21,15 +21,18 @@ import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; +import javax.inject.Inject; /** The Security module service implementation. */ public class SecurityModuleServiceImpl implements SecurityModuleService { - private final Map> securityModuleSuppliers = - new ConcurrentHashMap<>(); /** Default Constructor. */ + @Inject public SecurityModuleServiceImpl() {} + private final Map> securityModuleSuppliers = + new ConcurrentHashMap<>(); + @Override public void register(final String name, final Supplier securityModuleSupplier) { securityModuleSuppliers.put(name, securityModuleSupplier); diff --git a/besu/src/main/java/org/hyperledger/besu/services/StorageServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/StorageServiceImpl.java index 6629da690e8..dd5d822ccc3 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/StorageServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/StorageServiceImpl.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import javax.inject.Inject; /** The Storage service implementation. */ public class StorageServiceImpl implements StorageService { @@ -31,6 +32,7 @@ public class StorageServiceImpl implements StorageService { private final Map factories; /** Instantiates a new Storage service. */ + @Inject public StorageServiceImpl() { this.segments = List.of(KeyValueSegmentIdentifier.values()); this.factories = new ConcurrentHashMap<>(); diff --git a/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolValidatorServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolValidatorServiceImpl.java index 1e1f94fb324..46af0a6ea54 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolValidatorServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/TransactionPoolValidatorServiceImpl.java @@ -19,15 +19,17 @@ import org.hyperledger.besu.plugin.services.txvalidator.PluginTransactionPoolValidatorFactory; import java.util.Optional; +import javax.inject.Inject; /** The Transaction pool validator service implementation. */ public class TransactionPoolValidatorServiceImpl implements TransactionPoolValidatorService { - private Optional factory = Optional.empty(); - /** Default Constructor. */ + @Inject public TransactionPoolValidatorServiceImpl() {} + private Optional factory = Optional.empty(); + @Override public PluginTransactionPoolValidator createTransactionValidator() { return factory diff --git a/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java index 8595a3c030b..c7049c9aa0a 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/TransactionSelectionServiceImpl.java @@ -19,15 +19,17 @@ import org.hyperledger.besu.plugin.services.txselection.PluginTransactionSelectorFactory; import java.util.Optional; +import javax.inject.Inject; /** The Transaction Selection service implementation. */ public class TransactionSelectionServiceImpl implements TransactionSelectionService { - private Optional factory = Optional.empty(); - /** Default Constructor. */ + @Inject public TransactionSelectionServiceImpl() {} + private Optional factory = Optional.empty(); + @Override public PluginTransactionSelector createPluginTransactionSelector() { return factory diff --git a/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java b/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java index 54cce205a36..8ec00e81703 100644 --- a/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java +++ b/besu/src/main/java/org/hyperledger/besu/services/TransactionSimulationServiceImpl.java @@ -30,6 +30,7 @@ import org.hyperledger.besu.plugin.services.TransactionSimulationService; import java.util.Optional; +import javax.inject.Inject; /** TransactionSimulationServiceImpl */ @Unstable @@ -43,6 +44,7 @@ public class TransactionSimulationServiceImpl implements TransactionSimulationSe private TransactionSimulator transactionSimulator; /** Create an instance to be configured */ + @Inject public TransactionSimulationServiceImpl() {} /** diff --git a/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java new file mode 100644 index 00000000000..a246d18d2ff --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/FlexGroupPrivacyTest.java @@ -0,0 +1,168 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY; + +import org.hyperledger.besu.components.BesuComponent; +import org.hyperledger.besu.components.BesuPluginContextModule; +import org.hyperledger.besu.components.MockBesuCommandModule; +import org.hyperledger.besu.components.NoOpMetricsSystemModule; +import org.hyperledger.besu.components.PrivacyTestModule; +import org.hyperledger.besu.config.GenesisConfigFile; +import org.hyperledger.besu.controller.BesuController; +import org.hyperledger.besu.cryptoservices.NodeKeyUtils; +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.enclave.EnclaveFactory; +import org.hyperledger.besu.ethereum.GasLimitCalculator; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; +import org.hyperledger.besu.ethereum.core.InMemoryKeyValueStorageProvider; +import org.hyperledger.besu.ethereum.core.MiningParameters; +import org.hyperledger.besu.ethereum.core.PrivacyParameters; +import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; +import org.hyperledger.besu.ethereum.eth.sync.SyncMode; +import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule; +import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; +import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; +import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider; +import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoaderModule; +import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; +import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.evm.precompile.PrecompiledContract; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.testutil.TestClock; + +import java.math.BigInteger; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Path; +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Component; +import dagger.Module; +import dagger.Provides; +import io.vertx.core.Vertx; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +class FlexGroupPrivacyTest { + + private final Vertx vertx = Vertx.vertx(); + + @AfterEach + public void cleanUp() { + vertx.close(); + } + + @Test + void flexibleEnabledPrivacy() { + final BesuController besuController = + DaggerFlexGroupPrivacyTest_FlexGroupPrivacyTestComponent.builder() + .build() + .getBesuController(); + + final PrecompiledContract flexiblePrecompiledContract = + getPrecompile(besuController, FLEXIBLE_PRIVACY); + + assertThat(flexiblePrecompiledContract.getName()).isEqualTo("FlexiblePrivacy"); + } + + private PrecompiledContract getPrecompile( + final BesuController besuController, final Address defaultPrivacy) { + return besuController + .getProtocolSchedule() + .getByBlockHeader(blockHeader(0)) + .getPrecompileContractRegistry() + .get(defaultPrivacy); + } + + private BlockHeader blockHeader(final long number) { + return new BlockHeaderTestFixture().number(number).buildHeader(); + } + + @Singleton + @Component( + modules = { + FlexGroupPrivacyParametersModule.class, + FlexGroupPrivacyTest.PrivacyTestBesuControllerModule.class, + PrivacyTestModule.class, + MockBesuCommandModule.class, + BonsaiCachedMerkleTrieLoaderModule.class, + NoOpMetricsSystemModule.class, + BesuPluginContextModule.class, + BlobCacheModule.class + }) + interface FlexGroupPrivacyTestComponent extends BesuComponent { + BesuController getBesuController(); + } + + @Module + static class FlexGroupPrivacyParametersModule { + + @Provides + PrivacyParameters providePrivacyParameters( + final PrivacyStorageProvider storageProvider, final Vertx vertx) { + try { + return new PrivacyParameters.Builder() + .setEnabled(true) + .setEnclaveUrl(new URI("http://127.0.0.1:8000")) + .setStorageProvider(storageProvider) + .setEnclaveFactory(new EnclaveFactory(vertx)) + .setFlexiblePrivacyGroupsEnabled(true) + .build(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + } + + @Module + static class PrivacyTestBesuControllerModule { + + @Provides + @Singleton + @SuppressWarnings("CloseableProvides") + BesuController provideBesuController( + final PrivacyParameters privacyParameters, + final DataStorageConfiguration dataStorageConfiguration, + final FlexGroupPrivacyTestComponent context, + @Named("dataDir") final Path dataDir) { + + return new BesuController.Builder() + .fromGenesisFile(GenesisConfigFile.mainnet(), SyncMode.FULL) + .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) + .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .storageProvider(new InMemoryKeyValueStorageProvider()) + .networkId(BigInteger.ONE) + .miningParameters(MiningParameters.newDefault()) + .dataStorageConfiguration(dataStorageConfiguration) + .nodeKey(NodeKeyUtils.generate()) + .metricsSystem(new NoOpMetricsSystem()) + .dataDirectory(dataDir) + .clock(TestClock.fixed()) + .privacyParameters(privacyParameters) + .transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT) + .gasLimitCalculator(GasLimitCalculator.constant()) + .evmConfiguration(EvmConfiguration.DEFAULT) + .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(context) + .build(); + } + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java index ceb0be40fe6..6298b70a953 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyReorgTest.java @@ -21,6 +21,12 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.hyperledger.besu.components.BesuComponent; +import org.hyperledger.besu.components.BesuPluginContextModule; +import org.hyperledger.besu.components.EnclaveModule; +import org.hyperledger.besu.components.MockBesuCommandModule; +import org.hyperledger.besu.components.NoOpMetricsSystemModule; +import org.hyperledger.besu.components.PrivacyTestModule; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.crypto.KeyPair; @@ -47,7 +53,9 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; +import org.hyperledger.besu.ethereum.mainnet.BlockImportResult; import org.hyperledger.besu.ethereum.mainnet.HeaderValidationMode; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; import org.hyperledger.besu.ethereum.privacy.PrivateStateRootResolver; @@ -56,6 +64,7 @@ import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider; import org.hyperledger.besu.ethereum.privacy.storage.PrivateStateStorage; import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoaderModule; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.log.LogsBloomFilter; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; @@ -70,19 +79,21 @@ import java.util.Collections; import java.util.Optional; import java.util.function.Supplier; +import javax.inject.Named; +import javax.inject.Singleton; import com.google.common.base.Suppliers; +import dagger.Component; +import dagger.Module; +import dagger.Provides; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; @SuppressWarnings("rawtypes") public class PrivacyReorgTest { - @TempDir private Path folder; - private static final Supplier SIGNATURE_ALGORITHM = Suppliers.memoize(SignatureAlgorithmFactory::getInstance); @@ -130,11 +141,15 @@ public class PrivacyReorgTest { .signAndBuild(KEY_PAIR); private final BlockDataGenerator gen = new BlockDataGenerator(); - private BesuController besuController; - private PrivateStateRootResolver privateStateRootResolver; private PrivacyParameters privacyParameters; private Enclave mockEnclave; private Transaction privacyMarkerTransaction; + private final PrivacyReorgTestComponent component = + DaggerPrivacyReorgTest_PrivacyReorgTestComponent.create(); + + private final BesuController besuController = component.getBesuController(); + private final PrivateStateRootResolver privateStateRootResolver = + component.getPrivacyParameters().getPrivateStateRootResolver(); @BeforeEach public void setUp() throws IOException { @@ -174,29 +189,6 @@ public void setUp() throws IOException { .build(); privacyParameters.setPrivacyUserId(ENCLAVE_PUBLIC_KEY.toBase64String()); - - privateStateRootResolver = - new PrivateStateRootResolver(privacyParameters.getPrivateStateStorage()); - - besuController = - new BesuController.Builder() - .fromGenesisFile( - GenesisConfigFile.fromResource("/privacy_reorg_genesis.json"), SyncMode.FULL) - .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) - .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) - .storageProvider(new InMemoryKeyValueStorageProvider()) - .networkId(BigInteger.ONE) - .miningParameters(MiningParameters.newDefault()) - .nodeKey(NodeKeyUtils.generate()) - .metricsSystem(new NoOpMetricsSystem()) - .dataDirectory(folder) - .clock(TestClock.fixed()) - .privacyParameters(privacyParameters) - .transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT) - .gasLimitCalculator(GasLimitCalculator.constant()) - .evmConfiguration(EvmConfiguration.DEFAULT) - .networkConfiguration(NetworkingConfiguration.create()) - .build(); } @Test @@ -204,7 +196,8 @@ public void privacyGroupHeadIsTracked() { // Setup an initial blockchain with one private transaction final ProtocolContext protocolContext = besuController.getProtocolContext(); final DefaultBlockchain blockchain = (DefaultBlockchain) protocolContext.getBlockchain(); - final PrivateStateStorage privateStateStorage = privacyParameters.getPrivateStateStorage(); + final PrivateStateStorage privateStateStorage = + component.getPrivacyParameters().getPrivateStateStorage(); final Block firstBlock = gen.block( @@ -244,7 +237,7 @@ public void reorgToChainAtEqualHeight() { // Setup an initial blockchain with one private transaction final ProtocolContext protocolContext = besuController.getProtocolContext(); final DefaultBlockchain blockchain = (DefaultBlockchain) protocolContext.getBlockchain(); - + assertThat(blockchain.getChainHeadBlockNumber()).isEqualTo(0); final Block firstBlock = gen.block( getBlockOptionsWithTransaction( @@ -252,8 +245,9 @@ public void reorgToChainAtEqualHeight() { privacyMarkerTransaction, FIRST_BLOCK_WITH_SINGLE_TRANSACTION_STATE_ROOT)); - appendBlock(besuController, blockchain, protocolContext, firstBlock); - + var importResult = appendBlock(besuController, blockchain, protocolContext, firstBlock); + assertThat(importResult.isImported()).isTrue(); + assertThat(blockchain.getChainHeadBlockNumber()).isEqualTo(1); // Check that the private state root is not the empty state assertPrivateStateRoot( privateStateRootResolver, blockchain, STATE_ROOT_AFTER_TRANSACTION_APPENDED_TO_EMPTY_STATE); @@ -394,12 +388,12 @@ public void reorgToLongerChain() { } @SuppressWarnings("unchecked") - private void appendBlock( + private BlockImportResult appendBlock( final BesuController besuController, final DefaultBlockchain blockchain, final ProtocolContext protocolContext, final Block block) { - besuController + return besuController .getProtocolSchedule() .getByBlockHeader(blockchain.getChainHeadHeader()) .getBlockImporter() @@ -487,4 +481,93 @@ private BlockDataGenerator.BlockOptions getBlockOptions( .hasOmmers(false) .setLogsBloom(LogsBloomFilter.empty()); } + + @Singleton + @Component( + modules = { + PrivacyReorgTest.PrivacyReorgParametersModule.class, + PrivacyReorgTest.PrivacyReorgTestBesuControllerModule.class, + PrivacyReorgTest.PrivacyReorgTestGenesisConfigModule.class, + EnclaveModule.class, + PrivacyTestModule.class, + MockBesuCommandModule.class, + NoOpMetricsSystemModule.class, + BonsaiCachedMerkleTrieLoaderModule.class, + BlobCacheModule.class, + BesuPluginContextModule.class + }) + interface PrivacyReorgTestComponent extends BesuComponent { + + BesuController getBesuController(); + + PrivacyParameters getPrivacyParameters(); + } + + @Module + static class PrivacyReorgParametersModule { + + // TODO: copypasta, get this from the enclave factory + private static final Bytes ENCLAVE_PUBLIC_KEY = + Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="); + + @Provides + PrivacyParameters providePrivacyReorgParameters( + final PrivacyStorageProvider storageProvider, final EnclaveFactory enclaveFactory) { + + PrivacyParameters retval = + new PrivacyParameters.Builder() + .setEnabled(true) + .setStorageProvider(storageProvider) + .setEnclaveUrl(URI.create("http//1.1.1.1:1234")) + .setEnclaveFactory(enclaveFactory) + .build(); + retval.setPrivacyUserId(ENCLAVE_PUBLIC_KEY.toBase64String()); + return retval; + } + } + + @Module + static class PrivacyReorgTestBesuControllerModule { + + @Provides + @Singleton + @SuppressWarnings("CloseableProvides") + BesuController provideBesuController( + final PrivacyParameters privacyParameters, + final GenesisConfigFile genesisConfigFile, + final PrivacyReorgTestComponent context, + final @Named("dataDir") Path dataDir) { + + // dataStorageConfiguration default + // named privacyReorgParams + BesuController retval = + new BesuController.Builder() + .fromGenesisFile(genesisConfigFile, SyncMode.FULL) + .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) + .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .storageProvider(new InMemoryKeyValueStorageProvider()) + .networkId(BigInteger.ONE) + .miningParameters(MiningParameters.newDefault()) + .nodeKey(NodeKeyUtils.generate()) + .metricsSystem(new NoOpMetricsSystem()) + .dataDirectory(dataDir) + .clock(TestClock.fixed()) + .privacyParameters(privacyParameters) + .transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT) + .gasLimitCalculator(GasLimitCalculator.constant()) + .evmConfiguration(EvmConfiguration.DEFAULT) + .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(context) + .build(); + return retval; + } + } + + @Module + static class PrivacyReorgTestGenesisConfigModule { + @Provides + GenesisConfigFile providePrivacyReorgGenesisConfigFile() { + return GenesisConfigFile.fromResource("/privacy_reorg_genesis.json"); + } + } } diff --git a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java index dc5b7003c84..4d488ced3bc 100644 --- a/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java +++ b/besu/src/test/java/org/hyperledger/besu/PrivacyTest.java @@ -1,5 +1,5 @@ /* - * Copyright ConsenSys AG. + * Copyright contributors to Hyperledger Besu. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at @@ -16,18 +16,17 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.hyperledger.besu.ethereum.core.PrivacyParameters.DEFAULT_PRIVACY; -import static org.hyperledger.besu.ethereum.core.PrivacyParameters.FLEXIBLE_PRIVACY; -import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_BACKGROUND_THREAD_COUNT; -import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_CACHE_CAPACITY; -import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_IS_HIGH_SPEC; -import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_MAX_OPEN_FILES; - -import org.hyperledger.besu.cli.config.EthNetworkConfig; -import org.hyperledger.besu.cli.config.NetworkName; + +import org.hyperledger.besu.components.BesuComponent; +import org.hyperledger.besu.components.BesuPluginContextModule; +import org.hyperledger.besu.components.MockBesuCommandModule; +import org.hyperledger.besu.components.NoOpMetricsSystemModule; +import org.hyperledger.besu.components.PrivacyParametersModule; +import org.hyperledger.besu.components.PrivacyTestModule; +import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.datatypes.Address; -import org.hyperledger.besu.enclave.EnclaveFactory; import org.hyperledger.besu.ethereum.GasLimitCalculator; import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.BlockHeaderTestFixture; @@ -37,126 +36,47 @@ import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration; import org.hyperledger.besu.ethereum.eth.sync.SyncMode; import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration; +import org.hyperledger.besu.ethereum.eth.transactions.BlobCacheModule; import org.hyperledger.besu.ethereum.eth.transactions.TransactionPoolConfiguration; import org.hyperledger.besu.ethereum.p2p.config.NetworkingConfiguration; -import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider; -import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder; -import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; +import org.hyperledger.besu.ethereum.trie.diffbased.bonsai.cache.BonsaiCachedMerkleTrieLoaderModule; import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.precompile.PrecompiledContract; import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValuePrivacyStorageFactory; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory; -import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; -import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration; -import org.hyperledger.besu.services.BesuConfigurationImpl; import org.hyperledger.besu.testutil.TestClock; -import java.io.IOException; import java.math.BigInteger; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; +import javax.inject.Named; +import javax.inject.Singleton; +import dagger.Component; +import dagger.Module; +import dagger.Provides; import io.vertx.core.Vertx; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; -public class PrivacyTest { +class PrivacyTest { private final Vertx vertx = Vertx.vertx(); - @TempDir private Path dataDir; - @AfterEach public void cleanUp() { vertx.close(); } @Test - public void defaultPrivacy() throws IOException, URISyntaxException { - final BesuController besuController = setUpControllerWithPrivacyEnabled(false); + void defaultPrivacy() { + final BesuController besuController = + DaggerPrivacyTest_PrivacyTestComponent.builder().build().getBesuController(); final PrecompiledContract precompiledContract = getPrecompile(besuController, DEFAULT_PRIVACY); assertThat(precompiledContract.getName()).isEqualTo("Privacy"); } - @Test - public void flexibleEnabledPrivacy() throws IOException, URISyntaxException { - final BesuController besuController = setUpControllerWithPrivacyEnabled(true); - - final PrecompiledContract flexiblePrecompiledContract = - getPrecompile(besuController, FLEXIBLE_PRIVACY); - - assertThat(flexiblePrecompiledContract.getName()).isEqualTo("FlexiblePrivacy"); - } - - private BesuController setUpControllerWithPrivacyEnabled(final boolean flexibleEnabled) - throws IOException, URISyntaxException { - final Path dbDir = Files.createTempDirectory(dataDir, "database"); - final var miningParameters = MiningParameters.newDefault(); - final var dataStorageConfiguration = DataStorageConfiguration.DEFAULT_FOREST_CONFIG; - final PrivacyParameters privacyParameters = - new PrivacyParameters.Builder() - .setEnabled(true) - .setEnclaveUrl(new URI("http://127.0.0.1:8000")) - .setStorageProvider( - createKeyValueStorageProvider( - dataDir, dbDir, dataStorageConfiguration, miningParameters)) - .setEnclaveFactory(new EnclaveFactory(vertx)) - .setFlexiblePrivacyGroupsEnabled(flexibleEnabled) - .build(); - return new BesuController.Builder() - .fromEthNetworkConfig(EthNetworkConfig.getNetworkConfig(NetworkName.MAINNET), SyncMode.FULL) - .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) - .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) - .storageProvider(new InMemoryKeyValueStorageProvider()) - .networkId(BigInteger.ONE) - .miningParameters(miningParameters) - .dataStorageConfiguration(dataStorageConfiguration) - .nodeKey(NodeKeyUtils.generate()) - .metricsSystem(new NoOpMetricsSystem()) - .dataDirectory(dataDir) - .clock(TestClock.fixed()) - .privacyParameters(privacyParameters) - .transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT) - .gasLimitCalculator(GasLimitCalculator.constant()) - .evmConfiguration(EvmConfiguration.DEFAULT) - .networkConfiguration(NetworkingConfiguration.create()) - .build(); - } - - private PrivacyStorageProvider createKeyValueStorageProvider( - final Path dataDir, - final Path dbDir, - final DataStorageConfiguration dataStorageConfiguration, - final MiningParameters miningParameters) { - final var besuConfiguration = new BesuConfigurationImpl(); - besuConfiguration - .init(dataDir, dbDir, dataStorageConfiguration) - .withMiningParameters(miningParameters); - return new PrivacyKeyValueStorageProviderBuilder() - .withStorageFactory( - new RocksDBKeyValuePrivacyStorageFactory( - new RocksDBKeyValueStorageFactory( - () -> - new RocksDBFactoryConfiguration( - DEFAULT_MAX_OPEN_FILES, - DEFAULT_BACKGROUND_THREAD_COUNT, - DEFAULT_CACHE_CAPACITY, - DEFAULT_IS_HIGH_SPEC), - Arrays.asList(KeyValueSegmentIdentifier.values()), - RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS))) - .withCommonConfiguration(besuConfiguration) - .withMetricsSystem(new NoOpMetricsSystem()) - .build(); - } - private PrecompiledContract getPrecompile( final BesuController besuController, final Address defaultPrivacy) { return besuController @@ -169,4 +89,55 @@ private PrecompiledContract getPrecompile( private BlockHeader blockHeader(final long number) { return new BlockHeaderTestFixture().number(number).buildHeader(); } + + @Singleton + @Component( + modules = { + PrivacyParametersModule.class, + PrivacyTest.PrivacyTestBesuControllerModule.class, + PrivacyTestModule.class, + MockBesuCommandModule.class, + BonsaiCachedMerkleTrieLoaderModule.class, + NoOpMetricsSystemModule.class, + BesuPluginContextModule.class, + BlobCacheModule.class + }) + interface PrivacyTestComponent extends BesuComponent { + + BesuController getBesuController(); + } + + @Module + static class PrivacyTestBesuControllerModule { + + @Provides + @Singleton + @SuppressWarnings("CloseableProvides") + BesuController provideBesuController( + final PrivacyParameters privacyParameters, + final DataStorageConfiguration dataStorageConfiguration, + final PrivacyTestComponent context, + @Named("dataDir") final Path dataDir) { + + return new BesuController.Builder() + .fromGenesisFile(GenesisConfigFile.mainnet(), SyncMode.FULL) + .synchronizerConfiguration(SynchronizerConfiguration.builder().build()) + .ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig()) + .storageProvider(new InMemoryKeyValueStorageProvider()) + .networkId(BigInteger.ONE) + .miningParameters(MiningParameters.newDefault()) + .dataStorageConfiguration(dataStorageConfiguration) + .nodeKey(NodeKeyUtils.generate()) + .metricsSystem(new NoOpMetricsSystem()) + .dataDirectory(dataDir) + .clock(TestClock.fixed()) + .privacyParameters(privacyParameters) + .transactionPoolConfiguration(TransactionPoolConfiguration.DEFAULT) + .gasLimitCalculator(GasLimitCalculator.constant()) + .evmConfiguration(EvmConfiguration.DEFAULT) + .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(context) + .build(); + } + } } diff --git a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java index 5b2a56078f5..5fefc7ef224 100644 --- a/besu/src/test/java/org/hyperledger/besu/RunnerTest.java +++ b/besu/src/test/java/org/hyperledger/besu/RunnerTest.java @@ -22,8 +22,10 @@ import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_CACHE_CAPACITY; import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_IS_HIGH_SPEC; import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_MAX_OPEN_FILES; +import static org.mockito.Mockito.mock; import org.hyperledger.besu.cli.config.EthNetworkConfig; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.config.MergeConfigOptions; @@ -483,6 +485,7 @@ private BesuController getController( .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) .randomPeerPriority(Boolean.FALSE) + .besuComponent(mock(BesuComponent.class)) .maxPeers(25) .maxRemotelyInitiatedPeers(15) .build(); diff --git a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java index 05057f15c83..bbc7dea1abb 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainexport/RlpBlockExporterTest.java @@ -16,10 +16,12 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; import org.hyperledger.besu.chainimport.RlpBlockImporter; import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; import org.hyperledger.besu.ethereum.GasLimitCalculator; @@ -102,6 +104,7 @@ private static BesuController createController(final @TempDir Path dataDir) thro .gasLimitCalculator(GasLimitCalculator.constant()) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(mock(BesuComponent.class)) .build(); } diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java index 73015afd005..7b1a4bc7d2c 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/JsonBlockImporterTest.java @@ -17,7 +17,9 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.JsonUtil; import org.hyperledger.besu.controller.BesuController; @@ -463,6 +465,7 @@ protected BesuController createController(final GenesisConfigFile genesisConfigF .gasLimitCalculator(GasLimitCalculator.constant()) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(mock(BesuComponent.class)) .build(); } } diff --git a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java index e37b8a5fd08..7d4fabb2225 100644 --- a/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java +++ b/besu/src/test/java/org/hyperledger/besu/chainimport/RlpBlockImporterTest.java @@ -16,9 +16,11 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; import org.hyperledger.besu.cli.config.EthNetworkConfig; import org.hyperledger.besu.cli.config.NetworkName; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.MergeConfigOptions; import org.hyperledger.besu.controller.BesuController; import org.hyperledger.besu.cryptoservices.NodeKeyUtils; @@ -77,6 +79,7 @@ public void blockImport() throws IOException { .gasLimitCalculator(GasLimitCalculator.constant()) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(mock(BesuComponent.class)) .build(); final RlpBlockImporter.ImportResult result = rlpBlockImporter.importBlockchain(source, targetController, false); @@ -110,6 +113,7 @@ public void blockImportRejectsBadPow() throws IOException { .gasLimitCalculator(GasLimitCalculator.constant()) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(mock(BesuComponent.class)) .build(); assertThatThrownBy( @@ -140,6 +144,7 @@ public void blockImportCanSkipPow() throws IOException { .gasLimitCalculator(GasLimitCalculator.constant()) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(mock(BesuComponent.class)) .build(); final RlpBlockImporter.ImportResult result = diff --git a/besu/src/test/java/org/hyperledger/besu/components/EnclaveModule.java b/besu/src/test/java/org/hyperledger/besu/components/EnclaveModule.java new file mode 100644 index 00000000000..20f9c1bf497 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/components/EnclaveModule.java @@ -0,0 +1,98 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.components; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.crypto.KeyPair; +import org.hyperledger.besu.crypto.SignatureAlgorithm; +import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.enclave.Enclave; +import org.hyperledger.besu.enclave.EnclaveFactory; +import org.hyperledger.besu.enclave.types.ReceiveResponse; +import org.hyperledger.besu.ethereum.privacy.PrivateTransaction; +import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput; +import org.hyperledger.besu.plugin.data.Restriction; + +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.function.Supplier; + +import com.google.common.base.Suppliers; +import dagger.Module; +import dagger.Provides; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; + +@Module +public class EnclaveModule { + + private static final Supplier SIGNATURE_ALGORITHM = + Suppliers.memoize(SignatureAlgorithmFactory::getInstance); + + private static final Bytes ENCLAVE_PUBLIC_KEY = + Bytes.fromBase64String("A1aVtMxLCUHmBVHXoZzzBgPbW/wj5axDpW9X8l91SGo="); + + private static final Bytes32 PRIVACY_GROUP_BYTES32 = + Bytes32.fromHexString("0xf250d523ae9164722b06ca25cfa2a7f3c45df96b09e215236f886c876f715bfa"); + + private static final Bytes MOCK_PAYLOAD = + Bytes.fromHexString( + "0x608060405234801561001057600080fd5b5060008054600160a060020a03191633179055610199806100326000396000f3fe6080604052600436106100565763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416633fa4f245811461005b5780636057361d1461008257806367e404ce146100ae575b600080fd5b34801561006757600080fd5b506100706100ec565b60408051918252519081900360200190f35b34801561008e57600080fd5b506100ac600480360360208110156100a557600080fd5b50356100f2565b005b3480156100ba57600080fd5b506100c3610151565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60025490565b604080513381526020810183905281517fc9db20adedc6cf2b5d25252b101ab03e124902a73fcb12b753f3d1aaa2d8f9f5929181900390910190a16002556001805473ffffffffffffffffffffffffffffffffffffffff191633179055565b60015473ffffffffffffffffffffffffffffffffffffffff169056fea165627a7a72305820c7f729cb24e05c221f5aa913700793994656f233fe2ce3b9fd9a505ea17e8d8a0029"); + + private static final KeyPair KEY_PAIR = + SIGNATURE_ALGORITHM + .get() + .createKeyPair( + SIGNATURE_ALGORITHM + .get() + .createPrivateKey( + new BigInteger( + "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63", 16))); + + private static final PrivateTransaction PRIVATE_TRANSACTION = + PrivateTransaction.builder() + .chainId(BigInteger.valueOf(1337)) + .gasLimit(1000) + .gasPrice(Wei.ZERO) + .nonce(0) + .payload(MOCK_PAYLOAD) + .to(null) + .privateFrom(ENCLAVE_PUBLIC_KEY) + .privateFor(Collections.singletonList(ENCLAVE_PUBLIC_KEY)) + .restriction(Restriction.RESTRICTED) + .value(Wei.ZERO) + .signAndBuild(KEY_PAIR); + + @Provides + EnclaveFactory provideMockableEnclaveFactory() { + Enclave mockEnclave = mock(Enclave.class); + final BytesValueRLPOutput rlpOutput = new BytesValueRLPOutput(); + PRIVATE_TRANSACTION.writeTo(rlpOutput); + when(mockEnclave.receive(any())) + .thenReturn( + new ReceiveResponse( + rlpOutput.encoded().toBase64String().getBytes(StandardCharsets.UTF_8), + PRIVACY_GROUP_BYTES32.toBase64String(), + ENCLAVE_PUBLIC_KEY.toBase64String())); + EnclaveFactory enclaveFactory = mock(EnclaveFactory.class); + when(enclaveFactory.createVertxEnclave(any())).thenReturn(mockEnclave); + return enclaveFactory; + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java b/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java new file mode 100644 index 00000000000..ae82b8b9288 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/components/GenesisConfigModule.java @@ -0,0 +1,38 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.components; + +import org.hyperledger.besu.config.GenesisConfigFile; + +import javax.inject.Named; + +import dagger.Module; +import dagger.Provides; + +@Module +public class GenesisConfigModule { + + @Named("default") + @Provides + GenesisConfigFile provideDefaultGenesisConfigFile() { + return GenesisConfigFile.DEFAULT; + } + + @Named("mainnet") + @Provides + GenesisConfigFile provideMainnetGenesisConfigFile() { + return GenesisConfigFile.mainnet(); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/components/MockBesuCommandModule.java b/besu/src/test/java/org/hyperledger/besu/components/MockBesuCommandModule.java new file mode 100644 index 00000000000..743b4ee8de9 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/components/MockBesuCommandModule.java @@ -0,0 +1,50 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.components; + +import static org.mockito.Mockito.mock; + +import org.hyperledger.besu.cli.BesuCommand; +import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; + +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Module +public class MockBesuCommandModule { + + @Provides + BesuCommand provideBesuCommand() { + return mock(BesuCommand.class); + } + + @Provides + @Singleton + MetricsConfiguration provideMetricsConfiguration() { + return MetricsConfiguration.builder().build(); + } + + @Provides + @Named("besuCommandLogger") + @Singleton + Logger provideBesuCommandLogger() { + return LoggerFactory.getLogger(MockBesuCommandModule.class); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/components/NoOpMetricsSystemModule.java b/besu/src/test/java/org/hyperledger/besu/components/NoOpMetricsSystemModule.java new file mode 100644 index 00000000000..e7807e3d759 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/components/NoOpMetricsSystemModule.java @@ -0,0 +1,40 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.components; + +import org.hyperledger.besu.metrics.ObservableMetricsSystem; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.MetricsSystem; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class NoOpMetricsSystemModule { + + @Provides + @Singleton + MetricsSystem provideMetricsSystem() { + return new NoOpMetricsSystem(); + } + + @Provides + @Singleton + ObservableMetricsSystem provideObservableMetricsSystem() { + return new NoOpMetricsSystem(); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/components/PrivacyParametersModule.java b/besu/src/test/java/org/hyperledger/besu/components/PrivacyParametersModule.java new file mode 100644 index 00000000000..0b8fcf744ff --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/components/PrivacyParametersModule.java @@ -0,0 +1,47 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.components; + +import org.hyperledger.besu.enclave.EnclaveFactory; +import org.hyperledger.besu.ethereum.core.PrivacyParameters; +import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider; + +import java.net.URI; +import java.net.URISyntaxException; + +import dagger.Module; +import dagger.Provides; +import io.vertx.core.Vertx; + +/** Provides a general use PrivacyParameters instance for testing. */ +@Module +public class PrivacyParametersModule { + + @Provides + PrivacyParameters providePrivacyParameters( + final PrivacyStorageProvider storageProvider, final Vertx vertx) { + try { + return new PrivacyParameters.Builder() + .setEnabled(true) + .setEnclaveUrl(new URI("http://127.0.0.1:8000")) + .setStorageProvider(storageProvider) + .setEnclaveFactory(new EnclaveFactory(vertx)) + .setFlexiblePrivacyGroupsEnabled(false) + .build(); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/components/PrivacyTestModule.java b/besu/src/test/java/org/hyperledger/besu/components/PrivacyTestModule.java new file mode 100644 index 00000000000..13cafe1ab45 --- /dev/null +++ b/besu/src/test/java/org/hyperledger/besu/components/PrivacyTestModule.java @@ -0,0 +1,111 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.components; + +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_BACKGROUND_THREAD_COUNT; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_CACHE_CAPACITY; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_IS_HIGH_SPEC; +import static org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions.DEFAULT_MAX_OPEN_FILES; + +import org.hyperledger.besu.ethereum.privacy.storage.PrivacyStorageProvider; +import org.hyperledger.besu.ethereum.privacy.storage.keyvalue.PrivacyKeyValueStorageProviderBuilder; +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; +import org.hyperledger.besu.ethereum.worldstate.DataStorageConfiguration; +import org.hyperledger.besu.metrics.noop.NoOpMetricsSystem; +import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValuePrivacyStorageFactory; +import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory; +import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory; +import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBFactoryConfiguration; +import org.hyperledger.besu.services.BesuConfigurationImpl; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import javax.inject.Named; +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; +import io.vertx.core.Vertx; + +@Module +public class PrivacyTestModule { + + @Provides + @Named("dataDir") + Path provideDataDir() { + try { + return Files.createTempDirectory("PrivacyTestDatadir"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Provides + Vertx provideVertx() { + return Vertx.vertx(); + } + + @Provides + DataStorageConfiguration provideDataStorageConfiguration() { + return DataStorageConfiguration.DEFAULT_FOREST_CONFIG; + } + + @Provides + @Singleton + @Named("dbDir") + Path provideDbDir(@Named("dataDir") final Path dataDir) { + try { + final Path dbDir = Files.createTempDirectory(dataDir, "database"); + return dbDir; + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Provides + @Singleton + @Named("flexibleEnabled") + Boolean provideFlexibleEnabled() { + return true; + } + + @Provides + @Singleton + @SuppressWarnings("CloseableProvides") + PrivacyStorageProvider provideKeyValueStorageProvider( + @Named("dbDir") final Path dbDir, + final DataStorageConfiguration dataStorageConfiguration, + @Named("dataDir") final Path dataDir) { + final var besuConfiguration = new BesuConfigurationImpl(); + besuConfiguration.init(dataDir, dbDir, dataStorageConfiguration); + return new PrivacyKeyValueStorageProviderBuilder() + .withStorageFactory( + new RocksDBKeyValuePrivacyStorageFactory( + new RocksDBKeyValueStorageFactory( + () -> + new RocksDBFactoryConfiguration( + DEFAULT_MAX_OPEN_FILES, + DEFAULT_BACKGROUND_THREAD_COUNT, + DEFAULT_CACHE_CAPACITY, + DEFAULT_IS_HIGH_SPEC), + Arrays.asList(KeyValueSegmentIdentifier.values()), + RocksDBMetricsFactory.PRIVATE_ROCKS_DB_METRICS))) + .withCommonConfiguration(besuConfiguration) + .withMetricsSystem(new NoOpMetricsSystem()) + .build(); + } +} diff --git a/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java index 731fd2ac568..c7caf62ec2a 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/AbstractBftBesuControllerBuilderTest.java @@ -19,6 +19,7 @@ import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; @@ -157,6 +158,7 @@ public void setup() throws JsonProcessingException { .storageProvider(storageProvider) .gasLimitCalculator(gasLimitCalculator) .evmConfiguration(EvmConfiguration.DEFAULT) + .besuComponent(mock(BesuComponent.class)) .networkConfiguration(NetworkingConfiguration.create()); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java index 82f98ba8266..aa79b944a11 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/CliqueBesuControllerBuilderTest.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; @@ -190,6 +191,7 @@ public void setup() throws JsonProcessingException { .storageProvider(storageProvider) .gasLimitCalculator(gasLimitCalculator) .evmConfiguration(EvmConfiguration.DEFAULT) + .besuComponent(mock(BesuComponent.class)) .networkConfiguration(NetworkingConfiguration.create()); } diff --git a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java index 0e4948ddd5c..c788f417103 100644 --- a/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java +++ b/besu/src/test/java/org/hyperledger/besu/controller/MergeBesuControllerBuilderTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; +import org.hyperledger.besu.components.BesuComponent; import org.hyperledger.besu.config.CheckpointConfigOptions; import org.hyperledger.besu.config.GenesisConfigFile; import org.hyperledger.besu.config.GenesisConfigOptions; @@ -190,6 +191,7 @@ MergeBesuControllerBuilder visitWithMockConfigs(final MergeBesuControllerBuilder .storageProvider(storageProvider) .evmConfiguration(EvmConfiguration.DEFAULT) .networkConfiguration(NetworkingConfiguration.create()) + .besuComponent(mock(BesuComponent.class)) .networkId(networkId); } diff --git a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/peers/EnodeURLImpl.java b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/peers/EnodeURLImpl.java index e1d158f3fce..e087edd4312 100644 --- a/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/peers/EnodeURLImpl.java +++ b/ethereum/p2p/src/main/java/org/hyperledger/besu/ethereum/p2p/peers/EnodeURLImpl.java @@ -381,10 +381,11 @@ public Builder ipAddress(final String ip) { return ipAddress(ip, EnodeDnsConfiguration.dnsDisabled()); } - public Builder ipAddress(final String ip, final EnodeDnsConfiguration enodeDnsConfiguration) { + public Builder ipAddress( + final String hostField, final EnodeDnsConfiguration enodeDnsConfiguration) { if (enodeDnsConfiguration.dnsEnabled()) { try { - this.ip = InetAddress.getByName(ip); + this.ip = InetAddress.getByName(hostField); if (enodeDnsConfiguration.updateEnabled()) { if (this.ip.isLoopbackAddress()) { this.ip = InetAddress.getLocalHost(); @@ -398,10 +399,10 @@ public Builder ipAddress(final String ip, final EnodeDnsConfiguration enodeDnsCo this.ip = InetAddresses.forString("127.0.0.1"); } } - } else if (InetAddresses.isUriInetAddress(ip)) { - this.ip = InetAddresses.forUriString(ip); - } else if (InetAddresses.isInetAddress(ip)) { - this.ip = InetAddresses.forString(ip); + } else if (InetAddresses.isUriInetAddress(hostField)) { + this.ip = InetAddresses.forUriString(hostField); + } else if (InetAddresses.isInetAddress(hostField)) { + this.ip = InetAddresses.forString(hostField); } else { throw new IllegalArgumentException("Invalid ip address."); }