环境:
Ubuntu :20.04.1
fisco-bcos: 3.11.0
go-sdk: v3.0.2
go 1.22.0
solidity 0.8.11
说明
根据官方的文档go-sdk使用 ,在我自己的环境中有些许差异, 所以整理一下步骤与大家分享,本次教程以用go-sdk部署一个helloworld合约为例子
下载go-sdk
在github上git clone
或许下载最新版的go-sdkmaster分支
下载完成后,进入go-sdk里面的v3目录,
执行go mod tidy
命令,把相关依赖包下载下来
编写合约
合约就以简单的helloworld为例子
// 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;
}
}
下载bcos-c-sdk动态库
使用go-sdk文件目录下的download_csdk_lib.sh
脚本文件
或者去github https://github.com/FISCO-BCOS/bcos-c-sdk/releases/tag/v3.6.0
下载libbcos-c-sdk.so文件
注意,使用脚本下载会默认下载到/usr/local/lib
目录下,但是坑就是这么来的,ubuntu系统执行的时候,扫描的动态库不是在这个目录下,所以需要自己找到该系统的默认动态库路径
export $LD_LIBRARY_PATH//使用此命令
结果
-bash: export: “/opt/ros/noetic/lib”: 不是有效的标识符
所以需要把libbcos-c-sdk.so复制到此/opt/ros/noetic/lib
目录下 其他linux系统可能也是不同的目录需自己用命令寻找
安装智能合约编译工具
在tools文件夹下有download_solc.sh
文件,指定solidity版本
bash ../tools/download_solc.sh -v 0.8.11
下载完成就有一个执行文件
安装合约转go语言编译工具abigen
在v3目录下执行
go build ./cmd/abigen
执行完后,会有一个abigen执行文件
开始部署智能合约
在v3目录下新建一个helloworld文件夹,并把abigen和solc-0.8.11,还有HelloWorld.sol复制进该文件夹
生成bin和abi文件
在helloworld文件夹下执行命令
./solc-0.8.11 --bin --abi -o ./ ./HelloWorld.sol
会生成HelloWorld.bin和HelloWorld.abi文件
生成go文件
此时利用abigen工具将HelloWorld.bin和HelloWorld.abi转换成HelloWorld.go
./abigen --bin ./HelloWorld.bin --abi ./HelloWorld.abi --pkg helloworld --type HelloWorld --out ./HelloWorld.go
这样相关业务go文件代码已经生成
编写部署合约
此时我们还需要编写一个部署HelloWorld合约的go文件
在hellowrold文件下新建一个cmd目录,在cmd目录创建一个main.go
下面代码与官方文档给的有所不同,在import代码块里有所改动
package main
import (
"context"
"encoding/hex"
"fmt"
"github.com/FISCO-BCOS/go-sdk/v3/helloworld"
"github.com/FISCO-BCOS/go-sdk/v3/types"
"log"
"github.com/FISCO-BCOS/go-sdk/v3/client"
)
func main() {
privateKey, _ := hex.DecodeString("145e247e170ba3afd6ae97e88f00dbc976c2345d511b0f6713355d19d8b80b58")
config := &client.Config{IsSMCrypto: false, GroupID: "group0",
PrivateKey: privateKey, Host: "127.0.0.1", Port: 20200, TLSCaFile: "./conf/ca.crt", TLSKeyFile: "./conf/sdk.key", TLSCertFile: "./conf/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 := helloworld.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 := helloworld.NewStore(contractAddress, client)
// if err != nil {
// log.Fatal(err)
// }
fmt.Println("================================")
helloSession := &helloworld.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() //调用合约Get方法
if err != nil {
fmt.Printf("helloworld.Get() failed: %v", err)
return
}
done := make(chan bool)
// 监听合约set事件
_, err = helloSession.WatchAllSetValue(nil, func(ret int, logs []types.Log) {
fmt.Printf("WatchAllSetValue receive status: %d, logs: %v\n", ret, logs)
setValue, err := helloSession.ParseSetValue(logs[0])
if err != nil {
fmt.Printf("helloworld.WatchAllSetValue() failed: %v", err)
panic(any(err))
}
fmt.Printf("receive setValue: %+v\n", *setValue)
done <- true
})
if err != nil {
fmt.Printf("helloworld.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("helloworld.Get() failed: %v", err)
return
}
fmt.Printf("Get: %s\n", ret)
<-done
}
证书拷贝
可以看到部署go文件还需要证书,我们需要把自己的链子的ca.crt
,sdk.crt
和sdk.key
找到,并且在v3目录下新建一个conf文件夹,将三个证书放入conf目录下【因为之后go run需要在v3目录下执行,读取文件需要根据相对路径读取】
执行代码
在v3
目录下执行
go run helloworld/cmd/main.go
执行成功结果
结论
相关环境配好了之后,以后写好合约代码,也可以根据此环境进行编译部署执行go文件了