区块链学习笔记——2.比特币原理

比特币原理

参考资料:

其实并没有什么比特币,只有UTXO

【基础知识】:比特币原理分析

比特币来源

2008年10月31日,中本聪公布了比特币白皮书《比特币:一个点对点的电子现金系统》,提出比特币网络,其特点如下:

  • 防止双重支付(双花问题);

  • 无铸币厂或其他信任方;

  • 参与者可匿名;

  • 通过工作量证明方式发行新币;

  • 基于工作量证明的新币发行过程中,也同时阻止了双重支付的发生。

比特币是在比特币网络中产生并流转的加密货币。比特币网络本质上是一个公开的分布式账本,即使在用户匿名情况下,也可以查看并审核某个用户是否造假、非法铸币、将一笔钱同时花给几个人(双重支付)。若半数以上人都否认某个账本(51%攻击/共识),那这个账本就会被丢弃。

比特币技术原理

去中心化

没有中心化的公司或组织来控制服务器,每个用户都可以选择自己信任获认可的【支持比特币协议】的程序,这个程序运行时就是一个服务器或节点,它与其他比特币程序或节点相连,权利与义务相同。这些节点共同维护比特币网络。部分节点的加入和退出不会影响整个网络的运行,除非所有节点同时掉线。

交易和账本

分布式账本:每个节点复制账本的一个备份,同时这个账本里的账单也由这些节点共同记录完成。

1.UTXO

  • UTXO(unspent transaction output)未花费的交易输出,这是比特币交易中核心概念。
  • UTXO==比特币,实际的区块链中没有币的概念,都是UTXO
  • 比特币系统里没有账户,自然也没有余额等内容
  • UTXO是比特币拥有者的公钥锁定的一个数字,实际是是拥有者的公钥加密的数字,只有拥有者的私钥才能解开。
  • UTXO存储在全节点的数据库里
  • UTXO可以用于支付,新的UTXO可以由挖矿或交易产生。说通俗一些,UXTO就是交易中交易接收者应该收到的支付金额和交易发起者的收到的找零。
  • 转账将消耗掉属于你的UTXO,同时生成新的UTXO。
  • 假设你有5个比特币,你给X转了2个比特币,然后结束操作,你会发现你的5个比特币都没有了,这是因为按照区块链的规则,矿工默认将剩余的3个比特币作为自己的工资。为了避免自己的损失,需要在给X转了2个比特币以后再给自己转3个比特币,采不会出现上述情况。当然,如果用别人封装好的客户端是不会出现这个问题的。

现在的银行、信用卡、证券交易系统以及互联网第三方支付系统的核心都是基于账户(account based)的设计,由关系数据库支持。而比特币没有设计成基于账户的系统,而是发明了UTXO方案。

举个例子,张三挖到12.5 枚比特币。过了几天,他把其中 2.5 枚支付给李四。又过了几天,他和李四各出资 2.5 比特币凑成 5 比特币付给王五。如果是基于账户的设计,张、李、王三人在数据库中各有一个账户,则他们三人的账户变化如下图所示:

但在比特币中,这个过程是通过UTXO实现的,图示如下:

区块链账本里记录的是一笔又一笔的交易,每笔交易都有若干交易输入,也就是资金来源,也都有若干笔交易输出,也就是资金去向。一般来说,每一笔交易都要花费(spend)一笔输入,产生一笔输出,而其所产生的输出,就是“未花费过的交易输出”,也就是 UTXO。

比特币交易遵守几个规则。

第一,除了 coinbase 交易之外,所有的资金来源都必须来自前面某一个或者几个交易的 UTXO,就像接水管一样,一个接一个,此出彼入,此入彼出,生生不息,钱就在交易之间流动起来了。

第二,任何一笔交易的交易输入总量必须等于交易输出总量,等式两边必须配平。

上图第一个交易 #1001 号交易是 coinbase 交易。比特币是矿工挖出来的。当一个矿机费尽九牛二虎之力找到一个合格的区块之后,它就获得一个特权,能够创造一个 coinbase 交易,在其中放入一笔新钱,并且在交易输出的收款人地址一栏,堂堂正正的写上自己的地址。在我写文章的这一天(2016年8月9日),这笔比特币的数额规定为 12.5 枚,市价 48,576元人民币。这个 coinbase 交易随着张三挖出来的区块被各个节点接受,经过六个确认以后永远的烙印在历史中。

