回顾
首先回顾一下我们对比特币的印象。比特币的共识机制设定了一个只允许往里面写入的帐本,而且一旦数据被写入,它将永远被存储在那里。去中心化协议确保了账本中存储数据的共识,而矿工会执行协议并确认交易。这样账本从功能上形成了一种货币系统。同时,假设用货币奖励矿工能使矿工积极地完成记账工作。基于此本节将对如何建立货币系统做稍微深入的探索。
比特币的交易
比特币的交易过程其实就是不停地创造区块的过程,如何能通过记账来构建出一套货币系统呢,首先考虑一种朴素的记账想法:建立一个以账户为核心的系统,可以创造新的币并放入某人的账户,然后就可以转给其它人了。这也可能是有些人误认为是比特币所采用的方式。
记账过程 |
---|
系统制造25个币给爱丽丝,由矿工确认 |
爱丽丝转17个币给鲍勃,由爱丽丝签名 |
鲍勃转8个币给卡罗尔,由鲍勃签名 |
爱丽丝转15个币给戴维,由爱丽丝签名 |
这么做看似直接,但要想确认每笔交易是否真实就必须跟踪每一个账户的余额。例如当爱丽丝想要转给戴维15个币的时候她是否真有15个币,此时就必须回头去看和爱丽丝所有的交易。当然也可以为交易增加个字段来记录每次交易后的账户余额,但这也增加了记账的工作量。那比特币是怎么搞的呢。
在比特币中每笔交易都有输入和输出值,输入值可以看作将被消费掉的币,输出值看成本次交易中创造出来的币。铸造新币时只会创造新币不会消费旧币。每笔交易都有独一无二的ID,每笔交易可能有多个输出,输出索引从0开始。
观察上图,交易1是铸造新币的过程,因此没有输入和签名,其输出是给爱丽丝转移25个币。爱丽丝想要给鲍勃17个币,于是创造出新的一笔交易,交易中输入必须指明币的来源,这里指明了是交易1中的输出0。交易中还要明确收款人,也就是输出地址,这里有两个输出,同时要对交易签名。
- 地址转换。因为在一次交易中输出的币,要么在另一个交易中完全被消费掉,要么就一个都不被消费,不能只消费部分。因此在交易2中,爱丽丝要给鲍勃17个币,但她在之前获得了25个币,为了把这些币消费掉,她需要再给自己转8个币。这8个币可以转给爱丽丝所拥有的另外地址,这就形成了地址转换。
- 有效验证。为了验证交易的有效性,这里我们只需从爱丽丝所引用的交易开始,一直核查到账本上最新记录的交易为止,无需从账本建立之初的交易开始核查。由于使用了哈希指针,核查还是很快的。
- 资金合并。比特币交易可以有多个输入和输出,这样一个用户可以发起一笔交易,将他收到的币作为多个输入,输出到一个自己的地址,这样就完成了资金合并。
- 共同支付。两个人想要一起支付给另外一个人,同样可以发起一笔交易,里面有两个输入和一个输出,两个输入所引用的他俩各自的“上一笔交易”的输出地址,因此需要他俩的签名才行。
- 交易语法。比特币交易底层实现是将在网络上传输的一串字符,通过编译变成机器可执行的二进制代码,如下是Bitcoin Wiki中的例子。解释下里面什么意思,该笔交易的输入是从交易f5d8…的输出0获取的,然后输出将50 BTC发送到一个 比特币地址(这里用16进制4043…表示而没用normal base58)。当接受者想要花掉这笔钱,他只需引用这笔交易的输出0作为自己交易的输入即可。
比特币脚本
每笔交易输出不仅确定了一个公钥,同时指定了一个比特币脚本。最常见的比特币交易就是通过某人的签名去取得他在前一笔交易中获得的资金。这种情况下,我们希望交易的输出包含这样的信息:“凭借地址X的所有者的签名才能获取该笔资金”。地址其实就是一个公钥的哈希值,所以这里仅仅说地址X并没有告诉公钥在哪里,也没有给出一个检查签名的方法。因此交易输出必须这样描述:“凭借哈希值为X的公钥,以及这个公钥所有者的签名,才能获取该笔资金”。这实际上就是最常见的比特币脚本。
交易的输入包含了脚本(而不是签名),为了确认一笔交易正确地获取了上一笔交易所输出的资金,我们把交易的输入脚本和上一笔交易的输出脚本串联起来,这个脚本必须成功执行后才能获取资金。这两个脚本一个是输出脚本(scriptPubKey),另一个是输入脚本(scriptSig)。输出脚本只是指定了一个公钥(或是公钥哈希值的地址),输入脚本指定了一个对应公钥的签名。
智能合约
所谓智能合约(smart contracts)就是那些不同于需要通过法律或者仲裁机构来保护执行的普通合约,智能合约是比特币系统中可以用技术手段来强制执行的合约。比特币有非常好的特性让我们可以采用脚本、矿工和交易验证—而不是通过中心化权威机构—来实现第三方托管协议或是小额支付。但比特币脚本语言的设计也有很多缺陷,还是有很多现实需要的智能合约无法用比特币的工作控制语言来实现,如竞争记账权力问题。
Reference
- 《区块链技术驱动金融》
- https://en.bitcoin.it/wiki/Transaction