一般的电子支付平台都是中心化的、基于账户系统的。我们必须先开通账户,然后才能进行存取款和转账操作。比特币在这方面有很大的不同,它是一个完全基于交易数据的分布式账本,形式比较类似于现金交易,货币直接被转移,而不是中心化平台下的账户余额数量的变更。下面就来讲解一下这套机制的内部原理和被采用的原因。
在古装剧里我们经常可以看到人们用碎银子来付账:挑选一块或者几块碎银子,凑足金额,付给店家;如果不好找钱,可以把银子再剪碎。比特币跟银子的这种使用方式很相像,交易时钱包软件会从钱包里挑选出金额合适的一个或几个比特币,打包生成交易数据,通过分割的方式来实现找零。
在代码层面,Transaction代表交易,TxIn代表交易的输入,也就是付款,TxOut代表交易输出,也就是收款。一个Transaction包含一个TxIn数组和一个TxOut数组。TxOut对象包含金额信息和用于验证交易的脚本(称为锁定脚本)。它就类似于碎银子,是我们交易时实际使用的货币,在比特币里称为Coin(又叫UTXO:Unspent Transaction Output)。锁定脚本代表拥有者的身份标记,未来消费这个Coin时需要用脚本来校验交易者的身份信息,确认Coin的所有权。TxIn对象包含对以前的某个TxOut对象的索引和交易发起者的身份信息(称为解锁脚本)。
每次交易时,原有的Coin经过等量变换后(可能被分割或重组),变成新的Coin,并被打上收款方的身份标记。交易信息被打包到区块中,然后组装成区块链,这样就形成了比特币的账本。
碎银子来源于银锭,银锭一般是由官府负责铸造。而比特币的铸币过程被称为挖矿。矿工通过哈希碰撞来夺得铸币权,然后制造出一个比特币的Coin,记录到区块链中,这样这个Coin就开始进入比特币的流通体系。
由于比特币的账本是基于交易信息的,所以挖矿是作为一种特殊的、“无中生有”的交易(Coinbase交易)被记录进区块链。这个交易并不需要实际的输入,它的TxIn是虚拟的,不用指向以前的某个TxOut对象。和普通交易一样的是,CoinBase交易的输出就是最后产生的新的Coin,并会打上矿工的身份标记以示所有权。另外,矿工负责将交易信息打包成区块,并广播到P2P网络中。在这个过程中,矿工会统计和收集打包的交易里的交易费用,作为自己挖矿奖励的一部分,一并计入所挖到的Coin的金额里。
由于碎银子是实物,它的所有权一般不存在争议,谁拿在手里就可以认为是谁的。而比特币是一种数字货币和资产,需要有一种机制来标识和验证所有权。比特币实际采用的是secp256k1椭圆曲线加密算法和基于脚本的自定义校验流程。前者为比特币的交易安全打下了坚实的基础,后者则让上层应用可以灵活的定制和扩展交易方式,例如基于多重签名的中介担保和联合账户。
对于数字内容和数字资产的身份标识,一般采用数字签名的方式,基于非对称加密算法,使用私钥对数据进行签名,使用公钥对签名进行校验。比特币也是一样,交易发起方使用自己的私钥,对交易核心信息的哈希进行签名,把签名数据放入TxIn的解锁脚本中。在交易的TxOut的锁定脚本中则放入收款方的公钥数据和校验指令,以供这个TxOut未来被使用时校验其合法性。
这里有两个TxOut对象,注意不要搞混了。一个是当前交易的收款方TxOut,一个是当前交易的TxIn对应的以前收到的某个TxOut。要记住,TxIn只是之前TxOut对象的索引加上用户消费时的签名。验证一个交易时,用到的是TxIn和它对应的之前TxOut,而不是当前交易收款方的TxOut。如果把TxOut比作用带锁的盒子锁起来的碎银子,TxIn就相当于提供记录盒子所在位置的地图和开锁的钥匙。
上面说的校验过程是比特币钱包一般采用的方法。比特币核心只是提供了一套基于脚本的自定义校验机制,具体怎么操作,可以由上层钱包应用自主选择。下面的常用的一些脚本模板:
最简单的校验脚本(早期版本中曾使用过)
Pubkey script: OP_CHECKSIG
Signature script:
一般的P2KH校验脚本
Pubkey script: OP_DUP OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG
Signature script:
P2SH校验脚本
Pubkey script: OP_HASH160 OP_EQUAL
Signature script: [sig] [sig...]
多重签名校验脚本
Pubkey script: [B pubkey] [C pubkey...] OP_CHECKMULTISIG
Signature script: OP_0 [B sig] [C sig...]
2-3的P2SH多重签名校验脚本
Pubkey script: OP_HASH160 OP_EQUAL
Redeem script: OP_CHECKMULTISIG
Signature script: OP_0
比特币的内核中并没有账户的概念,只需要公私钥对就可以进行交易。上层应用中会把公私钥对包装成账户,以方便用户的使用。所以比特币的账户不需要到哪里去申请,个人可以随便创建,而且可以创建很多个。
比特币钱包是面向普通用户的上层应用,满足用户的转账和消费需求。钱包可以创建一个或多个账户,钱包的余额就是钱包里所有账户名下的Coin/UTXO的总金额,就跟古人的钱袋子一样。
为什么比特币不采用基于账户的记账方式?原因还是在于去中心化。
在基于账户的支付体系中,交易是有严格次序的,每一笔交易对应账户余额的相应变化,只有中心化的服务器才能保证交易的顺序性和数据的一致性。
但比特币是完全去中心化的,没有中心服务器来控制交易的次序。例如,在同一时刻,可能有多个人向同一个账户转账,这时不同的节点收到这些交易信息的顺序是不一样的,它们看到该账户的余额也是不一样的。这样账户余额信息就无法在不同节点中保持数据的一致性。再例如,一个账户连续发起多个交易,虽然这些交易在本地是有次序的,但在P2P网络中传播时,却无法保证它们以相同的次序传到所有的节点。这样的话,以账户和余额为基础的交易就可能出现问题,无法被正确的校验。
所以,比特币选择了传统货币的交易方式,直接跟踪记录货币本身的转移,而非记录账户余额的变化,从而绕开前面列举的问题。
去中心化虽然很美好,但也让比特币的功能和性能受到很多限制。不过这更激发了业界人士的创造力和想象力。他们通过不断的努力,设计出各种巧妙的方案,改进现有的系统和拓展新的应用,这也正是区块链技术特别吸引人的一面。