以太坊基本概念介绍

535 阅读6分钟

在学习以太坊智能合约编程之前,我们有必要先了解一下以太坊相关的基本概念。

帐户

与比特币的UTXO模型不同,以太坊采用的是帐户模型。帐户本身又分为两种类型,一种是由私钥控制,另外一种就是智能合约。智能合约可以通过私钥帐户或者其它智能合约来创建。

帐户的定义如下:

// Account is the Ethereum consensus representation of accounts.  
// These objects are stored in the main account trie.  
type Account struct {  
   Nonce    uint64  
   Balance  *big.Int  
   Root     common.Hash // merkle root of the storage trie  
   CodeHash []byte  
}

各字段的含意如下: Nonce : 是用来防止双花的,每成功发送并打包一次交易后,自动加1。 Balance : 是帐户余额,单位是 wei。 Root : 合约帐户的状态变量的 Merkle 树根。智能合约的本质就是维护一组状态变量。 CodeHash : 合约代码的哈希值

交易

以太坊的另外一个重要概念叫交易。转帐是交易,创建智能合约是交易,调用智能合约也是交易。下面是使用 rpc 发起一个交易的参数:

{
  "jsonrpc": "2.0",
  "method": "eth_sendTransaction",
  "params": [
    {
      "from": "0xf4bc2b33e080991222858a592775193a7ca932c6",
      "to": "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
      "gas": "0x76c0",
      "gasPrice": "0x9184e72a000",
      "value": "0x9184e72a",
      "data": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675"
    }
  ],
  "id": 1
}

一个交易由以下几个字段定义:

from : 交易发起者 to: 交易接收者,如果为空,表示创建一个合约。 gas:允许使用的最大gas gasPrice:gas价格,计量是ether,单位wei value: 转帐的ether data:交易数据

gas 和 gasPrice 是什么呢?智能合约经编译后,由一些基础原子操作 op 组成,每个 op 都对应一定的 gas , 所有执行的 op 所需要的 gas 总和与 gasPrice 的乘积便是调用者需要向矿工支付的费用。gas 的设计是为了防止攻击的。试想,如果某个智能合约里面有个死循环,节点在运行合约时,资源会被耗尽,矿工无法打包,网络被堵死。而有了 gas 和 gasPrice 概念后,每执行一步,evm 就会进行计费,费用超过了限制后,程序将被强行终止。需要注意一点的是,无论合约调用成功还是失败,gas 一经收取便不再退还,历史上曾经发生过因为没有收取失败的交易的费用,导致以太坊被DDOS攻击的事件。

我们经常说以太坊网络拥堵是怎么回事呢?当矿工接收到到我们发送的交易后,会根据交易的 gasPrice 优先选择高的交易进行打包,所以低 gasPrice就交易需要排队。Richer 为了交易尽快被执行,就会提高 gasPrice ,导致低 gasPrice 的交易一直在排除等待。

交易参数中的 to 如果是空,data 则是智能合约编译后的代码;如果 to 是一个合约地址,data 则描述了调用智能合约的哪一个函数以及参数是什么。

除了通过交易调用智能合约,还可以通过另外一种方法来调用智能合约函数而无需花费 gas 。这种调用不会导致智能合约的状态变量发生改变,因此节点也不需要向其它节点广播任何信息。

以太坊智能合约的存储空间由2^256个 slot 组成,每个slot的大小是32bytes。合约的状态变量通过sha3函数映射到这个巨大的存储空间上。

+--------+--------+--------+--------+-------+-----+------
| slot1  | slot2  | slot3  | slot4  | slot5 | ... | slot2^256 
+--------+--------+--------+--------+-------+-----+------

以太坊在持久化存储状态变量时,使用的是 Merkle 树,这颗树的根就是 Account 中的 Root。

智能合约又叫 smart contract,它与AI里的智能概念不同,智能合约强调的是Code is Law,代码一经发布,就会按事先设计好的逻辑执行,理论上就没有人可以操纵它的结果,他的计算总是可信的,这就是智能合约的魅力所在。

区块

若干个交易被矿工打包在一起组成了一个区块,一个区块头的部分字段如下:

difficulty              3393930978663113
extraData               0x737061726b706f6f6c2d636e2d6e6f64652d3031
gasLimit                8000029
gasUsed                 7980102
hash                    0xe2813542fb7829957b9f535982e126e54893f53dd28bf3eae38facae536e980d
miner                   0x5a0b54d5dc17e0aadc383d2db43b0a0d3e029c4c
mixHash                 0x543f2ad3ce64aafcae5d133e7883d272061c2f90508b11c0d274f9790fd009ca
nonce                   11187430928983643115
number                  5903045
parentHash              0xfcb74cff4034c44410feccf6766c2f358c3f23db092dd5e8eae8de903c685b39
receiptsRoot            0xc4ac8d3a6ee03dfa85287ddc419aa75c8a294d1b820e123668982aae3c59eeb1
size                    43634
stateRoot               0x43374ec343c8aa4fb99c78acedb015128ebf80838709fc15fca2ed53c4d0f7ff
timestamp               1530691577
totalDifficulty         0x1171d0869f13c025207
transactionsRoot        0x0955dc7ee31a25f449272a1d2360a581af5a1f3d628dd8bb154034e194be5fd6

所有的区块通过 parentHash 链接起来叫区块链。stateRoot 是 记录帐户的 Merkle 树根,通过这颗树可以获取到当前区块下的帐户信息。 transactionsRoot当前区块包含的交易列表的 Merkle 树根。receiptsRoot 是交易收据的 Merkle 树根,收据里面存储了交易产生的事件,gas 花费等信息。