Compare commits

...

2 Commits

Author SHA1 Message Date
Collin Jackson
c2d6866b90 Updates 2024-10-03 15:06:32 -07:00
Collin Jackson
05c6ad4bc8 docs: Update README 2024-10-03 14:59:12 -07:00
8 changed files with 372 additions and 212 deletions

View File

@ -1,5 +1,6 @@
# network-cli # network-api
This repository contains the Nexus Network CLI and the interface definition for the Orchestrator server API. This repository contains the Nexus network command-line interface and
the interface it uses to communicate with Nexus servers.
See the [CLI readme](./clients/cli/README.md) to get started. See the [CLI readme](./clients/cli/README.md) to get started.

272
clients/cli/Cargo.lock generated
View File

@ -24,6 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"getrandom 0.2.15",
"once_cell", "once_cell",
"version_check", "version_check",
"zerocopy", "zerocopy",
@ -39,14 +40,18 @@ dependencies = [
] ]
[[package]] [[package]]
name = "allo-isolate" name = "alloc-no-stdlib"
version = "0.1.25" version = "2.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b6d794345b06592d0ebeed8e477e41b71e5a0a49df4fc0e4184d5938b99509" checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
[[package]]
name = "alloc-stdlib"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
dependencies = [ dependencies = [
"anyhow", "alloc-no-stdlib",
"atomic",
"backtrace",
] ]
[[package]] [[package]]
@ -56,21 +61,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
[[package]] [[package]]
name = "android_log-sys" name = "android-tzdata"
version = "0.3.1" version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]] [[package]]
name = "android_logger" name = "android_system_properties"
version = "0.13.3" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f" checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [ dependencies = [
"android_log-sys", "libc",
"env_logger",
"log",
"once_cell",
] ]
[[package]] [[package]]
@ -441,12 +443,6 @@ dependencies = [
"syn 2.0.71", "syn 2.0.71",
] ]
[[package]]
name = "atomic"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba"
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -571,10 +567,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae"
[[package]] [[package]]
name = "build-target" name = "brotli"
version = "0.4.0" version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "832133bbabbbaa9fbdba793456a2827627a7d2b8fb96032fa1e7666d7895832b" checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
"brotli-decompressor",
]
[[package]]
name = "brotli-decompressor"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
dependencies = [
"alloc-no-stdlib",
"alloc-stdlib",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
@ -588,12 +599,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]]
name = "bytemuck"
version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773d90827bc3feecfb67fab12e24de0749aad83c74b9504ecde46237b5cd24e2"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -622,6 +627,20 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.9" version = "4.5.9"
@ -691,16 +710,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "console_error_panic_hook"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
dependencies = [
"cfg-if",
"wasm-bindgen",
]
[[package]] [[package]]
name = "constant_time_eq" name = "constant_time_eq"
version = "0.3.1" version = "0.3.1"
@ -767,42 +776,12 @@ dependencies = [
"typenum", "typenum",
] ]
[[package]]
name = "dart-sys-fork"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "933dafff26172b719bb9695dd3715a1e7792f62dcdc8a5d4c740db7e0fedee8b"
dependencies = [
"cc",
]
[[package]]
name = "dashmap"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
dependencies = [
"cfg-if",
"num_cpus",
]
[[package]] [[package]]
name = "data-encoding" name = "data-encoding"
version = "2.6.0" version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2"
[[package]]
name = "delegate-attr"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51aac4c99b2e6775164b412ea33ae8441b2fde2dbf05a20bc0052a63d08c475b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.71",
]
[[package]] [[package]]
name = "derivative" name = "derivative"
version = "2.2.0" version = "2.2.0"
@ -864,16 +843,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "env_logger"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
dependencies = [
"log",
"regex",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -923,46 +892,6 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
[[package]]
name = "flutter_rust_bridge"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aebee2d1d5b8b3cfbbb11919b44791b4e0f037328195efd3832c7f7e0c6c6c8b"
dependencies = [
"allo-isolate",
"android_logger",
"anyhow",
"build-target",
"bytemuck",
"byteorder",
"console_error_panic_hook",
"dart-sys-fork",
"delegate-attr",
"flutter_rust_bridge_macros",
"futures",
"js-sys",
"lazy_static",
"oslog",
"threadpool",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
]
[[package]]
name = "flutter_rust_bridge_macros"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c061770f5f09e99d6143612e95cfc1ba2ae773746fbe5826a9c914a533b0723"
dependencies = [
"hex",
"md-5",
"proc-macro2",
"quote",
"syn 2.0.71",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -1247,6 +1176,15 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "home"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
dependencies = [
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "http" name = "http"
version = "1.1.0" version = "1.1.0"
@ -1360,6 +1298,29 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "idna" name = "idna"
version = "0.5.0" version = "0.5.0"
@ -1495,16 +1456,6 @@ dependencies = [
"regex-automata 0.1.10", "regex-automata 0.1.10",
] ]
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest 0.10.7",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.4" version = "2.7.4"
@ -1633,18 +1584,20 @@ dependencies = [
"ark-test-curves", "ark-test-curves",
"ark-vesta", "ark-vesta",
"async-stream", "async-stream",
"base64", "chrono",
"clap", "clap",
"elf", "elf",
"flutter_rust_bridge",
"futures", "futures",
"getrandom 0.2.15", "getrandom 0.2.15",
"hex", "hex",
"home",
"iana-time-zone",
"jsonrpsee", "jsonrpsee",
"nexus-core", "nexus-core",
"prost", "prost",
"prost-build", "prost-build",
"rand 0.8.5", "rand 0.8.5",
"random_word",
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
@ -1830,17 +1783,6 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "oslog"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8343ce955f18e7e68c0207dd0ea776ec453035685395ababd2ea651c569728b3"
dependencies = [
"cc",
"dashmap",
"log",
]
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -2115,6 +2057,20 @@ dependencies = [
"rand_core 0.5.1", "rand_core 0.5.1",
] ]
[[package]]
name = "random_word"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07eed67a16dde2cc3c7f65c072acd8d5b2e53d4aab95067c320db851c7651f29"
dependencies = [
"ahash",
"brotli",
"once_cell",
"paste",
"rand 0.8.5",
"unicase",
]
[[package]] [[package]]
name = "rayon" name = "rayon"
version = "1.10.0" version = "1.10.0"
@ -2197,7 +2153,6 @@ dependencies = [
"base64", "base64",
"bytes", "bytes",
"encoding_rs", "encoding_rs",
"futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2",
@ -2635,15 +2590,6 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "threadpool"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
dependencies = [
"num_cpus",
]
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.8.0" version = "1.8.0"
@ -2871,6 +2817,15 @@ version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicase"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.15" version = "0.3.15"
@ -3070,6 +3025,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets 0.52.6",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"

View File

@ -16,15 +16,14 @@ clap = { version = "4.5", features = ["derive"] }
futures = "0.3" futures = "0.3"
prost = "0.13" prost = "0.13"
rand = "0.8.5" rand = "0.8.5"
reqwest = { version = "0.12", features = ["blocking"] } reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1.38", features = ["full"] } tokio = { version = "1.38", features = ["full"] }
tokio-tungstenite = { version = "0.23", features = ["native-tls"] } tokio-tungstenite = { version = "0.23", features = ["native-tls"] }
tracing = "0.1" tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] } tracing-subscriber = { version = "0.3", features = ["std", "env-filter"] }
uuid = { version = "1.9", features = ["v4", "fast-rng"] } uuid = { version = "1.9", features = ["v4", "fast-rng"] }
home = "0.5.9"
base64 = "0.22.1" random_word = { version = "0.4.3", features = ["en"] }
flutter_rust_bridge = "=2.1.0"
nexus-core = { git = "https://github.com/nexus-xyz/nexus-zkvm.git" } nexus-core = { git = "https://github.com/nexus-xyz/nexus-zkvm.git" }
getrandom = { version = "0.2", features = ["js"] } getrandom = { version = "0.2", features = ["js"] }
# Workaround for "failed to resolve patches for `https://github.com/rust-lang/crates.io-index`" # Workaround for "failed to resolve patches for `https://github.com/rust-lang/crates.io-index`"
@ -60,6 +59,8 @@ ark-grumpkin = "0.4.0"
ark-pallas = "0.4.0" ark-pallas = "0.4.0"
ark-vesta = "0.4.0" ark-vesta = "0.4.0"
ark-test-curves = { version = "0.4.2", features = ["bls12_381_curve"] } ark-test-curves = { version = "0.4.2", features = ["bls12_381_curve"] }
iana-time-zone = "0.1.60"
chrono = "0.4.38"
[patch.crates-io] [patch.crates-io]
ark-crypto-primitives = { git = "https://github.com/arkworks-rs/crypto-primitives", rev = "d27a5c8" } ark-crypto-primitives = { git = "https://github.com/arkworks-rs/crypto-primitives", rev = "d27a5c8" }

View File

@ -10,6 +10,13 @@ curl https://network-cli.nexus.xyz/install.sh | sh
If you do not already have Rust, you will be prompted to install it. If you do not already have Rust, you will be prompted to install it.
## Terms of Use
Use of the CLI is subject to the [Terms of Use](https://nexus.xyz/terms_of_use).
The first time you run it, it prompts you to accept the terms. To accept the terms
noninteractively (for example, in a continuous integration environment),
add `NONINTERACTIVE=1` at the start of the command.
## Known issues ## Known issues
Currently only proving is supported. Submitting programs to the network is in private beta. Currently only proving is supported. Submitting programs to the network is in private beta.

View File

@ -1,14 +1,19 @@
use std::{error::Error, path::PathBuf}; use std::{error::Error, path::PathBuf, process::Command};
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let out_dir: PathBuf = "./src/generated/".into(); let out_dir: PathBuf = "./src/generated/".into();
let proto_file: PathBuf = "../../proto/orchestrator.proto".into(); let proto_file: PathBuf = "../../proto/orchestrator.proto".into();
let proto_dir = proto_file.parent().unwrap(); let proto_dir = proto_file.parent().unwrap();
prost_build::Config::new() match Command::new("protoc --version").spawn() {
.out_dir(out_dir) Ok(_) => prost_build::Config::new()
.protoc_arg("--experimental_allow_proto3_optional") .out_dir(out_dir)
.compile_protos(&[&proto_file], &[proto_dir])?; .protoc_arg("--experimental_allow_proto3_optional")
.compile_protos(&[&proto_file], &[proto_dir])?,
Err(_) => {
// Skipping protobuf compilation.
}
}
Ok(()) Ok(())
} }

