2017-12-21 22:18:23 -05:00
|
|
|
# Tendermint Blockchain
|
|
|
|
|
|
|
|
Here we describe the data structures in the Tendermint blockchain and the rules for validating them.
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
## Data Structures
|
2017-12-21 22:18:23 -05:00
|
|
|
|
|
|
|
The Tendermint blockchains consists of a short list of basic data types:
|
2018-01-25 02:11:07 +00:00
|
|
|
|
2018-01-26 17:26:11 -05:00
|
|
|
- `Block`
|
2018-01-25 02:11:07 +00:00
|
|
|
- `Header`
|
|
|
|
- `Vote`
|
|
|
|
- `BlockID`
|
|
|
|
- `Signature`
|
|
|
|
- `Evidence`
|
2017-12-21 22:18:23 -05:00
|
|
|
|
|
|
|
## Block
|
|
|
|
|
2017-12-26 15:30:27 -05:00
|
|
|
A block consists of a header, a list of transactions, a list of votes (the commit),
|
2018-01-21 18:19:38 -05:00
|
|
|
and a list of evidence of malfeasance (ie. signing conflicting votes).
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
type Block struct {
|
|
|
|
Header Header
|
|
|
|
Txs [][]byte
|
|
|
|
LastCommit []Vote
|
|
|
|
Evidence []Evidence
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Header
|
|
|
|
|
|
|
|
A block header contains metadata about the block and about the consensus, as well as commitments to
|
|
|
|
the data in the current block, the previous block, and the results returned by the application:
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
type Header struct {
|
|
|
|
// block metadata
|
|
|
|
Version string // Version string
|
|
|
|
ChainID string // ID of the chain
|
2018-01-25 02:11:07 +00:00
|
|
|
Height int64 // Current block height
|
2017-12-21 22:18:23 -05:00
|
|
|
Time int64 // UNIX time, in millisconds
|
|
|
|
|
|
|
|
// current block
|
|
|
|
NumTxs int64 // Number of txs in this block
|
|
|
|
TxHash []byte // SimpleMerkle of the block.Txs
|
|
|
|
LastCommitHash []byte // SimpleMerkle of the block.LastCommit
|
|
|
|
|
|
|
|
// previous block
|
|
|
|
TotalTxs int64 // prevBlock.TotalTxs + block.NumTxs
|
|
|
|
LastBlockID BlockID // BlockID of prevBlock
|
|
|
|
|
|
|
|
// application
|
|
|
|
ResultsHash []byte // SimpleMerkle of []abci.Result from prevBlock
|
|
|
|
AppHash []byte // Arbitrary state digest
|
2018-07-31 21:19:57 +03:00
|
|
|
ValidatorsHash []byte // SimpleMerkle of the current ValidatorSet
|
|
|
|
NextValidatorsHash []byte // SimpleMerkle of the next ValidatorSet
|
2017-12-21 22:18:23 -05:00
|
|
|
ConsensusParamsHash []byte // SimpleMerkle of the ConsensusParams
|
|
|
|
|
|
|
|
// consensus
|
|
|
|
EvidenceHash []byte // SimpleMerkle of []Evidence
|
2018-07-30 12:59:16 +04:00
|
|
|
ProposerAddress []byte // Address of the original proposer of the block
|
2017-12-21 22:18:23 -05:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2018-01-25 02:11:07 +00:00
|
|
|
Further details on each of these fields is described below.
|
2017-12-26 15:30:27 -05:00
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
## BlockID
|
|
|
|
|
|
|
|
The `BlockID` contains two distinct Merkle roots of the block.
|
|
|
|
The first, used as the block's main hash, is the Merkle root
|
|
|
|
of all the fields in the header. The second, used for secure gossipping of
|
|
|
|
the block during consensus, is the Merkle root of the complete serialized block
|
2017-12-26 15:30:27 -05:00
|
|
|
cut into parts. The `BlockID` includes these two hashes, as well as the number of
|
|
|
|
parts.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
type BlockID struct {
|
2017-12-26 18:43:03 -05:00
|
|
|
Hash []byte
|
|
|
|
Parts PartsHeader
|
|
|
|
}
|
|
|
|
|
|
|
|
type PartsHeader struct {
|
|
|
|
Hash []byte
|
|
|
|
Total int32
|
2017-12-21 22:18:23 -05:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Vote
|
|
|
|
|
|
|
|
A vote is a signed message from a validator for a particular block.
|
|
|
|
The vote includes information about the validator signing it.
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
type Vote struct {
|
|
|
|
Timestamp int64
|
|
|
|
Address []byte
|
|
|
|
Index int
|
|
|
|
Height int64
|
|
|
|
Round int
|
|
|
|
Type int8
|
|
|
|
BlockID BlockID
|
|
|
|
Signature Signature
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2017-12-26 15:30:27 -05:00
|
|
|
There are two types of votes:
|
2018-08-27 15:33:46 +08:00
|
|
|
a _prevote_ has `vote.Type == 1` and
|
|
|
|
a _precommit_ has `vote.Type == 2`.
|
2017-12-26 15:30:27 -05:00
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
## Signature
|
|
|
|
|
|
|
|
Tendermint allows for multiple signature schemes to be used by prepending a single type-byte
|
2017-12-26 15:30:27 -05:00
|
|
|
to the signature bytes. Different signatures may also come with fixed or variable lengths.
|
|
|
|
Currently, Tendermint supports Ed25519 and Secp256k1.
|
|
|
|
|
|
|
|
### ED25519
|
|
|
|
|
|
|
|
An ED25519 signature has `Type == 0x1`. It looks like:
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
// Implements Signature
|
|
|
|
type Ed25519Signature struct {
|
|
|
|
Type int8 = 0x1
|
|
|
|
Signature [64]byte
|
|
|
|
}
|
2017-12-26 15:30:27 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
where `Signature` is the 64 byte signature.
|
|
|
|
|
|
|
|
### Secp256k1
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2017-12-26 15:30:27 -05:00
|
|
|
A `Secp256k1` signature has `Type == 0x2`. It looks like:
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
// Implements Signature
|
|
|
|
type Secp256k1Signature struct {
|
|
|
|
Type int8 = 0x2
|
|
|
|
Signature []byte
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2017-12-26 15:30:27 -05:00
|
|
|
where `Signature` is the DER encoded signature, ie:
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```hex
|
2017-12-26 15:30:27 -05:00
|
|
|
0x30 <length of whole message> <0x02> <length of R> <R> 0x2 <length of S> <S>.
|
|
|
|
```
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
## Evidence
|
|
|
|
|
2018-09-05 02:30:36 -04:00
|
|
|
Forthcoming, see [this issue](https://github.com/tendermint/tendermint/issues/2329)
|
2017-12-26 16:33:42 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
## Validation
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2017-12-26 18:43:03 -05:00
|
|
|
Here we describe the validation rules for every element in a block.
|
2017-12-21 22:18:23 -05:00
|
|
|
Blocks which do not satisfy these rules are considered invalid.
|
|
|
|
|
|
|
|
We abuse notation by using something that looks like Go, supplemented with English.
|
2017-12-26 15:30:27 -05:00
|
|
|
A statement such as `x == y` is an assertion - if it fails, the item is invalid.
|
|
|
|
|
|
|
|
We refer to certain globally available objects:
|
|
|
|
`block` is the block under consideration,
|
|
|
|
`prevBlock` is the `block` at the previous height,
|
2017-12-26 18:43:03 -05:00
|
|
|
and `state` keeps track of the validator set, the consensus parameters
|
2018-07-31 21:19:57 +03:00
|
|
|
and other results from the application. At the point when `block` is the block under consideration,
|
2018-08-27 15:33:46 +08:00
|
|
|
the current version of the `state` corresponds to the state
|
|
|
|
after executing transactions from the `prevBlock`.
|
2017-12-26 18:43:03 -05:00
|
|
|
Elements of an object are accessed as expected,
|
2018-08-27 15:33:46 +08:00
|
|
|
ie. `block.Header`.
|
2018-07-31 21:19:57 +03:00
|
|
|
See [here](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/state.md) for the definition of `state`.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
### Header
|
2017-12-21 22:18:23 -05:00
|
|
|
|
|
|
|
A Header is valid if its corresponding fields are valid.
|
|
|
|
|
|
|
|
### Version
|
|
|
|
|
|
|
|
Arbitrary string.
|
|
|
|
|
|
|
|
### ChainID
|
|
|
|
|
|
|
|
Arbitrary constant string.
|
|
|
|
|
|
|
|
### Height
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
block.Header.Height > 0
|
|
|
|
block.Header.Height == prevBlock.Header.Height + 1
|
|
|
|
```
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
The height is an incrementing integer. The first block has `block.Header.Height == 1`.
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
### Time
|
|
|
|
|
|
|
|
The median of the timestamps of the valid votes in the block.LastCommit.
|
2017-12-26 18:43:03 -05:00
|
|
|
Corresponds to the number of nanoseconds, with millisecond resolution, since January 1, 1970.
|
2017-12-27 15:14:49 -05:00
|
|
|
|
2018-01-25 02:11:07 +00:00
|
|
|
Note: the timestamp of a vote must be greater by at least one millisecond than that of the
|
2017-12-27 15:14:49 -05:00
|
|
|
block being voted on.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
|
|
|
### NumTxs
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
block.Header.NumTxs == len(block.Txs)
|
|
|
|
```
|
|
|
|
|
|
|
|
Number of transactions included in the block.
|
|
|
|
|
|
|
|
### TxHash
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
block.Header.TxHash == SimpleMerkleRoot(block.Txs)
|
|
|
|
```
|
|
|
|
|
|
|
|
Simple Merkle root of the transactions in the block.
|
|
|
|
|
|
|
|
### LastCommitHash
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
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.
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
The first block has `block.Header.LastCommitHash == []byte{}`
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
### TotalTxs
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-26 16:33:42 -05:00
|
|
|
block.Header.TotalTxs == prevBlock.Header.TotalTxs + block.Header.NumTxs
|
2017-12-21 22:18:23 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
The cumulative sum of all transactions included in this blockchain.
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
The first block has `block.Header.TotalTxs = block.Header.NumberTxs`.
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
### LastBlockID
|
|
|
|
|
2018-01-26 17:26:11 -05:00
|
|
|
LastBlockID is the previous block's BlockID:
|
2018-01-25 02:11:07 +00:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-27 15:14:49 -05:00
|
|
|
prevBlockParts := MakeParts(prevBlock, state.LastConsensusParams.BlockGossip.BlockPartSize)
|
|
|
|
block.Header.LastBlockID == BlockID {
|
|
|
|
Hash: SimpleMerkleRoot(prevBlock.Header),
|
2017-12-26 18:43:03 -05:00
|
|
|
PartsHeader{
|
2017-12-27 15:14:49 -05:00
|
|
|
Hash: SimpleMerkleRoot(prevBlockParts),
|
|
|
|
Total: len(prevBlockParts),
|
2017-12-26 18:43:03 -05:00
|
|
|
},
|
2017-12-21 22:18:23 -05:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2018-01-25 02:11:07 +00:00
|
|
|
Note: it depends on the ConsensusParams,
|
2017-12-21 22:18:23 -05:00
|
|
|
which are held in the `state` and may be updated by the application.
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
The first block has `block.Header.LastBlockID == BlockID{}`.
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
### ResultsHash
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-26 18:43:03 -05:00
|
|
|
block.ResultsHash == SimpleMerkleRoot(state.LastResults)
|
2017-12-21 22:18:23 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
Simple Merkle root of the results of the transactions in the previous block.
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
The first block has `block.Header.ResultsHash == []byte{}`.
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
### AppHash
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-26 18:43:03 -05:00
|
|
|
block.AppHash == state.AppHash
|
2017-12-21 22:18:23 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
Arbitrary byte array returned by the application after executing and commiting the previous block.
|
|
|
|
|
2017-12-26 16:33:42 -05:00
|
|
|
The first block has `block.Header.AppHash == []byte{}`.
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
### ValidatorsHash
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
block.ValidatorsHash == SimpleMerkleRoot(state.Validators)
|
|
|
|
```
|
|
|
|
|
|
|
|
Simple Merkle root of the current validator set that is committing the block.
|
|
|
|
This can be used to validate the `LastCommit` included in the next block.
|
2018-07-31 21:19:57 +03:00
|
|
|
|
|
|
|
### NextValidatorsHash
|
|
|
|
|
|
|
|
```go
|
|
|
|
block.NextValidatorsHash == SimpleMerkleRoot(state.NextValidators)
|
|
|
|
```
|
2018-08-27 15:33:46 +08:00
|
|
|
|
2018-07-31 21:19:57 +03:00
|
|
|
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.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
|
|
|
### ConsensusParamsHash
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-27 15:14:49 -05:00
|
|
|
block.ConsensusParamsHash == SimpleMerkleRoot(state.ConsensusParams)
|
2017-12-21 22:18:23 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
Simple Merkle root of the consensus parameters.
|
|
|
|
May be updated by the application.
|
|
|
|
|
2018-07-30 12:59:16 +04:00
|
|
|
### ProposerAddress
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2018-07-30 12:59:16 +04:00
|
|
|
block.Header.ProposerAddress in state.Validators
|
2017-12-26 16:33:42 -05:00
|
|
|
```
|
|
|
|
|
2018-07-30 12:59:16 +04:00
|
|
|
Address of the original proposer of the block. Must be a current validator.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-26 17:26:11 -05:00
|
|
|
NOTE: we also need to track the round.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-26 17:26:11 -05:00
|
|
|
## EvidenceHash
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
block.EvidenceHash == SimpleMerkleRoot(block.Evidence)
|
|
|
|
```
|
|
|
|
|
|
|
|
Simple Merkle root of the evidence of Byzantine behaviour included in this block.
|
|
|
|
|
|
|
|
## Txs
|
|
|
|
|
|
|
|
Arbitrary length array of arbitrary length byte-arrays.
|
|
|
|
|
|
|
|
## LastCommit
|
|
|
|
|
2017-12-26 15:30:27 -05:00
|
|
|
The first height is an exception - it requires the LastCommit to be empty:
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
if block.Header.Height == 1 {
|
|
|
|
len(b.LastCommit) == 0
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Otherwise, we require:
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-21 22:18:23 -05:00
|
|
|
len(block.LastCommit) == len(state.LastValidators)
|
|
|
|
talliedVotingPower := 0
|
|
|
|
for i, vote := range block.LastCommit{
|
|
|
|
if vote == nil{
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
vote.Type == 2
|
|
|
|
vote.Height == block.LastCommit.Height()
|
|
|
|
vote.Round == block.LastCommit.Round()
|
|
|
|
vote.BlockID == block.LastBlockID
|
|
|
|
|
2017-12-26 18:43:03 -05:00
|
|
|
val := state.LastValidators[i]
|
|
|
|
vote.Verify(block.ChainID, val.PubKey) == true
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2017-12-26 18:43:03 -05:00
|
|
|
talliedVotingPower += val.VotingPower
|
2017-12-21 22:18:23 -05:00
|
|
|
}
|
|
|
|
|
2017-12-26 18:43:03 -05:00
|
|
|
talliedVotingPower > (2/3) * TotalVotingPower(state.LastValidators)
|
2017-12-21 22:18:23 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
Includes one (possibly nil) vote for every current validator.
|
|
|
|
Non-nil votes must be Precommits.
|
|
|
|
All votes must be for the same height and round.
|
|
|
|
All votes must be for the previous block.
|
|
|
|
All votes must have a valid signature from the corresponding validator.
|
|
|
|
The sum total of the voting power of the validators that voted
|
2017-12-26 15:30:27 -05:00
|
|
|
must be greater than 2/3 of the total voting power of the complete validator set.
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2017-12-26 18:43:03 -05:00
|
|
|
### Vote
|
|
|
|
|
|
|
|
A vote is a signed message broadcast in the consensus for a particular block at a particular height and round.
|
|
|
|
When stored in the blockchain or propagated over the network, votes are encoded in TMBIN.
|
|
|
|
For signing, votes are encoded in JSON, and the ChainID is included, in the form of the `CanonicalSignBytes`.
|
|
|
|
|
|
|
|
We define a method `Verify` that returns `true` if the signature verifies against the pubkey for the CanonicalSignBytes
|
|
|
|
using the given ChainID:
|
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-26 18:43:03 -05:00
|
|
|
func (v Vote) Verify(chainID string, pubKey PubKey) bool {
|
|
|
|
return pubKey.Verify(v.Signature, CanonicalSignBytes(chainID, v))
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2018-01-25 02:11:07 +00:00
|
|
|
where `pubKey.Verify` performs the appropriate digital signature verification of the `pubKey`
|
2017-12-26 18:43:03 -05:00
|
|
|
against the given signature and message bytes.
|
|
|
|
|
2017-12-21 22:18:23 -05:00
|
|
|
## Evidence
|
|
|
|
|
2018-06-15 23:17:53 -07:00
|
|
|
There is currently only one kind of evidence:
|
2017-12-21 22:18:23 -05:00
|
|
|
|
|
|
|
```
|
2018-06-15 23:17:53 -07:00
|
|
|
// amino: "tendermint/DuplicateVoteEvidence"
|
|
|
|
type DuplicateVoteEvidence struct {
|
|
|
|
PubKey crypto.PubKey
|
|
|
|
VoteA *Vote
|
|
|
|
VoteB *Vote
|
|
|
|
}
|
2017-12-21 22:18:23 -05:00
|
|
|
```
|
|
|
|
|
2018-06-15 23:17:53 -07:00
|
|
|
DuplicateVoteEvidence `ev` is valid if
|
2017-12-21 22:18:23 -05:00
|
|
|
|
2018-06-15 23:17:53 -07:00
|
|
|
- `ev.VoteA` and `ev.VoteB` can be verified with `ev.PubKey`
|
|
|
|
- `ev.VoteA` and `ev.VoteB` have the same `Height, Round, Address, Index, Type`
|
|
|
|
- `ev.VoteA.BlockID != ev.VoteB.BlockID`
|
|
|
|
- `(block.Height - ev.VoteA.Height) < MAX_EVIDENCE_AGE`
|
2017-12-26 18:43:03 -05:00
|
|
|
|
|
|
|
# Execution
|
|
|
|
|
|
|
|
Once a block is validated, it can be executed against the state.
|
|
|
|
|
2018-01-25 02:11:07 +00:00
|
|
|
The state follows this recursive equation:
|
2017-12-26 18:43:03 -05:00
|
|
|
|
2018-01-03 10:46:43 +01:00
|
|
|
```go
|
2017-12-26 18:43:03 -05:00
|
|
|
state(1) = InitialState
|
2018-01-21 18:19:38 -05:00
|
|
|
state(h+1) <- Execute(state(h), ABCIApp, block(h))
|
|
|
|
```
|
|
|
|
|
2018-01-25 02:11:07 +00:00
|
|
|
where `InitialState` includes the initial consensus parameters and validator set,
|
2018-01-21 18:19:38 -05:00
|
|
|
and `ABCIApp` is an ABCI application that can return results and changes to the validator
|
|
|
|
set (TODO). Execute is defined as:
|
|
|
|
|
|
|
|
```go
|
|
|
|
Execute(s State, app ABCIApp, block Block) State {
|
2018-07-31 21:19:57 +03:00
|
|
|
// Fuction ApplyBlock executes block of transactions against the app and returns the new root hash of the app state,
|
|
|
|
// modifications to the validator set and the changes of the consensus parameters.
|
|
|
|
AppHash, ValidatorChanges, ConsensusParamChanges := app.ApplyBlock(block)
|
2018-01-21 18:19:38 -05:00
|
|
|
|
|
|
|
return State{
|
|
|
|
LastResults: abciResponses.DeliverTxResults,
|
2018-07-31 21:19:57 +03:00
|
|
|
AppHash: AppHash,
|
2018-01-21 18:19:38 -05:00
|
|
|
LastValidators: state.Validators,
|
2018-07-31 21:19:57 +03:00
|
|
|
Validators: state.NextValidators,
|
2018-08-27 15:33:46 +08:00
|
|
|
NextValidators: UpdateValidators(state.NextValidators, ValidatorChanges),
|
2018-07-31 21:19:57 +03:00
|
|
|
ConsensusParams: UpdateConsensusParams(state.ConsensusParams, ConsensusParamChanges),
|
2018-01-21 18:19:38 -05:00
|
|
|
}
|
|
|
|
}
|
2017-12-26 18:43:03 -05:00
|
|
|
```
|