0%

EOS学习笔记

简介

EOS: Enterprise Operation System 中文意思为:商业级区块链操作系统。EOS 项目的目标是建立可以承载商业级智能合约与应用的区块链基础设施,成为区块链世界的“底层操作系统”。

EOS通过石墨烯技术解决延迟和数据吞吐量问题,TPS可达到数千,交易的确认时间也只有数秒。同时声称未来使用并行链的方式,最高可以达到数百万TPS。此外,在 EOS 上转账交易及运行智能合约不需要消耗 EOS代币。而是EOS 系统当中,抵押代币获取对应的资源,来执行相应交易,在EOS运行程序完全免费的说是不准确的。

EOS底层使用的是石墨烯技术,石墨烯是一个开源的区块链底层库,采用的是 DPOS(Delegated Proof-of-Stake 股份授权证明机制 )的共识机制。DPOS为了提高出块速度TPS,限制了参与记账了人数,在DPOS中,记账者不称为矿工,而是改称为见证人Witness,现在EOS中,又有一个新词:Block Producer,简称BP,翻译为超级节点。

DPOS下节点需要参与见证人选举,只有赢得选举的节点才能负责出块,在EOS中,赢得选举的21个节点见证人轮流出块。另外还有100个备用见证人(候选节点),在21个见证人出现问题后做替补。EOS的发行总量是10亿,见证人在完成打包交易区块后,可以领取到区块的奖励,区块的奖励来自对发行量的通胀增发,通胀率每年接近5%。

钱包和账户

钱包

EOS钱包功能官方上定义很单一,仅仅存私钥公钥,提供私钥公钥生成和导入,其他的功能由EOS账户统一管理,比如代币查询、交易、合约功能都属于账户关联下的功能。

账户

EOS账号由一串自定义字符组成,与以太坊中不同。账户名下有EOS系统的代币和用户调用eosio.token合约创建的代币、合约和公钥等

钱包和账户关系

EOS里面的key是公私钥对成对出现的,key和password不是同一个概念,虽然看起来都是一串很长的字符,但是password是针对钱包wallet的,而key则是针对账户account的。

假如创建了钱包hearing,不等于已经在链上有了hearing这个账户,实际上wallet和account两者之间完全是没有关系的,只有当你将account的key放在wallet里的时候,它们两者之间才有了联系。EOS账户创建需要关联钱包公钥,账户创建可以使用同一个钱包公钥创建多个账户,但各个账户是独立的。可以理解成使用同一个密码创建了不同的账户,账户数据相互独立。

每一个account都会有两组公私钥对,对应该账户的两个角色——owner和active。所以我们每次创建账户的时候,都需要给新账户导入两个key进去。官方推荐用户平时使用 Active 私钥,把Owner 私钥离线保存。只有重大安全问题时需要用到 Owner 私钥。

权限

-p

