Code Monkey home page Code Monkey logo

go-sdk's Introduction

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. 开启CGO支持go env -w CGO_ENABLED=1

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

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
go.mod
go.sum
hello_main.go

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" hello_main.go

go-sdk's People

Contributors

bxq2011hust avatar chinamonkeyking avatar dyy8888 avatar jc0803kevin avatar joy-shuang avatar kasperliu avatar keyon11 avatar leowei1234567 avatar maggiengwu avatar rookielinlucy666 avatar skyhuihui avatar subowei avatar subway2023 avatar sulenn avatar suutaku avatar wheatli avatar yekai1003 avatar yinghuochongfly avatar zhanglin9833 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-sdk's Issues

go mod tidy时出现了模糊导入的问题

go1.16.9 darwin/amd64

报错如下:
imports
github.com/FISCO-BCOS/go-sdk/abi imports
github.com/ethereum/go-ethereum/crypto imports
github.com/btcsuite/btcd/btcec/v2/ecdsa tested by
github.com/btcsuite/btcd/btcec/v2/ecdsa.test imports
github.com/btcsuite/btcd/chaincfg/chainhash: ambiguous import: found package github.com/btcsuite/btcd/chaincfg/chainhash in multiple modules:
github.com/btcsuite/btcd v0.21.0-beta (/Users/coyee/go/pkg/mod/github.com/btcsuite/[email protected]/chaincfg/chainhash)
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 (/Users/coyee/go/pkg/mod/github.com/btcsuite/btcd/chaincfg/[email protected])

之前使用旧版本sdk时未出现过,请问是我本地环境有问题吗?这个问题怎么解决?

同时监听多个合约的多个事件问题

type EventLogParams struct {
FromBlock string json:"fromBlock"
ToBlock string json:"toBlock"
Addresses []string json:"addresses"
Topics []string json:"topics"
GroupID string json:"groupID"
FilterID string json:"filterID"
}
请问如何对一条链在一个连接下订阅多个合约的多个合约事件,看参数合约地址和topics是支持的,但是实际操作并没有得到推送,请问这个场景 现在的go-sdk支持吗?如果支持 请问那个版本支持?

console crash

Darwin Station 18.7.0 Darwin Kernel Version 18.7.0: Tue Aug 20 16:57:14 PDT 2019; root:xnu-4903.271.2~2/RELEASE_X86_64 x86_64

All console commands crash except help >.<

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x45d0a9f]

goroutine 1 [running]:
github.com/FISCO-BCOS/go-sdk/client.(*Client).GetPeers(...)
	/Users/john/Desktop/bcos/go-sdk/client/go_client.go:366
github.com/FISCO-BCOS/go-sdk/cmd/commandline.glob..func25(0x4c5bda0, 0x4c92c28, 0x0, 0x0)
	/Users/john/Desktop/bcos/go-sdk/cmd/commandline/commands.go:207 +0x2f
github.com/spf13/cobra.(*Command).execute(0x4c5bda0, 0x4c92c28, 0x0, 0x0, 0x4c5bda0, 0x4c92c28)
	/Users/john/go-workspace/pkg/mod/github.com/spf13/[email protected]/command.go:846 +0x29d
github.com/spf13/cobra.(*Command).ExecuteC(0x4c57960, 0x4044b6a, 0x4c11be0, 0xc000000180)
	/Users/john/go-workspace/pkg/mod/github.com/spf13/[email protected]/command.go:950 +0x349
github.com/spf13/cobra.(*Command).Execute(...)
	/Users/john/go-workspace/pkg/mod/github.com/spf13/[email protected]/command.go:887
github.com/FISCO-BCOS/go-sdk/cmd/commandline.Execute()
	/Users/john/Desktop/bcos/go-sdk/cmd/commandline/root.go:66 +0x31
main.main()
	/Users/john/Desktop/bcos/go-sdk/cmd/console.go:8 +0x20

It's something wrong of my environment ?
I want to make sure if your guys have tested.
thanks.

部署合约问题

store.main.go 编译成功,执行一直停在那,没输出结果。会是什么原因导致的呢?控制台编译成功,和fisco bcos 交互有信息输出。

go-sdk使用channel调用sendTransaction时,receipt.Notify阻塞

go-sdk/conn/channel.go
----------------func (hc *channelSession) sendTransaction(ctx context.Context, msg interface{}) ([]byte, error)
----------------------------<-receipt.Notify

版本:fisco-bcos v2.3.0 solidity0.4.25 golang 1.13.6
在receipt.Notify堵塞无响应。去节点查看日志,发现节点已经异步发送,日志如下:

