Go语言打造以太坊智能合约测试框架(level2)

传送门: 柏链项目学院
第二课 智能合约自动化编译
前期内容回顾
之前我们的介绍的是如何通过solc编译智能合约,并且调用智能合约,本节我们继续实践,将智能合约的代码自动化编译以及abi文件生成搞定。
我们需要掌握什么技能呢?
- go语言调用命令行
- toml配置文件处理
- awk工具的使用
go调用命令行
go调用命令行,我们使用exec包
- LookPath 可以判断一个可执行程序是否存在
- Command 创建一个命令行
- cmd.Run() 运行命令行,也可以使用Start()模式,可以去接收管道信息来得到程序返回结果
- 如果是一个shell脚本,那么可以用/bin/bash来启动
toml配置文件处理
TOML的全称是Tom's Obvious, Minimal Language,因为它的作者是GitHub联合创始人Tom Preston-Werner。TOML 的目标是成为一个极简的配置文件格式。TOML 被设计成可以无歧义地被映射为哈希表,从而被多种语言解析。
toml学习教程
在使用的时候,记得要安装toml第三方包。
go get -u github.com/BurntSushi/toml
之后可以根据我们的需要,来编写配置文件,配置文件的目的仍然是为了让程序运行更灵活,而不应该成为我们的负担!
awk工具使用
awk其实是一个语言,unix平台上处理文本的一种语言,其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。该语言的能力十分强大,可以支持字符串处理,打印等操作,工程中对于文本处理要求比较高的环节多会使用awk进行操作。
awk功能举例:
- factory.txt 是一个工厂内目前产品库存情况,如果数量低于75,需要重新下订单,如何处理?
yekaideMacBook-Pro:awk yk$ cat factory.txt
ProdA 70
ProdB 85
ProdC 74
示例如下:
awk '{if ($2 < 75) printf("%s reorder\n",$0);if ($2 >= 75) print $0}' factory.txt
- 查看本系统中shell是bash的用户名,并打印
cat /etc/passwd |grep bash|awk -F ":" '{print $1}'
- awk处理合约的go文件,将abi信息截取处理存储到文本当中
awk '/const.+ABI = .+/{print substr($4,2,length($4)-2) }' pdbank.go > pdbank.abi
编写自动编译功能
main.go
package main
import (
"fmt"
"os"
)
func Usage() {
fmt.Printf("%s 1 -- compiler code\n", os.Args[0])
fmt.Printf("%s 2 -- build test code\n", os.Args[0])
}
func main() {
if len(os.Args) < 2 {
Usage()
os.Exit(0)
}
if os.Args[1] == "1" {
CompilerRun()
} else if os.Args[1] == "1" {
//build test code
} else {
Usage()
os.Exit(0)
}
}
接下来开始做填空题,也就是如何编译,我们先来实现。先编写扫描目录的代码,获取指定目录的sol文件,然后自动化的形成编译命令,送到命令行执行。
扫描指定目录的sol文件
func CompilerRun() error {
infos, err := ioutil.ReadDir("sol")
if err != nil {
fmt.Println("failed to readdir ", err)
return err
}
for _, v := range infos {
//后4位位.sol
strNameRune := []rune(v.Name())
strfix := string(strNameRune[len(strNameRune)-4:])
if strfix == ".sol" && !v.IsDir() {
fmt.Println(v.IsDir(), v.Name(), v.Size(), "ok")
err = CompilerOnece("sol", v.Name(), "contracts")
if err != nil {
fmt.Println("call ompilerOnece err", err)
break
}
}
}
return err
}
编译函数
//编译一个智能合约
func CompilerOnece(solPath, solName, targetPath string) error {
//xxx.sol - > xxx.go
goName := strings.Replace(solName, ".sol", ".go", -1)
cmd := exec.Command("abigen", "-sol", solPath+"/"+solName, "-pkg", targetPath, "-out", targetPath+"/"+goName)
return cmd.Run()
}
构建abi函数,我们需要先用awk实现一个shell脚本,用来处理go文件的abi信息。
func BuildAbi(goCodeName string) error {
abiName := strings.Replace(goCodeName, ".go", ".abi", -1)
cmd := exec.Command("/bin/bash", "abi.sh", goCodeName, abiName)
err := cmd.Run()
fmt.Println("run BuildAbi ok!!", err)
return nil
}
abi.sh
filename=$1
targetfile=$2
awk '/const.+ABI = .+/{print substr($4,2,length($4)-2) }' $filename > $targetfile
统一调用处理
func ParseRun() {
solfiles, err := ParseDir("sol")
fmt.Println(solfiles, err)
for _, solfile := range solfiles {
fmt.Println(solfile)
codeName, err := Compiler(solfile, "sol", "contracts")
if err != nil {
fmt.Println("failed to complie code", err)
return
}
err = BuildAbi(codeName)
if err != nil {
fmt.Println("failed to build abi", err)
return
}
}
}
这样我们的基础工作完成了,但是代码不够完美,我们需要将部分写死的变量用配置文件来设置,所以再加入toml处理配置文件的部分。
添加config.tomls
[version]
auth = "yekai"
company = "pdj"
buildday = "2019-01-01"
ver = "1.0.0" # 版本
[common]
solidityPath = "sol"
goPath = "contracts"
abiSH = "./abi.sh"
添加config.go
package main
import (
"log"
"github.com/BurntSushi/toml"
)
type ServerConfig struct {
Version VersionInfo
Common CommonInfo
}
type VersionInfo struct {
Auth string
Company string
BuildDay string
Ver string
}
type CommonInfo struct {
SolidityPath string //智能合约原路径
GoPath string //输出go代码路径
AbiSH string //处理abi的shell脚本路径
}
var ServConf ServerConfig
func init() {
getConfig()
}
func getConfig() {
var servConf ServerConfig
_, err := toml.DecodeFile("config.toml", &servConf)
if err != nil {
log.Panic("faild to decodefile ", err)
}
ServConf = servConf
//fmt.Println(servConf)
}
接下来替换原来的代码部分
package main
import (
"fmt"
"io/ioutil"
"os/exec"
"strings"
)
//编译一个智能合约
func CompilerOnece(solPath, solName, targetPath string) error {
//xxx.sol - > xxx.go
goName := strings.Replace(solName, ".sol", ".go", -1)
cmd := exec.Command("abigen", "-sol", solPath+"/"+solName, "-pkg", targetPath, "-out", targetPath+"/"+goName)
return cmd.Run()
}
//构造abi
func BuildAbi(codePath string) error {
//"contracts/pdbank.go"
//xxx.sol - > xxx.abi
abiName := strings.Replace(codePath, ".sol", ".abi", -1)
goName := strings.Replace(codePath, ".sol", ".go", -1)
cmd := exec.Command(ServConf.Common.AbiSH, goName, abiName)
return cmd.Run()
}
//扫描目录,获得全部的文件
func CompilerRun() error {
infos, err := ioutil.ReadDir(ServConf.Common.SolidityPath)
if err != nil {
fmt.Println("failed to readdir ", err)
return err
}
for _, v := range infos {
//后4位位.sol
strNameRune := []rune(v.Name())
strfix := string(strNameRune[len(strNameRune)-4:])
if strfix == ".sol" && !v.IsDir() {
fmt.Println(v.IsDir(), v.Name(), v.Size(), "ok")
err = CompilerOnece(ServConf.Common.SolidityPath, v.Name(), ServConf.Common.GoPath)
if err != nil {
fmt.Println("call ompilerOnece err", err)
break
}
//创建abi
err = BuildAbi(ServConf.Common.GoPath + "/" + v.Name())
if err != nil {
fmt.Println("call BuildAbi err", err)
break
}
}
}
return err
}

