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.

420 lines
11 KiB

7 years ago
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. wire "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. DefaultBlockPartSize = 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 %v, got %v", 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 %v, got %v", 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 %v", 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() data.Bytes {
  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}#%v`,
  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#%v", 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() data.Bytes {
  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: %v
  179. %s Data: %v
  180. %s Validators: %v
  181. %s App: %v
  182. %s}#%v`,
  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 data.Bytes
  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. return len(commit.Precommits) != 0
  257. }
  258. func (commit *Commit) ValidateBasic() error {
  259. if commit.BlockID.IsZero() {
  260. return errors.New("Commit cannot be for nil block")
  261. }
  262. if len(commit.Precommits) == 0 {
  263. return errors.New("No precommits in commit")
  264. }
  265. height, round := commit.Height(), commit.Round()
  266. // validate the precommits
  267. for _, precommit := range commit.Precommits {
  268. // It's OK for precommits to be missing.
  269. if precommit == nil {
  270. continue
  271. }
  272. // Ensure that all votes are precommits
  273. if precommit.Type != VoteTypePrecommit {
  274. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  275. precommit.Type)
  276. }
  277. // Ensure that all heights are the same
  278. if precommit.Height != height {
  279. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  280. height, precommit.Height)
  281. }
  282. // Ensure that all rounds are the same
  283. if precommit.Round != round {
  284. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  285. round, precommit.Round)
  286. }
  287. }
  288. return nil
  289. }
  290. func (commit *Commit) Hash() data.Bytes {
  291. if commit.hash == nil {
  292. bs := make([]interface{}, len(commit.Precommits))
  293. for i, precommit := range commit.Precommits {
  294. bs[i] = precommit
  295. }
  296. commit.hash = merkle.SimpleHashFromBinaries(bs)
  297. }
  298. return commit.hash
  299. }
  300. func (commit *Commit) StringIndented(indent string) string {
  301. if commit == nil {
  302. return "nil-Commit"
  303. }
  304. precommitStrings := make([]string, len(commit.Precommits))
  305. for i, precommit := range commit.Precommits {
  306. precommitStrings[i] = precommit.String()
  307. }
  308. return fmt.Sprintf(`Commit{
  309. %s BlockID: %v
  310. %s Precommits: %v
  311. %s}#%v`,
  312. indent, commit.BlockID,
  313. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  314. indent, commit.hash)
  315. }
  316. //-----------------------------------------------------------------------------
  317. type Data struct {
  318. // Txs that will be applied by state @ block.Height+1.
  319. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  320. // This means that block.AppHash does not include these txs.
  321. Txs Txs `json:"txs"`
  322. // Volatile
  323. hash data.Bytes
  324. }
  325. func (data *Data) Hash() data.Bytes {
  326. if data.hash == nil {
  327. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  328. }
  329. return data.hash
  330. }
  331. func (data *Data) StringIndented(indent string) string {
  332. if data == nil {
  333. return "nil-Data"
  334. }
  335. txStrings := make([]string, MinInt(len(data.Txs), 21))
  336. for i, tx := range data.Txs {
  337. if i == 20 {
  338. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  339. break
  340. }
  341. txStrings[i] = fmt.Sprintf("Tx:%v", tx)
  342. }
  343. return fmt.Sprintf(`Data{
  344. %s %v
  345. %s}#%v`,
  346. indent, strings.Join(txStrings, "\n"+indent+" "),
  347. indent, data.hash)
  348. }
  349. //--------------------------------------------------------------------------------
  350. type BlockID struct {
  351. Hash data.Bytes `json:"hash"`
  352. PartsHeader PartSetHeader `json:"parts"`
  353. }
  354. func (blockID BlockID) IsZero() bool {
  355. return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
  356. }
  357. func (blockID BlockID) Equals(other BlockID) bool {
  358. return bytes.Equal(blockID.Hash, other.Hash) &&
  359. blockID.PartsHeader.Equals(other.PartsHeader)
  360. }
  361. func (blockID BlockID) Key() string {
  362. return string(blockID.Hash) + string(wire.BinaryBytes(blockID.PartsHeader))
  363. }
  364. func (blockID BlockID) WriteSignBytes(w io.Writer, n *int, err *error) {
  365. if blockID.IsZero() {
  366. wire.WriteTo([]byte("null"), w, n, err)
  367. } else {
  368. wire.WriteJSON(CanonicalBlockID(blockID), w, n, err)
  369. }
  370. }
  371. func (blockID BlockID) String() string {
  372. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  373. }