info|2020-08-03 22:06:55.675796|[g:1][BLOCKVERIFIER][executeBlock]Execute block takes,time(ms)=1,txNum=1,num=1,blockHash=c44617219d7b9da04ed42362f6a774b5016e628e2c257a9afeb32542d66e4815,stateRoot=66850592882819b898bac7c70adf9fee4f8d70e5dc867741b072f0604ca3f6bc,dbHash=66850592882819b898bac7c70adf9fee4f8d70e5dc867741b072f0604ca3f6bc,transactionRoot=55ba3f1a6f92b18f2f126e634bbce97d6776b440ec24c0ded5ef676fb8fda403,receiptRoot=97b6e5a0a8706801a194e39e64554357378ddcf4781af14f1868e57de46e5158,transactionReceipts=d30b8f78d6b7c13c7246c38b48f0868765b9d134
info|2020-08-03 22:06:55.675834|[g:1][CONSENSUS][PBFT],totalCost=1
info|2020-08-03 22:06:55.676562|[g:1]Re-generate prepare_requests since block has been executed, time = 1596463615675 , block_hash: c4461721...
info|2020-08-03 22:06:55.676579|[g:1][CONSENSUS][PBFT]handlePrepareMsg: add prepare cache and broadcastSignReq,reqNum=1,hash=c4461721...,nodeIdx=2,addPrepareTime=1,myNode=7c022d12...
info|2020-08-03 22:06:55.676864|[g:1][CONSENSUS][PBFT]handlePrepareMsg Succ,Timecost=2.642,INFO=handlePrepareMsg,reqIdx=0,view=140,reqNum=1,curNum=0,consNum=1,curView=140,fromIp=127.0.0.1:30302,hash=e9c50483...,nodeIdx=2,myNode=7c022d12...,curChangeCycle=2
info|2020-08-03 22:06:55.677395|[g:1][CONSENSUS][PBFT]handleSignMsg Succ,Timecost=0.504,INFO=handleSignMsg,num=1,curNum=0,GenIdx=1,Sview=140,view=140,fromIdx=1,fromNode=592273a4...,fromIp=127.0.0.1:30301,hash=c4461721...,nodeIdx=2,myNode=7c022d12...
info|2020-08-03 22:06:55.678909|[g:1][CONSENSUS][PBFT]checkAndCommit, SignReq enough,number=1,sigSize=3,hash=c4461721...,nodeIdx=2,myNode=7c022d12...
info|2020-08-03 22:06:55.678926|[g:1][CONSENSUS][PBFT]checkAndCommit: backup/updateCommittedPrepare,reqNum=1,hash=e9c50483...,nodeIdx=2,myNode=7c022d12...
info|2020-08-03 22:06:55.679051|[g:1][CONSENSUS][PBFT]checkAndCommit: broadcastCommitReq,prepareHeight=1,hash=c4461721...,nodeIdx=2,myNode=7c022d12...
info|2020-08-03 22:06:55.679483|[g:1][CONSENSUS][PBFT]checkAndCommit: broadcastCommitReq before checkandsave,time = =1
info|2020-08-03 22:06:55.679494|[g:1][CONSENSUS][PBFT]checkAndSave finished ,time = =0
info|2020-08-03 22:06:55.679500|[g:1][CONSENSUS][PBFT]handleSignMsg Succ,Timecost=0.951,INFO=handleSignMsg,num=1,curNum=0,GenIdx=0,Sview=140,view=140,fromIdx=0,fromNode=0e824a87...,fromIp=127.0.0.1:30302,hash=c4461721...,nodeIdx=2,myNode=7c022d12...
info|2020-08-03 22:06:55.680787|[g:1][CONSENSUS][PBFT]checkAndSave finished ,time = =0
info|2020-08-03 22:06:55.680801|[g:1][CONSENSUS][PBFT]handleCommitMsg Succ,INFO=handleCommitMsg,reqNum=1,curNum=0,GenIdx=0,Cview=140,view=140,fromIdx=0,fromNode=0e824a87...,fromIp=127.0.0.1:30302,hash=c4461721...,nodeIdx=2,myNode=7c022d12...,Timecost=0.479
info|2020-08-03 22:06:55.684994|[g:1][CONSENSUS][PBFT]checkAndSave: CommitReq enough,prepareHeight=1,commitSize=3,hash=c4461721...,nodeIdx=2,myNode=7c022d12...
info|2020-08-03 22:06:55.685247|[g:1][BLOCKCHAIN][WriteTxOnCommit]Write tx to block time record,openTableTimeCost=0,constructVectorTimeCost=0,insertTableTimeCost=0,encodeNonceVectorTimeCost=0,insertNonceVectorTimeCost=0,totalTimeCost=0
info|2020-08-03 22:06:55.685359|[g:1][g:1][STORAGE][CachedStorage]CachedStorage commit: 8 num: 1
info|2020-08-03 22:06:55.687334|[g:1][STORAGE]Start commit block: 1 to backend storage
info|2020-08-03 22:06:55.687863|[g:1][STORAGE][RocksDB][Commit]Write to db,encodeTimeCost=0,writeDBTimeCost=0,totalTimeCost=0
info|2020-08-03 22:06:55.687883|[g:1][STORAGE][g:1]

