Hang

Blockchain

2017-08-12

介绍#

区块链是由一串使用密码学方法产生的数据块组成的,每一个区块都包含了上一个区块的哈希值(hash),从创始区块(genesis block)开始连接到当前区块,形成块链(类似数据结构中的链表).每一个区块都确保按照时间顺序在上一个区块之后产生,否则前一个区块的哈希值是未知的。

其优势在于:

  • 完全分布式的,无中心节点(单点故障)
  • 任何节点都可以创建交易。在经过一段时间的确认之后,就可以合理地确认该交易是否有效。
  • 修改交易记录的成本非常高

区块链也是比特币等技术的基础。它也是一种非常重要的新思想,促使人们对现有的网络,社会,经济等进行重新思考。

区块结构#

头结构#

大小(bytes) 字段 描述
4 版本 版本号
32 父区块哈希值 引用区块链中父区块的哈希值
32 merkle 根 该区块交易的 merkle 树根的哈希值
4 时间戳 该区块产生的近似时间(精确到秒的 unix 时间戳)
4 难度目标 该区块工作量证明算法的难度目标
4 Nonce 用于工作量证明算法的计数器

区块结构#

大小(bytes) 字段 描述
4 区块大小 该字段之后的区块大小
80 区块头 区块头结构 (上面的大小之和)
1-9 可变整交易计数器 交易的数量
可变 交易 记录在区块里的交易信息

创世区块#

比特币区块链的第一个区块,创建于 2009 年,我们称之为创世区块。它是比特币区块链里所有区块的共同祖先,这意味着你从任一区块,循链向后回溯,最终都将到达创世区块。每一个节点都“知道”创世区块的哈希值、结构、被创建的时间和里面的一个交易。因此,每个节点都把该区块作为区块链的首区块,从而构建了一个安全的、可信的区块链的根。

创世区块的哈希值为

0000000000 19d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

分叉#

对于区块链中的任意一个区块,到达创世块的路径只有一条。然而,从创世块开始,会有分叉的情况出现。当创建两个区块的时间差只有几秒时,经常会创建出一个分叉区块。这时候不同的客户端可能接收到的区块不一样,然后各自在这个基础上继续拓展新的区块,直到有一个较长的出现,则作为主链条.其他的视为无效.

如上图所示,绿色区块为创世区块。黑色区块为主区块(主链条),紫色的称为 orphan blocks. 主链条的累积工作量是最大的,并不总是区块长度(高度)最长的。

Proof-of-work(工作量证明)#

区块链从第一个区块开始,依赖于旷工们去拓展链条的长度。矿工们都进行一些数学计算,谁先算出一个合法的目标数值就可以宣称自己挖到了一个新的 Block.这种检验的方式可以成为“工作量证明”(以下简称为 POW).POW 在 blockchain 之前就已存在,应用于垃圾邮件过滤以及防范拒绝服务攻击扥等。其基本原理都是相同的,但不同的系统会应用不同的 hash 算法以及进行不同长度的难度调整。下面以垃圾邮件的过滤为例来简要说明一下:

邮件 Header#

基本原理: 发送邮件的人需要在邮件的 Header 里加一条,里面是一个字符串,字符串里包含了发送的时间,接受者邮件,以及一个随机数等。这个字符串的哈希值必须符合一定的条件(前置 N 位为 0).有了这样的要求,发送者必须经过暴力破解方式来尝试出一个合法的值,需要消耗一定的计算量。对于接受者来说,它可以很快地检验出来这个字符串是否满足要求(hash 函数的单项特性).对于前者来说,增加 N 之后计算难度会成指数级增长,而对于后者来说校验时间是固定的。对于普通的邮件接收来说,这两个时间都是可以忽略不计(通常在 s 级之内)的。 但对于垃圾邮件的发送者来说,因为他需要发送大量的邮件,这个时间累积起来就很可观了。所以可以有效地进行垃圾邮件的过滤。

Header 格式如下

X-Hashcash: 1:20:1303030600:adam@cypherspace.org::McMybZIhxKXu57jd:ckvi

  • 1 : Hashcash 版本
  • 20 : hash 值的前置 0 的个数
  • 1303030600 : 发送邮件的时间
  • adam@cypherspace.org: 接收者
  • (ext): 扩展(Version 1 里忽略)
  • McMybZIhxKXu57jd : 随机数的 base64
  • ckvi: 计数器的 base64

上面包含了接受者,所以对不于不同的邮件接收人,哈希值都要重新计算。

对于发送者来说:

  1. Header 中包含了接受者,所以对不于不同的邮件接收人,哈希值都要重新计算。
  2. 首先设一个初始化的 Header(包含一个初始的随机数),然后开始计算 160 位的SHA-1 hash 值。如果前 20 位为 0,那么成功生成一个合法的 Header.如果不成功,增加计数器继续计算。平均下来每次大概需要2^20次计算能得到一个合法的值。

对于接收者来说:

  1. 根据 Header 内容计算哈希值,判断前二十位是否为 0.这是有一个耗时固定的操作,而且远比发送者所耗资源要少
  2. 检查发送时间及邮件是否正确
  3. 将 hash 值入库,如果已经存在,则视为非法

在 Linux/Mac 上可以用openssl的命令来进行一个简单地校验:

echo -n 1:52:380119:calvin@comics.net:::9B760005E92F0DAE | openssl sha1
0000000000000756af69e2ffbdb930261873cd71

(注意 52 是要求二进制的 0,上面的结果是 13 位 10 进制的)

Bitcoin#

挖矿的流程与上面非常类似,只是具体的变量不同. 挖矿的公式可以概括为如下所示:

SHA256(SHA256(version + prev_hash + merkle_root + ntime + nbits + x )) < TARGET

目的就是找到一个合适的 x(0~2^32)

  • SHA256: hash 算法
  • versio: block 的版本
  • prev_hash: 上一个 block 的 hash 值
  • merkle_root: 需要写入的交易记录的 hash 树的值
  • ntime: 更新时间
  • nbits: 当前难度

    TARGET 越小,解出 x 的难度就越大(类比于前面的邮件的例子就是前置的 0 越多,计算的次数越多).

    一旦你找到了 x,你就可以广播一个新的 block,其他客户端会验证你的 block 是否合法。如果你的 block 被接受,由于每个 block 中的第一笔交易必须是将新产生 25 个比特币发送到某个地址(public key),当然你会把这个地址设为你所拥有的地址来得到这 25 个比特币。

REF#

  1. Wiki
  2. Hashcash