本节对数据共享系统的区块链部分做一个简单的介绍,包括目录结构、文件作用、设计思路。
购买专栏前请认真阅读:《基于区块链与IPFS的数据共享系统》专栏简介
├── bin //保存了二进制文件方便启动网络
│ ├── configtxgen //生成创世区块和通道材料
│ └── cryptogen //生成密钥
├── chaincode //链码
│ ├── datashare.go
│ ├── go.mod
│ └── go.sum
├── configtx.yaml //来自byfn
├── crypto-config.yaml //来自byfn
├── docker-compose-byfn.yaml //byfn中的节点配置与IPFS容器配置
├── explorer //区块链浏览器
│ ├── config.json
│ ├── connection-profile
│ └── docker-compose.yaml
├── start.sh //启动网络脚本
├── stop.sh //关闭网络脚本
└── tape //fabric压测工具tape
├── config-temp.yaml
├── tape
└── test
启动脚本为启动区块链网络以及IPFS容器,之后使用sed命令更换区块链浏览器、tape配置文件中的私钥。
这里解释一下为什么需要替换私钥文件,因为每次区块链网络重启后都会重新生成私钥文件,区块链浏览器、tape在使用时访问Fabric网络需要使用私钥文件。
具体步骤如下面代码所示,首先是获取私钥文件名称;然后使用模版文件 config-temp.yaml
替换当前的配置文件;使用sed命令替换priv_sk字段,此时配置文件中的私钥就替换好了。
#替换tape配置文件的私钥
priv_sk=$(ls crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp/keystore)
cp -rf ./tape/config-temp.yaml ./tape/config.yaml
sed -i "s/priv_sk/$priv_sk/" ./tape/config.yaml
关闭网络脚本中依次清理区块链网络与区块链浏览器的Docker容器、网络相关材料以及链码容器。
#清理之前的网络
docker-compose -f explorer/docker-compose.yaml down -v
docker-compose -f docker-compose-byfn.yaml down -v
#清理网络相关材料
rm -rf channel-artifacts
rm -rf crypto-config
#清理链码容器
clearContainers
removeUnwantedImages
这个文件是将BYFN中的first-network默认启动的网络相关的yaml文件整理了一下,整合到了一个yaml文件里,看着会比较清晰。此外,IPFS容器配置也放到了此文件,方便IPFS启动。
在本链码中,使用结构体存储数据的传输记录,字段有发送者、接受者、使用发送者公钥加密的文件CID(IPFS Hash)、使用接受者公钥加密的文件CID、文件名称、区块链交易Hash、时间戳。
// 数据传输记录结构体
type Record struct {
Sender string `json:"sender"`
Receiver string `json:"receiver"`
SenderEncrypted_cid string `json:"secid"`
ReceiverEncrypted_cid string `json:"recid"`
Filename string `json:"filename"`
Txid string `json:"txid"`
Timestamp string `json:"timestamp"`
}
在invoke中可以看到有两个主要的函数queryRecord
和sendData
,其中queryRecord
是用来查询传输记录的,传入的参数为用户的公钥,然后是通过APIstub.GetState()
获取Fabric账本中的键为args[0]
对应的值。
提示:在Fabric默认使用的levelDB中,数据使用Key-Value键值对存储数据。
sendData
函数为负责将传输记录上链,关键代码如下:
# 实例化Record结构体并使用传入的参数赋值
var record = Record{Sender: args[0], Receiver: args[1], SenderEncrypted_cid: args[2], ReceiverEncrypted_cid: args[3], Filename: args[4], Timestamp: time, Txid: APIstub.GetTxID()}
# 获取用户当前已存的传输记录
recordsAsBytes, err := APIstub.GetState(args[1])
#使用json反序列化,将json格式的数据转化为结构体,方便操作
json.Unmarshal(recordsAsBytes, &records)
#添加新的记录到所有的传输记录中
records = append(records, record)
#将新的传输记录存储至账本中
APIstub.PutState(args[1], recordsAsBytes)