Commit block: 1 to backend storage finished, current cached block: 1
Flush elapsed time: 0.0006s

info|2020-08-03 22:06:55.688039|[g:1][STORAGE]Submited block task: 1, current syncd block: 1
info|2020-08-03 22:06:55.688085|[g:1][STORAGE][Commit]Commit db time record,getDataTimeCost=0,commitTimeCost=3,clearTimeCost=0,totalTimeCost=3
info|2020-08-03 22:06:55.688103|[g:1][BLOCKCHAIN][Commit]Commit block time record(write),writeHash2BlockTimeCost=0,writeNumber2HashTimeCost=0,writeNumberTimeCost=0,writeTotalTransactionCountTimeCost=0,writeTxToBlockTimeCost=0,dbCommitTimeCost=3,updateBlockNumberTimeCost=0
info|2020-08-03 22:06:55.688342|[g:1][SYNC][id:7c022d12...][sendSyncStatusByTree],blockNumber=1,currentHash=c4461721...,selectedNodes=2
info|2020-08-03 22:06:55.688376|[g:1][SYNC][id:7c022d12...][Status]Send current status when maintainBlocks,number=1,genesisHash=6ac93b39...,currentHash=c4461721...,peer=0e824a87...
info|2020-08-03 22:06:55.688403|[g:1][SYNC][id:7c022d12...][Status]Send current status when maintainBlocks,number=1,genesisHash=6ac93b39...,currentHash=c4461721...,peer=592273a4...
info|2020-08-03 22:06:55.688529|[g:1] [SYNC][id:7c022d12...][Status]Receive status from peer,peerNodeId=0e824a87...,peerBlockNumber=1,genesisHash=6ac93b39...,latestHash=c4461721...
info|2020-08-03 22:06:55.688552|[g:1] [SYNC][id:7c022d12...][Status]Receive status from peer,peerNodeId=592273a4...,peerBlockNumber=1,genesisHash=6ac93b39...,latestHash=c4461721...
info|2020-08-03 22:06:55.688565|[g:1]Push block notify: 1-1
**

  • info|2020-08-03 22:06:55.688653|[g:1][CHANNEL]blockNotify Push channel message success,topic=_block_notify_1,seq=00000000,session=219.228.148.201:58628

**
info|2020-08-03 22:06:55.688666|[g:1][BLOCKCHAIN][Commit]Commit block time record,beforeTimeCost=0,writeBlockTimeCost=3,addBlockCacheTimeCost=0,noteReadyTimeCost=0,totalTimeCost=3
info|2020-08-03 22:06:55.689183|[g:1][CONSENSUS][PBFT]CommitBlock Succ,prepareHeight=1,reqIdx=0,hash=c4461721...,nodeIdx=2,myNode=7c022d12...,genSigTimeCost=1,commitBlockTimeCost=3,dropTxsTimeCost=1,noteSealingTimeCost=0,totalTimeCost=5
info|2020-08-03 22:06:55.689199|[g:1][CONSENSUS]delCache,hash=c4461721...
info|2020-08-03 22:06:55.689211|[g:1][CONSENSUS][PBFT]checkAndSave finished ,time = =5
info|2020-08-03 22:06:55.689216|[g:1][CONSENSUS][PBFT]handleCommitMsg Succ,INFO=handleCommitMsg,reqNum=1,curNum=0,GenIdx=1,Cview=140,view=140,fromIdx=1,fromNode=592273a4...,fromIp=127.0.0.1:30301,hash=c4461721...,nodeIdx=2,myNode=7c022d12...,Timecost=4.671
info|2020-08-03 22:06:55.689303|[g:1][CONSENSUS][ConsensusEngine]resetConfig: updateMaxBlockTransactions,txCountLimit=500
info|2020-08-03 22:06:55.689322|[g:1][CONSENSUS][SEALER]increase maxNoTimeoutTx,maxNoTimeoutTx=1
info|2020-08-03 22:06:55.689328|[g:1][CONSENSUS]delCache,hash=c4461721...
info|2020-08-03 22:06:55.689333|[g:1][CONSENSUS][PBFT]^^^^^^^^Report,num=1,sealerIdx=0,hash=c4461721...,next=2,tx=1,nodeIdx=2