过了几天,张三打算付 2.5 个比特币给李四,张三就发起一#2001号交易,这个交易的资金来源项写着“#1001(1)”,也就是 #1001 号交易——张三挖出矿的那个 coinbase 交易——的第一项 UTXO。然后在本交易的交易输出 UTXO 项中,把2.5个比特币的收款人地址设为李四的地址。

请注意,这一笔交易必须将前面产生那一项 12.5 个比特币的输出项全部消耗,而由于张三只打算付给李四 2.5 个比特币,为了要消耗剩下的10比特币,他只好把剩余的那 10 个比特币支付给自己,这样才能符合输入与输出配平的规则。

再过几天,张三和李四打算AA制合起来给王五付 5 枚比特币。那么张三或李四发起 #3001 号交易,在交易输入部分,有两个资金来源,分别是#2001(1) 和 #2001(2),代表第 #2001 号交易的第 (1) 和第 (2) 项 UTXO。然后在这个交易的输出部分里如法炮制,给王五5比特币,把张三剩下的 7.5 比特币发还给自己。以后王五若要再花他这5比特币,就必须在他的交易里注明资金的来源是 #3001(1)。

所以,其实并没有什么比特币,只有 UTXO。当我们说张三拥有 10 枚比特币的时候,我实际上是说,当前区块链账本中,有若干笔交易的 UTXO 项收款人写的是张三的地址,而这些 UTXO 项的数额总和是 10。因为在比特币系统里,一个人可以拥有的地址资源,可谓取之不尽用之不竭。要知道自己的一大堆地址里一共收了多少 UTXO,人是算不过来的,需要由比特币钱包代为跟踪计算。

2.交易的结构

  • 交易的输入:UTXO+解锁脚本(签名、发送者公钥)
  • 交易的输出:锁定的比特币数量+锁定脚本(接收者的公钥Hash)

3.交易的验证

交易的验证是基于栈的一种脚本语言,主要操作有OP_DUP、OP_EQUALVERIFY、OP_HASH160、OP_CHECKSIG、OP_ADD、OP_SUB、OP_MUL、OP_DIV。而操作表达式用的是逆波兰式

锁定脚本:OP_DUP OP_HASH160 <发送者的公钥的Hash> OP_EQUALVERIFY OP_CHECKSIG

解锁脚本:<发送者签名> <发送者公钥>

交易验证:运行解锁脚本+锁定脚本 => True

合法的交易必须满足如下条件:

  • 交易的size要小于区块size的上限
  • 交易输入UTXO是存在的
  • 交易输入的UTXO没有被其它交易引用,即没有被花费两次(Double Spending)
  • 输入总金额 > 输出总金额
  • 解锁脚本验证

4. 区块的生成

矿工在挖矿之前要先创建区块,区块内需要创建的内容包括:

  • 将coinbase交易打包进区块
  • 将交易池中高优先级的交易打包进区块,其中优先级=交易的额度*UTXO的深度/交易的size,这样做的一方面是考虑到“放粉尘攻击”,单次大批量的小额交易将被延后。
  • 创建区块的头部,头部包括:版本号、父区块Hash(如果父区块进行了任意修改,则Hash值将改变,从而串改将会被发现)、Root of Merkle Tree(所有具体交易信息存储在该树中)、时间戳、难度值、Nonce

5. 区块的传播

挖矿成功后将,将计算出来的随机数Nonce值填入头部,然后向周围广播,相邻区块收到广播以后立即进行如下验证:

  • 验证POW的Nonce值是否符合难度值
  • 检查时间戳是否小于等于当前时间2小时
  • 检查Merkle树根是否正确
  • 检查区块Size要小于区块Size要求的上限
  • 第一笔交易必须是Coinbase交易
  • 验证每笔交易

6.什么是Merkle Tree?

通常我们验证文件完整性的时候都是传输完文件以后再传输一个原文件的Hash值,然后计算文件的Hash与传输得到的Hash是否一致来判断传输的文件是否完整,但文件太大以后都是分块传输的,那么能否只通过小部分的文件块就能验证整个文件的完整性?答案是肯定的。

验证方法:

  • 将文件分块,然后通过各个块构造Markle Tree
  • 传输文件和文件对应Markle Tree上从叶子节点到根节点的补Hash串,计算得到根Hash串
  • 判断计算得到的根Hash串与原始根Hash串是否一致
  • 如果一致则说明数据准确,否则验证失败

