Peer Configuration
The peer configuration file (configs/peer/config.json
) determines how your blockchain operates.
Here's an example of how peer configuration file looks like:
Peer configuration example
{
"PUBLIC_KEY": null,
"PRIVATE_KEY": null,
"DISABLE_PANIC_TERMINAL_COLORS": false,
"KURA": {
"INIT_MODE": "strict",
"BLOCK_STORE_PATH": "./storage",
"BLOCKS_PER_STORAGE_FILE": 1000,
"ACTOR_CHANNEL_CAPACITY": 100,
"DEBUG_OUTPUT_NEW_BLOCKS": false
},
"SUMERAGI": {
"KEY_PAIR": null,
"PEER_ID": null,
"BLOCK_TIME_MS": 2000,
"TRUSTED_PEERS": null,
"COMMIT_TIME_LIMIT_MS": 4000,
"MAX_TRANSACTIONS_IN_BLOCK": 512,
"ACTOR_CHANNEL_CAPACITY": 100,
"GOSSIP_BATCH_SIZE": 500,
"GOSSIP_PERIOD_MS": 1000
},
"TORII": {
"P2P_ADDR": null,
"API_URL": null,
"TELEMETRY_URL": null,
"MAX_TRANSACTION_SIZE": 32768,
"MAX_CONTENT_LEN": 16384000,
"FETCH_SIZE": 10,
"QUERY_IDLE_TIME_MS": 30000
},
"BLOCK_SYNC": {
"GOSSIP_PERIOD_MS": 10000,
"BLOCK_BATCH_SIZE": 4,
"ACTOR_CHANNEL_CAPACITY": 100
},
"QUEUE": {
"MAX_TRANSACTIONS_IN_QUEUE": 65536,
"MAX_TRANSACTIONS_IN_QUEUE_PER_USER": 65536,
"TRANSACTION_TIME_TO_LIVE_MS": 86400000,
"FUTURE_THRESHOLD_MS": 1000
},
"LOGGER": {
"MAX_LOG_LEVEL": "INFO",
"TELEMETRY_CAPACITY": 1000,
"COMPACT_MODE": false,
"LOG_FILE_PATH": null,
"TERMINAL_COLORS": true
},
"GENESIS": {
"ACCOUNT_PUBLIC_KEY": null,
"ACCOUNT_PRIVATE_KEY": null
},
"WSV": {
"ASSET_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"ASSET_DEFINITION_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"ACCOUNT_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"DOMAIN_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"IDENT_LENGTH_LIMITS": {
"min": 1,
"max": 128
},
"TRANSACTION_LIMITS": {
"max_instruction_number": 4096,
"max_wasm_size_bytes": 4194304
},
"WASM_RUNTIME_CONFIG": {
"FUEL_LIMIT": 23000000,
"MAX_MEMORY": 524288000
}
},
"NETWORK": {
"ACTOR_CHANNEL_CAPACITY": 100
},
"TELEMETRY": {
"NAME": null,
"URL": null,
"MIN_RETRY_PERIOD": 1,
"MAX_RETRY_DELAY_EXPONENT": 4,
"FILE": null
},
"SNAPSHOT": {
"CREATE_EVERY_MS": 60000,
"DIR_PATH": "./storage",
"CREATION_ENABLED": true
}
}
{
"PUBLIC_KEY": null,
"PRIVATE_KEY": null,
"DISABLE_PANIC_TERMINAL_COLORS": false,
"KURA": {
"INIT_MODE": "strict",
"BLOCK_STORE_PATH": "./storage",
"BLOCKS_PER_STORAGE_FILE": 1000,
"ACTOR_CHANNEL_CAPACITY": 100,
"DEBUG_OUTPUT_NEW_BLOCKS": false
},
"SUMERAGI": {
"KEY_PAIR": null,
"PEER_ID": null,
"BLOCK_TIME_MS": 2000,
"TRUSTED_PEERS": null,
"COMMIT_TIME_LIMIT_MS": 4000,
"MAX_TRANSACTIONS_IN_BLOCK": 512,
"ACTOR_CHANNEL_CAPACITY": 100,
"GOSSIP_BATCH_SIZE": 500,
"GOSSIP_PERIOD_MS": 1000
},
"TORII": {
"P2P_ADDR": null,
"API_URL": null,
"TELEMETRY_URL": null,
"MAX_TRANSACTION_SIZE": 32768,
"MAX_CONTENT_LEN": 16384000,
"FETCH_SIZE": 10,
"QUERY_IDLE_TIME_MS": 30000
},
"BLOCK_SYNC": {
"GOSSIP_PERIOD_MS": 10000,
"BLOCK_BATCH_SIZE": 4,
"ACTOR_CHANNEL_CAPACITY": 100
},
"QUEUE": {
"MAX_TRANSACTIONS_IN_QUEUE": 65536,
"MAX_TRANSACTIONS_IN_QUEUE_PER_USER": 65536,
"TRANSACTION_TIME_TO_LIVE_MS": 86400000,
"FUTURE_THRESHOLD_MS": 1000
},
"LOGGER": {
"MAX_LOG_LEVEL": "INFO",
"TELEMETRY_CAPACITY": 1000,
"COMPACT_MODE": false,
"LOG_FILE_PATH": null,
"TERMINAL_COLORS": true
},
"GENESIS": {
"ACCOUNT_PUBLIC_KEY": null,
"ACCOUNT_PRIVATE_KEY": null
},
"WSV": {
"ASSET_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"ASSET_DEFINITION_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"ACCOUNT_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"DOMAIN_METADATA_LIMITS": {
"max_len": 1048576,
"max_entry_byte_size": 4096
},
"IDENT_LENGTH_LIMITS": {
"min": 1,
"max": 128
},
"TRANSACTION_LIMITS": {
"max_instruction_number": 4096,
"max_wasm_size_bytes": 4194304
},
"WASM_RUNTIME_CONFIG": {
"FUEL_LIMIT": 23000000,
"MAX_MEMORY": 524288000
}
},
"NETWORK": {
"ACTOR_CHANNEL_CAPACITY": 100
},
"TELEMETRY": {
"NAME": null,
"URL": null,
"MIN_RETRY_PERIOD": 1,
"MAX_RETRY_DELAY_EXPONENT": 4,
"FILE": null
},
"SNAPSHOT": {
"CREATE_EVERY_MS": 60000,
"DIR_PATH": "./storage",
"CREATION_ENABLED": true
}
}
INFO
Note that for convenient container deployment, configuration options specified via environment variables always override the corresponding values in the configuration file. This way, you can have a basic configuration file and also configure some options in a docker-compose.yml
or in your shell's environment file (.bashrc
, .zshrc
, etc.).
Some of the configuration options are required, while others are used for fine-tuning. When you create a new peer, you are required to provide the following:
The peer's Public and private keys (
PUBLIC_KEY
andPRIVATE_KEY
)Iroha public addresses (
P2P_ADDR
,API_URL
,TELEMETRY_URL
)Trusted peers (
TRUSTED_PEERS
)Public and private keys for the genesis account (
ACCOUNT_PUBLIC_KEY
andACCOUNT_PRIVATE_KEY
)
INFO
Configuration options have different underlying types and default values, which are denoted in code as types wrapped in a single Option<..>
or in a double Option<Option<..>>
. Refer to configuration types for details.
Generation
You can use kagami
to generate the default peer configuration:
$ kagami config peer > peer-config.json
$ kagami config peer > peer-config.json
Public and private keys
The configs/peer/config.json
peer configuration file should contain a pair of the user's public PUBLIC_KEY
and private PRIVATE_KEY
cryptographic keys for their account's ACCOUNT_ID
.
For details on cryptographic keys, see Public Key Cryptography.
Trusted Peers
Iroha is a blockchain ledger. In order for it to work optimally and be Byzantine-fault tolerant with the maximum number of faults allowed, it needs to be started with a set number of peers: 4
, 7
, 10
, ... 3f+1
, where f
is the allowed number of faults.
So usually, when you want to start an Iroha deployment, you should already know a number of peers that you can trust and join their blockchain. The way it works in the examples is that you just specify in four config.json
files four peers with their public keys and API addresses.
Since Iroha has no automatic peer discovery, the only other way to make peers known to each other is to use the iroha_client_cli
to register new peers). This is not too difficult with the provided client libraries. With Python's Beautiful Soup, the curated list of peers can be updated, registered, and un-registered on its own.
The list of trusted peers is a part of SUMERAGI
configuration. Here's an example of SUMERAGI_TRUSTED_PEERS
environment variable to configure trusted peers:
'[{"address":"iroha0:1337", "public_key": "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"}, {"address":"iroha1:1338", "public_key": "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"}, {"address": "iroha2:1339", "public_key": "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"}, {"address": "iroha3:1340", "public_key": "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
'[{"address":"iroha0:1337", "public_key": "ed01201c61faf8fe94e253b93114240394f79a607b7fa55f9e5a41ebec74b88055768b"}, {"address":"iroha1:1338", "public_key": "ed0120cc25624d62896d3a0bfd8940f928dc2abf27cc57cefeb442aa96d9081aae58a1"}, {"address": "iroha2:1339", "public_key": "ed0120faca9e8aa83225cb4d16d67f27dd4f93fc30ffa11adc1f5c88fd5495ecc91020"}, {"address": "iroha3:1340", "public_key": "ed01208e351a70b6a603ed285d666b8d689b680865913ba03ce29fb7d13a166c4e7f1f"}]'
Iroha Public Addresses
TORII
is the module in charge of handling incoming and outgoing connections.
API_URL
The API_URL
is the location to which the client(s) make their requests. You can also use it to change some peer-specific configuration options.
Most of the time, the only reason to change the API_URL
is to change the port, in case 8080
is either closed, or if you want to randomise ports to avoid certain kinds of attacks.
P2P_ADDR
The P2P_ADDR
is the internal address used for communication between peers. This address should be included in the TRUSTED_PEERS
section of the configuration file.
TELEMETRY_URL
The TELEMETRY_URL
is used to specify the prometheus endpoint address. It's set by adding "TELEMETRY_URL": "127.0.0.1:8180"
to the TORII
section of the configuration file.
It's not meant to be human-readable. However, a GET
request to the 127.0.0.1:8180/status
will give you a JSON-encoded representation of the top-level metrics, while a GET
request to 127.0.0.1:8180/metrics
will give you a (somewhat verbose) list of all available metrics gathered in Iroha. You might want to change this if you're having trouble gathering metrics using prometheus
.
INFO
Learn how to monitor Iroha performance using prometheus.
Genesis
When you configure a peer, you have to provide private and public keys for the genesis account.
You can do this via the configuration file (ACCOUNT_PUBLIC_KEY
, ACCOUNT_PRIVATE_KEY
) or environment variables (IROHA_GENESIS_ACCOUNT_PUBLIC_KEY
, IROHA_GENESIS_ACCOUNT_PRIVATE_KEY
).
To learn more about genesis block, genesis account, and cryptographic keys, see the following:
Aside from the public and private keys for the genesis account, which are required configuration options, you can also fine-tune other genesis block configurations, such as:
WAIT_FOR_PEERS_RETRY_COUNT_LIMIT
: the number of attempts to connect to peers before genesis block is submittedWAIT_FOR_PEERS_RETRY_PERIOD_MS
: how long to wait before retrying a connection to peersGENESIS_SUBMISSION_DELAY_MS
: the delay before the genesis block submission after the minimum number of peers were discovered.
Logger
Let's cover the most useful LOGGER
configurations, MAX_LOG_LEVEL
and LOG_FILE_PATH
.
MAX_LOG_LEVEL
The MAX_LOG_LEVEL
is used to determine which messages are logged.
With "MAX_LOG_LEVEL": "WARN"
you won't get any messages unless they are either a warning or an error. Beside WARN
, other available options are:
TRACE
(log every time you enter a function)DEBUG
(use when you know something went wrong)INFO
(the default)WARN
(log everything that could be an error)ERROR
(to silence any logging except for error messages)
LOG_FILE_PATH
Another useful option is "LOG_FILE_PATH": bunyan.json
. It creates (if it didn't already exist) a file called bunyan.json
that contains the message log in a structured format.
This is extremely useful for two reasons. Firstly, you can use the bunyan
log viewer to filter information more precisely than Iroha would allow you to do. Do you only want messages from a specific module or package? You can do that with bunyan
. Secondly, while copying logs is not too big of a problem if your instance is just a small setup, for bigger setups the log will be larger. Having it saved to a file makes much more sense in that case.
INFO
You can also set LOG_FILE_PATH
to /dev/stdout
if you want to use bunyan's logging facilities directly without saving the output.
Kura
Kura is the persistent storage engine of Iroha (Japanese for warehouse). The BLOCK_STORE_PATH
specifies where the blocks are stored. You can change it to a custom location if for some reason the default location (./storage
) is not available or desirable.