区块链的供应链溯源应用开发
一 、环境准备
(1)更新镜像源
apt update
(2)安装(openssl、jdk、git)
apt -y install openssl default-jdk git
(3)配置JAVA_HOME环境变量
echo “export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/” >> /etc/profile
source /etc/profile
(4)下载区块链开发部署工具
使用curl命令下载build_chain.sh区块链开发部署工具
curl -#LO https://github.com/FISCO-BCOS/FISCO-BCOS/releases/download/v2.11.0/build_chain.sh && chmod u+x build_chain.sh
(5)下载fisco-bcos二进制程序
使用wget命令下载fisco-bcos二进制程序
wget -c http://res.zhonghui.vip/blockchain/training/trace/resourse/fisco-bcos.tar.gz
解压缩文件,使用tar命令将fisco-bcos.tar.gz压缩包解压。-x参数解压文件,-v参数显示解压过程,-f参数指定文件
tar -xvf fisco-bcos.tar.gz
(6) 搭建并启动区块链网络
搭建区块链网络
bash build_chain.sh -l 127.0.0.1:4 -p 30300,20200,8545 -e ./fisco-bcos
启动区块链网络
bash nodes/127.0.0.1/start_all
(7) 安装并启动webase-front服务
使用wget命令下载
wget -c http://res.zhonghui.vip/blockchain/training/trace/resourse/webase-front.zip
unzip webase-front.zip
cp -r nodes/127.0.0.1/sdk/* webase-front/conf/
启动webase-front服务
cd webase-front
bash start.sh
在网站中打开:http://127.0.0.1:5002/WeBASE-Front
(8)合约功能开发
编写供应链(Logistics.sol)合约
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
contract Logistics {
struct LogisticsData {
address cargo; // 货物合约地址
address orgin; // 货物上级合约地址
address destination; // 货物下级合约地址
string memo; // 备注信息
uint createdAt; // 创建时间
uint queryCount; // 已查询次数
}
LogisticsData[] private _logisticsData; // 全部物流信息数组
uint public recordCount; // 所有记录条数
uint public queryCount; // 所有查询次数
function newLogistics(address cargo, address orgin, address
destination, string memory memo) public {
_logisticsData.push(LogisticsData({
cargo:cargo, // 货物合约地址
orgin:orgin, // 货物上级合约地址
destination: destination, // 货物下级合约地址
memo:memo, // 备注信息
createdAt:now, // 创建时间初始化为当前时间
queryCount:0 // 查询次数初始化为0
}));
recordCount = recordCount + 1; // 所有记录条数增加1
}
function getLogisticsInfo(address cargo) public
returns(LogisticsData[] memory _cargoLogisticsData) {
// 使用new关键字初始化LogisticsData[]数组,长度为3,将其赋值给_cargoLogisticsData数组变量
_cargoLogisticsData = new LogisticsData[](3);
// 进行3次循环
for (uint i=0; i < 3; i ++) {
// 在所有物流记录中查询货物合约地址为cargo的记录
for (uint j=0; j < _logisticsData.length; j++) {
if (_logisticsData[j].cargo == cargo) {
// 把此条物流记录查询次数增加1
_logisticsData[j].queryCount =_logisticsData[j].queryCount + 1;
// 把此条物流记录添加到_cargoLogisticsData数组变量中
_cargoLogisticsData[i] = _logisticsData[j];
}
}
// 把货物上级合约地址赋值给cargo,进行上级货物物流记录的查询
cargo = _cargoLogisticsData[i].orgin;
if (cargo == address(0)) {
// 货物上级地址为空,终止循环
break;
}
}
// 把全部记录查询次数增加1
queryCount = queryCount + 1;
return _cargoLogisticsData;
}
}
编写原产品(Material.sol)合约
pragma solidity 0.6.10;
contract Material {
address private _owner; // 合约创建者
string private _name; // 原产品名
string private _memo; // 备注信息
uint private _createdAt;// 创建时间
constructor(string memory materialName, string memory memo)
public {
_owner = msg.sender; // 把创建合约的地址赋值给_owner
_name = materialName; // 把原产品名赋值给_name
_memo = memo; // 把备注信息赋值给_memo
_createdAt = now; // 把当前时间赋值给_createdAt
}
function getMaterialInfo() public view returns(address, string
memory, string memory , uint){
return (_owner, _name, _memo, _createdAt);
}
}
编写中间产品(Product.sol)合约
pragma solidity 0.6.10;
import "./Logistics.sol";
contract Product {
address private _owner; // 合约创建者
string private _name; // 中间产品名
string private _memo; // 备注信息
uint private _createdAt; // 创建时间
address private _materialAddress; // 原产品合约地址
constructor(address materialAddress, address logisticsAddress,
string memory productName, string memory memo, string memory
logisticsMemo) public {
_owner = msg.sender;
// 把创建合约的地址赋值给_owner
_name = productName;
// 把中间产品名赋值给_name
_materialAddress = materialAddress;
// 把原产品合约地址赋值给_materialAddress
_memo = memo; // 把备注信息赋值给_memo
_createdAt = now; // 把当前时间赋值给_createdAt
// 调用供应链合约,保存供应链数据
Logistics(logisticsAddress).newLogistics(materialAddress,
address(0), address(this), logisticsMemo);
}
function getProductInfo() public view returns(address, string
memory, string memory memo, uint){
return (_owner, _name, _memo, _createdAt);
}
}
编写商品(Goods.sol)合约
pragma solidity 0.6.10;
import "./Logistics.sol";
contract Goods {
address private _owner; // 合约创建者
string private _name; // 商品名
string private _memo; // 备注信息
uint private _createdAt; // 创建时间
address private _productAddress; // 中间产品合约地址
address private _logisticsAddress; // 供应链合约地址
constructor(address materialAddress, address productAddress,
address logisticsAddress, string memory goodsName, string memory
memo, string memory logisticsMemo) public {
_owner = msg.sender; // 把创建合约的地址赋值给
_owner
_name = goodsName; // 把商品名赋值给_name
_productAddress = productAddress; // 把中间产品合约地址赋值
给_productAddress
_memo = memo; // 把备注信息赋值给memo
_createdAt = now; // 把当前时间赋值给
_createdAt
_logisticsAddress = logisticsAddress;// 把供应链合约地址赋值给
_logisticsAddress
// 调用供应链合约,保存供应链数据
Logistics(logisticsAddress).newLogistics(productAddress,
materialAddress, address(this), logisticsMemo);
}
function getGoodsInfo() public view returns(address, string
memory, string memory memo, uint){
return (_owner, _name, _memo, _createdAt);
}
function sell(string memory logisticsMemo) public {
// 调用供应链合约,保存供应链数据
Logistics(_logisticsAddress).newLogistics(address(this),
_productAddress, address(0), logisticsMemo);
}
}
(9)导出合约文件
二、 构建项目
(1)生成go合约文件
mkdir web && cd web
mkdir contract && cd contract
将导出的合约文件移动到当前contract文件夹下并解压
mv /root/Downloads/trace.zip ./
unzip trace.zip
<