1.密码学以及加密货币简单介绍
我们知道加密货币是基于密码学的,密码学运用了一些很巧妙的但是很高深的数学理论,而比特币只是使用了相对简单的密码学的知识,哈希和数字签名。
1.1 Hash函数
Hash函数有以下几点属性:
- 输入可以是任意大小的string
- 输出大小是固定的
- 计算n位字符串耗时O(n)
对于比特币的Hash函数(比特币用的SHA - 256,输出大小是256位):
- collision‐resistance
collision:两个不同的x、y,H(x) == H(y)
collision‐resistance是指没人能找到collision ,但是collision是存在的
为了找到collision,计算机需要计算2^256 +1次(最坏情况),2^128 次(平均情况)
这是什么概念?把所有计算机从宇宙开始至今找到collision的几率都非常低
但是没有任何一个hash 函数被证明是collision‐resistance的,因为概率特别低,所以我们可以认为它是collision‐resistance
例子:两个文件的hash值相同,我们就可以认为是同一个文件 - hiding
假设r取值范围是非常发散的,给定y = H(r||x),找到x是不太可行的(||串联) - puzzle‐friendliness
假设r取值范围是非常发散的,给定y = H(r||x),y是n位输出,在时间小于O(2^n)不可能找到x
这意味着想要hash函数输出一个特定的值,如果随机选取x,那么找到特定值是非常困难的
目前有很多种Hash函数,比特币使用的是SHA - 256 算法:
1.2 Hash指针
Hash指针不仅能获取信息,也能验证该信息是否被改变
在普通使用指针的数据结构中,都可以把指针替换为Hash指针,例如,链表(blockchain)、二叉树(Merkle树)
-
blockchain
blockchain的一个有用的使用场景是防篡改日志,当前只会保存创世块的Hash指针,假设a块被篡改为a1块,此时b块存贮a块的Hash值就会不一致,因为collision‐resistance,因为a!=a1 所以H(a) != H(a1),此时就会检测到不一致,如果还想成功篡改,那么就需要篡改b块的数据,以此类推会一直到创世块,但是创世块的Hash值是已经被记录的,所以篡改始终会被检测到
-
Merkle树
Merkle树就是用Hash指针的二叉树,data都是叶子节点,每两个叶子节点组成的父节点包含两个相应的Hash指针,如下图
根据blockchain,Merkle树也是能够检测到篡改的,只需要记录根节点的Hash指针
1.3 数字签名
比特币使用的是ECDSA,椭圆曲线数字签名算法,是一种非对称加密的算法
公钥的主要作用:加密;验证签名。私钥的主要作用:签名;解密。
通过私钥可以计算出公钥,反之则不行。
公钥加密:公钥加密的内容可以用私钥来解密——只有私钥持有者才能解密。
私钥签名:私钥签名的内容可以用公钥验证。公钥能验证的签名可以认为是私钥签名的。
signature = sign(sk, msg) //sk: secret key
isValid = verify(pk, msg, signature) // pk: public key
ECDSA算法:
Private key: 256位
Public key, uncompressed: 512位
Public key, compressed: 257位
Message to be signed: 256位(限制大小、提高效率; 经过RSA-256算法哈希过的message就是256位)
Signature: 512位
技巧:1.msg大小是任意的,所以可以签名H(msg)。 2.签名Hash指针,这样整个区块都会被保护(可以只签名blockchain 的最后一个区块的Hash指针,这样整个blockchain都被保护)
公钥的Hash作为身份标识(比特币的地址)
2.比特币如何实现去中心化
比特币实现去中心化是通过技术与激励机制结合实现的,但是没有真正意义上的去中心化
2.1 比特币去中心化的5个问题
2.2 分布式共识
比特币基于p2p网络的,当Alice向Bob支付Btc的时候,实际上会广播这一笔交易到所有的比特币网络节点。
注意Bob在不在线不会影响到他是否接收这笔钱
很多用户都在广播这些交易到整个网络,各个节点必须完成共识这些交易的的合法性,以及发生的顺序,这样系统会有一个全局的账本,为了提高效率,把很多交易打包成块,基于这些区块完成共识就行了,账本记录了已经达成共识的区块组成一条blockchain
每个节点 都有一个池子,保存了收到的未完成的交易(还没有被包含进blockchain)因为是p2p网络,每个节点池子里的交易可能不一样,那么所有的节点怎么共识确定一个block呢?
一种方法:假设每间隔固定时间(10分钟),每个节点从自己的池子里打包一些交易作为block,输入某种共识协议中,最终会输出一个合法的、已经共识确认的block作为blockchain的最后一个block,剩余未打包的交易,等待下次block确认就行了
上面方法和比特币有点类似,但比特币并不是这么工作的。因为某些节点可能会崩溃,或者是恶意的;而且p2p网络不是完美的,延迟等各种问题让所有节点运行某种共识协议不太可行
- 比特币的共识机制(Proof Of Work)
因为比特币网络所有节点都没有身份标识的,所以没有办法惩罚那些恶意节点(eg包含非法交易、二次消费),但是正因为比特币是一种货币,所以可以通过奖励比特币的方式来奖励诚实的节点,所有的节点在不断地竞争计算机的算力,去解决一个hash 谜题,找到一个nounce值,连接前一个区块的hash以及本区块的交易,然后hash计算得出一个值,这个值需要小于某个targe
H(nonce || prev_hash || tx || tx || ... || tx) < target
这样就找到个下一个区块。现在一个区块就包含了一系列交易、上一个区块的hash值、以及一个nounce值,由于puzzle‐friendliness属性,想要找到这个nounce值只能一个个去试。