时间戳服务与存在证明

存在证明

存在证明就是向第三方证明某个物品/事件,在过去的某个时刻存在过。

这是一件很简单的事情,提供票据、通信记录之类的就可以办到。但这些并不严格,因为这些证据都是非常易伪造或销毁。要完成证明,必须依赖强有力的证据链,这个必须是任何人都无法伪造与销毁的,或者说伪造成本极其高昂近乎不可能。

回忆一下,电影里经常出现的绑匪镜头,他们为了证明在某个时间确实拥有人质,而不是事前拍摄的视频,通常会用当天的发行量很大的报纸来辅助证明。当香港媒体误报“成龙高楼坠亡”时,成龙也不得不拿报纸来证明自己的存在:

124897097_11n

报纸之所以能够成为有效的时间证明系统是因为:

  1. 不可伪造性。新闻等信息是无法预测的,尤其是证券大盘数据,报纸上大量充满这样的信息,所以无人能够提前伪造。
  2. 公开且不可销毁。报纸通常拥有很大的发行数量,受众广泛,一旦发布出去就分散到各个角落,很难再次收集齐全并全部销毁。通常图书馆也会存档数十年期限的报纸。
  3. 具有时间特征。报纸具有很强时间特征,版面到处可见的是时间标记。

借助报纸可以完成某个时间之后的存在证明,但无法完成某个时间之前的。例如,你拿9月1号的报纸拍摄进照片,那么仅能证明其在9月1号之后拍摄,可能是9月1号,也可能是9月15号。

时间戳服务

比特币本质是构造了一个永不停息、无坚不摧的时间戳系统

qq20130804-9

然后该系统上添加若干特性后使得具有货币的功能。报纸从另一个角度讲也是一种时间戳服务。

比特币具有下列优良的特性可以更完美的用于存在证明:

  • 不可预测/伪造。因block的计算是随机事件,其hash值是一个32字节的随机大数(2^256)。想蒙对该数的概率实在是太低了。
  • 不可销毁/修改。Block Chain拥有巨大的算力在维护与延续,对于N个确认的block,想篡改是不可能的。
  • block具有天然时间特性。timestamp是block meta字段之一。
  • block可以存储信息。对于block meta信息,是无法控制的。但block会收录交易,而交易是可以”写入”自己的数据。

数字摘要

简单来说,对一串数据进行Hash运算,得到的Hash值称为数字摘要。除了Hash函数,还有其他方式,如密钥签名等也可以得到。Hash值通常是一个非常巨大的数,例如用SHA256时,Hash值区间非常大:1~2^256。数字摘要的计算过程不可逆,那么可以认为:

欲证明你拥有某个文件,提供该文件的Hash值(及Hash函数)即可。第三方可以轻易验证文件的Hash值来判断之。

比特币做存在证明

时间点后向证明

因为block hash的不可伪造性,能提供Block Hash即可证明存在于该Block时刻之后。例如,你在拍照的时候,拿着打印有block hash的纸即可证明:你在该block时刻之后进行的拍摄。

时间点前向证明

前向证明需要精心构造一个包含数字摘要的交易,待该交易进入block中。便可以证明你在该block时刻之前拥有该数字摘要。前向证明的关键是能把信息写入时间戳服务载体

时间区间证明

有时候,仅仅证明时间点之前或之后是不够的,需要能够确认到某一个时刻。将上述方式综合即可完成:

  1. 将block A的hash值添入数据文件,并制作文件数字摘要。(时间点后向证明)
  2. 将摘要信息构造至交易中,广播之。(时间点前向证明)
  3. 当交易被block B收录进去,那么即可证明,该文件于block A与B的时间间隔中存在。

如果交易给了足够的矿工费(Transaction Fee),具有较高优先级的话,便很有可能被紧随其后的block收录。连续的block约10分钟,那么就在一个相对小的时间内作了证明,可以近似认为是时间点。

构造特殊交易

带有数字摘要的交易如何构造呢?下面以32字节的数字摘要为例,提出数个可行方法,其他长度的可变换得出。

方式一:交易额承载信息

32字节可以分割为16个双字节,每个双字节的数值范围是:0~65535。比特币的现行单位可以分割至小数点后八位,那么我们可以利用最后的5位来存放一个数值,一共需要16个输出(Tx output)即可完成32字节的信息存储。中间涉及比特币最大数量为:

.00065535 * 16 = .0104856 btc

需要的比特币数量很少,约0.01Btc,且输出依然发回给自己的地址,唯一的代价就是付出矿工费(Tx Fee)。任何人都可以使用之。

SatoshiDice种子文件时间证明

著名站点SatoshiDice就是采用这种方式为其服务端种子文件做时间前向证明的。下面演示一下步骤。服务端的种子文件为hash.keys,我们对其做SHA256运算,得到hash值,32个字节。

$ sha256sum hash.keys
# hash of file "hash.keys", in hex:
9b0d87ac871518cfd8601aa456b58fa74c01194cfeb25e7f3eecf43759d6ccb4  hash.keys

将该hash转为16个10进制数值:

9b0d = 39693
87ac = 34732
8715 = 34581
18cf = 6351
d860 = 55392
1aa4 = 6820
56b5 = 22197
8fa7 = 36775
4c01 = 19457
194c = 6476
feb2 = 65202
5e7f = 24191
3eec = 16108
f437 = 62519
59d6 = 22998
ccb4 = 52404

将这16个数除以10^8,作为输出额度,构造交易

qq20130812-2

交易被收录,证明完成。

方式二:数字摘要的Hash作地址输入

回顾一下地址的生成算法(下图是一个未压缩公钥生成地址的过程,公钥是否压缩对该证明过程没有影响):

qq20130812-3

我们用数字摘要的Hash值代替图中红色框中的值,然后得到一个地址,我们把0.00000001 btc打入该地址,形成交易,收录后完成证明。验证时,需要首先得到数字摘要hash值,再生成对应的地址,核对地址是否一致即可。

这个方法有个缺点,打入该地址的币永远消失了,因为没有其对应的私钥。虽然可以只需1聪,目前价值几乎忽略不计,但毕竟浪费了。该方法可以进一步衍生一些类似的方法。曾有个网站使用之,后来该网站关闭了。

方式三:数字摘要的Hash作私钥

大小介于1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之间的数,都可以认为是一个合法的私钥,其大小为32字节。那么,可以把数字摘要的Hash作私钥,并推算出公钥和地址。

将任意币值输出至该地址构成交易,交易收录后,通过私钥再转移走即可。这样便在block chain里留下了这个地址。验证时重复该过程,检查地址是否一致即可。

该方法不会像方法二那样形成浪费,也比较容易操作。我们依然SatoshiDice的种子文件为例,种子数字摘要的Hash为:9b0d87ac871518cfd8601aa456b58fa74c01194cfeb25e7f3eecf43759d6ccb4

借助bitaddress.org,输入私钥(种子hash)后:

qq20130812-5

得到两把公钥,分别对应两个地址。证明时将币打入任何一个地址即可,建议使用未压缩公钥地址,因为并不是所有客户端都对压缩公钥支持良好。然后将该私钥导入任何一个客户端,再把该地址的钱转移到一个安全的地方。最后,公开私钥和对应收录地址的交易。

总结

方法二浪费,应避免使用。方法一繁琐,需要工具辅助转换。方法三相对容易,门槛低一些,大部分客户端都支持,私钥公钥地址的推导也有很多工具支持。

就这样比特币系统轻松的完成了存在证明,安全稳固,公信力远胜任何第三方、机构、政府。过程极其简单,使得任何一人都可以轻易地做出存在证明,其意义非常重大。可以预见,未来将比特币作为存在证明会得到广泛的应用。

工作证明与挖矿

工作证明

工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。

比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。

工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。

挖矿

挖矿即不断接入新的Block延续Block Chain的过程。

blockchain

挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:

  1. 发行新的货币(总量达到之前)
  2. 维系货币的支付功能
  3. 通过算力保障系统安全

金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。

Block Hash算法

Block头部信息的构成:

字段名 含义 大小(字节)
Version 版本号 4
hashPrevBlock 上一个block hash值 32
hashMerkleRoot 上一个block产生之后至新block生成此时间内,
交易数据打包形成的Hash
32
Time Unix时间戳 4
Bits 目标值,即难度 4
Nonce 随机数 4

下面采用高度为125552的block数据为例,演示block hash的计算过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php                                                                                                                             
$header_hex = "01000000" . // version
// previous block hash
"81cd02ab7e569e8bcd9317e2fe99f2de44d49ab2b8851ba4a308000000000000" .
// merkle root hash of transactions in this block
"e320b6c2fffc8d750423db8b1eb942ae710e951ed797f7affc8892b0f1fc122b" .
// Time
"c7f5d74d" .
// Bits (Difficulty)
"f2b9441a" .
// Nonce
"42a14695";
$header_bin = pack("H*", $header_hex); // hex to bin
$h = hash('sha256', hash('sha256', $header_bin, true), true); // double sha256

echo bin2hex($h), "\n";
// output: 1dbd981fe6985776b644b173a4d0385ddc1aa2a829688d1e0000000000000000
echo bin2hex(strrev($h)), "\n";
// output: 00000000000000001e8d6829a8a21adc5d38d0a473b144b6765798e61f98bd1d

该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。

产量调节

Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。

1
2
3
4
5
6
// 目标时间窗口长度:两周
static const int64 nTargetTimespan = 14 * 24 * 60 * 60;
// block频率,每10分钟一块
static const int64 nTargetSpacing = 10 * 60;
// 每两周的产量2016,也是调节周期
static const int64 nInterval = nTargetTimespan / nTargetSpacing;

但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Only change once per interval
if ((pindexLast->nHeight+1) % nInterval != 0) {
// 未达到周期个数,无需调节
return pindexLast->nBits;
}

// Go back by what we want to be 14 days worth of blocks
const CBlockIndex* pindexFirst = pindexLast;
for (int i = 0; pindexFirst && i < nInterval-1; i++)
pindexFirst = pindexFirst->pprev;

// 计算本次2016个块的实际产生时间
// Limit adjustment step
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
// 限定幅度,最低为1/4,最高为4倍
if (nActualTimespan < nTargetTimespan/4)
nActualTimespan = nTargetTimespan/4;
if (nActualTimespan > nTargetTimespan*4)
nActualTimespan = nTargetTimespan*4;

// 根据最近2016个块的时间,重新计算目标难度
// Retarget
CBigNum bnNew;
bnNew.SetCompact(pindexLast->nBits);
bnNew *= nActualTimespan;
bnNew /= nTargetTimespan;

if (bnNew > bnProofOfWorkLimit)
bnNew = bnProofOfWorkLimit;

return bnNew.GetCompact();

Block字段详解

  • Version,版本号,很少变动,一般用于软件全网升级时做标识
  • hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接
  • hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化
  • Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子
  • Bits,可以推算出难度值,用于验证block hash难度是否达标
  • Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻

最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:

  1. 形成分支博弈,使得算力总是在主分支上角逐
  2. 算力攻击的概率难度呈指数上升(泊松分布)

每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。

新block诞生过程

下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:

  1. 节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值
  2. 更新时间戳
  3. 尝试不同的随机数(Nonce),进行hash计算
  4. 重复该过程至找到合理的hash
  5. 打包block:先装入block meta信息,然后是交易数据
  6. 对外部广播出新block
  7. 其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿

由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。

主链分叉

从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:

  1. 不同高度的分支,总是接受最高(即最长)的那条分支
  2. 相同高度的,接受难度最大的
  3. 高度相同且难度一致的,接受时间最早的
  4. 若所有均相同,则按照从网络接受的顺序
  5. 等待Block Chain高度增一,则重新选择Best Chain

blockchain

按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。

分支博弈

我们假设所有的节点:

  1. 都是理性的,追求收益最大化
  2. 都是不诚实的,且不惜任何手段获取利益

所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。

一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。

对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。

Hash Dance

Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。

Hash Dance起名源于Google Dance.

算力攻击的概率

本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System

算力攻击是一个概率问题,这里作简单叙述:

  • p = 诚实节点挖出block概率
  • q = 攻击者挖出block概率,q = 1 - p
  • qz = 攻击者从z个block追上的概率

算力攻击的概率

我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)Z个块时,攻击者胜出的期望为lambda

攻击者胜出的期望

攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k<=z,那么追赶上后续z-k个块的概率为(q/p)^(z-k),即:

k个块概率符合泊松分布

展开为如下形式:

k个块概率符合泊松分布

计算该过程的C语言代码如下:

1
2
#include <math.h>
double AttackerSuccessProbability(double q, int z)
{
    double sum    = 1.0;
    double p      = 1.0 - q;
    double lambda = z * (q / p);
    int i, k;
    for (k = 0; k <= z; k++) {
        double poisson = exp(-lambda);
        for (i = 1; i <= k; i++)
            poisson *= lambda / i;
        sum -= poisson * (1 - pow(q / p, z - k));
    }
    return sum;
}

