Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

[PIE-1809] Add import chain json utility #1832

Merged

Conversation

mbaxter
Copy link
Contributor

@mbaxter mbaxter commented Aug 7, 2019

PR description

Add a CLI utility for importing blocks from a json file containing minimally specified block and transaction data.

Example command:

pantheon --network=DEV blocks import --format=JSON --from="/path/to/file.json"

Example import file:

{
  "blocks": [
    {
      "number": 1,
      "transactions": [
        {
          "fromPrivateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
          "gasLimit": "0xFFFFF1",
          "gasPrice": "0xFF",
          "value": "0x01",
          "to": "627306090abaB3A6e1400e9345bC60c78a8BEf57"
        },
        {
          "fromPrivateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
          "gasLimit": "0xFFFFF2",
          "gasPrice": "0xEF",
          "to": "f17f52151EbEF6C7334FAD080c5704D77216b732"
        }
      ]
    }
  ]
}

Example output:

2019-08-07 19:07:58.453-04:00 | main | INFO  | BlocksSubCommand | Import JSON block data from /path/to/file.json 
2019-08-07 19:07:59.334-04:00 | main | INFO  | KeyPairUtil | Loaded key 0x5285b91de23f6e519836e0d0fe8413eef43f453a2e0af2d154b6bbae92175bdbfca37d0eec7095bf4b8ddfbf813aa669b26640dbeaf218ed3846744cd869bc01 from /data/key 
2019-08-07 19:07:59.594-04:00 | main | INFO  | ProtocolScheduleBuilder | Protocol schedule created with milestones: [ConstantinopleFix: 0] 
2019-08-07 19:07:59.775-04:00 | main | WARN  | ChainImporter | Importing to a non-empty database with chain height 2.  This may cause imported blocks to be considered non-canonical. 
2019-08-07 19:07:59.828-04:00 | main | INFO  | ChainImporter | Preparing to import block at height 1 (parent: 0xa08d1edb37ba1c62db764ef7c2566cbe368b850f5b3762c6c24114a3fd97b87f) 
2019-08-07 19:08:02.961-04:00 | main | INFO  | ChainImporter | Successfully created and imported block at height 1 (0xb062d54fbcdbe150f2ee38d10f2393c796f66048d5fc36ef8cee02c0bf807e3e) 
2019-08-07 19:08:02.967-04:00 | main | WARN  | ChainImporter | 1 / 1 imported blocks are not on the canonical chain: #1 (0xb062d54fbcdbe150f2ee38d10f2393c796f66048d5fc36ef8cee02c0bf807e3e) 

@mbaxter mbaxter marked this pull request as ready for review August 8, 2019 20:44
@@ -256,4 +322,9 @@ private void outputBlock(final List<Block> blocks) {
}
return metricsService;
}

@FunctionalInterface
public interface ChainImporterFactory {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this need to be an explicit functional interface? Could we not use a Supplier?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could use Function<PantheonController<T>, ChainImporter<T>> instead. But, I prefer making explicit interfaces for reasons of readability and discoverability. It's a pattern we use pretty extensively in the codebase.

Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting, I find the explicit interface less readable because the parameter looks like it could be a full blown object with more methods. Not a blocking issue though

"Unable to create block using current consensus engine: "
+ genesisConfigOptions.getConsensusEngine());
}
return maybeBlock.get();
Copy link
Contributor

@RatanRSur RatanRSur Aug 8, 2019

Choose a reason for hiding this comment

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

(optional) use orElseThrow and inline maybeBlock

}

public void importChain(final String chainJson) throws IOException {
checkDatabaseIsEmpty();
Copy link
Contributor

@RatanRSur RatanRSur Aug 8, 2019

Choose a reason for hiding this comment

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

(optional) this sounds stricter than it is, how about warnIfDatabaseNotEmpty?

@@ -0,0 +1,33 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a way to parse the blocks directly into a sequence without the need of a separate class?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Maybe? But I think the structure is pretty clear as is and it provides a place to add additional data if we need it in the future.

public void importChain(final String chainJson) throws IOException {
checkDatabaseIsEmpty();

ChainData chainData = mapper.readValue(chainJson, ChainData.class);
Copy link
Contributor

@RatanRSur RatanRSur Aug 8, 2019

Choose a reason for hiding this comment

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

Regarding the comment on the ChainData file. This reads like there's probably more to ChainData than just a sequence of blocks

public void importChain(final String chainJson) throws IOException {
checkDatabaseIsEmpty();

ChainData chainData = mapper.readValue(chainJson, ChainData.class);
Copy link
Contributor

Choose a reason for hiding this comment

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

can this be final?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep - I always miss the finals 😄

}

// Check that imported blocks form the canonical chain, if not print a warning
this.checkImportedBlocksAreOnCanonicalChain(importedBlocks);
Copy link
Contributor

Choose a reason for hiding this comment

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

(optional) The comment could probably be removed (and thus not at risk of getting outdated) if the method was something like warnIfImportedBlocksNotOnCanonicalChain

+ System.lineSeparator()
+ "This command imports blocks from a file into the database."
+ System.lineSeparator()
+ " --from=<FILE> File containing blocks to import"
+ " --format=<format> The type of data to be imported (default: RLP)."
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there somewhere the user can see that JSON is a valid option to this flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call - will update!

description = "The type of data to be imported (default: ${DEFAULT-VALUE}).",
hidden = true,
description =
"The type of data to be imported, possible values are: ${COMPLETION-CANDIDATES} (default: ${DEFAULT-VALUE}).",
Copy link
Contributor

Choose a reason for hiding this comment

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

I didn't know ${COMPLETION-CANDIDATES} existed. Looks like I should open another PR to add this to other options as well.

@mbaxter mbaxter merged commit 6998e65 into PegaSysEng:master Aug 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants