一、入门:使用Fabric-SDK-Go开发第一个Fabric应用

List:

- Fabric的版本是v2.5.9

- go的版本是1.22.4

Content:

文章重点是4和5部分,也是能跑通第一个应用的关键。

1.将官方的测试网络跑通,根据官方的教程即可,一直执行到:查询运行在 peer0.org2.example.com asset-transfer (basic)  链码,出现了查询成功的结果。

使用Fabric的测试网络 — hyperledger-fabricdocs master 文档

说一下,很多教程都说把测试网络的network关闭并清理数据,其实完全没有必要,数据清理后看不到什么效果,按照这个教程来就行。

2.在linux中创建一个go项目,创建的位置不影响

1.mkdir myFirstFabric
2.code myFirstFabric或者cd myFirstFabric
3.在vscode中新建main.go或者vim main.go,再wq!保存退出
4.go mod init myfirstfabric 初始化项目

Tips:你的应用程序是通过fabric-sdk-go创建一个客户端,加上相关配置文件,再通过智能合约的function来与fabric账本连接交互的,由于前边已经按照1把合约部署好了,所以你只要把fabric-sdk-go和相关配置搞好就可以了。下图是官方给的交互图。

3.准备配置文件(很简单)。在myFirstFabric的项目中创建一个config文件夹(与main.go同一级)或者"mkdir config",再将fabric-sample/test-network下的organizations文件夹复制到config中,目录如下:

4.重点来了:在config文件夹下创建配置文件config.yaml。编写配置文件比较繁琐,不过如果你是按照1所说的流程下来的话,可以直接复制这个config.yaml文件,然后把相应的通道名称和相应的pathurl改成自己文件所对应的位置即可。我先给出官方给的config.yaml模板:fabric-sdk-go/pkg/core/config/testdata/template/config.yaml at v1.0.0 · hyperledger/fabric-sdk-go · GitHub

下面是我自己的配置文件config.yaml,也是通过官方样例修改的,这里要细心一点儿。

#
# Copyright SecureKey Technologies Inc. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
#


#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: 1.0.0

#
# The client section used by GO SDK.
#
client:

  organization: org1

  logging:
    level: info

  # Root of the MSP directories with keys and certs.
  cryptoconfig:
    path: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations

  # Some SDKs support pluggable KV stores, the properties under "credentialStore"
  # are implementation specific

  # [Optional] BCCSP config for the client. Used by GO SDK.
  BCCSP:
    security:
     enabled: true
     default:
      provider: "SW"
     hashAlgorithm: "SHA2"
     softVerify: true
     level: 256

  tlsCerts:
    # [Optional]. Use system certificate pool when connecting to peers, orderers (for negotiating TLS) Default: false
    systemCertPool: true

    # [Optional]. Client key and cert for TLS handshake with peers and orderers
    client:
      key:
        path: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/client.key
      cert:
        path: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/tls/client.crt

channels:
  # multi-org test channel
  channel1:

    # anchor peers only for the bootstrap config is required, other org's peers will be discovered
    peers:
      peer0.org1.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

      peer0.org2.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

    policies:
      queryChannelConfig:
        minResponses: 1
        maxTargets: 1
        retryOpts:
          attempts: 5
          initialBackoff: 500ms
          maxBackoff: 5s
          backoffFactor: 2.0


#
# list of participating organizations in this network
#
organizations:
  org1:
    mspid: Org1MSP

    # This org's MSP store (absolute path or relative to client.cryptoconfig)
    cryptoPath: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp


    peers:
      - peer0.org1.example.com

  org2:
    mspid: Org2MSP

    # This org's MSP store (absolute path or relative to client.cryptoconfig)
    cryptoPath: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp


    peers:
      - peer0.org2.example.com


#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
#
peers:
  # defining bootstrap peers only
  peer0.org1.example.com:
    # [Optional] Default: Infer from hostname
#    url: peer0.org1.example.com:7051
    url: peer0.org1.example.com:7051

    grpcOptions:
      ssl-target-name-override: peer0.org1.example.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false

    tlsCACerts:
      path: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem

  peer0.org2.example.com:
#    url: peer0.org2.example.com:8051
    url: peer0.org2.example.com:9051

    grpcOptions:
      ssl-target-name-override: peer0.org2.example.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false

    tlsCACerts:
      path: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem

#
# List of orderers to send transaction and channel create/update requests to. For the time
# being only one orderer is needed. If more than one is defined, which one get used by the
# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers.
#
orderers:
  # needed to fetch the ordrerer config for create channel
  orderer.example.com:
    # [Optional] Default: Infer from hostname
#    url: orderer.example.com:7050
    url: orderer.example.com:7050

    grpcOptions:
      ssl-target-name-override: orderer.example.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false

    tlsCACerts:
      path: /root/go/src/github.com/myGoFabric/jxslExplorer/config/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem


# EntityMatchers enable substitution of network hostnames with static configurations
 # so that properties can be mapped. Regex can be used for this purpose
# UrlSubstitutionExp can be empty which means the same network hostname will be used
# UrlSubstitutionExp can be given same as mapped peer url, so that mapped peer url can be used
# UrlSubstitutionExp can have golang regex matchers like ${1}.local.example.${2}:${3} for pattern
 # like peer0.org1.example.com:1234 which converts peer0.org1.example.com to peer0.org1.local.example.com:1234
# sslTargetOverrideUrlSubstitutionExp follow in the same lines as
 # SubstitutionExp for the fields gprcOptions.ssl-target-name-override respectively
