比特幣交易原理分析

shuwoom的部落格發表於2018-05-06

最近一直在自學區塊鏈,這段時間開始系統總結一些學習的內容,寫成部落格內容,也定期每週釋出更新到微信公眾號(微信公眾號:shuwoom 的部落格),希望能給初學者或者想要系統學習區塊鏈技術的同學一些幫助。

cmd-markdown-logo

在這一系列技術總結後,會帶大家動手從零開發一個迷你區塊鏈。

迷你區塊鏈體驗地址: miniblockchain.shuwoom.com/index

博文地址: shuwoom.com/?p=430

關鍵字:比特幣、區塊鏈、交易指令碼、智慧合約、UTXO賬戶模型、價值轉移

1.比特幣的UTXO模型

首先,在講比特幣交易過程之前要說明一個事情。比特幣系統是沒有餘額的概念的,它使用的是UTXO模型(Unspent Transaction Outputs,未使用過的交易輸出),我們在交易過程中經常說的錢包餘額,實際上是一個錢包地址的UTXO集合。所以,在比特幣網路中,儲存比特幣餘額的是交易輸出,準確點說就是未使用過的交易輸出,而每一筆交易的輸入實際上引用的是上一筆交易的輸出。下圖是比特幣系統中交易輸入輸出的過程:

圖0 比特幣系統中交易輸入輸出過程

如下圖,每一筆交易記錄了時間、傳送人、接收人和金額。那如果要計算A的餘額,那麼就要遍歷所有跟A有關的交易,減去A傳送的每一筆金額,並加上A接收的每一筆金額,可以計算出。

  • A的餘額 = 20-10=10

  • B的餘額 = 20+10+5-5=30

  • C的餘額 = 20-5=15

  • D的餘額 = 20+5=25

比特幣系統中計算餘額的方法也是類似這樣。所以,要計算一個使用者的比特幣餘額,就需要遍歷整個交易的歷史。而以太坊由於採用了Account模型,也就是採用餘額的概念,所以不需要溯源整個交易歷史。

圖1 賬本

所以,我們可以將UTXO理解為一個幣:它是有一個金額以及一個擁有者。一筆交易若要有效,就必須滿足兩個條件:

(1)這個交易必須包含一個有效簽名,來自它所花費的UTXO的擁有者

(2)被花費的UTXO的總金額必須大於等於該交易產生的UTXO總金額。

2.交易過程

上面,我們介紹了比特幣的UTXO模型,解釋了比特幣“餘額”的概念。接下來,我們正式開始講解比特幣的交易過程,並在接下來的分析過程中我們會回答兩個很重要的問題:

(1)如何保證使用者只能使用自己的比特幣?(比特幣賬本是全網公開的)

(2)如何保證一筆交易的有效性?

下圖,是一筆交易的完整過程。這裡面交易有兩種型別,一種是Coinbase交易,也就是挖礦獎勵的比特幣,由於沒有傳送人,所以比較特殊。另一種就是我們常見的普通交易了,包含輸入和輸出的。

圖2 比特幣交易基本過程

這裡我們假設,由於Alice挖礦被獎勵了12.5個比特幣。而Alice在一筆交易中,需要轉賬給Bob10個比特幣。而Bob最終確認並接收了Alice傳送的10個比特幣,而同時由於多出了2.5個比特幣。其實這筆交易最終是生成了2個輸出,一個是傳送給Bob的10個比特幣,另一個是找零產生的發給Alice的2.5個比特幣(備註:這裡不考慮交易費)。

在這裡面,發生了幾個關鍵的操作:

(1)最開始,Alice由於挖礦被獎勵了12.5個比特幣,從而產生一筆Coinbase交易。這個交易中包含一個輸入和一個輸出。輸出中,包含當前輸出的索引、金額、鎖定指令碼和接受者的公鑰。這裡鎖定指令碼的作用是,設定成只有Alice才能使用這筆輸出。而要使用這個UTXO,就必須要證明自己是Alice。如何證明,我們會在後面講解。

