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.

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