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.

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