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

Voting Key generation using typescript and multi file support #177

Merged
merged 24 commits into from
Jun 15, 2021

Conversation

fboucquez
Copy link
Owner

@fboucquez fboucquez commented Mar 2, 2021

Update:

This PR now supports both the original catapult tools' voting key file generation and the native typescript. The original is the one used by default. You can enable the new native typescript with the useExperimentalNativeVotingKeyGeneration: true custom preset.

I'm also working on multi-voting file support. The voting file metadata (public key, start, and end epoch) is loaded directly from the .dat files.

Voting file upgrade idea:

  1. Bootstrap knows the network "current" finalizationEpoch (by either a manually upgraded custom preset value for offline setup or asking the network for online)
  2. If the node's current voting file has an end epoch close to the current epoch (close to expiring), --upgrade will create 'private_key_tree2.dat' that continues the current file. I defined "Close to expiring" when the epoch is in the upper half of the voting file. If the file's epoch length is 360, close to expiring will be 180+. Our nodes are 180 epochs, current epoch is 104 so they are close to expiring.
  3. When a new voting file is created, bootstrap will advise running the link command again. The link command detects what has changed and announces the required transactions (linking the new voting key). The voting key files metadata (public key, start, and end epochs) will be in addresses.yml so it can also be linked using the symbol CLI if desired.

For the end-user, the upgrade process is pretty much the same:

$ npm install -g symbol-bootstrap
$ symbol-bootstrap start -p mainnet -a dual -c custom-preset.yml --upgrde
>>> New Voting File Created!
$ symbol-bootstrap link

We can also add a new command "upgradeVotingFiles" that does the --upgrade of voting files explicitly

TODOs:

  • Test how the node behaves when transitioning from one file to another
  • Double-check if we need to unlink already expired voting keys in the network. I think there is a limit about how many public keys can be linked. We may only need the current voting key and the future voting key
  • Double-check want to do with old voting key files. Do we need to remove them? If we need to remove them, we need to "shift them", if voting file 1 is removed, voting file 2 should be renamed to voting key 1, 3 to voting key 2, etc

Slack chat: https://nemgroup-workspace.slack.com/archives/C015AEQ9ZL2/p1616410897191200

Related to #149

Original:
This is my first implementation of voting key file generation done in Javascript/Typescript.

I think the code is ok, the main issue is that the SDK is really slow generating keys and signing data. The SDK uses tweetnacl, which is small but slow. These are some numbers on my dev machine when creating the voting key file:

(votingKeyEndEpoch - votingKeyStartEpoch + 1 -> TIME)

  • 1 epoch -> 50 MS
  • 5 epochs -> 114 MS
  • 1000 epochs -> 10 seconds
  • 10000 epochs -> 1 minute 41 seconds
  • 26280 epochs -> 4 Minutes 25 seconds

@gimer , could you validate the logic in https://github.com/nemtech/symbol-bootstrap/blob/native_voting_key_file/src/service/VotingUtils.ts#L24?

As unit testing, I'm comparing files generates with catapult tools against files generated using the native implementation. Checking that the headers and sizes are the same. I would add more assertions validating the internal items (private key and signatures).

To speed up the implementation we could:

  • Change the SDK crypto library. It could make the SDK faster but it would make it heavier, it may not work on Web, it could have secondary effects. Not Recommended at this stage.
  • Change the crypto lib Bootstrap uses for the voting key implementation but keep the SDK for the rest of the key generation. Maybe something like monocypher

Before doing any improvement, I want to double-check the logic is fine.

I'm pushing hard for this feature not because I want to reimplement the tool. This will allow me to make Bootstrap config offline without docker and OS independent (catapult tools wouldn't need to be compiled and installed in the offline machine). Supernodes will have fewer excuses to not use Bootstrap to setup the configuration (when runing barebone or with docker compose in the final online node machine)

Fixes #169
Related to #170

Update:
noble-ed25519 takes ~40 seconds for the 26280 epochs

src/service/VotingUtils.ts Outdated Show resolved Hide resolved
src/service/VotingUtils.ts Outdated Show resolved Hide resolved
@gimre-xymcity
Copy link

