ECDLP Cooperative Pool — API Reference

Puzzle #135 probabilistic-sampling experiment · All data CC0 · ← Dashboard

Base URL: https://pp.867635.xyz

Auth: 公开池目前无需鉴权(如果未来开启,所有 POST 端点需 Authorization: Bearer <POOL_KEY>)。

Content type: 所有 POST 请求体 application/json;所有响应 application/json(除 //docs)。

Shard math: 249 shards 共覆盖 [2134, 2135);单 shard 宽度 285range_start = 2^134 + shard_id × 2^85

Shard priority: /v1/claim 按 Bayesian tier (S→A→B→C) 派发,不是顺序。完整说明见 /strategy,机器可读定义见 GET /v1/strategy

Client Protocol(worker 主循环)

POST/v1/claim

申领一个 shard,进入运行状态。服务器会自动回收过期 lease。每个 worker 不会重复领取自己已扫过的 shard。 派发顺序:Tier S (40-45% / 55-60% / 80-85%) → A → B → C,详见 /strategy

# request body
{ "worker_id": "myhost-abc123" }
# response (200)
{
  "shard_id":    "473812149032693",
  "range_start": "44b8000000000000000000000000000000",
  "range_end":   "44b9ffffffffffffffffffffffffffffff",
  "lease_until": 1747645200,
  "tier":        "S",                // 此 shard 所属 Bayesian tier (S|A|B|C)
  "pct":         42.31               // shard 在 2^49 空间的百分位
}
# 错误
400 { "error": "worker_id required" }
503 { "error": "no shard available, retry later" }
# curl 示例
curl -X POST https://pp.867635.xyz/v1/claim \
  -H "content-type: application/json" \
  -d '{"worker_id":"myhost-abc123"}'

POST/v1/heartbeat

每 30 秒发送一次。同时延长 lease(防止被回收)+ 上报进度。所有数值字段可选;缺省则保留旧值。

# request body (除 worker_id/shard_id 外字段全部可选)
{
  "worker_id": "myhost-abc123",
  "shard_id":  "473812149032693",
  "ops":   1234567890,     // 累计 ops
  "dps":   42,             // 累计 distinguished points
  "speed": 5120            // 当前速度 MKeys/s
}
# response
{ "ok": true, "extended_until": 1747645800 }

POST/v1/complete

shard 扫描结束(达到 ops 预算或解出)调用。found=true 时只发送布尔标记,私钥不离开客户端,命中通过 Telegram 等 side-channel 通知,服务端只存 "REDACTED"。

# request body
{
  "worker_id": "myhost-abc123",
  "shard_id":  "473812149032693",
  "found":     false        // 命中也只发 true,不发 private_key
}
# response
{ "ok": true }
安全:客户端不应该把 private_key 放进 body。服务端 schema 中 private_key 字段在命中时被强制写入字符串 "REDACTED"

Public Statistics

GET/v1/stats

全局 shard 状态计数。

# response
{
  "total":   "562949953421312",   // 2^49 总 shard 数
  "touched": 47,                  // 曾被申领过的 shard 数
  "open":    5,                   // 当前可领取(含 lease 过期)
  "taken":   1,                   // 当前有效 lease 持有中
  "done":    41,                  // 已完成扫描
  "hits":    0                    // 命中次数
}

GET/v1/workers

活跃 + 最近完成的 workers 列表(dashboard 用)。active[] 现已包含 tierpct 字段。

# response
{
  "now": 1747645200,
  "active": [{
    "worker_id":   "...",
    "shard_id":    "473812149032693",
    "status":      "taken",
    "taken_at":    1747640000,
    "lease_until": 1747645200,
    "ops_done":    1234567890,
    "dp_count":    42,
    "speed_mks":   5120,
    "range_start": "...",
    "range_end":   "...",
    "tier":        "S",                // S | A | B | C
    "pct":         42.31
  }],
  "recent": [/* 最近 50 个 done shard */]
}

GET/v1/health

健康检查。

# response
{ "ok": true }

Shard Priority Strategy

完整 rationale + 数据来源见 /strategy(人类阅读)。下面两个 JSON 端点用于机器读取。

GET/v1/strategy

静态返回 tier 定义、5%-桶位置、claim 顺序,以及数据来源摘要。前端 / 第三方分析工具用。

# response
{
  "schema":       "v1",
  "total_shards": "562949953421312",
  "claim_order":  ["S", "A", "B", "C"],
  "tiers": {
    "S": {
      "label":     "S",
      "priority":  30,
      "bands":     [[40,45],[55,60],[80,85]],
      "capacity":  "84442492963196",
      "width_pct": 15,
      "rationale": "完全冷区, posterior > 8% per 5%-band"
    },
    "A": { ... },
    "B": { ... },
    "C": { ... }
  },
  "evidence": {
    "large_puzzles_sample":    12,
    "cold_zone_enrichment":    1.22,
    "observed_cold_hits":      7,
    "uniform_expected_cold_hits": 5.8,
    "caveats": [
      "n=12 是小样本,1.22× 非统计强证据",
      "行为先验:10 年扫描密度集中在 0-10% / 95-100% / 中点 50%",
      "若 #135 真为均匀随机,按 tier 扫与按顺序扫期望耗时相同",
      "若哪怕 10% 的偏置成立,按 tier 扫期望耗时减半"
    ]
  }
}

GET/v1/tier_stats

每个 tier 实时 claimed / active / done 计数与容量。Dashboard 顶部 "Tier coverage" 用。

# response
{
  "schema": "v1",
  "now":    1747645200,
  "tiers": {
    "S": {
      "priority":  30,
      "capacity":  "84442492963196",   // 该 tier 总 shard 数
      "claimed":   42,                 // 该 tier 已申领过的 shard 数
      "active":    7,                  // 当前 lease 持有中
      "done":      30,
      "width_pct": 15
    },
    "A": { ... }, "B": { ... }, "C": { ... }
  }
}

Open Research Data(CC0)

三个 /v1/research/* 端点暴露的是 append-only 的 shard_attempts 表 — 每次申领都是一行新记录,lease 过期/重新申领不会覆盖历史。即使一个 shard 被多个 worker 反复领过,全部 attempt 都保留。

GET/v1/research/dump

原始 attempt 记录,可分页。

limit int (默认 1000, 上限 5000) · offset int (默认 0) · since unix-ts (默认 0)

# response
{
  "schema": "v1",
  "limit": 1000, "offset": 0, "since": 0,
  "count": 47,
  "attempts": [{
    "attempt_id":     1,
    "shard_id":       "473812149032693",
    "worker_id":      "...",
    "started_at":     1747640000,
    "ended_at":       1747641320,
    "final_status":   "completed",  // completed | completed_hit | expired | null(active)
    "ops_done":       3214000000,
    "dp_count":       42,
    "speed_mks":      5120,
    "last_heartbeat": 1747641310
  }]
}
# curl 示例
curl 'https://pp.867635.xyz/v1/research/dump?limit=100&since=1747000000'

GET/v1/research/distribution

已完成 attempts 的 ops / speed 直方图 + 整体 summary。

# response
{
  "schema": "v1",
  "summary": {
    "total_attempts": 50,
    "completed":      47,
    "expired":        2,
    "hits":           0,
    "still_active":   1,
    "avg_ops_done":   3214000000,
    "avg_speed_mks":  5050
  },
  "ops_distribution":   [{ "bucket": "1G-1T", "n": 47 }, ...],
  "speed_distribution": [{ "bucket": "5k-10k", "n": 42 }, ...]
}

Buckets: ops ∈ {0, <1M, 1M-1G, 1G-1T, 1T-1P, ≥1P} · speed (MK/s) ∈ {0, <1k, 1k-5k, 5k-10k, ≥10k}

GET/v1/research/coverage

已被申领过的全部 distinct shard_id 列表 + 覆盖率。

limit int (默认 1000, 上限 10000) · offset int (默认 0)

# response
{
  "schema": "v1",
  "total_distinct_shards": 47,
  "total_possible_shards": "562949953421312",
  "coverage_fraction":     8.35e-14,
  "limit": 1000, "offset": 0,
  "shard_ids": ["473812149032693", "..."]
}

使用示范:最小 worker 循环(伪码)

WORKER_ID="myhost-$(openssl rand -hex 8)"
while true; do
  CLAIM=$(curl -sX POST $POOL/v1/claim -H "content-type: application/json" \
    -d "{\"worker_id\":\"$WORKER_ID\"}")
  SID=$(echo $CLAIM | jq -r .shard_id)
  RS=$(echo $CLAIM | jq -r .range_start)
  RE=$(echo $CLAIM | jq -r .range_end)

  # run solver — 心跳每 30s 发送 ops/dps/speed
  ./rckangaroo -lottery-shard $SID -start $RS ... &
  SOLVER_PID=$!
  while kill -0 $SOLVER_PID 2>/dev/null; do
    sleep 30
    curl -sX POST $POOL/v1/heartbeat -H "content-type: application/json" \
      -d "{\"worker_id\":\"$WORKER_ID\",\"shard_id\":\"$SID\",\"ops\":$OPS,\"dps\":$DPS,\"speed\":$SPEED}"
  done

  curl -sX POST $POOL/v1/complete -H "content-type: application/json" \
    -d "{\"worker_id\":\"$WORKER_ID\",\"shard_id\":\"$SID\",\"found\":false}"
done