liujie
liujie
Published on 2024-06-12 / 7 Visits
0
0

比特币交易原理

比特币交易

现在,你已经创建好公私钥对了,已经准备好接收比特币了。你的好朋友 Tom 表示他愿意给你 10 BTC。为了收到资金,你需要创建一个地址,你要对自己的公钥运行哈希函数,得到公钥的哈希值,然后转化成一个 base58check 格式;整个过程最终会产生以 “1” 或 “3” 开头的比特币地址。再次提醒,有了私钥就可以推导出公钥,有了公钥就可以推导出公钥哈希值,但反过来都是不行的。这就是一条单行道。不过,公钥哈希值和地址是可以相互转换的。(译者注:作者在这里介绍的是 P2PKH 地址)。

img

现在,你可以把地址给 Tom,然后等待接收 10 BTC。Tom 为了给你发送比特币,需要创建一笔交易,并将你的地址写到其中一个输出中。交易的输出有以下几个字段:索引号,帮助网络在这笔资金被花费时(例如:你要花费这 10 BTC 时)找出这笔交易;价值,以 “聪” 为单位的比特币数量,也即是被发送的数额;锁定脚本(也叫公钥脚本)。公钥脚本的作用就是把 Tom 发送给你的比特币锁在你给 Tom 提供的地址(公钥哈希值)上。现在,你就是唯一掌控着某一把私钥(希望如此!),因此唯一能够满足这个公钥脚本、解锁这个地址中的资金的人了!

img

当交易被验证、由矿工挖出后。你的钱包(软件)(记录着你的地址)会向你展示你拥有了 10 BTC。实际上,你的钱包(软件)只是在跟踪属于你的地址的输出(在公钥脚本中记录了你的公钥哈希值的输出)。这些输出被称为 “未花费的交易输出(UTXO)”,它们会一直静静地呆在那里,直到有人使用交易来提供解锁某个输出所需的数据,并将这个输出中的比特币转移到另一个地址(这会创建另一个 UTXO)。比特币网络实际上只是 UTXO 的一张网,所有的 UTXO 都等待着被解锁、然后发送到某个地方形成一个新的 UTXO。比特币不是一个基于账户的系统,意思是用户其实并没有像银行账户那样的东西,比特币也不是像账户余额那样的东西。实际上,用户只是持有可以解锁网络中的某一些 UTXO 的私钥。这也意味着你在花费一个 UTXO 时不能只花一部分,每次你创建一笔交易、花费某一个 UTXO 时,都是把其中的价值全部解锁、花出去。如果你不想把一个 UTXO 的所有价值都发送给某个人,你就必须在交易中包含一个输出(地址)来接收你想保留下来的比特币。你也可以使用相同的地址来接收剩余的比特币,但这不是理想的做法。最好的做法是,你创建一个新的地址来接收剩余的比特币,以提高隐私性。

现在,你已经可以使用 Tom 所创建的、带有 10 BTC 的 UTXO 了,你的朋友 Sarah 也想加入比特币网络、使用比特币。为了发送你的 10 BTC,你也要创建一条新的交易,用一系列的输入和输出来表达你的意图。

img

交易的输入

首先,你使用 Tom 给你支付的交易的 ID 和输出的索引号,找出正确的 UTXO 以及对应的公钥脚本。必须满足公钥脚本所指定的条件,才能花费该 UTXO 中锁定的比特币。

然后,你创建一个 “签名脚本(signature script)”,也就是用来满足公钥脚本要求的数据。在我们这个案例中,签名脚本由一个数字签名和你的公钥组成;被签名的数据,对应的就是你为 Sarah 创建的交易整体。具体来说,交易整体包含前序交易(Tom 给你支付的交易)的 ID、被花费的输出的索引号、输出的公钥脚本、你为 Sarah 设置的新的公钥脚本,以及你发送给 Sarah 的数额(锁在这个新的公钥脚本中的数额),等等。所有这些数据使用 SHA256 哈希函数哈希两次。然后,你使用自己的私钥签名这个 256 比特的哈希值,得到的就是所需的签名。把签名和你的公钥组合起来,就是签名脚本。

(译者注:签名脚本中的公钥,正是所花费的 UTXO 的锁定脚本中的公钥哈希值所对应的公钥;而用于签名的私钥,也正是这个公钥背后的私钥。)

交易的输出

就像 Tom 交易的输出,你的交易的输出也带有下列信息:一个新的索引号,用于定位这笔交易;比特币的数量(以聪计量);一个新的公钥脚本,使用 Sarah 提供给你的地址,因此会把这些比特币锁进 Sarah 的地址。现在,只有拥有这个地址背后的私钥的人(最好是 Sarah),才能花费这些比特币。

公钥脚本

创建好上述交易后,你需要把交易广播给比特币网络的矿工。矿工会取出你的签名脚本,并跟公钥脚本一起运行。如果运行的结果为真,那么你的交易就是有效的,可以被添加到区块中。

这个案例中的脚本(签名脚本 + 公钥脚本)长这样:

<Sig> <PubKey> OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG

比特币的 Script 是一种基于堆栈的编程语言。它处理的流程如下图所示:

img

步骤 1:向堆栈推入签名脚本。首先是签名,然后是你的公钥。

步骤 2:执行公钥脚本的 OP_DUP 操作码,复制栈顶的元素。在我们这里就是复制公钥。

步骤 3:执行 OP_HASH160 操作码,对栈顶的元素执行哈希计算,在这里就是哈希复制出来的公钥。现在,我们已经有签名、公钥和公钥哈希值了。

步骤 4:将公钥哈希值推入栈中(也就是你交给 Tom,被 Tom 放在第一笔交易中的公钥哈希值)。

步骤 5:执行 OP_EQUALVERIFY,检查栈顶的两个元素是否相等。在这里,就是你交给 Tom 的公钥哈希值,和你在签名脚本中提供的公钥的哈希值。这两个元素应该相等,如果不相等,交易就会失败;如果相等,则这两个元素会被弹出堆栈,最终只剩下公钥 + 签名。

步骤 6:就像在上文的 “数字签名” 一节讲的,OP_CHECKSIG 会使用公钥来校验签名。如果校验不通过,则交易会失败。如果通过,则公钥和签名都会被弹出,堆栈中只剩下 “True(真)”。

如果运行通过,说明这是一笔有效的交易,矿工可以把它添加到区块中,等待整个网络的公认了。


Comment