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.

456 lines
13 KiB

7 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "strings"
  8. "time"
  9. wire "github.com/tendermint/go-wire"
  10. "github.com/tendermint/go-wire/data"
  11. cmn "github.com/tendermint/tmlibs/common"
  12. "github.com/tendermint/tmlibs/merkle"
  13. )
  14. // Block defines the atomic unit of a Tendermint blockchain.
  15. type Block struct {
  16. *Header `json:"header"`
  17. *Data `json:"data"`
  18. LastCommit *Commit `json:"last_commit"`
  19. }
  20. // MakeBlock returns a new block and corresponding partset from the given information.
  21. // TODO: Add version information to the Block struct.
  22. func MakeBlock(height int, chainID string, txs []Tx, commit *Commit,
  23. prevBlockID BlockID, valHash, appHash []byte, partSize int) (*Block, *PartSet) {
  24. block := &Block{
  25. Header: &Header{
  26. ChainID: chainID,
  27. Height: height,
  28. Time: time.Now(),
  29. NumTxs: len(txs),
  30. LastBlockID: prevBlockID,
  31. ValidatorsHash: valHash,
  32. AppHash: appHash, // state merkle root of txs from the previous block.
  33. },
  34. LastCommit: commit,
  35. Data: &Data{
  36. Txs: txs,
  37. },
  38. }
  39. block.FillHeader()
  40. return block, block.MakePartSet(partSize)
  41. }
  42. // ValidateBasic performs basic validation that doesn't involve state data.
  43. func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockID BlockID,
  44. lastBlockTime time.Time, appHash []byte) error {
  45. if b.ChainID != chainID {
  46. return errors.New(cmn.Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", chainID, b.ChainID))
  47. }
  48. if b.Height != lastBlockHeight+1 {
  49. return errors.New(cmn.Fmt("Wrong Block.Header.Height. Expected %v, got %v", lastBlockHeight+1, b.Height))
  50. }
  51. /* TODO: Determine bounds for Time
  52. See blockchain/reactor "stopSyncingDurationMinutes"
  53. if !b.Time.After(lastBlockTime) {
  54. return errors.New("Invalid Block.Header.Time")
  55. }
  56. */
  57. if b.NumTxs != len(b.Data.Txs) {
  58. return errors.New(cmn.Fmt("Wrong Block.Header.NumTxs. Expected %v, got %v", len(b.Data.Txs), b.NumTxs))
  59. }
  60. if !b.LastBlockID.Equals(lastBlockID) {
  61. return errors.New(cmn.Fmt("Wrong Block.Header.LastBlockID. Expected %v, got %v", lastBlockID, b.LastBlockID))
  62. }
  63. if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
  64. return errors.New(cmn.Fmt("Wrong Block.Header.LastCommitHash. Expected %v, got %v", b.LastCommitHash, b.LastCommit.Hash()))
  65. }
  66. if b.Header.Height != 1 {
  67. if err := b.LastCommit.ValidateBasic(); err != nil {
  68. return err
  69. }
  70. }
  71. if !bytes.Equal(b.DataHash, b.Data.Hash()) {
  72. return errors.New(cmn.Fmt("Wrong Block.Header.DataHash. Expected %v, got %v", b.DataHash, b.Data.Hash()))
  73. }
  74. if !bytes.Equal(b.AppHash, appHash) {
  75. return errors.New(cmn.Fmt("Wrong Block.Header.AppHash. Expected %X, got %v", appHash, b.AppHash))
  76. }
  77. // NOTE: the AppHash and ValidatorsHash are validated later.
  78. return nil
  79. }
  80. // FillHeader fills in any remaining header fields that are a function of the block data
  81. func (b *Block) FillHeader() {
  82. if b.LastCommitHash == nil {
  83. b.LastCommitHash = b.LastCommit.Hash()
  84. }
  85. if b.DataHash == nil {
  86. b.DataHash = b.Data.Hash()
  87. }
  88. }
  89. // Hash computes and returns the block hash.
  90. // If the block is incomplete, block hash is nil for safety.
  91. func (b *Block) Hash() data.Bytes {
  92. // fmt.Println(">>", b.Data)
  93. if b == nil || b.Header == nil || b.Data == nil || b.LastCommit == nil {
  94. return nil
  95. }
  96. b.FillHeader()
  97. return b.Header.Hash()
  98. }
  99. // MakePartSet returns a PartSet containing parts of a serialized block.
  100. // This is the form in which the block is gossipped to peers.
  101. func (b *Block) MakePartSet(partSize int) *PartSet {
  102. return NewPartSetFromData(wire.BinaryBytes(b), partSize)
  103. }
  104. // HashesTo is a convenience function that checks if a block hashes to the given argument.
  105. // A nil block never hashes to anything, and nothing hashes to a nil hash.
  106. func (b *Block) HashesTo(hash []byte) bool {
  107. if len(hash) == 0 {
  108. return false
  109. }
  110. if b == nil {
  111. return false
  112. }
  113. return bytes.Equal(b.Hash(), hash)
  114. }
  115. // String returns a string representation of the block
  116. func (b *Block) String() string {
  117. return b.StringIndented("")
  118. }
  119. // StringIndented returns a string representation of the block
  120. func (b *Block) StringIndented(indent string) string {
  121. if b == nil {
  122. return "nil-Block"
  123. }
  124. return fmt.Sprintf(`Block{
  125. %s %v
  126. %s %v
  127. %s %v
  128. %s}#%v`,
  129. indent, b.Header.StringIndented(indent+" "),
  130. indent, b.Data.StringIndented(indent+" "),
  131. indent, b.LastCommit.StringIndented(indent+" "),
  132. indent, b.Hash())
  133. }
  134. // StringShort returns a shortened string representation of the block
  135. func (b *Block) StringShort() string {
  136. if b == nil {
  137. return "nil-Block"
  138. } else {
  139. return fmt.Sprintf("Block#%v", b.Hash())
  140. }
  141. }
  142. //-----------------------------------------------------------------------------
  143. // Header defines the structure of a Tendermint block header
  144. type Header struct {
  145. ChainID string `json:"chain_id"`
  146. Height int `json:"height"`
  147. Time time.Time `json:"time"`
  148. NumTxs int `json:"num_txs"` // XXX: Can we get rid of this?
  149. LastBlockID BlockID `json:"last_block_id"`
  150. LastCommitHash data.Bytes `json:"last_commit_hash"` // commit from validators from the last block
  151. DataHash data.Bytes `json:"data_hash"` // transactions
  152. ValidatorsHash data.Bytes `json:"validators_hash"` // validators for the current block
  153. AppHash data.Bytes `json:"app_hash"` // state after txs from the previous block
  154. }
  155. // Hash returns the hash of the header.
  156. // NOTE: hash is nil if required fields are missing.
  157. func (h *Header) Hash() data.Bytes {
  158. if len(h.ValidatorsHash) == 0 {
  159. return nil
  160. }
  161. return merkle.SimpleHashFromMap(map[string]interface{}{
  162. "ChainID": h.ChainID,
  163. "Height": h.Height,
  164. "Time": h.Time,
  165. "NumTxs": h.NumTxs,
  166. "LastBlockID": h.LastBlockID,
  167. "LastCommit": h.LastCommitHash,
  168. "Data": h.DataHash,
  169. "Validators": h.ValidatorsHash,
  170. "App": h.AppHash,
  171. })
  172. }
  173. // StringIndented returns a string representation of the header
  174. func (h *Header) StringIndented(indent string) string {
  175. if h == nil {
  176. return "nil-Header"
  177. }
  178. return fmt.Sprintf(`Header{
  179. %s ChainID: %v
  180. %s Height: %v
  181. %s Time: %v
  182. %s NumTxs: %v
  183. %s LastBlockID: %v
  184. %s LastCommit: %v
  185. %s Data: %v
  186. %s Validators: %v
  187. %s App: %v
  188. %s}#%v`,
  189. indent, h.ChainID,
  190. indent, h.Height,
  191. indent, h.Time,
  192. indent, h.NumTxs,
  193. indent, h.LastBlockID,
  194. indent, h.LastCommitHash,
  195. indent, h.DataHash,
  196. indent, h.ValidatorsHash,
  197. indent, h.AppHash,
  198. indent, h.Hash())
  199. }
  200. //-------------------------------------
  201. // Commit contains the evidence that a block was committed by a set of validators.
  202. // NOTE: Commit is empty for height 1, but never nil.
  203. type Commit struct {
  204. // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
  205. // Any peer with a block can gossip precommits by index with a peer without recalculating the
  206. // active ValidatorSet.
  207. BlockID BlockID `json:"blockID"`
  208. Precommits []*Vote `json:"precommits"`
  209. // Volatile
  210. firstPrecommit *Vote
  211. hash data.Bytes
  212. bitArray *cmn.BitArray
  213. }
  214. // FirstPrecommit returns the first non-nil precommit in the commit
  215. func (commit *Commit) FirstPrecommit() *Vote {
  216. if len(commit.Precommits) == 0 {
  217. return nil
  218. }
  219. if commit.firstPrecommit != nil {
  220. return commit.firstPrecommit
  221. }
  222. for _, precommit := range commit.Precommits {
  223. if precommit != nil {
  224. commit.firstPrecommit = precommit
  225. return precommit
  226. }
  227. }
  228. return nil
  229. }
  230. // Height returns the height of the commit
  231. func (commit *Commit) Height() int {
  232. if len(commit.Precommits) == 0 {
  233. return 0
  234. }
  235. return commit.FirstPrecommit().Height
  236. }
  237. // Round returns the round of the commit
  238. func (commit *Commit) Round() int {
  239. if len(commit.Precommits) == 0 {
  240. return 0
  241. }
  242. return commit.FirstPrecommit().Round
  243. }
  244. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  245. func (commit *Commit) Type() byte {
  246. return VoteTypePrecommit
  247. }
  248. // Size returns the number of votes in the commit
  249. func (commit *Commit) Size() int {
  250. if commit == nil {
  251. return 0
  252. }
  253. return len(commit.Precommits)
  254. }
  255. // BitArray returns a BitArray of which validators voted in this commit
  256. func (commit *Commit) BitArray() *cmn.BitArray {
  257. if commit.bitArray == nil {
  258. commit.bitArray = cmn.NewBitArray(len(commit.Precommits))
  259. for i, precommit := range commit.Precommits {
  260. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  261. // not just the one with +2/3 !
  262. commit.bitArray.SetIndex(i, precommit != nil)
  263. }
  264. }
  265. return commit.bitArray
  266. }
  267. // GetByIndex returns the vote corresponding to a given validator index
  268. func (commit *Commit) GetByIndex(index int) *Vote {
  269. return commit.Precommits[index]
  270. }
  271. // IsCommit returns true if there is at least one vote
  272. func (commit *Commit) IsCommit() bool {
  273. return len(commit.Precommits) != 0
  274. }
  275. // ValidateBasic performs basic validation that doesn't involve state data.
  276. func (commit *Commit) ValidateBasic() error {
  277. if commit.BlockID.IsZero() {
  278. return errors.New("Commit cannot be for nil block")
  279. }
  280. if len(commit.Precommits) == 0 {
  281. return errors.New("No precommits in commit")
  282. }
  283. height, round := commit.Height(), commit.Round()
  284. // validate the precommits
  285. for _, precommit := range commit.Precommits {
  286. // It's OK for precommits to be missing.
  287. if precommit == nil {
  288. continue
  289. }
  290. // Ensure that all votes are precommits
  291. if precommit.Type != VoteTypePrecommit {
  292. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  293. precommit.Type)
  294. }
  295. // Ensure that all heights are the same
  296. if precommit.Height != height {
  297. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  298. height, precommit.Height)
  299. }
  300. // Ensure that all rounds are the same
  301. if precommit.Round != round {
  302. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  303. round, precommit.Round)
  304. }
  305. }
  306. return nil
  307. }
  308. // Hash returns the hash of the commit
  309. func (commit *Commit) Hash() data.Bytes {
  310. if commit.hash == nil {
  311. bs := make([]interface{}, len(commit.Precommits))
  312. for i, precommit := range commit.Precommits {
  313. bs[i] = precommit
  314. }
  315. commit.hash = merkle.SimpleHashFromBinaries(bs)
  316. }
  317. return commit.hash
  318. }
  319. // StringIndented returns a string representation of the commit
  320. func (commit *Commit) StringIndented(indent string) string {
  321. if commit == nil {
  322. return "nil-Commit"
  323. }
  324. precommitStrings := make([]string, len(commit.Precommits))
  325. for i, precommit := range commit.Precommits {
  326. precommitStrings[i] = precommit.String()
  327. }
  328. return fmt.Sprintf(`Commit{
  329. %s BlockID: %v
  330. %s Precommits: %v
  331. %s}#%v`,
  332. indent, commit.BlockID,
  333. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  334. indent, commit.hash)
  335. }
  336. //-----------------------------------------------------------------------------
  337. // SignedHeader is a header along with the commits that prove it
  338. type SignedHeader struct {
  339. Header *Header `json:"header"`
  340. Commit *Commit `json:"commit"`
  341. }
  342. //-----------------------------------------------------------------------------
  343. // Data contains the set of transactions included in the block
  344. type Data struct {
  345. // Txs that will be applied by state @ block.Height+1.
  346. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  347. // This means that block.AppHash does not include these txs.
  348. Txs Txs `json:"txs"`
  349. // Volatile
  350. hash data.Bytes
  351. }
  352. // Hash returns the hash of the data
  353. func (data *Data) Hash() data.Bytes {
  354. if data.hash == nil {
  355. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  356. }
  357. return data.hash
  358. }
  359. // StringIndented returns a string representation of the transactions
  360. func (data *Data) StringIndented(indent string) string {
  361. if data == nil {
  362. return "nil-Data"
  363. }
  364. txStrings := make([]string, cmn.MinInt(len(data.Txs), 21))
  365. for i, tx := range data.Txs {
  366. if i == 20 {
  367. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  368. break
  369. }
  370. txStrings[i] = fmt.Sprintf("Tx:%v", tx)
  371. }
  372. return fmt.Sprintf(`Data{
  373. %s %v
  374. %s}#%v`,
  375. indent, strings.Join(txStrings, "\n"+indent+" "),
  376. indent, data.hash)
  377. }
  378. //--------------------------------------------------------------------------------
  379. // BlockID defines the unique ID of a block as its Hash and its PartSetHeader
  380. type BlockID struct {
  381. Hash data.Bytes `json:"hash"`
  382. PartsHeader PartSetHeader `json:"parts"`
  383. }
  384. // IsZero returns true if this is the BlockID for a nil-block
  385. func (blockID BlockID) IsZero() bool {
  386. return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
  387. }
  388. // Equals returns true if the BlockID matches the given BlockID
  389. func (blockID BlockID) Equals(other BlockID) bool {
  390. return bytes.Equal(blockID.Hash, other.Hash) &&
  391. blockID.PartsHeader.Equals(other.PartsHeader)
  392. }
  393. // Key returns a machine-readable string representation of the BlockID
  394. func (blockID BlockID) Key() string {
  395. return string(blockID.Hash) + string(wire.BinaryBytes(blockID.PartsHeader))
  396. }
  397. // WriteSignBytes writes the canonical bytes of the BlockID to the given writer for digital signing
  398. func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) {
  399. if blockID.IsZero() {
  400. wire.WriteTo([]byte("null"), w, n, err)
  401. } else {
  402. wire.WriteJSON(CanonicalBlockID(blockID), w, n, err)
  403. }
  404. }
  405. // String returns a human readable string representation of the BlockID
  406. func (blockID BlockID) String() string {
  407. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  408. }