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.

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