区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

时间:2021-03-04 20:32:55

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

作者: AlexTan
CSDN: http://blog.csdn.net/alextan_
Github: https://github.com/AlexTan-b-z
e-mail: alextanbz@gmail.com

前言:

(ps:这是本博主撰写的第二部系列作品,第一部是写的java入门教程,受到了不少读者的喜欢,如果你也喜欢的话,欢迎关注哟!)

本教程主要面向区块链新手,用通俗易懂的方式讲解区块链技术。

本章节内容是以比特币为例讲区块链技术原理。

加密算法:

1. 哈希(hash)算法

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

如图所示,哈希函数,指无论输入什么值,其输出结果为固定长度的字符串的函数,这串字符串就被命名为哈希值。哈希函数它是不可逆的,即是单向的,只能通过输入计算得到输出,不能通过输出得到输入。且只要输入结果不一样,其输出结果也不一样。

SHA256

SHA: Secure Hash Algorithm(安全哈希算法),256代表无论输入什么值(可以是文件、也可以是文本),其输出结果为256位的二进制数。

SHA是美国国家安全局 (NSA) 设计,美国国家标准与技术研究院 (NIST) 发布的一系列密码散列函数,经历了SHA-0,SHA-1,SHA-2,SHA-3系列发展。NSA于2007年正式宣布在全球范围内征集新新一代(SHA-3)算法设计,2012年公布评选结果, Keccak算法最终获胜成为唯一官方标准SHA-3算法,但还有四种算法同时进入了第三轮评选,分别是:BLAKE, GrøSTL, JH和SKEIN,这些算法其实也非常安全,而且经受审查,被各种竞争币频繁使用。
比特币采用SHA256算法,该算法属于SHA-2系列,在中本聪发明比特币时(2008)被公认为最安全最先进的算法之一。除了生成地址中有一个环节使用了REPID-160算法,比特币系统中但凡有需要做Hash运算的地方都是用SHA256。随着比特币被更多人了解,大家开始好奇中本聪为何选择了SHA256,同时对SHA256的安全性发表各种意见,SHA256妥妥经受了质疑,到目前为止,没有公开的证据表明SHA256有漏洞,SHA256依然牢牢抗住保卫比特币安全的大旗。当然大家心里都明白,没有永远安全的算法,SHA256被替代是早晚的事,中本聪自己也说明了算法升级的必要和过程。

而以太访是用的KECCAK-256 算法:SHA3-256(M) = KECCAK [512] (M || 01, 256)

关于区块链的算法演进推荐这篇文章:区块链核心技术演进之路-算法演进

2. 非对称性加密算法

要了解非对称性加密算法就得首先知道对称加密法。加密,就得有秘钥,所谓对称加密,即加密的秘钥和解密的秘钥是同一个秘钥,举个例子:

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

假设一串数字 123456 通过秘钥1 加密得到234567 ,然后也可以通过234567和秘钥1解密得到123456,加密和解密的秘钥相同,我们称这样的加密法为对称加密法。

那么非对称加密法是什么呢?同理,加密和解密的秘钥不相同的加密算法我们称之为非对称性加密算法,加密的秘钥我们称之为私钥,解密的秘钥我们称之为公钥。

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

理解了非对称加密算法,那就好理解数字签名以及交易了。

交易

在比特币中实际上是不存在什么比特币的,而只有UTXO,UTXO 代表 Unspent Transaction Output,即未花费的交易输出。在比特币社区里,Transaction (交易)被简称为 TX,所以上面这个短语缩写为 UTXO。因此,在比特币中是不存在什么余额的概念的,区块当中是没有余额这个字段的,区块当中只有一笔一笔的交易数据,即TX,而余额是通过计算UTXO而得到的。想要深入研究的朋友具体请参照:精通比特币-交易其实并没有什么比特币,只有 UTXO

那么,具体怎样实现一笔交易呢?假设小明要向小红转账1个BTC,那么小明就会发起一笔交易(UTXO),这笔交易会用小红的公钥加密,因此只有用小红的私钥才能解密这笔交易,即只有小红才能花费这笔UTXO。这样就实现了转账。
区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

数字签名

那么,怎么实现数字签名呢?假设要证明一段数字资产是小明的,那么小明就可以用自己的私钥对这段数字资产加密,由于公钥都是公开的,即任何人都可以用小明的公钥去解密这个数字资产,即证明了这个数字资产是属于小明的,这样也就实现了数字签名。

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

