Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 3 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ This will launch the interactive prompt. Type `help` to get a list of commands.

## Notes:
* If you want to run your own server, please see [zingo lightwalletd](https://github.com/zingolabs/lightwalletd), and then run `./zingo-cli --server http://127.0.0.1:9067`
* The log file is in `~/.zcash/zingo-wallet.debug.log`. Wallet is stored in `~/.zcash/zingo-wallet.dat`
* The default log file is in `~/.zcash/zingo-wallet.debug.log`. A default wallet is stored in `~/.zcash/zingo-wallet.dat`
* Currently, the default, hard-coded `lightwalletd` server is https://lwdv3.zecwallet.co:443/. To change this, you can modify line 25 of `lib/src/lightclient/lightclient_config.rs`

## Running in non-interactive mode:
Expand All @@ -66,50 +66,6 @@ Here are some CLI arguments you can pass to `zingo-cli`. Please run `zingo-cli -
* Example: `./zingo-cli --server 127.0.0.1:9067 --data-dir /Users/ZingoRocks/my-test-wallet` will use the provided directory to store `zingo-wallet.dat` and logs. If the provided directory does not exist, it will create it.

## Regtest
Experimental!
We have recently added support for `Network::Regtest` enum: https://github.com/zcash/librustzcash/blob/main/zcash_primitives/src/constants/regtest.rs
This has not been sufficiently tested, but now compiles.
There is an experimental feature flag available with `zingo-cli`, in which the cli works in regtest mode, by also locally running `zcashd` and `lightwalletd`.

This documentation to run regtest "manually" is a placeholder until flags are more functional.
We also aim to be able to select any network type with cli flags.

The CLI can work in regtest mode, by locally running a `zcashd` and `lightwalletd`.

For example:
Create the directories `~/.zcash/zd/` and `~/.zcash/ld`
`zcashd` works in regtest with the following invocation, run from your `zcash` directory (explicit path, substitute your own username):
`./src/zcashd --printtoconsole -conf=/home/username/.zcash/zd/zcash.conf --datadir=/home/username/.zcash/zd/`
and the following in a `zcash.conf` file in the specified directory:
```
regtest=1
nuparams=5ba81b19:1 # Overwinter
nuparams=76b809bb:1 # Sapling
nuparams=2bb40e60:1 # Blossom
nuparams=f5b9230b:1 # Heartwood
nuparams=e9ff75a6:1 # Canopy
nuparams=c2d6d0b4:1 # NU5

txindex=1
insightexplorer=1
experimentalfeatures=1
rpcuser=xxxxxx
rpcpassword=xxxxxx

rpcport=18232
rpcallowip=127.0.0.1
```

In another terminal instance, navigate to your `lightwalletd` directory, and run
`./lightwalletd --no-tls-very-insecure --zcash-conf-path ~/.zcash/zd/zcash.conf --data-dir ~/.zcash/zd/ --log-file ~/.zcash/ld/lwd-log --log-level 7`
`lightwalletd`'s terminal output will not have clear success, but the log file will show something like:
`{"app":"lightwalletd","level":"info","msg":"Got sapling height 1 block height 0 chain regtest ..."}`

Now you will need to add blocks to your regtest chain if you have not done so previously.
In still another terminal instance in the `zcash` directory, you can run `./src/zcash-cli -regtest generate 11` to generate 11 blocks.
Please note that by adding more than 100 blocks it is difficult or impossible to rewind the chain. The config means that after the first block all network upgrades should be in place.

Finally, from your `zingolib` directory, with a release build (`cargo build --release`), you can run:
`./target/release/zingo-cli --regtest --server=127.0.0.1:9067`
You should see a single line printed out saying `regtest detected and network set correctly!` and the interactive cli application should work with your regtest network!

Tested with `zcash` commit `1e6f46`, `lightwalletd` commit `db2795`, and `zingolib` commit `252abe` or better.
Please see `zingolib/regtest/README.md` for a detailed explanation.
2 changes: 1 addition & 1 deletion cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ pub fn startup(
// Try to get the configuration
let (config, latest_block_height) = ZingoConfig::create_on_data_dir(server.clone(), data_dir)?;

// check for regtest flag and network in config.
// Diagnostic check for regtest flag and network in config, panic if mis-matched.
if regtest && config.chain == Network::Regtest {
println!("regtest detected and network set correctly!");
} else if regtest && config.chain != Network::Regtest {
Expand Down
223 changes: 221 additions & 2 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::thread::spawn;

use log::error;
use zingo_cli::{
attempt_recover_seed, configure_clapapp, report_permission_error, start_interactive, startup,
Expand Down Expand Up @@ -52,6 +54,225 @@ pub fn main() {
}
};

let regtest = matches.is_present("regtest");
if regtest {
use std::ffi::OsString;
use std::fs::File;
use std::io;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::{thread, time};

// confirm we are in a git directory, get info on it
let revparse_raw = Command::new("git")
.args(["rev-parse", "--show-toplevel"])
.output()
.expect("no git!? time to quit.");

let revparse = std::str::from_utf8(&revparse_raw.stdout).expect("revparse error");

let ident_raw = Command::new("git")
.args(["var", "GIT_AUTHOR_IDENT"])
.output()
.expect("problem ident. cannot invent!");

let ident = std::str::from_utf8(&ident_raw.stdout).expect("ident error");
// stand in for zingolabs.
if ident.starts_with("dannasessha <sessha@zingolabs.com>") {
// proceed
} else {
panic!("Zingo-cli's regtest mode must be run within its git tree");
}

// Cross-platform OsString
let mut worktree_home = OsString::new();
worktree_home.push(revparse.trim_end());

// convert this back into a path for windows compatibile dir building
let bin_location: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("bin"),
]
.iter()
.collect();

let zcash_confs: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("conf"),
OsString::from(""),
]
.iter()
.collect();

let mut flagged_zcashd_conf: String = "--conf=".to_string();
flagged_zcashd_conf.push_str(zcash_confs.to_str().expect("error making zcash_datadir"));
flagged_zcashd_conf.push_str("zcash.conf");

let zcash_datadir: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("datadir"),
OsString::from("zcash"),
OsString::from(""),
]
.iter()
.collect();

let mut flagged_datadir: String = "--datadir=".to_string();
flagged_datadir.push_str(zcash_datadir.to_str().expect("error making zcash_datadir"));

let mut zcash_logs: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("logs"),
OsString::from(""),
]
.iter()
.collect();

let mut zcashd_bin = bin_location.to_owned();
zcashd_bin.push("zcashd");

// TODO reorg code, look for all needed bins ASAP
// check for file. This might be superfluous considering
// .expect() attached to the call, below?
if !std::path::Path::is_file(zcashd_bin.as_path()) {
panic!("can't find zcashd bin! exiting.");
}

println!("zcashd datadir: {}", &flagged_datadir);
println!("zcashd conf file: {}", &flagged_zcashd_conf);
let mut zcashd_command = Command::new(zcashd_bin)
.args([
"--printtoconsole",
&flagged_zcashd_conf,
&flagged_datadir,
// Right now I can't get zcashd to write to debug.log with this flag
//"-debuglogfile=.../zingolib/regtest/logs/debug.log",
//debug=1 will at least print to stdout
"-debug=1",
])
// piping stdout off...
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.expect("failed to start zcashd");

// ... to ... here
if let Some(mut zcashd_log) = zcashd_command.stdout.take() {
std::thread::spawn(move || {
let mut zcashd_stdout_log: String = String::new();
zcashd_stdout_log.push_str(zcash_logs.to_str().expect("error converting to str"));
zcashd_stdout_log.push_str("zcashd_stdout.log");

let mut zcashd_logfile =
File::create(zcashd_stdout_log).expect("file::create Result error");
std::io::copy(&mut zcashd_log, &mut zcashd_logfile)
.expect("io::copy error writing zcashd_studout.log");
});
}
println!("zcashd is starting in regtest mode, please standby about 10 seconds...");
// wait 10 seconds for zcashd to fire up
// very generous, plan to tune down
let ten_seconds = time::Duration::from_millis(10_000);
thread::sleep(ten_seconds);

// TODO this process does not shut down when rust client shuts down!
// Needs a cleanup function, or something.
println!("zcashd start section completed, zcashd should be running.");
println!("Standby, lightwalletd is about to start. This should only take a moment.");

let mut lwd_bin = bin_location.to_owned();
lwd_bin.push("lightwalletd");

if !std::path::Path::is_file(lwd_bin.as_path()) {
panic!("can't find lwd bin! exiting.");
}

let lwd_confs: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("conf"),
OsString::from(""),
]
.iter()
.collect();

let mut unflagged_lwd_conf: String = String::new();
unflagged_lwd_conf.push_str(lwd_confs.to_str().expect("trouble making flagged_lwd_conf"));
unflagged_lwd_conf.push_str("lightwalletdconf.yml");

// for lwd config
let mut unflagged_zcashd_conf: String = String::new();
unflagged_zcashd_conf.push_str(
zcash_confs
.to_str()
.expect("error making unflagged zcash conf"),
);
unflagged_zcashd_conf.push_str("zcash.conf");

let lwd_datadir: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("datadir"),
OsString::from("lightwalletd"),
OsString::from(""),
]
.iter()
.collect();

let mut unflagged_lwd_datadir: String = String::new();
unflagged_lwd_datadir.push_str(lwd_datadir.to_str().expect("error making lwd_datadir"));

let lwd_logs: PathBuf = [
worktree_home.clone(),
OsString::from("regtest"),
OsString::from("logs"),
OsString::from(""),
]
.iter()
.collect();
let mut unflagged_lwd_log: String = String::new();
unflagged_lwd_log.push_str(lwd_logs.to_str().expect("error making lwd_datadir"));
unflagged_lwd_log.push_str("lwd.log");

let lwd_command = Command::new(lwd_bin)
.args([
"--no-tls-very-insecure",
"--zcash-conf-path",
&unflagged_zcashd_conf,
"--config",
&unflagged_lwd_conf,
"--data-dir",
&unflagged_lwd_datadir,
"--log-file",
&unflagged_lwd_log,
])
// this will print stdout of lwd process' output also to the zingo-cli stdout
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()
.expect("failed to start lwd");

// this client's stdout is less verbose so logging it may not be needed along with the working lwd.log file.
//let mut lwd_stdout_logfile =
//File::create("/zingolib/regtest/logs/lwd-ping.log").unwrap();
// the next line is a halting process..
//io::copy(&mut lwd_command.stdout.unwrap(), &mut lwd_stdout_logfile).unwrap();

// wait 5 seconds for lwd to fire up
// very generous, plan to tune down
let five_seconds = time::Duration::from_millis(5_000);
thread::sleep(five_seconds);

// this process does not shut down when rust client shuts down!
// TODO Needs a cleanup function, or something.
println!("lwd start section completed, lightwalletd should be running!");
println!("Standby, Zingo-cli should be running in regtest mode momentarily...");
}

let server = ZingoConfig::get_server_or_default(maybe_server);

// Test to make sure the server has all of scheme, host and port
Expand All @@ -65,8 +286,6 @@ pub fn main() {

let nosync = matches.is_present("nosync");

let regtest = matches.is_present("regtest");

let startup_chan = startup(
server,
seed,
Expand Down
Loading