Release/v0.19.4pull/1590/head
@ -0,0 +1,23 @@ | |||
# Roadmap | |||
BREAKING CHANGES: | |||
- Better support for injecting randomness | |||
- Upgrade consensus for more real-time use of evidence | |||
FEATURES: | |||
- Use the chain as its own CA for nodes and validators | |||
- Tooling to run multiple blockchains/apps, possibly in a single process | |||
- State syncing (without transaction replay) | |||
- Add authentication and rate-limitting to the RPC | |||
IMPROVEMENTS: | |||
- Improve subtleties around mempool caching and logic | |||
- Consensus optimizations: | |||
- cache block parts for faster agreement after round changes | |||
- propagate block parts rarest first | |||
- Better testing of the consensus state machine (ie. use a DSL) | |||
- Auto compiled serialization/deserialization code instead of go-wire reflection | |||
BUG FIXES: | |||
- Graceful handling/recovery for apps that have non-determinism or fail to halt | |||
- Graceful handling/recovery for violations of safety, or liveness |
@ -0,0 +1,69 @@ | |||
#!/usr/bin/env bash | |||
# make all the files | |||
tendermint init --home ./tester/node0 | |||
tendermint init --home ./tester/node1 | |||
tendermint init --home ./tester/node2 | |||
tendermint init --home ./tester/node3 | |||
file0=./tester/node0/config/genesis.json | |||
file1=./tester/node1/config/genesis.json | |||
file2=./tester/node2/config/genesis.json | |||
file3=./tester/node3/config/genesis.json | |||
genesis_time=`cat $file0 | jq '.genesis_time'` | |||
chain_id=`cat $file0 | jq '.chain_id'` | |||
value0=`cat $file0 | jq '.validators[0].pub_key.value'` | |||
value1=`cat $file1 | jq '.validators[0].pub_key.value'` | |||
value2=`cat $file2 | jq '.validators[0].pub_key.value'` | |||
value3=`cat $file3 | jq '.validators[0].pub_key.value'` | |||
rm $file0 | |||
rm $file1 | |||
rm $file2 | |||
rm $file3 | |||
echo "{ | |||
\"genesis_time\": $genesis_time, | |||
\"chain_id\": $chain_id, | |||
\"validators\": [ | |||
{ | |||
\"pub_key\": { | |||
\"type\": \"AC26791624DE60\", | |||
\"value\": $value0 | |||
}, | |||
\"power:\": 10, | |||
\"name\":, \"\" | |||
}, | |||
{ | |||
\"pub_key\": { | |||
\"type\": \"AC26791624DE60\", | |||
\"value\": $value1 | |||
}, | |||
\"power:\": 10, | |||
\"name\":, \"\" | |||
}, | |||
{ | |||
\"pub_key\": { | |||
\"type\": \"AC26791624DE60\", | |||
\"value\": $value2 | |||
}, | |||
\"power:\": 10, | |||
\"name\":, \"\" | |||
}, | |||
{ | |||
\"pub_key\": { | |||
\"type\": \"AC26791624DE60\", | |||
\"value\": $value3 | |||
}, | |||
\"power:\": 10, | |||
\"name\":, \"\" | |||
} | |||
], | |||
\"app_hash\": \"\" | |||
}" >> $file0 | |||
cp $file0 $file1 | |||
cp $file0 $file2 | |||
cp $file2 $file3 |
@ -0,0 +1,169 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
##### main base config options ##### | |||
# TCP or UNIX socket address of the ABCI application, | |||
# or the name of an ABCI application compiled in with the Tendermint binary | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
# A custom human readable name for this node | |||
moniker = "alpha" | |||
# If this node is many blocks behind the tip of the chain, FastSync | |||
# allows them to catchup quickly by downloading blocks in parallel | |||
# and verifying their commits | |||
fast_sync = true | |||
# Database backend: leveldb | memdb | |||
db_backend = "leveldb" | |||
# Database directory | |||
db_path = "data" | |||
# Output level for logging, including package level options | |||
log_level = "main:info,state:info,*:error" | |||
##### additional base config options ##### | |||
# Path to the JSON file containing the initial validator set and other meta data | |||
genesis_file = "config/genesis.json" | |||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol | |||
priv_validator_file = "config/priv_validator.json" | |||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol | |||
node_key_file = "config/node_key.json" | |||
# Mechanism to connect to the ABCI application: socket | grpc | |||
abci = "socket" | |||
# TCP or UNIX socket address for the profiling server to listen on | |||
prof_laddr = "" | |||
# If true, query the ABCI app on connecting to a new peer | |||
# so the app can decide if we should keep the connection or not | |||
filter_peers = false | |||
##### advanced configuration options ##### | |||
##### rpc server configuration options ##### | |||
[rpc] | |||
# TCP or UNIX socket address for the RPC server to listen on | |||
laddr = "tcp://0.0.0.0:46657" | |||
# TCP or UNIX socket address for the gRPC server to listen on | |||
# NOTE: This server only supports /broadcast_tx_commit | |||
grpc_laddr = "" | |||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool | |||
unsafe = false | |||
##### peer to peer configuration options ##### | |||
[p2p] | |||
# Address to listen for incoming connections | |||
laddr = "tcp://0.0.0.0:46656" | |||
# Comma separated list of seed nodes to connect to | |||
seeds = "" | |||
# Comma separated list of nodes to keep persistent connections to | |||
# Do not add private peers to this list if you don't want them advertised | |||
persistent_peers = "" | |||
# Path to address book | |||
addr_book_file = "config/addrbook.json" | |||
# Set true for strict address routability rules | |||
addr_book_strict = true | |||
# Time to wait before flushing messages out on the connection, in ms | |||
flush_throttle_timeout = 100 | |||
# Maximum number of peers to connect to | |||
max_num_peers = 50 | |||
# Maximum size of a message packet payload, in bytes | |||
max_packet_msg_payload_size = 1024 | |||
# Rate at which packets can be sent, in bytes/second | |||
send_rate = 512000 | |||
# Rate at which packets can be received, in bytes/second | |||
recv_rate = 512000 | |||
# Set true to enable the peer-exchange reactor | |||
pex = true | |||
# Seed mode, in which node constantly crawls the network and looks for | |||
# peers. If another node asks it for addresses, it responds and disconnects. | |||
# | |||
# Does not work if the peer-exchange reactor is disabled. | |||
seed_mode = false | |||
# Authenticated encryption | |||
auth_enc = true | |||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) | |||
private_peer_ids = "" | |||
##### mempool configuration options ##### | |||
[mempool] | |||
recheck = true | |||
recheck_empty = true | |||
broadcast = true | |||
wal_dir = "data/mempool.wal" | |||
##### consensus configuration options ##### | |||
[consensus] | |||
wal_file = "data/cs.wal/wal" | |||
# All timeouts are in milliseconds | |||
timeout_propose = 3000 | |||
timeout_propose_delta = 500 | |||
timeout_prevote = 1000 | |||
timeout_prevote_delta = 500 | |||
timeout_precommit = 1000 | |||
timeout_precommit_delta = 500 | |||
timeout_commit = 1000 | |||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) | |||
skip_timeout_commit = false | |||
# BlockSize | |||
max_block_size_txs = 10000 | |||
max_block_size_bytes = 1 | |||
# EmptyBlocks mode and possible interval between empty blocks in seconds | |||
create_empty_blocks = true | |||
create_empty_blocks_interval = 0 | |||
# Reactor sleep duration parameters are in milliseconds | |||
peer_gossip_sleep_duration = 100 | |||
peer_query_maj23_sleep_duration = 2000 | |||
##### transactions indexer configuration options ##### | |||
[tx_index] | |||
# What indexer to use for transactions | |||
# | |||
# Options: | |||
# 1) "null" (default) | |||
# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). | |||
indexer = "kv" | |||
# Comma-separated list of tags to index (by default the only tag is tx hash) | |||
# | |||
# It's recommended to index only a subset of tags due to possible memory | |||
# bloat. This is, of course, depends on the indexer's DB and the volume of | |||
# transactions. | |||
index_tags = "" | |||
# When set to true, tells indexer to index all tags. Note this may be not | |||
# desirable (see the comment above). IndexTags has a precedence over | |||
# IndexAllTags (i.e. when given both, IndexTags will be indexed). | |||
index_all_tags = false |
@ -0,0 +1,39 @@ | |||
{ | |||
"genesis_time": "0001-01-01T00:00:00Z", | |||
"chain_id": "test-chain-A2i3OZ", | |||
"validators": [ | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
} | |||
], | |||
"app_hash": "" | |||
} |
@ -0,0 +1 @@ | |||
{"priv_key":{"type":"954568A3288910","value":"7lY+k6EDllG8Q9gVbF5313t/ag2YGkBVKdVa0YHJ9xO5k0w3Q/hke0Z7UFT1KgVDGRUEKzwAwwjwFQUvgF0ZWg=="}} |
@ -0,0 +1,14 @@ | |||
{ | |||
"address": "122A9414774A2FCAD026201DA477EF3F41970EF0", | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"priv_key": { | |||
"type": "954568A3288910", | |||
"value": "YLxp3ho+kySgAnzjBptbxDzSGw2ntGZLsIHQsaVxY/cP6TgB2Odg9ZsH3CZp3XfsF2mj+QC6U6hNFCsvL9BziQ==" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
moniker = "penguin" | |||
fast_sync = true | |||
db_backend = "leveldb" | |||
log_level = "state:info,*:error" | |||
[rpc] | |||
laddr = "tcp://0.0.0.0:46657" | |||
[p2p] | |||
laddr = "tcp://0.0.0.0:46656" | |||
seeds = "" |
@ -0,0 +1,169 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
##### main base config options ##### | |||
# TCP or UNIX socket address of the ABCI application, | |||
# or the name of an ABCI application compiled in with the Tendermint binary | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
# A custom human readable name for this node | |||
moniker = "bravo" | |||
# If this node is many blocks behind the tip of the chain, FastSync | |||
# allows them to catchup quickly by downloading blocks in parallel | |||
# and verifying their commits | |||
fast_sync = true | |||
# Database backend: leveldb | memdb | |||
db_backend = "leveldb" | |||
# Database directory | |||
db_path = "data" | |||
# Output level for logging, including package level options | |||
log_level = "main:info,state:info,*:error" | |||
##### additional base config options ##### | |||
# Path to the JSON file containing the initial validator set and other meta data | |||
genesis_file = "config/genesis.json" | |||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol | |||
priv_validator_file = "config/priv_validator.json" | |||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol | |||
node_key_file = "config/node_key.json" | |||
# Mechanism to connect to the ABCI application: socket | grpc | |||
abci = "socket" | |||
# TCP or UNIX socket address for the profiling server to listen on | |||
prof_laddr = "" | |||
# If true, query the ABCI app on connecting to a new peer | |||
# so the app can decide if we should keep the connection or not | |||
filter_peers = false | |||
##### advanced configuration options ##### | |||
##### rpc server configuration options ##### | |||
[rpc] | |||
# TCP or UNIX socket address for the RPC server to listen on | |||
laddr = "tcp://0.0.0.0:46657" | |||
# TCP or UNIX socket address for the gRPC server to listen on | |||
# NOTE: This server only supports /broadcast_tx_commit | |||
grpc_laddr = "" | |||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool | |||
unsafe = false | |||
##### peer to peer configuration options ##### | |||
[p2p] | |||
# Address to listen for incoming connections | |||
laddr = "tcp://0.0.0.0:46656" | |||
# Comma separated list of seed nodes to connect to | |||
seeds = "" | |||
# Comma separated list of nodes to keep persistent connections to | |||
# Do not add private peers to this list if you don't want them advertised | |||
persistent_peers = "" | |||
# Path to address book | |||
addr_book_file = "config/addrbook.json" | |||
# Set true for strict address routability rules | |||
addr_book_strict = true | |||
# Time to wait before flushing messages out on the connection, in ms | |||
flush_throttle_timeout = 100 | |||
# Maximum number of peers to connect to | |||
max_num_peers = 50 | |||
# Maximum size of a message packet payload, in bytes | |||
max_packet_msg_payload_size = 1024 | |||
# Rate at which packets can be sent, in bytes/second | |||
send_rate = 512000 | |||
# Rate at which packets can be received, in bytes/second | |||
recv_rate = 512000 | |||
# Set true to enable the peer-exchange reactor | |||
pex = true | |||
# Seed mode, in which node constantly crawls the network and looks for | |||
# peers. If another node asks it for addresses, it responds and disconnects. | |||
# | |||
# Does not work if the peer-exchange reactor is disabled. | |||
seed_mode = false | |||
# Authenticated encryption | |||
auth_enc = true | |||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) | |||
private_peer_ids = "" | |||
##### mempool configuration options ##### | |||
[mempool] | |||
recheck = true | |||
recheck_empty = true | |||
broadcast = true | |||
wal_dir = "data/mempool.wal" | |||
##### consensus configuration options ##### | |||
[consensus] | |||
wal_file = "data/cs.wal/wal" | |||
# All timeouts are in milliseconds | |||
timeout_propose = 3000 | |||
timeout_propose_delta = 500 | |||
timeout_prevote = 1000 | |||
timeout_prevote_delta = 500 | |||
timeout_precommit = 1000 | |||
timeout_precommit_delta = 500 | |||
timeout_commit = 1000 | |||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) | |||
skip_timeout_commit = false | |||
# BlockSize | |||
max_block_size_txs = 10000 | |||
max_block_size_bytes = 1 | |||
# EmptyBlocks mode and possible interval between empty blocks in seconds | |||
create_empty_blocks = true | |||
create_empty_blocks_interval = 0 | |||
# Reactor sleep duration parameters are in milliseconds | |||
peer_gossip_sleep_duration = 100 | |||
peer_query_maj23_sleep_duration = 2000 | |||
##### transactions indexer configuration options ##### | |||
[tx_index] | |||
# What indexer to use for transactions | |||
# | |||
# Options: | |||
# 1) "null" (default) | |||
# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). | |||
indexer = "kv" | |||
# Comma-separated list of tags to index (by default the only tag is tx hash) | |||
# | |||
# It's recommended to index only a subset of tags due to possible memory | |||
# bloat. This is, of course, depends on the indexer's DB and the volume of | |||
# transactions. | |||
index_tags = "" | |||
# When set to true, tells indexer to index all tags. Note this may be not | |||
# desirable (see the comment above). IndexTags has a precedence over | |||
# IndexAllTags (i.e. when given both, IndexTags will be indexed). | |||
index_all_tags = false |
@ -0,0 +1,39 @@ | |||
{ | |||
"genesis_time": "0001-01-01T00:00:00Z", | |||
"chain_id": "test-chain-A2i3OZ", | |||
"validators": [ | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
} | |||
], | |||
"app_hash": "" | |||
} |
@ -0,0 +1 @@ | |||
{"priv_key":{"type":"954568A3288910","value":"H71dc/TIG7nTselfa9nG0WRArXLKYnm7P5eFCk2lk8ASKQ3sIHpbdxCSHQD/RcdHe7TiabJeuOssNPvPWiyQEQ=="}} |
@ -0,0 +1,14 @@ | |||
{ | |||
"address": "BEA1B57F5806CF9AC4D54C8CF806DED5C0F102E1", | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"priv_key": { | |||
"type": "954568A3288910", | |||
"value": "o0IqrHSPtd5YqGefodWxpJuRzvuVBjgbH785vbMgk7Vvno3kYJHVp1xVG4Q2N8rD+aubZ2SFPvA1ldX9IOwqxQ==" | |||
} | |||
} |
@ -1,42 +0,0 @@ | |||
{ | |||
"genesis_time":"0001-01-01T00:00:00Z", | |||
"chain_id":"test-chain-wt7apy", | |||
"validators":[ | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data":"F08446C80A33E10D620E21450821B58D053778528F2B583D423B3E46EC647D30" | |||
}, | |||
"power":10, | |||
"name":"node1" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "A8423F70A9E512643B4B00F7C3701ECAD1F31B0A1FAA45852C41046353B9A07F" | |||
}, | |||
"power":10, | |||
"name":"node2" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "E52EFFAEDFE1D618ECDA71DE3B23592B3612CAABA0C10826E4C3120B2198C29A" | |||
}, | |||
"power":10, | |||
"name":"node3" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "2B8FC09C07955A02998DFE5AF1AAD1C44115ECA7635FF51A867CF4265D347C07" | |||
}, | |||
"power":10, | |||
"name":"node4" | |||
} | |||
], | |||
"app_hash":"" | |||
} |
@ -1,6 +0,0 @@ | |||
{ | |||
"priv_key" : { | |||
"data" : "DA9BAABEA7211A6D93D9A1986B4279EAB3021FAA1653D459D53E6AB4D1CFB4C69BF7D52E48CF00AC5779AA0A6D3C368955D5636A677F72370B8ED19989714CFC", | |||
"type" : "ed25519" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
{ | |||
"address":"4DC2756029CE0D8F8C6C3E4C3CE6EE8C30AF352F", | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data":"F08446C80A33E10D620E21450821B58D053778528F2B583D423B3E46EC647D30" | |||
}, | |||
"last_height":0, | |||
"last_round":0, | |||
"last_step":0, | |||
"last_signature":null, | |||
"priv_key":{ | |||
"type":"ed25519", | |||
"data":"4D3648E1D93C8703E436BFF814728B6BD270CFDFD686DF5385E8ACBEB7BE2D7DF08446C80A33E10D620E21450821B58D053778528F2B583D423B3E46EC647D30" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
moniker = "penguin" | |||
fast_sync = true | |||
db_backend = "leveldb" | |||
log_level = "state:info,*:error" | |||
[rpc] | |||
laddr = "tcp://0.0.0.0:46657" | |||
[p2p] | |||
laddr = "tcp://0.0.0.0:46656" | |||
seeds = "" |
@ -0,0 +1,169 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
##### main base config options ##### | |||
# TCP or UNIX socket address of the ABCI application, | |||
# or the name of an ABCI application compiled in with the Tendermint binary | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
# A custom human readable name for this node | |||
moniker = "charlie" | |||
# If this node is many blocks behind the tip of the chain, FastSync | |||
# allows them to catchup quickly by downloading blocks in parallel | |||
# and verifying their commits | |||
fast_sync = true | |||
# Database backend: leveldb | memdb | |||
db_backend = "leveldb" | |||
# Database directory | |||
db_path = "data" | |||
# Output level for logging, including package level options | |||
log_level = "main:info,state:info,*:error" | |||
##### additional base config options ##### | |||
# Path to the JSON file containing the initial validator set and other meta data | |||
genesis_file = "config/genesis.json" | |||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol | |||
priv_validator_file = "config/priv_validator.json" | |||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol | |||
node_key_file = "config/node_key.json" | |||
# Mechanism to connect to the ABCI application: socket | grpc | |||
abci = "socket" | |||
# TCP or UNIX socket address for the profiling server to listen on | |||
prof_laddr = "" | |||
# If true, query the ABCI app on connecting to a new peer | |||
# so the app can decide if we should keep the connection or not | |||
filter_peers = false | |||
##### advanced configuration options ##### | |||
##### rpc server configuration options ##### | |||
[rpc] | |||
# TCP or UNIX socket address for the RPC server to listen on | |||
laddr = "tcp://0.0.0.0:46657" | |||
# TCP or UNIX socket address for the gRPC server to listen on | |||
# NOTE: This server only supports /broadcast_tx_commit | |||
grpc_laddr = "" | |||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool | |||
unsafe = false | |||
##### peer to peer configuration options ##### | |||
[p2p] | |||
# Address to listen for incoming connections | |||
laddr = "tcp://0.0.0.0:46656" | |||
# Comma separated list of seed nodes to connect to | |||
seeds = "" | |||
# Comma separated list of nodes to keep persistent connections to | |||
# Do not add private peers to this list if you don't want them advertised | |||
persistent_peers = "" | |||
# Path to address book | |||
addr_book_file = "config/addrbook.json" | |||
# Set true for strict address routability rules | |||
addr_book_strict = true | |||
# Time to wait before flushing messages out on the connection, in ms | |||
flush_throttle_timeout = 100 | |||
# Maximum number of peers to connect to | |||
max_num_peers = 50 | |||
# Maximum size of a message packet payload, in bytes | |||
max_packet_msg_payload_size = 1024 | |||
# Rate at which packets can be sent, in bytes/second | |||
send_rate = 512000 | |||
# Rate at which packets can be received, in bytes/second | |||
recv_rate = 512000 | |||
# Set true to enable the peer-exchange reactor | |||
pex = true | |||
# Seed mode, in which node constantly crawls the network and looks for | |||
# peers. If another node asks it for addresses, it responds and disconnects. | |||
# | |||
# Does not work if the peer-exchange reactor is disabled. | |||
seed_mode = false | |||
# Authenticated encryption | |||
auth_enc = true | |||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) | |||
private_peer_ids = "" | |||
##### mempool configuration options ##### | |||
[mempool] | |||
recheck = true | |||
recheck_empty = true | |||
broadcast = true | |||
wal_dir = "data/mempool.wal" | |||
##### consensus configuration options ##### | |||
[consensus] | |||
wal_file = "data/cs.wal/wal" | |||
# All timeouts are in milliseconds | |||
timeout_propose = 3000 | |||
timeout_propose_delta = 500 | |||
timeout_prevote = 1000 | |||
timeout_prevote_delta = 500 | |||
timeout_precommit = 1000 | |||
timeout_precommit_delta = 500 | |||
timeout_commit = 1000 | |||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) | |||
skip_timeout_commit = false | |||
# BlockSize | |||
max_block_size_txs = 10000 | |||
max_block_size_bytes = 1 | |||
# EmptyBlocks mode and possible interval between empty blocks in seconds | |||
create_empty_blocks = true | |||
create_empty_blocks_interval = 0 | |||
# Reactor sleep duration parameters are in milliseconds | |||
peer_gossip_sleep_duration = 100 | |||
peer_query_maj23_sleep_duration = 2000 | |||
##### transactions indexer configuration options ##### | |||
[tx_index] | |||
# What indexer to use for transactions | |||
# | |||
# Options: | |||
# 1) "null" (default) | |||
# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). | |||
indexer = "kv" | |||
# Comma-separated list of tags to index (by default the only tag is tx hash) | |||
# | |||
# It's recommended to index only a subset of tags due to possible memory | |||
# bloat. This is, of course, depends on the indexer's DB and the volume of | |||
# transactions. | |||
index_tags = "" | |||
# When set to true, tells indexer to index all tags. Note this may be not | |||
# desirable (see the comment above). IndexTags has a precedence over | |||
# IndexAllTags (i.e. when given both, IndexTags will be indexed). | |||
index_all_tags = false |
@ -0,0 +1,39 @@ | |||
{ | |||
"genesis_time": "0001-01-01T00:00:00Z", | |||
"chain_id": "test-chain-A2i3OZ", | |||
"validators": [ | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
} | |||
], | |||
"app_hash": "" | |||
} |
@ -0,0 +1 @@ | |||
{"priv_key":{"type":"954568A3288910","value":"COHZ/Y2cWGWxJNkRwtpQBt5sYvOnb6Gpz0lO46XERRJFBIdSWD5x1UMGRSTmnvW1ec5G4bMdg6zUZKOZD+vVPg=="}} |
@ -0,0 +1,14 @@ | |||
{ | |||
"address": "F0AA266949FB29ADA0B679C27889ED930BD1BDA1", | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"priv_key": { | |||
"type": "954568A3288910", | |||
"value": "khADeZ5K/8u/L99DFaZNRq8V5g+EHWbwfqFjhCrppaAiBkOkm8YDRMBqaJwDyKtzL5Ff8GRSWPoNfAzv3XLAhQ==" | |||
} | |||
} |
@ -1,42 +0,0 @@ | |||
{ | |||
"genesis_time":"0001-01-01T00:00:00Z", | |||
"chain_id":"test-chain-wt7apy", | |||
"validators":[ | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data":"F08446C80A33E10D620E21450821B58D053778528F2B583D423B3E46EC647D30" | |||
}, | |||
"power":10, | |||
"name":"node1" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "A8423F70A9E512643B4B00F7C3701ECAD1F31B0A1FAA45852C41046353B9A07F" | |||
}, | |||
"power":10, | |||
"name":"node2" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "E52EFFAEDFE1D618ECDA71DE3B23592B3612CAABA0C10826E4C3120B2198C29A" | |||
}, | |||
"power":10, | |||
"name":"node3" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "2B8FC09C07955A02998DFE5AF1AAD1C44115ECA7635FF51A867CF4265D347C07" | |||
}, | |||
"power":10, | |||
"name":"node4" | |||
} | |||
], | |||
"app_hash":"" | |||
} |
@ -1,6 +0,0 @@ | |||
{ | |||
"priv_key" : { | |||
"data" : "F7BCABA165DFC0DDD50AE563EFB285BAA236EA805D35612504238A36EFA105958756442B1D9F942D7ABD259F2D59671657B6378E9C7194342A7AAA47A66D1E95", | |||
"type" : "ed25519" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
{ | |||
"address": "DD6C63A762608A9DDD4A845657743777F63121D6", | |||
"pub_key": { | |||
"type": "ed25519", | |||
"data": "A8423F70A9E512643B4B00F7C3701ECAD1F31B0A1FAA45852C41046353B9A07F" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"last_signature": null, | |||
"priv_key": { | |||
"type": "ed25519", | |||
"data": "7B0DE666FF5E9B437D284BCE767F612381890C018B93B0A105D2E829A568DA6FA8423F70A9E512643B4B00F7C3701ECAD1F31B0A1FAA45852C41046353B9A07F" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
moniker = "penguin" | |||
fast_sync = true | |||
db_backend = "leveldb" | |||
log_level = "state:info,*:error" | |||
[rpc] | |||
laddr = "tcp://0.0.0.0:46657" | |||
[p2p] | |||
laddr = "tcp://0.0.0.0:46656" | |||
seeds = "" |
@ -0,0 +1,169 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
##### main base config options ##### | |||
# TCP or UNIX socket address of the ABCI application, | |||
# or the name of an ABCI application compiled in with the Tendermint binary | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
# A custom human readable name for this node | |||
moniker = "delta" | |||
# If this node is many blocks behind the tip of the chain, FastSync | |||
# allows them to catchup quickly by downloading blocks in parallel | |||
# and verifying their commits | |||
fast_sync = true | |||
# Database backend: leveldb | memdb | |||
db_backend = "leveldb" | |||
# Database directory | |||
db_path = "data" | |||
# Output level for logging, including package level options | |||
log_level = "main:info,state:info,*:error" | |||
##### additional base config options ##### | |||
# Path to the JSON file containing the initial validator set and other meta data | |||
genesis_file = "config/genesis.json" | |||
# Path to the JSON file containing the private key to use as a validator in the consensus protocol | |||
priv_validator_file = "config/priv_validator.json" | |||
# Path to the JSON file containing the private key to use for node authentication in the p2p protocol | |||
node_key_file = "config/node_key.json" | |||
# Mechanism to connect to the ABCI application: socket | grpc | |||
abci = "socket" | |||
# TCP or UNIX socket address for the profiling server to listen on | |||
prof_laddr = "" | |||
# If true, query the ABCI app on connecting to a new peer | |||
# so the app can decide if we should keep the connection or not | |||
filter_peers = false | |||
##### advanced configuration options ##### | |||
##### rpc server configuration options ##### | |||
[rpc] | |||
# TCP or UNIX socket address for the RPC server to listen on | |||
laddr = "tcp://0.0.0.0:46657" | |||
# TCP or UNIX socket address for the gRPC server to listen on | |||
# NOTE: This server only supports /broadcast_tx_commit | |||
grpc_laddr = "" | |||
# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool | |||
unsafe = false | |||
##### peer to peer configuration options ##### | |||
[p2p] | |||
# Address to listen for incoming connections | |||
laddr = "tcp://0.0.0.0:46656" | |||
# Comma separated list of seed nodes to connect to | |||
seeds = "" | |||
# Comma separated list of nodes to keep persistent connections to | |||
# Do not add private peers to this list if you don't want them advertised | |||
persistent_peers = "" | |||
# Path to address book | |||
addr_book_file = "config/addrbook.json" | |||
# Set true for strict address routability rules | |||
addr_book_strict = true | |||
# Time to wait before flushing messages out on the connection, in ms | |||
flush_throttle_timeout = 100 | |||
# Maximum number of peers to connect to | |||
max_num_peers = 50 | |||
# Maximum size of a message packet payload, in bytes | |||
max_packet_msg_payload_size = 1024 | |||
# Rate at which packets can be sent, in bytes/second | |||
send_rate = 512000 | |||
# Rate at which packets can be received, in bytes/second | |||
recv_rate = 512000 | |||
# Set true to enable the peer-exchange reactor | |||
pex = true | |||
# Seed mode, in which node constantly crawls the network and looks for | |||
# peers. If another node asks it for addresses, it responds and disconnects. | |||
# | |||
# Does not work if the peer-exchange reactor is disabled. | |||
seed_mode = false | |||
# Authenticated encryption | |||
auth_enc = true | |||
# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) | |||
private_peer_ids = "" | |||
##### mempool configuration options ##### | |||
[mempool] | |||
recheck = true | |||
recheck_empty = true | |||
broadcast = true | |||
wal_dir = "data/mempool.wal" | |||
##### consensus configuration options ##### | |||
[consensus] | |||
wal_file = "data/cs.wal/wal" | |||
# All timeouts are in milliseconds | |||
timeout_propose = 3000 | |||
timeout_propose_delta = 500 | |||
timeout_prevote = 1000 | |||
timeout_prevote_delta = 500 | |||
timeout_precommit = 1000 | |||
timeout_precommit_delta = 500 | |||
timeout_commit = 1000 | |||
# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) | |||
skip_timeout_commit = false | |||
# BlockSize | |||
max_block_size_txs = 10000 | |||
max_block_size_bytes = 1 | |||
# EmptyBlocks mode and possible interval between empty blocks in seconds | |||
create_empty_blocks = true | |||
create_empty_blocks_interval = 0 | |||
# Reactor sleep duration parameters are in milliseconds | |||
peer_gossip_sleep_duration = 100 | |||
peer_query_maj23_sleep_duration = 2000 | |||
##### transactions indexer configuration options ##### | |||
[tx_index] | |||
# What indexer to use for transactions | |||
# | |||
# Options: | |||
# 1) "null" (default) | |||
# 2) "kv" - the simplest possible indexer, backed by key-value storage (defaults to levelDB; see DBBackend). | |||
indexer = "kv" | |||
# Comma-separated list of tags to index (by default the only tag is tx hash) | |||
# | |||
# It's recommended to index only a subset of tags due to possible memory | |||
# bloat. This is, of course, depends on the indexer's DB and the volume of | |||
# transactions. | |||
index_tags = "" | |||
# When set to true, tells indexer to index all tags. Note this may be not | |||
# desirable (see the comment above). IndexTags has a precedence over | |||
# IndexAllTags (i.e. when given both, IndexTags will be indexed). | |||
index_all_tags = false |
@ -0,0 +1,39 @@ | |||
{ | |||
"genesis_time": "0001-01-01T00:00:00Z", | |||
"chain_id": "test-chain-A2i3OZ", | |||
"validators": [ | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "D+k4AdjnYPWbB9wmad137Bdpo/kAulOoTRQrLy/Qc4k=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "b56N5GCR1adcVRuENjfKw/mrm2dkhT7wNZXV/SDsKsU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "IgZDpJvGA0TAamicA8ircy+RX/BkUlj6DXwM791ywIU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
}, | |||
{ | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" | |||
}, | |||
"power": 10, | |||
"name": "" | |||
} | |||
], | |||
"app_hash": "" | |||
} |
@ -0,0 +1 @@ | |||
{"priv_key":{"type":"954568A3288910","value":"9Y9xp/tUJJ6pHTF5SUV0bGKYSdVbFtMHu+Lr8S0JBSZAwneaejnfOEU1LMKOnQ07skrDUaJcj5di3jAyjxJzqg=="}} |
@ -0,0 +1,14 @@ | |||
{ | |||
"address": "9A1A6914EB5F4FF0269C7EEEE627C27310CC64F9", | |||
"pub_key": { | |||
"type": "AC26791624DE60", | |||
"value": "KGAZfxZvIZ7abbeIQ85U1ECG6+I62KSdaH8ulc0+OiU=" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"priv_key": { | |||
"type": "954568A3288910", | |||
"value": "jb52LZ5gp+eQ8nJlFK1z06nBMp1gD8ICmyzdM1icGOgoYBl/Fm8hntptt4hDzlTUQIbr4jrYpJ1ofy6VzT46JQ==" | |||
} | |||
} |
@ -1,42 +0,0 @@ | |||
{ | |||
"genesis_time":"0001-01-01T00:00:00Z", | |||
"chain_id":"test-chain-wt7apy", | |||
"validators":[ | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data":"F08446C80A33E10D620E21450821B58D053778528F2B583D423B3E46EC647D30" | |||
}, | |||
"power":10, | |||
"name":"node1" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "A8423F70A9E512643B4B00F7C3701ECAD1F31B0A1FAA45852C41046353B9A07F" | |||
}, | |||
"power":10, | |||
"name":"node2" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "E52EFFAEDFE1D618ECDA71DE3B23592B3612CAABA0C10826E4C3120B2198C29A" | |||
}, | |||
"power":10, | |||
"name":"node3" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "2B8FC09C07955A02998DFE5AF1AAD1C44115ECA7635FF51A867CF4265D347C07" | |||
}, | |||
"power":10, | |||
"name":"node4" | |||
} | |||
], | |||
"app_hash":"" | |||
} |
@ -1,6 +0,0 @@ | |||
{ | |||
"priv_key" : { | |||
"data" : "95136FCC97E4446B3141EDF9841078107ECE755E99925D79CCBF91085492680B3CA1034D9917DF1DED4E4AB2D9BC225919F6CB2176F210D2368697CC339DF4E7", | |||
"type" : "ed25519" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
{ | |||
"address": "6D6A1E313B407B5474106CA8759C976B777AB659", | |||
"pub_key": { | |||
"type": "ed25519", | |||
"data": "E52EFFAEDFE1D618ECDA71DE3B23592B3612CAABA0C10826E4C3120B2198C29A" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"last_signature": null, | |||
"priv_key": { | |||
"type": "ed25519", | |||
"data": "622432A370111A5C25CFE121E163FE709C9D5C95F551EDBD7A2C69A8545C9B76E52EFFAEDFE1D618ECDA71DE3B23592B3612CAABA0C10826E4C3120B2198C29A" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
# This is a TOML config file. | |||
# For more information, see https://github.com/toml-lang/toml | |||
proxy_app = "tcp://127.0.0.1:46658" | |||
moniker = "penguin" | |||
fast_sync = true | |||
db_backend = "leveldb" | |||
log_level = "state:info,*:error" | |||
[rpc] | |||
laddr = "tcp://0.0.0.0:46657" | |||
[p2p] | |||
laddr = "tcp://0.0.0.0:46656" | |||
seeds = "" |
@ -1,42 +0,0 @@ | |||
{ | |||
"genesis_time":"0001-01-01T00:00:00Z", | |||
"chain_id":"test-chain-wt7apy", | |||
"validators":[ | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data":"F08446C80A33E10D620E21450821B58D053778528F2B583D423B3E46EC647D30" | |||
}, | |||
"power":10, | |||
"name":"node1" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "A8423F70A9E512643B4B00F7C3701ECAD1F31B0A1FAA45852C41046353B9A07F" | |||
}, | |||
"power":10, | |||
"name":"node2" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "E52EFFAEDFE1D618ECDA71DE3B23592B3612CAABA0C10826E4C3120B2198C29A" | |||
}, | |||
"power":10, | |||
"name":"node3" | |||
} | |||
, | |||
{ | |||
"pub_key":{ | |||
"type":"ed25519", | |||
"data": "2B8FC09C07955A02998DFE5AF1AAD1C44115ECA7635FF51A867CF4265D347C07" | |||
}, | |||
"power":10, | |||
"name":"node4" | |||
} | |||
], | |||
"app_hash":"" | |||
} |
@ -1,6 +0,0 @@ | |||
{ | |||
"priv_key" : { | |||
"data" : "8895D6C9A1B46AB83A8E2BAE2121B8C3E245B9E9126EBD797FEAC5058285F2F64FDE2E8182C88AD5185A49D837C581465D57BD478C41865A66D7D9742D8AEF57", | |||
"type" : "ed25519" | |||
} | |||
} |
@ -1,15 +0,0 @@ | |||
{ | |||
"address": "829A9663611D3DD88A3D84EA0249679D650A0755", | |||
"pub_key": { | |||
"type": "ed25519", | |||
"data": "2B8FC09C07955A02998DFE5AF1AAD1C44115ECA7635FF51A867CF4265D347C07" | |||
}, | |||
"last_height": 0, | |||
"last_round": 0, | |||
"last_step": 0, | |||
"last_signature": null, | |||
"priv_key": { | |||
"type": "ed25519", | |||
"data": "0A604D1C9AE94A50150BF39E603239092F9392E4773F4D8F4AC1D86E6438E89E2B8FC09C07955A02998DFE5AF1AAD1C44115ECA7635FF51A867CF4265D347C07" | |||
} | |||
} |
@ -0,0 +1,71 @@ | |||
# Tendermint Specification | |||
This is a markdown specification of the Tendermint blockchain. | |||
It defines the base data structures, how they are validated, | |||
and how they are communicated over the network. | |||
If you find discrepancies between the spec and the code that | |||
do not have an associated issue or pull request on github, | |||
please submit them to our [bug bounty](https://tendermint.com/security)! | |||
## Contents | |||
### Data Structures | |||
- [Overview](#overview) | |||
- [Encoding and Digests](encoding.md) | |||
- [Blockchain](blockchain.md) | |||
- [State](state.md) | |||
### P2P and Network Protocols | |||
- [The Base P2P Layer](p2p): multiplex the protocols ("reactors") on authenticated and encrypted TCP connections | |||
- [Peer Exchange (PEX)](reactors/pex): gossip known peer addresses so peers can find each other | |||
- [Block Sync](reactors/block_sync): gossip blocks so peers can catch up quickly | |||
- [Consensus](reactors/consensus): gossip votes and block parts so new blocks can be committed | |||
- [Mempool](reactors/mempool): gossip transactions so they get included in blocks | |||
- Evidence: TODO | |||
### More | |||
- Light Client: TODO | |||
- Persistence: TODO | |||
## Overview | |||
Tendermint provides Byzantine Fault Tolerant State Machine Replication using | |||
hash-linked batches of transactions. Such transaction batches are called "blocks". | |||
Hence, Tendermint defines a "blockchain". | |||
Each block in Tendermint has a unique index - its Height. | |||
A block at `Height == H` can only be committed *after* the | |||
block at `Height == H-1`. | |||
Each block is committed by a known set of weighted Validators. | |||
Membership and weighting within this set may change over time. | |||
Tendermint guarantees the safety and liveness of the blockchain | |||
so long as less than 1/3 of the total weight of the Validator set | |||
is malicious or faulty. | |||
A commit in Tendermint is a set of signed messages from more than 2/3 of | |||
the total weight of the current Validator set. Validators take turns proposing | |||
blocks and voting on them. Once enough votes are received, the block is considered | |||
committed. These votes are included in the *next* block as proof that the previous block | |||
was committed - they cannot be included in the current block, as that block has already been | |||
created. | |||
Once a block is committed, it can be executed against an application. | |||
The application returns results for each of the transactions in the block. | |||
The application can also return changes to be made to the validator set, | |||
as well as a cryptographic digest of its latest state. | |||
Tendermint is designed to enable efficient verification and authentication | |||
of the latest state of the blockchain. To achieve this, it embeds | |||
cryptographic commitments to certain information in the block "header". | |||
This information includes the contents of the block (eg. the transactions), | |||
the validator set committing the block, as well as the various results returned by the application. | |||
Note, however, that block execution only occurs *after* a block is committed. | |||
Thus, application results can only be included in the *next* block. | |||
Also note that information like the transaction results and the validator set are never | |||
directly included in the block - only their cryptographic digests (Merkle roots) are. | |||
Hence, verification of a block requires a separate data structure to store this information. | |||
We call this the `State`. Block verification also requires access to the previous block. |
@ -1,71 +1 @@ | |||
# Tendermint Specification | |||
This is a markdown specification of the Tendermint blockchain. | |||
It defines the base data structures, how they are validated, | |||
and how they are communicated over the network. | |||
If you find discrepancies between the spec and the code that | |||
do not have an associated issue or pull request on github, | |||
please submit them to our [bug bounty](https://tendermint.com/security)! | |||
## Contents | |||
### Data Structures | |||
- [Overview](#overview) | |||
- [Encoding and Digests](encoding.md) | |||
- [Blockchain](blockchain.md) | |||
- [State](state.md) | |||
### P2P and Network Protocols | |||
- [The Base P2P Layer](p2p): multiplex the protocols ("reactors") on authenticated and encrypted TCP connections | |||
- [Peer Exchange (PEX)](reactors/pex): gossip known peer addresses so peers can find each other | |||
- [Block Sync](reactors/block_sync): gossip blocks so peers can catch up quickly | |||
- [Consensus](reactors/consensus): gossip votes and block parts so new blocks can be committed | |||
- [Mempool](reactors/mempool): gossip transactions so they get included in blocks | |||
- Evidence: TODO | |||
### More | |||
- Light Client: TODO | |||
- Persistence: TODO | |||
## Overview | |||
Tendermint provides Byzantine Fault Tolerant State Machine Replication using | |||
hash-linked batches of transactions. Such transaction batches are called "blocks". | |||
Hence, Tendermint defines a "blockchain". | |||
Each block in Tendermint has a unique index - its Height. | |||
A block at `Height == H` can only be committed *after* the | |||
block at `Height == H-1`. | |||
Each block is committed by a known set of weighted Validators. | |||
Membership and weighting within this set may change over time. | |||
Tendermint guarantees the safety and liveness of the blockchain | |||
so long as less than 1/3 of the total weight of the Validator set | |||
is malicious or faulty. | |||
A commit in Tendermint is a set of signed messages from more than 2/3 of | |||
the total weight of the current Validator set. Validators take turns proposing | |||
blocks and voting on them. Once enough votes are received, the block is considered | |||
committed. These votes are included in the *next* block as proof that the previous block | |||
was committed - they cannot be included in the current block, as that block has already been | |||
created. | |||
Once a block is committed, it can be executed against an application. | |||
The application returns results for each of the transactions in the block. | |||
The application can also return changes to be made to the validator set, | |||
as well as a cryptographic digest of its latest state. | |||
Tendermint is designed to enable efficient verification and authentication | |||
of the latest state of the blockchain. To achieve this, it embeds | |||
cryptographic commitments to certain information in the block "header". | |||
This information includes the contents of the block (eg. the transactions), | |||
the validator set committing the block, as well as the various results returned by the application. | |||
Note, however, that block execution only occurs *after* a block is committed. | |||
Thus, application results can only be included in the *next* block. | |||
Also note that information like the transaction results and the validator set are never | |||
directly included in the block - only their cryptographic digests (Merkle roots) are. | |||
Hence, verification of a block requires a separate data structure to store this information. | |||
We call this the `State`. Block verification also requires access to the previous block. | |||
Spec moved to [docs/spec](./docs/spec). |
@ -0,0 +1,138 @@ | |||
Terraform & Ansible | |||
=================== | |||
Automated deployments are done using `Terraform <https://www.terraform.io/>`__ to create servers on Digital Ocean then | |||
`Ansible <http://www.ansible.com/>`__ to create and manage testnets on those servers. | |||
Install | |||
------- | |||
NOTE: see the `integration bash script <https://github.com/tendermint/tendermint/blob/zach/ansible/networks/remote/integration.sh>`__ that can be run on a fresh DO droplet and will automatically spin up a 4 node testnet. The script more or less does everything described below. | |||
- Install `Terraform <https://www.terraform.io/downloads.html>`__ and `Ansible <http://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html>`__ on a Linux machine. | |||
- Create a `DigitalOcean API token <https://cloud.digitalocean.com/settings/api/tokens>`__ with read and write capability. | |||
- Install the python dopy package (``pip install dopy``) | |||
- Create SSH keys (``ssh-keygen``) | |||
- Set environment variables: | |||
:: | |||
export DO_API_TOKEN="abcdef01234567890abcdef01234567890" | |||
export SSH_KEY_FILE="$HOME/.ssh/id_rsa.pub" | |||
These will be used by both ``terraform`` and ``ansible``. | |||
Terraform | |||
--------- | |||
This step will create four Digital Ocean droplets. First, go to the correct directory: | |||
:: | |||
cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/terraform | |||
then: | |||
:: | |||
terraform init | |||
terraform apply -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" | |||
and you will get a list of IP addresses that belong to your droplets. | |||
With the droplets created and running, let's setup Ansible. | |||
Using Ansible | |||
------------- | |||
The playbooks in `the ansible directory <https://github.com/tendermint/tendermint/tree/master/networks/remote/ansible>`__ | |||
run ansible roles to configure the sentry node architecture. You must switch to this directory to run ansible (``cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/ansible``). | |||
There are several roles that are self-explanatory: | |||
First, we configure our droplets by specifying the paths for tendermint (``BINARY``) and the node files (``CONFIGDIR``). The latter expects any number of directories named ``node0, node1, ...`` and so on (equal to the number of droplets created). For this example, we use pre-created files from `this directory <https://github.com/tendermint/tendermint/tree/master/docs/examples>`__. To create your own files, use either the ``tendermint testnet`` command or review `manual deployments <./deploy-testnets.html>`__. | |||
Here's the command to run: | |||
:: | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet config.yml -e BINARY=$GOPATH/src/github.com/tendermint/tendermint/build/tendermint -e CONFIGDIR=$GOPATH/src/github.com/tendermint/tendermint/docs/examples | |||
Voila! All your droplets now have the ``tendermint`` binary and required configuration files to run a testnet. | |||
Next, we run the install role: | |||
:: | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml | |||
which as you'll see below, executes ``tendermint node --proxy_app=kvstore`` on all droplets. Although we'll soon be modifying this role and running it again, this first execution allows us to get each ``node_info.id`` that corresponds to each ``node_info.listen_addr``. (This part will be automated in the future). In your browser (or using ``curl``), for every droplet, go to IP:46657/status and note the two just mentioned ``node_info`` fields. Notice that blocks aren't being created (``latest_block_height`` should be zero and not increasing). | |||
Next, open ``roles/install/templates/systemd.service.j2`` and look for the line ``ExecStart`` which should look something like: | |||
:: | |||
ExecStart=/usr/bin/tendermint node --proxy_app=kvstore | |||
and add the ``--p2p.persistent_peers`` flag with the relevant information for each node. The resulting file should look something like: | |||
:: | |||
[Unit] | |||
Description={{service}} | |||
Requires=network-online.target | |||
After=network-online.target | |||
[Service] | |||
Restart=on-failure | |||
User={{service}} | |||
Group={{service}} | |||
PermissionsStartOnly=true | |||
ExecStart=/usr/bin/tendermint node --proxy_app=kvstore --p2p.persistent_peers=167b80242c300bf0ccfb3ced3dec60dc2a81776e@165.227.41.206:46656,3c7a5920811550c04bf7a0b2f1e02ab52317b5e6@165.227.43.146:46656,303a1a4312c30525c99ba66522dd81cca56a361a@159.89.115.32:46656,b686c2a7f4b1b46dca96af3a0f31a6a7beae0be4@159.89.119.125:46656 | |||
ExecReload=/bin/kill -HUP $MAINPID | |||
KillSignal=SIGTERM | |||
[Install] | |||
WantedBy=multi-user.target | |||
Then, stop the nodes: | |||
:: | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet stop.yml | |||
Finally, we run the install role again: | |||
:: | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml | |||
to re-run ``tendermint node`` with the new flag, on all droplets. The ``latest_block_hash`` should now be changing and ``latest_block_height`` increasing. Your testnet is now up and running :) | |||
Peek at the logs with the status role: | |||
:: | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet status.yml | |||
Logging | |||
------- | |||
The crudest way is the status role described above. You can also ship logs to Logz.io, an Elastic stack (Elastic search, Logstash and Kibana) service provider. You can set up your nodes to log there automatically. Create an account and get your API key from the notes on `this page <https://app.logz.io/#/dashboard/data-sources/Filebeat>`__, then: | |||
:: | |||
yum install systemd-devel || echo "This will only work on RHEL-based systems." | |||
apt-get install libsystemd-dev || echo "This will only work on Debian-based systems." | |||
go get github.com/mheese/journalbeat | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet logzio.yml -e LOGZIO_TOKEN=ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 | |||
Cleanup | |||
------- | |||
To remove your droplets, run: | |||
:: | |||
terraform destroy -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" |
@ -1,52 +0,0 @@ | |||
Using Ansible | |||
============= | |||
.. figure:: assets/a_plus_t.png | |||
:alt: Ansible plus Tendermint | |||
Ansible plus Tendermint | |||
The playbooks in `the ansible directory <https://github.com/tendermint/tendermint/tree/master/networks/remote/ansible>`__ | |||
run ansible `roles <http://www.ansible.com/>`__ to configure the sentry node architecture. | |||
Prerequisites | |||
------------- | |||
- Install `Ansible 2.0 or higher <https://www.ansible.com>`__ on a linux machine. | |||
- Create a `DigitalOcean API token <https://cloud.digitalocean.com/settings/api/tokens>`__ with read and write capability. | |||
- Create SSH keys | |||
- Install the python dopy package (for the digital_ocean.py script) | |||
Build | |||
----- | |||
:: | |||
export DO_API_TOKEN="abcdef01234567890abcdef01234567890" | |||
export SSH_KEY_FILE="$HOME/.ssh/id_rsa.pub" | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml | |||
# The scripts assume that you have your validator set up already. | |||
# You can create the folder structure for the sentry nodes using `tendermint testnet`. | |||
# For example: tendermint testnet --v 0 --n 4 --o build/ | |||
# Then copy your genesis.json and modify the config.toml as you see fit. | |||
# Reconfig the sentry nodes with a new BINARY and the configuration files from the build folder: | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet config.yml -e BINARY=`pwd`/build/tendermint -e CONFIGDIR=`pwd`/build | |||
Shipping logs to logz.io | |||
------------------------ | |||
Logz.io is an Elastic stack (Elastic search, Logstash and Kibana) service provider. You can set up your nodes to log there automatically. Create an account and get your API key from the notes on `this page <https://app.logz.io/#/dashboard/data-sources/Filebeat>`__. | |||
:: | |||
yum install systemd-devel || echo "This will only work on RHEL-based systems." | |||
apt-get install libsystemd-dev || echo "This will only work on Debian-based systems." | |||
go get github.com/mheese/journalbeat | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet logzio.yml -e LOGZIO_TOKEN=ABCDEFGHIJKLMNOPQRSTUVWXYZ012345 | |||
@ -0,0 +1,132 @@ | |||
#!/usr/bin/env bash | |||
# XXX: this script is intended to be run from a fresh Digital Ocean droplet | |||
# NOTE: you must set this manually now | |||
echo "export DO_API_TOKEN=\"yourToken\"" >> ~/.profile | |||
sudo apt-get update -y | |||
sudo apt-get upgrade -y | |||
sudo apt-get install -y jq unzip python-pip software-properties-common make | |||
# get and unpack golang | |||
curl -O https://storage.googleapis.com/golang/go1.10.linux-amd64.tar.gz | |||
tar -xvf go1.10.linux-amd64.tar.gz | |||
## move binary and add to path | |||
mv go /usr/local | |||
echo "export PATH=\$PATH:/usr/local/go/bin" >> ~/.profile | |||
## create the goApps directory, set GOPATH, and put it on PATH | |||
mkdir goApps | |||
echo "export GOPATH=/root/goApps" >> ~/.profile | |||
echo "export PATH=\$PATH:\$GOPATH/bin" >> ~/.profile | |||
source ~/.profile | |||
## get the code and move into repo | |||
REPO=github.com/tendermint/tendermint | |||
go get $REPO | |||
cd $GOPATH/src/$REPO | |||
## build | |||
git checkout zach/ansible | |||
make get_tools | |||
make get_vendor_deps | |||
make build | |||
# generate an ssh key | |||
ssh-keygen -f $HOME/.ssh/id_rsa -t rsa -N '' | |||
echo "export SSH_KEY_FILE=\"\$HOME/.ssh/id_rsa.pub\"" >> ~/.profile | |||
source ~/.profile | |||
# install terraform | |||
wget https://releases.hashicorp.com/terraform/0.11.7/terraform_0.11.7_linux_amd64.zip | |||
unzip terraform_0.11.7_linux_amd64.zip -d /usr/bin/ | |||
# install ansible | |||
sudo apt-get update -y | |||
sudo apt-add-repository ppa:ansible/ansible -y | |||
sudo apt-get update -y | |||
sudo apt-get install ansible -y | |||
# required by ansible | |||
pip install dopy | |||
# the next two commands are directory sensitive | |||
cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/terraform | |||
terraform init | |||
terraform apply -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" -auto-approve | |||
# let the droplets boot | |||
sleep 60 | |||
# get the IPs | |||
ip0=`terraform output -json public_ips | jq '.value[0]'` | |||
ip1=`terraform output -json public_ips | jq '.value[1]'` | |||
ip2=`terraform output -json public_ips | jq '.value[2]'` | |||
ip3=`terraform output -json public_ips | jq '.value[3]'` | |||
# to remove quotes | |||
strip() { | |||
opt=$1 | |||
temp="${opt%\"}" | |||
temp="${temp#\"}" | |||
echo $temp | |||
} | |||
ip0=$(strip $ip0) | |||
ip1=$(strip $ip1) | |||
ip2=$(strip $ip2) | |||
ip3=$(strip $ip3) | |||
# all the ansible commands are also directory specific | |||
cd $GOPATH/src/github.com/tendermint/tendermint/networks/remote/ansible | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet config.yml -e BINARY=$GOPATH/src/github.com/tendermint/tendermint/build/tendermint -e CONFIGDIR=$GOPATH/src/github.com/tendermint/tendermint/docs/examples | |||
sleep 10 | |||
# get each nodes ID then populate the ansible file | |||
id0=`curl $ip0:46657/status | jq .result.node_info.id` | |||
id1=`curl $ip1:46657/status | jq .result.node_info.id` | |||
id2=`curl $ip2:46657/status | jq .result.node_info.id` | |||
id3=`curl $ip3:46657/status | jq .result.node_info.id` | |||
id0=$(strip $id0) | |||
id1=$(strip $id1) | |||
id2=$(strip $id2) | |||
id3=$(strip $id3) | |||
# remove file we'll re-write to with new info | |||
old_ansible_file=$GOPATH/src/github.com/tendermint/tendermint/networks/remote/ansible/roles/install/templates/systemd.service.j2 | |||
rm $old_ansible_file | |||
# need to populate the `--p2p.persistent_peers` flag | |||
echo "[Unit] | |||
Description={{service}} | |||
Requires=network-online.target | |||
After=network-online.target | |||
[Service] | |||
Restart=on-failure | |||
User={{service}} | |||
Group={{service}} | |||
PermissionsStartOnly=true | |||
ExecStart=/usr/bin/tendermint node --proxy_app=kvstore --p2p.persistent_peers=$id0@$ip0:46656,$id1@$ip1:46656,$id2@$ip2:46656,$id3@$ip3:46656 | |||
ExecReload=/bin/kill -HUP \$MAINPID | |||
KillSignal=SIGTERM | |||
[Install] | |||
WantedBy=multi-user.target | |||
" >> $old_ansible_file | |||
# now, we can re-run the install command | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet install.yml | |||
# and finally restart it all | |||
ansible-playbook -i inventory/digital_ocean.py -l sentrynet restart.yml | |||
echo "congratulations, your testnet is now running :)" |
@ -1,33 +0,0 @@ | |||
Using Terraform | |||
=============== | |||
This is a `Terraform <https://www.terraform.io/>`__ configuration that sets up DigitalOcean droplets. | |||
Prerequisites | |||
------------- | |||
- Install `HashiCorp Terraform <https://www.terraform.io>`__ on a linux machine. | |||
- Create a `DigitalOcean API token <https://cloud.digitalocean.com/settings/api/tokens>`__ with read and write capability. | |||
- Create SSH keys | |||
Build | |||
----- | |||
:: | |||
export DO_API_TOKEN="abcdef01234567890abcdef01234567890" | |||
export SSH_KEY_FILE="$HOME/.ssh/id_rsa.pub" | |||
terraform init | |||
terraform apply -var DO_API_TOKEN="$DO_API_TOKEN" -var SSH_KEY_FILE="$SSH_KEY_FILE" | |||
At the end you will get a list of IP addresses that belongs to your new droplets. | |||
Destroy | |||
------- | |||
Run the below: | |||
:: | |||
terraform destroy |