You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
9.2 KiB

  1. # Block Structure
  2. The tendermint consensus engine records all agreements by a supermajority of
  3. nodes into a blockchain, which is replicated among all nodes. This blockchain
  4. is accessible via various rpc endpoints, mainly `/block?height=` to get the full
  5. block, as well as `/blockchain?minHeight=_&maxHeight=_` to get a list of headers.
  6. But what exactly is stored in these blocks?
  7. ### Block
  8. A [Block](/docs/specs/tendermint-types#Block) contains:
  9. * a [Header](#header) contains merkle hashes for various chain states
  10. * the [Data]((/docs/specs/tendermint-types#Data) is all transactions which are to be processed
  11. * the [LastCommit](#commit) > 2/3 signatures for the last block
  12. The signatures returned along with block `H` are those validating block `H-1`.
  13. This can be a little confusing, but we must also consider that the
  14. [Header](/docs/specs/tendermint-types#Header) also contains the `LastCommitHash`.
  15. It would be impossible for a Header to include the commits that sign it, as it
  16. would cause an infinite loop here. But when we get block `H`, we find
  17. `Header.LastCommitHash`, which must match the hash of `LastCommit`.
  18. ### Header
  19. The [Header](/docs/specs/tendermint-types#Header) contains lots of information (follow
  20. link for up-to-date info). Notably, it maintains the `Height`, the `LastBlockID`
  21. (to make it a chain), and hashes of the data, the app state, and the validator set.
  22. This is important as the only item that is signed by the validators is the `Header`,
  23. and all other data must be validated against one of the merkle hashes in the `Header`.
  24. The `DataHash` can provide a nice check on the [Data](/docs/specs/tendermint-types#Data)
  25. returned in this same block. If you are subscribed to new blocks, via tendermint RPC, in order to display or process the new transactions
  26. you should at least validate that the `DataHash` is valid.
  27. 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.
  28. The `ValidatorHash` contains a hash of the current
  29. [Validators](/docs/specs/tendermint-types#Validator). Tracking all changes in the
  30. validator set is complex, but a client can quickly compare this hash
  31. with the [hash of the currently known validators](/docs/specs/tendermint-types#ValidatorSet.Hash)
  32. to see if there have been changes.
  33. The `AppHash` serves as the basis for validating any merkle proofs that come
  34. from the [ABCI application](https://github.com/tendermint/abci). It represents
  35. the state of the actual application, rather that the state of the blockchain
  36. itself. This means it's necessary in order to perform any business logic,
  37. such as verifying and account balance.
  38. **Note** After the transactions are committed to a block, they still need to
  39. be processed in a separate step, which happens between the blocks. If you
  40. find a given transaction in the block at height `H`, the effects of running
  41. that transaction will be first visible in the `AppHash` from the block
  42. header at height `H+1`.
  43. Like the `LastCommit` issue, this is a requirement of the
  44. immutability of the block chain, as the application only applies transactions
  45. *after* they are commited to the chain.
  46. ### Commit
  47. The [Commit](/docs/specs/tendermint-types#Commit) contains a set of
  48. [Votes](/docs/specs/tendermint-types#Vote) that were made by the validator set to
  49. reach consensus on this block. This is the key to the security in any PoS
  50. system, and actually no data that cannot be traced back to a block header
  51. with a valid set of Votes can be trusted. Thus, getting the Commit data
  52. and verifying the votes is extremely important.
  53. As mentioned above, in order to find the `precommit votes` for block header `H`,
  54. we need to query block `H+1`. Then we need to check the votes, make sure they
  55. really are for that block, and properly formatted. Much of this code is implemented
  56. in Go in the [light-client](https://github.com/tendermint/light-client) package,
  57. especially [Node.SignedHeader](https://github.com/tendermint/light-client/blob/develop/rpc/node.go#L117).
  58. If you look at the code, you will notice that we need to provide the `chainID`
  59. of the blockchain in order to properly calculate the votes. This is to protect
  60. anyone from swapping votes between chains to fake (or frame) a validator.
  61. Also note that this `chainID` is in the `genesis.json` from _Tendermint_,
  62. not the `genesis.json` from the basecoin app ([that is a different chainID...](https://github.com/tendermint/basecoin/issues/32)).
  63. Once we have those votes,
  64. and we calculated the proper [sign bytes](/docs/specs/tendermint-types#Vote.WriteSignBytes)
  65. using the chainID and a [nice helper function](/docs/specs/tendermint-types#SignBytes),
  66. we can verify them. The light client is responsible for maintaining a set of
  67. validators that we trust. Each vote only stores the validators `Address`, as well
  68. as the `Signature`. Assuming we have a local copy of the trusted validator set,
  69. we can look up the `Public Key` of the validator given its `Address`, then
  70. verify that the `Signature` matches the `SignBytes` and `Public Key`.
  71. Then we sum up the total voting power of all validators, whose votes fulfilled
  72. all these stringent requirements. If the total number of voting power for a single block is greater
  73. than 2/3 of all voting power, then we can finally trust the
  74. block header, the AppHash, and the proof we got from the ABCI application.
  75. To make this a bit more concrete, you can take a look at a
  76. [StaticCertifier](https://github.com/tendermint/light-client/blob/develop/rpc/certifier.go#L23)
  77. to see how this logic works, given a static set of validators. And you can see
  78. an example of how one can perform the entire chain of validation in the
  79. proxy server [proof call](https://github.com/tendermint/light-client/blob/develop/proxy/viewer.go#L61)
  80. or the [test code for auditing](https://github.com/tendermint/light-client/blob/develop/rpc/tests/node_test.go#L102).
  81. #### Vote Sign Bytes
  82. The `sign-bytes` of a vote is produced by taking a [`stable-json`](https://github.com/substack/json-stable-stringify)-like deterministic JSON [`wire`](/docs/specs/wire-protocol) encoding of the vote (excluding the `Signature` field), and wrapping it with `{"chain_id":"my_chain","vote":...}`.
  83. For example, a precommit vote might have the following `sign-bytes`:
  84. ```json
  85. {"chain_id":"my_chain","vote":{"block_hash":"611801F57B4CE378DF1A3FFF1216656E89209A99","block_parts_header":{"hash":"B46697379DBE0774CC2C3B656083F07CA7E0F9CE","total":123},"height":1234,"round":1,"type":2}}
  86. ```
  87. ### Block Hash
  88. The [block hash](/docs/specs/tendermint-types#Block.Hash) is the [Simple Tree hash](Merkle-Trees#simple-tree-with-dictionaries) of the fields of the block `Header` encoded as a list of `KVPair`s.
  89. ### Transaction
  90. A transaction is any sequence of bytes. It is up to your [ABCI](https://github.com/tendermint/abci) application to accept or reject transactions.
  91. ### BlockID
  92. Many of these data structures refer to the [BlockID](/docs/specs/tendermint-types#BlockID),
  93. which is the `BlockHash` (hash of the block header, also referred to by the next block)
  94. along with the `PartSetHeader`. The `PartSetHeader` is explained below and is used internally
  95. to orchestrate the p2p propogation. For clients, it is basically opaque bytes,
  96. but they must match for all votes.
  97. ### PartSetHeader
  98. The [PartSetHeader](/docs/specs/tendermint-types#PartSetHeader) contains the total number of pieces in a [PartSet](/docs/specs/tendermint-types#PartSet), and the Merkle root hash of those pieces.
  99. ### PartSet
  100. PartSet is used to split a byteslice of data into parts (pieces) for transmission.
  101. By splitting data into smaller parts and computing a Merkle root hash on the list,
  102. you can verify that a part is legitimately part of the complete data, and the
  103. part can be forwarded to other peers before all the parts are known. In short,
  104. it's a fast way to securely propagate a large chunk of data (like a block) over a gossip network.
  105. PartSet was inspired by the LibSwift project.
  106. Usage:
  107. ```Go
  108. data := RandBytes(2 << 20) // Something large
  109. partSet := NewPartSetFromData(data)
  110. partSet.Total() // Total number of 4KB parts
  111. partSet.Count() // Equal to the Total, since we already have all the parts
  112. partSet.Hash() // The Merkle root hash
  113. partSet.BitArray() // A BitArray of partSet.Total() 1's
  114. header := partSet.Header() // Send this to the peer
  115. header.Total // Total number of parts
  116. header.Hash // The merkle root hash
  117. // Now we'll reconstruct the data from the parts
  118. partSet2 := NewPartSetFromHeader(header)
  119. partSet2.Total() // Same total as partSet.Total()
  120. partSet2.Count() // Zero, since this PartSet doesn't have any parts yet.
  121. partSet2.Hash() // Same hash as in partSet.Hash()
  122. partSet2.BitArray() // A BitArray of partSet.Total() 0's
  123. // In a gossip network the parts would arrive in arbitrary order, perhaps
  124. // in response to explicit requests for parts, or optimistically in response
  125. // to the receiving peer's partSet.BitArray().
  126. for !partSet2.IsComplete() {
  127. part := receivePartFromGossipNetwork()
  128. added, err := partSet2.AddPart(part)
  129. if err != nil {
  130. // A wrong part,
  131. // the merkle trail does not hash to partSet2.Hash()
  132. } else if !added {
  133. // A duplicate part already received
  134. }
  135. }
  136. data2, _ := ioutil.ReadAll(partSet2.GetReader())
  137. bytes.Equal(data, data2) // true
  138. ```