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

上文讲解了一笔交易中存在一个输入和一个输出的情况,一个输入和多个输出的情形与之处理方式一样,不再赘述。本文着重讲解多个输入的交易,如何完成签名。

以一个包含两个输入和两个输出的交易为例,其它更多输入和输出的交易实现,原理一致。

下面是根据交易数据结构,通过查询各自输入对应上一笔输出,找到各自的输出脚本后,完成全部填充后的一笔交易信息:

{

    "txid": "6f92259760fb24fc81f06cfe984c33d883724d655243824b755d763a2180609c",

    "hash": "6f92259760fb24fc81f06cfe984c33d883724d655243824b755d763a2180609c",

    "size": 185,

    "vsize": 185,

    "version": 1,

    "locktime": 0,

    "vin": [

        {

            "txid": "350216356afc5ddb2143786318f9ccbee97abbcc5c9f4cfadbbb4d5c8dc3ccd9",

            "vout": 0,

            "scriptSig": {

                "asm": "OP_DUP OP_HASH160 b2fd829c977a49044cd21e8762a99ce670800dbe OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914b2fd829c977a49044cd21e8762a99ce670800dbe88ac"

            },

            "sequence": 4294967295

        },

        {

            "txid": "dffdc8363aa6ddcaa7df62a8eeef635cc248b778da245e1d99c303148e1f5d24",

            "vout": 0,

            "scriptSig": {

                "asm": "OP_DUP OP_HASH160 c8e9a628b5d1e49020efc51153fab992213d96fa OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914c8e9a628b5d1e49020efc51153fab992213d96fa88ac"

            },

            "sequence": 4294967295

        }

    ],

    "vout": [

        {

            "value": 188638,

            "n": 0,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ad46f3b798adeb378f732a864ccf4516b8d02c6a OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1GoCu28SQu17FGEc4cv3of9ugwAcoPxGqE"

                ]

            }

        },

        {

            "value": 200000,

            "n": 1,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad23 OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1Ne7gN9gUUpDp3JWK32bZyRH8ixCyPJQJa"

                ]

            }

        }

    ]

}

如结构所示,总共两个输入,每个输入对应的上一个输出脚本也都填充好了,那么,签名的时候,都用这一份原始交易数据内容么?

1、理解的偏差

因为我最先实现的一对一交易,所以在构建多对多的交易数据时,我想当然认为,在对原始数据填充输入脚本这部分的操作应该这么做:

a、找到输入1的上一笔输出交易信息,从该信息中提取出属于自己的输出脚本,填充到本次交易输入1的脚本域中;

b、找到输入2的上一笔输出交易信息,从该信息中提取出属于自己的输出脚本,填充到本次交易输入2的脚本域中;

c、完成本次交易整个数据的赋值和填充后,形成一个原始交易数据;

d、将步骤c的原始交易数据用输入1对应的私钥进行签名,得到sign1,将其重新回填到输入1 的脚本域;

e、将步骤c的原始交易数据用输入2对应的私钥进行签名,得到sign2,将其重新回填到输入2的脚本域;

f、完成上述步骤后,得到真正可以广播出去的交易数据。

我按照以上思路做完签名后,发现数据广播出去失败,返回错误,提示该交易数据签名数据错误。

2、真正的原始交易数据

出现问题后上网搜索一遍,发现没有这方面的任何解答,好在公司能上外网,终于找到一个国外同行们的解答:

https://bitcoin.stackexchange.com/questions/41209/how-to-sign-a-transaction-with-multiple-inputs

通过阅读理解,再结合keepkey的firmware源码中该部分的实现,整理出来处理思路如下:

1、对于多个输入的交易签名,在构建原始交易数据时,本着用谁的私钥签名,就先填充谁的脚本域的原则,比如,现在要用输入1对应的私钥对这笔交易进行签名,那么在构建原始交易数据时,其它的输入中的脚本域不做填充,并且赋值script_len =0。

2、构建一个原始交易1,用私钥1来完成签名,得到sign1,原始交易1的数据结构如下:

0100000002d9ccc38d5c4dbbdbfa4c9f5cccbb7ae9beccf91863784321db5dfc6a35160235000000001976a914b2fd829c977a49044cd21e8762a99ce670800dbe88acffffffff245d1f8e1403c3991d5e24da78b748c25c63efeea862dfa7cadda63a36c8fddf0000000000ffffffff02dee00200000000001976a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac400d0300000000001976a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac0000000001000000

