比特幣原始交易解析
阿新 • • 發佈:2019-01-11
在比特幣當中,一筆交易的構成並非簡單地由一個賬戶餘額減去所轉賬的數額,再由向另一個賬戶餘額新增相同的數額。比特幣的交易是由一系列被稱為opcode的指令所組成的指令碼。也就是說,這些交易資料構成了比特幣本身。在執行指令碼的過程中,比特幣會將這些指令一一壓入棧中,並計算它們是否合法。
那麼,比特幣是如何解析並處理交易資料的呢?在傳輸、儲存的過程當中,比特幣會先將資料序列化成二進位制形式,成為原始交易(raw transaction)。有關於比特幣資料序列化的細節在我的另一篇部落格————比特幣原始碼學習筆記(二)當中有介紹。下面,我們以比特幣測試網路上的一筆交易為例,讓我們看一下一筆原始交易是怎樣構成的。該筆交易的ID為64f14bf86bbc45b2cc924c3a5da547868754af3e79493fe60aadfc1718ae9cce。區塊鏈瀏覽器顯示,該筆交易發生在2015年1月24日23點46分33秒,位於區塊高度319522,大小為191位元組,金額0.01(測試網路)。該交易的原始資料十六進位制表示如下:
010000000196c472ac5cbc3cf6acae1493d4d32f119f39ec9e440176b2fb7de6e6024b9f21010000006a473044022034519a85fb5299e180865dda936c5d53edabaaf6d15cd1740aac9878b76238e002207345fcb5a62deeb8d9d80e5b412bd24d09151c2008b7fef10eb5f13e484d1e0d01210207c9ece04a9b5ef3ff441f3aad6bb63e323c05047a820ab45ebbe61385aa7446ffffffff0140420f00000000001976a914053496c1ea3d54d649ed54de490fda342522244088ac00000000
乍看之下,這端資料如同莫爾斯電碼一般讓人無從下手。其實,只要我們瞭解比特幣的結構便不難理解它。
01000000
版本號的Little-Endian(反序)格式
01
輸入未花費交易(UTXO)的數量
96c472ac5cbc3cf6acae1493d4d32f119f39ec9e440176b2fb7de6e6024b9f21
上一筆交易輸出的雜湊,Little-Endian格式。該筆交易可以通過區塊鏈瀏覽器的輸入交易中找到
01000000
該筆輸入交易在上一筆交易輸出所在的位置output_no,Little-Endian格式。同樣可通過區塊鏈瀏覽器
6a
該段資料為其後面緊隨的scriptSig,即解鎖指令碼的位元組數,十六進位制格式
47
PUSHDATA 47,將47個位元組的資料壓入棧中
3044022034519a85fb5299e180865dda936c5d53edabaaf6d15cd1740aac9878b76238e002207345fcb5a62deeb8d9d80e5b412bd24d09151c2008b7fef10eb5f13e484d1e0d
簽名部分,解鎖指令碼scriptSig的第一部分
01
SIGHASH_ALL指令,為了保護簽名部分不被篡改
21
PUSHDATA 21,將21個位元組的資料壓入棧中
0207c9ece04a9b5ef3ff441f3aad6bb63e323c05047a820ab45ebbe61385aa7446
Big-Endian格式的公鑰,解鎖指令碼的第二部分
ffffffff
順序編號,在該筆交易中為不可用。如果locktime為非零,則至少一筆輸入交易的順序編號必須小於0xffffffff
01
輸出交易的數量
40420f0000000000
交易的數額,Little-Endian格式
19
上鎖指令碼(P2PKH)的大小。後面為該指令碼的內容
76
OP_DUP,上鎖指令碼scriptPubKey的一部分
a9
OP_HASH160,上鎖指令碼scriptPubKey的一部分
14
PUSHDATA 14,將14個位元組壓入棧中,上鎖指令碼scriptPubKey的一部分
053496c1ea3d54d649ed54de490fda3425222440
接收方公鑰的雜湊,其結果為RIPEMD160(SHA256(pubkey))
88
OP_EQUALVERIFY,上鎖指令碼scriptPubKey的一部分
ac
OP_CHECKSIG,上鎖指令碼scriptPubKey的一部分
00000000
nLockTime,可以為UNIX時間戳或者區塊高度。在達到這個數值之前,該筆交易不可被新增進區塊。若nLockTime為0則表示該交易可以被立刻執行。
關於opcode,在此不一一介紹,可於比特幣官網找到。對於輸入、輸出交易的具體構成和工作原理,可以在我的部落格 比特幣原始碼學習筆記(一)當中找到。
形象地講,一筆交易輸出TxOut的指令碼scriptPubKey主要由接收方公鑰的Hash和指令OP_EQUALVERIFY、OP_CHECKSIG構成,如同給這筆轉賬裡的比特幣上了一把鎖,能夠解開這把鎖鑰匙的擁有者即OP_HASH160公鑰的擁有者,只有用相對應的私鑰才可以使用被鎖住的比特幣。為了開啟這把鎖,在下一筆交易中,擁有者需要建立一個指令碼scriptSig提供自己的簽名和公鑰。節點在驗證交易的時候,會首先驗證該公鑰的Hash160是否與上一筆交易輸出中的OP_HASH160相同,即表明該公鑰為接收方所擁有。為了確保是接收方本人的操作,節點接下來要驗證所提供的簽名是否與公鑰相匹配。如果驗證通過,則該交易為合法,否則便會被拒絕。
順便提一下,隔離見證(Segregated Witness)的原理即是將簽名部分不放入腳本當中,而是傳送至“隔離見證”的部分。由於去掉了簽名,隔離見證減小了資料本身的大小,這樣即可在不修改比特幣1mb的區塊限制下增加交易數量,並同時相容舊版本與新版本的客戶端。同樣,該措施避免了修改scriptSig中的簽名部分而發起的交易可鍛性攻擊(transaction malleability)。