以太坊开发指南 #1

2021-02-25 11:35:24 浏览数 (1)

  • 译文出自:登链翻译计划[1]
  • 译者:翻译小组[2]
  • 校对:Tiny 熊[3]

你应该听说过了以太坊[4]了,准备进入以太坊的世界冒险了吗?这篇文章将快速介绍一些区块链基础知识,然后让了解与模拟的以太坊节点进行交互--读取区块数据,检查账户余额并发送交易。在这个过程中,我们将理解传统的应用程序与这种新的去中心化应用之间的差异。

(软)要求

本文希望面向所有的开发者,不过文章里还是会涉及到 Python 工具,但它们只是思想的载体--如果你不是 Python 开发者也没有问题,它只是可以帮助我们更快速进入到以太坊。

本文假定你:

  • 熟悉命令终端。
  • 你已经写了几行 Python 代码。
  • 你的机器上安装了 Python 3.6 或更高版本 (强烈建议使用虚拟环境[5]),并且
  • 你已经使用了 pip(Python 的软件包安装程序)。

再次强调,这些都是不是必须的,或者你不打算敲本文中的代码,也不影响你理解本文。

简单介绍一下区块链

描述以太坊的方法有很多,但其核心还是区块链。区块链是由一系列的区块组成的,所以我们从区块链开始。最简单的说,以太坊区块链上的每个区块只是一些元数据(metadata)和交易列表。在 JSON 格式中,它看起来像这样:

代码语言:javascript复制
{
   "number": 1234567,
   "hash": "0xabc123...",
   "parentHash": "0xdef456...",
   "miner": "0xa1b2c3...",
   ...,
   "transactions": [...]
}

每个区块都有一个对之前区块的引用,parentHash是前一个区块的哈希值。

注意: 以太坊广泛使用哈希函数[6]来产生固定长度的值(哈希)。哈希值在以太坊中扮演着重要的角色,但你现在可以放心地将其视为唯一的 ID。

区块结构

区块链本质上是一个链表,每个区块都有一个对前一个区块的引用。

这种数据结构并不新颖,但治理网络的规则(如:点对点协议)却很新颖。区块链没有中央权威机构,网络中的对等节点必须协作来维持网络,并竞争决定将哪些交易纳入下一个区块。因此,当你想给朋友转账时,你需要将这笔交易广播到网络上,然后等待它被包含在即将到来的区块中。

区块链验证金钱从一个用户发送到另一个用户的唯一方法是使用区块链的原生货币(即由该区块链创建和管理的货币)。在以太坊中,原生货币被称为ether(以太币),它是以太坊区块链包含了账户余额的唯一官方记录。

新的开发工具链

新的去中心化技术栈催生了新的开发者工具。这些工具存在于许多编程语言中,但本文将从 Python 的角度来看。(重申一下:即使 Python 不是你的首选语言,跟上文章也不会有太大的问题。)

想要与以太坊进行交互的 Python 开发者可能会接触到**Web3.py[7]**。Web3.py 是一个库,用来帮助我们简化连接以太坊节点,以及发送和接收数据。

注:以太坊节点以太坊客户端可互换使用。在任何一种情况下,它们都是指以太坊网络中的参与者所运行的软件。这个软件可以读取区块数据、在新区块加入到链上(挖矿)时接收更新、广播新交易等。

以太坊客户端可以配置为通过IPC[8]、HTTP 或 Websockets 来访问,所以 Web3.py 也需要进行这个配置。Web3.py 将这些连接选项称为提供者。你需要从三个提供者中选择一个来连接 Web3.py 实例和你的节点。

1_OrElsXOF45w-AgBuezCqjQ配置以太坊节点和Web3.py通过相同通信的协议,本图中用IPC

一旦 Web3.py 配置正确,你就可以开始与区块链进行交互。下面是几个 Web3.py 的使用例子,抛砖引玉。

代码语言:javascript复制
# 读取区块:
w3.eth.getBlock('latest')

# 发送交易:
w3.eth.sendTransaction({'from': ..., 'to': ..., 'value': ...})

安装环境

在这个演练中,我们仅在 Python 解释器中进行,不会创建任何目录、文件、类或函数。

**注意:**在下面的例子中,以开头的命令是表示在终端中运行。(不要输入,它只是表示行的开始。)

首先,安装IPython[9],以方便用户在其中进行探索。IPython 提供了 tab 补全功能,让你更容易看到 Web3.py 内的有哪些可用方法。

代码语言:javascript复制
$ pip install ipython

Web3.py 以 web3的名义发布,安装方式如下:

代码语言:javascript复制
$ pip install web3

另外, 我们后面要模拟一个区块链,这就需要多一些依赖。则可以通过下面命令安装:

代码语言:javascript复制
$ pip install web3[tester]

准备好了!

开启沙盒环境

