需求分析

xx工具是一个全网资产探测引擎,其中一个功能是自动发现全网被挂马或者被篡改的网站并记录下来。现在欲将这些资产信息写到区块链上,通过链码实现增删改查的功能,并通过可视化界面进行操作和分类展示。

一条资产数据记录包含ip、port、label、domain、maindata等字段内容。系统最终需能够根据指定字段名或者时间段等过滤展示,因此区块链系统需要支持富查询,故stateDB选择couchDB

系统主要包由区块链系统、链码、网站后台、前端四部分构成。底层基于hyperledger fabric进行构建。

数据源由xx工具收集后经过数据清洗写入到文件中。后台读取文件内容后解析,调用链码写入区块链和couchDB;并通过调用链码实现根据时间段删除以及查询等功能。

资产数据每天采集一次,约10万条左右,数据量较大,因此写入区块链采用go routine实现。

环境搭建

节点拓扑图

image-20200531214035600

工具安装

项目中fabric的运行采用Docker的方式,因此需要安装Docker,docker-compose(用于同时启动多个Docker镜像,且可以共享同一个网络);另外fabric使用golang开发,并且SDK选择了fabric-sdk-go,因此需要安装go。

1.Docker

17.03.0-ce或以上版本,具体安装方式可以在网上找教程,此处以centOS为例

  • 卸载旧版本

    1
    2
    3
    4
    $ sudo yum remove docker \
    docker-common \
    docker-selinux \
    docker-engine
  • 安装依赖

    1
    2
    3
    $ sudo yum install -y yum-utils \
    device-mapper-persistent-data \
    lvm2
  • yum 软件源(否则会很慢)

1
2
3
$ sudo yum-config-manager \
--add-repo \
https://mirrors.ustc.edu.cn/docker-ce/linux/centos/docker-ce.repo
  • 安装Docker CE

    1
    2
    $ sudo yum makecache fast
    $ sudo yum install docker-ce
  • 启动Docker CE

    1
    2
    $ sudo systemctl enable docker
    $ sudo systemctl start docker
  • 建立Docker用户组和用户

    为了避免使用root用户,需要使用 docker 的用户加入 docker 用户组

    1
    2
    3
    $ sudo groupadd docker
    $ sudo usermod -aG docker $USER
    $ sudo service docker restart
  • 查看Docker版本和测试

    1
    2
    $ docker -v
    $ docker run hello-world

2.docker-compose

1.8或者以上版本

  • 安装

    1
    2
    $ sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose && \
    sudo chmod +x /usr/local/bin/docker-compose
  • 查看版本

    1
    $ docker-compose version

    其它系统安装方式:https://docs.docker.com/compose/install/

3.go

1.9.x或者以上版本,以go1.13为例

  • 下载

    sudo wget https://dl.google.com/go/go1.13.4.linux-amd64.tar.gz

  • 安装

    1
    2
    $ sudo tar -xvf go1.13.4.linux-amd64.tar.gz
    $ sudo mv go /usr/local
  • 设置环境变量

    环境变量需要设置的是GOROOTGOPATHPATH,GOROOT是安装Go软件包的位置,GOPATH是工作目录的位置,要设置全局环境变量就把下面代码写入/etc/profile或者/etc/bashrc,用户变量就写入~/.profile,或者~/.bashrc.

    1
    2
    3
    export GOROOT=/usr/local/go
    export GOPATH=$HOME/Projects/go
    export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

    这里要注意,go的很多包在下载的时候会很慢或失败,可以使用代理或者GOPROXY解决。

代码结构与片段

代码框架图

整个系统采用前后端分离模式,后端通过http接口与前端通信。前端代码不包含在该项目中。后端web采用gin框架。底层搭建fabric环境,通过fabric-sdk-go实现对区块链以及链码进行操作。

image-20200531212212447

fabric部署

1.公私钥和证书

配置文件为fixtures下的crypto-config.yaml,根据实际节点情况进行修改,修改好后执行命令:

1
./bin/cryptogen generate --config=./crypto-config.yaml

执行成功会生成crypto-config目录。

2.创世区块

该步骤需要配置文件configtx.yaml,该配置中指定了节点组织架构,访问策略等,需要特别说明是的区块的大小以及区块出块时间也在该配置文件中

