github.com/aakash4dev/cometbft@v0.38.2/types/block.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/cosmos/gogoproto/proto"
    11  	gogotypes "github.com/cosmos/gogoproto/types"
    12  
    13  	"github.com/aakash4dev/cometbft/crypto"
    14  	"github.com/aakash4dev/cometbft/crypto/merkle"
    15  	"github.com/aakash4dev/cometbft/crypto/tmhash"
    16  	"github.com/aakash4dev/cometbft/libs/bits"
    17  	cmtbytes "github.com/aakash4dev/cometbft/libs/bytes"
    18  	cmtmath "github.com/aakash4dev/cometbft/libs/math"
    19  	cmtsync "github.com/aakash4dev/cometbft/libs/sync"
    20  	cmtproto "github.com/aakash4dev/cometbft/proto/tendermint/types"
    21  	cmtversion "github.com/aakash4dev/cometbft/proto/tendermint/version"
    22  	"github.com/aakash4dev/cometbft/version"
    23  )
    24  
    25  const (
    26  	// MaxHeaderBytes is a maximum header size.
    27  	// NOTE: Because app hash can be of arbitrary size, the header is therefore not
    28  	// capped in size and thus this number should be seen as a soft max
    29  	MaxHeaderBytes int64 = 626
    30  
    31  	// MaxOverheadForBlock - maximum overhead to encode a block (up to
    32  	// MaxBlockSizeBytes in size) not including it's parts except Data.
    33  	// This means it also excludes the overhead for individual transactions.
    34  	//
    35  	// Uvarint length of MaxBlockSizeBytes: 4 bytes
    36  	// 2 fields (2 embedded):               2 bytes
    37  	// Uvarint length of Data.Txs:          4 bytes
    38  	// Data.Txs field:                      1 byte
    39  	MaxOverheadForBlock int64 = 11
    40  )
    41  
    42  // Block defines the atomic unit of a CometBFT blockchain.
    43  type Block struct {
    44  	mtx cmtsync.Mutex
    45  
    46  	Header     `json:"header"`
    47  	Data       `json:"data"`
    48  	Evidence   EvidenceData `json:"evidence"`
    49  	LastCommit *Commit      `json:"last_commit"`
    50  }
    51  
    52  // ValidateBasic performs basic validation that doesn't involve state data.
    53  // It checks the internal consistency of the block.
    54  // Further validation is done using state#ValidateBlock.
    55  func (b *Block) ValidateBasic() error {
    56  	if b == nil {
    57  		return errors.New("nil block")
    58  	}
    59  
    60  	b.mtx.Lock()
    61  	defer b.mtx.Unlock()
    62  
    63  	if err := b.Header.ValidateBasic(); err != nil {
    64  		return fmt.Errorf("invalid header: %w", err)
    65  	}
    66  
    67  	// Validate the last commit and its hash.
    68  	if b.LastCommit == nil {
    69  		return errors.New("nil LastCommit")
    70  	}
    71  	if err := b.LastCommit.ValidateBasic(); err != nil {
    72  		return fmt.Errorf("wrong LastCommit: %v", err)
    73  	}
    74  
    75  	if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
    76  		return fmt.Errorf("wrong Header.LastCommitHash. Expected %v, got %v",
    77  			b.LastCommit.Hash(),
    78  			b.LastCommitHash,
    79  		)
    80  	}
    81  
    82  	// NOTE: b.Data.Txs may be nil, but b.Data.Hash() still works fine.
    83  	if !bytes.Equal(b.DataHash, b.Data.Hash()) {
    84  		return fmt.Errorf(
    85  			"wrong Header.DataHash. Expected %v, got %v",
    86  			b.Data.Hash(),
    87  			b.DataHash,
    88  		)
    89  	}
    90  
    91  	// NOTE: b.Evidence.Evidence may be nil, but we're just looping.
    92  	for i, ev := range b.Evidence.Evidence {
    93  		if err := ev.ValidateBasic(); err != nil {
    94  			return fmt.Errorf("invalid evidence (#%d): %v", i, err)
    95  		}
    96  	}
    97  
    98  	if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
    99  		return fmt.Errorf("wrong Header.EvidenceHash. Expected %v, got %v",
   100  			b.EvidenceHash,
   101  			b.Evidence.Hash(),
   102  		)
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  // fillHeader fills in any remaining header fields that are a function of the block data
   109  func (b *Block) fillHeader() {
   110  	if b.LastCommitHash == nil {
   111  		b.LastCommitHash = b.LastCommit.Hash()
   112  	}
   113  	if b.DataHash == nil {
   114  		b.DataHash = b.Data.Hash()
   115  	}
   116  	if b.EvidenceHash == nil {
   117  		b.EvidenceHash = b.Evidence.Hash()
   118  	}
   119  }
   120  
   121  // Hash computes and returns the block hash.
   122  // If the block is incomplete, block hash is nil for safety.
   123  func (b *Block) Hash() cmtbytes.HexBytes {
   124  	if b == nil {
   125  		return nil
   126  	}
   127  	b.mtx.Lock()
   128  	defer b.mtx.Unlock()
   129  
   130  	if b.LastCommit == nil {
   131  		return nil
   132  	}
   133  	b.fillHeader()
   134  	return b.Header.Hash()
   135  }
   136  
   137  // MakePartSet returns a PartSet containing parts of a serialized block.
   138  // This is the form in which the block is gossipped to peers.
   139  // CONTRACT: partSize is greater than zero.
   140  func (b *Block) MakePartSet(partSize uint32) (*PartSet, error) {
   141  	if b == nil {
   142  		return nil, errors.New("nil block")
   143  	}
   144  	b.mtx.Lock()
   145  	defer b.mtx.Unlock()
   146  
   147  	pbb, err := b.ToProto()
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  	bz, err := proto.Marshal(pbb)
   152  	if err != nil {
   153  		return nil, err
   154  	}
   155  	return NewPartSetFromData(bz, partSize), nil
   156  }
   157  
   158  // HashesTo is a convenience function that checks if a block hashes to the given argument.
   159  // Returns false if the block is nil or the hash is empty.
   160  func (b *Block) HashesTo(hash []byte) bool {
   161  	if len(hash) == 0 {
   162  		return false
   163  	}
   164  	if b == nil {
   165  		return false
   166  	}
   167  	return bytes.Equal(b.Hash(), hash)
   168  }
   169  
   170  // Size returns size of the block in bytes.
   171  func (b *Block) Size() int {
   172  	pbb, err := b.ToProto()
   173  	if err != nil {
   174  		return 0
   175  	}
   176  
   177  	return pbb.Size()
   178  }
   179  
   180  // String returns a string representation of the block
   181  //
   182  // See StringIndented.
   183  func (b *Block) String() string {
   184  	return b.StringIndented("")
   185  }
   186  
   187  // StringIndented returns an indented String.
   188  //
   189  // Header
   190  // Data
   191  // Evidence
   192  // LastCommit
   193  // Hash
   194  func (b *Block) StringIndented(indent string) string {
   195  	if b == nil {
   196  		return "nil-Block"
   197  	}
   198  	return fmt.Sprintf(`Block{
   199  %s  %v
   200  %s  %v
   201  %s  %v
   202  %s  %v
   203  %s}#%v`,
   204  		indent, b.Header.StringIndented(indent+"  "),
   205  		indent, b.Data.StringIndented(indent+"  "),
   206  		indent, b.Evidence.StringIndented(indent+"  "),
   207  		indent, b.LastCommit.StringIndented(indent+"  "),
   208  		indent, b.Hash())
   209  }
   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#%X", b.Hash())
   217  }
   218  
   219  // ToProto converts Block to protobuf
   220  func (b *Block) ToProto() (*cmtproto.Block, error) {
   221  	if b == nil {
   222  		return nil, errors.New("nil Block")
   223  	}
   224  
   225  	pb := new(cmtproto.Block)
   226  
   227  	pb.Header = *b.Header.ToProto()
   228  	pb.LastCommit = b.LastCommit.ToProto()
   229  	pb.Data = b.Data.ToProto()
   230  
   231  	protoEvidence, err := b.Evidence.ToProto()
   232  	if err != nil {
   233  		return nil, err
   234  	}
   235  	pb.Evidence = *protoEvidence
   236  
   237  	return pb, nil
   238  }
   239  
   240  // FromProto sets a protobuf Block to the given pointer.
   241  // It returns an error if the block is invalid.
   242  func BlockFromProto(bp *cmtproto.Block) (*Block, error) {
   243  	if bp == nil {
   244  		return nil, errors.New("nil block")
   245  	}
   246  
   247  	b := new(Block)
   248  	h, err := HeaderFromProto(&bp.Header)
   249  	if err != nil {
   250  		return nil, err
   251  	}
   252  	b.Header = h
   253  	data, err := DataFromProto(&bp.Data)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	b.Data = data
   258  	if err := b.Evidence.FromProto(&bp.Evidence); err != nil {
   259  		return nil, err
   260  	}
   261  
   262  	if bp.LastCommit != nil {
   263  		lc, err := CommitFromProto(bp.LastCommit)
   264  		if err != nil {
   265  			return nil, err
   266  		}
   267  		b.LastCommit = lc
   268  	}
   269  
   270  	return b, b.ValidateBasic()
   271  }
   272  
   273  //-----------------------------------------------------------------------------
   274  
   275  // MaxDataBytes returns the maximum size of block's data.
   276  //
   277  // XXX: Panics on negative result.
   278  func MaxDataBytes(maxBytes, evidenceBytes int64, valsCount int) int64 {
   279  	maxDataBytes := maxBytes -
   280  		MaxOverheadForBlock -
   281  		MaxHeaderBytes -
   282  		MaxCommitBytes(valsCount) -
   283  		evidenceBytes
   284  
   285  	if maxDataBytes < 0 {
   286  		panic(fmt.Sprintf(
   287  			"Negative MaxDataBytes. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
   288  			maxBytes,
   289  			-(maxDataBytes - maxBytes),
   290  		))
   291  	}
   292  
   293  	return maxDataBytes
   294  }
   295  
   296  // MaxDataBytesNoEvidence returns the maximum size of block's data when
   297  // evidence count is unknown (will be assumed to be 0).
   298  //
   299  // XXX: Panics on negative result.
   300  func MaxDataBytesNoEvidence(maxBytes int64, valsCount int) int64 {
   301  	maxDataBytes := maxBytes -
   302  		MaxOverheadForBlock -
   303  		MaxHeaderBytes -
   304  		MaxCommitBytes(valsCount)
   305  
   306  	if maxDataBytes < 0 {
   307  		panic(fmt.Sprintf(
   308  			"Negative MaxDataBytesNoEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
   309  			maxBytes,
   310  			-(maxDataBytes - maxBytes),
   311  		))
   312  	}
   313  
   314  	return maxDataBytes
   315  }
   316  
   317  //-----------------------------------------------------------------------------
   318  
   319  // Header defines the structure of a CometBFT block header.
   320  // NOTE: changes to the Header should be duplicated in:
   321  // - header.Hash()
   322  // - abci.Header
   323  // - https://github.com/aakash4dev/cometbft/blob/main/spec/blockchain/blockchain.md
   324  type Header struct {
   325  	// basic block info
   326  	Version cmtversion.Consensus `json:"version"`
   327  	ChainID string               `json:"chain_id"`
   328  	Height  int64                `json:"height"`
   329  	Time    time.Time            `json:"time"`
   330  
   331  	// prev block info
   332  	LastBlockID BlockID `json:"last_block_id"`
   333  
   334  	// hashes of block data
   335  	LastCommitHash cmtbytes.HexBytes `json:"last_commit_hash"` // commit from validators from the last block
   336  	DataHash       cmtbytes.HexBytes `json:"data_hash"`        // transactions
   337  
   338  	// hashes from the app output from the prev block
   339  	ValidatorsHash     cmtbytes.HexBytes `json:"validators_hash"`      // validators for the current block
   340  	NextValidatorsHash cmtbytes.HexBytes `json:"next_validators_hash"` // validators for the next block
   341  	ConsensusHash      cmtbytes.HexBytes `json:"consensus_hash"`       // consensus params for current block
   342  	AppHash            cmtbytes.HexBytes `json:"app_hash"`             // state after txs from the previous block
   343  	// root hash of all results from the txs from the previous block
   344  	// see `DeterministicExecTxResult` to understand which parts of a tx is hashed into here
   345  	LastResultsHash cmtbytes.HexBytes `json:"last_results_hash"`
   346  
   347  	// consensus info
   348  	EvidenceHash    cmtbytes.HexBytes `json:"evidence_hash"`    // evidence included in the block
   349  	ProposerAddress Address           `json:"proposer_address"` // original proposer of the block
   350  }
   351  
   352  // Populate the Header with state-derived data.
   353  // Call this after MakeBlock to complete the Header.
   354  func (h *Header) Populate(
   355  	version cmtversion.Consensus, chainID string,
   356  	timestamp time.Time, lastBlockID BlockID,
   357  	valHash, nextValHash []byte,
   358  	consensusHash, appHash, lastResultsHash []byte,
   359  	proposerAddress Address,
   360  ) {
   361  	h.Version = version
   362  	h.ChainID = chainID
   363  	h.Time = timestamp
   364  	h.LastBlockID = lastBlockID
   365  	h.ValidatorsHash = valHash
   366  	h.NextValidatorsHash = nextValHash
   367  	h.ConsensusHash = consensusHash
   368  	h.AppHash = appHash
   369  	h.LastResultsHash = lastResultsHash
   370  	h.ProposerAddress = proposerAddress
   371  }
   372  
   373  // ValidateBasic performs stateless validation on a Header returning an error
   374  // if any validation fails.
   375  //
   376  // NOTE: Timestamp validation is subtle and handled elsewhere.
   377  func (h Header) ValidateBasic() error {
   378  	if h.Version.Block != version.BlockProtocol {
   379  		return fmt.Errorf("block protocol is incorrect: got: %d, want: %d ", h.Version.Block, version.BlockProtocol)
   380  	}
   381  	if len(h.ChainID) > MaxChainIDLen {
   382  		return fmt.Errorf("chainID is too long; got: %d, max: %d", len(h.ChainID), MaxChainIDLen)
   383  	}
   384  
   385  	if h.Height < 0 {
   386  		return errors.New("negative Height")
   387  	} else if h.Height == 0 {
   388  		return errors.New("zero Height")
   389  	}
   390  
   391  	if err := h.LastBlockID.ValidateBasic(); err != nil {
   392  		return fmt.Errorf("wrong LastBlockID: %w", err)
   393  	}
   394  
   395  	if err := ValidateHash(h.LastCommitHash); err != nil {
   396  		return fmt.Errorf("wrong LastCommitHash: %v", err)
   397  	}
   398  
   399  	if err := ValidateHash(h.DataHash); err != nil {
   400  		return fmt.Errorf("wrong DataHash: %v", err)
   401  	}
   402  
   403  	if err := ValidateHash(h.EvidenceHash); err != nil {
   404  		return fmt.Errorf("wrong EvidenceHash: %v", err)
   405  	}
   406  
   407  	if len(h.ProposerAddress) != crypto.AddressSize {
   408  		return fmt.Errorf(
   409  			"invalid ProposerAddress length; got: %d, expected: %d",
   410  			len(h.ProposerAddress), crypto.AddressSize,
   411  		)
   412  	}
   413  
   414  	// Basic validation of hashes related to application data.
   415  	// Will validate fully against state in state#ValidateBlock.
   416  	if err := ValidateHash(h.ValidatorsHash); err != nil {
   417  		return fmt.Errorf("wrong ValidatorsHash: %v", err)
   418  	}
   419  	if err := ValidateHash(h.NextValidatorsHash); err != nil {
   420  		return fmt.Errorf("wrong NextValidatorsHash: %v", err)
   421  	}
   422  	if err := ValidateHash(h.ConsensusHash); err != nil {
   423  		return fmt.Errorf("wrong ConsensusHash: %v", err)
   424  	}
   425  	// NOTE: AppHash is arbitrary length
   426  	if err := ValidateHash(h.LastResultsHash); err != nil {
   427  		return fmt.Errorf("wrong LastResultsHash: %v", err)
   428  	}
   429  
   430  	return nil
   431  }
   432  
   433  // Hash returns the hash of the header.
   434  // It computes a Merkle tree from the header fields
   435  // ordered as they appear in the Header.
   436  // Returns nil if ValidatorHash is missing,
   437  // since a Header is not valid unless there is
   438  // a ValidatorsHash (corresponding to the validator set).
   439  func (h *Header) Hash() cmtbytes.HexBytes {
   440  	if h == nil || len(h.ValidatorsHash) == 0 {
   441  		return nil
   442  	}
   443  	hbz, err := h.Version.Marshal()
   444  	if err != nil {
   445  		return nil
   446  	}
   447  
   448  	pbt, err := gogotypes.StdTimeMarshal(h.Time)
   449  	if err != nil {
   450  		return nil
   451  	}
   452  
   453  	pbbi := h.LastBlockID.ToProto()
   454  	bzbi, err := pbbi.Marshal()
   455  	if err != nil {
   456  		return nil
   457  	}
   458  	return merkle.HashFromByteSlices([][]byte{
   459  		hbz,
   460  		cdcEncode(h.ChainID),
   461  		cdcEncode(h.Height),
   462  		pbt,
   463  		bzbi,
   464  		cdcEncode(h.LastCommitHash),
   465  		cdcEncode(h.DataHash),
   466  		cdcEncode(h.ValidatorsHash),
   467  		cdcEncode(h.NextValidatorsHash),
   468  		cdcEncode(h.ConsensusHash),
   469  		cdcEncode(h.AppHash),
   470  		cdcEncode(h.LastResultsHash),
   471  		cdcEncode(h.EvidenceHash),
   472  		cdcEncode(h.ProposerAddress),
   473  	})
   474  }
   475  
   476  // StringIndented returns an indented string representation of the header.
   477  func (h *Header) StringIndented(indent string) string {
   478  	if h == nil {
   479  		return "nil-Header"
   480  	}
   481  	return fmt.Sprintf(`Header{
   482  %s  Version:        %v
   483  %s  ChainID:        %v
   484  %s  Height:         %v
   485  %s  Time:           %v
   486  %s  LastBlockID:    %v
   487  %s  LastCommit:     %v
   488  %s  Data:           %v
   489  %s  Validators:     %v
   490  %s  NextValidators: %v
   491  %s  App:            %v
   492  %s  Consensus:      %v
   493  %s  Results:        %v
   494  %s  Evidence:       %v
   495  %s  Proposer:       %v
   496  %s}#%v`,
   497  		indent, h.Version,
   498  		indent, h.ChainID,
   499  		indent, h.Height,
   500  		indent, h.Time,
   501  		indent, h.LastBlockID,
   502  		indent, h.LastCommitHash,
   503  		indent, h.DataHash,
   504  		indent, h.ValidatorsHash,
   505  		indent, h.NextValidatorsHash,
   506  		indent, h.AppHash,
   507  		indent, h.ConsensusHash,
   508  		indent, h.LastResultsHash,
   509  		indent, h.EvidenceHash,
   510  		indent, h.ProposerAddress,
   511  		indent, h.Hash(),
   512  	)
   513  }
   514  
   515  // ToProto converts Header to protobuf
   516  func (h *Header) ToProto() *cmtproto.Header {
   517  	if h == nil {
   518  		return nil
   519  	}
   520  
   521  	return &cmtproto.Header{
   522  		Version:            h.Version,
   523  		ChainID:            h.ChainID,
   524  		Height:             h.Height,
   525  		Time:               h.Time,
   526  		LastBlockId:        h.LastBlockID.ToProto(),
   527  		ValidatorsHash:     h.ValidatorsHash,
   528  		NextValidatorsHash: h.NextValidatorsHash,
   529  		ConsensusHash:      h.ConsensusHash,
   530  		AppHash:            h.AppHash,
   531  		DataHash:           h.DataHash,
   532  		EvidenceHash:       h.EvidenceHash,
   533  		LastResultsHash:    h.LastResultsHash,
   534  		LastCommitHash:     h.LastCommitHash,
   535  		ProposerAddress:    h.ProposerAddress,
   536  	}
   537  }
   538  
   539  // FromProto sets a protobuf Header to the given pointer.
   540  // It returns an error if the header is invalid.
   541  func HeaderFromProto(ph *cmtproto.Header) (Header, error) {
   542  	if ph == nil {
   543  		return Header{}, errors.New("nil Header")
   544  	}
   545  
   546  	h := new(Header)
   547  
   548  	bi, err := BlockIDFromProto(&ph.LastBlockId)
   549  	if err != nil {
   550  		return Header{}, err
   551  	}
   552  
   553  	h.Version = ph.Version
   554  	h.ChainID = ph.ChainID
   555  	h.Height = ph.Height
   556  	h.Time = ph.Time
   557  	h.Height = ph.Height
   558  	h.LastBlockID = *bi
   559  	h.ValidatorsHash = ph.ValidatorsHash
   560  	h.NextValidatorsHash = ph.NextValidatorsHash
   561  	h.ConsensusHash = ph.ConsensusHash
   562  	h.AppHash = ph.AppHash
   563  	h.DataHash = ph.DataHash
   564  	h.EvidenceHash = ph.EvidenceHash
   565  	h.LastResultsHash = ph.LastResultsHash
   566  	h.LastCommitHash = ph.LastCommitHash
   567  	h.ProposerAddress = ph.ProposerAddress
   568  
   569  	return *h, h.ValidateBasic()
   570  }
   571  
   572  //-------------------------------------
   573  
   574  // BlockIDFlag indicates which BlockID the signature is for.
   575  type BlockIDFlag byte
   576  
   577  const (
   578  	// BlockIDFlagAbsent - no vote was received from a validator.
   579  	BlockIDFlagAbsent BlockIDFlag = iota + 1
   580  	// BlockIDFlagCommit - voted for the Commit.BlockID.
   581  	BlockIDFlagCommit
   582  	// BlockIDFlagNil - voted for nil.
   583  	BlockIDFlagNil
   584  )
   585  
   586  const (
   587  	// Max size of commit without any commitSigs -> 82 for BlockID, 8 for Height, 4 for Round.
   588  	MaxCommitOverheadBytes int64 = 94
   589  	// Commit sig size is made up of 64 bytes for the signature, 20 bytes for the address,
   590  	// 1 byte for the flag and 14 bytes for the timestamp
   591  	MaxCommitSigBytes int64 = 109
   592  )
   593  
   594  // CommitSig is a part of the Vote included in a Commit.
   595  type CommitSig struct {
   596  	BlockIDFlag      BlockIDFlag `json:"block_id_flag"`
   597  	ValidatorAddress Address     `json:"validator_address"`
   598  	Timestamp        time.Time   `json:"timestamp"`
   599  	Signature        []byte      `json:"signature"`
   600  }
   601  
   602  func MaxCommitBytes(valCount int) int64 {
   603  	// From the repeated commit sig field
   604  	var protoEncodingOverhead int64 = 2
   605  	return MaxCommitOverheadBytes + ((MaxCommitSigBytes + protoEncodingOverhead) * int64(valCount))
   606  }
   607  
   608  // NewCommitSigAbsent returns new CommitSig with BlockIDFlagAbsent. Other
   609  // fields are all empty.
   610  func NewCommitSigAbsent() CommitSig {
   611  	return CommitSig{
   612  		BlockIDFlag: BlockIDFlagAbsent,
   613  	}
   614  }
   615  
   616  // CommitSig returns a string representation of CommitSig.
   617  //
   618  // 1. first 6 bytes of signature
   619  // 2. first 6 bytes of validator address
   620  // 3. block ID flag
   621  // 4. timestamp
   622  func (cs CommitSig) String() string {
   623  	return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}",
   624  		cmtbytes.Fingerprint(cs.Signature),
   625  		cmtbytes.Fingerprint(cs.ValidatorAddress),
   626  		cs.BlockIDFlag,
   627  		CanonicalTime(cs.Timestamp))
   628  }
   629  
   630  // BlockID returns the Commit's BlockID if CommitSig indicates signing,
   631  // otherwise - empty BlockID.
   632  func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID {
   633  	var blockID BlockID
   634  	switch cs.BlockIDFlag {
   635  	case BlockIDFlagAbsent:
   636  		blockID = BlockID{}
   637  	case BlockIDFlagCommit:
   638  		blockID = commitBlockID
   639  	case BlockIDFlagNil:
   640  		blockID = BlockID{}
   641  	default:
   642  		panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag))
   643  	}
   644  	return blockID
   645  }
   646  
   647  // ValidateBasic performs basic validation.
   648  func (cs CommitSig) ValidateBasic() error {
   649  	switch cs.BlockIDFlag {
   650  	case BlockIDFlagAbsent:
   651  	case BlockIDFlagCommit:
   652  	case BlockIDFlagNil:
   653  	default:
   654  		return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag)
   655  	}
   656  
   657  	switch cs.BlockIDFlag {
   658  	case BlockIDFlagAbsent:
   659  		if len(cs.ValidatorAddress) != 0 {
   660  			return errors.New("validator address is present")
   661  		}
   662  		if !cs.Timestamp.IsZero() {
   663  			return errors.New("time is present")
   664  		}
   665  		if len(cs.Signature) != 0 {
   666  			return errors.New("signature is present")
   667  		}
   668  	default:
   669  		if len(cs.ValidatorAddress) != crypto.AddressSize {
   670  			return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
   671  				crypto.AddressSize,
   672  				len(cs.ValidatorAddress),
   673  			)
   674  		}
   675  		// NOTE: Timestamp validation is subtle and handled elsewhere.
   676  		if len(cs.Signature) == 0 {
   677  			return errors.New("signature is missing")
   678  		}
   679  		if len(cs.Signature) > MaxSignatureSize {
   680  			return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
   681  		}
   682  	}
   683  
   684  	return nil
   685  }
   686  
   687  // ToProto converts CommitSig to protobuf
   688  func (cs *CommitSig) ToProto() *cmtproto.CommitSig {
   689  	if cs == nil {
   690  		return nil
   691  	}
   692  
   693  	return &cmtproto.CommitSig{
   694  		BlockIdFlag:      cmtproto.BlockIDFlag(cs.BlockIDFlag),
   695  		ValidatorAddress: cs.ValidatorAddress,
   696  		Timestamp:        cs.Timestamp,
   697  		Signature:        cs.Signature,
   698  	}
   699  }
   700  
   701  // FromProto sets a protobuf CommitSig to the given pointer.
   702  // It returns an error if the CommitSig is invalid.
   703  func (cs *CommitSig) FromProto(csp cmtproto.CommitSig) error {
   704  	cs.BlockIDFlag = BlockIDFlag(csp.BlockIdFlag)
   705  	cs.ValidatorAddress = csp.ValidatorAddress
   706  	cs.Timestamp = csp.Timestamp
   707  	cs.Signature = csp.Signature
   708  
   709  	return cs.ValidateBasic()
   710  }
   711  
   712  //-------------------------------------
   713  
   714  // ExtendedCommitSig contains a commit signature along with its corresponding
   715  // vote extension and vote extension signature.
   716  type ExtendedCommitSig struct {
   717  	CommitSig                 // Commit signature
   718  	Extension          []byte // Vote extension
   719  	ExtensionSignature []byte // Vote extension signature
   720  }
   721  
   722  // NewExtendedCommitSigAbsent returns new ExtendedCommitSig with
   723  // BlockIDFlagAbsent. Other fields are all empty.
   724  func NewExtendedCommitSigAbsent() ExtendedCommitSig {
   725  	return ExtendedCommitSig{CommitSig: NewCommitSigAbsent()}
   726  }
   727  
   728  // String returns a string representation of an ExtendedCommitSig.
   729  //
   730  // 1. commit sig
   731  // 2. first 6 bytes of vote extension
   732  // 3. first 6 bytes of vote extension signature
   733  func (ecs ExtendedCommitSig) String() string {
   734  	return fmt.Sprintf("ExtendedCommitSig{%s with %X %X}",
   735  		ecs.CommitSig,
   736  		cmtbytes.Fingerprint(ecs.Extension),
   737  		cmtbytes.Fingerprint(ecs.ExtensionSignature),
   738  	)
   739  }
   740  
   741  // ValidateBasic checks whether the structure is well-formed.
   742  func (ecs ExtendedCommitSig) ValidateBasic() error {
   743  	if err := ecs.CommitSig.ValidateBasic(); err != nil {
   744  		return err
   745  	}
   746  
   747  	if ecs.BlockIDFlag == BlockIDFlagCommit {
   748  		if len(ecs.Extension) > MaxVoteExtensionSize {
   749  			return fmt.Errorf("vote extension is too big (max: %d)", MaxVoteExtensionSize)
   750  		}
   751  		if len(ecs.ExtensionSignature) > MaxSignatureSize {
   752  			return fmt.Errorf("vote extension signature is too big (max: %d)", MaxSignatureSize)
   753  		}
   754  		return nil
   755  	}
   756  
   757  	if len(ecs.ExtensionSignature) == 0 && len(ecs.Extension) != 0 {
   758  		return errors.New("vote extension signature absent on vote with extension")
   759  	}
   760  	return nil
   761  }
   762  
   763  // EnsureExtensions validates that a vote extensions signature is present for
   764  // this ExtendedCommitSig.
   765  func (ecs ExtendedCommitSig) EnsureExtension(extEnabled bool) error {
   766  	if extEnabled {
   767  		if ecs.BlockIDFlag == BlockIDFlagCommit && len(ecs.ExtensionSignature) == 0 {
   768  			return fmt.Errorf("vote extension signature is missing; validator addr %s, timestamp %v",
   769  				ecs.ValidatorAddress.String(),
   770  				ecs.Timestamp,
   771  			)
   772  		}
   773  		if ecs.BlockIDFlag != BlockIDFlagCommit && len(ecs.Extension) != 0 {
   774  			return fmt.Errorf("non-commit vote extension present; validator addr %s, timestamp %v",
   775  				ecs.ValidatorAddress.String(),
   776  				ecs.Timestamp,
   777  			)
   778  		}
   779  		if ecs.BlockIDFlag != BlockIDFlagCommit && len(ecs.ExtensionSignature) != 0 {
   780  			return fmt.Errorf("non-commit vote extension signature present; validator addr %s, timestamp %v",
   781  				ecs.ValidatorAddress.String(),
   782  				ecs.Timestamp,
   783  			)
   784  		}
   785  	} else {
   786  		if len(ecs.Extension) != 0 {
   787  			return fmt.Errorf("vote extension present but extensions disabled; validator addr %s, timestamp %v",
   788  				ecs.ValidatorAddress.String(),
   789  				ecs.Timestamp,
   790  			)
   791  		}
   792  		if len(ecs.ExtensionSignature) != 0 {
   793  			return fmt.Errorf("vote extension signature present but extensions disabled; validator addr %s, timestamp %v",
   794  				ecs.ValidatorAddress.String(),
   795  				ecs.Timestamp,
   796  			)
   797  		}
   798  	}
   799  	return nil
   800  }
   801  
   802  // ToProto converts the ExtendedCommitSig to its Protobuf representation.
   803  func (ecs *ExtendedCommitSig) ToProto() *cmtproto.ExtendedCommitSig {
   804  	if ecs == nil {
   805  		return nil
   806  	}
   807  
   808  	return &cmtproto.ExtendedCommitSig{
   809  		BlockIdFlag:        cmtproto.BlockIDFlag(ecs.BlockIDFlag),
   810  		ValidatorAddress:   ecs.ValidatorAddress,
   811  		Timestamp:          ecs.Timestamp,
   812  		Signature:          ecs.Signature,
   813  		Extension:          ecs.Extension,
   814  		ExtensionSignature: ecs.ExtensionSignature,
   815  	}
   816  }
   817  
   818  // FromProto populates the ExtendedCommitSig with values from the given
   819  // Protobuf representation. Returns an error if the ExtendedCommitSig is
   820  // invalid.
   821  func (ecs *ExtendedCommitSig) FromProto(ecsp cmtproto.ExtendedCommitSig) error {
   822  	ecs.BlockIDFlag = BlockIDFlag(ecsp.BlockIdFlag)
   823  	ecs.ValidatorAddress = ecsp.ValidatorAddress
   824  	ecs.Timestamp = ecsp.Timestamp
   825  	ecs.Signature = ecsp.Signature
   826  	ecs.Extension = ecsp.Extension
   827  	ecs.ExtensionSignature = ecsp.ExtensionSignature
   828  
   829  	return ecs.ValidateBasic()
   830  }
   831  
   832  //-------------------------------------
   833  
   834  // Commit contains the evidence that a block was committed by a set of validators.
   835  // NOTE: Commit is empty for height 1, but never nil.
   836  type Commit struct {
   837  	// NOTE: The signatures are in order of address to preserve the bonded
   838  	// ValidatorSet order.
   839  	// Any peer with a block can gossip signatures by index with a peer without
   840  	// recalculating the active ValidatorSet.
   841  	Height     int64       `json:"height"`
   842  	Round      int32       `json:"round"`
   843  	BlockID    BlockID     `json:"block_id"`
   844  	Signatures []CommitSig `json:"signatures"`
   845  
   846  	// Memoized in first call to corresponding method.
   847  	// NOTE: can't memoize in constructor because constructor isn't used for
   848  	// unmarshaling.
   849  	hash cmtbytes.HexBytes
   850  }
   851  
   852  // GetVote converts the CommitSig for the given valIdx to a Vote. Commits do
   853  // not contain vote extensions, so the vote extension and vote extension
   854  // signature will not be present in the returned vote.
   855  // Returns nil if the precommit at valIdx is nil.
   856  // Panics if valIdx >= commit.Size().
   857  func (commit *Commit) GetVote(valIdx int32) *Vote {
   858  	commitSig := commit.Signatures[valIdx]
   859  	return &Vote{
   860  		Type:             cmtproto.PrecommitType,
   861  		Height:           commit.Height,
   862  		Round:            commit.Round,
   863  		BlockID:          commitSig.BlockID(commit.BlockID),
   864  		Timestamp:        commitSig.Timestamp,
   865  		ValidatorAddress: commitSig.ValidatorAddress,
   866  		ValidatorIndex:   valIdx,
   867  		Signature:        commitSig.Signature,
   868  	}
   869  }
   870  
   871  // VoteSignBytes returns the bytes of the Vote corresponding to valIdx for
   872  // signing.
   873  //
   874  // The only unique part is the Timestamp - all other fields signed over are
   875  // otherwise the same for all validators.
   876  //
   877  // Panics if valIdx >= commit.Size().
   878  //
   879  // See VoteSignBytes
   880  func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte {
   881  	v := commit.GetVote(valIdx).ToProto()
   882  	return VoteSignBytes(chainID, v)
   883  }
   884  
   885  // Size returns the number of signatures in the commit.
   886  func (commit *Commit) Size() int {
   887  	if commit == nil {
   888  		return 0
   889  	}
   890  	return len(commit.Signatures)
   891  }
   892  
   893  // ValidateBasic performs basic validation that doesn't involve state data.
   894  // Does not actually check the cryptographic signatures.
   895  func (commit *Commit) ValidateBasic() error {
   896  	if commit.Height < 0 {
   897  		return errors.New("negative Height")
   898  	}
   899  	if commit.Round < 0 {
   900  		return errors.New("negative Round")
   901  	}
   902  
   903  	if commit.Height >= 1 {
   904  		if commit.BlockID.IsZero() {
   905  			return errors.New("commit cannot be for nil block")
   906  		}
   907  
   908  		if len(commit.Signatures) == 0 {
   909  			return errors.New("no signatures in commit")
   910  		}
   911  		for i, commitSig := range commit.Signatures {
   912  			if err := commitSig.ValidateBasic(); err != nil {
   913  				return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
   914  			}
   915  		}
   916  	}
   917  	return nil
   918  }
   919  
   920  // Hash returns the hash of the commit
   921  func (commit *Commit) Hash() cmtbytes.HexBytes {
   922  	if commit == nil {
   923  		return nil
   924  	}
   925  	if commit.hash == nil {
   926  		bs := make([][]byte, len(commit.Signatures))
   927  		for i, commitSig := range commit.Signatures {
   928  			pbcs := commitSig.ToProto()
   929  			bz, err := pbcs.Marshal()
   930  			if err != nil {
   931  				panic(err)
   932  			}
   933  
   934  			bs[i] = bz
   935  		}
   936  		commit.hash = merkle.HashFromByteSlices(bs)
   937  	}
   938  	return commit.hash
   939  }
   940  
   941  // WrappedExtendedCommit wraps a commit as an ExtendedCommit.
   942  // The VoteExtension fields of the resulting value will by nil.
   943  // Wrapping a Commit as an ExtendedCommit is useful when an API
   944  // requires an ExtendedCommit wire type but does not
   945  // need the VoteExtension data.
   946  func (commit *Commit) WrappedExtendedCommit() *ExtendedCommit {
   947  	cs := make([]ExtendedCommitSig, len(commit.Signatures))
   948  	for idx, s := range commit.Signatures {
   949  		cs[idx] = ExtendedCommitSig{
   950  			CommitSig: s,
   951  		}
   952  	}
   953  	return &ExtendedCommit{
   954  		Height:             commit.Height,
   955  		Round:              commit.Round,
   956  		BlockID:            commit.BlockID,
   957  		ExtendedSignatures: cs,
   958  	}
   959  }
   960  
   961  // StringIndented returns a string representation of the commit.
   962  func (commit *Commit) StringIndented(indent string) string {
   963  	if commit == nil {
   964  		return "nil-Commit"
   965  	}
   966  	commitSigStrings := make([]string, len(commit.Signatures))
   967  	for i, commitSig := range commit.Signatures {
   968  		commitSigStrings[i] = commitSig.String()
   969  	}
   970  	return fmt.Sprintf(`Commit{
   971  %s  Height:     %d
   972  %s  Round:      %d
   973  %s  BlockID:    %v
   974  %s  Signatures:
   975  %s    %v
   976  %s}#%v`,
   977  		indent, commit.Height,
   978  		indent, commit.Round,
   979  		indent, commit.BlockID,
   980  		indent,
   981  		indent, strings.Join(commitSigStrings, "\n"+indent+"    "),
   982  		indent, commit.hash)
   983  }
   984  
   985  // ToProto converts Commit to protobuf
   986  func (commit *Commit) ToProto() *cmtproto.Commit {
   987  	if commit == nil {
   988  		return nil
   989  	}
   990  
   991  	c := new(cmtproto.Commit)
   992  	sigs := make([]cmtproto.CommitSig, len(commit.Signatures))
   993  	for i := range commit.Signatures {
   994  		sigs[i] = *commit.Signatures[i].ToProto()
   995  	}
   996  	c.Signatures = sigs
   997  
   998  	c.Height = commit.Height
   999  	c.Round = commit.Round
  1000  	c.BlockID = commit.BlockID.ToProto()
  1001  
  1002  	return c
  1003  }
  1004  
  1005  // FromProto sets a protobuf Commit to the given pointer.
  1006  // It returns an error if the commit is invalid.
  1007  func CommitFromProto(cp *cmtproto.Commit) (*Commit, error) {
  1008  	if cp == nil {
  1009  		return nil, errors.New("nil Commit")
  1010  	}
  1011  
  1012  	var (
  1013  		commit = new(Commit)
  1014  	)
  1015  
  1016  	bi, err := BlockIDFromProto(&cp.BlockID)
  1017  	if err != nil {
  1018  		return nil, err
  1019  	}
  1020  
  1021  	sigs := make([]CommitSig, len(cp.Signatures))
  1022  	for i := range cp.Signatures {
  1023  		if err := sigs[i].FromProto(cp.Signatures[i]); err != nil {
  1024  			return nil, err
  1025  		}
  1026  	}
  1027  	commit.Signatures = sigs
  1028  
  1029  	commit.Height = cp.Height
  1030  	commit.Round = cp.Round
  1031  	commit.BlockID = *bi
  1032  
  1033  	return commit, commit.ValidateBasic()
  1034  }
  1035  
  1036  //-------------------------------------
  1037  
  1038  // ExtendedCommit is similar to Commit, except that its signatures also retain
  1039  // their corresponding vote extensions and vote extension signatures.
  1040  type ExtendedCommit struct {
  1041  	Height             int64
  1042  	Round              int32
  1043  	BlockID            BlockID
  1044  	ExtendedSignatures []ExtendedCommitSig
  1045  
  1046  	bitArray *bits.BitArray
  1047  }
  1048  
  1049  // Clone creates a deep copy of this extended commit.
  1050  func (ec *ExtendedCommit) Clone() *ExtendedCommit {
  1051  	sigs := make([]ExtendedCommitSig, len(ec.ExtendedSignatures))
  1052  	copy(sigs, ec.ExtendedSignatures)
  1053  	ecc := *ec
  1054  	ecc.ExtendedSignatures = sigs
  1055  	return &ecc
  1056  }
  1057  
  1058  // ToExtendedVoteSet constructs a VoteSet from the Commit and validator set.
  1059  // Panics if signatures from the ExtendedCommit can't be added to the voteset.
  1060  // Panics if any of the votes have invalid or absent vote extension data.
  1061  // Inverse of VoteSet.MakeExtendedCommit().
  1062  func (ec *ExtendedCommit) ToExtendedVoteSet(chainID string, vals *ValidatorSet) *VoteSet {
  1063  	voteSet := NewExtendedVoteSet(chainID, ec.Height, ec.Round, cmtproto.PrecommitType, vals)
  1064  	ec.addSigsToVoteSet(voteSet)
  1065  	return voteSet
  1066  }
  1067  
  1068  // addSigsToVoteSet adds all of the signature to voteSet.
  1069  func (ec *ExtendedCommit) addSigsToVoteSet(voteSet *VoteSet) {
  1070  	for idx, ecs := range ec.ExtendedSignatures {
  1071  		if ecs.BlockIDFlag == BlockIDFlagAbsent {
  1072  			continue // OK, some precommits can be missing.
  1073  		}
  1074  		vote := ec.GetExtendedVote(int32(idx))
  1075  		if err := vote.ValidateBasic(); err != nil {
  1076  			panic(fmt.Errorf("failed to validate vote reconstructed from LastCommit: %w", err))
  1077  		}
  1078  		added, err := voteSet.AddVote(vote)
  1079  		if !added || err != nil {
  1080  			panic(fmt.Errorf("failed to reconstruct vote set from extended commit: %w", err))
  1081  		}
  1082  	}
  1083  }
  1084  
  1085  // ToVoteSet constructs a VoteSet from the Commit and validator set.
  1086  // Panics if signatures from the commit can't be added to the voteset.
  1087  // Inverse of VoteSet.MakeCommit().
  1088  func (commit *Commit) ToVoteSet(chainID string, vals *ValidatorSet) *VoteSet {
  1089  	voteSet := NewVoteSet(chainID, commit.Height, commit.Round, cmtproto.PrecommitType, vals)
  1090  	for idx, cs := range commit.Signatures {
  1091  		if cs.BlockIDFlag == BlockIDFlagAbsent {
  1092  			continue // OK, some precommits can be missing.
  1093  		}
  1094  		vote := commit.GetVote(int32(idx))
  1095  		if err := vote.ValidateBasic(); err != nil {
  1096  			panic(fmt.Errorf("failed to validate vote reconstructed from commit: %w", err))
  1097  		}
  1098  		added, err := voteSet.AddVote(vote)
  1099  		if !added || err != nil {
  1100  			panic(fmt.Errorf("failed to reconstruct vote set from commit: %w", err))
  1101  		}
  1102  	}
  1103  	return voteSet
  1104  }
  1105  
  1106  // EnsureExtensions validates that a vote extensions signature is present for
  1107  // every ExtendedCommitSig in the ExtendedCommit.
  1108  func (ec *ExtendedCommit) EnsureExtensions(extEnabled bool) error {
  1109  	for _, ecs := range ec.ExtendedSignatures {
  1110  		if err := ecs.EnsureExtension(extEnabled); err != nil {
  1111  			return err
  1112  		}
  1113  	}
  1114  	return nil
  1115  }
  1116  
  1117  // ToCommit converts an ExtendedCommit to a Commit by removing all vote
  1118  // extension-related fields.
  1119  func (ec *ExtendedCommit) ToCommit() *Commit {
  1120  	cs := make([]CommitSig, len(ec.ExtendedSignatures))
  1121  	for idx, ecs := range ec.ExtendedSignatures {
  1122  		cs[idx] = ecs.CommitSig
  1123  	}
  1124  	return &Commit{
  1125  		Height:     ec.Height,
  1126  		Round:      ec.Round,
  1127  		BlockID:    ec.BlockID,
  1128  		Signatures: cs,
  1129  	}
  1130  }
  1131  
  1132  // GetExtendedVote converts the ExtendedCommitSig for the given validator
  1133  // index to a Vote with a vote extensions.
  1134  // It panics if valIndex is out of range.
  1135  func (ec *ExtendedCommit) GetExtendedVote(valIndex int32) *Vote {
  1136  	ecs := ec.ExtendedSignatures[valIndex]
  1137  	return &Vote{
  1138  		Type:               cmtproto.PrecommitType,
  1139  		Height:             ec.Height,
  1140  		Round:              ec.Round,
  1141  		BlockID:            ecs.BlockID(ec.BlockID),
  1142  		Timestamp:          ecs.Timestamp,
  1143  		ValidatorAddress:   ecs.ValidatorAddress,
  1144  		ValidatorIndex:     valIndex,
  1145  		Signature:          ecs.Signature,
  1146  		Extension:          ecs.Extension,
  1147  		ExtensionSignature: ecs.ExtensionSignature,
  1148  	}
  1149  }
  1150  
  1151  // Type returns the vote type of the extended commit, which is always
  1152  // VoteTypePrecommit
  1153  // Implements VoteSetReader.
  1154  func (ec *ExtendedCommit) Type() byte { return byte(cmtproto.PrecommitType) }
  1155  
  1156  // GetHeight returns height of the extended commit.
  1157  // Implements VoteSetReader.
  1158  func (ec *ExtendedCommit) GetHeight() int64 { return ec.Height }
  1159  
  1160  // GetRound returns height of the extended commit.
  1161  // Implements VoteSetReader.
  1162  func (ec *ExtendedCommit) GetRound() int32 { return ec.Round }
  1163  
  1164  // Size returns the number of signatures in the extended commit.
  1165  // Implements VoteSetReader.
  1166  func (ec *ExtendedCommit) Size() int {
  1167  	if ec == nil {
  1168  		return 0
  1169  	}
  1170  	return len(ec.ExtendedSignatures)
  1171  }
  1172  
  1173  // BitArray returns a BitArray of which validators voted for BlockID or nil in
  1174  // this extended commit.
  1175  // Implements VoteSetReader.
  1176  func (ec *ExtendedCommit) BitArray() *bits.BitArray {
  1177  	if ec.bitArray == nil {
  1178  		ec.bitArray = bits.NewBitArray(len(ec.ExtendedSignatures))
  1179  		for i, extCommitSig := range ec.ExtendedSignatures {
  1180  			// TODO: need to check the BlockID otherwise we could be counting conflicts,
  1181  			//       not just the one with +2/3 !
  1182  			ec.bitArray.SetIndex(i, extCommitSig.BlockIDFlag != BlockIDFlagAbsent)
  1183  		}
  1184  	}
  1185  	return ec.bitArray
  1186  }
  1187  
  1188  // GetByIndex returns the vote corresponding to a given validator index.
  1189  // Panics if `index >= extCommit.Size()`.
  1190  // Implements VoteSetReader.
  1191  func (ec *ExtendedCommit) GetByIndex(valIdx int32) *Vote {
  1192  	return ec.GetExtendedVote(valIdx)
  1193  }
  1194  
  1195  // IsCommit returns true if there is at least one signature.
  1196  // Implements VoteSetReader.
  1197  func (ec *ExtendedCommit) IsCommit() bool {
  1198  	return len(ec.ExtendedSignatures) != 0
  1199  }
  1200  
  1201  // ValidateBasic checks whether the extended commit is well-formed. Does not
  1202  // actually check the cryptographic signatures.
  1203  func (ec *ExtendedCommit) ValidateBasic() error {
  1204  	if ec.Height < 0 {
  1205  		return errors.New("negative Height")
  1206  	}
  1207  	if ec.Round < 0 {
  1208  		return errors.New("negative Round")
  1209  	}
  1210  
  1211  	if ec.Height >= 1 {
  1212  		if ec.BlockID.IsZero() {
  1213  			return errors.New("extended commit cannot be for nil block")
  1214  		}
  1215  
  1216  		if len(ec.ExtendedSignatures) == 0 {
  1217  			return errors.New("no signatures in commit")
  1218  		}
  1219  		for i, extCommitSig := range ec.ExtendedSignatures {
  1220  			if err := extCommitSig.ValidateBasic(); err != nil {
  1221  				return fmt.Errorf("wrong ExtendedCommitSig #%d: %v", i, err)
  1222  			}
  1223  		}
  1224  	}
  1225  	return nil
  1226  }
  1227  
  1228  // ToProto converts ExtendedCommit to protobuf
  1229  func (ec *ExtendedCommit) ToProto() *cmtproto.ExtendedCommit {
  1230  	if ec == nil {
  1231  		return nil
  1232  	}
  1233  
  1234  	c := new(cmtproto.ExtendedCommit)
  1235  	sigs := make([]cmtproto.ExtendedCommitSig, len(ec.ExtendedSignatures))
  1236  	for i := range ec.ExtendedSignatures {
  1237  		sigs[i] = *ec.ExtendedSignatures[i].ToProto()
  1238  	}
  1239  	c.ExtendedSignatures = sigs
  1240  
  1241  	c.Height = ec.Height
  1242  	c.Round = ec.Round
  1243  	c.BlockID = ec.BlockID.ToProto()
  1244  
  1245  	return c
  1246  }
  1247  
  1248  // ExtendedCommitFromProto constructs an ExtendedCommit from the given Protobuf
  1249  // representation. It returns an error if the extended commit is invalid.
  1250  func ExtendedCommitFromProto(ecp *cmtproto.ExtendedCommit) (*ExtendedCommit, error) {
  1251  	if ecp == nil {
  1252  		return nil, errors.New("nil ExtendedCommit")
  1253  	}
  1254  
  1255  	extCommit := new(ExtendedCommit)
  1256  
  1257  	bi, err := BlockIDFromProto(&ecp.BlockID)
  1258  	if err != nil {
  1259  		return nil, err
  1260  	}
  1261  
  1262  	sigs := make([]ExtendedCommitSig, len(ecp.ExtendedSignatures))
  1263  	for i := range ecp.ExtendedSignatures {
  1264  		if err := sigs[i].FromProto(ecp.ExtendedSignatures[i]); err != nil {
  1265  			return nil, err
  1266  		}
  1267  	}
  1268  	extCommit.ExtendedSignatures = sigs
  1269  	extCommit.Height = ecp.Height
  1270  	extCommit.Round = ecp.Round
  1271  	extCommit.BlockID = *bi
  1272  
  1273  	return extCommit, extCommit.ValidateBasic()
  1274  }
  1275  
  1276  //-------------------------------------
  1277  
  1278  // Data contains the set of transactions included in the block
  1279  type Data struct {
  1280  
  1281  	// Txs that will be applied by state @ block.Height+1.
  1282  	// NOTE: not all txs here are valid.  We're just agreeing on the order first.
  1283  	// This means that block.AppHash does not include these txs.
  1284  	Txs Txs `json:"txs"`
  1285  
  1286  	// Volatile
  1287  	hash cmtbytes.HexBytes
  1288  }
  1289  
  1290  // Hash returns the hash of the data
  1291  func (data *Data) Hash() cmtbytes.HexBytes {
  1292  	if data == nil {
  1293  		return (Txs{}).Hash()
  1294  	}
  1295  	if data.hash == nil {
  1296  		data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  1297  	}
  1298  	return data.hash
  1299  }
  1300  
  1301  // StringIndented returns an indented string representation of the transactions.
  1302  func (data *Data) StringIndented(indent string) string {
  1303  	if data == nil {
  1304  		return "nil-Data"
  1305  	}
  1306  	txStrings := make([]string, cmtmath.MinInt(len(data.Txs), 21))
  1307  	for i, tx := range data.Txs {
  1308  		if i == 20 {
  1309  			txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  1310  			break
  1311  		}
  1312  		txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  1313  	}
  1314  	return fmt.Sprintf(`Data{
  1315  %s  %v
  1316  %s}#%v`,
  1317  		indent, strings.Join(txStrings, "\n"+indent+"  "),
  1318  		indent, data.hash)
  1319  }
  1320  
  1321  // ToProto converts Data to protobuf
  1322  func (data *Data) ToProto() cmtproto.Data {
  1323  	tp := new(cmtproto.Data)
  1324  
  1325  	if len(data.Txs) > 0 {
  1326  		txBzs := make([][]byte, len(data.Txs))
  1327  		for i := range data.Txs {
  1328  			txBzs[i] = data.Txs[i]
  1329  		}
  1330  		tp.Txs = txBzs
  1331  	}
  1332  
  1333  	return *tp
  1334  }
  1335  
  1336  // DataFromProto takes a protobuf representation of Data &
  1337  // returns the native type.
  1338  func DataFromProto(dp *cmtproto.Data) (Data, error) {
  1339  	if dp == nil {
  1340  		return Data{}, errors.New("nil data")
  1341  	}
  1342  	data := new(Data)
  1343  
  1344  	if len(dp.Txs) > 0 {
  1345  		txBzs := make(Txs, len(dp.Txs))
  1346  		for i := range dp.Txs {
  1347  			txBzs[i] = Tx(dp.Txs[i])
  1348  		}
  1349  		data.Txs = txBzs
  1350  	} else {
  1351  		data.Txs = Txs{}
  1352  	}
  1353  
  1354  	return *data, nil
  1355  }
  1356  
  1357  //-----------------------------------------------------------------------------
  1358  
  1359  // EvidenceData contains any evidence of malicious wrong-doing by validators
  1360  type EvidenceData struct {
  1361  	Evidence EvidenceList `json:"evidence"`
  1362  
  1363  	// Volatile. Used as cache
  1364  	hash     cmtbytes.HexBytes
  1365  	byteSize int64
  1366  }
  1367  
  1368  // Hash returns the hash of the data.
  1369  func (data *EvidenceData) Hash() cmtbytes.HexBytes {
  1370  	if data.hash == nil {
  1371  		data.hash = data.Evidence.Hash()
  1372  	}
  1373  	return data.hash
  1374  }
  1375  
  1376  // ByteSize returns the total byte size of all the evidence
  1377  func (data *EvidenceData) ByteSize() int64 {
  1378  	if data.byteSize == 0 && len(data.Evidence) != 0 {
  1379  		pb, err := data.ToProto()
  1380  		if err != nil {
  1381  			panic(err)
  1382  		}
  1383  		data.byteSize = int64(pb.Size())
  1384  	}
  1385  	return data.byteSize
  1386  }
  1387  
  1388  // StringIndented returns a string representation of the evidence.
  1389  func (data *EvidenceData) StringIndented(indent string) string {
  1390  	if data == nil {
  1391  		return "nil-Evidence"
  1392  	}
  1393  	evStrings := make([]string, cmtmath.MinInt(len(data.Evidence), 21))
  1394  	for i, ev := range data.Evidence {
  1395  		if i == 20 {
  1396  			evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  1397  			break
  1398  		}
  1399  		evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  1400  	}
  1401  	return fmt.Sprintf(`EvidenceData{
  1402  %s  %v
  1403  %s}#%v`,
  1404  		indent, strings.Join(evStrings, "\n"+indent+"  "),
  1405  		indent, data.hash)
  1406  }
  1407  
  1408  // ToProto converts EvidenceData to protobuf
  1409  func (data *EvidenceData) ToProto() (*cmtproto.EvidenceList, error) {
  1410  	if data == nil {
  1411  		return nil, errors.New("nil evidence data")
  1412  	}
  1413  
  1414  	evi := new(cmtproto.EvidenceList)
  1415  	eviBzs := make([]cmtproto.Evidence, len(data.Evidence))
  1416  	for i := range data.Evidence {
  1417  		protoEvi, err := EvidenceToProto(data.Evidence[i])
  1418  		if err != nil {
  1419  			return nil, err
  1420  		}
  1421  		eviBzs[i] = *protoEvi
  1422  	}
  1423  	evi.Evidence = eviBzs
  1424  
  1425  	return evi, nil
  1426  }
  1427  
  1428  // FromProto sets a protobuf EvidenceData to the given pointer.
  1429  func (data *EvidenceData) FromProto(eviData *cmtproto.EvidenceList) error {
  1430  	if eviData == nil {
  1431  		return errors.New("nil evidenceData")
  1432  	}
  1433  
  1434  	eviBzs := make(EvidenceList, len(eviData.Evidence))
  1435  	for i := range eviData.Evidence {
  1436  		evi, err := EvidenceFromProto(&eviData.Evidence[i])
  1437  		if err != nil {
  1438  			return err
  1439  		}
  1440  		eviBzs[i] = evi
  1441  	}
  1442  	data.Evidence = eviBzs
  1443  	data.byteSize = int64(eviData.Size())
  1444  
  1445  	return nil
  1446  }
  1447  
  1448  //--------------------------------------------------------------------------------
  1449  
  1450  // BlockID
  1451  type BlockID struct {
  1452  	Hash          cmtbytes.HexBytes `json:"hash"`
  1453  	PartSetHeader PartSetHeader     `json:"parts"`
  1454  }
  1455  
  1456  // Equals returns true if the BlockID matches the given BlockID
  1457  func (blockID BlockID) Equals(other BlockID) bool {
  1458  	return bytes.Equal(blockID.Hash, other.Hash) &&
  1459  		blockID.PartSetHeader.Equals(other.PartSetHeader)
  1460  }
  1461  
  1462  // Key returns a machine-readable string representation of the BlockID
  1463  func (blockID BlockID) Key() string {
  1464  	pbph := blockID.PartSetHeader.ToProto()
  1465  	bz, err := pbph.Marshal()
  1466  	if err != nil {
  1467  		panic(err)
  1468  	}
  1469  
  1470  	return fmt.Sprint(string(blockID.Hash), string(bz))
  1471  }
  1472  
  1473  // ValidateBasic performs basic validation.
  1474  func (blockID BlockID) ValidateBasic() error {
  1475  	// Hash can be empty in case of POLBlockID in Proposal.
  1476  	if err := ValidateHash(blockID.Hash); err != nil {
  1477  		return fmt.Errorf("wrong Hash")
  1478  	}
  1479  	if err := blockID.PartSetHeader.ValidateBasic(); err != nil {
  1480  		return fmt.Errorf("wrong PartSetHeader: %v", err)
  1481  	}
  1482  	return nil
  1483  }
  1484  
  1485  // IsZero returns true if this is the BlockID of a nil block.
  1486  func (blockID BlockID) IsZero() bool {
  1487  	return len(blockID.Hash) == 0 &&
  1488  		blockID.PartSetHeader.IsZero()
  1489  }
  1490  
  1491  // IsComplete returns true if this is a valid BlockID of a non-nil block.
  1492  func (blockID BlockID) IsComplete() bool {
  1493  	return len(blockID.Hash) == tmhash.Size &&
  1494  		blockID.PartSetHeader.Total > 0 &&
  1495  		len(blockID.PartSetHeader.Hash) == tmhash.Size
  1496  }
  1497  
  1498  // String returns a human readable string representation of the BlockID.
  1499  //
  1500  // 1. hash
  1501  // 2. part set header
  1502  //
  1503  // See PartSetHeader#String
  1504  func (blockID BlockID) String() string {
  1505  	return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartSetHeader)
  1506  }
  1507  
  1508  // ToProto converts BlockID to protobuf
  1509  func (blockID *BlockID) ToProto() cmtproto.BlockID {
  1510  	if blockID == nil {
  1511  		return cmtproto.BlockID{}
  1512  	}
  1513  
  1514  	return cmtproto.BlockID{
  1515  		Hash:          blockID.Hash,
  1516  		PartSetHeader: blockID.PartSetHeader.ToProto(),
  1517  	}
  1518  }
  1519  
  1520  // FromProto sets a protobuf BlockID to the given pointer.
  1521  // It returns an error if the block id is invalid.
  1522  func BlockIDFromProto(bID *cmtproto.BlockID) (*BlockID, error) {
  1523  	if bID == nil {
  1524  		return nil, errors.New("nil BlockID")
  1525  	}
  1526  
  1527  	blockID := new(BlockID)
  1528  	ph, err := PartSetHeaderFromProto(&bID.PartSetHeader)
  1529  	if err != nil {
  1530  		return nil, err
  1531  	}
  1532  
  1533  	blockID.PartSetHeader = *ph
  1534  	blockID.Hash = bID.Hash
  1535  
  1536  	return blockID, blockID.ValidateBasic()
  1537  }
  1538  
  1539  // ProtoBlockIDIsNil is similar to the IsNil function on BlockID, but for the
  1540  // Protobuf representation.
  1541  func ProtoBlockIDIsNil(bID *cmtproto.BlockID) bool {
  1542  	return len(bID.Hash) == 0 && ProtoPartSetHeaderIsZero(&bID.PartSetHeader)
  1543  }