2. 区块:

什么是区块呢?可以说区块是区块链技术里最核心的地方,所有交易数据都是储存于此,具体怎么存储数据的呢?为什么大家都在说区块里的数据不可篡改呢?我们接着看。

区块是一种被包含在公开账簿(区块链)里的聚合了交易信息的容器数据结构。它由一个包含元数据的区块头和紧跟其后的构成区块主体的一长串交易组成。区块头是80字节,而平均每个交易至少是250字节,而且平均每个区块至少包含超过500个交易。因此,一个包含所有交易的完整区块比区块头的1000倍还要大。

区块结构

大小 字段 描述
4字节 区块大小 用字节表示的该字段之后的区块大小
80字节 区块头 组成区块头的几个字段
1-9(可变整数) 交易计数器 交易的数量
可变的 交易 记录在区块里的交易信息

区块结构如上表所示,相信区块大小和交易计数器都好理解,也就是说,里面最核心的就是区块头和交易了,区块头就是由几个字段组成的一个80字节的数据结构。那么多交易,为了检索、验证的效率等要求,不可能随便乱存储的,它是用merkle tree(一种数据结构,后面会详细讲)来存储交易数据的。。我们先讲区块头。

区块头

区块头由三组区块元数据组成。首先是一组引用父区块哈希值的数据,这组元数据用于将该区块与区块链中前一区块相连接,看到这里,我想大家应该就明白了区块与区块直接是怎么链接起来的。相信大家都学过链表,链表是通过指针把结构体连接起来的,而区块是通过哈希值来连接区块的。第二组元数据,即难度、时间戳和nonce(与挖矿竞争相关)。第三组元数据是merkle树根(一种用来有效地总结区块中所有交易的数据结构)。

大小 字段 描述
4字节 版本 版本号,用于跟踪软件/协议的更新
32字节 父区块哈希值 引用区块链中父区块的哈希值
32字节 Merkle根 该区块中交易的merkle树根的哈希值
4字节 时间戳 该区块产生的近似时间(精确到秒的Unix时间戳)
4字节 难度目标 该区块工作量证明算法的难度目标
4字节 Nonce 用于工作量证明算法的计数器

区块图:

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

如图所示,区块链的结构大致如此(图中未表示出区块大小和交易计数器两个字段,但不妨碍理解),下面的交易,是Merkle Tree的形式,最下面的叶子节点是每个交易的hash,从下往上数第二层的节点是Hash(A+B),以此类推,一直到树根,上面说道,平均每个区块包含500个交易,图上只画了4个交易,能理解即可。而父区块哈希值是上个整个区块进行哈希运算得到的值,因此,不难理解,一旦某个区块中的任何一个交易或者说任何一个字段发生改变,其整个区块的哈希值也会随着改变,所以在这个区块以后的所有区块都得重新计算(挖矿与共识后面会讲到),想想比特币的第一个区块(即创世块)是从2009年诞生,一直到现在,其累积了多少算力才运算到现在的这个区块,如果想篡改区块当中以前发生的交易,很明显,越早的区块越难以被篡改,因为其消耗的算力是难以估量的。

Merkle Tree

Merkle Tree是一种哈希二叉树,它是一种用作快速归纳和校验大规模数据完整性的数据结构。这种二叉树包含加密哈希值。

在比特币网络中,Merkle树被用来归纳一个区块中的所有交易,同时生成整个交易集合的数字指纹,且提供了一种校验区块是否存在某交易的高效途径。生成一棵完整的Merkle树需要递归地对哈希节点对进行哈希,并将新生成的哈希节点插入到Merkle树中,直到只剩一个哈希节点,该节点就是Merkle树的根。

为了证明区块中存在某个特定的交易,一个节点只需要计算log2(N)个32字节的哈希值,形成一条从特定交易到树根的认证路径或者Merkle路径即可。随着交易数量的急剧增加,这样的计算量就显得异常重要,因为相对于交易数量的增长,以基底为2的交易数量的对数的增长会缓慢许多。这使得比特币节点能够高效地产生一条10或者12个哈希值(320-384字节)的路径,来证明了在一个巨量字节大小的区块中上千交易中的某笔交易的存在。

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

如图所示, 一个节点能够通过生成一条仅有4个32字节哈希值长度(总128字节)的Merkle路径,来证明区块中存在一笔交易K。该路径有4个哈希值(在图7-5中由蓝色标注)HL、HIJ、HMNOP和HABCDEFGH。由这4个哈希值产生的认证路径,再通过计算另外四对哈希值HKL、HIJKL、HIJKLMNOP和Merkle树根(在图中由虚线标注),任何节点都能证明HK(在图中由绿色标注)包含在Merkle根中。

3. 挖矿和共识

相信大部分朋友们都听说过这两个词。挖矿是增加比特币货币供应的一个过程,就相当于银行发行纸币,但银行是中心化的,比特币是去中心化的。挖矿同时还保护着比特币系统的安全,防止欺诈交易,避免“双重支付”,“双重支付”是指多次花费同一笔比特币。矿工们通过为比特币网络提供算力来换取获得比特币奖励的机会。因此可以说是矿工,来维持了整个比特币网络的安全(关于这点下面会接着讲)。

去中心化共识

可以将区块链看作一本记录所有交易的公开总帐簿(列表),比特币网络中的每个参与者都把它看作一本所有权的权威记录。但在不考虑相信任何人的情况下,比特币网络中的所有参与者如何达成对任意一个所有权的共识呢?所有的传统支付系统都依赖于一个中心认证机构,依靠中心机构提供的结算服务来验证并处理所有的交易。比特币没有中心机构,几乎所有的完整节点都有一份公共总帐的备份,这份总帐可以被视为认证过的记录。区块链并不是由一个中心机构创造的,它是由比特币网络中的所有节点各自独立竞争完成的。换句话说比特币网络中的所有节点,依靠着节点间的不稳定的网络连接所传输的信息,最终得出同样的结果并维护了同一个公共总帐。

中本聪的主要发明就是这种去中心化的自发共识机制。这种自发,是指没有经过明确选举或者没有固定达成的共识的时间。换句话说,共识是数以千计的独立节点遵守了简单的规则通过异步交互自发形成的产物。所有的比特币属性,包括货币、交易、支付以及不依靠中心机构和信任的安全模型等都是这个机制的衍生物。比特币的去中心化共识由所有网络节点的4种独立过程相互作用而产生:

▷ 每个全节点依据综合标准对每个交易进行独立验证

▷ 通过完成工作量证明算法的验算,挖矿节点将交易记录独立打包进新区块,

▷ 每个节点独立的对新区块进行校验并组装进区块链

▷ 每个节点对区块链进行独立选择,在工作量证明机制下选择累计工作量最大的区块链

上面提到了工作量证明,可能有的朋友会问,什么是工作量证明呢?简单的理解工作量证明就是证明挖矿节点消耗了多少的算力(可以简单的理解成计算了多少次),才计算出整个区块,那挖矿是怎么进行的呢?我们接着讲。

挖矿

挖矿大致有下面几个过程:

  1. 挖矿首先要进行的是收集比特币网络中刚产生的交易,我们假定个数为500个。
  2. 然后把这些交易通过哈希计算构造成我们上面所讲的Merkle Tree,生成树根
  3. 得到树根后,我们紧接着就是构造区块头,前面两步都是不怎么消耗算力的,这一步最消耗算力的,构造区块头分以下几小步:
    1. 获取版本号
    2. 计算前区块哈希
    3. 添加merkle tree 树根
    4. 计算nonce(前面有提到),同时得到难度目标(最消耗算力的环节)
    5. 计算成功后得到时间戳,区块诞生。

具体什么是nonce呢,我们举个例子:

哈希函数的输入数据的长度是任意的,将产生一个长度固定且绝不雷同的值,可将其视为输入的数字指纹。对于特定输入,哈希的结果每次都一样,任何实现相同哈希函数的人都可以计算和验证。一个加密哈希函数的主要特征就是不同的输入几乎不可能出现相同的数字指纹。因此,相对于随机选择输入,有意地选择输入去生成一个想要的哈希值几乎是不可能的。

无论输入的大小是多少,SHA256函数的输出的长度总是256bit。我们将使用Python解释器来计算语句 “I am Satoshi Nakamoto” 的SHA256的哈希值。

$ python
Python 2.7.1
>>> import hashlib
>>> print hashlib.sha256("I am Satoshi Nakamoto").hexdigest() 5d7c7ba21cbbcd75d14800b100252d5b428e5b1213d27c385bc141ca6b47989e

如上所示,5d7c7ba21cbbcd75d14800b100252d5b428e5b1213d27c385bc141ca6b47989e是”I am Satoshi Nakamoto”的哈希值。改变原句中的任何一个字母、标点、或增加字母都会产生不同的哈希值。

如果我们改变原句,得到的应该是完全不同的哈希值。例如,我们在句子末尾加上一个数字,运行Python脚本。

# example of iterating a nonce in a hashing algorithm's input
import hashlib
text = "I am Satoshi Nakamoto"
# iterate nonce from 0 to 19
for nonce in xrange(20):
# add the nonce to the end of the text
input = text + str(nonce)
# calculate the SHA-256 hash of the input (text+nonce)
hash = hashlib.sha256(input).hexdigest() # show the input and hash result
print input, '=>', hash

执行这个脚本就能生成这些只是末尾数字不同的语句的哈希值。如下显示了我们只是增加了这个数字,却得到了非常不同的哈希值。

$ python hash_example.py

I am Satoshi Nakamoto0 => a80a81401765c8eddee25df36728d732...
I am Satoshi Nakamoto1 => f7bc9a6304a4647bb41241a677b5345f...
I am Satoshi Nakamoto2 => ea758a8134b115298a1583ffb80ae629...
I am Satoshi Nakamoto3 => bfa9779618ff072c903d773de30c99bd...
I am Satoshi Nakamoto4 => bce8564de9a83c18c31944a66bde992f...
I am Satoshi Nakamoto5 => eb362c3cf3479be0a97a20163589038e...
I am Satoshi Nakamoto6 => 4a2fd48e3be420d0d28e202360cfbaba...
I am Satoshi Nakamoto7 => 790b5a1349a5f2b909bf74d0d166b17a...
I am Satoshi Nakamoto8 => 702c45e5b15aa54b625d68dd947f1597...
I am Satoshi Nakamoto9 => 7007cf7dd40f5e933cd89fff5b791ff0...
I am Satoshi Nakamoto10 => c2f38c81992f4614206a21537bd634a...
I am Satoshi Nakamoto11 => 7045da6ed8a914690f087690e1e8d66...
I am Satoshi Nakamoto12 => 60f01db30c1a0d4cbce2b4b22e88b9b...
I am Satoshi Nakamoto13 => 0ebc56d59a34f5082aaef3d66b37a66...
I am Satoshi Nakamoto14 => 27ead1ca85da66981fd9da01a8c6816...
I am Satoshi Nakamoto15 => 394809fb809c5f83ce97ab554a2812c...
I am Satoshi Nakamoto16 => 8fa4992219df33f50834465d3047429...
I am Satoshi Nakamoto17 => dca9b8b4f8d8e1521fa4eaa46f4f0cd...
I am Satoshi Nakamoto18 => 9989a401b2a3a318b01e9ca9a22b0f3...
I am Satoshi Nakamoto19 => cda56022ecb5b67b2bc93a2d764e75f...

每个语句都生成了一个完全不同的哈希值。它们看起来是完全随机的,但你在任何计算机上用Python执行上面的脚本都能重现这些完全相同的哈希值。

类似这样在语句末尾的变化的数字叫做nonce。Nonce是用来改变加密函数输出的,在这个示例中改变了这个语句的SHA256指纹。

为了使这个哈希算法变得富有挑战,我们来设定一个具有任意性的目标:找到一个语句,使之哈希值的十六进制表示以0开头。幸运的是,这很容易!在例8-10中语句 “I am Satoshi Nakamoto13” 的哈希值是 0ebc56d59a34f5082aaef3d66b37a661696c2b618e62432727216ba9531041a5,刚好满足条件。我们得到它用了13次。用概率的角度来看,如果哈希函数的输出是平均分布的,我们可以期望每16次得到一个以0开头的哈希值(十六进制每一位数字为0到F)。从数字的角度来看,我们要找的是小于 0x1000000000000000000000000000000000000000000000000000000000000000的哈希值。我们称这个为目标阀值,我们的目的是找到一个小于这个目标的哈希值。如果我们减小这个目标值,那找到一个小于它的哈希值会越来越难。

简单打个比方,想象人们不断扔一对色子以得到小于一个特定点数的游戏。第一局,目标是12。只要你不扔出两个6,你就会赢。然后下一局目标为11。玩家只能扔10或更小的点数才能赢,不过也很简单。假如几局之后目标降低为了5。现在有一半机率以上扔出来的色子加起来点数会超过5,因此无效。随着目标越来越小,要想赢的话,扔色子的次数会指数级的上升。最终当目标为2时(最小可能点数),只有一个人平均扔36次或2%扔的次数中,他才能赢。

在上面的例子中,成功的nonce为13,且这个结果能被所有人独立确认。任何人将13加到语句 “I am Satoshi Nakamoto” 后面再计算哈希值都能确认它比目标值要小。这个正确的结果同时也是工作量证明(Proof of Work),因为它证明我们的确花时间找到了这个nonce。验证这个哈希值只需要一次计算,而我们找到它却花了13次。如果目标值更小(难度更大),那我们需要多得多的哈希计算才能找到合适的nonce,但其他人验证它时只需要一次哈希计算。此外,知道目标值后,任何人都可以用统计学来估算其难度,因此就能知道找到这个nonce需要多少工作。

比特币的工作量证明和上面例子中的挑战非常类似。矿工用一些交易构建一个候选区块。接下来,这个矿工计算这个区块头信息的哈希值,看其是否小于当前目标值。如果这个哈希值不小于目标值,矿工就会修改这个nonce(通常将之加1)然后再试一次。按当前比特币系统的难度,矿工得试10^15次(10的15次方)才能找到一个合适的nonce使区块头信息哈希值足够小。

校验区块

某个区块诞生后,相应的矿工把它公布到区块链网络,紧接着是其他节点校验这个区块,当新区块在网络中传播时,每一个节点在将它转发到其节点之前,会进行一系列的测试去验证它。这确保了只有有效的区块会在网络中传播。独立校验还确保了诚实的矿工生成的区块可以被纳入到区块链中,从而获得奖励。行为不诚实的矿工所产生的区块将被拒绝,这不但使他们失去了奖励,而且也浪费了本来可以去寻找工作量证明解的机会,因而导致其电费亏损。

当一个节点接收到一个新的区块,它将对照一个长长的标准清单对该区块进行验证,若没有通过验证,这个区块将被拒绝。这些标准可以在比特币核心客户端的CheckBlock函数和CheckBlockHead函数中获得,它包括:

  • ▷ 区块的数据结构语法上有效
  • ▷ 区块头的哈希值小于目标难度(确认包含足够的工作量证明)
  • ▷ 区块时间戳早于验证时刻未来两个小时(允许时间错误)
  • ▷ 区块大小在长度限制之内
  • ▷ 第一个交易(且只有第一个)是coinbase交易
  • ▷ 使用检查清单验证区块内的交易并确保它们的有效性,本书177页
  • ▷ “交易的独立校验”一节已经讨论过这个清单。

每一个节点对每一个新区块的独立校验,确保了矿工无法欺诈。

矿工们验证每笔新的交易并把它们记录在总帐簿上。每10分钟就会有一个新的区块被“挖掘”出来,每个区块里包含着从上一个区块产生到目前这段时间内发生的所有交易,这些交易被依次添加到区块链中。我们把包含在区块内且被添加到区块链上的交易称为“确认”交易,交易经过“确认”之后,新的拥有者才能够花费他在交易中得到的比特币,这也是为什么比特币交易后要等一小段时间交易才能被确认。

矿工们在挖矿过程中会得到两种类型的奖励:创建新区块的新币奖励(创币交易),以及区块中所含交易的交易费(为什么要存在交易费呢?这是为了避免一些用户随意大量产生一些无意义的交易,因为每笔交易都是需要消耗矿工的算力的,同时也是为了给矿工一定的奖励反馈。试想一下,如果没有交易费,像这类用户就会给整个比特币网络带来大量的算力消耗,甚至可能导致整个网络堵塞、瘫痪)。为了得到这些奖励,矿工们争相完成一种基于加密哈希算法的数学难题,这些难题的答案包括在新区块中,作为矿工的计算工作量的证明,被称为”“工作量证明”。该算法的竞争的机制以及获胜者有权在区块链上进行交易记录的机制,这二者是比特币安全的基石。

新比特币的生成过程被称为挖矿是因为它的奖励机制被设计为速度递减模式,类似于贵重金属的挖矿过程。比特币的货币是通过挖矿发行的,类似于*银行通过印刷银行纸币来发行货币。矿工通过创造一个新区块得到的比特币数量大约每四年(或准确说是每210,000个块)减少一半。开始时为2009年1月每个区块奖励50个比特币,然后到2012年11月减半为每个区块奖励25个比特币。之后将在2016年的某个时刻再次减半为每个新区块奖励12.5个比特币。基于这个公式,比特币挖矿奖励以指数方式递减,直到2140年。届时所有的比特币(20,999,999,980)全部发行完毕。换句话说在2140年之后,不会再有新的比特币产生。

矿工们同时也会获取交易费。每笔交易都可能包含一笔交易费,交易费是每笔交易记录的输入和输出的差额。在挖矿过程中成功“挖出”新区块的矿工可以得到该区块中包含的所有交易“小费”。目前,这笔费用占矿工收入的0.5%或更少,大部分收益仍来自挖矿所得的比特币奖励。然而随着挖矿奖励的递减,以及每个区块中包含的交易数量增加,交易费在矿工收益中所占的比重将会逐渐增加。在2140年之后,所有的矿工收益都将由交易费构成。

如果我们拥有可信任的中心化服务机构,状态转换系统可以很容易地实现,可以简单地将上述功能准确编码。然而,我们想把比特币系统建成为去中心化的货币系统,为了确保每个人都同意交易的顺序,我们需要将状态转换系统与一个共识系统结合起来。比特币的去中心化共识进程要求网络中的节点不断尝试将交易打包成“区块”。网络被设计为大约每十分钟产生一个区块,每个区块包含一个时间戳、一个随机数、一个对上一个区块的引用(即哈希)和上一区块生成以来发生的所有交易列表。这样随着时间流逝就创建出了一个持续增长的区块链,它不断地更新,从而能够代表比特币账本的最新状态。

依照这个范式,检查一个区块是否有效的算法如下:

  1. 检查区块引用的上一个区块是否存在且有效。
  2. 检查区块的时间戳是否晚于以前的区块的时间戳,而且早于未来2小时[2]。
  3. 检查区块的工作量证明是否有效。
  4. 将上一个区块的最终状态赋于S[0]
  5. 假设TX是区块的交易列表,包含n笔交易。对于属于0……n-1的所有i,进行状态转换S[i+1] = APPLY(S[i],TX[i])。如果任何一笔交易i在状态转换中出错,退出程序,返回错误。
  6. 返回正确,状态S[n]是这一区块的最终状态。

本质上,区块中的每笔交易必须提供一个正确的状态转换,要注意的是,“状态”并不是编码到区块的。它纯粹只是被校验节点记住的抽象概念,对于任意区块都可以从创世状态开始,按顺序加上每一个区块的每一笔交易,(妥妥地)计算出当前的状态。另外,需要注意矿工将交易收录进区块的顺序。如果一个区块中有A、B两笔交易,B花费的是A创建的UTXO,如果A在B以前,这个区块是有效的,否则,这个区块是无效的。

区块验证算法的有趣部分是“工作量证明”概念:对每个区块进行SHA256哈希处理,将得到的哈希视为长度为256比特的数值,该数值必须小于不断动态调整的目标数值,本书写作时目标数值大约是2^190。工作量证明的目的是使区块的创建变得困难,从而阻止女巫攻击者恶意重新生成区块链。因为SHA256是完全不可预测的伪随机函数,创建有效区块的唯一方法就是简单地不断试错,不断地增加随机数的数值,查看新的哈希数值是否小于目标数值。如果当前的目标数值是2^192,就意味着平均需要尝试2^64次才能生成有效的区块。一般而言,比特币网络每隔2016个区块重新设定目标数值,保证平均每十分钟生成一个区块。为了对矿工的计算工作进行奖励,每一个成功生成区块的矿工有权在区块中包含一笔凭空发给他们自己25BTC的交易。另外,如果交易的输入大于输出,差额部分就作为“交易费用”付给矿工。顺便提一下,对矿工的奖励是比特币发行的唯一机制,创世状态中并没有比特币。

为了更好地理解挖矿的目的,让我们分析比特币网络出现恶意攻击者时会发生什么。因为比特币的密码学基础是非常安全的,所以攻击者会选择攻击没有被密码学直接保护的部分:交易顺序。攻击者的策略非常简单:

  1. 向卖家发送100BTC购买商品(尤其是无需邮寄的电子商品)。
  2. 等待直至商品发出。
  3. 创建另一笔交易,将相同的100BTC发送给自己的账户。
  4. 使比特币网络相信发送给自己账户的交易是最先发出的。

一旦步骤(1)发生,几分钟后矿工将把这笔交易打包到区块,假设是第270000个区块。大约一个小时以后,在此区块后面将会有五个区块,每个区块间接地指向这笔交易,从而确认这笔交易。这时卖家收到货款,并向买家发货。因为我们假设这是数字商品,攻击者可以即时收到货。现在,攻击者创建另一笔交易,将相同的100BTC发送到自己的账户。如果攻击者只是向全网广播这一消息,这一笔交易不会被处理。矿工会运行状态转换函数APPLY(S,TX),发现这笔交易将花费已经不在状态中的UTXO。所以,攻击者会对区块链进行分叉,将第269999个区块作为父区块重新生成第270000个区块,在此区块中用新的交易取代旧的交易。因为区块数据是不同的,这要求重新进行工作量证明。另外,因为攻击者生成的新的第270000个区块有不同的哈希,所以原来的第270001到第270005的区块不指向它,因此原有的区块链和攻击者的新区块是完全分离的。在发生区块链分叉时,区块链长的分支被认为是诚实的区块链,合法的的矿工将会沿着原有的第270005区块后挖矿,只有攻击者一人在新的第270000区块后挖矿。攻击者为了使得他的区块链最长,他需要拥有比除了他以外的全网更多的算力来追赶(即51%攻击)。

共识攻击

当你看到这里的时候,不难理解,攻击方式有两种,一种是篡改以前已经产生的交易,这个难度有多大在前面讲区块的时候有讲到,还有一种攻击就是共识攻击。共识攻击只能篡改某个刚发生的交易或者说可以捏造一个交易,那怎么才能使这个攻击生效呢?很简单,只要你能控制着整个比特币网络中的51%的算力,你就能使你的攻击生效,这也就是常说的51%的攻击。需要注意的是,51%攻击并不是像它的命名里说的那样,攻击者需要至少51%的算力才能发起,实际上,即使其拥有不到51%的系统算力,依然可以尝试发起这种攻击。之所以命名为51%攻击,只是因为在攻击者的算力达到51%这个阈值的时候,其发起的攻击尝试几乎肯定会成功。本质上来看,共识攻击,就像是系统中所有矿工的算力被分成了两组,一组为诚实算力,一组为攻击者算力,两组人都在争先恐后地计算块链上的新块,只是攻击者算力算出来的是精心构造的、包含或者剔除了某些交易的块。因此,攻击者拥有的算力越少,在这场决逐中获胜的可能性就越小。从另一个角度讲,一个攻击者拥有的算力越多,其故意创造的分叉块链就可能越长,可能被篡改的最近的块或者或者受其控制的未来的块就会越多。一些安全研究组织利用统计模型得出的结论是,算力达到全网的30%就足以发动51%攻击了。

全网算力的急剧增长已经使得比特币系统不再可能被某一个矿工攻击,因为一个矿工已经不可能占据全网哪怕的1%算力。但是中心化控制的矿池则引入了矿池操作者出于利益而施行攻击的风险。矿池操作者控制了候选块的生成,同时也控制哪些交易会被放到新生成的块中。这样一来,矿池操作者就拥有了剔除特定交易或者双重支付的权力。如果这种权利被矿池操作者以微妙而有节制的方式滥用的话,那么矿池操作者就可以在不为人知的情况下发动共识攻击并获益。

总结

区块链技术里的每个技术点,里面的每个环节,构成一个生态系统。通过挖矿和共识实现去中心化,通过挖矿的激励机制来鼓励矿工参与挖矿,通过区块链来记账,且保证其安全性、不可篡改,通过私钥公钥来实现签名、发送交易等,这里面的每个技术点构成一个圈,缺少其中一个,圈就围不起来。

画个图

捐助地址:

BTC:

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

36Q4ivp2bJer9fUQ6uyj4a4yLuTpp28D1T

ETH:

区块链入门教程之从比特币到以太访再到智能合约从架构概念到应用实战(DAPP)(二、比特币原理、概念讲解)

0x786fda245ff497ce18e53618369a3e730a18fc1b

ENS: alextan.eth