golang如何连接以太坊合约。近一段时间在学习以太坊智能合约,在学习过程中走了不少弯路,本文是对此处相关知识的总结希望可以帮助后来者少走弯路。
Solidity
合约编写通过继承zeppelin-solidity提供的功能,编写一个ERC-20
代币合约,核心代码甚至只需要定义一下代币数量和名称。
在实际部署合约时候,建议将所有继承到的合约都直接Copy到了源码之中,这样做原因是Solidity目前对于import的支持还很弱,可以避免不必要到错误。在示例代码中为了便于理解,我也做了如上操作。
下面到这个合约SuperCoin
,主要除了定义了名称、数量之外,借助继承的合约还具备:白名单管理、铸币到白名单、铸币总量限制等功能,具体怎样实现上述功能可以自行查看源码,此处就不介绍Solidity到基础知识了。
Ganache
和Truffle
和编写和测试合约Ganache是一个个人的以太坊客户端,可以启动一个私有链用于开发测试的区块链环境。Truffle framework是一个使用非常广泛的智能合约开发框架,通过Truffle可以快速开发和测试合约。
Ganache
和Truffle
安装Ganache官方提供的下载地址,下载安装允许即可不需要修改默认设置。
Truffle的目录结构跟Web项目相似度非常高,node_modules和Web一样是用来存放依赖库的目录,同样的安装依赖库也需要使用npm命令,安装方式请参考:npmjs
Trffule官方提供的安装方式便是借助npm的:
zeppelin-solidity
安装zeppelin-solidity
是开发基于ERC-20代币必须要用到的库,功能比较完善,通过继承这个库的合约,可以非常方便的实现ERC-20协议、铸币、白名单等常见的功能。
安装按完成后即可通过import方式引入相关依赖合约:
Truffle
编写和测试合约安装完成Truffle后,cd到目标文件夹,执行 truffle init
命令,程序便会生成如下图目录,需要注意的示目标文件夹必须是空文件夹:
contracts 目录存放合约文件,migrateions 目录,test 目录存放测试文件。
初始化truffle目录后即可编写合约,详细用法可参考官方文档:
SuperCoin.sol
文件,写入合约内容,solidity对于import引入方式比较糟糕,并且不同版本solidity语法还略有不同,库所使用的语法可能已经在最新版失效,建议使用过程中直接在node_modules/zeppelin-solidity
找到对应需要继承的合约,复制到源码中进行最新版本适配和使用;2_deploy_contracts.js
文件,写入合约部署配置,此步骤是固定写法,不需要修改;/truffle/test
目录下提供的范例。使用truffle migrate
不是合约的时候可能会出现Error: No network specified. Cannot determine current network.
的错误,可以使用将下面配置测试网络的代码放到truffle.js
文件内即可。
Geth
和Remix
编写和测试合约什么是Geth
?官方解释是:Geth是用Go实现的命令行界面运行的完整功能以太坊节点。借助Geth实现:在主网络挖矿、地址间转账、创建合约和发送交易、浏览区块历史等功能。我们主要需要用Geth创建合约和发送交易等功能。
Geth
安装拉取go-ethereum
源码,建议配置命令行科学上网后再尝试:go get -u github.com/ethereum/go-ethereum
,go-ethereum是以太坊源码,我们用Golang连接以太坊合约需要便是要借助它来实现。
Geth安装可运行命令行工具,官方分别给出来两个系统下安装包和源码两种方式:Windows、Mac
Mac下我推荐使用源码方式安装:
执行完毕上面两个步骤,如果没有报错, build/bin/geth 便是生成好的 geth 可执行文件。
需要注意等是源码方式安装完毕后,需要将可执行文件手动添加到环境变量。
Geth
客户端正确执行上一步安装Geth,在命令行输入geth -h
可测试geth是否正确安装,也可以通过这个命令查看geth提供的工具。
使用全默认配置启动geth客户端,在命令行输入geth
回车执行即可,geth会默认启动一个主网络节点,并尝试连接到其他节点,开始同步全量的区块数据。
启动一个geth开发环境dev节点,这个是我们在本地使用最多的启动方式,命令如下:
geth --networkid=1234 --nodiscover --rpc --rpcport=8545 --ws --wsport=8546 --rpccorsdomain="*" --dev --dev.period 1 --datadir=/Users/james/eth/dev console 2>>eth_dev_log
命令 | 解释 |
---|---|
--networkid=1234 | 指定网络ID,只有网络ID一致等节点才可以相互链接,以太主网路网络ID是1,不设置情况下默认ID也是1 |
--nodiscover | 设置为不被其他节点发现 |
--rpc --rpcport=8545 | 开启RPC连接方式,并设置端口为8545 |
--rpccorsdomain="*" | RPC允许所有跨域连接,这个设置主要是为了Remix在线连接本地开发网络 |
--ws --wsport=8546 | 开启WebSocket连接方式,并设置端口为8546 |
--dev --dev.period 1 | 开启开发网络无交易时自动挖矿设置,如不添加此设置在没有新交易时,默认不自动挖矿 |
--datadir=/eth/dev | 设置节点区块数据本地磁盘路径,不设置时将使用默认路径 |
console | Geth启动后仍可接收命令行命令,如不开启又需要使用命令行也可以通过geth attach ipc:\\.\pipe\geth.ipc 方式连接到当前节点 |
console 2>>eth_dev_log | 将命令行操作记录输出到指定文件 |
启动的运行效果如下图,geth客户端运行起来后,类似于eth.blockNumber
的方法可以在:管理API查阅:
更多参数可以使用geth -h
方式查看。
Remix
介绍Remix
是以太坊官方提供的在线合约构建和debug的IDE和工具集,项目地址: https://github.com/ethereum/remix-ide 、 在线工具: https://remix.ethereum.org
下面简单介绍一下怎样用remix部署合约到前一步geth启动起来的dev环境:
coin.sol
文件;Web3 Provider
,此步骤将连接本地启动的dev环境;SuperCoin
;具体操作如下图所示:
部署过程中有两个重要生成内容,abi和bin需要保存下来,入下图所示,object里面内容即为bin,内容copy后保存为super_coin.bin
文件,abi内容点击复制后,保存为super_coin.abi
文件。
Golang
连接合约abigen
生成合约交互工具super_coin.go
ABI是程序的二进制接口。一般来说,ABI是两个程序模块之间的接口,而且通常其中一个程序处于机器级别。也就是说事实上ABI接口就是用于将数据编码/解码到机器代码的方法。
在以太坊上,就是通过ABI把Solidity合约写入到EVM,后续也是借助ABI来从事务中读取到数据的。
具体使用的来说,需要先获取到合约abi文件,再用abigen
工具生成super_coin.go
,最后程序调用super_coin.go
实现合约的部署、方法调用(白名单管理、铸币、转账、余额查询)等交互操作。
可以借助前面提到的Remix工具生成abi文件。
coin.sol
文件;SuperCoin
;super_coin.abi
文件。 具体操作如下图abigen
生成super_coin.go
abigen是go-ethereum一个内置工具,可以使用下面方法安装
abigen --abi super_coin.abi --pkg coin --type SuperCoin --out super_coin.go --bin super_coin.bin
命令 | 解释 |
---|---|
--abi super_coin.abi | 指定abi文件来源 |
--pkg coin | 指定输出文件的包名 |
--type SuperCoin | 指定合约结构体名称 |
--out super_coin.go | 指定合约交互文件名称 |
--bin super_coin.bin | 指定合约部署来源 |
更多使用方法可使用abigen -h
命令来查看。
super_coin.go
实现与合约交互如下面代码,ethclient.Dial()
创建出来和以太坊的链接,再将这个链接传入 super_coin.go
的 NewSuperCoin()
方法即可创建出来合约对象,super_coin.go
提供了几乎所有程序需要和合约交互的方法,详细使用可以查看示例代码 connecter.go 。或查阅 官方文档。
Infura
连接主网络或测试网络项目开发过程中,测试阶段使用dev网络是没问题的,开发完毕后我们需要在测试运行,以及正式部署运行,这时候往往会发现 geth 运行起来的节点如果在国内的服务器上,经常会出现链接不到节点,或者链接不稳定的情况。这个时候你可能会考虑将 geth 运行在国外的服务器,实际上这个时候我们可以选择使用 Infura
, Infura
可以给我们提供稳定的测试网络 Rinkeby
、Ropsten
和主网络 Mainnet
的链接,使用也毫无门槛,只需要如下将 ethclient.Dial()
url替换即可。
官网地址: http://infura.io/