以太坊学习摘要

以太坊

以太坊(Ethereum)是一个建立在区块链技术之上, 去中心化应用平台。它允许任何人在平台中建立和使用通过区块链技术运行的去中心化应用。与比特币相比,以太坊属于区块链2.0的范畴。

从平台角度来看,以太坊类似于苹果或者安卓的应用商店;从技术角度来说,以太坊类似于一个区块链操作系统。

下图是以太坊的组成:

以太坊组成.png

所以,可以理解为:“以太坊=区块链+智能合约”。开发者在以太坊上可以开发任意的应用,实现任意的智能合约。以太坊的虚拟机和智能合约扩展了外部应用程序在区块链技术上的应用。另外,以太坊中的智能合约是运行在虚拟机(也就是EVM,Ethereum Virtual Machine,以太坊虚拟机)上的。

智能合约

智能合约就是以太坊上的程序,它是代码和数据(状态)的集合。所以,不管什么样功能的合约,站在技术的角度上来讲,就是通过执行一组程序改变了一些值。

我们不但可以实现数字货币,还可以实现众筹合约、担保合约、融资租赁合约、期货合约以及各种金融与非金融的订单合约。

在以太坊中,每个合约都有一个唯一的地址来标识它自己(由创建者的哈希地址和曾经发送过的交易的数量推算出来)。客户端可以与这个地址进行交互,可以发送ether,调用函数,查询当前的状态等。

有三种常见的智能合约语言,这些语言可以被编译成智能合约运行在以太坊虚拟矿机上。它们是:

  • Solidity:和Javascript语言类似。这是目前最受欢迎的和功能丰富的智能合约脚本语言。
  • Serpent:和Python语言类似,在以太坊历史的早期受欢迎。
  • LLL (Lisp Like Language):和Lisp类似,只有在早期使用。它大概是最难用的。

状态

状态可以理解为以太坊中的某些内容发生变化。

对于区块链账本,这里的变化可以指一笔转账,也可以是合约的某个规则被激活等,总之就是数据动了,以太坊中将变化的过程称为状态转变函数

在以太坊系统中,状态是由被称为“账户”的对象和在两个账户之间转移价值和信息的状态转换构成的。

以太坊的每个区块头中都包含了指向三棵树(状态树、交易树、数据树)的指针。

账户

以太坊具有账户的概念。在以太坊中有两类的账户:外部账户 和 合约账户。

外部账户

外部账户(EOA,Externally Owned Account),它就是一个一般账户的概念。外部账户是由一对秘钥定义的,一个私钥一个公钥,公钥的后20位作为地址。

外部账户没有关联任何的代码。

合约账户

智能合约的部署是指把合约字节码发布到区块链上,并使用一个特定的地址来标示这个合约,这个地址称为合约账户。合约账户是可编程的,可以执行图灵完备的计算任务,合约账户之间可以传递消息。

区别和联系

合约账户的地址是通过合约创建者的地址和该地址发出过的交易数量计算得到的。

一个外部账户可以通过创建和用自己的私钥来对交易进行签名,来发送消息给另一个外部账户或合约账户。

在两个外部账户之间传送消息是价值转移的过程。但从外部账户到合约账户的消息会激活合约账户的代码,允许它执行各种动作(比如转移代币,写入内部存储,挖出一个新代币,执行一些运算,创建一个新的合约等等)。

只有当外部账户发出指令时,合同账户才会执行相应的操作。

账户的结构

以太坊中的账户包含以下4个部分:

  • 随机数(Nonce)。用于确定每笔交易智能被处理一次的计数器,也就是每个账户的交易计数,用于防止重放攻击。当某个账户发送一笔交易时,根据已生成的交易数来累加这个数字。
  • 账户目前的以太币余额(Balance)。
  • 账户的存储(Root),它是一个哈希值,指向的是一棵patricia trie(帕夏尔前缀树)。默认为空
  • 账户的合约代码(CodeHash),只有合约账户才有,否则为空。

交易

以太坊中的交易就是状态的转换过程。

交易在以太坊中是在签名的数据包,这个数据包中存储了从外部账户发送的消息。所谓的交易就是一个消息,这个消息被发送者签名了。

交易类型:

  • 转账交易。也就是从一个账户往另一个账户转账发以太币。
  • 合约创建交易。也就是创建一个合约,因为创建合约也要消耗以太坊。
  • 合约执行交易。在以太坊中,执行合约也算一种交易。

