1. 程式人生 > >比特幣原始碼情景分析之script指令碼驗證(1)

比特幣原始碼情景分析之script指令碼驗證(1)

Bitcoin script是一種簡單的指令執行框架1)指令碼概述指令碼主要由兩部分構成:指令碼物件CScript和執行函式VerifyScript。指令碼物件分為兩類:scriptSig和scriptPublicKeyscriptSig位於交易中的txin中,而scriptPubKey位於txout中,scriptSig解鎖scriptPubKey,具體關係如下:
一個交易可能有多個txin和多個txout。一個txin引用一個未花掉的txout,比如上圖的C.txin_1引用A.txout_1那麼C.txin_1.scriptSig解鎖A.txout_1.scriptPubKey鎖定指令碼,當scriptSig解鎖scriptPubkey時,只需先執行解鎖指令碼scriptSig,然後執行鎖定scriptPub即可,驗證通過證明C.txin_1可以合法使用A.txout_1生成新的交易2)指令碼構成
一個指令碼由指令和資料構成,比如<largedata> <sig> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG上面<>中的是資料,OP_開頭的是指令,所有的指令佔一個位元組(8位)其實這個指令碼真正儲存結構如下OP_PUSHDATA4 [F0][00][00][E0] <largedata> [0F] <sig>OP_DUP OP_HASH160 [14]<pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG上圖橙色的部分是資料長度,也就說指令碼中的所有資料都是以資料大小為先導。這個很好理解,一段非格式化的資料,順序取值時必須知道即將要取得物件的是什麼型別的,佔用空間多大。3)指令碼執行
指令碼執行就是解釋指令碼內容,涉及讀取指令碼中的資料到堆疊stack, 讀取stack的內容,生成資料並寫入stack1)largedata資料獲取指令 OP_PUSHDATA4 [F0][00][00][E0] :    指令碼執行函式讀取第一個位元組,發現是OP_PUSHDATA4指令,便知道接下來4個位元組空間儲存的是資料的大小資訊,於是取接下來的4個位元組,拼接為一個32位數字,然後就知道資料的長度N,緊接著取N個位元組放置到stack,這N個位元組就是資料的內容2)sig資料獲取指令 [0F] <sig>:    上一個操作執行完成後,執行函式又讀取一個位元組,發現是0F, 不是任何合法指令便認為是資料的大小資訊,於是讀取接下來16個位元組的內容作為資料並3)複製資料指令
OP_DUP:    上一個操作執行完成後,執行函式又讀取一個位元組,發現是OP_DUP, 該指令的規則是讀取stack棧頂的資料並複製一份壓入棧頂上面的執行過程對應的stack變化如下:
4)交易指令碼模板    節點在生成交易時可以編寫任意的指令碼,但是由於鎖定指令碼(scriptPubKey)解鎖指令碼(scriptSig)是由網路中不同的節點生成和執行的,所以鎖定節點要想解鎖交易必須得能理解對應的鎖定指令碼才能生成合適的解鎖指令碼,因此需要一些標準的指令碼模板。這樣通過比較鎖定指令碼和標準指令碼,就能知道鎖定指令碼是什麼指令碼,需要產生什麼解鎖指令碼。    目前主流的交易指令碼模板如下:  1.P2PK(Pay-to-Public-Key)    藍色部分是解鎖指令碼,紅色部分是鎖定指令碼, 該指令碼目前不常用,因為鎖定指令碼中包含pubkey, 即包含使用者的錢包地址資訊,且由於鎖定指令碼是儲存在區塊鏈上的,任何人都能查詢到,自然缺乏隱私保護
<sig> <pubKey> OP_CHECKSIG 2.P2PKH(Pay-to-Public-Key-Hash):    P2PKH可以很好的解決P2PK的隱私問題,因為P2PKH的鎖定指令碼中只有pubKeyHash值,其他使用者沒法從pubKeyHash反推出pubKey進而獲取錢包地址。    目前,比特幣網路大部分交易都是以P2PKH方式進行的,其解鎖指令碼與鎖定指令碼如下:<sig> <pubKey>OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG按照我們前面的分析,該指令碼在記憶體中的真正資料結構如下[0x08] <sig> [0x06] <pubKey>OP_DUP OP_HASH160 [0x14] <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG解鎖指令碼執行完成後棧裡已經有sig, pubkey兩個資料,鎖定指令碼的執行流程如下:
堆疊指令操作
([sig], [pubkey])OP_DUP複製棧頂元素[pubkey]至堆疊S
([sig,[pubkey], [pubkey])OP_HASH160pop出一個元素,並進行hash160運算,將結果push回S
([sig,[pubkey], [hash160_pubkey]) 0×14 push後面20位元組的資料
 ([sig,[pubkey], [hash160_pubkey], [hash160]) OP_EQUALVERIFY pop出2個元素,比較大小。若不相等,則標記交易為無效
  ([sig,[pubkey]) OP_CHECKSIG pop出兩個元素,驗證簽名,如成功,則壓入TRUE;否則壓入FALSE
 (TRUE)
 3.MS(Multiple Signatures)多重簽名    N是存檔公鑰總數,M是要求啟用交易的最少公鑰數。
OP_0 <Sig1><Sig2>  M <pubKey 1><pubKey2> ... <pubKeyN> N OP_CHECKMULTISIG 4.P2SH(Pay-to-Script-Hash)   MS和P2PK一樣,將pubkey暴露在鎖定指令碼中,缺乏隱私,因而P2SH出現了,該指令碼鎖定指令碼中只有hash,並將多簽名鎖定指令碼交給解鎖者生成<Sig1> <Sig2> <2 PK1 PK2 PK3 PK4 PK5 5 OP_CHECKMULTISIG> OP_HASH160 8ac1d7a2fa204a16dc984fa81cfdf86a2a4e1731 OP_EQUAL這個指令碼模板的特點是會執行兩次驗證1)第一層驗證,紅色部分是鎖定指令碼,藍色部分是解鎖指令碼2)第二層驗證,藍色部分是鎖定指令碼,紫色部分是解鎖指令碼/********************************* 本文來自CSDN博主"愛踢門"******************************************/