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

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

前言

本来网上教程很多,其实可以不用写,自己也是跟着这些教程做的。现在的知识更新的太快,踩了不少坑,就想写出来和大家分享下。希望能帮到大家。我的环境是 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 接口暴露的。 区块链相关的关注点关注下。

恒温 回复

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

恒温 #11 · 2019年10月09日 Author
皆非 回复

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

恒温 回复

wx 已加。 大佬带路啊

13楼 已删除
恒温 回复

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

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

恒温 #16 · 2021年08月06日 Author
xyh421 回复

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

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