honeycrisp npt mining
Goal: make Apple Silicon the most efficient Neptune (NPT) miner available,
combining aruminium (bare-Metal GPU), acpu (NEON+AMX), and unimem
(zero-copy unified memory) into a single mining pipeline under
trisha-honeycrisp.
situation
network (as of 2026-05-22, block ~39295)
| metric | value |
|---|---|
| PoW algorithm | HardforkBeta (activated block 38000) |
| algorithm type | pure Tip5 hash search — no memory requirement |
| difficulty | ~11 × 10¹² |
| target block interval | 588 s (9.8 min) |
| implied network hashrate | ~18.8 GH/s |
HardforkBeta replaced memory-hard PoW (40 GB buffer, 63-hash index derivation) with a simple fast_mast_hash check: ~11 Tip5 operations per guess, zero random memory access. This makes the workload 100% compute-bound.
per-guess operation count (HardforkBeta)
1 × Tip5::hash_pair (nonce derivation)
1 × Tip5::hash_varlen/300 (encode nonce + zero paths: 30 perms)
3 × Tip5::hash_pair (pow path through block MAST)
2 × Tip5::hash_varlen/5 (~1 perm each)
3 × Tip5::hash_pair (kernel + header path)
──────────────────────────────────────────────────
~40 Tip5 permutations total per guess
Each Tip5 permutation:
- 5 rounds × (S-box + 16×16 MDS + round constants)
- ~30 Goldilocks multiplications per round = ~150 gl_mul per permutation
- ~6000 gl_mul per guess total
measured baseline
| hardware | hashrate | power | KH/W |
|---|---|---|---|
| M4 Max (16T, rayon, triton-vm Tip5) | 0.33 MH/s | ~30W | 11 |
| RTX 3090 (NPT-GPU-Miner v1.6) | ~9 MH/s† | 320W | 28 |
| RTX 4090 (NPT-GPU-Miner v1.6) | ~21 MH/s† | 280W | 75 |
| RTX 5090 (NPT-GPU-Miner v1.6) | ~39 MH/s† | 580W | 67 |
† v1.6 benchmarks are pre-HardforkBeta (memory-hard PoW). Post-HardforkBeta GPU performance is uncharted; estimated 4–8× higher as the 63-hash index derivation bottleneck is removed.
what exists in this repo
| component | location | state |
|---|---|---|
| Tip5 WGSL shader | wgpu/shaders/tip5.wgsl | real, complete |
| Goldilocks WGSL | wgpu/shaders/goldilocks.wgsl | real, vec2<u32> encoding |
| Mine.wgsl kernel | wgpu/shaders/mine.wgsl | real, wired into wgpu backend |
| wgpu GPU dispatch | wgpu/accelerator.rs | real, 8 pipelines |
| NEON gl_mul | ~/cyber/honeycrisp/acpu/src/field/goldilocks.rs | real, mul+umulh asm |
| AMX GEMV | ~/cyber/honeycrisp/acpu/src/gemm/ | real, K-blocked AMX tiles |
| aruminium Metal dispatch | ~/cyber/honeycrisp/aruminium/src/ | real, IMP-resolved ~2μs |
| unimem IOSurface | ~/cyber/honeycrisp/unimem/ | real |
| Neptune HardforkBeta CPU mine | honeycrisp/neptune_mine.rs | real, rayon |
| Tip5 MSL shader (aruminium) | — | missing |
| NEON Tip5 permutation | — | missing |
| honeycrisp GPU mining wire-up | — | missing |
architecture
┌─────────────────────────────────────────────────────┐
│ trisha mine --neptune │
│ honeycrisp/neptune_mine.rs │
└───────────────┬───────────────────────────┬──────────┘
│ │
┌────────────▼──────────┐ ┌────────────▼──────────┐
│ GPU path │ │ CPU complement │
│ aruminium dispatch │ │ NEON Tip5 (acpu) │
│ tip5.metal kernel │ │ 4-way interleaved │
│ ulong Goldilocks │ │ gl_mul latency-hidden │
│ unimem zero-copy │ │ │
└────────────┬──────────┘ └────────────┬──────────┘
│ │
└──────────┬────────────────┘
│
┌────────────▼──────────┐
│ result merge │
│ submit winning nonce │
│ via NeptuneClient │
└───────────────────────┘
The GPU evaluates nonce batches of 65536. The CPU generates the next batch while the GPU computes. unimem IOSurface gives both sides access to the same physical memory — no copy on dispatch or readback.
implementation plan
phase 0 — wire wgpu mine kernel into neptune_mine.rs (1–2 days)
The wgpu backend already has a working Mine.wgsl kernel and a mine()
dispatch method in accelerator.rs. The gap is that honeycrisp/neptune_mine.rs
never calls it — it only does CPU rayon.
tasks:
H0.1 add `trisha-wgpu` as optional dep to trisha-honeycrisp/Cargo.toml
H0.2 add WgpuBackend construction in neptune_mine::mine_hardfork_beta()
behind cfg(feature = "gpu") — falls back to rayon if GPU unavailable
H0.3 wire nonce batch → accelerator.mine() → result poll
H0.4 benchmark: wgpu GPU MH/s on M4 Max vs 0.33 MH/s CPU baseline
This gives us GPU mining immediately using existing shaders. Expected: 8–15 MH/s on M4 Max with no new shader code.
deliverable: trisha mine --neptune --backend gpu works on Apple Silicon.
phase 1 — aruminium Tip5 MSL kernel (1 week)
Replace the wgpu/WGSL path with a direct Metal/MSL kernel via aruminium.
Key advantage: Metal MSL has native ulong (64-bit unsigned integer) and
ushort/uint SIMD intrinsics. Goldilocks multiply with native ulong is
cleaner and faster than WGSL's vec2<u32> emulation.
tip5.metal — Goldilocks field arithmetic:
// p = 2^64 - 2^32 + 1. epsilon = 2^32 - 1 = p.wrapping_neg()
constant ulong GL_P = 0xFFFFFFFF00000001UL;
constant ulong GL_EPS = 0x00000000FFFFFFFFUL;
// gl_mul: 64×64 → Goldilocks.
// Metal lacks mulhi64; emulate with four 32-bit multiplies.
ulong gl_mul(ulong a, ulong b) {
uint a_lo = (uint)a, a_hi = (uint)(a >> 32);
uint b_lo = (uint)b, b_hi = (uint)(b >> 32);
// cross products — only hi lanes needed for reduction
ulong lo = (ulong)a_lo * b_lo;
ulong mid1 = (ulong)a_lo * b_hi;
ulong mid2 = (ulong)a_hi * b_lo;
ulong hi = (ulong)a_hi * b_hi;
// combine to 128-bit {hi128, lo128}
ulong lo128 = lo + (mid1 << 32) + (mid2 << 32);
ulong hi128 = hi + (mid1 >> 32) + (mid2 >> 32)
+ (lo128 < lo ? 1UL : 0UL); // carry
// reduce: 2^64 ≡ epsilon (mod p)
ulong hi_hi = hi128 >> 32;
ulong hi_lo = hi128 & GL_EPS;
ulong t0 = lo128 - hi_hi;
if (t0 > lo128) t0 -= GL_EPS; // borrow
ulong t1 = hi_lo * GL_EPS;
ulong res = t0 + t1;
if (res < t0) res += GL_EPS; // carry
return res >= GL_P ? res - GL_P : res;
}
kernel structure:
kernel void npt_mine(
device ulong* nonces_out buffer(0),
constant ulong* path_a buffer(1), // 5*HEIGHT ulongs
constant ulong* mast_paths buffer(2), // pow+header+kernel digests
constant ulong* target buffer(3), // 5 ulongs (threshold)
constant ulong& nonce_base buffer(4),
device atomic_uint* found buffer(5),
uint tid thread_position_in_grid)
{
ulong nonce[5] = { nonce_base + tid, tid, ... }; // per-thread nonce
// fast_mast_hash: ~40 Tip5 permutations
ulong state[16] = {};
tip5_absorb_300(state, nonce, path_a); // hash_varlen(300 BFEs)
tip5_hash_pair(state, mast_paths + 0*5); // 3 hash_pairs: pow path
tip5_hash_pair(state, mast_paths + 1*5);
tip5_hash_pair(state, mast_paths + 2*5);
tip5_hash_varlen_5(state, mast_paths + 3*5); // hash_varlen(5) header
tip5_hash_pair(state, mast_paths + 4*5);
tip5_hash_pair(state, mast_paths + 5*5);
tip5_hash_varlen_5(state, mast_paths + 6*5); // hash_varlen(5) kernel
tip5_hash_pair(state, mast_paths + 7*5); // final hash_pair
// compare digest vs target (lexicographic on 5-element Goldilocks tuple)
if (digest_le(state, target)) {
uint slot = atomic_fetch_add_explicit(found, 1, memory_order_relaxed);
if (slot == 0) {
for (int i = 0; i < 5; i++) nonces_out[i] = nonce[i];
}
}
}
Threadgroup size: 256. Grid: 65536 threads per dispatch = 65536 guesses per aruminium call. Dispatch latency via IMP-resolved path: ~2 µs.
tasks:
H1.1 implement tip5.metal: gl_mul, gl_add, gl_sub, gl_pow7,
sbox_layer (lookup for 4 elems + x^7 for 12), mds_layer (16×16
circulant), tip5_permute (5 rounds), tip5_absorb_300, hash_pair,
hash_varlen_5, fast_mast_hash
H1.2 implement npt_mine kernel (tid-based nonce, threshold compare, atomic CAS)
H1.3 add AruMine struct in honeycrisp/: compiles pipeline from tip5.metal,
owns aruminium::Gpu + aruminium::Pipeline + unimem buffers
H1.4 expose mine_batch(nonce_base, path_a, mast_paths, target) -> Option<[u64;5]>
H1.5 replace wgpu path in mine_hardfork_beta() with AruMine::mine_batch()
H1.6 benchmark: aruminium MH/s vs wgpu MH/s, measure dispatch overhead
Expected: 12–20 MH/s on M4 Max, 24–40 MH/s on M4 Ultra.
deliverable: mine_hardfork_beta dispatches to Metal via aruminium.
Measured MH/s logged to stderr. wgpu removed from the hot path.
phase 2 — NEON Tip5 CPU complement (3–4 days)
The GPU runs 65536-nonce batches. Between GPU dispatches (~1 ms each), the
CPU is idle. Fill that gap with a NEON-accelerated CPU path that runs
independently using acpu's existing gl_mul.
4-way NEON interleaved Tip5:
Tip5 permutation is sequential (each round depends on prior), but we can
interleave 4 independent hashes across NEON registers to hide the gl_mul
3-cycle multiply latency on M4:
// 4 independent Tip5 states in parallel, hiding gl_mul latency
// Each state: [u64; 16] mapped to 8× uint64x2_t NEON registers
4-way interleaving provides ~3× throughput improvement over scalar on M4 (eliminates mul stalls across independent chains).
tasks:
H2.1 implement tip5_permute in acpu/src/poseidon/ using gl_mul from
acpu/src/field/goldilocks.rs. scalar first, tested against
triton-vm's Tip5 test vectors.
H2.2 implement 4-way NEON interleave: sbox_x4, mds_x4, add_rc_x4
using uint64x2_t (NEON intrinsics, 2 states per register pair)
H2.3 implement hash_pair_neon, hash_varlen_neon using tip5_permute_x4
H2.4 implement fast_mast_hash_neon (all 8 Tip5 calls using NEON path)
H2.5 spawn CPU miner thread in neptune_mine running NEON path in parallel
with GPU dispatch loop; merge results via AtomicBool found flag
H2.6 benchmark NEON vs triton-vm Tip5 on M4 Max (expect 2–4 MH/s CPU)
Expected: +2–4 MH/s from CPU complement running concurrently with GPU.
deliverable: CPU and GPU mine simultaneously. Total: 14–24 MH/s M4 Max, 26–44 MH/s M4 Ultra.
phase 3 — unimem zero-copy pipeline (3 days)
Currently: GPU dispatch copies nonce batch into a staging buffer (CPU write), dispatches compute, copies result back (CPU read). On Apple unified memory, this copy is unnecessary — both CPU and GPU can directly read/write the same physical page.
unimem pipeline:
// Persistent IOSurface buffers — allocated once, never copied
let nonce_buf = new; // nonces
let result_buf = new; // winning nonce
let found_buf = new; // atomic flag
loop
Double-buffer variant: while GPU executes batch N, CPU fills batch N+1. Requires two IOSurface nonce buffers alternating.
tasks:
H3.1 integrate unimem::Buffer into AruMine for nonce_buf + result_buf
H3.2 eliminate all intermediate Vec<u64> allocations in the dispatch loop
H3.3 implement double-buffer: alternate A/B nonce buffers, CPU fills while
GPU computes, commit_async + wait on prior batch
H3.4 benchmark: zero-copy vs staged-copy dispatch throughput
H3.5 measure peak MH/s with pipeline overlap on M4 Max
Expected: 10–20% throughput gain from eliminating copy overhead and saturating GPU without stalls.
deliverable: Fully pipelined zero-copy mining loop. Peak MH/s measured.
performance targets
| hardware | phase 0 | phase 1 | phase 2+3 | power | KH/W |
|---|---|---|---|---|---|
| M4 Max (40-core GPU) | 8–12 MH/s | 12–18 MH/s | 15–22 MH/s | ~45W | 333–489 |
| M4 Ultra (80-core GPU) | 16–24 MH/s | 24–36 MH/s | 30–44 MH/s | ~80W | 375–550 |
| RTX 4090 (est. post-HFB) | — | — | ~80–120 MH/s | 280W | 286–429 |
M4 Ultra matches or exceeds RTX 4090 in KH/W (energy efficiency) while using 3.5× less power. Apple is structurally better positioned for mining operations constrained by electricity cost or thermal budget.
competitive thesis
-
No NVIDIA dependency. The entire Apple silicon stack (GPU + NEON + AMX) is self-contained. No CUDA driver updates, no NVML, no PCIe slot.
-
Unified memory eliminates PCIe bottleneck. The zero-copy unimem path means nonce batches never cross a PCIe bus. On a dedicated NVIDIA rig, every nonce batch traverses 16× PCIe lanes at ~32 GB/s. On Apple, it's direct physical memory access at >200 GB/s.
-
First-mover in Apple mining. The NPT GPU miner community is entirely NVIDIA-focused. No Apple MSL Tip5 kernel exists publicly. Shipping this before others captures the entire Mac mining market.
-
MacBook as silent miner. M4 Max in a MacBook Pro dissipates ~45W under GPU load — within its sustained thermal envelope. An RTX 4090 rig requires dedicated rack space, 1200W PSU, and industrial cooling.
-
Foundation for STARK proving. The same aruminium Tip5 kernel serves both mining and STARK proof generation (the Poseidon2/Tip5 FRI commit step). Phase 1 builds the primitive that phases everything else in the honeycrisp roadmap.
dependency on honeycrisp workspace
This feature requires crates from ~/cyber/honeycrisp/:
| crate | version | used for |
|---|---|---|
aruminium |
workspace | Metal device, pipeline, buffer, dispatch |
acpu |
workspace | NEON gl_mul, tip5_permute_x4 |
unimem |
workspace | IOSurface zero-copy buffers |
These are not yet dependencies of trisha-honeycrisp/Cargo.toml. Add them
as path dependencies gated behind cfg(target_os = "macos").
success criteria
# phase 0
# stderr: "M4 Max GPU: 12.3 MH/s (37.3× CPU baseline)"
# phase 1
# stderr: "aruminium: 17.8 MH/s | dispatch: 2.1 µs | batch: 65536"
# phase 2+3
# stderr: "GPU: 18.4 MH/s | CPU NEON: 3.1 MH/s | total: 21.5 MH/s"
# energy
# M4 Max @ 21 MH/s / 45W = 467 KH/W
# beats RTX 4090 @ 100 MH/s / 280W = 357 KH/W