BIP-65 OP_CHECKLOCKTIMEVERIFY

Published: Nov 14, 2019 by Cypherpunks Core

原文:BIP-65 OP_CHECKLOCKTIMEVERIFY
該BIP為比特幣 script 系統描述了一個新的 OPCode (OP_CHECKLOCKTIMEVERIFY),該 OPCode 允許交易輸出在未來的某個點之前變得不可花費。

概要

  • *CHECKLOCKTIMEVERIFY 重新定義了現有的 NOP2 OPCode (其實就是 OP_CHECKLOCKTIMEVERIFY 指令替換了 OP_NOP2 指令)。執行時,如果以下任何一個條件成立,則 OPCode 直譯器將以錯誤終止:**

  • 堆棧是空的;
  • 堆棧中的頂層項目小於0;
  • 頂層堆棧項的鎖定時間類型(高度vs.時間戳)與 nLockTime 欄位不同;
  • 頂部堆棧項大於交易的 nLockTime 欄位;
  • txin(交易輸入)的 nSequence 欄位是 0xffffffff ;

否則, OPCode 執行將繼續,如同NOP執行一樣。

交易中的 nLockTime 欄位可防止交易被挖出,直到達到某個區塊高度或區塊時間為止。通過將傳給 CHECKLOCKTIMEVERIFY 的參數與 nLockTime 欄位進行比較,我們間接驗證是否已達到所需的區塊高度或區塊時間; 直到該區塊高度或區塊時間已經達到,交易輸出仍然不可花費。

動機

交易中的 nLockTime 欄位可用於證明 將來可以花費這筆交易輸出,方法是構造一個有效的交易開銷,並對nLockTime欄位進行設定。

然而, nLockTime 欄位不能證明在未來的某個時間內不可能花費交易輸出,因為無法知道是否建立了支出該輸出的其他交易的有效簽名。

第三方託管

  • *如果 Alice 和 Bob 聯合經營一家企業,他們可能希望確保所有資金都儲存在需要雙方同時批准的 2-of-2 的多重(多重簽名的交易)交易輸出中。但是,他們發現在特殊情況下,例如任何一個人受到“嚴重的車禍”,他們都需要備用的方法,繼續動用該筆資金。因此,他們任命他們的律師 Lenny 擔任第三方。**

在任何時候,Lenny 隨時可以同 Alice 或 Bob 一起串謀非法竊取資金。同樣,Lenny 可能更願意不竊取資金,以阻止不良行為者企圖強行從他那裡獲取 secret keys 。

但是,使用 CHECKLOCKTIMEVERIFY 可以將資金儲存在以下格式的 scriptPubKeys 中:

IF
    <now + 3 months> CHECKLOCKTIMEVERIFY DROP
    <Lenny's pubkey> CHECKSIGVERIFY
    1
ELSE
    2
ENDIF
<Alice's pubkey> <Bob's pubkey> 2 CHECKMULTISIG

在任何時候,資金都可以用下面的 OPCode 來支付:

0 <Alice's signature> <Bob's signature> 0

Lenny 經過 3 個月後,Alice 或 Bob 中的一個可以用以下 OPCode 支付資金:

0 <Alice/Bob's signature> <Lenny's signature> 1

非交互式定期退款 | Non-interactive time-locked refunds

存在許多協議,其中建立交易輸出,這需要雙方的合作來花費輸出。為確保一方的失敗不會導致資金損失,退款交易使用 nLockTime 提前設定。這些退款交易需要互動式建立,此外,目前易受交易延展性影響。 ` CHECKLOCKTIMEVERIFY` 可用於這些協議,用非互動式設定取代互動式設定,另外,使交易延展性不成問題。

雙因素錢包 | Two-factor wallets

諸如 GreenAddress 之類的服務將比特幣儲存為 2-of-2 的多重簽名 OPCode ScriptPubKey,使得一個金鑰對由使用者控制,另一個金鑰對由服務控制。為了花費資金,使用者使用本地安裝的生成所需簽名之一的錢包軟體,然後使用雙因素身份驗證方法來授權該服務建立第二個 SIGHASH_NONE 簽名,該簽名在將來的某個時間被鎖定,並向用戶傳送該儲存簽名。如果使用者需要花費資金並且服務不可用,他們會等到 nLockTime 過期。

