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.

1357 lines
35 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
10 years ago
10 years ago
7 years ago
7 years ago
7 years ago
7 years ago
10 years ago
11 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "strings"
  7. "time"
  8. "github.com/gogo/protobuf/proto"
  9. gogotypes "github.com/gogo/protobuf/types"
  10. "github.com/tendermint/tendermint/crypto"
  11. "github.com/tendermint/tendermint/crypto/merkle"
  12. "github.com/tendermint/tendermint/crypto/tmhash"
  13. "github.com/tendermint/tendermint/libs/bits"
  14. tmbytes "github.com/tendermint/tendermint/libs/bytes"
  15. tmmath "github.com/tendermint/tendermint/libs/math"
  16. tmsync "github.com/tendermint/tendermint/libs/sync"
  17. tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
  18. tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
  19. )
  20. const (
  21. // MaxHeaderBytes is a maximum header size.
  22. MaxHeaderBytes int64 = 626
  23. // MaxOverheadForBlock - maximum overhead to encode a block (up to
  24. // MaxBlockSizeBytes in size) not including it's parts except Data.
  25. // This means it also excludes the overhead for individual transactions.
  26. //
  27. // Uvarint length of MaxBlockSizeBytes: 4 bytes
  28. // 2 fields (2 embedded): 2 bytes
  29. // Uvarint length of Data.Txs: 4 bytes
  30. // Data.Txs field: 1 byte
  31. MaxOverheadForBlock int64 = 11
  32. )
  33. // Block defines the atomic unit of a Tendermint blockchain.
  34. type Block struct {
  35. mtx tmsync.Mutex
  36. Header `json:"header"`
  37. Data `json:"data"`
  38. Evidence EvidenceData `json:"evidence"`
  39. LastCommit *Commit `json:"last_commit"`
  40. }
  41. // ValidateBasic performs basic validation that doesn't involve state data.
  42. // It checks the internal consistency of the block.
  43. // Further validation is done using state#ValidateBlock.
  44. func (b *Block) ValidateBasic() error {
  45. if b == nil {
  46. return errors.New("nil block")
  47. }
  48. b.mtx.Lock()
  49. defer b.mtx.Unlock()
  50. if err := b.Header.ValidateBasic(); err != nil {
  51. return fmt.Errorf("invalid header: %w", err)
  52. }
  53. // Validate the last commit and its hash.
  54. if b.LastCommit == nil {
  55. return errors.New("nil LastCommit")
  56. }
  57. if err := b.LastCommit.ValidateBasic(); err != nil {
  58. return fmt.Errorf("wrong LastCommit: %v", err)
  59. }
  60. if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
  61. return fmt.Errorf("wrong Header.LastCommitHash. Expected %v, got %v",
  62. b.LastCommit.Hash(),
  63. b.LastCommitHash,
  64. )
  65. }
  66. // NOTE: b.Data.Txs may be nil, but b.Data.Hash() still works fine.
  67. if !bytes.Equal(b.DataHash, b.Data.Hash()) {
  68. return fmt.Errorf(
  69. "wrong Header.DataHash. Expected %v, got %v",
  70. b.Data.Hash(),
  71. b.DataHash,
  72. )
  73. }
  74. // NOTE: b.Evidence.Evidence may be nil, but we're just looping.
  75. for i, ev := range b.Evidence.Evidence {
  76. switch ev.(type) {
  77. case *ConflictingHeadersEvidence:
  78. // ConflictingHeadersEvidence must be broken up in pieces and never
  79. // committed as a single piece.
  80. return fmt.Errorf("found ConflictingHeadersEvidence (#%d)", i)
  81. case *PotentialAmnesiaEvidence:
  82. // PotentialAmnesiaEvidence does not contribute to anything on its own, so
  83. // reject it as well.
  84. return fmt.Errorf("found PotentialAmnesiaEvidence (#%d)", i)
  85. }
  86. if err := ev.ValidateBasic(); err != nil {
  87. return fmt.Errorf("invalid evidence (#%d): %v", i, err)
  88. }
  89. }
  90. if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
  91. return fmt.Errorf("wrong Header.EvidenceHash. Expected %v, got %v",
  92. b.EvidenceHash,
  93. b.Evidence.Hash(),
  94. )
  95. }
  96. return nil
  97. }
  98. // fillHeader fills in any remaining header fields that are a function of the block data
  99. func (b *Block) fillHeader() {
  100. if b.LastCommitHash == nil {
  101. b.LastCommitHash = b.LastCommit.Hash()
  102. }
  103. if b.DataHash == nil {
  104. b.DataHash = b.Data.Hash()
  105. }
  106. if b.EvidenceHash == nil {
  107. b.EvidenceHash = b.Evidence.Hash()
  108. }
  109. }
  110. // Hash computes and returns the block hash.
  111. // If the block is incomplete, block hash is nil for safety.
  112. func (b *Block) Hash() tmbytes.HexBytes {
  113. if b == nil {
  114. return nil
  115. }
  116. b.mtx.Lock()
  117. defer b.mtx.Unlock()
  118. if b.LastCommit == nil {
  119. return nil
  120. }
  121. b.fillHeader()
  122. return b.Header.Hash()
  123. }
  124. // MakePartSet returns a PartSet containing parts of a serialized block.
  125. // This is the form in which the block is gossipped to peers.
  126. // CONTRACT: partSize is greater than zero.
  127. func (b *Block) MakePartSet(partSize uint32) *PartSet {
  128. if b == nil {
  129. return nil
  130. }
  131. b.mtx.Lock()
  132. defer b.mtx.Unlock()
  133. pbb, err := b.ToProto()
  134. if err != nil {
  135. panic(err)
  136. }
  137. bz, err := proto.Marshal(pbb)
  138. if err != nil {
  139. panic(err)
  140. }
  141. return NewPartSetFromData(bz, partSize)
  142. }
  143. // HashesTo is a convenience function that checks if a block hashes to the given argument.
  144. // Returns false if the block is nil or the hash is empty.
  145. func (b *Block) HashesTo(hash []byte) bool {
  146. if len(hash) == 0 {
  147. return false
  148. }
  149. if b == nil {
  150. return false
  151. }
  152. return bytes.Equal(b.Hash(), hash)
  153. }
  154. // Size returns size of the block in bytes.
  155. func (b *Block) Size() int {
  156. pbb, err := b.ToProto()
  157. if err != nil {
  158. return 0
  159. }
  160. return pbb.Size()
  161. }
  162. // String returns a string representation of the block
  163. //
  164. // See StringIndented.
  165. func (b *Block) String() string {
  166. return b.StringIndented("")
  167. }
  168. // StringIndented returns an indented String.
  169. //
  170. // Header
  171. // Data
  172. // Evidence
  173. // LastCommit
  174. // Hash
  175. func (b *Block) StringIndented(indent string) string {
  176. if b == nil {
  177. return "nil-Block"
  178. }
  179. return fmt.Sprintf(`Block{
  180. %s %v
  181. %s %v
  182. %s %v
  183. %s %v
  184. %s}#%v`,
  185. indent, b.Header.StringIndented(indent+" "),
  186. indent, b.Data.StringIndented(indent+" "),
  187. indent, b.Evidence.StringIndented(indent+" "),
  188. indent, b.LastCommit.StringIndented(indent+" "),
  189. indent, b.Hash())
  190. }
  191. // StringShort returns a shortened string representation of the block.
  192. func (b *Block) StringShort() string {
  193. if b == nil {
  194. return "nil-Block"
  195. }
  196. return fmt.Sprintf("Block#%X", b.Hash())
  197. }
  198. // ToProto converts Block to protobuf
  199. func (b *Block) ToProto() (*tmproto.Block, error) {
  200. if b == nil {
  201. return nil, errors.New("nil Block")
  202. }
  203. pb := new(tmproto.Block)
  204. pb.Header = *b.Header.ToProto()
  205. pb.LastCommit = b.LastCommit.ToProto()
  206. pb.Data = b.Data.ToProto()
  207. protoEvidence, err := b.Evidence.ToProto()
  208. if err != nil {
  209. return nil, err
  210. }
  211. pb.Evidence = *protoEvidence
  212. return pb, nil
  213. }
  214. // FromProto sets a protobuf Block to the given pointer.
  215. // It returns an error if the block is invalid.
  216. func BlockFromProto(bp *tmproto.Block) (*Block, error) {
  217. if bp == nil {
  218. return nil, errors.New("nil block")
  219. }
  220. b := new(Block)
  221. h, err := HeaderFromProto(&bp.Header)
  222. if err != nil {
  223. return nil, err
  224. }
  225. b.Header = h
  226. data, err := DataFromProto(&bp.Data)
  227. if err != nil {
  228. return nil, err
  229. }
  230. b.Data = data
  231. b.Evidence.FromProto(&bp.Evidence)
  232. if bp.LastCommit != nil {
  233. lc, err := CommitFromProto(bp.LastCommit)
  234. if err != nil {
  235. return nil, err
  236. }
  237. b.LastCommit = lc
  238. }
  239. return b, b.ValidateBasic()
  240. }
  241. //-----------------------------------------------------------------------------
  242. // MaxDataBytes returns the maximum size of block's data.
  243. //
  244. // XXX: Panics on negative result.
  245. func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
  246. maxDataBytes := maxBytes -
  247. MaxOverheadForBlock -
  248. MaxHeaderBytes -
  249. int64(valsCount)*MaxVoteBytes -
  250. int64(evidenceCount)*MaxEvidenceBytes
  251. if maxDataBytes < 0 {
  252. panic(fmt.Sprintf(
  253. "Negative MaxDataBytes. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  254. maxBytes,
  255. -(maxDataBytes - maxBytes),
  256. ))
  257. }
  258. return maxDataBytes
  259. }
  260. // MaxDataBytesUnknownEvidence returns the maximum size of block's data when
  261. // evidence count is unknown. MaxEvidencePerBlock will be used for the size
  262. // of evidence.
  263. //
  264. // XXX: Panics on negative result.
  265. func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int, maxNumEvidence uint32) int64 {
  266. maxEvidenceBytes := int64(maxNumEvidence) * MaxEvidenceBytes
  267. maxDataBytes := maxBytes -
  268. MaxOverheadForBlock -
  269. MaxHeaderBytes -
  270. int64(valsCount)*MaxVoteBytes -
  271. maxEvidenceBytes
  272. if maxDataBytes < 0 {
  273. panic(fmt.Sprintf(
  274. "Negative MaxDataBytesUnknownEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  275. maxBytes,
  276. -(maxDataBytes - maxBytes),
  277. ))
  278. }
  279. return maxDataBytes
  280. }
  281. //-----------------------------------------------------------------------------
  282. // Header defines the structure of a Tendermint block header.
  283. // NOTE: changes to the Header should be duplicated in:
  284. // - header.Hash()
  285. // - abci.Header
  286. // - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md
  287. type Header struct {
  288. // basic block info
  289. Version tmversion.Consensus `json:"version"`
  290. ChainID string `json:"chain_id"`
  291. Height int64 `json:"height"`
  292. Time time.Time `json:"time"`
  293. // prev block info
  294. LastBlockID BlockID `json:"last_block_id"`
  295. // hashes of block data
  296. LastCommitHash tmbytes.HexBytes `json:"last_commit_hash"` // commit from validators from the last block
  297. DataHash tmbytes.HexBytes `json:"data_hash"` // transactions
  298. // hashes from the app output from the prev block
  299. ValidatorsHash tmbytes.HexBytes `json:"validators_hash"` // validators for the current block
  300. NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"` // validators for the next block
  301. ConsensusHash tmbytes.HexBytes `json:"consensus_hash"` // consensus params for current block
  302. AppHash tmbytes.HexBytes `json:"app_hash"` // state after txs from the previous block
  303. // root hash of all results from the txs from the previous block
  304. LastResultsHash tmbytes.HexBytes `json:"last_results_hash"`
  305. // consensus info
  306. EvidenceHash tmbytes.HexBytes `json:"evidence_hash"` // evidence included in the block
  307. ProposerAddress Address `json:"proposer_address"` // original proposer of the block
  308. }
  309. // Populate the Header with state-derived data.
  310. // Call this after MakeBlock to complete the Header.
  311. func (h *Header) Populate(
  312. version tmversion.Consensus, chainID string,
  313. timestamp time.Time, lastBlockID BlockID,
  314. valHash, nextValHash []byte,
  315. consensusHash, appHash, lastResultsHash []byte,
  316. proposerAddress Address,
  317. ) {
  318. h.Version = version
  319. h.ChainID = chainID
  320. h.Time = timestamp
  321. h.LastBlockID = lastBlockID
  322. h.ValidatorsHash = valHash
  323. h.NextValidatorsHash = nextValHash
  324. h.ConsensusHash = consensusHash
  325. h.AppHash = appHash
  326. h.LastResultsHash = lastResultsHash
  327. h.ProposerAddress = proposerAddress
  328. }
  329. // ValidateBasic performs stateless validation on a Header returning an error
  330. // if any validation fails.
  331. //
  332. // NOTE: Timestamp validation is subtle and handled elsewhere.
  333. func (h Header) ValidateBasic() error {
  334. if len(h.ChainID) > MaxChainIDLen {
  335. return fmt.Errorf("chainID is too long; got: %d, max: %d", len(h.ChainID), MaxChainIDLen)
  336. }
  337. if h.Height < 0 {
  338. return errors.New("negative Height")
  339. } else if h.Height == 0 {
  340. return errors.New("zero Height")
  341. }
  342. if err := h.LastBlockID.ValidateBasic(); err != nil {
  343. return fmt.Errorf("wrong LastBlockID: %w", err)
  344. }
  345. if err := ValidateHash(h.LastCommitHash); err != nil {
  346. return fmt.Errorf("wrong LastCommitHash: %v", err)
  347. }
  348. if err := ValidateHash(h.DataHash); err != nil {
  349. return fmt.Errorf("wrong DataHash: %v", err)
  350. }
  351. if err := ValidateHash(h.EvidenceHash); err != nil {
  352. return fmt.Errorf("wrong EvidenceHash: %v", err)
  353. }
  354. if len(h.ProposerAddress) != crypto.AddressSize {
  355. return fmt.Errorf(
  356. "invalid ProposerAddress length; got: %d, expected: %d",
  357. len(h.ProposerAddress), crypto.AddressSize,
  358. )
  359. }
  360. // Basic validation of hashes related to application data.
  361. // Will validate fully against state in state#ValidateBlock.
  362. if err := ValidateHash(h.ValidatorsHash); err != nil {
  363. return fmt.Errorf("wrong ValidatorsHash: %v", err)
  364. }
  365. if err := ValidateHash(h.NextValidatorsHash); err != nil {
  366. return fmt.Errorf("wrong NextValidatorsHash: %v", err)
  367. }
  368. if err := ValidateHash(h.ConsensusHash); err != nil {
  369. return fmt.Errorf("wrong ConsensusHash: %v", err)
  370. }
  371. // NOTE: AppHash is arbitrary length
  372. if err := ValidateHash(h.LastResultsHash); err != nil {
  373. return fmt.Errorf("wrong LastResultsHash: %v", err)
  374. }
  375. return nil
  376. }
  377. // Hash returns the hash of the header.
  378. // It computes a Merkle tree from the header fields
  379. // ordered as they appear in the Header.
  380. // Returns nil if ValidatorHash is missing,
  381. // since a Header is not valid unless there is
  382. // a ValidatorsHash (corresponding to the validator set).
  383. func (h *Header) Hash() tmbytes.HexBytes {
  384. if h == nil || len(h.ValidatorsHash) == 0 {
  385. return nil
  386. }
  387. hbz, err := h.Version.Marshal()
  388. if err != nil {
  389. return nil
  390. }
  391. pbt, err := gogotypes.StdTimeMarshal(h.Time)
  392. if err != nil {
  393. return nil
  394. }
  395. pbbi := h.LastBlockID.ToProto()
  396. bzbi, err := pbbi.Marshal()
  397. if err != nil {
  398. return nil
  399. }
  400. return merkle.HashFromByteSlices([][]byte{
  401. hbz,
  402. cdcEncode(h.ChainID),
  403. cdcEncode(h.Height),
  404. pbt,
  405. bzbi,
  406. cdcEncode(h.LastCommitHash),
  407. cdcEncode(h.DataHash),
  408. cdcEncode(h.ValidatorsHash),
  409. cdcEncode(h.NextValidatorsHash),
  410. cdcEncode(h.ConsensusHash),
  411. cdcEncode(h.AppHash),
  412. cdcEncode(h.LastResultsHash),
  413. cdcEncode(h.EvidenceHash),
  414. cdcEncode(h.ProposerAddress),
  415. })
  416. }
  417. // StringIndented returns an indented string representation of the header.
  418. func (h *Header) StringIndented(indent string) string {
  419. if h == nil {
  420. return "nil-Header"
  421. }
  422. return fmt.Sprintf(`Header{
  423. %s Version: %v
  424. %s ChainID: %v
  425. %s Height: %v
  426. %s Time: %v
  427. %s LastBlockID: %v
  428. %s LastCommit: %v
  429. %s Data: %v
  430. %s Validators: %v
  431. %s NextValidators: %v
  432. %s App: %v
  433. %s Consensus: %v
  434. %s Results: %v
  435. %s Evidence: %v
  436. %s Proposer: %v
  437. %s}#%v`,
  438. indent, h.Version,
  439. indent, h.ChainID,
  440. indent, h.Height,
  441. indent, h.Time,
  442. indent, h.LastBlockID,
  443. indent, h.LastCommitHash,
  444. indent, h.DataHash,
  445. indent, h.ValidatorsHash,
  446. indent, h.NextValidatorsHash,
  447. indent, h.AppHash,
  448. indent, h.ConsensusHash,
  449. indent, h.LastResultsHash,
  450. indent, h.EvidenceHash,
  451. indent, h.ProposerAddress,
  452. indent, h.Hash())
  453. }
  454. // ToProto converts Header to protobuf
  455. func (h *Header) ToProto() *tmproto.Header {
  456. if h == nil {
  457. return nil
  458. }
  459. return &tmproto.Header{
  460. Version: h.Version,
  461. ChainID: h.ChainID,
  462. Height: h.Height,
  463. Time: h.Time,
  464. LastBlockId: h.LastBlockID.ToProto(),
  465. ValidatorsHash: h.ValidatorsHash,
  466. NextValidatorsHash: h.NextValidatorsHash,
  467. ConsensusHash: h.ConsensusHash,
  468. AppHash: h.AppHash,
  469. DataHash: h.DataHash,
  470. EvidenceHash: h.EvidenceHash,
  471. LastResultsHash: h.LastResultsHash,
  472. LastCommitHash: h.LastCommitHash,
  473. ProposerAddress: h.ProposerAddress,
  474. }
  475. }
  476. // FromProto sets a protobuf Header to the given pointer.
  477. // It returns an error if the header is invalid.
  478. func HeaderFromProto(ph *tmproto.Header) (Header, error) {
  479. if ph == nil {
  480. return Header{}, errors.New("nil Header")
  481. }
  482. h := new(Header)
  483. bi, err := BlockIDFromProto(&ph.LastBlockId)
  484. if err != nil {
  485. return Header{}, err
  486. }
  487. h.Version = ph.Version
  488. h.ChainID = ph.ChainID
  489. h.Height = ph.Height
  490. h.Time = ph.Time
  491. h.Height = ph.Height
  492. h.LastBlockID = *bi
  493. h.ValidatorsHash = ph.ValidatorsHash
  494. h.NextValidatorsHash = ph.NextValidatorsHash
  495. h.ConsensusHash = ph.ConsensusHash
  496. h.AppHash = ph.AppHash
  497. h.DataHash = ph.DataHash
  498. h.EvidenceHash = ph.EvidenceHash
  499. h.LastResultsHash = ph.LastResultsHash
  500. h.LastCommitHash = ph.LastCommitHash
  501. h.ProposerAddress = ph.ProposerAddress
  502. return *h, h.ValidateBasic()
  503. }
  504. //-------------------------------------
  505. // BlockIDFlag indicates which BlockID the signature is for.
  506. type BlockIDFlag byte
  507. const (
  508. // BlockIDFlagAbsent - no vote was received from a validator.
  509. BlockIDFlagAbsent BlockIDFlag = iota + 1
  510. // BlockIDFlagCommit - voted for the Commit.BlockID.
  511. BlockIDFlagCommit
  512. // BlockIDFlagNil - voted for nil.
  513. BlockIDFlagNil
  514. )
  515. // CommitSig is a part of the Vote included in a Commit.
  516. type CommitSig struct {
  517. BlockIDFlag BlockIDFlag `json:"block_id_flag"`
  518. ValidatorAddress Address `json:"validator_address"`
  519. Timestamp time.Time `json:"timestamp"`
  520. Signature []byte `json:"signature"`
  521. }
  522. // NewCommitSigForBlock returns new CommitSig with BlockIDFlagCommit.
  523. func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig {
  524. return CommitSig{
  525. BlockIDFlag: BlockIDFlagCommit,
  526. ValidatorAddress: valAddr,
  527. Timestamp: ts,
  528. Signature: signature,
  529. }
  530. }
  531. // ForBlock returns true if CommitSig is for the block.
  532. func (cs CommitSig) ForBlock() bool {
  533. return cs.BlockIDFlag == BlockIDFlagCommit
  534. }
  535. // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other
  536. // fields are all empty.
  537. func NewCommitSigAbsent() CommitSig {
  538. return CommitSig{
  539. BlockIDFlag: BlockIDFlagAbsent,
  540. }
  541. }
  542. // Absent returns true if CommitSig is absent.
  543. func (cs CommitSig) Absent() bool {
  544. return cs.BlockIDFlag == BlockIDFlagAbsent
  545. }
  546. // CommitSig returns a string representation of CommitSig.
  547. //
  548. // 1. first 6 bytes of signature
  549. // 2. first 6 bytes of validator address
  550. // 3. block ID flag
  551. // 4. timestamp
  552. func (cs CommitSig) String() string {
  553. return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}",
  554. tmbytes.Fingerprint(cs.Signature),
  555. tmbytes.Fingerprint(cs.ValidatorAddress),
  556. cs.BlockIDFlag,
  557. CanonicalTime(cs.Timestamp))
  558. }
  559. // BlockID returns the Commit's BlockID if CommitSig indicates signing,
  560. // otherwise - empty BlockID.
  561. func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID {
  562. var blockID BlockID
  563. switch cs.BlockIDFlag {
  564. case BlockIDFlagAbsent:
  565. blockID = BlockID{}
  566. case BlockIDFlagCommit:
  567. blockID = commitBlockID
  568. case BlockIDFlagNil:
  569. blockID = BlockID{}
  570. default:
  571. panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag))
  572. }
  573. return blockID
  574. }
  575. // ValidateBasic performs basic validation.
  576. func (cs CommitSig) ValidateBasic() error {
  577. switch cs.BlockIDFlag {
  578. case BlockIDFlagAbsent:
  579. case BlockIDFlagCommit:
  580. case BlockIDFlagNil:
  581. default:
  582. return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag)
  583. }
  584. switch cs.BlockIDFlag {
  585. case BlockIDFlagAbsent:
  586. if len(cs.ValidatorAddress) != 0 {
  587. return errors.New("validator address is present")
  588. }
  589. if !cs.Timestamp.IsZero() {
  590. return errors.New("time is present")
  591. }
  592. if len(cs.Signature) != 0 {
  593. return errors.New("signature is present")
  594. }
  595. default:
  596. if len(cs.ValidatorAddress) != crypto.AddressSize {
  597. return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
  598. crypto.AddressSize,
  599. len(cs.ValidatorAddress),
  600. )
  601. }
  602. // NOTE: Timestamp validation is subtle and handled elsewhere.
  603. if len(cs.Signature) == 0 {
  604. return errors.New("signature is missing")
  605. }
  606. if len(cs.Signature) > MaxSignatureSize {
  607. return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
  608. }
  609. }
  610. return nil
  611. }
  612. // ToProto converts CommitSig to protobuf
  613. func (cs *CommitSig) ToProto() *tmproto.CommitSig {
  614. if cs == nil {
  615. return nil
  616. }
  617. return &tmproto.CommitSig{
  618. BlockIdFlag: tmproto.BlockIDFlag(cs.BlockIDFlag),
  619. ValidatorAddress: cs.ValidatorAddress,
  620. Timestamp: cs.Timestamp,
  621. Signature: cs.Signature,
  622. }
  623. }
  624. // FromProto sets a protobuf CommitSig to the given pointer.
  625. // It returns an error if the CommitSig is invalid.
  626. func (cs *CommitSig) FromProto(csp tmproto.CommitSig) error {
  627. cs.BlockIDFlag = BlockIDFlag(csp.BlockIdFlag)
  628. cs.ValidatorAddress = csp.ValidatorAddress
  629. cs.Timestamp = csp.Timestamp
  630. cs.Signature = csp.Signature
  631. return cs.ValidateBasic()
  632. }
  633. //-------------------------------------
  634. // Commit contains the evidence that a block was committed by a set of validators.
  635. // NOTE: Commit is empty for height 1, but never nil.
  636. type Commit struct {
  637. // NOTE: The signatures are in order of address to preserve the bonded
  638. // ValidatorSet order.
  639. // Any peer with a block can gossip signatures by index with a peer without
  640. // recalculating the active ValidatorSet.
  641. Height int64 `json:"height"`
  642. Round int32 `json:"round"`
  643. BlockID BlockID `json:"block_id"`
  644. Signatures []CommitSig `json:"signatures"`
  645. // Memoized in first call to corresponding method.
  646. // NOTE: can't memoize in constructor because constructor isn't used for
  647. // unmarshaling.
  648. hash tmbytes.HexBytes
  649. bitArray *bits.BitArray
  650. }
  651. // NewCommit returns a new Commit.
  652. func NewCommit(height int64, round int32, blockID BlockID, commitSigs []CommitSig) *Commit {
  653. return &Commit{
  654. Height: height,
  655. Round: round,
  656. BlockID: blockID,
  657. Signatures: commitSigs,
  658. }
  659. }
  660. // CommitToVoteSet constructs a VoteSet from the Commit and validator set.
  661. // Panics if signatures from the commit can't be added to the voteset.
  662. // Inverse of VoteSet.MakeCommit().
  663. func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet {
  664. voteSet := NewVoteSet(chainID, commit.Height, commit.Round, tmproto.PrecommitType, vals)
  665. for idx, commitSig := range commit.Signatures {
  666. if commitSig.Absent() {
  667. continue // OK, some precommits can be missing.
  668. }
  669. added, err := voteSet.AddVote(commit.GetVote(int32(idx)))
  670. if !added || err != nil {
  671. panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
  672. }
  673. }
  674. return voteSet
  675. }
  676. // GetVote converts the CommitSig for the given valIdx to a Vote.
  677. // Returns nil if the precommit at valIdx is nil.
  678. // Panics if valIdx >= commit.Size().
  679. func (commit *Commit) GetVote(valIdx int32) *Vote {
  680. commitSig := commit.Signatures[valIdx]
  681. return &Vote{
  682. Type: tmproto.PrecommitType,
  683. Height: commit.Height,
  684. Round: commit.Round,
  685. BlockID: commitSig.BlockID(commit.BlockID),
  686. Timestamp: commitSig.Timestamp,
  687. ValidatorAddress: commitSig.ValidatorAddress,
  688. ValidatorIndex: valIdx,
  689. Signature: commitSig.Signature,
  690. }
  691. }
  692. // VoteSignBytes returns the bytes of the Vote corresponding to valIdx for
  693. // signing.
  694. //
  695. // The only unique part is the Timestamp - all other fields signed over are
  696. // otherwise the same for all validators.
  697. //
  698. // Panics if valIdx >= commit.Size().
  699. //
  700. // See VoteSignBytes
  701. func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte {
  702. v := commit.GetVote(valIdx).ToProto()
  703. return VoteSignBytes(chainID, v)
  704. }
  705. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  706. // Implements VoteSetReader.
  707. func (commit *Commit) Type() byte {
  708. return byte(tmproto.PrecommitType)
  709. }
  710. // GetHeight returns height of the commit.
  711. // Implements VoteSetReader.
  712. func (commit *Commit) GetHeight() int64 {
  713. return commit.Height
  714. }
  715. // GetRound returns height of the commit.
  716. // Implements VoteSetReader.
  717. func (commit *Commit) GetRound() int32 {
  718. return commit.Round
  719. }
  720. // Size returns the number of signatures in the commit.
  721. // Implements VoteSetReader.
  722. func (commit *Commit) Size() int {
  723. if commit == nil {
  724. return 0
  725. }
  726. return len(commit.Signatures)
  727. }
  728. // BitArray returns a BitArray of which validators voted for BlockID or nil in this commit.
  729. // Implements VoteSetReader.
  730. func (commit *Commit) BitArray() *bits.BitArray {
  731. if commit.bitArray == nil {
  732. commit.bitArray = bits.NewBitArray(len(commit.Signatures))
  733. for i, commitSig := range commit.Signatures {
  734. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  735. // not just the one with +2/3 !
  736. commit.bitArray.SetIndex(i, !commitSig.Absent())
  737. }
  738. }
  739. return commit.bitArray
  740. }
  741. // GetByIndex returns the vote corresponding to a given validator index.
  742. // Panics if `index >= commit.Size()`.
  743. // Implements VoteSetReader.
  744. func (commit *Commit) GetByIndex(valIdx int32) *Vote {
  745. return commit.GetVote(valIdx)
  746. }
  747. // IsCommit returns true if there is at least one signature.
  748. // Implements VoteSetReader.
  749. func (commit *Commit) IsCommit() bool {
  750. return len(commit.Signatures) != 0
  751. }
  752. // ValidateBasic performs basic validation that doesn't involve state data.
  753. // Does not actually check the cryptographic signatures.
  754. func (commit *Commit) ValidateBasic() error {
  755. if commit.Height < 0 {
  756. return errors.New("negative Height")
  757. }
  758. if commit.Round < 0 {
  759. return errors.New("negative Round")
  760. }
  761. if commit.Height >= 1 {
  762. if commit.BlockID.IsZero() {
  763. return errors.New("commit cannot be for nil block")
  764. }
  765. if len(commit.Signatures) == 0 {
  766. return errors.New("no signatures in commit")
  767. }
  768. for i, commitSig := range commit.Signatures {
  769. if err := commitSig.ValidateBasic(); err != nil {
  770. return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
  771. }
  772. }
  773. }
  774. return nil
  775. }
  776. // Hash returns the hash of the commit
  777. func (commit *Commit) Hash() tmbytes.HexBytes {
  778. if commit == nil {
  779. return nil
  780. }
  781. if commit.hash == nil {
  782. bs := make([][]byte, len(commit.Signatures))
  783. for i, commitSig := range commit.Signatures {
  784. pbcs := commitSig.ToProto()
  785. bz, err := pbcs.Marshal()
  786. if err != nil {
  787. panic(err)
  788. }
  789. bs[i] = bz
  790. }
  791. commit.hash = merkle.HashFromByteSlices(bs)
  792. }
  793. return commit.hash
  794. }
  795. // StringIndented returns a string representation of the commit.
  796. func (commit *Commit) StringIndented(indent string) string {
  797. if commit == nil {
  798. return "nil-Commit"
  799. }
  800. commitSigStrings := make([]string, len(commit.Signatures))
  801. for i, commitSig := range commit.Signatures {
  802. commitSigStrings[i] = commitSig.String()
  803. }
  804. return fmt.Sprintf(`Commit{
  805. %s Height: %d
  806. %s Round: %d
  807. %s BlockID: %v
  808. %s Signatures:
  809. %s %v
  810. %s}#%v`,
  811. indent, commit.Height,
  812. indent, commit.Round,
  813. indent, commit.BlockID,
  814. indent,
  815. indent, strings.Join(commitSigStrings, "\n"+indent+" "),
  816. indent, commit.hash)
  817. }
  818. // ToProto converts Commit to protobuf
  819. func (commit *Commit) ToProto() *tmproto.Commit {
  820. if commit == nil {
  821. return nil
  822. }
  823. c := new(tmproto.Commit)
  824. sigs := make([]tmproto.CommitSig, len(commit.Signatures))
  825. for i := range commit.Signatures {
  826. sigs[i] = *commit.Signatures[i].ToProto()
  827. }
  828. c.Signatures = sigs
  829. c.Height = commit.Height
  830. c.Round = commit.Round
  831. c.BlockID = commit.BlockID.ToProto()
  832. if commit.hash != nil {
  833. c.Hash = commit.hash
  834. }
  835. c.BitArray = commit.bitArray.ToProto()
  836. return c
  837. }
  838. // FromProto sets a protobuf Commit to the given pointer.
  839. // It returns an error if the commit is invalid.
  840. func CommitFromProto(cp *tmproto.Commit) (*Commit, error) {
  841. if cp == nil {
  842. return nil, errors.New("nil Commit")
  843. }
  844. var (
  845. commit = new(Commit)
  846. bitArray *bits.BitArray
  847. )
  848. bi, err := BlockIDFromProto(&cp.BlockID)
  849. if err != nil {
  850. return nil, err
  851. }
  852. bitArray.FromProto(cp.BitArray)
  853. sigs := make([]CommitSig, len(cp.Signatures))
  854. for i := range cp.Signatures {
  855. if err := sigs[i].FromProto(cp.Signatures[i]); err != nil {
  856. return nil, err
  857. }
  858. }
  859. commit.Signatures = sigs
  860. commit.Height = cp.Height
  861. commit.Round = cp.Round
  862. commit.BlockID = *bi
  863. commit.hash = cp.Hash
  864. commit.bitArray = bitArray
  865. return commit, commit.ValidateBasic()
  866. }
  867. //-----------------------------------------------------------------------------
  868. // SignedHeader is a header along with the commits that prove it.
  869. // It is the basis of the light client.
  870. type SignedHeader struct {
  871. *Header `json:"header"`
  872. Commit *Commit `json:"commit"`
  873. }
  874. // ValidateBasic does basic consistency checks and makes sure the header
  875. // and commit are consistent.
  876. //
  877. // NOTE: This does not actually check the cryptographic signatures. Make sure
  878. // to use a Verifier to validate the signatures actually provide a
  879. // significantly strong proof for this header's validity.
  880. func (sh SignedHeader) ValidateBasic(chainID string) error {
  881. if sh.Header == nil {
  882. return errors.New("missing header")
  883. }
  884. if sh.Commit == nil {
  885. return errors.New("missing commit")
  886. }
  887. if err := sh.Header.ValidateBasic(); err != nil {
  888. return fmt.Errorf("invalid header: %w", err)
  889. }
  890. if err := sh.Commit.ValidateBasic(); err != nil {
  891. return fmt.Errorf("invalid commit: %w", err)
  892. }
  893. if sh.ChainID != chainID {
  894. return fmt.Errorf("header belongs to another chain %q, not %q", sh.ChainID, chainID)
  895. }
  896. // Make sure the header is consistent with the commit.
  897. if sh.Commit.Height != sh.Height {
  898. return fmt.Errorf("header and commit height mismatch: %d vs %d", sh.Height, sh.Commit.Height)
  899. }
  900. if hhash, chash := sh.Hash(), sh.Commit.BlockID.Hash; !bytes.Equal(hhash, chash) {
  901. return fmt.Errorf("commit signs block %X, header is block %X", chash, hhash)
  902. }
  903. return nil
  904. }
  905. // String returns a string representation of SignedHeader.
  906. func (sh SignedHeader) String() string {
  907. return sh.StringIndented("")
  908. }
  909. // StringIndented returns an indented string representation of SignedHeader.
  910. //
  911. // Header
  912. // Commit
  913. func (sh SignedHeader) StringIndented(indent string) string {
  914. return fmt.Sprintf(`SignedHeader{
  915. %s %v
  916. %s %v
  917. %s}`,
  918. indent, sh.Header.StringIndented(indent+" "),
  919. indent, sh.Commit.StringIndented(indent+" "),
  920. indent)
  921. }
  922. // ToProto converts SignedHeader to protobuf
  923. func (sh *SignedHeader) ToProto() *tmproto.SignedHeader {
  924. if sh == nil {
  925. return nil
  926. }
  927. psh := new(tmproto.SignedHeader)
  928. if sh.Header != nil {
  929. psh.Header = sh.Header.ToProto()
  930. }
  931. if sh.Commit != nil {
  932. psh.Commit = sh.Commit.ToProto()
  933. }
  934. return psh
  935. }
  936. // FromProto sets a protobuf SignedHeader to the given pointer.
  937. // It returns an error if the hader or the commit is invalid.
  938. func SignedHeaderFromProto(shp *tmproto.SignedHeader) (*SignedHeader, error) {
  939. if shp == nil {
  940. return nil, errors.New("nil SignedHeader")
  941. }
  942. sh := new(SignedHeader)
  943. if shp.Header != nil {
  944. h, err := HeaderFromProto(shp.Header)
  945. if err != nil {
  946. return nil, err
  947. }
  948. sh.Header = &h
  949. }
  950. if shp.Commit != nil {
  951. c, err := CommitFromProto(shp.Commit)
  952. if err != nil {
  953. return nil, err
  954. }
  955. sh.Commit = c
  956. }
  957. return sh, nil
  958. }
  959. //-----------------------------------------------------------------------------
  960. // Data contains the set of transactions included in the block
  961. type Data struct {
  962. // Txs that will be applied by state @ block.Height+1.
  963. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  964. // This means that block.AppHash does not include these txs.
  965. Txs Txs `json:"txs"`
  966. // Volatile
  967. hash tmbytes.HexBytes
  968. }
  969. // Hash returns the hash of the data
  970. func (data *Data) Hash() tmbytes.HexBytes {
  971. if data == nil {
  972. return (Txs{}).Hash()
  973. }
  974. if data.hash == nil {
  975. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  976. }
  977. return data.hash
  978. }
  979. // StringIndented returns an indented string representation of the transactions.
  980. func (data *Data) StringIndented(indent string) string {
  981. if data == nil {
  982. return "nil-Data"
  983. }
  984. txStrings := make([]string, tmmath.MinInt(len(data.Txs), 21))
  985. for i, tx := range data.Txs {
  986. if i == 20 {
  987. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  988. break
  989. }
  990. txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  991. }
  992. return fmt.Sprintf(`Data{
  993. %s %v
  994. %s}#%v`,
  995. indent, strings.Join(txStrings, "\n"+indent+" "),
  996. indent, data.hash)
  997. }
  998. // ToProto converts Data to protobuf
  999. func (data *Data) ToProto() tmproto.Data {
  1000. tp := new(tmproto.Data)
  1001. if len(data.Txs) > 0 {
  1002. txBzs := make([][]byte, len(data.Txs))
  1003. for i := range data.Txs {
  1004. txBzs[i] = data.Txs[i]
  1005. }
  1006. tp.Txs = txBzs
  1007. }
  1008. if data.hash != nil {
  1009. tp.Hash = data.hash
  1010. }
  1011. return *tp
  1012. }
  1013. // DataFromProto takes a protobuf representation of Data &
  1014. // returns the native type.
  1015. func DataFromProto(dp *tmproto.Data) (Data, error) {
  1016. if dp == nil {
  1017. return Data{}, errors.New("nil data")
  1018. }
  1019. data := new(Data)
  1020. if len(dp.Txs) > 0 {
  1021. txBzs := make(Txs, len(dp.Txs))
  1022. for i := range dp.Txs {
  1023. txBzs[i] = Tx(dp.Txs[i])
  1024. }
  1025. data.Txs = txBzs
  1026. } else {
  1027. data.Txs = Txs{}
  1028. }
  1029. data.hash = dp.Hash
  1030. return *data, nil
  1031. }
  1032. //-----------------------------------------------------------------------------
  1033. // EvidenceData contains any evidence of malicious wrong-doing by validators
  1034. type EvidenceData struct {
  1035. Evidence EvidenceList `json:"evidence"`
  1036. // Volatile
  1037. hash tmbytes.HexBytes
  1038. }
  1039. // Hash returns the hash of the data.
  1040. func (data *EvidenceData) Hash() tmbytes.HexBytes {
  1041. if data.hash == nil {
  1042. data.hash = data.Evidence.Hash()
  1043. }
  1044. return data.hash
  1045. }
  1046. // StringIndented returns a string representation of the evidence.
  1047. func (data *EvidenceData) StringIndented(indent string) string {
  1048. if data == nil {
  1049. return "nil-Evidence"
  1050. }
  1051. evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21))
  1052. for i, ev := range data.Evidence {
  1053. if i == 20 {
  1054. evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  1055. break
  1056. }
  1057. evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  1058. }
  1059. return fmt.Sprintf(`EvidenceData{
  1060. %s %v
  1061. %s}#%v`,
  1062. indent, strings.Join(evStrings, "\n"+indent+" "),
  1063. indent, data.hash)
  1064. }
  1065. // ToProto converts EvidenceData to protobuf
  1066. func (data *EvidenceData) ToProto() (*tmproto.EvidenceData, error) {
  1067. if data == nil {
  1068. return nil, errors.New("nil evidence data")
  1069. }
  1070. evi := new(tmproto.EvidenceData)
  1071. eviBzs := make([]tmproto.Evidence, len(data.Evidence))
  1072. for i := range data.Evidence {
  1073. protoEvi, err := EvidenceToProto(data.Evidence[i])
  1074. if err != nil {
  1075. return nil, err
  1076. }
  1077. eviBzs[i] = *protoEvi
  1078. }
  1079. evi.Evidence = eviBzs
  1080. if data.hash != nil {
  1081. evi.Hash = data.hash
  1082. }
  1083. return evi, nil
  1084. }
  1085. // FromProto sets a protobuf EvidenceData to the given pointer.
  1086. func (data *EvidenceData) FromProto(eviData *tmproto.EvidenceData) error {
  1087. if eviData == nil {
  1088. return errors.New("nil evidenceData")
  1089. }
  1090. eviBzs := make(EvidenceList, len(eviData.Evidence))
  1091. for i := range eviData.Evidence {
  1092. evi, err := EvidenceFromProto(&eviData.Evidence[i])
  1093. if err != nil {
  1094. return err
  1095. }
  1096. eviBzs[i] = evi
  1097. }
  1098. data.Evidence = eviBzs
  1099. data.hash = eviData.GetHash()
  1100. return nil
  1101. }
  1102. //--------------------------------------------------------------------------------
  1103. // BlockID
  1104. type BlockID struct {
  1105. Hash tmbytes.HexBytes `json:"hash"`
  1106. PartSetHeader PartSetHeader `json:"parts"`
  1107. }
  1108. // Equals returns true if the BlockID matches the given BlockID
  1109. func (blockID BlockID) Equals(other BlockID) bool {
  1110. return bytes.Equal(blockID.Hash, other.Hash) &&
  1111. blockID.PartSetHeader.Equals(other.PartSetHeader)
  1112. }
  1113. // Key returns a machine-readable string representation of the BlockID
  1114. func (blockID BlockID) Key() string {
  1115. pbph := blockID.PartSetHeader.ToProto()
  1116. bz, err := pbph.Marshal()
  1117. if err != nil {
  1118. panic(err)
  1119. }
  1120. return string(blockID.Hash) + string(bz)
  1121. }
  1122. // ValidateBasic performs basic validation.
  1123. func (blockID BlockID) ValidateBasic() error {
  1124. // Hash can be empty in case of POLBlockID in Proposal.
  1125. if err := ValidateHash(blockID.Hash); err != nil {
  1126. return fmt.Errorf("wrong Hash")
  1127. }
  1128. if err := blockID.PartSetHeader.ValidateBasic(); err != nil {
  1129. return fmt.Errorf("wrong PartSetHeader: %v", err)
  1130. }
  1131. return nil
  1132. }
  1133. // IsZero returns true if this is the BlockID of a nil block.
  1134. func (blockID BlockID) IsZero() bool {
  1135. return len(blockID.Hash) == 0 &&
  1136. blockID.PartSetHeader.IsZero()
  1137. }
  1138. // IsComplete returns true if this is a valid BlockID of a non-nil block.
  1139. func (blockID BlockID) IsComplete() bool {
  1140. return len(blockID.Hash) == tmhash.Size &&
  1141. blockID.PartSetHeader.Total > 0 &&
  1142. len(blockID.PartSetHeader.Hash) == tmhash.Size
  1143. }
  1144. // String returns a human readable string representation of the BlockID.
  1145. //
  1146. // 1. hash
  1147. // 2. part set header
  1148. //
  1149. // See PartSetHeader#String
  1150. func (blockID BlockID) String() string {
  1151. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartSetHeader)
  1152. }
  1153. // ToProto converts BlockID to protobuf
  1154. func (blockID *BlockID) ToProto() tmproto.BlockID {
  1155. if blockID == nil {
  1156. return tmproto.BlockID{}
  1157. }
  1158. return tmproto.BlockID{
  1159. Hash: blockID.Hash,
  1160. PartSetHeader: blockID.PartSetHeader.ToProto(),
  1161. }
  1162. }
  1163. // FromProto sets a protobuf BlockID to the given pointer.
  1164. // It returns an error if the block id is invalid.
  1165. func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) {
  1166. if bID == nil {
  1167. return nil, errors.New("nil BlockID")
  1168. }
  1169. blockID := new(BlockID)
  1170. ph, err := PartSetHeaderFromProto(&bID.PartSetHeader)
  1171. if err != nil {
  1172. return nil, err
  1173. }
  1174. blockID.PartSetHeader = *ph
  1175. blockID.Hash = bID.Hash
  1176. return blockID, blockID.ValidateBasic()
  1177. }