mirror of
https://github.com/logos-blockchain/research.git
synced 2026-08-07 19:53:10 +00:00
76 lines
3.7 KiB
Python
76 lines
3.7 KiB
Python
"""The mining benchmark must turn effort searches into a measured mint rate:
|
|
per-core and whole-machine tokens/s, with failed searches excluded."""
|
|
from pathlib import Path
|
|
|
|
import equix_bench.mining as mining
|
|
from equix_bench.mining import measure_point
|
|
from equix_bench.protocol import Result, Run
|
|
from equix_bench.registry import Adapter
|
|
|
|
|
|
def _result(wall_ns, attempts, achieved, ok=True, target=1000):
|
|
runs = [Run(index=0, wall_ns=wall_ns, solutions=1 if achieved else 0, compile_ns=0,
|
|
attempts=attempts, achieved_effort=achieved, verify_result=None)]
|
|
# Winning-token wire bytes are emitted only when the target was reached:
|
|
# a 16-byte solution and an 8-byte nonce, as the real runners produce.
|
|
minted = achieved >= target
|
|
return Result(ok=ok, impl_name="equix-rust", impl_version="1", impl_commit="c",
|
|
operation="effort", runtime_requested="try-compile", runtime_effective="compiled",
|
|
env={}, runs=runs, solutions_hex=["ab" * 16] if minted else None,
|
|
peak_rss_kb=4000, error=None,
|
|
winning_nonce_hex="00" * 8 if minted else None)
|
|
|
|
|
|
def _adapter():
|
|
return Adapter(name="equix-rust", exec=["/bin/true"], protocol_version=1,
|
|
capabilities=["effort"], runtimes=[], env={})
|
|
|
|
|
|
def test_measure_point_rates_and_scaling(monkeypatch):
|
|
# Every search: 0.5 s, 100 attempts, reaches the target -> 2 tokens/s/core.
|
|
monkeypatch.setattr(mining, "run",
|
|
lambda a, s, r, timeout=900.0: _result(500_000_000, 100, 1000))
|
|
p = measure_point(_adapter(), "abcd", effort=1000, samples=5, workers=4,
|
|
tokens_per_worker=3, nonce_bytes=8, max_attempts=1_000_000,
|
|
repo_root=Path("."), timeout=10)
|
|
assert p.samples == 5
|
|
assert abs(p.tokens_per_sec_1core - 2.0) < 1e-9 # 5 tokens / 2.5 s
|
|
assert abs(p.token_s_mean - 0.5) < 1e-9
|
|
assert p.attempts_mean == 100
|
|
# 4 workers, each streams 3 tokens (3/1.5s = 2/s), no contention -> 8 tokens/s.
|
|
assert p.ok_workers == 4
|
|
assert abs(p.tokens_per_sec_machine - 8.0) < 1e-9
|
|
assert abs(p.scaling_efficiency - 1.0) < 1e-9
|
|
# Message sizes measured from every minted token: constant 16 B + 8 B.
|
|
assert (p.solution_bytes_min, p.solution_bytes_max, p.nonce_bytes_wire) == (16, 16, 8)
|
|
|
|
|
|
def test_measure_point_excludes_failed_searches(monkeypatch):
|
|
# achieved (500) never reaches target (1000) -> every sample rejected.
|
|
monkeypatch.setattr(mining, "run",
|
|
lambda a, s, r, timeout=900.0: _result(500_000_000, 100, 500))
|
|
p = measure_point(_adapter(), "abcd", effort=1000, samples=4, workers=2,
|
|
tokens_per_worker=2, nonce_bytes=8, max_attempts=1_000_000,
|
|
repo_root=Path("."), timeout=10)
|
|
assert p.samples == 0
|
|
assert p.tokens_per_sec_1core == 0
|
|
assert p.tokens_per_sec_machine == 0
|
|
|
|
|
|
def test_distinct_nonce_ranges_do_not_overlap(monkeypatch):
|
|
# Record the nonce_start each invocation used; ranges must be STRIDE-spaced
|
|
# and disjoint between the 1-core samples and the concurrent worker streams.
|
|
seen = []
|
|
def rec(a, spec, r, timeout=900.0):
|
|
seen.append(spec.nonce_start)
|
|
return _result(100_000_000, 10, 1000)
|
|
monkeypatch.setattr(mining, "run", rec)
|
|
measure_point(_adapter(), "abcd", effort=1000, samples=3, workers=2,
|
|
tokens_per_worker=2, nonce_bytes=8, max_attempts=1_000_000,
|
|
repo_root=Path("."), timeout=10)
|
|
S = mining.STRIDE
|
|
# 3 sequential 1-core samples at 0,S,2S; then worker0 streams 3S,4S, worker1 5S,6S.
|
|
assert seen[:3] == [0, S, 2 * S]
|
|
assert sorted(seen[3:]) == [3 * S, 4 * S, 5 * S, 6 * S]
|
|
assert len(set(seen)) == len(seen) # all disjoint
|