10000 - I hope you remember that for publicnet limit is 1460, so the tool should probably check that limit somewhere

@fboucquez
Copy link
Owner Author

fboucquez commented Mar 2, 2021

10000 - I hope you remember that for publicnet limit is 1460, so the tool should probably check that limit somewhere

Thanks. We also use bootstrap for private networks, epoch length would be large in this case. I can add the limit the public/testnet nodes

@fboucquez fboucquez changed the title WIP Voting Key generation using typescript Voting Key generation using typescript Mar 2, 2021
@fboucquez
Copy link
Owner Author

fboucquez commented Mar 2, 2021

Update, I've added multi implementation (all implementations pass the vector tests). The fastest one by far is noble-ed25519. It's the current default.
Bootstrap doesn't need catapult tools anymore when creating the node configuration. (Nemgen is still used but for new networks)

src/service/VotingUtils.ts Outdated Show resolved Hide resolved
src/service/VotingUtils.ts Show resolved Hide resolved
src/service/VotingUtils.ts Show resolved Hide resolved
src/service/VotingUtils.ts Show resolved Hide resolved
@fboucquez fboucquez changed the title Voting Key generation using typescript Voting Key generation using typescript (Post-Launch) Mar 4, 2021
@fboucquez fboucquez changed the title Voting Key generation using typescript (Post-Launch) Voting Key generation using typescript and multi file support Mar 31, 2021
# Conflicts:
#	cmds/config-testnet-supernode.sh
#	package-lock.json
#	package.json
#	presets/testnet/network.yml
#	src/model/Addresses.ts
#	src/service/BootstrapUtils.ts
#	src/service/ConfigLoader.ts
#	test/service/BootstrapUtils.test.ts
#	test/supernode.yml
# Conflicts:
#	CHANGELOG.md
#	src/service/LinkService.ts
#	src/service/RewardProgramService.ts
# Conflicts:
#	CHANGELOG.md
#	presets/shared.yml
#	src/service/ConfigService.ts
#	src/service/VotingService.ts
@fboucquez fboucquez force-pushed the native_voting_key_file branch 3 times, most recently from 1f65bd3 to 8e8d422 Compare June 3, 2021 15:53

Voting file upgrade:
- If the node's current voting file has an end epoch close to the current epoch ("close to expiring") this command creates a new 'private_key_treeX.dat' that continues the current file.
- "Close to expiring" happens when the epoch is in the upper half of the voting file. If the file's epoch length is 720, close to expiring will be 360+.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the default should be to allow the user to upgrade 1 month before keys expire.
Allow them to override with a warning.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I think at this stage allowing the user to upgrade 3 months in advance is fine, especially because this is the first upgrade and people need to get the process in place (like all nodes). We could reduce the default values in a later voting key upgrade

Copy link
Contributor

Choose a reason for hiding this comment

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

I think a month is more than enough time to run the update command.
Allnode could create a cron job that runs every 6 months to generate new key files. If they want to run it early, then nothing stopping them since there is an override option.
We are kind thinking similar except your suggestion would require an update later to the bootstrap.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Ok, I will upgrade the preset. Defaults will be:

votingKeyDesiredLifetime: 6 months in epochs (how long the file last)
votingKeyDesiredFutureLifetime: 1 month in epochs (1 month before the current file expires bootstrap will create a new file)

README.md Outdated
@@ -277,6 +277,7 @@ General users should install this tool like any other node module.
* [`symbol-bootstrap run`](docs/run.md) - It boots the network via docker using the generated `docker-compose.yml` file and configuration. The config and compose methods/commands need to be called before this method. This is just a wrapper for the `docker-compose up` bash call.
* [`symbol-bootstrap start`](docs/start.md) - Single command that aggregates config, compose and run in one line!
* [`symbol-bootstrap stop`](docs/stop.md) - It stops the docker-compose network if running (symbol-bootstrap started with --detached). This is just a wrapper for the `docker-compose down` bash call.
* [`symbol-bootstrap upgradeVotingKeys`](docs/upgradeVotingKeys.md) - It upgrades the voting keys and files when required.
Copy link
Contributor