1
2
$ mkdir artifacts
$ ./bin/configtxgen -profile OneOrgOrdererGenesis -outputBlock ./artifacts/genesis.block

3.生成通道

mychannel为通道id。

1
$ ./bin/configtxgen -profile OneOrgOrdererGenesis -outputCreateChannelTx ./artifacts/mychannel.tx -channelID mychannel

4.生成锚节点更新

1
./bin/configtxgen -profile OneOrgChannel -outputAnchorPeersUpdate ./artifacts/Org1MSPanchors.tx -channelID dbappchannel -asOrg Org1MSP

以上步骤1.2.3.4可通过执行fixtures下的start.sh脚本一件完成

运行节点

1.准备docker配置文件

配置fixtrues下的docker-compose.yaml文件,包含的服务有orderer.example.com、ca.org1.example.com、peer0.org1.example.com、peer1.org1.example.com和couchdb五个Docker。

配置时要特别注意ORDERER_GENERAL_LOCALMSPID,FABRIC_CA_SERVER_CA_KEYFILE,CORE_PEER_NETWORKID,CORE_PEER_LOCALMSPID等参数。另外要注意网络问题,特别是多节点部署时,通常后面启动报错是会有网络不通的问题,可通过docker network ls,docker inspect $network_name等命令查看网络问题。

2.启动docker

1
2
$ cd fixtures && docker-compose up --force-recreate -d
$ docker ps -a

image-20200531223615377

如果显示有节点Exited,可以用docker logs $containerID查看错误信息,根据具体错误信息排查。

3.停止docker

1
cd fixtures && docker-compose down

安装调用链码

1.命令行方式

  • 启动容器

    1
    $ docker exec -it cli bash
  • 创建Channel

    1
    $ peer channel create -o orderer.example.com:7050 -c mychannel -f ./mychannel.tx
  • Peer加入Channel

    1
    $ peer channel join -b mychannel.block
  • 安装智能合约

1
peer chaincode install -n mycc -p projectPath/chaincode/go/example02/cmd/ -v 1.0

这里链码使用的是fabric-sample的例子

  • 实例化智能合约

    区块初始化数据为a为100,b为200

    1
    $ peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer')"
  • 查询query

Peer上查询a,显示100

1
$ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
  • 调用invoke

    1
    peer chaincode invoke -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'

2.fabric-sdk方式

​ 若采用sdk调用链码,需要两个部分,一个是配置文件config.yaml,另一个是调用代码。

  • config.yaml

    配置文件在根目录下,配置时需注意channels,mspid参数要与前面的配置保持一致,否则会报错。

  • 代码部分

    代码部分需要使用依赖管理工具dep,在Gopkg.toml中指定fabric-sdk-go的版本,当然也可以用其它的包管理工具。

    1
    2
    3
    4
    5
    6
    ignored = ["github.com/sumapchain/chaincode"]

    [[constraint]]
    # Release v1.0.0-alpha4
    name = "github.com/hyperledger/fabric-sdk-go"
    revision = "a906355f73d060d7bf95874a9e90dc17589edbb3"

    代码实现在sdkInit目录下,start.go的init中指定了参数,该部分需要根据实际情况进行修改。sdk_setup.go实现了三个函数,初始化fabricSDK—SetupSDK(),创建通道并将指定的Peers加入—CreateChannel(),安装并实例化链码—InstallAndInstantiateCC()

  • 调用合约

    eduServide.go是对世界状态数据库进行增删改查的操作,通过一下方式进行调用链码,需要注意ExecuteQuery,新增或者删除操作,是需要发起交易写入区块链的,因此需要用Execute,若用Query,则操作无效,但不会报错。

    1
    2
    req := channel.Request{ChaincodeID: t.ChaincodeID, Fcn: "register", Args: [][]byte{[]byte(key), b}}
    respone, err := t.Client.Execute(req)
  • 富查询

    系统中较多涉及到富查询功能,在实现时通过构造查询语句queryString,将queryString作为参数传递给链码执行返回查询结果。对于富查询语句可参考https://docs.couchdb.org/en/latest/api/database/find.html#find-selectors和https://hyperledger-fabric.readthedocs.io/en/release-2.0/couchdb_tutorial.html#query-the-couchdb-state-database

  • 系统后台

    采用gin框架,基本没有什么问题,就是在数据上传时由于数据量大需要采用goroutine。

