uhash-cli 0.5.1

UniversalHash proof-of-work miner for Bostrom blockchain
Documentation
use std::process::Command;

fn uhash_bin() -> String {
    if let Ok(path) = std::env::var("CARGO_BIN_EXE_uhash") {
        return path;
    }

    let exe = std::env::current_exe().expect("current_exe");
    let debug_dir = exe
        .parent()
        .and_then(|p| p.parent())
        .expect("target/debug dir");
    let unix_path = debug_dir.join("uhash");
    if unix_path.exists() {
        return unix_path.display().to_string();
    }
    let windows_path = debug_dir.join("uhash.exe");
    if windows_path.exists() {
        return windows_path.display().to_string();
    }

    panic!("could not locate uhash binary");
}

#[test]
fn e2e_help_is_local_compute_only() {
    let output = Command::new(uhash_bin())
        .arg("--help")
        .output()
        .expect("run --help");

    assert!(
        output.status.success(),
        "--help failed: {}",
        String::from_utf8_lossy(&output.stderr)
    );
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("prove"), "missing prove command");
    assert!(stdout.contains("mine"), "missing mine command");
    assert!(stdout.contains("verify"), "missing verify command");
    assert!(stdout.contains("inspect"), "missing inspect command");
    assert!(stdout.contains("bench"), "missing bench command");
    assert!(stdout.contains("tune"), "missing tune command");
    assert!(
        !stdout.contains("send"),
        "send command should not be present"
    );
    assert!(
        !stdout.contains("status"),
        "status command should not be present"
    );
    assert!(
        !stdout.contains("--rpc"),
        "--rpc should not be present in global options"
    );
}

#[test]
fn e2e_prove_and_verify_roundtrip() {
    let challenge = "abcd";
    let prove = Command::new(uhash_bin())
        .arg("--json")
        .arg("prove")
        .arg("--challenge")
        .arg(challenge)
        .arg("--difficulty")
        .arg("8")
        .arg("--max-attempts")
        .arg("50000")
        .output()
        .expect("run prove");
    assert!(
        prove.status.success(),
        "prove failed: {}",
        String::from_utf8_lossy(&prove.stderr)
    );

    let payload: serde_json::Value =
        serde_json::from_slice(&prove.stdout).expect("prove json response");
    let nonce = payload["nonce"].as_u64().expect("nonce");
    let hash = payload["hash"].as_str().expect("hash").to_string();

    let verify = Command::new(uhash_bin())
        .arg("--json")
        .arg("verify")
        .arg("--challenge")
        .arg(challenge)
        .arg("--nonce")
        .arg(nonce.to_string())
        .arg("--hash")
        .arg(hash)
        .arg("--difficulty")
        .arg("8")
        .output()
        .expect("run verify");

    assert!(
        verify.status.success(),
        "verify failed: {}",
        String::from_utf8_lossy(&verify.stderr)
    );
    let out: serde_json::Value = serde_json::from_slice(&verify.stdout).expect("verify json");
    assert_eq!(out["valid"].as_bool(), Some(true));
}