(2)然後,由於Alice要傳送給Bob10個比特幣,那麼她首先要做的就是確認自己有沒有足夠的“餘額”去支付這筆交易。我們在上一節說了,要計算使用者的餘額,就要遍歷Alice的所有交易記錄,這裡,我們假設Alice就只有一筆Coinbase交易,也就是說Alice當前的餘額是12.5個比特幣。由於12.5大於所要支出的10個比特幣,所以交易可以進行。

(3)接下來,就是要建立一筆交易。這筆交易包含1個輸入、2個輸出(一個傳送給Alice,一個找零發給自己)。

由於比特幣採用UTXO模型,一筆交易的輸入實際上使用的是上一筆交易的輸出(UTXO)。輸入中也包含傳送者的公鑰,這裡是Alice的公鑰。這裡,有一個很重要的問題,我們怎麼知道Alice使用的是自己的UTXO呢?如果Alice使用的是別人的UTXO,我們怎麼去校驗呢?

這裡,我們看到輸入中除了引用上一個交易輸出和傳送者Alice的公鑰,還包含了一個解鎖指令碼。解鎖指令碼里包含了Alice的對上一筆交易輸出的簽名和自己的公鑰。在《區塊鏈快速入門》中,我們知道通過數字簽名技術,我們可以使用公鑰對使用者的簽名(私鑰加密)進行驗證從而證明簽名者是否使用者本人。如下圖,我們就可以通過解鎖指令碼中提供的Alice的簽名和公鑰去驗證Alice使用的是否是自己的UTXO。

圖3 數字簽名技術(簽名和驗證)

(4)上一步,我們驗證了該交易中輸入所引用的上一筆UTXO確實是Alice的,從而證明了該輸入的有效性。接下來,就需要建立2個輸出,一個是給Bod的10個比特幣,同時包含一個鎖定指令碼,該鎖定指令碼限定只有Bod才能使用;另一個是找零產生的輸出,傳送給Alice的2.5個比特幣,同樣的也包含一個鎖定指令碼,並且限定只有Alice本人才能使用。

(5)最後交易建立完成後,就向比特幣網路廣播出去,當比特幣網路確認這筆交易並且將這筆交易在下一次挖礦競賽中,將該交易打包進區塊中並得到全網共識確認後,這筆交易就確認有效了。

比特幣的基本交易過程就基本這樣。

下圖我們可以瞭解下,一個比特幣真實交易是包含哪些資料的?

b6f6b339b546a13822192b06ccbdd817afea5311845f769702ae2912f7d94ab5交易

圖4 普通交易

3.關鍵概念

一個交易包含以下資訊:

  • 輸入:一個或多個交易輸入

  • 輸出:一個或多個交易輸出

  • 時間:交易時間戳UNIX

3.1 交易分類

交易分為2類:

  • Coinbase交易:挖礦獎勵,沒有輸入,只有輸出。如下圖5所示。

  • 普通交易:使用者之間的普通轉賬交易,如上圖4所示

圖5 Coinbase交易

3.2 交易輸入

交易的輸入結構如下:

圖6 交易輸入結構

3.3 交易輸出

交易的輸出結構如下:

圖7 交易輸出結構

3.4 交易指令碼

(1)概念

比特幣客戶端使用一個用類Forth指令碼語言編寫的指令碼去驗證比特幣的交易,這個指令碼語言不是圖靈完備的,不具備迴圈等複雜的特性。它是一種基於堆疊的執行語言,該指令碼語言的簡單特性,雖然使得它不能實現複雜的功能,但是也提高了交易指令碼的安全性(設計簡單,減少了攻擊面)。而以太坊就是詬病比特幣交易指令碼功能有限,所以設計了一個圖靈完備的指令碼語言,也就是我們常說的智慧合約指令碼語言,能實現更復雜的功能,但同時也增加了安全隱患。

當一筆比特幣交易被驗證時,每一個輸入中的解鎖指令碼與其所引用的輸出中的鎖定指令碼同時執行,從而檢查這筆交易是否有效。如圖8所示,是最為常見型別的比特幣交易的解鎖和鎖定指令碼。

圖8 解鎖指令碼和鎖定指令碼

