基于以太坊的产品溯源方案

溯源,指的是往上游寻找发源的地方,比喻向上寻求历史根源。

这里有一个对商品的溯源需求,实现溯源方案有很多技术方案,无非是db+前端、或者是db+中间件+前端;db也是有很多选择,mysql、sqlserver、oracle、mongodb、redis等等不列举了;中间件也是可选择java、php、c/c++等等;前端就更加多了什么vue、h5、ios、android等等。我这里选择不用中间件,直接db+前端,db使用以太坊、前端使用h5。

补充说明下中间件可以带来很多好处,但这里我为了让这个流程简单清晰就没有使用。

现实现一套产品溯源系统,db使用以太坊、前端使用h5。如下

角色如下(角色功能如其名):

<option>消费者</option>
<option>商店</option>
<option>批发商</option>
<option>生产商</option>
<option>监管部门</option>

合约如下:

pragma solidity ^0.4.18;
contract ProductSystem{struct Product{//产品生产信息string name; //产品名称uint num;//库存量string key;//批号uint date;//生产时间address producer;//生产厂商}mapping(uint=>Product) public product;  //产品数组struct Warehouse{//仓库string name;//产品名称string key;//批号uint num;//库存量uint price;//价格}struct Message{//流通信息address seller;//卖方address buyer;//买方uint time;//交易日期uint num;//数量string key;//批号}struct Role{//角色string name;//名称uint typ;//角色类型uint flag;//可操作标记(0不可操作;1可以操作)uint ware_key;uint mess_key;mapping(uint=>Warehouse) ware;//仓库数据mapping(uint=>Message) mess;//购买记录}struct Role_address{//昵称与地址的映射string name;address add;}struct Report{//举报信息address people;//举报人string key;//产品批号}uint product_key;//批号的基准值uint report_key;//举报信息的基准值uint public name_address_key;//账户的基准值mapping(address=>Role) public role;mapping(uint=>Report) public report;mapping(uint=>Role_address) public role_address;event enroll_key(bool key);event product_production_key(bool key);event transaction_key(bool key);event reporting_key(bool key);event process_account_key(bool key);event huifu_account_key(bool key);function Productsystem()public{//初始化product_key=0;report_key=0;name_address_key=0;}function name_address(string _name)constant returns(address){uint i;for(i=0;i<name_address_key;i++){if(compare(_name,role_address[i].name)){return role_address[i].add;}}return;}function enroll(string _name,uint _type)public returns(bool)//注册角色{uint i;if(role[msg.sender].flag==1){emit enroll_key(false);return false;}for(i=0;i<name_address_key;i++){if(compare(_name,role_address[i].name)){emit enroll_key(false);return false;}}role_address[name_address_key].name=_name;role_address[name_address_key].add=msg.sender;name_address_key++;role[msg.sender].name=_name;role[msg.sender].typ=_type;role[msg.sender].flag=1;role[msg.sender].ware_key=0;role[msg.sender].mess_key=0;emit enroll_key(true);return true;}/*function product_inquire(uint i)constant public returns(string){string memory results;results="name:";results=strConcat(results,product[i].name);return results;}*/function product_production(string _name,uint _num,string _key,address _producer)public returns(bool){//生产产品uint w_key;if(role[_producer].typ!=0||role[_producer].flag!=1){emit product_production_key(false);return false;}if(_producer!=msg.sender){emit product_production_key(false);return false;}uint i;for(i=0;i<product_key;i++){if(compare(_key,product[i].key)){emit product_production_key(false);return false;}}product[product_key].name=_name;product[product_key].num=_num;product[product_key].key=_key;product[product_key].date=block.timestamp;product[product_key].producer=_producer;w_key=role[_producer].ware_key;product_key=product_key+1;role[_producer].ware[w_key].name=_name;role[_producer].ware[w_key].key=_key;role[_producer].ware[w_key].num=_num;role[_producer].ware[w_key].price=0;role[_producer].ware_key++;emit product_production_key(true);return true;}//function product_management_add(address account,Warehouse _ware)public{//    role[account].ware.push(_ware);//}function compare(string _a,string _b)returns(bool){//判断字符串是否相等bytes memory a = bytes(_a);bytes memory b = bytes(_b);if (a.length != b.length)return false;// @todo unroll this loopfor (uint i = 0; i < a.length; i ++)if (a[i] != b[i])return false;return true;}function product_management_inquire(address account,string _name)constant public returns (uint){//监管者查询仓库中某产品的数量uint sum=0;uint i;if(role[msg.sender].typ!=4)return;for(i=0;i<role[account].ware_key;i++){if(compare(_name,role[account].ware[i].name)){sum+=role[account].ware[i].num;}}return sum;}function inquire_product(string _name)constant public returns (uint){//查询本人仓库中某产品的数量uint sum=0;uint i;for(i=0;i<role[msg.sender].ware_key;i++){if(compare(_name,role[msg.sender].ware[i].name)){sum+=role[msg.sender].ware[i].num;}}return sum;}function transaction(address _from,address to,string _name,string _key,uint _price)public returns(bool){//产品交易函数uint i;uint j;uint w_key;uint m_key;if(role[_from].typ==4||role[to].typ==4||role[to].typ==0){emit transaction_key(false);return false;}if(_from!=msg.sender){emit transaction_key(false);return false;}if(role[_from].flag==0){emit transaction_key(false);return false;}for(i=0;i<role[_from].ware_key;i++){if(compare(_key,role[_from].ware[i].key)){if(!compare(role[_from].ware[i].name,_name)){emit transaction_key(false);return false;}w_key=role[to].ware_key;//将交易产品的信息写入买方的仓库role[to].ware[w_key].name=_name;role[to].ware[w_key].key=_key;role[to].ware[w_key].price=_price;role[to].ware[w_key].num=role[_from].ware[i].num;for(j=i;j<role[_from].ware_key-1;j++){//从卖方仓库中删除交易产品的信息role[_from].ware[j].name=role[_from].ware[j+1].name;role[_from].ware[j].key= role[_from].ware[j+1].key;role[_from].ware[j].num=role[_from].ware[j+1].num;role[_from].ware[j].price=role[_from].ware[j+1].price;}role[to].ware_key++;role[_from].ware_key--;m_key=role[to].mess_key;//交易信息写入买方的交易信息数组role[to].mess[m_key].seller=_from;role[to].mess[m_key].buyer=to;role[to].mess[m_key].time=block.timestamp;role[to].mess[m_key].num=role[to].ware[w_key].num;role[to].mess[m_key].key=_key;role[to].mess_key++;emit transaction_key(true);return true;}}emit transaction_key(false);return false;}function strConcat(string _a, string _b) returns (string){//字符串拼接bytes memory _ba = bytes(_a);bytes memory _bb = bytes(_b);string memory ret = new string(_ba.length + _bb.length);bytes memory bret = bytes(ret);uint k = 0;for (uint i = 0; i < _ba.length; i++)bret[k++] = _ba[i];for (i = 0; i < _bb.length; i++) bret[k++] = _bb[i];return string(ret);}function inquire(address account,string _key)constant public returns (string){//查询产品交易信息链uint i;string memory results;results="";if(role[account].flag==0){return;}if(0==role[account].typ){results=role[account].name;return results;}for(i=0;i<role[account].mess_key;i++){if(compare(_key,role[account].mess[i].key)){results=inquire(role[account].mess[i].seller,_key);break;}}if(i==role[account].mess_key){return "errer!!!";}results=strConcat("<=",results);results=strConcat(role[account].name,results);return results;}function reporting(address _account,string _key)public returns(bool){//消费者提交举报信息if(_account!=msg.sender){emit reporting_key(false);return false;}else{report[report_key].people=_account;report[report_key].key=_key;report_key++;}emit reporting_key(true);return true;}function buyer_inquire_mess(uint _int)constant public returns(address,address,uint,uint,string){//返回消费记录/*uint i;string memory results;for(i=0;i<role[_account].mess_key;i++){results=strConcat(results,"seller:");results=strConcat(results,role[role[_account].mess[i].seller].name);results=strConcat(results,"   ");results=strConcat(results,"buyer:");results=strConcat(results,role[role[_account].mess[i].buyer].name);results=strConcat(results,"   ");results=strConcat(results,"key:");results=strConcat(results,role[_account].mess[i].key);results=strConcat(results,"\n ");}*/if(_int<role[msg.sender].mess_key)return (role[msg.sender].mess[_int].seller,role[msg.sender].mess[_int].buyer,role[msg.sender].mess[_int].time,role[msg.sender].mess[_int].num,role[msg.sender].mess[_int].key);elsereturn;}function buyer_inquire_ware(uint _int)constant public returns(string,string,uint,uint){//返回仓库信息/*uint i;string memory results;for(i=0;i<role[_account].ware_key;i++){results=strConcat(results,"name:");results=strConcat(results,role[_account].ware[i].name);results=strConcat(results,"   ");results=strConcat(results,"key:");results=strConcat(results,role[_account].ware[i].key);results=strConcat(results,"\n ");}*/if(_int<role[msg.sender].ware_key)return (role[msg.sender].ware[_int].name,role[msg.sender].ware[_int].key,role[msg.sender].ware[_int].num,role[msg.sender].ware[_int].price);elsereturn;}function process_report(address _account)constant public returns(string){//处理举报信息uint i;uint j;string memory results;if(role[msg.sender].typ!=4)return;for(i=report_key-1;i>=0;i--){if(_account==report[i].people){results=inquire(report[i].people,report[i].key);for(j=i;j<report_key-1;j++){report[j].people=report[j+1].people;report[j].key=report[j+1].key;}report_key--;break;}}return results;}function process_account(address _account)public returns(bool){//处理违规账户if(role[msg.sender].typ!=4){emit process_account_key(false);return false;}role[_account].flag=0;emit process_account_key(true);return true;}function huifu_account(address _account)public returns(bool){//恢复违规账户if(role[msg.sender].typ!=4){emit huifu_account_key(false);return false;}role[_account].flag=1;emit huifu_account_key(true);return true;}
}

搭建本地以太坊开发环境,弄一个私链,不清楚搭建看这个网址

1.启动本地环境

Geth输入命令

geth -targetgaslimit 4294967295 -rpc -rpcaddr “127.0.0.1” -rpcport “8101” -port “30301” -rpcapi “eth,web3,personal” -networkid 123 -identity 123 -nodiscover -maxpeers 5 -datadir “/root/ethereum/chain2” -unlock 0 -rpccorsdomain “*” -mine console

其中,datadir表示数据存储位置,123表示识别ID,要保持和其他节点一致,port表示使用的和别的节点连接的端口,rpc表示与外界进行交互,其中暴露的端口rpcport默认为8545也可以修改为自己的8101,rpcdomain表示允许进行访问的网站域名集,*表示所有网站都可以访问,否则会出现无法进行跨域访问的报错,console表示控制台打开。

  1. 创建账户并解锁账户,挖矿,使账户具有一定的余额

    > eth.accounts
    ["0x4aeb1e38b0821c26d6d834e4e7680301bbbba7f1", "0x2a35fc2bb657e247b10cff2a009b0912d4f9eace", "0x1340037bcc54787b2b629189b4eff3eded6741c5", "0x63cbdd13bf223ce6ce675457155c2198b377b05f", "0x424a7972e9fa609c0834c23e7dfd83a68de8531b", "0x79143c7d4af835e9836276ff8788614865811b04"]
    >
    > eth.getBalance(eth.accounts[0])
    1.36757044740584e+23
    

personal.newcount(“password”);//创建新账户

personal.unlockAccount(eth.account[0]);//解锁账户

miner.start()//开始挖矿

3.发布合约,修改连接文件

使用loadScript(“001.js”);将合约发布,将合约地址复制。

打开项目中的连接文件conect.js,将地址替换为新的合约地址。

INFO [03-30|17:58:14] Regenerated local transaction journal    transactions=0 accounts=0
INFO [03-30|18:12:50] Submitted contract creation              fullhash=0xdec1c60c8361169a2db4cec9ee9cd8e891e3ea142857ae517b3066fe5f35d7c7 contract=0x4dfA7D24F4913Fbb6869ed2180200e767328573B
INFO [03-30|18:14:03] Updated mining threads                   threads=0
INFO [03-30|18:14:03] Transaction pool price threshold updated price=18000000000
INFO [03-30|18:14:03] Starting mining operation
INFO [03-30|18:14:03] Commit new mining work                   number=28153 txs=1 uncles=0 elapsed=2.477ms

前端管理界面就不上代码了,源码见下。

源码地址

本地调试可使用webstorm打开工程或者直接文件夹中找到index.html,双击index.html在浏览器中打开,修改相关配置:

conect.js 文件

if (typeof web3 !== 'undefined')  web3 = new Web3(web3.currentProvider);
else   web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8101"));//此处为geth填写的rpcportif(!web3.isConnected()) console.log("UnConected")
else console.log("Conected")deployeAddr="0xA975A87c72A2E4141E85365AFf0424b7da45Ae3A";           //此处为合约发布后的地址

index.js 文件

if (typeof web3 !== 'undefined')  web3 = new Web3(web3.currentProvider);
else
{  web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8101"));}

打开index.html愉快的工作了!个人信息界面

溯源项目(全套源码)相关推荐

  1. java计算机毕业设计精品旅游项目管理系统源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计精品旅游项目管理系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计精品旅游项目管理系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目架构 ...

  2. 2020最新web前端开发学习资料,全套源码无加密网盘下载

    前言--2020web前端开发最新学习资料完整版,全套源码无加密网盘下载 最近小编整理了多套的学习资料(视频+资料+源码),无加密: 两套是某马老师讲解的,讲得挺不错,小编基本学完!还有多个项目实战! ...

  3. 「全套源码」基于Cocos实现的贪吃蛇游戏

    感谢『简书 ID: 何小成』友情提供 http://www.jianshu.com/p/dcebe85e0620 01 前言 贪吃蛇相信大家都玩过.我对贪吃蛇的最初印象就是在电子词典上,一只像素蛇在屏 ...

  4. 2020最新java学习资料,全套源码无加密网盘下载

    点击上方蓝字关注我们! 前言--------2020最新java学习资料完整版,全套源码无加密网盘下载 最近小编整理了三套java的学习资料(视频+资料+源码),无加密: 1.2020java会员版 ...

  5. 今年我读了四个开源项目的源码,来分享下心得

    今年来看了 RocketMQ.Kafka.Dubbo .Tomcat 的源码,之前也有读者询问过如何读源码,索性就来分享一下. 其实还看了一点点 Linux.Redis.jdk8,这几个阅读的目的和上 ...

  6. 开源项目实例源码_今年我读了四个开源项目的源码,来分享下心得

    今年来看了 RocketMQ.Kafka.Dubbo .Tomcat 的源码,之前也有读者询问过如何读源码,索性就来分享一下. 其实还看了一点点 Linux.Redis.jdk8,这几个阅读的目的和上 ...

  7. 达人探店小程序全套源码

    简介: 达人探店小程序全套源码,UI做的很简陋,分享给初学者学习一下小程序. 前台采用了微信小程序(WXML+WXSS+Javascript) 后台是IDEA开发JAVA用了spring-boot,数 ...

  8. 移通好闹钟微信小程序全套源码

    介绍: 移通好闹钟微信小程序全套源码,前端+后台+开发文档. 带视频演示文件 网盘下载地址: http://kekewl.org/ByWeMCkuZ900 图片:

  9. 鸿蒙开源源码,基于鸿蒙系统开源项目OpenHarmony源码静态分析

    #ifndef __scc #define __scc(X) ((long) (X)) // 转为long类型 typedef long syscall_arg_t; #endif #define _ ...

  10. 分享java web 期末项目实验源码20套,BBS论坛,ERP管理系统,OA自动化等等

    分享java web 期末项目实验源码20套,BBS论坛,ERP管理系统,OA自动化等等 我自己也从里面学习到了很多东西! 1.BBS论坛系统(jsp+sql) 2.ERP管理系统(jsp+servl ...

最新文章

  1. js,jq设置获取属性,样式
  2. 认识微软Visual Studio Tools for AI
  3. ssh 连接服务器_使用 SSH Key 访问服务器
  4. jQuery获取自身HTML
  5. ABP Vnext 4.4:统一Ef Core的DbContext/移除EF Core Migrations项目
  6. php根本自学不了,PHP开发自学还是培训?
  7. 理解总结篇—List、Set、Map
  8. 计算机丢失shlwapi,请教高手提示shlwapi.dll错误应该怎么处理?
  9. matlab程序svm四等级分类,支持向量机(SVM)多分类matlab程序代码
  10. SAM4E单片机之旅——11、UART之PDC收发
  11. 20201022-成信大-C语言程序设计-20201学期《C语言程序设计B》C-trainingExercises19
  12. PowerMILL宏自动化编程视频教程
  13. 模仿QQ侧滑样式,借鉴了张鸿洋的最简单侧滑
  14. dbind-WARNING **: Error retrieving accessibility bus address
  15. cocos2dx之Box2D
  16. 内网穿透技术有哪些(经验分享)
  17. 你真的了解中兴吗?带你认识科技品牌 刷新认知
  18. 【MATLAB】Matlab删除文件或者文件
  19. 2021用户行为分析领域最具商业合作价值企业盘点
  20. oracle amp lt是什么东西,在网页设计中amp;amp;nbsp;是什么意思

热门文章

  1. python摄像头动作捕捉_为动作捕捉设备写MOTIONBUILDER插件
  2. 微信小程序实现tab标签页的切换及动态的选中下划线移动
  3. VSCode如何返回上一步
  4. Postgresql的使用-1 创建数据库
  5. 头像加相框微信小程序
  6. 王阳明:心力是克服万难的本源(附提升心力的12种方法)
  7. 微信授权登陆跳转提示10003 redirect_uri域名与后台配置不一致
  8. Java框架面试题及答案
  9. 微信小程序快捷键和windows快捷键
  10. 清明节日期的计算方法