深入浅出,一文读懂如何构造一笔比特币交易
摘要:比特币,作为第一个成功的加密货币,其核心魅力之一在于其去中心化的交易系统,每一笔比特币的转移,都通过一种被称为“交易”的特殊数据结构在比特币网络上广播和验证,理解如何构造一笔比特币交易,是深入理解比特...
比特币,作为第一个成功的加密货币,其核心魅力之一在于其去中心化的交易系统,每一笔比特币的转移,都通过一种被称为“交易”的特殊数据结构在比特币网络上广播和验证,理解如何构造一笔比特币交易,是深入理解比特币工作原理的关键一步,本文将从交易的基本组成入手,逐步拆解构造一笔完整交易的详细过程。
比特币交易的基本构成要素
在动手构造交易之前,我们首先需要了解其核心组成部分,一笔比特币交易本质上是一组数据,包含以下关键信息:
-
输入:指明了交易花费的资金来源,每个输入都引用了之前一笔未花费的交易输出,通常包含:
- 交易ID:被引用的前一笔交易的哈希值,像一个“账单号”。
- 输出索引:在前一笔交易中,具体是哪个输出被花费。
- 解锁脚本:也称为“脚本签名”,这是一段脚本,用于证明花费这笔资金的人拥有其所有权,最常见的形式是
Sigature + PubKey(签名 + 公钥)。
-
输出:指明了交易资金的最终去向,每个输出都包含:
- 金额:要转账的比特币数量(以聪为单位,1 BTC = 100,000,000 聪)。
- 锁定脚本:也称为“脚本公钥”,这是一段脚本,规定了未来谁能花费这笔资金,最常见的形式是
OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG,其含义是“谁能提供与该公钥哈希匹配的签名和公钥,谁就能花费这笔钱”。
-
版本号:交易格式版本,用于未来的升级。
-
锁定时间:一个可选字段,规定了该交易最早何时可以被矿工打包进区块,可以是区块高度或一个具体的时间戳。
构造比特币交易的详细步骤
构造一笔比特币交易,就像填写一张复杂的支票,需要精确地填写每一项,整个过程可以分为以下几个核心步骤:
第一步:确定交易目标(花费多少,发给谁)
这是交易的起点,你需要明确两件事:
- 总输出金额:你想转给接收方的总金额是多少?你想转出 1.2 BTC。
- 找零地址:由于比特币的UTXO模型,你不能只花掉一部分UTXO,如果你引用的一个UTXO价值是2 BTC,而你只想花掉1.2 BTC,那么多出来的0.8 BTC必须返回给你自己,这个返回的地址就是“找零地址”。
第二步:选择合适的UTXO作为输入
这是构造交易中最关键也最复杂的一步,你的比特币并不存储在“账户”里,而是由一个个未花费的交易输出组成的集合,这个集合被称为UTXO集。
- 什么是UTXO? 它是“未花费的交易输出”的缩写,可以理解为比特币网络上的“原子化硬币”,每个UTXO都有固定的面值(0.5 BTC, 1 BTC, 2 BTC)。
- 如何选择UTXO?
- 列出所有可用的UTXO:通过查询你的钱包,获取所有属于你地址的UTXO列表。
- 组合凑额:你需要从这些UTXO中选择一个或多个组合,使其总额大于等于你的总输出金额 + 交易费。
- 示例:你想转出1.2 BTC,并预留0.001 BTC作为交易费,你需要凑够至少1.201 BTC。
- 策略:你可以选择一个面值为1.5 BTC的UTXO(花费掉1.201 BTC,找零0.299 BTC),或者选择两个面值为0.6 BTC和0.7 BTC的UTXO(凑够1.3 BTC,花费1.201 BTC,找零0.099 BTC),选择哪个组合取决于矿工费和隐私策略。
第三步:计算交易费
交易费是矿工打包你的交易所获得的报酬,也是激励网络安全运行的关键。
- 交易费 = 输入UTXO总额 - 输出总额
- 如何估算? 交易费的大小通常与交易的大小(字节)和网络的拥堵程度成正比。
- 交易大小:交易中的输入和输出越多,交易数据就越大,费用也越高,一个标准P2PKH(Pay-to-Public-Key-Hash)输入大约占用148字节,一个输出大约占用34字节。
- 费率:通常以“聪/字节”为单位,你可以通过比特币浏览器或钱包查看当前网络的建议费率,费率为10聪/字节,一笔包含2个输入和2个输出的交易大小约为 (1482) + (342) = 364字节,那么交易费就是 364 * 10 = 3640聪 = 0.0000364 BTC。
第四步:构建交易数据结构
我们可以开始将所有信息组织成标准的交易格式了,这通常遵循“序列化”规则,将各种数据类型打包成字节流。
- 版本号:写入一个4字节的整数,
0x01000000(对应版本1)。 - 输入数量:写入一个变长整数,表示你选择了多少个UTXO作为输入。
- 循环遍历每个输入:
- 前一笔交易哈希:写入被引用UTXO的原始交易ID(小端序)。
- 输出索引:写入一个4字节整数,表示被引用UTXO在原交易中的位置。
- 解锁脚本长度:写入一个变长整数,表示接下来解锁脚本的字节长度。
- 解锁脚本:写入脚本内容(
签名 + 公钥)。 - 序列号:写入一个4字节整数,用于替代交易功能,通常设为
0xffffffff。
- 输出数量:写入一个变长整数,表示你有几个接收方(包括找零)。
- 循环遍历每个输出:
- 金额:写入一个8字节整数,表示输出的聪数(小端序)。
- 锁定脚本长度:写入一个变长整数。
- 锁定脚本:写入脚本内容(例如接收方的公钥哈希脚本)。
- 锁定时间:写入一个4字节整数,设为0表示立即生效。
第五步:签名交易(创建解锁脚本)
这是安全的核心,在上一步中,解锁脚本我们留空了,我们需要用我们的私钥来签名,以证明我们有权花费这些UTXO。
这个过程被称为“签名哈希”(Signature Hashing):
- 创建签名哈希:比特币协议会对交易数据(除了签名本身)进行哈希,生成一个“待签名的消息”,这个消息的内容取决于你想要签名的输入,为了安全,它会包含所有输入和输出信息。
- 使用私钥签名:用你的私钥对上一步生成的签名哈希进行加密签名(通常使用ECDSA算法),生成一个数字签名。
- 填充解锁脚本:将生成的
签名和你的公钥按照约定的顺序(通常是签名 + 公钥)填充到对应UTXO输入的解锁脚本中。
注意:一笔交易中的每个输入都可以由不同的私钥签名,因此构造多签交易时,需要为每个输入分别执行签名过程。
第六步:广播交易
最后一步,将构造完成并签名的原始交易数据(字节流)通过比特币节点广播到整个网络。
- 验证:网络中的每个节点都会验证这笔交易:
- 语法是否正确。
- 每个输入引用的UTXO是否存在且未被花费。
- 每个输入的解锁脚本是否能成功执行其对应的锁定脚本(即验证签名是否有效)。
- 输入总额是否大于等于输出总额。
- 入块:验证通过的交易会被放入内存池,等待矿工将其打包进一个新的区块,至此,交易才算最终确认。
一个简单的例子
假设Alice要向Bob发送0.1 BTC。
- 目标:输出1个给Bob的0.1 BTC,需要一个找零输出给自己。
- 选择UTXO:Alice找到一个属于自己的UTXO,价值为0.15 BTC。
- 计算费用:她估算交易费为0.005 BTC。
- 构建交易:
- 输入总额:0.15 BTC
- 输出总额:0.1 BTC (给Bob) + 0.045 BTC (找零) = 0.145 BTC
- 交易费:0.15 - 0.
