公开的加密谜题与赏金,以带类型的记录形式呈现。你请求一个谜题,就能得到它的地址、密钥材料以及链上发生的情况。
每个谜题帖都有同样的三样东西:地址、奖品,以及谁解出了什么。每个扫描器和追踪器都会从帖子中重新录入这些信息,每次还略有不同。所以它们在这里只存在一次,以代码的形式。一个谜题就是一条 TypeScript 记录。类型检查器在测试之前读取它。CLI、MCP 服务器以及 Pi 和 OMP 扩展读取同一个注册表。
文档,每个谜题一页,外加一个实时演练场:puzzles.agntn.dev。
[!WARNING] 1.0 之前。API、CLI 标志和数据模型仍可能变动。如果你要基于它构建,请固定精确版本。
PuzzleSpec 字面量,由同一个 puzzle() 工厂为所有链构建。没有 JSON,没有构建步骤。get("bits/71") 只导入一个集合模块。@agntn/explorers 调用 puzzle.balance()。基础单位以 bigint 表示,错误信息中的 API 密钥会被脱敏。puzzles watch 列出记录遗漏的存款和支出、发生变动的奖品、某次支出泄露的公钥、发生变化的源页面。它从不编辑记录。由你来编辑。puzzles eligibility 收集来源、地址、来自浏览器的生命周期总额、带证据的状态以及什么算作解答。任何无人能填的内容都会以 missing 行返回,绝不猜测。puzzles_assets 把提示背后的图片、阶段文件和存档帖子交给模型,并与记录中固定的 SHA-256 进行校验。链接会失效。这些不会。pnpm add @agntn/puzzles
需要 Node.js 26 或更高版本才能使用 CLI。
npx @agntn/puzzles stats
它会打印总数、每种状态各有多少个,以及有多少个谜题拥有已知公钥。无需密钥、无需配置、无需网络。这些记录随包一起提供。下面的裸 puzzles 命令,是在本地执行 pnpm add 之后的 pnpm exec puzzles,或者是在执行 pnpm add -g @agntn/puzzles 之后直接使用 puzzles。
puzzles show hash-collision/sha256
hash-collision/sha256 unsolved 0.27734251 BTC 35Snmmy3uhaer2gTboc81ayCip4m9DT4ko
chain: bitcoin address kind: p2sh
hash160: 292fb39df7cd619a396069383928e6bfb74ebec5
redeem script: 6e879169a87ca887 (hash 292fb39df7cd619a396069383928e6bfb74ebec5)
public key: unknown
private key: unknown
started: 2013-09-13 05:59:09
transactions: 1
funding 2013-09-13 05:59:09 0.1 BTC 397f12ee15f8a3d2ab25c0f6bb7d3c64d2038ca056af10dd8251b98ae0f076b0
explorer: https://blockstream.info/address/35Snmmy3uhaer2gTboc81ayCip4m9DT4ko
source: https://bitcointalk.org/index.php?topic=293382.0
| 命令 | 输出内容 |
|---|---|
puzzles stats | 总计、状态计数、奖金总额和数据版本 |
puzzles collections | 每个集合一行:键、计数、作者 |
puzzles authors [key] | 每个作者一行,或某个作者的记录及其来源事实 |
puzzles author <key> | 某个作者的记录,直接来自 puzzles_author 工具 |
puzzles solvers [key] | 每个具名解题者一行,或某个解题者的记录:每次解题、个人资料和来源事实 |
puzzles solver <key> | 某个解题者的记录,直接来自 puzzles_solver 工具 |
puzzles show <id> | 某个谜题的记录:关键材料、交易、提示和链接。--json 输出数据 |
puzzles hints <id> | 集合的提示、谜题自身的提示,然后是它的提示文件。--json 输出两者 |
puzzles stages <id> | 多阶段谜题的各个阶段及其页面、文件和已公布的答案。--json 输出列表 |
puzzles assets <id> | 谜题附带的文件及其 SHA-256 和大小,以及它引用的归档页面。--read <path> 写入一个,--check/--live 进行验证 |
puzzles list [collection] | 每行一个谜题。--address、--chain、--status、--technique 和 --with-pubkey 用于缩小范围,--limit 和 --offset 用于分页 |
puzzles verify [id] | 将已公布的密钥及其配方与地址进行核对。--all 或 list 过滤器用于一组,不匹配时退出码为 1 |
puzzles balance [id] | 实时余额。list 过滤器检查整组,每行一个。--api-key,或每条链一个变量 |
puzzles watch [id] | 链上已知但记录中没有的内容。--since 也会检查源页面,发现任何问题退出码为 1 |
puzzles eligibility <query> | 处理奖金前的检查清单,按 id 或地址。任何字段缺失时退出码为 1 |
puzzles export | 整个数据集及其 data_version |
puzzles mcp | 通过 stdio 运行的 MCP 服务器 |
--json 输出文本背后的数据,bigint 以字符串形式表示,缺失字段则省略。这些命令来自与智能体相同的工具定义,因此标志中的拼写错误在这里会失败,就像对模型一样失败。标志和退出码见 CLI 指南。
import { get, stats, verify } from "@agntn/puzzles";
import { bits } from "@agntn/puzzles/collections/bits";
const puzzle = await get("bits/71"); // loads the bits collection, nothing else
puzzle?.address().value; // "1PWo3JeB9jrGwfHDNpdGK54CRas7fsVzXU"
puzzle?.keyRange(); // [2n ** 70n, 2n ** 71n - 1n]
(await verify(bits.require(1))).verified; // true, key 1 derives its address
(await stats()).unsolved; // how many are still waiting for a key
(await bits.require(71).balance()).totalUnits(); // 7.10190014 when I ran it, mempool.space decides
大致就是这样。集合本身就是一个独立条目,其中的一切都是同步的。跨集合的视图会等待加载完成。错误都派生自 PuzzlesError,余额则拥有自己独立的一族,位于 BalanceError 之下。其余内容都在指南中:records、registry、lookups、verification、balances。