Wallet creation: Make mnemonic length configurable, default to 24 words. (#1697)

## Issue Addressed

Fixes #1665.

## Proposed Changes

`lighthouse account_manager wallet create` now generates a 24-word
mnemonic. The user can override this by passing `--mnemonic-length 12`
(or another legal bip39 length).

## Additional Info

CLI `--help`:
```
        --mnemonic-length <MNEMONIC_LENGTH>       The number of words to use for the mnemonic phrase. [default: 24]
```

In case of an invalid argument:
```
% lighthouse account_manager wallet create --mnemonic-length 25
error: Invalid value for '--mnemonic-length <MNEMONIC_LENGTH>': Mnemonic length must be one of 12, 15, 18, 21, 24
```
This commit is contained in:
Geoffry Song 2020-10-02 07:51:50 +00:00
parent b56dbc3ba0
commit 2cc20101d4
4 changed files with 40 additions and 12 deletions

View File

@ -23,6 +23,14 @@ pub const PASSWORD_FLAG: &str = "password-file";
pub const TYPE_FLAG: &str = "type"; pub const TYPE_FLAG: &str = "type";
pub const MNEMONIC_FLAG: &str = "mnemonic-output-path"; pub const MNEMONIC_FLAG: &str = "mnemonic-output-path";
pub const STDIN_INPUTS_FLAG: &str = "stdin-inputs"; pub const STDIN_INPUTS_FLAG: &str = "stdin-inputs";
pub const MNEMONIC_LENGTH_FLAG: &str = "mnemonic-length";
pub const MNEMONIC_TYPES: &[MnemonicType] = &[
MnemonicType::Words12,
MnemonicType::Words15,
MnemonicType::Words18,
MnemonicType::Words21,
MnemonicType::Words24,
];
pub const NEW_WALLET_PASSWORD_PROMPT: &str = pub const NEW_WALLET_PASSWORD_PROMPT: &str =
"Enter a password for your new wallet that is at least 12 characters long:"; "Enter a password for your new wallet that is at least 12 characters long:";
pub const RETYPE_PASSWORD_PROMPT: &str = "Please re-enter your wallet's new password:"; pub const RETYPE_PASSWORD_PROMPT: &str = "Please re-enter your wallet's new password:";
@ -78,6 +86,20 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.long(STDIN_INPUTS_FLAG) .long(STDIN_INPUTS_FLAG)
.help("If present, read all user inputs from stdin instead of tty."), .help("If present, read all user inputs from stdin instead of tty."),
) )
.arg(
Arg::with_name(MNEMONIC_LENGTH_FLAG)
.long(MNEMONIC_LENGTH_FLAG)
.value_name("MNEMONIC_LENGTH")
.help("The number of words to use for the mnemonic phrase.")
.takes_value(true)
.validator(|len| {
match len.parse::<usize>().ok().and_then(|words| MnemonicType::for_word_count(words).ok()) {
Some(_) => Ok(()),
None => Err(format!("Mnemonic length must be one of {}", MNEMONIC_TYPES.iter().map(|t| t.word_count().to_string()).collect::<Vec<_>>().join(", "))),
}
})
.default_value("24"),
)
} }
pub fn cli_run(matches: &ArgMatches, base_dir: PathBuf) -> Result<(), String> { pub fn cli_run(matches: &ArgMatches, base_dir: PathBuf) -> Result<(), String> {
@ -86,7 +108,11 @@ pub fn cli_run(matches: &ArgMatches, base_dir: PathBuf) -> Result<(), String> {
// Create a new random mnemonic. // Create a new random mnemonic.
// //
// The `tiny-bip39` crate uses `thread_rng()` for this entropy. // The `tiny-bip39` crate uses `thread_rng()` for this entropy.
let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English); let mnemonic_length = clap_utils::parse_required(matches, MNEMONIC_LENGTH_FLAG)?;
let mnemonic = Mnemonic::new(
MnemonicType::for_word_count(mnemonic_length).expect("Mnemonic length already validated"),
Language::English,
);
let wallet = create_wallet_from_mnemonic(matches, &base_dir.as_path(), &mnemonic)?; let wallet = create_wallet_from_mnemonic(matches, &base_dir.as_path(), &mnemonic)?;
@ -95,7 +121,7 @@ pub fn cli_run(matches: &ArgMatches, base_dir: PathBuf) -> Result<(), String> {
.map_err(|e| format!("Unable to write mnemonic to {:?}: {:?}", path, e))?; .map_err(|e| format!("Unable to write mnemonic to {:?}: {:?}", path, e))?;
} }
println!("Your wallet's 12-word BIP-39 mnemonic is:"); println!("Your wallet's {}-word BIP-39 mnemonic is:", mnemonic_length);
println!(); println!();
println!("\t{}", mnemonic.phrase()); println!("\t{}", mnemonic.phrase());
println!(); println!();

View File

@ -97,9 +97,9 @@ lighthouse --testnet medalla account wallet create
You will be prompted for a wallet name and a password. The output will look like this: You will be prompted for a wallet name and a password. The output will look like this:
``` ```
Your wallet's 12-word BIP-39 mnemonic is: Your wallet's 24-word BIP-39 mnemonic is:
thank beach essence clerk gun library key grape hotel wise dutch segment glad marble art pelican nurse large guilt response brave affair kite essence welcome gauge peace once picnic debris devote ticket blood bike solar junk
This mnemonic can be used to fully restore your wallet, should This mnemonic can be used to fully restore your wallet, should
you lose the JSON file or your password. you lose the JSON file or your password.
@ -114,12 +114,12 @@ a piece of paper and storing it in a safe place would be prudent.
Your wallet's UUID is: Your wallet's UUID is:
e762671a-2a33-4922-901b-62a43dbd5227 1c8c13d5-d065-4ef7-bad3-14e9d8146140
You do not need to backup your UUID or keep it secret. You do not need to backup your UUID or keep it secret.
``` ```
**Don't forget to make a backup** of the 12-word BIP-39 mnemonic. It can be **Don't forget to make a backup** of the 24-word BIP-39 mnemonic. It can be
used to restore your validator if there is a data loss. used to restore your validator if there is a data loss.
### 4.2 Create a Validator from the Wallet ### 4.2 Create a Validator from the Wallet

View File

@ -3,7 +3,7 @@
Lighthouse uses a _hierarchical_ key management system for producing validator Lighthouse uses a _hierarchical_ key management system for producing validator
keys. It is hierarchical because each validator key can be _derived_ from a keys. It is hierarchical because each validator key can be _derived_ from a
master key, making the validators keys _children_ of the master key. This master key, making the validators keys _children_ of the master key. This
scheme means that a single 12-word mnemonic can be used to backup all of your scheme means that a single 24-word mnemonic can be used to backup all of your
validator keys without providing any observable link between them (i.e., it is validator keys without providing any observable link between them (i.e., it is
privacy-retaining). Hierarchical key derivation schemes are common-place in privacy-retaining). Hierarchical key derivation schemes are common-place in
cryptocurrencies, they are already used by most hardware and software wallets cryptocurrencies, they are already used by most hardware and software wallets
@ -13,8 +13,10 @@ to secure BTC, ETH and many other coins.
We defined some terms in the context of validator key management: We defined some terms in the context of validator key management:
- **Mnemonic**: a string of 12-words that is designed to be easy to write down - **Mnemonic**: a string of 24 words that is designed to be easy to write down
and remember. E.g., _"enemy fog enlist laundry nurse hungry discover turkey holiday resemble glad discover"_. and remember. E.g., _"radar fly lottery mirror fat icon bachelor sadness
type exhaust mule six beef arrest you spirit clog mango snap fox citizen
already bird erase"_.
- Defined in BIP-39 - Defined in BIP-39
- **Wallet**: a wallet is a JSON file which stores an - **Wallet**: a wallet is a JSON file which stores an
encrypted version of a mnemonic. encrypted version of a mnemonic.
@ -49,7 +51,7 @@ In step (1), we created a wallet in `~/.lighthouse/wallets` with the name
Thanks to the hierarchical key derivation scheme, we can delete all of the Thanks to the hierarchical key derivation scheme, we can delete all of the
aforementioned directories and then regenerate them as long as we remembered aforementioned directories and then regenerate them as long as we remembered
the 12-word mnemonic (we don't recommend doing this, though). the 24-word mnemonic (we don't recommend doing this, though).
Creating another validator is easy, it's just a matter of repeating step (2). Creating another validator is easy, it's just a matter of repeating step (2).
The wallet keeps track of how many validators it has generated and ensures that The wallet keeps track of how many validators it has generated and ensures that

View File

@ -1,10 +1,10 @@
# Create a wallet # Create a wallet
A wallet allows for generating practically unlimited validators from an A wallet allows for generating practically unlimited validators from an
easy-to-remember 12-word string (a mnemonic). As long as that mnemonic is easy-to-remember 24-word string (a mnemonic). As long as that mnemonic is
backed up, all validator keys can be trivially re-generated. backed up, all validator keys can be trivially re-generated.
The 12-word string is randomly generated during wallet creation and printed out The 24-word string is randomly generated during wallet creation and printed out
to the terminal. It's important to **make one or more backups of the mnemonic** to the terminal. It's important to **make one or more backups of the mnemonic**
to ensure your ETH is not lost in the case of data loss. It very important to to ensure your ETH is not lost in the case of data loss. It very important to
**keep your mnemonic private** as it represents the ultimate control of your **keep your mnemonic private** as it represents the ultimate control of your