创建钱包和账户

  1. 开启keosd

    1
    $ keosd &
    1
    $ pkill keosd
  2. 开启nodeos

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ nodeos -e -p eosio \
    --plugin eosio::producer_plugin \
    --plugin eosio::chain_api_plugin \
    --plugin eosio::http_plugin \
    --plugin eosio::history_plugin \
    --plugin eosio::history_api_plugin \
    --access-control-allow-origin='*' \
    --contracts-console \
    --http-validate-host=false \
    --verbose-http-errors \
    --filter-on='*' >> nodeos.log 2>&1 &
  3. 钱包操作

    1
    2
    3
    4
    5
    6
    7
    $ cleos wallet list   # 查看钱包
    $ cleos wallet create --to-console/--file -n hearing # 创建钱包,生成私钥,-n指定钱包名,默认名为default
    $ cleos wallet open # 打开钱包
    $ cleos wallet unlock # 解锁钱包,需要提供钱包私钥
    $ cleos wallet create_key # 在钱包中创建私钥
    Created new private key with a public key of: "EOS7qyuXyBtqMYLYBveB3APTiWeyu1d6Z4mTLX1mMP5ZU3kWUqXcJ"
    $ cleos wallet keys # 查看钱包的keys
  4. 导入开发者Key

    每个新的EOSIO链都有一个名为“eosio”的默认“系统”账户。此帐户用于通过加载系统合同来设置链,该合同规定了EOSIO链的治理和共识。每个新的EOSIO链都带有一个开发密钥,这个密钥是相同的(5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3)。这个账户在我看来就是一个使用5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3秘钥对创建的,所以开发者需要把它导入到某个钱包,并得到对应的公钥。

    1
    $ cleos wallet import --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3   # 将开发者私钥导入到default钱包,会输出对应的公钥,可通过-n指定钱包
  5. 创建秘钥

    1
    2
    3
    $ cleos create key --to-console
    Private key: 5KRuAjE9xf6zK3AeMTZa9yLCZMQmhaBxuZePRtdUnWqB5nkd5Jk
    Public key: EOS8XaSdS9EieYyWuAfUma7cmB4TEuPWjcU8mpMRR2jztuwd1Cs2a
    1
    2
    3
    $ cleos create key --to-console
    Private key: 5J3BgEZ168EEP9shdnWBhZsPZRAfjjpUyKVxx1qjezXzJW9bEZv
    Public key: EOS81sw5LyVND1KjYoGA7iYNSo9ezgyucEjNzVAP1bPBHRdgkJo29
  6. 向wallet导入秘钥

    1
    2
    $ cleos wallet import -n hearing --private-key 5J3BgEZ168EEP9shdnWBhZsPZRAfjjpUyKVxx1qjezXzJW9bEZv
    imported private key for: EOS81sw5LyVND1KjYoGA7iYNSo9ezgyucEjNzVAP1bPBHRdgkJo29
    1
    2
    $ cleos wallet import -n hearing --private-key 5KRuAjE9xf6zK3AeMTZa9yLCZMQmhaBxuZePRtdUnWqB5nkd5Jk
    imported private key for: EOS8XaSdS9EieYyWuAfUma7cmB4TEuPWjcU8mpMRR2jztuwd1Cs2a
  7. 创建账户

    1
    $ cleos create account [OPTIONS] creator name OwnerKey [ActiveKey]  # 命令中的key为public-key
    1
    2
    $ cleos create account eosio hearing EOS81sw5LyVND1KjYoGA7iYNSo9ezgyucEjNzVAP1bPBHRdgkJo29 EOS8XaSdS9EieYyWuAfUma7cmB4TEuPWjcU8mpMRR2jztuwd1Cs2a
    $ cleos create account hearing hearing1 EOS81sw5LyVND1KjYoGA7iYNSo9ezgyucEjNzVAP1bPBHRdgkJo29 EOS8XaSdS9EieYyWuAfUma7cmB4TEuPWjcU8mpMRR2jztuwd1Cs2a

智能合约

在eos私有节点操作中,我们通常是一个合约对应一个合约账户,并且一个账户中只能部署一个智能合约。如果在同一个账户部署多个合约,那么最后部署的合约会覆盖掉之前的合约。

HelloWorld

  1. 编写合约

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <eosiolib/eosio.hpp>

    using namespace eosio;

    class [[eosio::contract("hello")]] hello : public contract {
    public:
    using contract::contract;

    [[eosio::action]]
    void hi( name user ) {
    print( "Hello, ", user);
    }
    };

    EOSIO_DISPATCH( hello, (hi))
  2. 编译合约

    1
    $ eosio-cpp -I include -o hello.wasm hello.cpp --abigen
  3. 创建账户

    1
    $ cleos create account eosio hello EOS7qyuXyBtqMYLYBveB3APTiWeyu1d6Z4mTLX1mMP5ZU3kWUqXcJ -p eosio@active    # -p指定账户的权限
  4. 部署合约

    1
    $ cleos set contract hello CONTRACTS_DIR/hello -p hello@active
  5. 调用合约

    1
    $ cleos push action hello hi '["bob"]' -p alice@active

eosio.token合约

在eos目录中自带的合约中,有一个eosio.token智能合约,这个智能合约的功能是为账户发放token,token可以用来转账操作。

  1. 创建账户

    1
    $ cleos create account eosio eosio.token EOS81sw5LyVND1KjYoGA7iYNSo9ezgyucEjNzVAP1bPBHRdgkJo29 EOS8XaSdS9EieYyWuAfUma7cmB4TEuPWjcU8mpMRR2jztuwd1Cs2a
  2. 把eosio.token合约部署到eosio.token账户上

    1
    $ cleos set contract eosio.token ./eosio.token
  3. 创建代币

    1
    $ cleos push action eosio.token create '[ "eosio", "1000000000.0000 EOS", 0, 0, 0]' -p eosio.token@active
  4. 为账户发放token

    1
    $ cleos push action eosio.token issue '[ "lilei", "1000.0000 EOS", "" ]' -p eosio@active
  5. 交易token

    1
    $ cleos push action eosio.token transfer '[ "eosio", "hearing", "25.0000 EOS", "m" ]' -p eosio@active
  6. 查询余额

    1
    $ cleos get currency balance eosio.token hearing EOS

单主机多节点

关于配置

比如机器10.186.11.211上的部分配置:

1
2
3
4
5
6
7
8
9
10
bnet-endpoint = 10.186.11.211:4321    

//for communicatin with cleos
http-server-address = 10.186.11.211:8888

