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

feat: implement bls key generation #86

Merged
merged 4 commits into from
Aug 9, 2022
Merged

feat: implement bls key generation #86

merged 4 commits into from
Aug 9, 2022

Conversation

gitferry
Copy link
Contributor

@gitferry gitferry commented Aug 8, 2022

In Cosmos, a node generates all the genesis keys (including the account's key and validator's key) and stores keys in a config file before it starts running. In this PR, we added BLS key generation along with all the above keys. In particular, this PR includes:

  1. refactoring the BLS library to better support BLS functionalities
  2. wrapping load and save private validator functions from Tendermint with BLS generation
  3. generation of proof-of-possession
  4. BLS generation to testnet

Copy link
Contributor

@aakoshh aakoshh left a comment

Choose a reason for hiding this comment

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

This looks great!

One question: the description says the node generates keys, including validator and account keys when it starts, but I don't see the account key (Secp256k1) being generated from the mnemonic.

@@ -159,7 +163,8 @@ func InitTestnet(
return err
}

nodeIDs[i], valPubKeys[i], err = genutil.InitializeNodeValidatorFiles(nodeConfig)
//accInfo, err := clientCtx.Keyring.KeyByAddress(clientCtx.FromAddress)
nodeIDs[i], valKeys[i], err = datagen.InitializeNodeValidatorFiles(nodeConfig, []byte("hello world"))
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the "hello world" for? It looks like something that should not remain in production; a comment would not be amiss to explain.

Copy link
Contributor

Choose a reason for hiding this comment

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

So this calls https://github.com/babylonchain/babylon/pull/86/files#diff-954502830d7f26453fec2475dc8a85e43ffc312df8151a4745ad0be244dfbbfaR17

It looks to me that "hello world" should fail to validate when the validator tries to register their key with Babylon, because there we will use the account key that signed the transaction to validate the Proof-of-Possession.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, "hello world" definitely does not work. I was using it as a placeholder and I forgot to replace it with the account key. Now I have fixed it. Thanks for pointing that out.

}

func GenPrivKey() PrivateKey {
return genPrivKey(rand.Reader)
Copy link
Contributor

Choose a reason for hiding this comment

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

Ah good, for a moment I thought this was from the basic pseudo random package, not crypto/rand 👍

}

// GetAddress returns the address of the validator.
// Implements PrivValidator.
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe there could be that interface assignment trick after the declaration of WrappedFilePV as well to make sure it's implemented?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean that it would be better for WrappedFilePV to implement PrivValidator? If so, I'm not sure it is helpful to us because it is the internal logic of Tendermint, see here. We don't need to implement SignVote and SignProposal. But we do need to implement stuff like SignBLS. This will be implemented in a future PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, thanks, I didn't know it's not implementing the full interface.

privval/types.go Outdated
type ValidatorKeys struct {
ValPubkey tmcrypto.PubKey
BlsPubkey bls12381.PublicKey
Pop *types.ProofOfPossession
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Pop *types.ProofOfPossession
PoP *types.ProofOfPossession

A bit more intuitive?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it's better. Thanks!

privval/types.go Outdated
Comment on lines 32 to 34
// BuildPop builds a proof-of-possession by encrypt(key = BLS_sk, data = encrypt(key = Ed25519_sk, data = Secp256k1_pk))
// where valPrivKey is Ed25519_sk, accPubkey is Secp256k1_pk, blsPrivkey is BLS_sk
func BuildPop(valPrivKey tmcrypto.PrivKey, blsPrivkey bls12381.PrivateKey, msg []byte) (*types.ProofOfPossession, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it be possible to use an actual account public key type instead of msg []byte, as the comment describes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we can do it. Thanks!

Comment on lines +46 to +48
privKey := tmed25519.GenPrivKeyFromSecret([]byte(mnemonic))
blsPrivKey := bls12381.GenPrivKeyFromSecret([]byte(mnemonic))
filePV = privval.NewWrappedFilePV(privKey, blsPrivKey, pvKeyFile, pvStateFile)
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 are risk of overriding an existing private key with a new one with a valid, but different mnemonic, thus losing the keys?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it will overwrite the old keys when a new key is generated. But it's for testing only. Do we need to worry about a key backup in MVP?

Copy link
Contributor

Choose a reason for hiding this comment

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

It didn't look like it was here to support tests, more like it's accidentally under the testutil package, thanks for pointing that out. Because it's called from cmd/babylond/cmd/testnet.go it looks like an actual thing that could be used in production as well. At least there was nothing to suggest that wasn't the idea.


// InitializeNodeValidatorFiles creates private validator and p2p configuration files.
func InitializeNodeValidatorFiles(config *cfg.Config, msg []byte) (string, *privval.ValidatorKeys, error) {
return InitializeNodeValidatorFilesFromMnemonic(config, "", msg)
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 understand the empty mnemonic. According to https://github.com/babylonchain/babylon/pull/86/files#diff-954502830d7f26453fec2475dc8a85e43ffc312df8151a4745ad0be244dfbbfaR43 that will result in no BLS keys? What's the point of that?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, okay, it does generate BLS but not from a mnemonic. It looked confusing that one arm says LoadOrGenFilePV and the other says NewWrappedFilePV, like the first option wasn't wrapped.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it is confusing. Sorry about that. I have changed the function name

@gitferry
Copy link
Contributor Author

gitferry commented Aug 9, 2022

Thanks, @aakoshh for your comments. I have added account key into the generation of PoP. Please see the updates. The account key is generated via testutil.GenerateSaveCoinKey() with mnemonic as one of the arguments.

@gitferry gitferry merged commit e09cd50 into main Aug 9, 2022
@gitferry gitferry deleted the bls-keyring branch August 9, 2022 04:01
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.

2 participants