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.

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