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.

396 lines
9.9 KiB

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