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.

471 lines
14 KiB

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