View File

@ -0,0 +1,57 @@
use crate::config::analytics_token;
use chrono::Datelike;
use chrono::Timelike;
use reqwest::header::{ACCEPT, CONTENT_TYPE};
use serde_json::{json, Value};
use std::{
env,
time::{SystemTime, UNIX_EPOCH},
};
pub fn track(
event_name: String,
description: String,
ws_addr_string: &str,
event_properties: Value,
) {
println!("{}", description);
let token = analytics_token(ws_addr_string);
if token.is_empty() {
return;
}
let local_now = chrono::offset::Local::now();
let mut properties = json!({
"token": token,
"time": SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_millis(),
"distinct_id": event_properties["prover_id"],
"prover_type": "volunteer",
"client_type": "cli",
"operating_system": env::consts::OS,
"time_zone": iana_time_zone::get_timezone().unwrap(),
"local_hour": local_now.hour(),
"local_weekday_number_from_monday": local_now.weekday().number_from_monday(),
"ws_addr_string": ws_addr_string,
});
for (k, v) in event_properties.as_object().unwrap() {
properties[k] = v.clone();
}
let body = json!({
"event": event_name,
"properties": properties
});
tokio::spawn(async move {
let client = reqwest::Client::new();
let _ = client
.post("https://api.mixpanel.com/track?ip=1")
.body(format!("[{}]", body.to_string()))
.header(ACCEPT, "text/plain")
.header(CONTENT_TYPE, "application/json")
.send()
.await
.unwrap()
.text()
.await
.unwrap();
});
}