{

    "txid": "6f92259760fb24fc81f06cfe984c33d883724d655243824b755d763a2180609c",

    "hash": "6f92259760fb24fc81f06cfe984c33d883724d655243824b755d763a2180609c",

    "size": 185,

    "vsize": 185,

    "version": 1,

    "locktime": 0,

    "vin": [

        {

            "txid": "350216356afc5ddb2143786318f9ccbee97abbcc5c9f4cfadbbb4d5c8dc3ccd9",

            "vout": 0,

            "scriptSig": {

                "asm": "OP_DUP OP_HASH160 b2fd829c977a49044cd21e8762a99ce670800dbe OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914b2fd829c977a49044cd21e8762a99ce670800dbe88ac"

            },

            "sequence": 4294967295

        },

        {

            "txid": "dffdc8363aa6ddcaa7df62a8eeef635cc248b778da245e1d99c303148e1f5d24",

            "vout": 0,

            "scriptSig": {

                "asm": "",

                "hex": ""

            },

            "sequence": 4294967295

        }

    ],

    "vout": [

        {

            "value": 188638,

            "n": 0,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ad46f3b798adeb378f732a864ccf4516b8d02c6a OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1GoCu28SQu17FGEc4cv3of9ugwAcoPxGqE"

                ]

            }

        },

        {

            "value": 200000,

            "n": 1,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad23 OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1Ne7gN9gUUpDp3JWK32bZyRH8ixCyPJQJa"

                ]

            }

        }

    ]

}

得到的sign1如下:

473044022073d0210a320b3d6ce3088da58e9f31dd87fda550762b248b794172b3ccaac13902205da717b785a4219518cd3f5903d130886c2b8905c543abb389fbbafa41e90c300141043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994

3、在构建第二个原始交易2,用私钥2完成签名,得到sign2。原始交易1的数据结构如下:

0100000002d9ccc38d5c4dbbdbfa4c9f5cccbb7ae9beccf91863784321db5dfc6a351602350000000000ffffffff245d1f8e1403c3991d5e24da78b748c25c63efeea862dfa7cadda63a36c8fddf000000001976a914c8e9a628b5d1e49020efc51153fab992213d96fa88acffffffff02dee00200000000001976a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac400d0300000000001976a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac0000000001000000

{

    "txid": "55b61a575943ed9718989dabb4d8b5cdd90d3097d375f0354274894894f06ce5",

    "hash": "55b61a575943ed9718989dabb4d8b5cdd90d3097d375f0354274894894f06ce5",

    "size": 185,

    "vsize": 185,

    "version": 1,

    "locktime": 0,

    "vin": [

        {

            "txid": "350216356afc5ddb2143786318f9ccbee97abbcc5c9f4cfadbbb4d5c8dc3ccd9",

            "vout": 0,

            "scriptSig": {

                "asm": "",

                "hex": ""

            },

            "sequence": 4294967295

        },

        {

            "txid": "dffdc8363aa6ddcaa7df62a8eeef635cc248b778da245e1d99c303148e1f5d24",

            "vout": 0,

            "scriptSig": {

                "asm": "OP_DUP OP_HASH160 c8e9a628b5d1e49020efc51153fab992213d96fa OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914c8e9a628b5d1e49020efc51153fab992213d96fa88ac"

            },

            "sequence": 4294967295

        }

    ],

    "vout": [

        {

            "value": 188638,

            "n": 0,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ad46f3b798adeb378f732a864ccf4516b8d02c6a OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1GoCu28SQu17FGEc4cv3of9ugwAcoPxGqE"

                ]

            }

        },

        {

            "value": 200000,

            "n": 1,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad23 OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1Ne7gN9gUUpDp3JWK32bZyRH8ixCyPJQJa"

                ]

            }

        }

    ]

}

得到的sign2如下:

47304402207f179bbf1ba47beaa80f9916c587700e1ed5141f2476bd803c6ec3bc953c0d1a0220662fee1ed87879f8ef5cc6877068dea9906809f86e22f713a4e674986f0647b8014104e152cd7210e4c2a0791514ca2d7d75e0bf25c7763488ffe73694c7d10b21471fe6ccdada299c6ab5d61ea7c13f3c480516cc980cab0820d7f67dbcc1da2831d1

.........

n、完成所有的签名后,分别将sign1、sign2......分别重新回填到各自的输入脚本域中,更新各自的script_len值,最终形成真正能够广播的交易数据:

0100000002d9ccc38d5c4dbbdbfa4c9f5cccbb7ae9beccf91863784321db5dfc6a35160235000000008a473044022073d0210a320b3d6ce3088da58e9f31dd87fda550762b248b794172b3ccaac13902205da717b785a4219518cd3f5903d130886c2b8905c543abb389fbbafa41e90c300141043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994ffffffff245d1f8e1403c3991d5e24da78b748c25c63efeea862dfa7cadda63a36c8fddf000000008a47304402207f179bbf1ba47beaa80f9916c587700e1ed5141f2476bd803c6ec3bc953c0d1a0220662fee1ed87879f8ef5cc6877068dea9906809f86e22f713a4e674986f0647b8014104e152cd7210e4c2a0791514ca2d7d75e0bf25c7763488ffe73694c7d10b21471fe6ccdada299c6ab5d61ea7c13f3c480516cc980cab0820d7f67dbcc1da2831d1ffffffff02dee00200000000001976a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac400d0300000000001976a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac00000000

{

    "txid": "4ec1953b1e468b4f965b7eac307023ea801a5a75f0adef7387c500c06d2ae5ce",

    "hash": "4ec1953b1e468b4f965b7eac307023ea801a5a75f0adef7387c500c06d2ae5ce",

    "size": 436,

    "vsize": 436,

    "version": 1,

    "locktime": 0,

    "vin": [

        {

            "txid": "350216356afc5ddb2143786318f9ccbee97abbcc5c9f4cfadbbb4d5c8dc3ccd9",

            "vout": 0,

            "scriptSig": {

                "asm": "3044022073d0210a320b3d6ce3088da58e9f31dd87fda550762b248b794172b3ccaac13902205da717b785a4219518cd3f5903d130886c2b8905c543abb389fbbafa41e90c30[ALL] 043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994",

                "hex": "473044022073d0210a320b3d6ce3088da58e9f31dd87fda550762b248b794172b3ccaac13902205da717b785a4219518cd3f5903d130886c2b8905c543abb389fbbafa41e90c300141043d23e5f0758a53e2a18c8156051ca136d4639db5ceace580583983151113c1e5dcd7523f777fcd5b7ba16fef8dcbf4c2dbcaf91dd0c5d72080703517b96c4994"

            },

            "sequence": 4294967295

        },

        {

            "txid": "dffdc8363aa6ddcaa7df62a8eeef635cc248b778da245e1d99c303148e1f5d24",

            "vout": 0,

            "scriptSig": {

                "asm": "304402207f179bbf1ba47beaa80f9916c587700e1ed5141f2476bd803c6ec3bc953c0d1a0220662fee1ed87879f8ef5cc6877068dea9906809f86e22f713a4e674986f0647b8[ALL] 04e152cd7210e4c2a0791514ca2d7d75e0bf25c7763488ffe73694c7d10b21471fe6ccdada299c6ab5d61ea7c13f3c480516cc980cab0820d7f67dbcc1da2831d1",

                "hex": "47304402207f179bbf1ba47beaa80f9916c587700e1ed5141f2476bd803c6ec3bc953c0d1a0220662fee1ed87879f8ef5cc6877068dea9906809f86e22f713a4e674986f0647b8014104e152cd7210e4c2a0791514ca2d7d75e0bf25c7763488ffe73694c7d10b21471fe6ccdada299c6ab5d61ea7c13f3c480516cc980cab0820d7f67dbcc1da2831d1"

            },

            "sequence": 4294967295

        }

    ],

    "vout": [

        {

            "value": 188638,

            "n": 0,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ad46f3b798adeb378f732a864ccf4516b8d02c6a OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ad46f3b798adeb378f732a864ccf4516b8d02c6a88ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1GoCu28SQu17FGEc4cv3of9ugwAcoPxGqE"

                ]

            }

        },

        {

            "value": 200000,

            "n": 1,

            "scriptPubKey": {

                "asm": "OP_DUP OP_HASH160 ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad23 OP_EQUALVERIFY OP_CHECKSIG",

                "hex": "76a914ed5f9b6dce1fdcdb0c904b2b6928d5e25594ad2388ac",

                "reqSigs": 1,

                "type": "pubkeyhash",

                "addresses": [

                    "1Ne7gN9gUUpDp3JWK32bZyRH8ixCyPJQJa"

                ]

            }

        }

    ]

}


以上数据都是真正在BTC网络上实现交易的,请各位查阅。

如果你觉得这篇文档对你有帮助,别忘了打赏:

1HKQyLvLL4zCsbewjxdbV9WsCmqyaZYUUT

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,539评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,911评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,337评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,723评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,795评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,762评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,742评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,508评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,954评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,247评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,404评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,104评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,736评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,352评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,557评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,371评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,292评论 2 352

推荐阅读更多精彩内容