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.

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