监听合约事件功能被禁止

在使用BCOS部署合约之后,有采用合约抛出事件的方式。
但是调用由Solidity生成的GO代码的Watch***Event()函数会阻塞住。在查看go-sdk 源代码之后,看到这一部分

func initClient(conn ServerCodec, idgen func() ID, services *serviceRegistry) *Connection {
	_, isHTTP := conn.(*httpConn)
	c := &Connection{
		idgen:       idgen,
		isHTTP:      isHTTP,
		services:    services,
		writeConn:   conn,
		close:       make(chan struct{}),
		closing:     make(chan struct{}),
		didClose:    make(chan struct{}),
		reconnected: make(chan ServerCodec),
		readOp:      make(chan readOp),
		readErr:     make(chan error),
		reqInit:     make(chan *requestOp),
		reqSent:     make(chan error, 1),
		reqTimeout:  make(chan *requestOp),
	}
	// FIXME: remove substration releated code
	// if !isHTTP {
	// 	go c.dispatch(conn)
	// }
	return c
}

既然兼容以太坊EVM,为什么不支持事件监听呢?

将部署的合约地址以 文件 的形式进行保存后 将其读出 在调用合约的获取相关函数时 出现0x1a的 被调用的合约地址不存在

#```go
package models

import (
"bufio"
// "errors"
#"io"
"log"
"math/big"
"os"
manage "proj3/manage"

"github.com/FISCO-BCOS/go-sdk/client"
"github.com/FISCO-BCOS/go-sdk/conf"
"github.com/FISCO-BCOS/go-sdk/core/types"
"github.com/ethereum/go-ethereum/common"
// import store

)

type ContractServiceType struct {
// ConfigPath string
Client *client.Client
Instance *manage.Manage
Session *manage.ManageSession
isCreated bool
ContractAddr common.Address
}

// 判断所给路径文件/文件夹是否存在
func Exists(path string) bool {
_, err := os.Stat(path) //os.Stat获取文件信息
if err != nil {
if os.IsExist(err) {
return true
}
return false
}
return true
}

/*
函数名:WriteString2File
描述:将数据以字符串的形式写入到文件中。
*/
func WriteString2File(data string) {
//创建文件,将部署的合约写进取
fliePath := "./config.txt"
file, err := os.OpenFile(fliePath, os.O_WRONLY|os.O_CREATE, 0666)
if err != nil {
log.Fatal("file open error:", err)
}
defer file.Close()
write := bufio.NewWriter(file)
_, err = write.WriteString(data)
if err != nil {
log.Fatal("write addr error:", err)
}
//刷新缓冲区
write.Flush()
}

/*
函数名:ReadStringFromFile
描述:从之前写入的文件中读取部署的合约地址。
*/
func ReadStringFromFile() (contractAddr []byte, ret bool) {
filePath := "./config.txt"
file, err := os.Open(filePath)
if err != nil {
log.Fatal("file open error:", err)
return nil, false
}
defer file.Close()

var chunk []byte
buf := make([]byte, 1024)
//以字节的形式进行读取。
for {
	//从file读取到buff中。
	n, err := file.Read(buf)
	if err != nil && err != io.EOF {
		log.Fatal("读取文件到缓冲区失败!")
		file.Close()
		return nil, false
	}

	if n == 0 {
		break
	}

	//读取到最终的缓冲区中。
	chunk = append(chunk, buf[:n]...)
}
return chunk, true

}

/*
函数名:CreateConnectSession
描述:基于配置文件与区块链节点创建会话,连接成功后,会将部署的合约地址进行文件写入操作。
*/
func (server *ContractServiceType) CreateConnectSession(config string) {

if config == "" {
	return
}

//1.解析配置
configs, err := conf.ParseConfigFile(config)
if err != nil {
	log.Fatal("parse config file error:", err)
	return
}
//2.连接远程
server.Client, err = client.Dial(&configs[0])
if err != nil {
	log.Fatal("connect error:", err)
	return
}
if Exists("./config.txt") { //之前已经对其进行部署.

	//读取出之前部署的合约地址,将其与新的client进行绑定。
	contractAddrByte, ret := ReadStringFromFile()
	if !ret {
		log.Fatal("while read config from file error")
		return
	}
	server.ContractAddr = common.BytesToAddress(contractAddrByte)
	server.Instance, err = manage.NewManage(server.ContractAddr, server.Client)

	if err != nil {
		log.Fatal("create manange new instance error:", err)
		return
	}

} else {
	//3.部署合约
	server.ContractAddr, _, server.Instance, err = manage.DeployManage(server.Client.GetTransactOpts(), server.Client)
	if err != nil {
		log.Fatal("deploy contract error:", err)
		return
	}
	//3.1将合约地址写入文件。
	WriteString2File(server.ContractAddr.String())
}

//4.连接合约
server.Session = &manage.ManageSession{Contract: server.Instance, CallOpts: *server.Client.GetCallOpts(), TransactOpts: *server.Client.GetTransactOpts()}
server.isCreated = true

}

