0%

区块链技术与应用-以太坊

1. 概述

以太坊中的出块时间缩短为十几秒,设计了基于gost的协议。以太坊中的mining puzzle是memory hard的,限制了ASIC的使用(ASIC resistance)。

proof of work –> proof of stake

Bitcoin: decentralized currency
Ethereum: decentrailized contract(去中心化的合约)

2. 以太坊账户

基于账户的模型(account-based ledger)

有余额的概念,转账交易时只需验证账户上是否有足够的余额,不用验证币的来源,对于double spending attack有天然的防御。

缺点: replay attack
a向b转10个币,写入区块链中,b又广播一次a向b转账的交易
防范:

1
2
3
A -> B(10 ETH)
nonce = 21
singed by A

nonce 为交易次数,每一个交易的nonce唯一

以太坊中有两类账户:

  • 外部账户(externally owned account)

    • 由公私钥对控制
    • 属性:
      balance(账户余额)
      nonce(计数器)
  • 合约账户(smart contract account)

    • 特点:
      一个合约可以调用其他合约,但合约账户不能主动发起交易
    • 属性:
      nonce
      code
      storage

3. 状态树

1
2
3
4
5
为了实现从账户地址到账户状态的映射
addr -> state
160 bits 40个16进制的数
state: 外部账户(balance nonce)
合约账户(nonce code storage)

(key, value)
RLP:Recursive Length Prefix

3.1. trie(字典树)

trie

特点:

  1. 每个节点的分支数目取决于key值中每个元素的取值范围(在以太坊中分叉数为17,因为是16进制,加上一位结束标志)
  2. tire的查找效率取决于key的长度,键值越长,查找需要访问内存的次数越多。(在以太坊中key的长度为40)
  3. 不会出现碰撞(只要地址不同就不可能碰撞)
  4. 插入顺序不影响树的结构
  5. 更新的局部性很好,只更新相关的分支

缺点:

  1. 浪费存储空间

3.2. Patricia trie(tree)

为了解决trie的存储浪费,同时提高查找效率,引入了pt

pt 是前缀树,对于字典树进行路径压缩。

pt

注意:
在pt中新插入元素,原来压缩的路径可能会扩展开

3.3. MPT(Merkle Patricia tree)

使用哈希指针的pt

以太坊中使用的是 modified MPT
mpt

blocks

保存历史状态是为了支持回滚操作

blockheader代码:
headcode

block代码:
blockcode

extblock代码:
ext

4. 交易树和收据树

对于状态树来说,查找的键值就是账户的地址,对于交易树和收据树来说,查找的键值就是这个交易在发布的区块里的序号,交易的排列顺序是由发布这个区块的节点决定的。

区别:

  • 交易树和收据树是只把当前发布的区块的交易组织起来的;而状态树是把系统中所有账户的状态都要包含进来,不管这个账户与当前的交易有没有关系。

  • 每个区块的交易树和收据树都是独立的,他们是不会共享节点的,一个区块和另一个区块发布的交易本身我们也认为是独立的。

作用:

  • 提供Merkel proof
  • 查找过去n天产生与某个只能合约相关的交易

4.1. bloom filter

可以支持高效的查找,判断某个元素是否在某个集合中。
思想: 为集合计算出一个紧凑的摘要,哈希映射
缺点:

  • 哈希碰撞(false positive)
  • 不支持删除操作(哈希碰撞)

通过bloom filter可以过快速过滤掉无关的区块

以太坊的运行过程可以看做是一个交易驱动的状态机(transaction-driven state machine),状态的转换是确定的

5. GHOST 协议

在以太坊中出现分叉的情况更为常见
ghost1

(uncle区块:当一个区块a被挖出时,感知到有相同的区块b被挖出,则b是c的uncle区块)被包含的uncle区块可获得7/8的出块奖励。

新区块如果包含一个uncle区块可以获得额外的1/32的出块奖励,一个新区块最多包含2个uncle block。

初代ghost协议存在的问题:

  • 只能包含两个uncle区块
  • 为了商业竞争,可能故意不包含uncle区块

修改协议:

  • 祖父,曾祖父区块。。。都可以作为uncle区块,因为区块不太可能都是由同一个矿池挖出,所以会有其他区块包含uncle区块,使得uncle区块可以获得奖励。

uncle2

  • 以太坊中规定最多可以包含前6代的uncle区块,6代之前的不是uncle区块,或者说合法的uncle只有6个辈分。
  • 对于当前块来讲,包含任意辈分的uncle,都能获得额外的1/32的出块奖励。

以太坊中有两种reward,block reward和gas fee,uncle block不能获得gas fee。gas fee与比特币中的交易费类似。

问题:

  1. 包含uncle block时要执行uncle block中的交易吗?
    不检查uncle block中交易的合法性,值检查uncle是否符合挖矿难度

  2. 如果分叉之后还跟着一串该怎么办?
    q2
    如果每个都给奖励,会降低分叉攻击的成本。以太坊中规定只给第一个区块奖励。

6. 挖矿算法

挖矿是保证区块链安全的一个重要保障,所以我们可以说block chain is secured by mining.

但是比特币的挖矿算法后来出现了ASIC芯片,使得具有强算力的设备在挖矿上有更大的优势,这与去中心化的思想是背道而驰的。(只能专业的机器,普通的计算设备不能参与挖矿)

后来出现的加密货币的挖矿算法在设计的时候尽量降低对于ASIC的依赖,增加对内存的需求,即

ASIC resistance
memory hard mining puzzle

LiteCoin 就是基于这种思想的加密货币

6.1. LiteCoin

使用基于scrypt的mining puzzle

litecoin

开设一个很大的数组,按照顺序填充一些伪随机数,使用seed填充第一个值,后一个值是有前一个值取哈希得到的。
求解puzzle时,读取A位置的数,根据他的取值算出下一个读取的位置,比如是B,以此类推。

问题:

  • 对于轻节点不友好,验证和求解需要同样的内存

实际上litecoin的内存只有128k

6.2. 以太坊

以太坊使用memory hard的挖矿算法。

  • 有两个数据集,小数据集16M cache,大数据集1G dataset(DAG)。大数据集是从小数据集中生成出来的。
  • 小数据集是轻节点保存的
  • 大数据集是挖矿节点使用的
  • 这两个数据集是不断增大的

6.2.1. 伪代码

生成小数据集:
code-16m

生成大数据集:
code-1g
code-1gc

挖矿/验证函数:
code-mining-check

挖矿函数:
code-mine

全部函数:
code-eth

6.3. 几点说明

  1. 以太坊实际上只有gpu挖矿,没有出现ASIC矿机,从这一点上讲是比较成功的。

  2. 以太坊构思从工作量证明转向权益证明,即POW->POS,但至今没有转变。

  3. 以太坊中使用了预挖矿(pre-mining)的过程,所谓预挖矿是指预留一些以太币给开发者。

7. 难度调整算法

与比特币的每隔2016个区块调整一次不同,以太坊是每隔区块都有可能调整难度。

难度调整算法:
difficult

diffcult-1

diffcult-2

diffcult-e

以太坊发展的4个阶段:
4stage

拜占庭阶段调整挖矿难度具体代码实现:
code-difficult

code-diffi-base

8. 权益证明(proof of stake)

例如,根据持有币的多少来确定挖矿难度,持有币越多,挖矿难度越低,但这个设计会有问题,因为持有币多的人总会很容易挖到矿。所以有的加密货币要求投入的币会锁定一段时间。有时候叫做proof of deposit。

早期的权益证明会遇到两边下注的问题(nothing at stake)
nothing-at-stake

在下面分支投入的币不会影响上面分支

8.1. Casper the Friendly Finality Gadget(FFG)

以太坊想要使用的权益证明

1
2
3
4
5
6
7
8
9
10
以太坊中引入了一个validator的概念:
validator(验证者): 要成为一个validator,必须要投入一些以太币作为保证金,这些保证金会被系统锁定

validator职责:推动系统达成共识,投票决定哪条链是最长合法链,投票的权重取决于投入保证金的多少。

具体做法类似于数据库中的 two-phase commit,第一轮 prepare message, 第二轮 commit message

挖矿时每挖出100个区块,就作为一个epoch。 决定其能否作为一个 ,要进行投票。每一轮投票都要得到2/3以上的验证者才能通过。

在实际中不再区分这两个message,且将100个区块降为50个区块。每个epoch只用一轮投票,这轮投票对于上一个epoch来说是commit message,对于下一个epoch来说是prepare message,连续两轮投票都得到2/3以上的多数,才算有效。

epoch

验证者参与这个过程:

  • 如果验证者履行职责,可以得到相应的奖励
  • 如果验证者有不良行为,要受到相应的惩罚
    • 行政不作为(该投票不投票),扣除一部分保证金
    • 乱投票(两边下注),没收保证金(销毁)
  • 每个验证者有一定任期,任期满了之后有一定等待期,在等待期可以接受其他节点检举揭发对其惩处,如果等待期通过,则可以取回保证金和相应的奖励

9. 智能合约

  • 智能合约是运行在区块链上的一段带密码,代码逻辑定义了合约内容
  • 智能合约的账户保存了合约当前的运行状态
    • balance: 当前余额
    • nonce: 交易次数
    • code:合约代码
    • storage: 存储,数据结构是一颗MPT
  • Solidity是智能合约最常用的语言,语法上与JavaScript很相近

solidity

9.1. 如何调用智能合约

调用智能合约与转账类似,例如A转账给B,若B是一个普通账户,则与比特币中的转账是相同的;若B是一个合约账户,这个转账实际上是发起对B合约的一次调用,具体调用的函数是在data域中说明的。

9.1.1. 外部账户调用

call
其中:

  • TO CONTRACT ADDRESS: 是被调用的合约的地址
  • 中间一行是调用的参数

汽油费是给发布这个区块的矿工的,汽油费如果不给的话,矿工不会把这个交易打包进入区块。

9.1.2. 一个合约调用另一个合约

call-1

由于以太坊中合约账户不能主动发起交易,所以在这个例子中应该还有一个外部账户,调用了合约B。

call-2
call-3

9.1.3. fallback 函数

fallback

9.2. 智能合约的创建和运行

C&R

9.3. 汽油费(gas fee)

gas-fee

死循环不可解,是一个Halting Problem

9.4. 错误处理

error

如果汽油费不够,则会引起回滚,但是已经消耗的汽油费不退,此举是为了防止恶意节点发起拒绝服务攻击。

9.5. 嵌套调用

qiantao

9.6. 智能合约可以获得的区块信息

  • block.blockhash(uint blockNumber) returns (bytes32) : 给定区块的哈希—仅对最近的256个区块有效而不包括当前区块
  • block.coinbase(address):挖出当前区块的矿工地址
  • block.difficulity(uint):当前区块难度
  • block.gaslimit(uint):当前区块gas限额
  • block.number(uint):当前区块好
  • block.timestamp(uint):自unix epoch起始当前区块以秒计的时间戳。

9.7. 智能合约可以获得的调用信息

  • msg.data(bytes):完整的calldata
  • msg.gas(unit):剩余gas
  • msg.sender(address):消息发送者(当前调用)
  • msg.sig(bytes4):calldata的前4字节(也就是函数表示服)
  • msg.value(uint):随消息发送的wei的数量
  • now(uint):目前区块时间戳(block.timestamp)
  • tx.gasprice(uint):交易的gas价格
  • tx.origin(address):交易发起者(完全的调用链)

9.8. 地址类型

addresstype

9.8.1. transfer vs. send vs. call

这三个函数都可以用于转账

  1. transfer和send 这两个是专门为了转账的函数,区别在于,transfer会导致连锁回滚;send不会导致连锁回滚
  2. call本意是用来调用函数的,也可以转账。也不会连锁回滚。把剩下的汽油都发过去

10. the Dao

  • DAO(Decentralized Autonomous Organization) 去中心化的自治组织

    • 建立在代码的基础上的组织, 组织的规章制度写在代码里,通过区块链的共识协议维护规章制度的正常执行
  • DAC(Decentralized Autonomous Corporation)

  • the Dao: 2016年5月出现的一个致力于众筹投资的组织。使用以太币换取代币,由投入币的多少确定投票资格。收益的取回方式:split Dao,split直到子Dao中只有一个用户。
    the dao
    由于代码的漏洞,黑客发动了重入攻击。取走了很多以太币
    这件事引起了轩然大波,在社区引发了激烈讨论,以太坊开发团队首先试图冻结与the Dao相关的交易,发布软件升级,实现软分叉,但由于升级的代码中不收取与the Dao相关交易的汽油费,导致产生了很多攻击。后又发布另一个版本的升级,实现硬分叉。以太坊分为了两个社区,旧链改为ETC,新链仍使用ETH.

10.1. 反思

  1. 关于智能合约的反思
  • Is smart contract really smart?
    smart contract is anything but smart.

  • Irrerocability is a double edged sword

  • Nothing is irrevovable(不可篡改)

  • Is solidity the right programming language?

  1. what does decentralization mean?
    对规则的修改需要用去中心化的方式来修改

  2. decentralized != distributed

11. 美链

beautiflu-chain

batchtransfer

当value很大时,amount可能会溢出,会导致体统上凭空出现很多代币。

12. 课程总结

  • 中心化的组织也可以使用去中心化的支付方式
  • 缺乏一种全球流通的货币
  • 未来互联网的发展方向:支付渠道和信息渠道的统一
  • 加密货币不应该与现有货币竞争
  • 随着协议的改进,支付效率提高了很多
  • 评价