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.

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