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.

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