11
clients/cli/src/config.rs Normal file
View File

@ -0,0 +1,11 @@
pub fn analytics_token(ws_addr_string: &str) -> String {
if ws_addr_string.starts_with("wss://dev.orchestrator.nexus.xyz:443/") {
return "504d4d443854f2cd10e2e385aca81aa4".into();
} else if ws_addr_string.starts_with("wss://staging.orchestrator.nexus.xyz:443/") {
return "30bcb58893992aabc5aec014e7b903d2".into();
} else if ws_addr_string.starts_with("wss://beta.orchestrator.nexus.xyz:443/") {
return "3c16d3853f4258414c9c9109bbbdef0e".into();
} else {
return "".into();
};
}

View File

@ -1,7 +1,11 @@
// Copyright (c) 2024 Nexus. All rights reserved. // Copyright (c) 2024 Nexus. All rights reserved.
mod analytics;
mod config;
mod generated; mod generated;
use crate::analytics::track;
use std::borrow::Cow; use std::borrow::Cow;
use clap::Parser; use clap::Parser;
@ -11,6 +15,9 @@ use generated::pb::{
ProverRequest, ProverRequestRegistration, ProverResponse, ProverType, ProverRequest, ProverRequestRegistration, ProverResponse, ProverType,
}; };
use prost::Message as _; use prost::Message as _;
use random_word::Lang;
use serde_json::json;
use std::{fs, path::Path, time::SystemTime};
use tokio_tungstenite::tungstenite::protocol::{frame::coding::CloseCode, CloseFrame, Message}; use tokio_tungstenite::tungstenite::protocol::{frame::coding::CloseCode, CloseFrame, Message};
use tracing_subscriber::fmt::format::FmtSpan; use tracing_subscriber::fmt::format::FmtSpan;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
@ -22,14 +29,12 @@ use nexus_core::{
NexusVM, NexusVM,
}, },
prover::nova::{ prover::nova::{
init_circuit_trace, init_circuit_trace, key::CanonicalSerialize, pp::gen_vm_pp, prove_seq_step, types::*,
key::{CanonicalSerialize},
prove_seq_step,
types::*,
pp::gen_vm_pp,
}, },
}; };
use std::env;
use zstd::stream::Encoder; use zstd::stream::Encoder;
use rand::{ RngCore };
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
struct Args { struct Args {
@ -40,13 +45,9 @@ struct Args {
#[arg(short, long, default_value_t = 443u16)] #[arg(short, long, default_value_t = 443u16)]
port: u16, port: u16,
/// Whether to connect using secure web sockets /// Whether to hang up after the first proof
#[arg(short, long, default_value_t = true)] #[arg(short, long, default_value_t = false)]
use_https: bool, just_once: bool,
/// Whether to loop and keep the connection open
#[arg(short, long, default_value_t = true)]
keep_listening: bool,
} }
#[tokio::main] #[tokio::main]
@ -61,50 +62,101 @@ async fn main() {
let ws_addr_string = format!( let ws_addr_string = format!(
"{}://{}:{}/prove", "{}://{}:{}/prove",
if args.use_https { "wss" } else { "ws" }, if args.port == 443 { "wss" } else { "ws" },
args.hostname, args.hostname,
args.port args.port
); );
let prover_id = format!("prover_{}", rand::random::<u32>());
let k = 4; let k = 4;
// TODO(collinjackson): Get parameters from a file or URL. // TODO(collinjackson): Get parameters from a file or URL.
let pp = gen_vm_pp::<C1, seq::SetupParams<(G1, G2, C1, C2, RO, SC)>>(k as usize, &()) let pp = gen_vm_pp::<C1, seq::SetupParams<(G1, G2, C1, C2, RO, SC)>>(k as usize, &())
.expect("error generating public parameters"); .expect("error generating public parameters");
println!( // If the prover_id file is found, use the contents, otherwise generate a new random id
"{} supplying proofs to Orchestrator at {}", // and store it.
prover_id, &ws_addr_string let _ = match env::var("NONINTERACTIVE") {
Ok(_) => (),
Err(_) => {
println!(
"Do you agree to the Nexus Beta Terms of Use (https://nexus.xyz/terms-of-use)? (Y/n)"
);
let mut input = String::new();
let _ = std::io::stdin().read_line(&mut input);
if input.chars().nth(0).unwrap() == 'n' || input.chars().nth(0).unwrap() == 'N' {
return ();
}
}
};
let mut prover_id = format!(
"{}-{}-{}",
random_word::gen(Lang::En),
random_word::gen(Lang::En),
rand::thread_rng().next_u32() % 100,
);
match home::home_dir() {
Some(path) if !path.as_os_str().is_empty() => {
let nexus_dir = Path::new(&path).join(".nexus");
prover_id = match fs::read(nexus_dir.join("prover-id")) {
Ok(buf) => String::from_utf8(buf).unwrap(),
Err(_) => {
let _ = fs::create_dir(nexus_dir.clone());
fs::write(nexus_dir.join("prover-id"), prover_id.clone()).unwrap();
prover_id
}
}
}
_ => {
println!("Unable to get home dir.");
}
};
track(
"connect".into(),
format!("Connecting to {}...", &ws_addr_string),
&ws_addr_string,
json!({"prover_id": prover_id}),
);
let (mut client, _) = tokio_tungstenite::connect_async(&ws_addr_string)
.await
.unwrap();
track(
"connected".into(),
"Connected.".into(),
&ws_addr_string,
json!({"prover_id": prover_id}),
); );
let registration = ProverRequest { let registration = ProverRequest {
contents: Some(prover_request::Contents::Registration( contents: Some(prover_request::Contents::Registration(
ProverRequestRegistration { ProverRequestRegistration {
prover_type: ProverType::Volunteer.into(), prover_type: ProverType::Volunteer.into(),
prover_id: prover_id, prover_id: prover_id.clone().into(),
estimated_proof_cycles_hertz: None, estimated_proof_cycles_hertz: None,
}, },
)), )),
}; };
let (mut client, _) = tokio_tungstenite::connect_async(ws_addr_string)
.await
.unwrap();
client client
.send(Message::Binary(registration.encode_to_vec())) .send(Message::Binary(registration.encode_to_vec()))
.await .await
.unwrap(); .unwrap();
println!("Sent registration message...");
track(
"register".into(),
format!("Your assigned prover identifier is {}.", prover_id),
&ws_addr_string,
json!({"ws_addr_string": ws_addr_string, "prover_id": prover_id}),
);
println!(
"Network stats are available at https://beta.nexus.xyz/."
);
loop { loop {
let program_message = match client.next().await.unwrap().unwrap() { let program_message = match client.next().await.unwrap().unwrap() {
Message::Binary(b) => b, Message::Binary(b) => b,
_ => panic!("Unexpected message type"), _ => panic!("Unexpected message type"),
}; };
println!("Received program message...");
let program = ProverResponse::decode(program_message.as_slice()).unwrap(); let program = ProverResponse::decode(program_message.as_slice()).unwrap();
let Program::Rv32iElfBytes(elf_bytes) = program let Program::Rv32iElfBytes(elf_bytes) = program
@ -118,32 +170,35 @@ async fn main() {
let to_prove = program.to_prove.unwrap(); let to_prove = program.to_prove.unwrap();
let Input::RawBytes(input) = to_prove.input.unwrap().input.unwrap(); let Input::RawBytes(input) = to_prove.input.unwrap().input.unwrap();
println!( track(
"Received a {} byte program to prove with {} bytes of input", "program".into(),
elf_bytes.len(), format!(
input.len() "Received a {} byte program to prove with {} bytes of input",
elf_bytes.len(),
input.len()
),
&ws_addr_string,
json!({"prover_id": prover_id}),
); );
let mut vm: NexusVM<MerkleTrie> = let mut vm: NexusVM<MerkleTrie> =
parse_elf(&elf_bytes.as_ref()).expect("error loading and parsing RISC-V instruction"); parse_elf(&elf_bytes.as_ref()).expect("error loading and parsing RISC-V instruction");
vm.syscalls.set_input(&input); vm.syscalls.set_input(&input);
let k = 4;
// TODO(collinjackson): Get outputs // TODO(collinjackson): Get outputs
let completed_trace = trace(&mut vm, k as usize, false).expect("error generating trace"); let completed_trace = trace(&mut vm, k as usize, false).expect("error generating trace");
let tr = init_circuit_trace(completed_trace).expect("error initializing circuit trace"); let tr = init_circuit_trace(completed_trace).expect("error initializing circuit trace");
let total_steps = tr.steps(); let total_steps = tr.steps();
println!("Program trace {} steps", total_steps);
let start: usize = match to_prove.step_to_start { let start: usize = match to_prove.step_to_start {
Some(step) => step as usize, Some(step) => step as usize,
None => 0, None => 0,
}; };
let steps_to_prove = to_prove.steps_to_prove; let steps_to_prove = match to_prove.steps_to_prove {
let mut end: usize = match steps_to_prove { Some(steps) => steps as usize,
Some(steps) => start + steps as usize,
None => total_steps, None => total_steps,
}; };
let mut end: usize = start + steps_to_prove;
if end > total_steps { if end > total_steps {
end = total_steps end = total_steps
} }
@ -162,22 +217,63 @@ async fn main() {
.unwrap(); .unwrap();
let z_st = tr.input(start).expect("error starting circuit trace"); let z_st = tr.input(start).expect("error starting circuit trace");
println!("Proving...");
let mut proof = IVCProof::new(&z_st); let mut proof = IVCProof::new(&z_st);
println!("Proving from {} to {}", start, end); let mut completed_fraction = 0.0;
let mut steps_proven = 0;
track(
"progress".into(),
format!(
"Program trace is {} steps. Proving from {} to {}...",
total_steps, start, end
),
&ws_addr_string,
json!({
"completed_fraction": completed_fraction,
"steps_in_trace": total_steps,
"steps_to_prove": steps_to_prove,
"steps_proven": steps_proven,
"cycles_proven": steps_proven * k,
"k": k,
"prover_id": prover_id,
}),
);
let start_time = SystemTime::now();
let mut progress_time = start_time;
for step in start..end { for step in start..end {
proof = prove_seq_step(Some(proof), &pp, &tr).expect("error proving step"); proof = prove_seq_step(Some(proof), &pp, &tr).expect("error proving step");
println!("Proved step {}", step); steps_proven += 1;
let steps_proven = step - start + 1; completed_fraction = steps_proven as f32 / steps_to_prove as f32;
let progress = ProverRequest { let progress = ProverRequest {
contents: Some(prover_request::Contents::Progress(Progress { contents: Some(prover_request::Contents::Progress(Progress {
completed_fraction: steps_proven as f32 / steps_to_prove.unwrap() as f32, completed_fraction: completed_fraction,
steps_in_trace: total_steps as i32, steps_in_trace: total_steps as i32,
steps_to_prove: (end - start) as i32, steps_to_prove: steps_to_prove as i32,
steps_proven: steps_proven as i32, steps_proven: steps_proven as i32,
})), })),
}; };
let progress_duration = SystemTime::now().duration_since(progress_time).unwrap();
let cycles_proven = steps_proven * 4;
let proof_cycles_hertz = k * 1000 / progress_duration.as_millis();
let proof_cycles_per_minute = k * 60 * 1000 / progress_duration.as_millis();
track(
"progress".into(),
format!("Proved step {} at {} Hz.", step, proof_cycles_hertz),
&ws_addr_string,
json!({
"completed_fraction": completed_fraction,
"steps_in_trace": total_steps,
"steps_to_prove": steps_to_prove,
"steps_proven": steps_proven,
"cycles_proven": steps_proven * 4,
"k": k,
"progress_duration_millis": progress_duration.as_millis(),
"proof_cycles_hertz": proof_cycles_hertz,
"proof_cycles_per_minute": proof_cycles_per_minute,
"prover_id": prover_id,
}),
);
progress_time = SystemTime::now();
client client
.send(Message::Binary(progress.encode_to_vec())) .send(Message::Binary(progress.encode_to_vec()))
.await .await
@ -200,17 +296,30 @@ async fn main() {
.send(Message::Binary(response.encode_to_vec())) .send(Message::Binary(response.encode_to_vec()))
.await .await
.unwrap(); .unwrap();
let duration = SystemTime::now().duration_since(start_time).unwrap();
let proof_cycles_hertz = cycles_proven * 1000 / duration.as_millis();
let proof_cycles_per_minute = cycles_proven * 60 * 1000 / duration.as_millis();
track(
"proof".into(),
format!("Proof sent! You proved at {} Hz.", proof_cycles_hertz),
&ws_addr_string,
json!({
"proof_duration_sec": duration.as_secs(),
"proof_duration_millis": duration.as_millis(),
"proof_cycles_hertz": proof_cycles_hertz,
"proof_cycles_per_minute": proof_cycles_per_minute,
"prover_id": prover_id,
}),
);
} }
} }
// TODO(collinjackson): Consider verifying the proof before sending it // TODO(collinjackson): Consider verifying the proof before sending it
// proof.verify(&public_params, proof.step_num() as _).expect("error verifying execution") // proof.verify(&public_params, proof.step_num() as _).expect("error verifying execution")
println!("Proof sent!"); if args.just_once {
if args.keep_listening {
println!("Waiting for another program to prove...");
} else {
break; break;
} else {
println!("Waiting for another program to prove...");
} }
} }
@ -221,5 +330,10 @@ async fn main() {
})) }))
.await .await
.unwrap(); .unwrap();
println!("Sent proof and closed connection..."); track(
"disconnect".into(),
"Sent proof and closed connection...".into(),
&ws_addr_string,
json!({ "prover_id": prover_id }),
);
} }