Skip to content

Commit

Permalink
Wallet creation: Make mnemonic length configurable, default to 24 wor…
Browse files Browse the repository at this point in the history
…ds. (#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
```
  • Loading branch information
goffrie authored and paulhauner committed Oct 3, 2020
1 parent 17c5da4 commit 8fde9a4
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 12 deletions.
30 changes: 28 additions & 2 deletions account_manager/src/wallet/create.rs
Expand Up @@ -23,6 +23,14 @@ pub const PASSWORD_FLAG: &str = "password-file";
pub const TYPE_FLAG: &str = "type";
pub const MNEMONIC_FLAG: &str = "mnemonic-output-path";
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 =
"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:";
Expand Down Expand Up @@ -78,6 +86,20 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
.long(STDIN_INPUTS_FLAG)
.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, wallet_base_dir: PathBuf) -> Result<(), String> {
Expand All @@ -86,7 +108,11 @@ pub fn cli_run(matches: &ArgMatches, wallet_base_dir: PathBuf) -> Result<(), Str
// Create a new random mnemonic.
//
// 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, &wallet_base_dir.as_path(), &mnemonic)?;

Expand All @@ -95,7 +121,7 @@ pub fn cli_run(matches: &ArgMatches, wallet_base_dir: PathBuf) -> Result<(), Str
.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!("\t{}", mnemonic.phrase());
println!();
Expand Down
8 changes: 4 additions & 4 deletions book/src/become-a-validator-source.md
Expand Up @@ -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:

```
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
you lose the JSON file or your password.
Expand All @@ -114,12 +114,12 @@ a piece of paper and storing it in a safe place would be prudent.
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.
```

**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.

### 4.2 Create a Validator from the Wallet
Expand Down
10 changes: 6 additions & 4 deletions book/src/key-management.md
Expand Up @@ -3,7 +3,7 @@
Lighthouse uses a _hierarchical_ key management system for producing validator
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
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
privacy-retaining). Hierarchical key derivation schemes are common-place in
cryptocurrencies, they are already used by most hardware and software wallets
Expand All @@ -13,8 +13,10 @@ to secure BTC, ETH and many other coins.

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
and remember. E.g., _"enemy fog enlist laundry nurse hungry discover turkey holiday resemble glad discover"_.
- **Mnemonic**: a string of 24 words that is designed to be easy to write down
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
- **Wallet**: a wallet is a JSON file which stores an
encrypted version of a mnemonic.
Expand Down Expand Up @@ -49,7 +51,7 @@ In step (1), we created a wallet in `~/.lighthouse/{testnet}/wallets` with the n

Thanks to the hierarchical key derivation scheme, we can delete all of the
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).
The wallet keeps track of how many validators it has generated and ensures that
Expand Down
4 changes: 2 additions & 2 deletions book/src/wallet-create.md
@@ -1,10 +1,10 @@
# Create a wallet

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.

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 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
Expand Down

0 comments on commit 8fde9a4

Please sign in to comment.