区块链测试 以太坊 (Ethereum) 部署私链和合约

恒温 · 2019年10月03日 · 最后由 恒温 回复于 2021年08月06日 · 3569 次阅读

前言

本来网上教程很多,其实可以不用写,自己也是跟着这些教程做的。现在的知识更新的太快,踩了不少坑,就想写出来和大家分享下。希望能帮到大家。我的环境是 macOS majave。

环境准备

  1. go 环境,这个自行百度

  2. Ethereum

    1. 首先,先要安装 homebrew https://brew.sh/index_zh-cn.html
    2. 安装 Ethereum:这里用的是 ethereum 的 go 语言客户端
      1. brew tap ethereum/ethereum
      2. brew install ethereum
    3. 安装好了之后运行:geth version
    Geth
    Version: 1.9.5-stable
    Architecture: amd64
    Protocol Versions: [63]
    Network Id: 1
    Go Version: go1.13
    Operating System: darwin
    GOPATH=/Users/lihuazhang/go
    GOROOT=/usr/local/opt/go/libexec
    
    
  3. 安装以太坊编程语言 Solidity —— brew install solidity

  4. nodejs 环境 —— 自行百度,推荐使用 nvm

  5. 安装 truffle —— npm install –g truffle

准备以太坊私链节点

  1. 创建个目录:比如 ethereum,然后创建一个 json 文件 genesis.json

  2. 创世块配置文件:genesis.json

{
    "nonce": "0x0000000000000042",
    "difficulty": "0x400",
    "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "coinbase": "0x0000000000000000000000000000000000000000",
    "timestamp": "0x00",
    "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa",
    "gasLimit": "0x4c4b4000000",
    "config": {
        "chainId": 15,
        "homesteadBlock": 0,
        "eip150Block": 0,
        "eip155Block": 0,
        "eip158Block": 0,
        "byzantiumBlock": 0,
        "constantinopleBlock": 0,
        "petersburgBlock": 0
    },
    "alloc": {}
}

这里要特别注意:byzantiumBlock,constantinopleBlock,petersburgBlock 几个都要放进去。最新的以太坊版本已经在用 byzantiumBlock 了。如果不加的话,合约编译的时候就要指定拜占庭。否则合约执行的时候会返回莫名其妙的错误,这个坑我踩了很久。

  1. 执行 geth --datadir data/chain0 init genesis.json

  2. 再执行 geth --networkid 15 --datadir data/chain0 --identity "mychain00" --port 30000 --rpc --rpcaddr 0.0.0.0 --rpccorsdomain "*" --rpcport 8545 --rpcapi eth,net,web3,personal --allow-insecure-unlock --nodiscover console 参数自行百度

  3. 进入 console 之后,创建账号:personal.newAccount('123456') # 123456是密码

  4. 开始挖矿,输入 miner.start(),出现下面这种图标就算挖到了。

编写和部署合约

1) 在 ethereum 目录下创建一个目录比如 contracts,然后终端进入到这个 contracts 目录,执行 truffle init 会生成contractsmigrationstest三个目录和truffle-config.js文件

2) contracts 就是智能合约存放的目录,默认情况下已经帮你创建好Migrations.sol合约,不用管它在contracts文件夹下创建一个新文件HelloWorld.sol,文件内容如下:

pragma solidity >=0.4.21 <0.6.0;

contract HelloWorld {

  //say hello world
  function say() public pure returns (string memory ) {
    return "Hello World!";
  }

  //print name
  function print(string memory  name) public pure returns (string memory ) {
    return name;
  }

  function multiply(uint a) public pure returns(uint d) {
        return a * 7;
    }
}

3) 修改migrateions文件中2_deploy_contracts.js的内容,如下:

var HelloWorld = artifacts.require("./HelloWorld.sol");
module.exports = function(deployer) {
   deployer.deploy(HelloWorld);
};

4) 修改truffle-config.js的 networks 部分和 compile 部分内容如下:

development: {
 host: "localhost",     // Localhost (default: none)
 port: 8545,            // 前面部署链的端口
 network_id: "*",       // Any network (default: none)
 gas: 53170200,
 from: "0x4860a6d6f378df07d86a227a5d2a7f553ca68e50" //前面部署链的创建的账号的地址
},
compilers: {
    solc: {
      version: "0.4.25",    // Fetch exact version from solc-bin (default: truffle's version)
      docker: false,        // Use "0.5.1" you've installed locally with docker (default: false)
      settings: {          // See the solidity docs for advice about optimization and evmVersion
       optimizer: {
         enabled: false,
         runs: 200
       },
       evmVersion: "byzantium"
      }
    }
}

