区块链发票(后端)
区块链发票系统(后端)
背景描述
税收是国家的财政来源,制造假发票,虚开发票影响国家税收。为了提高发票透明度,市税务局请你开发一套区块链税务系统进行试点。发票的整个开具、使用、核心
流程包括:
税务局首先登记有资格认领发票的试点企业。经过登记的企业采用有资格认领区块链发票。
税务局将试点发票登记进入区块链发票池,发票池中是合法的区块链发票,没有经过登记进入发票池发票均为无效发票。
试点企业认领区块链发票,税务局登记企业认领了哪些发票。
试点企业根据实际发生的业务,将认领的发票开具给他人,企业只能开具自己认领的发票,不得使用其他企业认领的发票。
收到发票的企业可以核销抵税。
限制要求:为了提高系统可信度,由市场监督管理局代表企业运营 2 个节点,一个处于企业的上链业务,另一个节点向公众提供发票查询服务;财政局作为监督节点,不参与业务。
分析
- Order节点:由市税务局、市场监督管理局和财政局共同管理的区块链税务系统需要至少1个Order节点来管理交易的顺序和一致性。
- Peer节点:考虑到区块链系统的可扩展性和容错性,建议至少有3个Peer节点。这些节点可以分别由市税务局、市场监督管理局和财政局控制。
- 组织分配:
- 市税务局:作为整个系统的发起者和主要管理者,可以担任一个Peer节点,并负责区块链发票的登记、发行和核查等操作。
- 市场监督管理局:作为系统可信度的代表,该机构可以担任一个Peer节点,负责对企业的上链业务进行监督和审核,并向公众提供发票查询服务。
- 财政局:作为监督节点,该机构不参与具体的业务操作。可以担任第三个Peer节点,负责监督和验证系统中的交易和数据。
- 部门对应组织:
- 税务部门:属于市税务局,负责发票登记、发行和核查。
- 市场监管部门:属于市场监督管理局,负责对企业上链业务进行监督和审核。
- 财政部门:属于财政局,负责监督和验证系统中的交易和数据。
结论
财政局: orderer.zxy.com 一个order节点
市税务局: peer.chen.com 一个peer节点
市场监察局: peer.zhou.com 两个peer节点
需要实现功能
1、税务局将发票放入发票池
2、添加试点企业
3、将发票分配给指定的企业
4、开发票
5、查询发票
注:因实际情况,具体的实现逻辑有所不同,现在为最初版本,能实现基本功能但是逻辑不严谨,后续改进
搭建
网络环境
crypto-config.yaml
,搭建好网络拓扑
1 | # 排序节点的组织定义 |
configtx.yaml
,网络的基本配置,用来生成创世块和channel通道
1 | # 定义组织机构实体 |
docker-compose.yaml
,使用docker容器,启动网络
1 | version: '2.1' |
docker-compose-base.yaml
,共同的网络配置
1 | version: '2.1' |
编写智能合约和应用
1、编写一个工具类,用于封装对数据的增删查
1 | package utils |
2、根据需求定义好结构体
1 | package model |
3、编写合约
1 | package api |
4、合约的初始化及调用
1 | package main |
5、统一接口应用返回参数
1 | package app |
6、fabric-go-sdk的使用
1 | package blockchain |
7、编写应用接口
1 | package v1 |
8、定义路由
1 | package routers |
9、定义程序主入口
1 | package main |
10、编写dockerfile文件,用来构建镜像
1 | FROM golang:1.14 AS app |
11、docker-compose.yaml文件
1 | FROM golang:1.14 AS app |
12、编写运行脚本
构建application
1
2
3
docker-compose build运行application
1
2
3
docker-compose up -d停止application
1
2
3
docker-compose down启动网络
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
74#!/bin/bash
if [[ `uname` == 'Darwin' ]]; then
echo "Mac OS"
export PATH=${PWD}/hyperledger-fabric-darwin-amd64-1.4.12/bin:$PATH
fi
if [[ `uname` == 'Linux' ]]; then
echo "Linux"
export PATH=${PWD}/hyperledger-fabric-linux-amd64-1.4.12/bin:$PATH
fi
echo "一、清理环境"
./stop.sh
echo "二、生成证书和秘钥( MSP 材料),生成结果将保存在 crypto-config 文件夹中"
cryptogen generate --config=./crypto-config.yaml
echo "三、创建排序通道创世区块"
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./config/genesis.block -channelID firstchannel
echo "四、生成通道配置事务'appchannel.tx'"
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./config/appchannel.tx -channelID appchannel
echo "五、为 CHEN 定义锚节点"
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./config/CHENAnchor.tx -channelID appchannel -asOrg CHEN
echo "六、为 ZHOU 定义锚节点"
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./config/ZHOUAnchor.tx -channelID appchannel -asOrg ZHOU
echo "区块链 : 启动"
docker-compose up -d
echo "正在等待节点的启动完成,等待10秒"
sleep 10
CHENPeer0Cli="CORE_PEER_ADDRESS=peer0.chen.com:7051 CORE_PEER_LOCALMSPID=CHENMSP CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/chen.com/users/Admin@chen.com/msp"
CHENPeer1Cli="CORE_PEER_ADDRESS=peer1.chen.com:7051 CORE_PEER_LOCALMSPID=CHENMSP CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/chen.com/users/Admin@chen.com/msp"
ZHOUPeer0Cli="CORE_PEER_ADDRESS=peer0.zhou.com:7051 CORE_PEER_LOCALMSPID=ZHOUMSP CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/zhou.com/users/Admin@zhou.com/msp"
ZHOUPeer1Cli="CORE_PEER_ADDRESS=peer1.zhou.com:7051 CORE_PEER_LOCALMSPID=ZHOUMSP CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/zhou.com/users/Admin@zhou.com/msp"
echo "七、创建通道"
docker exec cli bash -c "$CHENPeer0Cli peer channel create -o orderer.zxy.com:7050 -c appchannel -f /etc/hyperledger/config/appchannel.tx"
echo "八、将所有节点加入通道"
docker exec cli bash -c "$CHENPeer0Cli peer channel join -b appchannel.block"
docker exec cli bash -c "$CHENPeer1Cli peer channel join -b appchannel.block"
docker exec cli bash -c "$ZHOUPeer0Cli peer channel join -b appchannel.block"
docker exec cli bash -c "$ZHOUPeer1Cli peer channel join -b appchannel.block"
echo "九、更新锚节点"
docker exec cli bash -c "$CHENPeer0Cli peer channel update -o orderer.zxy.com:7050 -c appchannel -f /etc/hyperledger/config/CHENAnchor.tx"
docker exec cli bash -c "$ZHOUPeer0Cli peer channel update -o orderer.zxy.com:7050 -c appchannel -f /etc/hyperledger/config/ZHOUAnchor.tx"
# -n 链码名,可以自己随便设置
# -v 版本号
# -p 链码目录,在 /opt/gopath/src/ 目录下
echo "十、安装链码"
docker exec cli bash -c "$CHENPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode"
docker exec cli bash -c "$ZHOUPeer0Cli peer chaincode install -n fabric-realty -v 1.0.0 -l golang -p chaincode"
# 只需要其中一个节点实例化
# -n 对应上一步安装链码的名字
# -v 版本号
# -C 是通道,在fabric的世界,一个通道就是一条不同的链
# -c 为传参,传入init参数
echo "十一、实例化链码"
docker exec cli bash -c "$CHENPeer0Cli peer chaincode instantiate -o orderer.zxy.com:7050 -C appchannel -n fabric-realty -l golang -v 1.0.0 -c '{\"Args\":[\"init\"]}' -P \"AND ('CHENMSP.member','ZHOUMSP.member')\""
echo "正在等待链码实例化完成,等待5秒"
sleep 5
# 进行链码交互,验证链码是否正确安装及区块链网络能否正常工作
echo "十二、验证链码"
docker exec cli bash -c "$CHENPeer0Cli peer chaincode invoke -C appchannel -n fabric-realty -c '{\"Args\":[\"hello\"]}'"
docker exec cli bash -c "$ZHOUPeer0Cli peer chaincode invoke -C appchannel -n fabric-realty -c '{\"Args\":[\"hello\"]}'"停止网络
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#!/bin/bash
# 清除链码容器
function clearContainers() {
CONTAINER_IDS=$(docker ps -a | awk '($2 ~ /dev-peer.*fabric-realty.*/) {print $1}')
if [ -z "$CONTAINER_IDS" -o "$CONTAINER_IDS" == " " ]; then
echo "---- No containers available for deletion ----"
else
docker rm -f $CONTAINER_IDS
fi
}
# 清除链码镜像
function removeUnwantedImages() {
DOCKER_IMAGE_IDS=$(docker images | awk '($1 ~ /dev-peer.*fabric-realty.*/) {print $3}')
if [ -z "$DOCKER_IMAGE_IDS" -o "$DOCKER_IMAGE_IDS" == " " ]; then
echo "---- No images available for deletion ----"
else
docker rmi -f $DOCKER_IMAGE_IDS
fi
}
echo "清理环境"
mkdir -p config
mkdir -p crypto-config
rm -rf config/*
rm -rf crypto-config/*
docker-compose down -v
clearContainers
removeUnwantedImages
echo "清理完毕"
13、根据顺序启动即可,经测试,应用接口均可用 http://localhost:8000/api/v1/