问题合集

概述

hyperledger fabric的配置是一个较为繁琐的过程,整个系统的开发过程中,遇到了各种问题,特别是在前期的环境搭建过程,到目前为止,对一些配置也没有完全仔细的研究过,对于改变网络架构的情况,应该还会遇到很多意想不到的问题。但在这个简单的项目开发过程中,学习到了很多,对fabric1.4有了更深的认识,以及对docker,go等有了更多的学习。

过程中遇到的问题,只记录了部分,在此记录一下,帮助有需要的朋友少走一点弯路。

  1. Unable to initialize the Fabric SDK: failed to create SDK: failed to initialize configuration: unable to load identity config: failed to initialize identity config from config backend: failed to create identity config from backends: failed to load all CA configs : failed to load server certs: open : no such file or directory

    解决办法:检查docker-compose.ymal配置文件,ca的部分是否有错误

  2. stub.DelState()执行不成功
    解决办法:要注意Invoke()和Query()的区别,调用的地方不能弄错,删除数据库操作需要Execute

  3. Chaincode installed
    Unable to install and instantiate the chaincode: failed to instantiate the chaincode: sending deploy transaction proposal failed: Transaction processing for endorser [localhost:7051]: Chaincode status Code: (500) UNKNOWN. Description: chaincode registration failed: container exited with 0

    解决办法:peer节点与其他节点之间的网络不通。查看docker-compose.yml文件中的配置,多个docker是不是在同一个网络

  4. 链码修改后不生效

    解决办法:重启服务前要删除创建链码生成的docker image,删除命令可以参考MakeFile文件

  5. 创建应用通道失败: create channel failed: create channel failed: SendEnvelope failed: calling orderer ‘localhost:7050’ failed: Orderer Server Status Code: (400) BAD_REQUEST. Description: error authorizing update: error validating DeltaSet: policy for [Group] /Channel/Application not satisfied: Failed to reach implicit threshold of 1 sub-policies, required 1 remaining

    解决办法:检查config.yaml文件中org中mspid是否和docker-compose.yaml以及configtx.yaml中一致。

  6. ca节点报错:Error: Failed to find private key for certificate in ‘/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem’: Could not find matching private key for SKI: Failed getting key for SKI [[139 23 134 41 187 180 28 134 172 114 144 24 14 8 90 144 229 235 246 159 157 108 197 75 176 236 120 190 227 196 237 254]]: Key with SKI 8b178629bbb41c86ac7290180e085a90e5ebf69f9d6cc54bb0ec78bee3c4edfe not found in /etc/hyperledger/fabric-ca-server/msp/keystore

    解决办法:重新生成证书后,docker-compose.yaml中ca的私钥FABRIC_CA_SERVER_CA_KEYFIL没有更新

  7. INFO 003 Endorser and orderer connections initialized
    Error: got unexpected status: BAD_REQUEST – error validating channel creation transaction for new channel ‘mychannel’, could not succesfully apply update to template configuration: error authorizing update: error validating DeltaSet: policy for [Group] /Channel/Application not satisfied: implicit policy evaluation failed - 0 sub-policies were satisfied, but this policy requires 1 of the ‘Admins’ sub-policies to be satisfied

解决办法:一种可能,fabric1.4.4版本出现这个报错,检查configtx.yaml文件,修改为下图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Capabilities:
# Channel capabilities apply to both the orderers and the peers and must be
# supported by both.
# Set the value of the capability to true to require it.
# Note that setting a later Channel version capability to true will also
# implicitly set prior Channel version capabilities to true. There is no need
# to set each version capability to true (prior version capabilities remain
# in this sample only to provide the list of valid values).
Channel: &ChannelCapabilities
# V1.4.3 for Channel is a catchall flag for behavior which has been
# determined to be desired for all orderers and peers running at the v1.4.3
# level, but which would be incompatible with orderers and peers from
# prior releases.
# Prior to enabling V1.4.3 channel capabilities, ensure that all
# orderers and peers on a channel are at v1.4.3 or later.
V1_4_3: true
# V1.3 for Channel enables the new non-backwards compatible
# features and fixes of fabric v1.3
V1_3: false
# V1.1 for Channel enables the new non-backwards compatible
# features and fixes of fabric v1.1
V1_1: false

