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(());
}