Go语言打造以太坊智能合约测试框架(level2)的更多相关文章
- Go语言打造以太坊智能合约测试框架(level1)
传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...
- Go语言打造以太坊智能合约测试框架(level3)
传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...
- 以太坊智能合约Hello World示例程序
简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...
- 以太坊智能合约 Solidity 的常用数据类型介绍
目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...
- 如何通过以太坊智能合约来进行众筹(ICO)
前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还 ...
- 以太坊智能合约介绍,Solidity介绍
以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...
- 深入以太坊智能合约 ABI
开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI.本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI ...
- rpc接口调用以太坊智能合约
rpc接口调用以太坊智能合约 传送门: 柏链项目学院 在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...
- 使用web3.js监听以太坊智能合约event
传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event 当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...
随机推荐
- Android studio无法创建类和接口问题解决办法。提示 Unable to parse template "Class"
重新配置了studio 的工作环境, 没问题,后来加需求要新增java类和接口,这就出现问题了,新建的时候,就会报错: Unable to parse template "Interface ...
- 物理dataguard 正常切换 脚色转换,switchover_status 状态改变
正常切换切换前: 主库:SQL> select DATABASE_ROLE from v$database;DATABASE_ROLE----------------PRIMARY SQL> ...
- windows之自动化在虚拟机部署操作系统并自带python环境
(1)使用详情: **************************** * 操作说明 * **************************** 1.修改Config文件夹中的Se ...
- Vue2.x源码学习笔记-Vue源码调试
如果我们不用单文件组件开发,一般直接<script src="dist/vue.js">引入开发版vue.js这种情况下debug也是很方便的,只不过vue.js文件代 ...
- C# 定时关机小程序
1.打开VS2019,创建界面和按钮 2. 代码如下: private void button1_Click(object sender, EventArgs e) { downpc(txttime. ...
- SpringCloud学习系列汇总
Spring Cloud常用组件使用汇总 使用SpringBoot2.0.3整合SpringCloud 服务注册与发现Eureka 自定义Eureka集群负载均衡策略 如何使用高可用的Eureka F ...
- 从壹开始微服务 [ DDD ] 之三 ║ 简单说说:领域、子域、限界上下文
前言 哈喽大家好,DDD领域驱动设计系列又开始了,前天周二的那篇入门文章中,也收到了一定的效果(写小说的除外),同时我也是倍感鸭梨,怎么说呢,DDD领域驱动设计已经有十年历史了,甚至更久,但是包括我在 ...
- Identity Server 4 - Hybrid Flow - 使用ABAC保护MVC客户端和API资源
这个系列文章介绍的是Identity Server 4 实施 OpenID Connect 的 Hybrid Flow. 保护MVC客户端: https://www.cnblogs.com/cgzl/ ...
- PERL学习笔记---正则表达式的应用
使用m//匹配 //这是m//(模式匹配)的一种简写.同qw//操作一样,可以使用任何成对的分隔符.因此,可以使用m(fred), m<fred>, m{fred}, m[fred],或者 ...
- .NET Core微服务之基于Steeltoe使用Zipkin实现分布式追踪
Tip: 此篇已加入.NET Core微服务基础系列文章索引 => Steeltoe目录快速导航: 1. 基于Steeltoe使用Spring Cloud Eureka 2. 基于Steelt ...