# Orderer capabilities apply only to the orderers, and may be safely
# used with prior release peers.
# Set the value of the capability to true to require it.
# Note that setting a later Orderer version capability to true will also
# implicitly set prior Orderer version capabilities to true. There is no need
# to set each version capability to true (prior version capabilities remain
# in this sample only to provide the list of valid values).
Orderer: &OrdererCapabilities
# V1.4.2 for Orderer is a catchall flag for behavior which has been
# determined to be desired for all orderers running at the v1.4.2
# level, but which would be incompatible with orderers from prior releases.
# Prior to enabling V1.4.2 orderer capabilities, ensure that all
# orderers on a channel are at v1.4.2 or later.
V1_4_2: true
# V1.1 for Orderer enables the new non-backwards compatible
# features and fixes of fabric v1.1
V1_1: false

# Application capabilities apply only to the peer network, and may be safely
# used with prior release orderers.
# Set the value of the capability to true to require it.
# Note that setting a later Application version capability to true will also
# implicitly set prior Application version capabilities to true. There is no need
# to set each version capability to true (prior version capabilities remain
# in this sample only to provide the list of valid values).
Application: &ApplicationCapabilities
# V1.4.2 for Application enables the new non-backwards compatible
# features and fixes of fabric v1.4.2
V1_4_2: true
# V1.3 for Application enables the new non-backwards compatible
# features and fixes of fabric v1.3.
V1_3: false
# V1.2 for Application enables the new non-backwards compatible
# features and fixes of fabric v1.2 (note, this need not be set if
# later version capabilities are set)
V1_2: false
# V1.1 for Application enables the new non-backwards compatible
# features and fixes of fabric v1.1 (note, this need not be set if
# later version capabilities are set).
V1_1: false

另一种可能,检查代码ccPolicy := cauthdsl.SignedByAnyMember([]string{"Org1MSP"})Org1MSP部分是否正确(根据实际情况填写)

  1. gRPC Transport Status Code: (4) DeadlineExceeded. Description: context deadline exceeded

    解决方法:检查链码返回的数据是否超出grpc定义的最大限度

  2. Failed to get endorsing peers: error getting endorsers from channel response: no endorsement combination can be satisfied

    解决方法:查看channel文件capabilities的版本信息

    1
    ./bin/configtxgen -profile OneOrgChannel -inspectChannelCreateTx ./artifacts/channel.tx

    是否与configtx.yaml中的Capabilities部分一致。否则修改configtx.yaml,重新生成证书和通道配置。

  3. couchDB查询结果按顺序排序。根据官方网站给出的语法:https://docs.couchdb.org/en/stable/api/database/find.html#find-sort,在实际运用中会报错“"error": “no_usable_index”,”reason”: “No index exists for this sort, try indexing by the sort fields.””。但数据库中确实已经创建了该索引。

    实际上,错误原因是:如果创建的一条索引包含了多条属性,那么查询是指定sort就要包含响应的所有属性。

    ![image-20200619135756392](基于hyperledger fabric1.4的资产分类系统.assets/image-20200619135756392.png)

下一步工作

目前对fabric有了一个初步认识,但对于具体的功能模块还需要进一步学习,例如:MSP,BCCSP,Fabric-CA,共识机制等等,这将是后面的一部分工作,另外,熟悉原理后将对fabric的算法进行替换,替换为国密,以及对Fabric-CA进行替换等。另外,对于fabric2.0,需要进一步了解与1.4版本的差异之处。

项目地址:

参考文献:

https://docs.couchdb.org/en/latest/api/database/find.html#find-selectors

https://hyperledger-fabric.readthedocs.io/en/release-2.0/couchdb_tutorial.html#query-the-couchdb-state-database

https://www.cnblogs.com/llongst/p/9571363.html

https://chainhero.io/2018/06/tutorial-build-blockchain-app-v1-1-0/#configuration

https://www.chaindesk.cn/witbook/11/221