-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Tutorial Bios Boot Sequence
The description below covers the bios boot sequence to start a blockchain from a single "genesis" node, transitioning to a voted on set of producers.
The script bios-boot-tutorial.py
implements these steps in a single-server installation (all nodeos
nodes running on the same server). The script can be run directly from the tutorials/bios-boot-tutorial
directory. The -a
or --all
Alternatively, each step of the process can be run individually by the script (as a continuing set of steps). Additionally, after running the first set of steps to get to a running set of producers, you can use the script to replace the system contract using the eosio.msig
contract, then randomly transfer tokens among accounts.
cd tutorials/bios-boot-tutorial
./bios-boot-tutorial.py -a # to execute all options except replace system and transfer tokens, use -h for help
The script logs the commands it executes in ./output.log
. This enables you to see what work it has done. You can also find in the ./nodes
folder, subfolders for each of the various nodeos
instances that are run. Output from those instances are captured in their respective subfolders.
Note: Presently, the -a
option can fail due to the way that the accounting is done for purchase RAM. To work around this problem, use --extra-issue 10000
(or some suitable sized number) to issue more than the 1B tokens issued.
The remainder of this document discusses the same set of steps as the bios-boot-tutorial.py
script, but walks you through the commands one by one, enabling you to directly experience using the commands. The manual steps below do not try to bring up a full blockchain or do the same scope of work as the script. For example, the script generates around 3000 accounts by default (and optionally up to 30,000) and 30+ running nodeos
nodes, etc. This would be too unwieldy to do manually! Use this description in conjunction with the script to solidify your understanding of the process.
Note: In a live network, the steps involved require considerable coordination among independent parties who participate in the network. It is likely that the boot sequence will be done collectively by a small group within the blockchain community who work together closely to get an initial distributed network up and running. The network will then be expanded to incorporate more members. A pre-step to the bios boot process will be loading the collective account, key, and token balance information for each account.
The steps here can be readily expanded for the networked case. Some assumptions are made here regarding how the parties involved will coordinate with each other. However, there are many ways that the community can choose to coordinate. The technical aspects of the process are objective; assumptions of how the coordination might occur are speculative. Several approaches have already been suggested by the community. You are encouraged to review the various approaches and get involved in the discussions as appropriate.
In this tutorial, we will start a number of nodeos
nodes, point them to each other, and eventually vote on a set of producers. All of the nodeos
nodes will run on the same server. In the following sections, we take various steps to prepare our candidate set of producers. We will use the naming convention accountnumXY
, with XY chosen from the digits 1-5, e.g.,
accountnum11
accountnum12
..
accountnum15
accountnum21
...
accountnum55
As stated above, the script implements these steps, however, it uses different (and many more) data values. See the file
accounts.json
for the producer names and the user account names that the script uses.
Since all of the nodeos
nodes will run on the same server, we need separate config and data directories for each. The following example creates directories for each nodeos
under the directory ~/eosio_test
. Use whatever method works best for you to create a number of accounts, keeping in mind the naming restrictions that account names must be exactly 12 characters, from the set of a-z and 1-5.
$ mkdir ~/eosio_test
$ for (( i = 1; i <= 5; i++ )); do for (( j = 1 ; j <=5 ; j++ )); do mkdir ~/eosio_test/accountnum$i$j; done; done
You will use these directories with the --config-dir
and --data-dir
parameters on the nodeos
command line.
When we set up our producers, we will want to configure them to point to each other in order to perform peer-to-peer communication. If you set up a full mesh configuration, each node will point to all other nodes. A full mesh network will quickly grow unwieldy. The description below tells how to point nodes to other nodes in order to create the peer-to-peer communication. Use this for the nodes you select to be peers, but it is recommended NOT to use this for all nodes, as your configuration will grow explosively.
Determine the set of IP addresses and port numbers for peer-to-peer communication among each nodeos
node (you will use this later when you actually start your producer nodes). Each nodeos
can be configured by setting the p2p-peer-address
configuration property, either on the command line when starting nodeos
(one argument per peer), or by setting the property in the config.ini
file for nodeos
(one line per peer).
For example, assuming we are using port numbers 9011-9055 for the producers (i.e., accountnum11
- accountnum55
, respectively), include the following arguments on the nodeos
command line for accountnum12
:
--p2p-peer-address localhost:9011 --p2p-peer-address localhost:9013 --p2p-peer-address localhost:9014 ...
OR
In the config.ini
file for accountnum12
, add lines for each peer:
p2p-peer-address = localhost:9011
p2p-peer-address = localhost:9013
p2p-peer-address = localhost:9014
...
If using the configuration file approach, you will have many copies of the config.ini
file, one in each ~/eosio_test/accountnumXY
directory. Whether using the command line or config file approach, be careful to NOT include the producer's own address in the list of peers.
The "genesis" node is the first nodeos
that we start, that will originate the blockchain. All other nodes will derive from the genesis node. Do the following on the genesis node.
Note: In a real life scenario, it is doubtful that all IP addresses and port numbers will be known during the bios boot process. For example, the earliest started nodes will not have IP addresses and ports for later started nodes. This information can be added progressively.
Create a wallet. By default, keosd
is automatically started to manage the wallet.
$ cleos wallet create
Be sure to save the wallet password to enable unlocking the wallet in the future.
The same wallet will be used for all key management for all accounts in this tutorial, regardless of which nodeos
is being accessed. In a distributed deployment, wallet management should be a local-only activity.
The genesis.json
file defines the initial chain state. All nodes must start from the same initial state. Two properties in particular are highlighted here. The initial_timestamp
represents the start time of the blockchain. The initial_key
is used by the genesis node to start producing. It needs to be the same among all nodes. The initial_key
property in genesis.json
must match the public key of the genesis nodeos
. The nodeos
key pair can be specified using the --private-key
argument on the nodeos
command line, or by setting the private-key
property in the config.ini
file.
The genesis.json
file used by the script can be found in the tutorial/bios-boot-tutorial
directory. All nodeos
instances will be started using this file. The script specifies the nodeos
key pair on the command line. The script allows you to specify the key pair for the genesis node (--private-key
and --public-key
options). If specifying the genesis node's key, be sure to make any necessary changes to your genesis.json
file. The script will start the genesis node with that key pair, and will create the eosio.*
accounts using this key pair.
nodeos
comes pre-configured with a key pair, but we don't want to use that key. Create a key pair to be used for the eosio
account when starting the genesis node. The tutorial script comes pre-configured with its own custom key pair. (see above)
$ cleos create key
Private key: 5JGxnezvp3N4V1NxBo8LPBvCrdR85bZqZUFvBZ8ACrbRC3ZWNYv
Public key: EOS8VJybqtm41PMmXL1QUUDSfCrs9umYN4U1ZNa34JhPZ9mU5r2Cm
Start the genesis node using the generated key pair.
$ nodeos -e -p eosio --private-key '[ "EOS8VJybqtm41PMmXL1QUUDSfCrs9umYN4U1ZNa34JhPZ9mU5r2Cm","5JGxnezvp3N4V1NxBo8LPBvCrdR85bZqZUFvBZ8ACrbRC3ZWNYv" ]' --plugin eosio::producer_plugin --plugin eosio::chain_api_plugin --plugin eosio::http_plugin --plugin eosio::history_api_plugin
There are several system accounts that are needed. These are:
eosio.bpay
eosio.msig
eosio.names
eosio.ram
eosio.ramfee
eosio.saving
eosio.stake
eosio.token
eosio.vpay
Repeat the following steps to create an account for each of the system accounts. In this tutorial, we will use the same key pair for both the account owner and active keys, so we only need to provide the key value once on the command line. For most general accounts, it is good practice to use separate keys for owner and active. The script uses the same key for all of the eosio.*
accounts. You can use different keys for each.
$ cleos create key # for eosio.bpay
Private key: 5KAVVPzPZnbAx8dHz6UWVPFDVFtU1P5ncUzwHGQFuTxnEbdHJL4
Public key: EOS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG
$ cleos wallet import 5KAVVPzPZnbAx8dHz6UWVPFDVFtU1P5ncUzwHGQFuTxnEbdHJL4
imported private key for: EOS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG
$ cleos create account eosio eosio.bpay EOS84BLRbGbFahNJEpnnJHYCoW9QPbQEk2iHsHGGS6qcVUq9HhutG
executed transaction: ca68bb3e931898cdd3c72d6efe373ce26e6845fc486b42bc5d185643ea7a90b1 200 bytes 280 us
# eosio <= eosio::newaccount {"creator":"eosio","name":"eosio.bpay","owner":{"threshold":1,"keys":[{"key":"EOS84BLRbGbFahNJEpnnJH...
Set the eosio.token
contract. This contract enables you to create, issue, transfer, and get information about tokens. Note that the example assumes you built eos
in the ~/Documents/eos
folder.
$ cleos set contract eosio.token ~/Documents/eos/build/contracts/eosio.token
Reading WAST/WASM from /Users/tutorial/Documents/eos/build/contracts/eosio.token/eosio.token.wasm...
Using already assembled WASM...
Publishing contract...
executed transaction: 17fa4e06ed0b2f52cadae2cd61dee8fb3d89d3e46d5b133333816a04d23ba991 8024 bytes 974 us
# eosio <= eosio::setcode {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d01000000017f1560037f7e7f0060057f7e...
# eosio <= eosio::setabi {"account":"eosio.token","abi":{"types":[],"structs":[{"name":"transfer","base":"","fields":[{"name"...
Set the eosio.msig
contract. The msig contract enables and simplifies defining and managing permission levels and performing multi-signature actions. Note that this assumes that you built EOSIO in the ~/Documents/eos
folder.
$ cleos set contract eosio.msig ~/Documents/eos/build/contracts/eosio.msig
Reading WAST/WASM from /Users/tutorial/Documents/eos/build/contracts/eosio.msig/eosio.msig.wasm...
Using already assembled WASM...
Publishing contract...
executed transaction: 007507ad01de884377009d7dcf409bc41634e38da2feb6a117ceced8554a75bc 8840 bytes 925 us
# eosio <= eosio::setcode {"account":"eosio.msig","vmtype":0,"vmversion":0,"code":"0061736d010000000198011760017f0060047f7e7e7...
# eosio <= eosio::setabi {"account":"eosio.msig","abi":{"types":[{"new_type_name":"account_name","type":"name"}],"structs":[{...
Create the SYS
currency with a maximum value of 10 billion tokens. Then issue one billion tokens. Replace SYS
with your specific currency designation.
$ cleos push action eosio.token create '[ "eosio", "10000000000.0000 SYS" ]' -p eosio.token
executed transaction: 0440461e0d8816b4a8fd9d47c1a6a53536d3c7af54abf53eace884f008429697 120 bytes 326 us
# eosio.token <= eosio.token::create {"issuer":"eosio","maximum_supply":"10000000000.0000 SYS"}
$ cleos push action eosio.token issue '[ "eosio", "1000000000.0000 SYS", "memo" ]' -p eosio
executed transaction: a53961a566c1faa95531efb422cd952611b17d728edac833c9a55582425f98ed 128 bytes 432 us
# eosio.token <= eosio.token::issue {"to":"eosio","quantity":"1000000000.0000 SYS","memo":"memo"}
In the first step above, the create
action from the eosio.token
contract, authorized by the eosio.token
account, creates 10B SYS
tokens in the eosio
account. This effectively creates the maximum supply of tokens, but does not put any tokens into circulation. Tokens not in circulation can be considered to be held in reserve.
In the second step, the eosio.token
contract's issue
action takes 1B SYS
tokens out of reserve and puts them into circulation. At the time of issue, the tokens are held within the eosio
account. Since the eosio
account owns the reserve of uncirculated tokens, its authority is required to do the action.
As a point of interest, from an economic point of view, moving token from reserve into circulation, such as by issuing tokens, is an inflationary action. Issuing tokens is just one way that inflation can occur.
Set the eosio.system
contract. This contract provides the actions for pretty much all token-based operational behavior. Prior to installing the system contract, actions are done independent of accounting. Once the system contract is enabled, actions now have an economic element to them. Resources (cpu, network, memory) must be paid for. Likewise, new accounts must be paid for. The system contract enables tokens to be staked and unstaked, resources to be purchased, potential producers to be registered and subsequently voted on, producer rewards to be claimed, privileges and limits to be set, and more.
$ cleos set contract eosio ~/Documents/eos/build/contracts/eosio.system
Reading WAST/WASM from /Users/tutorial/Documents/eos/build/contracts/eosio.system/eosio.system.wasm...
Using already assembled WASM...
Publishing contract...
executed transaction: 2150ed87e4564cd3fe98ccdea841dc9ff67351f9315b6384084e8572a35887cc 39968 bytes 4395 us
# eosio <= eosio::setcode {"account":"eosio","vmtype":0,"vmversion":0,"code":"0061736d0100000001be023060027f7e0060067f7e7e7f7f...
# eosio <= eosio::setabi {"account":"eosio","abi":{"types":[],"structs":[{"name":"buyrambytes","base":"","fields":[{"name":"p...
In the next set of steps, we will transition from a single block producer (the genesis node) to multiple producers. Up to this point, only the built-in eosio
account has been privileged and can sign blocks. The target is to manage the blockchain by a collection of elected producers operating under a rule of 2/3 + 1 producers agreeing before a block is final
Producers are chosen by election. The list of producers can change. Rather than give privileged authority directly to any producer, the governing rules are associated with a special built-in account named eosio.prods
. This account represents the group of elected producers. The eosio.prods
account (effectively the producer group) operates using permissions defined by the eosio.msig
contract.
As soon as possible after installing the eosio.system
contract, we want to make eosio.msig
a privileged account so that it can authorize on behalf of the eosio
account. As soon as possible, eosio
will resign its authority and eosio.prods
will take over.
We make eosio.msig
privileged using the following.
$ push action eosio setpriv '["eosio.msig", 1]' -p eosio@active
If you've followed the tutorial steps above to this point, you now have a single host, single-node configuration with the following contracts installed:
- eosio.token
- eosio.msig
- eosio.system
Accounts eosio
and eosio.msig
are privileged accounts. The other eosio.*
accounts have been created but are not privileged.
We are now ready to being staking accounts and expanding the network of producers.
Staking is the process of allocating tokens acquired by an entity in the "real world" (e.g., an individual purchasing something at a Crowdsale or some other means) to an account within the EOSIO system. Staking and unstaking are an on-going process throughout the life of a blockchain. The initial staking done during the bios boot process is special. During the bios boot sequence, accounts are staked with their tokens. However, until producers are elected, tokens are effectively in a frozen state. Thus the goal of the initial staking done during the bios boot sequence is to get tokens allocated to their accounts and ready for use, and get the voting process going so that producers can get elected and the blockchain running "live".
The following recommendation is given for the initial staking process:
- 0.1 token (literally, not 10% of the account's tokens) is staked for RAM. By default,
cleos
stakes 8 KB of RAM on account creation, paid by the account creator. In the initial staking, theeosio
account is the account creator doing the staking. Tokens staked during the initial token staking process cannot be unstaked and made liquid until after the minimum voting requirements have been met. - 0.45 token is staked for CPU, and 0.45 token is staked for network.
- The next available tokens up to 9 total are held as liquid tokens.
- Remaining tokens are staked 50/50 CPU and network.
Example 1. accountnum11 has 100 SYS. It will be staked as 0.1000 SYS on RAM; 45.4500 SYS on CPU; 45.4500 SYS on network; and 9.0000 SYS held for liquid use.
Example 2. accountnum33 has 5 SYS. It will be staked as 0.1000 SYS on RAM; 0.4500 SYS on CPU; 0.4500 SYS on network; and 4.0000 SYS held for liquid use.
To make the tutorial more realistic, we distribute the 1B tokens to accounts using a Pareto distribution. The Pareto distribution models an 80-20 rule, e.g., in this case, 80% of the tokens are held by 20% of the population. The examples here do not show how to generate the distribution, focusing instead on the commands to do the staking. The script bios-boot-tutorial.py
that accompanies this tutorial uses the Python NumPy (numpy) library to generate a Pareto distribution.
Use the following steps to stake tokens for each account. These steps must be done individually for each account.
The key pair is created here for this tutorial. In a "live" scenario, the key value(s) and token share for an account should already be established through some well-defined out-of-band process.
$ cleos create key # for accountnum11 Private key: 5K7EYY3j1YY14TSFVfqgtbWbrw3FA8BUUnSyFGgwHi8Uy61wU1o Public key: EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt $ cleos wallet import 5K7EYY3j1YY14TSFVfqgtbWbrw3FA8BUUnSyFGgwHi8Uy61wU1o imported private key for: EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt
Create a staked account with initial resources and public key.
$ cleos system newaccount eosio --transfer accountnum11 EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt --stake-net "100000.0000 SYS" --stake-cpu "100000.0000 SYS"
775292ms thread-0 main.cpp:419 create_action ] result: {"binargs":"0000000000ea30551082d4334f4d113200200000"} arg: {"code":"eosio","action":"buyrambytes","args":{"payer":"eosio","receiver":"accountnum11","bytes":8192}}
775295ms thread-0 main.cpp:419 create_action ] result: {"binargs":"0000000000ea30551082d4334f4d113200ca9a3b00000000045359530000000000ca9a3b00000000045359530000000001"} arg: {"code":"eosio","action":"delegatebw","args":{"from":"eosio","receiver":"accountnum11","stake_net_quantity":"100000.0000 SYS","stake_cpu_quantity":"100000.0000 SYS","transfer":true}}
executed transaction: fb47254c316e736a26873cce1290cdafff07718f04335ea4faa4cb2e58c9982a 336 bytes 1799 us
# eosio <= eosio::newaccount {"creator":"eosio","name":"accountnum11","owner":{"threshold":1,"keys":[{"key":"EOS8mUftJXepGzdQ2TaC...
# eosio <= eosio::buyrambytes {"payer":"eosio","receiver":"accountnum11","bytes":8192}
# eosio <= eosio::delegatebw {"from":"eosio","receiver":"accountnum11","stake_net_quantity":"100000.0000 SYS","stake_cpu_quantity...
Some set of the accounts created will be registered as producers. Choose some set of the staked accounts to be producers.
Use the following command to register as a producer. This makes the node a candidate to be a producer, but the node will not actually be a producer unless it is elected.
$ cleos system regproducer accountnum11 EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt https://accountnum11.com/EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt
1487984ms thread-0 main.cpp:419 create_action ] result: {"binargs":"1082d4334f4d11320003fedd01e019c7e91cb07c724c614bbf644a36eff83a861b36723f29ec81dc9bdb4e68747470733a2f2f6163636f756e746e756d31312e636f6d2f454f53386d5566744a586570477a64513254614364754e7553504166584a48663232756578347534316162314556763945416857740000"} arg: {"code":"eosio","action":"regproducer","args":{"producer":"accountnum11","producer_key":"EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt","url":"https://accountnum11.com/EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt","location":0}}
executed transaction: 4ebe9258bdf1d9ac8ad3821f6fcdc730823810a345c18509ac41f7ef9b278e0c 216 bytes 896 us
# eosio <= eosio::regproducer {"producer":"accountnum11","producer_key":"EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt","u...
To facilitate the voting process, list the available producers.
$ cleos system listproducers
Producer Producer key Url Scaled votes
accountnum11 EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt https://accountnum11.com/EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22 0.0000
accountnum22 EOS5kgeCLuQo8MMLnkZfqcBA3GRFgQsPyDddHWmXceRLjRX8LJRaH https://accountnum22.com/EOS5kgeCLuQo8MMLnkZfqcBA3GRFgQsPyD 0.0000
accountnum33 EOS63CnoyfeEQDjXXxwywN5PPKW7RYHC9tbtmvb8vFBGZooktz7kG https://accountnum33.com/EOS63CnoyfeEQDjXXxwywN5PPKW7RYHC9t 0.0000
accountnum44 EOS6kBaCHrvz7VdUfFBLrLdhNjXYaKBmRkpDXU9PhbEUiHbspr7rz https://accountnum44.com/EOS6kBaCHrvz7VdUfFBLrLdhNjXYaKBmRk 0.0000
Use the following command to start the producers. Recall that in this tutorial, all of the producers are running on a single server, so command line arguments are used to ensure each producer is using its own directory.
In a separate window for each producer, run the following nodeos
command, adjusting the command line arguments for
each producer.
$ nodeos --genesis-json ~/eosio_test/accountnum11/genesis.json --block-log-dir ~/eosio_test/accountnum11/blocks --config-dir ~/eosio_test/accountnum11/ --data-dir ~/eosio_test/accountnum11/ --http-server-address 127.0.0.1:8011 --p2p-listen-endpoint 127.0.0.1:9011 --enable-stale-production --producer-name accountnum11 --private-key '[ "EOS8mUftJXepGzdQ2TaCduNuSPAfXJHf22uex4u41ab1EVv9EAhWt","5K7EYY3j1YY14TSFVfqgtbWbrw3FA8BUUnSyFGgwHi8Uy61wU1o" ]' --plugin eosio::producer_plugin --plugin eosio::chain_api_plugin --plugin eosio::http_plugin --plugin eosio::history_api_plugin --p2p-peer-address localhost:9022 --p2p-peer-address localhost:9033 --p2p-peer-address localhost:9044
Note that until all producers are up, connection error messages such as the following will be generated.
1826099ms thread-0 net_plugin.cpp:2927 plugin_startup ] starting listener, max clients is 25
1826099ms thread-0 net_plugin.cpp:676 connection ] created connection to localhost:9022
1826099ms thread-0 net_plugin.cpp:1948 connect ] host: localhost port: 9022
1826099ms thread-0 net_plugin.cpp:676 connection ] created connection to localhost:9033
1826099ms thread-0 net_plugin.cpp:1948 connect ] host: localhost port: 9033
1826099ms thread-0 net_plugin.cpp:676 connection ] created connection to localhost:9044
1826099ms thread-0 net_plugin.cpp:1948 connect ] host: localhost port: 9044
1826100ms thread-0 net_plugin.cpp:1989 operator() ] connection failed to localhost:9022: Connection refused
1826100ms thread-0 net_plugin.cpp:1989 operator() ] connection failed to localhost:9033: Connection refused
1826100ms thread-0 net_plugin.cpp:1989 operator() ] connection failed to localhost:9044: Connection refused
For convenience, the following command lines can be copied to run nodeos
in separate shell windows for accounts accountnum22
, accountnum33
, and accountnum44
. If you run these, you can see how multiple nodes respond when running in a peer-to-peer configuration. This assumes that accounts have been staked using the relevant key pairs (the key pairs can be seen in each of the command lines below).
$ nodeos --genesis-json ~/eosio_test/accountnum22/genesis.json --block-log-dir ~/eosio_test/accountnum22/blocks --config-dir ~/eosio_test/accountnum22/ --data-dir ~/eosio_test/accountnum22/ --http-server-address 127.0.0.1:8022 --p2p-listen-endpoint 127.0.0.1:9022 --enable-stale-production --producer-name accountnum22 --private-key '[ "EOS5kgeCLuQo8MMLnkZfqcBA3GRFgQsPyDddHWmXceRLjRX8LJRaH","5Jh4rseyguLx5Y7KE2oLL81PRmDcyyzbyyyJd3GvdHijKqENbRk" ]' --plugin eosio::producer_plugin --plugin eosio::chain_api_plugin --plugin eosio::http_plugin --p2p-peer-address localhost:9011 --p2p-peer-address localhost:9033 --p2p-peer-address localhost:9044
$ nodeos --genesis-json ~/eosio_test/accountnum33/genesis.json --block-log-dir ~/eosio_test/accountnum33/blocks --config-dir ~/eosio_test/accountnum33/ --data-dir ~/eosio_test/accountnum33/ --http-server-address 127.0.0.1:8033 --p2p-listen-endpoint 127.0.0.1:9033 --enable-stale-production --producer-name accountnum33 --private-key '[ "EOS63CnoyfeEQDjXXxwywN5PPKW7RYHC9tbtmvb8vFBGZooktz7kG","5JWp5K24x5dbAFBNP7hwzSRS7XjD7wjHL4nrAwSLdRuJnERjgqB" ]' --plugin eosio::producer_plugin --plugin eosio::chain_api_plugin --plugin eosio::http_plugin --p2p-peer-address localhost:9011 --p2p-peer-address localhost:9022 --p2p-peer-address localhost:9044
$ nodeos --genesis-json ~/eosio_test/accountnum44/genesis.json --block-log-dir ~/eosio_test/accountnum44/blocks --config-dir ~/eosio_test/accountnum44/ --data-dir ~/eosio_test/accountnum44/ --http-server-address 127.0.0.1:8044 --p2p-listen-endpoint 127.0.0.1:9044 --enable-stale-production --producer-name accountnum44 --private-key '[ "EOS6kBaCHrvz7VdUfFBLrLdhNjXYaKBmRkpDXU9PhbEUiHbspr7rz","5KeGoDkbhEdkZTpYqQg2rPZvtxqfWAtGgixuCLUt1Dmoq4NmXCj" ]' --plugin eosio::producer_plugin --plugin eosio::chain_api_plugin --plugin eosio::http_plugin --p2p-peer-address localhost:9011 --p2p-peer-address localhost:9022 --p2p-peer-address localhost:9033
This also expects that the genesis.json
file, e.g, see below, has been copied to the respective account directories.
{
"initial_timestamp": "2018-03-02T12:00:00.000",
"initial_key": "EOS8Znrtgwt8TfpmbVpTKvA2oB8Nqey625CLN8bCN3TEbgx86Dsvr",
"initial_configuration": {
"max_block_net_usage": 1048576,
"target_block_net_usage_pct": 1000,
"max_transaction_net_usage": 524288,
"base_per_transaction_net_usage": 12,
"net_usage_leeway": 500,
"context_free_discount_net_usage_num": 20,
"context_free_discount_net_usage_den": 100,
"max_block_cpu_usage": 100000,
"target_block_cpu_usage_pct": 500,
"max_transaction_cpu_usage": 50000,
"min_transaction_cpu_usage": 100,
"max_transaction_lifetime": 3600,
"deferred_trx_expiration_window": 600,
"max_transaction_delay": 3888000,
"max_inline_action_size": 4096,
"max_inline_action_depth": 4,
"max_authority_depth": 6,
"max_generated_transaction_count": 16
},
"initial_chain_id": "0000000000000000000000000000000000000000000000000000000000000000"
}
Note: Output from each node is captured in the file stderr
within that node's working directory, e.g., ./nodes/accountnum44/stderr
. By default, the nodes started by the script continue to run. Care must be taken to avoid the disk filling from 30+ nodes running simultaneously, each separately writing its output to a file in the file system.
Voting for producers can begin as accounts are staked and producers are registered.
The following command enables votes to be cast.
$ cleos system voteproducer prods accountnum23 accountnum11 accountnum33
In this example, account accountnum23
has voted for accountnum11
and accountnum33
. Block production does not begin until 15% of the available votes have been voted.
Producers can claim rewards after 150,000,000 tokens have been staked. Strategies for selecting the optimal time to claim rewards no doubt vary greatly. This tutorial does not cover that topic.
Use the following to claim rewards.
$ cleos system claimrewards accountnum33
An account can register to be a proxy for voting purposes. Other accounts can then delegate their votes to the proxy account.
Register as a voting proxy. In this example, proxyvoter11
is being set up to act as a proxy voter.
$ cleos system regproxy proxyvoter11
Now other accounts can delegate their votes to be voted by proxyvoter11
:
$ cleos system voteproducer proxy accountnum24 proxyvoter11
$ cleos system voteproducer proxy accountnum34 proxyvoter11
Here, accounts accountnum24
and accountnum34
have proxied their votes to proxyvoter11
.
Once producers have been elected and the minimum number requirements have been met, the eosio
account can resign, leaving the eosio.msig
account as the only privileged account.
Resigning is basically involves setting the keys of the eosio.*
accounts to null. Use the following command to clear the eosio.*
accounts' owner and active keys:
$ cleos push action eosio updateauth '{"account": "eosio", "permission": "owner", "parent": "", "auth": {"threshold": 1, "keys": [], "waits": [], "accounts": [{"weight": 1, "permission": {"actor": "eosio.prods", "permission": "active"}}]}}' -p eosio@owner
$ cleos push action eosio updateauth '{"account": "eosio", "permission": "active", "parent": "owner", "auth": {"threshold": 1, "keys": [], "waits": [], "accounts": [{"weight": 1, "permission": {"actor": "eosio.prods", "permission": "active"}}]}}' -p eosio@active