该课程是北京大学开设的介绍比特币基本原理的课程,可以当做比特币的入门级课程(替代白皮书),推荐阅读。
第一课、课程基本信息
第二课、BTC 密码学原理
- crypto-currency 加密货币
- cryptographic hash function
- collision resistance(哈希碰撞)抗碰撞性 :不同的输入可能会有相同的输出
- 绝对不可能人为制造出Hash碰撞实现 H(x) = H(y)
- x ≠ y,=> H(x) = H(y)
- 比如我们有256位的hash数,那么输出就是2^256个可能,但出入是无限大的。
- 可以用对一个message求 digest,用来检测对message的篡改
- MD5曾经是个很流行的hash函数,但现在已经被人知道怎么制造hash碰撞了
- hiding
- hash函数计算过程是单向的,不可逆的
- collision resistance 和 hiding 配合可以实现 digital commitment(digital equivalent of a sealed envelope)
- 问题:预测结果不能够提前公开,因为公开预测结果可能会影响实际走。但预测结果不公开,又怎么能保证你的预测是提前做出来的?
- 答案:这就要使用到sealed envelope,写到邮件里,放到公证处,结果公开后再打开
- 那么digital sealed envelop怎么实现呢?
- 在发生前我先公布哈希值H(x),等到事情发生后我再公布x
- 实际操作过程中要注意的:输入要足够大,且分布均匀。
- 比如股市不够大,可能就几千支,那么常用的做法就是 拼接一个随机数,对 H(x || nonce)整个取哈希
- puzzle friendly
- 哪个输入更可能会获取这个hash值,这个范围是不知道的
- 挖矿实际上就是找一个nonce,nonce和区块的块头信息合并一起计算一个hash值:
- H(block header || nonce) ≤ target
- 所以这个过程才能叫做工作量证明 proof of work
- difficult to solve,but easy to verify. << 挖矿很难,验证很容易
- collision resistance(哈希碰撞)抗碰撞性 :不同的输入可能会有相同的输出
- 比特币中用的hash函数是 SHA - 256
- secure hash algorithm
- 比特币如何开户呢?
- 开户过程很简单,本地创建公私钥即可(public key,private key)
- 公私钥 概念来自非对称加密体系 : asymmetric encryption algorithm
- 对称加密:加密和解密用的是同个钥匙
- 缺点:秘钥分发不是很方便
- 加密用的是公钥,解密用的是私钥。加密和解密用的是同一个人的公钥和私钥。
- 公钥就相当于银行帐号,别人给我转账就我的公钥就行了,私钥就相当于我的账户密码。
- 问题:比特币信息都是公开的,那我要公钥和私钥干什么呢?
- 是用来做签名的
- 交易时我用私钥来签名,别人验证签名用的是我的公钥。
- 问题:万一有个人产生的公私钥和别人的公私钥相同怎么办呢?
- 攻击方法:出现两个人公私钥相同的概率是非常低的,目前还没有发现有人能用这种方法能攻击成功的先例。
- a good source of randommess,要用好的随机源
第三课、BTC 数据结构
- hash pointers 哈希指针
- 区块链用哈希指针,代替了普通的指针
- Block chain is a linked list using hash pointers.
- 第一个区块是系统产生的,叫:Genesis block,创世区块
- 最近的一个区块叫 most recent block
- 每个区块都有一个hash pointer
- 当前的H()是把前一个H()的内容包括前一个H(),包在一起取了Hash值
- 通过这样的数据结构可以实现:temper-evident log
- 如果前一个Hash指针内容被改了,下一个Hash指针的内容也会被改。
- 这个数据结构的好处是:我只要记住最后一个Hash值,我就能检测前面所有区块链是否被变更。
- 这就是普通链表和区块链的区别
- 普通链表改变其中一个节点的内容对其它链表是没有影响的
- 区块链是牵一发而动全身,改变任何一个区块,就会引发多米诺骨牌效应
- 有了这个性质,比特币就不需要保存整条节点了,当我真需要很早的区块,我问别的机器要就好了
- Merkle tree
- 只要我记住 根hash值,就能检测树中任何节点是否被修改
- 这种效率比单链检查变更效率更高。
- 每个区块所包含的hash pointer实际上是组装成一个Merkle tree的形式
- 每个区块可以分成两部分
- block header
- 一个区块所包含的所有交易组成的Merkle tree的根哈希值是保存在block header中的,但block header中没有交易的具体内容
- block body
- block body存在交易信息的
- block header
- Merkle tree的作用:
- 提供 Merkle proof,实现交易校验
- 我是个轻节点,我只有block header,你说你给我转账,那我怎么校验呢
- 只要我把你提供的交易hash,通过merkle计算后,和我轻节点中的hash保持相等,就表示转账成功了。
- 我是个轻节点,我只有block header,你说你给我转账,那我怎么校验呢
- proof of membership(proof of inclusion)
- Merkle proof的时间复杂度:O(log(n)),n是节点深度
- proof of non-membership
- 也是可以的,使用sorter Merkle tree,但比特币中是不需要 proof of non-membership的,所以没有用sorter Merkle tree
- 提供 Merkle proof,实现交易校验
- 只要数据结构是无环的,实际上都可以用Hash pointer代替
- 因为无环就变成循环依赖了,就变成死锁了
第四课、BTC协议
- 央行如果发行数字货币,那么怎么实现?
- 如果央行用私钥发行数字货币,我们用公钥进行检验,验证对了就可以使用,是不是就可以了呢?
- 如果这样就可以了,就不需要区块链了,这没用到区块链的技术,这用到的是 非对称加密。
- 非对称加密 是解决了 不能伪造 的问题,但我可以把央行发行的数字货币复制成很多份,可能会实现 多花。
- 如果央行用私钥发行数字货币,我们用公钥进行检验,验证对了就可以使用,是不是就可以了呢?
- double spending attack(双花攻击)
- 数字货币面临的主要问题
- 现在央行给数字货币维护一个表,每个数字货币有个编号,017->wang
- 任何两个人之间进行支付,都要通过央行。这个方案实践中也是可以用的,但是太麻烦了。
- 那能不能搞一个去中心化的方案,把央行的职能换成由大家共同承担。
- 非对称加密就可以实现数字货币的校验,区块链是为了解决数字货币双花的问题。
- 数字货币的两个问题
- 谁来发行货币(矿工)
- 怎么防范double spending attack
- 怎么防范double spending attack
- 区块链中有两种hash pointer
- 一种是为了把区块给串联起来
- 另外一种是要在交易时,说明币来源的hash pointer,防止凭空捏造。
- 收款地址是通过公钥取hash,经过一些转换计算出来的
- 非对称加密体系
- 用你的公钥加密,你收到信息后用私钥解密
- 你需要给我回复的时候,再用我的公钥加密,然后发给我,我用我的私钥解密
- A 给 B 转账
- 输入部分:说明币的来源 + A的公钥
- coinbase(挖矿出来的) + 公钥
- 输出部分:B的公钥
- 输入部分:说明币的来源 + A的公钥
- 比特币系统中是用脚本来实现的,交易的输入和输出是走脚本校验的。BitCoin Script
- 区块链中有两种hash pointer
- Block header || Block body
- Block header
- Version
- hash of previous block header
- 前一个区块的hash,只包括前一个区块的block header
- Merkle root hash
- target
- H(block header) ≤ target
- nonce
- 系统中的节点分为 全节点 和 轻节点
- full node(fully validating node)
- light node
- 只保存block header的节点
- 账本内容要取得分布式共识 distributed consensus
- impossiblity result不肯能结论
- FLP impossiblity result
- asynchronous faulty:系统如果是异步的,是没有网络时延的,哪怕系统中有一个成员是faulty的,你也没办法达成共识
- CAP Theorem
- C:Consistency 一致性
- A:Availability 可用性
- P:Partition tolerance 容错性
- 任何一个分布式系统这三个性质中最多只能满足两个
- FLP impossiblity result
- impossiblity result不肯能结论
- Block header
- Consensus in BitCoin
- 解决恶意节点的问题
- 想法一:既然系统中大多数节点是好的,那直接投票行不行?
- 问题一:有的区块犯懒,行政不作为
- 问题二:效率问题,网络时延
- 问题三(最大的问题):用超级计算机产生很多地址,来影响投票,也就是 sybil attack(女巫攻击)
- 既然是投票,那就有个问题是谁能参与投票?也就是membership都是谁
- 联盟链 hyperledger:只有某些大公司才能投票,fabric
- 比特币也是投票,但是用算力来投票
- nonce是4 bytes
- 如果某个节点,找到了符合要求的nonce,我们就说它获得了记账权
- 所谓的记账权就是往比特币这个去中心化的账本里,写入下一个区块的权利。只有找到nonce,获得记账权的节点,才有权利发布下一个区块。
- 其它节点收到这个区块的内容后,要验证一下这个区块的合法性:
- 验证Block header 的mBits域
- 验证nonce
- 看一下block body的交易列表:
- 要有合法签名
- 以前没有被人花掉过
- 有没有可能一个区块所有节点都被检查通过了,但我们仍然不愿意接受?
- 插在区块链中间的节点要被接受吗
- 不接受,接受的区块应该是在扩展最长区块链
- 分叉攻击 forking attack
- 区块链在正常情况下也可能出现分叉
- 如果有两个节点,同时获得记账权,等长的临时性区块会维持一段时间,最终会分出胜负
- 插在区块链中间的节点要被接受吗
- block reward 出块奖励
- 铸币coinbase Transaction是比特币系统中发行比特币系统中的唯一方法
- 如何防范女巫攻击?
第五课、BTC实现
- UTXO:Unspent Transaction Output
- 为了检测double spending
- 你想花掉的币,只有在UTXO里,才是合法的
- total inputs == total outputs + Transaction fee(服务费)
- 问题:只有区块奖励的话,某个节点比较自私,只打包自己的节点?
- 帮别人打包是有交易费的
- 示例:
- block header
- nonceId是32位,大家现在可能把nonceId全部遍历一遍,很可能都找不到满足target的值,那怎么办呢?

