欢迎转载,但请注明出处!!
最近项目需要接触到了数字货币,然后需要弄明白比特币整个交易流程,在自行构建tx(transaction)数据的过程中,遇到一些问题,现在简明扼要地进行阐述和讲解。
注:以下的例子中假设都使用的P2PKH交易标准(pay-to-public-key-hash)
一、一个输入一个输出的交易构建与签名实现
比特币交易数据的结构如下:
standard BTC Tx struct defined below:
4byte version
1byte tx_in_count
?? tx_in
1byte tx_out_count
?? tx_out
4byte lock_time
具体每个成员的含义,请自行通过阅读bitcoin 协议说明的官方文档了解。
如果一个交易中只包含一个输入和一个输出,则构建一个交易的原始数据如下(已使用https://btc.com/tools/tx/decode完成解码显示):
{
"txid": "400b47d407b0e216c6e0d74df2387f52823e50b3d7a463ac6881806580134d0f",
"hash": "400b47d407b0e216c6e0d74df2387f52823e50b3d7a463ac6881806580134d0f",
"size": 110,
"vsize": 110,
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "a37938cb6e7b91dbc36f9e07bdd292b9bfc8a7034cb254e7e3c92075e0d3cfc9",
"vout": 0,
"scriptSig": {
"asm": "OP_DUP OP_HASH160 b2fd829c977a49044cd21e8762a99ce670800dbe OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914b2fd829c977a49044cd21e8762a99ce670800dbe88ac"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 98000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 762d0c29ad755dd850af43e6b99ef48f1ff680ab OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914762d0c29ad755dd850af43e6b99ef48f1ff680ab88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"1BmrhbLE6vdy1mSMTAnq1YDL3XCPLVu64t"
]
}
}
]
}
其对应的16进制串为:
0100000001c9cfd3e07520c9e3e754b24c03a7c8bfb992d2bd079e6fc3db917b6ecb3879a3000000001976a914b2fd829c977a49044cd21e8762a99ce670800dbe88acffffffff01d07e0100000000001976a914762d0c29ad755dd850af43e6b99ef48f1ff680ab88ac0000000001000000
这里插一句:一笔交易在广播到BTC网络之前,需要先进行签名处理,简而言之就是需要证明两个事情:
1、这笔交易中的输入,确实有钱存在,且大于等于输出的数额;
2、这笔交易中的输入,确实是你的(即你掌握了这笔交易输入所描述的那笔钱的私钥)
为了达成以上的证明,需要将自己的签名数据和公钥信息加入到交易的输入脚本中,一并广播出去,这样才能通过其它节点对这个交易合法性的检查,最终被写入区块。
签名的大致流程如下:
1、准备好一个原始的交易数据;
2、对这个原始的交易数据进行两次SHA256 hash运算,得到固定长度的hash散列;
3、使用椭圆曲线算法,结合你自己的私钥,对上述的hash散列值进行加密计算,得到签名数据;
重点是:如何准备好一个原始的交易数据???
解答:根据交易的数据结构,可以很轻易地填充好注入version、tx_in_num、tx_out_num、lock_time等数据,但是tx_in结构中本身就包含了script_len和signature_script这两个成员,在填充原始交易的时候,这两个成员也需要进行赋值填充:
以P2PKH交易类型为例,从上图,可看出signature_script中置入的数据:
OP_DUP OP_HASH160 b2fd829c977a49044cd21e8762a99ce670800dbe OP_EQUALVERIFY OP_CHECKSIG
这部分数据其实是你将要花费的这笔UTXO所在交易的输出脚本。说白了就是你发起的这笔交易中,你的输入必定能够在区块链中找到一条记录,那条记录里面描述了其他人给你支付了一笔钱。我们置入的这部分数据,就是从那条记录中取出的输出脚本。由于P2PKH交易的输出脚本格式固定,所以script_len也能轻易计算出长度,script_len = 25。
输入中的script_len和signature_script填充完成以后,就可以对这个原始的tx交易数据进行签名了,签名步骤如上所述,最后得到的签名数据如下:
4730440220195ee72370253823b08b155c78daba812549104e5b1b4a6c1fecf4364e2c1cca0220169b3c0c558eb9e61ca3a6ac816c0c251427573b3e147be62701a3208c2775090141043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994
将这部分数据重新置入到signature_script域中,根据这部分脚本的数据长度,重新对script_len 赋值,得到真正可以广播的交易数据如下(已使用https://btc.com/tools/tx/decode完成解码显示):
{
"txid": "31be8c8d939081f411e6e557c7bdc25e99ab9f777e680cd651b77660a828d607",
"hash": "31be8c8d939081f411e6e557c7bdc25e99ab9f777e680cd651b77660a828d607",
"size": 223,
"vsize": 223,
"version": 1,
"locktime": 0,
"vin": [
{
"txid": "a37938cb6e7b91dbc36f9e07bdd292b9bfc8a7034cb254e7e3c92075e0d3cfc9",
"vout": 0,
"scriptSig": {
"asm": "30440220195ee72370253823b08b155c78daba812549104e5b1b4a6c1fecf4364e2c1cca0220169b3c0c558eb9e61ca3a6ac816c0c251427573b3e147be62701a3208c277509[ALL] 043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994",
"hex": "4730440220195ee72370253823b08b155c78daba812549104e5b1b4a6c1fecf4364e2c1cca0220169b3c0c558eb9e61ca3a6ac816c0c251427573b3e147be62701a3208c2775090141043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994"
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 98000,
"n": 0,
"scriptPubKey": {
"asm": "OP_DUP OP_HASH160 762d0c29ad755dd850af43e6b99ef48f1ff680ab OP_EQUALVERIFY OP_CHECKSIG",
"hex": "76a914762d0c29ad755dd850af43e6b99ef48f1ff680ab88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"1BmrhbLE6vdy1mSMTAnq1YDL3XCPLVu64t"
]
}
}
]
}
真正的16进制数据串如下:
0100000001c9cfd3e07520c9e3e754b24c03a7c8bfb992d2bd079e6fc3db917b6ecb3879a3000000008a4730440220195ee72370253823b08b155c78daba812549104e5b1b4a6c1fecf4364e2c1cca0220169b3c0c558eb9e61ca3a6ac816c0c251427573b3e147be62701a3208c2775090141043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994ffffffff01d07e0100000000001976a914762d0c29ad755dd850af43e6b99ef48f1ff680ab88ac00000000
直接通过P2P方式或者使用网站API就能把这笔交易广播出去了。
多个输入的交易,比这个稍微复杂一下,待续。
如果你觉得这篇文档对你有帮助,别忘了打赏:
1HKQyLvLL4zCsbewjxdbV9WsCmqyaZYUUT