美文网首页
比特币多个输入交易数据的签名实现

比特币多个输入交易数据的签名实现

作者: david_hmy | 来源:发表于2018-08-09 16:04 被阅读0次

欢迎转载,但请注明出处!!

    最近项目需要接触到了数字货币,然后需要弄明白比特币整个交易流程,在自行构建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

相关文章

网友评论

      本文标题:比特币多个输入交易数据的签名实现

      本文链接:https://www.haomeiwen.com/subject/dtqcbftx.html