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.

802 lines
22 KiB

max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
7 years ago
10 years ago
10 years ago
7 years ago
7 years ago
10 years ago
10 years ago
11 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/pkg/errors"
  9. "github.com/tendermint/tendermint/crypto"
  10. "github.com/tendermint/tendermint/crypto/merkle"
  11. cmn "github.com/tendermint/tendermint/libs/common"
  12. "github.com/tendermint/tendermint/version"
  13. )
  14. const (
  15. // MaxHeaderBytes is a maximum header size (including amino overhead).
  16. MaxHeaderBytes int64 = 653
  17. // MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to
  18. // MaxBlockSizeBytes in size) not including it's parts except Data.
  19. //
  20. // Uvarint length of MaxBlockSizeBytes: 4 bytes
  21. // 2 fields (2 embedded): 2 bytes
  22. // Uvarint length of Data.Txs: 4 bytes
  23. // Data.Txs field: 1 byte
  24. MaxAminoOverheadForBlock int64 = 11
  25. )
  26. // Block defines the atomic unit of a Tendermint blockchain.
  27. type Block struct {
  28. mtx sync.Mutex
  29. Header `json:"header"`
  30. Data `json:"data"`
  31. Evidence EvidenceData `json:"evidence"`
  32. LastCommit *Commit `json:"last_commit"`
  33. }
  34. // MakeBlock returns a new block with an empty header, except what can be
  35. // computed from itself.
  36. // It populates the same set of fields validated by ValidateBasic.
  37. func MakeBlock(height int64, txs []Tx, lastCommit *Commit, evidence []Evidence) *Block {
  38. block := &Block{
  39. Header: Header{
  40. Height: height,
  41. NumTxs: int64(len(txs)),
  42. },
  43. Data: Data{
  44. Txs: txs,
  45. },
  46. Evidence: EvidenceData{Evidence: evidence},
  47. LastCommit: lastCommit,
  48. }
  49. block.fillHeader()
  50. return block
  51. }
  52. // ValidateBasic performs basic validation that doesn't involve state data.
  53. // It checks the internal consistency of the block.
  54. // Further validation is done using state#ValidateBlock.
  55. func (b *Block) ValidateBasic() error {
  56. if b == nil {
  57. return errors.New("nil block")
  58. }
  59. b.mtx.Lock()
  60. defer b.mtx.Unlock()
  61. if len(b.ChainID) > MaxChainIDLen {
  62. return fmt.Errorf("ChainID is too long. Max is %d, got %d", MaxChainIDLen, len(b.ChainID))
  63. }
  64. if b.Height < 0 {
  65. return errors.New("Negative Header.Height")
  66. } else if b.Height == 0 {
  67. return errors.New("Zero Header.Height")
  68. }
  69. // NOTE: Timestamp validation is subtle and handled elsewhere.
  70. newTxs := int64(len(b.Data.Txs))
  71. if b.NumTxs != newTxs {
  72. return fmt.Errorf("Wrong Header.NumTxs. Expected %v, got %v",
  73. newTxs,
  74. b.NumTxs,
  75. )
  76. }
  77. // TODO: fix tests so we can do this
  78. /*if b.TotalTxs < b.NumTxs {
  79. return fmt.Errorf("Header.TotalTxs (%d) is less than Header.NumTxs (%d)", b.TotalTxs, b.NumTxs)
  80. }*/
  81. if b.TotalTxs < 0 {
  82. return errors.New("Negative Header.TotalTxs")
  83. }
  84. if err := b.LastBlockID.ValidateBasic(); err != nil {
  85. return fmt.Errorf("Wrong Header.LastBlockID: %v", err)
  86. }
  87. // Validate the last commit and its hash.
  88. if b.Header.Height > 1 {
  89. if b.LastCommit == nil {
  90. return errors.New("nil LastCommit")
  91. }
  92. if err := b.LastCommit.ValidateBasic(); err != nil {
  93. return fmt.Errorf("Wrong LastCommit")
  94. }
  95. }
  96. if err := ValidateHash(b.LastCommitHash); err != nil {
  97. return fmt.Errorf("Wrong Header.LastCommitHash: %v", err)
  98. }
  99. if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
  100. return fmt.Errorf("Wrong Header.LastCommitHash. Expected %v, got %v",
  101. b.LastCommit.Hash(),
  102. b.LastCommitHash,
  103. )
  104. }
  105. // Validate the hash of the transactions.
  106. // NOTE: b.Data.Txs may be nil, but b.Data.Hash()
  107. // still works fine
  108. if err := ValidateHash(b.DataHash); err != nil {
  109. return fmt.Errorf("Wrong Header.DataHash: %v", err)
  110. }
  111. if !bytes.Equal(b.DataHash, b.Data.Hash()) {
  112. return fmt.Errorf(
  113. "Wrong Header.DataHash. Expected %v, got %v",
  114. b.Data.Hash(),
  115. b.DataHash,
  116. )
  117. }
  118. // Basic validation of hashes related to application data.
  119. // Will validate fully against state in state#ValidateBlock.
  120. if err := ValidateHash(b.ValidatorsHash); err != nil {
  121. return fmt.Errorf("Wrong Header.ValidatorsHash: %v", err)
  122. }
  123. if err := ValidateHash(b.NextValidatorsHash); err != nil {
  124. return fmt.Errorf("Wrong Header.NextValidatorsHash: %v", err)
  125. }
  126. if err := ValidateHash(b.ConsensusHash); err != nil {
  127. return fmt.Errorf("Wrong Header.ConsensusHash: %v", err)
  128. }
  129. // NOTE: AppHash is arbitrary length
  130. if err := ValidateHash(b.LastResultsHash); err != nil {
  131. return fmt.Errorf("Wrong Header.LastResultsHash: %v", err)
  132. }
  133. // Validate evidence and its hash.
  134. if err := ValidateHash(b.EvidenceHash); err != nil {
  135. return fmt.Errorf("Wrong Header.EvidenceHash: %v", err)
  136. }
  137. // NOTE: b.Evidence.Evidence may be nil, but we're just looping.
  138. for i, ev := range b.Evidence.Evidence {
  139. if err := ev.ValidateBasic(); err != nil {
  140. return fmt.Errorf("Invalid evidence (#%d): %v", i, err)
  141. }
  142. }
  143. if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
  144. return fmt.Errorf("Wrong Header.EvidenceHash. Expected %v, got %v",
  145. b.EvidenceHash,
  146. b.Evidence.Hash(),
  147. )
  148. }
  149. if len(b.ProposerAddress) != crypto.AddressSize {
  150. return fmt.Errorf("Expected len(Header.ProposerAddress) to be %d, got %d",
  151. crypto.AddressSize, len(b.ProposerAddress))
  152. }
  153. return nil
  154. }
  155. // fillHeader fills in any remaining header fields that are a function of the block data
  156. func (b *Block) fillHeader() {
  157. if b.LastCommitHash == nil {
  158. b.LastCommitHash = b.LastCommit.Hash()
  159. }
  160. if b.DataHash == nil {
  161. b.DataHash = b.Data.Hash()
  162. }
  163. if b.EvidenceHash == nil {
  164. b.EvidenceHash = b.Evidence.Hash()
  165. }
  166. }
  167. // Hash computes and returns the block hash.
  168. // If the block is incomplete, block hash is nil for safety.
  169. func (b *Block) Hash() cmn.HexBytes {
  170. if b == nil {
  171. return nil
  172. }
  173. b.mtx.Lock()
  174. defer b.mtx.Unlock()
  175. if b == nil || b.LastCommit == nil {
  176. return nil
  177. }
  178. b.fillHeader()
  179. return b.Header.Hash()
  180. }
  181. // MakePartSet returns a PartSet containing parts of a serialized block.
  182. // This is the form in which the block is gossipped to peers.
  183. // CONTRACT: partSize is greater than zero.
  184. func (b *Block) MakePartSet(partSize int) *PartSet {
  185. if b == nil {
  186. return nil
  187. }
  188. b.mtx.Lock()
  189. defer b.mtx.Unlock()
  190. // We prefix the byte length, so that unmarshaling
  191. // can easily happen via a reader.
  192. bz, err := cdc.MarshalBinaryLengthPrefixed(b)
  193. if err != nil {
  194. panic(err)
  195. }
  196. return NewPartSetFromData(bz, partSize)
  197. }
  198. // HashesTo is a convenience function that checks if a block hashes to the given argument.
  199. // Returns false if the block is nil or the hash is empty.
  200. func (b *Block) HashesTo(hash []byte) bool {
  201. if len(hash) == 0 {
  202. return false
  203. }
  204. if b == nil {
  205. return false
  206. }
  207. return bytes.Equal(b.Hash(), hash)
  208. }
  209. // Size returns size of the block in bytes.
  210. func (b *Block) Size() int {
  211. bz, err := cdc.MarshalBinaryBare(b)
  212. if err != nil {
  213. return 0
  214. }
  215. return len(bz)
  216. }
  217. // String returns a string representation of the block
  218. func (b *Block) String() string {
  219. return b.StringIndented("")
  220. }
  221. // StringIndented returns a string representation of the block
  222. func (b *Block) StringIndented(indent string) string {
  223. if b == nil {
  224. return "nil-Block"
  225. }
  226. return fmt.Sprintf(`Block{
  227. %s %v
  228. %s %v
  229. %s %v
  230. %s %v
  231. %s}#%v`,
  232. indent, b.Header.StringIndented(indent+" "),
  233. indent, b.Data.StringIndented(indent+" "),
  234. indent, b.Evidence.StringIndented(indent+" "),
  235. indent, b.LastCommit.StringIndented(indent+" "),
  236. indent, b.Hash())
  237. }
  238. // StringShort returns a shortened string representation of the block
  239. func (b *Block) StringShort() string {
  240. if b == nil {
  241. return "nil-Block"
  242. }
  243. return fmt.Sprintf("Block#%v", b.Hash())
  244. }
  245. //-----------------------------------------------------------------------------
  246. // MaxDataBytes returns the maximum size of block's data.
  247. //
  248. // XXX: Panics on negative result.
  249. func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
  250. maxDataBytes := maxBytes -
  251. MaxAminoOverheadForBlock -
  252. MaxHeaderBytes -
  253. int64(valsCount)*MaxVoteBytes -
  254. int64(evidenceCount)*MaxEvidenceBytes
  255. if maxDataBytes < 0 {
  256. panic(fmt.Sprintf(
  257. "Negative MaxDataBytes. BlockSize.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  258. maxBytes,
  259. -(maxDataBytes - maxBytes),
  260. ))
  261. }
  262. return maxDataBytes
  263. }
  264. // MaxDataBytesUnknownEvidence returns the maximum size of block's data when
  265. // evidence count is unknown. MaxEvidenceBytesPerBlock will be used as the size
  266. // of evidence.
  267. //
  268. // XXX: Panics on negative result.
  269. func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 {
  270. maxDataBytes := maxBytes -
  271. MaxAminoOverheadForBlock -
  272. MaxHeaderBytes -
  273. int64(valsCount)*MaxVoteBytes -
  274. MaxEvidenceBytesPerBlock(maxBytes)
  275. if maxDataBytes < 0 {
  276. panic(fmt.Sprintf(
  277. "Negative MaxDataBytesUnknownEvidence. BlockSize.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  278. maxBytes,
  279. -(maxDataBytes - maxBytes),
  280. ))
  281. }
  282. return maxDataBytes
  283. }
  284. //-----------------------------------------------------------------------------
  285. // Header defines the structure of a Tendermint block header.
  286. // NOTE: changes to the Header should be duplicated in:
  287. // - header.Hash()
  288. // - abci.Header
  289. // - /docs/spec/blockchain/blockchain.md
  290. type Header struct {
  291. // basic block info
  292. Version version.Consensus `json:"version"`
  293. ChainID string `json:"chain_id"`
  294. Height int64 `json:"height"`
  295. Time time.Time `json:"time"`
  296. NumTxs int64 `json:"num_txs"`
  297. TotalTxs int64 `json:"total_txs"`
  298. // prev block info
  299. LastBlockID BlockID `json:"last_block_id"`
  300. // hashes of block data
  301. LastCommitHash cmn.HexBytes `json:"last_commit_hash"` // commit from validators from the last block
  302. DataHash cmn.HexBytes `json:"data_hash"` // transactions
  303. // hashes from the app output from the prev block
  304. ValidatorsHash cmn.HexBytes `json:"validators_hash"` // validators for the current block
  305. NextValidatorsHash cmn.HexBytes `json:"next_validators_hash"` // validators for the next block
  306. ConsensusHash cmn.HexBytes `json:"consensus_hash"` // consensus params for current block
  307. AppHash cmn.HexBytes `json:"app_hash"` // state after txs from the previous block
  308. LastResultsHash cmn.HexBytes `json:"last_results_hash"` // root hash of all results from the txs from the previous block
  309. // consensus info
  310. EvidenceHash cmn.HexBytes `json:"evidence_hash"` // evidence included in the block
  311. ProposerAddress Address `json:"proposer_address"` // original proposer of the block
  312. }
  313. // Populate the Header with state-derived data.
  314. // Call this after MakeBlock to complete the Header.
  315. func (h *Header) Populate(
  316. version version.Consensus, chainID string,
  317. timestamp time.Time, lastBlockID BlockID, totalTxs int64,
  318. valHash, nextValHash []byte,
  319. consensusHash, appHash, lastResultsHash []byte,
  320. proposerAddress Address,
  321. ) {
  322. h.Version = version
  323. h.ChainID = chainID
  324. h.Time = timestamp
  325. h.LastBlockID = lastBlockID
  326. h.TotalTxs = totalTxs
  327. h.ValidatorsHash = valHash
  328. h.NextValidatorsHash = nextValHash
  329. h.ConsensusHash = consensusHash
  330. h.AppHash = appHash
  331. h.LastResultsHash = lastResultsHash
  332. h.ProposerAddress = proposerAddress
  333. }
  334. // Hash returns the hash of the header.
  335. // It computes a Merkle tree from the header fields
  336. // ordered as they appear in the Header.
  337. // Returns nil if ValidatorHash is missing,
  338. // since a Header is not valid unless there is
  339. // a ValidatorsHash (corresponding to the validator set).
  340. func (h *Header) Hash() cmn.HexBytes {
  341. if h == nil || len(h.ValidatorsHash) == 0 {
  342. return nil
  343. }
  344. return merkle.SimpleHashFromByteSlices([][]byte{
  345. cdcEncode(h.Version),
  346. cdcEncode(h.ChainID),
  347. cdcEncode(h.Height),
  348. cdcEncode(h.Time),
  349. cdcEncode(h.NumTxs),
  350. cdcEncode(h.TotalTxs),
  351. cdcEncode(h.LastBlockID),
  352. cdcEncode(h.LastCommitHash),
  353. cdcEncode(h.DataHash),
  354. cdcEncode(h.ValidatorsHash),
  355. cdcEncode(h.NextValidatorsHash),
  356. cdcEncode(h.ConsensusHash),
  357. cdcEncode(h.AppHash),
  358. cdcEncode(h.LastResultsHash),
  359. cdcEncode(h.EvidenceHash),
  360. cdcEncode(h.ProposerAddress),
  361. })
  362. }
  363. // StringIndented returns a string representation of the header
  364. func (h *Header) StringIndented(indent string) string {
  365. if h == nil {
  366. return "nil-Header"
  367. }
  368. return fmt.Sprintf(`Header{
  369. %s Version: %v
  370. %s ChainID: %v
  371. %s Height: %v
  372. %s Time: %v
  373. %s NumTxs: %v
  374. %s TotalTxs: %v
  375. %s LastBlockID: %v
  376. %s LastCommit: %v
  377. %s Data: %v
  378. %s Validators: %v
  379. %s NextValidators: %v
  380. %s App: %v
  381. %s Consensus: %v
  382. %s Results: %v
  383. %s Evidence: %v
  384. %s Proposer: %v
  385. %s}#%v`,
  386. indent, h.Version,
  387. indent, h.ChainID,
  388. indent, h.Height,
  389. indent, h.Time,
  390. indent, h.NumTxs,
  391. indent, h.TotalTxs,
  392. indent, h.LastBlockID,
  393. indent, h.LastCommitHash,
  394. indent, h.DataHash,
  395. indent, h.ValidatorsHash,
  396. indent, h.NextValidatorsHash,
  397. indent, h.AppHash,
  398. indent, h.ConsensusHash,
  399. indent, h.LastResultsHash,
  400. indent, h.EvidenceHash,
  401. indent, h.ProposerAddress,
  402. indent, h.Hash())
  403. }
  404. //-------------------------------------
  405. // Commit contains the evidence that a block was committed by a set of validators.
  406. // NOTE: Commit is empty for height 1, but never nil.
  407. type Commit struct {
  408. // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
  409. // Any peer with a block can gossip precommits by index with a peer without recalculating the
  410. // active ValidatorSet.
  411. BlockID BlockID `json:"block_id"`
  412. Precommits []*Vote `json:"precommits"`
  413. // Volatile
  414. firstPrecommit *Vote
  415. hash cmn.HexBytes
  416. bitArray *cmn.BitArray
  417. }
  418. // FirstPrecommit returns the first non-nil precommit in the commit.
  419. // If all precommits are nil, it returns an empty precommit with height 0.
  420. func (commit *Commit) FirstPrecommit() *Vote {
  421. if len(commit.Precommits) == 0 {
  422. return nil
  423. }
  424. if commit.firstPrecommit != nil {
  425. return commit.firstPrecommit
  426. }
  427. for _, precommit := range commit.Precommits {
  428. if precommit != nil {
  429. commit.firstPrecommit = precommit
  430. return precommit
  431. }
  432. }
  433. return &Vote{
  434. Type: PrecommitType,
  435. }
  436. }
  437. // Height returns the height of the commit
  438. func (commit *Commit) Height() int64 {
  439. if len(commit.Precommits) == 0 {
  440. return 0
  441. }
  442. return commit.FirstPrecommit().Height
  443. }
  444. // Round returns the round of the commit
  445. func (commit *Commit) Round() int {
  446. if len(commit.Precommits) == 0 {
  447. return 0
  448. }
  449. return commit.FirstPrecommit().Round
  450. }
  451. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  452. func (commit *Commit) Type() byte {
  453. return byte(PrecommitType)
  454. }
  455. // Size returns the number of votes in the commit
  456. func (commit *Commit) Size() int {
  457. if commit == nil {
  458. return 0
  459. }
  460. return len(commit.Precommits)
  461. }
  462. // BitArray returns a BitArray of which validators voted in this commit
  463. func (commit *Commit) BitArray() *cmn.BitArray {
  464. if commit.bitArray == nil {
  465. commit.bitArray = cmn.NewBitArray(len(commit.Precommits))
  466. for i, precommit := range commit.Precommits {
  467. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  468. // not just the one with +2/3 !
  469. commit.bitArray.SetIndex(i, precommit != nil)
  470. }
  471. }
  472. return commit.bitArray
  473. }
  474. // GetByIndex returns the vote corresponding to a given validator index
  475. func (commit *Commit) GetByIndex(index int) *Vote {
  476. return commit.Precommits[index]
  477. }
  478. // IsCommit returns true if there is at least one vote
  479. func (commit *Commit) IsCommit() bool {
  480. return len(commit.Precommits) != 0
  481. }
  482. // ValidateBasic performs basic validation that doesn't involve state data.
  483. // Does not actually check the cryptographic signatures.
  484. func (commit *Commit) ValidateBasic() error {
  485. if commit.BlockID.IsZero() {
  486. return errors.New("Commit cannot be for nil block")
  487. }
  488. if len(commit.Precommits) == 0 {
  489. return errors.New("No precommits in commit")
  490. }
  491. height, round := commit.Height(), commit.Round()
  492. // Validate the precommits.
  493. for _, precommit := range commit.Precommits {
  494. // It's OK for precommits to be missing.
  495. if precommit == nil {
  496. continue
  497. }
  498. // Ensure that all votes are precommits.
  499. if precommit.Type != PrecommitType {
  500. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  501. precommit.Type)
  502. }
  503. // Ensure that all heights are the same.
  504. if precommit.Height != height {
  505. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  506. height, precommit.Height)
  507. }
  508. // Ensure that all rounds are the same.
  509. if precommit.Round != round {
  510. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  511. round, precommit.Round)
  512. }
  513. }
  514. return nil
  515. }
  516. // Hash returns the hash of the commit
  517. func (commit *Commit) Hash() cmn.HexBytes {
  518. if commit == nil {
  519. return nil
  520. }
  521. if commit.hash == nil {
  522. bs := make([][]byte, len(commit.Precommits))
  523. for i, precommit := range commit.Precommits {
  524. bs[i] = cdcEncode(precommit)
  525. }
  526. commit.hash = merkle.SimpleHashFromByteSlices(bs)
  527. }
  528. return commit.hash
  529. }
  530. // StringIndented returns a string representation of the commit
  531. func (commit *Commit) StringIndented(indent string) string {
  532. if commit == nil {
  533. return "nil-Commit"
  534. }
  535. precommitStrings := make([]string, len(commit.Precommits))
  536. for i, precommit := range commit.Precommits {
  537. precommitStrings[i] = precommit.String()
  538. }
  539. return fmt.Sprintf(`Commit{
  540. %s BlockID: %v
  541. %s Precommits:
  542. %s %v
  543. %s}#%v`,
  544. indent, commit.BlockID,
  545. indent,
  546. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  547. indent, commit.hash)
  548. }
  549. //-----------------------------------------------------------------------------
  550. // SignedHeader is a header along with the commits that prove it.
  551. type SignedHeader struct {
  552. *Header `json:"header"`
  553. Commit *Commit `json:"commit"`
  554. }
  555. // ValidateBasic does basic consistency checks and makes sure the header
  556. // and commit are consistent.
  557. //
  558. // NOTE: This does not actually check the cryptographic signatures. Make
  559. // sure to use a Verifier to validate the signatures actually provide a
  560. // significantly strong proof for this header's validity.
  561. func (sh SignedHeader) ValidateBasic(chainID string) error {
  562. // Make sure the header is consistent with the commit.
  563. if sh.Header == nil {
  564. return errors.New("SignedHeader missing header.")
  565. }
  566. if sh.Commit == nil {
  567. return errors.New("SignedHeader missing commit (precommit votes).")
  568. }
  569. // Check ChainID.
  570. if sh.ChainID != chainID {
  571. return fmt.Errorf("Header belongs to another chain '%s' not '%s'",
  572. sh.ChainID, chainID)
  573. }
  574. // Check Height.
  575. if sh.Commit.Height() != sh.Height {
  576. return fmt.Errorf("SignedHeader header and commit height mismatch: %v vs %v",
  577. sh.Height, sh.Commit.Height())
  578. }
  579. // Check Hash.
  580. hhash := sh.Hash()
  581. chash := sh.Commit.BlockID.Hash
  582. if !bytes.Equal(hhash, chash) {
  583. return fmt.Errorf("SignedHeader commit signs block %X, header is block %X",
  584. chash, hhash)
  585. }
  586. // ValidateBasic on the Commit.
  587. err := sh.Commit.ValidateBasic()
  588. if err != nil {
  589. return cmn.ErrorWrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
  590. }
  591. return nil
  592. }
  593. func (sh SignedHeader) String() string {
  594. return sh.StringIndented("")
  595. }
  596. // StringIndented returns a string representation of the SignedHeader.
  597. func (sh SignedHeader) StringIndented(indent string) string {
  598. return fmt.Sprintf(`SignedHeader{
  599. %s %v
  600. %s %v
  601. %s}`,
  602. indent, sh.Header.StringIndented(indent+" "),
  603. indent, sh.Commit.StringIndented(indent+" "),
  604. indent)
  605. }
  606. //-----------------------------------------------------------------------------
  607. // Data contains the set of transactions included in the block
  608. type Data struct {
  609. // Txs that will be applied by state @ block.Height+1.
  610. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  611. // This means that block.AppHash does not include these txs.
  612. Txs Txs `json:"txs"`
  613. // Volatile
  614. hash cmn.HexBytes
  615. }
  616. // Hash returns the hash of the data
  617. func (data *Data) Hash() cmn.HexBytes {
  618. if data == nil {
  619. return (Txs{}).Hash()
  620. }
  621. if data.hash == nil {
  622. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  623. }
  624. return data.hash
  625. }
  626. // StringIndented returns a string representation of the transactions
  627. func (data *Data) StringIndented(indent string) string {
  628. if data == nil {
  629. return "nil-Data"
  630. }
  631. txStrings := make([]string, cmn.MinInt(len(data.Txs), 21))
  632. for i, tx := range data.Txs {
  633. if i == 20 {
  634. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  635. break
  636. }
  637. txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  638. }
  639. return fmt.Sprintf(`Data{
  640. %s %v
  641. %s}#%v`,
  642. indent, strings.Join(txStrings, "\n"+indent+" "),
  643. indent, data.hash)
  644. }
  645. //-----------------------------------------------------------------------------
  646. // EvidenceData contains any evidence of malicious wrong-doing by validators
  647. type EvidenceData struct {
  648. Evidence EvidenceList `json:"evidence"`
  649. // Volatile
  650. hash cmn.HexBytes
  651. }
  652. // Hash returns the hash of the data.
  653. func (data *EvidenceData) Hash() cmn.HexBytes {
  654. if data.hash == nil {
  655. data.hash = data.Evidence.Hash()
  656. }
  657. return data.hash
  658. }
  659. // StringIndented returns a string representation of the evidence.
  660. func (data *EvidenceData) StringIndented(indent string) string {
  661. if data == nil {
  662. return "nil-Evidence"
  663. }
  664. evStrings := make([]string, cmn.MinInt(len(data.Evidence), 21))
  665. for i, ev := range data.Evidence {
  666. if i == 20 {
  667. evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  668. break
  669. }
  670. evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  671. }
  672. return fmt.Sprintf(`EvidenceData{
  673. %s %v
  674. %s}#%v`,
  675. indent, strings.Join(evStrings, "\n"+indent+" "),
  676. indent, data.hash)
  677. }
  678. //--------------------------------------------------------------------------------
  679. // BlockID defines the unique ID of a block as its Hash and its PartSetHeader
  680. type BlockID struct {
  681. Hash cmn.HexBytes `json:"hash"`
  682. PartsHeader PartSetHeader `json:"parts"`
  683. }
  684. // IsZero returns true if this is the BlockID for a nil-block
  685. func (blockID BlockID) IsZero() bool {
  686. return len(blockID.Hash) == 0 && blockID.PartsHeader.IsZero()
  687. }
  688. // Equals returns true if the BlockID matches the given BlockID
  689. func (blockID BlockID) Equals(other BlockID) bool {
  690. return bytes.Equal(blockID.Hash, other.Hash) &&
  691. blockID.PartsHeader.Equals(other.PartsHeader)
  692. }
  693. // Key returns a machine-readable string representation of the BlockID
  694. func (blockID BlockID) Key() string {
  695. bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader)
  696. if err != nil {
  697. panic(err)
  698. }
  699. return string(blockID.Hash) + string(bz)
  700. }
  701. // ValidateBasic performs basic validation.
  702. func (blockID BlockID) ValidateBasic() error {
  703. // Hash can be empty in case of POLBlockID in Proposal.
  704. if err := ValidateHash(blockID.Hash); err != nil {
  705. return fmt.Errorf("Wrong Hash")
  706. }
  707. if err := blockID.PartsHeader.ValidateBasic(); err != nil {
  708. return fmt.Errorf("Wrong PartsHeader: %v", err)
  709. }
  710. return nil
  711. }
  712. // String returns a human readable string representation of the BlockID
  713. func (blockID BlockID) String() string {
  714. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  715. }