主页 > imtoken官网注册 > 揭秘比特币和区块链(五):深入理解比特币交易的脚本

揭秘比特币和区块链(五):深入理解比特币交易的脚本

imtoken官网注册 2023-07-19 05:09:02

本文作者为火币区块链研究中心技术专家廖雪峰。拥有十年软件开发经验,精通Java/Python/Ruby/Visual Basic/Objective C/Lisp等编程语言。他对开源框架有深入的研究。Spring 2.0 Core Technologies and Best Practices”一书,并在GitHub上托管了多个业余开源项目。在本文中,廖雪峰详细介绍了比特币和比特币区块链的相关知识。

另外,想要快速了解和掌握区块链技术的同学,可以购买极客时代出品的“区块链通俗易懂”专栏。专栏以区块链技术为基础,带你形成完整的区块链知识体系。作者还将教你如何搭建自己的迷你区块链,带你走进区块链的世界。

在比特币区块链中,每个区块都指向前一个区块,这些由SHA256计算出来的区块哈希链是比特币账本不可篡改的基础。

在一个区块中,比特币系统使用一笔交易来代表一笔比特币交易。一个区块至少包含一个交易。这些交易的 Hash 通过 Merkle Tree 计算出所有交易的 Merkle Hash,并包含在区块 Hash 中,使得交易无法被修改。

如果我们仔细观察每笔交易,我们可以看到每笔交易都有一个或多个输入(TxIn)和一个或多个输出(TxOut),除了第一个交易是由矿工开采的:

第一个矿工的收益交易通常称为 Coinbase,它没有输入,所以 TxIn 的 Hash 总是标记为 00000000...0000

对于其他交易,任何TxIn都会唯一地追溯到该区块之前区块链上的某个交易Hash,索引:

通过交易哈希和索引(从0开始),可以唯一确定一个未花费的交易输出——UTXO(Unspent Transaction Output)。这样,每个 Tx 输入都与前一个 Tx 输出相关联。

假设在最后一笔交易中,Bob 支付了 Alice 0.15 BTC。

由于比特币没有账户的概念,所以这笔交易的输出既不是爱丽丝的名字,也不是爱丽丝的公钥。

一个区块链等于多少比特币

那么,Alice 想要花掉这个0.15 BTC,她应该如何证明她拥有这个 UTXO,并且其他人不能冒充 Alice 来花费这个 UTXO?

答案是比特币交易产生的输出不是一个简单的公钥地址,而是一个脚本。在 Bob 向 Alice 支付 0.15 BTC 的交易中,Bob 创建了一个类似于以下内容的输出脚本:

OP_DUP OP_HASH160 abcd1234...9876 OP_EQUALVERIFY OP_CHECKSIG

其中 abcd1234...9876 是 Alice 的公钥哈希。整个脚本意味着任何可以提供签名和公钥让脚本运行的人都可以为此交易花费 1.5 BTC。

由于只能使用 Alice 的私钥来创建签名,因此没有 Alice 的私钥创建的签名将无法通过此脚本的验证,因此其他人无法冒充 Alice 来花费此输出。

一旦 Alice 提供了一个签名和她自己的公钥,她实际上已经创建了另一个交易来花费这个输出。

每个人都可以验证 Alice 创建的这个新交易是有效的。如果有效,交易将被矿工打包成一个新区块,使其成为区块链不可更改的一部分。

我们以著名的 Pizza Transaction 为例,验证一笔交易是否有效。

在事务 cca75078...4d79 中,提供 sigScript 的唯一 TxIn 输入是:

一个区块链等于多少比特币

8b4830450221009908144ca6539e09512b9295c8
a27050d478fbb96f8addbc3d075544dc41328702
201aa528be2b907d316d2da068dd9eb1e23243d9
7e444d59290d2fddf25269ee0e0141042e930f39
ba62c6534ee98ed20ca98959d34aa9e057cda01c
fd422c6bab3667b76426529382c23f42b9b08d78
32d4fee1d6b437a8526e59667ce9c4e9dcebcabb

sigScript 实际上由两部分组成:

签名:30450221...ee0e01(71字节+1字节签名类型)一个区块链等于多少比特币,实际签名为30450221...ee0e去掉最后一个字节01,签名类型为SIGHASH_ALL(0x0< @1)。

