UTXO
Bitcoin 采用了 UTXO 模型作為其底層存盤的資料結構,其全稱為 Unspent Transaction output,也就是未被使用的交易輸出,
- 位元幣客戶端會在每次接收到新block時更新會所有未花掉的output,檢查一個交易是否合法只需要看這個交易的所有input是否在這個未花費的output表中
- 輸出存在已使用和未使用兩個狀態,BTC賬本歷史并不記錄某個地址對應的BTC余額,地址的總余額是某一時刻與它關聯的所有未使用輸出的BTC數額之和,**所有未使用的交易輸出(Unspent Transaction Outputs,UTXO)就構成了BTC這個區塊鏈網路的一個狀態,**網路中的(全功能)節點各自維護一個狀態的副本,并在某一時刻就系統的狀態達成最終一致,
- 一個輸入同樣也是一個串列,包含對之前一個未使用輸出的參考,以及能夠證明交易創建者滿足該輸出使用條件的有效簽名,即證明交易創建者對他參考的未使用輸出中BTC的使用權,被參考的輸出會從UTXO中洗掉,一筆交易還要滿足以下條件:輸出所包含的總金額應小于等于輸入所包含的總金額,這時輸入與輸出的差額作為交易費作為激勵費用獎勵給記賬的節點,滿足以上輸入與輸出的交易被看作是“合法的”,
- 當一個地址要發布一筆交易時,它所做的其實是向BTC整個網路中的節點廣播該條交易,該條交易會被標記為“未確認的”(Unconfirmed),BTC網路并不是收到一條廣播就立刻更新系統的狀態,而是有區塊以及記憶體池的設計,
在某一個時刻,所有BTC節點都維護著一個記錄UTXO的賬本,并有一個接收未確認交易的記憶體池(Mempool),當收到一條交易廣播時,節點就會把該交易加入自己的記憶體池,
腳本
- 鎖定腳本是放置在輸出上的花費條件:它指定將來要花費輸出必須滿足的條件. scriptPubKey: 通常包含公鑰或位元幣地址(公鑰的哈希)
- 解鎖腳本是可以“解決”或滿足鎖定腳本放置到輸出上的條件,從而花費輸出的腳本.大多數情況下,它們包含用戶錢包利用私鑰生成的數字簽名. scriptSig:
- 每個位元幣驗證節點通過一起執行鎖定和解鎖腳本來驗證交易.只有正確滿足輸出條件的有效交易才會導致輸出被視為“已花費”并從未使用的交易輸出集和(UTXO集)中移除,
- 首先,使用堆疊執行引擎執行解鎖腳本,如果解鎖腳本沒有錯誤地執行(例如,它沒有遺留的“懸掛(dangling)”運算子),則復制主堆疊并執行鎖定腳本,如果使用從解鎖腳本復制的堆疊資料執行鎖定腳本的結果為“TRUE”,則解鎖腳本已成功解決由鎖定腳本施加的條件,證明該輸入是用于花費UTXO的有效授權,如果在執行組合腳本后仍然存在除“TRUE”之外的結果,則輸入無效,因為它未能滿足放置在UTXO上的消費條件,
- 請注意,交易的每個輸入都是獨立簽署的,這是至關重要的,因為簽名和輸入都不必屬于同一個“所有者”或被其使用,事實上,一個名為“CoinJoin”的特定交易方案利用這一事實來創建隱私的多方交易,
- 多方可以協作構建交易并各自簽署一個輸入,
創建數字簽名
在位元幣的ECDSA演算法實作中,被簽名的“訊息”是交易,或者更準確地說是交易中特定資料子集的哈希(參見下文 簽名哈希的型別 (SIGHASH),簽名密鑰是用戶的私鑰,結果是如下簽名:
((Sig = F_{sig}(F_{hash}(m), dA)))
其中:
-
dA 是簽名私鑰
-
m 是交易(或交易的一部分)
-
F__hash 是哈希函式
-
F__sig 是簽名演算法
-
Sig 是簽名結果
生成簽名 Sig ,由兩部分組成: R 和 S: Sig = (R, S) , 再使用DER 的國際標準編碼方案序列化為位元組流,
簽名的序列化 (DER)
R 和 S 的序列化位元組流
序列化格式由以下九個元素組成:
-
0x30 —— 標識 DER 序列的開始
-
0x45 —— 序列長度 (69 bytes)
-
0x02 —— 接下來是一個整數
-
0x21 —— 整數的長度 (33 bytes)
-
R —— 00884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb
-
0x02 —— 接下來是另一個整數
-
0x20 —— 另一個整數的長度 (32 bytes)
-
S —— 4b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813
-
一個后綴 (0x01) 標識使用的哈希型別 (SIGHASH_ALL)
驗證簽名

簽名驗證演算法采用訊息(交易或其部分資料的散列),簽名者的公鑰和簽名( R 和 S 值),如果簽名對此訊息和公鑰有效,則回傳TRUE,
簽名哈希的型別 (SIGHASH)
有三種 SIGHASH 標志: ALL, NONE, 和 SINGLE
| SIGHASH flag | Value | Description |
|---|---|---|
| ALL | 0x01 | 簽名應用于所有輸入和輸出, |
| NONE | 0x02 | 簽名應用于所有輸入,不包括任何輸出 |
| SINGLE | 0x03 | 簽名應用于所有輸入,但僅應用于與簽名輸入具有相同索引編號的一個輸出 |
BTC Transaction RAW
{
"version": 1,
"locktime": 0,
"vin": [
{
//一個交易ID,參考包含正在使用的UTXO的交易
"txid":"7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
//一個輸出索引(vout),用于標識來自該交易的哪個UTXO被參考(第一個為零)
"vout": 0,
//一個 scriptSig(解鎖腳本),滿足放置在UTXO上的條件,解鎖它用于支出
//大多數情況下,解鎖腳本是一個證明位元幣所有權的數字簽名和公鑰,但是并不是所有的解鎖腳本都包含簽名
"scriptSig": "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
//一個序列號
"sequence": 4294967295
}
],
"vout": [
{
//位元幣數額,最小單位為 聰 satoshis
"value": 0.01500000,
//定義了花費這些輸出所需條件的scriptPubKey
"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"
},
{
"value": 0.08450000,
"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
}
]
}
資料結構定義
class CTransaction
{
const std::vector<CTxIn> vin;
const std::vector<CTxOut> vout;
//const int32_t nVersion;
//const uint32_t nLockTime;
}
class CTxIn
{
COutPoint prevout; //來自哪一筆交易的輸出
CScript scriptSig; //簽名
uint32_t nSequence;//用于鎖定時間(locktime)或禁用 (0xFFFFFFFF)
}
class CTxOut
{
CAmount nValue; //余額
CScript scriptPubKey; //持有當前輸出的公鑰
}
//--------------------------------------------------------------
class COutPoint
{
uint256 hash; //參考的交易id
uint32_t n; //第幾條輸出
}
//Serialized script
typedef prevector<28, unsigned char> CScriptBase;
class CScript : public CScriptBase
{}
typedef int64_t CAmount;
序列化
交易序列化 —— 輸出
| Size | Field | Description |
|---|---|---|
| 8 位元組 (小端序) | 數量 Amount | 以聰(satoshis = 10-8 bitcoin) 為單位的位元幣價值 |
| 1——9 位元組 (VarInt) | 鎖定腳本的大小 Locking-Script Size | 后面的鎖定腳本的位元組數 |
| 變數 | 鎖定腳本 Locking-Script | 定義花費該輸出的條件的腳本 |
交易序列化 —— 輸入
| Size | Field | Description |
|---|---|---|
| 32 位元組 | 交易的哈希值 Transaction Hash | 指向包含要花費的UTXO的交易的指標 |
| 4 位元組 | 輸出的索引 Output Index | 要花費的UTXO的索引,從0開始 |
| 1——9 位元組 (VarInt) | 解鎖腳本的大小 Unlocking-Script Size | 后面的解鎖腳本的位元組長度 |
| 變數 | 解鎖腳本 Unlocking-Script | 滿足UTXO鎖定腳本條件的腳本 |
| 4 位元組 | 序列號 Sequence Number | 用于鎖定時間(locktime)或禁用 (0xFFFFFFFF) |
手續費
在每一筆合法的交易中,所有的輸入的 value 之和必須大于所有輸出的 value 之和,這兩者之間的差值就是礦工費:
sum(inputs.value) = sum(outputs.value) + fee
- 交易費用是以交易資料的大小(KB)計算的,而不是位元幣交易的價值,
- 在Bitcoin Core中,收費中繼策略由 minrelaytxfee 選項設定,當前的默認值是每KB資料0.00001位元幣或0.01毫位元幣,因此,默認情況下,低于0.00001位元幣的交易將被視為免費,并且只在記憶體池有空間時才會被中轉;否則,它們將被丟棄,位元幣節點可以通過調整 minrelaytxfee 的值來覆寫默認的收費中繼策略,
- 費用估算的API介面
curl https://bitcoinfees.earn.com/api/v1/fees/recommended
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/248655.html
標籤:區塊鏈
