Skip to content

Commit

Permalink
better terminal output (nexus-xyz#77)
Browse files Browse the repository at this point in the history
* initial impl of tui

* integrate tui with prover

* improve env

* better time formatting

* build artifact in prove command

* use tui in tools

* stray comment

* remove verification from prove commands
  • Loading branch information
slumber authored Feb 22, 2024
1 parent 476980f commit 9e4b09e
Show file tree
Hide file tree
Showing 22 changed files with 1,261 additions and 136 deletions.
571 changes: 560 additions & 11 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"vm",
"tools",
"tools/tools-dev",
"tools/tui",
"config",
"config/serde_wrapper",
"prover",
Expand Down
4 changes: 1 addition & 3 deletions config/bases/rust.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
RUST_LOG="""\
nexus-network=debug,\
nexus-prover=info,\
nexus-tools-dev=debug,\
nexus-nova::sequential=debug,\
nexus-nova::pcd=debug\
nexus-tools-dev=debug\
"""

RUST_BACKTRACE="full"
Expand Down
1 change: 1 addition & 0 deletions prover/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ zstd = { version = "0.12", default-features = false }

nexus-vm = { path = "../vm" }
nexus-nova = { path = "../nova", features = ["spartan"] }
nexus-tui = { path = "../tools/tui" }

tracing = "0.1"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
Expand Down
105 changes: 55 additions & 50 deletions prover/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,61 +47,79 @@ pub fn run(opts: &VMOpts, pow: bool) -> Result<Trace, ProofError> {
}

pub fn prove_seq(pp: &SeqPP, trace: Trace) -> Result<IVCProof, ProofError> {
let k = trace.k;
// let k = trace.k;
let tr = Tr(trace);
let icount = tr.instructions();
let z_0 = tr.input(0)?;
let mut proof = IVCProof::new(pp, &z_0);

println!("\nProving Execution Trace:");
println!("step. {:7} {:8} {:32} time", "pc", "mem[pc]", "inst");

let start = Instant::now();

let num_steps = tr.steps();
for i in 0..num_steps {
print!("{:4}. {:51}", i, format!("{} instructions...", k));
io::stdout().flush().unwrap();

let t = Instant::now();
proof = IVCProof::prove_step(proof, &tr)?;
let mut term = nexus_tui::TerminalHandle::new();
let mut term_ctx = term
.context("Computing")
.on_step(|step| format!("step {step}"))
.num_steps(num_steps)
.with_loading_bar("Proving")
.completion_header("Proved")
.completion_stats(move |elapsed| {
format!(
"{num_steps} step(s) in {elapsed}; {:.2} instructions / second",
icount as f32 / elapsed.as_secs_f32()
)
});

for _ in 0..num_steps {
let _guard = term_ctx.display_step();

println!(
"{:?} {:0.2}%",
t.elapsed(),
((i + 1) as f32) * 100.0 / (num_steps as f32)
);
proof = IVCProof::prove_step(proof, &tr)?;
}
println!(
"\nProof Complete: {:.2} instructions / second",
icount as f64 / start.elapsed().as_secs_f64()
);

print!("\nVerifying Proof... ");
io::stdout().flush().unwrap();
let t = Instant::now();
proof.verify(num_steps).expect("verify"); // TODO add verify errors?
println!("{:?}", t.elapsed());
Ok(proof)
}

pub fn prove_par(pp: ParPP, trace: Trace) -> Result<PCDNode, ProofError> {
let k = trace.k;
let tr = Tr(trace);

let steps = tr.steps();
println!("\nproving {steps} steps...");

let start = Instant::now();

let mut vs = (0..steps)
let num_steps = tr.steps();
assert!((num_steps + 1).is_power_of_two());

let on_step = move |iter: usize| {
let b = (num_steps + 1).ilog2();
let a = b - 1 - (num_steps - iter).ilog2();

let step = 2usize.pow(a + 1) * iter - (2usize.pow(a) - 1) * (2usize.pow(b + 1) - 1);
let step_type = if iter <= num_steps / 2 {
"leaf"
} else if iter == num_steps - 1 {
"root"
} else {
"node"
};
format!("{step_type} {step}")
};

let mut term = nexus_tui::TerminalHandle::new();
let mut term_ctx = term
.context("Computing")
.on_step(on_step)
.num_steps(num_steps)
.with_loading_bar("Proving")
.completion_header("Proved")
.completion_stats(move |elapsed| {
format!(
"tree root in {elapsed}; {:.2} instructions / second",
(k * num_steps) as f32 / elapsed.as_secs_f32()
)
});

let mut vs = (0..num_steps)
.step_by(2)
.map(|i| {
print!("leaf step {i}... ");
io::stdout().flush().unwrap();
let t = Instant::now();
let _guard = term_ctx.display_step();

let v = PCDNode::prove_step(&pp, &tr, i, &tr.input(i)?)?;
println!("{:?}", t.elapsed());
Ok(v)
})
.collect::<Result<Vec<_>, ProofError>>()?;
Expand All @@ -110,29 +128,16 @@ pub fn prove_par(pp: ParPP, trace: Trace) -> Result<PCDNode, ProofError> {
if vs.len() == 1 {
break;
}
println!("proving {} vertex steps", vs.len() / 2);
vs = vs
.chunks(2)
.map(|ab| {
print!("vertex step ... ");
io::stdout().flush().unwrap();
let t = Instant::now();
let _guard = term_ctx.display_step();

let c = PCDNode::prove_from(&pp, &tr, &ab[0], &ab[1])?;
println!("{:?}", t.elapsed());
Ok(c)
})
.collect::<Result<Vec<_>, ProofError>>()?;
}

println!(
"\nProof Complete: {:.2} instructions / second",
(k * tr.steps()) as f64 / start.elapsed().as_secs_f64()
);

print!("\nVerifying root... ");
io::stdout().flush().unwrap();
let t = Instant::now();
vs[0].verify(&pp)?;
println!("{:?}", t.elapsed());
Ok(vs.into_iter().next().unwrap())
}
25 changes: 19 additions & 6 deletions prover/src/pp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ pub fn gen_to_file(k: usize, par: bool, pp_file: &str) -> Result<(), ProofError>
path = ?pp_file,
"Generating public parameters",
);
let mut term = nexus_tui::TerminalHandle::new();
let mut term_ctx = term
.context("Setting up")
.on_step(|_step| "public parameters".into());
let _guard = term_ctx.display_step();

if par {
let pp: ParPP = gen_vm_pp(k)?;
Expand All @@ -85,26 +90,34 @@ pub fn gen_or_load<SP>(gen: bool, k: usize, pp_file: &str) -> Result<PP<SP>, Pro
where
SP: SetupParams<G1, G2, C1, C2, RO, Tr> + Sync,
{
let t = std::time::Instant::now();
let mut term = nexus_tui::TerminalHandle::new();

let pp: PP<SP> = if gen {
tracing::info!(
target: LOG_TARGET,
"Generating public parameters",
);
let mut term_ctx = term
.context("Setting up")
.on_step(|_step| "public parameters".into());
let _guard = term_ctx.display_step();

gen_vm_pp(k)?
} else {
tracing::info!(
target: LOG_TARGET,
path = ?pp_file,
"Loading public parameters",
);
let mut term_ctx = term
.context("Loading")
.on_step(|_step| "public parameters".into());
let _guard = term_ctx.display_step();

load_pp(pp_file)?
};
tracing::info!(
target: LOG_TARGET,
"Done in {:?}",
t.elapsed(),
);
drop(term);

show_pp(&pp);
Ok(pp)
}
4 changes: 2 additions & 2 deletions tools/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ tracing = { version = "0.1", default-features = false, features = ["std"] }

cargo_metadata = "0.18.1"
clap.workspace = true
serde_json.workspace = true

nexus-tools-dev = { path = "./tools-dev", default-features = false }
nexus-config = { path = "../config" }
nexus-riscv = { path = "../riscv" }
nexus-prover = { path = "../prover" }
nexus-network = { path = "../network" }
nexus-tui = { path = "./tui" }

ark-serialize.workspace = true
41 changes: 22 additions & 19 deletions tools/src/command/prove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use anyhow::Context;
use ark_serialize::CanonicalSerialize;

use nexus_config::vm as vm_config;
use nexus_network::client::Client;
use nexus_tools_dev::{
command::common::{
prove::{CommonProveArgs, LocalProveArgs, ProveArgs},
Expand Down Expand Up @@ -56,18 +55,22 @@ pub fn handle_command(args: ProveArgs) -> anyhow::Result<()> {
}
}

fn request_prove(path: &Path, url: &str) -> anyhow::Result<()> {
fn request_prove(_path: &Path, _url: &str) -> anyhow::Result<()> {
// TODO: network errors cannot be converted to anyhow.

let client = Client::new(url).map_err(|err| anyhow::anyhow!("url is invalid: {err}"))?;
let proof = client
.submit_proof("account".to_string(), path)
.map_err(|err| anyhow::anyhow!("failed to send request: {err}"))?;

tracing::info!(
// let client = Client::new(url).map_err(|err| anyhow::anyhow!("url is invalid: {err}"))?;
// let proof = client
// .submit_proof("account".to_string(), path)
// .map_err(|err| anyhow::anyhow!("failed to send request: {err}"))?;

// tracing::info!(
// target: LOG_TARGET,
// hash = %proof.hash,
// "Prove request submitted",
// );
tracing::warn!(
target: LOG_TARGET,
hash = %proof.hash,
"Prove request submitted",
"Networking commands are disabled",
);

Ok(())
Expand Down Expand Up @@ -114,20 +117,20 @@ fn local_prove(
let state = nexus_prover::pp::gen_or_load(false, DEFAULT_K, path_str)?;
let root = nexus_prover::prove_par(state, trace)?;

let mut buf = Vec::new();
root.serialize_compressed(&mut buf)?;

let current_dir = std::env::current_dir()?;
let path = current_dir.join("nexus-proof.json");
let path = current_dir.join("nexus-proof");
tracing::info!(
target: LOG_TARGET,
path = %path.to_string_lossy(),
"Storing the proof",
path = %path.display(),
"Saving the proof",
);
let proof = nexus_network::api::Proof { proof: Some(buf), ..Default::default() };

let serialized = serde_json::to_vec(&proof)?;
std::fs::write(path, serialized)?;
let mut term = nexus_tui::TerminalHandle::new();
let mut context = term.context("Saving").on_step(|_step| "proof".into());
let _guard = context.display_step();

let file = std::fs::File::create(path)?;
root.serialize_compressed(file)?;
} else {
let state = nexus_prover::pp::gen_or_load(false, DEFAULT_K, path_str)?;
nexus_prover::prove_seq(&state, trace)?;
Expand Down
57 changes: 30 additions & 27 deletions tools/src/command/request.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use anyhow::Context;

use nexus_network::client::Client;
use nexus_tools_dev::command::common::RequestArgs;

use crate::LOG_TARGET;
Expand All @@ -12,32 +11,36 @@ pub fn handle_command(args: RequestArgs) -> anyhow::Result<()> {
request_proof(hash, &url)
}

fn request_proof(hash: String, url: &str) -> anyhow::Result<()> {
let current_dir = std::env::current_dir()?;
let path = current_dir.join("nexus-proof.json");
let path_str = path.to_str().context("path is not valid utf8")?;

// TODO: network errors cannot be converted to anyhow.
let client = Client::new(url).map_err(|err| anyhow::anyhow!("url is invalid: {err}"))?;
let proof = client
.fetch_proof(&hash)
.map_err(|err| anyhow::anyhow!("failed to send request: {err}"))?;

if proof.total_nodes > proof.complete_nodes {
tracing::info!(
target: LOG_TARGET,
"Proof is not complete: {}/{}",
proof.complete_nodes,
proof.total_nodes,
);
} else {
tracing::info!(
target: LOG_TARGET,
"Storing proof to {path_str}",
);
let serialized = serde_json::to_vec(&proof)?;
std::fs::write(path_str, serialized)?;
}
fn request_proof(_hash: String, _url: &str) -> anyhow::Result<()> {
// let current_dir = std::env::current_dir()?;
// let path = current_dir.join("nexus-proof.json");
// let path_str = path.to_str().context("path is not valid utf8")?;

// // TODO: network errors cannot be converted to anyhow.
// let client = Client::new(url).map_err(|err| anyhow::anyhow!("url is invalid: {err}"))?;
// let proof = client
// .fetch_proof(&hash)
// .map_err(|err| anyhow::anyhow!("failed to send request: {err}"))?;

// if proof.total_nodes > proof.complete_nodes {
// tracing::info!(
// target: LOG_TARGET,
// "Proof is not complete: {}/{}",
// proof.complete_nodes,
// proof.total_nodes,
// );
// } else {
// tracing::info!(
// target: LOG_TARGET,
// "Storing proof to {path_str}",
// );
// let serialized = serde_json::to_vec(&proof)?;
// std::fs::write(path_str, serialized)?;
// }
tracing::warn!(
target: LOG_TARGET,
"Networking commands are disabled",
);

Ok(())
}
Loading

0 comments on commit 9e4b09e

Please sign in to comment.