/*
函数名:NewVaccine
描述:产生一个新的疫苗。
*/
func (server *ContractServiceType) NewVaccine(name string, id *big.Int, addr string, validity *big.Int) (*types.Transaction, *types.Receipt, error) {

if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
	// log.Fatal("instance is null then constructor it again please.")
	// return nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
	server.CreateConnectSession("./conf/config.toml")
}
//ame string, id *big.Int, addr string, range1 *big.Int
return server.Session.CreateVaccine(name, id, addr, validity)

}

/*
函数名:GetVaccineById
描述:基于id获取疫苗信息。
*/
func (server *ContractServiceType) GetVaccineById(id *big.Int) (string, *big.Int, string, *big.Int, *big.Int, error) {
if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
// log.Fatal("instance is null then constructor it again please.")
// return "", nil, "", nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
server.CreateConnectSession("./conf/config.toml")
}

return server.Session.GetVaccineInfo(id)

}

/*
函数名:GetVaccineCnt
描述:获取工厂疫苗的数量。
*/
func (server *ContractServiceType) GetVaccineCnt() (*big.Int, error) {
if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
// log.Fatal("instance is null then constructor it again please.")
// return nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
server.CreateConnectSession("./conf/config.toml")
}

return server.Session.GetVaccineCount()

}

/*
函数名:GetVaccineWithAll
描述:获取所有疫苗信息。
*/
func (server *ContractServiceType) GetVaccineWithAll() ([]string, []*big.Int, []string, []*big.Int, []*big.Int, error) {
if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
// log.Fatal("instance is null then constructor it again please.")
// return nil, nil, nil, nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
server.CreateConnectSession("./conf/config.toml")
}

return server.Session.GetVaccineAll()

}

/*
函数名:GetVaccineWithAll
描述:获取疫苗的追踪链信息。
*/
func (server *ContractServiceType) GetTransitOfVaccineAll(id *big.Int) ([]string, []*big.Int, []string, error) {
if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
// log.Fatal("instance is null then constructor it again please.")
// return nil, nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
server.CreateConnectSession("./conf/config.toml")
}
return server.Session.GetVaccineTransit(id)
}

/*
函数名:AddTransitForVaccineById
描述:为疫苗的行径添加到区块链。
*/
func (server *ContractServiceType) AddTransitForVaccineById(id *big.Int, addr string, time *big.Int, remark string) (*types.Transaction, *types.Receipt, error) {
if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
// log.Fatal("instance is null then constructor it again please.")
// return nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
server.CreateConnectSession("./conf/config.toml")
}
return server.Session.AddTransit(id, addr, time, remark)
}


首先,简要介绍一下这个代码。
它根据配置文件进行解析,并进行连接,然后会根据config.txt是否存在来决定之前是否已经存在一个合约。
如果是,我们就会进行合约地址的读取,这里的读取是采用了以 字节 的形式进行读取,然后到绑定时,通过```common.ByteToAddress()```进行转换;如果为否,那么我就进行合约的部署并对其地址进行 文件写入。

现在,我们假定一个前提,就是已经存在config.txt,然后进行地址的转换。
在进行疫苗的创建时,我们可以看到:合约地址为


关于断链之后,无法再次监听到事件

在监听调用事件后,一分钟左右没有再次监听调用事件,则会报错“channel Read error:EOF”,导致无法再次链接监听事件。希望解答并支持,谢谢!!!

abigen不兼容高版本go

当使用1.15及以上版本的go语言,生成abigen时,会报错如下:
undefined: utils.NewApp
undefined: utils.OriginCommandHelpTemplate
而使用1.14及以下版本go不会报错

go-sdk稳定版的问题

您好,请问下有计划go-sdk什么时候出稳定版么,可用于生产环境的,谢谢~

go-sdk部署合约异常

用go-sdk部署合约后,合约地址为全零,无法调用;但是利用console部署合约就一切正常,合约地址也是正常的,合约也可以正常调用。

重连后无法重连的问题

由于源码中关闭使用sync.Once,导致重连一次后无法继续重连,所以需要修改一下源码946行,增加hc.closeOnce = sync.Once{}
hc.c = con
hc.closed = make(chan interface{})
//增加1行
hc.closeOnce = sync.Once{}
hc.nodeInfo.Protocol = 1

关于合约调用问题