//for sync block
p2p-listen-endpoint = 10.186.11.211:9876
p2p-peer-address = 10.186.11.223:9876
p2p-peer-address = 10.186.11.220:9876
p2p-peer-address = 10.186.11.141:9876
  • bnet-endpoint: 所监听的传入链接的端点。 默认:0.0.0.0:4321
  • http-server-address: 本地的http服务地址 默认: 127.0.0.1:8888
  • p2p-listen-endpoint: 所监听的p2p传入链接的端点。 默认:0.0.0.0:9876
  • p2p-peer-address: 公共的p2p对等节点地址。

启动keosd

1
$ keosd --http-server-address 127.0.0.1:8899

创建钱包

1
2
3
4
5
$ cleos --wallet-url http://127.0.0.1:8899  wallet create --to-console
Creating wallet: default
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5J2VNR7bJpNtuJXwaEy2LNug5BNbBRRZUR8DcMPd7CrqMVtvnVn"

加载eosio秘钥

1
2
$ cleos --wallet-url http://127.0.0.1:8899 wallet import --private-key 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
imported private key for: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

启动第一个生产节点

1
$ nodeos --enable-stale-production --producer-name eosio --plugin eosio::chain_api_plugin --plugin eosio::net_api_plugin --max-transaction-time=1000 --hard-replay-blockchain

启动第二个生产节点

加载eosio.bios合约

要启动其他节点,必须先加载eosio.bios合同。通过此合同,可以直接控制其他帐户的资源分配并访问其他特权API调用。(如果第一次已经加载了合约,那么这一步可以跳过)

1
$ cleos --wallet-url http://127.0.0.1:8899 set contract eosio ./eosio.bios

创建账户(inita)

1
2
3
4
5
6
7
8
$ cleos create key --to-console
Private key: 5JcjxL4XqNvR85aQ9hAqworWJuoJfDoGo7wUtZLDbVePRXWCxUf
Public key: EOS58iXdanxG4nwok3AVSrDGu4Fj2dTB9HqeLUdbQu6wRRgyq18CS

$ cleos --wallet-url http://127.0.0.1:8899 wallet import --private-key 5JcjxL4XqNvR85aQ9hAqworWJuoJfDoGo7wUtZLDbVePRXWCxUf
imported private key for: EOS58iXdanxG4nwok3AVSrDGu4Fj2dTB9HqeLUdbQu6wRRgyq18CS

$ cleos --wallet-url http://127.0.0.1:8899 create account eosio inita EOS58iXdanxG4nwok3AVSrDGu4Fj2dTB9HqeLUdbQu6wRRgyq18CS EOS58iXdanxG4nwok3AVSrDGu4Fj2dTB9HqeLUdbQu6wRRgyq18CS

命令行启动节点

1
$ nodeos --producer-name inita --plugin eosio::chain_api_plugin --plugin eosio::net_api_plugin --http-server-address 127.0.0.1:8889 --p2p-listen-endpoint 127.0.0.1:9877 --p2p-peer-address 127.0.0.1:9876 --config-dir node2 --data-dir node2 --private-key 5JcjxL4XqNvR85aQ9hAqworWJuoJfDoGo7wUtZLDbVePRXWCxUf

将inita注册为具有bios节点的生产者,并且bios节点需要执行动作来更新生产者计划(测试失败):

1
$ cleos --wallet-url http://127.0.0.1:8899 push action eosio setprods "{ \"schedule\": [{\"producer_name\": \"inita\",\"block_signing_key\": \"EOS58iXdanxG4nwok3AVSrDGu4Fj2dTB9HqeLUdbQu6wRRgyq18CS\"}]}" -p eosio@active

配置文件启动节点

也可以通过conf文件启动多个节点,方式如下:

node2.ini:

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
# for communicatin with cleos
http-server-address = 127.0.0.1:8889

# for sync block
p2p-listen-endpoint = 127.0.0.1:9877
p2p-peer-address = 127.0.0.1:9876
p2p-peer-address = 127.0.0.1:9878

# agent-name = "EOS Test Agent"

# if eosio, this flag must be true, else must be set false, it decide whether or not
# product block
enable-stale-production = true

# producer name
producer-name = inita

# producer key,get by use"cleos ceate key"
# private-key =["EOS8Znrtgwt8TfpmbVpTKvA2oB8Nqey625CLN8bCN3TEbgx86Dsvr", "5K463ynhZoCDDa4RDcr63cUwWLTnKqmdcoTKTHBjqoKfv4u5V7p"]

# load plugin
plugin = eosio::chain_api_plugin
plugin = eosio::history_api_plugin
plugin = eosio::chain_plugin
plugin = eosio::history_plugin
plugin = eosio::net_plugin
plugin = eosio::net_api_plugin

node3.ini:

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
# for communicatin with cleos
http-server-address = 127.0.0.1:8890

