Golang SDK For FISCO BCOS 3.0.0+
FISCO BCOS Go语言版本的SDK,主要实现的功能有:
- FISCO BCOS 3.0 JSON-RPC服务
Solidity
合约编译为Go文件- 部署、查询、写入智能合约
- 控制台
go-sdk
的使用可以当做是一个package
进行使用,亦可对项目代码进行编译,直接使用控制台通过配置文件来进行访问FISCO BCOS。
- Golang, 版本需不低于
1.17
,本项目采用go module
进行包管理。具体可查阅Using Go Modules,环境配置 https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/installation.html#fisco-bcos) - FISCO BCOS 3.0.0+, 需要提前运行 FISCO BCOS 区块链平台(对应2.0版本sdk),可参考安装搭建
- FISCO BCOS 2.2.0+, 需要提前运行 FISCO BCOS 区块链平台(对应1.0版本sdk),可参考安装搭建
- Solidity编译器,默认0.4.25版本
type Config struct {
IsSMCrypto bool
PrivateKey []byte
GroupID string
NodeURL string
}
- IsSMCrypto:使用的签名算法,ture表示使用国密SM2,false表示使用普通ECDSA。
- PrivateKey:节点签发交易时所使用的私钥,支持国密和非国密。(pem文件可使用LoadECPrivateKeyFromPEM方法解析) 请使用get_account.sh和get_gm_account.sh脚本生成。使用方式参考这里。 如果想使用Go-SDK代码生成,请参考这里。
- GroupID:账本id
- NodeURL:连接的节点的ip和port(示例:127.0.0.1:20200)
在使用控制台需要先拉取代码或下载代码:
- 拉取代码并编译
git clone https://github.com/FISCO-BCOS/go-sdk.git
cd go-sdk
git checkout dev-3.0.0
-
搭建FISCO BCOS 3.0以上版本节点,请参考这里。
-
请拷贝对应的SDK证书到conf文件夹。
-
go-sdk需要依赖csdk的动态库,下载地址为(https://github.com/yinghuochongfly/bcos-c-sdk/releases/download/v3.0.1-rc4/libbcos-c-sdk.so),需要下载动态库,拷贝到/usr/local/lib/bcos-c-sdk/libs/linux文件夹下。
-
go-sdk需要使用cgo,linux环境需要设置环境变量 export GODEBUG=cgocheck=0。(可以添加到/etc/profile文件中)
-
最后,编译,运行控制台查看可用指令:
go mod tidy
go build -ldflags="-r /usr/local/lib/bcos-c-sdk/libs/linux" -o console cmd/console.go
./console help
以下的示例是通过import
的方式来使用go-sdk
,如引入RPC控制台库:
import "github.com/FISCO-BCOS/go-sdk/client"
在利用SDK进行项目开发时,对智能合约进行操作时需要将Solidity智能合约利用go-sdk的abigen
工具转换为Go
文件代码。整体上主要包含了五个流程:
- 准备需要编译的智能合约
- 配置好相应版本的
solc
编译器 - 构建go-sdk的合约编译工具
abigen
- 编译生成go文件
- 使用生成的go文件进行合约调用
下面的内容作为一个示例进行使用介绍。
1.提供一份简单的样例智能合约Store.sol
如下:
pragma solidity ^0.4.25;
contract Store {
event ItemSet(bytes32 key, bytes32 value);
string public version;
mapping (bytes32 => bytes32) public items;
constructor(string _version) public {
version = _version;
}
function setItem(bytes32 key, bytes32 value) external {
items[key] = value;
emit ItemSet(key, value);
}
}
2.安装对应版本的solc
编译器,目前FISCO BCOS默认的solc
编译器版本为0.4.25。
# 如果是国密则添加-g选项
bash tools/download_solc.sh -v 0.4.25
3.构建go-sdk
的代码生成工具abigen
# 下面指令在go-sdk目录下操作,编译生成abigen工具
go build ./cmd/abigen
执行命令后,检查根目录下是否存在abigen
,并将准备的智能合约Store.sol
放置在一个新的目录下:
mkdir ./store
mv Store.sol ./store
4.编译生成go文件,先利用solc
将合约文件生成abi
和bin
文件,以前面所提供的Store.sol
为例:
# 国密请使用 ./solc-0.4.25-gm --bin --abi -o ./store ./store/Store.sol
./solc-0.4.25 --bin --abi -o ./store ./store/Store.sol
Store.sol
目录下会生成Store.bin
和Store.abi
。此时利用abigen
工具将Store.bin
和Store.abi
转换成Store.go
:
# 国密请使用 ./abigen --bin ./store/Store.bin --abi ./store/Store.abi --pkg store --type Store --out ./store/Store.go --smcrypto=true
./abigen --bin ./store/Store.bin --abi ./store/Store.abi --pkg store --type Store --out ./store/Store.go
最后store目录下面存在以下文件:
Store.abi Store.bin Store.go Store.sol
5.调用生成的Store.go
文件进行合约调用
至此,合约已成功转换为go文件,用户可根据此文件在项目中利用SDK进行合约操作。具体的使用可参阅下一节。
创建main函数,调用Store合约,
touch store_main.go
下面的例子先部署合约,在部署过程中设置的Store.sol
合约中有一个公开的名为version
的全局变量,这种公开的成员将自动创建getter
函数,然后调用Version()
来获取version的值。
写入智能合约需要我们用私钥来对交易事务进行签名,我们创建的智能合约有一个名为SetItem
的外部方法,它接受soliditybytes32
类型的两个参数(key,value)。 这意味着在Go文件中需要传递一个长度为32个字节的字节数组。
package main
import (
"fmt"
"log"
"encoding/hex"
"github.com/FISCO-BCOS/go-sdk/client"
"github.com/FISCO-BCOS/go-sdk/conf"
"github.com/FISCO-BCOS/go-sdk/store"
)
func main() {
privateKey, _ := hex.DecodeString("145e247e170ba3afd6ae97e88f00dbc976c2345d511b0f6713355d19d8b80b58")
config := &conf.Config{IsSMCrypto: false, GroupID: "group0", PrivateKey: privateKey, NodeURL: "127.0.0.1:20200"}
client, err := client.Dial(config)
if err != nil {
log.Fatal(err)
}
input := "Store deployment 1.0"
address, receipt, instance, err := store.DeployStore(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 := store.NewStore(contractAddress, client)
// if err != nil {
// log.Fatal(err)
// }
fmt.Println("================================")
storeSession := &store.StoreSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()}
version, err := storeSession.Version()
if err != nil {
log.Fatal(err)
}
fmt.Println("version :", version) // "Store deployment 1.0"
// contract write interface demo
fmt.Println("================================")
key := [32]byte{}
value := [32]byte{}
copy(key[:], []byte("foo"))
copy(value[:], []byte("bar"))
_, receipt, err = storeSession.SetItem(key, value)
if err != nil {
log.Fatal(err)
}
fmt.Printf("transaction hash of receipt: %s\n", receipt.GetTransactionHash())
// read the result
result, err := storeSession.Items(key)
if err != nil {
log.Fatal(err)
}
fmt.Println("get item: " + string(result[:])) // "bar"
}