传送门: 柏链项目学院


第二课 智能合约自动化编译

前期内容回顾

之前我们的介绍的是如何通过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功能举例:

  1. 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
  1. 查看本系统中shell是bash的用户名,并打印
cat /etc/passwd |grep bash|awk -F ":" '{print $1}'
  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)的更多相关文章

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

    传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...

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

    传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...

  3. 以太坊智能合约Hello World示例程序

    简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...

  4. 以太坊智能合约 Solidity 的常用数据类型介绍

    目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...

  5. 如何通过以太坊智能合约来进行众筹(ICO)

    前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约. 写在前面 本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊.智能合约有所了解,如果你还 ...

  6. 以太坊智能合约介绍,Solidity介绍

    以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...

  7. 深入以太坊智能合约 ABI

    开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI.本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI ...

  8. rpc接口调用以太坊智能合约

    rpc接口调用以太坊智能合约 传送门: 柏链项目学院   在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...

  9. 使用web3.js监听以太坊智能合约event

    传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event   当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...

随机推荐

  1. Mybaits-plus实战(一)

    1. Mybaits-plus实战(一) 1.1. 快速开始 1.1.1. 配置文件 # 扫描位置 mybatis-plus.mapper-locations=classpath:/mapper/*M ...

  2. 改造断路器集群监控Hystrix Turbine实现自动注册消费者、实时监控多个服务

    在上一篇文章中,我们搭建了Hystrix Dashoard,对指定接口进行监控.但是只能对一个接口进行监听,功能比较局限: Turbine:汇总系统内多个服务的数据并显示到 Hystrix Dashb ...

  3. 基于Servlet+jsp的web计算器

    基于Servlet+jsp的web计算器 这次老大为了让我们自己复习web中页面的跳转给布置得任务 天下代码一大抄,关键看你怎么抄 首先我想到的计算算法不是什么堆栈,是简单的(其实很复杂,但是我就只需 ...

  4. h5实现实时时钟

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <meta nam ...

  5. 安卓开发笔记(二十五):ViewPager的使用

    首先我们来看看运行之后的效果: 然后我们也不多说废话了,下面是这个项目所需要的全部代码,很多博主写这个都不把代码写完,因此笔者自己也琢磨了一会儿才把这个弄出来,感觉很烦,但我肯定会把代码写全的.我这里 ...

  6. Git常用简介

    Git是什么 git是目前最先进的分布式版本控制系统,它的核心架构如下图所示,分为四个核心区域.git的常用命令主要是关于这四个区域. 本地工作区-work 本地工作区就是我们实际电脑中的文件夹以及文 ...

  7. devm_xxx机制【转】

    前言 devm是内核提供的基础机制,用于方便驱动开发者所分配资源的自动回收.参考内核文档devres.txt.总的来说,就是驱动开发者只需要调用这类接口分配期望的资源,不用关心释放问题.这些资源的释放 ...

  8. SVN的安装与配置

    单独安装 SVN:1.安装:yum -y install subversionmkdir -p /data/svn/ 创建创库目录svnadmin create /data/svn/repos 构建版 ...

  9. IM开发者的零基础通信技术入门(二):通信交换技术的百年发展史(下)

    1.系列文章引言 1.1 适合谁来阅读? 本系列文章尽量使用最浅显易懂的文字.图片来组织内容,力求通信技术零基础的人群也能看懂.但个人建议,至少稍微了解过网络通信方面的知识后再看,会更有收获.如果您大 ...

  10. 用github展示自己的网页要做哪些准备(总结)

    以前,如果想建立一个自己的网站,需要买域名,买存储空间,对个人来说维护成本比较高. 并且很多人只是想有一个网页展示自己的作品或者展示个人的简历. 在github越来越成熟的现在,直接使用github托 ...