这本迷你书的本意是给任何想用Go进行以太坊开发的同学一个概括的介绍。本意是如果你已经对以太坊和Go有一些熟悉,但是对于怎么把两者结合起来还有些无从下手,那这本书就是一个好的起点。你会学习如何用Go与智能合约交互,还有如何完成一些日常的查询和任务。
这本书里有很多我希望我当初学习用Go以太坊开发的时候能有的代码范例。你上手Go语言以太坊开发的大部分所需知识,这本书里面都会手把手介绍到。
当然了,以太坊还是一直在飞速的发展的进化的。所以难免会有些过期的内容,或者你认为有可以值得提升的地方,那就是你提 issue 或者 pull request 的好机会了:)这本书是完全开源并且免费的,你可以在 github 上看到源码。
介绍
以太坊是一个开源,公开,基于区块链的分布式计算平台和具备智能合约(脚本)功能的操作系统。它通过基于交易的状态转移支持中本聪共识的一个改进算法。
-维基百科
以太坊是一个区块链,允许开发者创建完全去中心化运行的应用程序,这意味着没有单个实体可以将其删除或修改它。部署到以太坊上的每个应用都由以太坊网络上每个完整客户端执行。
Solidity
Solidity是一种用于编写智能合约的图灵完备编程语言。Solidity被编译成以太坊虚拟机可执行的字节码。
go-ethereum
本书中,我们将使用Go的官方以太坊实现go-ethereum来和以太坊区块链进行交互。Go-ethereum,也被简称为Geth,是最流行的以太坊客户端。因为它是用Go开发的,当使用Golang开发应用程序时,Geth提供了读写区块链的一切功能。
本书的例子在go-ethereum版本1.8.10-stable
和Go版本go1.10.2
下完成测试。
Block Explorers
Etherscan是一个用于查看和深入研究区块链上数据的网站。这些类型的网站被称为区块浏览器,因为它们允许您查看区块(包含交易)的内容。区块是区块链的基础构成要素。区块包含在已分配的出块时间内开采出的所有交易数据。区块浏览器也允许您查看智能合约执行期间释放的事件以及诸如支付的gas和交易的以太币数量等。
Swarm and Whisper
我们还将深入研究蜂群(Swarm)和耳语(Whisper),分别是一个文件存储协议和一个点对点的消息传递协议,它们是实现完全去中心化和分布式应用程序需要的另外两个核心。
寻求帮助
寻求Go(Golang)帮助可以加入gophers slack上的#ethereum频道。
客户端
客户端是以太坊网络的入口。客户端需要广播交易和读取区块链数据。接下来中将学习如何在Go应用程序中初始化客户端。
初始化客户端
用Go初始化以太坊客户端是和区块链交互所需的基本步骤。首先,导入go-etherem的ethclient
包并通过调用接收区块链服务提供者URL的Dial
来初始化它。
若您没有现有以太坊客户端,您可以连接到infura网关。Infura管理着一批安全,可靠,可扩展的以太坊[geth和parity]节点,并且在接入以太坊网络时降低了新人的入门门槛。
client, err := ethclient.Dial("https://mainnet.infura.io")
若您运行了本地geth实例,您还可以将路径传递给IPC端点文件。
client, err := ethclient.Dial("/home/user/.ethereum/geth.ipc")
对每个Go以太坊项目,使用ethclient是您开始的必要事项,您将在本书中非常多的看到这一步骤。
使用Ganache
Ganache(正式名称为testrpc)是一个用Node.js编写的以太坊实现,用于在本地开发去中心化应用程序时进行测试。现在我们将带着您完成安装并连接到它。
首先通过NPM安装ganache。
npm install -g ganache-cli
然后运行ganache cli客户端。
ganache-cli
现在连到http://localhost:8584
上的ganache RPC主机。
client, err := ethclient.Dial("http://localhost:8545")
if err != nil {
log.Fatal(err)
}
在启动ganache时,您还可以使用相同的助记词来生成相同序列的公开地址。
ganache-cli -m "much repair shock carbon improve miss forget sock include bullet interest solution"
我强烈推荐您通过阅读其文档熟悉ganache。
完整代码
package main
import (
"fmt"
"log"
"github.com/ethereum/go-ethereum/ethclient"
)
func main() {
client, err := ethclient.Dial("https://mainnet.infura.io")
if err != nil {
log.Fatal(err)
}
fmt.Println("we have a connection")
_ = client // we'll use this in the upcoming sections
}