1、以太坊概览
以太坊使用Solidity编程语言编写智能合约。智能合约完全按照程序运行,而且防停机、防审查、防欺诈、防第三方干扰。部署智能合约或者调用其方法需要用到以太币。
以太坊使用区块链数据结构和工作量证明共识协议。有两种网络中的节点:普通节点和矿工。普通节点只备份区块链上的数据,而矿工通过挖矿创建区块链。
2 、以太坊账户
要创建以太坊账户,只需要一个非对称加密密钥对——由不同的算法(例如RSA、ECC等)生成。以太坊使用椭圆曲线加密算法(ECC),ECC有多个参数用来调节速度和安全性,以太坊使用secp256k1参数。
每个账户用一个地址表示。有了密钥之后,就需要生成地址。
从公钥生成地址的过程如下:
(1)生成公钥的keccak-256哈希。它将给出一个256位的数字。
(2)丢弃前面的96位,即12字节。现在得到160位二进制数据,即20
字节。
(3)把地址编译成十六进制的字符串。最后将得到一个40字符的字
节串,就是账户地址。
3、交易
交易是一个签名数据包,用于从一个账户向另一个账户或者向一个合约转以太币、调用合约方法或者部署一个新合约。
交易使用椭圆曲线数字签名算法(ECDSA)签名,ECDSA是一种基于ECC的数字签名算法。
交易包含:
(1) 信息接收者
(2) 识别发起人及其意愿的签名
(3) 要转账的以太币数量
(4) 交易执行允许进行的计算资源最大值(叫作gas上限)
(5) 交易发起人愿意为单位计算资源支付的费用(叫作gas价格)
如果交易目的是调用合约方法,则还包含输入数据。
如果其目的是部署合约,则可以包含初始化代码。
用交易所消耗的gas乘以gas价格计算得到交易费。
4、共识
用户需要确保节点不能够篡改区块链,还需要一个机制检查区块是否合法。
以太坊使用工作量证明共识协议防止区块链被篡改。
工作量证明系统需要解决一个复杂问题以创建一个新的区块。
在工作量证明系统中,创建区块的过程称为挖矿。
矿工(miner)是网络中挖区块的节点。矿工一旦成功挖到区块,就向网络中的所有其他节点广播该区块。区块有一个区块头(header)和一系列交易。每一个区块存储前一个区块的哈希值,由此创建一个相连的链。
为了挖区块,矿工首先从收到的广播中收集新的、未挖出的交易,然后滤掉不合法的交易。
合法的交易必须满足正确地使用私钥签名、账户有足够的余额进行交易等件。现在矿工创建一个有区块头和内容的区块。
内容(content)是区块包含的交易列表。
区块头包含:
(1) 前一个区块的哈希
(2) 区块序号
(3) 随机数(nonce)
(4) 目标值(target):是一个256位的数字
(5) 时间戳(timestamp)
(6) 难度值(difficulty):是目标值的一种不同表述方法,目标值越低,发现随机数需要的时间越多;目标值越高,需要的时间越少。
(7) 矿工地址(address)等内容。
Tip:
(1)网络中的任何节点都可以检查区块链是否合法,首先检查交易在区块链中是否合法以及时间戳的验证情况,然后检查区块的目标值和随机数是否合法、矿工是否得到合法的回报等。
(2)如果网络中的节点接收到两个不同的合法区块链,那么所有区块的整体难度值较高的那个区块链被视为合法的区块链。
例如,假设网络中的一个节点想改变一个区块中的一些交易,就需要重新计算该块以及该块后面所有区块的随机数。可是在该节点计算的同时,网络其他节点已经又挖出了许多新的区块,因此当它重新计算到最新区块时会因整体难度值较低而被系统拒绝。可见,私自篡改账本的难度是非常大的。
5、时间戳
当一个矿工广播一个新挖出的区块时,其他节点对其时间戳的验证取决于其时间戳是否大于前一个区块的时间戳。
如果一个矿工使用的时间戳大于当前时间戳,则难度值较低,因为难度值与当前时间戳成反比,因此网络将接受区块时间戳是当前时间戳的矿工,因为它的难度值比较高。
如果一个矿工使用的时间戳大于前一个区块时间戳,且小于当前时间戳,难度值会高一些,因此要花费更多时间挖区块。
6、随机数
随机数是一个64位未签名证书。矿工不断地尝试随机数,直到发现目标值。
每个矿工挖的区块的哈希是不同的,因为哈希取决于如时间戳、矿工地址等内容,而且对于所有矿工来说这些内容很可能是不一样的。因此,解决问题并不是一场比赛,而更像是一件碰运气的事。所以,矿工可能因为算力大而走运,但那并不意味着该矿工总会发现下一个区块。
7、区块时间
区块难度值公式使用了一个长达10s的阈值,以确保挖出父区块和子区块的时间差在10s和20s之间。
无效块(stale block):在以太坊中,无效块称为“叔块(uncle block)。如果两个矿工用几乎相同的时间挖下一个区块,会发生什么呢?两个区块肯定都是合法的,但是区块链不能包含区块序号相同的两个区块,而且两个矿工都得不到回报。尽管这是个常见问题,解决方法却很简单,最后难度值较高的区块链将被网络接受。所以最后被忽略的合法区块叫作无效无效块。
网络中生成的无效无效块总数与生成新区块所需的平均时间成反比。更短的区块生成时间意味着新挖出来的区块向整个网络广播的时间更短,矿工发现问题解决办法的概率更大,所以当区块向整个网络广播时,其他一些矿工可能也解决了问题并进行了广播,由此产生了无效块。但是如果生成区块的平均时间长一点,多个矿工能解决问题的概率就小一点,而且即使它们都解决了问题,也很可能存在时间差,在这个时间差里,第一个被解决的区块就可以进行广播,另一个矿工就可以停止挖那个区块并继续挖下一个区块。
在无效块上工作的网络是在无效块上挖下一个区块,结果是网络算力损失,因为算力用在了没有用的事情上。所以,在挖出下一个区块之后,难度值将降低,原因是用于挖区块的时间比平均时间更长。难度值降低会影响整体区块链安全。如果无效块率太高,将在很大程度上影响区块链安全。
以太坊如何解决无效块?——ghost协议
以太坊用ghost协议解决无效块带来的安全问题。ghost协议仅仅把无效块添加到母链上,掩盖了安全问题,由此增加了区块链的整体难度值,因为区块链的整体难度值还包括无效块的难度值之和。
但是如何才能在不产生交易冲突的情况下把无效块添加到母链中呢?
事实上,任何区块链都可以接纳零个或者多个无效块。为了激励矿工接纳无效块,矿工接纳无效块将得到回报。此外,发现无效块的矿工也将得到回报。无效块中的交易不用于计算确认,无效块矿工也不向无效块接纳的交易收取交易费。
矿工接纳无效块得到的回报计算公式如下:
8、分叉
(1) 普通分叉:普通分叉是由于两个或者多个矿工几乎同时发现了一个区块引起的暂时冲突。如果一个难度值高于另一个,冲突就解决了。
更改源代码可能引起冲突。根据冲突类型,可能要求有50%以上算力的矿工升级,也可能要求所有矿工升级,以解决冲突。
(2) 软分叉:要求有50%以上算力的矿工升级以解决冲突。如更新源代码使旧区块/交易的一部分失效,则有50%以上算力的矿工升级后可以解决。
(3) 硬分叉:要求所有矿工升级以解决冲突。如更新源代码是为了更改对矿工的回报,则全部矿工需要升级以解决冲突。
9、创世区块
创世区块(genesis block)是区块链中的第一个区块,其区块序号是0。它是区块链中唯一一个不指向前一个区块的区块,因为没有前一个区块。它也不包含交易,因为还没产生任何以太币。
只有网络中的两个节点有相同的创世区块,它们才会彼此配对,也就是说,如果两个对等节点有相同的创世区块才会进行同步区块,否则它们将彼此拒绝。
每一个节点生成自己的创世区块。对于不同的网络,创世区块被硬编码到客户端里。
10、以太坊虚拟机(EVM)
EVM是以太坊智能合约字节码(byte-code)的执行环境,网络中的每个节点都运行EVM。所有节点执行使用EVM指向智能合约的全部交易,因此它们进行同样的计算,并存储同样的数值。
每个节点执行并存储最终状态。如,如果有一个智能合约存储参加派对的每个人的姓名和细节,只要增加新的人,就向网络广播新的交易。网络中的任何节点想要展示参加派对的每个人的细节,只需读取合约的最终状态即可。
每个交易需要在网络中进行一些计算和存储。因此需要有交易费,否则整个网络里将充斥着垃圾交易,而且没有交易费用矿工就没有理由在区块中接纳交易,它们将开始挖空区块。
11、gas
gas(燃料)是计算资源的计量单位。
每一个交易都需要包含gas上限。如果交易使用的gas少于或等于gas上限,交易继续进行。如果gas总数超过gas上限,则撤销所有修改,除了仍然合法且矿工仍然能够收到费用的交易。
矿工决定gas价格。如果交易gas价格低于矿工决定的gas价格,矿工将拒绝挖交易。
如果gas价格低于期望,矿工可以拒绝将交易接纳入区块。
gas价格以wei为单位。
EVM的每个操作都被分配了一个数字,用以表示它可以消耗的gas。
交易成本影响一个账户可以转账给另一个账户的以太币上限。如,如果某个账户里共有5个以太币,它不能把全部5个以太币转入其他账户,因为如果把所有以太币都汇走,账户就没有余额支付交易费了。
12、发现对等节点
节点不需要连接到网络中的每一个节点;相反,它只连接到几个其他节点,这些节点再连接到另外几个节点。按照这个方式,整个网络彼此连接。
节点如何发现网络中的一些其他节点?
以太坊有自己的节点发现协议可用于解决这个问题,该协议以Kadelima协议为基础。在节点发现协议中有一种特殊的节点,叫作Bootstrap(初始启动)节点。Bootstrap节点保存了一段时间内与它们连接的所有节点的列表,但其本身不保存区块链。当对等节点连接到以太坊网络时,它们首先连接到Bootstrap节点,Bootstrap节点分享在刚才事先定义的时间里连接到它们的对等节点列表。然后对等节点与对等节点连接并同步。
13、Whisper和Swarm
Whisper是一个去中心化的通信协议,Swarm则是一个去中心化的文件系统。
14、geth (go-ethereum)
geth是以太坊、Whisper和Swarm节点的一个实现。合并它们的目的是让它们看起来像单一的DApp,通过一个节点客户端就可以访问三个DApp。
geth是一种CLI应用,它用Go语言编写。
14.1 安装geth
OS X :推荐在OS X中使用brew安装geth。在终端运行下面两个命令安装geth:
brew tap ethereum/ethereum
brew install ethereum
windows :下载ZIP文件,解压缩,执行geth.exe文件。
下载地址:https://github.com/ethereum/go-ethereum/wiki/Installation-instructions-for-Windows
14.2 JSON-RPC和JavaScript操作台
geth为其他应用提供了与其进行通信的JSON-RPC API。geth使用HTTP、WebSocket和其他协议服务于JSON-RPC API。
geth还提供了一个交互JavaScript操作台,可以使用JavaScript API进行程序交互。该交互操作台使用JSON-RPC与geth进行通信。
14.3 geth的子命令和选项
(1)连接至主网网络:
以太坊网络中的节点默认用30303端口通信。但是节点还可以收听一些端口。
为了连接到主网网络,只需要运行geth命令即可。例如:
geth --datadir "/users/packt/ethereum" --networkid 1
其中,--datadir选项用于指定在哪里存储区块链。如果没有提供,默认路径是“$HOME/.ethereum”;
--networkid用于指定网络ID。1代表主网网络ID。如果没提供网络ID,默认值是1。2代表测试网络ID。
(2)创建私有网络:
要创建私有网络,只需给出一个随机网络ID即可。通常创建私有网络的目的是进行开发。可以简单使用--dev标记运行一个私有网络,该网络允许多个与日志和调试相关的标记,而不用给出一个随机网络ID并放上多个与日志和调试相关的标记。
14.4 创建账户
(1)geth还允许创建账户,即生成密钥和相关地址。
geth account new
当运行上述命令时,需要输入密码以加密账户。如果忘记密码,就无法访问账户了。
(2)在本地钱包获得所有账户的列表
geth account list
密钥默认存储在--datadir路径中,但用户可以使用--keystore选项指定一个不同的目录。
1.挖矿
默认geth不启动挖矿。为了指示geth开始挖矿,只需要提供--mine选项。
--minerthreads选项用于指定哈希过程中使用的线程总数,默认使用8个线程。
etherbase是挖矿赚取的回报存入的地址。
-unlock可以使用-unlock选项解锁一个或者多个账户。使用逗号分隔地址可以提供多个地址
--minergpus用于指定挖矿使用的GPU。为了得到GPU列表,可以使用geth gpuinfo命令。每个GPU需要1~2GB的RAM。默认只使用CPU。
2.快速同步
快速同步(fast synchronization)不下载整个区块,而只下载区块头、交易凭证和最新的状态数据库。
因此用户不需要下载和重播全部交易。为了检查区块链的真实性,该算法在每一个已定义的区块序号之后下载一个完整的区块。
为了在下载区块链过程中使用fast sync,用户需要在运行geth的过程中使用--fast。
出于安全原因,fast sync只在初始同步时运行(即该节点自身的区块链为空时)。在节点成功与网络同步后,fast sync就永远禁用了。
15、以太坊钱包
以太坊钱包允许用户进行创建账户、发送以太币、部署合约、调用合约方法等操作。以太坊钱包与geth捆绑在一起。运行以太坊时,它会尝试发现一个本地geth实例并与之连接。如果它不能发现geth正在运行,它就启动自己的geth节点。
16、浏览器钱包(Mist)
浏览器钱包(Mist)是以太坊、Whisper和Swarm的一个客户端,它允许用户发送交易、发送Whisper信息、检查区块链等。
目前,浏览器中运行的前端JavaScript可以使用web3.js库(该库为其他应用提供以太坊操作台的JavaScript API与geth通信)访问geth节点的web3 API。
Mist的基本思想是创建第三代Web(Web 3.0),即使用以太坊、Whisper和Swarm替代中心化服务器端,这样就不需要服务器端了。
17、以太坊的缺点
(1)Sybil攻击:攻击者可能试图用他控制的普通节点占满整个网络,那么用户很有可能只连接到攻击者节点。一旦连接到攻击者节点,攻击者可以拒绝从所有节点转播区块和交易,从而将用户从网络中断开。攻击者只能转播他创建的区块,从而会将用户放到分开的网络上。
(2)51%攻击:如果攻击者掌握了网络中一半以上的算力,他就可以比网络中其他人更快地生成区块。拥有50%以上的算力,矿工就可以重写交易,阻止全部/一些交易被挖出,并阻止其他矿工挖出的区块被添加到区块链中。