Compare commits

..
2 Commits
4 changed files with 5 additions and 254 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"schemaVersion": 1,
"label": "Git Clones",
"message": "189,482",
"message": "190,252",
"color": "green",
"namedLogo": "git"
}
+4 -3
View File
@@ -1,6 +1,6 @@
{
"total_clones": 189482,
"last_updated": "2026-08-13T07:22:13Z",
"total_clones": 190252,
"last_updated": "2026-08-14T07:19:51Z",
"daily": {
"2026-03-27": 2189,
"2026-03-28": 1874,
@@ -140,6 +140,7 @@
"2026-08-09": 1076,
"2026-08-10": 1060,
"2026-08-11": 2182,
"2026-08-12": 641
"2026-08-12": 641,
"2026-08-13": 770
}
}
-111
View File
@@ -1,111 +0,0 @@
# Pearl reference oracle (OpenJarvis Phase 0 deliverable)
Phase 0-B of [Spec B](../../docs/design/2026-05-05-apple-silicon-pearl-mining-design.md)
called for "build a Python reference oracle for NoisyGEMM, validate against the
Pearl CUDA reference."
**Phase 0 found the oracle already exists upstream**, in two complementary forms:
| Layer | Upstream location | What it covers |
|---|---|---|
| Pure-Rust mining algorithm exposed to Python | `pearl/py-pearl-mining` | The complete `mine()` + `verify_plain_proof()` cycle. CPU-only. Hardware-portable. |
| PyTorch reference of production NoisyGEMM | `pearl/miner/miner-base/src/miner_base/noisy_gemm.py` | The same NoisyGEMM that vllm-miner accelerates with H100 CUDA. Bit-exact denoising verified by upstream test (`tests/test_noisy_gemm.py:92`). |
So this directory contains:
1. `smoke_test.py` — a runnable script that **actually mines a block on this machine** using the upstream Rust path, demonstrating the v1 architecture works on Apple Silicon (or any platform where `py-pearl-mining` builds).
2. This README documenting where the reference math lives.
## What this is *not*
This is **not a reimplementation** of NoisyGEMM. The original Spec B planned for that;
Phase 0 made it unnecessary. If you're tempted to write `noisy_gemm.py` here, stop —
read `pearl/miner/miner-base/src/miner_base/noisy_gemm.py` instead.
## Setup
You need:
- macOS arm64 (M1/M2/M3/M4) **or** Linux x86_64 / aarch64
- Python 3.12 (`uv venv --python 3.12 .venv` is the easiest)
- Rust 1.78+ (any recent toolchain — verified with 1.94 on macOS arm64)
- The Pearl source tree somewhere on disk
Build the wheel and install it (one-time, ~60 s on a fast Mac, ~5 min on first build):
```bash
# from the Pearl repo root
cd py-pearl-mining
uv pip install maturin
maturin build --release --interpreter "$(which python)"
# install the resulting wheel
uv pip install target/wheels/py_pearl_mining-*.whl
```
Or if Pearl publishes to PyPI in the future:
```bash
uv pip install py-pearl-mining
```
## Run the smoke test
```bash
python smoke_test.py
```
Actual output on Apple Silicon M2 Max (numbers will vary by hardware and run):
```
host: macOS-26.4.1-arm64-arm-64bit (arm64)
python: 3.12.1
[ok] pearl_mining loaded from <site-packages>/pearl_mining/__init__.py
[ok] PUBLICDATA_SIZE=164 MERKLE_LEAF_SIZE=1024
[ok] mine(m=256, n=128, k=1024, rank=32) returned a proof in 0.119 s
proof.m=256 proof.n=128 proof.k=1024 noise_rank=32
a.row_indices=[177, 185, 241, 249] bt.row_indices=[80, 81, 88, 89, 112, 113, 120, 121]
[ok] verify_plain_proof: ok=True ('Mining solution verified successfully', 0.2 ms)
[ok] all checks passed — Pearl mining works on this host
```
The `a.row_indices` and `bt.row_indices` values above are not constants — they're
`(offset + ROWS_PATTERN)` and `(offset + COLS_PATTERN)` for whichever offset the
miner happened to find a jackpot at. The smoke test verifies the *deltas* match
the configured `PeriodicPattern`, not the absolute values.
If it succeeds, this host can mine Pearl using the OpenJarvis `cpu-pearl` provider
(see Spec B §13). If it fails, the `[fail]` line tells you which step broke.
## What this proves (and what it doesn't)
**Proves:**
- The Pearl mining algorithm executes correctly on this host's CPU.
- Generated proofs verify under `verify_plain_proof`. (This is the same check
validators run on the inputs to the ZK proof.)
- The whole stack — `pearl-blake3`, `zk-pow`, `py-pearl-mining` — builds and
loads as a native CPython extension.
**Does NOT prove:**
- Network-difficulty hashrate. The smoke test uses
`nbits=0x1D2FFFFF` (test difficulty), much easier than mainnet. Real mining
expected hashrate on Apple Silicon CPU is several orders of magnitude lower
per share — see Spec B §1.5.6.
- ZK proof generation throughput. The smoke test calls `verify_plain_proof`,
not `generate_proof`. Plonky2 STARK proving takes seconds-to-minutes of CPU
per block (Spec B Open Q10).
- That this host can keep up with the network's block production rate.
## When to update this
- When Pearl bumps `py-pearl-mining` API: re-run the smoke test against the
new ref pinned in `OpenJarvis/src/openjarvis/mining/_constants.py`.
- When Pearl publishes a Mac wheel to PyPI: simplify the install instructions
above, drop the local `maturin build` step.
- When Spec B v2 adds the PyTorch-MPS reference path: extend `smoke_test.py`
with an MPS path comparison. The `miner-base` reference is already in
PyTorch, so the v2 smoke test would be a different test invoking
`miner_base.NoisyGemm` and comparing CPU vs MPS outputs for parity.
-139
View File
@@ -1,139 +0,0 @@
"""Pearl mining smoke test — runs an end-to-end mine + verify cycle.
Verifies that this host can run Pearl's pure-Rust mining algorithm via the
`pearl_mining` Python package. Used as Phase 0-B of the OpenJarvis Apple Silicon
mining spec ([Spec B]).
Exit codes:
0 all checks passed
1 pearl_mining import failed
2 mine() failed
3 verify_plain_proof rejected the proof
4 timing or sanity check failed
[Spec B]: ../../docs/design/2026-05-05-apple-silicon-pearl-mining-design.md
"""
from __future__ import annotations
import platform
import sys
import time
# Test fixture values — match upstream Pearl's tests/test_python_api.py so we are
# testing the same code path that Pearl's own CI exercises. Do not change
# without re-syncing with upstream.
DEFAULT_NBITS = 0x1D2FFFFF
DEFAULT_M = 256
DEFAULT_N = 128
DEFAULT_K = 1024
DEFAULT_RANK = 32
ROWS_PATTERN = [0, 8, 64, 72]
COLS_PATTERN = [0, 1, 8, 9, 32, 33, 40, 41]
def _ok(msg: str) -> None:
print(f"[ok] {msg}")
def _fail(msg: str, code: int) -> None:
print(f"[fail] {msg}")
sys.exit(code)
def main() -> None:
print(f"host: {platform.platform()} ({platform.machine()})")
print(f"python: {sys.version.split()[0]}")
try:
import pearl_mining
except ImportError as e:
_fail(f"could not import pearl_mining — install with `uv pip install py-pearl-mining` or build from source: {e}", 1)
_ok(f"pearl_mining loaded from {pearl_mining.__file__}")
_ok(
f"PUBLICDATA_SIZE={pearl_mining.PUBLICDATA_SIZE} "
f"MERKLE_LEAF_SIZE={pearl_mining.MERKLE_LEAF_SIZE}"
)
block_header = pearl_mining.IncompleteBlockHeader(
version=0,
prev_block=b"\x00" * 32,
merkle_root=b"0123456789abcdef" * 2,
timestamp=0x66666666,
nbits=DEFAULT_NBITS,
)
mining_config = pearl_mining.MiningConfiguration(
common_dim=DEFAULT_K,
rank=DEFAULT_RANK,
mma_type=pearl_mining.MMAType.Int7xInt7ToInt32,
rows_pattern=pearl_mining.PeriodicPattern.from_list(ROWS_PATTERN),
cols_pattern=pearl_mining.PeriodicPattern.from_list(COLS_PATTERN),
reserved=pearl_mining.MiningConfiguration.RESERVED,
)
t0 = time.perf_counter()
try:
plain_proof = pearl_mining.mine(
DEFAULT_M,
DEFAULT_N,
DEFAULT_K,
block_header,
mining_config,
signal_range=None,
wrong_jackpot_hash=False,
)
except Exception as e:
_fail(f"mine() raised: {e!r}", 2)
t_mine = time.perf_counter() - t0
_ok(
f"mine(m={DEFAULT_M}, n={DEFAULT_N}, k={DEFAULT_K}, rank={DEFAULT_RANK}) "
f"returned a proof in {t_mine:.3f} s"
)
print(
f" proof.m={plain_proof.m} proof.n={plain_proof.n} proof.k={plain_proof.k} "
f"noise_rank={plain_proof.noise_rank}"
)
print(
f" a.row_indices={plain_proof.a.row_indices} "
f"bt.row_indices={plain_proof.bt.row_indices}"
)
t0 = time.perf_counter()
ok, msg = pearl_mining.verify_plain_proof(block_header, plain_proof)
t_verify_ms = (time.perf_counter() - t0) * 1000
if not ok:
_fail(f"verify_plain_proof rejected our proof: {msg}", 3)
_ok(f"verify_plain_proof: ok=True ({msg!r}, {t_verify_ms:.1f} ms)")
if plain_proof.m != DEFAULT_M or plain_proof.n != DEFAULT_N or plain_proof.k != DEFAULT_K:
_fail("plain_proof dimensions do not match request", 4)
if plain_proof.noise_rank != DEFAULT_RANK:
_fail("plain_proof noise_rank does not match request", 4)
# Row indices are (offset + base_index) for some valid offset within the
# matrix dimension — see threads_partition() in zk-pow/src/ffi/mine.rs.
# We can't assert an absolute value (different offsets are valid every run),
# but we can assert the deltas match the pattern shape.
a_idxs = list(plain_proof.a.row_indices)
bt_idxs = list(plain_proof.bt.row_indices)
a_deltas = [v - a_idxs[0] for v in a_idxs]
bt_deltas = [v - bt_idxs[0] for v in bt_idxs]
if a_deltas != ROWS_PATTERN:
_fail(f"a.row_indices deltas ({a_deltas}) != ROWS_PATTERN ({ROWS_PATTERN})", 4)
if bt_deltas != COLS_PATTERN:
_fail(f"bt.row_indices deltas ({bt_deltas}) != COLS_PATTERN ({COLS_PATTERN})", 4)
print()
print("[ok] all checks passed — Pearl mining works on this host")
print()
print("Note: this used test difficulty (nbits=0x1D2FFFFF), not mainnet.")
print("Real-network shares per second will be many orders of magnitude lower.")
print("See docs/design/2026-05-05-apple-silicon-pearl-mining-design.md §1.5.6")
if __name__ == "__main__":
main()