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.

835 lines
23 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. // 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. BlockSize.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. MaxEvidenceBytesPerBlock will be used as the size
  287. // of evidence.
  288. //
  289. // XXX: Panics on negative result.
  290. func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 {
  291. maxDataBytes := maxBytes -
  292. MaxAminoOverheadForBlock -
  293. MaxHeaderBytes -
  294. int64(valsCount)*MaxVoteBytes -
  295. MaxEvidenceBytesPerBlock(maxBytes)
  296. if maxDataBytes < 0 {
  297. panic(fmt.Sprintf(
  298. "Negative MaxDataBytesUnknownEvidence. BlockSize.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  299. maxBytes,
  300. -(maxDataBytes - maxBytes),
  301. ))
  302. }
  303. return maxDataBytes
  304. }
  305. //-----------------------------------------------------------------------------
  306. // Header defines the structure of a Tendermint block header.
  307. // NOTE: changes to the Header should be duplicated in:
  308. // - header.Hash()
  309. // - abci.Header
  310. // - /docs/spec/blockchain/blockchain.md
  311. type Header struct {
  312. // basic block info
  313. Version version.Consensus `json:"version"`
  314. ChainID string `json:"chain_id"`
  315. Height int64 `json:"height"`
  316. Time time.Time `json:"time"`
  317. NumTxs int64 `json:"num_txs"`
  318. TotalTxs int64 `json:"total_txs"`
  319. // prev block info
  320. LastBlockID BlockID `json:"last_block_id"`
  321. // hashes of block data
  322. LastCommitHash cmn.HexBytes `json:"last_commit_hash"` // commit from validators from the last block
  323. DataHash cmn.HexBytes `json:"data_hash"` // transactions
  324. // hashes from the app output from the prev block
  325. ValidatorsHash cmn.HexBytes `json:"validators_hash"` // validators for the current block
  326. NextValidatorsHash cmn.HexBytes `json:"next_validators_hash"` // validators for the next block
  327. ConsensusHash cmn.HexBytes `json:"consensus_hash"` // consensus params for current block
  328. AppHash cmn.HexBytes `json:"app_hash"` // state after txs from the previous block
  329. LastResultsHash cmn.HexBytes `json:"last_results_hash"` // root hash of all results from the txs from the previous block
  330. // consensus info
  331. EvidenceHash cmn.HexBytes `json:"evidence_hash"` // evidence included in the block
  332. ProposerAddress Address `json:"proposer_address"` // original proposer of the block
  333. }
  334. // Populate the Header with state-derived data.
  335. // Call this after MakeBlock to complete the Header.
  336. func (h *Header) Populate(
  337. version version.Consensus, chainID string,
  338. timestamp time.Time, lastBlockID BlockID, totalTxs int64,
  339. valHash, nextValHash []byte,
  340. consensusHash, appHash, lastResultsHash []byte,
  341. proposerAddress Address,
  342. ) {
  343. h.Version = version
  344. h.ChainID = chainID
  345. h.Time = timestamp
  346. h.LastBlockID = lastBlockID
  347. h.TotalTxs = totalTxs
  348. h.ValidatorsHash = valHash
  349. h.NextValidatorsHash = nextValHash
  350. h.ConsensusHash = consensusHash
  351. h.AppHash = appHash
  352. h.LastResultsHash = lastResultsHash
  353. h.ProposerAddress = proposerAddress
  354. }
  355. // Hash returns the hash of the header.
  356. // It computes a Merkle tree from the header fields
  357. // ordered as they appear in the Header.
  358. // Returns nil if ValidatorHash is missing,
  359. // since a Header is not valid unless there is
  360. // a ValidatorsHash (corresponding to the validator set).
  361. func (h *Header) Hash() cmn.HexBytes {
  362. if h == nil || len(h.ValidatorsHash) == 0 {
  363. return nil
  364. }
  365. return merkle.SimpleHashFromByteSlices([][]byte{
  366. cdcEncode(h.Version),
  367. cdcEncode(h.ChainID),
  368. cdcEncode(h.Height),
  369. cdcEncode(h.Time),
  370. cdcEncode(h.NumTxs),
  371. cdcEncode(h.TotalTxs),
  372. cdcEncode(h.LastBlockID),
  373. cdcEncode(h.LastCommitHash),
  374. cdcEncode(h.DataHash),
  375. cdcEncode(h.ValidatorsHash),
  376. cdcEncode(h.NextValidatorsHash),
  377. cdcEncode(h.ConsensusHash),
  378. cdcEncode(h.AppHash),
  379. cdcEncode(h.LastResultsHash),
  380. cdcEncode(h.EvidenceHash),
  381. cdcEncode(h.ProposerAddress),
  382. })
  383. }
  384. // StringIndented returns a string representation of the header
  385. func (h *Header) StringIndented(indent string) string {
  386. if h == nil {
  387. return "nil-Header"
  388. }
  389. return fmt.Sprintf(`Header{
  390. %s Version: %v
  391. %s ChainID: %v
  392. %s Height: %v
  393. %s Time: %v
  394. %s NumTxs: %v
  395. %s TotalTxs: %v
  396. %s LastBlockID: %v
  397. %s LastCommit: %v
  398. %s Data: %v
  399. %s Validators: %v
  400. %s NextValidators: %v
  401. %s App: %v
  402. %s Consensus: %v
  403. %s Results: %v
  404. %s Evidence: %v
  405. %s Proposer: %v
  406. %s}#%v`,
  407. indent, h.Version,
  408. indent, h.ChainID,
  409. indent, h.Height,
  410. indent, h.Time,
  411. indent, h.NumTxs,
  412. indent, h.TotalTxs,
  413. indent, h.LastBlockID,
  414. indent, h.LastCommitHash,
  415. indent, h.DataHash,
  416. indent, h.ValidatorsHash,
  417. indent, h.NextValidatorsHash,
  418. indent, h.AppHash,
  419. indent, h.ConsensusHash,
  420. indent, h.LastResultsHash,
  421. indent, h.EvidenceHash,
  422. indent, h.ProposerAddress,
  423. indent, h.Hash())
  424. }
  425. //-------------------------------------
  426. // Commit contains the evidence that a block was committed by a set of validators.
  427. // NOTE: Commit is empty for height 1, but never nil.
  428. type Commit struct {
  429. // NOTE: The Precommits are in order of address to preserve the bonded ValidatorSet order.
  430. // Any peer with a block can gossip precommits by index with a peer without recalculating the
  431. // active ValidatorSet.
  432. BlockID BlockID `json:"block_id"`
  433. Precommits []*Vote `json:"precommits"`
  434. // Volatile
  435. firstPrecommit *Vote
  436. hash cmn.HexBytes
  437. bitArray *cmn.BitArray
  438. }
  439. // FirstPrecommit returns the first non-nil precommit in the commit.
  440. // If all precommits are nil, it returns an empty precommit with height 0.
  441. func (commit *Commit) FirstPrecommit() *Vote {
  442. if len(commit.Precommits) == 0 {
  443. return nil
  444. }
  445. if commit.firstPrecommit != nil {
  446. return commit.firstPrecommit
  447. }
  448. for _, precommit := range commit.Precommits {
  449. if precommit != nil {
  450. commit.firstPrecommit = precommit
  451. return precommit
  452. }
  453. }
  454. return &Vote{
  455. Type: PrecommitType,
  456. }
  457. }
  458. // Height returns the height of the commit
  459. func (commit *Commit) Height() int64 {
  460. if len(commit.Precommits) == 0 {
  461. return 0
  462. }
  463. return commit.FirstPrecommit().Height
  464. }
  465. // Round returns the round of the commit
  466. func (commit *Commit) Round() int {
  467. if len(commit.Precommits) == 0 {
  468. return 0
  469. }
  470. return commit.FirstPrecommit().Round
  471. }
  472. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  473. func (commit *Commit) Type() byte {
  474. return byte(PrecommitType)
  475. }
  476. // Size returns the number of votes in the commit
  477. func (commit *Commit) Size() int {
  478. if commit == nil {
  479. return 0
  480. }
  481. return len(commit.Precommits)
  482. }
  483. // BitArray returns a BitArray of which validators voted in this commit
  484. func (commit *Commit) BitArray() *cmn.BitArray {
  485. if commit.bitArray == nil {
  486. commit.bitArray = cmn.NewBitArray(len(commit.Precommits))
  487. for i, precommit := range commit.Precommits {
  488. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  489. // not just the one with +2/3 !
  490. commit.bitArray.SetIndex(i, precommit != nil)
  491. }
  492. }
  493. return commit.bitArray
  494. }
  495. // GetByIndex returns the vote corresponding to a given validator index
  496. func (commit *Commit) GetByIndex(index int) *Vote {
  497. return commit.Precommits[index]
  498. }
  499. // IsCommit returns true if there is at least one vote
  500. func (commit *Commit) IsCommit() bool {
  501. return len(commit.Precommits) != 0
  502. }
  503. // ValidateBasic performs basic validation that doesn't involve state data.
  504. // Does not actually check the cryptographic signatures.
  505. func (commit *Commit) ValidateBasic() error {
  506. if commit.BlockID.IsZero() {
  507. return errors.New("Commit cannot be for nil block")
  508. }
  509. if len(commit.Precommits) == 0 {
  510. return errors.New("No precommits in commit")
  511. }
  512. height, round := commit.Height(), commit.Round()
  513. // Validate the precommits.
  514. for _, precommit := range commit.Precommits {
  515. // It's OK for precommits to be missing.
  516. if precommit == nil {
  517. continue
  518. }
  519. // Ensure that all votes are precommits.
  520. if precommit.Type != PrecommitType {
  521. return fmt.Errorf("Invalid commit vote. Expected precommit, got %v",
  522. precommit.Type)
  523. }
  524. // Ensure that all heights are the same.
  525. if precommit.Height != height {
  526. return fmt.Errorf("Invalid commit precommit height. Expected %v, got %v",
  527. height, precommit.Height)
  528. }
  529. // Ensure that all rounds are the same.
  530. if precommit.Round != round {
  531. return fmt.Errorf("Invalid commit precommit round. Expected %v, got %v",
  532. round, precommit.Round)
  533. }
  534. }
  535. return nil
  536. }
  537. // Hash returns the hash of the commit
  538. func (commit *Commit) Hash() cmn.HexBytes {
  539. if commit == nil {
  540. return nil
  541. }
  542. if commit.hash == nil {
  543. bs := make([][]byte, len(commit.Precommits))
  544. for i, precommit := range commit.Precommits {
  545. bs[i] = cdcEncode(precommit)
  546. }
  547. commit.hash = merkle.SimpleHashFromByteSlices(bs)
  548. }
  549. return commit.hash
  550. }
  551. // StringIndented returns a string representation of the commit
  552. func (commit *Commit) StringIndented(indent string) string {
  553. if commit == nil {
  554. return "nil-Commit"
  555. }
  556. precommitStrings := make([]string, len(commit.Precommits))
  557. for i, precommit := range commit.Precommits {
  558. precommitStrings[i] = precommit.String()
  559. }
  560. return fmt.Sprintf(`Commit{
  561. %s BlockID: %v
  562. %s Precommits:
  563. %s %v
  564. %s}#%v`,
  565. indent, commit.BlockID,
  566. indent,
  567. indent, strings.Join(precommitStrings, "\n"+indent+" "),
  568. indent, commit.hash)
  569. }
  570. //-----------------------------------------------------------------------------
  571. // SignedHeader is a header along with the commits that prove it.
  572. type SignedHeader struct {
  573. *Header `json:"header"`
  574. Commit *Commit `json:"commit"`
  575. }
  576. // ValidateBasic does basic consistency checks and makes sure the header
  577. // and commit are consistent.
  578. //
  579. // NOTE: This does not actually check the cryptographic signatures. Make
  580. // sure to use a Verifier to validate the signatures actually provide a
  581. // significantly strong proof for this header's validity.
  582. func (sh SignedHeader) ValidateBasic(chainID string) error {
  583. // Make sure the header is consistent with the commit.
  584. if sh.Header == nil {
  585. return errors.New("SignedHeader missing header.")
  586. }
  587. if sh.Commit == nil {
  588. return errors.New("SignedHeader missing commit (precommit votes).")
  589. }
  590. // Check ChainID.
  591. if sh.ChainID != chainID {
  592. return fmt.Errorf("Header belongs to another chain '%s' not '%s'",
  593. sh.ChainID, chainID)
  594. }
  595. // Check Height.
  596. if sh.Commit.Height() != sh.Height {
  597. return fmt.Errorf("SignedHeader header and commit height mismatch: %v vs %v",
  598. sh.Height, sh.Commit.Height())
  599. }
  600. // Check Hash.
  601. hhash := sh.Hash()
  602. chash := sh.Commit.BlockID.Hash
  603. if !bytes.Equal(hhash, chash) {
  604. return fmt.Errorf("SignedHeader commit signs block %X, header is block %X",
  605. chash, hhash)
  606. }
  607. // ValidateBasic on the Commit.
  608. err := sh.Commit.ValidateBasic()
  609. if err != nil {
  610. return cmn.ErrorWrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
  611. }
  612. return nil
  613. }
  614. func (sh SignedHeader) String() string {
  615. return sh.StringIndented("")
  616. }
  617. // StringIndented returns a string representation of the SignedHeader.
  618. func (sh SignedHeader) StringIndented(indent string) string {
  619. return fmt.Sprintf(`SignedHeader{
  620. %s %v
  621. %s %v
  622. %s}`,
  623. indent, sh.Header.StringIndented(indent+" "),
  624. indent, sh.Commit.StringIndented(indent+" "),
  625. indent)
  626. }
  627. //-----------------------------------------------------------------------------
  628. // Data contains the set of transactions included in the block
  629. type Data struct {
  630. // Txs that will be applied by state @ block.Height+1.
  631. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  632. // This means that block.AppHash does not include these txs.
  633. Txs Txs `json:"txs"`
  634. // Volatile
  635. hash cmn.HexBytes
  636. }
  637. // Hash returns the hash of the data
  638. func (data *Data) Hash() cmn.HexBytes {
  639. if data == nil {
  640. return (Txs{}).Hash()
  641. }
  642. if data.hash == nil {
  643. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  644. }
  645. return data.hash
  646. }
  647. // StringIndented returns a string representation of the transactions
  648. func (data *Data) StringIndented(indent string) string {
  649. if data == nil {
  650. return "nil-Data"
  651. }
  652. txStrings := make([]string, cmn.MinInt(len(data.Txs), 21))
  653. for i, tx := range data.Txs {
  654. if i == 20 {
  655. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  656. break
  657. }
  658. txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  659. }
  660. return fmt.Sprintf(`Data{
  661. %s %v
  662. %s}#%v`,
  663. indent, strings.Join(txStrings, "\n"+indent+" "),
  664. indent, data.hash)
  665. }
  666. //-----------------------------------------------------------------------------
  667. // EvidenceData contains any evidence of malicious wrong-doing by validators
  668. type EvidenceData struct {
  669. Evidence EvidenceList `json:"evidence"`
  670. // Volatile
  671. hash cmn.HexBytes
  672. }
  673. // Hash returns the hash of the data.
  674. func (data *EvidenceData) Hash() cmn.HexBytes {
  675. if data.hash == nil {
  676. data.hash = data.Evidence.Hash()
  677. }
  678. return data.hash
  679. }
  680. // StringIndented returns a string representation of the evidence.
  681. func (data *EvidenceData) StringIndented(indent string) string {
  682. if data == nil {
  683. return "nil-Evidence"
  684. }
  685. evStrings := make([]string, cmn.MinInt(len(data.Evidence), 21))
  686. for i, ev := range data.Evidence {
  687. if i == 20 {
  688. evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  689. break
  690. }
  691. evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  692. }
  693. return fmt.Sprintf(`EvidenceData{
  694. %s %v
  695. %s}#%v`,
  696. indent, strings.Join(evStrings, "\n"+indent+" "),
  697. indent, data.hash)
  698. }
  699. //--------------------------------------------------------------------------------
  700. // BlockID defines the unique ID of a block as its Hash and its PartSetHeader
  701. type BlockID struct {
  702. Hash cmn.HexBytes `json:"hash"`
  703. PartsHeader PartSetHeader `json:"parts"`
  704. }
  705. // Equals returns true if the BlockID matches the given BlockID
  706. func (blockID BlockID) Equals(other BlockID) bool {
  707. return bytes.Equal(blockID.Hash, other.Hash) &&
  708. blockID.PartsHeader.Equals(other.PartsHeader)
  709. }
  710. // Key returns a machine-readable string representation of the BlockID
  711. func (blockID BlockID) Key() string {
  712. bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader)
  713. if err != nil {
  714. panic(err)
  715. }
  716. return string(blockID.Hash) + string(bz)
  717. }
  718. // ValidateBasic performs basic validation.
  719. func (blockID BlockID) ValidateBasic() error {
  720. // Hash can be empty in case of POLBlockID in Proposal.
  721. if err := ValidateHash(blockID.Hash); err != nil {
  722. return fmt.Errorf("Wrong Hash")
  723. }
  724. if err := blockID.PartsHeader.ValidateBasic(); err != nil {
  725. return fmt.Errorf("Wrong PartsHeader: %v", err)
  726. }
  727. return nil
  728. }
  729. // IsZero returns true if this is the BlockID of a nil block.
  730. func (blockID BlockID) IsZero() bool {
  731. return len(blockID.Hash) == 0 &&
  732. blockID.PartsHeader.IsZero()
  733. }
  734. // IsComplete returns true if this is a valid BlockID of a non-nil block.
  735. func (blockID BlockID) IsComplete() bool {
  736. return len(blockID.Hash) == tmhash.Size &&
  737. blockID.PartsHeader.Total > 0 &&
  738. len(blockID.PartsHeader.Hash) == tmhash.Size
  739. }
  740. // String returns a human readable string representation of the BlockID
  741. func (blockID BlockID) String() string {
  742. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  743. }