数据结构

  • AccountNonce:表明交易的发送者已经发送过的交易数,与账户中定义的随机数对应。
  • Price和GasLimit:用来抵抗拒绝服务攻击。就是为了让交易的执行带上成本,每进行一次交易都要支付一定的手续费,GasLimit是交易执行所需的计算量,Price是单价,两者的乘积就是手续费。如果交易在执行的过程中实际所需的消耗超出了Gas限制就会出错回滚,如果存在多余的Gas就会退还多余部分。
  • Recipient:接收方的地址。
  • Amount:发送的以太坊金额,单位wei。
  • Payload:交易携带的数据,根据不同的交易类型有不同的用法。
  • V、R、S:交易的签名数字。

以太坊的区块头中有交易信息。

计量单位

最小单位是wei。1 ether = 1000 000 000 000 000 000 wei。

kwei = 1000wei

mwei = 1000kwei

gwei = 1000mwei

szabo = 1000gwei

finney = 1000szabo

ether = 1000finney

收据

在以太坊中,收据是指每条交易执行所影响的数据条,在以太坊的区块头中存储了收据树的根哈希值。

收据实际上是一个数据的统计记录,记录了执行后的特征数据。

数据结构如下:

  • PostState: 状态树的根哈希。通过这个字段使得收据可以直接访问都状态数据。
  • CumulativeGasUsed:累计的Gas消耗,包含关联的本条交易以及之前的交易所消耗的Gas之和,或者说是指所在区域的Gas消耗之和。
  • TxHash:交易事务的哈希值。
  • ContractAddress:合约地址,如果是普通的转账交易则为空。
  • GasUsed:本条交易消耗的Gas。

Gas

在以太坊中Gas可以理解为在以太坊平台上执行程序需要付出的成本或者手续费。

Gas是通过以太坊中合约的执行计算量来决定的,这个计算量可以简单理解为是算力的消耗,执行一次SHA3哈希计算会消耗20个Gas,执行一次普通的转账交易就要消耗21000个Gas。

以太币总额 = 消耗的Gas ✖️ Gas单价。

以太坊客户端

以太坊客户端,其实我们可以把它理解为一个开发者工具,它提供账户管理、挖矿、转账、智能合约的部署和执行等等功能。

go-ethereum是官方的Go语言客户端。可用于挖矿、组件私有链、管理账号、部署智能合约等。它提供了一个交互式命令控制台,通过命令控制台中包含了以太坊的各种功能(API)。

除go-ethereum外,官方还提供了cpp-ethereum,基于C++写的。

以太坊网络

我们可以把以太网络分为3种:主网、测试网络和私有网络。

  • 生产环境网络(主网): 以太坊的生产网络顾名思义,也就是产生真正有价值的 的以太币的网络。
  • 测试网络: 以太坊的测试网络也是官方提供的,顾名思义就是专供用户来开发、调试和测试的。上面的合约执行不消耗真实的以太币。官方提供的为:Rinkeby
  • 私有网络:以太坊的私有网络,顾名思义就是由用户自己创建的私有网络。

以太币

以太币每年的产量则是固定的。

以太币的数量以这种形式存在:Pre-mine(矿前) + Block rewards(区块奖励) + Uncle rewards(叔块奖励) + Uncle referencing rewards(叔块引用奖励)

  • 矿前:2014年7月/8月间,为众筹大约发行了7200万以太币。这些币有的时候被称之为“矿前”。众筹阶段之后,以太币每年的产量被限制在7200万以太币的25%(每年以太币的矿产量,不高于1800万,除了一次性为crowdsale而发行的7200万以太币)
  • 区块奖励:每产生一个新区块就会产生5个新以太币。每年有225万个区块被挖出来,每个区块5个以太币,也就是每年会产出1130万个以太币。
  • 叔块奖励:有些区块被挖得稍晚一些,因此不能称为主区块链的组成部分,以太币称它们为“ uncles”,并且在之后的区块中,可以引用它们。如果uncles在之后的区块链中作为叔块被引用,每个叔块会为挖矿者产出大约4.375个以太币(5个以太币奖励的8分之7).这被称之为叔块奖励。
  • 叔块引用奖励:矿工每引用一个叔块,就得到了大约0.15个以太币(最多引用两个叔块)。

引用: