Skip to content

chinamonkeyking/go-sdk

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Golang SDK For FISCO BCOS

适配FISCO-BCOS v3 / 适配FISCO-BCOS v2

CodeFactor Codacy Badge codecov Code Lines version

FISCO-BCOS Go-SDK GitHub Actions Build Status


FISCO BCOS Go语言版本的SDK,主要实现的功能有:

go-sdk的使用可以当做是一个package进行使用,亦可对项目代码进行编译,直接使用控制台通过配置文件来进行访问FISCO BCOS,3.0版本的go sdk使用cgo依赖bcos-c-sdk以支持国密等特性,请注意先按照文档下载bcos-c-sdk的动态库。

环境准备

master分支的go-sdk对应FISCO-BCOS v3版本,如果使用的是FISCO-BCOS v2版本,请切换到FISCO-BCOS v2分支对应文档

配置结构体说明

type Config struct {
    TLSCaFile       string
    TLSKeyFile      string
    TLSCertFile     string
    TLSSmEnKeyFile  string
    TLSSmEnCertFile string
    IsSMCrypto      bool
    PrivateKey      []byte
    GroupID         string
    Host            string
    Port            int
    DisableSsl      bool
}
  • TLSCaFile/TLSKeyFile/TLSCertFile,建立TLS链接时需要用到的SDK端证书文件路径,如果是国密,其加密私钥和证书使用TLSSmEnKeyFile/TLSSmEnCertFile
  • IsSMCrypto:节点使用的签名和TLS算法,true表示使用国密,false表示使用RSA+ECDSA。
  • PrivateKey:节点签名交易时所使用的私钥,支持国密和非国密。(pem文件可使用LoadECPrivateKeyFromPEM方法解析) 请使用get_account.shget_gm_account.sh脚本生成。使用方式参考这里。 如果想使用Go-SDK代码生成,请参考这里
  • GroupID:账本的GroupID
  • Host:节点IP
  • Port:节点RPC端口
  • DisableSsl:使用TLS加密时为false,不使用TLS加密时为true,此配置项需与节点config.ini中的rpc.disable_ssl保持一致

控制台使用

  1. 搭建FISCO BCOS 3.2以上版本节点,请参考这里

  2. 请拷贝对应的SDK证书到conf文件夹,证书名为ca.crt/sdk.key/sdk.crt,国密时证书名为sm_ca.crt/sm_sdk.key/sm_sdk.crt/sm_ensdk.key/sm_ensdk.crt

  3. go-sdk需要依赖csdk的动态库,下载地址,将动态库放在/usr/local/lib目录下。在其他机器使用时也需要通过export LD_LIBRARY_PATH=${PWD}/lib设置动态库的搜索路径,其中${PWD}/lib需替换为bcos-c-sdk的动态库所在文件夹。如果编译后在其他机器运行,也可以在编译时使用-ldflags指定动态库搜索路径,如go build -ldflags="-r ${PWD}/lib"

    # 下面的脚本帮助用户下载bcos-c-sdk的动态库到/usr/local/lib目录下
    ./tools/download_csdk_lib.sh
  4. go-sdk需要使用cgo,需要设置环境变量export GODEBUG=cgocheck=0

  5. 最后,编译控制台程序:

git clone https://github.com/FISCO-BCOS/go-sdk.git
cd go-sdk
cd v3
go mod tidy
go build -ldflags="-r /usr/local/lib" -o console ./cmd/console.go
./console help

Package功能使用

以下的示例是通过import的方式来使用go-sdk,如引入RPC控制台库:

import "github.com/FISCO-BCOS/go-sdk/v3/client"

Solidity合约编译为Go文件

在利用SDK进行项目开发时,对智能合约进行操作时需要将Solidity智能合约利用go-sdk的abigen工具转换为Go文件代码。整体上主要包含了五个流程:

  • 准备需要编译的智能合约
  • 配置好相应版本的solc编译器
  • 构建go-sdk的合约编译工具abigen
  • 编译生成go文件
  • 使用生成的go文件进行合约调用

下面的内容作为一个示例进行使用介绍。

1.提供一份简单的样例智能合约HelloWorld.sol如下:

// SPDX-License-Identifier: Apache-2.0
pragma solidity >=0.6.10 <0.8.20;

contract HelloWorld {
    string value;
    event setValue(string v, address indexed from, address indexed to, int256 value);
    int public version;

    constructor(string memory initValue) {
        value = initValue;
        version = 0;
    }

    function get() public view returns (string memory) {
        return value;
    }

    function set(string calldata v) public returns (string memory) {
        string memory old = value;
        value = v;
        version = version + 1;
        emit setValue(v, tx.origin, msg.sender, version);
        return old;
    }
}

2.安装对应版本的solc编译器,目前FISCO BCOS默认的solc编译器版本为0.8.11。

# 如果是国密则添加-g选项
bash tools/download_solc.sh -v 0.8.11

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

# 下面指令在go-sdk目录下操作,编译生成abigen工具
cd v3
go build ./cmd/abigen
cd ..
cp v3/abigen .

执行命令后,检查根目录下是否存在abigen,并将准备的智能合约HelloWorld.sol放置在一个新的目录下:

mkdir ./hello
cp .ci/hello/HelloWorld.sol ./hello

4.编译生成go文件,先利用solc将合约文件生成abibin文件,以前面所提供的HelloWorld.sol为例:

# 国密请使用 ./solc-0.8.11-gm --bin --abi -o ./hello ./hello/HelloWorld.sol
./solc-0.8.11 --bin --abi -o ./hello ./hello/HelloWorld.sol

在MacOS下运行./solc-0.8.11时如果出现找不到libz3.dylib的错误,例如:

dyld[42564]: Library not loaded: /opt/homebrew/opt/z3/lib/libz3.dylib
  Referenced from: <08BAD135-54EC-3430-A170-26E7B4A5BA96> xxxxxx/.fisco/solc/solc-0.8.11
  Reason: tried xxxxxx

可尝试以下命令安装libz3

brew installz3

HelloWorld.sol目录下会生成HelloWorld.binHelloWorld.abi。此时利用abigen工具将HelloWorld.binHelloWorld.abi转换成HelloWorld.go

# 国密请使用 ./abigen --bin ./hello/HelloWorld.bin --abi ./hello/HelloWorld.abi --pkg hello --type HelloWorld --out ./hello/HelloWorld.go --smcrypto=true
# 注意:国密模式,请使用国密solc编译得到bin
./abigen --bin ./hello/HelloWorld.bin --abi ./hello/HelloWorld.abi --pkg hello --type HelloWorld --out ./hello/HelloWorld.go

最后hello目录下面存在以下文件:

HelloWorld.abi  HelloWorld.bin  HelloWorld.go  HelloWorld.sol

5.调用生成的HelloWorld.go文件进行合约调用

至此,合约已成功转换为go文件,用户可根据此文件在项目中利用SDK进行合约操作。具体的使用可参阅下一节。

部署智能合约

下面的例子先部署合约,在部署过程中设置的HelloWorld.sol合约中有一个公开的名为version的全局变量,这种公开的成员将自动创建getter函数,然后调用Version()来获取version的值。

写入智能合约需要我们用私钥来对交易事务进行签名,我们创建的智能合约有一个名为Set的方法,它接受string类型的参数,然后将其设置为value,并且将version加1。

新建一个go工程,目录结构如下

hello
  |—— HelloWorld.go
ca.crt
go.mod
go.sum
hello_main.go
sdk.crt
sdk.key

hello_main.go代码如下

package main

import (
	"context"
	"encoding/hex"
	"fmt"
	"log"

	"example/go-sdk/hello"

	"github.com/FISCO-BCOS/go-sdk/v3/client"
	"github.com/FISCO-BCOS/go-sdk/v3/types"
)

func main() {
	privateKey, _ := hex.DecodeString("145e247e170ba3afd6ae97e88f00dbc976c2345d511b0f6713355d19d8b80b58")
	config := &client.Config{IsSMCrypto: false, GroupID: "group0",
		PrivateKey: privateKey, Host: "127.0.0.1", Port: 20200, TLSCaFile: "./ca.crt", TLSKeyFile: "./sdk.key", TLSCertFile: "./sdk.crt"}
	client, err := client.DialContext(context.Background(), config)
	if err != nil {
		log.Fatal(err)
	}
	input := "HelloWorld deployment 1.0"
	fmt.Println("=================DeployHelloWorld===============")
	address, receipt, instance, err := hello.DeployHelloWorld(client.GetTransactOpts(), client, input)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("contract address: ", address.Hex()) // the address should be saved, will use in next example
	fmt.Println("transaction hash: ", receipt.TransactionHash)

	// load the contract
	// contractAddress := common.HexToAddress("contract address in hex String")
	// instance, err := hello.NewHelloWorld(contractAddress, client)
	// if err != nil {
	//     log.Fatal(err)
	// }

	fmt.Println("================================")
	helloSession := &hello.HelloWorldSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()}

	version, err := helloSession.Version()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println("version :", version) // "HelloWorld deployment 1.0"

	ret, err := helloSession.Get()
	if err != nil {
		fmt.Printf("hello.Get() failed: %v", err)
		return
	}
	done := make(chan bool)
	currentBlock, err := client.GetBlockNumber(context.Background())
	if err != nil {
		fmt.Printf("GetBlockNumber() failed: %v", err)
		return
	}
	_, err = helloSession.WatchAllSetValue(&currentBlock, func(ret int, logs []types.Log) {
		fmt.Printf("WatchAllSetValue receive statud: %d, logs: %v\n", ret, logs)
		setValue, err := helloSession.ParseSetValue(logs[0])
		if err != nil {
			fmt.Printf("hello.WatchAllSetValue() failed: %v", err)
			panic("WatchAllSetValue hello.WatchAllSetValue() failed")
		}
		fmt.Printf("receive setValue: %+v\n", *setValue)
		done <- true
	})
	if err != nil {
		fmt.Printf("hello.WatchAllSetValue() failed: %v", err)
		return
	}
	fmt.Printf("Get: %s\n", ret)
	fmt.Println("================================")

	oldValue, _, receipt, err := helloSession.Set("hello fisco")
	fmt.Println("old value is: ", oldValue)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("transaction hash of receipt: %s\n", receipt.GetTransactionHash())

	ret, err = helloSession.Get()
	if err != nil {
		fmt.Printf("hello.Get() failed: %v", err)
		return
	}
	fmt.Printf("Get: %s\n", ret)
	<-done
}

在项目目录下运行hello_world.go

go run -ldflags="-r /usr/local/lib" main.go

About

golang SDK of FISCO BCOS

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Go 87.5%
  • Solidity 8.7%
  • Shell 3.8%