本流程在test目錄下,其中用到的 solc-0.4.25 和 abigen 工具網上教程都比較詳細,就暫時不展開聊,今天就大概描述流程。
1.將目錄下的test.sol檔案編譯
pragma solidity ^0.4.25; import "./Table.sol"; contract test { string constant TABLE_NAME = "test2"; event insertEvent(string id, string title, uint iuser_id,uint ruser_id,int stauts); event updateEvent(string id, int stauts); constructor() public{ TableFactory tf = TableFactory(0x1001); tf.createTable(TABLE_NAME,"id","title,iuser_id,ruser_id,stauts,start_time,sign_time"); } function set(string id, string title, uint iuser_id,uint ruser_id,int stauts) public returns(int) { TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(TABLE_NAME); uint t = 0; Entry entry = table.newEntry(); entry.set("id",id); entry.set("title",title); entry.set("iuser_id",iuser_id); entry.set("ruser_id",ruser_id); entry.set("stauts",stauts); entry.set("start_time",now); entry.set("sign_time",t); int count = table.insert(id,entry); emit insertEvent(id,title,iuser_id,ruser_id,stauts); return count; } function update(string id,int stauts) public returns(int) { TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(TABLE_NAME); Condition condition = table.newCondition(); //condition.EQ("id",id); Entry entry = table.newEntry(); entry.set("stauts",stauts); if (stauts == 5){ entry.set("sign_time",now); } int count = table.update(id,entry,condition); emit updateEvent(id,stauts); return count; } function get(string id) public view returns (string,uint,uint,int,uint,uint) { TableFactory tf = TableFactory(0x1001); Table table = tf.openTable(TABLE_NAME); Condition condition = table.newCondition(); //condition.EQ("id",id); Entries entries = table.select(id,condition); if(entries.size() == 0){ return("", 0, 0, 0, 0, 0); } uint iuser_id; uint ruser_id; int stauts; iuser_id = entries.get(0).getUInt("iuser_id"); ruser_id = entries.get(0).getUInt("ruser_id"); stauts = entries.get(0).getInt("stauts"); return (entries.get(0).getString("title"), iuser_id, ruser_id, stauts,entries.get(0).getUInt("start_time"), entries.get(0).getUInt("sign_time")); } }
由於引用了Table.sol,所以還要將Table.sol放到目錄下。
pragma solidity ^0.4.24; contract TableFactory { function openTable(string) public view returns (Table); //open table function createTable(string, string, string) public returns (int256); //create table } //select condition contract Condition { function EQ(string, int256) public view; function EQ(string, string) public view; function EQ(string, address) public view; function NE(string, int256) public view; function NE(string, string) public view; function GT(string, int256) public view; function GE(string, int256) public view; function LT(string, int256) public view; function LE(string, int256) public view; function limit(int256) public view; function limit(int256, int256) public view; } //one record contract Entry { function getInt(string) public view returns (int256); function getUInt(string) public view returns (uint256); function getAddress(string) public view returns (address); function getBytes64(string) public view returns (bytes1[64]); function getBytes32(string) public view returns (bytes32); function getString(string) public view returns (string); function set(string, int256) public; function set(string, uint256) public; function set(string, string) public; function set(string, address) public; } //record sets contract Entries { function get(int256) public view returns (Entry); function size() public view returns (int256); } //Table main contract contract Table { function select(string, Condition) public view returns (Entries); function insert(string, Entry) public returns (int256); function update(string, Entry, Condition) public returns (int256); function remove(string, Condition) public returns (int256); function newEntry() public view returns (Entry); function newCondition() public view returns (Condition); } contract KVTableFactory { function openTable(string) public view returns (KVTable); function createTable(string, string, string) public returns (int256); } //KVTable per permiary key has only one Entry contract KVTable { function get(string) public view returns (bool, Entry); function set(string, Entry) public returns (int256); function newEntry() public view returns (Entry); }
然後執行命令:
./solc-0.4.25 --bin --abi -o ./ ./test.sol
結果如下:
2.abigen生成go檔案
./abigen --bin ./test.bin --abi ./test.abi --pkg test --type test --out ./test.go
結果如下:
3.複製節點的SDK檔案
將上面的sdk資料夾,直接複製到test目錄下
4.使用get_account.sh指令碼生成賬戶私鑰
get_account.sh
該指令碼在FISCO的console中,可以直接複製下來執行
./get_account.sh
執行完畢,生成一個目錄,裡面有我們需要的賬戶私鑰檔案(這個賬戶私鑰檔案(*.pem),可以重複使用),將它複製到test目錄下 。
5.配置config.toml
可以複製go-sdk裡的config.toml
也可以直接新建一個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 # [[Network.Connection]] # NodeURL="127.0.0.1:20200" # GroupID=2 [Account] # only support PEM format for now KeyFile="./accounts/0x2b4c58c9b6bb9165931c9956f96d69723bb92754.pem" [Chain] ChainID=1 SMCrypto=false [log] Path="./"
將config.toml的KeyFile修改為上一步獲得的pem檔案的名字,然後其他的NodeURL和GroupID等,根據自己需要進行修改。
6.使用介面
在test目錄下新建一個cmd目錄,編寫一個main.go來呼叫鏈碼
package main import ( "math/big" "fmt" "log" "test" "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") //讀取config.toml檔案 if err != nil { log.Fatal(err) } config := &configs[0] client, err := client.Dial(config) //載入配置檔案,生成client進行相關鏈操作 if err != nil { log.Fatal(err) } contractAddress := common.HexToAddress("0xac05ff0709f443db85f7cd524e142e1778a8e426") // 這裡請放入剛剛部署的合約地址,注意,是你自己的機子部署的地址 instance, err := test.NewTest(contractAddress, client) //根據地址和client生成test合約物件 if err != nil { log.Fatal(err) } testSession := &test.TestSession{Contract: instance, CallOpts: *client.GetCallOpts(), TransactOpts: *client.GetTransactOpts()} a := big.NewInt(7) b := big.NewInt(8) c := big.NewInt(0) _,tx,receipt,err := testSession.Set("5","gosdk_title",a,b,c) 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是一樣,只是存在不同的地方而已 title,iuser_id,ruser_id,stauts,start_time,sign_time,err := testSession.Get("5") if err != nil{ log.Fatal(err) } fmt.Printf("title: %s\niuser_id: %d\nruser_id: %d\nstauts: %d\nstart_time: %d\nsign_time: %d\n",title,iuser_id,ruser_id,stauts,start_time,sign_time) }
在執行這個main.go之前應該先部署鏈碼,但是由於筆者是先在webase上編寫test.sol部署後,才進行go-sdk的配置的,所以這裡就不重複部署了。
go mod init
go mod tidy
go run ./cmd/main.go
結果如下: