-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: BLS Key Separation and ERC2335 Implementation
## Description This PR was created from epic #336, separates BLS key from priv_validator_key.json, and applies ERC2335. There are still issues in CI that are being resolved, but I'm uploading a PR to first discuss the changed structure and ideas. ### ERC2335 structure - Use [keystorev4](github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4) with [prysm](https://github.com/prysmaticlabs/prysm) as reference - Add ERC2335 encryption/decryption and password generation functions ### Change WrappedFilePV to include BLS structure and use cometbft's FilePV directly ```go type WrappedFilePVKey struct { CometPVKey privval.FilePVKey BlsPVKey BlsPVKey } ``` ### BLS separation - At the time of `babylond init`, only priv_validator_key.json is created. - `babylond create-bls-key` creates a BLS key with the password entered as the prompt and encrypts it into an ERC2335 structure. - The generated BLS key in ERC2335 format is saved as `bls_key.json`, and the password is saved as `bls_password.txt`. An example of a `bls_key.json` is below: ```json { "crypto": { "checksum": { "function": "sha256", "message": "d291102754ece0a5ab9d4c3c75f452069d192df6c90d616e466d7e7884f41b3a", "params": {} }, "cipher": { "function": "aes-128-ctr", "message": "e638d3f04b803c3ec934c31749ed20c1ffcd48ab481b4fad6b303aa2e7ff991c", "params": { "iv": "473e315746ec9997f0d0e423f73e2d3d" } }, "kdf": { "function": "pbkdf2", "message": "", "params": { "c": 262144, "dklen": 32, "prf": "hmac-sha256", "salt": "3f1b139f3663082f582acc6d48fd9bf8caf4ea9c4e51c6ef75c9bc5b5c04ee9e" } } }, "version": 4, "uuid": "", "path": "", "pubkey": "a28b189e76e8d61461811eec22bc8d5c926bf1276afde5344a3b9d3a2769a1a61ea42471a867d4811a85640dfde8fed702d81bcc9f56494ec65471151fac6e3c262541245f1b16c9e22000eef2142c43f6ad5ca8c31fc16081261cc54d3f034c", "description": "bbn196xcr99y5eehdg6lr38u8re0j6xeq0twup5rl4" } ``` An example of a `priv_validator_key.json` with BLS separated is below: ```json { "address": "3141C6C8EF5FDAE49931AE2F9EB295F5C9E2212A", "pub_key": { "type": "tendermint/PubKeyEd25519", "value": "CwCehdhn8DmcVTKn4I1RHzlmur5LbEZxSEr+zvf7Ifo=" }, "priv_key": { "type": "tendermint/PrivKeyEd25519", "value": "HIHCMsU9+J3FjEU7gooSed5moKRjar6TfLa3Nb1CSCULAJ6F2GfwOZxVMqfgjVEfOWa6vktsRnFISv7O9/sh+g==" } } ``` ### Change DelegatorAddress to be stored in the description field of ERC2335 structure instead of storing it in `priv_validator_key.json`. - DelegatorAddress is stored in the description field of the `bls_key.json` file in erc2335 format. ```go type BlsPVKey struct { PubKey bls12381.PublicKey `json:"bls_pub_key"` PrivKey bls12381.PrivateKey `json:"bls_priv_key"` DelegatorAddress string // ... } ``` ## Test script $ ./babylond init my-node --chain-id test-chain-1 $ ./babylond keys add validator1 --keyring-backend test $ ./babylond add-genesis-account $(./babylond keys show validator1 -a --keyring-backend test) 2000000000000ubbn,2000000000000stake $ ./babylond gentx validator1 1500000000000stake --chain-id test-chain-1 --keyring-backend test --fees 400ubbn $ ./babylond collect-gentxs $ ./babylond create-bls-key $(./babylond keys show validator1 -a --keyring-backend test) $ ./babylond gen-helpers create-bls After the create-bls command, json file starting with the prefix "gen-bls" will be created in {home}/.babylond/config. > example: gen-bls-bbnvaloper196xcr99y5eehdg6lr38u8re0j6xeq0twpr77n5.json Copy data in the created file to the 'checkpointing.genesis_keys' field in genesis.json. Here is an example after inserting data to 'checkpointing.genesis_keys' field in genesis.json ```json "checkpointing": { "genesis_keys": [ { "validator_address": "bbnvaloper196xcr99y5eehdg6lr38u8re0j6xeq0twpr77n5", "bls_key": { "pubkey": "oosYnnbo1hRhgR7sIryNXJJr8Sdq/eU0SjudOidpoaYepCRxqGfUgRqFZA396P7XAtgbzJ9WSU7GVHEVH6xuPCYlQSRfGxbJ4iAA7vIULEP2rVyowx/BYIEmHMVNPwNM", "pop": { "ed25519_sig": "9YrVS1/KN0Fq6po0JbWirX+0enhxiShqxVw+lQFn22qam/2KaZXXzNMsOOOBoyQ9ZSD7ARc/TtohYBbhLIF/Cg==", "bls_sig": "pRAZUAH2ZDPZqgoiPTsFYTYndBctJXoY1lvN5GsWNNbPDYyIeXihaS28pqauHCcy" } }, "val_pubkey": { "key": "CwCehdhn8DmcVTKn4I1RHzlmur5LbEZxSEr+zvf7Ifo=" } } ] }, ``` ## Subsequent tasks - Ensure the BLS key file is created atomically with priv_validator_key.json - BLS key non-validation logic for non-validator - Remove DelegatorAddress from the `BlsPV` structure and obtain it from `GetValidatorByConsAddr()` function of the Epoch(Staking) module. - ~~Add the option to use the `--bls-password` flag when creating the BLS key~~ [1f14b31](1f14b31) - Modify not to keep `WrappedFilePV` since LastSignState is not used ```go type WrappedFilePV struct { Key WrappedFilePVKey LastSignState privval.FilePVLastSignState } ```
- Loading branch information
Showing
25 changed files
with
673 additions
and
326 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package erc2335 | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
|
||
keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4" | ||
) | ||
|
||
// Erc2335KeyStore represents an ERC-2335 compatible keystore used in keystorev4. | ||
type Erc2335KeyStore struct { | ||
Crypto map[string]interface{} `json:"crypto"` // Map containing the encryption details for the keystore such as checksum, cipher, and kdf. | ||
Version uint `json:"version"` // Version of the keystore format (e.g., 4 for keystorev4). | ||
UUID string `json:"uuid"` // Unique identifier for the keystore. | ||
Path string `json:"path"` // File path where the keystore is stored. | ||
Pubkey string `json:"pubkey"` // Public key associated with the keystore, stored as a hexadecimal string. | ||
Description string `json:"description"` // Optional description of the keystore, currently used to store the delegator address. | ||
} | ||
|
||
// Encrypt encrypts the private key using the keystorev4 encryptor. | ||
func Encrypt(privKey, pubKey []byte, password string) ([]byte, error) { | ||
if privKey == nil { | ||
return nil, fmt.Errorf("private key cannot be nil") | ||
} | ||
|
||
encryptor := keystorev4.New() | ||
cryptoFields, err := encryptor.Encrypt(privKey, password) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to encrypt private key: %w", err) | ||
} | ||
|
||
keystoreJSON := Erc2335KeyStore{ | ||
Crypto: cryptoFields, | ||
Version: 4, | ||
Pubkey: fmt.Sprintf("%x", pubKey), | ||
} | ||
|
||
return json.Marshal(keystoreJSON) | ||
} | ||
|
||
// Decrypt decrypts the private key from the keystore using the given password. | ||
func Decrypt(keystore Erc2335KeyStore, password string) ([]byte, error) { | ||
encryptor := keystorev4.New() | ||
return encryptor.Decrypt(keystore.Crypto, password) | ||
} | ||
|
||
// LoadKeyStore loads a keystore from a file. | ||
func LoadKeyStore(filePath string) (Erc2335KeyStore, error) { | ||
var keystore Erc2335KeyStore | ||
|
||
keyJSONBytes, err := os.ReadFile(filePath) | ||
if err != nil { | ||
return Erc2335KeyStore{}, fmt.Errorf("failed to read keystore file: %w", err) | ||
} | ||
|
||
if err := json.Unmarshal(keyJSONBytes, &keystore); err != nil { | ||
return Erc2335KeyStore{}, fmt.Errorf("failed to unmarshal keystore: %w", err) | ||
} | ||
|
||
return keystore, nil | ||
} |
Oops, something went wrong.