diff --git a/.gitignore b/.gitignore index fd2fef5..e03bfd4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ target *.iml .idea/ .vscode/ + +mwixnet-config.toml \ No newline at end of file diff --git a/README.md b/README.md index 8db7fd4..49d3972 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,20 @@ This is an implementation of @tromp's [CoinSwap Proposal](https://forum.grin.mw/ A set of n CoinSwap servers (nodei with i=1...n) are agreed upon in advance. They each have a known public key. +### Setup +#### init-config +To setup a new server, run `mwixnet --pass "server-password-here" init-config`. +This will generate a key for the server and then create a new config file named `mwixnet-config.toml` in the current working directory. +The configuration file will contain the private key of the server encrypted with the server password you provided. + +**Back this config file up! It's the only copy of the server's private key!** + +#### Wallet +A grin-wallet account must be created for receiving extra mwixnet fees. + +### Usage +With your wallet and fully synced node both online and listening at the addresses configured, the mwixnet server can be started by running `mwixnet --pass "server-password-here" --wallet_pass "wallet-password-here"` + ### SWAP API The first CoinSwap server (n1) provides the `swap` API, publicly available for use by GRIN wallets. diff --git a/src/config.rs b/src/config.rs index 2369c88..4f931a2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,22 +14,31 @@ use std::path::PathBuf; // The decrypted server config to be passed around and used by the rest of the mwixnet code #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] pub struct ServerConfig { + /// private key used by the server to decrypt onion packets pub key: SecretKey, + /// interval (in seconds) to wait before each mixing round pub interval_s: u32, + /// socket address the server listener should bind to pub addr: SocketAddr, + /// foreign api address of the grin node pub grin_node_url: SocketAddr, + /// owner api address of the grin wallet pub wallet_owner_url: SocketAddr, } -/// Encrypted server key, for storing on disk and decrypting with provided password +/// Encrypted server key, for storing on disk and decrypting with a password. +/// Includes a salt used by key derivation and a nonce used when sealing the encrypted data. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] struct EncryptedServerKey { encrypted_key: String, - pub salt: String, - pub nonce: String, + salt: String, + nonce: String, } impl EncryptedServerKey { + /// Generates a random salt for pbkdf2 key derivation and a random nonce for aead sealing. + /// Then derives an encryption key from the password and salt. Finally, it encrypts and seals + /// the server key with chacha20-poly1305 using the derived key and random nonce. pub fn from_secret_key( server_key: &SecretKey, password: &ZeroingString, @@ -104,13 +113,13 @@ impl EncryptedServerKey { /// The config attributes saved to disk #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] struct RawConfig { - pub encrypted_key: String, - pub salt: String, - pub nonce: String, - pub interval_s: u32, - pub addr: SocketAddr, - pub grin_node_url: SocketAddr, - pub wallet_owner_url: SocketAddr, + encrypted_key: String, + salt: String, + nonce: String, + interval_s: u32, + addr: SocketAddr, + grin_node_url: SocketAddr, + wallet_owner_url: SocketAddr, } /// Writes the server config to the config_path given, encrypting the server_key first. diff --git a/src/main.rs b/src/main.rs index 4704a92..7211b91 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use wallet::HttpWallet; use clap::App; use grin_util::{StopState, ZeroingString}; use std::env; +use std::io::{self, Write}; use std::path::PathBuf; use std::sync::Arc; @@ -26,7 +27,16 @@ mod wallet; const DEFAULT_INTERVAL: u32 = 12 * 60 * 60; -fn main() -> std::result::Result<(), Box> { +fn main() { + if let Err(e) = real_main() { + io::stderr().write_all(format!("mwixnet server exited with error:\n{}\n", e).as_bytes()).unwrap(); + std::process::exit(1); + } + + std::process::exit(0); +} + +fn real_main() -> std::result::Result<(), Box> { let yml = load_yaml!("../mwixnet.yml"); let args = App::from_yaml(yml).get_matches(); @@ -61,6 +71,7 @@ fn main() -> std::result::Result<(), Box> { }; config::write_config(&config_path, &server_config, &password)?; + println!("Config file written to {:?}. Please back this file up in a safe place.", config_path); return Ok(()); }