摘要
项目:基于区块链的凤鸡溯源项目
- 区块链网络配置文件编写进度:已经完成了区块链配置文件的编写,在区块链网络中,总共设置了四个组织,分别为育种组织、养殖户组织、政府职能组织、普通用户组织,所有用户均通过普通用户组织的节点进行查询溯源的操作。
- 智能合约的编写进度:已经完成了向区块链账本中添加数据及删除数据的合约编写,但还未测试其有效性。下周应该可以实现该项目的后端服务器。
- 关于各节点服务器的处理:真实用于生产应用的区块链网络是一个组织对应着一系列公司,一个节点对应一家公司,但这样实现成本较高,本次项目目的是学习,故采用docker容器技术,模拟出一系列服务器代替各个公司的服务器。
深度学习: MAE MAE是何凯明老师的新作,该模型是一个预训练模型,通过masked图片上的一些patch,让模型还原出原图片,得到一个能够很好的提取图片信息的encoder,在此基础上,再进行模型的训练。实验证明,使用该方法的ViT框架,在小规模的数据中,也可以得到很好的效果,该方法也可以考虑一定程度的运用在时序预测上,预训练时让模型看一小段时序数据,还原出全部数据,像Bert模型那样。 毕设:学弟已经掌握了区块链网络的搭建,同时也在搭建前端页面。
项目:区块链凤鸡溯源项目的实现
实现总流程
- 编写区块链网络配置文件:
- 编写证书配置文件,用配置文件生成各个组织的证书。
- 编写创世区块和通道的配置文件,生成创世区块及通道文件(.tx类型文件)。
- 编写启动区块链的配置文件及客户端配置文件(客户端是用来和区块链交互的,和go sdk效果一样,前者是在命令行输入命令,适合测试阶段使用)。启动区块链网络将各个组织加入通道(在fabric中通一个通道内的组织共享一个账本)。
- 实现智能合约
- 为各个组织编写链码,确定交易逻辑。
- 将链码分别安装到各个组织的节点上。
- 搭建服务端路由组
- 编写go-sdk函数,调用链码,与区块链交互。
- 利用gin框架搭建路由组
1.1 编写区块链网络配置文件
1.1.1 证书配置文件(crypto-config)
总体逻辑
总共4个组织,分别为育种组织、养殖户组织、政府职能组织、普通用户组织,前三个组织均设置为简单的2节点,2 user,普通用户组织为1节点,1 user。所有用户均通过该普通用户组织的节点进行查询溯源的操作。
详情
- 排序节点域名:orderer.trace.com。
- 育种组织域名:generate.trace.com, 节点2个,每个节点的user 2个。
- 养殖户组织域名:breed.trace.com,, 节点2个,每个节点的user 2个。
- 政府职能域名:government.trace.com, 节点2个,每个节点的user 2个。
- 普通用户域名:user.trace.com,, 节点1个,每个节点的user 1个。
生成证书文件命令:cryptogen generate --config=./crypto-config.yaml
代码
OrdererOrgs:
- Name: Orderer
Domain: trace.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: OrgGenerate
Domain: generate.trace.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 2
- Name: OrgBreed
Domain: breed.trace.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 2
- Name: OrgGovernment
Domain: government.trace.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 2
- Name: OrgUser
Domain: user.trace.com
EnableNodeOUs: true
Template:
Count: 1
Users:
Count: 1
1.1.2 创世区块及通道配置文件
总体逻辑
在该文件中需要配置各个组织的msp文件,组织间进行通信的锚节点,通信端口,排序机制,排序规则等。
- 生成创世区块文件命令:
configtxgen -profile OrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block - 生成通道文件命令:
configtxgen -profile OrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
详情
- 排序节点配置:
- 排序类型:solo
- 通信地址: orderer.trace.com:7050
- 产生区块时间:2s
- 交易规格:满足以下条件之一,就会产生区块。
当数据条数到达100条; 区块数据量超过64M; - 各个组织配置(各个组织配置都差不多,在此以育种组织为例):锚节点通信地址: peer0.generate.trace.com:7050
代码
---
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/trace.com/msp
- &org_generate
Name: OrgGenerateMSP
ID: OrgGenerateMSP
MSPDir: crypto-config/peerOrganizations/generate.trace.com/msp
AnchorPeers:
- Host: peer0.generate.trace.com
Port: 7051
- &org_breed
Name: OrgBreedMSP
ID: OrgBreedMSP
MSPDir: crypto-config/peerOrganizations/breed.trace.com/msp
AnchorPeers:
- Host: peer0.breed.trace.com
Port: 7051
- &org_government
Name: OrgGovernmentMSP
ID: OrgGovernmentMSP
MSPDir: crypto-config/peerOrganizations/government.trace.com/msp
AnchorPeers:
- Host: peer0.government.trace.com
Port: 7051
- &org_user
Name: OrgUserMSP
ID: OrgUserMSP
MSPDir: crypto-config/peerOrganizations/government.trace.com/msp
AnchorPeers:
- Host: peer0.user.trace.com
Port: 7051
Capabilities:
Global: &ChannelCapabilities
V1_1: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_2: true
Application: &ApplicationDefaults
Organizations:
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.trace.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 100
AbsoluteMaxBytes: 64 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Profiles:
OrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *org_generate
- *org_breed
- *org_government
- *org_user
OrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *org_generate
- *org_breed
- *org_government
- *org_user
Capabilities:
<<: *ApplicationCapabilities
1.1.3 启动区块链的配置文件及客户端配置文件
总体逻辑
企业级的区块链网络是各个组织对应着一系列公司,各个节点分别对应一家公司,这样实现成本较高,本次项目目的是学习,故采用docker容器,在一台电脑上,启动多个容器,实现区块链网络; 故在启动区块链的文件中需要配置容器版本,容器与外界的通信端口,容器卷的映射,tls加密通信的配置等。 客户端配置文件需要设置所用容器版本,客户端采用哪个证书账号进行登陆。
代码
因为每个节点都需要一个配置文件,代码繁多,但配置文件的配置都差不多,故在此以generate的peer0节点为例。
version: '2'
services:
peer0.generate.trace.com:
container_name: peer0.generate.trace.com
image: hyperledger/fabric-peer:latest
environment:
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=trace_default
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_GOSSIP_USELEADERELECTION=true
- CORE_PEER_GOSSIP_ORGLEADER=false
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_LOCALMSPID=OrgGenerateMSP
- CORE_PEER_ID=peer0.generate.trace.com
- CORE_PEER_ADDRESS=peer0.generate.trace.com:7051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.generate.trace.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.generate.trace.com:7051
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
volumes:
- /var/run/:/host/var/run/
- ./crypto-config/peerOrganizations/generate.trace.com/peers/peer0.generate.trace.com/msp:/etc/hyperledger/fabric/msp
- ./crypto-config/peerOrganizations/generate.trace.com/peers/peer0.generate.trace.com/tls:/etc/hyperledger/fabric/tls
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
networks:
default:
aliases:
- trace
ports:
- 7051:7051
- 7053:7053
cli:
container_name: cli
image: hyperledger/fabric-tools:latest
tty: true
stdin_open: true
environment:
- GOPATH=/opt/gopath
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_LOGGING_LEVEL=INFO
- CORE_PEER_ID=cli
- CORE_PEER_ADDRESS=peer0.generate.trace.com:7051
- CORE_PEER_LOCALMSPID=OrgGenerateMSP
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/generate.trace.com/peers/peer0.generate.trace.com/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/generate.trace.com/peers/peer0.generate.trace.com/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/generate.trace.com/peers/peer0.generate.trace.com/tls/ca.crt
- CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/generate.trace.com/users/Admin@generate.trace.com/msp
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- /var/run/:/host/var/run/
- ./chaincode/:/opt/gopath/src/github.com/chaincode
- ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
- ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
depends_on:
- peer0.generate.trace.com
networks:
default:
aliases:
- trace
1.2 实现智能合约
1.1.1 结构体设计
溯源的目的是让用户追溯购买的凤鸡来自哪个育种企业,被哪个养殖户养殖,是否经过检疫等等信息,所以每个凤鸡都需要有其独一无二的编号,无论其流经哪个组织,其编号不能变,但每个组织中凤鸡都有不同的属性,故如下定义结构体:
1.1.2 main函数
main函数主要分为两部分,第一部分为Init函数,该函数的作用是链码初始化。还有一部分是Invoke函数,该函数通过接受外部参数,执行对应的功能。
代码
package main
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
type GenerateChaincode struct {
}
func (t *GenerateChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
return shim.Success([]byte("OK"))
}
func (t *GenerateChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fun, args := stub.GetFunctionAndParameters()
if fun == "AddData" {
return AddData(stub, args)
} else if fun == "QueryDataByID" {
QueryDataByID(stub, args[0])
} else {
return shim.Error("input function error")
}
return shim.Success(nil)
}
func main() {
err := shim.Start(new(GenerateChaincode))
if err != nil {
fmt.Println("an error occurred when starting the chaincode")
}
}
1.1.3 添加、查询数据函数
- PutData函数:因为区块链中存入的数据是序列化的数据,该函数负责将输入数据序列化后存入区块链账本中。
- AddData函数: 输入数据,调用PutData将数据存入区块链。
- QueryDataByID函数: 输入凤鸡ID,溯源查询数据。
代码
func PutData(stub shim.ChaincodeStubInterface, gen commonModel.GenerateCrop) ([]byte, bool) {
data, err := json.Marshal(gen)
if err != nil {
return nil, false
}
err = stub.PutState(gen.ID, data)
if err != nil {
return nil, false
}
return data, true
}
func AddData(stub shim.ChaincodeStubInterface, args []string) peer.Response {
var data commonModel.GenerateCrop
err := json.Unmarshal([]byte(args[0]), &data)
if err != nil {
return shim.Error("data Unmarshal failed")
}
_, e := PutData(stub, data)
if e == false {
return shim.Error("data saved failed")
}
return shim.Success([]byte("successful saved"))
}
func QueryDataByID(stub shim.ChaincodeStubInterface, ID string) (commonModel.GenerateCrop, bool) {
var queryResult commonModel.GenerateCrop
data, err := stub.GetState(ID)
if err != nil {
return queryResult, false
}
err = json.Unmarshal(data, &queryResult)
if err != nil {
return queryResult, false
}
return queryResult, true
}
二、深度学习:MAE
2.1 框架
- 将一张输入图片,分割成多个patch;
- 随机mask掉一些patch;
- 将unmask的patch拉平得到embedding输入到encoder中;
- 将encoder的输入投映到原始的位置向量中;
- 经过线性层输入到decoder中,decoder还原出原始图片。
MAE 方法严格来讲属于一种去噪自编码器 (Denoising Auto-Encoders (DAE)),去噪自动编码器是一类自动编码器,它破坏输入信号,并学会重构原始的、未被破坏的信号。MAE 的 Encoder 和 Decoder 结构不同,是非对称式的。Encoder 将输入编码为 latent representation,而 Decoder 将从 latent representation 重建原始信号。
2.2 MAE Encoder
MAE Encoder 采用 ViT 架构,但只会作用于 unmasked images。和 ViT 思路一样,MAE Encoder 会先通过 Linear Projection 编码图片,再加上位置编码,随后送入一堆连续的 Transformer Block 里面。但是编码器只对整个图片 patches 集合的一个小子集 (例如25%)进行操作,而删除 masked patches。这里和 BERT 做法不一样,BERT 使用对于 mask 掉的部分使用特殊字符,而 MAE 不使用掩码标记。
2.3 MAE Decoder
MAE Decoder 采用 Transformer 架构,输入整个图片 patches 集合,不光是 unmasked tokens ,还有被 mask 掉的部分 。每个 mask tokens 都是一个共享的、学习的向量,它指示了这里有一个待预测的 tokens。作者还将位置嵌入添加到这个完整 image patch 集合中的所有 tokens 中,位置编码表示每个 patches 在图像中的位置的信息。 MAE Decoder 仅用于预训练期间执行图像重建任务。因为自监督学习的特点就是只用最后预训练好的 Encoder 完成分类任务。因此,可以灵活设计与编码器设计无关的解码器结构。作者用比编码器更窄更浅的很小的解码器做实验。 在这种非对称的设计下,tokens 就可以由轻量级解码器处理,这大大缩短了预训练的时间。
2.4 自监督学习目标函数
Decoder 的最后一层是一个 Linear Projection 层,其输出的 channel 数等于图像的像素 (pixel) 数。所以 Decoder 的输出会进一步 reshape 成图像的形状。损失函数就是 MSE Loss,即直接让 reconstructed image 和 input image 的距离越接近越好。
|