美文网首页Fabric区块链
Fabric Go SDK 开发

Fabric Go SDK 开发

作者: kamiSDY | 来源:发表于2018-06-14 15:10 被阅读748次

    下载与构建Fabric Go SDK

    首先,自从官方获取fabric-sdk-go的源码,有两种方式:

    • Go get
      go get -u github.com/hyperledger/fabric-sdk-go
    • Git clone
      git clone https://github.com/hyperledger/fabric-sdk-go.git

    需要注意的是,如果使用git,最好保持go的安装路径。因为如果想进行频繁修改或者debug,直接使用GOPATH的目录结构会很有用,安装也比较方便。

    然后,直接根据需求进行编译即可。如果只是想安装依赖,并在sample引用。则可以到项目下执行安装命令。

    # In the Fabric SDK Go directory
    cd $GOPATH/src/github.com/hyperledger/fabric-sdk-go/
    
    # Optional - Automatically install Go tools used by test suite
    make depend-install
    
    可能会遇到的问题
    • Coverage 安装失败
    • 该组件主要用来检测单元测试覆盖率报告的。
      可能在使用go get的时候会报错:
    go get github.com/axw/gocov/...
    go get github.com/AlekSi/gocov-xml
    

    错误:

    go get -v github.com/axw/gocov/...
    Fetching https://golang.org/x/tools/cover?go-get=1
    https fetch failed: Get https://golang.org/x/tools/cover?go-get=1: dial tcp 216.
    239.37.1:443: connectex: A connection attempt failed because the connected party
    did not properly respond after a period of time, or established connection fail
    ed because connected host has failed to respond.
    package golang.org/x/tools/cover: unrecognized import path "golang.org/x/tools/c
    over" (https fetch: Get https://golang.org/x/tools/cover?go-get=1: dial tcp 216.
    239.37.1:443: connectex: A connection attempt failed because the connected party
    did not properly respond after a period of time, or established connection fail
    ed because connected host has failed to respond.)
    

    解决方案:
    在GOPATH的目录下,按照目录结构创建文件夹,然后手动git克隆项目,直接在执行go get或者直接安装即可。

    mkdir -p $GOPATH/src/golang.org/x
    cd $GOPATH/src/golang.org/x
    git clone https://github.com/golang/net.git
    git clone https://github.com/golang/tools.git
    
    • sync.Map找不到
      如果在build的时候发现如下错误:
    # github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/greylist
    ../../go/src/github.com/hyperledger/fabric-sdk-go/pkg/client/common/discovery/greylist/greylist.go:26: undefined: sync.Map
    # github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache
    ../../go/src/github.com/hyperledger/fabric-sdk-go/pkg/util/concurrent/lazycache/lazycache.go:46: undefined: sync.Map
    

    发现这个包时Go1.9的feature。所以必须升级。我的版本是1.8.1。
    然后删除了/usr/local/go的路径,重新解压新的go放进去。然后出现错误:

    bash: /usr/local/go/bin/go: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
    

    发现下错了版本,换成64位的就OK了。

    sample

    如果安装成功,就会发现在GOPATH目录的bin中有很多依赖的组件已经安装成功了。
    Fabric Go SDK开发主要有两个注意点:Fabric网络配置和代码编写。

    首先,修改配置文件。这里我们直接参考在官方代码中的end2end项目。
    配置文件位于$GOPATH/src/github.com/hyperledger/fabric-sdk-go/test/fixtures/config中,我们选用config_test.yaml作为参考。
    具体的源码直接大家在项目里找到就行,这里简单说下几个注意的:

    • 目前go-sdk的doc非常少,也没有API开发手册之类的。test里的example大多都是直接用配置文件进行init的。但是源码中和一些单元测试中有直接通过opt参数进行配置的。大家自己选择。
    • 路径中我用了$HOME,一直说找不到user,debug了一下发现creds的map是空的。换成直接的目录就好了。所以,特别注意配置文件中证书或者cred的路径。
    • 出现错误:failed to create channel context: failed to get client context to create channel client: user not found。翻了下源码和其他配置文件,发现在配置文件中的organisations下需要配置User的列表。
    organizations:
      org1:
        mspid: org1.org
        cryptoPath:  "peer\\msp"
        peers:
          - peer0
        users:
          Admin:
            cert:
              pem: |
                -----BEGIN CERTIFICATE----
                -----END CERTIFICATE-----
    

    同时在翻看源码的关于初始化过程中,发现了一个关于证书命名的细节。在pkg/msp/certfileuserstore.go中,调用load方法,然后其中调用storeKeyFromUserIdentifier方法。其获取的cert文件名(默认)格式是:key.ID + "@" + key.MSPID + "-cert.pem"

    • 配置了channel之后,有一个子配置项orderers被注释掉了。如果不把orderer配置上,其默认会去channel中取orderer的地址。如果你的网络访问Orderer不是orderer的内部地址(在fabric网路中使用的),比如说nginx的映射地址。那么就会访问不到。所以这个地方最好把orderer配置上,然后在后面orderers的配置项中详细配置指定的orderer。

    然后,简单的代码例子:

    package main
    
    import (
        "encoding/binary"
        "fmt"
        "time"
    
        "github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
        "github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
        "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/core"
        "github.com/hyperledger/fabric-sdk-go/pkg/core/config"
        "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
    )
    
    const (
        channelID      = "default"
        orgName        = "bcs06071508"
        orgAdmin       = "Admin"
        ordererOrgName = "bcs06071508"
        ccID           = "obcs-example02"
    )
    
    // ExampleCC query and transaction arguments
    var queryArgs = [][]byte{[]byte("query"), []byte("b")}
    var txArgs = [][]byte{[]byte("move"), []byte("a"), []byte("b"), []byte("1")}
    
    func setupAndRun(configOpt core.ConfigProvider, sdkOpts ...fabsdk.Option) {
        //Init the sdk config
        sdk, err := fabsdk.New(configOpt, sdkOpts...)
        if err != nil {
            fmt.Println("Failed to create new SDK: %s", err)
        }
        defer sdk.Close()
        // ************ setup complete ************** //
    
        //prepare channel client context using client context
        clientChannelContext := sdk.ChannelContext(channelID, fabsdk.WithUser("Admin"), fabsdk.WithOrg(orgName))
    
        // Channel client is used to query and execute transactions (Org1 is default org)
        client, err := channel.New(clientChannelContext)
    
        if err != nil {
            fmt.Println("Failed to create new channel client: %s", err)
        }
    
        value := queryCC(client)
        fmt.Println("value is d%", int64(binary.BigEndian.Uint64(value)))
    
        eventID := "test([a-zA-Z]+)"
    
        // Register chaincode event (pass in channel which receives event details when the event is complete)
        reg, notifier, err := client.RegisterChaincodeEvent(ccID, eventID)
        if err != nil {
            fmt.Println("Failed to register cc event: %s", err)
        }
        defer client.UnregisterChaincodeEvent(reg)
    
        // Move funds
        executeCC(client)
    
        select {
        case ccEvent := <-notifier:
            fmt.Println("Received CC event: %#v\n", ccEvent)
        case <-time.After(time.Second * 20):
            fmt.Println("Did NOT receive CC event for eventId(%s)\n", eventID)
        }
    }
    
    func executeCC(client *channel.Client) {
        _, err := client.Execute(channel.Request{ChaincodeID: ccID, Fcn: "invoke", Args: txArgs},
            channel.WithRetry(retry.DefaultChannelOpts))
        if err != nil {
            fmt.Println("Failed to move funds: %s", err)
        }
    }
    
    func queryCC(client *channel.Client) []byte {
        response, err := client.Query(channel.Request{ChaincodeID: ccID, Fcn: "invoke", Args: queryArgs},
            channel.WithRetry(retry.DefaultChannelOpts))
        if err != nil {
            fmt.Println("Failed to query funds: %s", err)
        }
        fmt.Println(response)
    
        return response.Payload
    }
    
    func main() {
        configPath := "./config.yaml"
        //End to End testing
        setupAndRun(config.FromFile(configPath))
    }
    

    核心步骤就是三步:

    1. 初始化SDK对象。
    2. 创建需要的channelContext或者clientContext
    3. 调用相关接口。

    简单说几个文件:

    • pkg/fab/channel/transactor.go: 从channel中获取orderer信息,给orderer发送相关tx。
    • pkg/client/channel/chclient.go:创建channel的client,执行query或者invoke(execute)
    • pkg/fab/endpointconfig.go: 根据配置文件,初始化channel,peer和orderer。
    • pkg/client/channel/invoke/txnhandler.go: endorseHandler,创建和发送Tx。
    • pkg/fab/txn/proposal.go: proposal相关操作,创爱,签名,发送。
    • pkg/fab/peer/peer.go:peer的endpoint相关属性和方法实现
    • pkg/fab/orderer/orderer.go: orderer的相关相关属性和方法实现
    • pkg/fab/peer/peerendorser.go: endorse相关属性和方法实现
    • pkg/fab/txn/txn.go: 交易相关操作(orderer),调用grpc方法

    参考链接

    相关文章

      网友评论

      • 饶江金:请问如果没有ca 节点 配置文件应该怎么弄啊,难道直接去掉就行了吗
      • 逍遥子_:你好,我在执行make depend-install安装依赖的时候,报错:make: *** No rule to make target `depend-install'. Stop. 请问您遇到过么
        487e304f740c:兄弟 你这错是咋解决的呢
      • NPCXU:作者你好 我能看一下你的config.yaml的完整内容吗 里边有些配置不太明白
        kamiSDY:@NPCXU 是的,老实讲,本身SDK的支持GO这块做的没有Node和java那么丰富,以及一些doc之类的也不是很全。写东西都靠摸索。
        NPCXU:@kamiSDY 多谢回复 昨天啃了一天chainhero里面的例子 配置方面差不多理解了 主要是用go的sdk太不方便了 许多依赖都被墙了 在国外服务器上跑一点问题没有
        kamiSDY:@NPCXU 你可以把你不清楚的地方贴出来。我帮你看看。我的其实就是官方test的yaml
      • 逍遥子_:是执行类似:
        docker-compose -f config_test.yaml up -d
        这种类似的命令,将服务起来么
      • 逍遥子_:楼主你好,我是刚入门。你的sample里,go-sdk的网络是如何安装的,以及链码是如何安装的,这个能大致说下么,不是太懂。
        逍遥子_:@kamiSDY 大神,如何使用SDK,有时间也开个分享贴啊。go sdk的介绍实在太少了
        逍遥子_:@kamiSDY 万分感谢,已赞赏,金额不多,聊表心意。
        kamiSDY:我是用的类似`https://github.com/hyperledger/fabric-sdk-node/blob/release-1.1/test/fixtures/docker-compose.yaml`这个配置文件起来的。用的就是docker-compose -f filename up -d, 如果有参数就写在前民就行了。然后链码安装有几种方式。用sdk的话,GO我在之后有时间就更新一下。或者可以看下node sdk的使用方法。再或者可以使用peer cli进行安装。这个官方doc上也有教程。

      本文标题:Fabric Go SDK 开发

      本文链接:https://www.haomeiwen.com/subject/idsyeftx.html