在合约调用时,所需要的为 TransactOpts 类型,文档中给出的例子为 CallOpts 类型,在 TransactOpts 类型中,存在 SignerFn 签名的 callback 函数,请问此处应该怎么去编码?

关于合约事件监听的问题

我是copy代码库中的example下的event示例代码,但是也是监听不到,
image

是不是和我的bcos版本有关系,bcos是2.8的版本,go-sdk是dev版本,

从配置文件读取合约时,可以进行数据上链。但读取的时候出现0x1a的问题。

package models

import (
	"bufio"
	// "errors"
	"io"
	"log"
	"math/big"
	"os"
	manage "proj3/manage"

	"github.com/FISCO-BCOS/go-sdk/client"
	"github.com/FISCO-BCOS/go-sdk/conf"
	"github.com/FISCO-BCOS/go-sdk/core/types"
	"github.com/ethereum/go-ethereum/common"
	// import store
)

type ContractServiceType struct {
	// ConfigPath   string
	Client       *client.Client
	Instance     *manage.Manage
	Session      *manage.ManageSession
	isCreated    bool
	ContractAddr common.Address
}

// 判断所给路径文件/文件夹是否存在
func Exists(path string) bool {
	_, err := os.Stat(path) //os.Stat获取文件信息
	if err != nil {
		if os.IsExist(err) {
			return true
		}
		return false
	}
	return true
}

/*
	函数名:WriteString2File
	描述:将数据以字符串的形式写入到文件中。
*/
func WriteString2File(data string) {
	//创建文件,将部署的合约写进取
	fliePath := "./config.txt"
	file, err := os.OpenFile(fliePath, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		log.Fatal("file open error:", err)
	}
	defer file.Close()
	write := bufio.NewWriter(file)
	_, err = write.WriteString(data)
	if err != nil {
		log.Fatal("write addr error:", err)
	}
	//刷新缓冲区
	write.Flush()
}

/*
	函数名:ReadStringFromFile
	描述:从之前写入的文件中读取部署的合约地址。
*/
func ReadStringFromFile() (contractAddr []byte, ret bool) {
	filePath := "./config.txt"
	file, err := os.Open(filePath)
	if err != nil {
		log.Fatal("file open error:", err)
		return nil, false
	}
	defer file.Close()

	var chunk []byte
	buf := make([]byte, 1024)
	//以字节的形式进行读取。
	for {
		//从file读取到buff中。
		n, err := file.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatal("读取文件到缓冲区失败!")
			file.Close()
			return nil, false
		}

		if n == 0 {
			break
		}

		//读取到最终的缓冲区中。
		chunk = append(chunk, buf[:n]...)
	}
	return chunk, true
}

/*
	函数名:CreateConnectSession
	描述:基于配置文件与区块链节点创建会话,连接成功后,会将部署的合约地址进行文件写入操作。
*/
func (server *ContractServiceType) CreateConnectSession(config string) {

	if config == "" {
		return
	}

	//1.解析配置
	configs, err := conf.ParseConfigFile(config)
	if err != nil {
		log.Fatal("parse config file error:", err)
		return
	}
	//2.连接远程
	server.Client, err = client.Dial(&configs[0])
	if err != nil {
		log.Fatal("connect error:", err)
		return
	}
	if Exists("./config.txt") { //之前已经对其进行部署.

		//读取出之前部署的合约地址,将其与新的client进行绑定。
		contractAddrByte, ret := ReadStringFromFile()
		if !ret {
			log.Fatal("while read config from file error")
			return
		}
		server.ContractAddr = common.BytesToAddress(contractAddrByte)
		server.Instance, err = manage.NewManage(server.ContractAddr, server.Client)

		if err != nil {
			log.Fatal("create manange new instance error:", err)
			return
		}

	} else {
		//3.部署合约
		server.ContractAddr, _, server.Instance, err = manage.DeployManage(server.Client.GetTransactOpts(), server.Client)
		if err != nil {
			log.Fatal("deploy contract error:", err)
			return
		}
		//3.1将合约地址写入文件。
		WriteString2File(server.ContractAddr.String())
	}

	//4.连接合约
	server.Session = &manage.ManageSession{Contract: server.Instance, CallOpts: *server.Client.GetCallOpts(), TransactOpts: *server.Client.GetTransactOpts()}
	server.isCreated = true
}

/*
	函数名:NewVaccine
	描述:产生一个新的疫苗。
*/
func (server *ContractServiceType) NewVaccine(name string, id *big.Int, addr string, validity *big.Int) (*types.Transaction, *types.Receipt, error) {

	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}
	//ame string, id *big.Int, addr string, range1 *big.Int
	return server.Session.CreateVaccine(name, id, addr, validity)
}