- 字段解释
- Version:版本号,没法改
- previous block header hash
- merkle root hash
- time:有一定的调整空间
- nBits:挖矿时用的目标阈值,只能按照协议的要求定期进行调整,不能随便改
- nonce

- 可以改变coinbase中的hash值
“Coinbase 交易”也叫做“Generation 交易”,也就是“生成交易”,这是因为其他的普通交易中,都是去转账已有的比特币,而这个交易是专门从无到有的去生成新的比特币的。 精确一点说,coinbase 就是“生成交易”中的input 。 这就是coinbase 这个词的基本含义。
把 当前交易的输入脚本 和 上一笔交易的输出脚本 放在一起运行,看看会不会出错
- Bernoulli trial:a random experiment with binary outcome(伯努利试验:一项有二元结果的随机试验)
- Bernoulli process:a sequence of independent Bernoulli trails
- 性质1:无记忆性 memoryless 前面的实验结果对后面的实验是没有影响的
- Poisson process:实验的次数很多,每次成功的几率很小。在概率上可以用Poisson process近似
- 挖到矿的时间概率呈exponential distribution(指数分布)
- progress free:将来已经挖了多少时间,和未来还差多长时间能挖到是没有关系的。
- 如果过去做的工作做多,那么接下来成功的概率越大,会有什么结果?
- 算力强的矿工,会有不呈比例的优势。
- 比如A是B算力的10倍,理论上A比B挖到币的概率是10倍,如果是下次成功概率增大,A比B挖到的币成功的概率要大于10倍。
- Bernoulli process:a sequence of independent Bernoulli trails
- BitCoin is secured by mining.
- 比特币协议中要等6个confirmation,才认为前面的比特块是不可篡改的,也就是要等1个小时。