P2PKH 腳本驗證
驗證過程需要對簽名腳本和公鑰腳本進(jìn)行求值,在P2PKH 輸出中,公鑰腳本的格式是:
OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
發(fā)送方的簽名腳本被解析作為整個腳本的頭部。在P2PKH交易中,簽名腳本包含了一個secp256k1的簽名,和完整的公鑰,這樣和上面的公鑰腳本連在一起就創(chuàng)建了完整的腳本
<Sig> <PubKey> OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
腳本語言是一個基于棧的、故意被設(shè)計成無狀態(tài)、非圖靈完備的語言。無狀態(tài)確保交易一旦被放到區(qū)塊鏈上,就不會出現(xiàn)輸出永遠(yuǎn)不能被花費的情況。非圖靈完備(缺少循環(huán)和goto語句)讓腳本語言更加靈活(flexible)和可預(yù)見,大大簡化了安全模型。
為了測試交易是否有效,簽名腳本和公鑰腳本的操作逐語句執(zhí)行,從Bob的簽名腳本開始直到Alice的公鑰腳本。下面的圖展示了腳本的執(zhí)行過程。
- 簽名(Bob的簽名腳本中的)被壓入棧
- 公鑰被被壓入棧
- 執(zhí)行Alice公鑰腳本中的 OP_DUP 操作,棧頂元素被拷貝一次并且壓入棧中。
- 執(zhí)行 OP_HASH160,彈出棧頂元素,并對其進(jìn)行HASH160運算,并且將結(jié)果壓入棧中,這步操作實際上產(chǎn)生了一個Bob公鑰地址的哈希
- Alice將Bob在第一次交易中給他的公鑰腳本中的公鑰哈希壓入棧中,這樣在棧頂就有了兩個Bob的公鑰哈希
- 執(zhí)行OP_EQUALVERIFY操作,OP_EQUALVERIFY相當(dāng)于執(zhí)行OP_EQUAL和OP_VERIFY兩個操作;OP_EQUAL彈出棧頂?shù)膬蓚€元素,然后檢查它們是否相等,并將結(jié)果(0/1)壓入棧中;OP_VERIFY檢查棧頂元素是否為true。如果為false,立即停止執(zhí)行,返回失敗,否則彈出棧頂元素
- 執(zhí)行OP_CHECKSIG:彈出棧頂?shù)暮灻凸€,檢查一致,并且簽名是對所有的需要被簽名的數(shù)據(jù)進(jìn)行的,就將true壓入棧中,否則將false壓入棧中,表示交易無效
P2SH 腳本
公鑰腳本由發(fā)送方創(chuàng)建,發(fā)送方并不在乎公鑰腳本是干嘛用的。接收方很關(guān)心公鑰腳本,如果他們想,會讓發(fā)送方使用一個特殊的公鑰腳本。不幸的是,一般的公鑰腳本不像比特幣地址那樣簡單,而且在不同的程序之間無法互通(在BIP70支付協(xié)議實現(xiàn)之前)。
為了解決這個問題,pay-to-script-hash(P@SH)交易在2012念的時候被創(chuàng)建。它允許用戶創(chuàng)建一個公鑰腳本,這個公鑰腳本包含第二個腳本的哈希和回收腳本的。
基本的P2SH工作流如下圖所示,看起來幾乎和P2PKH的工作流一樣。Bob創(chuàng)建一個回收腳本,然后進(jìn)行哈希,并且將回收腳本給Alice,Alice創(chuàng)建一個P2SH-style輸出用于包含Bob的回收腳本。
當(dāng)Bob需要花那個輸出中的錢的時候,他在他的簽名腳本中包含回收腳本和他的簽名。P2P網(wǎng)絡(luò)確保完整的回收腳本的哈希和Alice在他的輸出中所給出的一致。然后執(zhí)行回收腳本,執(zhí)行成功就允許Bob花費那個輸出,否則執(zhí)行失敗。
回收腳本的哈希和公鑰腳本的哈希有同樣的功能---因此只需要通過一點點改動,它也可以被轉(zhuǎn)換成標(biāo)準(zhǔn)的比特幣地址。這是的搜集P2SH風(fēng)格的地址和P2PKH風(fēng)格的一樣簡單。哈希同樣可以隱藏哈希的具體內(nèi)容,所以P2SH腳本和P2PKH腳本一樣安全。