/*
	函数名:GetVaccineById
	描述:基于id获取疫苗信息。
*/
func (server *ContractServiceType) GetVaccineById(id *big.Int) (string, *big.Int, string, *big.Int, *big.Int, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return "", nil, "", nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}

	return server.Session.GetVaccineInfo(id)
}

/*
	函数名:GetVaccineCnt
	描述:获取工厂疫苗的数量。
*/
func (server *ContractServiceType) GetVaccineCnt() (*big.Int, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}

	return server.Session.GetVaccineCount()
}

/*
	函数名:GetVaccineWithAll
	描述:获取所有疫苗信息。
*/
func (server *ContractServiceType) GetVaccineWithAll() ([]string, []*big.Int, []string, []*big.Int, []*big.Int, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, nil, nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}

	return server.Session.GetVaccineAll()
}

/*
	函数名:GetVaccineWithAll
	描述:获取疫苗的追踪链信息。
*/
func (server *ContractServiceType) GetTransitOfVaccineAll(id *big.Int) ([]string, []*big.Int, []string, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}
	return server.Session.GetVaccineTransit(id)
}

/*
	函数名:AddTransitForVaccineById
	描述:为疫苗的行径添加到区块链。
*/
func (server *ContractServiceType) AddTransitForVaccineById(id *big.Int, addr string, time *big.Int, remark string) (*types.Transaction, *types.Receipt, error) {
	if server.Instance == nil || server.Client == nil || server.Session == nil || len(server.ContractAddr) == 0 {
		// log.Fatal("instance is null then constructor it again please.")
		// return nil, nil, errors.New("示例为空,是否存在没有为其进行合约部署。或者是client为空,没有正确的连接到区块链。Session为空,要确保有一个正确的连接。")
		server.CreateConnectSession("./conf/config.toml")
	}
	return server.Session.AddTransit(id, addr, time, remark)
}

首先,简要介绍一下这个代码。
它根据配置文件进行解析,并进行连接,然后会根据config.txt是否存在来决定之前是否已经存在一个合约。
如果是,我们就会进行合约地址的读取,这里的读取是采用了以 字节 的形式进行读取,然后到绑定时,通过common.ByteToAddress()进行转换;如果为否,那么我就进行合约的部署并对其地址进行 文件写入。

现在,我们假定一个前提,就是已经存在config.txt,然后进行地址的转换。
在进行疫苗的创建时,我们可以看到:合约地址为:b0b46170F5f0FEC54e38,它是可以正常创建的。但对其进行合约读取时,就出现了问题:call error of status 0x1a 官方的解释为:被调用的合约地址不存在。

效果见图片

getting
问题

定时间隔一秒调用GetBlockNumber出现阻塞情况

业务中需要使用定时并间隔一秒来获取当前最新高度,所以调用GetBlockNumber,发现运行一段时间大概24小时后 中日志
log.Info("in !!!!") 出现阻塞不能往下执行了。
具体代码:

func (this *FiscoManager) MonitorChain() {
	fetchBlockTicker := time.NewTicker(config.ETH_MONITOR_INTERVAL)
	for {
		select {
		case <-fetchBlockTicker.C:
			log.Info("in !!!!")
			currHeight, err := this.BlockNumber()
			log.Info("out !!!!")
			if err != nil {
				log.Fatalf("FiscoManager MonitorChain - failed to get current fisco height: %v", err)
				continue
			}
			height := uint64(currHeight)
			log.Debugf("FiscoManager - fiscobcos chain current height: %d", height)
			.....省略
		}
	}
}

func (this *FiscoManager) BlockNumber() (int64, error) {
	bn, err := this.client.GetBlockNumber(context.Background())
	if err != nil {
		return 0, fmt.Errorf("block number not found: %v", err)
	}
	str, err := strconv.Unquote(bytes2str(bn))
	if err != nil {
		return 0, fmt.Errorf("ParseInt: %v", err)
	}
	height, err := strconv.ParseInt(str, 0, 0)
	if err != nil {
		return 0, fmt.Errorf("ParseInt: %v", err)
	}
	return height, nil
}

SubscribeFilterLogs

确认一下,现在SubscribeFilterLogs和FilterLogs这两个接口能正常WORK吗,如果不能,怎么订阅evm的event消息

使用生成的.go文件无法获取事件

  • 链的版本是v2.4.1

  • sdk v1.0.0


使用生成的.go文件无法获取事件,是我这里用错了吗?如果错了有没有这块的使用样例?


solidity 事件代码

image


go 代码

image

abigen将文件转换成Go文件写接口没有生成解析返回值的代码