問題是,在許多情況下,使用者將不會擁有一些或全部交易輸出的有效簽名。使用 CHECKLOCKTIMEVERIFY 而不是按需建立退款簽名,而是使用以下形式的 scriptPubKeys :

IF
    <service pubkey> CHECKSIGVERIFY
ELSE
    <expiry time> CHECKLOCKTIMEVERIFY DROP
ENDIF
<user pubkey> CHECKSIG

現在,用戶總是可以通過等待到期時間來花費他們的資金而無需服務的合作。

支付通道 | Payment Channels

傑里米·斯皮爾曼( Jeremy Spilman )style 的支付通道首先設定一個存款,由 2-of-2 的多重簽名, tx1 控制的存款,然後調整第二個交易 tx2 ,將 tx1 的輸出用於支付者和收款者。在釋出 tx1 之前,建立一個退款交易 tx3 ,確保收款人消失時付款人可以取回其押金。當前創建退款交易的過程容易受到交易延展性攻擊的影響,此外,還要求付款人儲存退款。使用與雙因素錢包示例中相同的 scriptPubKey 形式可以解決這兩個問題。

發布數據的無信任付款 | Trustless Payments for Publishing Data

The PayPub protocol makes it possible to pay for information in a trustless way by first proving that an encrypted file contains the desired data, and secondly crafting scriptPubKeys used for payment such that spending them reveals the encryption keys to the data. However the existing implementation has a significant flaw: the publisher can delay the release of the keys indefinitely.

This problem can be solved interactively with the refund transaction technique; with CHECKLOCKTIMEVERIFY the problem can be non-interactively solved using scriptPubKeys of the following form:


通過首先證明加密文件包含所需的數據,然後製作用於支付的 scriptPubKeys 以便使它們花費來顯示數據的加密密鑰,PayPub 協議可以以不信任的方式支付信息。但是,現有的實現存在一個重大缺陷:發布者可以無限期地延遲密鑰的發布。

這個問題可以用退款交易技術互動地解決; 使用 CHECKLOCKTIMEVERIFY ,可以使用以下形式的scriptPubKeys以非互動方式解決問題:

IF
    HASH160 <Hash160(encryption key)> EQUALVERIFY
    <publisher pubkey> CHECKSIG
ELSE
    <expiry time> CHECKLOCKTIMEVERIFY DROP
    <buyer pubkey> CHECKSIG
ENDIF
  • *資料的買家現在正在提供一個有效期限的安全報價。如果發行商在到期時間到期之前未能接受報價,買家可以通過消費輸出來取消報價。**

證明犧牲礦工的手續費 | Proving sacrifice to miners’ fees

Proving the sacrifice of some limited resource is a common technique in a variety of cryptographic protocols. Proving sacrifices of coins to mining fees has been proposed as a universal public good to which the sacrifice could be directed, rather than simply destroying the coins. However doing so is non-trivial, and even the best existing technqiue - announce-commit sacrifices - could encourage mining centralization. CHECKLOCKTIMEVERIFY can be used to create outputs that are provably spendable by anyone (thus to mining fees assuming miners behave optimally and rationally) but only at a time sufficiently far into the future that large miners can’t profitably sell the sacrifices at a discount.


證明犧牲一些有限的資源是各種密碼協議中的常用技術。已經提出了證明將硬幣犧牲為採礦費的做法,作為犧牲品可以針對的一種普遍的公共物品,而不是簡單地銷毀硬幣。但是,這樣做並非易事,即使是現有的最佳技術-宣布承諾犧牲-也會鼓勵採礦業的集中化。 CHECKLOCKTIMEVERIFY 可用於創建任何人都可證明可使用的輸出(因此,假設礦工的行為合理且合理,則要收取採礦費),但前提是在足夠遠的將來,大型礦工無法以折扣價出售利潤。

