版权声明:可以转载,但请备注原文链接: shuwoom.com/?p=430
关键字:比特币、区块链、交易脚本、智能合约、UTXO账户模型、价值转移
1.比特币的UTXO模型
首先,在讲比特币交易过程之前要说明一个事情。比特币系统是没有余额的概念的,它使用的是UTXO模型(Unspent Transaction Outputs,未使用过的交易输出),我们在交易过程中经常说的钱包余额,实际上是一个钱包地址的UTXO集合。所以,在比特币网络中,存储比特币余额的是交易输出,准确点说就是未使用过的交易输出。
如下图,每一笔交易记录了时间、发送人、接收人和金额。那如果要计算A的余额,那么就要遍历所有跟A有关的交易,减去A发送的每一笔金额,并加上A接收的每一笔金额,可以计算出。
A的余额 = 20-10=10
B的余额 = 20+10+5-5=30
C的余额 = 20-5=15
D的余额 = 20+5=25
比特币系统中计算余额的方法也是类似这样。所以,要计算一个用户的比特币余额,就需要遍历整个交易的历史。而以太坊由于采用了Account模型,也就是采用余额的概念,所以不需要溯源整个交易历史。
图1 账本
2.交易过程
上面,我们介绍了比特币的UTXO模型,解释了比特币“余额”的概念。接下来,我们正式开始讲解比特币的交易过程,并在接下来的分析过程中我们会回答两个很重要的问题:
(1)如何保证用户只能使用自己的比特币?(比特币账本是全网公开的)
(2)如何保证一笔交易的有效性?
下图,是一笔交易的完整过程。这里面交易有两种类型,一种是Coinbase交易,也就是挖矿奖励的比特币,由于没有发送人,所以比较特殊。另一种就是我们常见的普通交易了,包含输入和输出的。
图2 比特币交易基本过程
这里我们假设,由于Alice挖矿被奖励了12.5个比特币。而Alice在一笔交易中,需要转账给Bob10个比特币。而Bob最终确认并接收了Alice发送的10个比特币,而同时由于多出了2.5个比特币。其实这笔交易最终是生成了2个输出,一个是发送给Bob的10个比特币,另一个是找零产生的发给Alice的2.5个比特币(备注:这里不考虑交易费)。
在这里面,发生了几个关键的操作:
(1)最开始,Alice由于挖矿被奖励了12.5个比特币,从而产生一笔Coinbase交易。这个交易中包含一个输入和一个输出。输出中,包含当前输出的索引、金额、锁定脚本和接受者的公钥。这里锁定脚本的作用是,设定成只有Alice才能使用这笔输出。而要使用这个UTXO,就必须要证明自己是Alice。如何证明,我们会在后面讲解。
(2)然后,由于Alice要发送给Bob10个比特币,那么她首先要做的就是确认自己有没有足够的“余额”去支付这笔交易。我们在上一节说了,要计算用户的余额,就要遍历Alice的所有交易记录,这里,我们假设Alice就只有一笔Coinbase交易,也就是说Alice当前的余额是12.5个比特币。由于12.5大于所要支出的10个比特币,所以交易可以进行。
(3)接下来,就是要创建一笔交易。这笔交易包含1个输入、2个输出(一个发送给Alice,一个找零发给自己)。
由于比特币采用UTXO模型,一笔交易的输入实际上使用的是上一笔交易的输出(UTXO)。输入中也包含发送者的公钥,这里是Alice的公钥。这里,有一个很重要的问题,我们怎么知道Alice使用的是自己的UTXO呢?如果Alice使用的是别人的UTXO,我们怎么去校验呢?
这里,我们看到输入中除了引用上一个交易输出和发送者Alice的公钥,还包含了一个解锁脚本。解锁脚本里包含了Alice的对上一笔交易输出的签名和自己的公钥。在《区块链快速入门》中,我们知道通过数字签名技术,我们可以使用公钥对用户的签名(私钥加密)进行验证从而证明签名者是否用户本人。如下图,我们就可以通过解锁脚本中提供的Alice的签名和公钥去验证Alice使用的是否是自己的UTXO。
图3 数字签名技术(签名和验证)
(4)上一步,我们验证了该交易中输入所引用的上一笔UTXO确实是Alice的,从而证明了该输入的有效性。接下来,就需要创建2个输出,一个是给Bod的10个比特币,同时包含一个锁定脚本,该锁定脚本限定只有Bod才能使用;另一个是找零产生的输出,发送给Alice的2.5个比特币,同样的也包含一个锁定脚本,并且限定只有Alice本人才能使用。
(5)最后交易创建完成后,就向比特币网络广播出去,当比特币网络确认这笔交易并且将这笔交易在下一次挖矿竞赛中,将该交易打包进区块中并得到全网共识确认后,这笔交易就确认有效了。
比特币的基本交易过程就基本这样。
下图我们可以了解下,一个比特币真实交易是包含哪些数据的?
b6f6b339b546a13822192b06ccbdd817afea5311845f769702ae2912f7d94ab5交易
图4 普通交易
3.关键概念
一个交易包含以下信息:
输入:一个或多个交易输入
输出:一个或多个交易输出
时间:交易时间戳UNIX
3.1 交易分类
交易分为2类:
Coinbase交易:挖矿奖励,没有输入,只有输出。如下图5所示。
普通交易:用户之间的普通转账交易,如上图4所示
图5 Coinbase交易
3.2 交易输入
交易的输入结构如下:
图6 交易输入结构
3.3 交易输出
交易的输出结构如下:
图7 交易输出结构
3.4 交易脚本
(1)概念
比特币客户端使用一个用类Forth脚本语言编写的脚本去验证比特币的交易,这个脚本语言不是图灵完备的,不具备循环等复杂的特性。它是一种基于堆栈的执行语言,该脚本语言的简单特性,虽然使得它不能实现复杂的功能,但是也提高了交易脚本的安全性(设计简单,减少了攻击面)。而以太坊就是诟病比特币交易脚本功能有限,所以设计了一个图灵完备的脚本语言,也就是我们常说的智能合约脚本语言,能实现更复杂的功能,但同时也增加了安全隐患。
当一笔比特币交易被验证时,每一个输入中的解锁脚本与其所引用的输出中的锁定脚本同时执行,从而检查这笔交易是否有效。如图8所示,是最为常见类型的比特币交易的解锁和锁定脚本。
图8 解锁脚本和锁定脚本
(2)验证过程
当我们拿到一笔交易时,如何验证这个交易输入是否有效,也就是如何校验该输入所引用的输出是否有效。
首先,将当前输入的解锁脚本,和该输入所引用的上一笔交易输出的锁定脚本如图8一样组合在一起,并进行下的验证过程,最终若返回TRUE,说明交易有效。
图9 交易有效性校验过程
从上面的校验过程,其实我们可以发现,如果要实现多人签名的校验以及定时消费的校验(规定多久后才能使用),同样可以采用上述的原理进行。
(3)实例分析
下面,我们通过分析一笔比特币真实交易,来加深了解比特币的交易脚本验证过程。
地址:
webbtc.com/tx/cca75078…
为了校验该交易有效,我们需要对
cca7507897abc89628f450e8b1e0c6fca4ec3f7b34cccf55f3f531c659ff4d79中输入所引用的上一笔输出的锁定脚本与当前输入中的解锁脚本进行校验。
解锁脚本(SriptSig):
8b4830450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e0141042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb
翻译后:
PUSHDATA(72)[30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e01] PUSHDATA(65)[042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb] |
该解锁脚本包含了发送者的签名(3045...0e01)和公钥(042e...cabb)。
该输入引用的上一笔输出的锁定脚本:
上一个交易ID:a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d
输出索引:0
可以找到输入所引用的上一笔交易输出是如下:
其锁定脚本为:1976a91446af3fb481837fadbb421727f9959c2d32a3682988ac
翻译后:
OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG |
我们将解锁脚本和锁定脚本组合在一起进行校验:
PUSHDATA(72)[30450221009908144ca6539e09512b9295c8a27050d478fbb96f8addbc3d075544dc41328702201aa528be2b907d316d2da068dd9eb1e23243d97e444d59290d2fddf25269ee0e01] PUSHDATA(65)[042e930f39ba62c6534ee98ed20ca98959d34aa9e057cda01cfd422c6bab3667b76426529382c23f42b9b08d7832d4fee1d6b437a8526e59667ce9c4e9dcebcabb] OP_DUP OP_HASH160 46af3fb481837fadbb421727f9959c2d32a36829 OP_EQUALVERIFY OP_CHECKSIG |
然后逐一执行指令:
栈 |
指令 |
说明 |
PUSH DATA 3045...0e01 |
将3045...0e01(签名)入栈 |
|
3045...0e01 |
PUSH DATA 042e...cabb |
将042e...cabb(公钥)入栈 |
042e...cabb 3045...0e01 |
OP_DUP 042e...cabb |
复制栈顶数据 |
042e...cabb 042e...cabb 3045...0e01 |
OP_HASH160 |
对栈顶数据先采用SH256哈希算法,随后对其运用RIPEMD160算法,得到: 46af3fb481837fadbb421727f9959c2d32a36829 |
46af...6829 042e...cabb 3045...0e01 |
PUSH DATA 46af...6829 |
将46af...6829入栈 |
46af...6829 46af...6829 042e...cabb 3045...0e01 |
OP_EQUALVERIFY |
校验栈顶两个数据是否相等 |
042e...cabb 3045...0e01 |
OP_CHECKSIG |
验证签名 |
TRUE |
RESULT |
返回为TRUE,说明交易有效 |
最终交易脚本返回TRUE,证明了交易的有效性。
备注:如果想要详细了解比特币的脚本语言,可以查看:en.bitcoin.it/wiki/Script
如果想在线校验交易,可以查看:webttc.com
参考
[1] 比特币账户模型。book.51cto.com/art/201711/…
[2] 主流区块链介绍。 blockchain.iethpay.com/blockchain_…
[3] 比特币交易查看。blockchain.info/zh-cn/tx/b6…
[4] 精通比特币。book.8btc.com/books/1/mas…
[5] Bitcoin Wiki Script en.bitcoin.it/wiki/Script
[6] Bitcoin Wiki Transaction en.bitcoin.it/wiki/Transa…
[7] 比特币在线校验交易 webbtc.com/script/cca7…
[8] 比特币脚本及交易分析 - 智能合约雏形。learnblockchain.cn/2017/11/10/…
[9] 深入理解比特币交易的脚本。www.infoq.com/cn/articles…