谈到区块链就不得不提一下密码朋克(Cypherpunk):
区块链:
区块链前景:
比特币是一种数字货币,先不谈什么是数字货币,我们先来了解下什么是货币:
一般等价物可以是任何东西,我们可以看看历史中出现的货币代表:
数字货币:
数字货币的信任从何而来:
比特币除了是数字货币外还是一个去中心化的记账系统:
账本如何验证:
那么如果其中有一个人更改了自己电脑上的账本,那么不就会出现假数据了吗。这样情况该如何解决?
例如下图中,通过hash函数计算出了账本的hash值,然后利用hash的特性进行账本数据的比较验证,也就是只需要对比hash值即可,那么就要比对比整个账本数据高效得多。这就好比我们下载文件时,经常会通过MD5来验证文件是否已经损坏或者被修改了:
那么计算出hash值并验证后,这些信息存储在什么地方呢?区块链中账本的hash值和区块序号以及时间戳都存放在区块链的头部分:
假设现在第一个账本已经完成验证且成功记账了(存到区块了),如果这时候又来了一个账本,那么当计算这个新账本的hash时会加上上一个区块(账本)的hash一起进行计算。如下:
可以看到,当出现第二个账本时,对该账本进行hash计算,会将上一个区块的hash也包含进去一起计算,最后得出来的才是这个新账本的hash。
因为在计算下一个区块的hash时必须包含上一个区块的hash一起来进行计算才能得出,所以才会说这些区块是通过hash串起来的。这样也就形成了区块链,每个区块都包含上一个区块的hash,如下:
由于这种下一个区块永远包含上一个区块的hash的特性,那么在进行账本验证的时候,只需要验证最后一个区块即可,因为到区块链中最后一个区块的hash摘要里就是间接包含了前面所有区块的hash,也就是验证最后一个区块时就可以间接验证前面所有区块的正确性,这样就无需整条区块链都进行逐个验证。只需要验证最后一个区块,并且验证的只是hash值,所以在速度上还是很快的。
银行系统:
比特币系统:
我们都知道银行账户与密码是没有紧密联系的,而私钥和地址则是有联系的,因为地址就是通过对私钥进行hash计算得出的,虽然私钥可以推导出地址,但是地址是无法推导出私钥的。银行账户则不是由密码计算出来的,所以私钥不像银行账户的密码那样能够随便重置的。唯一“重置”的办法就是新开一个地址。私有与地址的关系如下:
地址: 2A39CBa2390FDe
私钥: sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal
Hash(Hash(fun(sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal))) -> 2A39CBa2390FDe
{
"付款地址":"2A39CBa2390FDe"
"收款地址":"AAC9CBa239aFcc"
"金额":"0.2btc"
}
付款方需要拥有地址2A39CBa2390FDe的私钥才能进行支付,在不泄露私钥的前提下,如何证明我们拥有某个地址的所有权,也就是如何使用某个地址进行支付?这时候就需要用到非对称加密技术(对交易进行签名):
签名过程大概是这样:
1.对交易进行hash, 得到一个摘要信息(Hash值)
hash(‘
{"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金额":"0.2btc"
}‘) -> 8aDB23CDEA6
2.用私钥对交易摘要进行签名(付款方在安全的环境下进行,以避免私钥泄密), 用代码表示大概是这样:
#参数1为交易摘要
#参数2为私钥
#返回签名信息
sign("8aDB23CDEA6", "J78sknJhidhLIqdngalket") -> "3cdferdadgadg"
签名完成之后,就会开始在全网节点中广播这笔交易,广播内容包括:
广播过程实际上是发信息到相连的其它节点,其它节点在验证通过后再转发到与之相连的节点。比如说A节点发起这笔交易的广播,并让网络中的其他节点进行验证。B节点与A节点相邻,所以先收到这个广播信息,然后又广播给相邻的C节点,C节点又广播给相邻的D节点,如此循环下去,直至广播到整个比特币网络。
在其他节点收到交易信息的广播后,就会进行验证,主要是验证该签名信息是否是付款方使用私钥对原始的交易信息进行签名产生的,以及验证支付方地址是否拥有足够的支付金额。验证过程实际是签名过程的逆运算,用代码表示大概过程是这样的:
#参数1为签名信息
#参数2为付款方地址
#返回交易摘要
verify("3cdferdadgadg", "2A39CBa2390FDe") -> "8aDB23CDEA6"
如果验证输出的信息和原始交易信息的hash一致,则验证通过,记录账本,用代码表示大概是这样:
if(verify("3cdferdadgadg", "2A39CBa2390FDe")
== hash(‘{"付款地址":"2A39CBa2390FDe",
"收款地址":"AAC9CBa239aFcc",
"金额":"0.2btc"}‘)) :
# 写入账本
# 广播
else:
# donothing
回顾一下签名及验证:
### 签名 ###
#参数1为交易摘要
#参数2为私钥
#返回签名信息
sign("8aDB23CDEA6", "J78sknJhidhLIqdngalket") -> "3cdferdadgadg"
### 验证 ###
#参数1为签名信息
#参数2为付款方地址
#返回交易摘要
verify("3cdferdadgadg", "2A39CBa2390FDe") -> "8aDB23CDEA6"
可以看到签名是对交易的摘要信息以及私钥进行计算,得出签名信息。而验证则是通过对签名信息和付款方地址进行一个逆运算得出交易的摘要信息,能够成功逆运算得出交易的摘要信息就代表验证通过,继续广播。
整个的交易过程及运算都不包含用户的个人信息,保证了匿名、隐私。在安全性上,由于没有第三方机构或信用中心,所以不会有人能够冻结或减少你账户的金额。账户的所有权都在我们手上,只要私钥不泄露,就能够保证账户的安全性。
补充说明
上面为了更好的理解,我对一些信息进行了简化。
比特币系统使用了椭圆曲线签名算法,算法的私钥由32个字节随机数组成,通过私钥可以计算出公钥,公钥经过一序列哈希算法和编码算法得到比特币地址,地址也可以理解为公钥的摘要。
记账工作:
挖矿 - 工作量证明:
Hash(上一个Hash值,交易记录集,随机数) = 0000aFD635BCD
在进行工作量证明之前,记账节点会收集交集记录集,获取方式:
工作量分析,我们简单分析下记账难度有多大,Hash值是由数字和大小写字母构成的字符串,每一位有62种可能性(可能为26个大写字母、26个小写字母,10个数字中任一个),假设任何一个字符出现的概率是均等的,那么第一位为0的概率是1/62(其他位出现什么字符先不管),理论上需要尝试62次Hash运算才会出现一次第一位为0的情况,如果前两2位为0,就得尝试62的平方次Hash运算,以n个0开头就需要尝试62的n次方次运算。我们结合当前实际区块#522302信息来看看:
注:数据来源于 https://blockchain.info
以上这是一个真实的区块,区块的序号为522302,而该区块工作量证明的hash值以20个0开头,理论上需要尝试62的20次方次,这个数是非常非常巨大的,我已经算不清楚了,应该是亿亿级别以上了。如此大的计算量需要投入大量的计算设备、电力等。可想而知这个计算量是惊人的,靠单台计算机是无法计算出来的,所以现在的矿工都是组成矿池进行挖矿(矿池里的矿工按算力百分比来分收益)。
验证
在节点成功找到满足的Hash值之后,会马上对全网进行广播打包区块,网络的节点收到广播打包区块,会立刻对其进行验证。
如果验证通过,则表明已经有节点成功计算出符合条件的hash,自己就不再竞争当前区块打包,而是选择接受这个区块,记录到自己的账本中,然后进行下一个区块的竞争。
网络中只有最快得出hash的区块,才会添加的账本中,其他的节点进行复制,这样就保证了整个账本的唯一性。
假如节点有任何的作弊行为,都会导致网络的节点验证不通过,直接丢弃其打包的区块,这个区块就无法记录到总账本中,作弊的节点耗费的成本就白费了,因此在巨大的挖矿成本下,也使得矿工自觉自愿的遵守比特币系统的共识协议,也就确保了整个系统的安全。
上一小节我们介绍了,完成工作量证明才能获取唯一记账权。但是当很多的矿工同时进行挖矿,就会出现两个节点同时完成工作量证明的情况,这种时候该使用谁的区块?这就涉及到比特币中的共识机制了:
下面我们简单描述一下分叉的产生及解决,当不同的矿工同时挖出同一个区块时,就会产生区块链的分叉,如下:
注:因为区块是保存上一个区块的hash,所以箭头是指向上一个区块的
如上图,在3457这个区块上,产生了分叉,在同一时间上分别出现了3458A和3458B两个区块。此时,分叉不会马上得到解决,而是3458A和3458B两个区块都会分别被广播到比特币网络中。比特币网络中的节点视网络的情况,会分别接收到3458A或3458B的广播,也可能同时接收到3458A和3458B的广播。只接收到3458A的节点,会基于3458A区块上进行挖矿,而只接收到3458B的节点,则会基于3458B区块上进行挖矿。如果同时接收到3458A和3458B的节点,会先判断哪个区块的工作量更大,然后就基于工作量最大的那个区块上进行挖矿,另一个区块则放在一个备用区块池里。因为网络是不确定的,万一最后是备用区块池里的那个区块是有效的,则会把那个区块替换回去。
我们以上提到了不同的节点只会在各自接收到的分叉区块上进行挖矿,这样不同的分叉链之间就会进行一个竞争,最后始终是有一个分叉区块链的区块产出慢了一步,这样另一个分叉的区块链会变得更长一些,那么最终所有节点就会以那条最长的链作为主链。这样分叉就得以解决了。说白了就是由于分叉出现的两条区块会进行竞争,最终总是能竞争出一个最长的区块链,那么网络中的节点就会以那条最长的区块链为准。例如,最终是3458B所在的链先产出下一个区块,成为了最长的区块链那么就会以3458B所在的链为准:
原文地址:http://blog.51cto.com/zero01/2115489