github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/block.go (about)

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