在终端中运行ipython打开一个新的 Python 环境。这与运行 python相当,但更友好。

代码语言:javascript复制
$ ipython

这将打印出一些关于你正在运行的 Python 和 IPython 版本的信息,然后你应该看到一个等待输入的提示:

代码语言:javascript复制
In [1]:

你现在看到的是一个交互式的 Python shell,如果你跟着进行到了这里,现在可以导入 Web.py 了。

代码语言:javascript复制
In [1]: from web3 import Web3

Web3 模块介绍

除了作为以太坊的网关,Web3[10]模块还提供了一些方便的功能。让我们来探究探究。

在以太坊应用中,你通常需要转换货币面额。Web3 模块就为此提供了几个辅助方法:fromWei[11]和toWei[12]

**注:**计算机不擅长处理十进制数学。为了规避这个问题,开发者通常会将美元金额用美分存储。例如,价格为 5.99 美元的物品在数据库中存储为 599。 在处理ether中的交易时,也使用类似的模式。然而,以太币不是两个小数点,而是有 18 位,以太币的最小面额叫wei,所以发送交易时指定的就是这个值。 1 以太币(ether)=1000000000000000000 wei 1 wei = 0.000000000000000001 以太币(ether)

试一下将一些数值转换为 wei 或相反。请注意,以太币和 wei 之间还有其他的面额名称[13]。其中比较有名的是gwei,因为它往往是交易费用的体现方式。

代码语言:javascript复制
In [2]: Web3.toWei(1, 'ether')
Out[2]: 1000000000000000000

In [3]: Web3.fromWei(500000000, 'gwei')
Out[3]: Decimal('0.5')

Web3 模块上的其他实用方法包括数据格式转换器(如 toHex)、地址助手(如 isAddress)和哈希函数(如 keccak)。其中许多内容将在后面的系列文章中介绍。要查看所有可用的方法和属性,可以利用 IPython 的自动补全功能,输入Web3.并按两次 tab 键。

与链交互

接下来配置 Web3.py 与以太坊节点通信。这里我们可以选择使用 IPC、HTTP 或 Websocket 提供者。

我们不会完整的进行这个步骤,但一个使用 HTTP 提供者的完整工作流的例子像这样:

  • 下载一个以太坊节点,例如: Geth[14]
  • 在一个终端窗口启动 Geth,等待它同步网络。默认的 HTTP 端口是8545,但可以配置。
  • 告诉 Web3.py 通过 HTTP 连接到节点,使用localhost:8545w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • 使用w3实例与节点交互。

虽然这是一种 正式的方式,但如果你只是想要一个开发环境,同步过程需要几个小时,而且没有必要。Web3.py 为此暴露了第四个提供者,即以太坊 TesterProvider。这个测试器提供者连接到一个模拟的以太坊节点,它有更宽松的权限,还有虚拟以太币可以使用。

以太坊 TesterProvider 连接到一个模拟节点,对于快速开发环境来说非常方便。

这个模拟节点叫做**eth-tester[15]**,我们把它作为pip install web3[tester]命令的一部分进行安装。配置 Web3.py 来使用这个测试提供者很简单:

代码语言:javascript复制
In [4]: w3 = Web3(Web3.EthereumTesterProvider())

现在,你已经准备好在链上冲浪了!

快速预览功能

第一件事,先来个连接检查。

代码语言:javascript复制
In [5]: w3.isConnected()
Out[5]: True

由于我们使用的是测试提供者,这不是一个非常有价值的测试,但如果它确实失败了,很可能是你在实例化w3变量时输入错误。仔细检查你是否包含了内括号,即Web3.EthereumTesterProvider()

账户

为了方便起见,测试提供者创建了一些账户,并预分配测试以太币。首先,我们来看看这些账户的列表。

代码语言:javascript复制
In [6]: w3.eth.accounts
Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]

如果你运行这个命令,你应该看到一个以 0x开头的十个字符串的列表。每一个都是一个的公共地址,在某些方面,类似于支票账户上的账号。如果有人要给你转账,你需要把这个地址给他。

如前所述,测试提供者已经为这些账户中的每一个账户预分配了一些测试以太币。我们来看看第一笔账有多少钱。

代码语言:javascript复制
In [7]: w3.eth.getBalance(w3.eth.accounts[0])
Out[7]: 1000000000000000000000000

好多零啊!在你一路笑醒之前,先回忆一下之前关于货币面额的介绍。以太坊用最小的面额表示,wei。将其转换为以太币。

代码语言:javascript复制
In [8]: w3.fromWei(1000000000000000000000000, 'ether')
Out[8]: Decimal('1000000')

100 万测试以太币  , 也不算太寒酸。

区块数据

我们来看看这个模拟区块链的状态。

