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
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 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. // Returns nil if ValidatorHash is 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. }