-
Notifications
You must be signed in to change notification settings - Fork 35
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
Separate BLS key from priv_validator_key.json
#336
Comments
This should be done in two steps:
|
Some context of why and how BLS key is used can be found here. The BLS key should be treated as important as the ed25519 key used in Comet consens. Currently it is embeded in the In order for secure management of the BLS key, after separation, the BLS key should be kept following standard proposed by Ethereum https://github.com/ethereum/ercs/blob/master/ERCS/erc-2335.md so that it can work with related toolings. |
Hi, I am an engineer at B-Harvest. Our team plans to work on this issue, and we are considering proceeding as follows. If there are any issues or alternative suggestions, I’d appreciate it if you could share them. 1. Preserve
|
Hey @dongsam, sorry for the late reply. Thanks for taking this issue. The two steps approaching this sounds good to me. And I agree that combining 1 and 2 in one PR avoids most redundant code changes but I in general I prefer to have smaller PRs if possible as it is more friendly for review. Let's see how we can split it well. Some relies to coments/questions:
The I would be ideal if we have embed cometbft's FilePVKey into // WrappedFilePVKey wraps FilePVKey with BLS keys.
type WrappedFilePVKey struct {
CometPVKey privval.FilePVKey `json:"comet_pv_key"`
BLSPVKey erc2335.BLSPVKey `json:bls_pv_key`
}
We probably don't need migration. Let's focus on new users for now.
Storing the password in a separate file sounds good to me if it is part of ERC-2335. But maybe I was missing something, why it has to be a random password? Can it be a prompt asking user to specify the password when creating the BLS key? |
Hi @gitferry, Thanks for your reply. The The reason I brought up the random password was a concern about breaking atomicity the
when no password is specified via flags like --password. However, if it’s okay to prompt asking for the password, then there’s no need to use a random password. I’ll proceed with that approach. Thanks. |
Thanks @dongsam.
A note about the above: this is a secondary requirement. Ideally, we want the creation of BLS keys to be transparent to the user. That is, when the user creates the ed25519 key (i.e., |
Some notes from offline discussion:
|
After the meeting, I created the structures of // WrappedFilePVKey wraps FilePVKey with BLS keys.
type WrappedFilePVKey struct {
CometPVKey privval.FilePVKey `json:"comet_pv_key"`
BLSPVKey erc2335.BLSPVKey `json:bls_pv_key`
}
type CometPVKey struct {
Address types.Address `json:"address"`
PubKey cmtcrypto.PubKey `json:"pub_key"`
PrivKey cmtcrypto.PrivKey `json:"priv_key"`
}
type BLSPVKey struct {
BlsPubKey bls12381.PublicKey `json:"bls_pub_key"`
BlsPrivKey bls12381.PrivateKey `json:"bls_priv_key"`
} If the How about creating a .json file for the key according to the ERC2335 structure, but configuring the BLSKey structure of The BLS key to be created as a .json file will follow the ERC2335 structure as below. In other words, we want to call the type BLSFileKey struct {
Crypto struct {
KDF struct {
Function string `json:"function"` // "pbkdf2"
Params struct {
Dklen int `json:"dklen"` // 32
C int `json:"c"` // 262144
Prf string `json:"prf"` // "hmac-sha256"
Salt string `json:"salt"`
} `json:"params"`
Message string `json:"message"`
} `json:"kdf"`
Checksum struct {
Function string `json:"function"` // "sha256"
Params map[string]interface{} `json:"params"`
Message string `json:"message"`
} `json:"checksum"`
Cipher struct {
Function string `json:"function"` // "aes-128-ctr"
Params struct {
IV string `json:"iv"`
} `json:"params"`
Message string `json:"message"`
} `json:"cipher"`
} `json:"crypto"`
Description string `json:"description"` // "BLS-12381 private key"
Pubkey string `json:"pubkey"` // hex-encoded public key
Path string `json:"path"` // "m/12381/60/0/0"
UUID string `json:"uuid"` // random UUID
Version int `json:"version"` // 4
filePath string
} |
For
This is to load the private key into memory once during initiation, right? I wouldn't mind but how does Ethereum handle this situation? Eth validators also need automatic signing in consensus, right?
Yeah, I would imagine we will have an ERC2335 like this |
I have a question during refactoring. func InitializeNodeValidatorFilesFromMnemonic(config *cfg.Config, mnemonic string, addr sdk.AccAddress) (nodeID string, valKeys *privval.ValidatorKeys, err error) {
//...
var filePV *privval.WrappedFilePV
if len(mnemonic) == 0 {
filePV = privval.LoadOrGenWrappedFilePV(pvKeyFile, pvStateFile)
} else {
privKey := cmted25519.GenPrivKeyFromSecret([]byte(mnemonic))
blsPrivKey := bls12381.GenPrivKeyFromSecret([]byte(mnemonic))
filePV = privval.NewWrappedFilePV(privKey, blsPrivKey, pvKeyFile, pvStateFile)
}
filePV.SetAccAddress(addr)
//...
} In the above code, the mnemonic value is commonly used when creating ed25519 and bls keys. I wonder if this is intentional code or if it is lightly written code for a test environment. |
Yes, similarly, Ethereum Consensus client Prysm, which uses ERC-2335 for key storage and BLS signing, also caches the decrypted BLS key in memory for faster signing. [code] // Initialize public and secret key caches that are used to speed up the functions
// FetchValidatingPublicKeys and Sign
func (km *Keymanager) initializeKeysCachesFromKeystore() error {
lock.Lock()
defer lock.Unlock()
count := len(km.accountsStore.PrivateKeys)
orderedPublicKeys = make([][fieldparams.BLSPubkeyLength]byte, count)
secretKeysCache = make(map[[fieldparams.BLSPubkeyLength]byte]bls.SecretKey, count)
for i, publicKey := range km.accountsStore.PublicKeys {
publicKey48 := bytesutil.ToBytes48(publicKey)
orderedPublicKeys[i] = publicKey48
secretKey, err := bls.SecretKeyFromBytes(km.accountsStore.PrivateKeys[i])
if err != nil {
return errors.Wrap(err, "failed to initialize keys caches from account keystore")
}
secretKeysCache[publicKey48] = secretKey
}
return nil
} |
@wnjoon hey, tbh I can't remember but I think that's for testing purpose |
@dongsam thanks! This sounds good to me |
@dongsam Please ensure node cannot be started if either the BLS key file or |
@gitferry As part of the basic logic of cometBFT, whether it’s a non-validator node or a validator node, the What about allowing the key to be explicitly set up during the Should non-validator nodes that are not validators and do not participate in signing also be subject to the same conditions for BLS key validation? |
I think the current status in the testnet is that, people may start running the node before setting up the BLS keys so that the keys were not loaded properly.
It would be ideal if the BLS keys can be generated in the
Technically we should follow how non-validator nodes are treaded against |
Got it, we’re planning to split it into two PRs.
Yes, the current cometBFT code However, since ERC2335 requires a password, non-validator nodes would need to go through a password input step even if they don’t immediately use it, which could slightly impact the UX. |
The two PRs sounds good to me!
Ah, if so, we probably don't need non-validator to go through this, but how do we know if the node is a validator? Is it specified explicitly by any flag or config when starting the node? |
Currently, there is no explicit flag to indicate whether a node is a validator. To determine this clearly, we would need to get validator info from the staking module to check if the consensus public key of the current node is registered as a validator. However, this requires accessing the state, which can only be done after the app initialization is complete, making the process a bit more complex. For the first PR, we’ll skip validating whether the node is a validator and instead check the presence and format of the BLS key for all nodes. In the second PR, we’ll refactor and explore better ways to verify if a node is a validator. |
@dongsam Sounds good to me. Thanks for the explanation! |
We opened the first PR #396 as a draft in case there might be some waiting. We haven’t fully verified the CI pass yet, so there’s still some debugging to do on the breaking parts. However, the code structure, overall direction, and main logic are fairly finalized. Feel free to take a look and leave comments if you’d like. Anyway, once the CI passes, we’ll update the PR to R4R and formally request your review. |
Should consider utilizing some keyring for bls keys storage like ethereum bls key store - https://github.com/ethereum/ercs/blob/master/ERCS/erc-2335.md, or most recent versions of comet bft have support for bls keys - https://github.com/cometbft/cometbft/tree/main/crypto/bls12381
The text was updated successfully, but these errors were encountered: