用比特币更好地理解区块链
1 区块链是什么
- 区块链是一个分布式数据库,具备分布式存储、分布式记录、去中心化、分布式维护等特性
- 区块链1.0 可编程货币:数字化货币及支付系统
- 区块链2.0 可编程金融:股票、清算、私募、股权等金融领域
- 区块链3.0 可编程社会:公正、仲裁、审计、物流、医疗等领域
区块链应用做为人熟知的就是比特币。
1.2 区块链核心技术
- 密码学和数字签名用于身份地址标识
- 共识算法用于工作量证明
- 分布式存储技术用于存储交易记录和区块,分布式网络技术用于网络通信和节点发现
1.3 区块链本质
- 区块链本质是一个分布式数据库
- 区块链是公开的数据库,不是私人的数据库
- 区块链是加密货币和智能合约的基础
1.4 区块链组成链式结构
- 区块链是有着特定结构的数据库,一个有序后向连接的列表
- 区块按照插入的顺序进行存储,每个块都被连接到前一个块
- 快速地获取链上的最新块,并且高效地通过哈希来检索一个块
1.5 区块链主要技术名词
- 交易(Transaction),一次状态转移操作,在比特中一次交易就是一次转账,在fabric中就是一次对键值对的增删改查
- 区块(Block),交易的集合
- 链(Chain),区块的顺序排列
1.6 区块链类型
- 公有链,任何人都可以随意的加入和退出,比如比特币,以太坊
- 联盟链,主要用于商业团体之间的商业合作,所有的节点不是随意加入和退出的,比如Fabric
- 私有链,主要用于内部之间的商业共享
1.7 区块链特点
- 去中心化
- 去信任化(去中介)
- 数据共享
- 不可篡改(不是不可修改)
1.8 区块链中用到的重要技术
- P2P网络协议,Hyperledger Fabric使用gRPC对等服务实现
- 密码学知识——哈希,将不定长度的数据转换成固定长度的哈希值,常见的哈希算法有MD5,SHA1,SHA2(SHA2-256)等,区块链中用的最多的是SHA2-256。
- 密码学知识——加解密算法,非对称秘钥加密技术,区块链用的最多的是椭圆曲线算法
2. 比特币是什么
2.1 比特币是一种数字货币
一串数字可以当成一种货币,那么这串数字就叫数字货币,它是一种虚拟货币。
2.2 信任从何而来
- 财产只受自己的私钥控制
- 无通胀,不会因为通货膨胀而贬值,比特币的总量是不变的,总共是2100万个
- 没有假钞,任何作弊的支付无法得到比特币网络中其他旷工的认可
- 流通性好,点对点直接到账,没有银行这样的中转站,流通性比较好
2.3 去中心化记账系统
中心化的系统会有一个中心化的服务器来存储数据,通常是MySQL这样的数据库,这样就是一个中心化的服务器来存储数据。
比特币这样的去中心化的系统的数据不是存储在*化的数据库中,而是存储在比特币网络中每一个节点里,对于记账系统,也就是每一个节点都会有这样的账本。
那么比特币网络怎么保证这样的账本是有效的,换句话说如果有人单方面修改了账本,那么这个系统会出现什么样的问题?
3 比特币原理
3.1 账本如何验证?
账号 | 收入 | 支出 | 余额 |
---|---|---|---|
王二 | 100 | 190 | |
张三 | 100 | 30 | |
李四 | 120 | 90 | 170 |
赵五 | 300 | 500 |
上面的账本数据,分别存储在王二这四个人的数据库中。
如果这个时候上三把自己的余额改成了300,那么这个网络中就会存在一些假的数据,那么如何确认张三的这份数据是一个假的数据呢。
方案一
核对账本记录,少数服从多数。只要把张三的账本记录和其他人的账本进行核对,发现张三的账本不一样,那么少数服从多数的原则,张三的账本就是有问题的。
这个方案会有一个问题就是,如果有100万个节点,那个每次对账就需要和100万个节点的账本进行核对,效率很低很低,所以这只是一个思路,但是是绝对行不通的。
如果是中心化的系统,即上述的账本只存储在一个中心化的服务器中,那么假如这个账本被篡改了的话,在中心化的系统里面,基本上没办法验证账本的真实性,因为只有中心化的服务器中有这个数据,其他人是没有办法证明数据的真实有效性的。
比特币是怎么做的
比特币使用了哈希函数,做了如下的运算
哈希函数:Hash(原始信息) = 摘要信息
哈希函数的特点:
- 同样的原始信息用同一个哈希函数总能得到相同的摘要信息
- 原始信息只要发生了变化,哪怕是改变了一个字母,那么通过哈希函数算法来的摘要值也会完全不一样
- 从摘要信息无法逆向推导出原始信息
账号 | 收入 | 支出 | 余额 |
---|---|---|---|
王二 | 100 | 190 | |
张三 | 100 | 30 | |
李四 | 120 | 90 | 170 |
赵五 | 300 | 500 |
还是刚才这个账本,假如账本序号是0,账本有个最后更改的时间戳,再加上账本中的这些交易记录,通过某种哈希函数对上述信息做一个哈希运算,得到一个摘要信息。对账的时候,如果摘要信息和其他人的摘要信息能够对上的话,那么它的原始信息也是一样的,因为只有相同的账本信息才能得到相同的摘要信息。这样对比起来与对比账本的原始信息来看,这样的效率就要快的多。
这样的序号,时间戳,哈希值,还有账本的交易记录,就形成了一个区块。通常把序号,时间戳和哈希值叫做区块的头
假如几分钟之后,账本的信息发生了变化,账本中多了几条交易记录
账号 | 收入 | 支出 | 余额 |
---|---|---|---|
刘五 | 200 | 290 | |
丁六 | 10 | 30 |
上面这个账本的序号是1,并且有他自己的时间戳,那么这个区块的哈希值就是像下面这样运算
Hash(第一个账本的哈希值,序号1+新的时间戳+账本信息)= 新的哈希值
在对这个账本进行哈希的时候,会加入第一个账本的哈希值,这样作为一个原始的哈希值去做哈希函数。这样第二个区块就形成了,它包含了这个区块的哈希值,并与之前的区块形成一个单链,按照这样的方式以此类推就可以接着往后产生第3个块,第4个块,第n个块,这其实就是区块链。
这样一来逻辑就清晰了,在验证账本的时候,如果区块二的哈希值能够对上,说明区块二的账本信息与他前面的账本信息都是对的;如果区块二的哈希值没有对上,那么就验证一下它前面的区块一的哈希值,如果区块一的哈希值能够对上,说明区块一的账本信息与它前面的账本信息(区块0)都是对的,那么就是区块二的账本信息有问题了。以此类推依次往前验证。
每个节点在核对数据的时候,只需要核对最后一个区块的摘要信息,如果最后一个区块的摘要信息正确的话,那么证明整个区块链的账本是正确的,这样就可以完成高效的账本验证。
3.2 所有权问题
比特币系统里是怎么来确定某个账户的比特币是属于谁的,谁可以来支付整个账户下的比特币。
银行系统
刷卡的时候需要提供银行卡号与密码,如果对上了就可以付款了。如果发生了盗刷怎么办呢,有人捡到了你的银行卡,并且知道了你的密码,怎么证明这个银行卡的账号是我的,而不是盗刷的人的。
打比方我的卡被盗刷了,那么我就会去*那边报案,然后到银行验证我的信息。银行那边在开户的时候,都会要求我们填个人的信息,包括信息,身份证号,手机号等等,现在也会有拍照等等。等身份确认了时候,确认了这个卡就是我的,如果确认了那笔盗刷的交易不是我发起的后,可能就会撤回这笔交易(当然了这个只是我自己想的是这样)。
说到底,银行系统中在开户的时候就确定了账户的所有权问题。
比特币系统
比特币系统里是点对点的交易,如何在没有第三方介入的情况下确定账户的所有权。
在比特币系统中账户是由地址表示的,一条转账记录即使包含下面类似的东西
{
"付款地址": "xxxxxx",
"收款地址": "yyyyyy",
"转账金额": "0.2btc"
}
记录了从xxxxxx到yyyyyy的一条转账记录,转账了0.2个比特币。谁能够从xxxxxx进行支付,谁就拥有这个账户的所有权。
比特币是通过地址来记录账户的,同时还会拥有一个私钥,谁拥有这个地址对应的私钥,谁就可以通过这个账户来支付。
地址: xxxxxx
私钥: sdgbsgksdbasdksad
如果私钥泄露了的话,比特币就有可能丢失,没法像银行这样忘记密码或者重置密码之类的。
如何在不泄露私钥的情况下,证明账户所有权(拥有某个地址的私钥)
利用非对称加密技术对交易进行签名。
- 对交易进行hash得到摘要
- 用私钥对摘要进行签名
签名过程:
-
对原始的交易记录进行hash运算得到摘要信息
hash('{ "付款地址": "xxxxxx", "收款地址": "yyyyyy", "转账金额": "0.2btc" }') -> 8aDB23CDEA6
-
用摘要信息和私钥进行一个签名运算,得到签名信息
#参数1为交易摘要信息 #参数2位私钥 #返回签名信息 sign("8aDB23CDEA6","378sknJhidhLIqdngalkt") -> "3cdferdadfadg"
-
在签名运算之后,付款的节点就会在整个网络进行广播,包含交易的原始信息,交易的签名信息。网络中的节点就会帮他验证这笔交易,交易通过之后就会再向相邻的节点进行广播。
-
节点收到广播信息以后,就会进行验证,验证签名的信息是不是付款方用私钥对原始交易信息进行签名的。用签名信息与付款方地址进行验证的值是否是原始交易信息的摘要
#参数1位签名信息 #参数2位付款方地址 #返回交易摘要 verify("3cdferdadfadg","xxxxxx") -> "8aDB23CDEA6" if(verify("3cdferdadfadg","xxxxxx") == hash('{ "付款地址": "xxxxxx", "收款地址": "yyyyyy", "转账金额": "0.2btc" }')): # 验证通过,交易信息写入账本 # 广播 else: # donothing
这个签名和验证其实是一个逆运算。付款的地址可以理解为公钥,签名的过程其实是对摘要进行加密的过程,验证是一个解密过程,用付款地址公钥和签名信息进行解密,就得到了摘要。
#参数1为交易摘要信息
#参数2位私钥
#返回签名信息
sign("8aDB23CDEA6","378sknJhidhLIqdngalkt") -> "3cdferdadfadg"
#参数1位签名信息
#参数2位付款方地址(公钥)
#返回交易摘要
verify("3cdferdadfadg","xxxxxx") -> "8aDB23CDEA6"
所以这笔交易由私钥加密之后,才会被其他节点验证通过,因此账户的所有权是由私钥来控制的
3.3 为什么记账?(挖矿)
记账是一个hash打包的过程,这是需要消耗计算机资源的,比特币网络中的节点为什么会主动愿意消耗自己的计算机资源来帮其他节点记账呢?比特币系统做了一个奖励,完成记账的节点可以获得系统一定数量的比特币奖励的。这个也是比特币发行的一个过程。
规则
既然有奖励,那么比特币网络中的节点就会争相记账,这个时候就会设置一定的记账规则
- 一段时间(通常是10min)内只可以有一人可以记账成功
- 通过解决密码学难题(即工作量证明)竞争获得唯一记账权
- 其他节点复制记账结果
工作量证明
什么是工作量证明?
- 工作的结果作为数据加入区块链称为一个区块
- 完成这个工作的人也会获得奖励(这也就是通过挖矿获得比特币)
- 整个“努力工作并进行证明”的机制叫做工作量证明
之前说过节点在计算哈希值的时候,是采用下面的方式计算的
Hash(上一个Hash值,交易记录集) = 456635BCD
如果仅仅是上述工作量,那么每个节点都可以记账。为了保证一段时间内只有一个人可以记账的话,就必须要提高记账的难度。比特币要求得到结果的哈希值必须满足一定的条件,必须要以n个0开头。在计算Hash的时候,就需要引入一个变量,不断地改变变量的值,每次都可以得到一个全新的哈希值,只要不断地改变随机值,总可以找到一个随机值是满足这个条件的
Hash(上一个Hash值,交易记录集,随机数) = 00004aFD635BCD
现在的电脑通常得到一个4个0开头的哈希值需要2分钟左右,比特币现在矿工非常多,现在需要算的n个0,这个n值已经很大了。率先找到这个满足要求的哈希值的节点,就可以获得唯一的记账权
交易记录集
交易记录集是如何得到的
- 收集广播中还没有被记录账本的交易
- 验证这些没有记录交易的有效性,验证签名,验证这个付款地址有没有足够的余额
- 在交易集里会添加一笔给自己转账的交易(挖矿奖励),添加一笔给自己的地址,转12.5个比特币,如果这个节点比其他节点更快地找到哈希值的话,那么整个交易会被打包成区块放到区块链中,这样的打包的节点就会获得这个奖励
3.4 以谁的账本为准?(共识机制)
如果两个节点同时完成工作量证明,使用谁的区块?
采用工作量最大的链条作为总账本