# for sync block
p2p-listen-endpoint = 127.0.0.1:9878
p2p-peer-address = 127.0.0.1:9876
p2p-peer-address = 127.0.0.1:9877

# agent-name = "EOS Test Agent"

# if eosio, this flag must be true, else must be set false, it decide whether or not
# product block
enable-stale-production = true

# producer name
producer-name = initb

# producer key,get by use"cleos ceate key"
# private-key =["EOS8Znrtgwt8TfpmbVpTKvA2oB8Nqey625CLN8bCN3TEbgx86Dsvr", "5K463ynhZoCDDa4RDcr63cUwWLTnKqmdcoTKTHBjqoKfv4u5V7p"]

# load plugin
plugin = eosio::chain_api_plugin
plugin = eosio::history_api_plugin
plugin = eosio::chain_plugin
plugin = eosio::history_plugin
plugin = eosio::net_plugin
plugin = eosio::net_api_plugin

启动node2:

1
nodeos --config node2.ini --config-dir node2 --data-dir node2 --private-key 5JcjxL4XqNvR85aQ9hAqworWJuoJfDoGo7wUtZLDbVePRXWCxUf

启动node3:

1
nodeos --config node3.ini --config-dir node3 --data-dir node3 --private-key 5JcjxL4XqNvR85aQ9hAqworWJuoJfDoGo7wUtZLDbVePRXWCxUf

搭建测试网络的自动化脚本

为方便搭建测试环境,我将一些相关的操作都封装到了一个shell脚本中,在此附上脚本的github地址:https://github.com/ljd1996/eos_script/tree/master/mult_node.

该脚本的目录结构如下:

├── conf
│   ├── node10.ini
│   ├── node11.ini
│   ├── node12.ini
│   ├── node1.ini
│   ├── node2.ini
│   ├── node3.ini
│   ├── node4.ini
│   ├── node5.ini
│   ├── node6.ini
│   ├── node7.ini
│   ├── node8.ini
│   └── node9.ini
├── data
├── key
├── log
└── wpk
├── start.sh

下面我将分别介绍每个文件和目录的作用:

  • data目录主要存储节点启动后的区块等相关的数据,均由EOS自动生成,不需要自己做相关处理;
  • key目录用来存储节点构建过程中生成的账户的秘钥对;
  • log用来存项keos和nodeos运行过程中的日志输出;
  • wpk目录用来存储账户数据;
  • start.sh是脚本的源码。

其中,在运行脚本时我们唯一需要修改的是conf下面的配置文件,下面是其中一个配置文件的内容:

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
38
39
# for communicatin with cleos
http-server-address = 192.168.11.103:8888

# for sync block
p2p-listen-endpoint = 192.168.11.103:9876
p2p-peer-address = 192.168.11.103:9877
p2p-peer-address = 192.168.11.103:9878
p2p-peer-address = 192.168.11.103:9879
p2p-peer-address = 192.168.11.135:9880
p2p-peer-address = 192.168.11.135:9881
p2p-peer-address = 192.168.11.135:9882
p2p-peer-address = 192.168.11.135:9883
p2p-peer-address = 192.168.11.135:9884
p2p-peer-address = 192.168.11.135:9885
p2p-peer-address = 192.168.11.135:9886
p2p-peer-address = 192.168.11.135:9887
p2p-peer-address = 192.168.11.135:9888
p2p-peer-address = 192.168.11.135:9889
p2p-peer-address = 192.168.11.103:9890
p2p-peer-address = 192.168.11.103:9891
p2p-peer-address = 192.168.11.103:9892
p2p-peer-address = 192.168.11.103:9893
p2p-peer-address = 192.168.11.103:9894
p2p-peer-address = 192.168.11.103:9895
p2p-peer-address = 192.168.11.103:9896
p2p-peer-address = 192.168.11.103:9897
p2p-peer-address = 192.168.11.135:9877

# if eosio, this flag must be true, else must be set false, it decide whether or not product block
enable-stale-production = true

# load plugin
plugin = eosio::chain_api_plugin
plugin = eosio::history_api_plugin
plugin = eosio::chain_plugin
plugin = eosio::history_plugin
plugin = eosio::net_plugin
plugin = eosio::net_api_plugin
plugin = eosio::txn_test_gen_plugin
  • http-server-address: 开启的节点之中,这个值不能冲突,ip为本机的ip(ip:port)
  • p2p-listen-endpoint: 在节点的端到端连接中表示自己这个节点的位置,也需保持唯一,ip为本机的ip(ip:port)
  • p2p-peer-address: 端到端连接中其他节点的位置
  • enable-stale-production: 出块节点需要设置为true
  • plugin: 插件

在每次启动节点前,确定一下自己需要启动的节点数以及各自节点的网络地址,然后把conf下的配置文件按照上述原则进行修改,每个node.imi对应一个节点的配置文件,且命名规则和原来一样递增,否则可能会造成节点的开启失败。

