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

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

Loading…
Cancel
Save