代码语言:javascript复制
In [9]: w3.eth.getBlock('latest')
Out[9]: AttributeDict({
   'number': 0,
   'hash': HexBytes('0x9469878...'),
   'parentHash': HexBytes('0x0000000...'),
   ...
   'transactions': []
})

关于一个区块,很多信息都会被返回,但这里只介绍:

  1. 块号是零  - 无论你在多长时间前配置了测试提供者  。与真实的以太坊网络不同,以太坊网络大概每隔 15 秒就会挖掘一个新的区块,而模拟链则会等到你给它一些工作在增加区块。
  2. transactions是一个空列表,原因相同:我们还没有做任何事情。第一个区块是一个的空区块,只是为了开个头。
  3. 注意,parentHash只是一堆空的字节。这标志着它是链条上的第一个区块,也就是所谓的创世区块。

交易

在没有交易之前,我们停留在零区块,所以我们给它一个交易。从一个账户向另一个账户发送一些测试以太币。

代码语言:javascript复制
In [10]: tx_hash = w3.eth.sendTransaction({
   'from': w3.eth.accounts[0],
   'to': w3.eth.accounts[1],
   'value': w3.toWei(3, 'ether')
})

这时通常会等上几秒钟,等待交易挖到一个新的区块。完整的流程是这样的:

  1. 提交交易并持有交易哈希。在没有被挖出来之前,交易是 pending 的:tx_hash = w3.eth.sendTransaction({ ... })
  2. 等到交易被挖掘出来:w3.eth.waitForTransactionReceipt(tx_hash)
  3. 继续应用逻辑。如查看成功的交易:w3.eth.getTransaction(tx_hash)

我们的模拟环境会在一个新的区块中即时添加交易,所以我们可以立即查看交易:

代码语言:javascript复制
In [11]: w3.eth.getTransaction(tx_hash)
Out[11]: AttributeDict({
   'hash': HexBytes('0x15e9fb95dc39...'),
   'blockNumber': 1,
   'transactionIndex': 0,
   'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
   'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
   'value': 3000000000000000000,
   ...
})

你会看到一些熟悉的细节:fromtovalue字段应该与我们的 sendTransaction调用的输入相匹配。另一个令人欣慰的是,这项交易被列为区块号1内的第一笔交易('transactionIndex': 0)。

我们也可以通过检查两个相关账户的余额,轻松验证这次交易是否成功。三个以太币应从一个账号转移到另一个。

代码语言:javascript复制
In [12]: w3.eth.getBalance(w3.eth.accounts[0])
Out[12]: 999996999999999999979000

In [13]: w3.eth.getBalance(w3.eth.accounts[1])
Out[13]: 1000003000000000000000000

后者看起来不错! 余额从 1000000 到 100003 以太币。但第一笔账看起来减少的数量略大于三个以太币?是的,没有免费的午餐,使用以太坊公网需要支付矿工手续费,因为它从进行交易的账户中扣除了少量的交易费,金额为 21000wei。

**注意:**在公共网络上,交易费用根据网络需求和你希望交易处理的速度而变化。如果你对费用的计算方式有兴趣,请看我之前的帖子交易如何包含在一个区块中[16]

结束

本文结束,我们将在这个系列的第二部分继续探索一些概念:连接到一个真实的节点,智能合约和代币,


本翻译由 Cell Network[17] 赞助支持。

来源:https://snakecharmers.ethereum.org/a-developers-guide-to-ethereum-pt-1/ 作者:Marc Garreau

参考资料

[1]

登链翻译计划: https://github.com/lbc-team/Pioneer

[2]

翻译小组: https://learnblockchain.cn/people/412

[3]

Tiny 熊: https://learnblockchain.cn/people/15

[4]

以太坊: https://learnblockchain.cn/categories/ethereum/

[5]

虚拟环境: https://realpython.com/effective-python-environment/#virtual-environments

[6]

哈希函数: https://en.wikipedia.org/wiki/Hash_function

[7]

Web3.py: https://web3py.readthedocs.io/

[8]

IPC: https://en.wikipedia.org/wiki/Inter-process_communication

[9]

IPython: https://ipython.org/

[10]

Web3: https://web3py.readthedocs.io/en/stable/overview.html#base-api

[11]

fromWei: https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.fromWei

[12]

toWei: https://web3py.readthedocs.io/en/stable/web3.main.html#web3.Web3.toWei

[13]

其他的面额名称: https://web3py.readthedocs.io/en/stable/examples.html#converting-currency-denominations

[14]

Geth: https://geth.ethereum.org/

[15]

eth-tester: https://github.com/ethereum/eth-tester

[16]

交易如何包含在一个区块中: https://medium.com/ethereum-grid/ethereum-101-how-are-交易s-included-in-a-block-9ae5f491853f

[17]

Cell Network: https://www.cellnetwork.io/?utm_souce=learnblockchain

0 人点赞