如何存储

去中心化意味着无第三方参与交易,从而确保账本公信力。那么账本存储在哪里呢?

比特币并没有中心化的记账系统,而是通过分布式的区块链来记载比特币的拥有权和交易信息。每个比特币的参与者都拥有一份相同的区块链副本,区块链包含着多个随着时间排序的块,后一个块通过哈希指针指向前一个块,形成一个链,从链的顶端通过这个指针,可以一直找到底端第一个块,第一个块成为创世纪块。每个区块记录着前一个区块的哈希散列值,实际上是前一个节点头的哈希散列值,如果想改变一个区块包含的交易,必须改变这个区块之后所有的交易,由于每个区块的产生是需要条件和时间的,并且条件相当苛刻(后续会在共识机制相关的文章中详细说明),因此,一个区块一旦产生,并且被区块链的节点所接受,并且在这个节点之后又产生了一定数量的区块,那么这个区块基本是不可篡改的。

 从上图可见,区块链是由多个区块组成,每个区块是由区块头和区块体组成的,每一个区块头包含着区块的元信息,同时也包含一个指向前一个区块头哈希值的指针,这个指针是防止区块链被篡改的关键信息。区块体包含比特币的交易信息,第一个交易是特殊交易,是奖励给挖矿节点的酬劳,这也是唯一一种可以产生比特币的方式,也就是发行比特币的方式,其余的交易都是转账交易,比特币从一个地址支付给另外一个地址,这也是实现比特币价值转移的唯一方式。总结来看,比特币只有发行和转账两种交易,比特币产生以后只能从一个人转账给另外一个人,而不能凭空消失,比特币发行的总量是有限的,一共2100万,因此是一种通缩性货币。

拥有者如何证明自己拥有比特币?

区块链实际上是比特币的账本,记录着谁拥有多少比特币,只不过这个账本是保存在互联网上的、分布式的,并不是由一个中心机构或者服务器来存储。有了账本,剩下的问题就是比特币的拥有者如何证明自己拥有比特币?就像你在银行开立了一个账户,等你想给其他人转账的时候,你需要在ATM上插入卡,然后输入密码。卡就相当于比特币的地址,密码就相当于比特币的秘钥,有了正确的地址和秘钥,就可以对外宣称自己对比特币的拥有权,就可以把比特币转账给其他人来做一笔转账交易。

在ATM上提取一笔现金,输入密码解锁账户,我们相信ATM机不会泄露密码。那么在比特币的世界里,我们如何通过私钥来校验一个地址上的比特币的归属权呢?

比特币的归属权是通过加密领域技术来实现的,我们先来了解下加密领域的原理,加密领域大体上经过了3个阶段,第一个阶段拼算法,把加密逻辑写在一个非常高深的代码里,后来发现无论把多么复杂的逻辑写在代码里,总有高手可以破解。于是产生了对称秘钥加密,对称秘钥加密通过一个对称的秘钥进行加密数据,然后传输或者保存,需要的时候再通过同一个秘钥进行解密还原原来数据,缺点是秘钥是共享的,无法安全的保存秘钥,尤其是跨组织的场景。后来,聪明的安全科学家们发明了非对称加密算法,例如:RSA,非对称算法拥有一对秘钥,一个公钥和一个私钥,私钥可以推导出公钥,但是公钥不能推导出私钥,公钥加密的数据私钥可以解密,私钥加密的数据公钥可以解密,如果组织A向组织B传递数据,那么组织A使用公钥进行加密,组织B使用私钥进行解密,因此,组织B需要小心的保存好私钥,而公钥是公开的,这是典型的非对称加密场景,能够有效的防止数据被偷窥、被篡改。非对称加密还有另外一个场景,就是签名,签名是加密场景的逆向场景,商户B通过自己的私钥加密数据,然后把加密的数据传递给商户A,商户A通过公钥进行解密,如果解密的数据正确,则说明数据是由A发送的,有效的保证了数据的防篡改,从这两个场景我们看到,公钥是公开的,可发给任何人,私钥是私密的,用来解密或者签名的。

比特币证明归属权的示意图如下:

从上面的过程,我们总结了两个动作,锁定与解锁,这和我们平时锁锁头和开锁头是对应的,在比特币系统里是通过锁定脚本和解锁脚本来实现的。

  • 锁定脚本把比特币关联在一个比特币地址上,证明了比特币归属这个地址。

  • 解锁脚本提供证明,证明这个地址归我所有,这个比特币也归我所有,我可以用来支付。

下面我们举一个例子详细说明:

用户Alice在比特币里地址A上拥有10个比特币,Alice与Bob想做一笔交易,Bob把自己家的汽车卖给了Alice,Alice需要向Bob支付10个比特币,Bob的比特币地址是B。

在之前的交易中,Alice拥有的10个比特币被锁定在Alice的比特币地址A上,其来源可能是挖矿所得或者别人转账而来,我们会在后续详细描述如何获得比特币,这里我们只关注证明Alice拥有比特币的交易的锁定脚本。

锁定脚本的逻辑格式为:

比特币数量 来源 锁定地址
10 挖矿所得 地址A

如果想花费这个锁定脚本,需要的解锁脚本如下:

解锁地址 解锁
地址A 地址A的公钥、地址A用私钥对前一区块头哈希散列值的签名

具体的解锁过程如下:

  • 使用地址A的公匙推导出地址,与地址A对比,如果一致则证明公匙提供正确,进入下一步。
  • 使用地址A的公匙解密签名,如果获得的值与前一区块的哈希散列值一致,则证明解锁成功,可以花费地址上的10个比特币。

其实,锁定和解锁脚本是通过逆波兰表示法的基于堆栈的脚本实现的,由于本文篇幅有限,这里不展开介绍,会在后续的文章中详细介绍锁定和解锁脚本的原理和流程。

挖矿

【共识机制】比特币通过工作量证明的共识机制来决定记账权的。

 工作量大小是通过计算符合某一个标准的比特币区块头的哈希散列值来体现的。试图争夺记账权的节点称为挖矿节点,挖矿节点会把网络节点上发来的交易进行验证,验证后会存入缓冲区,形成一定的交易存储结构(交易使用Merkle树存储),放在区块体中,然后根据区块的基本信息构造区块头,区块头通常包含前一个区块的哈希散列值、Merkle根、时间戳、难度目标、以及一个填充的随机值。这里面的随机值是随机产生并且填充的,挖矿过程就是求出一个能够填充本区块头的随机值,让区块头的哈希散列值符合某一个标准,例如:哈希散列值的前某些位为0,难度目标就是用来表达哈希散列值标准的难度系数,可以通过概率算法计算出难度值与挖矿成功的可能性。

网络上的每一个矿机接收并验证了一批交易,然后就开始进行挖矿,视图计算满足某一难度值的区块头的哈希散列值,如果计算成功,则挖矿成功,向全网广播挖矿所得,全网节点验证后,把这个区块连接到区块的最上端,并且在全网达成一致。矿机需要反复的试验随机填充值来进行求解,一般采用产生随机数,尝试把产生的随机数填充到区块头,然后计算哈希,后续文章会介绍矿机联盟,矿机联盟会把随机数分成多个小区间,分配给联盟中的成员,共同求解。

P2P网络

比特币网络中的节点都是对等的,没有中心化的服务器,节点有不同的类型,不同的类型有不同的职责,我们会在将来的文章中详细介绍,这里我们只介绍全节点,也就是比特币核心客户端的工作机制。

比特币中的全节点除了存储完整区块链,还具有矿工、钱包、路由节点等的角色,他们的职责如下:

  • 矿工:
    就像挖矿的工人一样,做的是体力活,不断的尝试在构造的区块头的随机字段上填充数字,来找到满足一定标准的哈希散列值,如果找到,把此区块连接到区块链的最上端,并且把合法的区块链发送给邻接节点。
  • 钱包:
    区块链记载了创币交易和转账交易,这有别于通常意义的账户系统,通常意义的账户系统记录账户余额,而区块链里面只记录了交易,没有余额,钱包就是用来从区块链中算出某个地址拥有区块的余额,如果你学过关系型数据库,你可以把区块链理解为数据库的索引,也可以认为是一本书的目录。
  • 路由节点:
    负责在去中心化的网络环境中传递交易和区块,一个节点创建一笔交易,并发送给相邻的节点,相邻的节点验证后,再发送给相邻的节点,很快会传遍网络。如果一个节点通过挖矿,找到一个符合标准的区块,这个节点也会用相同的方式传递给相邻节点,然后相邻节点再继续传播下去,让网络的所有节点都达成一致。

P2P网络传播示意图:

猜你喜欢

转载自blog.csdn.net/weixin_40758380/article/details/81296936