Json Blocks Import timestamp (#358)

Allows for the setting of the timestamp in JSON block importer.
Ordinarily it is now and then 1 second for each block.  The initial time
can now be set via CLI option `--start-time`, which defaults to now.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/380/head
Danno Ferrin 5 years ago committed by GitHub
parent 21dc78af61
commit a933179254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 31
      besu/src/main/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommand.java
  2. 30
      besu/src/test/java/org/hyperledger/besu/cli/subcommands/blocks/BlocksSubCommandTest.java

@ -40,6 +40,9 @@ import java.io.PrintStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.Optional; import java.util.Optional;
import io.vertx.core.Vertx; import io.vertx.core.Vertx;
@ -122,12 +125,18 @@ public class BlocksSubCommand implements Runnable {
@Option( @Option(
names = "--format", names = "--format",
hidden = true,
description = description =
"The type of data to be imported, possible values are: ${COMPLETION-CANDIDATES} (default: ${DEFAULT-VALUE}).", "The type of data to be imported, possible values are: ${COMPLETION-CANDIDATES} (default: ${DEFAULT-VALUE}).",
arity = "1..1") arity = "1..1")
private final BlockImportFormat format = BlockImportFormat.RLP; private final BlockImportFormat format = BlockImportFormat.RLP;
@Option(
names = "--start-time",
description =
"The timestamp in seconds of the first block for JSON imports. Subsequent blocks will be 1 second later. (default: current time)",
arity = "1..1")
private final Long startTime = System.currentTimeMillis() / 1000;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Spec @Spec
private CommandSpec spec; private CommandSpec spec;
@ -141,7 +150,7 @@ public class BlocksSubCommand implements Runnable {
checkNotNull(parentCommand.rlpBlockImporter); checkNotNull(parentCommand.rlpBlockImporter);
checkNotNull(parentCommand.jsonBlockImporterFactory); checkNotNull(parentCommand.jsonBlockImporterFactory);
Optional<MetricsService> metricsService = initMetrics(parentCommand); final Optional<MetricsService> metricsService = initMetrics(parentCommand);
try { try {
// As blocksImportFile even if initialized as null is injected by PicoCLI and param is // As blocksImportFile even if initialized as null is injected by PicoCLI and param is
@ -182,6 +191,8 @@ public class BlocksSubCommand implements Runnable {
return parentCommand return parentCommand
.parentCommand .parentCommand
.getControllerBuilder() .getControllerBuilder()
// set to mainnet genesis block so validation rules won't reject it.
.clock(Clock.fixed(Instant.ofEpochSecond(startTime), ZoneOffset.UTC))
.miningParameters(getMiningParameters()) .miningParameters(getMiningParameters())
.build(); .build();
} catch (final Exception e) { } catch (final Exception e) {
@ -200,7 +211,7 @@ public class BlocksSubCommand implements Runnable {
private <T> void importJsonBlocks(final BesuController<T> controller, final Path path) private <T> void importJsonBlocks(final BesuController<T> controller, final Path path)
throws IOException { throws IOException {
JsonBlockImporter<T> importer = parentCommand.jsonBlockImporterFactory.get(controller); final JsonBlockImporter<T> importer = parentCommand.jsonBlockImporterFactory.get(controller);
final String jsonData = Files.readString(path); final String jsonData = Files.readString(path);
importer.importChain(jsonData); importer.importChain(jsonData);
} }
@ -270,15 +281,13 @@ public class BlocksSubCommand implements Runnable {
final BesuController<?> controller = createBesuController(); final BesuController<?> controller = createBesuController();
try { try {
switch (format) { if (format == BlockExportFormat.RLP) {
case RLP:
exportRlpFormat(controller); exportRlpFormat(controller);
break; } else {
default:
throw new ParameterException( throw new ParameterException(
spec.commandLine(), "Unsupported format: " + format.toString()); spec.commandLine(), "Unsupported format: " + format.toString());
} }
} catch (IOException e) { } catch (final IOException e) {
throw new ExecutionException( throw new ExecutionException(
spec.commandLine(), "An error occurred while exporting blocks.", e); spec.commandLine(), "An error occurred while exporting blocks.", e);
} finally { } finally {
@ -292,7 +301,7 @@ public class BlocksSubCommand implements Runnable {
private void exportRlpFormat(final BesuController<?> controller) throws IOException { private void exportRlpFormat(final BesuController<?> controller) throws IOException {
final ProtocolContext<?> context = controller.getProtocolContext(); final ProtocolContext<?> context = controller.getProtocolContext();
RlpBlockExporter exporter = final RlpBlockExporter exporter =
parentCommand.rlpBlockExporterFactory.get(context.getBlockchain()); parentCommand.rlpBlockExporterFactory.get(context.getBlockchain());
exporter.exportBlocks(blocksExportFile, getStartBlock(), getEndBlock()); exporter.exportBlocks(blocksExportFile, getStartBlock(), getEndBlock());
} }
@ -339,11 +348,11 @@ public class BlocksSubCommand implements Runnable {
} }
// Error if data directory is empty // Error if data directory is empty
Path databasePath = final Path databasePath =
Paths.get( Paths.get(
parentCommand.parentCommand.dataDir().toAbsolutePath().toString(), parentCommand.parentCommand.dataDir().toAbsolutePath().toString(),
BesuController.DATABASE_PATH); BesuController.DATABASE_PATH);
File databaseDirectory = new File(databasePath.toString()); final File databaseDirectory = new File(databasePath.toString());
if (!databaseDirectory.isDirectory() || databaseDirectory.list().length == 0) { if (!databaseDirectory.isDirectory() || databaseDirectory.list().length == 0) {
// Empty data directory, nothing to export // Empty data directory, nothing to export
throw new CommandLine.ParameterException( throw new CommandLine.ParameterException(

@ -56,22 +56,18 @@ public class BlocksSubCommandTest extends CommandTestAbstract {
+ System.lineSeparator(); + System.lineSeparator();
private static final String EXPECTED_BLOCK_IMPORT_USAGE = private static final String EXPECTED_BLOCK_IMPORT_USAGE =
"Usage: besu blocks import [-hV] --from=<FILE>" "Usage: besu blocks import [-hV] [--format=<format>] --from=<FILE>\n"
// "Usage: besu blocks import [-hV] [--format=<format>] --from=<FILE>" + " [--start-time=<startTime>]\n"
+ System.lineSeparator() + "This command imports blocks from a file into the database.\n"
+ "This command imports blocks from a file into the database." + " --format=<format> The type of data to be imported, possible values are:\n"
// Hide format for while JSON option is under development + " RLP, JSON (default: RLP).\n"
// + System.lineSeparator() + " --from=<FILE> File containing blocks to import.\n"
// + " --format=<format> The type of data to be imported, possible values + " -h, --help Show this help message and exit.\n"
// are: RLP,\n" + " --start-time=<startTime>\n"
// + " JSON (default: RLP)." + " The timestamp in seconds of the first block for JSON\n"
+ System.lineSeparator() + " imports. Subsequent blocks will be 1 second later.\n"
+ " --from=<FILE> File containing blocks to import." + " (default: current time)\n"
+ System.lineSeparator() + " -V, --version Print version information and exit.\n";
+ " -h, --help Show this help message and exit."
+ System.lineSeparator()
+ " -V, --version Print version information and exit."
+ System.lineSeparator();
private static final String EXPECTED_BLOCK_EXPORT_USAGE = private static final String EXPECTED_BLOCK_EXPORT_USAGE =
"Usage: besu blocks export [-hV] [--end-block=<LONG>] [--start-block=<LONG>]" "Usage: besu blocks export [-hV] [--end-block=<LONG>] [--start-block=<LONG>]"
@ -138,7 +134,7 @@ public class BlocksSubCommandTest extends CommandTestAbstract {
@Test @Test
public void callingBlockImportSubCommandHelpMustDisplayUsage() { public void callingBlockImportSubCommandHelpMustDisplayUsage() {
parseCommand(BLOCK_SUBCOMMAND_NAME, BLOCK_IMPORT_SUBCOMMAND_NAME, "--help"); parseCommand(BLOCK_SUBCOMMAND_NAME, BLOCK_IMPORT_SUBCOMMAND_NAME, "--help");
assertThat(commandOutput.toString()).isEqualToIgnoringWhitespace(EXPECTED_BLOCK_IMPORT_USAGE); assertThat(commandOutput.toString()).isEqualTo(EXPECTED_BLOCK_IMPORT_USAGE);
assertThat(commandErrorOutput.toString()).isEmpty(); assertThat(commandErrorOutput.toString()).isEmpty();
} }

Loading…
Cancel
Save