【运维老鸟中秋新作】以太坊联盟链-多节点私链搭建手册

修订日期 姓名 邮箱 2018-09-23 brucefeng [email protected]

一. 前言

这半个月都在处理其他的事情,没来得及更新博客,今天看了下最近的博客访问量增加不少,说明51CTO的小伙伴们对区块链的兴趣程度还是极大的,但是考虑到前面的几篇文章更多的都是关注于开发层面,而作为运维出身的笔者很清楚51CTO上面的大部分读者还是运维同学,所以在中秋节到来之际,写一篇运维同学比较感兴趣也比较有兴趣去学习的文章。

说实话,最近这大半年,区块链的圈子一直非常火(我指的是技术圈子,跟业务无关),不仅仅是区块链开发方向,区块链运维也是蛮紧俏的,因为除了需要掌握传统的DevOps技术之外(此处的传统并不是老技术,特指运维必备技能统称),更要熟悉区块链层面的相关软件或者平台,比如以太坊与超级账本的私有化搭建与部署,当然现在最火爆的还是对以太坊的研究。

二. 环境配置

1.配置操作系统环境

本文的操作环境是在虚拟机上完成,共计三台虚拟机(配置尽量高上去,如下这个配置挖矿太耗时)

主机名 IP地址 操作系统 内存/GB CPU/核
nodeA.brucefeng.com 172.16.222.189 Ubuntu18.04 LTS 2 2
nodeB.brucefeng.com 172.16.222.190 Ubuntu18.04 LTS 2 2
nodeC.brucefeng.com 172.16.222.191 Ubuntu18.04 LTS 2 2

以nodeA为例进行相关配置,其他节点配置操作相同

(1) 更新软件源

根据自己需要选择是否需要更换软件源,此处用的是原生的即可。

$ sudo apt-get  update

(2) 安装相关工具

sudo apt-get  install vim openssh-server ntp ntpdate make gcc net-tools  -y

(3) 配置主机名

$ sudo hostname nodeA.brucefeng.com

(4) 配置地址解析

$ vim /etc/hosts
127.0.0.1       localhost
172.16.222.189  nodeA.brucefeng.com
172.16.222.190  nodeB.brucefeng.com
172.16.222.191  nodeC.brucefeng.com

hostname --fqdn验证

$ hostname -f
nodeA.brucefeng.com

(5) 同步时间

  • 修改时区
$ sudo timedatectl set-timezone "Asia/Shanghai" 
  • 手动同步
$ sudo ntpdate time1.aliyun.com    
  • 同步硬件时间
$ sudo hwclock  -w # 系统时间同步至硬件

手动设置完毕后,再通过如下方式进行ntp服务的配置,可以选择现有或者自建的时间服务器

  • 测试连通性
$ ntpdate -q time1.aliyun.com
server 203.107.6.88, stratum 2, offset 0.050751, delay 0.06232
22 Sep 21:04:36 ntpdate[8082]: adjust time server 203.107.6.88 offset 0.050751 sec 
  • 修改配置文件
$ sudo cp /etc/ntp.conf  /etc/ntp.conf_brucefeng_201809231208 #备份配置文件
$ sudo vim /etc/ntp.conf //修改配置文件

修改信息如下

# Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board
# on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for
# more information.
#pool 0.ubuntu.pool.ntp.org iburst
#pool 1.ubuntu.pool.ntp.org iburst
#pool 2.ubuntu.pool.ntp.org iburst
#pool 3.ubuntu.pool.ntp.org iburst

server time1.aliyun.com
server time2.aliyun.com
server time3.aliyun.com
server time4.aliyun.com
server time5.aliyun.com
server time6.aliyun.com
server time7.aliyun.com
  • 启动ntp服务
$ sudo systemctl  restart ntp  #启动ntp服务

2.配置Golang环境

如下操作在三台机器上均需要执行完毕

(1) 下载go安装包

$ mkdir ethereum ;cd ethereum
$ wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz

(2) 解压安装包

$ sudo tar zxvf  go1.11.linux-amd64.tar.gz   -C /usr/local/

(3) 配置环境变量

$  mkdir -p ~/workspace/{src,pkg,bin}
$ sudo cp  /etc/profile /etc/profile_brucefeng_201809231354
$ sudo vim /etc/profile 

添加如下配置

#Setting For Golang
export GOROOT="/usr/local/go"
export GOPATH="/home/ubuntu/workspace"
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin

(4) 检查配置

$ source /etc/profile
$ go env

出现如下信息表示安装完毕

GOARCH="amd64"
GOBIN="/home/ubuntu/workspace/bin"
GOCACHE="/home/ubuntu/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/ubuntu/workspace"
GOPROXY=""
......

三. 安装部署

1.获取源代码

以太坊的源码文件网址如下

https://github.com/ethereum/go-ethereum