我们选取几个值,结果如下:

概率结果

可以看到,由于block的链式形式,随着块数的上升,攻击者赢得的概率呈指数下降。这是很多应用等待六个甚至六个以上确认的原因,一旦超过N个确认,攻击者得逞的可能微乎其微,概率值快速趋近零。

当攻击者的算力超过50%时,便可以控制Block Chain,俗称51%攻击。

算力攻击的危害

攻击者算出block后,block&Txs必须能够通过验证,否则其他节点都会拒掉,攻击便无意义。攻击者无法做出下列行为:

  1. 偷盗他人的币。消费某个地址的币时,需要对应的ECDSA私钥签名,而私钥是无法破解的。
  2. 凭空制造比特币。每个block奖励的币值是统一的规则,篡改奖励币值会导致其他节点会拒绝该block。

唯一的益处是可以选择性的收录进入block的交易,对自己的币进行多重消费(Double Spending)

过程是这样的:假设现在block高度为100,攻击者给商户发了一个交易10BTC,记作交易A,通常这笔交易会被收录进高度101的block中,当商户在101块中看到这笔交易后,就把货物给了攻击者。此时,攻击者便开始构造另一个高度为101的block,但用交易B替换了交易A,交易B中的输入是同一笔,使得发给商户的那笔钱发给他自己。同时,攻击者需要努力计算block,使得他的分支能够赶上主分支,并合并(Merge)被大家接受,一旦接受,便成功地完成了一次Double Spending。

攻击难度呈指数上升,所以成功的Double Spending通常是一个极小概率事件。

算力巨头

全网算力的上升对比特币是极其有利的,这是毫无疑问的。但目前大矿池与矿业巨头使得算力高度集中化,这与中本聪所设想的一CPU一票(one-CPU-one-vote)的分散局面背道而驰,或许是他未曾预料的。

挖矿是一项专业劳动,最后必然会交给最专业的人或团队,因为这样才能实现资源配置最优,效率最高。普通投资人通过购买算力巨头的股票:1. 完成投资;2. 分享算力红利。看似中心化的背后其实依然是分散的:

  1. 矿业公司的背后是无数分散的投资人
  2. 矿池背后是无数分散的个体算力

既得利益使得算力巨头倾向于维护系统而不是破坏,因其收益均建立在比特币系统之上,既得利益者断然不会搬石头砸自己脚。甚至很多巨头在达到一定算力占比后会主动控制算力增长,使得低于某阈值内。

后记

本篇几乎都在讲挖矿,因为挖矿对于比特币系统来说实在是太重要了。需要了解:1. block是基于工作量证明的。2. block以链式结构存在时的深远意义。

比特币基础知识

基本概念

椭圆曲线数字签名算法

椭圆曲线数字签名算法(ECDSA)是使用椭圆曲线对数字签名算法(DSA)的模拟,该算法是构成比特币系统的基石。

私钥

非公开,拥有者需安全保管。通常是由随机算法生成的,说白了,就是一个巨大的随机整数,256位、32字节。大小介于1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之间的数,都可以认为是一个合法的私钥。于是,除了随机方法外,采用特定算法由固定的输入,得到32字节输出的算法就可以成为得到私钥的方法。于是,便有了迷你私钥(Mini Privkey),原理很简单,例如,采用SHA256的一种实现:

private key = SHA256(<passphase>)

迷你私钥存在安全问题,因为输入集合太小,易被构造常见组合的彩虹表暴力破解,所以通常还是使用系统随机生成的比较好,无安全隐患。

公钥

公钥与私钥是相对应的,一把私钥可以推出唯一的公钥,但公钥却无法推导出私钥。公钥有两种形式:压缩与非压缩。

早期比特币均使用非压缩公钥,现大部分客户端已默认使用压缩公钥。这个貌似是比特币系统一个长得像feature的bug,早期人少活多代码写得不够精细,openssl库的文档又不足够好,导致Satoshi以为必须使用非压缩的完整公钥,后来大家发现其实公钥的左右两个32字节是有关联的,左侧(X)可以推出右侧(Y)的平方值,有左侧(X)就可以了。

现在系统里两种方式共存,应该会一直共存下去。两种公钥的首个字节为标识位,压缩为33字节,非压缩为65字节。以0x04开头为非压缩,0x02/0x03开头为压缩公钥,0x02/0x03的选取由右侧Y开方后的奇偶决定。

压缩形式可以减小Tx/Block的体积,每个Tx Input减少32字节。

签名

使用私钥对数据进行签署(Sign)会得到签名(Signature)。通常会将数据先生成Hash值,然后对此Hash值进行签名。签名(signature)有两部分组成: R + S。由签名(signature)与Hash值,便可以推出一个公钥,验证此公钥,便可知道此签名是否由公钥对应的私钥签名。

通常,每个签名会有三个长度:73、72、71,符合校验的概率为25%、50%、25%。所以每次签署后,需要找出符合校验的签名长度,再提供给验证方。

地址

地址是为了人们交换方便而弄出来的一个方案,因为公钥太长了(130字符串或66字符串)。地址长度为25字节,转为base58编码后,为34或35个字符。base58是类似base64的编码,但去掉了易引起视觉混淆的字符,又在地址末尾添加了4个字节校验位,保障在人们交换个别字符错误时,也能够因地址校验失败而制止了误操作。

由于存在公钥有两种形式,那么一个公钥便对应两个地址。这两个地址都可由同一私钥签署交易。

公钥生成地址的算法:

1
2
3
4
Version = 1 byte of 0 (zero); on the test network, this is 1 byte of 111
Key hash = Version concatenated with RIPEMD-160(SHA-256(public key))
Checksum = 1st 4 bytes of SHA-256(SHA-256(Key hash))
Bitcoin Address = Base58Encode(Key hash concatenated with Checksum)

下图是非压缩公钥生成地址的过程:

pubkeytoaddr

对于压缩公钥生成地址时,则只取公钥的X部分即可。

推导关系

三者推导关系:私钥 >> 公钥 >> 两个地址。过程均不可逆。拥有私钥便拥有一切,但通常为了方便,会把对应的公钥、地址也存储起来。

交易

比特币的交易(Transation,缩写Tx),并不是通常意义的交易,例如一手交钱一手交货,而是转账。交易由N个输入和M个输出两部分组成。交易的每个输入便是前向交易的某个输出,那么追踪到源头,必然出现一个没有输入的交易,此类交易称为CoinBase Tx。CoinBase类交易是奖励挖矿者而产生的交易,该交易总是位于Block块的第一笔。

qq20130727-18

拥有一个输入与输出的Tx数据:

Input:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10
90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501

Output:
Value: 5000000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG

一旦某个Tx的第N个输出成为另一个Tx的输入,那么该笔比特币即为已花费。每个交易有唯一Hash字符串来标识,通过对交易数据做两次SHA256哈希运算而来:

Tx Hash ID = SHA256(SHA256(Tx Data))

矿工费

矿工费(Transaction Fee)是鼓励矿工将Tx打包进Block的激励报酬。计算一笔交易的矿工费:

Transaction Fee = SUM(Input's amount) - SUM(Output's amount)

每笔Tx的矿工费必然大于等于零,否则该笔Tx即为非法,不会被网络接收。

数据块

数据块(Block)是存储Block Meta与Tx的地方。Block的第一笔Tx总是CoinBase Tx,因此Block中的交易数量总是大于等于1,随后是这段时间内网络广播出来的Tx。

找到合适的Block是一件非常困难的事情,需要通过大量的数学计算才能发现,该计算过程称为“挖矿”。首个发现者,会得到一些比特币作为奖励。

数据链

多个Block连接起来成为数据链(Block Chain)。

blockchain

为了引入容错与竞争机制,比特币系统允许Block Chain出现分叉,但每个节点总是倾向于选择最高的、难度最大的链,并称之为Best Chain,节点只认可Best Chain上的数据。

首个Block称为Genesis Block,并设定高度为零,后续每新增一个Block,高度则递增一。目前是不允许花费Genesis Block中的比特币的。

  • 每个Block中的Tx在此Block中均唯一
  • 一个Tx通常只会在一个Block里,也可能会出现在多个Block中,但只会在Best Chain中的某一个Block出现一次

货币存储

比特币是密码货币、纯数字化货币,没有看得见摸得着的硬币或纸币。一个人持有比特币意味着:

  1. 其拥有一些地址的私钥
  2. 这些地址是数笔交易的输出,且未花费

