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.

367 lines
9.3 KiB

10 years ago
10 years ago
9 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. "strings"
  7. "time"
  8. . "github.com/tendermint/go-common"
  9. "github.com/tendermint/go-merkle"
  10. "github.com/tendermint/go-wire"
  11. )
  12. const MaxBlockSize = 22020096 // 21MB TODO make it configurable
  13. type Block struct {
  14. *Header `json:"header"`
  15. *Data `json:"data"`
  16. LastCommit *Commit `json:"last_commit"`
  17. }
  18. // Basic validation that doesn't involve state data.
  19. func (b *Block) ValidateBasic(chainID string, lastBlockHeight int, lastBlockHash []byte,
  20. lastBlockParts PartSetHeader, lastBlockTime time.Time, appHash []byte) error {
  21. if b.ChainID != chainID {
  22. return errors.New(Fmt("Wrong Block.Header.ChainID. Expected %v, got %v", chainID, b.ChainID))
  23. }
  24. if b.Height != lastBlockHeight+1 {
  25. return errors.New(Fmt("Wrong Block.Header.Height. Expected %v, got %v", lastBlockHeight+1, b.Height))
  26. }
  27. /* TODO: Determine bounds for Time
  28. See blockchain/reactor "stopSyncingDurationMinutes"
  29. if !b.Time.After(lastBlockTime) {
  30. return errors.New("Invalid Block.Header.Time")
  31. }
  32. */
  33. if b.NumTxs != len(b.Data.Txs) {
  34. return errors.New(Fmt("Wrong Block.Header.NumTxs. Expected %v, got %v", len(b.Data.Txs), b.NumTxs))
  35. }
  36. if !bytes.Equal(b.LastBlockHash, lastBlockHash) {
  37. return errors.New(Fmt("Wrong Block.Header.LastBlockHash. Expected %X, got %X", lastBlockHash, b.LastBlockHash))
  38. }
  39. if !b.LastBlockParts.Equals(lastBlockParts) {
  40. return errors.New(Fmt("Wrong Block.Header.LastBlockParts. Expected %v, got %v", lastBlockParts, b.LastBlockParts))
  41. }
  42. if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
  43. return errors.New(Fmt("Wrong Block.Header.LastCommitHash. Expected %X, got %X", b.LastCommitHash, b.LastCommit.Hash()))
  44. }
  45. if b.Header.Height != 1 {
  46. if err := b.LastCommit.ValidateBasic(); err != nil {
  47. return err
  48. }
  49. }
  50. if !bytes.Equal(b.DataHash, b.Data.Hash()) {
  51. return errors.New(Fmt("Wrong Block.Header.DataHash. Expected %X, got %X", b.DataHash, b.Data.Hash()))
  52. }
  53. if !bytes.Equal(b.AppHash, appHash) {
  54. return errors.New(Fmt("Wrong Block.Header.AppHash. Expected %X, got %X", appHash, b.AppHash))
  55. }
  56. // NOTE: the AppHash and ValidatorsHash are validated later.
  57. return nil
  58. }
  59. func (b *Block) FillHeader() {
  60. if b.LastCommitHash == nil {
  61. b.LastCommitHash = b.LastCommit.Hash()
  62. }
  63. if b.DataHash == nil {
  64. b.DataHash = b.Data.Hash()
  65. }
  66. }
  67. // Computes and returns the block hash.
  68. // If the block is incomplete, block hash is nil for safety.
  69. func (b *Block) Hash() []byte {
  70. fmt.Println(">>", b.Data)
  71. if b.Header == nil || b.Data == nil || b.LastCommit == nil {
  72. return nil
  73. }
  74. b.FillHeader()
  75. return b.Header.Hash()
  76. }
  77. func (b *Block) MakePartSet() *PartSet {
  78. return NewPartSetFromData(wire.BinaryBytes(b))
  79. }
  80. // Convenience.
  81. // A nil block never hashes to anything.
  82. // Nothing hashes to a nil hash.
  83. func (b *Block) HashesTo(hash []byte) bool {
  84. if len(hash) == 0 {
  85. return false
  86. }
  87. if b == nil {
  88. return false
  89. }
  90. return bytes.Equal(b.Hash(), hash)
  91. }
  92. func (b *Block) String() string {
  93. return b.StringIndented("")
  94. }
  95. func (b *Block) StringIndented(indent string) string {
  96. if b == nil {
  97. return "nil-Block"
  98. }
  99. return fmt.Sprintf(`Block{
  100. %s %v
  101. %s %v
  102. %s %v
  103. %s}#%X`,
  104. indent, b.Header.StringIndented(indent+" "),
  105. indent, b.Data.StringIndented(indent+" "),
  106. indent, b.LastCommit.StringIndented(indent+" "),
  107. indent, b.Hash())
  108. }
  109. func (b *Block) StringShort() string {
  110. if b == nil {
  111. return "nil-Block"
  112. } else {
  113. return fmt.Sprintf("Block#%X", b.Hash())
  114. }
  115. }
  116. //-----------------------------------------------------------------------------
  117. type Header struct {
  118. ChainID string `json:"chain_id"`
  119. Height int `json:"height"`
  120. Time time.Time `json:"time"`
  121. NumTxs int `json:"num_txs"`
  122. LastBlockHash []byte `json:"last_block_hash"`
  123. LastBlockParts PartSetHeader `json:"last_block_parts"`
  124. LastCommitHash []byte `json:"last_commit_hash"`
  125. DataHash []byte `json:"data_hash"`
  126. ValidatorsHash []byte `json:"validators_hash"`
  127. AppHash []byte `json:"app_hash"` // state merkle root of txs from the previous block
  128. }
  129. // NOTE: hash is nil if required fields are missing.
  130. func (h *Header) Hash() []byte {
  131. if len(h.ValidatorsHash) == 0 {
  132. return nil
  133. }
  134. return merkle.SimpleHashFromMap(map[string]interface{}{
  135. "ChainID": h.ChainID,
  136. "Height": h.Height,
  137. "Time": h.Time,
  138. "NumTxs": h.NumTxs,
  139. "LastBlock": h.LastBlockHash,
  140. "LastBlockParts": h.LastBlockParts,
  141. "LastCommit": h.LastCommitHash,
  142. "Data": h.DataHash,
  143. "Validators": h.ValidatorsHash,
  144. "App": h.AppHash,
  145. })
  146. }
  147. func (h *Header) StringIndented(indent string) string {
  148. if h == nil {
  149. return "nil-Header"
  150. }
  151. return fmt.Sprintf(`Header{
  152. %s ChainID: %v
  153. %s Height: %v
  154. %s Time: %v
  155. %s NumTxs: %v
  156. %s LastBlock: %X
  157. %s LastBlockParts: %v
  158. %s LastCommit: %X
  159. %s Data: %X
  160. %s Validators: %X
  161. %s App: %X
  162. %s}#%X`,
  163. indent, h.ChainID,
  164. indent, h.Height,
  165. indent, h.Time,
  166. indent, h.NumTxs,
  167. indent, h.LastBlockHash,
  168. indent, h.LastBlockParts,
  169. indent, h.LastCommitHash,
  170. indent, h.DataHash,
  171. indent, h.ValidatorsHash,
  172. indent, h.AppHash,
  173. indent, h.Hash())
  174. }
  175. //-------------------------------------
  176. // NOTE: Commit is empty for height 1, but never nil.
  177. type Commit struct {
  178. // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
  179. // Any peer with a block can gossip precommits by index with a peer without recalculating the
  180. // active ValidatorSet.
  181. Precommits []*Vote `json:"precommits"`
  182. // Volatile
  183. firstPrecommit *Vote
  184. hash []byte
  185. bitArray *BitArray
  186. }
  187. func (commit *Commit) FirstPrecommit() *Vote {
  188. if len(commit.Precommits) == 0 {
  189. return nil
  190. }
  191. if commit.firstPrecommit != nil {
  192. return commit.firstPrecommit
  193. }
  194. for _, precommit := range commit.Precommits {
  195. if precommit != nil {
  196. commit.firstPrecommit = precommit
  197. return precommit
  198. }
  199. }
  200. return nil
  201. }
  202. func (commit *Commit) Height() int {
  203. if len(commit.Precommits) == 0 {
  204. return 0
  205. }
  206. return commit.FirstPrecommit().Height
  207. }
  208. func (commit *Commit) Round() int {
  209. if len(commit.Precommits) == 0 {
  210. return 0
  211. }
  212. return commit.FirstPrecommit().Round
  213. }
  214. func (commit *Commit) Type() byte {
  215. return VoteTypePrecommit
  216. }
  217. func (commit *Commit) Size() int {
  218. if commit == nil {
  219. return 0
  220. }
  221. return len(commit.Precommits)
  222. }
  223. func (commit *Commit) BitArray() *BitArray {
  224. if commit.bitArray == nil {
  225. commit.bitArray = NewBitArray(len(commit.Precommits))
  226. for i, precommit := range commit.Precommits {
  227. commit.bitArray.SetIndex(i, precommit != nil)
  228. }
  229. }
  230. return commit.bitArray
  231. }
  232. func (commit *Commit) GetByIndex(index int) *Vote {
  233. return commit.Precommits[index]
  234. }
  235. func (commit *Commit) IsCommit() bool {
  236. if len(commit.Precommits) == 0 {
  237. return false
  238. }
  239. return true
  240. }
  241. func (commit *Commit) ValidateBasic() error {
  242. if len(commit.Precommits) == 0 {
  243. return errors.New("No precommits in commit")
  244. }
  245. height, round := commit.Height(), commit.Round()
  246. for _, precommit := range commit.Precommits {
  247. // It's OK for precommits to be missing.
  248. if precommit == nil {
  249. continue
  250. }
  251. // Ensure that all votes are precommits
  252. if precommit.Type != VoteTypePrecommit {
  253. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  254. precommit.Type)
  255. }
  256. // Ensure that all heights are the same
  257. if precommit.Height != height {
  258. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  259. height, precommit.Height)
  260. }
  261. // Ensure that all rounds are the same
  262. if precommit.Round != round {
  263. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  264. round, precommit.Round)
  265. }
  266. }
  267. return nil
  268. }
  269. func (commit *Commit) Hash() []byte {
  270. if commit.hash == nil {
  271. bs := make([]interface{}, len(commit.Precommits))
  272. for i, precommit := range commit.Precommits {
  273. bs[i] = precommit
  274. }
  275. commit.hash = merkle.SimpleHashFromBinaries(bs)
  276. }
  277. return commit.hash
  278. }
  279. func (commit *Commit) StringIndented(indent string) string {
  280. if commit == nil {
  281. return "nil-Commit"
  282. }
  283. precommitStrings := make([]string, len(commit.Precommits))
  284. for i, precommit := range commit.Precommits {
  285. precommitStrings[i] = precommit.String()
  286. }
  287. return fmt.Sprintf(`Commit{
  288. %s Precommits: %v
  289. %s}#%X`,
  290. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  291. indent, commit.hash)
  292. }
  293. //-----------------------------------------------------------------------------
  294. type Data struct {
  295. // Txs that will be applied by state @ block.Height+1.
  296. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  297. // This means that block.AppHash does not include these txs.
  298. Txs Txs `json:"txs"`
  299. // Volatile
  300. hash []byte
  301. }
  302. func (data *Data) Hash() []byte {
  303. if config.GetBool("disable_data_hash") {
  304. // we could use the part_set hash instead
  305. data.hash = []byte{}
  306. return data.hash
  307. }
  308. if data.hash == nil {
  309. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  310. }
  311. return data.hash
  312. }
  313. func (data *Data) StringIndented(indent string) string {
  314. if data == nil {
  315. return "nil-Data"
  316. }
  317. txStrings := make([]string, MinInt(len(data.Txs), 21))
  318. for i, tx := range data.Txs {
  319. if i == 20 {
  320. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  321. break
  322. }
  323. txStrings[i] = fmt.Sprintf("Tx:%v", tx)
  324. }
  325. return fmt.Sprintf(`Data{
  326. %s %v
  327. %s}#%X`,
  328. indent, strings.Join(txStrings, "\n"+indent+" "),
  329. indent, data.hash)
  330. }