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文件,然后把相应的通道名称和相应的path和url改成自己文件所对应的位置即可。我先给出官方给的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) { // 实现链码查询逻辑 }
教程就到这了,请文明转载,注明出处。