公钥:042e930f...cabb(65 字节)

为了验证交易是否有效,我们首先需要根据TxIn声明的Previous Output Hash:a1075db5…d48d和索引0一个区块链等于多少比特币,找到上一笔交易的输出:

本次交易输出的脚本为:

1976a91446af3fb481837fadbb421727f9959c2d32a3682988ac

比特币的脚本由一系列指令和数据组成,每条指令占用一个字节,数据由数据头的长度决定。从上述二进制脚本翻译的比特币指令如下:

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG

一个区块链等于多少比特币

现在,我们有了签名、公钥和脚本:

sig: 30450221...ee0e01
pubkey: 042e930f...cabb
OP_DUP OP_HASH160 46af3fb4…6829 OP_EQUALVERIFY OP_CHECKSIG

然后可以运行此脚本来验证交易是否有效。

比特币脚本被设计为在堆栈上运行的虚拟机指令。它只有有限数量的指令,并且故意设计为没有循环和条件跳转。因此,比特币脚本不是图灵完备的语言。

比特币脚本的执行非常简单。我们首先需要准备一个空栈,然后将签名和公钥压入栈中:

接下来,我们可以执行 TxOut 脚本:

OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG

首先执行OP_DUP,这条指令复制栈顶元素,所以结果变成:

然后执行OP_HASH160,对栈顶元素计算SHA256/RipeMD160,其实就是计算公钥Hash,所以运行结果变成:

一个区块链等于多少比特币

下一条指令其实是一条数据,我们直接把数据压栈:

然后,执行OP_EQUALVERIFY,这条指令会比较栈顶的两个元素是否相等。如果它们不相等,则整个脚本将无法执行。如果相等,脚本会继续执行,所以运行结果变成:

最后,执行指令 OP_CHECKSIG,验证签名。首先,我们根据签名类型SIGHASH_ALL(0x0<@1)验证整个交易。验证方式为:

移除当前Transaction的所有TxIn的scriptSig(红色部分),将当前TxIn的scriptSig替换为UTXO的脚本(蓝色部分),并调整长度字段(绿色部分):

最后加上little-endian 4字节签名类型0x01(灰色部分),计算两次SHA256,得到:

c2d48f45…2669

现在,使用 ECDSA 算法验证签名:

boolean ecdsa_verify_signature(byte[] message, byte[] signature, byte[] pubkey)

根据签名的验证结果,我们可以确认交易是否有效。

一个区块链等于多少比特币

由于脚本的引入,我们可以看到比特币实际上通过编程脚本实现了一种严格基于计算机程序验证的数字货币所有权转移机制。由于计算机程序的可扩展性,比特币支付不限于必须支付到某个公钥地址。使用脚本,我们可以构造各种支付条件,比如多重签名验证条件:

2    3 OP_CHECKMULTISIGN

这个多重签名脚本,提供多个公钥地址,需要多重签名验证,允许在M个签名类型中至少使用N个签名。上面的脚本允许提供 3 个公钥地址的任意两个有效签名。

当我们在第三方在线钱包中托管比特币时,我们可以使用多重签名来保证输出只有在与第三方钱包共同签名后才能使用,这样可以保证黑客也可以攻击第三方钱包。无法使用用户的比特币。

使用 OP_CHECKLOCKTIMEVERIFY,我们可以为一个事务指定一个锁定时间,在此之前不能花费事务输出。该指令实际上实现了支付宝7天资金锁定然后支付给卖家的功能。

还有一些交易没有指定公钥哈希。例如本次交易的脚本如下:

OP_HASH256 6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000 OP_EQUAL

这意味着谁能提供 SHA256 为 6fe28c0a...0000 的数据,谁就可以花费这笔交易。

(注:交易已经消费,有人找到符合条件的数据)

从比特币的脚本中,我们可以看到基于区块链的数字货币支付实际上是一种数字货币所有权的安全转移。如果我们以数字形式在区块链上登记金融资产或实物资产,则可以通过脚本安全地实现各种条件下的所有权转移,这正是智能合约在区块链上的应用。

原文发表时间:2017年1月12日