所有货币记录均以交易形式存储在整个blockchain数据块中,无交易无货币。货币不会凭空产生,也不会凭空消失。遗失了某个地址的私钥,意味着该地址上的Tx无法签署,无法成为下一个Tx的输入,便认为该笔比特币永久消失了。

货币发行

既然所有交易的输入源头都是来自CoinBase,产生CoinBase时即意味着货币发行。比特币采用衰减发行,每四年产量减半,第一个四年每个block的coinbase奖励50BTC,随后是25btc, 12.5btc, …并最终于2140年为零,此时总量达到极限为2100万个btc。

total_bitcoins_over_time_graph

减半周期,严格来说,并不是准确的四年,而是每生成210000个block。之所以俗称四年减半,是因为比特币系统会根据全网算力的大小自动调整难度系统,使得大约每两周产生2016个block,那么四年约21万块block。

该函数GetBlockValue()用于计算挖得Block的奖励值:

1
2
3
4
5
6
7
8
9
int64 static GetBlockValue(int nHeight, int64 nFees)
{
int64 nSubsidy = 50 * COIN;

// Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years
nSubsidy >>= (nHeight / 210000);

return nSubsidy + nFees;
}

当达到2100万btc以后,不再有来自CoinBase的奖励了,矿工的收入来源仅剩下交易的矿工费。此时,每个block的收入绝对值btc很低,但此时比特币应当会非常繁荣,币值也会相当的高,使得矿工们依然有利可图。

杜绝多重支付

传统货币存在多重支付(Double Spending)问题,典型的比如非数字时代的支票诈骗、数字时代的信用卡诈骗等。在比特币系统里,每笔交易的确认均需要得到全网广播,并收录进Block后才能得到真正确认。每笔钱的花销,均需要检测上次输入交易的状态。数据是带时间戳的、公开的,BlockChain由巨大的算力保障其安全性。所以比特币系统将货币的多重支付的风险极大降低,几近于零。通过等待多个Block确认,更是从概率上降低至零。一般得到6个确认后,可认为非常安全。但对于能影响你人生的重大支付,建议等待20~30个确认。

匿名性

任何人均可以轻易生成大量的私钥、公钥、地址。地址本身是匿名的,通过多个地址交易可进一步提高匿名性。但该匿名性并不像媒体宣传的那样,是某种程度上的匿名。因为比特币的交易数据是公开的,所以任何一笔资金的流向均是可以追踪的。

不了解比特币的人为它的匿名性产生一些担忧,比如担心更利于从事非法业务;了解比特币的人却因为它的伪匿名性而苦恼。传统货币在消费中也是匿名的,且是法律保障的,大部分国家都不允许个人涂画纸币。

地址本身是匿名的,但你可以通过地址对应的私钥签名消息来向公众证明你拥有某个比特币地址。

其他名词

哈希

哈希(Hash)是一种函数,将一个数映射到另一个集合当中。不同的哈希函数映射的空间不同,反映到计算机上就是生成的值长度不一样。同一个哈希函数,相同的输入必然是相同的输出,但同一个输出却可能有不同的输入,这种情况称为哈希碰撞。

常见的哈希函数有CRC32, MD5, SHA1, SHA-256, SHA-512, RIPEMD-160等,哈希函数在计算中有着非常广泛的用途。比特币里主要采用的是SHA-256RIPEMD-160

脑钱包&纸钱包

前面提到过的脑钱包与纸钱包,这其实不算是钱包的分类,只是生成、存储密钥的方式而已。脑钱包属于迷你私钥的产物。脑钱包就是记在脑袋里的密钥,纸钱包就是打印到纸上的密钥,仅此而已。

有同学提到过,以一个计算机文件作为输入,例如一个数MB大小的照片,通过某种Hash运算后得到私钥的方法。这个方案的安全性还是不错的,同时可以防止盗私钥木马根据特征扫描私钥。文本形式存储私钥是有特征的,而一个照片文件却难以察觉,即使放在云盘等第三方存储空间中都是安全的。

比特币客户端与钱包

简介

拥有和保存比特币,需要通过客户端,通常把该软件称为钱包。目前,整个比特币项目由Bitcoin Foundation来开发与维护,通常把他们称为官方团队。官方推出的客户端是Bitcoin Qt, 由C++编写核心功能,GUI界面由Python Qt完成。不含有GUI界面的被成为bitcoind,许多服务与核心功能均由其实现。运行bitcoind的通常称为节点(Bitcoin Node), 一个节点通常拥有完整的BlockChain数据,并实时与外界网络同步更新。

