Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security Module Plugin API #713

Merged
merged 104 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
8dff540
Node Key Security Provider BouncyCastle backed internal plugin
usmansaleem Apr 14, 2020
33482d5
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 14, 2020
bf62f2c
wip
usmansaleem Apr 15, 2020
76f01f1
wip - renaming plugin name
usmansaleem Apr 15, 2020
3db6b44
refactoring package name
usmansaleem Apr 15, 2020
72b4dc9
wip
usmansaleem Apr 15, 2020
3a30a73
wip - refactor package name
usmansaleem Apr 15, 2020
d5392e7
wip
usmansaleem Apr 15, 2020
160d9df
Merge upstream/master
usmansaleem Apr 15, 2020
b934f3a
wip - clean compile
usmansaleem Apr 15, 2020
2505c3d
spotless fix
usmansaleem Apr 15, 2020
afd1124
test compilation fix
usmansaleem Apr 15, 2020
87e063f
spotless fix
usmansaleem Apr 15, 2020
977b3f0
license header
usmansaleem Apr 15, 2020
5c3e76a
spotless fix
usmansaleem Apr 15, 2020
8a69d3a
spotless fix
usmansaleem Apr 15, 2020
4d14a37
mock fix in CommandTestAbstract
usmansaleem Apr 15, 2020
e044e49
supplier memoize
usmansaleem Apr 15, 2020
4b2209a
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 15, 2020
94f2996
supplier memoize moved into BouncyCastleSecurityModule
usmansaleem Apr 15, 2020
295caef
Fixing PublicKeySubCommand and its unit tests
usmansaleem Apr 15, 2020
7bd3790
updating plugin cli option and removing unit test cases
usmansaleem Apr 15, 2020
4f08b33
Register SecurityModuleService in dsl ThreadBesuRunner
usmansaleem Apr 15, 2020
3b18e3e
refactoring threadbesunoderunner
usmansaleem Apr 15, 2020
a2187a3
variable names cleanup
usmansaleem Apr 15, 2020
c133689
cleanup
usmansaleem Apr 15, 2020
f7e796c
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 15, 2020
ee607f8
remove memoize from bcsecuritymodule
usmansaleem Apr 16, 2020
77b604d
remove nodeKey instance variable from BesuCommand
usmansaleem Apr 16, 2020
1196a41
Fixing CommandTestAbstract mocks and PublicKeySubCommandTest
usmansaleem Apr 16, 2020
cb93117
cleaning up security module name constant
usmansaleem Apr 16, 2020
aa6ead8
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 16, 2020
0774c4e
Using extended Functional interface
usmansaleem Apr 16, 2020
a7d0dfe
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 16, 2020
3630ab8
plugin api changes hash
usmansaleem Apr 16, 2020
92412c4
Ditching BouncyCastle from plugin and package name. Moving to localfile
usmansaleem Apr 16, 2020
2db11f7
exception msg
usmansaleem Apr 16, 2020
d3b1cac
unit test for Plugin
usmansaleem Apr 16, 2020
e1aea38
header
usmansaleem Apr 16, 2020
26962c6
final
usmansaleem Apr 16, 2020
bc45536
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 16, 2020
7a8fb1d
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 17, 2020
690618d
using final keyword in nodePrivateKeyFile()
usmansaleem Apr 17, 2020
570271a
Making PublicKey interface;
usmansaleem Apr 17, 2020
de52ac4
Plugin API hash
usmansaleem Apr 17, 2020
0575240
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 17, 2020
8850fe8
tidying up LocalFileSecurityModulePlugin
usmansaleem Apr 17, 2020
cce1bcb
review - converting Signature to interface
usmansaleem Apr 17, 2020
d83e47f
refactoring Signature and PublicKey in data subpackage
usmansaleem Apr 17, 2020
c5f1738
review - refactoring inner class to be top level class. Adding javadoc
usmansaleem Apr 17, 2020
3088be3
refactoring method out of SecurityModuleProvider
usmansaleem Apr 17, 2020
c28cc76
spotless fix
usmansaleem Apr 17, 2020
7341cfc
adding unstable annotation in plugin interfaces
usmansaleem Apr 17, 2020
eaf709f
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 17, 2020
1627081
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 20, 2020
6a27c66
expose buildNodeKey from BesuCommand so that PublicKeySubcommand can …
usmansaleem Apr 20, 2020
7c19a1a
Merge upstream master
usmansaleem Apr 20, 2020
25af953
use functional reference for nodekey in public key subcommand
usmansaleem Apr 20, 2020
2487f0f
unextend SecurityModuleProvider from Functional.
usmansaleem Apr 20, 2020
007b87a
SecurityModuleException
usmansaleem Apr 20, 2020
47ab014
plugin checksum
usmansaleem Apr 20, 2020
a6ae3a9
Use Runnable function reference to initialize besu configuration serv…
usmansaleem Apr 20, 2020
4943186
LocalFileSecurityModulePlugin - Use isDocker directly
usmansaleem Apr 20, 2020
fc0be7f
review - rename variable to nodeKey
usmansaleem Apr 20, 2020
0a9525a
review - javadoc
usmansaleem Apr 20, 2020
e2ff900
fix compilation issues
usmansaleem Apr 20, 2020
c643c23
use orElseGet
usmansaleem Apr 20, 2020
30c52d1
settings.gradle ordering
usmansaleem Apr 20, 2020
bb7bc22
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 20, 2020
1ad1c45
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 20, 2020
a9a42f4
Expose ECPoint from PublicKey interface'
usmansaleem Apr 21, 2020
860a411
ECPoint byte[] to BigInteger conversion padding
usmansaleem Apr 21, 2020
91c90c9
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 21, 2020
2aac744
javadoc
usmansaleem Apr 21, 2020
aa53c23
checksum
usmansaleem Apr 21, 2020
715450d
spotless fix
usmansaleem Apr 21, 2020
79b4f31
plugin checksum and final keyword
usmansaleem Apr 21, 2020
ee26e5c
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 21, 2020
4bad3f5
ECPointUtil unsigned x y
usmansaleem Apr 22, 2020
4897a0a
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 22, 2020
8b6589f
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 22, 2020
3437e7f
merge upstream master
usmansaleem Apr 22, 2020
24cccad
spotless fix
usmansaleem Apr 23, 2020
39deda8
rename method
usmansaleem Apr 23, 2020
c25d921
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 23, 2020
d9fec18
Removing internal plugin and directly instantiating KeyPairSecurityMo…
usmansaleem Apr 23, 2020
afbc588
removing internal plugin from acceptance dsl
usmansaleem Apr 23, 2020
6283c0c
javadoc
usmansaleem Apr 23, 2020
26aebd3
final keywords
usmansaleem Apr 23, 2020
eb6712a
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 23, 2020
317bc51
ECPointUtil toUnsignedByteArray cleanup and unit tests
usmansaleem Apr 24, 2020
6f675cb
cleaning up KeyPairSecurityModule
usmansaleem Apr 24, 2020
5dee1ab
typo
usmansaleem Apr 24, 2020
73df123
review suggestion - exception message in keypairsecuritymodule
usmansaleem Apr 24, 2020
5f83f01
ECPointUtil cleanup - Use BC BigIntegers.asUnsignedByteArray
usmansaleem Apr 24, 2020
3f62973
Merge upstream master
usmansaleem Apr 25, 2020
6a36b4e
review suggestions
usmansaleem Apr 27, 2020
75c5803
review suggestion - Register default SecurityModuleProvider with Secu…
usmansaleem Apr 27, 2020
b18f39b
spotless fix
usmansaleem Apr 27, 2020
b5dba6d
plugin api checksum
usmansaleem Apr 27, 2020
6322e08
Using Supplier<SecurityModule> instead of SecurityModuleSupplier
usmansaleem Apr 27, 2020
3405b17
plugin api checksum
usmansaleem Apr 27, 2020
519370c
--security-module cli option instead of --security-module-provider
usmansaleem Apr 27, 2020
a47c113
Merge remote-tracking branch 'upstream/master' into nodekey_plugin
usmansaleem Apr 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.controller.BesuControllerBuilder;
import org.hyperledger.besu.controller.GasLimitCalculator;
import org.hyperledger.besu.crypto.KeyPairSecurityModule;
import org.hyperledger.besu.crypto.KeyPairUtil;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import org.hyperledger.besu.ethereum.eth.EthProtocolConfiguration;
import org.hyperledger.besu.ethereum.eth.sync.SynchronizerConfiguration;
Expand All @@ -37,12 +39,14 @@
import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
import org.hyperledger.besu.plugin.services.SecurityModuleService;
import org.hyperledger.besu.plugin.services.StorageService;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;