Choose a reason for hiding this comment

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

upgradeVotingKeys not sure if command name. Not really upgrading the voting keys. Maybe registerVotingKeys

Copy link
Owner Author

Choose a reason for hiding this comment

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

Unsure, the command creates the file when necessary, it doesn't register in the network. For that, the link command is required (or symbol cli)

Copy link
Contributor

Choose a reason for hiding this comment

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

hehe...maybe register is not a good name either.
upgradeVotingKeys doesnt make much sense to me since voting key/files are not upgradable.
@segfaultxavi thoughts?
maybe addVotingKeys or createVotingKeys

Copy link
Contributor

Choose a reason for hiding this comment

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

renewVotingKeys?

Copy link
Owner Author

@fboucquez fboucquez Jun 14, 2021

Choose a reason for hiding this comment

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

Options:

  1. updateVotingKeys
  2. createVotingKeys
  3. addVotingKeys
  4. renewVotingKeys

maybe 3 ? @segfaultxavi @Wayonb

Copy link
Contributor

Choose a reason for hiding this comment

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

This command, together with link, does two things, right? Creates new keys AND removes (or unregisters) the old ones. I think add and create both fail to convey the second action. I can see @Wayonb's point that the keys are not actually "updated", so I suggested the renew option :)
But this command will be very seldom used (twice a year!) so let's go with whatever :D

Copy link
Owner Author

Choose a reason for hiding this comment

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

I've talked to @Wayonb , updateVotingKeys is the name.

presets/mainnet/network.yml Show resolved Hide resolved
src/service/LinkService.ts Show resolved Hide resolved
src/service/VotingService.ts Outdated Show resolved Hide resolved
const votingUtils = new VotingUtils();
await BootstrapUtils.deleteFile(join(votingKeysFolder, 'metadata.yml'));
let newFileCreated = false;
while (true) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why while(true)? maybe I am missing something.
Are multiple files getting created? I would assume when the loop is finish either it creates a voting key file or not.

Copy link
Owner Author

Choose a reason for hiding this comment

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

if you have a short votingKeyDesiredLifetime and a large votingKeyDesiredFutureLifetime in your custom preset, the service generates multiple files. Most people would not change this, but you have the option of having smaller files at once if you like

Copy link
Contributor

Choose a reason for hiding this comment

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

ok. I would suggest not generating keys that are not been used.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Fair enough. I have removed the while and only one file can be created at a given time. Also, votingKeyDesiredFutureLifetime cannot be greater than votingKeyDesiredLifetime.

src/service/VotingService.ts Outdated Show resolved Hide resolved
src/service/VotingUtils.ts Show resolved Hide resolved
@fboucquez fboucquez requested a review from Wayonb June 8, 2021 13:48

Voting file update:
- If the node's current voting file has an end epoch close to the current epoch ("close to expiring") this command creates a new 'private_key_treeX.dat' that continues the current file.
- By default, "Close to expiring" happens the voting file in the . By default, bootstrap will allow creating new files once the current file reaches its last month.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know what are you trying to say here, the first sentence makes no sense.

Copy link
Owner Author

Choose a reason for hiding this comment

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

Yeap, what about now?

segfaultxavi
segfaultxavi previously approved these changes Jun 15, 2021
Copy link
Contributor

@segfaultxavi segfaultxavi left a comment

Choose a reason for hiding this comment

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

👍

Wayonb
Wayonb previously approved these changes Jun 15, 2021
@@ -7,6 +7,9 @@ The changelog format is based on [Keep a Changelog](https://keepachangelog.com/e
## [1.0.7] - NEXT
**Milestone**: Mainnet(1.0.1.0)

- Added multi voting key file support.
- Added `upgradeVotingKeys` command.

Copy link
Contributor

Choose a reason for hiding this comment

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

updateVotingKeys?

@fboucquez fboucquez dismissed stale reviews from Wayonb and segfaultxavi via ea7c963 June 15, 2021 16:33
@fboucquez fboucquez merged commit 8f889b6 into dev Jun 15, 2021
@fboucquez fboucquez deleted the native_voting_key_file branch June 15, 2021 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants