比特币基础原理

比特币是什么?

比特币是一种基于分布式网络的数字货币。

比特币系统(广义的比特币)则是用来构建这种数字货币的网络系统,是一个分布式的点对点网络系统。


数字货币是什么?

    货币可以承载债务,价格的一般等价物。货币的本质是等价物,它可以是任何东西,如:一张纸,一个数字,只要人们认可它的价值。人民币,美元等作为国家信用货币,其价值由国家主权背书。而数字货币是一种不依赖信用和实物的新型货币,它的价值由大家的共识决定。比特币就是一种数字货币。


运行原理

    银行系统的数据库里记录着客户身份id以及对应的财产,下文称这样的记录为账本,如张三的x卡xx月xx日转入1w, 余额10w;

    比特币系统也同样有这样的账本,不同银行由单一的组织负责记录,比特币的记账由所有运行系统的人共同参与记录,每个节点都保存(同步)一份完整的账本。

    同时使用多数原则,来保证账本的一致性。举个例子:如果有人在自己电脑上把自己的余额从1万改为1百万,他这个账本和大多数人的账本不一致,就会被比特币系统认为是无效的。


比特币使用区块链技术来支撑整个系统的运行,主要包含如下区块技术原理:

区块链记账原理

区块链(1.0):一个基于密码学安全的分布式账本,是一个方便验证,不可篡改的账本。

区块链(2.0): 引入智能合约区块链,如以太坊

区块链(1.0)如何实现?

  • 哈希函数:Hash(原始信息) = 摘要信息,原始信息可以是任意的信息, hash之后会得到一个简短的摘要信息。

  • 哈希函数特点:

        1:  同样的原始信息用同一个哈希函数总能得到相同的摘要信息

        2:  原始信息任何微小的变化都会哈希出面目全非的摘要信息

        3:  从摘要信息无法逆向推算出原始信息

举例说明:

    Hash(张三借给李四100万,利息1%,1年后还本息 …..) = AC4635D34DEF
账本上记录了AC4635D34DEF这样一条记录。

哈希函数作用:

  • 简化信息

  • 标识信息

  • 隐藏信息

  • 验证信息


区块链记账方法

假设有一个账页序号为0的账页交易记录如下:

账号 入账 出账 余额 备注说明
王徐 100w 190w 收到xxx货款
超俊 100w 30w xxxx
李旧 120w 90w 170w xxxx

记账时间为:2017-10-22 10:22:02

区块链在记账是会把账页信息(包含序号、记账时间、交易记录)作为原始信息进行Hash, 得到一个Hash值,如:787635ACDFG, 用函数表示为:

Hash(序号0、记账时间、交易记录) = 787635ACDFG

账页信息和Hash值组合在一起就构成了第一个区块。

在记第2个账页的时候,会把上一个块的Hash值和当前的账页信息一起作为原始信息进行Hash,即:

Hash(上一个Hash值、序号1、记账时间、交易记录) = 456635BCD

这样第2个区块不仅包含了本账页信息,还间接的包含了第一个区块的信息。

依次按照此方法继续记账,则最新的区块总是间接包含了所有之前的账页信息。

所有这些区块组合起来就形成了区块链,

这样的区块链就构成了一个便于验证(只要验证最后一个区块的Hash值就相当于验证了整个账本),

不可更改(任何一个交易信息的更改,会让所有之后的区块的Hash值发生变化,这样在验证时就无法通过)的总账本。


比特币所有权及隐私问题-非对称加密应用

比特币系统是如何确定某个账户的比特币是属于谁的?谁可以支付这个账户比特币?


传统的银行系统:

    首先我们需要把我们的个人信息(如身份证)给银行,银行给我们开立相对应的账户,银行在开户的时候确立了对账户的所有权。

    进行支付的时候,银行对交易双方完成转账


匿名账本

    那么比特币如何在没有第三方银行的参与下,在确保隐私的同时如何确定账户所有权的呢?

    实际上比特币的账户是用地址来表示,账本上不显示个人信息,转账是把比特币从一个地址转移到另一个地址。

转账记录如这样:

{
   "付款地址":"2A39CBa2390FDe"
   "收款地址":"AAC9CBa239aFcc"
   "金额":"0.3btc"
}

下来问题就变为了 谁有权用某个地址进行付款。支付和所有权 实际是同一个问题,如果此比特币只有我可以用来支付,那么说明我拥有所有权。比特币中采用地址和私钥来解决这个问题。

比特币中谁拥有某个地址的私钥(如果完全没有加密概念的人,可以简单的把私钥当作密码),谁就能用这个地址进行支付。

比特币地址和私钥是一个非对称的关系,私钥经过一系列运算(其中有两次Hash)之后,可以得到地址, 但是无法从地址反推得到私钥。

地址: 2A39CBa2390FDe
私钥: sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal

Hash(Hash(fun(sdgHsdniNIhdsgaKIhkgnakgaihNKHIskdgal)))  -> 2A39CBa2390FDe

那么针对上面的交易例子,只有拥有了私钥才能进行下一步的交易。

接下来的问题则更变成如何证明你拥有某个地址的私钥?---》 非对称加密技术

1: 对交易信息进行签名

在签名之前,会先对交易信息进行Hash运算得到摘要信息,然后对摘要信息进行签名。过程大概是这样:

*对交易进行hash, 得到一个摘要信息(Hash值)

hash('
   {"付款地址":"2A39CBa2390FDe",
   "收款地址":"AAC9CBa239aFcc",
   "金额":"0.2btc"
   }') -> 8aDB23CDEA6

用私钥对交易摘要进行签名(付款方在安全的环境下进行,以避免私钥泄密), 用代码表示大概是这样。

1
2
3
4
#参数1为交易摘要
#参数2为私钥
#返回签名信息
sign("8aDB23CDEA6", "J78sknJhidhLIqdngalket") -> "3cdferdadgadg"

2: 广播

    在签名运算之后,付款节点就开始在全网进行广播:我支付了0.2btc到AAC9CBa239aFcc,签名信息是3cdferdadgadg,你们来确认一下吧。

    广播过程实际上是发信息到相连的其它节点,其它节点在验证通过后再转发到与之相连的节点,这样的扩散过程。

    广播的信息包含了交易原始信息和签名信息

3: 验证

    其它节点在收到广播信息之后,会验证签名信息是不是付款方用私钥对交易原始信息签名产生的,如果验证通过说明确实是付款方本人发出的交易,说明交易有效,才会记录到账本中去。

验证过程实际是签名过程的逆运算,用代码表示大概过程是这样的:

#参数1为签名信息
#参数2为付款方地址
#返回交易摘要
verify("3cdferdadgadg", "2A39CBa2390FDe") -> "8aDB23CDEA6"

如果验证输出的信息和原始交易信息的hash一致,则验证通过,记录账本,用代码表示大概是这样:

1
2
3
4
5
6
7
8
if(verify("3cdferdadgadg", "2A39CBa2390FDe")
   == hash('{"付款地址":"2A39CBa2390FDe",
             "收款地址":"AAC9CBa239aFcc",
             "金额":"0.2btc"}')) :
   # 写入账本
   # 广播
else:
  # donothing

比特币挖矿-工作量证明

    比特币记账是把交易记录、交易时间、账本序号、上一个Hash值等信息计算Hash打包的过程。完成记账的节点可以获得系统给与的一定数量的比特币奖励,这个奖励的过程也就是比特币的发行过程,因此大家形象的把记账称为“挖矿”。

    记账是有奖励的,每次记账都可以给自己凭空增加一定数量的个比特币,争相记账会出现记账不一致的问题,比特币系统引入工作量证明来解决这个问题,规则如下:

  • 一段时间内(10分钟左右,具体时间会与密码学难题难度相互影响)只有一人可以记账成功

  • 通过解决密码学难题(即工作量证明)竞争获得唯一记账权

  • 其他节点复制记账结果

不过在进行工作量证明之前,记账节点会做进行如下准备工作:

  • 收集广播中还没有被记录账本的原始交易信息

  • 检查每个交易信息中付款地址有没有足够的余额

  • 验证交易是否有正确的签名

  • 把验证通过的交易信息进行打包记录

  • 添加一个奖励交易:给自己的地址增加12.5比特币

工作量证明

区块记账会把上一个块的Hash值和当前的账页信息一起作为原始信息进行Hash。如果仅仅是这样,显然每个人都可以很轻松的完成记账。

为了保证10分钟左右只有一个人可以记账,就必须要提高记账的难度,使得Hash的结果必须以若干个0开头。同是为了满足这个条件,在进行Hash时引入一个随机数变量。

用伪代码表示一下:

# 没有难度时为:Hash(上一个Hash值,交易记录集) = 456635BCD
Hash(上一个Hash值,交易记录集,随机数) = 0000aFD635BCD

我们知道改变Hash的原始信息的任何一部分,Hash值也会随之不断的变化,因此在运算Hash时,不断的改变随机数的值,总可以找的一个随机数使的Hash的结果以若干个0开头(下文把这个过程称为猜谜),率先找到随机数的节点就获得此次记账的唯一记账权。

计算量分析

    Hash值是由数字和大小写字母构成的字符串,每一位有62种可能性(可能为26个大写字母、26个小写字母,10个数字中任一个),假设任何一个字符出现的概率是均等的,那么第一位为0的概率是1/62(其他位出现什么字符先不管),理论上需要尝试62次Hash运算才会出现一次第一位为0的情况,如果前两2位为0,就得尝试62的平方次Hash运算,以n个0开头就需要尝试62的n次方次运算。

    我们结合当前实际区块#493050信息来看看:

我们可以看到Hash值以18个0开头,理论上需要尝试62的18次方次,这个数是非常非常巨大的,我已经算不清楚了,应该是亿亿级别以上了。如此大的计算量需要投入大量的计算设备、电力等,
目前应该没有单矿工独立参与挖矿了,基本都是由矿工联合起来组成矿池进行挖矿(矿池里的矿工按算力百分比来分收益)。


验证

在节点成功找到满足的Hash值之后,会马上对全网进行广播打包区块,网络的节点收到广播打包区块,会立刻对其进行验证。

如果验证通过,则表明已经有节点成功解迷,自己就不再竞争当前区块打包,而是选择接受这个区块,记录到自己的账本中,然后进行下一个区块的竞争猜谜。
网络中只有最快解谜的区块,才会添加的账本中,其他的节点进行复制,这样就保证了整个账本的唯一性。

假如节点有任何的作弊行为,都会导致网络的节点验证不通过,直接丢弃其打包的区块,这个区块就无法记录到总账本中,作弊的节点耗费的成本就白费了,因此在巨大的挖矿成本下,也使得矿工自觉自愿的遵守比特币系统的共识协议,也就确保了整个系统的安全。