脚本使用方法:

1
2
# 清除相关数据
$ ./start.sh clean
1
2
3
4
5
6
# 运行脚本启动节点
$ ./start.sh run wallet_dir contracts_dir node_num

# wallet_dir:本地钱包所在目录
# contracts_dir:EOS中系统智能合约所在目录
# node_num:在本机要开启的节点数,视conf中的配置文件数而定

多主机多节点测试网搭建

本节主要介绍如何通过自动化脚本在两台物理机上分别开启多个节点,并测试TPS的过程。

主机A的配置

在主机A:192.168.11.103中开启12个节点,其中节点1–eosio节点作为出块节点。下面给出几个配置文件的内容:

node1.imi:

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
38
39
# for communicatin with cleos
http-server-address = 192.168.11.103:8888

# for sync block
p2p-listen-endpoint = 192.168.11.103:9876
p2p-peer-address = 192.168.11.103:9877
p2p-peer-address = 192.168.11.103:9878
p2p-peer-address = 192.168.11.103:9879
p2p-peer-address = 192.168.11.135:9880
p2p-peer-address = 192.168.11.135:9881
p2p-peer-address = 192.168.11.135:9882
p2p-peer-address = 192.168.11.135:9883
p2p-peer-address = 192.168.11.135:9884
p2p-peer-address = 192.168.11.135:9885
p2p-peer-address = 192.168.11.135:9886
p2p-peer-address = 192.168.11.135:9887
p2p-peer-address = 192.168.11.135:9888
p2p-peer-address = 192.168.11.135:9889
p2p-peer-address = 192.168.11.103:9890
p2p-peer-address = 192.168.11.103:9891
p2p-peer-address = 192.168.11.103:9892
p2p-peer-address = 192.168.11.103:9893
p2p-peer-address = 192.168.11.103:9894
p2p-peer-address = 192.168.11.103:9895
p2p-peer-address = 192.168.11.103:9896
p2p-peer-address = 192.168.11.103:9897
p2p-peer-address = 192.168.11.135:9877

# if eosio, this flag must be true, else must be set false, it decide whether or not product block
enable-stale-production = true

# load plugin
plugin = eosio::chain_api_plugin
plugin = eosio::history_api_plugin
plugin = eosio::chain_plugin
plugin = eosio::history_plugin
plugin = eosio::net_plugin
plugin = eosio::net_api_plugin
plugin = eosio::txn_test_gen_plugin

node12.imi:

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
38
39
# for communicatin with cleos
http-server-address = 192.168.11.103:8909

# for sync block
p2p-listen-endpoint = 192.168.11.103:9897
p2p-peer-address = 192.168.11.103:9876
p2p-peer-address = 192.168.11.103:9877
p2p-peer-address = 192.168.11.103:9878
p2p-peer-address = 192.168.11.103:9879
p2p-peer-address = 192.168.11.135:9881
p2p-peer-address = 192.168.11.135:9882
p2p-peer-address = 192.168.11.135:9883
p2p-peer-address = 192.168.11.135:9884
p2p-peer-address = 192.168.11.135:9885
p2p-peer-address = 192.168.11.135:9886
p2p-peer-address = 192.168.11.135:9887
p2p-peer-address = 192.168.11.135:9888
p2p-peer-address = 192.168.11.135:9889
p2p-peer-address = 192.168.11.103:9890
p2p-peer-address = 192.168.11.103:9891
p2p-peer-address = 192.168.11.103:9892
p2p-peer-address = 192.168.11.103:9893
p2p-peer-address = 192.168.11.103:9894
p2p-peer-address = 192.168.11.103:9895
p2p-peer-address = 192.168.11.103:9896
p2p-peer-address = 192.168.11.135:9880
p2p-peer-address = 192.168.11.135:9877

# if eosio, this flag must be true, else must be set false, it decide whether or not product block
# enable-stale-production = true

# load plugin
plugin = eosio::chain_api_plugin
plugin = eosio::history_api_plugin
plugin = eosio::chain_plugin
plugin = eosio::history_plugin
plugin = eosio::net_plugin
plugin = eosio::net_api_plugin
plugin = eosio::txn_test_gen_plugin

开启节点:

1
$ ./start.sh run /home/hearing/eosio-wallet ~/Downloads/eosio.contracts 12

主机B的配置

在主机A:192.168.11.135中开启10个节点,所有节点都不出块。下面给出一个配置文件的内容:

node1.imi:

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
# for communicatin with cleos
http-server-address = 192.168.11.135:8892

# for sync block
p2p-listen-endpoint = 192.168.11.135:9880
p2p-peer-address = 192.168.11.103:9876
p2p-peer-address = 192.168.11.103:9877
p2p-peer-address = 192.168.11.103:9878
p2p-peer-address = 192.168.11.103:9879
p2p-peer-address = 192.168.11.135:9881
p2p-peer-address = 192.168.11.135:9882
p2p-peer-address = 192.168.11.135:9883
p2p-peer-address = 192.168.11.135:9884
p2p-peer-address = 192.168.11.135:9885
p2p-peer-address = 192.168.11.135:9886
p2p-peer-address = 192.168.11.135:9887
p2p-peer-address = 192.168.11.135:9888
p2p-peer-address = 192.168.11.135:9889
p2p-peer-address = 192.168.11.103:9890
p2p-peer-address = 192.168.11.103:9891
p2p-peer-address = 192.168.11.103:9892
p2p-peer-address = 192.168.11.103:9893
p2p-peer-address = 192.168.11.103:9894
p2p-peer-address = 192.168.11.103:9895
p2p-peer-address = 192.168.11.103:9896
p2p-peer-address = 192.168.11.103:9897
p2p-peer-address = 192.168.11.135:9877

开启节点:

1
$ ./start.sh run /home/hearing/eosio-wallet ~/Downloads/eosio.contracts 10

测试tps