5) 编译合约:truffle compile

6) 部署合约:truffle migrate --reset --network development

7) 如果部署的时候,遇到 authentication needed: password or unlock 错误。请解锁账号:去 geth 那个终端执行 personal.unlockAccount(eth.accounts[0], "123456", 10000)

8) 运行部署命令之后,需要交易确认,这个时候需要继续挖矿,把交易打包到下一个区块,在 geth console 里运行 miner.start()

9) 部署成功的日志:

➜  contract truffle migrate --reset --network development

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.



Starting migrations...
======================
> Network name:    'development'
> Network id:      15
> Block gas limit: 0x359abe9aa9


1_initial_migration.js
======================

   Replacing 'Migrations'
   ----------------------
   > transaction hash:    0x6df6bc66f92db8100b6ee015b6277227585752e097d08639295a5303938d4501
   > Blocks: 0            Seconds: 4
   > contract address:    0xAE36440bDbEF7FbFc71dC6508D42E381F80851D8
   > block number:        3200
   > block timestamp:     1570087488
   > account:             0xb36CFa79Ccd84694C6372E94aDF76ae83c09685D
   > balance:             6400
   > gas used:            261393
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00522786 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00522786 ETH


2_deploy_contracts.js
=====================

   Replacing 'HelloWorld'
   ----------------------
   > transaction hash:    0x95687f6120bf9034ce2548c60645750bd38db05f7839c0fd5560ad5d624546ab
   > Blocks: 0            Seconds: 0
   > contract address:    0xE6b2d56B65E2d39B1Bb976bf11813c8366E2DE26
   > block number:        3204
   > block timestamp:     1570087493
   > account:             0xb36CFa79Ccd84694C6372E94aDF76ae83c09685D
   > balance:             6410
   > gas used:            240179
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00480358 ETH


   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00480358 ETH


Summary
=======
> Total deployments:   2
> Final cost:          0.01003144 ETH

调用合约

  1. 我们已经拿到了合约的地址:0xE6b2d56B65E2d39B1Bb976bf11813c8366E2DE26
  2. 我们要拿到 abi,在 build 目录下面找到对应的 HelloWorld.json,把 abi 那个数组拿出来,需要进行压缩。https://www.sojson.com/yasuo.html
  3. 然后到 geth console 下面把刚刚的挖矿给停了,敲 miner.stop(),别管刷的日志。
  4. 然后敲打:abi=[{"constant":true,"inputs":[],"name":"say","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"name","type":"string"}],"name":"print","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"}] 类似这样,你的 abi 和我不一样。
  5. 然后在输入:testContract=eth.contract(abi).at("0xE6b2d56B65E2d39B1Bb976bf11813c8366E2DE26")
  6. 就可以开始使用 testContract 了,试试看 testContract.say()
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 15 条回复 时间 点赞

开始区块链测试了?技术真是变化太快了

恒温 #15 · 2019年10月07日 Author
simonpatrick 回复

是啊,8 月份转了区块链测试了。

阿里也在做区块链?貌似好厉害的

区块链合约接口的话应该怎样测试呢?

期待大佬分享更多区块链测试的内容

今天第一天入职 区块链公司做测试,看了一天 合约、域名、接口,一脸懵逼,上这来看看,还真有相关的分享。虽然不太懂,但得学啊。

皆非 回复

嗯 你们是做公链吗?

程明远 回复

和普通的接口测试没啥区别,都有 rpc 接口暴露的。 区块链相关的关注点关注下。

恒温 回复

我们做的是公链,我现在还在熟悉合约这块。 刚进入这个行业,一切都是新的开始。

皆非 回复

可以多交流下。加我微信啊

恒温 回复

wx 已加。 大佬带路啊

4楼 已删除
恒温 回复

大楼,带我。我也是区块链

如何克服以太坊手续费太高问题呀

xyh421 回复

合约写的时候,要考虑开销治理。
目前想到的好像只有这个,其他的我也不知道

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册