Optional Tor Send/Listen Functionality (#226)

* udpate for beta release

* initial tor explorations

* rustfmt

* basic tor tx send working

* rustfmt

* add tor proxy info to config file

* rustfmt

* add utilities to output tor hidden service configuration files

* output tor config as part of listener startup

* rustfmt

* fully automate config and startup of tor process

* rustfmt

* remove unnecessary process kill commands from listener

* rustfmt

* assume defaults for tor sending config if section doesn't exist in grin-wallet.toml

* rustfmt

* ignore tor dev test

* update default paths output by config, compilation + confirmed working on windows

* rustfmt

* fix on osx/unix

* add timeout to tor connector, remove unwrap in client

* allow specifiying tor address without 'http://[].onion' on the command line

* fix api test

* rustfmt

* update address derivation path as per spec

* rustfmt

* move tor init to separate function

* rustfmt

* re-ignore tor dev test

* listen on tor by default if tor available

* rustfmt

* test fix

* remove explicit send via tor flag, and assume tor if address fits

* rustfmt
This commit is contained in:
Yeastplume
2019-10-14 20:24:09 +01:00
committed by GitHub
parent c60301946f
commit b4eeb50c66
34 changed files with 2311 additions and 153 deletions
+44 -13
View File
@@ -60,8 +60,13 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
// add wallet to proxy
//let wallet1 = test_framework::create_wallet(&format!("{}/wallet1", test_dir), client1.clone());
let config1 = initial_setup_wallet(test_dir, "wallet1");
let (wallet1, mask1_i) =
instantiate_wallet(config1.clone(), client1.clone(), "password", "default")?;
let wallet_config1 = config1.clone().members.unwrap().wallet;
let (wallet1, mask1_i) = instantiate_wallet(
wallet_config1.clone(),
client1.clone(),
"password",
"default",
)?;
wallet_proxy.add_wallet(
"wallet1",
client1.get_send_instance(),
@@ -74,8 +79,13 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
execute_command(&app, test_dir, "wallet2", &client2, arg_vec.clone())?;
let config2 = initial_setup_wallet(test_dir, "wallet2");
let (wallet2, mask2_i) =
instantiate_wallet(config2.clone(), client2.clone(), "password", "default")?;
let wallet_config2 = config2.clone().members.unwrap().wallet;
let (wallet2, mask2_i) = instantiate_wallet(
wallet_config2.clone(),
client2.clone(),
"password",
"default",
)?;
wallet_proxy.add_wallet(
"wallet2",
client2.get_send_instance(),
@@ -137,8 +147,9 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
// Mine a bit into wallet 1 so we have something to send
// (TODO: Be able to stop listeners so we can test this better)
let wallet_config1 = config1.clone().members.unwrap().wallet;
let (wallet1, mask1_i) =
instantiate_wallet(config1.clone(), client1.clone(), "password", "default")?;
instantiate_wallet(wallet_config1, client1.clone(), "password", "default")?;
let mask1 = (&mask1_i).as_ref();
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
api.set_active_account(m, "mining")?;
@@ -211,8 +222,13 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
execute_command(&app, test_dir, "wallet1", &client1, arg_vec)?;
bh += 1;
let (wallet1, mask1_i) =
instantiate_wallet(config1.clone(), client1.clone(), "password", "default")?;
let wallet_config1 = config1.clone().members.unwrap().wallet;
let (wallet1, mask1_i) = instantiate_wallet(
wallet_config1.clone(),
client1.clone(),
"password",
"default",
)?;
let mask1 = (&mask1_i).as_ref();
// Check our transaction log, should have 10 entries
@@ -238,8 +254,13 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
execute_command(&app, test_dir, "wallet2", &client1, arg_vec)?;
// check results in wallet 2
let (wallet2, mask2_i) =
instantiate_wallet(config2.clone(), client2.clone(), "password", "default")?;
let wallet_config2 = config2.clone().members.unwrap().wallet;
let (wallet2, mask2_i) = instantiate_wallet(
wallet_config2.clone(),
client2.clone(),
"password",
"default",
)?;
let mask2 = (&mask2_i).as_ref();
grin_wallet_controller::controller::owner_single_use(wallet2.clone(), mask2, |api, m| {
@@ -296,8 +317,13 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
bh += 1;
// Check our transaction log, should have bh entries + one for the self receive
let (wallet1, mask1_i) =
instantiate_wallet(config1.clone(), client1.clone(), "password", "default")?;
let wallet_config1 = config1.clone().members.unwrap().wallet;
let (wallet1, mask1_i) = instantiate_wallet(
wallet_config1.clone(),
client1.clone(),
"password",
"default",
)?;
let mask1 = (&mask1_i).as_ref();
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
@@ -332,8 +358,13 @@ fn command_line_test_impl(test_dir: &str) -> Result<(), grin_wallet_controller::
bh += 1;
// Check our transaction log, should have bh entries + 2 for the self receives
let (wallet1, mask1_i) =
instantiate_wallet(config1.clone(), client1.clone(), "password", "default")?;
let wallet_config1 = config1.clone().members.unwrap().wallet;
let (wallet1, mask1_i) = instantiate_wallet(
wallet_config1.clone(),
client1.clone(),
"password",
"default",
)?;
let mask1 = (&mask1_i).as_ref();
grin_wallet_controller::controller::owner_single_use(wallet1.clone(), mask1, |api, m| {
+42 -17
View File
@@ -63,13 +63,23 @@ macro_rules! setup_proxy {
let arg_vec = vec!["grin-wallet", "-p", "password", "init", "-h"];
// should create new wallet file
let $client1 = LocalWalletClient::new("wallet1", wallet_proxy.tx.clone());
execute_command(&app, $test_dir, "wallet1", &$client1, arg_vec.clone())?;
let target = std::path::PathBuf::from(format!("{}/wallet1/grin-wallet.toml", $test_dir));
println!("{:?}", target);
if !target.exists() {
execute_command(&app, $test_dir, "wallet1", &$client1, arg_vec.clone())?;
}
// add wallet to proxy
let config1 = initial_setup_wallet($test_dir, "wallet1");
let wallet_config1 = config1.clone().members.unwrap().wallet;
//config1.owner_api_listen_port = Some(13420);
let ($wallet1, mask1_i) =
instantiate_wallet(config1.clone(), $client1.clone(), "password", "default")?;
let ($wallet1, mask1_i) = instantiate_wallet(
wallet_config1.clone(),
$client1.clone(),
"password",
"default",
)?;
let $mask1 = (&mask1_i).as_ref();
wallet_proxy.add_wallet(
"wallet1",
@@ -80,12 +90,21 @@ macro_rules! setup_proxy {
// Create wallet 2, which will run a listener
let $client2 = LocalWalletClient::new("wallet2", wallet_proxy.tx.clone());
execute_command(&app, $test_dir, "wallet2", &$client2, arg_vec.clone())?;
let target = std::path::PathBuf::from(format!("{}/wallet2/grin-wallet.toml", $test_dir));
if !target.exists() {
execute_command(&app, $test_dir, "wallet2", &$client2, arg_vec.clone())?;
}
let config2 = initial_setup_wallet($test_dir, "wallet2");
let wallet_config2 = config2.clone().members.unwrap().wallet;
//config2.api_listen_port = 23415;
let ($wallet2, mask2_i) =
instantiate_wallet(config2.clone(), $client2.clone(), "password", "default")?;
let ($wallet2, mask2_i) = instantiate_wallet(
wallet_config2.clone(),
$client2.clone(),
"password",
"default",
)?;
let $mask2 = (&mask2_i).as_ref();
wallet_proxy.add_wallet(
"wallet2",
@@ -150,7 +169,7 @@ pub fn config_command_wallet(
/// Handles setup and detection of paths for wallet
#[allow(dead_code)]
pub fn initial_setup_wallet(dir_name: &str, wallet_name: &str) -> WalletConfig {
pub fn initial_setup_wallet(dir_name: &str, wallet_name: &str) -> GlobalWalletConfig {
let mut current_dir;
current_dir = env::current_dir().unwrap_or_else(|e| {
panic!("Error creating config file: {}", e);
@@ -160,11 +179,7 @@ pub fn initial_setup_wallet(dir_name: &str, wallet_name: &str) -> WalletConfig {
let _ = fs::create_dir_all(current_dir.clone());
let mut config_file_name = current_dir.clone();
config_file_name.push("grin-wallet.toml");
GlobalWalletConfig::new(config_file_name.to_str().unwrap())
.unwrap()
.members
.unwrap()
.wallet
GlobalWalletConfig::new(config_file_name.to_str().unwrap()).unwrap()
}
fn get_wallet_subcommand<'a>(
@@ -247,10 +262,19 @@ pub fn execute_command(
) -> Result<String, grin_wallet_controller::Error> {
let args = app.clone().get_matches_from(arg_vec);
let _ = get_wallet_subcommand(test_dir, wallet_name, args.clone());
let mut config = initial_setup_wallet(test_dir, wallet_name);
let config = initial_setup_wallet(test_dir, wallet_name);
let mut wallet_config = config.clone().members.unwrap().wallet;
let tor_config = config.clone().members.unwrap().tor;
//unset chain type so it doesn't get reset
config.chain_type = None;
wallet_args::wallet_command(&args, config.clone(), client.clone(), true, |_| {})
wallet_config.chain_type = None;
wallet_args::wallet_command(
&args,
wallet_config.clone(),
tor_config,
client.clone(),
true,
|_| {},
)
}
// as above, but without necessarily setting up the wallet
@@ -283,11 +307,12 @@ where
let args = app.clone().get_matches_from(arg_vec);
let _ = get_wallet_subcommand(test_dir, wallet_name, args.clone());
let config = config::initial_setup_wallet(&ChainTypes::AutomatedTesting, None).unwrap();
let mut wallet_config = config.members.unwrap().wallet.clone();
let mut wallet_config = config.clone().members.unwrap().wallet;
wallet_config.chain_type = None;
wallet_config.api_secret_path = None;
wallet_config.node_api_secret_path = None;
wallet_args::wallet_command(&args, wallet_config, client.clone(), true, f)
let tor_config = config.members.unwrap().tor.clone();
wallet_args::wallet_command(&args, wallet_config, tor_config, client.clone(), true, f)
}
pub fn post<IN>(url: &Url, api_secret: Option<String>, input: &IN) -> Result<String, api::Error>
+2 -1
View File
@@ -4,7 +4,8 @@
"params": {
"chain_type": "AutomatedTesting",
"wallet_config": null,
"logging_config": null
"logging_config": null,
"tor_config": null
},
"id": 1
}
+9 -1
View File
@@ -59,7 +59,15 @@ fn owner_v2_sanity() -> Result<(), grin_wallet_controller::Error> {
});
// run the foreign listener for wallet 2
let arg_vec = vec!["grin-wallet", "-p", "password", "listen", "-l", "23415"];
let arg_vec = vec![
"grin-wallet",
"-p",
"password",
"listen",
"-l",
"23415",
"-n",
];
// Set owner listener running
thread::spawn(move || {
let yml = load_yaml!("../src/bin/grin-wallet.yml");
+7 -2
View File
@@ -72,9 +72,14 @@ fn owner_v3_lifecycle() -> Result<(), grin_wallet_controller::Error> {
execute_command(&app, test_dir, "wallet2", &client2, arg_vec.clone())?;
let config2 = initial_setup_wallet(test_dir, "wallet2");
let wallet_config2 = config2.clone().members.unwrap().wallet;
//config2.api_listen_port = 23415;
let (wallet2, mask2_i) =
instantiate_wallet(config2.clone(), client2.clone(), "password", "default")?;
let (wallet2, mask2_i) = instantiate_wallet(
wallet_config2.clone(),
client2.clone(),
"password",
"default",
)?;
wallet_proxy.add_wallet(
"wallet2",
client2.get_send_instance(),
+101
View File
@@ -0,0 +1,101 @@
// Copyright 2019 The Grin Developers
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_use]
extern crate clap;
#[macro_use]
extern crate log;
extern crate grin_wallet;
use grin_wallet_impls::test_framework::{self, LocalWalletClient, WalletProxy};
use grin_wallet_util::grin_core::global::{self, ChainTypes};
use clap::App;
use std::thread;
use std::time::Duration;
use grin_wallet_impls::DefaultLCProvider;
use grin_wallet_util::grin_keychain::ExtKeychain;
use grin_wallet_util::grin_util as util;
#[macro_use]
mod common;
use common::{execute_command, initial_setup_wallet, instantiate_wallet};
// Development testing helper for tor/socks investigation.
// Not (yet) to be run as part of automated testing
fn setup_no_clean() {
util::init_test_logger();
global::set_mining_mode(ChainTypes::AutomatedTesting);
}
#[ignore]
#[test]
fn socks_tor() -> Result<(), grin_wallet_controller::Error> {
let test_dir = "target/test_output/socks_tor";
let yml = load_yaml!("../src/bin/grin-wallet.yml");
let app = App::from_yaml(yml);
setup_no_clean();
setup_proxy!(test_dir, chain, wallet1, client1, mask1, wallet2, client2, _mask2);
// Tor should be running at this point for wallet 2, with a hidden service
// bound to the listening port 53415. By default, tor will also be running
// a socks proxy lister at 127.0.0.1 9050 (both wallets can use for now)
//
// Relevant torrc config:
// HiddenServiceDir ./hidden_service/
// HiddenServicePort 80 127.0.0.1:53415
//
// tor -f torrc
// Substitute whatever onion address has been created
let onion_address = "2a6at2obto3uvkpkitqp4wxcg6u36qf534eucbskqciturczzc5suyid";
// run the foreign listener for wallet 2
let arg_vec = vec!["grin-wallet", "-p", "password", "listen"];
// Set owner listener running
thread::spawn(move || {
let yml = load_yaml!("../src/bin/grin-wallet.yml");
let app = App::from_yaml(yml);
execute_command(&app, test_dir, "wallet2", &client2, arg_vec.clone()).unwrap();
});
// dumb pause for now, hidden service should already be running
thread::sleep(Duration::from_millis(3000));
// mine into wallet 1 a bit
let bh = 5u64;
let _ =
test_framework::award_blocks_to_wallet(&chain, wallet1.clone(), mask1, bh as usize, false);
// now, test send from wallet 1 over tor
let arg_vec = vec![
"grin-wallet",
"-p",
"password",
"send",
"-c",
"2",
"-d",
onion_address,
"10",
];
execute_command(&app, test_dir, "wallet1", &client1, arg_vec)?;
Ok(())
}