• FiscoBcos使用Go调用合约


    环境: fisco2.8.0
    go 1.17
    go-sdk 1.0.0
    solidity 0.4.25

    前言

    请提前启动好四个fisco节点。

    请准备好一个属于此fisco节点的账户私钥【待会调用合约和部署合约会用到】

    此文章将讲解 官方文档使用gosdk部署helloworld合约并调用其方法 合约开发样例

    官网提示

    Golang, 版本需不低于1.13.6,本项目采用go module进行包管理。具体可查阅Using Go Modules,环境配置
    FISCO BCOS 2.2.0+, 需要提前运行 FISCO BCOS 区块链平台,可参考安装搭建
    Solidity编译器,默认0.4.25版本

    gosdk的拉取

    # 拉取代码
    git clone https://github.com/FISCO-BCOS/go-sdk.git
    
    # 若因为网络问题导致长时间无法执行上面的命令,请尝试以下命令:
    git clone https://gitee.com/FISCO-BCOS/go-sdk.git
    
    • 1
    • 2
    • 3
    • 4
    • 5
    root@192-168-19-133:/usr/project/goproject# ll
    drwxr-xr-x 17 root root 4096 1116 10:29 go-sdk/
    
    • 1
    • 2

    go-sdk的tag版本

    root@192-168-19-133:/usr/project/goproject/go-sdk# git show
    commit d1a8411d0e7600e2ece7c50c6da523ee52f32a45 (HEAD -> master, tag: v1.0.0, origin/master, origin/HEAD)
    Merge: 5ca92a0 797900f
    Author: XingQiang Bai <bxq2011hust@qq.com>
    Date:   Thu May 12 17:22:46 2022 +0800
    
        Merge pull request #148 from FISCO-BCOS/release-v1.0.0
    
        Release v1.0.0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    创建 helloworld的项目

    我选择不跟官网的步骤,不在go-sdk目录进行创建,选择在gopath的工作目录下面进行项目创建【这样比较方便管理】

    root@192-168-19-133:/usr/project/goproject# mkdir helloworld
    
    • 1

    然后进行go项目初始化

    root@192-168-19-133:/usr/project/goproject/helloworld# go mod init helloworld
    go: creating new go.mod: module helloworld
    
    • 1
    • 2

    然后在helloworld目录下,编写一个HelloWorld.sol的合约

    pragma solidity>=0.4.24 <0.6.11;
    
    contract HelloWorld {
        string value;
    
        constructor() public {
            value = "你好,golang!";
        }
    
        function get() public view returns (string memory) {
            return value;
        }
    
        function set(string v) public {
            value = v;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    进行安装solc编译器

    在helloworld项目下执行此命令,需要用到在go-sdk里面的下载编译器脚本文件, go-sdk的目录需要根据各自的实际情况来选择

     bash  /usr/project/goproject/go-sdk/tools/download_solc.sh -v 0.4.25 # 它会做链接到当前目录下
    
    • 1
    root@192-168-19-133:/usr/project/goproject/helloworld# bash  /usr/project/goproject/go-sdk/tools/download_solc.sh -v 0.4.25
    Downloading solc 0.4.25 solc-linux.tar.gz from https://github.com/FISCO-BCOS/solidity/releases/download/v0.4.25/solc-linux.tar.gz
    ==============================================================
    [INFO] os            : linux
    [INFO] solc version  : 0.4.25
    [INFO] solc location : ./solc-0.4.25
    ==============================================================
    [INFO] ./solc-0.4.25 --version
    solc, the solidity compiler commandline interface
    Version: 0.4.25+commit.46d177ad.mod.Linux.g++
    root@192-168-19-133:/usr/project/goproject/helloworld# ll
    总用量 12
    drwxr-xr-x 2 root root 4096 1116 10:46 ./
    drwxrwxrwx 8 root root 4096 1116 10:38 ../
    -rw-r--r-- 1 root root  294 1116 10:43 HelloWorld.sol
    lrwxrwxrwx 1 root root   29 1116 10:46 solc-0.4.25 -> /root/.fisco/solc/solc-0.4.25*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    生成abi,bin文件

    使用solc 进行编译 命令的意思是,根据HelloWorld.sol生成abi,bin文件到当前目录下

    root@192-168-19-133:/usr/project/goproject/helloworld# ./solc-0.4.25 --bin --abi -o ./ ./HelloWorld.sol #
    root@192-168-19-133:/usr/project/goproject/helloworld# ll
    总用量 20
    drwxr-xr-x 2 root root 4096 1116 10:49 ./
    drwxrwxrwx 8 root root 4096 1116 10:38 ../
    -rw-r--r-- 1 root root  375 1116 10:49 HelloWorld.abi
    -rw-r--r-- 1 root root 2010 1116 10:49 HelloWorld.bin
    -rw-r--r-- 1 root root  294 1116 10:43 HelloWorld.sol
    lrwxrwxrwx 1 root root   29 1116 10:46 solc-0.4.25 -> /root/.fisco/solc/solc-0.4.25*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    构建go-sdk的代码生成工具abigen

    该工具用于将 abi 和 bin 文件转换为 go 文件
    进入go-sdk目录,编译生成abigen工具 [会生成一个abigen的二进制文件]

    root@192-168-19-133:/usr/project/goproject/go-sdk# go build ./cmd/abigen/
    root@192-168-19-133:/usr/project/goproject/go-sdk# ll | grep abigen
    -rwxr-xr-x  1 root root 21519720 1116 11:33 abigen*
    
    • 1
    • 2
    • 3

    若 上面步骤报错:可以在go-sdk目录执行此命令,把依赖重新下载导入一下

    go mod tidy
    
    • 1

    然后将此文件复制到helloworld项目,[此abigen可以复用,以后想用abigen,直接复制就可以了,不需要再去go-sdk里再编译]

     cp -r abigen ../helloworld/`
    
    • 1

    编译生成go文件

    在helloworld目录下执行命令编译

    ./abigen --bin ./HelloWorld.bin --abi ./HelloWorld.abi --pkg helloworld --type HelloWorld --out ./HelloWorld.go
    
    • 1

    命令的意思是使用bin,abi文件在当前目录下 生成一个包为helloworld ,类型为HelloWorld的HelloWorld.go文件

    root@192-168-19-133:/usr/project/goproject/helloworld# ll
    drwxrwxrwx 4 root root     4096 1116 11:36 ./
    drwxrwxrwx 8 root root     4096 1116 11:35 ../
    -rwxrwxrwx 1 root root 21519720 1116 11:37 abigen*
    -rwxrwxrwx 1 root root      531 1116 11:06 config.toml*
    -rw-r--r-- 1 root root     1970 1116 11:31 go.mod
    -rwxrwxrwx 1 root root      375 1116 10:49 HelloWorld.abi*
    -rwxrwxrwx 1 root root     2010 1116 10:49 HelloWorld.bin*
    -rwxrwxrwx 1 root root    13739 1116 11:03 HelloWorld.go*
    -rwxrwxrwx 1 root root      294 1116 10:43 HelloWorld.sol*
    lrwxrwxrwx 1 root root       29 1116 10:46 solc-0.4.25 -> /root/.fisco/solc/solc-0.4.25*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    准备部署合约的相关文件

    拷贝 config.toml 并修改配置

    将 go-sdk目录下config.toml拷贝到helloworld目录下

    cp -r ../go-sdk/config.toml .
    
    • 1

    拷贝节点的sdk文件目录到helloworld目录下【根据自己的机子存放情况来执行命令】
    拷贝账户私钥到helloworld目录下【前言有说明】

    当前目录存在的文件

    root@192-168-19-133:/usr/project/goproject/helloworld# ll
    总用量 21120
    drwxrwxrwx 4 root root     4096 1116 12:41 ./
    drwxrwxrwx 8 root root     4096 1116 11:35 ../
    -rwxrwxrwx 1 root root 21519720 1116 11:37 abigen*
    -rwxrwxrwx 1 root root      249 1116 11:05 admin.pem*   ## 私钥
    -rwxrwxrwx 1 root root      531 1116 11:06 config.toml* ## 配置文件
    -rw-r--r-- 1 root root     1970 1116 11:31 go.mod  # go mod文件
    -rwxrwxrwx 1 root root      375 1116 10:49 HelloWorld.abi*
    -rwxrwxrwx 1 root root     2010 1116 10:49 HelloWorld.bin*
    -rwxrwxrwx 1 root root    13739 1116 11:03 HelloWorld.go*
    -rwxrwxrwx 1 root root      294 1116 10:43 HelloWorld.sol*
    drwxrwxrwx 2 root root     4096 1116 11:03 sdk/ # 节点连接证书
    lrwxrwxrwx 1 root root       29 1116 10:46 solc-0.4.25 -> /root/.fisco/solc/solc-0.4.25*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    修该config.toml

    
    [Network]
    #type rpc or channel
    Type="channel"
    # 三个节点证书,使用相对路径
    CAFile="./sdk/ca.crt"   
    Cert="./sdk/sdk.crt"
    Key="./sdk/sdk.key"
    # if the certificate context is not empty, use it, otherwise read from the certificate file
    # multi lines use triple quotes
    CAContext=''''''
    KeyContext=''''''
    CertContext=''''''
    
    [[Network.Connection]]
    NodeURL="127.0.0.1:20200"  # 节点的地址
    GroupID=1  # 群组id
    # [[Network.Connection]]
    # NodeURL="127.0.0.1:20200"
    # GroupID=2
    
    [Account]
    # only support PEM format for now
    KeyFile="./admin.pem"  #使用什么账户调用合约
    
    [Chain]
    ChainID=1 #链id
    SMCrypto=false # 费国密
    
    [log]
    Path="./"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    编写部署合约的go文件 并部署

    在helloworld目录下创建cmd文件夹,在cmd文件夹下创建一个main.go文件
    代码如下

    package main
    
    import (
        "fmt"
        "log"
        "helloworld"  //导入本地项目helloworld
        "github.com/FISCO-BCOS/go-sdk/client"
        "github.com/FISCO-BCOS/go-sdk/conf"
    )
    
    func main(){
        configs, err := conf.ParseConfigFile("config.toml")  //读取config.toml文件
        if err != nil {
            log.Fatal(err)
        }
        config := &configs[0]
    
        client, err := client.Dial(config)  //加载配置文件,生成client进行相关链操作
        if err != nil {
            log.Fatal(err)
        }
        address, tx, instance, err := helloworld.DeployHelloWorld(client.GetTransactOpts(), client) // 调用hellowrold的部署合约方法
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("contract address: ", address.Hex())  // 合约的地址
        fmt.Println("transaction hash: ", tx.Hash().Hex())  //此次部署合约的交易hash
        _ = instance
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    然后在helloworld目录下执行依赖包导入命令

    go mod tidy
    
    • 1

    如果导入失败了,可以复制go-sdk的go.mod和go.sum文件,修改好项目名,进行go mod tidy
    还有确保GO111MODULE是on

    此时项目的目录

    root@192-168-19-133:/usr/project/goproject/helloworld# ll
    总用量 21120
    drwxrwxrwx 4 root root     4096 1116 12:50 ./
    drwxrwxrwx 8 root root     4096 1116 11:35 ../
    -rwxrwxrwx 1 root root 21519720 1116 11:37 abigen*
    -rwxrwxrwx 1 root root      249 1116 11:05 admin.pem*
    drwxrwxrwx 2 root root     4096 1116 12:47 cmd/
    -rwxrwxrwx 1 root root      531 1116 12:42 config.toml*
    -rw-r--r-- 1 root root     1970 1116 11:31 go.mod
    -rw-r--r-- 1 root root    46323 1116 11:31 go.sum
    -rwxrwxrwx 1 root root      375 1116 10:49 HelloWorld.abi*
    -rwxrwxrwx 1 root root     2010 1116 10:49 HelloWorld.bin*
    -rwxrwxrwx 1 root root    13739 1116 11:03 HelloWorld.go*
    -rwxrwxrwx 1 root root      294 1116 10:43 HelloWorld.sol*
    drwxrwxrwx 2 root root     4096 1116 11:03 sdk/
    lrwxrwxrwx 1 root root       29 1116 10:46 solc-0.4.25 -> /root/.fisco/solc/solc-0.4.25*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在helloworld 文件夹下执行命令 go run cmd/main.go

    root@192-168-19-133:/usr/project/goproject/helloworld# go run cmd/main.go
    contract address:  0xA2132f9E796F954f4483A7078a357114F54D2f1B
    transaction hash:  0x741fe11c3f1da7ad2ca43deb3b7045c170ce43aa5b3581bdfbf86a6fc323e331
    
    • 1
    • 2
    • 3

    然后就获得了部署合约的地址,部署成功

    编写get/set方法的go文件,并调用

    根据官网的例子,在helloworld文件夹下创建contract文件夹,并在在contract文件夹下编写go文件helloworld_set_get.go文件

    package main
    
    import (
        "fmt"
        "log"
        "helloworld"  //导入本地项目helloworld
        "github.com/FISCO-BCOS/go-sdk/client"
        "github.com/FISCO-BCOS/go-sdk/conf"
        "github.com/ethereum/go-ethereum/common"
    )
    
    func main() {
        configs, err := conf.ParseConfigFile("config.toml")   //读取配置文件
        if err != nil {
            log.Fatal(err)
        }
        config := &configs[0]  
        client, err := client.Dial(config)  //加载配置文件,生成client
        if err != nil {
            log.Fatal(err)
        }
    
        // load the contract
        contractAddress := common.HexToAddress("0xA2132f9E796F954f4483A7078a357114F54D2f1B") // 这里请放入刚刚部署的合约地址,注意,是你自己的机子部署的地址
        instance, err := helloworld.NewHelloWorld(contractAddress, client)  //根据地址和client生成helloworld合约对象
        if err != nil {
            log.Fatal(err)
        }
    
        helloworldSession := &helloworld.HelloWorldSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()}  //根据合约对象和client的call和transact进行实例化一个合约通信对象 helloworldSession
    
        value, err := helloworldSession.Get()    // 调用get方法
        if err != nil {
            log.Fatal(err)
        }
        fmt.Println("value :", value)
    
        value = "Hello, Hello,Hello"
        tx, receipt, err := helloworldSession.Set(value)  // 调用set方法
        if err != nil {
            log.Fatal(err)
        }
    
        fmt.Printf("tx sent: %s\n", tx.Hash().Hex())  //调用set方法的交易hash
        fmt.Printf("transaction hash of receipt: %s\n", receipt.GetTransactionHash())  //调用set方法的交易hash ,与上面的hash是一样,只是存在不同的地方而已
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    执行go文件,在helloworld目录下

     go run contract/helloworld_set_get.go
    
    • 1

    结果

    root@192-168-19-133:/usr/project/goproject/helloworld# go run contract/helloworld_set_get.go
    value : 你好,golang!
    tx sent: 0x5a49ac1b48ebe717c75cbeb3a3144a031db8cfd5a0cdf7c38a151a87f1454583
    transaction hash of receipt: 0x5a49ac1b48ebe717c75cbeb3a3144a031db8cfd5a0cdf7c38a151a87f1454583
    
    • 1
    • 2
    • 3
    • 4

    结语

    相较于fisco的java-sdk ,go-sdk的使用起来还是比较困难,因为webase也集成了java-sdk,一键就能导出所有所需要的java项目文件。
    若有空,我将讲解如果结合goweb的框架,集成fisco和使用go文件调用合约,生成web项目【我比较倾向讲解beego框架】。

  • 相关阅读:
    2023数维杯数学建模竞赛D题思路+模型+代码+论文
    Reka Core, Flash, and Edge: A Series of Powerful Multimodal Language Models
    Linux中汇编语言的学习(加法、乘法、除法、左移、右移、按位与等多种命令操作实例以及ARM的 N、Z、C、V 标志位的解释)
    [李宏毅老师深度学习视频]深度学习全连接层+反向传播机制【手写笔记】
    论文阅读——BERT
    多台电脑之间共享、传输文件数据:不借助数据线与软件的方法
    linux 命令大全
    【人工智能数学基础】几何解释——最小二乘法
    数据结构绪论、顺序表课后练习题
    kudeadm 部署 k8s
  • 原文地址:https://blog.csdn.net/weixin_52865146/article/details/134346565