比特幣腳本的功能雖然有限,但它的重要性不言而喻,而其在今日迎來了重要升級,Bitcoin core協(xié)議維護(hù)者Pieter Wuille正式公布了Miniscript
比特幣腳本的功能雖然有限,但它的重要性不言而喻,而其在今日迎來了重要升級,Bitcoin core協(xié)議維護(hù)者Pieter Wuille正式公布了Miniscript技術(shù)項目。
Pieter Wuille介紹道:
“簡而言之,它是一種以結(jié)構(gòu)化、可組合的方式編寫(某些)比特幣腳本的方法,其允許各種靜態(tài)分析、通用簽名和策略編寫。
想象一下,一家公司想用2-of-3多重簽名策略來保護(hù)他們的冷存儲資金。問題是,其中一位高管有一個自己的2FA雙因子驗證/多重簽名/timelock設(shè)置。為什么整個設(shè)置不能成為多重簽名“參與者”之一?
當(dāng)前很多工作都集中在對區(qū)塊鏈本身功能的擴(kuò)展上,以支持更復(fù)雜的應(yīng)用,但我覺得我們忘記了,以可訪問、可組合、可分析的方式使用這些功能,在今天基本上是不可能的。
我希望Miniscript和PSBT這樣的東西,可以減少軟件之間的一些障礙。理想情況下,執(zhí)行人員的2FA設(shè)置可以完美地與冷存儲設(shè)置交互,計算必要的組合腳本,并且仍然能夠簽名。
該項目包括一個策略編譯器,你可以知道在什么條件下輸出應(yīng)該是可使用的,及其相對概率是什么,它將為其找到最經(jīng)濟(jì)的Miniscript兼容腳本(僅限于一些轉(zhuǎn)換)。
為了這個項目,我們已討論了很長一段時間(包括今年早些時候在斯坦福區(qū)塊鏈活動上)。直至我們對比特幣共識及標(biāo)準(zhǔn)化規(guī)則進(jìn)行了大量測試,我才對發(fā)布內(nèi)容感到滿意,而當(dāng)下便是公布之時。
而從開始至今,我們重寫整個設(shè)計近3次,Andrew Poelstra和sanket1729在持續(xù)討論額外的可能性、問題及分析技術(shù)。
正如大家所知的,我對命名這件事并不擅長,所以我需要指出,這個項目與Minisketch(https://github.com/sipa/minisketch)完全無關(guān),Minisketch庫是Greg Maxwell、tomatodread和我一起編寫的,其目的是支持高效的基于集調(diào)節(jié)的交易中繼(Erlay)。
它也和我們在Taproot上的研究工作無關(guān)。當(dāng)然,對Miniscript的研究確實教會了我們一些關(guān)于腳本的知識,這些知識可以為將來對腳本的改進(jìn)提供設(shè)計依據(jù),并且Miniscript可以根據(jù)需要進(jìn)行擴(kuò)展。
如果需要的話,我會在Bitcoin Core中加入這部分內(nèi)容(我相信這可能非常有用),但理想情況下,它會被包含在很多錢包技術(shù)中。Andrew Poelstra和sanket1729一直在為它開發(fā)一個Rust庫:
https://github.com/apoelstra/rust-miniscript/
”
以下內(nèi)容,是Miniscript項目技術(shù)文檔的譯文(部分):
Miniscript介紹
Miniscript是一種以結(jié)構(gòu)化方式編寫比特幣腳本子集,并支持分析、合成、通用簽名等功能的語言。
比特幣腳本是一種獨特的基于棧的語言,其具有很多邊界用例,旨在實現(xiàn)由簽名、哈希鎖(hash lock)和時間鎖(time lock)的各種組合組成的支出條件。盡管比特幣腳本的功能有限,但其仍然是非常重要的:
考慮一個支出條件的組合,找到最經(jīng)濟(jì)的腳本來實現(xiàn)它;
給定兩個腳本,構(gòu)建一個實現(xiàn)其支出條件組合的腳本(例如,一個多重簽名,其中的一個“key”是另一個多重簽名);
給定一個腳本,找出其允許的支出條件;
給定一個腳本并訪問足夠的私鑰集,為它構(gòu)造一個通用的令人滿意的witness(驗證內(nèi)容);
給定一個腳本,能夠預(yù)測花費一個輸出的成本;
給定一個腳本,了解特定的資源限制(如操作限制)在花費時是否會受到影響;
Miniscript作為腳本的代表,使得這些操作成為可能,其有一個允許合成的結(jié)構(gòu)。它非常易于靜態(tài)分析各種屬性(支出條件、正確性、安全性、延展性等)。它可成為支出策略編制者的目標(biāo)(見下文)。最后,兼容腳本可以很容易地轉(zhuǎn)換為Miniscript格式,從而避免了對支持它的簽名設(shè)備等附加元數(shù)據(jù)的需要。
目前,Miniscript實際上只為P2WSH和P2SH-P2WSH嵌入式腳本設(shè)計。它的大多數(shù)構(gòu)造在p2sh中也可以正常工作,但一些(可選)安全屬性依賴于隔離見證(Segwit)特定規(guī)則。此外,已實現(xiàn)的策略編譯器假定了一個隔離見證(Segwit)特定成本模型。
Miniscript由Blockstream Research的Pieter Wuille、Andrew Poelstra和Sanket Kanjalkar共同設(shè)計和實現(xiàn),但也有其他人參與討論。
鏈接:
1、C++編譯器:https://github.com/sipa/miniscript
2、Bitcoin Core兼容C++實現(xiàn):https://github.com/sipa/miniscript/tree/master/bitcoin/script
3、Rust-miniscript實現(xiàn):https://github.com/apoelstra/rust-miniscript
4、在斯坦福區(qū)塊鏈活動上談?wù)摰腗iniscript內(nèi)容:http://diyhpl.us/wiki/transcripts/stanford-blockchain-conference/2019/miniscript/ (中文版)
MiniScript編譯器策略
在這里,你可以看到Miniscript編譯器的演示。根據(jù)下面的說明編寫支出策略,并觀察它如何影響構(gòu)造的Miniscript。
策略
and(pk(A),or(pk(B),or(9@pk(C),older(1000))))
支持策略:
pk(NAME): 需要名為NAME的公鑰進(jìn)行簽名,名稱可以是最多16個字符的任何字符串;
after(NUM), older(NUM): 要求nlocktime/nsequence值至少為NUM,NUM不能為0;
sha256(HEX), hash256(HEX): 要求顯示64個字符HEX的預(yù)映射(preimage),特殊值H可用作HEX;
ripemd160(HEX), hash160(HEX): 要求顯示40個字符HEX的預(yù)映射(preimage),特殊值H可用作HEX;
and(POL,POL): 要求滿足這兩個子策略;
or([N@]POL,[N@]POL): 要求滿足其中一個子策略。數(shù)字N表示每個子表達(dá)式的相對概率(因此9@,要比默認(rèn)值高9倍);
thresh(NUM,POL,POL,...): 要求滿足以下子策略中的NUM(假設(shè)所有組合的可能性都相同);
編譯
Miniscript輸出:
and_v(or_c(c:pk(B),or_c(c:pk(C),v:older(1000))),c:pk(A))
支出成本分析
腳本(Script): 114 WU
輸入(Input)Input:142.900000 WU
總計:256.900000 WU
生成的腳本結(jié)構(gòu)
OP_CHECKSIGOP_NOTIFOP_CHECKSIGOP_NOTIFOP_CHECKSEQUENCEVERIFYOP_VERIFYOP_ENDIFOP_ENDIFOP_CHECKSIG
分析Miniscript
在這里,你可以分析Miniscript表達(dá)式的結(jié)構(gòu)等等。
Miniscript
and_v(or_c(c:pk(B),or_c(c:pk(C),v:older(1000))),c:pk(A))
提供類型為“B”的良好miniscript表達(dá)式。
分析:
大?。?14字節(jié)腳本
生成的腳本結(jié)構(gòu)
OP_CHECKSIGOP_NOTIFOP_CHECKSIGOP_NOTIFOP_CHECKSIGOP_NOTIFOP_CHECKSEQUENCEVERIFYOP_VERIFYOP_ENDIFOP_ENDIFOP_CHECKSIG
Miniscript reference翻譯表
此表顯示了所有Miniscript片段及其相關(guān)語義和比特幣腳本。不改變其子表達(dá)式語義的片段稱為wrapper(包裝類)。普通片段使用“fragment(arguments,…)”表示法,而wrapper(包裝類)使用前綴編寫,前綴由冒號與其他片段分開。冒號將在后續(xù)wrapper(包裝類)之間刪除;例如vc:pk(key)是應(yīng)用于給定密鑰的pk片段的c:包裝類的v:包裝類;
含義 | Miniscript片段 | 比特幣腳本 |
---|---|---|
false | 0 |
0 |
true | 1 |
1 |
check(key) | pk(key) |
<key> |
pk_h(key) |
DUP HASH160 <HASH160(key)> EQUALVERFIFY | |
nSequence ≥ n (and compatible) | older(n) |
<n> CHECKSEQUENCEVERIFY |
nLockTime ≥ n (and compatilbe) | after(n) |
<n> CHECKLOCKTIMEVERIFY |
len(x) = 32 and SHA256(x) = h | sha256(h) |
SIZE <32> EQUALVERIFY SHA256 <h> EQUAL |
len(x) = 32 and HASH256(x) = h | hash256(h) |
SIZE <32> EQUALVERIFY HASH256 <h> EQUAL |
len(x) = 32 and RIPEMD160(x) = h | ripemd160(h) |
SIZE <32> EQUALVERIFY RIPEMD160 <h> EQUAL |
len(x) = 32 and HASH160(x) = h | hash160(h) |
SIZE <32> EQUALVERIFY HASH160 <h> EQUAL |
(XandY) orZ | andor(X,Y,Z) |
[X]NOTIF[Z]ELSE[Y]ENDIF |
XandY | and_v(X,Y) |
[X][Y] |
and_b(X,Y) |
[X][Y]BOOLAND | |
and_n(X,Y) =andor(X,Y,0) |
[X]NOTIF 0 ELSE[Y]ENDIF | |
XorZ | or_b(X,Z) |
[X][Z]BOOLOR |
or_c(X,Z) |
[X]NOTIF[Z]ENDIF | |
or_d(X,Z) |
[X]IFDUP NOTIF[Z]ENDIF | |
or_i(X,Z) |
IF[X]ELSE[Z]ENDIF | |
X1+ ... +Xn= k | thresh(k,X1,...,Xn) |
[X1][X2]ADD ...[Xn]ADD ... <k> EQUAL |
check(key1) + ... + check(keyn) = k | thresh_m(k,key1,...,keyn) |
<k> <key1> ... <keyn> <n> CHECKMULTISIG |
X(identities) | a:X |
TOALTSTACK[X]FROMALTSTACK |
s:X |
SWAP[X] | |
c:X |
[X]CHECKSIG | |
t:X =and_v(X,1) |
[X]1 | |
d:X |
DUP IF[X]ENDIF | |
v:X |
[X]VERIFY(or
VERIFYversion of last opcode in [X]) |
|
j:X |
SIZE 0NOTEQUAL IF[X]ENDIF | |
n:X |
[X]0NOTEQUAL | |
l:X =or_i(0,X) |
IF 0 ELSE[X]ENDIF | |
u:X =or_i(X,0) |
IF[X]ELSE 0 ENDIF |
and_n片段和t:、l:以及u:包裝類(wrapper)對于其他Miniscript而言是語法糖,如上表所示。在下面的內(nèi)容中,它們將不再被包括在內(nèi),因為它們的屬性可通過查看它們的擴(kuò)展來派生。
正確性屬性
并非每個Miniscript表達(dá)式都可以彼此組合。有些通過在棧中放入“true”或“false”值來返回結(jié)果,另一些只能中止或繼續(xù)。有些需要使用完全已知數(shù)量的參數(shù)的子表達(dá)式,而另一些則需要具有非零頂部棧元素的子表達(dá)式來滿足。為了對所有這些屬性進(jìn)行建模,我們?yōu)镸iniscript定義了一個正確性類型系統(tǒng)。
每個ministcript表達(dá)式都有四種基本類型之一:
"B" 基本表達(dá)式:這些表達(dá)式從棧頂獲取輸入。當(dāng)滿足時,它們將最多4字節(jié)的非零值推送到棧上。當(dāng)不滿足時,它們將一個精確的0推送到棧上(如果不滿足而不中止是完全可能的)。此類型用于大多數(shù)表達(dá)式,并且是頂級表達(dá)式所必需的。示例是 older(n) = CHECKSEQUENCEVERIFY;
"V" 驗證表達(dá)式:像"B"表達(dá)式一樣,它們從棧頂獲取輸入。然而一旦滿足,它們就可繼續(xù)工作而無需推送任何東西。它們在不中止的情況下,是無法不滿足的。一個"V"表達(dá)式可使用"B" 表達(dá)式上的v: wrapper獲得,或者通過使用and_v,or_i,or_c,或andor組合其他"V" 表達(dá)式獲得。例子有vc:pk(key) = CHECKSIGVERIFY;
"K" Key表達(dá)式:它們也同樣從棧頂獲取輸入,但不會直接驗證條件,而是將公鑰推送到棧上,對于該棧,仍需要簽名來滿足表達(dá)式??墒褂胏:wrapper(CHECKSIG)將 "K"表達(dá)式轉(zhuǎn)換為"B"表達(dá)式。例如pk_h(key) = DUP HASH160
"W"包裝表達(dá)式:它們從棧頂獲取輸入,并將非零(滿足時)或零(不滿足時)推送到棧頂部或one below。例如,一個3輸入"W"表達(dá)式會把棧"A B C D E F"轉(zhuǎn)換成"A B F 0" 或"A B 0 F"(如果不滿足),而如果滿足,則轉(zhuǎn)換成 "A B F n"或"A B n F"(n為非零值)。每個"W"表達(dá)式要么是s:B (SWAP B)要么是a:B (TOALTSTACK B FROMALTSTACK)。例子有sc:pk(key) = SWAP CHECKSIG;
然后有5個類型修飾符(modifier),它們負(fù)責(zé)保證附加屬性:
“z”zero arg:此表達(dá)式始終只消耗0個棧元素;
"o" One-arg: 此表達(dá)式始終只消耗一個棧元素;
"n"非零:此表達(dá)式始終使用至少一個棧元素,此表達(dá)式的dissatisfaction,要求頂部輸入棧元素為零;
"d" 不滿足:此表達(dá)式的不滿足可無條件構(gòu)造。這意味著dissatisfaction不能包括任何簽名或哈希預(yù)映射preimage,也不能依賴于滿足的時間鎖;
"u"單位:當(dāng)滿足時,此表達(dá)式將在棧上精確放置一個1(而不是任何非零值);
下表列出了每個Miniscript表達(dá)式的正確性要求及其子表達(dá)式中的類型屬性:
資源限制
不同類型的比特幣腳本有不同的資源限制,無論是通過共識還是標(biāo)準(zhǔn)。其中一些會影響其他有效的Miniscripts:
超過10000字節(jié)的腳本因共識而無效(bare, P2SH, P2WSH, P2SH-P2WSH);
超過520字節(jié)的腳本因共識無效(P2SH);
腳本滿足操作,其中非push操作碼總數(shù)加上參與所有已執(zhí)行thresh_ms的key數(shù)大于201,因共識而無效(bare, P2SH, P2WSH, P2SH-P2WSH);
除c:pk(key)(P2PK)、c:pk_h(key)(P2PKH)和thresh_m(k,...)之外n=3的任何內(nèi)容在標(biāo)準(zhǔn)性無效(bare);
超過3600字節(jié)的腳本因標(biāo)準(zhǔn)無效(P2WSH, P2SH-P2WSH);
序列化腳本簽名(scriptSig)超過1650字節(jié)的腳本,因標(biāo)準(zhǔn)無效(P2SH);
由100多個棧元素組成的witness腳本,因標(biāo)準(zhǔn)無效(P2WSH, P2SH-P2WSH);
MiniScript的存在,使驗證滿足腳本不受這些限制影響的能力變得容易。請注意,這與驗證是否永遠(yuǎn)無法達(dá)到限制不同(這也是可能的)。例如,考慮or_b(X,Y),其中x和y都需要執(zhí)行大量的thresh_ms來satisfaction。在這種情況下,滿足x或y中的一個不會超過操作限制,而滿足兩者則都會超過。因為這兩者都不需要滿足,所以限制并不能阻止satisfaction。
安全屬性
上面的類型系統(tǒng)保證對應(yīng)的比特幣腳本是:
共識和標(biāo)準(zhǔn)性完成:假設(shè)不違反上一節(jié)中列出的資源限制,對于語義允許的每一組滿足條件,可構(gòu)建一個通過比特幣共識規(guī)則和通用標(biāo)準(zhǔn)性規(guī)則的witness;
共識健全:除非滿足支出條件,否則無法構(gòu)建對腳本有效的共識witness。由于標(biāo)準(zhǔn)性規(guī)則只允許共識有效滿足的一個子集,因此此屬性還意味著標(biāo)準(zhǔn)的健全性。
通過對比Bitcoin Core的共識和標(biāo)準(zhǔn)性實現(xiàn),及驗證大量隨機(jī)Miniscript表達(dá)式的隨機(jī)滿足性,P2WSH的完整性屬性得到了廣泛測試。通過考慮每個片段腳本中所有可能的執(zhí)行路徑,可推斷出健全性。
為了使這些屬性不僅適用于腳本,而且適用于整個交易,witness必須提交與驗證相關(guān)的所有數(shù)據(jù)。實際上,這意味著不需要任何數(shù)字簽名就可滿足其條件的腳本是不安全的。例如,如果一個輸出可通過簡單地傳遞某個nLockTime(Miniscript中的after(n)片段)來使用,但沒有任何數(shù)字簽名,攻擊者就可以修改支出交易中的nLockTime字段。
關(guān)鍵詞: Bitcoin core Miniscript 比特幣