前言
本文记录数据共享演示系统的开发全过程,包括环境搭建、BUG解决、开发思路等……
GitHub仓库
区块链网络
环境搭建
前置准备环境安装参考:传送门,本地开发环境如下:
- git v2.34.1
- curl v7.81.0
- docker v20.10.21
- docker-compose v1.29.2
- go v1.20
- jq v1.6
- fabric v2.2 fabric-ca v1.4.7
运行测试网络
按照Fabric教程启动测试网络,验证环境搭建是否成功,参考:传送门
改造测试网络
将network.sh
文件复制到数据共享演示系统项目目录下,从头阅读network.sh
文件,将提及的相关文件复制到项目目录下,
生成加密材料时,将组织从两个修改为四个
cryptogen
./organizations/cryptogen
中新建crypto-config-org3.yaml
、和crypto-config-org4.yaml
配置文件
- 在
network.sh
中的createOrgs()
函数中添加生成org3
、org4
加密材料的代码
ca
- 在
/organizations/fabric-ca/org1/fabric-ca-server-config.yaml
、/organizations/fabric-ca/org2/fabric-ca-server-config.yaml
和/organizations/fabric-ca/orderOrg/fabric-ca-server-config.yaml
中的affiliations
节添加org3、org4
的所属部门信息,
docker/docker-compose-ca.yaml
中添加ca_org3
和ca_org4
配置项
/organizations/fabric-ca/
中新建org3、org4
文件夹及其中的fabric-ca-server-config.yaml
配置文件
- 修改
organizations/fabric-ca/registerEnroll.sh
中端口号,添加createOrg3()、createOrg4()
- 在
network.sh
中的createOrgs()
函数中调用registerEnroll.sh
的createOrg3()、createOrg4()
函数
- 修改
./organizations/ccp-generate.sh
中端口号,添加Org3、Org4
修改network.sh
中createConsortium()
的Two->Four
- 修改
./configtx/configtx.yaml
,Organizations:
中添加Org3、Org4
,Profiles:
中添加Org3、Org4
并且Two->Four
修改./docker/docker-compose-test-net.yaml
:volumes
中添加org34
、services
中修改org12
的端口号并添加org34
、cli
中添加org34
(默认用的levelDB
)修改./docker/docker-compose-couch.yaml
:添加org34
修改scripts/createChannel.sh
,createChannelTx()
中Two->Four
(config.yaml
中的profiles
),最后joinChannel()、setAnchorPeer()
调用加34
- 修改
scripts/envVar.sh
:添加org4
- 修改
scripts/createChannel.sh
:修改端口号,添加org4
修改scripts/deployCC.sh
:最后调用函数处添加org34
修改network.sh
中networkDown()
:添加关闭org4
容器,删除org34
生成的文件和证书
启动测试网络
使用cryptogen
- 启动节点容器:此命令创建一个由四个
peer
节点和一个orderer
节点组成的 Fabric 网络,运行此命令时没有创建任何channel
- 创建通道:在
Org1、Org2、Org3
和Org4
之间创建一个默认名称为mychannel
的通道,并将它们的peer
节点加入该通道,最后为每个组织设置了锚节点
1
|
./network.sh createChannel
|
- 安装链码:
deployCC
子命令将在peer0.org1.example.com
和peer0.org2.example.com
上安装 asset-transfer (basic)
链码。 然后在使用通道标志(或mychannel
如果未指定通道)的通道上部署指定的通道的链码
1
|
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
|
- 初始化链码:
1
2
3
4
5
6
7
8
|
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'
|
- 查询账本:
1
|
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
|
- 调用链码改变账本上的资产所有者:
1
2
|
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset6","Wyatt"]}'
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
|
- 切换组织和节点查询账本:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp
export CORE_PEER_ADDRESS=localhost:8051
peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'
|
- 关闭网络:该命令将停止并删除节点和链码容器,删除组织加密材料,并从
Docker Registry
移除链码镜像。 该命令还删除之前运行的通道项目和docker
卷
使用 Fabric CA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
./network.sh up createChannel -ca
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset6","Wyatt"]}'
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
|
拷贝Fabric-trace
项目的blockchain-explorer
,替换本项目的organizations
文件夹,修改配置文件,启动explorer
1
2
3
4
|
docker-compose up -d
docker-compose down -v
docker volume ls
docker volume prune
|
手动部署Fabcar链码
复制fabric-samples/chaincode
目录到Fabric-Data-Sharing
- 安装链码依赖项(Go):
1
2
3
|
./network.sh up createChannel
cd Fabric-Data-Sharing/chaincode/fabcar/go
GO111MODULE=on go mod vendor
|
- 打包链代码:
1
2
3
4
5
6
|
cd ../../../test-network
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1
|
- 在节点上安装链码包:
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
|
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer lifecycle chaincode install fabcar.tar.gz
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer lifecycle chaincode install fabcar.tar.gz
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install fabcar.tar.gz
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp
export CORE_PEER_ADDRESS=localhost:8051
peer lifecycle chaincode install fabcar.tar.gz
|
- 为组织批准链码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
peer lifecycle chaincode queryinstalled
export CC_PACKAGE_ID=fabcar_1:xxx
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:6051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:5051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
|
- 提交链码到通道
1
2
3
4
5
|
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
|
- 调用链码
1
2
3
|
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt -c '{"function":"initLedger","Args":[]}'
peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
|
- 升级链码
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
|
cd ../chaincode/fabcar/go
GO111MODULE=on go mod vendor
cd ../../../test-network
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
peer lifecycle chaincode package fabcar_2.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_2
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer lifecycle chaincode install fabcar_2.tar.gz
export NEW_CC_PACKAGE_ID=fabcar_2:xxx
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer lifecycle chaincode install fabcar_2.tar.gz
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install fabcar_2.tar.gz
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp
export CORE_PEER_ADDRESS=localhost:8051
peer lifecycle chaincode install fabcar_2.tar.gz
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 2.0 --package-id $NEW_CC_PACKAGE_ID --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name fabcar --version 2.0 --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 2.0 --sequence 2 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"function":"initLedger","Args":[]}'
peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"function":"createCar","Args":["CAR11","Honda","Accord","Black","Tom"]}'
peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
|
启动应用程序与区块链交互
复制fabric-samples/fabcar
到Fabric-Data-Sharing
目录下
启动网络:
1
2
|
cd Fabric-Data-Sharing/fabcar
./startFabric.sh go
|
启动应用程序(Go):
1
2
|
cd Fabric-Data-Sharing/fabcar/go
go run fabcar.go
|
关闭网络:
1
2
|
cd Fabric-Data-Sharing/fabcar
./networkDown.sh
|
在 Fabric 中使用私有数据
创建集合定义的 JSON 文件:确定私有数据的访问权限
使用链码 API 读写私有数据:读取和写入带有集合定义的私有数据需要使用 GetPrivateData()
和 PutPrivateData()
接口
- 启动网络:
1
2
3
4
5
6
7
8
|
cd chaincode/marbles02_private/go
GO111MODULE=on go mod vendor
cd ../../../test-network
docker rm -f $(docker ps -a | awk '($2 ~ /dev-peer.*.marblesp.*/) {print $1}')
docker rmi -f $(docker images | awk '($1 ~ /dev-peer.*.marblesp.*/) {print $3}')
./network.sh up createChannel -s couchdb
|
- 安装并定义一个带集合的链码:
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
64
65
66
67
68
69
70
71
72
73
|
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer lifecycle chaincode package marblesp.tar.gz --path ../chaincode/marbles02_private/go/ --lang golang --label marblespv1
peer lifecycle chaincode install marblesp.tar.gz
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer lifecycle chaincode install marblesp.tar.gz
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install marblesp.tar.gz
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp
export CORE_PEER_ADDRESS=localhost:8051
peer lifecycle chaincode install marblesp.tar.gz
peer lifecycle chaincode queryinstalled
export CC_PACKAGE_ID=marblespv1:xxx
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp
export CORE_PEER_ADDRESS=localhost:8051
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --collections-config ../chaincode/marbles02_private/collections_config.json --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export ORG3_CA=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export ORG4_CA=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marblesp --version 1.0 --sequence 1 --collections-config ../chaincode/marbles02_private/collections_config.json --tls --cafile $ORDERER_CA --peerAddresses localhost:5051 --tlsRootCertFiles $ORG1_CA --peerAddresses localhost:6051 --tlsRootCertFiles $ORG2_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG3_CA --peerAddresses localhost:8051 --tlsRootCertFiles $ORG4_CA
|
- 存储私有数据:Org1 的成员已经被授权使用弹珠私有数据示例中的所有私有数据进行交易,切换回 Org1 节点并提交添加一个弹珠的请求。私有数据 price 将会和私有数据 name, owner, color, size 分开存储。因此,
initMarble
方法会调用 PutPrivateData()
接口两次来存储私有数据。另外注意,传递私有数据时使用 --transient
参数。作为瞬态的输入不会被记录到交易中,以此来保证数据的隐私性。瞬态数据会以二进制的方式被传输,所以在 CLI 中使用时,必须使用 base64 编码
1
2
3
4
5
6
7
|
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
export MARBLE=$(echo -n "{\"name\":\"marble1\",\"color\":\"blue\",\"size\":35,\"owner\":\"tom\",\"price\":99}" | base64 | tr -d \\n)
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marblesp --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"Args":["InitMarble"]}' --transient "{\"marble\":\"$MARBLE\"}"
|
- 授权节点查询私有数据:集合定义定义允许 Org1 和 Org2 的所有成员在他们的私有数据库中保存
name, color, size, owner
私有数据,但是只有 Org1 的成员才可以在他们的私有数据库中保存price
私有数据。作为一个已授权的 Org1 的节点,我们可以查询两个私有数据集。Org2 的节点的私有数据库中不存在 price
数据。当你尝试查询这个数据时,将只能看到私有数据的公共 hash。
1
2
3
4
5
6
7
8
9
10
11
12
|
peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarble","marble1"]}'
peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarblePrivateDetails","marble1"]}'
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarble","marble1"]}'
peer chaincode query -C mychannel -n marblesp -c '{"Args":["ReadMarblePrivateDetails","marble1"]}'
|
- 清除私有数据:数据在过了一定数量的区块后进行 “清除”,仅仅把数据的哈希作为交易不可篡改的证据保存下来。(知道这个功能就行,时间关系此处不实操)
- 使用私有数据索引:可以通过打包链码目录中的索引
META-INF/statedb/couchdb/collections/<collection_name>/indexes
目录,将索引也用于私有数据数据集。在生产环境中部署链码时,建议在链码目录中定义所有索引,这样当链码在通道中的节点上安装和初始化的时候就可以自动作为一个单元自动部署。当使用 --collections-config
标识私有数据集的 JSON 文件路径时,通道上链码初始化的时候相关的索引会自动被部署。
- 关闭网络:
使用CouchDB索引完成富查询
- 启动网络:
1
2
3
4
|
cd chaincode/marbles02/go
GO111MODULE=on go mod vendor
cd ../../../test-network
./network.sh up createChannel -s couchdb
|
- 安装、批准、提交和初始化链码:
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
64
|
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=${PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer lifecycle chaincode package marbles.tar.gz --path ../chaincode/marbles02/go --lang golang --label marbles_1
peer lifecycle chaincode install marbles.tar.gz
peer lifecycle chaincode queryinstalled
export CC_PACKAGE_ID=marbles_1:
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:6051
peer lifecycle chaincode install marbles.tar.gz
peer lifecycle chaincode queryinstalled
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install marbles.tar.gz
peer lifecycle chaincode queryinstalled
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export CORE_PEER_LOCALMSPID="Org4MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org4.example.com/users/Admin@org4.example.com/msp
export CORE_PEER_ADDRESS=localhost:8051
peer lifecycle chaincode install marbles.tar.gz
peer lifecycle chaincode queryinstalled
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export ORG3_CA=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export ORG4_CA=${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --version 1.0 --sequence 1 --init-required --tls --cafile $ORDERER_CA --peerAddresses localhost:5051 --tlsRootCertFiles $ORG1_CA --peerAddresses localhost:6051 --tlsRootCertFiles $ORG2_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG3_CA --peerAddresses localhost:8051 --tlsRootCertFiles $ORG4_CA
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name marbles --isInit --tls --cafile $ORDERER_CA --peerAddresses localhost:5051 --tlsRootCertFiles $ORG1_CA --peerAddresses localhost:6051 --tlsRootCertFiles $ORG2_CA --peerAddresses localhost:7051 --tlsRootCertFiles $ORG3_CA --peerAddresses localhost:8051 --tlsRootCertFiles $ORG4_CA -c '{"Args":["Init"]}'
docker logs peer0.org1.example.com 2>&1 | grep "CouchDB index"
|
- 查询CouchDB状态数据库
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
|
#使用 Org1 创建一个拥有者是 “tom” 的 marble
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:5051
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
# Rich Query with index name explicitly specified:
peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"]}'
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n marbles --peerAddresses localhost:5051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:6051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt --peerAddresses localhost:8051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org4.example.com/peers/peer0.org4.example.com/tls/ca.crt -c '{"Args":["initMarble","marble5","red","35","tom"]}'
# Example two: query fully supported by the index with additional data
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\",\"color\":\"red\"}, \"use_index\":[\"/indexOwnerDoc\", \"indexOwner\"]}"]}'
# Example three: query not supported by the index
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"owner\":\"tom\"}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
# Example four: query with $or supported by the index
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"$or\":[{\"docType\":\"marble\"},{\"owner\":\"tom\"}]}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
# Example five: Query with $or not supported by the index
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarbles", "{\"selector\":{\"$or\":[{\"docType\":\"marble\",\"owner\":\"tom\"},{\"color\":\"yellow\"}]}, \"use_index\":[\"indexOwnerDoc\", \"indexOwner\"]}"]}'
# Rich Query with index name explicitly specified and a page size of 3:
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3",""]}'
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesWithPagination", "{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}","3","g1AAAABLeJzLYWBgYMpgSmHgKy5JLCrJTq2MT8lPzkzJBYqz5yYWJeWkGoOkOWDSOSANIFk2iCyIyVySn5uVBQAGEhRz"]}'
|
上面的第一个富查询json格式化后:
1
2
3
4
5
6
|
{
"Args": [
"queryMarbles",
"{\"selector\":{\"docType\":\"marble\",\"owner\":\"tom\"}, \"use_index\":[\"_design/indexOwnerDoc\", \"indexOwner\"]}"
]
}
|
webdav
使用nginx搭建webdav文件服务器(BUG)
- 安装
nginx
:注意必须安装nginx-full
, 默认的nginx
里面并不包含webdav
模块
1
|
sudo apt install -y nginx-full
|
- 创建发布目录:
1
2
3
|
# 用来保存共享文件的位置
sudo mkdir -p /home/dav
sudo chown -R www-data:www-data /home/dav
|
- 配置
1
|
sudo gedit /etc/nginx/sites-enabled/webdav.conf
|
内容如下:
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
|
server {
listen 8081;
server_name localhost;
# 设置使用utf-8编码,防止中文文件名乱码
charset utf-8;
# 认证方式
auth_basic realm_name;
# 存放认证用户名、密码文件(确认有对应权限)
auth_basic_user_file /etc/nginx/.passwords.list;
# webdav服务访问的根目录
root /home/dav/;
# dav allowed method
dav_methods PUT DELETE MKCOL COPY MOVE;
# Allow current scope perform specified DAV method
dav_ext_methods PROPFIND OPTIONS;
# In this folder, newly created folder or file is to have specified permission. If none is given, default is user:rw. If all or group permission is specified, user could be skipped
# 创建文件的默认权限
dav_access user:rw group:rw all:r;
# 临时文件位置
client_body_temp_path /tmp;
# MAX size of uploaded file, 0 mean unlimited
client_max_body_size 0;
# Allow autocreate folder here if necessary
# 允许自动创建文件夹(如果有需要的话)
create_full_put_path on;
}
|
- 测试配置文件
- 创建用户登录验证信息(用户名-密码)
1
2
|
echo -n 'username:' | sudo tee -a /etc/nginx/.passwords.list
openssl passwd -apr1 | sudo tee -a /etc/nginx/.passwords.list
|
- 重启nginx服务
1
|
sudo systemctl restart nginx
|
- 查看nginx状态
1
|
sudo systemctl status nginx
|
使用apache搭建webdav文件服务器(不适用)
- 安装
apache2
1
|
sudo apt-get install apache2
|
- 启动关联到的模块
1
2
3
|
sudo a2enmod dav_fs
sudo a2enmod dav
sudo a2enmod dav_lock
|
- 关联文件
1
2
3
4
|
sudo ln -s /etc/apache2/mods-available/dav.load /etc/apache2/mods-enabled/dav.load
sudo ln -s /etc/apache2/mods-available/dav_fs.load /etc/apache2/mods-enabled/dav_fs.load
sudo ln -s /etc/apache2/mods-available/dav_lock.load /etc/apache2/mods-enabled/dav_lock.load
sudo ln -s /etc/apache2/mods-available/dav_fs.conf /etc/apache2/mods-enabled/dav_fs.conf
|
- 重启服务
1
|
sudo /etc/init.d/apache2 restart
|
- 创建共享目录
1
2
|
sudo mkdir /var/www/sync # 接受客户端发来的文件,放在sync文件夹里
sudo chown www-data:www-data /var/www/sync
|
- 创建用户
1
2
3
4
|
sudo htpasswd -c /var/www/me.dav wyatt
# 这里会要求你设置密码,后面登录时会用到,用户名即为 wyatt
sudo chown root:www-data /var/www/me.dav
sudo chmod 640 /var/www/me.dav
|
- 配置文件
1
|
sudo gedit /etc/apache2/sites-available/000-default.conf
|
在VirtualHost
节点中加入配置信息:(注意:先在 DocumentRoot /var/www/sync/ 前加#, 避免重复)
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
|
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
#ServerName www.example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
DocumentRoot /var/www/sync/
<Directory /var/www/sync/>
Options Indexes MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
Alias /webdav /var/www/sync
<Location /webdav>
DAV On
AuthType Basic
AuthName "webdav"
AuthUserFile /var/www/me.dav
Require valid-user
</Location>
</VirtualHost>
|
- 重启服务并登录
1
2
3
|
sudo /etc/init.d/apache2 restart
sudo apt-get install cadaver
cadaver http://127.0.0.1/webdav/
|
Bug1:Apache2无法启动,报错 for apache2.service failed because the control process exited with error code.
原因:端口占用
解决:杀掉占用了端口的进程
1
2
3
4
5
6
|
# 查看是什么进程占用了端口
netstat -lnp|grep 80
# 按照PID杀掉此进程
kill -9 PID
# 重新启动apache2
sudo /etc/init.d/apache2 start
|
gin+webdav+vue
数据存储服务:各个参与方都运行一个gin实现的webdav服务器,并将共享目录的文件摘要上传到区块链中记录(智能合约),结合前端技术,实现在数据存储服务页面上设置共享目录,上传下载等操作
- 上传目前是直接将共享文件放入共享目录,没有写前端上传API
数据共享系统:使用gin编写一个数据共享系统服务器,展示区块链中记录的文件摘要。当用户请求文件时,该数据共享系统请求参与方的数据存储服务,并将请求记录存入区块链
数据存储服务与数据共享系统的区别与联系:
- 数据存储服务后台是各个参与方自己管理的一个数据库;数据共享系统展示所有参与方的数据,通过请求响应获取各个参与方的数据
- 数据共享系统包含数据存储服务;数据存储服务是数据共享系统的一部分
开发步骤:
- 阅读并大概理解ginwebdav源码
- 编写智能合约
数据存储服务实操:
- 启动网络:链码路径
../chaincode/fabcar/go/
、使用CA
、couchdb
、初始化链码
1
2
|
cd Fabric-Data-Sharing/fabcar
./startFabric.sh go
|
- 启动应用程序(Go):复制
fabcar
应用程序的代码、证书密钥和配置文件到win下,修改代码和配置文件使之适配新路径,实现在宿主机通过API,连接虚拟机中的区块链网络,调用其智能合约(此路不通,因为区块链网络节点是在本地启动,节点地址都设置为localhost:port,若要在宿主机访问,需要修改为宿主机ip+port)
1
2
3
|
# 手动启动(不使用goland)
cd Fabric-Data-Sharing/fabcar/go
go run fabcar.go
|
- 关闭网络:
1
2
|
cd Fabric-Data-Sharing/fabcar
./networkDown.sh
|
进度表
2023.7.6-2023.7.9
- 搭建环境并运行测试网络
- 改造测试网络使之适配项目(四个组织一个通道、使用Fabric-CA、使用couchDB)
2023.7.10
- 网络浏览器拉取镜像失败(已解决,网络原因)
- (BUG)资产转移链码调用失败,显示成功,但是查询后没有改变,在原测试网络再试下能否转移成功(已解决,背书的Peer节点不够,原示例只有
org12
的peer
节点背书,未过半数peer
节点)
2023.7.11
- 网络浏览器启动失败(初步查明原因:签名证书不匹配)
- 排查原因步骤
- 用
fabric-sample
试一下能否成功启动(可以启动成功)
- 查看容器日志发现无法连接
peer
节点且pg
数据库查询失败
- 检查配置的证书文件路径及名称
- 检查配置文件格式
- 检查数据卷残留(发现有残留,但官方推荐的
docker-compose down -v
按道理会清除 Postgres data and user wallet
数据卷,查看控制台输出发现是由于fabric-test
网络在启动中,所以无法关闭,导致报错结束命令执行,怀疑是该原因造成后续删除数据卷的步骤未执行)
2023.7.12
- 手动部署
fabcar
链码(Go
)、修改链码、升级链码
- 看教程的编写你的第一个应用,实操用应用程序调用
fabcar
链码,而不是用cli
调用
2023.7.13
- 逐行看
fabcar
应用程序的Go
代码如何实现
- 学习私有数据的概念,在 Fabric 中实操使用私有数据的例程
2023.7.14
- 逐行看使用私有数据的
marbles
例程的链码
2023.7.15
- 看如何使用CouchDB
- 了解下
marbles
例程的链码下索引的概念(couchDB的特性)
2023.7.16
- 在 Fabric 中实操使用CouchDB的例程(有BUG,无法在节点安装链码)
2023.7.18
- 看链码开发者教程
- Ubuntu使用nginx搭建webdav文件服务器(BUG,80只显示欢迎页,改到8081后可以输入用户名密码,但验证失败,显示404)
2023.7.22
- Ubuntu使用nginx搭建webdav文件服务器(尝试解决BUG失败)
2023.7.23
- 使用APACHE建webdav文件服务器
2023.7.29
- 看gin+webdav源码
- 成功启动webdav服务器
2023.7.30
- 尝试在win系统中开发数据存储服务(失败原因:无法连接区块链网络)
- 在ubuntu中安装goland,配置环境
- 解决ubuntu系统问题:apparmor权限规则问题导致经常黑屏,通过修改apparmor的权限规则文件解决;修改后无黑屏现象,但无法启动通过snap的软件商店安装的goland,故从官网下载goland安装包重新安装
2023.7.31
- 在ubuntu中启动webdav服务器
- 编译错误:缺少io/fs包;解决:升级go版本到1.17
- 成功在dataStorage连接区块链网络调用智能合约
2023.8.1
- 虚拟机中安装的ubuntu系统频繁出现内核错误,无法解决,故重装系统Ubuntu22.04.2
- 在新系统中重新配置项目环境,成功启动区块链网络、webdav服务器、调用智能合约
2023.8.4
- 仿照fabcar编写智能合约定义数据结构体,实现简单增删改查,使用fabric-sdk-go完成调用
2023.8.5
- 在数据储存服务中提取文件摘要,并调用API上传文件相关信息到区块链,同时也通过API从区块链中查询出文件信息(键查询)
- 使用例程学习CouchDB,建立索引,使用富查询完成例程中的资产的查询
2023.8.6
- 在链码中添加索引文件(dataHash、dataName),智能合约中完成QueryInfoByHash函数,在客户端应用程序中完成QueryByHash函数,通过gin框架成功调用该接口,使用APIPOST成功通过QueryByHash的测试
2023.8.7
- 完成QueryAllInfos、QueryInfoById、QueryInfoByHash、QueryInfoByName、ChangeInfoByName接口测试
- 完善uploadSingleFile接口的内部细节:
- 查询在区块链中查询是否存在哈希值一样的文件,若存在,则说明是同一文件,不再上传,直接返回提示信息
- 查询在区块链中查询是否存在文件名一样的文件,上面通过了哈希值校验,说明文件名相同,但内容不同,则覆盖原文件,更新dataVersion(先从区块链中获取version,再更新),区块链中会保存原文件的记录,但内容已被覆盖(BUG:提取DataId时遇到问题)
2023.8.8
- 解决uploadSingleFile接口中无法提取到DataId的BUG
- 优化代码,抽象出连接区块链的connectToBlockchain函数,减少代码冗余
2023.8.9
- 复习javascript基础
- 复习Vue2基础
- 阅读Vue3官方文档-开始,并动手实践,跟着教程成功使用 Vite + Vue 3 创建了一个项目
2023.8.10-2023.8.17
- 学习
vue3
+typescript
+vue-router
+pinia
+element-plus
+axios
在项目中如何配置和使用
2023.8.18
- 修改Ubuntu的DNS,解决网速慢问题,修改Ubuntu的Dock位置、字体大小
- 在
Ubuntu
中搭建数据共享演示系统的前端开发环境,完成axios
二次封装
- 优化项目目录,删除无用文件,重新构建项目启动路径
- 将项目的启动和关闭过程记录在
README.md
中
- 创建
update_json_path
脚本文件,实现自动化根据当前区块链网络生成的秘钥修改区块链浏览器配置文件
2023.8.19
- 修改中间件:链接区块链网络时事先生成管理员和用户的身份并存储在
wallet/
中
- 解决了在GO中使用
GO MOD
模式导入本地自定义包/函数的问题
- 将生成身份填充钱包和连接区块链的代码封装到工具包中
2023.8.20
- 替换Fabric生成的身份文件中的
\n
- 完成后端登录接口开发,后端使用前端发送身份和私钥,与钱包中的身份文件中的私钥做对比,若一致则登录成功;否则登陆失败
2023.8.21
- 完善登录接口
- 编写生成token的函数,利用token实现用户登录状态的保持
- 编写请求拦截器,通过GIN的中间件实现,完成token的验证以及用户信息的解析提取
- 抽象出http的请求处理函数
- Fabric生成的身份文件中
\n
不能删除,不然会报错秘钥错误,但用户登录时使用的秘钥含有\n
又不太美观,后期可以考虑用BASE64优化
- 修改上传文件时的上传者为TOKEN中保存的identity
- 若header中未携带token则提示登录
- 待优化:避免重复登陆,该用户存在TOKEN且未过期的话,返回该TOKEN
2023.8.24
- 学习vue项目中的layout模块开发
2023.8.25
- 学习vue项目中的登录获取用户信息、退出登录、路由鉴权和真实接口替代mock接口
2023.8.26
- 继续学习vue项目中的真实接口替代mock接口、接口ts数据类型定义
- 完成数据共享系统的的真实接口替代mock接口、接口ts数据类型定义
- 修改后端登录接口获取请求体中RAW数据(JSON),原来是获取表单数据,表单类型适合上传文件
2023.8.27
- 首页使用了粒子效果(安装
particles
、vue3 tsparticles
),并将登录框水平垂直居中,输入框加入提示文字
- 主题颜色:蓝色、紫色;删除模板的滚动条
scss
代码
- 添加主题切换按钮,借助element-plus的暗色模式,删除原来模板的顶部和主题颜色
- 修改折叠后边框宽度使logo和icon水平居中,隐藏logo旁标题
- 使用后端的登录接口,新开发后端获取用户信息的接口
- 完成前端的退出登录和路由鉴权
- 设置用户头像为el组件提供的icon,修改tabbar右侧按钮大小为默认
- 学习模板中的主体内容开发
2023.8.28
- 学习模板中的主体内容开发
- 分析项目的文件管理模块,理清思路
2023.8.29-9.2
-
智能合约
- 文件结构体中新建一个字段说明文件的查看范围(公开/指定一个组织)
- 新建索引文件
indexDataAuthority
- 编写函数
QueryAllInfoByOwnerPrefix
,通过字段dataOwner
的前缀组织名查询文件信息
- 编写函数
QueryFilesByDataAuthority
,通过字段dataAuthority
的值(public/Org*
)查询文件信息
-
后端开发接口
/query/myorg
获取token
中的identity
的Org为发布者的所有文件,使用couchdb的模糊查询(正则匹配)
/query/public
获取文件范围为公开public
的所有文件
/query/spec
获取token
中的identity
的Org
为指定接收者的所有文件
- 上传文件接口:接收文件返回URL、Hash、Name、Size、Type
- 上传文件表单接口:接收URL、Hash、Name、Size、Type、文件描述、授权范围
-
前端文件管理分为两个个子页面
- 展示所有公开分享的文件
- 展示本组织为特定接收方的文件
-
点击【分享】按钮分享文件
- 填写相关信息
- 文件描述:单选框+补充说明
- 分享范围:单选框
- 上传文件
- 字段校验:除了补充说明均为必填项
-
本组织分享的文件:显示【查看】(【修改】按钮暂时不开发)
- 点击【查看】:浏览器能加载的直接打开,加载不了会下载
- 点击【修改】:获取文件信息,重新上传(暂时不开发)
- 关键词搜索文件描述字段:模糊查询
- 智能合约层面编写查询函数:正则查询
dataDeScription
,并且dataAuthority
为public
- 编写相应的前后端调用方法
- 前端输入框为空时,【查询】按钮不可用
- 【重置】按钮:清除关键字,重新获取表格数据
-
非本组织分享的文件:显示【请求查看】按钮,点击发送查看请求,记录入区块链,该文件信息在公开页不显示,在我的请求中显示。请求授权过程:发送授权请求=>同意授权=>查看数据
-
具体操作:
- 新加一个菜单项【请求授权】:两个子页面显示【我的请求】、【我的授权】
- 智能合约:
- 创建
ReqAuthInfo
结构体:记录信息类型、请求授权记录ID、请求者、请求的文件ID、请求时间、是否同意、操作者、操作时间
- 创建
QueryReqAuthResult
结构体:接收区块链查询结果
CreateReqAuthInfo
:创建请求授权记录
QueryReqAuthInfoByReqUser
:根据请求者查询所有的请求授权记录
QueryReqAuthInfoByOperator
:根据响应者查询所有的请求授权记录
QueryReqAuthInfoByReqAuthId
:根据请求授权记录ID查询请求授权记录
- !!!BUG创建
KEY
:作为区块链中所有记录的ID
:由于智能合约安装在多个节点中,所以不能用全局变量,其他节点无法同步变量更新;(解决)改为在后端计数递增然后传递给合约
QueryReqAuthInfoByReqUserAndReqDataId
:根据请求者和请求的文件ID查询请求授权信息
ChangeReqAuthInfoIsAuth
:根据Key
和reqAuthId
修改请求授权记录的IsAuth
字段
- 修改
QueryAllInfos
为QueryAllFileInfos
:由于返回字段的结构不一致,故此处改为返回所有文件信息
- 后端:
- 中间件:创建对应智能合约的创建记录函数和查询函数
- 请求处理
- 新建全局变量
REQAUTHID
:作为每条请求授权记录信息的ReqAuthId
- 创建结构体
ReqAuthInfo
:定义创建请求授权记录
- 创建对应中间件的创建记录函数和查询函数
- 修改
QueryAllInfosToAllHandler
为QueryInfosToPublicByAuthorizedHandler
:返回所有公开的且请求授权记录中的该文件使未被授权给该用户的
- 先查询到所有授权范围为公开的文件信息
- 再查询到所有该登录用户的请求授权记录信息
- 再用所有授权范围为公开的文件信息的
dataId
字段与所有请求授权记录信息中的reqDataId
字段的值做比对,哪个文件信息比对成功,说明哪个文件信息被该登录用户请求过,所以从所有授权范围为公开的文件信息中去除比对成功的该条文件信息,所有文件信息全部比对过后,返回所有授权范围为公开且没有被该登录用户请求过文件信息
- 新建
QueryFileInfoByReqUserHandler
:根据请求者查询请求过的所有文件信息的接口用于【我的请求】页展示
- 新建
QueryReqAuthInfoByReqUserAndDataIdHandler
:根据请求者和请求的文件ID查询请求授权信息
- 新建
QueryFileInfoWithRequestAuthInfoByOperatorHandler
:根据登陆用户查询需要授权和授权过的所有请求授权信息和对应的文件信息的接口
- 修改
QueryAllInfosToSpecHandler
:查询特定接收方的所有文件信息且过滤掉已经被请求过的文件的接口
- 修改
QueryAllInfos
为QueryAllFileInfos
:返回所有文件信息
- 前端:
- 点击【请求】后该文件信息从【公开文件】页移至【我的请求】页
- 不能重复请求同一文件:点击【请求授权】后在【公开文件】页直接不显示
- 在【公开文件】页提示文件已移动至【我的请求】页
- 【我的请求】页展示登录用户所有请求过的文件,未授权的显示【待授权】按钮(禁用),授权了的显示【查看】按钮、(暂时没做:被拒绝的显示【请求被拒绝】按钮)
v-if
和v-show
的判断函数中异步的promise
对象总是返回true
- 【我的授权】页展示登录用户所有的作为操作者的请求授权信息及其对应的文件信息,展示【请求者】和【请求时间】,操作栏显示【查看】和【授权】
- 点击【授权】后,修改该条请求授权信息中的
isAuth
字段,然后将按钮变为【已授权】,不可再次点击
-
本组织为特定接收方的文件:显示【查看】按钮,点击也要通过请求授权
-
在登陆页校验:管理员直接跳转到区块链浏览器,用户首页显示数据统计
- 历史/今日被请求的文件排行榜
- 历史/今日被请求的组织排行榜
- 历史/今日发布文件的组织排行榜
- 历史发布总文件数(顶部居中)
- 每天发布文件数的趋势折线图(中间一横排)
- 实时发布文件的流水图(向下自动划)(右下角)
- 参考数据大屏、Fabric-trace、hyperledger explorer
- 调研Fabric关于HISTORY的API
-
演示时开两个浏览器代表不同用户
2023.9.17
添加文件访问记录上链功能
- 智能合约
- 创建
FileAccessInfo
结构体:信息类型、文件访问记录ID、文件ID、文件名、访问者、访问时间
- 创建
QueryFileAccessResult
结构体:接收区块链查询结果
CreateFileAccessInfo
:创建文件访问记录
QueryAllFileAccessInfos
:查询所有的文件访问记录
QueryFileAccessInfoByAccessId
:通过AccessId
查询文件访问记录
- 后端
- 中间件:创建对应智能合约的创建记录函数和查询函数
- 请求处理:
CreateFileAccessInfo
:创建文件访问记录
- 将
httpHandlers.go
移至gowebdav
:避免import cycle
- 修改
webdav
客户端的Defaulthandle
:将文件访问记录上链
- 前端
- 配置
webdav
服务器的代理
requestWebdav
:进行axios
二次封装,使用请求与响应拦截器
src/api/webdav/index.ts
:请求webdav
服务器的相关API
- 修改文件管理和请求授权四个子页面的【查看】按钮回调函数:
- 发送文件访问记录给服务器,服务器将该记录上链,弹窗提示用户文件访问记录上链
- 显示文件内容
2023.9.19-9.23
2023.9.24
- 在虚拟机中安装
mysql
- 学习使用
gorm
进行CRUD
2023.9.25
2023.9.26-9.30
- 数据库
- 角色->一对多->用户(根据用户【多】外键查询到所属角色)
- 角色->多对多->菜单(根据关联表
roles_menus
,查询用户拥有的菜单权限)
用户表users
:
字段名 |
数据类型 |
主/外键 |
允许空 |
含义 |
id |
bigint |
Y |
N |
自增主键 |
username |
varchar(32) |
N |
N |
用户名 |
password |
varchar(255) |
N |
N |
用户密码 |
role_id |
bigint |
Y |
Y |
角色id |
created_at |
datetime |
N |
Y |
创建时间 |
updated_at |
datetime |
N |
Y |
更新时间 |
deleted_at |
datetime |
N |
Y |
删除时间 |
字段名 |
数据类型 |
主/外键 |
允许空 |
含义 |
id |
bigint |
Y |
N |
自增主键 |
rolename |
varchar(32) |
N |
N |
角色名 |
created_at |
datetime |
N |
Y |
创建时间 |
updated_at |
datetime |
N |
Y |
更新时间 |
deleted_at |
datetime |
N |
Y |
删除时间 |
字段名 |
数据类型 |
主/外键 |
允许空 |
含义 |
id |
bigint |
Y |
N |
自增主键 |
menuname |
varchar(32) |
N |
N |
菜单名 |
pid |
bigint |
N |
Y |
父级菜单ID |
code |
varchar(32) |
N |
Y |
前端路由值 |
level |
bigint |
N |
N |
级数 |
created_at |
datetime |
N |
Y |
创建时间 |
updated_at |
datetime |
N |
Y |
更新时间 |
deleted_at |
datetime |
N |
Y |
删除时间 |
字段名 |
数据类型 |
主/外键 |
允许空 |
含义 |
menu_id |
bigint |
Y |
N |
菜单ID |
role_id |
bigint |
Y |
N |
角色ID |
-
后端
- 拆分路由组件到
router
包
- 在
controller
包中统一返回的json
响应格式
- 拆分请求处理函数到
controller
包
- 修改
template.go
使得直接访问数据存储服务不显示后台文件数据
- 使用数据库中用户信息登录相关接口及数据库操作
- 添加用户、删除用户相关接口及数据库操作
-
前端
- 使用数据库中用户信息登录
- 路由鉴权:不同用户显示不同菜单
- 404页面
- 调整侧边栏logo和title显示
- 完成用户管理页面显示所有用户信息、添加用户和删除用户【软删除】
2023.10.1
数据库、后端、前端
- 角色管理:显示已有角色、添加角色、删除角色、为角色分配菜单权限
注意:菜单深度写死为三
2023.10.2
智能合约
- 新建链上情报研究报告文件对象字段:数据类型、题名、编号、密级、完成单位、总页数、作者、审查批准人(职务)、主题词、摘要、版本号、hash、完成日期、版本号
前端、数据库
- 添加可视化统计菜单,其下有数据大屏和区块信息两个子菜单
- 前端约束添加的角色名与后端生成的区块链身份相同
后端
2023.10.3
智能合约
- 添加查询链上全部
Irr
类型文件的函数
- 添加查询全部dataReceiver为public的Irr类型的文件信息的接口
数据库
后端
- 超级管理员角色连接区块链使用Org1-MSP
- 测试完成
Irr
类型文件上链的接口
- 查询链上全部
Irr
类型文件的接口
- 查询全部dataReceiver为public的Irr类型的文件信息的接口
前端
- 点击区块信息后打开新标签页跳转到区块链浏览器,原页面路由跳转回点击前的路由
- 文件管理菜单拆分为发布文件、公开文件、受控文件、私有文件四个子菜单
- 完成文件辑要页显示
2023.9.18迭代需求
2023.11
2023.10.4
- 调整文件辑要页显示的标签宽度/列宽度
- 关键词查询公开文件
- 查看【公开文件】时的webdav访问控制(TOKEN)及文件访问记录上链
- 发布文件及前端表单校验
2023.10.5
- 完成数据存储服务的文件访问业务
- 首先校验是否为登录用户
- 然后校验查询字符串的值是否与请求的文件名匹配
- 其次校验文件的授权范围
- 最后将文件访问记录上链
- 受控文件的webdav访问控制
- 请求授权记录创建与查询
- 【受控文件】页的显示
- webdav的请求者、请求文件与文件授权范围和请求授权记录比对
- 文件访问记录上链
- 【我的请求】页的显示
- 【我的授权】页的显示(未测试)
2023.10.6
2024.1
- 完成一对多私发
- 每个组织启动一个webdav即可,前后端和区块链网络启动在集群服务器中
- 为什么用属性基加密而不用对称加密
- 节省资源
- 对称加密需要在后端根据请求用户手动判断能否解密
- 属性基加密的只需要将请求用户作为属性输入解密函数即可判断
- 安全性高
- 属性基加密在访问策略在发送方发送时就已经被确定,即使主密钥泄露也无法直接解密密文
- 对称加密的密钥泄露后可直接解密密文
TODO
2014.1
可选项
2024.10.26
BUG1:并发问题。由于全局配置的KEY同时读,导致KEY不唯一;解决:后端对KEY加锁
- 加锁的衍生问题:加锁后后端处理过慢,被阻塞的请求等待时间过长,前端异步无响应,后端实际都上传成功,若此时用户重复点击发布,由于哈希检测是在上传文件时,发布文件时未检测,这将导致重复上传现象;解决:前端增加超时时间限制,防止重复点击
- 加锁的衍生问题:由于上链时间长,多个下载文件请求同时到后端会堵塞;解决:同上,前端增加超时时间限制,防止重复点击生成多条访问记录;(增加提示信息)
BUG2:虚拟机局域网问题。由于测试环境中webdav服务启动在虚拟机中,所以局域网中其他PC无法通过虚拟机IP访问文件;解决:虚拟机网络用桥接
- 之所以上传可以成功,下载不成功是因为:上传有代理服务器做请求转发,开发环境下通过vue-cli在宿主机启动一个代理服务器(生产环境下启动nginx作为代理服务器),代理服务器可以和webdav通信,而下载是客户端直接访问虚拟机上的webdav服务,无法被代理服务器捕获到,webdav中虽然配置了cors解决跨域,但虚拟机的网络配置导致其无法被局域网其他PC访问
- 浏览器访问页面,实际上是从目标服务器获取到
index.html
等静态资源后在本地浏览器加载,而访问目标服务器时,若目标服务器配有代理服务器,则会先访问到代理服务器,由代理服务器转发请求到实际的目标服务器;在开发环境下,通过vue-cli启动了一个代理服务器,所有该服务的请求都会走该代理服务器
理想的实际架构:区块链和前后端服务启动在保密机器中,各个组织启动各自的webdav服务和peer节点
测试时的架构:区块链(包括所有组织的peer节点)、前后端、webdav(一个)都启动在一台虚拟机中
时间 |
内容 |
2023.6.10-2023.7.5 |
需求分析、总体设计、技术选型 |
2023.7.6-2023.7.9 |
1. 搭建环境并运行测试网络;2. 改造测试网络使之适配项目(四个组织一个通道、使用Fabric-CA、使用couchDB) |
2023.7.10 |
1. 网络浏览器拉取镜像失败(已解决,网络原因);2. (BUG)资产转移链码调用失败,显示成功,但是查询后没有改变,在原测试网络再试下能否转移成功(已解决,背书的Peer节点不够,原示例只有org12 的peer 节点背书,未过半数peer 节点) |
2023.7.11 |
网络浏览器启动失败(初步查明原因:签名证书不匹配)排查原因步骤:1)用fabric-sample 试一下能否成功启动(可以启动成功);2) 查看容器日志发现无法连接peer 节点且pg 数据库查询失败;3)检查配置的证书文件路径及名称;4)检查配置文件格式;5)检查数据卷残留(发现有残留,但官方推荐的docker-compose down -v 按道理会清除 Postgres data and user wallet 数据卷,查看控制台输出发现是由于fabric-test 网络在启动中,所以无法关闭,导致报错结束命令执行,怀疑是该原因造成后续删除数据卷的步骤未执行) |
2023.7.12 |
1. 手动部署fabcar 链码(Go )、修改链码、升级链码;2. 看教程的编写你的第一个应用,实操用应用程序调用fabcar 链码,而不是用cli 调用 |
2023.7.13 |
1. 逐行看fabcar 应用程序的Go 代码如何实现;2. 学习私有数据的概念,在 Fabric 中实操使用私有数据的例程 |
2023.7.14 |
逐行看使用私有数据的marbles 例程的链码 |
2023.7.15 |
看如何使用CouchDB |
2023.7.16 |
在 Fabric 中实操使用CouchDB的例程(有BUG,无法在节点安装链码) |
2023.7.18-2023.9.2 |
完成系统原型开发:前后端和区块链网络 |
2023.9.17 |
添加文件访问记录上链功能 |
2023.9.19-9.23 |
学习如何开发用户管理、角色管理和菜单管理模块 |
2023.9.24 |
在虚拟机中安装mysql ;学习使用gorm 进行CRUD |
2023.9.25 |
学习gorm 结构体的创建技巧和结合gin 使用 |
2023.9.26-10.1 |
完成权限管理菜单下的用户管理和角色管理 |
2023.10.2-10.6 |
重构系统功能;结合链上数据添加数据存储服务的权限访问控制 |
2024.1 |
完成数据评价和数据统计功能;增加私发一对多功能;对私发数据基于属性加密后上链 |