可以选择通过git clone或者下载zip包的方式进行源代码的获取,为了方便起见,本文直接下载zip包上传至三台节点进行解压部署。

(1) 下载源码包

$ cd /home/ubuntu/ethereum
$ wget  https://github.com/ethereum/go-ethereum/archive/master.zip

(2) 解压源码包

$ unzip master.zip
$ mkdir ~/workspace/github.com/
$ mv go-ethereum-master/   ~/workspace/github.com/go-ethereum
$ cd ~/workspace/github.com/go-ethereum ; make geth  #编译安装

(3) 添加环境变量

$ sudo vim /etc/profile

添加并修改如下信息

export GETH="$GOPATH/github.com/go-ethereum/build"
export PATH=$PATH:$GOROOT/bin:$GETH/bin

(4) 测试生效

$ source /etc/profile
$ geth --help

2.创建创世区块

(1) 创建数据存储目录

$ mkdir -p /home/ubuntu/nodeA/data0
$ cd /home/ubuntu/nodeA

(2) 创世区块配置文件genesis.json

{
"config": {
        "chainId": 66,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
  "alloc"      : {},
  "coinbase"   : "0x0000000000000000000000000000000000000000",
  "difficulty" : "0x20000",
  "extraData"  : "",
  "gasLimit"   : "0x2fefd8",
  "nonce"      : "0x0000000000000042",
  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash" :"0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp"  : "0x00"
}

(3) 初始化创世区块

$ geth  --datadir data0/  init genesis.json

3.启动服务

$ geth --datadir data0/ --networkid 66 --nodiscover console
  • nodiscover :设置为不自动发现,用于控制联盟链的节点加入

Welcome to the Geth JavaScript console! 显示启动成功

4.节点通信

(1) 查看集群节点

> admin.peers
[]

目前为空状态,表明未于其他节点进行通信。

(2) 获取节点信息

> admin.nodeInfo.enode

分别在三个节点的console上执行命令,显示如下:

NodeA

"enode://d0d6a32cacb349c8f8c92372dc3a1e118384720636519a46c14067a3b62f6cfa8[email protected][::]:30303?discport=0"

NodeB

"enode://d9fc148c9808fbfee7954bd3324bfdff42777de7d2545ac3c2357f05939dbd8ee[email protected][::]:30303?discport=0"

NodeC

"enode://246782d2429f4697e18009505989ed82c2c0a664aab96ed80b96e28be42b6d9e2[email protected][::]:30303?discport=0"

(3)将NodeB加入NodeA

在NodeA节点上执行如下命令

>admin.addPeer("enode://d9fc148c9808fbfee7954bd3324bfdff42777de7d2545ac3c2357f05939dbd8ee[email protected]172.16.222.190:30303")

返回true表示加入成功

注意点

  • 将[::]修改为正确节点的IP地址(此处不支持DNS解析的域名)
  • 删除discport=0

(4) 查看新加入的节点

> admin.peers

在NodeA节点上执行如下命令

通过查看localAddress跟remoteAddress查看节点关联信息。

在NodeB节点上执行如下命令

在NodeC节点上执行如下命令

> admin.peers
[]

(5) 将NodeC加入NodeA与NodeB

在NodeA节点上执行如下命令

>admin.addPeer("enode://246782d2429f4697e18009505989ed82c2c0a664aab96ed80b96e28be42b6d9e2[email protected]172.16.222.191:30303")

在NodeB节点上执行如下命令

>admin.addPeer("enode://246782d2429f4697e18009505989ed82c2c0a664aab96ed80b96e28be42b6d9e2[email protected]172.16.222.191:30303")

(6) 查看节点加入信息

在NodeA节点上执行如下命令

在NodeB节点上执行如下命令

在NodeC节点上执行如下命令

注意: 节点关机后,会自动被删除,节点重新启动后,会自动加入节点集群,但是如果所有节点全部断掉,则需要重新添加。

四.转账测试

1.创建账户

(1) 查看当前节点上的账户

> personal.listAccounts

或者

> eth.accounts

(2) 创建新账户

> personal.newAccount("brucefeng1991")
"0xcd3d95c64394452313b539a1f2de54eab2b80eed"
> personal.newAccount("brucefeng1992")
"0xc4f132a71da05257a71ae5872beabd12c50dbb81"

(3) 查看创建的账户

> personal.listAccounts
["0xcd3d95c64394452313b539a1f2de54eab2b80eed",
"0xc4f132a71da05257a71ae5872beabd12c50dbb81"]

查看账户地址

> personal.listWallets

(4) 查看挖矿账户

> eth.coinbase
INFO [09-23|18:17:20.246] Etherbase automatically configured       address=0xcD3d95c64394452313b539a1f2dE54Eab2B80eEd
"0xcd3d95c64394452313b539a1f2de54eab2b80eed"

默认情况下,平台会选择创建的第一个账户作为挖矿账户(coinbase),可以通过miner.setEthbase()进行coinbase账户的设置。

2.挖矿测试

注意:在执行挖矿命令之前,务必在节点上面设置挖矿账户(coinbase),否则会报错Error: etherbase missing: etherbase must be explicitly specified

(1) 账户信息

NodeA

["0xcd3d95c64394452313b539a1f2de54eab2b80eed", "0xc4f132a71da05257a71ae5872beabd12c50dbb81"]

NodeB

["0x22160d844b4016ed8f45ce63c405de72b1946696", "0x23e80b2f1f74fc6da4bcb015d17ed642bcc98c06"]

NodeC

["0xa37539c0f41fea23c81f65b196df825202bc3bb5", "0x3c9cdb2f29606a0b35ae95b51521a41bb5b48e27"]

(2) 直接挖矿

> miner.start()
INFO [09-23|18:57:41.223] Updated mining threads                   threads=6
INFO [09-23|18:57:41.223] Transaction pool price threshold updated price=1000000000
null
> INFO [09-23|18:57:41.225] Commit new mining work                   number=1 sealhash=b16ebe…9b0094 uncles=0 txs=0 gas=0 fees=0 elapsed=794.985μs
> INFO [09-23|18:57:52.671] Successfully sealed new block            number=1 sealhash=b16ebe…9b0094 hash=082473…eb94b6 elapsed=11.446s
INFO [09-23|18:57:52.671] ined potential block                  number=1 hash=082473…eb94b6
INFO [09-23|18:57:52.672] Commit new mining work                   number=2 sealhash=7a67a7…3c98aa uncles=0 txs=0 gas=0 fees=0 elapsed=1.062ms
INFO [09-23|18:57:55.115] Successfully sealed new block            number=2 sealhash=7a67a7…3c98aa hash=c5cd53…c3e66b elapsed=2.443s
INFO [09-23|18:57:55.115] ined potential block                  number=2 hash=c5cd53…c3e66b
INFO [09-23|18:57:55.116] Commit new mining work                   number=3 sealhash=cc1414…f36ad7 uncles=0 txs=0 gas=0 fees=0 elapsed=343.53μs
INFO [09-23|18:57:55.166] Successfully sealed new block            number=3 sealhash=cc1414…f36ad7 hash=765d41…03ce17 elapsed=50.270ms
INFO [09-23|18:57:55.166] ined potential block                  number=3 hash=765d41…03ce17
INFO [09-23|18:57:55.167] Commit new mining work                   number=4 sealhash=cb5122…e36b2c uncles=0 txs=0 gas=0 fees=0 elapsed=718.996μs
INFO [09-23|18:57:58.048] Successfully sealed new block            number=4 sealhash=cb5122…e36b2c hash=ab1e6d…03b40b elapsed=2.881s
INFO [09-23|18:57:58.048] ined potential block                  number=4 hash=ab1e6d…03b40b
INFO [09-23|18:57:58.049] Commit new mining work                   number=5 sealhash=0dd5ab…5d47d9 uncles=0 txs=0 gas=0 fees=0 elapsed=159.

注意:尽量将虚拟机的配置调高一点,否则会出现以下这些信息,耗时非常久。

INFO [09-23|18:48:45.223] Updated mining threads                   threads=2
INFO [09-23|18:48:45.229] Transaction pool price threshold updated price=1000000000
INFO [09-23|18:48:45.230] Etherbase automatically configured       address=0x22160D844B4016eD8f45cE63C405DE72B1946696
null
> INFO [09-23|18:48:45.236] Commit new mining work                   number=1 sealhash=88e805…da6df6 uncles=0 txs=0 gas=0 fees=0 elapsed=4.290ms
INFO [09-23|18:48:48.930] Generating DAG in progress               epoch=0 percentage=0 elapsed=2.961s
INFO [09-23|18:48:51.895] Generating DAG in progress               epoch=0 percentage=1 elapsed=5.926s
INFO [09-23|18:48:54.739] Generating DAG in progress               epoch=0 percentage=2 elapsed=8.770s
..........无尽的等待.........
INFO [09-23|18:53:50.638] Generated ethash verification cache      epoch=0 elapsed=5m4.669s
INFO [09-23|18:54:08.357] Generating DAG in progress               epoch=1 percentage=0  elapsed=15.480s
INFO [09-23|18:54:19.874] Generating DAG in progress               epoch=1 percentage=1  elapsed=26.997s
INFO [09-23|18:54:29.911] Generating DAG in progress               epoch=1 percentage=2  elapsed=37.034s
..........无尽的等待.........
WARN [09-23|18:57:57.836] Discarded bad propagated block           number=1 hash=082473…eb94b6
INFO [09-23|18:57:58.398] Block synchronisation started
INFO [09-23|18:57:58.404] Mining aborted due to sync
INFO [09-23|18:57:58.611] Imported new state entries               count=1 elapsed=1.352ms   processed=1 pending=0 retry=0 duplicate=0 unexpected=0
INFO [09-23|18:57:58.870] Imported new block headers               count=4 elapsed=95.436ms  number=4 hash=ab1e6d…03b40b
INFO [09-23|18:57:58.889] Imported new chain segment               blocks=4 txs=0 mgas=0.000 elapsed=16.862ms  mgasps=0.000 number=4 hash=ab1e6d…03b40b cache=849.00B
INFO [09-23|18:57:58.892] Imported new block headers               count=1 elapsed=20.452ms  number=5 hash=75e595…4e4cc2
INFO [09-23|18:57:58.893] Imported new chain segment               blocks=1 txs=0 mgas=0.000 elapsed=316.348μs mgasps=0.000 number=5 hash=7
..........无尽的等待.........
INFO [09-23|19:07:35.250] Generated ethash verification cache      epoch=1 elapsed=13m42.368s
INFO [09-23|19:09:28.613] Successfully sealed new block            number=37 sealhash=95e0e0…ad356d hash=7506d6…015be8 elapsed=10m54.093s
INFO [09-23|19:09:28.614] ined potential block                  number=37 hash=7506d6…015be8
INFO [09-23|19:09:28.619] Commit new mining work                   number=38 sealhash=96b6b0…b3d462 uncles=0 txs=0 gas=0 fees=0 elapsed=662.942μs
INFO [09-23|19:12:33.104] Successfully sealed new block            number=38 sealhash=96b6b0…b3d462 hash=a91e1b…a15902 elapsed=3m4.484s
INFO [09-23|19:12:33.105] ined potential block                  number=38 hash=a91e1b…a15902
INFO [09-23|19:12:33.107] Commit new mining work                   number=39 sealhash=6bf2a3…0d8be3 uncles=0 txs=0 gas=0 fees=0 elapsed=2.170ms

(3) 停止挖矿

> miner.stop()

3.查询余额

NodeA

coinbase账户: 0xcd3d95c64394452313b539a1f2de54eab2b80eed

> eth.getBalance(eth.coinbase)
180000000000000000000

或者

> eth.getBalance(eth.accounts[0])
180000000000000000000

或者对结果进行单位转换

>  web3.fromWei(eth.getBalance(eth.accounts[0]),‘ether‘)
180

NodeB查询NodeA的coinbase账户

> eth.getBalance("0xcd3d95c64394452313b539a1f2de54eab2b80eed")
180000000000000000000

NodeC查询NodeA的coinbase账户

> eth.getBalance("0xcd3d95c64394452313b539a1f2de54eab2b80eed")
180000000000000000000

同样,在NodeA和NodeC上面同样可以查询NodeB上面账号地址的余额。

4.交易转账

场景: NodeA(原有额度:180)的挖矿地址向NodeB(原有额度:10)的挖矿地址转入2 ETH

(1) 解锁账户

在进行交易转账之前,我们需要对交易转出方的账户进行解锁操作。

NodeA上执行命令

> personal.unlockAccount("0xcd3d95c64394452313b539a1f2de54eab2b80eed")
Unlock account 0xcd3d95c64394452313b539a1f2de54eab2b80eed
Passphrase:
true

(2) 设置转账金额

将ETH转成Wei进行交易

> transferAmount= web3.toWei(2,‘ether‘)
"2000000000000000000"

(3) 执行转账

>eth.sendTransaction({from:"0xcd3d95c64394452313b539a1f2de54eab2b80eed",to:"0x22160d844b4016ed8f45ce63c405de72b1946696",value:transferAmount})

返回结果

INFO [09-23|20:13:20.968] Setting new local account                address=0xcD3d95c64394452313b539a1f2dE54Eab2B80eEd
INFO [09-23|20:13:20.968] Submitted transaction                    fullhash=0xd115c9ccfb1bfcc92faaf3ef6fae34ba670ef68cb03807d82d943141851985ce recipient=0x22160D844B4016eD8f45cE63C405DE72B1946696
"0xd115c9ccfb1bfcc92faaf3ef6fae34ba670ef68cb03807d82d943141851985ce"

(4) 查询交易池状态

> txpool.status
{
  pending: 1,
  queued: 0
}

(5) 执行挖矿

指定只挖一个区块

> miner.start()  ; admin.sleepBlocks(1),miner.stop()

(6) 查看结果

  • 查看交易池
> txpool.status

{
  pending: 0,
  queued: 0
}
  • 查看余额

NodeB的CoinBase账户余额

> web3.fromWei(eth.getBalance("0x22160d844b4016ed8f45ce63c405de72b1946696"),‘ether‘)
12

五.合约部署

用于测试的合约,我们可以沿用上一篇博客《以太坊智能合约项目-Token合约开发与部署中定义的Token合约。

pragma solidity ^0.4.24;

contract EIP20Interface{
    //获取_owner地址的余额
    function balanceOf(address _owner) public view returns (uint256 balance);
    //转账:从自己账户向_to地址转入_value个Token
    function transfer(address _to, uint256 _value)public returns (bool success);

    //转账:从_from向_to转_value个Token
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
    //允许_spender从自己(调用方)账户转走_value个Token
    function approve(address _spender, uint256 _value) returns (bool success);
    //自己_owner查询__spender地址可以转走自己多少个Token
    function allowance(address _owner, address _spender) view returns (uint256 remaining);

    //转账的时候必须要调用的时间,比如Tranfer,TransferFrom
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    //成功执行approve方法后调用的事件
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract BFCToken is EIP20Interface {
    //1.获取token名字,比如"BruceFeng Coin"
    string public name;
     //2.获取Token简称,比如"BFC"
    string public symbol;
    //3.获取小数位,比如以太坊的decimals为18
    uint8 public decimals;
     //4.获取token发布的总量,比如HT 5亿
    uint256 public totalSupply;

    mapping(address=>uint256) balances ;

    mapping(address=>mapping(address=>uint256)) allowances;
    function BFCToken(string _name,string _symbol, uint8 _decimals,uint256 _totalSupply) public{
    name = _name;
    symbol = _symbol;
    decimals = _decimals;
    totalSupply = _totalSupply;
    balances[msg.sender] = _totalSupply;
    }

    //获取_owner地址的余额
    function balanceOf(address _owner) public view returns (uint256 balance){
        return balances[_owner];
    }
    //转账:从自己账户向_to地址转入_value个Token
    function transfer(address _to, uint256 _value)public  returns (bool success){
        require(_value >0 && balances[_to] + _value > balances[_to] && balances[msg.sender] > _value);
        balances[_to] += _value;
        balances[msg.sender] -= _value;
        Transfer(msg.sender, _to,_value);

        return true;
    }

    //转账:从_from向_to转_value个Token
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success){
        uint256 allowan = allowances[_from][_to];
        require(allowan > _value && balances[_from] >= _value && _to == msg.sender && balances[_to] + _value>balances[_to]);
        allowances[_from][_to] -= _value;
        balances[_from] -= _value;
        balances[_to] += _value;
        Transfer(_from,_to,_value);
        return true;
    }
    //允许_spender从自己(调用方)账户转走_value个Token
    function approve(address _spender, uint256 _value) returns (bool success){
        require(_value >0 && balances[msg.sender] > _value);
        allowances[msg.sender][_spender] = _value;
        Approval(msg.sender,_spender,_value);
        return true;
    }
    //自己_owner查询_spender地址可以转走自己多少个Token
    function allowance(address _owner, address _spender) view returns (uint256 remaining){
        return allowances[_owner][_spender];
    }

}

1.获取信息

(1) 获取合约的ABI信息

[
    {
        "constant": true,
        "inputs": [],
        "name": "name",
        "outputs": [
            {
                "name": "",
                "type": "string"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_spender",
                "type": "address"
            },
            {
                "name": "_value",
                "type": "uint256"
            }
        ],
        "name": "approve",
        "outputs": [
            {
                "name": "success",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "totalSupply",
        "outputs": [
            {
                "name": "",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_from",
                "type": "address"
            },
            {
                "name": "_to",
                "type": "address"
            },
            {
                "name": "_value",
                "type": "uint256"
            }
        ],
        "name": "transferFrom",
        "outputs": [
            {
                "name": "success",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "decimals",
        "outputs": [
            {
                "name": "",
                "type": "uint8"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [
            {
                "name": "_owner",
                "type": "address"
            }
        ],
        "name": "balanceOf",
        "outputs": [
            {
                "name": "balance",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [],
        "name": "symbol",
        "outputs": [
            {
                "name": "",
                "type": "string"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "constant": false,
        "inputs": [
            {
                "name": "_to",
                "type": "address"
            },
            {
                "name": "_value",
                "type": "uint256"
            }
        ],
        "name": "transfer",
        "outputs": [
            {
                "name": "success",
                "type": "bool"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "constant": true,
        "inputs": [
            {
                "name": "_owner",
                "type": "address"
            },
            {
                "name": "_spender",
                "type": "address"
            }
        ],
        "name": "allowance",
        "outputs": [
            {
                "name": "remaining",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [
            {
                "name": "_name",
                "type": "string"
            },
            {
                "name": "_symbol",
                "type": "string"
            },
            {
                "name": "_decimals",
                "type": "uint8"
            },
            {
                "name": "_totalSupply",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "nonpayable",
        "type": "constructor"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": true,
                "name": "_from",
                "type": "address"
            },
            {
                "indexed": true,
                "name": "_to",
                "type": "address"
            },
            {
                "indexed": false,
                "name": "_value",
                "type": "uint256"
            }
        ],
        "name": "Transfer",
        "type": "event"
    },
    {
        "anonymous": false,
        "inputs": [
            {
                "indexed": true,
                "name": "_owner",
                "type": "address"
            },
            {
                "indexed": true,
                "name": "_spender",
                "type": "address"
            },
            {
                "indexed": false,
                "name": "_value",
                "type": "uint256"
            }
        ],
        "name": "Approval",
        "type": "event"
    }
]

通过http://www.bejson.com/zhuanyi/进行JSON压缩后的结果如下

[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_totalSupply","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]

在NodeA上执行命令,将以上ABI压缩字段复制给ABI变量

> ABI = [{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"},{"name":"_decimals","type":"uint8"},{"name":"_totalSupply","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]

(2) 获取合约对象

bruceToken = eth.contract(ABI)

(3) 获取合约二进制代码

通过BYTECODE获取Object信息

赋值的时候,切记在前面加上0x

> bruceHEX = "0x608060405234801561001057600080fd5b50604051610e97380380610e9783398101806040528101908080518201929190602001805182019291906020018051906020019092919080519060200190929190505050836000908051906020019061006a9291906100f1565b5082600190805190602001906100819291906100f1565b5081600260006101000a81548160ff021916908360ff1602179055508060038190555080600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050610196565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061013257805160ff1916838001178555610160565b82800160010185558215610160579182015b8281111561015f578251825591602001919060010190610144565b5b50905061016d9190610171565b5090565b61019391905b8082111561018f576000816000905550600101610177565b5090565b90565b610cf2806101a56000396000f300608060405260043610610099576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde031461009e578063095ea7b31461012e57806318160ddd1461019357806323b872dd146101be578063313ce5671461024357806370a082311461027457806395d89b41146102cb578063a9059cbb1461035b578063dd62ed3e146103c0575b600080fd5b3480156100aa57600080fd5b506100b3610437565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f35780820151818401526020810190506100d8565b50505050905090810190601f1680156101205780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561013a57600080fd5b50610179600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506104d5565b604051808215151515815260200191505060405180910390f35b34801561019f57600080fd5b506101a861061f565b6040518082815260200191505060405180910390f35b3480156101ca57600080fd5b50610229600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610625565b604051808215151515815260200191505060405180910390f35b34801561024f57600080fd5b50610258610957565b604051808260ff1660ff16815260200191505060405180910390f35b34801561028057600080fd5b506102b5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061096a565b6040518082815260200191505060405180910390f35b3480156102d757600080fd5b506102e06109b3565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610320578082015181840152602081019050610305565b50505050905090810190601f16801561034d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561036757600080fd5b506103a6600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610a51565b604051808215151515815260200191505060405180910390f35b3480156103cc57600080fd5b50610421600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3f565b6040518082815260200191505060405180910390f35b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104cd5780601f106104a2576101008083540402835291602001916104cd565b820191906000526020600020905b8154815290600101906020018083116104b057829003601f168201915b505050505081565b60008082118015610524575081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054115b151561052f57600080fd5b81600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60035481565b600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082811180156106f5575082600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410155b801561072c57503373ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16145b80156107b75750600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401115b15156107c257600080fd5b82600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555082600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555082600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b600260009054906101000a900460ff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60018054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a495780601f10610a1e57610100808354040283529160200191610a49565b820191906000526020600020905b815481529060010190602001808311610a2c57829003601f168201915b505050505081565b60008082118015610ae15750600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482600460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205401115b8015610b2b575081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054115b1515610b3657600080fd5b81600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555081600460003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820eac390c09a7095b2652ffac48f264fa4ad528bc27003ccd6b90fa2f33d8bb7820029"

2.执行部署

(1) 实例化Token合约

中秋节Token发给大家,祝大家中秋节快乐 :-)

bruceTokenBZQJT = bruceToken.new("Brucefeng ZHONGQIU Token ","BZQJT",18,8888000000000000000000,{from:eth.accounts[0],data:bruceHEX,gas:3000000})

参数信息

  • name : "Brucefeng ZHONGQIU Token "
  • symbol: BZQJT"
  • decimals: 18
  • totalSupply: 8888000000000000000000

记录下如下信息即可

  • 交易Hash: 0xe8118238fc7eeec6a8e3e07d8877b480fbe06716add30aa2cf4a5fa5629e1b3a
  • 合约地址: 0xc191EceD0ddf7D9aE883E24Ff6ed5fd6004c718F

(2) 打包交易,执行挖矿

查看交易池信息

> txpool.status
{
  pending: 1,
  queued: 0
}
> 

执行挖矿

miner.start()  ; admin.sleepBlocks(1),miner.stop()

3.测试合约

因为针对于合约的测试,在本文中并非是重点,所以,此处只进行简单的测试

(1) Token参数值

> bruceTokenBZQJT.name()
"Brucefeng ZHONGQIU Token "
> bruceTokenBZQJT.symbol()
"BZQJT"
> bruceTokenBZQJT.decimals()
18
> bruceTokenBZQJT.totalSupply()
8.888e+21

(2) Token转账操作

从当前NodeA的coinbase账户转账0.8个中秋Token到NodeB的coinbase账户

>bruceTokenBZQJT.transfer("0x22160d844b4016ed8f45ce63c405de72b1946696",800000000000000000,{from:eth.accounts[0],data:bruceHEX,gas:3000000})

查看NodeA,NodeB的coinbase账户中中秋Token的余额

4.节点同步

此处的节点同步并非同步合约到其他节点,合约在一台节点上部署完毕后,所有节点均已经同步,此处的节点同步代指在其他节点上面想要对合约进行相关的操作时需要准备的操作。

(1) 获取合约信息

  • 获取合约的ABI信息
  • 获取合约对象
  • 获取合约的二进制代码

以上三个步骤直接参照上文进行变量定义即可,只是不需要执行执行部署的操作了。

(2) 获取合约实例

通过合约地址直接可以获取合约实例

> TokenNodeB = bruceToken.at("0xc191EceD0ddf7D9aE883E24Ff6ed5fd6004c718F")

此时,可以在新的节点上面对合约进行任意功能内的测试与使用了。

六.附录

1. 创世区块配置文件参数说明

参数名 说明
chainId 指定独立的区块链网络ID,1-4为保留ID,其中1为主网ID,其余为测试网
alloc 用来设置账号以及账号的以太币数量,私有链可以不进行设置
coinbase 用于获取挖矿奖励的矿工账号
difficulty 设置挖矿的难度系数
extraData 附加信息,自定义即可
gasLimit 设置对gas的消耗总量的限制,私有链中可以填写任意数值(大数值)
nonce 用于进行挖矿的随机数
mixhash 与nonce配合使用,用于挖矿
parentHash 上一个区块的Hash值,由于该区块为创世区块,所以父Hash值为0
timestamp 时间戳

data0目录中的相关文件列表

  • chaindata : 存储区块数据
  • keystore: 存储账户数据

2. 私链服务启动常见参数说明

参数名 说明
identity 用于标识区块链的名称
init 用于指定创世区块的位置,并且创建创世区块以及相关目录结构
datadir 设置当前区块链网络数据存放的位置
port 区块链启动的监听端口,默认为30303
rpc 启用RPC服务,可以用于智能合约的部署与调试,默认监听127.0.0.1,端口为8545
rpcapi 设置RPC提供的API接口类型,一般为db,eth.net.web3
networkid 设置当前区块链的网络ID
nodiscover 设置节点不被自动发现,用于控制节点的加入
console 启用命令行模式,用于执行命令
help 帮助命令,所有参数的汇总

3.控制台命令说明

以太坊提供了一个交互式的JavaScript环境,可以在该环境中进行命令或者代码的执行操作,其中一些常用的以太坊JavaScript对象可以直接被调用。

对象名 说明
eth 操作区块链相关的方法
eth.accounts 查看当前系统中的所有账户地址
eth.getBalance() 查询账户余额,返回单位为Wei(1 ether=10^18Wei)
eth.blockNumber 列出区块总数
eth.getTransaction() 获取指定交易的状态信息
eth.getBlock() 获取指定区块的信息
net 用于查看p2p网络状态
admin 管理节点相关的方法
admin.peers 查看通讯的节点信息
admin.addPeer() 添加通讯P2P节点
miner 启动/停止挖矿相关方法
personal 用于管理账户
personal.newAccount() 创建账户
personal.unlockAccount() 解锁账户
txpool 查看交易池信息, txpool.status()
web3 包含了以上对象以及单位换算等方法
web3.fromWei() Wei换算成ether或者其他单位
web3.toWei() 将ether或者其他单位换算成Wei

原文地址:http://blog.51cto.com/clovemfong/2280872

时间: 2024-09-30 18:10:20

【运维老鸟中秋新作】以太坊联盟链-多节点私链搭建手册的相关文章

运维老鸟分享-学好Linux技术大绝招

随着互联网的飞速发展,越来越多的人开始学习Linux技术,很多初学者面对Linux技术的海洋无从下手,近10年一线互联网运维老鸟为菜鸟总结了学好Linux技能的大绝招: 1.基于vmware虚拟机安装Linux操作系统,首选CentOSLinux操作系统; 2.初学者完成Linux系统分区及安装之后,需熟练掌握Linux系统管理必备命令,命令包括:cd.ls.pwd.clear.chmod.chown.chattr.useradd.userdel.groupadd.vi.vim.cat.more

(转)运维老鸟教你安装centos6.5如何选择安装包

运维老鸟教你安装centos6.5如何选择安装包 原文:http://blog.51cto.com/oldboy/1564620 近来发现越来越多的运维小伙伴们都有最小化安装系统的洁癖,因此,找老男孩来咨询,这个"洁癖"好习惯啊,必须支持,,因此发布本文和大家分享下. (1)系统安装类型选择及自定义额外包组 进入如图2-28所示界面.上半部分是系统定制的不同的系统安装类型选择项,默认是"Desktop",这里我们选择"Minimal",即最小化安

运维老鸟教你安装centos6.5如何选择安装包

签:老男孩教育 Centos6.5安装选包 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://oldboy.blog.51cto.com/2561410/1564620 近来发现越来越多的运维小伙伴们都有最小化安装系统的洁癖,因此,找老男孩来咨询,这个"洁癖"好习惯啊,必须支持,,因此发布本文和大家分享下. (1)系统安装类型选择及自定义额外包组 进入如图2-28所示界面.上半部分是系统定制的不同的系统安装类型选择项,

运维老鸟分享linux运维发展路线规划【转】

linux运维发展路线常见的就是下面两条路线: 第一条:运维应用-->系统架构-->运维开发-->系统开发 第二条:运维应用-->应用dba-->架构dba-->开发DBA 下面详细每个阶段的职位说明(以北上广为例): 01.运维应用级别:这个阶段就是玩别人的软件,例如:linux,nginx,mysql,php,nagios  大多数的linux运维工程师,网络工程师,系统工程师都是这个阶段. 这个阶段的工资平均3-10K.处在这个阶段的伙伴们要注意了.这里属于金字塔

一个运维老鸟的年终总结述职报告

整理文档,偶然发现了老男孩于大约10年前写的年终工作述职报告,又到了年底了,希望这篇报告能发挥余热对大家写述职报告有帮助.      时间过的飞快,转眼间,来XXX一年出头了.这一年来让我感受了很多,经历了很多,学到了很多. 在领导的带领下,在同学们的配合和帮助下,我不断的学习新知识.总结新经验,努力加强着自身的素质和修养,完成了入职至今自己岗位上各项工作任务,简单汇报如下: 一.严以律己 从200x年x月x日加入公司以来,在平时工作中,我始终努力以工作高标准严格要求自己,严格遵守公司的各项规章

Windows下以太坊集成开发环境(Remix-IDE)搭建与智能合约的简单应用

前面我们介绍了在以太坊平台下开发区块链私有链的过程,以及在私有链下进行挖矿的操作,而随着区块链技术的发展,区块链技术已不仅限于比特币的应用,未来将重在着眼于向其他领域的扩展推广,以此开启区块链2.0以智能合约为代表的时代.本文选用remix作为开发应用平台,配合geth客户端实现与以太坊网络的交互,下一篇文章则改用truffle和ganache搭建开发框架(这是后话). 本文分为remix-ide搭建和智能合约部署应用两部分. 一.remix-ide搭建 [准备工作] 1.安装Node.js.N

Linux系统从新手到运维老鸟学习指南

Linux是在1990年底到1991年由芬兰大学的学生LinusTorvalds利用Minix操作系统作为开发平台编写了内核,目前由世界各地的爱好者共同开发和维护的与UNIX兼容的操作系统,也是自由和开放源代码的类Unix操作系统.Linux的标志和吉祥物是一只可爱.友善的企鹅,名字叫Tux.现在随着Linux应用的极速扩展越来越多的朋友开始接触到Linux,我们中的大部分平时都习惯使用Windwos这时候往往会有很茫然的感觉,不晓得从哪开始学起.这里介绍对于Linux我是怎么样从一无所知的菜鸟

运维之我的docker-swarm集群中删除节点和服务

删除swam节点 如果有的确实想要从swarm集群中删除,你应该先把这个节点容器排空,然后再把节点从集群中去掉. 排空节点(其实就是把这个节点上的容器先从其它节点启动,再停掉排空节点上的容器,保证你定义服务的预先状态不受影响) docker node update --availability drain g36lvv23ypjd8v7ovlst2n3yt 删除指定节点 docker node rm  node9 docker node rm --force node9 删除服务 删除服务以后容

[区块链]以太坊手动添加静态节点

如果每次都向某个节点同步区块,可以手动的添加为静态节点,这样可以大大的提高同步效率 这里套用一下https://blog.csdn.net/weixin_40903789/article/details/79619646的私链,感谢,我就不用再创建虚拟机了做静态节点了 作用默认大家已经安装好了mist,下载地址,它是一个集web3和钱包的工具,默认也会有geth的安装,当然也可以使用上述地址geth的安装方法 创世的文件来一个,必须套用别人的,地址 下载完成后,为了方便我把它放在了geth的同级