钱包中通常含有:

  • 公钥、私钥、地址
  • 与钱包中地址相关的交易信息
  • 其他辅助数据

最核心的数据就是密钥,拥有密钥便拥有一切,相关信息均可由其而来。钱包并不一定需要包含完整的BlockChain数据,不包含BlockChain数据的钱包称为轻钱包(Light Weight Wallet)。对于大部分日常使用来讲,轻钱包便足够了。

分类

  • 完全节点型(Full Node):含有BlockChain所有完整数据
  • 简易节点型(SPV Node):Header-Only Clients,仅有Block头部信息,无需交易数据
  • CS型(Server-Client):服务端-客户端模式,大部分数据存储在服务端
  • BS型:所有数据均通过浏览器在线使用

Bitcoin Qt,因为其是一款完整的钱包软件,需要下载大约超过10GB的BlockChain数据(24万个block),对于大部分人来讲,是没有必要的。目前,官方主页上默认推荐的客户端已经不再是Bitcoin Qt, 而是MultiBit(支持Windows, MacOS和Linux的轻钱包);移动端目前最好用的是Bitcoin Wallet(安卓平台),iOS平台由于政策原因,一直未有出色的软件,Blockchain.Info为iOS提供了一个简单的钱包软件,Blockchain for the iPhone。还有就是在线钱包,如优秀的BlockChain.Info,其安全性均超过自行保存管理,推荐使用之。

最近还有一种流行的钱包:脑钱包。因其安全性较低,并不推荐大家使用,仅临时性场合使用之。其原理是由一串密码短语,通过Hash运算,得到密钥,只要记住这串密语即可使用钱包。因为密码短语符合大家习惯和记忆特点,可以通过计算大量常见组合来破解。除了暴力破解的问题外,失忆是最大的风险,比如摔个跟头跌成脑震荡,或长期不用自然忘得一干二净。

选择&存储

  • 日常使用的额度通常小于10个币,可以存放在电脑或手机App中。通常存放1个币以下是比较保险的,丢了不太心疼嘛

  • 持有几十、几百个币的,可以选择BlockChain.Info,Inputs.io等在线钱包。其也可以当做日常钱包使用。

  • 持有上千甚至数万的,应该分开存储,并隔离存放。使用离线电脑生产密钥,打印出来托管至银行等高安全场所存储,并销毁现有密钥。同时还需要多份隔离存储,甚至对密钥进行加密。

密钥即一切,如不慎弄丢钱包,便永远失去这笔比特币。所以钱包需要小心妥善保管,不在自己的PC或者手机App中存储大量比特币,丢失的风险太高,病毒木马、硬件损坏、手机丢失等均造成无法挽救的损失。俗话讲鸡蛋不要搁在一个篮子里,多种方式存储也是降低风险的有效方式。目前丢失的比特币或有数百万BTC之巨。

常见钱包

  • Bitcoin-Qt - 官方客户端,基于C++/Qt,全平台,完全数据。
  • MultiBit - 全平台,轻钱包,官方推荐
  • Electrum - 著名轻钱包
  • Armory - 基于Python,含有诸多特性的轻钱包
  • BlockChain.info - 非常著名在线钱包

开发库

  • bitcoind - 官方客户端,无GUI,开发者必备
  • libcoin - libcoin
  • libbitcoin - asynchronous C++ library for Bitcoin
  • cbitcoin - A low-level bitcoin library written in standard C
  • Bitcoinj - a Java implementation of the Bitcoin protocol
  • gocoin - Bitcoin client library for Go / golang
  • pynode - Bitcoin P2P router, in python
  • bitcointools - Python-based tools for the Bitcoin cryptocurrency system,By Gavin Andresen
  • bitcoin-abe - Abe: block browser for Bitcoin and similar currencies

数据检索


参考

  1. Bitcoin Foundation: https://bitcoinfoundation.org/
  2. Why Apple Is Afraid Of Bitcoin: http://www.forbes.com/sites/jonmatonis/2012/06/13/why-apple-is-afraid-of-bitcoin/
  3. List of Bitcoin-related software: https://en.bitcoin.it/wiki/Software
  4. Bitcoin Clients: https://en.bitcoin.it/wiki/Clients

