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

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

作者: 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