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.

423 lines
11 KiB

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