diff --git a/CHANGELOG.md b/CHANGELOG.md index 25ccafa5d..14615ab16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,102 @@ # Changelog +## 0.24.0 + +*September 6th, 2018* + +Special thanks to external contributors with PRs included in this release: ackratos, james-ray, bradyjoestar, +peerlink, Ahmah2009, bluele, b00f. + +This release includes breaking upgrades in the block header, +including the long awaited changes for delaying validator set updates by one +block. It also fixes enforcement on the max size of blocks, and includes a BFT +timestamp in each block that can be safely used by applications. There are also some +minor breaking changes to the rpc, config, and ABCI. + +From here on, breaking changes will be broken down to better reflect how users +are affected by a change. + +A few more breaking changes are in the works - each will come with a clear +Architecture Decision Record (ADR) explaining the change. You can review ADRs +[here](https://github.com/tendermint/tendermint/tree/develop/docs/architecture) +or in the [open Pull Requests](https://github.com/tendermint/tendermint/pulls). + +BREAKING CHANGES: + +* CLI/RPC/Config + - [config] [\#2169](https://github.com/tendermint/tendermint/issues/2169) Replace MaxNumPeers with MaxNumInboundPeers and MaxNumOutboundPeers + - [config] [\#2300](https://github.com/tendermint/tendermint/issues/2300) Reduce default mempool size from 100k to 5k, until ABCI rechecking is implemented. + - [rpc] [\#1815](https://github.com/tendermint/tendermint/issues/1815) `/commit` returns a `signed_header` field instead of everything being top-level + +* Apps + - [abci] Added address of the original proposer of the block to Header + - [abci] Change ABCI Header to match Tendermint exactly + - [abci] [\#2159](https://github.com/tendermint/tendermint/issues/2159) Update use of `Validator` (see + [ADR-018](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-018-ABCI-Validators.md)): + - Remove PubKey from `Validator` (so it's just Address and Power) + - Introduce `ValidatorUpdate` (with just PubKey and Power) + - InitChain and EndBlock use ValidatorUpdate + - Update field names and types in BeginBlock + - [state] [\#1815](https://github.com/tendermint/tendermint/issues/1815) Validator set changes are now delayed by one block + - updates returned in ResponseEndBlock for block H will be included in RequestBeginBlock for block H+2 + +* Go API + - [lite] [\#1815](https://github.com/tendermint/tendermint/issues/1815) Complete refactor of the package + - [node] [\#2212](https://github.com/tendermint/tendermint/issues/2212) NewNode now accepts a `*p2p.NodeKey` (@bradyjoestar) + - [libs/common] [\#2199](https://github.com/tendermint/tendermint/issues/2199) Remove Fmt, in favor of fmt.Sprintf + - [libs/common] SplitAndTrim was deleted + - [libs/common] [\#2274](https://github.com/tendermint/tendermint/issues/2274) Remove unused Math functions like MaxInt, MaxInt64, + MinInt, MinInt64 (@Ahmah2009) + - [libs/clist] Panics if list extends beyond MaxLength + - [crypto] [\#2205](https://github.com/tendermint/tendermint/issues/2205) Rename AminoRoute variables to no longer be prefixed by signature type. + +* Blockchain Protocol + - [state] [\#1815](https://github.com/tendermint/tendermint/issues/1815) Validator set changes are now delayed by one block (!) + - Add NextValidatorSet to State, changes on-disk representation of state + - [state] [\#2184](https://github.com/tendermint/tendermint/issues/2184) Enforce ConsensusParams.BlockSize.MaxBytes (See + [ADR-020](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-020-block-size.md)). + - Remove ConsensusParams.BlockSize.MaxTxs + - Introduce maximum sizes for all components of a block, including ChainID + - [types] Updates to the block Header: + - [\#1815](https://github.com/tendermint/tendermint/issues/1815) NextValidatorsHash - hash of the validator set for the next block, + so the current validators actually sign over the hash for the new + validators + - [\#2106](https://github.com/tendermint/tendermint/issues/2106) ProposerAddress - address of the block's original proposer + - [consensus] [\#2203](https://github.com/tendermint/tendermint/issues/2203) Implement BFT time + - Timestamp in block must be monotonic and equal the median of timestamps in block's LastCommit + - [crypto] [\#2239](https://github.com/tendermint/tendermint/issues/2239) Secp256k1 signature changes (See + [ADR-014](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-014-secp-malleability.md)): + - format changed from DER to `r || s`, both little endian encoded as 32 bytes. + - malleability removed by requiring `s` to be in canonical form. + +* P2P Protocol + - [p2p] [\#2263](https://github.com/tendermint/tendermint/issues/2263) Update secret connection to use a little endian encoded nonce + - [blockchain] [\#2213](https://github.com/tendermint/tendermint/issues/2213) Fix Amino routes for blockchain reactor messages + (@peerlink) + + +FEATURES: +- [types] [\#2015](https://github.com/tendermint/tendermint/issues/2015) Allow genesis file to have 0 validators (@b00f) + - Initial validator set can be determined by the app in ResponseInitChain +- [rpc] [\#2161](https://github.com/tendermint/tendermint/issues/2161) New event `ValidatorSetUpdates` for when the validator set changes +- [crypto/multisig] [\#2164](https://github.com/tendermint/tendermint/issues/2164) Introduce multisig pubkey and signature format +- [libs/db] [\#2293](https://github.com/tendermint/tendermint/issues/2293) Allow passing options through when creating instances of leveldb dbs + +IMPROVEMENTS: +- [docs] Lint documentation with `write-good` and `stop-words`. +- [scripts] [\#2196](https://github.com/tendermint/tendermint/issues/2196) Added json2wal tool, which is supposed to help our users restore (@bradyjoestar) + corrupted WAL files and compose test WAL files (@bradyjoestar) +- [mempool] [\#2234](https://github.com/tendermint/tendermint/issues/2234) Now stores txs by hash inside of the cache, to mitigate memory leakage +- [mempool] [\#2166](https://github.com/tendermint/tendermint/issues/2166) Set explicit capacity for map when updating txs (@bluele) + +BUG FIXES: +- [config] [\#2284](https://github.com/tendermint/tendermint/issues/2284) Replace `db_path` with `db_dir` from automatically generated configuration files. +- [mempool] [\#2188](https://github.com/tendermint/tendermint/issues/2188) Fix OOM issue from cache map and list getting out of sync +- [state] [\#2051](https://github.com/tendermint/tendermint/issues/2051) KV store index supports searching by `tx.height` (@ackratos) +- [rpc] [\#2327](https://github.com/tendermint/tendermint/issues/2327) `/dial_peers` does not try to dial existing peers +- [node] [\#2323](https://github.com/tendermint/tendermint/issues/2323) Filter empty strings from config lists (@james-ray) +- [abci/client] [\#2236](https://github.com/tendermint/tendermint/issues/2236) Fix closing GRPC connection (@bradyjoestar) + ## 0.23.1 *August 22nd, 2018* diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 2d5912756..cd5dc06d6 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -1,80 +1,22 @@ # Pending -Special thanks to external contributors with PRs included in this release: ackratos, james-ray, bradyjoestar, -peerlink, Ahmah2009, bluele, b00f +Special thanks to external contributors with PRs included in this release: BREAKING CHANGES: * CLI/RPC/Config - - [config] \#2169 Replace MaxNumPeers with MaxNumInboundPeers and MaxNumOutboundPeers - - [config] \#2300 Reduce default mempool size from 100k to 5k, until ABCI rechecking is implemented. - - [rpc] \#1815 `/commit` returns a `signed_header` field instead of everything being top-level * Apps - - [abci] Added address of the original proposer of the block to Header - - [abci] Change ABCI Header to match Tendermint exactly - - [abci] \#2159 Update use of `Validator` (see - [ADR-018](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-018-ABCI-Validators.md)): - - Remove PubKey from `Validator` (so it's just Address and Power) - - Introduce `ValidatorUpdate` (with just PubKey and Power) - - InitChain and EndBlock use ValidatorUpdate - - Update field names and types in BeginBlock - - [state] \#1815 Validator set changes are now delayed by one block - - updates returned in ResponseEndBlock for block H will be included in RequestBeginBlock for block H+2 * Go API - - [lite] \#1815 Complete refactor of the package - - [node] \#2212 NewNode now accepts a `*p2p.NodeKey` (@bradyjoestar) - - [libs/common] \#2199 Remove Fmt, in favor of fmt.Sprintf - - [libs/common] SplitAndTrim was deleted - - [libs/common] \#2274 Remove unused Math functions like MaxInt, MaxInt64, - MinInt, MinInt64 (@Ahmah2009) - - [libs/clist] Panics if list extends beyond MaxLength - - [crypto] \#2205 Rename AminoRoute variables to no longer be prefixed by signature type. * Blockchain Protocol - - [state] \#1815 Validator set changes are now delayed by one block (!) - - Add NextValidatorSet to State, changes on-disk representation of state - - [state] \#2184 Enforce ConsensusParams.BlockSize.MaxBytes (See - [ADR-020](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-020-block-size.md)). - - Remove ConsensusParams.BlockSize.MaxTxs - - Introduce maximum sizes for all components of a block, including ChainID - - [types] Updates to the block Header: - - \#1815 NextValidatorsHash - hash of the validator set for the next block, - so the current validators actually sign over the hash for the new - validators - - \#2106 ProposerAddress - address of the block's original proposer - - [consensus] \#2203 Implement BFT time - - Timestamp in block must be monotonic and equal the median of timestamps in block's LastCommit - - [crypto] \#2239 Secp256k1 signature changes (See - [ADR-014](https://github.com/tendermint/tendermint/blob/develop/docs/architecture/adr-014-secp-malleability.md)): - - format changed from DER to `r || s`, both little endian encoded as 32 bytes. - - malleability removed by requiring `s` to be in canonical form. * P2P Protocol - - [p2p] \#2263 Update secret connection to use a little endian encoded nonce - - [blockchain] \#2213 Fix Amino routes for blockchain reactor messages - (@peerlink) FEATURES: -- [types] \#2015 Allow genesis file to have 0 validators (@b00f) - - Initial validator set can be determined by the app in ResponseInitChain -- [rpc] \#2161 New event `ValidatorSetUpdates` for when the validator set changes -- [crypto/multisig] \#2164 Introduce multisig pubkey and signature format -- [libs/db] \#2293 Allow passing options through when creating instances of leveldb dbs IMPROVEMENTS: -- [docs] Lint documentation with `write-good` and `stop-words`. -- [scripts] \#2196 Added json2wal tool, which is supposed to help our users restore (@bradyjoestar) - corrupted WAL files and compose test WAL files (@bradyjoestar) -- [mempool] \#2234 Now stores txs by hash inside of the cache, to mitigate memory leakage -- [mempool] \#2166 Set explicit capacity for map when updating txs (@bluele) BUG FIXES: -- [config] \#2284 Replace `db_path` with `db_dir` from automatically generated configuration files. -- [mempool] \#2188 Fix OOM issue from cache map and list getting out of sync -- [state] \#2051 KV store index supports searching by `tx.height` (@ackratos) -- [rpc] \#2327 `/dial_peers` does not try to dial existing peers -- [node] \#2323 Filter empty strings from config lists (@james-ray) -- [abci/client] \#2236 Fix closing GRPC connection (@bradyjoestar) diff --git a/abci/version/version.go b/abci/version/version.go index 7223a86ad..f4dc4d235 100644 --- a/abci/version/version.go +++ b/abci/version/version.go @@ -1,9 +1,9 @@ package version -// NOTE: we should probably be versioning the ABCI and the abci-cli separately +import ( + "github.com/tendermint/tendermint/version" +) -const Maj = "0" -const Min = "12" -const Fix = "0" +// TODO: eliminate this after some version refactor -const Version = "0.12.0" +const Version = version.ABCIVersion diff --git a/docs/app-dev/abci-spec.md b/docs/app-dev/abci-spec.md index 63570f7f8..6d0f712a2 100644 --- a/docs/app-dev/abci-spec.md +++ b/docs/app-dev/abci-spec.md @@ -1,5 +1,9 @@ # ABCI Specification +### XXX + +DEPRECATED: Moved [here](../spec/abci/abci.md) + ## Message Types ABCI requests/responses are defined as simple Protobuf messages in [this @@ -177,7 +181,8 @@ See below for more details on the message types and how they are used. - **Usage**: - Signals the beginning of a new block. Called prior to any DeliverTxs. - - The header is expected to at least contain the Height. + - The header contains the height, timestamp, and more - it exactly matches the + Tendermint block header. We may seek to generalize this in the future. - The `LastCommitInfo` and `ByzantineValidators` can be used to determine rewards and punishments for the validators. NOTE validators here do not include pubkeys. @@ -253,7 +258,11 @@ See below for more details on the message types and how they are used. - **Usage**: - Signals the end of a block. - Called prior to each Commit, after all transactions. - - Validator set and consensus params are updated with the result. + - Validator updates returned for block H: + - apply to the NextValidatorsHash of block H+1 + - apply to the ValidatorsHash (and thus the validator set) for block H+2 + - apply to the RequestBeginBlock.LastCommitInfo (ie. the last validator set) for block H+3 + - Consensus params returned for block H apply for block H+1 ### Commit diff --git a/docs/app-dev/app-development.md b/docs/app-dev/app-development.md index 6c2ae9aba..3aaebb230 100644 --- a/docs/app-dev/app-development.md +++ b/docs/app-dev/app-development.md @@ -1,5 +1,10 @@ # Application Development Guide +## XXX + +This page is undergoing deprecation. All content is being moved to the new [home +of the ABCI specification](../spec/abci/README.md). + ## ABCI Design The purpose of ABCI is to provide a clean interface between state diff --git a/docs/spec/abci/README.md b/docs/spec/abci/README.md new file mode 100644 index 000000000..c0956db6f --- /dev/null +++ b/docs/spec/abci/README.md @@ -0,0 +1,19 @@ +# ABCI + +ABCI is the interface between Tendermint (a state-machine replication engine) +and an application (the actual state machine). It consists of a set of +*methods*, where each method has a corresponding `Request` and `Response` +message type. Tendermint calls the ABCI methods on the ABCI application by sending the `Request*` +messages and receiving the `Response*` messages in return. + +All message types are defined in a [protobuf file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto). +This allows Tendermint to run applications written in any programming language. + +This specification is split as follows: + +- [Methods and Types](abci.md) - complete details on all ABCI methods and + message types +- [Applications](apps.md) - how to manage ABCI application state and other + details about building ABCI applications +- [Client and Server](client-server.md) - for those looking to implement their + own ABCI application servers diff --git a/docs/spec/abci/abci.md b/docs/spec/abci/abci.md new file mode 100644 index 000000000..a1ca42f08 --- /dev/null +++ b/docs/spec/abci/abci.md @@ -0,0 +1,372 @@ +# ABCI Methods and Types + +## Overview + +The ABCI message types are defined in a [protobuf +file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto). + +ABCI methods are split across 3 separate ABCI *connections*: + +- `Consensus Connection: InitChain, BeginBlock, DeliverTx, EndBlock, Commit` +- `Mempool Connection: CheckTx` +- `Info Connection: Info, SetOption, Query` + +The `Consensus Connection` is driven by a consensus protocol and is responsible +for block exection. +The `Mempool Connection` is for validating new transactions, before they're +shared or included in a block. +The `Info Connection` is for initialization and for queries from the user. + +Additionally, there is a `Flush` method that is called on every connection, +and an `Echo` method that is just for debugging. + +## Errors + +Some methods (`Echo, Info, InitChain, BeginBlock, EndBlock, Commit`), +don't return errors because an error would indicate a critical failure +in the application and there's nothing Tendermint can do. The problem +should be addressed and both Tendermint and the application restarted. +All other methods (`SetOption, Query, CheckTx, DeliverTx`) return an +application-specific response `Code uint32`, where only `0` is reserved +for `OK`. + +## Tags + +Some methods (`CheckTx, BeginBlock, DeliverTx, EndBlock`) +include a `Tags` field in their `Response*`. Each tag is key-value pair denoting +something about what happened during the methods execution. + +Tags can be used to index transactions and blocks according to what happened +during their execution. + +Keys and values in tags must be UTF-8 encoded strings (e.g. +"account.owner": "Bob", "balance": "100.0", +"time": "2018-01-02T12:30:00Z") + +## Determinism + +Some methods (`SetOption, Query, CheckTx, DeliverTx`) return +non-deterministic data in the form of `Info` and `Log`. The `Log` is +intended for the literal output from the application's logger, while the +`Info` is any additional info that should be returned. + +All other fields in the `Response*` of all methods must be strictly deterministic. + +For this reason, it is recommended that applications not be exposed to any +external user or process except via the ABCI connections to a consensus engine +like Tendermint Core. + +## Block Execution + +The first time a new blockchain is started, Tendermint calls +`InitChain`. From then on, the follow sequence of methods is executed for each +block: + +`BeginBlock, [DeliverTx], EndBlock, Commit` + +where one `DeliverTx` is called for each transaction in the block. +The result is an updated application state. +Cryptographic commitments to the results of DeliverTx, EndBlock, and +Commit are included in the header of the next block. + +## Messages + +### Echo + +- **Request**: + - `Message (string)`: A string to echo back +- **Response**: + - `Message (string)`: The input string +- **Usage**: + - Echo a string to test an abci client/server implementation + +### Flush + +- **Usage**: + - Signals that messages queued on the client should be flushed to + the server. It is called periodically by the client + implementation to ensure asynchronous requests are actually + sent, and is called immediately to make a synchronous request, + which returns when the Flush response comes back. + +### Info + +- **Request**: + - `Version (string)`: The Tendermint version +- **Response**: + - `Data (string)`: Some arbitrary information + - `Version (Version)`: Version information + - `LastBlockHeight (int64)`: Latest block for which the app has + called Commit + - `LastBlockAppHash ([]byte)`: Latest result of Commit +- **Usage**: + - Return information about the application state. + - Used to sync Tendermint with the application during a handshake + that happens on startup. + - Tendermint expects `LastBlockAppHash` and `LastBlockHeight` to + be updated during `Commit`, ensuring that `Commit` is never + called twice for the same block height. + +### SetOption + +- **Request**: + - `Key (string)`: Key to set + - `Value (string)`: Value to set for key +- **Response**: + - `Code (uint32)`: Response code + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. +- **Usage**: + - Set non-consensus critical application specific options. + - e.g. Key="min-fee", Value="100fermion" could set the minimum fee + required for CheckTx (but not DeliverTx - that would be + consensus critical). + +### InitChain + +- **Request**: + - `Time (google.protobuf.Timestamp)`: Genesis time. + - `ChainID (string)`: ID of the blockchain. + - `ConsensusParams (ConsensusParams)`: Initial consensus-critical parameters. + - `Validators ([]ValidatorUpdate)`: Initial genesis validators. + - `AppStateBytes ([]byte)`: Serialized initial application state. Amino-encoded JSON bytes. +- **Response**: + - `ConsensusParams (ConsensusParams)`: Initial + consensus-critical parameters. + - `Validators ([]ValidatorUpdate)`: Initial validator set (if non empty). +- **Usage**: + - Called once upon genesis. + - If ResponseInitChain.Validators is empty, the initial validator set will be the RequestInitChain.Validators + - If ResponseInitChain.Validators is not empty, the initial validator set will be the + ResponseInitChain.Validators (regardless of what is in RequestInitChain.Validators). + - This allows the app to decide if it wants to accept the initial validator + set proposed by tendermint (ie. in the genesis file), or if it wants to use + a different one (perhaps computed based on some application specific + information in the genesis file). + +### Query + +- **Request**: + - `Data ([]byte)`: Raw query bytes. Can be used with or in lieu + of Path. + - `Path (string)`: Path of request, like an HTTP GET path. Can be + used with or in liue of Data. + - Apps MUST interpret '/store' as a query by key on the + underlying store. The key SHOULD be specified in the Data field. + - Apps SHOULD allow queries over specific types like + '/accounts/...' or '/votes/...' + - `Height (int64)`: The block height for which you want the query + (default=0 returns data for the latest committed block). Note + that this is the height of the block containing the + application's Merkle root hash, which represents the state as it + was after committing the block at Height-1 + - `Prove (bool)`: Return Merkle proof with response if possible +- **Response**: + - `Code (uint32)`: Response code. + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. + - `Index (int64)`: The index of the key in the tree. + - `Key ([]byte)`: The key of the matching data. + - `Value ([]byte)`: The value of the matching data. + - `Proof ([]byte)`: Proof for the data, if requested. + - `Height (int64)`: The block height from which data was derived. + Note that this is the height of the block containing the + application's Merkle root hash, which represents the state as it + was after committing the block at Height-1 +- **Usage**: + - Query for data from the application at current or past height. + - Optionally return Merkle proof. + +### BeginBlock + +- **Request**: + - `Hash ([]byte)`: The block's hash. This can be derived from the + block header. + - `Header (struct{})`: The block header. + - `LastCommitInfo (LastCommitInfo)`: Info about the last commit, including the + round, and the list of validators and which ones signed the last block. + - `ByzantineValidators ([]Evidence)`: List of evidence of + validators that acted maliciously. +- **Response**: + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing +- **Usage**: + - Signals the beginning of a new block. Called prior to + any DeliverTxs. + - The header contains the height, timestamp, and more - it exactly matches the + Tendermint block header. We may seek to generalize this in the future. + - The `LastCommitInfo` and `ByzantineValidators` can be used to determine + rewards and punishments for the validators. NOTE validators here do not + include pubkeys. + +### CheckTx + +- **Request**: + - `Tx ([]byte)`: The request transaction bytes +- **Response**: + - `Code (uint32)`: Response code + - `Data ([]byte)`: Result bytes, if any. + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. + - `GasWanted (int64)`: Amount of gas request for transaction. + - `GasUsed (int64)`: Amount of gas consumed by transaction. + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing + transactions (eg. by account). +- **Usage**: + - Technically optional - not involved in processing blocks. + - Guardian of the mempool: every node runs CheckTx before letting a + transaction into its local mempool. + - The transaction may come from an external user or another node + - CheckTx need not execute the transaction in full, but rather a light-weight + yet stateful validation, like checking signatures and account balances, but + not running code in a virtual machine. + - Transactions where `ResponseCheckTx.Code != 0` will be rejected - they will not be broadcast to + other nodes or included in a proposal block. + - Tendermint attributes no other value to the response code + +### DeliverTx + +- **Request**: + - `Tx ([]byte)`: The request transaction bytes. +- **Response**: + - `Code (uint32)`: Response code. + - `Data ([]byte)`: Result bytes, if any. + - `Log (string)`: The output of the application's logger. May + be non-deterministic. + - `Info (string)`: Additional information. May + be non-deterministic. + - `GasWanted (int64)`: Amount of gas requested for transaction. + - `GasUsed (int64)`: Amount of gas consumed by transaction. + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing + transactions (eg. by account). +- **Usage**: + - The workhorse of the application - non-optional. + - Execute the transaction in full. + - `ResponseDeliverTx.Code == 0` only if the transaction is fully valid. + +### EndBlock + +- **Request**: + - `Height (int64)`: Height of the block just executed. +- **Response**: + - `ValidatorUpdates ([]ValidatorUpdate)`: Changes to validator set (set + voting power to 0 to remove). + - `ConsensusParamUpdates (ConsensusParams)`: Changes to + consensus-critical time, size, and other parameters. + - `Tags ([]cmn.KVPair)`: Key-Value tags for filtering and indexing +- **Usage**: + - Signals the end of a block. + - Called after all transactions, prior to each Commit. + - Validator updates returned by block `H` impact blocks `H+1`, `H+2`, and + `H+3`, but only effects changes on the validator set of `H+2`: + - `H+1`: NextValidatorsHash + - `H+2`: ValidatorsHash (and thus the validator set) + - `H+3`: LastCommitInfo (ie. the last validator set) + - Consensus params returned for block `H` apply for block `H+1` + +### Commit + +- **Response**: + - `Data ([]byte)`: The Merkle root hash +- **Usage**: + - Persist the application state. + - Return a Merkle root hash of the application state. + - It's critical that all application instances return the + same hash. If not, they will not be able to agree on the next + block, because the hash is included in the next block! + +## Data Types + +### Header + +- **Fields**: + - `ChainID (string)`: ID of the blockchain + - `Height (int64)`: Height of the block in the chain + - `Time (google.protobuf.Timestamp)`: Time of the block. It is the proposer's + local time when block was created. + - `NumTxs (int32)`: Number of transactions in the block + - `TotalTxs (int64)`: Total number of transactions in the blockchain until + now + - `LastBlockID (BlockID)`: Hash of the previous (parent) block + - `LastCommitHash ([]byte)`: Hash of the previous block's commit + - `ValidatorsHash ([]byte)`: Hash of the validator set for this block + - `NextValidatorsHash ([]byte)`: Hash of the validator set for the next block + - `ConsensusHash ([]byte)`: Hash of the consensus parameters for this block + - `AppHash ([]byte)`: Data returned by the last call to `Commit` - typically the + Merkle root of the application state after executing the previous block's + transactions + - `LastResultsHash ([]byte)`: Hash of the ABCI results returned by the last block + - `EvidenceHash ([]byte)`: Hash of the evidence included in this block + - `ProposerAddress ([]byte)`: Original proposer for the block +- **Usage**: + - Provided in RequestBeginBlock + - Provides important context about the current state of the blockchain - + especially height and time. + - Provides the proposer of the current block, for use in proposer-based + reward mechanisms. + +### Validator + +- **Fields**: + - `Address ([]byte)`: Address of the validator (hash of the public key) + - `Power (int64)`: Voting power of the validator +- **Usage**: + - Validator identified by address + - Used in RequestBeginBlock as part of VoteInfo + - Does not include PubKey to avoid sending potentially large quantum pubkeys + over the ABCI + +### ValidatorUpdate + +- **Fields**: + - `PubKey (PubKey)`: Public key of the validator + - `Power (int64)`: Voting power of the validator +- **Usage**: + - Validator identified by PubKey + - Used to tell Tendermint to update the validator set + +### VoteInfo + +- **Fields**: + - `Validator (Validator)`: A validator + - `SignedLastBlock (bool)`: Indicates whether or not the validator signed + the last block +- **Usage**: + - Indicates whether a validator signed the last block, allowing for rewards + based on validator availability + +### PubKey + +- **Fields**: + - `Type (string)`: Type of the public key. A simple string like `"ed25519"`. + In the future, may indicate a serialization algorithm to parse the `Data`, + for instance `"amino"`. + - `Data ([]byte)`: Public key data. For a simple public key, it's just the + raw bytes. If the `Type` indicates an encoding algorithm, this is the + encoded public key. +- **Usage**: + - A generic and extensible typed public key + +### Evidence + +- **Fields**: + - `Type (string)`: Type of the evidence. A hierarchical path like + "duplicate/vote". + - `Validator (Validator`: The offending validator + - `Height (int64)`: Height when the offense was committed + - `Time (google.protobuf.Timestamp)`: Time of the block at height `Height`. + It is the proposer's local time when block was created. + - `TotalVotingPower (int64)`: Total voting power of the validator set at + height `Height` + +### LastCommitInfo + +- **Fields**: + - `Round (int32)`: Commit round. + - `Votes ([]VoteInfo)`: List of validators addresses in the last validator set + with their voting power and whether or not they signed a vote. diff --git a/docs/spec/abci/apps.md b/docs/spec/abci/apps.md new file mode 100644 index 000000000..fcba47355 --- /dev/null +++ b/docs/spec/abci/apps.md @@ -0,0 +1,207 @@ +# ABCI Applications + +Please ensure you've first read the spec for [ABCI Methods and Types](abci.md) + +Here we cover the following components of ABCI applications: + +- [State](#State) - the interplay between ABCI connections and application state + and the differences between `CheckTx` and `DeliverTx`. +- [Validator Set Updates](#Validator-Set-Updates) - how validator sets are + changed during `InitChain` and `EndBlock` +- [Query](#Query) - standards for using the `Query` method +- [Crash Recovery](#Crash-Recovery) - handshake protocol to synchronize + Tendermint and the application on startup. + +## State + +Since Tendermint maintains multiple concurrent ABCI connections, it is typical +for an application to maintain a distinct state for each, and for the states to +be sycnronized during `Commit`. + +### Commit + +Before `Commit` is called, Tendermint locks and flushes the mempool so that no new messages will +be received on the mempool connection. This provides an opportunity to safely update all three +states to the latest committed state at once. + +When `Commit` completes, it unlocks the mempool. + +Note that it is not possible to send transactions to Tendermint during `Commit` - if your app +tries to send a `/broadcast_tx` to Tendermint during Commit, it will deadlock. + +### Consensus Connection + +The Consensus Connection should maintain a `DeliverTxState` - +the working state for block execution. It should be updated by the calls to +`BeginBlock`, `DeliverTx`, and `EndBlock` during block execution and committed to +disk as the "latest committed state" during `Commit`. + +Updates made to the DeliverTxState by each method call must be readable by each subsequent method - +ie. the updates are linearizeable. + +### Mempool Connection + +The Mempool Connection should maintain a `CheckTxState` - +to process pending transactions in the mempool that have +not yet been committed. It should be initialized to the latest committed state +at the end of every `Commit`. Note it may be updated concurrently with the +DeliverTxState. + +Before calling `Commit`, Tendermint will lock and flush the mempool, +ensuring that all existing CheckTx are responded to and no new ones can +begin. + +After `Commit`, CheckTx is run again on all transactions that remain in the +node's local mempool after filtering those included in the block. To prevent the +mempool from rechecking all transactions every time a block is committed, set +the configuration option `mempool.recheck=false`. + +Finally, the mempool will unlock and new transactions can be processed through CheckTx again. + +Note that CheckTx doesn't have to check everything that affects transaction validity; the +expensive things can be skipped. In fact, CheckTx doesn't have to check +anything; it might say that any transaction is a valid transaction. +Unlike DeliverTx, CheckTx is just there as +a sort of weak filter to keep invalid transactions out of the blockchain. It's +weak, because a Byzantine node doesn't care about CheckTx; it can propose a +block full of invalid transactions if it wants. + +### Info Connection + +The Mempool Connection should maintain a `QueryState` for answering queries from the user, +and for initialization when Tendermint first starts up. +It should always contain the latest committed state associated with the +latest commited block. + +QueryState should be set to the latest `DeliverTxState` at the end of every `Commit`, +ie. after the full block has been processed and the state committed to disk. +Otherwise it should never be modified. + +## Validator Updates + +### EndBlock + +Updates to the Tendermint validator set can be made by returning +`ValidatorUpdate` objects in the `ResponseEndBlock`: + +``` +message ValidatorUpdate { + PubKey pub_key + int64 power +} + +message PubKey { + string type + bytes data +} +``` + +The `pub_key` currently supports only one type: + +- `type = "ed25519" and`data = ` + +The `power` is the new voting power for the validator, with the +following rules: + +- power must be non-negative +- if power is 0, the validator must already exist, and will be removed from the + validator set +- if power is non-0: + - if the validator does not already exist, it will be added to the validator + set with the given power + - if the validator does already exist, its power will be adjusted to the given power + +### InitChain + +ResponseInitChain has the option to return a list of validators. +If the list is not empty, Tendermint will adopt it for the validator set. +This way the application can determine the initial validator set for the +blockchain. + +ResponseInitChain also includes ConsensusParams, but these are presently +ignored. + +## Query + +Query is a generic message type with lots of flexibility to enable diverse sets +of queries from applications. Tendermint has no requirements from the Query +message for normal operation - that is, the ABCI app developer need not implement Query functionality if they do not wish too. +That said, Tendermint makes a number of queries to support some optional +features. These are: + +### Peer Filtering + +When Tendermint connects to a peer, it sends two queries to the ABCI application +using the following paths, with no additional data: + +- `/p2p/filter/addr/`, where `` denote the IP address and + the port of the connection +- `p2p/filter/id/`, where `` is the peer node ID (ie. the + pubkey.Address() for the peer's PubKey) + +If either of these queries return a non-zero ABCI code, Tendermint will refuse +to connect to the peer. + + +## Crash Recovery + +On startup, Tendermint calls the `Info` method on the Info Connection to get the latest +committed state of the app. The app MUST return information consistent with the +last block it succesfully completed Commit for. + +If the app succesfully committed block H but not H+1, then `last_block_height = H` and `last_block_app_hash = `. If the app +failed during the Commit of block H, then `last_block_height = H-1` and +`last_block_app_hash = `. + +We now distinguish three heights, and describe how Tendermint syncs itself with +the app. + +``` +storeBlockHeight = height of the last block Tendermint saw a commit for +stateBlockHeight = height of the last block for which Tendermint completed all + block processing and saved all ABCI results to disk +appBlockHeight = height of the last block for which ABCI app succesfully + completely Commit +``` + +Note we always have `storeBlockHeight >= stateBlockHeight` and `storeBlockHeight >= appBlockHeight` +Note also we never call Commit on an ABCI app twice for the same height. + +The procedure is as follows. + +First, some simeple start conditions: + +If `appBlockHeight == 0`, then call InitChain. + +If `storeBlockHeight == 0`, we're done. + +Now, some sanity checks: + +If `storeBlockHeight < appBlockHeight`, error +If `storeBlockHeight < stateBlockHeight`, panic +If `storeBlockHeight > stateBlockHeight+1`, panic + +Now, the meat: + +If `storeBlockHeight == stateBlockHeight && appBlockHeight < storeBlockHeight`, +replay all blocks in full from `appBlockHeight` to `storeBlockHeight`. +This happens if we completed processing the block, but the app forgot its height. + +If `storeBlockHeight == stateBlockHeight && appBlockHeight == storeBlockHeight`, we're done +This happens if we crashed at an opportune spot. + +If `storeBlockHeight == stateBlockHeight+1` +This happens if we started processing the block but didn't finish. + + If `appBlockHeight < stateBlockHeight` + replay all blocks in full from `appBlockHeight` to `storeBlockHeight-1`, + and replay the block at `storeBlockHeight` using the WAL. + This happens if the app forgot the last block it committed. + + If `appBlockHeight == stateBlockHeight`, + replay the last block (storeBlockHeight) in full. + This happens if we crashed before the app finished Commit + + If appBlockHeight == storeBlockHeight { + update the state using the saved ABCI responses but dont run the block against the real app. + This happens if we crashed after the app finished Commit but before Tendermint saved the state. diff --git a/docs/spec/abci/client-server.md b/docs/spec/abci/client-server.md new file mode 100644 index 000000000..1923b5e08 --- /dev/null +++ b/docs/spec/abci/client-server.md @@ -0,0 +1,104 @@ +# ABCI Client and Server + +This section is for those looking to implement their own ABCI Server, perhaps in +a new programming language. + +You are expected to have read [ABCI Methods and Types](abci.md) and [ABCI +Applications](apps.md). + +See additional details in the [ABCI +readme](https://github.com/tendermint/tendermint/blob/develop/abci/README.md)(TODO: deduplicate +those details). + +## Message Protocol + +The message protocol consists of pairs of requests and responses defined in the +[protobuf file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto). + +Some messages have no fields, while others may include byte-arrays, strings, integers, +or custom protobuf types. + +For more details on protobuf, see the [documentation](https://developers.google.com/protocol-buffers/docs/overview). + +For each request, a server should respond with the corresponding +response, where the order of requests is preserved in the order of +responses. + +## Server + +To use ABCI in your programming language of choice, there must be a ABCI +server in that language. Tendermint supports two kinds of implementation +of the server: + +- Asynchronous, raw socket server (Tendermint Socket Protocol, also + known as TSP or Teaspoon) +- GRPC + +Both can be tested using the `abci-cli` by setting the `--abci` flag +appropriately (ie. to `socket` or `grpc`). + +See examples, in various stages of maintenance, in +[Go](https://github.com/tendermint/tendermint/tree/develop/abci/server), +[JavaScript](https://github.com/tendermint/js-abci), +[Python](https://github.com/tendermint/tendermint/tree/develop/abci/example/python3/abci), +[C++](https://github.com/mdyring/cpp-tmsp), and +[Java](https://github.com/jTendermint/jabci). + +### GRPC + +If GRPC is available in your language, this is the easiest approach, +though it will have significant performance overhead. + +To get started with GRPC, copy in the [protobuf +file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto) +and compile it using the GRPC plugin for your language. For instance, +for golang, the command is `protoc --go_out=plugins=grpc:. types.proto`. +See the [grpc documentation for more details](http://www.grpc.io/docs/). +`protoc` will autogenerate all the necessary code for ABCI client and +server in your language, including whatever interface your application +must satisfy to be used by the ABCI server for handling requests. + +### TSP + +If GRPC is not available in your language, or you require higher +performance, or otherwise enjoy programming, you may implement your own +ABCI server using the Tendermint Socket Protocol, known affectionately +as Teaspoon. The first step is still to auto-generate the relevant data +types and codec in your language using `protoc`. Messages coming over +the socket are proto3 encoded, but additionally length-prefixed to +facilitate use as a streaming protocol. proto3 doesn't have an +official length-prefix standard, so we use our own. The first byte in +the prefix represents the length of the Big Endian encoded length. The +remaining bytes in the prefix are the Big Endian encoded length. + +For example, if the proto3 encoded ABCI message is 0xDEADBEEF (4 +bytes), the length-prefixed message is 0x0104DEADBEEF. If the proto3 +encoded ABCI message is 65535 bytes long, the length-prefixed message +would be like 0x02FFFF.... + +Note this prefixing does not apply for grpc. + +An ABCI server must also be able to support multiple connections, as +Tendermint uses three connections. + + +### Async vs Sync + +The main ABCI server (ie. non-GRPC) provides ordered asynchronous messages. +This is useful for DeliverTx and CheckTx, since it allows Tendermint to forward +transactions to the app before it's finished processing previous ones. + +Thus, DeliverTx and CheckTx messages are sent asycnhronously, while all other +messages are sent synchronously. + +## Client + +There are currently two use-cases for an ABCI client. One is a testing +tool, as in the `abci-cli`, which allows ABCI requests to be sent via +command line. The other is a consensus engine, such as Tendermint Core, +which makes requests to the application every time a new transaction is +received or a block is committed. + +It is unlikely that you will need to implement a client. For details of +our client, see +[here](https://github.com/tendermint/tendermint/tree/develop/abci/client). diff --git a/docs/spec/blockchain/blockchain.md b/docs/spec/blockchain/blockchain.md index dc3ba64b1..c24d2e10a 100644 --- a/docs/spec/blockchain/blockchain.md +++ b/docs/spec/blockchain/blockchain.md @@ -10,29 +10,25 @@ The Tendermint blockchains consists of a short list of basic data types: - `Header` - `BlockID` - `Time` -- `Vote` -- `Evidence` +- `Data` (for transactions) +- `Commit` and `Vote` +- `EvidenceData` and `Evidence` ## Block -A block consists of a header, a list of transactions, a list of votes (the commit), +A block consists of a header, transactions, votes (the commit), and a list of evidence of malfeasance (ie. signing conflicting votes). ```go type Block struct { Header Header - Txs [][]byte - LastCommit []Vote - Evidence []Evidence + Txs Data + Evidence EvidenceData + LastCommit Commit } ``` -The signatures returned along with block `X` are those validating block -`X-1`. This can be a little confusing, but consider that -the `Header` also contains the `LastCommitHash`. It would be impossible -for a Header to include the commits that sign it, as it would cause an -infinite loop here. But when we get block `X`, we find -`Header.LastCommitHash`, which must match the hash of `LastCommit`. +Note the `LastCommit` is the set of votes that committed the last block. ## Header @@ -44,7 +40,7 @@ type Header struct { // basic block info ChainID string Height int64 - Time time.Time + Time Time NumTxs int64 TotalTxs int64 @@ -90,15 +86,43 @@ type PartsHeader struct { } ``` +TODO: link to details of merkle sums. + ## Time Tendermint uses the [Google.Protobuf.WellKnownTypes.Timestamp](https://developers.google.com/protocol-buffers/docs/reference/csharp/class/google/protobuf/well-known-types/timestamp) format, which uses two integers, one for Seconds and for Nanoseconds. -TODO: clarify exact format and reconcile [this -comment](https://github.com/tendermint/tendermint/blob/892b170818cd3be4cd3f919d72dde1ad60c28bbb/types/proto3/block.proto#L43). +NOTE: there is currently a small divergence between Tendermint and the +Google.Protobuf.WellKnownTypes.Timestamp that should be resolved. See [this +issue](https://github.com/tendermint/go-amino/issues/223) for details. + +## Data + +Data is just a wrapper for a list of transactions, where transactions are +arbitrary byte arrays: + +``` +type Data struct { + Txs [][]byte +} +``` + +## Commit + +Commit is a simple wrapper for a list of votes, with one vote for each +validator. It also contains the relevant BlockID: + +``` +type Commit struct { + BlockID BlockID + Precommits []Vote +} +``` +NOTE: this will likely change to reduce the commit size by eliminating redundant +information - see [issue #1648](https://github.com/tendermint/tendermint/issues/1648). ## Vote @@ -128,9 +152,30 @@ Signatures in Tendermint are raw bytes representing the underlying signature. The only signature scheme currently supported for Tendermint validators is ED25519. The signature is the raw 64-byte ED25519 signature. +## EvidenceData + +EvidenceData is a simple wrapper for a list of evidence: + +``` +type EvidenceData struct { + Evidence []Evidence +} +``` + ## Evidence -Forthcoming, see [this issue](https://github.com/tendermint/tendermint/issues/2329) +Evidence in Tendermint is implemented as an interface. +This means any evidence is encoded using its Amino prefix. +There is currently only a single type, the `DuplicateVoteEvidence`. + +``` +// amino name: "tendermint/DuplicateVoteEvidence" +type DuplicateVoteEvidence struct { + PubKey PubKey + VoteA Vote + VoteB Vote +} +``` ## Validation @@ -155,13 +200,13 @@ See [here](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockc A Header is valid if its corresponding fields are valid. -### Version - -Arbitrary string. - ### ChainID -Arbitrary constant string. +``` +len(block.ChainID) < 50 +``` + +ChainID must be maximum 50 UTF-8 symbols. ### Height @@ -174,50 +219,27 @@ The height is an incrementing integer. The first block has `block.Header.Height ### Time -The median of the timestamps of the valid votes in the block.LastCommit. -Corresponds to the number of nanoseconds, with millisecond resolution, since January 1, 1970. +``` +block.Header.Timestamp >= prevBlock.Header.Timestamp + 1 ms +block.Header.Timestamp == MedianTime(block.LastCommit, state.LastValidators) +``` + +The block timestamp must be monotonic. +It must equal the weighted median of the timestamps of the valid votes in the block.LastCommit. Note: the timestamp of a vote must be greater by at least one millisecond than that of the block being voted on. +See the section on [BFT time](../consensus/bft-time.md) for more details. + ### NumTxs ```go -block.Header.NumTxs == len(block.Txs) +block.Header.NumTxs == len(block.Txs.Txs) ``` Number of transactions included in the block. -### TxHash - -```go -block.Header.TxHash == SimpleMerkleRoot(block.Txs) -``` - -Simple Merkle root of the transactions in the block. - -### LastCommitHash - -```go -block.Header.LastCommitHash == SimpleMerkleRoot(block.LastCommit) -``` - -Simple Merkle root of the votes included in the block. -These are the votes that committed the previous block. - -The first block has `block.Header.LastCommitHash == []byte{}` - -### DataHash - -The `DataHash` can provide a nice check on the -[Data](https://godoc.org/github.com/tendermint/tendermint/types#Data) -returned in this same block. If you are subscribed to new blocks, via -tendermint RPC, in order to display or process the new transactions you -should at least validate that the `DataHash` is valid. If it is -important to verify autheniticity, you must wait for the `LastCommit` -from the next block to make sure the block header (including `DataHash`) -was properly signed. - ### TotalTxs ```go @@ -248,25 +270,24 @@ which are held in the `state` and may be updated by the application. The first block has `block.Header.LastBlockID == BlockID{}`. -### ResultsHash +### LastCommitHash ```go -block.ResultsHash == SimpleMerkleRoot(state.LastResults) +block.Header.LastCommitHash == SimpleMerkleRoot(block.LastCommit) ``` -Simple Merkle root of the results of the transactions in the previous block. +Simple Merkle root of the votes included in the block. +These are the votes that committed the previous block. -The first block has `block.Header.ResultsHash == []byte{}`. +The first block has `block.Header.LastCommitHash == []byte{}` -### AppHash +### DataHash ```go -block.AppHash == state.AppHash +block.Header.DataHash == SimpleMerkleRoot(block.Txs.Txs) ``` -Arbitrary byte array returned by the application after executing and commiting the previous block. It serves as the basis for validating any merkle proofs that comes from the ABCI application and represents the state of the actual application rather than the state of the blockchain itself. - -The first block has `block.Header.AppHash == []byte{}`. +Simple Merkle root of the transactions included in the block. ### ValidatorsHash @@ -284,7 +305,8 @@ block.NextValidatorsHash == SimpleMerkleRoot(state.NextValidators) ``` Simple Merkle root of the next validator set that will be the validator set that commits the next block. -Modifications to the validator set are defined by the application. +This is included so that the current validator set gets a chance to sign the +next validator sets Merkle root. ### ConsensusParamsHash @@ -293,17 +315,26 @@ block.ConsensusParamsHash == SimpleMerkleRoot(state.ConsensusParams) ``` Simple Merkle root of the consensus parameters. -May be updated by the application. -### ProposerAddress +### AppHash ```go -block.Header.ProposerAddress in state.Validators +block.AppHash == state.AppHash ``` -Address of the original proposer of the block. Must be a current validator. +Arbitrary byte array returned by the application after executing and commiting the previous block. It serves as the basis for validating any merkle proofs that comes from the ABCI application and represents the state of the actual application rather than the state of the blockchain itself. -NOTE: we also need to track the round. +The first block has `block.Header.AppHash == []byte{}`. + +### LastResultsHash + +```go +block.ResultsHash == SimpleMerkleRoot(state.LastResults) +``` + +Simple Merkle root of the results of the transactions in the previous block. + +The first block has `block.Header.ResultsHash == []byte{}`. ## EvidenceHash @@ -313,6 +344,14 @@ block.EvidenceHash == SimpleMerkleRoot(block.Evidence) Simple Merkle root of the evidence of Byzantine behaviour included in this block. +### ProposerAddress + +```go +block.Header.ProposerAddress in state.Validators +``` + +Address of the original proposer of the block. Must be a current validator. + ## Txs Arbitrary length array of arbitrary length byte-arrays. @@ -378,16 +417,7 @@ against the given signature and message bytes. ## Evidence -There is currently only one kind of evidence: - -``` -// amino: "tendermint/DuplicateVoteEvidence" -type DuplicateVoteEvidence struct { - PubKey crypto.PubKey - VoteA *Vote - VoteB *Vote -} -``` +There is currently only one kind of evidence, `DuplicateVoteEvidence`. DuplicateVoteEvidence `ev` is valid if diff --git a/docs/spec/blockchain/encoding.md b/docs/spec/blockchain/encoding.md index 3ed06260f..1af470403 100644 --- a/docs/spec/blockchain/encoding.md +++ b/docs/spec/blockchain/encoding.md @@ -275,13 +275,11 @@ Because Tendermint only uses a Simple Merkle Tree, application developers are ex ### Amino -This section is pending an update, see [this issue](https://github.com/tendermint/tendermint/issues/1749). - Amino also supports JSON encoding - registered types are simply encoded as: ``` { - "type": "", + "type": "", "value": } ``` @@ -296,19 +294,18 @@ For instance, an ED25519 PubKey would look like: ``` Where the `"value"` is the base64 encoding of the raw pubkey bytes, and the -`"type"` is the full disfix bytes for Ed25519 pubkeys. +`"type"` is the amino name for Ed25519 pubkeys. ### Signed Messages -Signed messages (eg. votes, proposals) in the consensus are encoded using Amino-JSON, rather than in the standard binary format. +Signed messages (eg. votes, proposals) in the consensus are encoded using Amino-JSON, rather than in the standard binary format +(NOTE: this is subject to change: https://github.com/tendermint/tendermint/issues/1622) -When signing, the elements of a message are sorted by key and the sorted message is embedded in an -outer JSON that includes a `chain_id` field. +When signing, the elements of a message are sorted by key and prepended with +a `@chain_id` and `@type` field. We call this encoding the CanonicalSignBytes. For instance, CanonicalSignBytes for a vote would look like: ```json -{"chain_id":"my-chain-id","vote":{"block_id":{"hash":DEADBEEF,"parts":{"hash":BEEFDEAD,"total":3}},"height":3,"round":2,"timestamp":1234567890, "type":2} +{"@chain_id":"test_chain_id","@type":"vote","block_id":{"hash":"8B01023386C371778ECB6368573E539AFC3CC860","parts":{"hash":"72DB3D959635DFF1BB567BEDAA70573392C51596","total":"1000000"}},"height":"12345","round":"2","timestamp":"2017-12-25T03:00:01.234Z","type":2} ``` - -Note how the fields within each level are sorted. diff --git a/docs/spec/blockchain/state.md b/docs/spec/blockchain/state.md index 92df20f3d..3bad68bd1 100644 --- a/docs/spec/blockchain/state.md +++ b/docs/spec/blockchain/state.md @@ -8,10 +8,10 @@ transactions are never included in blocks, but their Merkle roots are - the stat Note that the `State` object itself is an implementation detail, since it is never included in a block or gossipped over the network, and we never compute -its hash. However, the types it contains are part of the specification, since -their Merkle roots are included in blocks. - -Details on an implementation of `State` with persistence is forthcoming, see [this issue](https://github.com/tendermint/tendermint/issues/1152) +its hash. Thus we do not include here details of how the `State` object is +persisted or queried. That said, the types it contains are part of the specification, since +their Merkle roots are included in blocks and their values are used in +validation. ```go type State struct { @@ -32,20 +32,15 @@ type State struct { type Result struct { Code uint32 Data []byte - Tags []KVPair -} - -type KVPair struct { - Key []byte - Value []byte } ``` `Result` is the result of executing a transaction against the application. -It returns a result code, an arbitrary byte array (ie. a return value), -and a list of key-value pairs ordered by key. The key-value pairs, or tags, -can be used to index transactions according to their "effects", which are -represented in the tags. +It returns a result code and an arbitrary byte array (ie. a return value). + +NOTE: the Result needs to be updated to include more fields returned from +processing transactions, like gas variables and tags - see +[issue 1007](https://github.com/tendermint/tendermint/issues/1007). ### Validator @@ -60,7 +55,7 @@ type Validator struct { } ``` -The `state.Validators` and `state.LastValidators` must always by sorted by validator address, +The `state.Validators`, `state.LastValidators`, and `state.NextValidators`, must always by sorted by validator address, so that there is a canonical order for computing the SimpleMerkleRoot. We also define a `TotalVotingPower` function, to return the total voting power: @@ -77,4 +72,59 @@ func TotalVotingPower(vals []Validators) int64{ ### ConsensusParams -This section is forthcoming. See [this issue](https://github.com/tendermint/tendermint/issues/1152). +ConsensusParams define various limits for blockchain data structures. +Like validator sets, they are set during genesis and can be updated by the application through ABCI. + +``` +type ConsensusParams struct { + BlockSize + TxSize + BlockGossip + EvidenceParams +} + +type BlockSize struct { + MaxBytes int + MaxGas int64 +} + +type TxSize struct { + MaxBytes int + MaxGas int64 +} + +type BlockGossip struct { + BlockPartSizeBytes int +} + +type EvidenceParams struct { + MaxAge int64 +} +``` + +#### BlockSize + +The total size of a block is limitted in bytes by the `ConsensusParams.BlockSize.MaxBytes`. +Proposed blocks must be less than this size, and will be considered invalid +otherwise. + +Blocks should additionally be limitted by the amount of "gas" consumed by the +transactions in the block, though this is not yet implemented. + +#### TxSize + +These parameters are not yet enforced and may disappear. See [issue +#2347](https://github.com/tendermint/tendermint/issues/2347). + +#### BlockGossip + +When gossipping blocks in the consensus, they are first split into parts. The +size of each part is `ConsensusParams.BlockGossip.BlockPartSizeBytes`. + +#### EvidenceParams + +For evidence in a block to be valid, it must satisfy: + +``` +block.Header.Height - evidence.Height < ConsensusParams.EvidenceParams.MaxAge +``` diff --git a/docs/spec/software/abci.md b/docs/spec/software/abci.md index aacdb43df..44d48f170 100644 --- a/docs/spec/software/abci.md +++ b/docs/spec/software/abci.md @@ -1,185 +1,3 @@ # Application Blockchain Interface (ABCI) -ABCI is the interface between Tendermint (a state-machine replication engine) -and an application (the actual state machine). - -The ABCI message types are defined in a [protobuf -file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto). - -For full details on the ABCI message types and protocol, see the [ABCI -specification](https://github.com/tendermint/tendermint/blob/develop/docs/app-dev/abci-spec.md). -Be sure to read the specification if you're trying to build an ABCI app! - -For additional details on server implementation, see the [ABCI -readme](https://github.com/tendermint/tendermint/blob/develop/abci/README.md). - -Here we provide some more details around the use of ABCI by Tendermint and -clarify common "gotchas". - -## ABCI connections - -Tendermint opens 3 ABCI connections to the app: one for Consensus, one for -Mempool, one for Queries. - -## Async vs Sync - -The main ABCI server (ie. non-GRPC) provides ordered asynchronous messages. -This is useful for DeliverTx and CheckTx, since it allows Tendermint to forward -transactions to the app before it's finished processing previous ones. - -Thus, DeliverTx and CheckTx messages are sent asycnhronously, while all other -messages are sent synchronously. - -## CheckTx and Commit - -It is typical to hold three distinct states in an ABCI app: CheckTxState, DeliverTxState, -QueryState. The QueryState contains the latest committed state for a block. -The CheckTxState and DeliverTxState may be updated concurrently with one another. -Before Commit is called, Tendermint locks and flushes the mempool so that no new changes will happen -to CheckTxState. When Commit completes, it unlocks the mempool. - -Thus, during Commit, it is safe to reset the QueryState and the CheckTxState to the latest DeliverTxState -(ie. the new state from executing all the txs in the block). - -Note, however, that it is not possible to send transactions to Tendermint during Commit - if your app -tries to send a `/broadcast_tx` to Tendermint during Commit, it will deadlock. - -## EndBlock Validator Updates - -Updates to the Tendermint validator set can be made by returning `Validator` -objects in the `ResponseBeginBlock`: - -``` -message Validator { - PubKey pub_key - int64 power -} - -message PubKey { - string type - bytes data -} -``` - -The `pub_key` currently supports two types: - -- `type = "ed25519" and`data = ` -- `type = "secp256k1" and `data = <33-byte OpenSSL compressed public key>` - -If the address is provided, it must match the address of the pubkey, as -specified [here](/docs/spec/blockchain/encoding.md#Addresses) - -(Note: In the v0.19 series, the `pub_key` is the [Amino encoded public -key](/docs/spec/blockchain/encoding.md#public-key-cryptography). -For Ed25519 pubkeys, the Amino prefix is always "1624DE6220". For example, the 32-byte Ed25519 pubkey -`76852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` would be -Amino encoded as -`1624DE622076852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85`) - -(Note: In old versions of Tendermint (pre-v0.19.0), the pubkey is just prefixed with a -single type byte, so for ED25519 we'd have `pub_key = 0x1 | pub`) - -The `power` is the new voting power for the validator, with the -following rules: - -- power must be non-negative -- if power is 0, the validator must already exist, and will be removed from the - validator set -- if power is non-0: - - if the validator does not already exist, it will be added to the validator - set with the given power - - if the validator does already exist, its power will be adjusted to the given power - -## InitChain Validator Updates - -ResponseInitChain has the option to return a list of validators. -If the list is not empty, Tendermint will adopt it for the validator set. -This way the application can determine the initial validator set for the -blockchain. - -ResponseInitChain also includes ConsensusParams, but these are presently -ignored. - -## Query - -Query is a generic message type with lots of flexibility to enable diverse sets -of queries from applications. Tendermint has no requirements from the Query -message for normal operation - that is, the ABCI app developer need not implement Query functionality if they do not wish too. -That said, Tendermint makes a number of queries to support some optional -features. These are: - -### Peer Filtering - -When Tendermint connects to a peer, it sends two queries to the ABCI application -using the following paths, with no additional data: - -- `/p2p/filter/addr/`, where `` denote the IP address and - the port of the connection -- `p2p/filter/id/`, where `` is the peer node ID (ie. the - pubkey.Address() for the peer's PubKey) - -If either of these queries return a non-zero ABCI code, Tendermint will refuse -to connect to the peer. - -## Info and the Handshake/Replay - -On startup, Tendermint calls Info on the Query connection to get the latest -committed state of the app. The app MUST return information consistent with the -last block it succesfully completed Commit for. - -If the app succesfully committed block H but not H+1, then `last_block_height = H` and `last_block_app_hash = `. If the app -failed during the Commit of block H, then `last_block_height = H-1` and -`last_block_app_hash = `. - -We now distinguish three heights, and describe how Tendermint syncs itself with -the app. - -``` -storeBlockHeight = height of the last block Tendermint saw a commit for -stateBlockHeight = height of the last block for which Tendermint completed all - block processing and saved all ABCI results to disk -appBlockHeight = height of the last block for which ABCI app succesfully - completely Commit -``` - -Note we always have `storeBlockHeight >= stateBlockHeight` and `storeBlockHeight >= appBlockHeight` -Note also we never call Commit on an ABCI app twice for the same height. - -The procedure is as follows. - -First, some simeple start conditions: - -If `appBlockHeight == 0`, then call InitChain. - -If `storeBlockHeight == 0`, we're done. - -Now, some sanity checks: - -If `storeBlockHeight < appBlockHeight`, error -If `storeBlockHeight < stateBlockHeight`, panic -If `storeBlockHeight > stateBlockHeight+1`, panic - -Now, the meat: - -If `storeBlockHeight == stateBlockHeight && appBlockHeight < storeBlockHeight`, -replay all blocks in full from `appBlockHeight` to `storeBlockHeight`. -This happens if we completed processing the block, but the app forgot its height. - -If `storeBlockHeight == stateBlockHeight && appBlockHeight == storeBlockHeight`, we're done -This happens if we crashed at an opportune spot. - -If `storeBlockHeight == stateBlockHeight+1` -This happens if we started processing the block but didn't finish. - - If `appBlockHeight < stateBlockHeight` - replay all blocks in full from `appBlockHeight` to `storeBlockHeight-1`, - and replay the block at `storeBlockHeight` using the WAL. - This happens if the app forgot the last block it committed. - - If `appBlockHeight == stateBlockHeight`, - replay the last block (storeBlockHeight) in full. - This happens if we crashed before the app finished Commit - - If appBlockHeight == storeBlockHeight { - update the state using the saved ABCI responses but dont run the block against the real app. - This happens if we crashed after the app finished Commit but before Tendermint saved the state. +This page has [moved](../spec/abci/apps.md). diff --git a/docs/tendermint-core/using-tendermint.md b/docs/tendermint-core/using-tendermint.md index a14392c44..28acc046b 100644 --- a/docs/tendermint-core/using-tendermint.md +++ b/docs/tendermint-core/using-tendermint.md @@ -42,7 +42,7 @@ definition](https://github.com/tendermint/tendermint/blob/master/types/genesis.g - `genesis_time`: Official time of blockchain start. - `chain_id`: ID of the blockchain. This must be unique for every blockchain. If your testnet blockchains do not have unique - chain IDs, you will have a bad time. The ChainID must be less than 50 bytes. + chain IDs, you will have a bad time. The ChainID must be less than 50 symbols. - `validators`: List of initial validators. Note this may be overridden entirely by the application, and may be left empty to make explicit that the application will initialize the validator set with ResponseInitChain. diff --git a/types/time/time.go b/types/time/time.go index 62aca9ec3..022bdf574 100644 --- a/types/time/time.go +++ b/types/time/time.go @@ -11,6 +11,8 @@ func Now() time.Time { } // Canonical returns UTC time with no monotonic component. +// Stripping the monotonic component is for time equality. +// See https://github.com/tendermint/tendermint/pull/2203#discussion_r215064334 func Canonical(t time.Time) time.Time { return t.Round(0).UTC() } diff --git a/version/version.go b/version/version.go index 68a9954f0..337ce4ead 100644 --- a/version/version.go +++ b/version/version.go @@ -3,19 +3,22 @@ package version // Version components const ( Maj = "0" - Min = "23" - Fix = "1" + Min = "24" + Fix = "0" ) var ( // Version is the current version of Tendermint // Must be a string because scripts like dist.sh read this file. - Version = "0.23.1" + Version = "0.24.0" // GitCommit is the current HEAD set using ldflags. GitCommit string ) +// ABCIVersion is the version of the ABCI library +const ABCIVersion = "0.14.0" + func init() { if GitCommit != "" { Version += "-" + GitCommit