證明犧牲一些有限的資源是各種密碼協議中的常見技術。已經提出將幣的犧牲證明為挖礦手續費,作為犧牲可以指向的普遍公共物品,而不是簡單地摧毀幣。然而,這樣做並非微不足道,即使是最好的現有技術 - 宣佈 - 承諾 - 也會鼓勵礦業集中。 CHECKLOCKTIMEVERIFY 可用於建立任何人都可以花費的產出(因此,假設礦工的行為是理想的和理性的,那麼開採費),但只有在未來足夠遠的時間,大型礦工才能以折扣銷售犧牲品。

凍結資金 | Freezing Funds

除了使用冷儲存,硬體錢包和 P2SH multisig 輸出來控制資金之外,現在資金可以直接在區塊鏈中凍結在 UTXO 中。使用下面的 scriptPubKey ,在提供的失效時間之前,沒有人能夠使用安全輸出。這種可靠地凍結資金的能力在需要減少脅迫或沒收風險的情況下可能會有用。

<expiry time> CHECKLOCKTIMEVERIFY DROP DUP HASH160 <pubKeyHash> EQUALVERIFY CHECKSIG

完全替換nLockTime欄位 | Replacing the nLockTime field entirely

另外,請注意如果 SignatureHash() 演算法可以選擇覆蓋 OPCode 的一部分,那麼簽名可能會要求 OPCode Sig包含CHECKLOCKTIMEVERIFY OPCode ,並且還需要執行它們。( CODESEPARATOR OPCode 非常接近於在比特幣的 v0.1 中實現這一點)。這種每簽名功能可以完全取代每個交易的 nLockTime 欄位,因為有效簽名現在可以證明交易輸出可以花費。

詳細規格 | Detailed Specification

參考下面轉載的參考實現,瞭解這些語義的精確語義和詳細基本原理。

case OP_NOP2:
case OP_NOP2:
{
    // CHECKLOCKTIMEVERIFY
    //
    // (nLockTime -- nLockTime )

    if (!(flags & SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY))
        break; // not enabled; treat as a NOP

    if (stack.size() < 1)
        return false;

    // Note that elsewhere numeric opcodes are limited to
    // operands in the range -2**31+1 to 2**31-1, however it is
    // legal for opcodes to produce results exceeding that
    // range. This limitation is implemented by CScriptNum's
    // default 4-byte limit.
    //
    // If we kept to that limit we'd have a year 2038 problem,
    // even though the nLockTime field in transactions
    // themselves is uint32 which only becomes meaningless
    // after the year 2106.
    //
    // Thus as a special case we tell CScriptNum to accept up
    // to 5-byte bignums, which are good until 2**32-1, the
    // same limit as the nLockTime field itself.
    const CScriptNum nLockTime(stacktop(-1), 5);

    // In the rare event that the argument may be < 0 due to
    // some arithmetic being done first, you can always use
    // 0 MAX CHECKLOCKTIMEVERIFY.
    if (nLockTime < 0)
        return false;

    // There are two types of nLockTime: lock-by-blockheight
    // and lock-by-blocktime, distinguished by whether
    // nLockTime < LOCKTIME_THRESHOLD.
    //
    // We want to compare apples to apples, so fail the script
    // unless the type of nLockTime being tested is the same as
    // the nLockTime in the transaction.
    if (!(
            (txTo.nLockTime <  LOCKTIME_THRESHOLD && nLockTime <  LOCKTIME_THRESHOLD) ||
            (txTo.nLockTime >= LOCKTIME_THRESHOLD && nLockTime >= LOCKTIME_THRESHOLD)
            ))
        return false;

    // Now that we know we're comparing apples-to-apples, the
    // comparison is a simple numeric one.
    if (nLockTime > (int64_t)txTo.nLockTime)
        return false;

    // Finally the nLockTime feature can be disabled and thus
    // CHECKLOCKTIMEVERIFY bypassed if every txin has been
    // finalized by setting nSequence to maxint. The
    // transaction would be allowed into the blockchain, making
    // the opcode ineffective.
    //
    // Testing if this vin is not final is sufficient to
    // prevent this condition. Alternatively we could test all
    // inputs, but testing just this input minimizes the data
    // required to prove correct CHECKLOCKTIMEVERIFY execution.
    if (txTo.vin[nIn].IsFinal())
        return false;

    break;

}

