比特幣:交易的資料結構

姜家志發表於2017-07-17

比特幣協議中最重要的部分就是交易,比特幣協議其他的部分也都是為了確保交易的生成、廣播、驗證和打包而實現的。
本文內容主要是針對交易的資料結構以及對原始交易進行解析,後期還會繼續寫交易的生命週期交易指令碼等文章。

原始交易

比特幣的交易是以位元組的形式存在塊中的,使用bitcoin-cli命令可以獲得一個原始的交易資料。例如:

bitcoin-cli getrawtransaction 2eb0e06af852f049f7dc641f740ded17a11cde138fd3d3d3c4a078649c053260

會得到一個完整的原始交易資料:

010000000112255d3c...88ac00000000複製程式碼

^rawtransaction
得到的原始交易是經過hex處理的,並沒有顯示為原始位元組。從上面的hex字串也並不能看到有用的資訊(如果想檢視json格式的交易可以檢視api).
原始的交易資料並不能直觀地體現交易的具體內容,如何才能得到具體的交易內容呢?藉助這個例子可以詳細的分析下交易結構和原始資料解析。先看下交易的資料結構。

交易的資料結構

一個完整的交易由以下的元素構成的:

  • 版本 version
  • 輸入 tx_in
  • 輸出 tx_out
  • 鎖定時間 lock_time

其中交易的輸入和輸出有可能是一個或多個,上面所說的交易就有一個輸入和兩個輸出。
版本(version)是明確一筆交易參照的規則,除非有重大升級的情況下,版本號基本無變化,是比較固定的一個值。
交易的鎖定時間是被該交易被加到區塊的最早時間,在大多數的情況下他的值都是0,表示需要立即被加入區塊中。如果鎖定時間大於0而小於5億,它的值就表示區塊高度。如果大於5億就表示一個Unix時間戳。
上面所描述的交易構成又是如何在原始交易裡面體現的呢?這就需要對原始交易進行拆解,看下交易結構如何在原始交易中定義的:

描述 長度 原始欄位
版本 4 01000000
交易輸入的個數 1+ 01
交易輸入 41+ 12255......ffffffff ^ins
輸出的個數 1+ 02
交易輸出 9+ 00e1f...988ac^outs
鎖定時間 4 00000000

通過上面的表格可以看到一個原始交易是如何儲存交易的。原始交易中除了包括交易所需要的資料之外,因為交易的輸入和輸出有可能會出現多個,所以原始交易還需要額外的欄位用來描述交易的輸入、輸出個數,輸入、輸出的個數並不是固定的,因此用來描述個數使用的是變長整數(VarInt),他的目的是在節省空間的情況下能夠儲存足夠使用的整數。
這裡描述了一個交易的資料結構以及他在原始交易中如何儲存的,但是並沒有拆解出具體的輸入輸出內容。下面就對輸入輸出進行詳細的拆解,先從輸入開始。

交易輸入

一個交易的輸入是由下面的元素組成:

  • 引用交易的hash
  • 引用交易的索引
  • 解鎖指令碼

那麼交易輸入又是如何在原始交易裡面進行儲存的呢?從上面的分析我們可以知道該例子交易中只有一個交易的輸入。下面就是從原始交易中解析下交易的輸入

描述 長度 原始欄位
前置交易hash 32 12255...ae^previous_hash
前置交易的索引 4 01000000
解鎖指令碼長度 1+ 8a
解鎖指令碼 4730...eae^in_script
序列 4 ffffffff

這裡獲取到的hash和網站上面顯示的hash並一致,這是因為位元組序的儲存和讀取的方式不一致造成的,即大端和小端模式

網路協議規定接收到第一個位元組是高位元組,存放在低地址,所以傳送時會首先去低地址取資料的高位元組

而在比特幣的儲存中hash是做為一個整數儲存的,因此在取hash時候需要從低地址開始獲取。
而解鎖指令碼的長度也是未知的,就需要使用一個可變整形用來表示解鎖指令碼的長度。對於交易指令碼的拆解會在以後的文章中進行。
通過上面表格的描述就可以從一個交易中拆解出它的輸入了,下面繼續對交易輸出進行拆解。

交易輸出

一個交易的輸出是由下面的元素組成的:

  • 輸出金額
  • 輸出指令碼

那交易的輸出在原始交易中又是如何儲存的呢?從上面的交易拆解中可以知道該例子交易是有兩個輸出,這裡只需要針對第一個輸出進行拆解即可:

描述 長度 原始欄位
value 單位是1聰 8 00e1f50500000000
鎖定指令碼長度 1+ 19
鎖定指令碼 76a9147072795a259b38bf476e053852ab85221ba9467b88ac

注意輸出的金額也涉及到大端傳輸的問題,解析的時候需要從低地址開始讀取。
這裡並沒有對鎖定指令碼進行拆解,所以還看不到輸出的地址,對於一個比特幣交易來說,交易本身是不用關心輸出的地址,交易只需要關心鎖定指令碼,當使用的時候能使用使用正確的解鎖指令碼即可動用比特幣。關於交易指令碼會在以後的內容裡詳細的介紹。
交易本身的資料結構並不沒有交易費的概念,每筆交易的手續費是使用總輸入-總輸出計算得到的,所以在交易的資料結構中沒有體現。
總結,一個原始的交易包含了一個交易所需要的所有資料,他們按照比特幣協議規定的規則進行儲存。在交易生成,驗證的時候也需要按照xiang'tong

相關文章