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.

941 lines
27 KiB

max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
max-bytes PR follow-up (#2318) * ReapMaxTxs: return all txs if max is negative this mirrors ReapMaxBytes behavior See https://github.com/tendermint/tendermint/pull/2184#discussion_r214439950 * increase MaxAminoOverheadForBlock tested with: ``` func TestMaxAminoOverheadForBlock(t *testing.T) { maxChainID := "" for i := 0; i < MaxChainIDLen; i++ { maxChainID += "𠜎" } h := Header{ ChainID: maxChainID, Height: 10, Time: time.Now().UTC(), NumTxs: 100, TotalTxs: 200, LastBlockID: makeBlockID(make([]byte, 20), 300, make([]byte, 20)), LastCommitHash: tmhash.Sum([]byte("last_commit_hash")), DataHash: tmhash.Sum([]byte("data_hash")), ValidatorsHash: tmhash.Sum([]byte("validators_hash")), NextValidatorsHash: tmhash.Sum([]byte("next_validators_hash")), ConsensusHash: tmhash.Sum([]byte("consensus_hash")), AppHash: tmhash.Sum([]byte("app_hash")), LastResultsHash: tmhash.Sum([]byte("last_results_hash")), EvidenceHash: tmhash.Sum([]byte("evidence_hash")), ProposerAddress: tmhash.Sum([]byte("proposer_address")), } b := Block{ Header: h, Data: Data{Txs: makeTxs(10000, 100)}, Evidence: EvidenceData{}, LastCommit: &Commit{}, } bz, err := cdc.MarshalBinary(b) require.NoError(t, err) assert.Equal(t, MaxHeaderBytes+MaxAminoOverheadForBlock-2, len(bz)-1000000-20000-1) } ``` * fix MaxYYY constants calculation by using math.MaxInt64 See https://github.com/tendermint/tendermint/pull/2184#discussion_r214444244 * pass mempool filter as an option See https://github.com/tendermint/tendermint/pull/2184#discussion_r214445869 * fixes after Dev's comments
6 years ago
6 years ago
10 years ago
10 years ago
6 years ago
6 years ago
10 years ago
lite2: light client with weak subjectivity (#3989) Refs #1771 ADR: https://github.com/tendermint/tendermint/blob/master/docs/architecture/adr-044-lite-client-with-weak-subjectivity.md ## Commits: * add Verifier and VerifyCommitTrusting * add two more checks make trustLevel an option * float32 for trustLevel * check newHeader time * started writing lite Client * unify Verify methods * ensure h2.Header.bfttime < h1.Header.bfttime + tp * move trust checks into Verify function * add more comments * more docs * started writing tests * unbonding period failures * tests are green * export ErrNewHeaderTooFarIntoFuture * make golangci happy * test for non-adjusted headers * more precision * providers and stores * VerifyHeader and VerifyHeaderAtHeight funcs * fix compile errors * remove lastVerifiedHeight, persist new trusted header * sequential verification * remove TrustedStore option * started writing tests for light client * cover basic cases for linear verification * bisection tests PASS * rename BisectingVerification to SkippingVerification * refactor the code * add TrustedHeader method * consolidate sequential verification tests * consolidate skipping verification tests * rename trustedVals to trustedNextVals * start writing docs * ValidateTrustLevel func and ErrOldHeaderExpired error * AutoClient and example tests * fix errors * update doc * remove ErrNewHeaderTooFarIntoFuture This check is unnecessary given existing a) ErrOldHeaderExpired b) h2.Time > now checks. * return an error if we're at more recent height * add comments * add LastSignedHeaderHeight method to Store I think it's fine if Store tracks last height * copy over proxy from old lite package * make TrustedHeader return latest if height=0 * modify LastSignedHeaderHeight to return an error if no headers exist * copy over proxy impl * refactor proxy and start http lite client * Tx and BlockchainInfo methods * Block method * commit method * code compiles again * lite client compiles * extract updateLiteClientIfNeededTo func * move final parts * add placeholder for tests * force usage of lite http client in proxy * comment out query tests for now * explicitly mention tp: trusting period * verify nextVals in VerifyHeader * refactor bisection * move the NextValidatorsHash check into updateTrustedHeaderAndVals + update the comment * add ConsensusParams method to RPC client * add ConsensusParams to rpc/mock/client * change trustLevel type to a new cmn.Fraction type + update SkippingVerification comment * stress out trustLevel is only used for non-adjusted headers * fixes after Fede's review Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com> * compare newHeader with a header from an alternative provider * save pivot header Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r349122824 * check header can still be trusted in TrustedHeader Refs https://github.com/tendermint/tendermint/pull/3989#discussion_r349101424 * lite: update Validators and Block endpoints - Block no longer contains BlockMeta - Validators now accept two additional params: page and perPage * make linter happy
5 years ago
10 years ago
  1. package types
  2. import (
  3. "bytes"
  4. "fmt"
  5. "strings"
  6. "sync"
  7. "time"
  8. "github.com/pkg/errors"
  9. "github.com/tendermint/tendermint/crypto"
  10. "github.com/tendermint/tendermint/crypto/merkle"
  11. "github.com/tendermint/tendermint/crypto/tmhash"
  12. "github.com/tendermint/tendermint/libs/bits"
  13. tmbytes "github.com/tendermint/tendermint/libs/bytes"
  14. tmmath "github.com/tendermint/tendermint/libs/math"
  15. "github.com/tendermint/tendermint/version"
  16. )
  17. const (
  18. // MaxHeaderBytes is a maximum header size (including amino overhead).
  19. MaxHeaderBytes int64 = 632
  20. // MaxAminoOverheadForBlock - maximum amino overhead to encode a block (up to
  21. // MaxBlockSizeBytes in size) not including it's parts except Data.
  22. // This means it also excludes the overhead for individual transactions.
  23. // To compute individual transactions' overhead use types.ComputeAminoOverhead(tx types.Tx, fieldNum int).
  24. //
  25. // Uvarint length of MaxBlockSizeBytes: 4 bytes
  26. // 2 fields (2 embedded): 2 bytes
  27. // Uvarint length of Data.Txs: 4 bytes
  28. // Data.Txs field: 1 byte
  29. MaxAminoOverheadForBlock int64 = 11
  30. )
  31. // Block defines the atomic unit of a Tendermint blockchain.
  32. type Block struct {
  33. mtx sync.Mutex
  34. Header `json:"header"`
  35. Data `json:"data"`
  36. Evidence EvidenceData `json:"evidence"`
  37. LastCommit *Commit `json:"last_commit"`
  38. }
  39. // ValidateBasic performs basic validation that doesn't involve state data.
  40. // It checks the internal consistency of the block.
  41. // Further validation is done using state#ValidateBlock.
  42. func (b *Block) ValidateBasic() error {
  43. if b == nil {
  44. return errors.New("nil block")
  45. }
  46. b.mtx.Lock()
  47. defer b.mtx.Unlock()
  48. if len(b.ChainID) > MaxChainIDLen {
  49. return fmt.Errorf("chainID is too long. Max is %d, got %d", MaxChainIDLen, len(b.ChainID))
  50. }
  51. if b.Height < 0 {
  52. return errors.New("negative Header.Height")
  53. } else if b.Height == 0 {
  54. return errors.New("zero Header.Height")
  55. }
  56. // NOTE: Timestamp validation is subtle and handled elsewhere.
  57. if err := b.LastBlockID.ValidateBasic(); err != nil {
  58. return fmt.Errorf("wrong Header.LastBlockID: %v", err)
  59. }
  60. // Validate the last commit and its hash.
  61. if b.Header.Height > 1 {
  62. if b.LastCommit == nil {
  63. return errors.New("nil LastCommit")
  64. }
  65. if err := b.LastCommit.ValidateBasic(); err != nil {
  66. return fmt.Errorf("wrong LastCommit: %v", err)
  67. }
  68. }
  69. if err := ValidateHash(b.LastCommitHash); err != nil {
  70. return fmt.Errorf("wrong Header.LastCommitHash: %v", err)
  71. }
  72. if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
  73. return fmt.Errorf("wrong Header.LastCommitHash. Expected %v, got %v",
  74. b.LastCommit.Hash(),
  75. b.LastCommitHash,
  76. )
  77. }
  78. // Validate the hash of the transactions.
  79. // NOTE: b.Data.Txs may be nil, but b.Data.Hash()
  80. // still works fine
  81. if err := ValidateHash(b.DataHash); err != nil {
  82. return fmt.Errorf("wrong Header.DataHash: %v", err)
  83. }
  84. if !bytes.Equal(b.DataHash, b.Data.Hash()) {
  85. return fmt.Errorf(
  86. "wrong Header.DataHash. Expected %v, got %v",
  87. b.Data.Hash(),
  88. b.DataHash,
  89. )
  90. }
  91. // Basic validation of hashes related to application data.
  92. // Will validate fully against state in state#ValidateBlock.
  93. if err := ValidateHash(b.ValidatorsHash); err != nil {
  94. return fmt.Errorf("wrong Header.ValidatorsHash: %v", err)
  95. }
  96. if err := ValidateHash(b.NextValidatorsHash); err != nil {
  97. return fmt.Errorf("wrong Header.NextValidatorsHash: %v", err)
  98. }
  99. if err := ValidateHash(b.ConsensusHash); err != nil {
  100. return fmt.Errorf("wrong Header.ConsensusHash: %v", err)
  101. }
  102. // NOTE: AppHash is arbitrary length
  103. if err := ValidateHash(b.LastResultsHash); err != nil {
  104. return fmt.Errorf("wrong Header.LastResultsHash: %v", err)
  105. }
  106. // Validate evidence and its hash.
  107. if err := ValidateHash(b.EvidenceHash); err != nil {
  108. return fmt.Errorf("wrong Header.EvidenceHash: %v", err)
  109. }
  110. // NOTE: b.Evidence.Evidence may be nil, but we're just looping.
  111. for i, ev := range b.Evidence.Evidence {
  112. if err := ev.ValidateBasic(); err != nil {
  113. return fmt.Errorf("invalid evidence (#%d): %v", i, err)
  114. }
  115. }
  116. if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
  117. return fmt.Errorf("wrong Header.EvidenceHash. Expected %v, got %v",
  118. b.EvidenceHash,
  119. b.Evidence.Hash(),
  120. )
  121. }
  122. if len(b.ProposerAddress) != crypto.AddressSize {
  123. return fmt.Errorf("expected len(Header.ProposerAddress) to be %d, got %d",
  124. crypto.AddressSize, len(b.ProposerAddress))
  125. }
  126. return nil
  127. }
  128. // fillHeader fills in any remaining header fields that are a function of the block data
  129. func (b *Block) fillHeader() {
  130. if b.LastCommitHash == nil {
  131. b.LastCommitHash = b.LastCommit.Hash()
  132. }
  133. if b.DataHash == nil {
  134. b.DataHash = b.Data.Hash()
  135. }
  136. if b.EvidenceHash == nil {
  137. b.EvidenceHash = b.Evidence.Hash()
  138. }
  139. }
  140. // Hash computes and returns the block hash.
  141. // If the block is incomplete, block hash is nil for safety.
  142. func (b *Block) Hash() tmbytes.HexBytes {
  143. if b == nil {
  144. return nil
  145. }
  146. b.mtx.Lock()
  147. defer b.mtx.Unlock()
  148. if b.LastCommit == nil {
  149. return nil
  150. }
  151. b.fillHeader()
  152. return b.Header.Hash()
  153. }
  154. // MakePartSet returns a PartSet containing parts of a serialized block.
  155. // This is the form in which the block is gossipped to peers.
  156. // CONTRACT: partSize is greater than zero.
  157. func (b *Block) MakePartSet(partSize int) *PartSet {
  158. if b == nil {
  159. return nil
  160. }
  161. b.mtx.Lock()
  162. defer b.mtx.Unlock()
  163. // We prefix the byte length, so that unmarshaling
  164. // can easily happen via a reader.
  165. bz, err := cdc.MarshalBinaryLengthPrefixed(b)
  166. if err != nil {
  167. panic(err)
  168. }
  169. return NewPartSetFromData(bz, partSize)
  170. }
  171. // HashesTo is a convenience function that checks if a block hashes to the given argument.
  172. // Returns false if the block is nil or the hash is empty.
  173. func (b *Block) HashesTo(hash []byte) bool {
  174. if len(hash) == 0 {
  175. return false
  176. }
  177. if b == nil {
  178. return false
  179. }
  180. return bytes.Equal(b.Hash(), hash)
  181. }
  182. // Size returns size of the block in bytes.
  183. func (b *Block) Size() int {
  184. bz, err := cdc.MarshalBinaryBare(b)
  185. if err != nil {
  186. return 0
  187. }
  188. return len(bz)
  189. }
  190. // String returns a string representation of the block
  191. func (b *Block) String() string {
  192. return b.StringIndented("")
  193. }
  194. // StringIndented returns a string representation of the block
  195. func (b *Block) StringIndented(indent string) string {
  196. if b == nil {
  197. return "nil-Block"
  198. }
  199. return fmt.Sprintf(`Block{
  200. %s %v
  201. %s %v
  202. %s %v
  203. %s %v
  204. %s}#%v`,
  205. indent, b.Header.StringIndented(indent+" "),
  206. indent, b.Data.StringIndented(indent+" "),
  207. indent, b.Evidence.StringIndented(indent+" "),
  208. indent, b.LastCommit.StringIndented(indent+" "),
  209. indent, b.Hash())
  210. }
  211. // StringShort returns a shortened string representation of the block
  212. func (b *Block) StringShort() string {
  213. if b == nil {
  214. return "nil-Block"
  215. }
  216. return fmt.Sprintf("Block#%v", b.Hash())
  217. }
  218. //-----------------------------------------------------------
  219. // These methods are for Protobuf Compatibility
  220. // Marshal returns the amino encoding.
  221. func (b *Block) Marshal() ([]byte, error) {
  222. return cdc.MarshalBinaryBare(b)
  223. }
  224. // MarshalTo calls Marshal and copies to the given buffer.
  225. func (b *Block) MarshalTo(data []byte) (int, error) {
  226. bs, err := b.Marshal()
  227. if err != nil {
  228. return -1, err
  229. }
  230. return copy(data, bs), nil
  231. }
  232. // Unmarshal deserializes from amino encoded form.
  233. func (b *Block) Unmarshal(bs []byte) error {
  234. return cdc.UnmarshalBinaryBare(bs, b)
  235. }
  236. //-----------------------------------------------------------------------------
  237. // MaxDataBytes returns the maximum size of block's data.
  238. //
  239. // XXX: Panics on negative result.
  240. func MaxDataBytes(maxBytes int64, valsCount, evidenceCount int) int64 {
  241. maxDataBytes := maxBytes -
  242. MaxAminoOverheadForBlock -
  243. MaxHeaderBytes -
  244. int64(valsCount)*MaxVoteBytes -
  245. int64(evidenceCount)*MaxEvidenceBytes
  246. if maxDataBytes < 0 {
  247. panic(fmt.Sprintf(
  248. "Negative MaxDataBytes. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  249. maxBytes,
  250. -(maxDataBytes - maxBytes),
  251. ))
  252. }
  253. return maxDataBytes
  254. }
  255. // MaxDataBytesUnknownEvidence returns the maximum size of block's data when
  256. // evidence count is unknown. MaxEvidencePerBlock will be used for the size
  257. // of evidence.
  258. //
  259. // XXX: Panics on negative result.
  260. func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int) int64 {
  261. _, maxEvidenceBytes := MaxEvidencePerBlock(maxBytes)
  262. maxDataBytes := maxBytes -
  263. MaxAminoOverheadForBlock -
  264. MaxHeaderBytes -
  265. int64(valsCount)*MaxVoteBytes -
  266. maxEvidenceBytes
  267. if maxDataBytes < 0 {
  268. panic(fmt.Sprintf(
  269. "Negative MaxDataBytesUnknownEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
  270. maxBytes,
  271. -(maxDataBytes - maxBytes),
  272. ))
  273. }
  274. return maxDataBytes
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Header defines the structure of a Tendermint block header.
  278. // NOTE: changes to the Header should be duplicated in:
  279. // - header.Hash()
  280. // - abci.Header
  281. // - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md
  282. type Header struct {
  283. // basic block info
  284. Version version.Consensus `json:"version"`
  285. ChainID string `json:"chain_id"`
  286. Height int64 `json:"height"`
  287. Time time.Time `json:"time"`
  288. // prev block info
  289. LastBlockID BlockID `json:"last_block_id"`
  290. // hashes of block data
  291. LastCommitHash tmbytes.HexBytes `json:"last_commit_hash"` // commit from validators from the last block
  292. DataHash tmbytes.HexBytes `json:"data_hash"` // transactions
  293. // hashes from the app output from the prev block
  294. ValidatorsHash tmbytes.HexBytes `json:"validators_hash"` // validators for the current block
  295. NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"` // validators for the next block
  296. ConsensusHash tmbytes.HexBytes `json:"consensus_hash"` // consensus params for current block
  297. AppHash tmbytes.HexBytes `json:"app_hash"` // state after txs from the previous block
  298. // root hash of all results from the txs from the previous block
  299. LastResultsHash tmbytes.HexBytes `json:"last_results_hash"`
  300. // consensus info
  301. EvidenceHash tmbytes.HexBytes `json:"evidence_hash"` // evidence included in the block
  302. ProposerAddress Address `json:"proposer_address"` // original proposer of the block
  303. }
  304. // Populate the Header with state-derived data.
  305. // Call this after MakeBlock to complete the Header.
  306. func (h *Header) Populate(
  307. version version.Consensus, chainID string,
  308. timestamp time.Time, lastBlockID BlockID,
  309. valHash, nextValHash []byte,
  310. consensusHash, appHash, lastResultsHash []byte,
  311. proposerAddress Address,
  312. ) {
  313. h.Version = version
  314. h.ChainID = chainID
  315. h.Time = timestamp
  316. h.LastBlockID = lastBlockID
  317. h.ValidatorsHash = valHash
  318. h.NextValidatorsHash = nextValHash
  319. h.ConsensusHash = consensusHash
  320. h.AppHash = appHash
  321. h.LastResultsHash = lastResultsHash
  322. h.ProposerAddress = proposerAddress
  323. }
  324. // Hash returns the hash of the header.
  325. // It computes a Merkle tree from the header fields
  326. // ordered as they appear in the Header.
  327. // Returns nil if ValidatorHash is missing,
  328. // since a Header is not valid unless there is
  329. // a ValidatorsHash (corresponding to the validator set).
  330. func (h *Header) Hash() tmbytes.HexBytes {
  331. if h == nil || len(h.ValidatorsHash) == 0 {
  332. return nil
  333. }
  334. return merkle.SimpleHashFromByteSlices([][]byte{
  335. cdcEncode(h.Version),
  336. cdcEncode(h.ChainID),
  337. cdcEncode(h.Height),
  338. cdcEncode(h.Time),
  339. cdcEncode(h.LastBlockID),
  340. cdcEncode(h.LastCommitHash),
  341. cdcEncode(h.DataHash),
  342. cdcEncode(h.ValidatorsHash),
  343. cdcEncode(h.NextValidatorsHash),
  344. cdcEncode(h.ConsensusHash),
  345. cdcEncode(h.AppHash),
  346. cdcEncode(h.LastResultsHash),
  347. cdcEncode(h.EvidenceHash),
  348. cdcEncode(h.ProposerAddress),
  349. })
  350. }
  351. // StringIndented returns a string representation of the header
  352. func (h *Header) StringIndented(indent string) string {
  353. if h == nil {
  354. return "nil-Header"
  355. }
  356. return fmt.Sprintf(`Header{
  357. %s Version: %v
  358. %s ChainID: %v
  359. %s Height: %v
  360. %s Time: %v
  361. %s LastBlockID: %v
  362. %s LastCommit: %v
  363. %s Data: %v
  364. %s Validators: %v
  365. %s NextValidators: %v
  366. %s App: %v
  367. %s Consensus: %v
  368. %s Results: %v
  369. %s Evidence: %v
  370. %s Proposer: %v
  371. %s}#%v`,
  372. indent, h.Version,
  373. indent, h.ChainID,
  374. indent, h.Height,
  375. indent, h.Time,
  376. indent, h.LastBlockID,
  377. indent, h.LastCommitHash,
  378. indent, h.DataHash,
  379. indent, h.ValidatorsHash,
  380. indent, h.NextValidatorsHash,
  381. indent, h.AppHash,
  382. indent, h.ConsensusHash,
  383. indent, h.LastResultsHash,
  384. indent, h.EvidenceHash,
  385. indent, h.ProposerAddress,
  386. indent, h.Hash())
  387. }
  388. //-------------------------------------
  389. // BlockIDFlag indicates which BlockID the signature is for.
  390. type BlockIDFlag byte
  391. const (
  392. // BlockIDFlagAbsent - no vote was received from a validator.
  393. BlockIDFlagAbsent BlockIDFlag = iota + 1
  394. // BlockIDFlagCommit - voted for the Commit.BlockID.
  395. BlockIDFlagCommit
  396. // BlockIDFlagNil - voted for nil.
  397. BlockIDFlagNil
  398. )
  399. // CommitSig is a part of the Vote included in a Commit.
  400. type CommitSig struct {
  401. BlockIDFlag BlockIDFlag `json:"block_id_flag"`
  402. ValidatorAddress Address `json:"validator_address"`
  403. Timestamp time.Time `json:"timestamp"`
  404. Signature []byte `json:"signature"`
  405. }
  406. // NewCommitSigForBlock returns new CommitSig with BlockIDFlagCommit.
  407. func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig {
  408. return CommitSig{
  409. BlockIDFlag: BlockIDFlagCommit,
  410. ValidatorAddress: valAddr,
  411. Timestamp: ts,
  412. Signature: signature,
  413. }
  414. }
  415. // ForBlock returns true if CommitSig is for the block.
  416. func (cs CommitSig) ForBlock() bool {
  417. return cs.BlockIDFlag == BlockIDFlagCommit
  418. }
  419. // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other
  420. // fields are all empty.
  421. func NewCommitSigAbsent() CommitSig {
  422. return CommitSig{
  423. BlockIDFlag: BlockIDFlagAbsent,
  424. }
  425. }
  426. // Absent returns true if CommitSig is absent.
  427. func (cs CommitSig) Absent() bool {
  428. return cs.BlockIDFlag == BlockIDFlagAbsent
  429. }
  430. func (cs CommitSig) String() string {
  431. return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}",
  432. tmbytes.Fingerprint(cs.Signature),
  433. tmbytes.Fingerprint(cs.ValidatorAddress),
  434. cs.BlockIDFlag,
  435. CanonicalTime(cs.Timestamp))
  436. }
  437. // BlockID returns the Commit's BlockID if CommitSig indicates signing,
  438. // otherwise - empty BlockID.
  439. func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID {
  440. var blockID BlockID
  441. switch cs.BlockIDFlag {
  442. case BlockIDFlagAbsent:
  443. blockID = BlockID{}
  444. case BlockIDFlagCommit:
  445. blockID = commitBlockID
  446. case BlockIDFlagNil:
  447. blockID = BlockID{}
  448. default:
  449. panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag))
  450. }
  451. return blockID
  452. }
  453. // ValidateBasic performs basic validation.
  454. func (cs CommitSig) ValidateBasic() error {
  455. switch cs.BlockIDFlag {
  456. case BlockIDFlagAbsent:
  457. case BlockIDFlagCommit:
  458. case BlockIDFlagNil:
  459. default:
  460. return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag)
  461. }
  462. switch cs.BlockIDFlag {
  463. case BlockIDFlagAbsent:
  464. if len(cs.ValidatorAddress) != 0 {
  465. return errors.New("validator address is present")
  466. }
  467. if !cs.Timestamp.IsZero() {
  468. return errors.New("time is present")
  469. }
  470. if len(cs.Signature) != 0 {
  471. return errors.New("signature is present")
  472. }
  473. default:
  474. if len(cs.ValidatorAddress) != crypto.AddressSize {
  475. return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
  476. crypto.AddressSize,
  477. len(cs.ValidatorAddress),
  478. )
  479. }
  480. // NOTE: Timestamp validation is subtle and handled elsewhere.
  481. if len(cs.Signature) == 0 {
  482. return errors.New("signature is missing")
  483. }
  484. if len(cs.Signature) > MaxSignatureSize {
  485. return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
  486. }
  487. }
  488. return nil
  489. }
  490. //-------------------------------------
  491. // Commit contains the evidence that a block was committed by a set of validators.
  492. // NOTE: Commit is empty for height 1, but never nil.
  493. type Commit struct {
  494. // NOTE: The signatures are in order of address to preserve the bonded
  495. // ValidatorSet order.
  496. // Any peer with a block can gossip signatures by index with a peer without
  497. // recalculating the active ValidatorSet.
  498. Height int64 `json:"height"`
  499. Round int `json:"round"`
  500. BlockID BlockID `json:"block_id"`
  501. Signatures []CommitSig `json:"signatures"`
  502. // Memoized in first call to corresponding method.
  503. // NOTE: can't memoize in constructor because constructor isn't used for
  504. // unmarshaling.
  505. hash tmbytes.HexBytes
  506. bitArray *bits.BitArray
  507. }
  508. // NewCommit returns a new Commit.
  509. func NewCommit(height int64, round int, blockID BlockID, commitSigs []CommitSig) *Commit {
  510. return &Commit{
  511. Height: height,
  512. Round: round,
  513. BlockID: blockID,
  514. Signatures: commitSigs,
  515. }
  516. }
  517. // CommitToVoteSet constructs a VoteSet from the Commit and validator set.
  518. // Panics if signatures from the commit can't be added to the voteset.
  519. // Inverse of VoteSet.MakeCommit().
  520. func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet {
  521. voteSet := NewVoteSet(chainID, commit.Height, commit.Round, PrecommitType, vals)
  522. for idx, commitSig := range commit.Signatures {
  523. if commitSig.Absent() {
  524. continue // OK, some precommits can be missing.
  525. }
  526. added, err := voteSet.AddVote(commit.GetVote(idx))
  527. if !added || err != nil {
  528. panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
  529. }
  530. }
  531. return voteSet
  532. }
  533. // GetVote converts the CommitSig for the given valIdx to a Vote.
  534. // Returns nil if the precommit at valIdx is nil.
  535. // Panics if valIdx >= commit.Size().
  536. func (commit *Commit) GetVote(valIdx int) *Vote {
  537. commitSig := commit.Signatures[valIdx]
  538. return &Vote{
  539. Type: PrecommitType,
  540. Height: commit.Height,
  541. Round: commit.Round,
  542. BlockID: commitSig.BlockID(commit.BlockID),
  543. Timestamp: commitSig.Timestamp,
  544. ValidatorAddress: commitSig.ValidatorAddress,
  545. ValidatorIndex: valIdx,
  546. Signature: commitSig.Signature,
  547. }
  548. }
  549. // VoteSignBytes constructs the SignBytes for the given CommitSig.
  550. // The only unique part of the SignBytes is the Timestamp - all other fields
  551. // signed over are otherwise the same for all validators.
  552. // Panics if valIdx >= commit.Size().
  553. func (commit *Commit) VoteSignBytes(chainID string, valIdx int) []byte {
  554. return commit.GetVote(valIdx).SignBytes(chainID)
  555. }
  556. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  557. // Implements VoteSetReader.
  558. func (commit *Commit) Type() byte {
  559. return byte(PrecommitType)
  560. }
  561. // GetHeight returns height of the commit.
  562. // Implements VoteSetReader.
  563. func (commit *Commit) GetHeight() int64 {
  564. return commit.Height
  565. }
  566. // GetRound returns height of the commit.
  567. // Implements VoteSetReader.
  568. func (commit *Commit) GetRound() int {
  569. return commit.Round
  570. }
  571. // Size returns the number of signatures in the commit.
  572. // Implements VoteSetReader.
  573. func (commit *Commit) Size() int {
  574. if commit == nil {
  575. return 0
  576. }
  577. return len(commit.Signatures)
  578. }
  579. // BitArray returns a BitArray of which validators voted for BlockID or nil in this commit.
  580. // Implements VoteSetReader.
  581. func (commit *Commit) BitArray() *bits.BitArray {
  582. if commit.bitArray == nil {
  583. commit.bitArray = bits.NewBitArray(len(commit.Signatures))
  584. for i, commitSig := range commit.Signatures {
  585. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  586. // not just the one with +2/3 !
  587. commit.bitArray.SetIndex(i, !commitSig.Absent())
  588. }
  589. }
  590. return commit.bitArray
  591. }
  592. // GetByIndex returns the vote corresponding to a given validator index.
  593. // Panics if `index >= commit.Size()`.
  594. // Implements VoteSetReader.
  595. func (commit *Commit) GetByIndex(valIdx int) *Vote {
  596. return commit.GetVote(valIdx)
  597. }
  598. // IsCommit returns true if there is at least one signature.
  599. // Implements VoteSetReader.
  600. func (commit *Commit) IsCommit() bool {
  601. return len(commit.Signatures) != 0
  602. }
  603. // ValidateBasic performs basic validation that doesn't involve state data.
  604. // Does not actually check the cryptographic signatures.
  605. func (commit *Commit) ValidateBasic() error {
  606. if commit.Height < 0 {
  607. return errors.New("negative Height")
  608. }
  609. if commit.Round < 0 {
  610. return errors.New("negative Round")
  611. }
  612. if commit.BlockID.IsZero() {
  613. return errors.New("commit cannot be for nil block")
  614. }
  615. if len(commit.Signatures) == 0 {
  616. return errors.New("no signatures in commit")
  617. }
  618. for i, commitSig := range commit.Signatures {
  619. if err := commitSig.ValidateBasic(); err != nil {
  620. return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
  621. }
  622. }
  623. return nil
  624. }
  625. // Hash returns the hash of the commit
  626. func (commit *Commit) Hash() tmbytes.HexBytes {
  627. if commit == nil {
  628. return nil
  629. }
  630. if commit.hash == nil {
  631. bs := make([][]byte, len(commit.Signatures))
  632. for i, commitSig := range commit.Signatures {
  633. bs[i] = cdcEncode(commitSig)
  634. }
  635. commit.hash = merkle.SimpleHashFromByteSlices(bs)
  636. }
  637. return commit.hash
  638. }
  639. // StringIndented returns a string representation of the commit
  640. func (commit *Commit) StringIndented(indent string) string {
  641. if commit == nil {
  642. return "nil-Commit"
  643. }
  644. commitSigStrings := make([]string, len(commit.Signatures))
  645. for i, commitSig := range commit.Signatures {
  646. commitSigStrings[i] = commitSig.String()
  647. }
  648. return fmt.Sprintf(`Commit{
  649. %s Height: %d
  650. %s Round: %d
  651. %s BlockID: %v
  652. %s Signatures:
  653. %s %v
  654. %s}#%v`,
  655. indent, commit.Height,
  656. indent, commit.Round,
  657. indent, commit.BlockID,
  658. indent,
  659. indent, strings.Join(commitSigStrings, "\n"+indent+" "),
  660. indent, commit.hash)
  661. }
  662. //-----------------------------------------------------------------------------
  663. // SignedHeader is a header along with the commits that prove it.
  664. // It is the basis of the lite client.
  665. type SignedHeader struct {
  666. *Header `json:"header"`
  667. Commit *Commit `json:"commit"`
  668. }
  669. // ValidateBasic does basic consistency checks and makes sure the header
  670. // and commit are consistent.
  671. // NOTE: This does not actually check the cryptographic signatures. Make
  672. // sure to use a Verifier to validate the signatures actually provide a
  673. // significantly strong proof for this header's validity.
  674. func (sh SignedHeader) ValidateBasic(chainID string) error {
  675. // Make sure the header is consistent with the commit.
  676. if sh.Header == nil {
  677. return errors.New("signedHeader missing header")
  678. }
  679. if sh.Commit == nil {
  680. return errors.New("signedHeader missing commit (precommit votes)")
  681. }
  682. // Check ChainID.
  683. if sh.ChainID != chainID {
  684. return fmt.Errorf("signedHeader belongs to another chain '%s' not '%s'",
  685. sh.ChainID, chainID)
  686. }
  687. // Check Height.
  688. if sh.Commit.Height != sh.Height {
  689. return fmt.Errorf("signedHeader header and commit height mismatch: %v vs %v",
  690. sh.Height, sh.Commit.Height)
  691. }
  692. // Check Hash.
  693. hhash := sh.Hash()
  694. chash := sh.Commit.BlockID.Hash
  695. if !bytes.Equal(hhash, chash) {
  696. return fmt.Errorf("signedHeader commit signs block %X, header is block %X",
  697. chash, hhash)
  698. }
  699. // ValidateBasic on the Commit.
  700. err := sh.Commit.ValidateBasic()
  701. if err != nil {
  702. return errors.Wrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
  703. }
  704. return nil
  705. }
  706. func (sh SignedHeader) String() string {
  707. return sh.StringIndented("")
  708. }
  709. // StringIndented returns a string representation of the SignedHeader.
  710. func (sh SignedHeader) StringIndented(indent string) string {
  711. return fmt.Sprintf(`SignedHeader{
  712. %s %v
  713. %s %v
  714. %s}`,
  715. indent, sh.Header.StringIndented(indent+" "),
  716. indent, sh.Commit.StringIndented(indent+" "),
  717. indent)
  718. }
  719. //-----------------------------------------------------------------------------
  720. // Data contains the set of transactions included in the block
  721. type Data struct {
  722. // Txs that will be applied by state @ block.Height+1.
  723. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  724. // This means that block.AppHash does not include these txs.
  725. Txs Txs `json:"txs"`
  726. // Volatile
  727. hash tmbytes.HexBytes
  728. }
  729. // Hash returns the hash of the data
  730. func (data *Data) Hash() tmbytes.HexBytes {
  731. if data == nil {
  732. return (Txs{}).Hash()
  733. }
  734. if data.hash == nil {
  735. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  736. }
  737. return data.hash
  738. }
  739. // StringIndented returns a string representation of the transactions
  740. func (data *Data) StringIndented(indent string) string {
  741. if data == nil {
  742. return "nil-Data"
  743. }
  744. txStrings := make([]string, tmmath.MinInt(len(data.Txs), 21))
  745. for i, tx := range data.Txs {
  746. if i == 20 {
  747. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  748. break
  749. }
  750. txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  751. }
  752. return fmt.Sprintf(`Data{
  753. %s %v
  754. %s}#%v`,
  755. indent, strings.Join(txStrings, "\n"+indent+" "),
  756. indent, data.hash)
  757. }
  758. //-----------------------------------------------------------------------------
  759. // EvidenceData contains any evidence of malicious wrong-doing by validators
  760. type EvidenceData struct {
  761. Evidence EvidenceList `json:"evidence"`
  762. // Volatile
  763. hash tmbytes.HexBytes
  764. }
  765. // Hash returns the hash of the data.
  766. func (data *EvidenceData) Hash() tmbytes.HexBytes {
  767. if data.hash == nil {
  768. data.hash = data.Evidence.Hash()
  769. }
  770. return data.hash
  771. }
  772. // StringIndented returns a string representation of the evidence.
  773. func (data *EvidenceData) StringIndented(indent string) string {
  774. if data == nil {
  775. return "nil-Evidence"
  776. }
  777. evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21))
  778. for i, ev := range data.Evidence {
  779. if i == 20 {
  780. evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  781. break
  782. }
  783. evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  784. }
  785. return fmt.Sprintf(`EvidenceData{
  786. %s %v
  787. %s}#%v`,
  788. indent, strings.Join(evStrings, "\n"+indent+" "),
  789. indent, data.hash)
  790. }
  791. //--------------------------------------------------------------------------------
  792. // BlockID defines the unique ID of a block as its Hash and its PartSetHeader
  793. type BlockID struct {
  794. Hash tmbytes.HexBytes `json:"hash"`
  795. PartsHeader PartSetHeader `json:"parts"`
  796. }
  797. // Equals returns true if the BlockID matches the given BlockID
  798. func (blockID BlockID) Equals(other BlockID) bool {
  799. return bytes.Equal(blockID.Hash, other.Hash) &&
  800. blockID.PartsHeader.Equals(other.PartsHeader)
  801. }
  802. // Key returns a machine-readable string representation of the BlockID
  803. func (blockID BlockID) Key() string {
  804. bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader)
  805. if err != nil {
  806. panic(err)
  807. }
  808. return string(blockID.Hash) + string(bz)
  809. }
  810. // ValidateBasic performs basic validation.
  811. func (blockID BlockID) ValidateBasic() error {
  812. // Hash can be empty in case of POLBlockID in Proposal.
  813. if err := ValidateHash(blockID.Hash); err != nil {
  814. return fmt.Errorf("wrong Hash")
  815. }
  816. if err := blockID.PartsHeader.ValidateBasic(); err != nil {
  817. return fmt.Errorf("wrong PartsHeader: %v", err)
  818. }
  819. return nil
  820. }
  821. // IsZero returns true if this is the BlockID of a nil block.
  822. func (blockID BlockID) IsZero() bool {
  823. return len(blockID.Hash) == 0 &&
  824. blockID.PartsHeader.IsZero()
  825. }
  826. // IsComplete returns true if this is a valid BlockID of a non-nil block.
  827. func (blockID BlockID) IsComplete() bool {
  828. return len(blockID.Hash) == tmhash.Size &&
  829. blockID.PartsHeader.Total > 0 &&
  830. len(blockID.PartsHeader.Hash) == tmhash.Size
  831. }
  832. // String returns a human readable string representation of the BlockID
  833. func (blockID BlockID) String() string {
  834. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  835. }