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.

417 lines
11 KiB

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