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.

905 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
6 years ago
10 years ago
10 years ago
6 years ago
6 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. // 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. LastResultsHash cmn.HexBytes `json:"last_results_hash"` // root hash of all results from the txs from the previous block
  313. // consensus info
  314. EvidenceHash cmn.HexBytes `json:"evidence_hash"` // evidence included in the block
  315. ProposerAddress Address `json:"proposer_address"` // original proposer of the block
  316. }
  317. // Populate the Header with state-derived data.
  318. // Call this after MakeBlock to complete the Header.
  319. func (h *Header) Populate(
  320. version version.Consensus, chainID string,
  321. timestamp time.Time, lastBlockID BlockID, totalTxs int64,
  322. valHash, nextValHash []byte,
  323. consensusHash, appHash, lastResultsHash []byte,
  324. proposerAddress Address,
  325. ) {
  326. h.Version = version
  327. h.ChainID = chainID
  328. h.Time = timestamp
  329. h.LastBlockID = lastBlockID
  330. h.TotalTxs = totalTxs
  331. h.ValidatorsHash = valHash
  332. h.NextValidatorsHash = nextValHash
  333. h.ConsensusHash = consensusHash
  334. h.AppHash = appHash
  335. h.LastResultsHash = lastResultsHash
  336. h.ProposerAddress = proposerAddress
  337. }
  338. // Hash returns the hash of the header.
  339. // It computes a Merkle tree from the header fields
  340. // ordered as they appear in the Header.
  341. // Returns nil if ValidatorHash is missing,
  342. // since a Header is not valid unless there is
  343. // a ValidatorsHash (corresponding to the validator set).
  344. func (h *Header) Hash() cmn.HexBytes {
  345. if h == nil || len(h.ValidatorsHash) == 0 {
  346. return nil
  347. }
  348. return merkle.SimpleHashFromByteSlices([][]byte{
  349. cdcEncode(h.Version),
  350. cdcEncode(h.ChainID),
  351. cdcEncode(h.Height),
  352. cdcEncode(h.Time),
  353. cdcEncode(h.NumTxs),
  354. cdcEncode(h.TotalTxs),
  355. cdcEncode(h.LastBlockID),
  356. cdcEncode(h.LastCommitHash),
  357. cdcEncode(h.DataHash),
  358. cdcEncode(h.ValidatorsHash),
  359. cdcEncode(h.NextValidatorsHash),
  360. cdcEncode(h.ConsensusHash),
  361. cdcEncode(h.AppHash),
  362. cdcEncode(h.LastResultsHash),
  363. cdcEncode(h.EvidenceHash),
  364. cdcEncode(h.ProposerAddress),
  365. })
  366. }
  367. // StringIndented returns a string representation of the header
  368. func (h *Header) StringIndented(indent string) string {
  369. if h == nil {
  370. return "nil-Header"
  371. }
  372. return fmt.Sprintf(`Header{
  373. %s Version: %v
  374. %s ChainID: %v
  375. %s Height: %v
  376. %s Time: %v
  377. %s NumTxs: %v
  378. %s TotalTxs: %v
  379. %s LastBlockID: %v
  380. %s LastCommit: %v
  381. %s Data: %v
  382. %s Validators: %v
  383. %s NextValidators: %v
  384. %s App: %v
  385. %s Consensus: %v
  386. %s Results: %v
  387. %s Evidence: %v
  388. %s Proposer: %v
  389. %s}#%v`,
  390. indent, h.Version,
  391. indent, h.ChainID,
  392. indent, h.Height,
  393. indent, h.Time,
  394. indent, h.NumTxs,
  395. indent, h.TotalTxs,
  396. indent, h.LastBlockID,
  397. indent, h.LastCommitHash,
  398. indent, h.DataHash,
  399. indent, h.ValidatorsHash,
  400. indent, h.NextValidatorsHash,
  401. indent, h.AppHash,
  402. indent, h.ConsensusHash,
  403. indent, h.LastResultsHash,
  404. indent, h.EvidenceHash,
  405. indent, h.ProposerAddress,
  406. indent, h.Hash())
  407. }
  408. //-------------------------------------
  409. // CommitSig is a vote included in a Commit.
  410. // For now, it is identical to a vote,
  411. // but in the future it will contain fewer fields
  412. // to eliminate the redundancy in commits.
  413. // See https://github.com/tendermint/tendermint/issues/1648.
  414. type CommitSig Vote
  415. // String returns the underlying Vote.String()
  416. func (cs *CommitSig) String() string {
  417. return cs.toVote().String()
  418. }
  419. // toVote converts the CommitSig to a vote.
  420. // TODO: deprecate for #1648. Converting to Vote will require
  421. // access to ValidatorSet.
  422. func (cs *CommitSig) toVote() *Vote {
  423. if cs == nil {
  424. return nil
  425. }
  426. v := Vote(*cs)
  427. return &v
  428. }
  429. //-------------------------------------
  430. // Commit contains the evidence that a block was committed by a set of validators.
  431. // NOTE: Commit is empty for height 1, but never nil.
  432. type Commit struct {
  433. // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
  434. // Any peer with a block can gossip precommits by index with a peer without recalculating the
  435. // active ValidatorSet.
  436. BlockID BlockID `json:"block_id"`
  437. Precommits []*CommitSig `json:"precommits"`
  438. // memoized in first call to corresponding method
  439. // NOTE: can't memoize in constructor because constructor
  440. // isn't used for unmarshaling
  441. height int64
  442. round int
  443. hash cmn.HexBytes
  444. bitArray *cmn.BitArray
  445. }
  446. // NewCommit returns a new Commit with the given blockID and precommits.
  447. // TODO: memoize ValidatorSet in constructor so votes can be easily reconstructed
  448. // from CommitSig after #1648.
  449. func NewCommit(blockID BlockID, precommits []*CommitSig) *Commit {
  450. return &Commit{
  451. BlockID: blockID,
  452. Precommits: precommits,
  453. }
  454. }
  455. // Construct a VoteSet from the Commit and validator set. Panics
  456. // if precommits from the commit can't be added to the voteset.
  457. // Inverse of VoteSet.MakeCommit().
  458. func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet {
  459. height, round, typ := commit.Height(), commit.Round(), PrecommitType
  460. voteSet := NewVoteSet(chainID, height, round, typ, vals)
  461. for idx, precommit := range commit.Precommits {
  462. if precommit == nil {
  463. continue
  464. }
  465. added, err := voteSet.AddVote(commit.GetVote(idx))
  466. if !added || err != nil {
  467. panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
  468. }
  469. }
  470. return voteSet
  471. }
  472. // GetVote converts the CommitSig for the given valIdx to a Vote.
  473. // Returns nil if the precommit at valIdx is nil.
  474. // Panics if valIdx >= commit.Size().
  475. func (commit *Commit) GetVote(valIdx int) *Vote {
  476. commitSig := commit.Precommits[valIdx]
  477. if commitSig == nil {
  478. return nil
  479. }
  480. // NOTE: this commitSig might be for a nil blockID,
  481. // so we can't just use commit.BlockID here.
  482. // For #1648, CommitSig will need to indicate what BlockID it's for !
  483. blockID := commitSig.BlockID
  484. commit.memoizeHeightRound()
  485. return &Vote{
  486. Type: PrecommitType,
  487. Height: commit.height,
  488. Round: commit.round,
  489. BlockID: blockID,
  490. Timestamp: commitSig.Timestamp,
  491. ValidatorAddress: commitSig.ValidatorAddress,
  492. ValidatorIndex: valIdx,
  493. Signature: commitSig.Signature,
  494. }
  495. }
  496. // VoteSignBytes constructs the SignBytes for the given CommitSig.
  497. // The only unique part of the SignBytes is the Timestamp - all other fields
  498. // signed over are otherwise the same for all validators.
  499. // Panics if valIdx >= commit.Size().
  500. func (commit *Commit) VoteSignBytes(chainID string, valIdx int) []byte {
  501. return commit.GetVote(valIdx).SignBytes(chainID)
  502. }
  503. // memoizeHeightRound memoizes the height and round of the commit using
  504. // the first non-nil vote.
  505. // Should be called before any attempt to access `commit.height` or `commit.round`.
  506. func (commit *Commit) memoizeHeightRound() {
  507. if len(commit.Precommits) == 0 {
  508. return
  509. }
  510. if commit.height > 0 {
  511. return
  512. }
  513. for _, precommit := range commit.Precommits {
  514. if precommit != nil {
  515. commit.height = precommit.Height
  516. commit.round = precommit.Round
  517. return
  518. }
  519. }
  520. }
  521. // Height returns the height of the commit
  522. func (commit *Commit) Height() int64 {
  523. commit.memoizeHeightRound()
  524. return commit.height
  525. }
  526. // Round returns the round of the commit
  527. func (commit *Commit) Round() int {
  528. commit.memoizeHeightRound()
  529. return commit.round
  530. }
  531. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  532. func (commit *Commit) Type() byte {
  533. return byte(PrecommitType)
  534. }
  535. // Size returns the number of votes in the commit
  536. func (commit *Commit) Size() int {
  537. if commit == nil {
  538. return 0
  539. }
  540. return len(commit.Precommits)
  541. }
  542. // BitArray returns a BitArray of which validators voted in this commit
  543. func (commit *Commit) BitArray() *cmn.BitArray {
  544. if commit.bitArray == nil {
  545. commit.bitArray = cmn.NewBitArray(len(commit.Precommits))
  546. for i, precommit := range commit.Precommits {
  547. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  548. // not just the one with +2/3 !
  549. commit.bitArray.SetIndex(i, precommit != nil)
  550. }
  551. }
  552. return commit.bitArray
  553. }
  554. // GetByIndex returns the vote corresponding to a given validator index.
  555. // Panics if `index >= commit.Size()`.
  556. // Implements VoteSetReader.
  557. func (commit *Commit) GetByIndex(valIdx int) *Vote {
  558. return commit.GetVote(valIdx)
  559. }
  560. // IsCommit returns true if there is at least one vote.
  561. func (commit *Commit) IsCommit() bool {
  562. return len(commit.Precommits) != 0
  563. }
  564. // ValidateBasic performs basic validation that doesn't involve state data.
  565. // Does not actually check the cryptographic signatures.
  566. func (commit *Commit) ValidateBasic() error {
  567. if commit.BlockID.IsZero() {
  568. return errors.New("Commit cannot be for nil block")
  569. }
  570. if len(commit.Precommits) == 0 {
  571. return errors.New("No precommits in commit")
  572. }
  573. height, round := commit.Height(), commit.Round()
  574. // Validate the precommits.
  575. for _, precommit := range commit.Precommits {
  576. // It's OK for precommits to be missing.
  577. if precommit == nil {
  578. continue
  579. }
  580. // Ensure that all votes are precommits.
  581. if precommit.Type != PrecommitType {
  582. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  583. precommit.Type)
  584. }
  585. // Ensure that all heights are the same.
  586. if precommit.Height != height {
  587. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  588. height, precommit.Height)
  589. }
  590. // Ensure that all rounds are the same.
  591. if precommit.Round != round {
  592. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  593. round, precommit.Round)
  594. }
  595. }
  596. return nil
  597. }
  598. // Hash returns the hash of the commit
  599. func (commit *Commit) Hash() cmn.HexBytes {
  600. if commit == nil {
  601. return nil
  602. }
  603. if commit.hash == nil {
  604. bs := make([][]byte, len(commit.Precommits))
  605. for i, precommit := range commit.Precommits {
  606. bs[i] = cdcEncode(precommit)
  607. }
  608. commit.hash = merkle.SimpleHashFromByteSlices(bs)
  609. }
  610. return commit.hash
  611. }
  612. // StringIndented returns a string representation of the commit
  613. func (commit *Commit) StringIndented(indent string) string {
  614. if commit == nil {
  615. return "nil-Commit"
  616. }
  617. precommitStrings := make([]string, len(commit.Precommits))
  618. for i, precommit := range commit.Precommits {
  619. precommitStrings[i] = precommit.String()
  620. }
  621. return fmt.Sprintf(`Commit{
  622. %s BlockID: %v
  623. %s Precommits:
  624. %s %v
  625. %s}#%v`,
  626. indent, commit.BlockID,
  627. indent,
  628. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  629. indent, commit.hash)
  630. }
  631. //-----------------------------------------------------------------------------
  632. // SignedHeader is a header along with the commits that prove it.
  633. // It is the basis of the lite client.
  634. type SignedHeader struct {
  635. *Header `json:"header"`
  636. Commit *Commit `json:"commit"`
  637. }
  638. // ValidateBasic does basic consistency checks and makes sure the header
  639. // and commit are consistent.
  640. //
  641. // NOTE: This does not actually check the cryptographic signatures. Make
  642. // sure to use a Verifier to validate the signatures actually provide a
  643. // significantly strong proof for this header's validity.
  644. func (sh SignedHeader) ValidateBasic(chainID string) error {
  645. // Make sure the header is consistent with the commit.
  646. if sh.Header == nil {
  647. return errors.New("SignedHeader missing header.")
  648. }
  649. if sh.Commit == nil {
  650. return errors.New("SignedHeader missing commit (precommit votes).")
  651. }
  652. // Check ChainID.
  653. if sh.ChainID != chainID {
  654. return fmt.Errorf("Header belongs to another chain '%s' not '%s'",
  655. sh.ChainID, chainID)
  656. }
  657. // Check Height.
  658. if sh.Commit.Height() != sh.Height {
  659. return fmt.Errorf("SignedHeader header and commit height mismatch: %v vs %v",
  660. sh.Height, sh.Commit.Height())
  661. }
  662. // Check Hash.
  663. hhash := sh.Hash()
  664. chash := sh.Commit.BlockID.Hash
  665. if !bytes.Equal(hhash, chash) {
  666. return fmt.Errorf("SignedHeader commit signs block %X, header is block %X",
  667. chash, hhash)
  668. }
  669. // ValidateBasic on the Commit.
  670. err := sh.Commit.ValidateBasic()
  671. if err != nil {
  672. return cmn.ErrorWrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
  673. }
  674. return nil
  675. }
  676. func (sh SignedHeader) String() string {
  677. return sh.StringIndented("")
  678. }
  679. // StringIndented returns a string representation of the SignedHeader.
  680. func (sh SignedHeader) StringIndented(indent string) string {
  681. return fmt.Sprintf(`SignedHeader{
  682. %s %v
  683. %s %v
  684. %s}`,
  685. indent, sh.Header.StringIndented(indent+" "),
  686. indent, sh.Commit.StringIndented(indent+" "),
  687. indent)
  688. }
  689. //-----------------------------------------------------------------------------
  690. // Data contains the set of transactions included in the block
  691. type Data struct {
  692. // Txs that will be applied by state @ block.Height+1.
  693. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  694. // This means that block.AppHash does not include these txs.
  695. Txs Txs `json:"txs"`
  696. // Volatile
  697. hash cmn.HexBytes
  698. }
  699. // Hash returns the hash of the data
  700. func (data *Data) Hash() cmn.HexBytes {
  701. if data == nil {
  702. return (Txs{}).Hash()
  703. }
  704. if data.hash == nil {
  705. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  706. }
  707. return data.hash
  708. }
  709. // StringIndented returns a string representation of the transactions
  710. func (data *Data) StringIndented(indent string) string {
  711. if data == nil {
  712. return "nil-Data"
  713. }
  714. txStrings := make([]string, cmn.MinInt(len(data.Txs), 21))
  715. for i, tx := range data.Txs {
  716. if i == 20 {
  717. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  718. break
  719. }
  720. txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  721. }
  722. return fmt.Sprintf(`Data{
  723. %s %v
  724. %s}#%v`,
  725. indent, strings.Join(txStrings, "\n"+indent+" "),
  726. indent, data.hash)
  727. }
  728. //-----------------------------------------------------------------------------
  729. // EvidenceData contains any evidence of malicious wrong-doing by validators
  730. type EvidenceData struct {
  731. Evidence EvidenceList `json:"evidence"`
  732. // Volatile
  733. hash cmn.HexBytes
  734. }
  735. // Hash returns the hash of the data.
  736. func (data *EvidenceData) Hash() cmn.HexBytes {
  737. if data.hash == nil {
  738. data.hash = data.Evidence.Hash()
  739. }
  740. return data.hash
  741. }
  742. // StringIndented returns a string representation of the evidence.
  743. func (data *EvidenceData) StringIndented(indent string) string {
  744. if data == nil {
  745. return "nil-Evidence"
  746. }
  747. evStrings := make([]string, cmn.MinInt(len(data.Evidence), 21))
  748. for i, ev := range data.Evidence {
  749. if i == 20 {
  750. evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  751. break
  752. }
  753. evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  754. }
  755. return fmt.Sprintf(`EvidenceData{
  756. %s %v
  757. %s}#%v`,
  758. indent, strings.Join(evStrings, "\n"+indent+" "),
  759. indent, data.hash)
  760. }
  761. //--------------------------------------------------------------------------------
  762. // BlockID defines the unique ID of a block as its Hash and its PartSetHeader
  763. type BlockID struct {
  764. Hash cmn.HexBytes `json:"hash"`
  765. PartsHeader PartSetHeader `json:"parts"`
  766. }
  767. // Equals returns true if the BlockID matches the given BlockID
  768. func (blockID BlockID) Equals(other BlockID) bool {
  769. return bytes.Equal(blockID.Hash, other.Hash) &&
  770. blockID.PartsHeader.Equals(other.PartsHeader)
  771. }
  772. // Key returns a machine-readable string representation of the BlockID
  773. func (blockID BlockID) Key() string {
  774. bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader)
  775. if err != nil {
  776. panic(err)
  777. }
  778. return string(blockID.Hash) + string(bz)
  779. }
  780. // ValidateBasic performs basic validation.
  781. func (blockID BlockID) ValidateBasic() error {
  782. // Hash can be empty in case of POLBlockID in Proposal.
  783. if err := ValidateHash(blockID.Hash); err != nil {
  784. return fmt.Errorf("Wrong Hash")
  785. }
  786. if err := blockID.PartsHeader.ValidateBasic(); err != nil {
  787. return fmt.Errorf("Wrong PartsHeader: %v", err)
  788. }
  789. return nil
  790. }
  791. // IsZero returns true if this is the BlockID of a nil block.
  792. func (blockID BlockID) IsZero() bool {
  793. return len(blockID.Hash) == 0 &&
  794. blockID.PartsHeader.IsZero()
  795. }
  796. // IsComplete returns true if this is a valid BlockID of a non-nil block.
  797. func (blockID BlockID) IsComplete() bool {
  798. return len(blockID.Hash) == tmhash.Size &&
  799. blockID.PartsHeader.Total > 0 &&
  800. len(blockID.PartsHeader.Hash) == tmhash.Size
  801. }
  802. // String returns a human readable string representation of the BlockID
  803. func (blockID BlockID) String() string {
  804. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  805. }