Fabric项目结构

用户通过浏览器访问项目的Goweb服务,service通过SDK调用链码查询或更新数据,链码将结果返回给service,Goweb服务将结果展示给用户
一、配置应用参数
应用程序需要很多参数,特别是Fabric组件的通信地址。 现在把所有内容放入新的配置文件中(Fabric SDK Go配置和自定义参数)。
$ cd $GOPATH/src/zhq/bill
$ vim config.yaml
将下面内容拷贝到config.yaml中,文件中的路径替换为自己的项目路径
name: "bill-network"
# Describe what the target network is/does.
description: "The network which will host my first blockchain"
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
version: 2
# The client section used by GO SDK.
client:
# Which organization does this application instance belong to? The value must be the name of an org
organization: Org1
logging:
level: info
# Global configuration for peer, event service and orderer timeouts
peer:
timeout:
connection: 3s
queryResponse: 45s
executeTxResponse: 30s
eventService:
timeout:
connection: 3s
registrationResponse: 3s
orderer:
timeout:
connection: 3s
response: 5s
# Root of the MSP directories with keys and certs. The Membership Service Providers is component that aims to offer an abstraction of a membership operation architecture.
#组织结构路径
cryptoconfig:
path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config"
# Some SDKs support pluggable KV stores, the properties under "credentialStore" are implementation specific
credentialStore:
path: "/tmp/bill-kvs"
# [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations requiring a key store. PKCS#11 based implementations does not.
cryptoStore:
path: "/tmp/bill-msp"
# BCCSP config for the client. Used by GO SDK. It's the Blockchain Cryptographic Service Provider.
# It offers the implementation of cryptographic standards and algorithms.
#设置加密方式为软件密,sha256
BCCSP:
security:
enabled: true
default:
provider: "SW"
hashAlgorithm: "SHA2"
softVerify: true
ephemeral: false
level: 256
tlsCerts:
systemCertPool: false
# [Optional]. But most apps would have this section so that channel objects can be constructed based on the content below.
# If one of your application is creating channels, you might not use this
channels:
mychannel:
orderers:
- orderer.example.com
# Network entity which maintains a ledger and runs chaincode containers in order to perform operations to the ledger. Peers are owned and maintained by members.
peers:
peer0.org1.example.com:
# [Optional]. will this peer be sent transaction proposals for endorsement? The peer must
# have the chaincode installed. The app can also use this property to decide which peers
# to send the chaincode install request. Default: true
endorsingPeer: true
# [Optional]. will this peer be sent query proposals? The peer must have the chaincode
# installed. The app can also use this property to decide which peers to send the
# chaincode install request. Default: true
chaincodeQuery: true
# [Optional]. will this peer be sent query proposals that do not require chaincodes, like
# queryBlock(), queryTransaction(), etc. Default: true
ledgerQuery: true
# [Optional]. will this peer be the target of the SDK's listener registration? All peers can
# produce events but the app typically only needs to connect to one to listen to events.
# Default: true
eventSource: true
peer1.org1.example.com:
# List of participating organizations in this network
organizations:
Org1:
mspid: Org1MSP
cryptoPath: "peerOrganizations/org1.example.com/users/{userName}@org1.example.com/msp"
peers:
- peer0.org1.example.com
- peer1.org1.example.com
certificateAuthorities:
- ca.org1.example.com
# List of orderers to send transaction and channel create/update requests to.
# The orderers consent on the order of transactions in a block to be committed to the ledger. For the time being only one orderer is needed.
orderers:
orderer.example.com:
url: grpcs://localhost:7050
grpcOptions:
ssl-target-name-override: orderer.example.com
grpc-max-send-message-length: 15
tlsCACerts:
path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem"
# List of peers to send various requests to, including endorsement, query and event listener registration.
peers:
peer0.org1.example.com:
# this URL is used to send endorsement and query requests
url: grpcs://localhost:7051
# this URL is used to connect the EventHub and registering event listeners
eventUrl: grpcs://localhost:7053
# These parameters should be set in coordination with the keepalive policy on the server
grpcOptions:
ssl-target-name-override: peer0.org1.example.com
grpc.http2.keepalive_time: 15
tlsCACerts:
path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem"
peer1.org1.example.com:
url: grpcs://localhost:8051
eventUrl: grpcs://localhost:8053
grpcOptions:
ssl-target-name-override: peer1.org1.example.com
grpc.http2.keepalive_time: 15
tlsCACerts:
# Certificate location absolute path
path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem"
# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows certificate management to be done via REST APIs.
certificateAuthorities:
ca.org1.example.com:
url: https://localhost:7054
# the properties specified under this object are passed to the 'http' client verbatim when making the request to the Fabric-CA server
httpOptions:
verify: false
registrar:
enrollId: admin
enrollSecret: adminpw
caName: ca.org1.example.com
二、初始化SDK
在这个阶段,我们只初始化一个客户端,它将与 peer,CA 和 orderer进行通信。 还创建了一个新通道, 并将Peer节点加入到此通道中
goLand新建项目bill,新建Blockchain目录,新建startInit.go文件
在startInit.go文件中创建FabricSetup结构体,保存sdk配置
type FabricSetup struct {
//应用配置文件路径
ConfigFile string
//通道ID
ChannelID string
//sdk是否已初始化过,若已初始化,不再做初始化操作
Initialized bool
//通道配置文件路径
ChannelConfig string
//组织管理员账户名
OrgAdmin string
//组织名
OrgName string
//ResourceMgmtClient 使用'github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient'包下的结构体,不要搞错
Admin resmgmtclient.ResourceMgmtClient
sdk *fabsdk.FabricSDK
}
初始化sdk
接下来要做的是创建通道,回忆手动启动一个网络时,创建通道前需要一些配置文件,这些文件现在已经准备好了,接下来是:
进入
CLI容器->创建通道->加入通道
以前都是通过命令行实现,现在通过代码实现:
func (setup *FabricSetup) Initialize() error {
fmt.Println("开始初始化。。。")
if setup.Initialized {
return errors.New("sdk已经初始化")
}
//使用指定的配置文件创建SDK
sdk, err := fabsdk.New(config.FromFile(setup.ConfigFile))
if err != nil {
return fmt.Errorf("创建SDK失败:%s", err.Error())
}
setup.sdk = sdk
//根据指定的具有特权的用户(admin)创建用于管理通道的客户端API
chMgmtClient, err := setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin), fabsdk.WithOrg(setup.OrgName)).ChannelMgmt()
//chMgmtClient, err := setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin), fabsdk.WithOrg(setup.OrgName)).ChannelMgmt()
if err != nil {
return fmt.Errorf("SDK添加管理用户失败:%s", err.Error())
}
//获取客户端的会话用户
session, err := setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin), fabsdk.WithOrg(setup.OrgName)).Session()
if err != nil {
return fmt.Errorf("获取会话用户失败:%s,%s:%s\n", setup.OrgName, setup.OrgAdmin, err.Error())
}
orgAdminUser := session
//指定用于创建或更新通道的参数
req := chmgmtclient.SaveChannelRequest{
ChannelID:setup.ChannelID,
ChannelConfig:setup.ChannelConfig,
SigningIdentity:orgAdminUser,
}
//使用指定参数创建或更新通道
err = chMgmtClient.SaveChannel(req)
if err != nil {
return fmt.Errorf("创建通道失败:%s\n",err.Error())
}
//创建或更新通过会有延迟,主线程等5秒
time.Sleep(time.Second * 5)
//创建一个用于管理系统资源的饿客户端API
setup.Admin,err = setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin)).ResourceMgmt()
if err != nil {
return fmt.Errorf("创建资源管理客户端失败:%s\n",err.Error())
}
//将peer加入通道
if err = setup.Admin.JoinChannel(setup.ChannelID); err != nil {
return fmt.Errorf("peer加入通道失败:%s\n",err.Error())
}
fmt.Println("初始化成功")
setup.Initialized = true
return nil
}
测试
在工程目录下新建main.go文件
package main
import (
"os"
"fmt"
"zhq/bill/Blockchain"
)
func main() {
setup := Blockchain.FabricSetup{
//组织内管理员用户
OrgAdmin: "Admin",
//组织ID
OrgName: "Org1",
//通道ID
ChannelID: "mychannel",
//应用配置文件路径
ConfigFile: "config.yaml",
//通道配置文件路径
ChannelConfig: os.Getenv("GOPATH") + "/src/zhq/bill/fixtures/artifacts/channel.tx",
}
err := setup.Initialize()
if err != nil {
fmt.Println(err)
}
}
指定了环境的GOPATH,用来编译链码
在开始编译之前,最后一件事是使用一个vendor目录来包含我们所有的依赖关系。 在我们的GOPATH中,我们有Fabric SDK Go和其他项目。 当尝试编译应用程序时,Golang会在GOPATH中搜索依赖项,但首先会检查项目中是否存在vendor文件夹。 如果依赖性得到满足,那么Golang就不会去看GOPATH或GOROOT。 这在使用几个不同版本的依赖关系时非常有用(可能会发生一些冲突,比如在例子中有多个BCCSP定义,通过使用像dep这样的工具来处理这些依赖关系在vendor目录中。
当您安装SDK依赖关系时,DEP会自动安装。 如果不是这种情况,您可以阅读以下说明安装它: dep安装
创建一个名为Gopkg.toml的文件并将其复制到里面:
$ vim Gopkg.toml
[[constraint]]
name = "github.com/hyperledger/fabric"
revision = "014d6befcf67f3787bb3d67ff34e1a98dc6aec5f"
[[constraint]]
name = "github.com/hyperledger/fabric-sdk-go"
revision = "614551a752802488988921a730b172dada7def1d"
这是dep一个限制,以便在 vendor 中指定希望SDK转到特定版本。
保存该文件,然后执行此命令将vendor目录与项目的依赖关系同步(这可能需要一段时间):
$ dep ensure
提醒:dep ensure由于时间久,执行一次后即可,在后面的Makefile中可注释@dep ensure命令。
编译应用程序
$ go build
一段时间后,一个名为 bill的新二进制文件将出现在项目的根目录下。 尝试像这样启动二进制文件:
$ ./bill
./bill命令执行失败
此时,它将无法工作,因为没有可以与SDK进行通信的网络。 须先启动网络,然后再次启动应用程序:
$ cd fixtures
$ docker-compose up -d
$ cd ..
$ ./bill

注意 :需要看到“初始化成功”。 如果没有看到则说明出现问题。 有> 启动完了,别忘了
docker-compose down关闭po
现在只用本地网络初始化SDK。 在下一步中,将与链码进行交互。
清理和Makefile
Fabric SDK生成一些文件,如证书,二进制文件和临时文件。 关闭网络不会完全清理环境,当需要重新启动时,这些文件将被重复使用以避免构建过程。 对于开发,可以快速测试,但对于真正的测试,需要清理所有内容并从头开始。
如何清理环境
-
关闭你的网络:
cd $GOPATH/src/zhq/bill/fixtures && docker-compose down -
删除证书存储(在配置文件中,
client.credentialStore中定义):rm -rf /tmp/bill-* -
删除一些不是由
docker-compose命令生成的docker容器和docker镜像:docker rm -f -v `docker ps -a --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null 和 docker rmi `docker images --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null
如何更有效率?
可以在一个步骤中自动完成所有这些任务。 构建和启动过程也可以自动化。 为此,将创建一个Makefile。 首先,确保 make 工具:
make --version
如果没有安装
make(Ubuntu):sudo apt install make
然后使用以下内容在项目的根目录下创建一个名为Makefile的文件:
$ cd $GOPATH/src/zhq/bill
$ vim Makefile
.PHONY: all dev clean build env-up env-down run
all: clean build env-up run
dev: build run
##### BUILD
build:
@echo "Build ..."
@dep ensure
@go build
@echo "Build done"
##### ENV
env-up:
@echo "Start environment ..."
@cd fixtures && docker-compose up --force-recreate -d
@echo "Sleep 15 seconds in order to let the environment setup correctly"
@sleep 15
@echo "Environment up"
env-down:
@echo "Stop environment ..."
@cd fixtures && docker-compose down
@echo "Environment down"
##### RUN
run:
@echo "Start app ..."
@./bill
##### CLEAN
clean: env-down
@echo "Clean up ..."
@rm -rf /tmp/bill-* bill
@docker rm -f -v `docker ps -a --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null || true
@docker rmi `docker images --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null || true
@echo "Clean up done"
现在完成任务:
- 整个环境将被清理干净,
- go程序将被编译,
- 之后将部署网络
- 最后该应用程序将启动并运行。
要使用它,请进入项目的根目录并使用make命令:
- 任务
all:make或make all - 任务
clean:清理一切并释放网络(make clean) - 任务
build:只需构建应用程序(make build) - 任务
env-up:只需建立网络(make env-up) - …