使用EOS官方推荐的txn_test_gen_plugin插件作为tps的测试工具,其原理如下:

  1. 在一个指定的节点上新建测试账户

    1
    $ curl --data-binary '["eosio", "5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3"]' http://192.168.11.103:8888/v1/txn_test_gen/create_test_accounts
  2. 在测试账户间进行自动交易(每10秒产生20个交易)

    1
    $ curl --data-binary '["", 10, 20]' http://192.168.11.103:8888/v1/txn_test_gen/start_generation
  3. 上述产生交易的步骤也可在其他节点上运行

  4. 查看节点的输出日志,计算tps

    • 出块节点的日志:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      info  2019-03-13T07:56:24.050 thread-0  producer_plugin.cpp:1584      produce_block        ] Produced block 00000519d3484607... #1305 @ 2019-03-13T07:56:24.000 signed by eosio [trxs: 371, lib: 1304, confirmed: 0]
      info 2019-03-13T07:56:24.539 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000051aaa2f783e... #1306 @ 2019-03-13T07:56:24.500 signed by eosio [trxs: 358, lib: 1305, confirmed: 0]
      info 2019-03-13T07:56:25.017 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000051beb1d3276... #1307 @ 2019-03-13T07:56:25.000 signed by eosio [trxs: 257, lib: 1306, confirmed: 0]
      info 2019-03-13T07:56:25.549 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000051c6c7937c6... #1308 @ 2019-03-13T07:56:25.500 signed by eosio [trxs: 155, lib: 1307, confirmed: 0]
      info 2019-03-13T07:56:26.028 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000051d9113d888... #1309 @ 2019-03-13T07:56:26.000 signed by eosio [trxs: 154, lib: 1308, confirmed: 0]
      info 2019-03-13T07:56:26.559 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000051ed4d34911... #1310 @ 2019-03-13T07:56:26.500 signed by eosio [trxs: 276, lib: 1309, confirmed: 0]
      info 2019-03-13T07:56:27.023 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000051f69ccd987... #1311 @ 2019-03-13T07:56:27.000 signed by eosio [trxs: 163, lib: 1310, confirmed: 0]
      info 2019-03-13T07:56:27.544 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 000005208f4e00f9... #1312 @ 2019-03-13T07:56:27.500 signed by eosio [trxs: 249, lib: 1311, confirmed: 0]
      info 2019-03-13T07:56:28.033 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 000005210110210b... #1313 @ 2019-03-13T07:56:28.000 signed by eosio [trxs: 214, lib: 1312, confirmed: 0]
      info 2019-03-13T07:56:28.526 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 00000522ea3e4544... #1314 @ 2019-03-13T07:56:28.500 signed by eosio [trxs: 314, lib: 1313, confirmed: 0]
      info 2019-03-13T07:56:29.017 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 000005234705e92a... #1315 @ 2019-03-13T07:56:29.000 signed by eosio [trxs: 259, lib: 1314, confirmed: 0]
      info 2019-03-13T07:56:29.527 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 00000524841be821... #1316 @ 2019-03-13T07:56:29.500 signed by eosio [trxs: 502, lib: 1315, confirmed: 0]
      info 2019-03-13T07:56:30.014 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 000005257f6d4e2e... #1317 @ 2019-03-13T07:56:30.000 signed by eosio [trxs: 897, lib: 1316, confirmed: 0]
      info 2019-03-13T07:56:30.521 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 00000526b3aa10f1... #1318 @ 2019-03-13T07:56:30.500 signed by eosio [trxs: 526, lib: 1317, confirmed: 0]
      info 2019-03-13T07:56:31.023 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000052756e32d73... #1319 @ 2019-03-13T07:56:31.000 signed by eosio [trxs: 652, lib: 1318, confirmed: 0]
      info 2019-03-13T07:56:31.514 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 000005288100c034... #1320 @ 2019-03-13T07:56:31.500 signed by eosio [trxs: 616, lib: 1319, confirmed: 0]
      info 2019-03-13T07:56:32.048 thread-0 producer_plugin.cpp:1584 produce_block ] Produced block 0000052914f4a78b... #1321 @ 2019-03-13T07:56:32.000 signed by eosio [trxs: 662, lib: 1320, confirmed: 0]
    • 其他节点的日志:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      info  2019-03-13T07:55:53.164 thread-0  producer_plugin.cpp:345       on_incoming_block    ] Received block 9f6a6c4c171e385a... #1243 @ 2019-03-13T07:55:53.000 signed by eosio [trxs: 128, lib: 1242, conf: 0, latency: 164 ms]
      info 2019-03-13T07:55:53.600 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block faff04083aafe1e8... #1244 @ 2019-03-13T07:55:53.500 signed by eosio [trxs: 79, lib: 1243, conf: 0, latency: 100 ms]
      info 2019-03-13T07:55:54.139 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block bf606f4ee1ee1498... #1245 @ 2019-03-13T07:55:54.000 signed by eosio [trxs: 113, lib: 1244, conf: 0, latency: 139 ms]
      info 2019-03-13T07:55:54.806 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block e7ba16b5cda9ae0e... #1246 @ 2019-03-13T07:55:54.500 signed by eosio [trxs: 224, lib: 1245, conf: 0, latency: 306 ms]
      info 2019-03-13T07:55:55.151 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 149c694678a74f0e... #1247 @ 2019-03-13T07:55:55.000 signed by eosio [trxs: 144, lib: 1246, conf: 0, latency: 151 ms]
      info 2019-03-13T07:55:55.634 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 06efdba68e432e11... #1248 @ 2019-03-13T07:55:55.500 signed by eosio [trxs: 112, lib: 1247, conf: 0, latency: 134 ms]
      info 2019-03-13T07:55:56.100 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 1722e7db91fbc95b... #1249 @ 2019-03-13T07:55:56.000 signed by eosio [trxs: 112, lib: 1248, conf: 0, latency: 100 ms]
      info 2019-03-13T07:55:56.615 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block a1ea6b148a9669a8... #1250 @ 2019-03-13T07:55:56.500 signed by eosio [trxs: 112, lib: 1249, conf: 0, latency: 115 ms]
      info 2019-03-13T07:55:57.131 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block ea93f8c7878d058b... #1251 @ 2019-03-13T07:55:57.000 signed by eosio [trxs: 112, lib: 1250, conf: 0, latency: 131 ms]
      info 2019-03-13T07:55:57.744 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block a0f4be3b1b68b79c... #1252 @ 2019-03-13T07:55:57.500 signed by eosio [trxs: 169, lib: 1251, conf: 0, latency: 244 ms]
      info 2019-03-13T07:55:58.173 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 7334cd134b162612... #1253 @ 2019-03-13T07:55:58.000 signed by eosio [trxs: 126, lib: 1252, conf: 0, latency: 173 ms]
      info 2019-03-13T07:55:58.730 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 0c563bf6bad3095a... #1254 @ 2019-03-13T07:55:58.500 signed by eosio [trxs: 169, lib: 1253, conf: 0, latency: 230 ms]
      info 2019-03-13T07:55:59.086 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 6d0901b8f1b15739... #1255 @ 2019-03-13T07:55:59.000 signed by eosio [trxs: 64, lib: 1254, conf: 0, latency: 86 ms]
      info 2019-03-13T07:55:59.778 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 01a641dfcb07dbe5... #1256 @ 2019-03-13T07:55:59.500 signed by eosio [trxs: 251, lib: 1255, conf: 0, latency: 278 ms]
      info 2019-03-13T07:56:00.131 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 308907ac4cf4bc98... #1257 @ 2019-03-13T07:56:00.000 signed by eosio [trxs: 85, lib: 1256, conf: 0, latency: 131 ms]
      info 2019-03-13T07:56:00.688 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 3834f77aa9b994c9... #1258 @ 2019-03-13T07:56:00.500 signed by eosio [trxs: 128, lib: 1257, conf: 0, latency: 188 ms]
      info 2019-03-13T07:56:01.359 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 4ad642cb075d8d2a... #1259 @ 2019-03-13T07:56:01.000 signed by eosio [trxs: 206, lib: 1258, conf: 0, latency: 359 ms]
      info 2019-03-13T07:56:01.630 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 9ed257c131cffcee... #1260 @ 2019-03-13T07:56:01.500 signed by eosio [trxs: 114, lib: 1259, conf: 0, latency: 130 ms]
      info 2019-03-13T07:56:02.114 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block be8627adc345d6a4... #1261 @ 2019-03-13T07:56:02.000 signed by eosio [trxs: 96, lib: 1260, conf: 0, latency: 114 ms]
      info 2019-03-13T07:56:02.732 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 6d609f6c67134258... #1262 @ 2019-03-13T07:56:02.500 signed by eosio [trxs: 211, lib: 1261, conf: 0, latency: 232 ms]
      info 2019-03-13T07:56:03.152 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block d884495e2f09d7ff... #1263 @ 2019-03-13T07:56:03.000 signed by eosio [trxs: 116, lib: 1262, conf: 0, latency: 152 ms]
      info 2019-03-13T07:56:03.741 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 2735616823a12a4b... #1264 @ 2019-03-13T07:56:03.500 signed by eosio [trxs: 133, lib: 1263, conf: 0, latency: 241 ms]
      info 2019-03-13T07:56:04.321 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 55d4565cc4094b30... #1265 @ 2019-03-13T07:56:04.000 signed by eosio [trxs: 192, lib: 1264, conf: 0, latency: 321 ms]
      info 2019-03-13T07:56:04.744 thread-0 producer_plugin.cpp:345 on_incoming_block ] Received block 1e4ba2d9bee5b06f... #1266 @ 2019-03-13T07:56:04.500 signed by eosio [trxs: 228, lib: 1265, conf: 0, latency: 244 ms]

      tps的计算方式为日志中的trxs数值乘以2,因为EOS的出块时间是每500毫秒出一个区块。

