Bitcoin Cash 交易构造与签名

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjj67868236_2/article/details/88883750

Bitcoin Cash 交易构造与签名

bitcoincash:qqe0dlh5u0mx7zctmrxeezh359zgtfszauhuyfes60

 

By 挖煤矿工 2018-09-03

 

BitcoinCash与旧的Bitcoin的交易签名不同,采用了类似Bitcoin SW的 BIP143协议,但是没有SW功能。

旧的Bitcoin的交易签名与构造详解:https://klmoney.wordpress.com/bitcoin-dissecting-transactions-part-2-building-a-transaction-by-hand/

BIP143协议:https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki

BitcoinCash的交易签名方式:https://github.com/Bitcoin-ABC/bitcoin-abc/blob/master/doc/abc/replay-protected-sighash.md

 

如果你从来没有做过BTC的签名,也没弄过SW,那么恭喜你,和我一样,上面的资料不用看了,下面我会手把手的教你如果购造一个BitcoinCash的最常用的P2PKH(Pay-to-Public-Key-Hash)交易,并签名。

 

你要对UTXO有一定的了解,才能看懂BCH的交易结构。

 

对txid为e1583427ce0b2ad9e4adc1621aada387f5d7b7fc105d7f0ea3d5d1339714cc88的交易进行分析,

https://bch.btc.com/e1583427ce0b2ad9e4adc1621aada387f5d7b7fc105d7f0ea3d5d1339714cc88

这个交易是从地址qzv8nyncjruxvwvq92zes6amtuj6cxrfp5creydtnm转出0.00027317个bch,转给自已(找零)0.00022090个,转给地址qz88qqxctlqkppds353wpx92ajxpc8x4lccgpz7lmf 为0.00005000个,矿工费花了0.00000227个BCH。

 

看一下这个交易的原始交易数据:

 

0100000001892f8ddd7b54bb79278a3859ba4474a68eb28956d549e09aa5e121423e0c5cb6000000006b483045022100fac3c23687a75f23038d104a8545932db9815afdb6436daf2f52507a3a62da58022020ec3941165cfb6c054efd9f4cac757adab9d8c378953ed621d118106a1779c34121023839c718238a1795a12aa2f7af43816a7ca51dee1b45576d6c81bb7eed710f19ffffffff024a560000000000001976a9149879927890f86639802a85986bbb5f25ac18690d88ac88130000000000001976a9148e7000d85fc16085b08d22e098aaec8c1c1cd5fe88ac00000000

 

看不懂?不要紧,把数据粘到这里解码一下:https://bch.btc.com/tools/tx/decode

这是一个典型的交易,有一个input和两个output的交易,其中一个output转帐到原地址(找零)。

用解析工具解析的内部,可以看个大概含义了,但是对于每一个数据的具体含义,要手工分析。

 

BCH的交易结构和BTC相同,但是签名数据的计算方式不同

下面,我们对这些数据手工分析

 

 

数据含义

长度

数据

 

 

【1】版本号

4byte

01000000

输入

 

【2】输入数量

1byte

01

 

【3】输入txid的反序

32byte

892f8ddd7b54bb79278a3859ba4474a68eb28956d549e09aa5e121423e0c5cb6

 

【4】输入tx的序号,LE小端编码

4byte

00000000

解锁脚本

(包括签名和公钥)

【5】脚本长度

1byte

6b

【6】签名长度

1byte

48

【7】签名数据

根据定义

3045022100fac3c23687a75f23038d104a8545932db9815afdb6436daf2f52507a3a62da58022020ec3941165cfb6c054efd9f4cac757adab9d8c378953ed621d118106a1779c3

【8】SigHash Code

1byte

41

【9】公钥长度

1byte

21

【10】公钥

根据定义

023839c718238a1795a12aa2f7af43816a7ca51dee1b45576d6c81bb7eed710f19

 

【11】序号

ffffffff表示没有序号

4byte

ffffffff

 

 

【12】输出数量

1byte

02

输出0

 

【13】转帐金额(单位为聪,LE小端编码)

8byte

4a56000000000000

锁定脚本

【14】锁定脚本长度

1byte

19

【15】OP_DUP

1byte

76

【16】OP_HASH160

1byte

a9

【17】公钥hash长度

1byte

14

【18】公钥hash

根据定义

9879927890f86639802a85986bbb5f25ac18690d

【19】OP_EQUALVERIFY

1byte

88

【20】OP_CHECKSIG

1byte

ac

输出1

 

转帐金额(单位为聪,LE小端编码)

8byte

8813000000000000

锁定脚本

锁定脚本长度

1byte

19

OP_DUP

1byte

76

OP_HASH160

1byte

a9

公钥hash长度

1byte

14

