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.

937 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. // - /docs/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. // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other
  416. // fields are all empty.
  417. func NewCommitSigAbsent() CommitSig {
  418. return CommitSig{
  419. BlockIDFlag: BlockIDFlagAbsent,
  420. }
  421. }
  422. // Absent returns true if CommitSig is absent.
  423. func (cs CommitSig) Absent() bool {
  424. return cs.BlockIDFlag == BlockIDFlagAbsent
  425. }
  426. func (cs CommitSig) String() string {
  427. return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}",
  428. tmbytes.Fingerprint(cs.Signature),
  429. tmbytes.Fingerprint(cs.ValidatorAddress),
  430. cs.BlockIDFlag,
  431. CanonicalTime(cs.Timestamp))
  432. }
  433. // BlockID returns the Commit's BlockID if CommitSig indicates signing,
  434. // otherwise - empty BlockID.
  435. func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID {
  436. var blockID BlockID
  437. switch cs.BlockIDFlag {
  438. case BlockIDFlagAbsent:
  439. blockID = BlockID{}
  440. case BlockIDFlagCommit:
  441. blockID = commitBlockID
  442. case BlockIDFlagNil:
  443. blockID = BlockID{}
  444. default:
  445. panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag))
  446. }
  447. return blockID
  448. }
  449. // ValidateBasic performs basic validation.
  450. func (cs CommitSig) ValidateBasic() error {
  451. switch cs.BlockIDFlag {
  452. case BlockIDFlagAbsent:
  453. case BlockIDFlagCommit:
  454. case BlockIDFlagNil:
  455. default:
  456. return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag)
  457. }
  458. switch cs.BlockIDFlag {
  459. case BlockIDFlagAbsent:
  460. if len(cs.ValidatorAddress) != 0 {
  461. return errors.New("validator address is present")
  462. }
  463. if !cs.Timestamp.IsZero() {
  464. return errors.New("time is present")
  465. }
  466. if len(cs.Signature) != 0 {
  467. return errors.New("signature is present")
  468. }
  469. default:
  470. if len(cs.ValidatorAddress) != crypto.AddressSize {
  471. return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
  472. crypto.AddressSize,
  473. len(cs.ValidatorAddress),
  474. )
  475. }
  476. // NOTE: Timestamp validation is subtle and handled elsewhere.
  477. if len(cs.Signature) == 0 {
  478. return errors.New("signature is missing")
  479. }
  480. if len(cs.Signature) > MaxSignatureSize {
  481. return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
  482. }
  483. }
  484. return nil
  485. }
  486. //-------------------------------------
  487. // Commit contains the evidence that a block was committed by a set of validators.
  488. // NOTE: Commit is empty for height 1, but never nil.
  489. type Commit struct {
  490. // NOTE: The signatures are in order of address to preserve the bonded
  491. // ValidatorSet order.
  492. // Any peer with a block can gossip signatures by index with a peer without
  493. // recalculating the active ValidatorSet.
  494. Height int64 `json:"height"`
  495. Round int `json:"round"`
  496. BlockID BlockID `json:"block_id"`
  497. Signatures []CommitSig `json:"signatures"`
  498. // Memoized in first call to corresponding method.
  499. // NOTE: can't memoize in constructor because constructor isn't used for
  500. // unmarshaling.
  501. hash tmbytes.HexBytes
  502. bitArray *bits.BitArray
  503. }
  504. // NewCommit returns a new Commit.
  505. func NewCommit(height int64, round int, blockID BlockID, commitSigs []CommitSig) *Commit {
  506. return &Commit{
  507. Height: height,
  508. Round: round,
  509. BlockID: blockID,
  510. Signatures: commitSigs,
  511. }
  512. }
  513. // CommitToVoteSet constructs a VoteSet from the Commit and validator set.
  514. // Panics if signatures from the commit can't be added to the voteset.
  515. // Inverse of VoteSet.MakeCommit().
  516. func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet {
  517. voteSet := NewVoteSet(chainID, commit.Height, commit.Round, PrecommitType, vals)
  518. for idx, commitSig := range commit.Signatures {
  519. if commitSig.Absent() {
  520. continue // OK, some precommits can be missing.
  521. }
  522. added, err := voteSet.AddVote(commit.GetVote(idx))
  523. if !added || err != nil {
  524. panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
  525. }
  526. }
  527. return voteSet
  528. }
  529. // GetVote converts the CommitSig for the given valIdx to a Vote.
  530. // Returns nil if the precommit at valIdx is nil.
  531. // Panics if valIdx >= commit.Size().
  532. func (commit *Commit) GetVote(valIdx int) *Vote {
  533. commitSig := commit.Signatures[valIdx]
  534. return &Vote{
  535. Type: PrecommitType,
  536. Height: commit.Height,
  537. Round: commit.Round,
  538. BlockID: commitSig.BlockID(commit.BlockID),
  539. Timestamp: commitSig.Timestamp,
  540. ValidatorAddress: commitSig.ValidatorAddress,
  541. ValidatorIndex: valIdx,
  542. Signature: commitSig.Signature,
  543. }
  544. }
  545. // VoteSignBytes constructs the SignBytes for the given CommitSig.
  546. // The only unique part of the SignBytes is the Timestamp - all other fields
  547. // signed over are otherwise the same for all validators.
  548. // Panics if valIdx >= commit.Size().
  549. func (commit *Commit) VoteSignBytes(chainID string, valIdx int) []byte {
  550. return commit.GetVote(valIdx).SignBytes(chainID)
  551. }
  552. // Type returns the vote type of the commit, which is always VoteTypePrecommit
  553. // Implements VoteSetReader.
  554. func (commit *Commit) Type() byte {
  555. return byte(PrecommitType)
  556. }
  557. // GetHeight returns height of the commit.
  558. // Implements VoteSetReader.
  559. func (commit *Commit) GetHeight() int64 {
  560. return commit.Height
  561. }
  562. // GetRound returns height of the commit.
  563. // Implements VoteSetReader.
  564. func (commit *Commit) GetRound() int {
  565. return commit.Round
  566. }
  567. // Size returns the number of signatures in the commit.
  568. // Implements VoteSetReader.
  569. func (commit *Commit) Size() int {
  570. if commit == nil {
  571. return 0
  572. }
  573. return len(commit.Signatures)
  574. }
  575. // BitArray returns a BitArray of which validators voted for BlockID or nil in this commit.
  576. // Implements VoteSetReader.
  577. func (commit *Commit) BitArray() *bits.BitArray {
  578. if commit.bitArray == nil {
  579. commit.bitArray = bits.NewBitArray(len(commit.Signatures))
  580. for i, commitSig := range commit.Signatures {
  581. // TODO: need to check the BlockID otherwise we could be counting conflicts,
  582. // not just the one with +2/3 !
  583. commit.bitArray.SetIndex(i, !commitSig.Absent())
  584. }
  585. }
  586. return commit.bitArray
  587. }
  588. // GetByIndex returns the vote corresponding to a given validator index.
  589. // Panics if `index >= commit.Size()`.
  590. // Implements VoteSetReader.
  591. func (commit *Commit) GetByIndex(valIdx int) *Vote {
  592. return commit.GetVote(valIdx)
  593. }
  594. // IsCommit returns true if there is at least one signature.
  595. // Implements VoteSetReader.
  596. func (commit *Commit) IsCommit() bool {
  597. return len(commit.Signatures) != 0
  598. }
  599. // ValidateBasic performs basic validation that doesn't involve state data.
  600. // Does not actually check the cryptographic signatures.
  601. func (commit *Commit) ValidateBasic() error {
  602. if commit.Height < 0 {
  603. return errors.New("negative Height")
  604. }
  605. if commit.Round < 0 {
  606. return errors.New("negative Round")
  607. }
  608. if commit.BlockID.IsZero() {
  609. return errors.New("commit cannot be for nil block")
  610. }
  611. if len(commit.Signatures) == 0 {
  612. return errors.New("no signatures in commit")
  613. }
  614. for i, commitSig := range commit.Signatures {
  615. if err := commitSig.ValidateBasic(); err != nil {
  616. return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
  617. }
  618. }
  619. return nil
  620. }
  621. // Hash returns the hash of the commit
  622. func (commit *Commit) Hash() tmbytes.HexBytes {
  623. if commit == nil {
  624. return nil
  625. }
  626. if commit.hash == nil {
  627. bs := make([][]byte, len(commit.Signatures))
  628. for i, commitSig := range commit.Signatures {
  629. bs[i] = cdcEncode(commitSig)
  630. }
  631. commit.hash = merkle.SimpleHashFromByteSlices(bs)
  632. }
  633. return commit.hash
  634. }
  635. // StringIndented returns a string representation of the commit
  636. func (commit *Commit) StringIndented(indent string) string {
  637. if commit == nil {
  638. return "nil-Commit"
  639. }
  640. commitSigStrings := make([]string, len(commit.Signatures))
  641. for i, commitSig := range commit.Signatures {
  642. commitSigStrings[i] = commitSig.String()
  643. }
  644. return fmt.Sprintf(`Commit{
  645. %s Height: %d
  646. %s Round: %d
  647. %s BlockID: %v
  648. %s Signatures:
  649. %s %v
  650. %s}#%v`,
  651. indent, commit.Height,
  652. indent, commit.Round,
  653. indent, commit.BlockID,
  654. indent,
  655. indent, strings.Join(commitSigStrings, "\n"+indent+" "),
  656. indent, commit.hash)
  657. }
  658. //-----------------------------------------------------------------------------
  659. // SignedHeader is a header along with the commits that prove it.
  660. // It is the basis of the lite client.
  661. type SignedHeader struct {
  662. *Header `json:"header"`
  663. Commit *Commit `json:"commit"`
  664. }
  665. // ValidateBasic does basic consistency checks and makes sure the header
  666. // and commit are consistent.
  667. //
  668. // NOTE: This does not actually check the cryptographic signatures. Make
  669. // sure to use a Verifier to validate the signatures actually provide a
  670. // significantly strong proof for this header's validity.
  671. func (sh SignedHeader) ValidateBasic(chainID string) error {
  672. // Make sure the header is consistent with the commit.
  673. if sh.Header == nil {
  674. return errors.New("signedHeader missing header")
  675. }
  676. if sh.Commit == nil {
  677. return errors.New("signedHeader missing commit (precommit votes)")
  678. }
  679. // Check ChainID.
  680. if sh.ChainID != chainID {
  681. return fmt.Errorf("signedHeader belongs to another chain '%s' not '%s'",
  682. sh.ChainID, chainID)
  683. }
  684. // Check Height.
  685. if sh.Commit.Height != sh.Height {
  686. return fmt.Errorf("signedHeader header and commit height mismatch: %v vs %v",
  687. sh.Height, sh.Commit.Height)
  688. }
  689. // Check Hash.
  690. hhash := sh.Hash()
  691. chash := sh.Commit.BlockID.Hash
  692. if !bytes.Equal(hhash, chash) {
  693. return fmt.Errorf("signedHeader commit signs block %X, header is block %X",
  694. chash, hhash)
  695. }
  696. // ValidateBasic on the Commit.
  697. err := sh.Commit.ValidateBasic()
  698. if err != nil {
  699. return errors.Wrap(err, "commit.ValidateBasic failed during SignedHeader.ValidateBasic")
  700. }
  701. return nil
  702. }
  703. func (sh SignedHeader) String() string {
  704. return sh.StringIndented("")
  705. }
  706. // StringIndented returns a string representation of the SignedHeader.
  707. func (sh SignedHeader) StringIndented(indent string) string {
  708. return fmt.Sprintf(`SignedHeader{
  709. %s %v
  710. %s %v
  711. %s}`,
  712. indent, sh.Header.StringIndented(indent+" "),
  713. indent, sh.Commit.StringIndented(indent+" "),
  714. indent)
  715. }
  716. //-----------------------------------------------------------------------------
  717. // Data contains the set of transactions included in the block
  718. type Data struct {
  719. // Txs that will be applied by state @ block.Height+1.
  720. // NOTE: not all txs here are valid. We're just agreeing on the order first.
  721. // This means that block.AppHash does not include these txs.
  722. Txs Txs `json:"txs"`
  723. // Volatile
  724. hash tmbytes.HexBytes
  725. }
  726. // Hash returns the hash of the data
  727. func (data *Data) Hash() tmbytes.HexBytes {
  728. if data == nil {
  729. return (Txs{}).Hash()
  730. }
  731. if data.hash == nil {
  732. data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  733. }
  734. return data.hash
  735. }
  736. // StringIndented returns a string representation of the transactions
  737. func (data *Data) StringIndented(indent string) string {
  738. if data == nil {
  739. return "nil-Data"
  740. }
  741. txStrings := make([]string, tmmath.MinInt(len(data.Txs), 21))
  742. for i, tx := range data.Txs {
  743. if i == 20 {
  744. txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  745. break
  746. }
  747. txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  748. }
  749. return fmt.Sprintf(`Data{
  750. %s %v
  751. %s}#%v`,
  752. indent, strings.Join(txStrings, "\n"+indent+" "),
  753. indent, data.hash)
  754. }
  755. //-----------------------------------------------------------------------------
  756. // EvidenceData contains any evidence of malicious wrong-doing by validators
  757. type EvidenceData struct {
  758. Evidence EvidenceList `json:"evidence"`
  759. // Volatile
  760. hash tmbytes.HexBytes
  761. }
  762. // Hash returns the hash of the data.
  763. func (data *EvidenceData) Hash() tmbytes.HexBytes {
  764. if data.hash == nil {
  765. data.hash = data.Evidence.Hash()
  766. }
  767. return data.hash
  768. }
  769. // StringIndented returns a string representation of the evidence.
  770. func (data *EvidenceData) StringIndented(indent string) string {
  771. if data == nil {
  772. return "nil-Evidence"
  773. }
  774. evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21))
  775. for i, ev := range data.Evidence {
  776. if i == 20 {
  777. evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  778. break
  779. }
  780. evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  781. }
  782. return fmt.Sprintf(`EvidenceData{
  783. %s %v
  784. %s}#%v`,
  785. indent, strings.Join(evStrings, "\n"+indent+" "),
  786. indent, data.hash)
  787. }
  788. //--------------------------------------------------------------------------------
  789. // BlockID defines the unique ID of a block as its Hash and its PartSetHeader
  790. type BlockID struct {
  791. Hash tmbytes.HexBytes `json:"hash"`
  792. PartsHeader PartSetHeader `json:"parts"`
  793. }
  794. // Equals returns true if the BlockID matches the given BlockID
  795. func (blockID BlockID) Equals(other BlockID) bool {
  796. return bytes.Equal(blockID.Hash, other.Hash) &&
  797. blockID.PartsHeader.Equals(other.PartsHeader)
  798. }
  799. // Key returns a machine-readable string representation of the BlockID
  800. func (blockID BlockID) Key() string {
  801. bz, err := cdc.MarshalBinaryBare(blockID.PartsHeader)
  802. if err != nil {
  803. panic(err)
  804. }
  805. return string(blockID.Hash) + string(bz)
  806. }
  807. // ValidateBasic performs basic validation.
  808. func (blockID BlockID) ValidateBasic() error {
  809. // Hash can be empty in case of POLBlockID in Proposal.
  810. if err := ValidateHash(blockID.Hash); err != nil {
  811. return fmt.Errorf("wrong Hash")
  812. }
  813. if err := blockID.PartsHeader.ValidateBasic(); err != nil {
  814. return fmt.Errorf("wrong PartsHeader: %v", err)
  815. }
  816. return nil
  817. }
  818. // IsZero returns true if this is the BlockID of a nil block.
  819. func (blockID BlockID) IsZero() bool {
  820. return len(blockID.Hash) == 0 &&
  821. blockID.PartsHeader.IsZero()
  822. }
  823. // IsComplete returns true if this is a valid BlockID of a non-nil block.
  824. func (blockID BlockID) IsComplete() bool {
  825. return len(blockID.Hash) == tmhash.Size &&
  826. blockID.PartsHeader.Total > 0 &&
  827. len(blockID.PartsHeader.Hash) == tmhash.Size
  828. }
  829. // String returns a human readable string representation of the BlockID
  830. func (blockID BlockID) String() string {
  831. return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartsHeader)
  832. }