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.

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