# In any case mappedHost's config will be used, so mapped host cannot be empty, if entityMatchers are used
entityMatchers:
  peer:
    # the below matcher will allow dynamic discovery to use the anchor peer (peer0.org1.example.com)
    # as a template for all org1 discovered peers config
    - pattern: (\w+).org1.example.com:(\d+)
      urlSubstitutionExp: ${1}.org1.example.com:${2}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org1.example.com
      mappedHost: peer0.org1.example.com

    - pattern: (\w+).org2.example.com:(\d+)
      urlSubstitutionExp: ${1}.org2.example.com:${2}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org2.example.com
      mappedHost: peer0.org2.example.com

看着很多其实不难,entityMathcers部分我就是按照官方给的,没有修改,我修改的地方主要就是通道名称、对应path部分。我这里用的通道名称是channel1,如果是按照1的流程应该是mychannel,把channel1改成mychannel即可

5.好了,最难的一步已经解决了。下面把这段代码复制到main.go中就可以啦,需要注意:

代码中通道名称我写的是channel1,我用的合约就是官方案例(步骤1)的合约,名称是basic,合约中可以使用智能合约中的“ReadAsset”函数和对应的账户名称(合约中是:asset1,asset2...)就可以查询到相关的账户信息了;也可以调用智能合约中的“GetAllAssets”方法获取整个账本的信息。

废话不说,注意修改channel的名称,下面是代码,代码都有注释,这里不在解释:

package main

import (
	"fmt"

	"github.com/hyperledger/fabric-sdk-go/pkg/client/channel"
	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)

func main() {
	// 创建SDK实例
	sdk, err := fabsdk.New(config.FromFile("/root/go/src/github.com/myGoFabric/jxslExplorer/config/config.yaml"))
	if err != nil {
		fmt.Printf("Failed to create SDK: %v\n", err)
		return
	}
	defer sdk.Close()

	// 创建通道客户端实例
	// clientContext := sdk.ChannelContext("channel1", fabsdk.WithUser("Admin"))
	clientContext := sdk.ChannelContext("channel1", fabsdk.WithUser("Admin"))
	client, err := channel.New(clientContext)

	if err != nil {
		fmt.Printf("Failed to create channel client: %v\n", err)
		return
	}

	// 根据交易ID查询链上交易
	response, err := client.Query(channel.Request{ChaincodeID: "basic", Fcn: "ReadAsset", Args: [][]byte{[]byte("asset1")}})
	// 获取整个的账本的数据
	// response, err := client.Query(channel.Request{ChaincodeID: "basic", Fcn: "GetAllAssets", Args: [][]byte{[]byte("GetAllAssets")}})

	if err != nil {
		fmt.Printf("Failed to query transaction: %v\n", err)
		return
	}

	fmt.Printf("Query transaction response: %s\n", string(response.Payload))
}

6.把相应的go包拉下来

go get -u github.com/hyperledger/fabric-sdk-go

go mod tidy

go mod vendor

然后如果还缺什么什么包,就go get -u xxx就可以了

7.到这里就完成98%了,下面是修改你的hosts了,其实很简单,在hosts文件下加入解析的地址就可以了。

vi /etc/hosts

在文件中写入:

127.0.0.1 orderer.example.com
127.0.0.1 peer0.org1.example.com
127.0.0.1 peer0.org2.example.com

然后Esc,:wq!保存退出即可

8.最后啦,编译go文件,并执行文件就可以了

go build

./myfirstfabric

你会看到下面类似的结果,就说明成功了:

Query transaction response: {"AppraisedValue":300,"Color":"blue","ID":"asset1","Owner":"Tomoko","Size":5}

入门之后就自己再拓展功能吧!

可能会出现的问题:

问题1:

Failed to create channel client: event service creation failed: could not get chConfig cache reference: QueryBlockConfig failed: no channel peers configured for channel [channel1]

解决方法:这个报错表明在创建通道客户端时遇到了问题,原因是没有为名为channel1的通道配置任何对等节点。需要确保在配置文件中正确指定了所需通道的对等节点信息。

问题2:

Failed to create channel client: event service creation failed: could not get chConfig cache reference: QueryBlockConfig failed: QueryBlockConfig failed: queryChaincode failed: Transaction processing for endorser [peer0.org1.example.com:7051]: Endorser Client Status Code: (2) CONNECTION_FAILED. Description: dialing connection on target [peer0.org1.example.com:7051]: connection is in TRANSIENT_FAILURE
 [fabsdk/util] 2024/08/21 14:49:26 UTC - lazyref.(*Reference).refreshValue -> WARN Error - initializer returned error: QueryBlockConfig failed: QueryBlockConfig failed: query

解决方法:重新执行步骤7

问题3:

Failed to query transaction: Multiple errors occurred: - Transaction processing for endorser [peer0.org2.example.com:9051]: Endorser Client Status Code: (2) CONNECTION_FAILED. Description: dialing connection on target [peer0.org2.example.com:9051]: connection is in TRANSIENT_FAILURE - Transaction processing for endorser [peer0.org1.example.com:7051]: Chaincode status Code: (500) UNKNOWN. Description: Function queryTransaction not found in contract SmartContract

解决方法:检查你的合约中使用的查询函数名称。应该会有下面一个类似的函数名

func (s *SmartContract) queryTransaction(ctx contractapi.TransactionContextInterface, transactionID string) (string, error) { // 实现链码查询逻辑 }

教程就到这了,请文明转载,注明出处。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值