solidity(v0.4.25)中写函数的返回值似乎无法解析出来,读函数需要添加constant关键字才可以拿到返回值(view关键字没有尝试)
// SetIdDTrace is a paid mutator transaction binding the contract method 0xbbf74676. // // Solidity: function setIdDTrace(int256 _idA, int256 _idD) returns(int256) func (_Tls *TlsSession) SetIdDTrace(_idA *big.Int, _idD *big.Int) (*types.Transaction, *types.Receipt, error) { return _Tls.Contract.SetIdDTrace(&_Tls.TransactOpts, _idA, _idD) }

// GetId is a free data retrieval call binding the contract method 0xd4e2e579. // // Solidity: function get_id(string idStr) constant returns(int256) func (_Tls *TlsSession) GetId(idStr string) (*big.Int, error) { return _Tls.Contract.GetId(&_Tls.CallOpts, idStr) }
感觉可以改进一下?XD

目前支持区块监听么?

我是个新手,请问目前支持监听最新的区块接口么,如果没有如何实现,或者说给个思路?

部署合约时失败,返回错误码0x16

合约代码在WeBASE-front中是可以部署成功的

solidity

pragma solidity 0.6.10;

contract Material {
    address private _owner; 
    string private _name;  
    string private _memo; 
    uint private _createdAt;
    
    constructor(string memory materialName, string memory memo) public {
        _owner = msg.sender; 
        _name = materialName;
        _memo = memo; 
        _createdAt = now;
    }
    
    function getMaterialInfo() public view returns(address, string memory, string memory memo, uint){
        return (_owner, _name, _memo, _createdAt);
    }
} 

使用0.6.10版本的solc生成abi和bin文件

solc --abi --bin -o ./ Material.sol

使用abigen生成go文件

abigen --abi ./Material.abi --bin ./Material.bin --pkg material --out material.go

go代码

address, _, _, err := material.DeployMaterial(bcosClient.GetTransactOpts(), bcosClient, "string", "string")

err = nil
address = 0x0000000000000000000000000000000000000000

查看交易信息后,status为0x16

在WeBASE-Front中部署成功后,使用以下代码能够正常调用

instance, err := material.NewMaterial(common.HexToAddress(materialAddress), bcosClient)
if err != nil {
    return
}

_owner, materialName, memo, timestamp, err := instance.GetMaterialInfo(bcosClient.GetCallOpts())
if err != nil {
    return
}

关于 3.1.0 go sdk 测试方案

一.特性描述
3.0 sdk 测试
二.代码修改点
client abi cmd conn等
三.影响的功能范围
整个项目
四.测试项

使用console进行测试

rpc
根据合约地址,查询合约代码 ./console getCode 0x745d4de0cf93b7d1db8dd8892daf05ac745766ce
根据交易哈希获取交易回执 ./console getTransactionReceipt 0x3a4df5710d6f3c448a956e4fb2bf6b07ff6516df91496f9b6e30ff07de026441
根据交易哈希获取交易 ./console getTransactionByHash 0x3a4df5710d6f3c448a956e4fb2bf6b07ff6516df91496f9b6e30ff07de026441
获取群组列表详情 ./console getGroupInfoList
获取群组信息 ./console getGroupInfo
获取系统配置 ./console getSystemConfigByKey tx_count_limit
获取群组块高 ./console getBlockNumber
获取群组列表 ./console getGroupList
获取群组的节点信息 ./console getGroupNodeInfo nodeId
获取群组id ./console getGroupID
获取群组的网络连接信息 ./console getGroupPeers
获取当前区块高度下的交易总量 ./console getTotalTransactionCount
获取群组的区块同步状态 ./console getSyncStatus
获取交易池待打包的交易数量 ./console getPendingTxSize
根据块高获取区块 ./console getBlockByNumber 0
根据块高获取区块哈希 ./console getBlockHashByNumber 0
根据区块哈希获取区块 ./console getBlockByHash 0x30de4c9a7a4546fcf511cec8d3f71cf9c5cbb99a0d4fceca66ae3c737fca3d9e
获取节点的共识状态 ./console getConsensusStatus
获取pbftview值 ./console getPbftView
获取群组观察节点列表 ./console getObserverList
获取群组共识节点列表 ./console getSealerList

SystemConfigService
根据关键字设置区块链系统配置 ./console setSystemConfigByKey tx_count_limit 999

ConsensusService
将指定节点移出群组 ./console removeNode
将指定节点添加为共识节点 ./console addSealer
将指定节点添加为观察节点 ./console addObserver

KVTableService
创建用户表 ./console createTable tableName1 keyName valueName
向指定用户表中写入一条记录 ./console set tableName1 key1 value1
查询用户表指定记录 ./console get tableName1 key1

amop
example下有相关amop示例代码

eventlog
example下有相关eventlog示例代码

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.