北京大学肖臻老师《区块链技术与应用》公开课 --- 学习笔记
课程介绍:
北京大学公开课《区块链技术与应用》由肖臻老师讲授,主要讲解区块链的基本概念和实现原理,面向广大对区块链技术和应用感兴趣的同学。通过这门课的学习,能够掌握比特币、以太坊等区块链技术的设计思路并有效解决实际问题。
课程地址:《区块链技术与应用》
课程前置基础
- 学过基本数据结构 (数组、链表、二叉树、哈希函数)
- 掌握了编程的基本技能
参考资料:
- 《比特币和加密货币技术》
- 以太坊白皮书、黄皮书、源代码
- solidity文档
比特币 BTC
先介绍一些区块链理论基础:密码学原理和数据结构
密码学原理
比特币被称为加密货币crypto-currency。区块链上内容都是公开的,包括区块的地址,转账的金额; 比特币主要用到了密码学中的两个功能:
- 哈希
- 签名
哈希函数
密码学中用到的哈希函数被称为cryptographic hash function:它有两个重要的性质:
- collision(这里指哈希碰撞) resistance :例如x≠y H(x)=H(y) 两个不同的输入,输出却是相等的,这就称哈希碰撞。
- 它是不可避免的,因为输入空间总大于输出空间。给出x,很难找到y,除非蛮力求解(brute-force)。
- 该性质的作用:对一个message求digest。比如message取m m的哈希值是H(m)=digest 如果有人想篡改m值而H(m)不变,则无法做到。
- 哈希碰撞无法人为制造,无法验证,是根据实践经验得来的。
- hiding 哈希函数的计算过程是单向的,不可逆的。(从H(x)无法推导出x) hiding性质前提是输入空间足够大,分布比较均匀。如果不是足够大,一般在x后面拼接一个随机数,如H(x||nonce)。
- 该性质的作用:和collision resistance 结合在一起,用来实现digital commitment(又称为digital equivalent of a sealed envelope) 把预测结果作为输入x,算出一个哈希值,讲哈希值公布,hiding让人们知道哈希值而不知道预测值,最后再将x公布,因为有collision resistance的性质,预测结果是不可篡改的。
除了密码学中要求的这两个性质外,比特币中用到的哈希函数还有第三个性质:
- puzzle friendly 指哈希值的预算事先是不可预测的。假如哈希值是00...0XX...X,一样事先无法知道哪个值更容易算出这个结果,还是要一个一个带入。
比特币挖矿的过程中实际就是找一个nonce,nonce跟区块的块头里的其他信息合一起作为输入,得出的哈希值要小于等于某个指定的目标预值。H(block header)≤target。block header 指块头,块头里有很多域,其中一个域是我们可以设置的随机数nonce,挖矿的过程是不停的试随机数,使得block header取哈希后落在指定的范围之内。
puzzle friendly是指挖矿过程中没有捷径,为了使输出值落在指定范围,只能一个一个去试。所以这个过程还可以作为工作量证明(proof of work)。 挖矿很难,验证很容易。(difficult to solve ,but easy to verify) ,难解、易验证
SHA-256
比特币中用的哈希函数叫作 SHA-256(secure hash algorithm ) 以上三个性质它都是满足的。
在比特币系统中开账户: 在本地创立一个公私钥匙对(public key ,private key),这就是一个账户。公私钥匙对是来自于非对称的加密技术(asymmetric encryption algorithm)。
签名用的是私钥,验证签名用的是公钥。
比特币的数据结构
1.哈希指针
内容:
- 地址
- 哈希
区块链是一个链表,用哈希指针替代普通的指针,好处是可以用一个哈希记录是否之前被篡改
2.Merkle Tree
是用哈希指针代替普通指针的二叉树
用处:提供 Merkle proof
一个比特币的示例:
区块链包括全节点和轻节点
Merkle proof
比特币的共识协议
与纸质货币的不同、问题
发行量控制
double spending attack (双花)
利用区块链解决这个问题。 包含2类哈希指针
- 指向之前的区块
- 指向交易(防双花)
每个交易包括
- 输入
- 支付者公钥
- 币的来源
- 输出
- 收款人公钥哈希
新问题 公钥保存
bitcoin区块链内容
- Block header
- version
- hash of previous block header
- Merkle root hash
- target(挖矿目标)
- H(block header)≤target (块身的正确性可由块头Merkle root保证)
- Block body
- transaction list
- Merkle tree
节点类别
- Full node (全节点),别名(fully validating node)
- Light node (轻节点)
分布共识 (distributed consensus)
impossibility result (不可能结论)
- FLP impossibility result
- 异步系统中(网络时延无上限)
- 即使一个成员有问题也不可能取得共识
- CAP Theorem
- CAP
- C : Consistency(一致性)
- A : Availability(可达成共识)
- P : Partition tolerance(分布容忍)
- 意义:分布式系统三性质只能选两个
- CAP
协议
- Paxos 协议
- C+P
- A 小概率会有问题
- Consensus in BitCoin
- 假设 大部分节点好的
- 公式方法
- 人头投票
- Sybil attack
- 创建大量节点投票
- 算力投票
- forking attack(分叉攻击)
- 选择最长合法链 - orphan 孤儿
- block reward(挖矿奖励) 唯一产生新币的方式
- hash rate
- 每秒可以试多少个hash
- 决定投票权重
- 人头投票
比特币系统的实现
账本
irrevocable ledger(不可篡改账本);
模式分为 transaction-based ledger(基于交易)、account-based ledger(基于账户)
transaction-based ledger(基于交易)
- BitCoin 模式
- 记录交易
- 不记录账户余额
- UTXO 数据库
UTXO 数据库
- Unspent Transaction Output(未被花掉的交易的输出)
- 由全节点维护(全节点的本地内存中)
- 元素
- 交易的哈希值
- 是交易中第几个输出
- 每个交易可能有多个输出、可能有多个输入
- total inputs = total outputs (一般情况)
- total inputs > total outputs
- transaction fee (交易费) 激励矿工打包自己的交易
- 目的:检测 double spending
account-based ledger(基于账户)
以太坊模式
区块链的例子
Difficulty
- 每2016个block更新一次
- 保证出块时间是十分钟左右
- 单靠 nonce 可能无法满足 difficulty 要求
Blok header
改变 hashMerkleRoot,每个区块链都有铸币交易
- 无输入
- 输出自己几个币
- 铸币交易 CoinBase 域可以写任何东西
- 64 bitc
- 挖矿两层循环
实例
- 输入输出用脚本来指定
- 验证交易(配对)、提供币
- Input Scripts(本交易)
- Output Scripts (U TXO 中的)
挖矿概率分析
每次挖矿 Bernoulli trial
a random experiment with binary outcome
挖矿过程 Bernoulli process
- 数学性质
- a sequence of independent Bernoulli trials。 memoryless
- 近似为 Poisson process
- progress free 过去的努力无用
- 出块时间:服从 exponential distribution(指数分布)
比特币奖励
geometric series(几何分布)。21w * 50 + 21w * 25 +.... =2100w
BitCoin is secured by mining
挖矿安全性
不可能偷币
无法伪造签名
可能双花
- 靠分叉
- 防范
- 等几个区块确认
- 杜绝普通
- 不杜绝
- 一小时
- zero confirmation
- 意思
- 发出即可,不用写入区块
- 可行原因 (交易有冲突,接受先发出的)
- 意思
- 等几个区块确认
selfish mining
- 要求大量算力
- 可以减少挖矿竞争; 别人比你少知道一个块
比特币网络 (工作原理)
application layer
BitCoin Block chaim
network layer
- P2P Overlay Network ,所有节点对等
- 加入需要种子节点(seed node)
- 加入与退出
- 进入不需要通知,启动客户端自动加入
- 推出不需要通知,一段时间无响应自动被去除
设计原则
- simple
- robust
- but not efficent
运行流程
- 收到信息
- 检查合法性
- 标记该信息为收到过,并转发给邻居节点
- 邻居节点自由选取 与 物理空间(地理) 和 网络空间(网络拓扑)的组织结构无关
- 再次收到同样信息不管
- 冲突交易与网络延迟
- 收到交易加入未完成集合
- 若交易冲突,通过下一个区块的结果
- 若区块记录的交易是本地先到的
- 若区块记录的交易是本地后到的
限制
- 区块大小最大 1M;传播最长时间:几十秒
- 可能一些合法交易一些节点根本收不到
- 可能一些节点转发非法交易
- 可能一些信息到不同节点的顺序不同
比特币的挖矿难度调整
目标阈值
- H(block header) ≤ target
- 和挖矿难度 difficulty 成反比
哈希算法
SHA-256:secure hash 256
挖矿难度
difficulty_1_target
最简单的情况的挖矿难度(target极大)
为什么要调挖矿难度?
- 控制挖矿时间为一个块十分钟,不调会越挖越快
- 可以不是十分钟吗?可以,以太坊为15秒;需要新的公式协议
- ghost;给予叔块(orphan block)奖励;uncle reward
- 越挖越快怎么了?
- 更容易分叉
- 分叉成为常态
- 可能出现2分叉以上的分叉;10分叉
- 分叉过多危害
- 系统不易达成共识
- 系统安全性变差
- 总算力(特别是诚实节点)被分散
- 更易被51%(恶意节点可能只需要总算力的11%即可完成攻击)
- 更容易分叉
调整规则
- 频率
- 2016 个 block
- 2 周
- 公式:
- actual time :2016个block实际用时
- expected time : 2016*10min≈2星期
- target不会增减4倍以上 :0.5周~8周
- 若攻击者不调;诚实者可通过block header中nBit变量判断出该区块不合法
比特币算力增长
- 算力:
- 挖矿难度:
- 难度调整曲线:
- 出块时间曲线:
- 指数增长
比特币挖矿
节点特性
先回顾一下全节点与轻节点
全节点
- 一直在线
- 在本地磁盘上维护完整的区块链信息
- 在内存维护UTXO集合;以便快速检验交易的正确性
- 监听比特币网络上的交易信息;验证每个交易的合法性
- 决定哪些交易会被打包到区块
- 监听其他矿工挖出的区块;检验合法性
- 挖矿
- 决定沿着哪条链挖下去;最长合法链
- 出现等长分叉时选择哪个分叉;先听到的
轻节点
- 不可以
- 一直在线
- 保存整个区块链
- 保存全部交易
- 检验大多是交易的合法性
- 检验网上发布的区块的正确性
- 检验哪个是最长合法链
- 可以
- 保存区块头
- 保存与自己相关的交易
- 检验与自己相关交易的合法性
- 检验挖矿难度;有头
- 检测哪个是最长连
综上:
挖矿设备
- CPU
- GPU
- ASIC 芯片
- 名称:Application Specific Integrated Circuit
- 只能挖一种币
- 由于mining puzzle
- 可能多币公用mining puzzle (merge mining) ; 新币引流
- Alternative mining puzzle;使得通用设备也可以挖矿
矿池
运行模式
- 矿主承担全节点的其他功能
- 哈希值分配给矿工计算
利益分配
- 通过矿工的工作量分配 => share
- almost valid block
- 降低难度后挖出的区块::70个0 → 60个0
- 不可偷区块奖励; 铸币交易的目标账户是矿主
使51%攻击更容易
- 可以召集算力; on demend mining
- 不用自己拥有大量算力
大型矿池可发动的攻击
- 分叉攻击
- Boycott(封锁账户)
- 不包含指定账户 A 的所有交易
- 自己不包含 A 相关交易
- 见到 A 相关交易立刻分叉
- 普通矿工从此也不敢打包 A 相关交易了
比特币脚本
交易结构
交易结构如下
其中output:
- 左 Output
- 之前某交易的 Output
- 此交易的输入
- 右 Output : 此交易的输出
input script 与 output script:
- 比特币脚本只有堆栈;没有内存空间、变量
- 基于站的语言;stack base laguage
交易结构:
- locktime
- 交易的生效时间
- 等多少个区块才可以被写入区块链
- blockhash 所在区块的哈希值
- comfirmations 已经有多少个确认区块了
- time 交易产生的时间
- block time 区块产生的时间
- vin
- 数组
- txid:作为输入的交易的 id
- vout:该交易的第几个输出
- scriptSig:输入脚本
- vout
- 数组
- value
- 金额
- 此处单位为比特币
- n: 序号(第几个输出)
- scriptPubKey
- asm:输出脚本操作
- reqSigs:该输出需要几个签名才可兑现
- type: 输出的类型
- address: 输出的地址
- value
交易过程
脚本形式
P2PK
- Pay to Public key
- 脚本
- 执行
- 1
- 2
- 3
P2PKH
- Pay to Public key Hash;最常用
- 脚本
- 执行
- 1
- 2
- 3
- 4
P2SH
Pay to Script Hash
脚本
- serialized redeemscript;脚本
- Sig;运行脚本需要的签名
执行
样例
- 1
- 2
为什么需要P2SH;支持多重签名
- 不使用P2SH
- 脚本
- 内容
- CHECKMULTISIG;检验多重签名
- X: Bitcoin 中 CHECKMULTISIG 执行存在 bug会从栈中多弹出一个元素
- 给出的M个签名的顺序要和他们在N个公钥中的相对顺序一致
- 执行
- 内容
- 问题:不同交易商指定的 N M 不同
- 麻烦
- 由用户自行加入购物交易输出脚本
- 脚本
- 使用P2SH; 脚本
- 内容:
- 执行:
- 1
- 2
- 不使用P2SH
Proof of Burn
- 说明
- return 直接报错
- 之后内容无意义
- 用于销毁比特币
- 小币种需要销毁一定的 Bitcoin 才可以得到该币种。 Altcoin: Alternative coin(替代币)
- 用于向区块链写入内容;所有人都可以
- 实例
- 全部作为交易费
- 对全节点友好; 不用在 UTXO 中记录该交易
总结
- 功能有限;无循环
- 使用简单;CHECKMULTISIG
比特币分叉
类型
- state fork
- 起因:对当前区块状态产生意见分歧
- 正常
- 故意
- deliberate fork
- 例如 forkign attack
- protocd fork
- 起因:协议升级
- 根据协议内容不同
- 硬分叉(hard fork)
- 软分叉(soft fork)
硬分叉(hard fork)
- 情况
- 加入新功能
- 且旧区块依然合法
- 对于旧协议新区块不合法
- 需要大量算力同意
- 只有有人不同意就会永久分叉
- 加入新功能
- 例子
更改 Bitcoin 区块大小限制
- 更改原因: 不改时交易吞吐量低
- 1M 只有 4000个交易
- 用10min
- 7 tx/sec
- 1M → 4M
- 更改原因: 不改时交易吞吐量低
ETH 与 ETC
- 情况: 以太坊硬分叉,分为 ETH 与 ETC 两种合法货币
- 问题:
- 分叉前一个币变两个币且都合法
- 由于公私钥相同,一个链上的交易在另一个链上依然合法,可以被在另一条链上重放
- 解决:两条链各带一个 chain ID
软分叉(soft fork)
- 情况
- 加入新功能
- 且旧区块不合法
- 对于旧协议新区块合法
- 需要大量算力同意
- 就算小部分节点不同意也不会永久分叉
- 加入新功能
- 例子
- 更改 Bitcoin 区块大小限制(假设)
- 1M → 0.5M
- 给 coinbase 域添加规定
- coinbase 铸币交易的自由填充域
- 提案
- 把 UTXO 组织成 Merkel tree
- coinbase 域 8bit 后的内容填充 UTXO 根哈希
- 方便查看账户余额
- P2SH:Pay to Script Hash
- 新节点两阶段验证
- 旧节点只验证第一阶段
- 更改 Bitcoin 区块大小限制(假设)
课堂问答
- 如果私钥被偷怎么办? 立刻新建账号转走余额
- Proof of burn 为什么抛出错误也可以被写入区块链? 抛出错误的是输出脚步,根本不会被执行
- 区块链大小变化历史:
比特币的匿名性
BTC的匿名力度到底如何
- 并不是完全无名,而是匿名; pseudonymity(使用假名)
- BTC安全性不如全匿名银行
- 所有人都可以查bitcoin账本
- 一般人无法查银行
- 可以建立不同公钥地址的关联
- 同一个交易的不同输出可能是同一个人
- 通过交易的必要性找到找零的地址
- 与现实生活发生关系的时候可以链接人和账户
- 与真是货币互换
- 买东西;几次特定交易筛选后很容易将账户与人彻底关联
- silk road 两度被抓
匿名的目的区分
向谁保密身份
- 保密容易
- 向fbi保密难
如何提高保密性
- 提高网络层匿名性 (多路径转发)
- 实现:数据包发出的路上多次转发
- 原理:只要一个节点不告诉别人谁发给他的就无法追查
- 提高应用层匿名性 (coin mixing)
- 实现:把币发给服务中心,多次交易后换成一堆与自己无关的别人的币
- 问题
- 可根据数额和时间被破解
- coin mixing服务中心可能收币跑路
- 实际使用
- 在线钱包有一定Coin mixing 性质
- 交易所有一点的coin mixing 性质
- 卖币
- 提币
- 换币
匿名困难的原因
- 区块链公开
- 区块链不可篡改 (一个交易暴露身份永远清不掉)
零知识证明
同态隐藏
- xy一点也不碰撞; 若E(x)=E(y) 则x=y
- 加密不可逆
- 盲签方法:
- 零币和零钞
- 设计动机:Bitcoin
- 可以提供匿名性
- 不可消除关联性
- 只要证明花的是真的币 不用交代花的是哪一个币
- 设计动机:Bitcoin
比特币引发的思考
哈希指针
指针如何指
- 其实没有指针只有哈希
- 全节点把所有区块存在一个(key,value)数据库中
- 大多为levelDB
- value为区块
- key为区块哈希
- 通过哈希可以直接找到区块
区块链
- 截断私钥的方式共享账户会降低账户安全性
- 应该用多重签名来共享账户
分布式共识
为什么比特币系统可以绕过分布式共识中那些不可能的结论
- Bitcoin 并没有真正达到共识;如果算力强甚至可以回滚到创世块
- 理论中的假设并不一定适用于现实模型; 没有真正的异步服务器;例:打电话
Bitcoin 的稀缺性
稀缺的东西不适合做货币
- 货币需要通胀
- 不然富者越富
量子计算
Bitcoin 是否会被冲击
- 量子计算离使用很远
- Bitcoin 地址用的不是公钥,是公钥的哈希
- 哈希函数会损失信息
- Bitcoin 一个地址不要用多次,每次转账剩余的钱转到一个新账户更安全;防止有钱的账户公钥泄露被量子计算偷钱
以太坊 ETH
以太坊概述
与 Bitcoin 的不同:
- 挖矿时间变化
- 减为15s一块
- 使用ghost共识协议
- mining puzzle 变化
- memory hard mining puzzle
- 内存要求高
- 限制了ASIC芯片的使用;ASIC resistance
- 权力证明替代工作量证明; proof of work → proof of stake
- memory hard mining puzzle
- 支持智能合约
- smart contract; decentralized contract
- 相较普通合约的优势
- 用司法手段维护合同比较困难;特别是涉及国家很多的小合同;众筹
- 一旦设立无法更改;且自动执行;无法扯皮
以太坊账户
与BTC不同
- BTC 基于 transaction-based ledger
- 花钱要说来源
- 一次必须花光一分钱
- ETH 基于 account-based ledger
- 和普通转账体验类似
- 天然防御 double spending attack
- 新的攻击方式;replay attck(重放攻击); 解决:给每个账户的交易案发生顺序编号
- 可开发金融衍生品;financial derivative
- 为什么要新建一套账户体系?
- Bitcoin 作为货币,主要目的是隐藏身份
- ETC 要支持智能合约,需要参与者有较为稳定的身份
账户类型
- externally owned account(外部账户)
- 内容:
- balance
- nonce; 交易计数器
- 内容:
- smart contract account(合约账户)
- 内容:
- balance
- nonce
- code
- storage
- 特性
- 不由公私钥对控制
- 不可凭空发出交易
- 内容:
以太坊数据结构
需求
- 完成账户地址到账户状态的映射
- 要包含的内容
- 地址;160bits
- 40个16进制数
- ETH-数据结构
- 状态
- balance
- nonce
- code
- storage
- 地址;160bits
- 需要的功能; 差账户余额的证明
- 尝试
- 哈希表;不满足
- 账户 Merkel tree
- 不排序:区块需要包含所以账户信息 内容太多,块太大
- 排序:加入新节点代价太大(若为奇数,半棵树要重构)
结构
键的存储(key,value)
设计过程
- trie 树(前缀树)
- Patricia tree(Patricia trie)(路径压缩前缀树)
- Merkel Patricia tree
成品
- Modified MPT
- Extension Node:路径压缩节点
- Branch Node:分支节点
- Leaf Node:叶节点(结束)
- 链接用哈希指针
- next node (Extension Node)
- 1 7 f (Branch Node)
- next node (Extension Node)
- 区块链规划
- 执行:全节点对于新区块;建立一个只有修改的账户的新MPT其他直接链接到上个区块的MPT
- 原因:
- ETH容易分叉
- 方便分叉到不对的链后快速回滚接上正确节点
以太坊代码中的数据结构
块头:
- ParentHash:前一个区块头的哈希值
- UncleHash:叔区块根哈希
- Coinbase:矿工地址
- Root:状态树根哈希
- TxHash:交易树根哈希
- ReceiptHash:收据树根哈希
- Bloom;Bloom filter ;与收据树相关
- Difficulty:挖矿难度
- Time:时间戳
- MixDigest:对 Nonce 进行一些运算后得到的哈希值
- Nonce:挖矿的随机数
区块:
- header :指向 block header 的指针
- uncles:指向叔块们的指针数组
- transactions:交易列表
区块链上的真正内容:
- Block 的前三项
值的存储(key,value)
方法:序列化后存储;RLP
- Recursive Length Profix
- 方法:nested array of bytes
- 特性:
- 任何东西都转换为一串字符数组储存
- 字符数组可以嵌套
以太坊交易树和收据树
收据树
- 产生:每个交易会生成一个收据
- 功能:方遍查询智能合约执行结果
- bloom filter
- 用处:查找指定元素是不是在集合中
- 实现:
- 将集合用哈希函数生成一个很小的摘要
- 通过一组哈希实现多次过滤
- 将集合用哈希函数生成一个很小的摘要
- 实际应用:
- 每个交易收据包含一个bloom filter;记录:
- 交易类型
- 地址
- ...
- 块头包含所有bloom filter的并集
- 查找信息时可以通过使用块头的bloom filter直接过滤掉大量无关区块
- 每个交易收据包含一个bloom filter;记录:
以太坊运行过程
- 交易驱动的状态机(transaction-driven state machine); 状态转移必须是确定的
- 问题:为什么区块链state tree中不止保存与本区块相关交易的状态?
- 查找一个账户余额变得困难
- 特别如果交易涉及新账户,则需要一直找到创世块才可以知道结果
代码数据结构
- bloom filter 长度为2048位
- ...自己看
以太坊GOHST协议
产生原因
- 分叉是常态
- 若分叉常见
- 矿池挖出的区块成为最长合法链的概率很大
- 矿池在网络中位置好,多个矿工同时出块可能矿池的块先到
- 由于上述原因:一份算力成长可能带来多份收益(Centralization bias 集中偏见)
实现机制
uncle block:
- 实现
- 叔父区块拥有 7/8 的出块奖励
- 包含叔的块可以额外拿 1/32 的出块奖励
- 一个块最多两个叔
- 包含叔块但不包含叔的交易
- 甚至不检查交易合法性
- 检查是不是一个合法发布的区块;是不是符合挖矿难度
- 用处:招安其他的链
- 问题
- 若有第三个叔无法包含
- 若挖出来之前都没叔出现,则拿不到额外奖励
- 矿池竞争,故意不让竞争对手当叔
- 改进一
- 认叔叔不限辈分,可以回溯;若不限制辈分则可以;不停产生合法分叉等着之后被友军包含
- 改进二
- 必须与当前区块在 7代 内有共同祖先
- 好处:鼓励提早合并
实例
- 叔区块列表
- 每个叔一行
- 包含叔的块
以太坊挖矿算法
挖矿意义
Block chain is secured by mining
ASIC resistance
方案
- memory hard mining puzzle
- 原因:
- ASIC 芯片在运算时性能爆炸;并行计算等方法
- 但内存读写速度很难有大的代差
- 例子
- 使用 Scrypt 作为哈希函数
- 用于 LiteCoin
- Scrypt
- 过程:
- 开一个大数组
- 按顺序填一些伪随机数;第一个填一个种子节点生成的随机数;之后每个数是前一个的哈希
- 解 puzzle 时;每次读取一个数;读取的数与上个读取的数相关
- 好处:若数组够大;不在内存保存数组会带来巨大的计算开销
- 坏处:对轻节点 memory hard
- 过程:
- 以太坊
- 使用 Scrypt 作为哈希函数
- 原因:
- proof of stake;就算我是吓唬人又如何?
弊端
调集大量挖矿算力变得容易;不用买矿机 云计算就够
以太坊
两个数据集
- 16M cache(轻节点保存)
- 1G dataset(DAG)(全节点保存)
- 定期增长
运行
- cache 的生成同 LiteCoin
- 生成更大的数组
- 在 cache 中读取256次,这256个数经过运算生成一个数填入 dataset; 类似 LiteCoin 解puzzle
- 循环上述操作直到 dataset 满
- 解 puzzle
- 用 blcok header 和 nonce 算出值,映射到 dataset 中的位置
- 读取该位置与该位置相邻位置的数
- 继续运算出下一个要读取的位置
- 比较最终得到的128个数的 hash 和目标难度
ethash算法伪代码
- 生成 cache
- 通过 seed 生成 cache
- 过程:
- cache中元素按序生成:每个元素产生时与上一个元素相关
- 每隔30000个块会重新生成seed:(对原来的seed求哈希值);利用新的seed生成新的 cache;
- cache的初始大小为16M;每隔30000个块重新生成时增大初始大小的 1/128——128K
- 通过 cache 生成 dataset中第 i 个元素
- 过程:
- datase (DAG) 初始大小 1G;每隔30000个块更新,同时增大初始大小的1/128;8M
- 通过 cache 中的第 (i% cache_size)个元素生成初始的mⅸ
- 两个不同的 dataset元素能对应同一个 cache中的元素
- 为了保证每个初始的mix都不同, i 也参与了哈希计算
- 循环256次
- 每次通过 get_int_from_item 根据当前的mⅸ值求得下一个要访问的cache元素的下标
- 用这个 cache 元素和 mix 通过 make_item 求得新的 mix 值;由于初始的mⅸ值不同所以访问 cache 的序列也都不同
- 返回mⅸ的哈希值,得到第 i 个 dataset中的元素
- 多次调用这个函数,就可以得到完整的dataset
- 过程:
- 生成 dataset
- 反复调用 calc_dataset_item 生成完整 dataset;共full_size个元素
- 挖矿与验证
- 矿工挖矿
- 通过 heade和 nonce求出一个初始的mix
- 进入64次循环
- 根据当前的mix值求出要访问的 dataset的元素的下标;full_size 为 dataset 的 size
- 临时计算出用到的 dataset
- 最后返回mix的哈希值,用来和 target比较
- 挖矿与验证
- 矿工挖矿
ASIC resistance
- 挖矿法
- proof of stake
币种的金钱属性
- pre-mining
- 创始人先挖(相当于拿股票)
- Genesis 部分:
- pre-sale; 卖 pre-mining 的币(相当于众筹)
以太币趋势
- 算力分布:
- 币值:
- 市值:
- HashRate(所有矿工每秒计算哈希次数):
以太坊挖矿难度调整
公式
- H :当前区块
- Hi :区块序号
- D(H) :本区块的难度
- P(H)Hd :父区块难度
- x * ζ2 :
- x :
- 调整力度
- 父区块难度的 1/2048
- ζ2 :
- y :与父区块 uncle 数有关
- 父区块有uncle y=2
- 父区块无uncle y=1
- Hs :当前区块时间戳
- P(H)Hs :父区块时间戳
- Hs-P(H)Hs :出块时间
- y :与父区块 uncle 数有关
- x :
- ε 难度炸弹:
- 设立原因:方便之后转入 proof of stake;挖矿指数性变难
- Hi :当前区块序号
- -3000000
- proof of stake 没弄出来,差点把自己炸死
- 争取了一年半
- 效果:
- 设立原因:方便之后转入 proof of stake;挖矿指数性变难
以太坊发展四个阶段
下调奖励:对之前的矿工公平
- Forntier
- Homestead
- Metropolis
- Byzantium
- Constantinople
- Serenity
代码
基础
- bigTime:当前区块时间戳
- bigParentTime:父区块时间戳
炸弹
-2999999;依照的是父区块
难度统计
- 难度:
- 出块时间:
- Total Difficulty:
- Total Difficulty:
- 所在链总难度
- 最长合法链为最难合法链
- Total Difficulty:
权益证明
提出原因
Proof of work 费电
Bitcoin
能耗趋势
- 比特币挖矿能耗(单位 TWH = 10^9 KWH)
分析:
- 能耗
- 69.95 TWH
- 相当于智利整个国家的能耗
- 647w个 美国家庭能耗
- 占世界能耗 0.31%
- 每个交易1000度电;34.26个家庭能耗
- 利润
- $60亿(利润)
- $34亿(能耗)
- 能耗
Ethereum
- 能耗趋势
- 分析
- 能耗
- 19.78 TWH
- 冰岛年能耗
- 54w个美国家庭
- 每个交易67度电; 2.25个美国家庭
- 占世界能耗 0.09%
- 利润
- $50亿(利润)
- $23.7亿(能耗)
- 能耗
费电好处
好多电本来也是过剩产能
Proof of stake (virtual mining)
- 开发时
- 留钱给开发者
- 或出售众筹
- Proof of Deposit: 用冻结币一段时间的方法降低挖矿难度
- 优势
- 省电
- Proof of work 维护区块链的资源不是闭环
- Proof of work是从外界买到的
- 矿机
- AltCoin Infanticide; Infant(婴孩)
- Proof of stake 被攻击会很爽。。
- Proof of work是从外界买到的
- 问题: 分叉两边下注
- ETH 中的协议:Casper the Friendly Finality Gadget (FFG)
- 意义:包含在 Finality 中的交易不会被取消
- 实现:
- Validator(验证者)
- 投入一定保证金(抵押)
- 正常完成任务可以获得奖励
- 如果不作为使得系统无法达成统一会被扣保证金 (惩处)
- 如果胡作非为(两边下注)会被扣完保证金 (惩处)
- 验证者有任期
- 任期之间有等待期
- 等待期时可以对验证者工作进行评估举报 (上述**(惩处)** 方式)
- 等待期结束正常的验证者可以取回保证金和奖励
- 被扣的钱直接销毁
- 每100个 block 为一个 epoch
- 对epoch进行投票
- 2/3 保证金同意才算有效
- 两阶段(two-phase commit)
- Prepare Message ;2/3
- Commit Message ; 2/3
- 优化后 50 block一组epoch
- 本次投票为前一次的 Commit Message 为本次 Prepare Message
- 连续两次投票通过才算通过
- 对epoch进行投票
- Validator(验证者)
- EOS 中的协议:DPOS:Delegated Proof of Stake
- 投票选21个超级节点
- 超级节点产生区块
以太坊智能合约
定义
- 运行在区块链上的一段代码
- 代码的逻辑定义了合约的内容
内容
- balance: 余额
- nonce : 交易次数
- code :合约代码
- storage : 存储(一颗MPT)
实例
如何调用Smart Contract
外部账户调用
- sender:发送者
- To contract : 目标合约
- 对合约发起转账交易极为调用
- 在data注明调用的函数; 红色
合约调用
- 直接调用
- 地址转为合约类型调用
- 被调用合约异常 调用者异常
- 直接用地址call
- 被调用者异常,call返回 false 调用者不异常
- dalegatecall
- 地址转为合约类型调用
- fallback函数
Smart Contract 创建和运行
- 创建合约
- 外部帐户发起一个转账交易到0X0的地址
- 转账的金额是0,但是要支付汽油费
- 合约的代码放在data域里
- 智能合约运行在EVM( Ethereum Virtual Machine)上; 增强可移植性
- 执行
- 以太坊是一个交易驱动的状态机
- 调用智能合约的交易发布到区块链上后
- 每个矿工都会执行这个交易
- 从当前状态确定性地转移到下一个状态
- gas fee
- 不可知是否会死循环
- 交易数据结构
- Price:单位gas 费
- GasLimit:最多愿意付多少
- Recipient:收款地址
- Amount:转账金额
- Payload:data域
- 执行
- 先扣 Price * GasLimit
- 多退 少回滚
- 错误处理
- 智能合约中不存在自定义的try- catch结构
- 一旦遇到异常,除特殊情况外,本次执行操作全部回滚
- 可以抛出错误的语句
- assert(bool condition)如果条件不满足就抛出 ;用于内部错误
- require(bool condition)如果条件不满足就抛掉;用于输入或者外部组件引起的错误
- revert()终止运行并回滚状态变动
- 嵌套调用
- call不会回滚
- 转成合约类型会回滚
- Gas
- Gas Limit :每个区块可以被上调下调 1/1024
- 怎么扣
- 全节点收到调用的时候从本地减掉目标账户汽油费
- 之后执行合约,多退少补
- 发布到区块链上的交易不一定都是成功执行的; 要扣崽种们的gas fee
- 弊端
- 没挖出矿的白花了运行合约的计算资源
- 算力小的节点特别吃亏
- Receipt 数据结构
- Status:交易执行情况
智能合约可以得到的信息
- 区块链信息:
- 调用信息:
- 地址类型:
- transfer
- 失败回滚
- gas上限2300
- send
- 失败return false
- gas上限2300
- call.value()
- 失败return false
- gas为本次剩余gas
- transfer
例子:简单拍卖
版本一(有错)
版本二
- 还是有错:
- 修改方式:
- 先清零再转账
- 不用 call 转账
- 版本二·改:
以太坊 The DAO
提出理念
- DAO Decentralized Autonomous Organization (去中心化自治组织)
- DAC Decentralized Autonomous Corporation (去中心化自治公司)
实例
The DAO
- 设计理念
- 功能
- 众筹投资; ETH换代币
- 按代币民主投票
- 投资后可以返现
- 取回收益
- split DAO
- child DAO
- 用于拆分出独立系统;拆分后的系统投资给自己;锁定28天之后获得退款
- 功能
- 代码
- 重入
- 问题
- 补救
- 锁定账户
- 增加大家都不能和The DAO 相关账户交易的新规则;软分叉
- 问题:出现不合规定(和 The DAO 发生交易的)交易不收崽种们的gas fee ,被攻击了
- 将TheDAO 所有钱打到一个新合约,新合约退钱
- 所有矿工挖到第192w个区块的时候自动把TheDAo中的钱转走(硬转 不用签名)
- 问题:
- 投票的人很少
- 很多人不认可多数人对
- 导致很多人留在旧链;ETC;Ethereum Classic
- 锁定账户
以太坊 反思
以太坊 反思以及智能合约
- Is smart contract really smart?(智能合约智能吗?) Smart contract is anything but smart
- 不可篡改性是双刃剑
- Irrevocability is a double edged sword
- 有错难改
- 不可改代码
- 不可阻止对合约的调用
- Nothing is irrevicable(没有什么是不可篡改的)
- Solidity 语言
- Is solidity the right programming language?(Solidity 语言设计上有问题)
- 与人的思维模式不同,容易出错;给别人转账还会调用别人的函数
- 语言验证目标;formal verification;证明代码只能做指定的事
- 编写智能合约的语言要有什么特点
- 不一定图灵完备
- 但能实现目标功能
- 解决方法:智能合约模板
- Is solidity the right programming language?(Solidity 语言设计上有问题)
- 为什么开源的bug还没人发现?
- Many eyeball fallacy
- 没人愿意看
- 觉得大家都看了
- 要检查
- Many eyeball fallacy
- What does decentralization mean?(去中心化代表什么?)
- 之所以可以成功硬分叉是因为大部分矿工(90%)同意分叉
- 用去中心化的方式修改规则
- 分叉也是区中心化系统的用户权力;恰恰是民主的体现
- decentralized ≠ distributed(去中心化不是分布式) 智能合约 为 State machine
- state machine
- 目的是容错
- 几台计算机重复相同操作
- 一台机子故障其他顶上
- 机子越多越慢
- 最初应用场景;mission critical applications
- air traffic contril
- stock exchange
- space shuttle
- 目的是容错
- 是用来达成共识的
- state machine
以太坊 美链
背景
ERC20
- Ethereum Request for Comments
- 代币发行规范
Beauty Chain(一种代币)
ICO
代币以智能合约的形式运行在以太坊平台上
问题
- 溢出攻击
攻击细节
- 参数
- [0]: _receivers 数组的存储地址为 0x40 = 64 从 [2] 开始
- [1]: __value 巨大
- [2]: 数组长度 2
- [3]: 地址
- [4]: 地址
- 交易
- 攻击结果
反思
数字运算要考虑溢出;SafeMath库
以太坊 总结
应用:
- 不可:
- 保险理赔
- 有机蔬菜
- 使用去中心化技术的商业模式不一定不是中心化
- 没有法律保护
- 应该用在已有系统解决的不太好的地方;全球之间的支付
- 价值随信息传播
- Information can flow freely on the Internet, but payment cannot
- 支付低效
- 不该与已有系统竞争
- 效率在增加
- 效率要比较才知道(历史环境) 比如电报
- 程序不易读
- If the business model is bad. it's still bad on the Internet;同样适用于 区块链