(2)驗證過程

當我們拿到一筆交易時,如何驗證這個交易輸入是否有效,也就是如何校驗該輸入所引用的輸出是否有效。

首先,將當前輸入的解鎖指令碼,和該輸入所引用的上一筆交易輸出的鎖定指令碼如圖8一樣組合在一起,並進行下的驗證過程,最終若返回TRUE,說明交易有效。

圖9 交易有效性校驗過程

從上面的校驗過程,其實我們可以發現,如果要實現多人簽名的校驗以及定時消費的校驗(規定多久後才能使用),同樣可以採用上述的原理進行。

(3)例項分析

下面,我們通過分析一筆比特幣真實交易,來加深瞭解比特幣的交易指令碼驗證過程。

地址:

webbtc.com/tx/cca75078…

圖10 cca7507897abc89628f450e8b1e0c6fca4ec3f7b34cccf55f3f531c659ff4d79交易資料

為了校驗該交易有效,我們需要對

cca7507897abc89628f450e8b1e0c6fca4ec3f7b34cccf55f3f531c659ff4d79中輸入所引用的上一筆輸出的鎖定指令碼與當前輸入中的解鎖指令碼進行校驗。

解鎖指令碼(SriptSig):

8b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb

翻譯後:

PUSHDATA(72)[30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e01] PUSHDATA(65)[042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb]

該解鎖指令碼包含了傳送者的簽名(綠色部分)和公鑰(紅色部分)。

該輸入引用的上一筆輸出的鎖定指令碼:

  • 上一個交易ID:a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d

  • 輸出索引:0

可以找到輸入所引用的上一筆交易輸出是如下:

其鎖定指令碼為:1976a91446af3fb481837fadbb421727f9959c2d32a3682988ac

翻譯後:

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG

我們將解鎖指令碼和鎖定指令碼組合在一起進行校驗:

PUSHDATA(72)[30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e01] PUSHDATA(65)[042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb]

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG

然後逐一執行指令:

指令

說明

PUSH DATA 3045…0e01

將3045…0e01(簽名)入棧

3045…0e01

PUSH DATA 042e…cabb

將042e…cabb(公鑰)入棧

042e…cabb

3045…0e01

OP_DUP 042e…cabb

複製棧頂資料

042e…cabb

042e…cabb

3045…0e01

OP_HASH160

對棧頂資料先採用SH256雜湊演算法,隨後對其運用RIPEMD160演算法,得到:

46af3fb481837fadbb421727f9959c2d32a36829

46af…6829

042e…cabb

3045…0e01

PUSH DATA 46af…6829

將46af…6829入棧

46af…6829

46af…6829

042e…cabb

3045…0e01

OP_EQUALVERIFY

校驗棧頂兩個資料是否相等

042e…cabb

3045…0e01

OP_CHECKSIG

驗證簽名

TRUE

RESULT

返回為TRUE,說明交易有效

最終交易指令碼返回TRUE,證明了交易的有效性。

備註:如果想要詳細瞭解比特幣的指令碼語言,可以檢視:en.bitcoin.it/wiki/Script

如果想線上校驗交易,可以檢視:webttc.com

關注我的微信公眾號(shuwoom的部落格),每週定期推送文章:

參考

[1] 比特幣賬戶模型。book.51cto.com/art/201711/…

[2] 主流區塊鏈介紹。 blockchain.iethpay.com/blockchain_…

[3] 比特幣交易檢視。blockchain.info/zh-cn/tx/b6…

[4] 精通比特幣。book.8btc.com/books/1/mas…

[5] Bitcoin Wiki Script en.bitcoin.it/wiki/Script

[6] Bitcoin Wiki Transaction en.bitcoin.it/wiki/Transa…

[7] 比特幣線上校驗交易webbtc.com/script/cca7…

[8] 比特幣指令碼及交易分析 – 智慧合約雛形。learnblockchain.cn/2017/11/10/…

[9] 深入理解比特幣交易的指令碼。www.infoq.com/cn/articles…

[10] 關於UTXO的思考。 http://ethfans.org/posts/thoughts-on-utxo


相關文章