美文网首页
第四题 搭建以太坊私有链环境

第四题 搭建以太坊私有链环境

作者: V1cttor | 来源:发表于2019-05-25 10:59 被阅读0次

    主要参考文档

    https://www.jianshu.com/p/e978535b1002
    默认操作目录为 /opt/module

    准备步骤

    1. 虚拟机安装Ubuntu(省略. 建议分配2G以上内存, 以下以Ubuntu 14.04.6 LTS 为例)
      更换更新源(省略, 可选, 加速安装过程)
      设置静态IP, 安装sshd
    sudo apt-get update
    sudo apt-get install openssh-server
    
    1. 安装nodejs, npm
      参考nodejs官网 https://nodejs.org/en/download/
      配置环境变量
    ubuntu@ubuntu:~$ node -v
    v8.16.0
    ubuntu@ubuntu:~$ npm -v
    6.4.1
    
    1. 安装go-ethererum
      sudo apt-get install software-properties-common
      sudo add-apt-repository -y ppa:ethereum/ethereum
      sudo apt-get update
      sudo apt-get install ethereum
    2. 创建私有链genesis.json
      创建Ethererum目录
    mdkir Ethererum
    cd Ethererum
    vim genesis.json
    
    {
        "nonce":"0x0000000000000042",
        "mixhash":"0x0000000000000000000000000000000000000000000000000000000000000000",
        "difficulty": "0x4000",
        "alloc": {},
        "coinbase":"0x0000000000000000000000000000000000000000",
        "timestamp": "0x00",
        "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
        "extraData": "0x",
         "config":{  
          "chainId":15,  
          "homesteadBlock":0,  
          "eip155Block":0,  
          "eip158Block":0  
        },  
        "gasLimit":"0xffffffff"
    }
    
    1. 初始化
    geth --datadir /opt/module/Ethererum/ init genesis.json
    geth --datadir /opt/module/Ethererum/ --identity "YXEtherum" --rpc  --rpcport "8545" --rpccorsdomain "*" --port 30303 --rpcapi db,eth,net,web3,miner,personal --networkid 10 --nodiscover console
    
    1. 挖矿
    INFO [01-27|11:48:34] IPC endpoint opened: ~/Ethererum/yx_data/geth.ipc
    INFO [01-27|11:48:34] HTTP endpoint opened: http://127.0.0.1:8545
    Welcome to the Geth JavaScript console!
    
    instance: Geth/YXEtherum/v1.7.3-stable/darwin-amd64/go1.9.3
     modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
    
    > INFO [01-27|11:48:37] Mapped network port                      proto=tcp extport=30303 intport=30303 interface="UPNP IGDv1-IP1"
    
    > eth.accounts // 查看当前账户
    []
    > personal.newAccount() // 创建新账户
    Passphrase:  // 输入密码
    Repeat passphrase: // 确认密码
    "0x77a4ee7daca8faecec59c52786dcac639dd6ab91"
    > eth.accounts 
    ["0x77a4ee7daca8faecec59c52786dcac639dd6ab91"] // 账户已创建
    > eth.getBalance(eth.accounts[0]) // 查看余额
    0
    > miner.start() // 开始挖矿
    INFO [01-27|11:53:37] Updated mining threads                   threads=0
    INFO [01-27|11:53:37] Transaction pool price threshold updated price=18000000000
    INFO [01-27|11:53:39] Generating DAG in progress               epoch=0 percentage=0 elapsed=1.691s
    INFO [01-27|11:53:41] Generating DAG in progress               epoch=0 percentage=1 elapsed=3.465s
    INFO [01-27|11:53:43] Generating DAG in progress               epoch=0 percentage=2 elapsed=5.187s
    ...
    ...
    INFO [01-27|12:00:55]  mined potential block                  number=3 hash=856ca2…60597c
    INFO [01-27|12:00:55] Commit new mining work                   number=4 txs=0 uncles=0 elapsed=209.521µs
    > miner.stop() // 挖出矿的时候,就可以停止了
    true
    > eth.getBalance(eth.accounts[0]) 
    15000000000000000000 
    > web3.fromWei(eth.getBalance(eth.accounts[0]), "ether");
    15 // 账号已经有15个以太了,有以太我们就可以做交易了。
    > exit 退出
    

    部署合约

    1. 搭建环境, 安装ganache-cli
    alias cnpm="npm --registry=http://registry.npm.taobao.org \
    --cache=$HOME/.npm/.cache/cnpm \
    --disturl=http://dist.cnpmjs.org \
    --userconfig=$HOME/.cnpmrc" # 使用淘宝镜像加快安装速度
    cnpm install -g ganache-cli 
    

    2.运行ganache-cli

    >ganache-cli
    Ganache CLI v6.0.3 (ganache-core: 2.0.2)
    
    Available Accounts
    ==================
    (0) 0x54a2d27c4b30139b538bf887982aae64cfa3c7a3
    (1) 0x2d221a7ca36bcbb30ccd574104812539721ceed8
    ...
    
    Private Keys
    ==================
    (0) 930186bf51b9d503e82cc6e9a1f8adaea58b249278fcf4ca42d7635b3195057f
    (1) e769615ea9103ec9f13a7bfe2f0e56b3337e0123298c78404d18c721abde3025
    ...
    
    HD Wallet
    ==================
    Mnemonic:      bar quit tobacco ring process twice kangaroo eye verify badge lazy phrase
    Base HD Path:  m/44'/60'/0'/0/{account_index}
    
    Listening on localhost:8545 // 注意这里的地址和端口号,默认8545,和 geth 一样,如果 geth 开启着,要关闭 geth,或者启用不同的端口号。
    
    1. 安装truffle(以下面为准, 不要参考开头的文档, 会出现版本问题)
      tree工具也是要单独安装, 没有也不影响
    >cnpm install -g truffle@4.1.10 
    //如果出现错误, 可以直接clone他给出的github地址
    >mkdir solidity-experiments
    >cd solidity-experiments/
    >truffle init
    >tree
    .
    ├── contracts
    │   └── Migrations.sol
    ├── migrations
    │   └── 1_initial_migration.js
    ├── test
    ├── truffle-config.js
    
    

    合约编译, 合并过程会以truffle-config.js为准, 修改该文件指定处:


    image.png
    image.png
    1. 编译发布
    >truffle compile # 编译合约
    >truffle migrate # 确保 ganache-cli 已开启
    Using network 'development'.
    
    Running migration: 1_initial_migration.js
      Deploying Migrations...
      ... 0x2a658b01d6...7ff
      Migrations: 0x38f1873ed43e7c6ce8a4eb78116c2bd186f6d3b0
    Saving successful migration to network... # migration 发布成功
      ... 0x6451ee5b....be4
    

    发布成功,然后我们就可以开始编写 solidity 合约,这里以 greeter demo 为例,运行

    truffle create contract Greeter
    
    
    1. 编写合约
    pragma solidity ^0.4.24; // 指定 solidity 版本
    
    contract Greeter         // The contract definition. A constructor of the same name will be automatically called on contract creation. 
    {
        address creator;     // At first, an empty "address"-type variable of the name "creator". Will be set in the constructor.
        string greeting;     // At first, an empty "string"-type variable of the name "greeting". Will be set in constructor and can be changed.
    
         // 构造函数
        function Greeter(string _greeting) public  
        {
            creator = msg.sender;
            greeting = _greeting;
        }
    
         // 只读函数
        function greet() constant public returns (string)          
        {
            return greeting;
        }
        
        function getBlockNumber() constant public returns (uint) // this doesn't have anything to do with the act of greeting
        {                                                   // just demonstrating return of some global variable
            return block.number;
        }
        
        // 非只读函数
        function setGreeting(string _newgreeting) public
        {
            greeting = _newgreeting;
        }
        
        // 自毁函数
        function kill() public
        { 
            if (msg.sender == creator)  // only allow this action if the account sending the signal is the creator
                selfdestruct(creator);       // kills this contract and sends remaining funds back to creator
        }
    
    }
    

    保存之后,编辑文件 migrations/2_deploy_contracts.js,如果没有则新建一个,文件内容如下:

    var Greeter = artifacts.require("./Greeter.sol");
    
    module.exports = function(deployer) {
      deployer.deploy(Greeter,"Hello World");
    };
    

    然后重新编译、部署:

    >truffle compile # 编译
    Compiling ./contracts/Greeter.sol...
    Compiling ./contracts/greeter.sol...
    Writing artifacts to ./build/contracts // 编译后的 json 文件存放在此目录下。
    
    >truffle migrate --reset # 发布
    Compiling ./contracts/Greeter.sol...
    Writing artifacts to ./build/contracts
    
    Using network 'development'.
    
    Running migration: 1_initial_migration.js
      Replacing Migrations...
      ... 0x9eca7628a5a47....c4e
      Migrations: 0xfae368dec758a241f610333cdbd2944009fe23be
    Saving successful migration to network...
      ... 0x74406ca1....ce5
    Saving artifacts...
    Running migration: 2_deploy_contracts.js
      Replacing Greeter...
      ... 0x081c7a46529....3dd
      Greeter: 0xb0d9df51125b0b7d58ec06f1af9e957dff7314ac # Greeter 合约地址
    Saving successful migration to network...
      ... 0x2e2396da9....764
    Saving artifacts...
    

    Greeter 合约部署完成,Greeter 的地址为 0xb0d9df51125b0b7d58ec06f1af9e957dff7314ac,可通过这个地址和合约进行交互,运行 truffle console

    >truffle console
    truffle(development)> var greeter = Greeter.at(Greeter.address)
    undefined
    truffle(development)> greeter.address
    '0x52e4b9ecd911843e5c2550df6458374480e5483d'
    truffle(development)> greeter.greet()
    'Hello World!'
    truffle(development)> greeter.setGreeting('Hello World!!!')
    { tx: '0xa6e0c1f376c005647d1e522740085979d710fceb3bb73883e8452c79274826d7',
      receipt: 
       { transactionHash: '0xa6e0c1f376c005647d1e522740085979d710fceb3bb73883e8452c79274826d7',
         transactionIndex: 0,
         blockHash: '0x9c0ccff9d47c894ef79fb13a507d37bbdd5f49d8ef7858c8b6dc20f34c7ed166',
         blockNumber: 9,
         from: '0x091127ffb8ecb383b80caca87f17dbfba7fed05c',
         to: '0x52e4b9ecd911843e5c2550df6458374480e5483d',
         gasUsed: 33688,
         cumulativeGasUsed: 33688,
         contractAddress: null,
         logs: [],
         status: '0x1',
         logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
         v: '0x1b',
         r: '0xa4c72524e7d107e6a04cd6f55c4988f1d1a191cc1d05c0f72c43eb035fa0efb0',
         s: '0x25151b7fbfc30636ee1c96f45d7b288efdecb8fa3ccf318d2c3f377b7919836d' },
      logs: [] }
    truffle(development)> greeter.greet()
    'Hello World!!!'
    
    1. 发布合约到私有链
      退出 ganache-cli,运行
    geth --datadir /opt/module/Ethererum/ --identity "YXEtherum" --rpc --rpcport "8545" --rpccorsdomain "*" --port 30303 --rpcapi "db,eth,net,web3" --networkid 10 --nodiscover --ethash.dagdir /opt/module/Ethererum/Ethash console
    
    // 解锁账号
    > personal.unlockAccount(eth.accounts[0], "yourpassword", 24*3600)
    true
    // 必须开启挖矿,否则合约无法提交、保存到区块链中。因为我们创建的私链中并没有其他节点处理交易。
    > miner.start() 
    

    然后在另一个窗口中运行 truffle migrate --reset,看到以下类似信息说明合约已成功部署。(要等到挖到矿以后才能部署, 耐心等待 :-D )

    Running migration: 2_deploy_contracts.js
      Deploying Greeter...
      ... 0xcafdaaf58....f70
      Greeter: 0x53410cc....69e # 合约地址
    Saving successful migration to network...
      ... 0x63026be34589....eea
    

    如何在私有链中查看合约? 拷贝 truffle compile 编译后的 build/contracts/Greeter.json 文件中的 abi 串,

    可以去https://www.json.cn/# 将json串压缩一下

    image.png
    然后在 geth console 窗口中,执行以下命令
    > var abi = JSON.parse('[{"inputs":[{"name":"_greeting","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[],"name":"greet","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getBlockNumber","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newgreeting","type":"string"}],"name":"setGreeting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]')
    undefined
    > var greeter = eth.contract(abi).at('0xb0d9df51125b0b7d58ec06f1af9e957dff7314ac')//这里的0xb0d9df51125b0b7d58ec06f1af9e957dff7314ac是合约发布的地址
    undefined
    > greeter.greet()
    "Hello World!"
    

    运行截图:


    image.png

    其他参考文档

    相关文章

      网友评论

          本文标题:第四题 搭建以太坊私有链环境

          本文链接:https://www.haomeiwen.com/subject/fyrazqtx.html