import java.io.File;
Expand Down Expand Up @@ -71,10 +75,12 @@ public class ThreadBesuNodeRunner implements BesuNodeRunner {
private BesuPluginContextImpl buildPluginContext(
final BesuNode node,
final StorageServiceImpl storageService,
final SecurityModuleServiceImpl securityModuleService,
final BesuConfiguration commonPluginConfiguration) {
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));

final Path pluginsPath = node.homeDirectory().resolve("plugins");
Expand Down Expand Up @@ -105,12 +111,16 @@ public void startNode(final BesuNode node) {
ThreadContext.put("node", node.getName());

final StorageServiceImpl storageService = new StorageServiceImpl();
final SecurityModuleServiceImpl securityModuleService = new SecurityModuleServiceImpl();
final Path dataDir = node.homeDirectory();
final BesuConfiguration commonPluginConfiguration =
new BesuConfigurationImpl(dataDir, dataDir.resolve(DATABASE_PATH));
final BesuPluginContextImpl besuPluginContext =
besuPluginContextMap.computeIfAbsent(
node, n -> buildPluginContext(node, storageService, commonPluginConfiguration));
node,
n ->
buildPluginContext(
node, storageService, securityModuleService, commonPluginConfiguration));

final ObservableMetricsSystem metricsSystem =
PrometheusMetricsSystem.init(node.getMetricsConfiguration());
Expand Down Expand Up @@ -139,7 +149,7 @@ public void startNode(final BesuNode node) {
.dataDirectory(node.homeDirectory())
.miningParameters(node.getMiningParameters())
.privacyParameters(node.getPrivacyParameters())
.nodePrivateKeyFile(KeyPairUtil.getDefaultKeyFile(node.homeDirectory()))
.nodeKey(new NodeKey(new KeyPairSecurityModule(KeyPairUtil.loadKeyPair(dataDir))))
.metricsSystem(metricsSystem)
.transactionPoolConfiguration(TransactionPoolConfiguration.builder().build())
.ethProtocolConfiguration(EthProtocolConfiguration.defaultConfig())
Expand Down
68 changes: 51 additions & 17 deletions besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
import org.hyperledger.besu.cli.presynctasks.PrivateDatabaseMigrationPreSyncTask;
import org.hyperledger.besu.cli.subcommands.PasswordSubCommand;
import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand;
import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand.KeyLoader;
import org.hyperledger.besu.cli.subcommands.RetestethSubCommand;
import org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand;
import org.hyperledger.besu.cli.subcommands.blocks.BlocksSubCommand.JsonBlockImporterFactory;
Expand All @@ -66,7 +65,9 @@
import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.controller.BesuControllerBuilder;
import org.hyperledger.besu.crypto.KeyPairSecurityModule;
import org.hyperledger.besu.crypto.KeyPairUtil;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.crypto.SECP256K1;
import org.hyperledger.besu.enclave.EnclaveFactory;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
Expand Down Expand Up @@ -110,16 +111,19 @@
import org.hyperledger.besu.plugin.services.BesuEvents;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.PicoCLIOptions;
import org.hyperledger.besu.plugin.services.SecurityModuleService;
import org.hyperledger.besu.plugin.services.StorageService;
import org.hyperledger.besu.plugin.services.exception.StorageException;
import org.hyperledger.besu.plugin.services.metrics.MetricCategory;
import org.hyperledger.besu.plugin.services.metrics.MetricCategoryRegistry;
import org.hyperledger.besu.plugin.services.securitymodule.SecurityModule;
import org.hyperledger.besu.plugin.services.storage.PrivacyKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBPlugin;
import org.hyperledger.besu.services.BesuConfigurationImpl;
import org.hyperledger.besu.services.BesuEventsImpl;
import org.hyperledger.besu.services.BesuPluginContextImpl;
import org.hyperledger.besu.services.PicoCLIOptionsImpl;
import org.hyperledger.besu.services.SecurityModuleServiceImpl;
import org.hyperledger.besu.services.StorageServiceImpl;
import org.hyperledger.besu.util.NetworkUtility;
import org.hyperledger.besu.util.PermissioningConfigurationValidator;
Expand Down Expand Up @@ -201,15 +205,12 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final BesuController.Builder controllerBuilderFactory;
private final BesuPluginContextImpl besuPluginContext;
private final StorageServiceImpl storageService;
private final SecurityModuleServiceImpl securityModuleService;
private final Map<String, String> environment;
private final MetricCategoryRegistryImpl metricCategoryRegistry =
new MetricCategoryRegistryImpl();
private final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter();

protected KeyLoader getKeyLoader() {
return KeyPairUtil::loadKeyPair;
}

// Public IP stored to prevent having to research it each time we need it.
private InetAddress autoDiscoveredDefaultIP = null;

Expand Down Expand Up @@ -815,6 +816,14 @@ void setBannedNodeIds(final List<String> values) {
arity = "1")
private String keyValueStorageName = DEFAULT_KEY_VALUE_STORAGE_NAME;

@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"})
@Option(
names = {"--security-module"},
paramLabel = "<NAME>",
description = "Identity for the Security Module to be used.",
arity = "1")
private String securityModuleName = DEFAULT_SECURITY_MODULE;

@Option(
names = {"--auto-log-bloom-caching-enabled"},
description = "Enable automatic log bloom caching (default: ${DEFAULT-VALUE})",
Expand Down Expand Up @@ -900,7 +909,8 @@ public BesuCommand(
controllerBuilderFactory,
besuPluginContext,
environment,
new StorageServiceImpl());
new StorageServiceImpl(),
new SecurityModuleServiceImpl());
}

