找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3102

积分

0

好友

424

主题
发表于 6 天前 | 查看: 25| 回复: 0

比特币区块链交易详情截图

比特币网络中的所有交易记录都公开透明,存储在区块链上。我们可以在诸如 btc.com 这样的区块浏览器上进行查询。

以比特币历史区块中的一条交易为例,其交易 ID(Transaction ID,简称 txid)为:
0627052b6f28912f2703066a912ea577f2ce4da4caa5a5fbd8a57286c345c2f2

从上方截图可以清晰地看到,在“输入”(Input)部分,地址 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK 花费了 0.1 个 BTC。这些资金在“输出”(Output)部分被分配给了两个地址:1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA 收到了 0.015 BTC,而原地址 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK 自己收到了 0.0845 BTC。

因此,这笔交易的核心是地址 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK 向地址 1GdK9UzpHBzqzX2A9JFP3Di4weBwqgmoQA 转账了 0.015 BTC。
你可能注意到,0.0845 + 0.015 = 0.0995,并不等于输入的 0.1 BTC。差额 0.0005 BTC 就是支付给矿工的手续费。

交易的原生面貌

上面的区块浏览器截图是可视化的结果,这条交易在比特币网络中的原始数据结构其实是这样的:

{
  "version": 1,
  "locktime": 0,
  "vin": [
    {
      "txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
      "vout": 0,
      "scriptSig": "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
      "sequence": 4294967295
    }
 ],
  "vout": [
    {
      "value": 0.01500000,
      "scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"
    },
    {
      "value": 0.08450000,
      "scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
    }
  ]
}

是不是感觉有点复杂?别急,我们一点点拆解。一条比特币交易主要由 vin (输入) 和 vout (输出) 两部分构成。

先从熟悉的数字看起:vout 里有两个 value 字段,分别是 0.01500000 和 0.08450000。这对应了转账金额和找零金额。

比特币地址是经过 Base58 编码的字符串。虽然 Base58 与常见的 Base64 编码类似,但专为去除容易混淆的字符(如0,O,I,l)而设计。为了探究地址的本质,我们可以对其进行解码。

使用一个名为 bitcoin.sh 的脚本工具,对地址进行 Base58 解码操作:

. bitcoin.sh
decodeBase58 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK

得到一串十六进制数:

007f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a801974ac6

这串数字看起来眼熟吗?它和我们之前在 vout 中看到的 scriptPubKey 字段里的部分数据非常接近:

{
  "value": 0.08450000,
  "scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",
}

解码后的十六进制数 007f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a801974ac6,比 scriptPubKey 中的 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 多出了开头的 “00” 和结尾的 “01974ac6”

其中:

  • “00” 是主网版本号前缀。
  • “01974ac6” 是校验和(Checksum)。这个校验和可以通过对前面的数据进行连续两次 SHA256 哈希计算,然后取结果的前 4 个字节得到。我们可以用 Python 来验证这个过程,这也是学习哈希函数的一个典型应用:
import hashlib
import codecs
key = codecs.decode('007f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8', 'hex')
r = hashlib.new('sha256', key).digest()
r = hashlib.new('sha256', r).digest()
print(codecs.encode(r, 'hex').decode("utf-8"))
# 输出:01974ac64161c88c363cc701200f529e517ab8a68d11e5f9e46bdb459cc34cd9

取前 8 个十六进制字符(即 4 个字节),正是 01974ac6。以上过程揭示了比特币地址本质上是公钥哈希,并加入了版本号和校验和进行编码。

理解交易输入与输出

为了便于理解,我们可以认为在 vout(输出)中,比特币被“锁定”在了两个比特币地址里。scriptPubKey 就是锁定脚本,它规定了未来谁能花费这笔钱。

那么 vin(输入)是做什么的呢?它的作用就是“解锁”之前被锁定的比特币。让我们再看一眼这笔交易的 vin

  "vin": [
    {
      "txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",
      "vout": 0,
      "scriptSig": "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",
      "sequence": 4294967295
    }
 ],
  • txid 引用了另一笔交易 7957a35f...
  • vout: 0 表示要花费的是那笔交易中的第 0 个输出。
  • scriptSig 就是解锁脚本,里面包含了地址 1Cdid9KFAaatwczBwBttQcwXYCpvK8h7FK 的所有者用其私钥生成的数字签名,以此证明“我有权使用这笔钱”。

