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.

453 lines
13 KiB

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