最近在研究比特币交易签名计算,网上没有完整介绍签名过程的例子。本文力图提供一个完整例子,详细介绍比特币签名的计算过程。
大小 字段名称 数据类型 描述
4字节 协议版本 uint32_t 明确这笔交易参照的规则协议的版本号
1-9字节 输入数量 var_int 被包含的输入交易的数量
不定 输入列表 tx_in[] 一个或多个输入交易构成的数组
1-9字节 输出数量 var_int 被包含的输出交易的数量
不定 输出列表 tx_out[] 一个或多个输出交易构成的数组
4字节 锁定时间 uint32_t 一个UNIX时间戳或区块号
其中tx_in 包括:
字段尺寸 |
描述 |
数据类型 |
说明 |
36 |
previous_output |
outpoint |
对前一输出的引用 |
1+ |
script length |
var_int |
signature script 的长度 |
? |
signature script |
uchar[] |
用于确认交易授权的计算脚本 |
4 |
sequence |
unit32_t |
Used for locktime or disabled(0xFFFFFFFF) |
OutPoint结构的构成:
字段尺寸 |
描述 |
数据类型 |
说明 |
32 |
hash |
char[32] |
引用的交易的散列 |
4 |
index |
uint32_t |
指定输出的索引,第一笔输出的索引是0,以此类推 |
字段尺寸 |
描述 |
数据类型 |
说明 |
8 |
value |
uint64_t |
交易的比特币数量(单位是0.00000001) |
1+ |
pk_script |
var_int |
pk_script的长度 |
? |
pk_script |
uchar[] |
Usually contains the public key as a Bitcoin script setting up conditions to claim this output |
将其他输入的pkscript长度调整为0,并末尾加上四字节小端序的sighash_type,并进行两次sha256:
在对这个hash进行签名计算,得出签名数据(签名时不用再计算hash,直接调用ecdsa-sign-digest)
使用electrum生成的未签名数据示例:
0100000001b37b9eefc3fa245f5ce36cb51c2d18a2d16e19d20867b23130e00f5280ccf82d010000002401ff210395cf5234e602954cba693138f3ba94c1cde7337675f5a94931e6226802d74d16fdffffff02002d3101000000001976a91425dc469afb4654d27742e3669bb3f5812268f2a188ac9ec2c901000000001976a9142dbbbd8bcff08a549be21efae747592049c9dc2d88ac71221300
签名后的数据:
0100000001b37b9eefc3fa245f5ce36cb51c2d18a2d16e19d20867b23130e00f5280ccf82d010000006a47304402202008714016f7e01c1a0010d7e6eb0b1f100b5a9b7c65a0506d62c1fbb9790cb102203daf6363c4039a739036ce152817f73d31319f060bbf5f354a0eeaf9f7ed3cd001210395cf5234e602954cba693138f3ba94c1cde7337675f5a94931e6226802d74d16fdffffff02002d3101000000001976a91425dc469afb4654d27742e3669bb3f5812268f2a188ac9ec2c901000000001976a9142dbbbd8bcff08a549be21efae747592049c9dc2d88ac71221300
交易记录:
https://www.blocktrail.com/tBTC/tx/8c6375e4509a186539dbbc2936feef7671f256969c917b633ec5db6b23c78ed1
计算过程:
协议版本:01000000
输入数量:01
输入列表:
b37b9eefc3fa245f5ce36cb51c2d18a2d16e19d20867b23130e00f5280ccf82d
(默认是大端,要去网上查询详情的话,用的是小端
2df8cc80520fe03031b26708d2196ed1a2182d1cb56ce35c5f24fac3ef9e7bb3)
OP_DUP(76) OP_HASH160(a9) 20字节数据(14)
2dbbbd8bcff08a549be21efae747592049c9dc2d OP_EQUALVERIFY (88)OP_CHECKSIG(ac)
1976a9142dbbbd8bcff08a549be21efae747592049c9dc2d88ac
输出数量:02
输出列表:
锁定时间:71221300
HashType :01000000(四字节)
两次hash值 (405c87d455f2f26e554c05b657769e2af253135367bcc69d4d772f873d39a23c)
进行2次sha256后,调用ecdsa_verify_digest计算签名,不需要在对2次sha256后的数据进行hash后再计算签名
签名值:r,s:
2008714016f7e01c1a0010d7e6eb0b1f100b5a9b7c65a0506d62c1fbb9790cb1
3daf6363c4039a739036ce152817f73d31319f060bbf5f354a0eeaf9f7ed3cd0
Pubk为0395cf5234e602954cba693138f3ba94c1cde7337675f5a94931e6226802d74d16