@VisibleForTesting
Expand All @@ -913,7 +923,8 @@ protected BesuCommand(
final BesuController.Builder controllerBuilderFactory,
final BesuPluginContextImpl besuPluginContext,
final Map<String, String> environment,
final StorageServiceImpl storageService) {
final StorageServiceImpl storageService,
final SecurityModuleServiceImpl securityModuleService) {
this.logger = logger;
this.rlpBlockImporter = rlpBlockImporter;
this.rlpBlockExporterFactory = rlpBlockExporterFactory;
Expand All @@ -923,6 +934,7 @@ protected BesuCommand(
this.besuPluginContext = besuPluginContext;
this.environment = environment;
this.storageService = storageService;
this.securityModuleService = securityModuleService;
}

public void parse(
Expand Down Expand Up @@ -1000,7 +1012,8 @@ private BesuCommand addSubCommands(
resultHandler.out()));
commandLine.addSubcommand(
PublicKeySubCommand.COMMAND_NAME,
new PublicKeySubCommand(resultHandler.out(), getKeyLoader()));
new PublicKeySubCommand(
resultHandler.out(), this::addConfigurationService, this::buildNodeKey));
commandLine.addSubcommand(
PasswordSubCommand.COMMAND_NAME, new PasswordSubCommand(resultHandler.out()));
commandLine.addSubcommand(RetestethSubCommand.COMMAND_NAME, new RetestethSubCommand());
Expand Down Expand Up @@ -1046,6 +1059,7 @@ private BesuCommand handleUnstableOptions() {

private BesuCommand preparePlugins() {
besuPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
besuPluginContext.addService(SecurityModuleService.class, securityModuleService);
besuPluginContext.addService(StorageService.class, storageService);
besuPluginContext.addService(MetricCategoryRegistry.class, metricCategoryRegistry);

Expand All @@ -1058,9 +1072,22 @@ private BesuCommand preparePlugins() {
.getMetricCategories()
.forEach(metricCategoryConverter::addRegistryCategory);

// register default security module
securityModuleService.register(
DEFAULT_SECURITY_MODULE, Suppliers.memoize(this::defaultSecurityModule)::get);

return this;
}

private SecurityModule defaultSecurityModule() {
return new KeyPairSecurityModule(loadKeyPair());
}

@VisibleForTesting
SECP256K1.KeyPair loadKeyPair() {
return KeyPairUtil.loadKeyPair(nodePrivateKeyFile());
}

private void parse(
final AbstractParseResultHandler<List<Object>> resultHandler,
final BesuExceptionHandler exceptionHandler,
Expand Down Expand Up @@ -1273,7 +1300,7 @@ public BesuControllerBuilder<?> getControllerBuilder() {
stratumExtranonce,
Optional.empty()))
.transactionPoolConfiguration(buildTransactionPoolConfiguration())
.nodePrivateKeyFile(nodePrivateKeyFile())
.nodeKey(buildNodeKey())
.metricsSystem(metricsSystem.get())
.privacyParameters(privacyParameters())
.clock(Clock.systemUTC())
Expand Down Expand Up @@ -1970,15 +1997,22 @@ private Path pluginsDir() {
}
}

public File nodePrivateKeyFile() {
File nodePrivateKeyFile = null;
if (isFullInstantiation()) {
nodePrivateKeyFile = standaloneCommands.nodePrivateKeyFile;
}
@VisibleForTesting
NodeKey buildNodeKey() {
return new NodeKey(securityModule());
}

private SecurityModule securityModule() {
return securityModuleService
.getByName(securityModuleName)
.orElseThrow(() -> new RuntimeException("Security Module not found: " + securityModuleName))
.get();
}

return nodePrivateKeyFile != null
? nodePrivateKeyFile
: KeyPairUtil.getDefaultKeyFile(dataDir());
private File nodePrivateKeyFile() {
final Optional<File> nodePrivateKeyFile =
isDocker ? Optional.empty() : Optional.ofNullable(standaloneCommands.nodePrivateKeyFile);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should no be any docker specific behaviour

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole file is using docker specific behavior using org/hyperledger/besu/cli/BesuCommand.java:2103

  private boolean isFullInstantiation() {
    return !isDocker;
  }

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's garbage code to be deleted. We don't provide the parameter in the docker image since 29c3c14#diff-ebacf6f6ae4ee68078bb16454b23247dL19 so this part of the code is dead since July 2019. It was discussed about removing it but it was not a priority. Now, if it's confusing, it should be a priority IMO.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I have created #785 and will clean it out in a separate PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Its a shame the docker code wasn't cleaned out before now - but the removal shouldn't be part of this work.

return nodePrivateKeyFile.orElseGet(() -> KeyPairUtil.getDefaultKeyFile(dataDir()));
}

private File privacyPublicKeyFile() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public interface DefaultCommandValues {
float DEFAULT_FRACTION_REMOTE_WIRE_CONNECTIONS_ALLOWED =
RlpxConfiguration.DEFAULT_FRACTION_REMOTE_CONNECTIONS_ALLOWED;
String DEFAULT_KEY_VALUE_STORAGE_NAME = "rocksdb";
String DEFAULT_SECURITY_MODULE = "localfile";

static Path getDefaultBesuDataPath(final Object command) {
// this property is retrieved from Gradle tasks or Besu running shell script.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import org.hyperledger.besu.cli.DefaultCommandValues;
import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand.AddressSubCommand;
import org.hyperledger.besu.cli.subcommands.PublicKeySubCommand.ExportSubCommand;
import org.hyperledger.besu.crypto.SECP256K1.KeyPair;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Util;

Expand All @@ -33,6 +33,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.Supplier;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand Down Expand Up @@ -62,25 +63,29 @@ public class PublicKeySubCommand implements Runnable {
private CommandSpec spec; // Picocli injects reference to command spec

private final PrintStream out;
private final KeyLoader keyLoader;
private final Runnable besuConfigurationService;
private final Supplier<NodeKey> nodeKey;

public PublicKeySubCommand(final PrintStream out, final KeyLoader keyLoader) {
public PublicKeySubCommand(
final PrintStream out,
final Runnable besuConfigurationService,
final Supplier<NodeKey> nodeKey) {
this.out = out;
this.keyLoader = keyLoader;
this.besuConfigurationService = besuConfigurationService;
this.nodeKey = nodeKey;
}

@Override
public void run() {
spec.commandLine().usage(out);
}

private Optional<KeyPair> getKeyPair() {
try {
return Optional.of(keyLoader.load(parentCommand.nodePrivateKeyFile()));
} catch (IOException e) {
LOG.error("An error occurred while trying to read the private key", e);
return Optional.empty();
}
private void initBesuConfigurationService() {
besuConfigurationService.run();
}

private NodeKey getNodeKey() {
return nodeKey.get();
}

/**
Expand Down Expand Up @@ -113,22 +118,24 @@ public void run() {
checkNotNull(parentCommand);
checkNotNull(parentCommand.parentCommand);

parentCommand.getKeyPair().ifPresent(this::outputPublicKey);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this change because NPE were being encountered?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mean not using getKeyPair anymore? or the usage of Optional.ofNullable?

parentCommand.initBesuConfigurationService();
final NodeKey nodeKey = parentCommand.getNodeKey();
Optional.ofNullable(nodeKey).ifPresent(this::outputPublicKey);
}

private void outputPublicKey(final KeyPair keyPair) {
private void outputPublicKey(final NodeKey nodeKey) {
// if we have an output file defined, print to it
// otherwise print to standard output.
if (publicKeyExportFile != null) {
final Path path = publicKeyExportFile.toPath();

try (final BufferedWriter fileWriter = Files.newBufferedWriter(path, UTF_8)) {
fileWriter.write(keyPair.getPublicKey().toString());
fileWriter.write(nodeKey.getPublicKey().toString());
} catch (final IOException e) {
LOG.error("An error occurred while trying to write the public key", e);
}
} else {
parentCommand.out.println(keyPair.getPublicKey().toString());
parentCommand.out.println(nodeKey.getPublicKey().toString());
}
}
}
Expand Down Expand Up @@ -165,11 +172,13 @@ public void run() {
checkNotNull(parentCommand);
checkNotNull(parentCommand.parentCommand);

parentCommand.getKeyPair().ifPresent(this::outputAddress);
parentCommand.initBesuConfigurationService();
final NodeKey nodeKey = parentCommand.getNodeKey();
Optional.ofNullable(nodeKey).ifPresent(this::outputAddress);
}

private void outputAddress(final KeyPair keyPair) {
final Address address = Util.publicKeyToAddress(keyPair.getPublicKey());
private void outputAddress(final NodeKey nodeKey) {
final Address address = Util.publicKeyToAddress(nodeKey.getPublicKey());

// if we have an output file defined, print to it
// otherwise print to standard output.
Expand All @@ -186,10 +195,4 @@ private void outputAddress(final KeyPair keyPair) {
}
}
}

@FunctionalInterface
public interface KeyLoader {

KeyPair load(final File keyFile) throws IOException;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@
package org.hyperledger.besu.controller;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.hyperledger.besu.crypto.KeyPairUtil.loadKeyPair;

import org.hyperledger.besu.config.GenesisConfigFile;
import org.hyperledger.besu.config.GenesisConfigOptions;
import org.hyperledger.besu.config.experimental.ExperimentalEIPs;
import org.hyperledger.besu.crypto.BouncyCastleSecurityModule;
import org.hyperledger.besu.crypto.NodeKey;
import org.hyperledger.besu.ethereum.ProtocolContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.methods.JsonRpcMethods;
Expand Down Expand Up @@ -61,7 +59,6 @@
import org.hyperledger.besu.metrics.ObservableMetricsSystem;

import java.io.Closeable;
import java.io.File;
import java.math.BigInteger;
import java.nio.file.Path;
import java.time.Clock;
Expand Down Expand Up @@ -129,11 +126,6 @@ public BesuControllerBuilder<C> miningParameters(final MiningParameters miningPa
return this;
}

public BesuControllerBuilder<C> nodePrivateKeyFile(final File nodePrivateKeyFile) {
this.nodeKey = new NodeKey(new BouncyCastleSecurityModule(loadKeyPair(nodePrivateKeyFile)));
return this;
}

public BesuControllerBuilder<C> nodeKey(final NodeKey nodeKey) {
this.nodeKey = nodeKey;
return this;
Expand Down
Loading