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.

390 lines
9.8 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. . "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() *PartSet {
  76. return NewPartSetFromData(wire.BinaryBytes(b))
  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. Precommits []*Vote `json:"precommits"`
  176. // Volatile
  177. firstPrecommit *Vote
  178. hash []byte
  179. bitArray *BitArray
  180. }
  181. func (commit *Commit) FirstPrecommit() *Vote {
  182. if len(commit.Precommits) == 0 {
  183. return nil
  184. }
  185. if commit.firstPrecommit != nil {
  186. return commit.firstPrecommit
  187. }
  188. for _, precommit := range commit.Precommits {
  189. if precommit != nil {
  190. commit.firstPrecommit = precommit
  191. return precommit
  192. }
  193. }
  194. return nil
  195. }
  196. func (commit *Commit) Height() int {
  197. if len(commit.Precommits) == 0 {
  198. return 0
  199. }
  200. return commit.FirstPrecommit().Height
  201. }
  202. func (commit *Commit) Round() int {
  203. if len(commit.Precommits) == 0 {
  204. return 0
  205. }
  206. return commit.FirstPrecommit().Round
  207. }
  208. func (commit *Commit) Type() byte {
  209. return VoteTypePrecommit
  210. }
  211. func (commit *Commit) Size() int {
  212. if commit == nil {
  213. return 0
  214. }
  215. return len(commit.Precommits)
  216. }
  217. func (commit *Commit) BitArray() *BitArray {
  218. if commit.bitArray == nil {
  219. commit.bitArray = NewBitArray(len(commit.Precommits))
  220. for i, precommit := range commit.Precommits {
  221. commit.bitArray.SetIndex(i, precommit != nil)
  222. }
  223. }
  224. return commit.bitArray
  225. }
  226. func (commit *Commit) GetByIndex(index int) *Vote {
  227. return commit.Precommits[index]
  228. }
  229. func (commit *Commit) IsCommit() bool {
  230. if len(commit.Precommits) == 0 {
  231. return false
  232. }
  233. return true
  234. }
  235. func (commit *Commit) ValidateBasic() error {
  236. if len(commit.Precommits) == 0 {
  237. return errors.New("No precommits in commit")
  238. }
  239. height, round := commit.Height(), commit.Round()
  240. for _, precommit := range commit.Precommits {
  241. // It's OK for precommits to be missing.
  242. if precommit == nil {
  243. continue
  244. }
  245. // Ensure that all votes are precommits
  246. if precommit.Type != VoteTypePrecommit {
  247. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  248. precommit.Type)
  249. }
  250. // Ensure that all heights are the same
  251. if precommit.Height != height {
  252. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  253. height, precommit.Height)
  254. }
  255. // Ensure that all rounds are the same
  256. if precommit.Round != round {
  257. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  258. round, precommit.Round)
  259. }
  260. }
  261. return nil
  262. }
  263. func (commit *Commit) Hash() []byte {
  264. if commit.hash == nil {
  265. bs := make([]interface{}, len(commit.Precommits))
  266. for i, precommit := range commit.Precommits {
  267. bs[i] = precommit
  268. }
  269. commit.hash = merkle.SimpleHashFromBinaries(bs)
  270. }
  271. return commit.hash
  272. }
  273. func (commit *Commit) StringIndented(indent string) string {
  274. if commit == nil {
  275. return "nil-Commit"
  276. }
  277. precommitStrings := make([]string, len(commit.Precommits))
  278. for i, precommit := range commit.Precommits {
  279. precommitStrings[i] = precommit.String()
  280. }
  281. return fmt.Sprintf(`Commit{
  282. %s Precommits: %v
  283. %s}#%X`,
  284. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  285. indent, commit.hash)
  286. }
  287. //-----------------------------------------------------------------------------
  288. type Data struct {
  289. // Txs that will be applied by state @ block.Height+1.
  290. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  291. // This means that block.AppHash does not include these txs.
  292. Txs Txs `json:"txs"`
  293. // Volatile
  294. hash []byte
  295. }
  296. func (data *Data) Hash() []byte {
  297. if data.hash == nil {
  298. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  299. }
  300. return data.hash
  301. }
  302. func (data *Data) StringIndented(indent string) string {
  303. if data == nil {
  304. return "nil-Data"
  305. }
  306. txStrings := make([]string, MinInt(len(data.Txs), 21))
  307. for i, tx := range data.Txs {
  308. if i == 20 {
  309. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  310. break
  311. }
  312. txStrings[i] = fmt.Sprintf("Tx:%v", tx)
  313. }
  314. return fmt.Sprintf(`Data{
  315. %s %v
  316. %s}#%X`,
  317. indent, strings.Join(txStrings, "\n"+indent+" "),
  318. indent, data.hash)
  319. }
  320. //--------------------------------------------------------------------------------
  321. type BlockID struct {
  322. Hash []byte `json:"hash"`
  323. PartsHeader PartSetHeader `json:"parts"`
  324. }
  325. func (blockID BlockID) IsZero() bool {
  326. return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
  327. }
  328. func (blockID BlockID) Equals(other BlockID) bool {
  329. return bytes.Equal(blockID.Hash, other.Hash) &&
  330. blockID.PartsHeader.Equals(other.PartsHeader)
  331. }
  332. func (blockID BlockID) Key() string {
  333. return string(blockID.Hash) + string(wire.BinaryBytes(blockID.PartsHeader))
  334. }
  335. func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) {
  336. if blockID.IsZero() {
  337. wire.WriteTo([]byte("null"), w, n, err)
  338. } else {
  339. wire.WriteTo([]byte(Fmt(`{"hash":"%X","parts":`, blockID.Hash)), w, n, err)
  340. blockID.PartsHeader.WriteSignBytes(w, n, err)
  341. wire.WriteTo([]byte("}"), w, n, err)
  342. }
  343. }
  344. func (blockID BlockID) String() string {
  345. return fmt.Sprintf(`%X:%v`, blockID.Hash, blockID.PartsHeader)
  346. }