Skip to content

Commit

Permalink
feat(mnemonic): new mnemonic spec (#193)
Browse files Browse the repository at this point in the history
* Add rpassword and handle its errors

* Remove update cmd

* Fix error msgs

* Replace "stored" -> "existing"

* Update insert used by create and import: don't write export to file

* Update import: read mnemonic from terminal

* Update create: let insert() return error if mnemonic exists

* Don't export if export file already exists

* Update msgs

* Rename Noop->Existing

* Remove unused code

update, remove, exporting multiple file, importing files are no longer
needed

* Remove read from file operations

* Tidy mnemonic module's structure

Move cmd_handler outside of mods.rs
Construct exported file's in FileIo::new().

* Rename error.rs -> results.rs

* Misc

* Exit tofnd after executing `create`, `import` or `export`; continue on `existing`

* Use correct cmd in tests

* fix export test

* fix `init_party` in tests

* Check if export file exists before spinning tofnd daemon

* Remove `KeyErr` error and check against actual error types in tests

* Add some comments

* Better error message for already existing export file

* Fix error messages and misc

* Rename assert_not_exported->check_if_not_exported

* Fix tests comments and add a check

* Export mnemonic to a file after creation

* Resolve rebase conflicts

* Update src/gg20/mnemonic/cmd_handler.rs

Co-authored-by: Gus Gutoski <[email protected]>

* chore(devops): docker cmds (#201)

* automate actions in entrypoint

* Update entrypoint.sh

Co-authored-by: Gus Gutoski <[email protected]>

* Move usage comment

* Add tofnd home to .gitignore

* get tofnd path from args

* simplify args parsing

* rename unsafe composite to test

* remove unsafe args from default compose file

* Use auto mnemonic command

* Update comment

* Add new line at gitignore

Co-authored-by: Gus Gutoski <[email protected]>

* update readme (#200)

* update readme

* update binary execution

* fix typo

Co-authored-by: Gus Gutoski <[email protected]>

* simplify `auto` description

Co-authored-by: Gus Gutoski <[email protected]>

Co-authored-by: Gus Gutoski <[email protected]>

* use correct protofile

* resolve rebase conflicts about handle_remove

Co-authored-by: Gus Gutoski <[email protected]>
  • Loading branch information
sdaveas and ggutoski authored Oct 5, 2021
1 parent eccda2a commit 1410356
Show file tree
Hide file tree
Showing 22 changed files with 547 additions and 547 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
/.vscode
bin/tofnd*
bin/tofnd*
/.tofnd
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ VOLUME [ "/.tofnd" ]
ENV UNSAFE ""
ENV MNEMONIC_CMD ""
ENV NOPASSWORD ""
ENV TOFND_HOME ""
ENTRYPOINT ["/entrypoint.sh"]
61 changes: 46 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ git clone [email protected]:axelarnetwork/tofnd.git --recursive
# Running the server
```
$ cargo run
# init tofnd
$ ./tofnd -m create

# IMPORTANT: store the content of ./.tofnd/export file at a safe, offline place, and then delete the file
$ rm ./.tofnd/export

# start tofnd daemon
$ ./tofnd
```
Terminate the server with `ctrl+C`.
Expand Down Expand Up @@ -59,7 +66,8 @@ We use [clap](https://clap.rs/) to manage command line arguments.
Users can specify:
1. Tofnd's root folder. Use `--directory` or `-d` to specify a full or a relative path. If no argument is provided, then the environment variable `TOFND_HOME` is used. If no environment variable is set either, the default `./tofnd` directory is used.
2. The port number of the gRPC server (default is 50051).
3. `mnemonic` operations for their `tofnd` instance (default is `Create`).
3. The option to run in _unsafe_ mode. By default, this option is off, and safe primes are used for keygen. Use the `--unsafe` flag only for testing.
4. `mnemonic` operations for their `tofnd` instance (default is `Existing`).
For more information, see on mnemonic options, see [Mnemonic](#mnemonic).
4. The option to run in _unsafe_ mode. By default, this option is off, and safe primes are used for keygen. **Attention: Use the `--unsafe` flag only for testing**.
5. By default, `tofnd` expects a password from the standard input. Users that don't want to use passwords can use the `--no-password` flag. **Attention: Use `--no-password` only for testing .**
Expand All @@ -79,30 +87,57 @@ FLAGS:

OPTIONS:
-d, --directory <directory> [env: TOFND_HOME=] [default: .tofnd]
-m, --mnemonic <mnemonic> [default: create] [possible values: stored, create, import, update, export]
-m, --mnemonic <mnemonic> [default: existing] [possible values: existing, create, import, export]
-p, --port <port> [default: 50051]]
```
# Docker
To run `tofnd` inside a container, run:
## Setup
To setup a `tofnd` container, use the `create` mnemonic command:
```
docker-compose up
docker-compose run -e MNEMONIC_CMD=create tofnd
```
For testing purposes, `docker-compose.unsafe.yml` is available which is equivelent to `cargo run -- --unsafe`. To create an unsafe `tofnd` container, run
This will initialize `tofnd`, and then exit.
## Execution
To run a `tofnd` daemon inside a container, run:
```
docker-compose -f docker-compose.unsafe.yml up
docker-compose up
```
## Storage
We use [data containers](https://docs.docker.com/engine/reference/commandline/volume_create/) to persist data across restarts. To clean up storage, remove all `tofnd` containers, and run
```
docker volume rm tofnd_tofnd
```
## Testing
For testing purposes, `docker-compose.test.yml` is available, which is equivelent to `./tofnd --no-password --unsafe`. To spin up a test `tofnd` container, run
```
docker-compose -f docker-compose.test.yml up
```
## The `auto` command
In containerized environments the `auto` mnemonic command can be used. This command is implemented in `entrypoint.sh` and does the following:
1. Try to use existing mnemonic. If successful then launch `tofnd` server.
2. Try to import a mnemonic from file. If successful then launch `tofnd` server.
3. Create a new mnemonic. The newly created mnemonic is automatically written to the file `TOFND_HOME/export`---rename this file to `TOFND_HOME/import` so as to unblock future executions of tofnd. Then launch `tofnd` server.
The rationale behind `auto` is that users can frictionlessly launch and restart their tofnd nodes without the need to execute multiple commands.
`auto` is currently the default command only in `docker-compose.test.yml`, but users can edit the `docker-compose.yml` to use it at their own discretion.
**Attention:** `auto` leaves the mnemonic on plain text on disk. You should remove the `TOFND_HOME/import` file and store the mnemonic at a safe, offline place.
# Mnemonic
`Tofnd` uses the [tiny-bip39](https://docs.rs/crate/tiny-bip39/0.8.0) crate to enable users manage mnemonic passphrases. Currently, each party can use only one passphrase.
Expand All @@ -113,17 +148,13 @@ Mnemonic is used to enable _recovery_ of shares in case of unexpected loss. See
The command line API supports the following commands:
* `Noop` does nothing and always succeeds; useful when the container restarts with the same mnemonic.
* `Create` creates a new mnemonic if there none exists, otherwise does nothing. The new passphrase is written in a file named _./tofnd/export_.
* `Import` adds a new mnemonic from file _./tofnd/import_ file; Succeeds when there is no other mnemonic already imported, fails otherwise.
* `Existing` Starts the gRPC daemon using an existing mnemonic; Fails if no mnemonic exist.
* `Export` writes the existing mnemonic to file _./tofnd/export_; Succeeds when there is an existing mnemonic, fails otherwise.
* `Create` Creates a new mnemonic, inserts it in the kv-store, exports it to a file and exits; Fails if a mnemonic already exists.
* `Update` updates existing mnemonic from file _./tofnd/import_; Succeeds when there is an existing mnemonic, fails otherwise. The old passphrase is written to file _./export_.
* `Import` Prompts user to give a new mnemonic from standard input, inserts it in the kv-store and exits; Fails if a mnemonic exists or if the provided string is not a valid bip39 mnemonic.
If a _./tofnd/export_ file already exists, then a new one is created with a new id, e.g. _./tofnd/export_2_, _./tofnd/export_3_, etc.
* `Export` Writes the existing mnemonic to _<tofnd_root>/.tofnd/export_ and exits; Succeeds when there is an existing mnemonic. Fails if no mnemonic is stored, or the export file already exists.
## Zeroization
Expand Down
9 changes: 8 additions & 1 deletion docker-compose.unsafe.yml → docker-compose.test.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
# usage:
# $ docker-compose up
# or
# $ docker-compose -f docker-compose.test.yml run -e MNEMONIC_CMD=<mnemonic_cmd> tofnd

volumes:
tofnd:

services:
tofnd:
build: .
container_name: tofnd
container_name: tofnd-test
hostname: tofnd
image: axelar/tofnd
volumes:
Expand All @@ -13,3 +18,5 @@ services:
# Attention! Use UNSAFE=true only for testing
- UNSAFE=true
- NOPASSWORD=true
- MNEMONIC_CMD=auto
- TOFND_HOME=.tofnd
11 changes: 7 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# usage:
# $ docker-compose up
# or
# $ docker-compose run -e MNEMONIC_CMD=<mnemonic_cmd> tofnd

volumes:
tofnd:

Expand All @@ -10,7 +15,5 @@ services:
volumes:
- tofnd:/.tofnd
environment:
# ATTENTION: use --unsafe only for testing
- UNSAFE=true
# available cmds: create (default), stored, update, import, export
- MNEMONIC_CMD=create
# available cmds: auto, create, existing (default), import, export
- MNEMONIC_CMD=auto
108 changes: 100 additions & 8 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,106 @@

set -e

OK=0
ERR=1

# create: create a new mnemonic, export it to a file under the name "import" and continue
create_mnemonic() {
echo "Creating mnemonic ..."
${PASSWORD} | tofnd ${ARGS} -m create && mv $EXPORT_PATH $IMPORT_PATH && echo "... ok" && return $OK
return $ERR
}

# import: import a mnemonic from $IMPORT_PATH and continue
import_mnemonic() {
echo "Importing mnemonic ..."

# check if import file exists
if [ ! -f "$IMPORT_PATH" ]; then \
echo "No import file found at $IMPORT_PATH"
return $ERR
fi

# check if password exists
if [ -n "${NOPASSWORD}" ]; then \
echo "No password"
(cat $IMPORT_PATH | tofnd ${ARGS} -m import) || return $ERR
else
echo "With password"
# TODO: provide actual password here
((echo $PASSWORD && cat $IMPORT_PATH) | tofnd ${ARGS} -m import) || return $ERR
fi
echo "... ok"
return $OK
}
# export: export the mnemonic to $EXPORT_PATH, move it to $IMPORT_PATH and exit
export_mnemonic() {
echo "Exporting mnemonic ..."
echo ${PASSWORD} | tofnd ${ARGS} -m export && mv $EXPORT_PATH $IMPORT_PATH || return $ERR
echo "... ok"
return $OK
}
# TODO: get actual password from user. See https://github.com/axelarnetwork/axelarate/issues/269.
PASSWORD=""
# gather user's args
ARGS=""
if [ -n "${NOPASSWORD}" ]; then \
ARGS="$ARGS --no-password"; \
fi
if [ -n "${UNSAFE}" ]; then \
ARGS="$ARGS --unsafe"; \
fi
# set tofnd root. TOFND_HOME can be set to a different path by the user.
TOFND_HOME=${TOFND_HOME:-"./.tofnd"}
IMPORT_PATH=$TOFND_HOME/import
EXPORT_PATH=$TOFND_HOME/export
echo "Using tofnd root:" $TOFND_HOME
# add '--no-password' and '--unsafe' flags to args if enabled
ARGS=${NOPASSWORD:+"${ARGS} --no-password"}
# add '--unsafe' flag to args if enabled
ARGS=${UNSAFE:+"${ARGS} --unsafe"}
# check mnemonic arg
if [ -n "${MNEMONIC_CMD}" ]; then \
ARGS="$ARGS -m $MNEMONIC_CMD"; \
case ${MNEMONIC_CMD} in
# auto: try to set up tofnd and then spin up tofnd with the existing mnemonic.
# Order of set up: 1) import mnemonic, 2) create mnemonic.
auto)
echo "Trying import" && import_mnemonic \
|| (echo "... skipping. Trying to create" && create_mnemonic) \
|| echo "... skipping"
;;
existing)
;;
create)
create_mnemonic || exit $ERR
exit $OK
;;
import)
import_mnemonic || exit $ERR
exit $OK
;;
export)
export_mnemonic || exit $ERR
exit $OK
;;
*)
echo "Unknown command: ${MNEMONIC_CMD}"
exit $ERR
;;
esac
echo "Using existing mnemonic ..."
ARGS="${ARGS} -m existing"
fi
exec tofnd $ARGS "$@"; \
# execute tofnd daemon
exec echo ${PASSWORD} | tofnd ${ARGS} "$@"; \
2 changes: 1 addition & 1 deletion proto
Submodule proto updated 0 files
6 changes: 3 additions & 3 deletions src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use anyhow::anyhow;
// TODO: move these into constants.rs
const DEFAULT_PATH_ROOT: &str = ".tofnd";
const TOFND_HOME_ENV_VAR: &str = "TOFND_HOME";
const DEFAULT_MNEMONIC_CMD: &str = "create";
const DEFAULT_MNEMONIC_CMD: &str = "existing";
const DEFAULT_PORT: &str = "50051";
const AVAILABLE_MNEMONIC_CMDS: [&str; 5] = ["stored", "create", "import", "update", "export"];
const AVAILABLE_MNEMONIC_CMDS: [&str; 4] = ["existing", "create", "import", "export"];

#[cfg(feature = "malicious")]
mod malicious;
Expand All @@ -32,7 +32,7 @@ impl Default for Config {
Config {
port: 50051,
safe_keygen: true,
mnemonic_cmd: Cmd::Noop,
mnemonic_cmd: Cmd::Existing,
tofnd_path: DEFAULT_PATH_ROOT.to_string(),
password_method: PasswordMethod::Prompt,
#[cfg(feature = "malicious")]
Expand Down
7 changes: 3 additions & 4 deletions src/gg20/mnemonic/bip39_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
//!
//! Zeroization:
//! All functions that accept and/or return structs that implement zeroization:
//! [super::Password], [super::Entropy], [bip39::Mnemonic], [bip39::Seed]
//! [crate::gg20::Password], [crate::gg20::Entropy], [bip39::Mnemonic], [bip39::Seed]
use super::error::bip39::{Bip39Error::*, Bip39Result};
use super::Entropy;
use crate::gg20::types::Password;
use super::results::bip39::{Bip39Error::*, Bip39Result};
use crate::gg20::types::{Entropy, Password};
use bip39::{Language, Mnemonic, Seed};

// TODO: we can enrich the API so that users can decide which language they want to use
Expand Down
Loading

0 comments on commit 1410356

Please sign in to comment.