启动测试网

用户可以主观地给候选节点投票,当所有代币的15%进行投票后,会由投票数靠前的节点(默认21个)出块,出块的节点票数必须大于0,且超级节点数默认不大于21个。

可以通过上述给出的链接中的脚本进行自动化启动,具体使用如下(我这里一共开启了包括创世节点在内共6个节点,主网启动后,由其中的三个节点轮流出块):

1
2
3
4
5
6
7
8
9
# 初始化
$ ./start.sh clean

# 开启节点并注册候选人
$ ./start.sh run_vote /home/hearing/eosio-wallet ~/Downloads/eosio.contracts/ 6

# 投票
# 数字4表示user2投票给prod2,user3投票给prod3,user4投票给user4
$ ./start.sh vote 4

此时会由prod2,3,4作为BP轮流出块(候选账户名需要跟节点名相同)。

注意:由于txn_test_gen_plugin的限制,当启动测试网后,貌似不能直接通过它去测试TPS(create_test_accounts会报错),故我这里加上了手动创建测试账户的过程(秘钥不能更改):

1
2
3
$ cleos system newaccount --transfer eosio txn.test.a EOS5hBSuDvcU2hHZJLAWCzBCCS7pV6SeQ4FuMhLPQPYqu9hcFakhy --stake-net "100000000.0000 EOS" --stake-cpu "100000000.0000 EOS" --buy-ram "20000.0000 EOS"
$ cleos system newaccount --transfer eosio txn.test.b EOS5gUGqvjsoAmqEJvSBAygi7XF75CaCDfpysZRRVPRBdAzcirTWG --stake-net "100000000.0000 EOS" --stake-cpu "100000000.0000 EOS" --buy-ram "20000.0000 EOS"
$ cleos system newaccount --transfer eosio txn.test.t EOS5gUGqvjsoAmqEJvSBAygi7XF75CaCDfpysZRRVPRBdAzcirTWG --stake-net "100000000.0000 EOS" --stake-cpu "100000000.0000 EOS" --buy-ram "20000.0000 EOS"

限制端口带宽的相关命令:

1
2
3
4
5
6
7
8
$ sudo iptables -t mangle -F
$ sudo tc qdisc del dev lo root
$ sudo tc qdisc add dev lo root handle 1: htb default 1
$ sudo tc class add dev lo parent 1: classid 1:1 htb rate 100mbps
$ sudo tc class add dev lo parent 1:1 classid 1:5 htb rate 256Kbit ceil 512Kbit prio 1
$ sudo tc filter add dev lo parent 1:0 prio 1 protocol ip handle 5 fw flowid 1:5
$ sudo iptables -A OUTPUT -t mangle -p tcp --sport 9877:9879 -j MARK --set-mark 5
$ sudo iptables -A INPUT -t mangle -p tcp --sport 9877:9879 -j MARK --set-mark 5

然后通过txn_test_gen_plugin提供的start_generation接口进行模拟交易,并测试TPS。

1
$ curl --data-binary '["", 20, 20]' http://127.0.0.1:8888/v1/txn_test_gen/start_generation