Skip to content

Latest commit

 

History

History
184 lines (128 loc) · 14.3 KB

testnet-api-tutorial.md

File metadata and controls

184 lines (128 loc) · 14.3 KB

Configuration service tutorial

Running testnet

Using Docker

Simply run the following command to configure and launch testnet with 4 nodes:

docker run -p 8000-8007:8000-8007 vitvakatu/exonum-configuration-example 4

Docker will automatically pull image from the repository and run 4 nodes with public endpoints at 127.0.0.1:8000, ..., 127.0.0.1:8003 and private ones at 127.0.0.1:8004, ..., 127.0.0.1:8007.

You can also use helper script:

./docker/example-start.sh <number of nodes>

To stop docker container, use docker stop <container id> command.

Manually

Build example binary

To build an example binary of exonum blockchain with the single configuration service mounted, run:

cargo install --example configuration

exonum crate system dependencies and rust toolchain configuration - exonum install instructions.

Generate testnet directory and config

4 is a required indexed parameter and stands for the number of nodes in testnet:

mkdir -p testnet/configuration_service
cd testnet/configuration_service
configuration generate-testnet --start 5400 4 --output_dir .
cd ..

This should create the following config for testnet:

$ tree configuration_service/
configuration_service/
└── validators
  ├── 0.toml
  ├── 1.toml
  ├── 2.toml
  └── 3.toml

Run 4 nodes

configuration run --node-config configuration_service/validators/0.toml --db-path configuration_service/db/0 --public-api-address 127.0.0.1:8000 --private-api-address 127.0.0.1:8010
...
configuration run --node-config configuration_service/validators/3.toml --db-path configuration_service/db/3 --public-api-address 127.0.0.1:8003 --private-api-address 127.0.0.1:8013
Parameters

Global variable service http api

All hashes, public-keys and signatures in tables are hexadecimal strings. config-body is a valid json, corresponding to exonum config serialization.

Public endpoints

Configurations' structure

This config is called actual config.

  1. Only single config may be scheduled to become next config at any moment of time. This config is called following config.

  2. For any current config, its following config will have actual_from greater than the actual_from of current config.

  3. For any current config, its following config will have previous_cfg_hash equal to hash of current config.

  4. Any config propose gets scheduled to become the following config only if it gets 2/3+1 supermajority of votes of validators of actual config. Thus, which entities can determine what the following config will be is specified in the contents of actual config.

Examples

Endpoint HTTP method Description Query parameters Response template
/api/services/configuration/v1/configs/actual GET Lookup actual config None {
  "config": config-body,
  "hash": config-hash
}
/api/services/configuration/v1/configs/following GET Lookup already scheduled following config which hasn't yet taken effect.
null if no config is scheduled
None {
  "config": config-body,
  "hash": config-hash
}
/api/services/configuration/v1/configs/<config-hash> GET Lookup config by config hash.
If no propose was submitted for a config (genesis config) - "propose" is null.
If only propose is present, then "committed_config" is null.
"propose" key has json-object values, that match propose-template.
<config-hash> - hash of looked up config. {
 "committed_config": config_body,
 "propose": {
  "num_validators": integer,
  "tx_propose": propose_transaction_body,
 "votes_history_hash": vote-history-hash
 }
}
/api/services/configuration/v1/configs/<config-hash>/votes GET Lookup votes for a config propose by config hash.
If a vote from validator is absent, null returned at the corresponding index in json array. If the config is absent altogether, null is returned instead of the array.
<config-hash> - hash of looked up config. [
  vote_for_propose_transaction_body,
  null,
  ...
]
/api/services/configuration/v1/configs/committed?previous_cfg_hash=<config-hash>&actual_from=<lowest-actual-from> GET Lookup all committed configs in commit order. <previous_cfg_hash> and <lowest_actual_from> are optional filtering parameters.
config-body is included in response if its previous_cfg_hash field equals the corresponding parameter.
It's included if its actual_from field is greater or equal than corresponding parameter.
[
 {
  "config": config-body,
  "hash": config-hash
 },
 {
  "config": config-body,
  "hash": config-hash
 },
 ...
]
/api/services/configuration/v1/configs/proposed?previous_cfg_hash=<config-hash>&actual_from=<lowest-actual-from> GET Lookup all proposed configs in commit order.
<previous_cfg_hash> and <lowest_actual_from> are optional filtering parameters.
propose-template is included in response if its previous_cfg_hash field equals the corresponding parameter.
It's included if its actual_from field is greater or equal than corresponding parameter.
[
 {
  "propose-data": propose-template,
  "hash": config-hash
 },
 {
  "propose-data": propose-template,
  "hash": config-hash
 },
 ...
]

Private endpoints

Posting a new config can be performed by any validator maintainer via private endpoint.

Propose and vote transactions restrictions

  • Propose transactions will only get submitted and executed with state change if all of the following conditions take place:

    1. new config body constitutes a valid json string and corresponds to StoredConfiguration format.

    2. previous_cfg_hash in proposed config body equals to hash of actual config.

    3. actual_from in proposed config body is greater than current height. current height is determined as the height of the last committed block + 1. This is important to obtain a sequential view of configs commit history. And, more important, the linear view of history of votes which conditioned scheduling of a config.

    4. a following config isn't already present.

    5. actual config contains the node-sender public key in the validators field array, as specified in from field of the propose transaction. The from field is determined by the public key of the node which postpropose endpoint is accessed for signing the transaction on maintainer's behalf.

    6. propose of config, which evaluates to the same hash, hasn't already been submitted.

  • Vote transactions will only get submitted and executed with state change if all of the following conditions take place:

    1. the vote transaction references a config propose with known config hash.

    2. a following config isn't already present.

    3. actual config contains the node-sender's public key in validators field, as specified in from field of vote transaction. The from field is determined by public key of node whose postvote endpoint is accessed for signing the transaction on the maintainer's behalf.

    4. previous_cfg_hash in the config propose, which is referenced by vote transaction, is equal to hash of actual config.

    5. actual_from in the config propose, which is referenced by vote transaction, is greater than current height.

    6. no vote from the same node public key has been submitted previously.

Examples

Endpoint HTTP method Description Response template
/api/services/configuration/v1/configs/postpropose POST Post proposed config body {
 "cfg_hash": configuration-hash,
 "tx_hash": transaction-hash
}
/api/services/configuration/v1/configs/<config-hash-vote-for>/postvote POST Vote for a configuration having specific hash {
 "tx_hash": transaction-hash
}