ledgeroot
v0.9.1
Published
MCP payment plugin and evidence engine for agent x402 payments. Every agent payment, on the record.
Downloads
2,817
Maintainers
Readme
Ledgeroot
面向 agent x402 支付的 MCP 支付插件 + 证据引擎
Every agent payment, on the record.
English · 中文
看它拦下一笔被提示注入的支付
$ LEDGEROOT_DRY_RUN=true npm run demo
1. 签发授权令 → demo-mandate(issuer 0x19E7…ff2A)
2. 正常支付 → paid,0.1 USDC 付给 agent402.tools/search
3. 同 requestId 重试 → paid,deduplicated: true(不再扣款)
4. 提示注入转账 → denied:payTo "0x…dead" is not bound by the mandate
5. 一键熔断 → 已撤销 1 条授权
6. 熔断后支付 → denied:unknown mandate "demo-mandate"
7. 离线验证 → verified,3 张收据,0 个问题摘自一次真实运行;第 4、6 行是收据里
reason字段的原文(拒付原因由代码以英文写出)。被拒付也是一张收据——第 4、6 步各自带签名留痕,所以账本最后是 3 张收据,且离线验证依然干净。
不用钱包、不用 USDC、不用网络、不用注册账号。完整闭环就是这些:授权 → 约束 → 支付 → 拒付 → 熔断 → 离线验证。
快速开始
1. 离线跑完整闭环(60 秒)
npm install
npm run build
LEDGEROOT_DRY_RUN=true npm run demo2. 接进 Claude Code
claude mcp add ledgeroot \
--env LEDGEROOT_PRIVATE_KEY=0x你的私钥 \
--env LEDGEROOT_SIGNING_KEY=0x收据签名密钥 \
--env LEDGEROOT_DB=/绝对路径/ledgeroot.sqlite \
-- npx ledgeroot serve之后全程对话:
- 签发授权:说「给它授权 5 USDC 买 agent402.tools 数据」→ Claude 调
ledgeroot_mandate_sign→ 你确认。 - agent 花钱:说「帮我调研 X,要买付费数据」→ agent 调
ledgeroot_pay→ 策略校验 → facilitator 结算 → 六段收据。 - 撤销:说「撤销它的授权」→
ledgeroot_mandate_revoke。 - 审计:说「验证证据」→
ledgeroot_verify。
自然语言解析由宿主完成。Ledgeroot 只提供结构化、确定性的工具;私钥经
--env传入并留在本机。
CLI
node dist/cli.js verify [--db <path>] [--check-chain] # 离线验证(可选加链上校验)
node dist/cli.js export [--db <path>] # 导出证据包 JSON
node dist/cli.js anchor [--db <path>] [--watch] [--every <秒>] [--min-receipts <n>] [--force]
# 提交 epoch 根上链。
# --watch 随收据到达持续锚定;
# 账本无新增则跳过,不会重复为同一个根付 gas
# 换合约会自动重锚;--force 用于合约未知的记录
node dist/cli.js buy <url> --mandate <id> \
[--method POST] [--body '<json>'] [--chain 143] # 取一个 URL、付掉它的 402、写下收据
node dist/cli.js jwks # 第三方验签所需的 JWKS
node dist/cli.js serve # 以 stdio 启动 MCP server作为库使用
import { PolicyEngine, defaultPolicies, merkleProof, verifyMerkleProof } from "ledgeroot";
import { LedgerootStore } from "ledgeroot/store";
import { verifyReceiptChain } from "ledgeroot/verify";子路径导出:ledgeroot · /store · /verify · /anchor · /receipt · /types。库本身不加载 .env——环境由调用方掌握(只有 CLI 与 server 入口调 loadEnv())。
真实支付与上链锚定
# Monad testnet。需要 LEDGEROOT_PRIVATE_KEY 与测试网 USDC(Circle faucet)。
npm run demo:pay -- <payTo地址> 0.001
npm run verify -- --db ./ledgeroot.sqlite
# 锚定 epoch 根(合约需要 Foundry;forge-std 是 git submodule)
forge install foundry-rs/forge-std && forge build && forge test
LEDGEROOT_DEPLOYER_PRIVATE_KEY=... npm run deploy:monad # owner 由 LEDGEROOT_PRIVATE_KEY 推导
npm run anchor -- --db ./ledgeroot.sqlite买入一个资源(402 流程)
ledgeroot_pay 结算的是调用方手里已经有报价的支付——因为 402 握手是宿主在别处做的,而那里发生的事审计轨迹看不见。ledgeroot_buy 自己去把报价拿来:
1 请求资源 → 402,带着卖家的支付要求
2 选一条能付的轨 → 本构建只注册的那一条网络
3 跑全部策略 → 对着*那份*报价,在签名之前
4 签授权 → 只有第 3 步放行才签
5 带支付重试 → 由卖家经它自己的 facilitator 结算
6 记收据 → 报价进第三段、结算进第五段、
响应体的哈希进第六段闸门卡在签名那一刻——那是"拒绝仍然免费"的最后一个时点。被拒绝会写成一张 denied 收据,带上卖家自己的报价,并列出每一条跑过的策略的判定:一次在真实卖家处被拦下的采购,连同原因一起留在账上。
| 结果 | 含义 |
|---|---|
| paid | 卖家收下了支付;收据带结算信息与交付哈希 |
| denied | 策略拒绝,或卖家提供的轨我们都付不了。两种情况下都没有签名,尝试都会记录;卖家还没报出报价时,收据里的报价是空的 |
| unpaid | 资源在没有支付的情况下返回(免费额度或 trial)。不写收据——没有支付可证明 |
闸门之后的失败——传输错误,或我们递了支付之后卖家仍要钱——是抛出而不是归类,因为是否已结算在此无从得知。幂等占位会保留,所以重试是拒绝,而不是再买一次。
📌 这一半的协议实现——读 402、造 payload、重试、结算——是
@x402/fetch。我们在它上面注册一条轨和一道闸门。自己重写握手只会得到一份更差的副本,而真正有意思的问题从来不是谁会跳那段 HTTP 舞。
⚠️ 我们要买的卖家只收主网。 agent402 实时 402 在十二条链里给了
eip155:143(Monad 主网),测试网上一条都没有。所以ledgeroot_buy默认chainId: 143,而一次真实采购就是一次真实的(虽然很小的)支付。
为什么用 Ledgeroot
- fail-closed 是结构性的。 每条策略都跑,第一个拒绝即中止支付,并且拒绝本身也被记录。不存在"跳过一次检查然后放行"的路径。
- 可验证,不只是有日志。 收据带 Ed25519 签名、哈希链互锁、commit 到链上 epoch Merkle 根。第三方离线即可验证——不连回、不经手任何厂商。
- 拒付也是证据。 被拦下的尝试与成功的支付产生同样格式的签名收据。那是 agent 任务失败唯一能被看见的地方。
- 它真的去买,不只是结算。
ledgeroot_buy自己去取资源,所以它据以判定的报价就是卖家发来的那一份,而第六段是它实际收到的响应体。 - 一把钥匙动钱,一把钥匙作证。 收据签名密钥与支付密钥刻意不互相回落。
- 钱不碰浮点。 全程六位小数 bigint 运算。
- 对"不知道"诚实。 证据缺失报
incomplete,绝不报成被篡改,也绝不放行。 - 证明的是执行,不只是意图。 一致性视图会把已付收据拿回它所属的 mandate 再校验一遍。
- MIT、本地 SQLite、无 SaaS、无遥测。 什么都不会离开本机。
它站在哪一格
生态位:链上稳定币 × agent 小额 402 支付(单价 $0.001–$0.05,百万笔/月量级)。
这个位由费率结构保证,不由技术优势保证:$0.30 + 2.9% 的卡组织费率摊在 $0.005 上等于 6000%,物理上不可行。所以 x402 存在;也所以我们不做大额——大额有发票、合同、退款流程,那是 Shopify / Stripe / Visa TAP / Mastercard 的地盘。
⚠️ 费率结构排除的是按交易金额抽成的对手,不排除按负载计费、把支付当平台功能送的云厂商——见 competitors.md §二。
在这个位里,Ledgeroot 只做三件事:
| 做 | 不做 | |---|---| | 授权 —— 用户自签的 mandate 约束 agent 能花多少、付给谁、到何时 | ❌ 不做托管 —— 私钥永不出本机 | | 执行前校验 —— fail-closed 策略引擎,五条默认策略 | ❌ 不做路由器 / 发现层 —— 分发层已被占据 | | 审计留痕 —— 六段收据 + 哈希链 + 上链锚定 + 离线三态验证 | ❌ 不做 LLM 推理闸门 —— 我们的优势恰恰是确定性 |
📌 在这个粒度下,"收据"本身不是产品($0.005 的万分之一),它是原料。能收费的只有把收据变成账的那一层。这个定位不影响收据的工程质量——上层要可信,底下每张收据就必须能独立验证。
对齐 MAS SAFR
Ledgeroot 的三层与 MAS《Safeguards for Agentic Finance at Runtime》的三个运行时保障功能一一对应——我们在看到这份文档之前就独立实现了同一套架构:
| SAFR 功能 | Ledgeroot 实现 |
|---|---|
| 身份与权限(establish agent's identity and authority) | mandate(EIP-712 签名授权令)+ ledgeroot_mandate_sign |
| 执行前评估(evaluate agent actions against controls before execution) | 策略引擎(fail-closed,五条默认策略)+ ledgeroot_pay 前置校验 |
| 审计留痕(maintain a clear audit record) | 六段收据 + RFC 8785 哈希链 + epoch Merkle 根上链 + ledgeroot_verify 离线三态验证 |
SAFR 是自愿性框架(2026-07-03 发布);真正有约束力的是 MAS 即将定稿的 AI 风险管理指南(覆盖 agentic AI)。两层都值得对齐——我们现在就按 SAFR 的三层实现。
能接什么
- 任意 MCP 宿主 —— Claude Code、opencode,以及任何说 MCP 的宿主(这是我们唯一维护的集成面)。
- x402 网关 —— 包括已上 Coinbase Bazaar 的那些。
- 目前是 Monad —— 默认 testnet(chainId 10143),主网(143)已接通购买、结算校验与锚定;facilitator 为
x402-facilitator.molandak.org。换链是补一个配置实例,不是重写;见已知边界。 - AP2 风格授权令 —— 可导入外部签名授权,并与本地策略取交集。
六段收据
意图 → 授权 → 计划 → 调用 → 交易哈希 → 交付凭证
| 段 | 内容 | 落在哪 |
|---|---|---|
| 1. 意图 | 自然语言说明 agent 为什么付这笔钱 | segments.intent.text |
| 2. 授权 | 覆盖本次支付的 mandate + 策略交集(mandate 实际约束了哪几条策略) | segments.mandate |
| 3. 计划 | 卖家发来的 402 报价原样,加上它的规范哈希 —— payTo 与报价金额都从这里读,因此"策略判定的是什么"与"收据记录的是什么"是同一个对象 | segments.plan |
| 4. 调用 | 逐条策略的判定结果,放行的和拒付的都记 | segments.call.policyResults |
| 5. 交易 | 结算协议 + txHash + chainId + payer | segments.tx |
| 6. 交付 | 只存响应体的哈希与字节数,不存原文 | segments.delivery |
几个刻意的地方:
- 段间由 RFC 8785 规范化哈希互锁:每张收据带
prevHash回指上一张的receiptHash,append-only,不支持原地更新(收据的id就是它内容的规范哈希——改一个字节就换了身份)。 - 每张收据带 Ed25519 detached 签名,JWS 式
protected头,签名覆盖{payload, protected},因此alg/kid落在被签字节内,不可事后替换。kid是公钥的 RFC 7638 JWK thumbprint——标识由密钥本身派生,无需注册表,也不会与密钥漂移。 - 哈希链证"内容没被改",签名证"谁做的陈述"。 两者独立:内容被改并重新哈希后链校验仍能通过,只有签名能发现。
- 公钥以 JWKS 发布(
npx ledgeroot jwks),并随证据包一起导出,第三方无需连回即可验签。 - 第六段只能由调用方回报(
ledgeroot_pay的responseBody)。Ledgeroot 结算支付,但不抓取资源——响应体只有 agent 见过,所以这一段的哈希只能由调用方提供。 - 第三段是可验证的,不只是描述性的。 报价原样存储并由哈希承诺,验证方会重算
canonicalHash(segments.plan.quote)做比对。签名后偷换报价会被这条抓住——即使把收据重新哈希并重新签名也一样。而payTo与报价金额取自同一个对象,调用方也就无法一边传一个合规的payTo、一边让报价指向别处。
签名密钥与支付密钥是分离的
| 变量 | 用途 | 落空时 |
|---|---|---|
| LEDGEROOT_PRIVATE_KEY | 动钱:签 EIP-3009 授权(未设 LEDGEROOT_ANCHOR_KEY 时也用它提交锚定) | 无法支付 |
| LEDGEROOT_SIGNING_KEY | 只做陈述:签收据 | 收据不签名 → verify 报 incomplete 而不是 verified |
刻意不互相回落:一把钥匙动钱,一把钥匙作证,互不兼任。无法归因的证据不该报 verified。
三态验证(离线优先)
验证不依赖任何服务器,ledgeroot verify 直接读本地库重算。
| 状态 | 含义 |
|---|---|
| verified | 全部检查通过 |
| tampered | 字节被检查过,对不上 —— 自哈希不符 / prevHash 断链 / 首张带 prevHash / plan.quoteHash 与所记录的报价对不上 / 重算 epoch 根与锚定根不符 / 已锚定 epoch 内的收据缺失 / 签名不符 / alg 不受支持 |
| incomplete | 证据缺失或取不到 —— 未签名 / 验证方不持有该 kid / 已付收据缺 txHash / 锚定记录无边界 / 未知结算协议 / 节点不可达 |
这条界线是整个产品最重要的纪律:tampered 优先于 incomplete,而取不到证据绝不报成被篡改。把网络故障报成篡改,会让告警整体失去可信度;反过来把缺失当放行,就是宣称做了一次没做的检查。
链上结算校验是显式选用的(--check-chain / checkChain: true):离线路径保持同步且零网络,链上校验才去拉 RPC。
| 链上校验的判定 |
|---|
| 交易不存在 → tampered(链上没有这笔) |
| 节点连不上 → incomplete(读不到 ≠ 不存在) |
| 交易回滚 / to 不是 USDC 合约 / 调用不是 transferWithAuthorization / to·value·from 与收据的 payTo·amount·payer 不符 → tampered |
| 非 x402 的结算协议 → incomplete(见已知边界) |
锚定边界:epoch 根覆盖的是「提交那一刻已存在的收据数」(receiptCount)。验证按该边界切片重算,所以锚定之后再发生支付不会误报篡改;反过来,已锚定的收据少于记录数 → tampered(是删除)。
锚定记录会写明合约。 每条本地锚定记录都标出它的根提交到了哪个合约,所以改 LEDGEROOT_ANCHOR_ADDRESS 会被识别出来而不是被静默跳过:旧合约的记录无法让新合约看起来"已锚过",下一次 anchor 会自动重提。早于该列存在的记录不带合约——目标未知,这才是 --force 的用途。
五条默认策略(fail-closed)
攻击形态各有对应的那条:
- 对手方白名单 —— 只付 mandate 里列出的 x402 网关
- payTo 绑定 —— 结算地址必须与 mandate 绑定一致(拦住上面 demo 里那笔提示注入转账的就是这一条)
- 报价漂移 —— 实际扣款与 402 报价的偏差不得超过阈值(默认 10%)
- 端点限速 —— 每个端点限制调用频率
- 限额 —— 单笔上限 + 累计上限
约束的语义:白名单与 payTo 列表为空 = 不约束(不是拒绝一切);限速要 mandate 显式配置 endpointRateLimit 才生效;限额两条恒生效。ledgeroot_mandate_import 会把 mandate 的约束与本地已注册策略取交集,写进收据第二段。
引擎跑完每一条策略并记录全部判定,返回第一个拒绝。金额一律走 decimal.ts 的 bigint 六位小数整数运算——钱不做浮点。
这几条里,链上表达不了的是报价漂移、端点限速、累计上限(structuring)与拒付留痕。 链上只知道地址,不知道 host、不知道报价、不记录"被拦下的尝试"。这是这一层存在的理由。
幂等、崩溃窗口与任务关联
x402 轨道与本地库不是一个事务。Ledgeroot 用两个可选关联键补上支付原语回答不了的问题:
requestId —— 幂等,且在动钱之前占位
朴素做法("结算成功后再写收据,重试时查收据去重")有一个致命窗口:钱已结算、收据还没落库时崩溃,则钱动了、没有记录、requestId 也查不到 → 重试再付一次。这既丢证据又丢钱,而且丢的正是产品声称要防的事。
所以 requestId 在尝试时被消耗,而不是在成功时:
| 步 | 动作 |
|---|---|
| 1 | 命中已有收据 → 直接回放(deduplicated: true),不再次扣款 |
| 2 | 策略放行后、动钱之前:在链外的 payment_intents 表占位 |
| 3 | 占位失败(该 key 已被占,说明上一次尝试的结果没被记录)→ 拒付,并记一条 denied 收据 |
| 4 | 结算 → 写收据 → 释放占位 |
为什么占位失败必须拒付而不是重试:那一行的含义是「我们不知道那笔支付有没有结算」。拒付是可恢复的,重复付款不是。
⚠️ 预写记录只能在链外:收据的
id是内容哈希,把status从pending改成paid就会改哈希,下一张收据的prevHash会指向不存在的哈希。链是 append-only 的,原地更新在结构上不可能。⚠️ 不传
requestId就没有这层保护——没有可对应的键。幂等必须主动要求。
taskId —— 意图链
把多笔支付归到同一个用户任务下;仪表盘据此聚合展示「N 笔 / 总额 / 拦截数」。
撤销
ledgeroot_mandate_revoke 撤销单条;存储层另有一键熔断(revokeAllMandates)供控制面调用。撤销后的下一笔当场拒付并留痕。
已知边界
诚实部分。这些是当前实现的边界,不是设计意图的否定;对应的排序与取舍记录在 roadmap.md。
| 边界 | 现状 |
|---|---|
| 支付路径仍然只支持测试网 | X402_NETWORKS 现在有两个实例(Monad 测试网 10143、主网 143),ledgeroot_buy 按 chainId 二选一。ledgeroot_pay 没有:bootstrap.ts 仍然无条件把 MONAD_TESTNET_X402 交给 facilitator,也没有环境变量能改 |
| 区块时间不是合格时间源 | 锚定已跑在 Monad 主网(0x958f887f203a08f43fe45ba00a6a4199b9e01b61),比之前的测试网合约进了一步,但区块时间戳仍不是外部权威;后续仍是 RFC 3161 合格时间戳 |
| MPP 只有接缝,没有实现 | segments.tx.protocol 是显式维度:未知协议报 incomplete,不放行也不冤枉。但 MPP 的字段级形状未定,所以没有预设载荷,也没有 provider。这是 roadmap.md 里排在第一位的待补项 |
| 热路径未加索引 | 全库没有一个 CREATE INDEX:单笔支付有 4 次未索引全表扫描,其中两次还会 JSON.parse 整个匹配集。单笔 O(n),一个月 O(n²) |
| 单进程、单租户 | 一个库、一把签名钥、一把付款钥。数据模型里没有租户边界——agentId / mandateId 不是隔离键 |
| 测试网锚定无证据价值 | 测试网部署仍在(0xc0234ea7e3af77e5ae686caff62ff88eaccd8c30),不产生证据;线上锚定合约是上面那个主网合约 |
| 包含证明只在库 API | merkleProof / verifyMerkleProof(RFC 6962 §2.1.3 审计路径)已实现并有交叉验证测试,但本仓库的 CLI 与 ledgeroot_verify 尚未输出或校验逐张证明;接入在 MandateKey 的证据包里 |
| 第三方独立验证仍要走证据包 | 独立验证器包(零依赖、单文件、断网可跑)尚未发布;目前第三方要验单张收据,需用导出的证据包(含公钥)或直接依赖本库 |
| 验证是全量的 | verify 每次遍历全部收据逐条重算 SHA-256 + Ed25519,无增量、无检查点;--check-chain 的 RPC 并发没有上限 |
| 合约测试不在 CI 里 | .github/workflows/ci.yml 只跑 typecheck、136 个 TypeScript 测试与 build;LedgerootAnchor.sol 的 forge test 目前仍只在本地跑 |
| 没有聚合层 | 全库没有一处 SQL 聚合(无 GROUP BY / SUM / COUNT),也没有对账导出。这是生态位里唯一能收费的那一层,目前完全不存在 |
| ERC-8004 只埋了字段 | Mandate.agentId 存在但未接注册表校验 |
锚定合约
contracts/src/LedgerootAnchor.sol —— 全项目唯一合约,只存 32 字节根 + 回指针 + epoch 计数器 + owner。
- 权限受控:
anchor()有onlyOwner。开放的anchor()会让"这个根在链上"只等于"有人往这里锚了东西"——攻击者可以发布伪造根,或顶掉诚实根让有效收据验成tampered。owner 是锚定钱包(设了LEDGEROOT_ANCHOR_KEY就取它,否则用LEDGEROOT_PRIVATE_KEY),不是部署者,因此两把钥匙可以分离。 - 所有权可转移:
transferOwnership让锚定钥匙可以在不重部署的前提下轮换。owner 原先固定在构造函数里,换锚定钱包就意味着重新部署、并让老合约上已锚的根全部落空。用一步而不是"先提名再接受"两步,是因为转错了现任 owner 还能再转回来,而两步握手的中间态会让合约无法锚定。 - epoch 由合约拥有:
lastEpoch每次锚定自增,客户端读合约而不是自己记数——否则一个全新的库会把它的第一次锚定标成 "epoch 1",不管合约已经走到多远。 - Merkle 用 RFC 6962 MTH:叶
SHA-256(0x00 ‖ d)、内部节点SHA-256(0x01 ‖ L ‖ R)、按最大 2 的幂切分(不复制奇数末节点)。域分隔是第二原像抗性的来源。测试用 RFC 9162 §2.1.2 的栈式算法作独立预言机交叉验证。 - 部署到 Monad 主网(chainId 143):
0x958f887f203a08f43fe45ba00a6a4199b9e01b61,owner 为锚定钱包。它接替了0xca08c795357ae8bcee8af592c827d419750fdf84(owner 是支付密钥);已锚在那份合约上的根留在那边。更早的测试网部署(0xc0234ea7e3af77e5ae686caff62ff88eaccd8c30)不产生证据。地址会变——以你自己的.env为准。
十一个 ledgeroot_* 工具
| 工具 | 作用 |
|---|---|
| ledgeroot_buy | 取一个 URL,付掉它回的 402。 所有策略在签名之前跑完;响应体哈希进第六段 |
| ledgeroot_pay | 受约束 x402 支付(幂等去重 + 任务关联),出六段收据;传卖家发来的 quote,收据即对它作出承诺;传 responseBody 让第六段覆盖交付 |
| ledgeroot_mandate_sign | 本地私钥现场签发授权令(id 可省略,自动生成) |
| ledgeroot_mandate_import | 导入 AP2 风格授权令(验签失败直接拒绝) |
| ledgeroot_mandate_list | 列出有效授权 |
| ledgeroot_mandate_revoke | 撤销授权(一键熔断) |
| ledgeroot_receipt_list | 列出收据(按 mandate / status / endpoint 过滤) |
| ledgeroot_receipt_get | 取单张收据 |
| ledgeroot_verify | 离线验证证据链 + 锚定;checkChain 额外核对链上结算 |
| ledgeroot_anchor | 提交 epoch Merkle 根上链 |
| ledgeroot_export | 导出证据包(收据 + 根 + 锚定记录 + 公钥 + 验证结论) |
环境变量
| 变量 | 说明 |
|---|---|
| LEDGEROOT_DB | SQLite 数据库路径(默认 ledgeroot.sqlite) |
| LEDGEROOT_PRIVATE_KEY | 动钱的私钥:支付签名。永不出本机 |
| LEDGEROOT_ANCHOR_KEY | 提交锚定的私钥。未设置时回落 LEDGEROOT_PRIVATE_KEY。设置它可让无人值守的锚定循环拿不到动钱的钥匙——它同时是合约的 owner,而合约可用 transferOwnership 移交所有权,所以轮换它不需要重部署 |
| LEDGEROOT_SIGNING_KEY | 收据签名密钥(32 字节 hex 种子)。与支付密钥刻意分离。未设置则收据不签名,验证报 incomplete |
| LEDGEROOT_FACILITATOR_URL | Monad x402 facilitator 地址(默认 https://x402-facilitator.molandak.org,公开、无需 API key) |
| LEDGEROOT_RPC_URL | Monad testnet RPC(默认 https://testnet-rpc.monad.xyz) |
| LEDGEROOT_MAINNET_RPC_URL | Monad 主网 RPC,验证落在 143 链上的收据时使用(默认 https://rpc.monad.xyz) |
| LEDGEROOT_CHAIN_ID | 锚定器目标链:10143 测试网(默认)或 143 主网 |
| LEDGEROOT_ANCHOR_ADDRESS | 锚定合约地址(未设置则无法锚定) |
| LEDGEROOT_DEPLOYER_PRIVATE_KEY | 仅 deploy/monad.ts 使用;合约 owner 由 LEDGEROOT_PRIVATE_KEY 推导 |
| LEDGEROOT_ANCHOR_BYTECODE | 部署用字节码;不设则读 forge build 产物 |
| LEDGEROOT_DRY_RUN | true 启用仿真:零钱包零 USDC 跑全流程(假 tx + 一次性私钥,禁止用于真实支付) |
仓库结构
src/
policy/ 策略引擎 + 五条默认策略 + Zod schema
receipt/ 六段收据构建 + RFC 8785 哈希链 + Ed25519 签名(JWKS / thumbprint kid)
anchor/ RFC 6962 Merkle(根 / 包含证明)+ 锚定器(viem)
verify/ 离线三态验证器 + 链上结算内容校验(ERC-3009 解码比对)
store/ SQLite append-only 存储(receipts / mandates / anchors / payment_intents)
x402/ facilitator 集成(EIP-3009 授权 + /verify + /settle)+ 买家(@x402/fetch,策略闸门卡在签名那一刻)
tools/ 十一个 ledgeroot_* MCP 工具
mandate.ts EIP-712 授权令(签发 / 验签 / 策略交集)
consistency.ts 授权-执行一致性分析(事后复核:已付收据是否越权)
decimal.ts USDC 六位小数 bigint 运算,无浮点
env.ts 环境加载 + dry-run 开关
cli.ts verify / export / anchor / jwks / serve
scripts/ demo(dry-run 全流程)/ pay-demo(真实支付)/ buy-demo(真实 x402 购买)/ deploy
contracts/ LedgerootAnchor(Solidity 0.8.24 + Foundry)
deploy/ 锚定合约部署(链由 LEDGEROOT_CHAIN_ID 选择)
docs/ 架构评估 / 路线图 / 竞品与标准调研 / 商业化方向
assets/ 字标(亮 / 暗两版)
test/ 15 个文件、136 个测试参与贡献
小而聚焦的改动最好落地,路线图是最好的入口:
- roadmap.md —— 排好序的计划,每项都带验收标准与涉及文件。
- 已知边界 —— 表里每一条都是真实且有边界的工作量。
- 提 PR 前先跑:
npm run typecheck && npm test && npm run build(CI 跑的就是这三条)。
刚接触代码?scripts/demo.ts 用单文件走完整闭环,test/pay.test.ts 端到端覆盖崩溃窗口那一组行为。
设计与调研文档
📌 这些文档以中文撰写,尚未有英文版。
| 文档 | 内容 | |---|---| | README.md | 文档索引与阅读顺序 | | architecture.md | 源码级架构评估:已做对的、规模层面的债、零外泄 vs 聚合的张力、链配置与协议接缝 | | roadmap.md | 行动规划:P0 正确性(已清)→ P1 差异化 → P2 可见性 → P3 公信力;含差距清单 N1–N15 与待定决策 Q1–Q17 | | commercialization.md | 生态位、四个取舍、商业模式分层、现在绝不做的事 | | landscape.md | 威胁分类法(载波 / 分发垄断者 / 直接竞品 / 监管时钟)、商品化半衰期、监控触发条件 | | competitors.md | 四个核心对手的深度拆解:Vaara、AWS AgentCore payments、TrustBench、Semantica(相邻) | | standards.md | 学术与标准全景:OAP、Vaara Receipt、IETF 草案、x402 与 MPP 并列支持的依据 | | tokenized-equities.md | 第二个垂直:Uniswap permissioned pools × 代币化股票,与两条 SEC 提案线 | | sec-comment-s7-2026-30.md | ⚠️ 给 SEC File S7-2026-30 的评论信草稿(标注 DRAFT,不可原样提交) |
许可
MIT © 2026 Ledgeroot
行业造好了锁,没人造钥匙圈;造好了刹车,没人造黑匣子。
⭐ Star · 📖 English README · 🗺️ 路线图 · 🛡️ 威胁全景
MIT · 无 SaaS · 无遥测 · 私钥永不出本机
