跳转至

协议

LedgerFlow 协议定义了一种授权令格式和授权证明模型,通过 x402 扩展为代理级支付授权提供支持。协议有意保持精简:一个授权令格式、一个证明格式、一个 x402 扩展命名空间。

设计哲学

LedgerFlow 借鉴了 Zanzibar 和 SpiceDB 的设计经验,但没有采用它们的完整架构:

  • 小的公开 API — 商户只问一个问题:"这个代理是否有权使用这个报价?"
  • 类型化约束 — 无需通用表达式引擎即可进行上下文感知检查
  • 时间绑定权限 — 过期是一等公民
  • 未来扩展点 — 一致性令牌(Zookies/ZedTokens)为 v2 预留

LedgerFlow 明确避免:

  • 通用关系图存储
  • 递归用户集遍历
  • Schema 编译
  • 通用表达式求值
  • 热路径上的多跳对象图遍历

授权令

授权令是一个自包含的、密码学签名的授权令牌。

结构

字段 描述
version 协议版本,从第一天起就明确版本化
warrant_id 授权令的唯一标识符
issuer 发行者(签名身份)
subject_signer 代理的签名身份(验证密钥)
payment_subjects 代理可以使用的结算身份
audience 授权令适用的商户范围
not_before_ms 有效期开始(Unix 毫秒)
expires_at_ms 有效期结束(Unix 毫秒)
delegation 是否以及多深可以子委托
constraints 类型化约束列表
metadata 发行者定义的元数据
signature 密码学签名(覆盖规范字节)

身份模型

LedgerFlow 分离两层身份:

签名身份 — 用于密码学验证:

pub struct SignerRef {
    pub alg: SigningAlgorithm,   // Ed25519 或 Secp256k1
    pub public_key: Vec<u8>,
    pub key_id: Option<String>,
}

支付主体 — 用于结算,对商户不透明:

pub struct PaymentSubjectRef {
    pub kind: PaymentSubjectKind, // Caip10, FacilitatorAccount, ExchangeAccount, Opaque
    pub value: String,
}

示例:caip10:eip155:8453:0xabc...binance:uid:12345678okx:subacct:agent-alpha

这种分离确保商户保持轨道无关。

受众范围

pub enum AudienceScope {
    MerchantIds(Vec<String>),   // 按稳定商户标识符
    MerchantHosts(Vec<String>), // 按主机名后缀
    Any,                         // 无限制(罕见)
}

优先使用商户 ID(当有稳定标识符时)。基于主机的范围是回退方案。

委托策略

pub struct DelegationPolicy {
    pub can_delegate: bool,
    pub max_depth: u8,
}

深度足以满足 v1。不需要图式递归委托。

授权证明

授权证明表明代理持有授权令,并将其用于特定交易。

证明绑定

证明必须绑定到:

  • LedgerFlow 挑战 ID
  • 授权令摘要
  • 精确选中的 x402 accepted 对象
  • 当前 HTTP 请求
  • 签名身份
  • 新鲜性元组(时间戳 + nonce)

规范请求哈希

request_hash = SHA256(
  UPPER(method) || "\n" ||
  LOWER(authority) || "\n" ||
  path_and_query_exact || "\n" ||
  SHA256(body_bytes)
)

有意保持简单。除非是 x402 负载或 LedgerFlow 扩展的一部分,否则不包含传输头部。

Accepted 哈希

accepted_hash 是选中的 x402 accepted 对象的规范 JSON 序列化的 SHA-256 摘要。

这是保持 LedgerFlow 与 x402 互补而非竞争的关键环节。商户报价仍然是 x402。LedgerFlow 只是授权该报价。

证明原像

proof_preimage = CBOR({
  domain: "ledgerflow-pop/v1",
  challenge_id: ...,
  warrant_digest: ...,
  accepted_hash: ...,
  request_hash: ...,
  created_at_ms: ...,
  nonce: ...,
  signer_key: ...
})

证明签名是对 SHA256(proof_preimage) 的 ED25519 签名。

重放保护

  • created_at_ms 必须在 60 秒验证窗口内
  • 重放键:challenge_id + nonce,使用原子 TTL 插入
  • 存储语义:SET key value NX PX ttl_ms(Redis)
  • 永远不要使用非原子的检查后设置流程

幂等重试

  • 相同的证明 + 相同的支付标识符 → 返回缓存的结果
  • 相同的 nonce 配合不同的请求哈希或 accepted 哈希 → 拒绝为重放

授权令传输

传输模式

  1. 内联 — 首次使用时发送授权令字节
  2. 摘要引用 — 商户缓存授权令后使用

规则:

  • 存在 inline_b64 → 商户验证并缓存
  • 仅存在 digest → 商户查找缓存的授权令
  • 未知摘要 → 商户拒绝,要求客户端重新发送内联版本

缓存键

warrant_digest 缓存,绝不要仅按签名者缓存。

warrant_digest = "sha256:" + hex(SHA256(canonical_signed_warrant_bytes))

精确、可移植、易于实现。

LedgerFlow 验证内容

商户端验证器检查:

  • 授权令签名有效性
  • 证明签名有效性
  • 授权令有效期(not_before / expires_at)
  • 受众范围符合受众约束
  • 资源范围符合资源约束
  • 工具范围符合工具约束
  • 资产和金额约束
  • 委托约束
  • 证明绑定到精确选中的 x402 accepted 对象
  • 证明绑定到当前 HTTP 请求
  • 证明未被重放

协议限制

限制
最大委托深度 64
最大授权令 TTL 90 天
最大授权令大小 8 KB
每个授权令最大约束数 32
证明新鲜性窗口 60 秒
推荐 nonce 长度 16 字节

参见