公钥hash

 

8e7000d85fc16085b08d22e098aaec8c1c1cd5fe

OP_EQUALVERIFY

1byte

88

OP_CHECKSIG

1byte

ac

 

 

【21】锁定时间

4byte

00000000

 

 

详细讲解每一项数据的来源

  1. 版本号

在BCH中,版本号是01000000,但是有些交易是02000000,暂时不知道差异。

  1. 输入数量

这里的每一个输入是一个UTXO,即使是同一个地址,也会存在多个UTXO作为输入。

  1. 输入txid的反序

这里指的是一个UTXO的ID,然后把数据高低换位。在2018-8-31 12:00 UTC 8+的时间,可以查到地址qzv8nyncjruxvwvq92zes6amtuj6cxrfp5creydtnm有一条UTXO,交易ID为b65c0c3e4221e1a59ae049d55689b28ea67444ba59388a2779bb547bdd8d2f89,把这个交易ID反序,就可以得到892f8ddd7b54bb79278a3859ba4474a68eb28956d549e09aa5e121423e0c5cb6。

  1. 输入tx的序号

同上,找到的UTXO为b65c0c3e4221e1a59ae049d55689b28ea67444ba59388a2779bb547bdd8d2f89,这条交易有两个输出,第一条(序号0)为转帐到qzv8nyncjruxvwvq92zes6amtuj6cxrfp5creydtnm的输出,第二条(序号1)是op_return。我们需要的序号是0,编码长度为4byte,LE小端编码,得到结果00000000。

  1. 脚本长度

这里的脚本长度,指的是解锁脚本的长度,包括两部分,一部分是签名,一部分是公钥,要把这两部分的长度加起来。

  1. 签名长度

签名数据的长度,这里的48是16进制,表示签名数据有72个byte。

  1. 签名数据

这一部分很复杂,放在后面详细讲解

  1. SigHash Code

这个可以认为是签名的类型。当前例子是P2PKH交易,BTC使用SIGHASH_ALL(0x01),BCH需要与SIGHASH_FORKID(0x40)做逻辑或运算,结果是0x41。

  1. 公钥长度

公钥的长度,现在使用的是压缩公钥,长度33(0x21)。

  1. 公钥

现在使用的是压缩公钥,只包括椭圆曲线Q点的X坐标,数据前补02(y为偶数)或03(y为奇数)。

  1. 序号

ffffffff表示没有序号,这里不使用这个功能。

  1. 输出数量

这个例子中有两个输出。如果带有op_return,也算是一个输出。

  1. 转帐金额

单位为聪,LE小端编码。转帐到这人地址的数量为22090聪,转化为16进制是564a,使用小端编码为8byte,结果是4a56000000000000

  1. 锁定脚本长度

包括几个操作码和公钥hash的长度。

此例子是P2PKH(支付到公钥地址模式),它的格式为:

OP_DUP(0x76)  OP_HASH160(0xa9) 公钥hash长度(0x14) [一个20字节的公钥hash]  OP_EQUALVERIFY(0x88) OP_CHECKSIG(0xac)

  1. OP_DUP
  2. OP_HASH160
  3. 公钥hash长度

固定长度20 byte(0x14)

  1. 公钥hash

公钥hash是由地址反向得到的。使用Base58Check 由base58编码的地址转化为byte数组。

  1. OP_EQUALVERIFY
  2. OP_CHECKSIG
  3. 锁定时间

当前值为00000000,表示立即生效。

< 500000000     含义为Block高度,处于该Block之前为锁定(不生效)

>= 500000000   含义为Unix时间戳,处于该时刻之前为锁定(不生效)。

 

 

下面开始讲第【7】条的签名部分

签名的数据是怎么来的?

原始签名数据---->两次SHA256---->ECDSA签名---->得到签名结果

签名需要私钥的,如果有多个输入,需要多个签名

原始签名数据的构成,包括下面10部分。

 

  1. nVersion of the transaction (4-byte little endian)

版本号为01000000,和交易结构中的保持一致

  1. hashPrevouts (32-byte hash)

输入的txid(反序),输入的序号(这里的序号是本次交易输入的序号,不是utxo中的序列),如果有多个输入,要把所有输入连接起来,组合以后进行两次SHA256运算。

输入0的txid(反序)32位

输入0的序号是00000000

输入1的txid(反序)32位

输入1的序号是01000000

……

……

把上面结构的数据连接起来:

【输入0的txid(反序)32位】----【输入0的序号是00000000】----【输入1的txid(反序)32位】----【输入1的序号是01000000】----【……】----【……】

然后做两次SHA256计算。

例子中只有一个输入,txid是b65c0c3e4221e1a59ae049d55689b28ea67444ba59388a2779bb547bdd8d2f89,序号是0,序号用4byte LE小端编码后是00000000。

