1. 程式人生 > >比特幣交易簽名(真)

比特幣交易簽名(真)

本文介紹比特幣的交易簽名和UTXO

比特幣和以太坊最大的區別是比特幣發起交易是基於UTXO(Unspent Transaction Output)

說utxo大家可能聽不懂,但是我們來親自籤一筆交易就會明白了

首先需要依賴包

const bitcoin = require('bitcoinjs-lib');

要簽名首先我們需要獲得一個賬戶的UTXO,也就是至少一筆的未被花費的交易支票,我們可以使用介面來獲得這樣的支票

https://blockchain.info/unspent?active=你的地址

{
    
    "unspent_outputs":[
    
        {
            "tx_hash":"23bfcc8d8f14e792946ebfeda4f8608b1b96e1efaae8c18ca0b5fab1a362c5c0",
            "tx_hash_big_endian":"c0c562a3b1fab5a08cc1e8aaefe1961b8b60f8a4edbf6e9492e7148f8dccbf23",
            "tx_index":56365906,
            "tx_output_n": 1,
            "script":"76a914d6c492056f3f99692b56967a42b8ad44ce76b67a88ac",
            "value": 890000,
            "value_hex": "0d9490",
            "confirmations":231264
        }
      
    ]
}

這裡是一個UTXO,裡面有890000的satoshi,記載著tx_hash(交易hash值)和value(交易包含的比特幣)

簽名首先需要知道的是每一筆支票被交易時都會花完支票中的所有的比特幣,意思是說除了這筆支票的轉出金額,剩下的比特幣都將被當做礦工費,所以我們需要在交易中寫好找零地址,也就是轉出地址應當包括轉出目標地址和自己的一個地址作為找零地址

簽名程式碼可以參考官網示例

        set = bitcoin.ECPair.fromWIF(privatekey);//匯入私鑰用於簽名
	txb = new bitcoin.TransactionBuilder();//初始化交易物件
	amount+=1e4;//消費金額是轉出金額加上10000的礦工費
	txb.setVersion(1);//設定交易版本號
	var tot=0;//用於記錄UTXO總量
	for(var i=0;i<tx.length;i++){//將UTXO的相關資訊依次填入交易體中
		txb.addInput(tx[i].tx_hash_big_endian, tx[i].tx_output_n);
		tot+=tx[i].value;
	}
	
	txb.addOutput(toaddress, amount-1e4);//填入轉出目標地址和對應的金額
	txb.addOutput(from, tot-amount); //填入找零地址,也就是原地址,並填入把找零金額
	for(var i=0;i<tx.length;i++){//對交易體中的UTXO依次簽名
		txb.sign(i, set);
	}

	console.log(txb.buildIncomplete().toHex());//得到最終交易序列

最終可以得到,需要注意的是填入UTXO作為input時應該填入的是tx_hash_big_endian引數,而不是大家以為的tx_hash(這絕對是個坑)

像這樣的序列

你可以通過這個網站驗證交易序列是否正確,還可以通過介面來發送交易,傳送成功後會返回

當這樣的一筆交易被髮出之後,將會為找零地址和轉出地址產生新的UTXO,從這裡我們可以看出,從比特幣的第一筆UTXO開始,伴隨著不斷地交易,會分成多個UTXO,而交易則改變了它們的所有權。