比特币是什么?

简介

比特币是一个自由软件项目,是一种基于密码学的电子货币,同时也是一种协议。整个系统采用去中心化思想构建,基于P2P模式运行。
其特点有:

  • 去中心化发行与运作,无央行存在
  • 货币不可伪造,无法多重支付,交易不可逆转
  • 紧缩货币,总量固定,但可以无限分割
  • 全球无障碍流通,快速支付且成本极低
  • 账户匿名,且任何人均无法冻结,无法收税
  • 天然审计

比特币由Satoshi Nakamoto创造(现已匿名消失),2008年11月1日,Satoshi在一个密码学的邮件列表中贴出了一篇论文:”Bitcoin P2P e-cash paper“:

qq20130720-1

创世纪块

2009年1月3日,第一个数据块(Genesis‎ Block)的生成宣告比特币系统诞生。Satoshi在Genesis Block数据区中写入如下信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ hexdump -n 255 -C blk00000.dat
00000000 f9 be b4 d9 1d 01 00 00 01 00 00 00 00 00 00 00 |................|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 00 00 00 00 00 00 00 00 00 00 00 00 3b a3 ed fd |............;...|
00000030 7a 7b 12 b2 7a c7 2c 3e 67 76 8f 61 7f c8 1b c3 |z{..z.,>gv.a....|
00000040 88 8a 51 32 3a 9f b8 aa 4b 1e 5e 4a 29 ab 5f 49 |..Q2:...K.^J)._I|
00000050 ff ff 00 1d 1d ac 2b 7c 01 01 00 00 00 01 00 00 |......+|........|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff |................|
00000080 ff ff 4d 04 ff ff 00 1d 01 04 45 54 68 65 20 54 |..M.......EThe T|
00000090 69 6d 65 73 20 30 33 2f 4a 61 6e 2f 32 30 30 39 |imes 03/Jan/2009|
000000a0 20 43 68 61 6e 63 65 6c 6c 6f 72 20 6f 6e 20 62 | Chancellor on b|
000000b0 72 69 6e 6b 20 6f 66 20 73 65 63 6f 6e 64 20 62 |rink of second b|
000000c0 61 69 6c 6f 75 74 20 66 6f 72 20 62 61 6e 6b 73 |ailout for banks|
000000d0 ff ff ff ff 01 00 f2 05 2a 01 00 00 00 43 41 04 |........*....CA.|
000000e0 67 8a fd b0 fe 55 48 27 19 67 f1 a6 71 30 b7 10 |g....UH'.g..q0..|
000000f0 5c d6 a8 28 e0 39 09 a6 79 62 e0 ea 1f 61 de |\..(.9..yb...a.|

还原出文本为:

The Times 03/Jan/2009 Chancellor on brink of second bailout for banks

该段文字为英国《泰晤士报》2009年01月03日头版新闻标题:

twcach2

这段文字暗示了比特币的诞生时间,并从中可以看出Satoshi对现有货币系统的强烈不满。

经过数年发展,已有大量计算机加入,形成了庞大的P2P网络,并构成巨大的算力屏障。除非小行星撞击地球,否则没有任何个人与组织能够关闭该系统。截止2013年7月19日,目前全网节点数约16万个:

qq20130720-2

一切才刚刚开始

由于比特币的诸多颠覆特性,被人称为“史上最危险的自由软件项目”,现在经历数次大波折的比特币不仅没有衰落反而越来越繁荣,无数人正投身于这场伟大的社会实践中去,而比特币将开创出人类新的货币史。


参考

  1. An open source P2P digital currency: http://bitcoin.org/
  2. Bitcoin: A Peer-to-Peer Electronic Cash System: http://bitcoin.org/bitcoin.pdf
  3. Satoshi Nakamoto: https://en.bitcoin.it/wiki/Satoshi_Nakamoto
  4. Bitcoin P2P Currency: The Most Dangerous Project We’ve Ever Seen:http://launch3.squarespace.com/blog/l019-bitcoin-p2p-currency-the-most-dangerous-project-weve-ev.html
  5. Genesis Blcok: https://en.bitcoin.it/wiki/Genesis_block
  6. Chancellor Alistair Darling on brink of second bailout for banks: http://www.thetimes.co.uk/tto/business/industries/banking/article2160028.ece
  7. Bitnods: http://getaddr.bitnodes.io/