https://github.com/petertodd/bitcoin/commit/ab0f54f38e08ee1e50ff72f801680ee84d0f1bf4

部署 | Deployment

我們重用BIP66中使用的雙閾值 IsSuperMajority() 切換機制,其閾值相同,但 nVersion = 4 。新規則對於 nVersion = 4 的每個區塊(高度為H)有效,並且至少有750之前的區塊(高度為H-1000..H-1)的 nVersion >= 4 。此外,當區塊之前的1000個區塊中的950個具有 nVersion >= 4 時, nVersion < 4 區塊將變為無效,並且全部進一步的阻止執行新的規則。

應該注意的是,BIP9涉及永久性地將高位設定為1,這導致 nVersion>= 所有先前的 IsSuperMajority() 軟分叉,因此 nVersion 中的位不會永久丟失。

SPV客戶 | SPV Clients

儘管SPV客戶端(當前)通常無法驗證區塊,而是信任礦工對其進行驗證,但他們能夠驗證區塊頭,因此可以驗證部署規則的子集。如果達到95%閾值時,前1000個區塊中的950個中有950個具有 nVersion >= 4 ,則SPV客戶端應拒絕 nVersion 4 區塊,以防止來自剩餘未升級礦工的5%的錯誤確認。

Credits

Thanks goes to Gregory Maxwell for suggesting that the argument be compared against the per-transaction nLockTime, rather than the current block height and time.

參考

PayPub

Jeremy Spilman支付通道

實現

Python / python-bitcoinlib

JavaScript / Node.js / bitcore

This document is placed in the public domain.

引用和參考

bip

Latest Posts

Cypherpunks Taiwan 重啟:我們為何再次聚集?
Cypherpunks Taiwan 重啟:我們為何再次聚集?

從 2019 到現在,世界與網路都變了很多,但我們對隱私的渴望沒有改變。在數位身份、鏈上足跡與 AI 大模型全面滲透的時代,Cypherpunks 的核心信念——Privacy is necessary for an open society in the electronic age,從未如此重要。這些年來,我們見證了比特幣的主流化、Web3 的爆炸成長,也見證了過度中心化平台對個人自由與資訊掌控權的反撲。是時候重新聚集了。

MuSig:一個新的多重簽名標準
MuSig:一個新的多重簽名標準

2019年2月15日,Andrew Poelstra 轉載blockstream。比特幣及Blockstream的Liquid等相關區塊鏈使用ECDSA簽名演算法來驗證儲存在系統裡的幣的所有權歸屬。業界於2008年決定使用這個演算法是基於當時廣泛使用且未申請專利的數位簽名系統。但ECDSA存在一些嚴重的技術侷限,尤其是多重簽名閾值簽名這兩種需要多個獨立方而非單一方的簽名非常難以通過ECDSA來實現。ECDSA簽名擁有十分複雜的代數結構,導致它們非常不靈活、難以操作,迫使比特幣開發者不得不用比特幣指令碼來開發跨鏈原子交換閃電網路這類應用。如果使用更加現代的簽名方案的話,可以讓這些應用更加小巧且隱私性更好。

Cosmos 區塊鏈的工作原理,Part-1:比較Cosmos 與比特幣、以太坊
Cosmos 區塊鏈的工作原理,Part-1:比較Cosmos 與比特幣、以太坊

編者注:本文對 Cosmos 網路中區塊鏈和比特幣、以太坊進行了鉅細靡遺的比較。作者先從區塊鏈系統的棧層出發,分析了比特幣、以太坊在不同棧層上的技術要點,最後迴歸到 Cosmos 網路中的區塊鏈,概念解釋尤為清晰,是不可多得的解釋文。