diff --git a/README.md b/README.md index 378d168..841d3ca 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ A *bLaZinGlY fAsT* tool for grinding vanity addresses on Solana. +## WSL users + +If you are running on Windows 10/11 with WSL2 and NVIDIA GPU, see [`WSL_README.md`](./WSL_README.md) for a tested setup/build/run flow. +The GPU build uses `build.rs` as Cargo entrypoint and auto-selects native vs WSL builder modules; set `VANITY_CUDA_ARCH` for your GPU (for example `86` for many RTX 30xx, `89` for many RTX 40xx). + ## 1) What Typically, solana developers wishing to obtain a vanity address for their program or token grind out ed25519 keypairs and sign off on a `SystemInstruction::CreateAccount` instruction. However, by using `SystemInstruction::CreateAccountWithSeed`, developers can bypass ed25519 and get extreme speedups on address searches. Although not as generic, this method covers many use cases. diff --git a/WSL_README.md b/WSL_README.md new file mode 100644 index 0000000..0d16ea4 --- /dev/null +++ b/WSL_README.md @@ -0,0 +1,110 @@ +# WSL + NVIDIA GPU Guide + +This guide documents a working setup for running `vanity` on Windows 10 + WSL2 with NVIDIA GPU acceleration. + +## 1) Prerequisites + +- Windows 10 with WSL2 enabled +- NVIDIA Windows driver that supports CUDA in WSL2 +- Ubuntu (or similar) WSL distro + +Inside WSL, verify GPU visibility: + +```bash +/usr/lib/wsl/lib/nvidia-smi || nvidia-smi +``` + +If this fails, update your Windows NVIDIA driver and run `wsl --update` from Windows. + +## 2) Install Toolchain in WSL + +```bash +sudo apt-get update +sudo apt-get install -y build-essential pkg-config curl git ca-certificates +curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y +source "$HOME/.cargo/env" +``` + +Install CUDA toolkit in WSL: + +```bash +wget https://developer.download.nvidia.com/compute/cuda/repos/wsl-ubuntu/x86_64/cuda-keyring_1.1-1_all.deb +sudo dpkg -i cuda-keyring_1.1-1_all.deb +sudo apt-get update +sudo apt-get install -y cuda-toolkit +``` + +Set environment: + +```bash +echo 'export PATH=/usr/local/cuda/bin:$PATH' >> ~/.bashrc +echo 'export LD_LIBRARY_PATH=/usr/local/cuda/lib64:${LD_LIBRARY_PATH:-}' >> ~/.bashrc +source ~/.bashrc +``` + +## 3) Build Notes (Important) + +- Cargo only uses `build.rs` as the build-script entrypoint. +- This repo keeps native GPU logic in `build_native.rs` and WSL-focused logic in `build_wsl.rs`. +- `build.rs` auto-detects WSL and picks the right builder. +- You can force selection with `VANITY_BUILD_IMPL`: + - `VANITY_BUILD_IMPL=wsl` + - `VANITY_BUILD_IMPL=native` +- Set `VANITY_CUDA_ARCH` for your GPU architecture. + +Examples: + +- RTX 30xx: `VANITY_CUDA_ARCH=86` +- RTX 40xx: `VANITY_CUDA_ARCH=89` + +You can pass a comma-separated list if needed: + +```bash +VANITY_CUDA_ARCH=86,89 +``` + +Build: + +```bash +VANITY_BUILD_IMPL=wsl VANITY_CUDA_ARCH=86 NVCC=/usr/local/cuda/bin/nvcc cargo build --release --features gpu +``` + +## 4) Usage + +Main commands: + +```bash +./target/release/vanity --help +./target/release/vanity grind --help +./target/release/vanity grind-keypair --help +./target/release/vanity verify --help +``` + +### Grind a mint-compatible keypair vanity prefix + +Use `grind-keypair` (not `grind`) when you need an actual Solana keypair (for example a mint keypair): + +```bash +./target/release/vanity grind-keypair --prefix DeFixxx --num-gpus 1 --num-cpus 1 --count 1 +``` + +Output is printed to terminal and includes: + +- `pubkey: ...` +- `keypair json (solana-compatible): [...]` + +Save the JSON array to a file such as `mint-keypair.json` for Solana tooling. + +## 5) Troubleshooting + +- `nvcc: command not found` + - Ensure CUDA toolkit is installed and `/usr/local/cuda/bin` is in `PATH`. + +- `CUDA driver version is insufficient for CUDA runtime version` + - Update Windows NVIDIA driver or install a CUDA toolkit version compatible with your current driver. + +- Link errors mentioning `__cxa_guard_*` or `__gxx_personality_v0` + - Ensure WSL builder is selected (`VANITY_BUILD_IMPL=wsl`) and `--features gpu` is enabled. + +- `gpu_keypair_init(...): cudaGetDeviceProperties ...` + - Verify `nvidia-smi` works inside WSL and GPU access is not blocked by policy. diff --git a/build.rs b/build.rs index e353b32..cc51559 100644 --- a/build.rs +++ b/build.rs @@ -1,31 +1,49 @@ +#[cfg(feature = "gpu")] +mod build_native; +#[cfg(feature = "gpu")] +mod build_wsl; + fn main() { #[cfg(feature = "gpu")] - build_cuda_libs(); + { + if use_wsl_builder() { + println!("cargo:warning=Using WSL CUDA builder"); + build_wsl::build_cuda_libs(); + } else { + println!("cargo:warning=Using native CUDA builder"); + build_native::build_cuda_libs(); + } + } } #[cfg(feature = "gpu")] -fn build_cuda_libs() { - println!("cargo::rerun-if-changed=kernels/"); - - cc::Build::new() - .cuda(true) - .include("kernels") - .file("kernels/utils.cu") - .file("kernels/vanity.cu") - .file("kernels/vanity_keypair.cu") - .file("kernels/base58.cu") - .file("kernels/sha256.cu") - .flag("-cudart=static") - .flag("-gencode=arch=compute_89,code=sm_89") - .flag("-gencode=arch=compute_89,code=compute_89") - .compile("libvanity.a"); +fn use_wsl_builder() -> bool { + use std::{env, fs, path::Path}; - // Add link directory - println!("cargo:rustc-link-search=native=/usr/local/cuda/lib64"); - println!("cargo:rustc-link-lib=cudart"); - println!("cargo:rustc-link-lib=cuda"); + // Manual override always wins: + // VANITY_BUILD_IMPL=wsl | native + if let Ok(v) = env::var("VANITY_BUILD_IMPL") { + let v = v.trim().to_ascii_lowercase(); + if v == "wsl" { + return true; + } + if v == "native" { + return false; + } + } - // Emit the location of the compiled library - let out_dir = std::env::var("OUT_DIR").unwrap(); - println!("cargo:rustc-link-search=native={}", out_dir); + // Auto-detect WSL. + if env::var_os("WSL_DISTRO_NAME").is_some() || env::var_os("WSL_INTEROP").is_some() { + return true; + } + if Path::new("/usr/lib/wsl/lib").exists() { + return true; + } + if let Ok(s) = fs::read_to_string("/proc/version") { + let sl = s.to_ascii_lowercase(); + if sl.contains("microsoft") || sl.contains("wsl") { + return true; + } + } + false } diff --git a/build_native.rs b/build_native.rs new file mode 100644 index 0000000..5cbc333 --- /dev/null +++ b/build_native.rs @@ -0,0 +1,48 @@ +use std::env; + +pub fn build_cuda_libs() { + fn parse_arches() -> Vec { + // Keep native default aligned with previous behavior (sm_89). + let raw = env::var("VANITY_CUDA_ARCH").unwrap_or_else(|_| "89".to_string()); + raw.split(',') + .map(str::trim) + .filter(|s| !s.is_empty()) + .map(|s| { + s.trim_start_matches("sm_") + .trim_start_matches("compute_") + .to_string() + }) + .collect() + } + + println!("cargo::rerun-if-changed=kernels/"); + println!("cargo:rerun-if-env-changed=VANITY_CUDA_ARCH"); + + let mut build = cc::Build::new(); + build + .cuda(true) + .include("kernels") + .file("kernels/utils.cu") + .file("kernels/vanity.cu") + .file("kernels/vanity_keypair.cu") + .file("kernels/base58.cu") + .file("kernels/sha256.cu") + .flag("-cudart=static"); + + let arches = parse_arches(); + println!("cargo:warning=Native build arch(es): {}", arches.join(",")); + for arch in arches { + let real = format!("-gencode=arch=compute_{arch},code=sm_{arch}"); + let virtual_ptx = format!("-gencode=arch=compute_{arch},code=compute_{arch}"); + build.flag(&real).flag(&virtual_ptx); + } + + build.compile("libvanity.a"); + + println!("cargo:rustc-link-search=native=/usr/local/cuda/lib64"); + println!("cargo:rustc-link-lib=cudart"); + println!("cargo:rustc-link-lib=cuda"); + + let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set by cargo"); + println!("cargo:rustc-link-search=native={}", out_dir); +} diff --git a/build_wsl.rs b/build_wsl.rs new file mode 100644 index 0000000..12c3e3f --- /dev/null +++ b/build_wsl.rs @@ -0,0 +1,162 @@ +use std::{ + env, + path::{Path, PathBuf}, + process::Command, +}; + +pub fn build_cuda_libs() { + fn resolve_nvcc() -> String { + if let Ok(nvcc) = env::var("NVCC") { + if Path::new(&nvcc).exists() { + return nvcc; + } + } + for candidate in ["/usr/local/cuda/bin/nvcc", "/usr/bin/nvcc"] { + if Path::new(candidate).exists() { + return candidate.to_string(); + } + } + panic!( + "Could not find nvcc. Install CUDA toolkit in WSL and ensure nvcc is in PATH, \ +or set NVCC explicitly (e.g. NVCC=/usr/local/cuda/bin/nvcc)." + ); + } + + fn parse_arches() -> Vec { + // Default to RTX 3070 (GA104) = compute capability 8.6 (sm_86). + // Override via VANITY_CUDA_ARCH, e.g. "89" or "86,89". + let raw = env::var("VANITY_CUDA_ARCH").unwrap_or_else(|_| "86".to_string()); + raw.split(',') + .map(str::trim) + .filter(|s| !s.is_empty()) + .map(|s| { + s.trim_start_matches("sm_") + .trim_start_matches("compute_") + .to_string() + }) + .collect() + } + + fn run_checked(cmd: &mut Command, context: &str) { + let status = cmd + .status() + .unwrap_or_else(|e| panic!("{context}: failed to spawn command: {e}")); + if !status.success() { + panic!("{context}: command exited with status {status}"); + } + } + + let sources = [ + "kernels/utils.cu", + "kernels/vanity.cu", + "kernels/vanity_keypair.cu", + "kernels/base58.cu", + "kernels/sha256.cu", + ]; + for src in sources { + println!("cargo:rerun-if-changed={src}"); + } + println!("cargo:rerun-if-env-changed=NVCC"); + println!("cargo:rerun-if-env-changed=VANITY_CUDA_ARCH"); + println!("cargo:rerun-if-env-changed=CUDAHOSTCXX"); + + let nvcc = resolve_nvcc(); + let arches = parse_arches(); + let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not set by cargo")); + let lib_path = out_dir.join("libvanity.a"); + + println!("cargo:warning=Using nvcc at {}", nvcc); + println!("cargo:warning=Target CUDA arch(es): {}", arches.join(",")); + println!("cargo:warning=Compiling CUDA via direct nvcc compile+dlink path"); + println!("cargo:warning=BUILD_RS_REV=2026-04-14-explicit-dlink-stdcpp"); + + let mut objects = Vec::with_capacity(sources.len()); + for src in sources { + let stem = Path::new(src) + .file_stem() + .expect("source file should have stem") + .to_string_lossy() + .into_owned(); + let obj = out_dir.join(format!("{stem}.o")); + objects.push(obj.clone()); + + let mut cmd = Command::new(&nvcc); + cmd.arg("-c") + .arg("-o") + .arg(&obj) + .arg("-O3") + .arg("-Xcompiler=-fPIC") + .arg("-cudart=shared") + .arg("-rdc=true") + .arg("-I") + .arg("kernels"); + + if let Ok(host_cxx) = env::var("CUDAHOSTCXX") { + if !host_cxx.trim().is_empty() { + cmd.arg("-ccbin").arg(host_cxx); + } + } + + for arch in &arches { + cmd.arg(format!("-gencode=arch=compute_{arch},code=sm_{arch}")); + cmd.arg(format!("-gencode=arch=compute_{arch},code=compute_{arch}")); + } + cmd.arg(src); + run_checked(&mut cmd, &format!("nvcc -c {src}")); + } + + let dlink_obj = out_dir.join("vanity_dlink.o"); + let mut dlink = Command::new(&nvcc); + dlink + .arg("-dlink") + .arg("-o") + .arg(&dlink_obj) + .arg("-cudart=shared"); + if let Ok(host_cxx) = env::var("CUDAHOSTCXX") { + if !host_cxx.trim().is_empty() { + dlink.arg("-ccbin").arg(host_cxx); + } + } + for arch in &arches { + dlink.arg(format!("-gencode=arch=compute_{arch},code=sm_{arch}")); + dlink.arg(format!("-gencode=arch=compute_{arch},code=compute_{arch}")); + } + for obj in &objects { + dlink.arg(obj); + } + dlink.arg("-lcudadevrt"); + run_checked(&mut dlink, "nvcc -dlink"); + + let mut ar = Command::new("ar"); + ar.arg("crs").arg(&lib_path); + for obj in &objects { + ar.arg(obj); + } + ar.arg(&dlink_obj); + run_checked(&mut ar, "ar crs libvanity.a"); + + let mut ranlib = Command::new("ranlib"); + ranlib.arg(&lib_path); + run_checked(&mut ranlib, "ranlib libvanity.a"); + + println!("cargo:rustc-link-search=native={}", out_dir.display()); + println!("cargo:rustc-link-lib=static=vanity"); + + let lib_search_dirs = [ + "/usr/local/cuda/lib64", + "/usr/lib/wsl/lib", + "/usr/lib/x86_64-linux-gnu", + ]; + for dir in lib_search_dirs { + if Path::new(dir).exists() { + println!("cargo:rustc-link-search=native={dir}"); + } + } + + println!("cargo:rustc-link-lib=cudart"); + println!("cargo:rustc-link-lib=cudadevrt"); + println!("cargo:rustc-link-lib=stdc++"); + // Don't link libcuda directly. cudart loads the driver at runtime, and + // many WSL installs expose only libcuda.so.1 without a libcuda.so dev symlink. + println!("cargo:warning=Skipping direct -lcuda link (WSL-friendly)"); +}