术语表 /闪电网络与 Layer 2
支付哈希
- 支付哈希是什么?
- 支付哈希是收款方生成的32字节秘密数据的 SHA-256摘要,它既是闪电网络支付的锁,也是各方称呼这笔支付所用的名称。
闪电网络路由上的每一跳都能看到同一个支付哈希,每个节点正是凭它识别这笔支付。BOLT 11要求每张发票恰好包含一个支付哈希,以52个 bech32 字符书写,承载256位。出示与之对应的秘密数据是领取这笔款项的唯一方式,事后保留该秘密数据即是您的收据。
运作方式
支付哈希的起点是它的反面:接收方随机选取32字节,称为支付原像,并只公布其 SHA-256。
该值以标签 p 写入发票,BOLT 11将其 data_length 固定为52,并要求它恰好出现一次。此后它在 update_add_htlc 中沿路由传递,消息类型为128,字段包括通道 ID、64位计数器、以毫聪计的金额、payment_hash 本身、CLTV 到期值和1366字节的洋葱数据包。它在该消息中发挥双重作用:它还作为关联数据输入洋葱构造,因此每一跳的 HMAC 都对它作出承诺。因此,把旧的洋葱数据包重放给另一个支付哈希,会在第一个检查的节点处失败。
结算则把哈希倒着走一遍。接收方在 update_fulfill_htlc 中返回原像,消息类型为130,是一个单独的32字节值,上游每个节点再沿同样的通道把它传回。节点若收到的原像经 SHA-256后与其持有的哈希不一致,并不会简单地忽略:BOLT 2规定,它必须发送警告并关闭连接,或者发送错误并使通道失败,因为这种情况不存在无辜的解释。
在链上,哈希会被缩减。HTLC 输出脚本根本不包含那个32字节的值,而是用 OP_HASH160 与 RIPEMD160(payment_hash) 进行比较,后者是一个20字节的承诺,花费方在见证数据中提供原像。两笔金额取整后相同、支付哈希也相同的已提供 HTLC,即使到期时间不同,也会产生逐字节相同的输出,因此 BOLT 3必须为它们规定排序规则。
有一项要求乍看奇怪,直到了解其背后的攻击才明白。节点必须接受携带同一支付哈希的多个 HTLC,BOLT 2给出了理由:如果拒绝重复项,攻击者就可以用已知哈希进行探测,从而得知该节点是否已在持有这笔支付。单独的64位 ID 用来区分这些重复项。
购买比特币时为何重要
本站评测的63家交易所中,有两家在手续费说明中记录了闪电网络出款:Strike,其提币说明称支持通过闪电网络和链上向钱包提币;Coinbase,其手续费表对闪电网络发送按所发送金额的0.2%计价。
这类出款一旦停滞,就没有可供查询的交易 ID,因为没有任何内容上链。支付哈希是您的钱包日志和交易所后台都持有的唯一字符串,因此请在关闭支付详情页之前把它复制出来。客服若向您索要闪电网络提币的“交易 ID”,要的就是这个值。
您收到的错误信息不会告诉您太多,这是有意为之。BOLT 4把五种不同的问题归并为同一个失败代码 incorrect_or_unknown_payment_details,编号为 PERM|15:最终节点不认识该哈希、支付密钥与之不匹配、该哈希对应的金额过低、到期时间离当前区块高度太近,或者缺少必需的支付元数据。规范解释了这样归并的原因:旧的拆分代码让转发节点可以把同一哈希以低得多的金额继续转发并读取回复,从而猜出支付的去向。您的钱包并非在向您隐瞒原因,而是根本没有被告知,因此重新生成发票后再次支付是切实可行的应对办法。
同一个值从您的节点到收款方的节点始终保持一致,包括多路径支付的每一部分,BOLT 4要求这些部分共用同一个支付哈希。任何人两次看到它,就知道看到的是同一笔支付。本站对 Phoenix 的评测引用了 ACINQ 自己的常见问题,其中承认它知道通过该钱包发出的支付的最终目的地和金额,这正是同一种暴露风险的直白说法,由厂商自己陈述,而非本站推断。
重复使用发票则更糟,原因与此相关。BOLT 4允许收到已支付哈希的最终节点自行决定,或视为未知,或收下款项,因此重新发布的二维码会有什么结果,取决于接收方恰好运行的是哪种实现。
解码 BOLT 11捐赠测试向量中的支付哈希
BOLT 11规范附带了一张完整的捐赠发票示例,其中的支付哈希是固定的测试值,任何钱包都不应生成这个值。
该示例的标题是"Please make a donation of any amount using payment_hash 0001020304050607080900010203040506070809000102030405060708090102",字符串以 lnbc1pvjluez 开头。在 lnbc 前缀和 bech32 分隔符之后,pvjluez 是时间戳,即自1970年起算的1496314658秒。接着是支付密钥字段,其后是 p 标签,再后是 p5,即长度:在 bech32 中 p 是1,5 是20,因此该字段长1 * 32 + 20 = 52个字符。这些字符 qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypq 解码后即为该标题中引用的哈希。
这里没有任何私密内容。规范公布了其示例所用的签名私钥 e126f68f7eafcc8b74f54d269fe206be715000f94dac067d1c04a8ca3b2db734,并称该部分的每张发票都带有支付密钥 1111111111111111111111111111111111111111111111111111111111111111,除非另有说明,因此这些字符串是解析器的测试数据,而不是付款请求。如果钱包或诊断工具在测试套件之外向您显示该哈希,说明有程序在回显规范内容,而不是在报告您的支付。
支付哈希 vs 交易 ID
支付哈希标识一笔闪电网络支付;交易 ID 标识存在于比特币区块链上的一笔交易。两者都是32字节,都显示为64个十六进制字符,因此常被互相填进对方的支持表单。交易 ID 是事后根据交易自身的字节计算出来的,可以粘贴到任何区块浏览器中。支付哈希则由接收方在支付产生之前选定,支付正常结算时从不出现在区块中,在区块浏览器里也查不到任何结果。搜索结果为空,通常意味着您手里的值是对的,用的工具却不对。
支付哈希 vs 支付密钥
支付哈希和支付密钥是同一张发票中两个不同的256位值,分别由标签 p 和 s 承载,各以52个 bech32 字符编码。支付哈希必然是公开的:每一跳都必须看到它才能构建自己的 HTLC。支付密钥只在洋葱数据包内交给最后一个节点,BOLT 11用一句话说明了它的作用,即它"prevents forwarding nodes from probing the payment recipient"(防止转发节点探测支付接收方)。读取方若找不到 s 字段,必须直接使支付失败。哈希是锁;支付密钥则证明付款人是从发票开具者那里拿到的发票。