比特币交易结构示意图

上图清晰地展示了交易间的关系:交易 A (txid: 7957a35f) 将一个输出(vout0)锁定到了地址 A。当用户(地址 A 的拥有者)想花费这笔钱时,他创建了交易 B (txid: 0627052b)。交易 B 的输入(vin)通过引用交易 A 的 txid 和 vout 索引,并附上自己的私钥签名(解锁脚本),成功解锁了那 0.1 BTC,然后通过两个新的输出(vout)将其重新分配。

如果不断追溯资金的源头,最终所有比特币都来源于一种特殊的交易——币基交易。币基交易没有 vin,是矿工成功挖出新区块时生成的奖励,这也是新比特币进入流通领域的唯一方式。

解锁与锁定脚本的运行机制

我们已经知道,vin 中的 scriptSig 是解锁脚本,vout 中的 scriptPubKey 是锁定脚本。比特币的脚本语言是一种基于堆栈的、逆波兰表示式的编程语言。

在深入脚本之前,需要理清私钥、公钥和比特币地址的关系,这背后涉及非对称加密椭圆曲线密码学的核心原理。

比特币密钥生成过程示意图

关键点在于:

  1. 私钥通过椭圆曲线乘法生成公钥,公钥经过哈希运算(RIPEMD160(SHA256(K)))生成比特币地址(即公钥哈希)。这两个过程都是单向的,无法从公钥或地址反推私钥。
  2. 私钥可以对信息进行签名,而对应的公钥可以验证这个签名。这是非对称加密的典型应用。

一个典型的锁定脚本(P2PKH 类型)如下:

OP_DUP OP_HASH160 <Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

这里的 <Public Key Hash> 就是公钥哈希(对应一个比特币地址)。脚本的意思是:“谁能提供一个签名和公钥,并且这个公钥的哈希值等于 <Public Key Hash>,谁就能花这笔钱。”

对应的典型解锁脚本为:

<Signature> <Public Key>

验证时,网络节点会将解锁脚本和对应的锁定脚本拼接起来执行:

<Signature> <Public Key> OP_DUP OP_HASH160 <Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

执行过程就像一个基于堆栈的计算器:

  1. 首先,将提供的 <Public Key> 进行哈希运算(HASH160),检查结果是否等于锁定脚本中给出的 <Public Key Hash>。这一步验证了公钥的合法性。
  2. 然后,使用提供的 <Public Key><Signature> 进行验证,确认这个签名确实是由该公钥对应的私钥对当前交易数据签名的。这一步验证了花费权。

这一切的核心妙处在于:拥有者无需暴露私钥,只需用私钥对交易生成一个签名,就能通过公钥验证来证明所有权。

那么,私钥到底对什么数据进行签名来生成这个 scriptSig 呢?我们看到的这一长串数字本质上就是签名。以交易 B (0627052b) 为例,其签名的生成步骤有些特殊:

  1. 在构造交易 B 时,先将它的 vin 中的 scriptSig (解锁脚本)字段,用其要花费的交易 A 的输出中的 scriptPubKey (锁定脚本)临时填充。
  2. 对第一步产生的整个交易数据(包含被填充的脚本),加上特定的签名类型前缀,计算其双重 SHA256 哈希值。
  3. 用私钥对第二步得到的哈希值进行加密(签名),得到最终的签名数据。
  4. 最后,将这个生成的签名数据(和公钥)填回交易 B 的 scriptSig 字段,替换掉之前临时填充的锁定脚本。这样,一个完整的、可验证的交易就生成了。

SHA256哈希算法处理流程图

上图中,sigScript 指解锁脚本,pkScript 指锁定脚本,直观展示了签名验证所覆盖的数据范围。

希望这篇对比特币交易从外在表现到内部数据结构的梳理,能帮助你更清晰地理解区块链上的价值转移是如何在密码学保障下安全进行的。如果你对区块链、加密算法或其他底层技术有更多兴趣,欢迎到 云栈社区基础 & 综合 板块或 安全/渗透/逆向 板块,与更多开发者一起交流探讨。




上一篇:微信小程序开发实战:两周实现7合1图片处理工具“逐影图像工坊”
下一篇:Qwen3.5-Plus模型发布:3970亿参数,性能比肩顶级闭源模型
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-2-23 10:27 , Processed in 0.958128 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表