组合后是892f8ddd7b54bb79278a3859ba4474a68eb28956d549e09aa5e121423e0c5cb600000000,两次SHA256后是1c68be60806e8f79ca8eba088575466de68f7e052bb8b701780c40a633b4dd15

  1. hashSequence (32-byte hash)

输入序列(这里的序列指得是utxo中的序列),如果有多个输入,把多个输入的序列连接,再做两次SHA256。

例子中只有一个输入,它的序列是0,用4byte小端编码后是00000000,两次SHA256后是3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044

  1. outpoint (32-byte hash + 4-byte little endian)

这里包括两部分。第一部分是当前输入(如果有两个输入,需要进行两次签名)的txid(反序),第二部分是当前输入在utxo中的序列,4byte LE小端编码。

例子中这两部分的数据分别是892f8ddd7b54bb79278a3859ba4474a68eb28956d549e09aa5e121423e0c5cb6和00000000

  1. scriptCode of the input (serialized as scripts inside CTxOuts)

当前输入的锁定脚本。和交易结构中的【14】至【20】结构相同,交易结构中指的是输出的锁定脚本,这里指的是输入的锁定脚本。因为例子中的第一个输出是找零到原来的输入,所以数据是相同的。

例子中的输入锁定脚本是1976a9149879927890f86639802a85986bbb5f25ac18690d88ac

 

 

  1. value of the output spent by this input (8-byte little endian)

当前输入的币数,单位是聪,8byte LE小端编码格式。

例子中的币数是27317聪,编码后是b56a000000000000

 

  1. nSequence of the input (4-byte little endian)

当前输入的序列。

此例子是P2PKH交易,使用ffffffff表示没有序号。

  1. hashOutputs (32-byte hash)

交易输出的哈希。输出金额(单位聪,8byte LE小端编码格式),输出锁定脚本长度(1byte),输出锁定脚本(结构参照交易结构【14】-【20】)。如果有多个输出,要把所有的输出数据连接起来,最后做两次SHA256。

输出0的金额

输出0的锁定脚本长度

输出0的锁定脚本

输出1的金额

输出1的锁定脚本长度

输出1的锁定脚本

……

……

……

例子中有两个输出,输出0的金额是22090,编码后是4a56000000000000,长度是0x19,锁定脚本是76a9149879927890f86639802a85986bbb5f25ac18690d88ac

输出1的金额是5000,编码后是8813000000000000,长度是0x19,锁定脚本是76a9148e7000d85fc16085b08d22e098aaec8c1c1cd5fe88ac

这部分数据连接起来是:

4a560000000000001976a9149879927890f86639802a85986bbb5f25ac18690d88ac88130000000000001976a9148e7000d85fc16085b08d22e098aaec8c1c1cd5fe88ac

做两次SHA256的结果是:7314809dcfc7f52e42fdaaf898e22f85813d92cb39c240f972e005c86e23f1b6

  1. nLocktime of the transaction (4-byte little endian)

锁定时间,当前值为00000000,表示立即生效。

< 500000000   含义为Block高度,处于该Block之前为锁定(不生效)

>= 500000000 含义为Unix时间戳,处于该时刻之前为锁定(不生效)。

 

  1. sighash type of the signature (4-byte little endian)

当前例子是P2PKH交易,BTC使用SIGHASH_ALL(0x01),BCH需要与SIGHASH_FORKID(0x40)做逻辑或运算,结果是0x41。转化为4byte LE小端编码格式,结果是41000000

 

 

 

 

把上面10条数据全部连接在一起:

010000001c68be60806e8f79ca8eba088575466de68f7e052bb8b701780c40a633b4dd153bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044892f8ddd7b54bb79278a3859ba4474a68eb28956d549e09aa5e121423e0c5cb6000000001976a9149879927890f86639802a85986bbb5f25ac18690d88acb56a000000000000ffffffff7314809dcfc7f52e42fdaaf898e22f85813d92cb39c240f972e005c86e23f1b60000000041000000

两次SHA256

287ebc95c349b791885797ede0c1aa865f1cdc95140179c2d83b7c308d201cb2

进行ECDSA签名,需要私钥,私钥为KyFj2LMgn54ByvzCWoPgPYK7XTBV7PywskiexBoJceziLy3V1UnR,

签名后的数据是:3045022100fac3c23687a75f23038d104a8545932db9815afdb6436daf2f52507a3a62da58022020ec3941165cfb6c054efd9f4cac757adab9d8c378953ed621d118106a1779c3

把这个签名后的数据填充到交易结构中,就可以广播出去了。

猜你喜欢

转载自blog.csdn.net/zjj67868236_2/article/details/88883750