帮助老师撰写以太坊课程的实验指导书,因此需要设计一个基于以太坊私链的溯源Dapp项目。

项目源码:https://github.com/HeXueZhi/FoodTransportation

实验环境:

  • win10:用于创建Dapp
  • CentOS7:用于搭建私链

一、私链的创建

前面的文章有写如何搭建私链。

以太坊搭建私链

二、以太坊Dapp的创建

Dapp整体基于truffle,前端采用webpack打包。

2.1 编写合约

合约编写以及编译采用remix(需要较好的网络环境),推荐使用老版本界面。remix入门

合约代码:

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
pragma solidity >=0.4.22 <0.7.0;

contract FoodTransportation{
struct Location{
string locationName;
string transPerson;
uint timeStamp;
}
string foodName;

mapping (uint => Location) trail;
uint8 locationNum;

function addNewLocation(string memory food,string memory locationName,string memory transPerson)public{
if(bytes(foodName).length == 0){
foodName = food;
}
Location memory newLocation;
newLocation.locationName = locationName;
newLocation.transPerson = transPerson;
newLocation.timeStamp = now;
trail[locationNum] = newLocation;
locationNum++;
}

function getLocationNum() public view returns(uint8){
return locationNum;
}

function getFoodName() public view returns(string memory){
return foodName;
}

function getLocation(uint8 locationNo) public view returns(string memory,string memory,uint){
return (trail[locationNo].locationName,trail[locationNo].transPerson,trail[locationNo].timeStamp);
}
}

这一步需要完成合约的编译和测试。

2.2 环境准备

win10系统中,安装node、truffle、ganache-cli。

执行truffle version查看版本。

{% image https://i.loli.net/2020/08/15/9PmGtVHWqx5iZhc.png 'truffle version' '' %}

尤其需要注意solidity和web3的版本。版本不同语法支持也不同,所以安装时,尽量选择于上图中相差不多的版本。

2.3 truffle+webpack创建项目

  1. 新建Dapp/FoodTransportation文件夹

  2. 文件夹下执行:

    1
    truffle unbox webpack

    此命令会下载truffle提供的官方示例,下载时间可能会有点长,耐心等待。下载完成后的提示以及目录结构如下图所示。

    download truffle-webpack

    此示例项目的运行启动:留个坑。

  3. 修改truffle-config.js为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    require('babel-register')
    module.exports = {
    networks: {
    development: {
    host: 'localhost',
    port: 8545,
    network_id: '*' // Match any network id
    }
    }
    }

    本文件夹下的powershell中执行:

    1
    npm install babel-register
  4. 删除contracts文件夹中的ConvertLib.solMetaCoin.sol文件,创建FoodTransportation.sol合约文件,复制刚才编写的合约代码。

  5. 修改migrations文件夹中的2_deploy_contracts.js文件。

    注意:这里直接删除这个文件也无妨,因为本项目使用web3来部署合约,不需要使用truffle migrate命令帮助部署合约。

    1
    2
    3
    4
    5
    const FoodTransportation = artifacts.require("./FoodTransportation");

    module.exports = function(deployer) {
    deployer.deploy(FoodTransportation);
    };
  6. powershell中执行truffle compile命令。truffle中自带的solc-js会对合约进行编译。在Dapp文件夹下会出现build文件夹,存放编译形成的json文件。

  7. 在Dapp的app文件夹下粘贴写好的html文件,src目录下粘贴需要的js文件和css文件。

  8. 修改webpack-config.js

    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
    const path = require('path');
    const CopyWebpackPlugin = require('copy-webpack-plugin');

    module.exports = {
    entry: './src/app.js',
    output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'app.js'
    },
    mode : 'development',
    plugins: [
    // Copy our app's index.html to the build folder.
    new CopyWebpackPlugin([
    { from: './index.html', to: "index.html" }
    ])
    ],
    module: {
    rules: [
    {
    test: /\.css$/,
    use: [ 'style-loader', 'css-loader' ]
    },
    { test: /\.json$/, exclude: /(node_modules|bower_components)/, use: 'json-loader' },
    {
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    loader: 'babel-loader',
    query: {
    presets: ['es2015'],
    plugins: ['transform-runtime']
    }
    }
    ]
    }
    }
  9. 在app目录下执行:

    1
    2
    3
    4
    5
    6
    7
    8
    npm install web3@0.18.4 --save-dev
    npm install webpack --save-dev
    npm install style-loader css-loader json-loader --save-dev
    npm install -D babel-loader@7 babel-core babel-preset-env --save-dev
    npm install babel-preset-es2015 --save-dev
    npm install babel-plugin-transform-runtime --save-dev
    npm run build
    npm run dev
  10. 进入http://localhost:8080查看界面。注意:现在如果没有启动私链,页面由于没有获取到账户,会发出警告,启动私链,连接metamask刷新即可。

三、合约部署

3.1 win10本地ganache测试

  1. 安装ganache-cli

    1
    npm install -g ganache-cli
  2. 执行ganache-cli

    ganache-cli

  3. 在谷歌浏览器中安装metamask插件,安装好后,先在metamask右上角选择localhost:8545网络,然后选择助记词恢复钱包账户。

  4. 然后在Dapp/app执行npm run dev,打开浏览器的http://localhost:8080/

  5. 按F12,查看console界面。

  6. 测试项目。

3.2 CentOS私链测试

  1. 开启私链,如无账户,先创建账户personal.newAccount(),输入密码。

  2. 开始挖矿。miner.start(1)

  3. 查看账户余额eth.getBalance(eth.accounts[0]),为了保证能够发起合约部署等交易,需要一些ETH。

  4. 设置虚拟机防火墙,打开8545端口。CentOS设置防火墙

  5. metamask连接CentOS的私链。需要新创建rpc网络。

    • rpc地址:http://192.168.2.151:8545,ip填虚拟机ip就可以。
    • chainID:填入genesis.json中的chainid即可。
  6. 切换至刚创建的网络,并导入账户。通过虚拟机私链文件夹下的keystore文件夹下的json文件导入到metamask即可。

    image-20200815203841886

  7. 导入账户之后刷新http://localhost:8080,再点击metamask,就能够连接刚刚导入的账户了。

    项目截图
    项目截图
  8. 测试项目。

  9. 测试完成后执行miner.stop()停止挖矿。