TronGreen

交易與支付基礎設施BOLT11 規格修正

BOLT11 改為拒收雙付款雜湊發票:LNP2PBot 重複出款後的規格補洞

閃電網路規格 BOLTs PR #1357 於 2026-10-19(UTC)合併,要求讀取 BOLT11 發票的一方,只有在恰好一個付款雜湊(p)與恰好一個付款秘密(s)欄位時才可付款。

示意圖:一張 BOLT11 發票含兩個付款雜湊,應用程式解析器取最後一個、閃電節點取第一個,造成帳務不一致;新規格要求 p 與 s 各恰好一個,否則付款失敗。
BOLT11 重複付款雜湊問題與新規格示意(TronGreen 原創圖表,依 lightning/bolts PR #1357、LND PR #11190、ZEUS PR #4631 整理)

這項修改源自 LNP2PBot 遭利用的漏洞:函式庫與節點對同一張發票讀出不同付款雜湊,導致服務誤判出款未完成而重複付款。LND 已在 v0.21.4-beta 先行拒收重複 p 欄位;ZEUS 錢包的修正 10/23 合併,同樣拒收重複 p,但與 LND 一樣尚未拒收重複 s,且還沒進入正式版。

重點摘要

BOLT11 規格從「付款方應使用第一個 p 欄位」改為「p、s 各須恰好一個,否則不得付款」,並新增機器可讀測試向量;LND v0.21.4-beta 只拒收重複 p,尚未涵蓋 s;有自行解析發票的出款服務,應確認解析器與節點讀到的是同一個付款雜湊。

文章目錄

規格改了什麼:p 與 s 都必須恰好一個

閃電網路規格儲存庫的 BOLTs PR #1357 由 Roasbeef 於 2026-09-10(UTC)開出,2026-10-19 17:22(UTC,台北時間 10/20 01:22)合併,Bitcoin Optech 在 10/23 出刊的第 428 期週報中加以介紹。修改針對 BOLT11 發票,也就是一般閃電錢包與交易所出款時最常見的 lnbc 開頭付款請求。

合併後的文字要求發票讀取方「除非恰好存在一個 p 欄位與恰好一個 s 欄位,否則必須讓付款失敗」。p 欄位是付款雜湊,s 欄位是付款秘密。原本規格對付款方的寫法是「應使用第一個 p 欄位」,現改為「必須使用該 p 欄位」,等於把容錯解讀改成硬性拒收。

PR 同時新增機器可讀的測試向量檔 bolt11/invoice-test.json,無效案例包括:缺少 p、兩個不同的 p、同一個 p 重複兩次、兩個不同的 s、缺少 s,以及長度錯誤的 n 欄位。原本「必須忽略的欄位」測試案例也已改寫,讓各家實作能用同一份資料對照自己的解析器。

起因:同一張發票被讀出兩個付款雜湊

PR 說明指出,近期一個熱門的 Telegram 點對點交易機器人遭到利用:有些函式庫取第一個付款雜湊、有些取最後一個;若同一套系統裡兩種行為並存,系統可能誤以為某筆提領從未付出,因而反覆出款。Optech 第 428 期週報明確指出受害者是 LNP2PBot,並稱攻擊造成重複出款。

LNP2PBot 建立者 2026-09-10(UTC)在 Stacker News 發布的鑑識結論說,問題不在機器人本身的程式,而在被許多 JavaScript 閃電專案使用的 invoices 解析套件:遇到兩個付款雜湊時,套件保留最後一個,節點則使用第一個。機器人追蹤的是一筆付款,節點實際結清的是另一筆,攻擊者每跑一輪就多拿一次。

同一篇貼文表示,該套件 8/7 已修正並同步推到 lightning 與 ln-service,但版本說明只寫「需要 Node.js 22 以上」這項破壞性變更,沒有安全公告,也沒有 CVE 編號。npm 登錄紀錄顯示 invoices 6.0.0 於 2026-08-07(UTC)發布、引擎需求為 Node.js 22 以上,ZEUS PR #4631 的說明也寫明該套件在 6.0.0 悄悄修正。依西班牙語媒體 CriptoTendencias 8/10 的報導,LNP2PBot 團隊宣布無限期停止營運,並表示攻擊造成的損失由專案自行吸收、用戶不會因此蒙受損失。上述損失金額並未見於本文引用的來源。

實作進度:LND 先行,但只管 p 欄位

LND 的 PR #11190 在 2026-09-23 合併,讓 zpay32 解碼器遇到第二個 p 欄位就回傳錯誤,無論兩個雜湊相同、不同,或第一個格式錯誤而第二個有效。Optech 第 425 期週報(10/2)已介紹這項改動。LND 0.21.4 版本說明也列出此項,並註明這比當時的 BOLT11 規格更嚴格,對仍會產生這種發票的錢包是互通性考量;v0.21.4-beta 於 10/1(UTC)發布。

需要留意的是,LND PR 說明自己承認範圍只限付款雜湊;s、d、h、x 等其他只應出現一次的欄位仍是「先出現者為準」,並把 s 列為下一步候選。合併後的規格則已同時要求 s 恰好一個,所以 LND 目前的發布版本與新規格在 s 欄位上仍有落差。

行動錢包 ZEUS 的 PR #4631 於 10/23(UTC)合併,作者說明其內建解碼器原本是「後出現者覆蓋」,與 invoices 套件同屬一類問題。依 PR 說明與合併版本程式碼,修正後只要出現第二個 p 欄位就丟出「Invoice contains multiple payment hashes」錯誤,不論長度或數值;找不到格式正確的 p 時也會報錯。s、d、h、n、x 等其他單次欄位則只取第一次出現且長度正確的值,長度錯誤的固定長度欄位被略過而不是拒收。

這套做法與 LND 目前行為一致,但和新規格仍有差距:重複的 s 不會被拒收;PR 作者也承認,現行 BOLT11 要求長度錯誤的 p、h、s、n 欄位應使付款失敗,ZEUS 為了不拒收節點會照付的發票,選擇比照 LND 略過。ZEUS 最新正式版 v13.2.3 於 10/12 發布,早於這次合併,因此修正尚未進入正式版。Core Lightning、LDK 與 Eclair 是否已有同等改動,本文未逐一核實。

AI 觀點分析與推論

AI 觀點:真正的漏洞在「兩個元件各讀各的」

這次事件的核心風險是:應用程式把付款雜湊當作帳務主鍵,卻沒有確認它與節點實際處理的是同一筆。規格把重複欄位改為拒收是正確方向,因為沒有正當用途需要兩個付款雜湊,拒收也不受各元件怎麼取捨影響。

但規格修正不會自動進到每一套出款系統。對交易所、P2P 機器人、打賞服務與商家收款系統而言,較實際的做法是三件事:一,出款前同時取得自家解析結果與節點解碼結果,付款雜湊不一致就拒付;二,出款完成後以節點回報的雜湊與原像對帳,而不是只看自家資料庫;三,把 invoices 這類解析套件列入安全更新監控,而不是只在大版本時才看版本說明。

AI 觀點分析與推論

AI 觀點:安全修補不該藏在例行升級裡

LNP2PBot 建立者的批評值得開源維護者正視:修正本身並不慢,問題是它和 Node.js 版本升級綁在同一個破壞性版本裡,下游很合理地把它排進「之後再做」的清單。對支付基礎設施而言,涉及付款識別、金額或收款方判定的修正,應該有獨立的安全公告或至少在版本說明中明講,否則再勤讀版本說明的維運者也無從判斷急迫性。

接下來值得追蹤的是:LND 與 ZEUS 是否把 s 欄位納入同樣的拒收規則並進入正式版,以及其他主要實作與常用解析套件是否通過新的 invoice-test.json 測試向量。

原始來源與延伸閱讀

  1. lightning/bolts PR #1357:bolt11: reject duplicate payment hashes in invoices ↗官方規格儲存庫 · 原始發布 2026-09-10 · 查閱 2026-10-24
  2. lightning/bolts 合併提交 b383d14(PR #1357 合併) ↗官方規格儲存庫 · 原始發布 2026-10-19 · 查閱 2026-10-24
  3. Bitcoin Optech Newsletter #428 ↗技術週報 · 原始發布 2026-10-23 · 查閱 2026-10-24
  4. Bitcoin Optech Newsletter #425 ↗技術週報 · 原始發布 2026-10-02 · 查閱 2026-10-24
  5. LND PR #11190:zpay32: reject duplicate payment hash fields ↗官方程式碼儲存庫 · 原始發布 2026-09-23 · 查閱 2026-10-24
  6. LND 0.21.4 版本說明(release-notes-0.21.4.md) ↗官方文件 · 原始發布 2026-10-01 · 查閱 2026-10-24
  7. ZEUS PR #4631:utils: match lnd on duplicate BOLT11 singleton tags ↗官方程式碼儲存庫 · 原始發布 2026-10-23 · 查閱 2026-10-24
  8. Stacker News:Conclusions of the @lnp2pBot forensic investigation, by its creator ↗當事方聲明 · 原始發布 2026-09-10 · 查閱 2026-10-24
  9. CriptoTendencias:LNp2pBot anuncia su cierre indefinido tras sufrir ataques ↗媒體報導 · 原始發布 2026-08-10 · 查閱 2026-10-24
  10. npm registry:invoices 套件中繼資料(6.0.0) ↗官方套件登錄 · 原始發布 2026-08-07 · 查閱 2026-10-29

更正與更新

本文發布後沒有更新。之後若有修改,會建立新版本並在這裡標示更新時間。

內容有誤?請見更正方式,或寄信至 [email protected](請附文章網址、段落與參考資料)。

延伸閱讀

更多 BTC 新聞