github.com/adoriasoft/tendermint@v0.34.0-dev1.0.20200722151356-96d84601a75a/types/block.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/gogo/protobuf/proto"
    11  	gogotypes "github.com/gogo/protobuf/types"
    12  
    13  	"github.com/tendermint/tendermint/crypto"
    14  	"github.com/tendermint/tendermint/crypto/merkle"
    15  	"github.com/tendermint/tendermint/crypto/tmhash"
    16  	"github.com/tendermint/tendermint/libs/bits"
    17  	tmbytes "github.com/tendermint/tendermint/libs/bytes"
    18  	tmmath "github.com/tendermint/tendermint/libs/math"
    19  	tmsync "github.com/tendermint/tendermint/libs/sync"
    20  	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
    21  	tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
    22  )
    23  
    24  const (
    25  	// MaxHeaderBytes is a maximum header size.
    26  	MaxHeaderBytes int64 = 626
    27  
    28  	// MaxOverheadForBlock - maximum overhead to encode a block (up to
    29  	// MaxBlockSizeBytes in size) not including it's parts except Data.
    30  	// This means it also excludes the overhead for individual transactions.
    31  	//
    32  	// Uvarint length of MaxBlockSizeBytes: 4 bytes
    33  	// 2 fields (2 embedded):               2 bytes
    34  	// Uvarint length of Data.Txs:          4 bytes
    35  	// Data.Txs field:                      1 byte
    36  	MaxOverheadForBlock int64 = 11
    37  )
    38  
    39  // Block defines the atomic unit of a Tendermint blockchain.
    40  type Block struct {
    41  	mtx tmsync.Mutex
    42  
    43  	Header     `json:"header"`
    44  	Data       `json:"data"`
    45  	Evidence   EvidenceData `json:"evidence"`
    46  	LastCommit *Commit      `json:"last_commit"`
    47  }
    48  
    49  // ValidateBasic performs basic validation that doesn't involve state data.
    50  // It checks the internal consistency of the block.
    51  // Further validation is done using state#ValidateBlock.
    52  func (b *Block) ValidateBasic() error {
    53  	if b == nil {
    54  		return errors.New("nil block")
    55  	}
    56  
    57  	b.mtx.Lock()
    58  	defer b.mtx.Unlock()
    59  
    60  	if err := b.Header.ValidateBasic(); err != nil {
    61  		return fmt.Errorf("invalid header: %w", err)
    62  	}
    63  
    64  	// Validate the last commit and its hash.
    65  	if b.LastCommit == nil {
    66  		return errors.New("nil LastCommit")
    67  	}
    68  	if b.Header.Height > 1 {
    69  		if err := b.LastCommit.ValidateBasic(); err != nil {
    70  			return fmt.Errorf("wrong LastCommit: %v", err)
    71  		}
    72  	}
    73  
    74  	if !bytes.Equal(b.LastCommitHash, b.LastCommit.Hash()) {
    75  		return fmt.Errorf("wrong Header.LastCommitHash. Expected %v, got %v",
    76  			b.LastCommit.Hash(),
    77  			b.LastCommitHash,
    78  		)
    79  	}
    80  
    81  	// NOTE: b.Data.Txs may be nil, but b.Data.Hash() still works fine.
    82  	if !bytes.Equal(b.DataHash, b.Data.Hash()) {
    83  		return fmt.Errorf(
    84  			"wrong Header.DataHash. Expected %v, got %v",
    85  			b.Data.Hash(),
    86  			b.DataHash,
    87  		)
    88  	}
    89  
    90  	// NOTE: b.Evidence.Evidence may be nil, but we're just looping.
    91  	for i, ev := range b.Evidence.Evidence {
    92  		switch ev.(type) {
    93  		case *ConflictingHeadersEvidence:
    94  			// ConflictingHeadersEvidence must be broken up in pieces and never
    95  			// committed as a single piece.
    96  			return fmt.Errorf("found ConflictingHeadersEvidence (#%d)", i)
    97  		case *PotentialAmnesiaEvidence:
    98  			// PotentialAmnesiaEvidence does not contribute to anything on its own, so
    99  			// reject it as well.
   100  			return fmt.Errorf("found PotentialAmnesiaEvidence (#%d)", i)
   101  		}
   102  
   103  		if err := ev.ValidateBasic(); err != nil {
   104  			return fmt.Errorf("invalid evidence (#%d): %v", i, err)
   105  		}
   106  	}
   107  
   108  	if !bytes.Equal(b.EvidenceHash, b.Evidence.Hash()) {
   109  		return fmt.Errorf("wrong Header.EvidenceHash. Expected %v, got %v",
   110  			b.EvidenceHash,
   111  			b.Evidence.Hash(),
   112  		)
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  // fillHeader fills in any remaining header fields that are a function of the block data
   119  func (b *Block) fillHeader() {
   120  	if b.LastCommitHash == nil {
   121  		b.LastCommitHash = b.LastCommit.Hash()
   122  	}
   123  	if b.DataHash == nil {
   124  		b.DataHash = b.Data.Hash()
   125  	}
   126  	if b.EvidenceHash == nil {
   127  		b.EvidenceHash = b.Evidence.Hash()
   128  	}
   129  }
   130  
   131  // Hash computes and returns the block hash.
   132  // If the block is incomplete, block hash is nil for safety.
   133  func (b *Block) Hash() tmbytes.HexBytes {
   134  	if b == nil {
   135  		return nil
   136  	}
   137  	b.mtx.Lock()
   138  	defer b.mtx.Unlock()
   139  
   140  	if b.LastCommit == nil {
   141  		return nil
   142  	}
   143  	b.fillHeader()
   144  	return b.Header.Hash()
   145  }
   146  
   147  // MakePartSet returns a PartSet containing parts of a serialized block.
   148  // This is the form in which the block is gossipped to peers.
   149  // CONTRACT: partSize is greater than zero.
   150  func (b *Block) MakePartSet(partSize uint32) *PartSet {
   151  	if b == nil {
   152  		return nil
   153  	}
   154  	b.mtx.Lock()
   155  	defer b.mtx.Unlock()
   156  
   157  	pbb, err := b.ToProto()
   158  	if err != nil {
   159  		panic(err)
   160  	}
   161  	bz, err := proto.Marshal(pbb)
   162  	if err != nil {
   163  		panic(err)
   164  	}
   165  	return NewPartSetFromData(bz, partSize)
   166  }
   167  
   168  // HashesTo is a convenience function that checks if a block hashes to the given argument.
   169  // Returns false if the block is nil or the hash is empty.
   170  func (b *Block) HashesTo(hash []byte) bool {
   171  	if len(hash) == 0 {
   172  		return false
   173  	}
   174  	if b == nil {
   175  		return false
   176  	}
   177  	return bytes.Equal(b.Hash(), hash)
   178  }
   179  
   180  // Size returns size of the block in bytes.
   181  func (b *Block) Size() int {
   182  	pbb, err := b.ToProto()
   183  	if err != nil {
   184  		return 0
   185  	}
   186  
   187  	return pbb.Size()
   188  }
   189  
   190  // String returns a string representation of the block
   191  func (b *Block) String() string {
   192  	return b.StringIndented("")
   193  }
   194  
   195  // StringIndented returns a string representation of the block
   196  func (b *Block) StringIndented(indent string) string {
   197  	if b == nil {
   198  		return "nil-Block"
   199  	}
   200  	return fmt.Sprintf(`Block{
   201  %s  %v
   202  %s  %v
   203  %s  %v
   204  %s  %v
   205  %s}#%v`,
   206  		indent, b.Header.StringIndented(indent+"  "),
   207  		indent, b.Data.StringIndented(indent+"  "),
   208  		indent, b.Evidence.StringIndented(indent+"  "),
   209  		indent, b.LastCommit.StringIndented(indent+"  "),
   210  		indent, b.Hash())
   211  }
   212  
   213  // StringShort returns a shortened string representation of the block
   214  func (b *Block) StringShort() string {
   215  	if b == nil {
   216  		return "nil-Block"
   217  	}
   218  	return fmt.Sprintf("Block#%v", b.Hash())
   219  }
   220  
   221  // ToProto converts Block to protobuf
   222  func (b *Block) ToProto() (*tmproto.Block, error) {
   223  	if b == nil {
   224  		return nil, errors.New("nil Block")
   225  	}
   226  
   227  	pb := new(tmproto.Block)
   228  
   229  	pb.Header = *b.Header.ToProto()
   230  	pb.LastCommit = b.LastCommit.ToProto()
   231  	pb.Data = b.Data.ToProto()
   232  
   233  	protoEvidence, err := b.Evidence.ToProto()
   234  	if err != nil {
   235  		return nil, err
   236  	}
   237  	pb.Evidence = *protoEvidence
   238  
   239  	return pb, nil
   240  }
   241  
   242  // FromProto sets a protobuf Block to the given pointer.
   243  // It returns an error if the block is invalid.
   244  func BlockFromProto(bp *tmproto.Block) (*Block, error) {
   245  	if bp == nil {
   246  		return nil, errors.New("nil block")
   247  	}
   248  
   249  	b := new(Block)
   250  	h, err := HeaderFromProto(&bp.Header)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	b.Header = h
   255  	data, err := DataFromProto(&bp.Data)
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  	b.Data = data
   260  	b.Evidence.FromProto(&bp.Evidence)
   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 int64, valsCount, evidenceCount int) int64 {
   279  	maxDataBytes := maxBytes -
   280  		MaxOverheadForBlock -
   281  		MaxHeaderBytes -
   282  		int64(valsCount)*MaxVoteBytes -
   283  		int64(evidenceCount)*MaxEvidenceBytes
   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  
   297  // MaxDataBytesUnknownEvidence returns the maximum size of block's data when
   298  // evidence count is unknown. MaxEvidencePerBlock will be used for the size
   299  // of evidence.
   300  //
   301  // XXX: Panics on negative result.
   302  func MaxDataBytesUnknownEvidence(maxBytes int64, valsCount int, maxNumEvidence uint32) int64 {
   303  	maxEvidenceBytes := int64(maxNumEvidence) * MaxEvidenceBytes
   304  	maxDataBytes := maxBytes -
   305  		MaxOverheadForBlock -
   306  		MaxHeaderBytes -
   307  		int64(valsCount)*MaxVoteBytes -
   308  		maxEvidenceBytes
   309  
   310  	if maxDataBytes < 0 {
   311  		panic(fmt.Sprintf(
   312  			"Negative MaxDataBytesUnknownEvidence. Block.MaxBytes=%d is too small to accommodate header&lastCommit&evidence=%d",
   313  			maxBytes,
   314  			-(maxDataBytes - maxBytes),
   315  		))
   316  	}
   317  
   318  	return maxDataBytes
   319  }
   320  
   321  //-----------------------------------------------------------------------------
   322  
   323  // Header defines the structure of a Tendermint block header.
   324  // NOTE: changes to the Header should be duplicated in:
   325  // - header.Hash()
   326  // - abci.Header
   327  // - https://github.com/tendermint/spec/blob/master/spec/blockchain/blockchain.md
   328  type Header struct {
   329  	// basic block info
   330  	Version tmversion.Consensus `json:"version"`
   331  	ChainID string              `json:"chain_id"`
   332  	Height  int64               `json:"height"`
   333  	Time    time.Time           `json:"time"`
   334  
   335  	// prev block info
   336  	LastBlockID BlockID `json:"last_block_id"`
   337  
   338  	// hashes of block data
   339  	LastCommitHash tmbytes.HexBytes `json:"last_commit_hash"` // commit from validators from the last block
   340  	DataHash       tmbytes.HexBytes `json:"data_hash"`        // transactions
   341  
   342  	// hashes from the app output from the prev block
   343  	ValidatorsHash     tmbytes.HexBytes `json:"validators_hash"`      // validators for the current block
   344  	NextValidatorsHash tmbytes.HexBytes `json:"next_validators_hash"` // validators for the next block
   345  	ConsensusHash      tmbytes.HexBytes `json:"consensus_hash"`       // consensus params for current block
   346  	AppHash            tmbytes.HexBytes `json:"app_hash"`             // state after txs from the previous block
   347  	// root hash of all results from the txs from the previous block
   348  	LastResultsHash tmbytes.HexBytes `json:"last_results_hash"`
   349  
   350  	// consensus info
   351  	EvidenceHash    tmbytes.HexBytes `json:"evidence_hash"`    // evidence included in the block
   352  	ProposerAddress Address          `json:"proposer_address"` // original proposer of the block
   353  }
   354  
   355  // Populate the Header with state-derived data.
   356  // Call this after MakeBlock to complete the Header.
   357  func (h *Header) Populate(
   358  	version tmversion.Consensus, chainID string,
   359  	timestamp time.Time, lastBlockID BlockID,
   360  	valHash, nextValHash []byte,
   361  	consensusHash, appHash, lastResultsHash []byte,
   362  	proposerAddress Address,
   363  ) {
   364  	h.Version = version
   365  	h.ChainID = chainID
   366  	h.Time = timestamp
   367  	h.LastBlockID = lastBlockID
   368  	h.ValidatorsHash = valHash
   369  	h.NextValidatorsHash = nextValHash
   370  	h.ConsensusHash = consensusHash
   371  	h.AppHash = appHash
   372  	h.LastResultsHash = lastResultsHash
   373  	h.ProposerAddress = proposerAddress
   374  }
   375  
   376  // ValidateBasic performs stateless validation on a Header returning an error
   377  // if any validation fails.
   378  //
   379  // NOTE: Timestamp validation is subtle and handled elsewhere.
   380  func (h Header) ValidateBasic() error {
   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() tmbytes.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 a 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  // ToProto converts Header to protobuf
   515  func (h *Header) ToProto() *tmproto.Header {
   516  	if h == nil {
   517  		return nil
   518  	}
   519  
   520  	return &tmproto.Header{
   521  		Version:            h.Version,
   522  		ChainID:            h.ChainID,
   523  		Height:             h.Height,
   524  		Time:               h.Time,
   525  		LastBlockId:        h.LastBlockID.ToProto(),
   526  		ValidatorsHash:     h.ValidatorsHash,
   527  		NextValidatorsHash: h.NextValidatorsHash,
   528  		ConsensusHash:      h.ConsensusHash,
   529  		AppHash:            h.AppHash,
   530  		DataHash:           h.DataHash,
   531  		EvidenceHash:       h.EvidenceHash,
   532  		LastResultsHash:    h.LastResultsHash,
   533  		LastCommitHash:     h.LastCommitHash,
   534  		ProposerAddress:    h.ProposerAddress,
   535  	}
   536  }
   537  
   538  // FromProto sets a protobuf Header to the given pointer.
   539  // It returns an error if the header is invalid.
   540  func HeaderFromProto(ph *tmproto.Header) (Header, error) {
   541  	if ph == nil {
   542  		return Header{}, errors.New("nil Header")
   543  	}
   544  
   545  	h := new(Header)
   546  
   547  	bi, err := BlockIDFromProto(&ph.LastBlockId)
   548  	if err != nil {
   549  		return Header{}, err
   550  	}
   551  
   552  	h.Version = ph.Version
   553  	h.ChainID = ph.ChainID
   554  	h.Height = ph.Height
   555  	h.Time = ph.Time
   556  	h.Height = ph.Height
   557  	h.LastBlockID = *bi
   558  	h.ValidatorsHash = ph.ValidatorsHash
   559  	h.NextValidatorsHash = ph.NextValidatorsHash
   560  	h.ConsensusHash = ph.ConsensusHash
   561  	h.AppHash = ph.AppHash
   562  	h.DataHash = ph.DataHash
   563  	h.EvidenceHash = ph.EvidenceHash
   564  	h.LastResultsHash = ph.LastResultsHash
   565  	h.LastCommitHash = ph.LastCommitHash
   566  	h.ProposerAddress = ph.ProposerAddress
   567  
   568  	return *h, h.ValidateBasic()
   569  }
   570  
   571  //-------------------------------------
   572  
   573  // BlockIDFlag indicates which BlockID the signature is for.
   574  type BlockIDFlag byte
   575  
   576  const (
   577  	// BlockIDFlagAbsent - no vote was received from a validator.
   578  	BlockIDFlagAbsent BlockIDFlag = iota + 1
   579  	// BlockIDFlagCommit - voted for the Commit.BlockID.
   580  	BlockIDFlagCommit
   581  	// BlockIDFlagNil - voted for nil.
   582  	BlockIDFlagNil
   583  )
   584  
   585  // CommitSig is a part of the Vote included in a Commit.
   586  type CommitSig struct {
   587  	BlockIDFlag      BlockIDFlag `json:"block_id_flag"`
   588  	ValidatorAddress Address     `json:"validator_address"`
   589  	Timestamp        time.Time   `json:"timestamp"`
   590  	Signature        []byte      `json:"signature"`
   591  }
   592  
   593  // NewCommitSigForBlock returns new CommitSig with BlockIDFlagCommit.
   594  func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig {
   595  	return CommitSig{
   596  		BlockIDFlag:      BlockIDFlagCommit,
   597  		ValidatorAddress: valAddr,
   598  		Timestamp:        ts,
   599  		Signature:        signature,
   600  	}
   601  }
   602  
   603  // ForBlock returns true if CommitSig is for the block.
   604  func (cs CommitSig) ForBlock() bool {
   605  	return cs.BlockIDFlag == BlockIDFlagCommit
   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  // Absent returns true if CommitSig is absent.
   617  func (cs CommitSig) Absent() bool {
   618  	return cs.BlockIDFlag == BlockIDFlagAbsent
   619  }
   620  
   621  func (cs CommitSig) String() string {
   622  	return fmt.Sprintf("CommitSig{%X by %X on %v @ %s}",
   623  		tmbytes.Fingerprint(cs.Signature),
   624  		tmbytes.Fingerprint(cs.ValidatorAddress),
   625  		cs.BlockIDFlag,
   626  		CanonicalTime(cs.Timestamp))
   627  }
   628  
   629  // BlockID returns the Commit's BlockID if CommitSig indicates signing,
   630  // otherwise - empty BlockID.
   631  func (cs CommitSig) BlockID(commitBlockID BlockID) BlockID {
   632  	var blockID BlockID
   633  	switch cs.BlockIDFlag {
   634  	case BlockIDFlagAbsent:
   635  		blockID = BlockID{}
   636  	case BlockIDFlagCommit:
   637  		blockID = commitBlockID
   638  	case BlockIDFlagNil:
   639  		blockID = BlockID{}
   640  	default:
   641  		panic(fmt.Sprintf("Unknown BlockIDFlag: %v", cs.BlockIDFlag))
   642  	}
   643  	return blockID
   644  }
   645  
   646  // ValidateBasic performs basic validation.
   647  func (cs CommitSig) ValidateBasic() error {
   648  	switch cs.BlockIDFlag {
   649  	case BlockIDFlagAbsent:
   650  	case BlockIDFlagCommit:
   651  	case BlockIDFlagNil:
   652  	default:
   653  		return fmt.Errorf("unknown BlockIDFlag: %v", cs.BlockIDFlag)
   654  	}
   655  
   656  	switch cs.BlockIDFlag {
   657  	case BlockIDFlagAbsent:
   658  		if len(cs.ValidatorAddress) != 0 {
   659  			return errors.New("validator address is present")
   660  		}
   661  		if !cs.Timestamp.IsZero() {
   662  			return errors.New("time is present")
   663  		}
   664  		if len(cs.Signature) != 0 {
   665  			return errors.New("signature is present")
   666  		}
   667  	default:
   668  		if len(cs.ValidatorAddress) != crypto.AddressSize {
   669  			return fmt.Errorf("expected ValidatorAddress size to be %d bytes, got %d bytes",
   670  				crypto.AddressSize,
   671  				len(cs.ValidatorAddress),
   672  			)
   673  		}
   674  		// NOTE: Timestamp validation is subtle and handled elsewhere.
   675  		if len(cs.Signature) == 0 {
   676  			return errors.New("signature is missing")
   677  		}
   678  		if len(cs.Signature) > MaxSignatureSize {
   679  			return fmt.Errorf("signature is too big (max: %d)", MaxSignatureSize)
   680  		}
   681  	}
   682  
   683  	return nil
   684  }
   685  
   686  // ToProto converts CommitSig to protobuf
   687  func (cs *CommitSig) ToProto() *tmproto.CommitSig {
   688  	if cs == nil {
   689  		return nil
   690  	}
   691  
   692  	return &tmproto.CommitSig{
   693  		BlockIdFlag:      tmproto.BlockIDFlag(cs.BlockIDFlag),
   694  		ValidatorAddress: cs.ValidatorAddress,
   695  		Timestamp:        cs.Timestamp,
   696  		Signature:        cs.Signature,
   697  	}
   698  }
   699  
   700  // FromProto sets a protobuf CommitSig to the given pointer.
   701  // It returns an error if the CommitSig is invalid.
   702  func (cs *CommitSig) FromProto(csp tmproto.CommitSig) error {
   703  
   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  // Commit contains the evidence that a block was committed by a set of validators.
   715  // NOTE: Commit is empty for height 1, but never nil.
   716  type Commit struct {
   717  	// NOTE: The signatures are in order of address to preserve the bonded
   718  	// ValidatorSet order.
   719  	// Any peer with a block can gossip signatures by index with a peer without
   720  	// recalculating the active ValidatorSet.
   721  	Height     int64       `json:"height"`
   722  	Round      int32       `json:"round"`
   723  	BlockID    BlockID     `json:"block_id"`
   724  	Signatures []CommitSig `json:"signatures"`
   725  
   726  	// Memoized in first call to corresponding method.
   727  	// NOTE: can't memoize in constructor because constructor isn't used for
   728  	// unmarshaling.
   729  	hash     tmbytes.HexBytes
   730  	bitArray *bits.BitArray
   731  }
   732  
   733  // NewCommit returns a new Commit.
   734  func NewCommit(height int64, round int32, blockID BlockID, commitSigs []CommitSig) *Commit {
   735  	return &Commit{
   736  		Height:     height,
   737  		Round:      round,
   738  		BlockID:    blockID,
   739  		Signatures: commitSigs,
   740  	}
   741  }
   742  
   743  // CommitToVoteSet constructs a VoteSet from the Commit and validator set.
   744  // Panics if signatures from the commit can't be added to the voteset.
   745  // Inverse of VoteSet.MakeCommit().
   746  func CommitToVoteSet(chainID string, commit *Commit, vals *ValidatorSet) *VoteSet {
   747  	voteSet := NewVoteSet(chainID, commit.Height, commit.Round, tmproto.PrecommitType, vals)
   748  	for idx, commitSig := range commit.Signatures {
   749  		if commitSig.Absent() {
   750  			continue // OK, some precommits can be missing.
   751  		}
   752  		added, err := voteSet.AddVote(commit.GetVote(int32(idx)))
   753  		if !added || err != nil {
   754  			panic(fmt.Sprintf("Failed to reconstruct LastCommit: %v", err))
   755  		}
   756  	}
   757  	return voteSet
   758  }
   759  
   760  // GetVote converts the CommitSig for the given valIdx to a Vote.
   761  // Returns nil if the precommit at valIdx is nil.
   762  // Panics if valIdx >= commit.Size().
   763  func (commit *Commit) GetVote(valIdx int32) *Vote {
   764  	commitSig := commit.Signatures[valIdx]
   765  	return &Vote{
   766  		Type:             tmproto.PrecommitType,
   767  		Height:           commit.Height,
   768  		Round:            commit.Round,
   769  		BlockID:          commitSig.BlockID(commit.BlockID),
   770  		Timestamp:        commitSig.Timestamp,
   771  		ValidatorAddress: commitSig.ValidatorAddress,
   772  		ValidatorIndex:   valIdx,
   773  		Signature:        commitSig.Signature,
   774  	}
   775  }
   776  
   777  // VoteSignBytes returns the bytes of the Vote corresponding to valIdx for
   778  // signing.
   779  //
   780  // The only unique part is the Timestamp - all other fields signed over are
   781  // otherwise the same for all validators.
   782  //
   783  // Panics if valIdx >= commit.Size().
   784  //
   785  // See VoteSignBytes
   786  func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte {
   787  	v := commit.GetVote(valIdx).ToProto()
   788  	return VoteSignBytes(chainID, v)
   789  }
   790  
   791  // Type returns the vote type of the commit, which is always VoteTypePrecommit
   792  // Implements VoteSetReader.
   793  func (commit *Commit) Type() byte {
   794  	return byte(tmproto.PrecommitType)
   795  }
   796  
   797  // GetHeight returns height of the commit.
   798  // Implements VoteSetReader.
   799  func (commit *Commit) GetHeight() int64 {
   800  	return commit.Height
   801  }
   802  
   803  // GetRound returns height of the commit.
   804  // Implements VoteSetReader.
   805  func (commit *Commit) GetRound() int32 {
   806  	return commit.Round
   807  }
   808  
   809  // Size returns the number of signatures in the commit.
   810  // Implements VoteSetReader.
   811  func (commit *Commit) Size() int {
   812  	if commit == nil {
   813  		return 0
   814  	}
   815  	return len(commit.Signatures)
   816  }
   817  
   818  // BitArray returns a BitArray of which validators voted for BlockID or nil in this commit.
   819  // Implements VoteSetReader.
   820  func (commit *Commit) BitArray() *bits.BitArray {
   821  	if commit.bitArray == nil {
   822  		commit.bitArray = bits.NewBitArray(len(commit.Signatures))
   823  		for i, commitSig := range commit.Signatures {
   824  			// TODO: need to check the BlockID otherwise we could be counting conflicts,
   825  			// not just the one with +2/3 !
   826  			commit.bitArray.SetIndex(i, !commitSig.Absent())
   827  		}
   828  	}
   829  	return commit.bitArray
   830  }
   831  
   832  // GetByIndex returns the vote corresponding to a given validator index.
   833  // Panics if `index >= commit.Size()`.
   834  // Implements VoteSetReader.
   835  func (commit *Commit) GetByIndex(valIdx int32) *Vote {
   836  	return commit.GetVote(valIdx)
   837  }
   838  
   839  // IsCommit returns true if there is at least one signature.
   840  // Implements VoteSetReader.
   841  func (commit *Commit) IsCommit() bool {
   842  	return len(commit.Signatures) != 0
   843  }
   844  
   845  // ValidateBasic performs basic validation that doesn't involve state data.
   846  // Does not actually check the cryptographic signatures.
   847  func (commit *Commit) ValidateBasic() error {
   848  	if commit.Height < 0 {
   849  		return errors.New("negative Height")
   850  	}
   851  	if commit.Round < 0 {
   852  		return errors.New("negative Round")
   853  	}
   854  
   855  	if commit.Height >= 1 {
   856  		if commit.BlockID.IsZero() {
   857  			return errors.New("commit cannot be for nil block")
   858  		}
   859  
   860  		if len(commit.Signatures) == 0 {
   861  			return errors.New("no signatures in commit")
   862  		}
   863  		for i, commitSig := range commit.Signatures {
   864  			if err := commitSig.ValidateBasic(); err != nil {
   865  				return fmt.Errorf("wrong CommitSig #%d: %v", i, err)
   866  			}
   867  		}
   868  	}
   869  	return nil
   870  }
   871  
   872  // Hash returns the hash of the commit
   873  func (commit *Commit) Hash() tmbytes.HexBytes {
   874  	if commit == nil {
   875  		return nil
   876  	}
   877  	if commit.hash == nil {
   878  		bs := make([][]byte, len(commit.Signatures))
   879  		for i, commitSig := range commit.Signatures {
   880  			pbcs := commitSig.ToProto()
   881  			bz, err := pbcs.Marshal()
   882  			if err != nil {
   883  				panic(err)
   884  			}
   885  
   886  			bs[i] = bz
   887  		}
   888  		commit.hash = merkle.HashFromByteSlices(bs)
   889  	}
   890  	return commit.hash
   891  }
   892  
   893  // StringIndented returns a string representation of the commit
   894  func (commit *Commit) StringIndented(indent string) string {
   895  	if commit == nil {
   896  		return "nil-Commit"
   897  	}
   898  	commitSigStrings := make([]string, len(commit.Signatures))
   899  	for i, commitSig := range commit.Signatures {
   900  		commitSigStrings[i] = commitSig.String()
   901  	}
   902  	return fmt.Sprintf(`Commit{
   903  %s  Height:     %d
   904  %s  Round:      %d
   905  %s  BlockID:    %v
   906  %s  Signatures:
   907  %s    %v
   908  %s}#%v`,
   909  		indent, commit.Height,
   910  		indent, commit.Round,
   911  		indent, commit.BlockID,
   912  		indent,
   913  		indent, strings.Join(commitSigStrings, "\n"+indent+"    "),
   914  		indent, commit.hash)
   915  }
   916  
   917  // ToProto converts Commit to protobuf
   918  func (commit *Commit) ToProto() *tmproto.Commit {
   919  	if commit == nil {
   920  		return nil
   921  	}
   922  
   923  	c := new(tmproto.Commit)
   924  	sigs := make([]tmproto.CommitSig, len(commit.Signatures))
   925  	for i := range commit.Signatures {
   926  		sigs[i] = *commit.Signatures[i].ToProto()
   927  	}
   928  	c.Signatures = sigs
   929  
   930  	c.Height = commit.Height
   931  	c.Round = commit.Round
   932  	c.BlockID = commit.BlockID.ToProto()
   933  	if commit.hash != nil {
   934  		c.Hash = commit.hash
   935  	}
   936  	c.BitArray = commit.bitArray.ToProto()
   937  	return c
   938  }
   939  
   940  // FromProto sets a protobuf Commit to the given pointer.
   941  // It returns an error if the commit is invalid.
   942  func CommitFromProto(cp *tmproto.Commit) (*Commit, error) {
   943  	if cp == nil {
   944  		return nil, errors.New("nil Commit")
   945  	}
   946  
   947  	var (
   948  		commit   = new(Commit)
   949  		bitArray *bits.BitArray
   950  	)
   951  
   952  	bi, err := BlockIDFromProto(&cp.BlockID)
   953  	if err != nil {
   954  		return nil, err
   955  	}
   956  
   957  	bitArray.FromProto(cp.BitArray)
   958  
   959  	sigs := make([]CommitSig, len(cp.Signatures))
   960  	for i := range cp.Signatures {
   961  		if err := sigs[i].FromProto(cp.Signatures[i]); err != nil {
   962  			return nil, err
   963  		}
   964  	}
   965  	commit.Signatures = sigs
   966  
   967  	commit.Height = cp.Height
   968  	commit.Round = cp.Round
   969  	commit.BlockID = *bi
   970  	commit.hash = cp.Hash
   971  	commit.bitArray = bitArray
   972  
   973  	return commit, commit.ValidateBasic()
   974  }
   975  
   976  //-----------------------------------------------------------------------------
   977  
   978  // SignedHeader is a header along with the commits that prove it.
   979  // It is the basis of the light client.
   980  type SignedHeader struct {
   981  	*Header `json:"header"`
   982  
   983  	Commit *Commit `json:"commit"`
   984  }
   985  
   986  // ValidateBasic does basic consistency checks and makes sure the header
   987  // and commit are consistent.
   988  //
   989  // NOTE: This does not actually check the cryptographic signatures.  Make sure
   990  // to use a Verifier to validate the signatures actually provide a
   991  // significantly strong proof for this header's validity.
   992  func (sh SignedHeader) ValidateBasic(chainID string) error {
   993  	if sh.Header == nil {
   994  		return errors.New("missing header")
   995  	}
   996  	if sh.Commit == nil {
   997  		return errors.New("missing commit")
   998  	}
   999  
  1000  	if err := sh.Header.ValidateBasic(); err != nil {
  1001  		return fmt.Errorf("invalid header: %w", err)
  1002  	}
  1003  	if err := sh.Commit.ValidateBasic(); err != nil {
  1004  		return fmt.Errorf("invalid commit: %w", err)
  1005  	}
  1006  
  1007  	if sh.ChainID != chainID {
  1008  		return fmt.Errorf("header belongs to another chain %q, not %q", sh.ChainID, chainID)
  1009  	}
  1010  
  1011  	// Make sure the header is consistent with the commit.
  1012  	if sh.Commit.Height != sh.Height {
  1013  		return fmt.Errorf("header and commit height mismatch: %d vs %d", sh.Height, sh.Commit.Height)
  1014  	}
  1015  	if hhash, chash := sh.Hash(), sh.Commit.BlockID.Hash; !bytes.Equal(hhash, chash) {
  1016  		return fmt.Errorf("commit signs block %X, header is block %X", chash, hhash)
  1017  	}
  1018  
  1019  	return nil
  1020  }
  1021  
  1022  func (sh SignedHeader) String() string {
  1023  	return sh.StringIndented("")
  1024  }
  1025  
  1026  // StringIndented returns a string representation of the SignedHeader.
  1027  func (sh SignedHeader) StringIndented(indent string) string {
  1028  	return fmt.Sprintf(`SignedHeader{
  1029  %s  %v
  1030  %s  %v
  1031  %s}`,
  1032  		indent, sh.Header.StringIndented(indent+"  "),
  1033  		indent, sh.Commit.StringIndented(indent+"  "),
  1034  		indent)
  1035  }
  1036  
  1037  // ToProto converts SignedHeader to protobuf
  1038  func (sh *SignedHeader) ToProto() *tmproto.SignedHeader {
  1039  	if sh == nil {
  1040  		return nil
  1041  	}
  1042  
  1043  	psh := new(tmproto.SignedHeader)
  1044  	if sh.Header != nil {
  1045  		psh.Header = sh.Header.ToProto()
  1046  	}
  1047  	if sh.Commit != nil {
  1048  		psh.Commit = sh.Commit.ToProto()
  1049  	}
  1050  
  1051  	return psh
  1052  }
  1053  
  1054  // FromProto sets a protobuf SignedHeader to the given pointer.
  1055  // It returns an error if the hader or the commit is invalid.
  1056  func SignedHeaderFromProto(shp *tmproto.SignedHeader) (*SignedHeader, error) {
  1057  	if shp == nil {
  1058  		return nil, errors.New("nil SignedHeader")
  1059  	}
  1060  
  1061  	sh := new(SignedHeader)
  1062  
  1063  	if shp.Header != nil {
  1064  		h, err := HeaderFromProto(shp.Header)
  1065  		if err != nil {
  1066  			return nil, err
  1067  		}
  1068  		sh.Header = &h
  1069  	}
  1070  
  1071  	if shp.Commit != nil {
  1072  		c, err := CommitFromProto(shp.Commit)
  1073  		if err != nil {
  1074  			return nil, err
  1075  		}
  1076  		sh.Commit = c
  1077  	}
  1078  
  1079  	return sh, nil
  1080  }
  1081  
  1082  //-----------------------------------------------------------------------------
  1083  
  1084  // Data contains the set of transactions included in the block
  1085  type Data struct {
  1086  
  1087  	// Txs that will be applied by state @ block.Height+1.
  1088  	// NOTE: not all txs here are valid.  We're just agreeing on the order first.
  1089  	// This means that block.AppHash does not include these txs.
  1090  	Txs Txs `json:"txs"`
  1091  
  1092  	// Volatile
  1093  	hash tmbytes.HexBytes
  1094  }
  1095  
  1096  // Hash returns the hash of the data
  1097  func (data *Data) Hash() tmbytes.HexBytes {
  1098  	if data == nil {
  1099  		return (Txs{}).Hash()
  1100  	}
  1101  	if data.hash == nil {
  1102  		data.hash = data.Txs.Hash() // NOTE: leaves of merkle tree are TxIDs
  1103  	}
  1104  	return data.hash
  1105  }
  1106  
  1107  // StringIndented returns a string representation of the transactions
  1108  func (data *Data) StringIndented(indent string) string {
  1109  	if data == nil {
  1110  		return "nil-Data"
  1111  	}
  1112  	txStrings := make([]string, tmmath.MinInt(len(data.Txs), 21))
  1113  	for i, tx := range data.Txs {
  1114  		if i == 20 {
  1115  			txStrings[i] = fmt.Sprintf("... (%v total)", len(data.Txs))
  1116  			break
  1117  		}
  1118  		txStrings[i] = fmt.Sprintf("%X (%d bytes)", tx.Hash(), len(tx))
  1119  	}
  1120  	return fmt.Sprintf(`Data{
  1121  %s  %v
  1122  %s}#%v`,
  1123  		indent, strings.Join(txStrings, "\n"+indent+"  "),
  1124  		indent, data.hash)
  1125  }
  1126  
  1127  // ToProto converts Data to protobuf
  1128  func (data *Data) ToProto() tmproto.Data {
  1129  	tp := new(tmproto.Data)
  1130  
  1131  	if len(data.Txs) > 0 {
  1132  		txBzs := make([][]byte, len(data.Txs))
  1133  		for i := range data.Txs {
  1134  			txBzs[i] = data.Txs[i]
  1135  		}
  1136  		tp.Txs = txBzs
  1137  	}
  1138  
  1139  	if data.hash != nil {
  1140  		tp.Hash = data.hash
  1141  	}
  1142  
  1143  	return *tp
  1144  }
  1145  
  1146  // DataFromProto takes a protobuf representation of Data &
  1147  // returns the native type.
  1148  func DataFromProto(dp *tmproto.Data) (Data, error) {
  1149  	if dp == nil {
  1150  		return Data{}, errors.New("nil data")
  1151  	}
  1152  	data := new(Data)
  1153  
  1154  	if len(dp.Txs) > 0 {
  1155  		txBzs := make(Txs, len(dp.Txs))
  1156  		for i := range dp.Txs {
  1157  			txBzs[i] = Tx(dp.Txs[i])
  1158  		}
  1159  		data.Txs = txBzs
  1160  	} else {
  1161  		data.Txs = Txs{}
  1162  	}
  1163  
  1164  	data.hash = dp.Hash
  1165  
  1166  	return *data, nil
  1167  }
  1168  
  1169  //-----------------------------------------------------------------------------
  1170  
  1171  // EvidenceData contains any evidence of malicious wrong-doing by validators
  1172  type EvidenceData struct {
  1173  	Evidence EvidenceList `json:"evidence"`
  1174  
  1175  	// Volatile
  1176  	hash tmbytes.HexBytes
  1177  }
  1178  
  1179  // Hash returns the hash of the data.
  1180  func (data *EvidenceData) Hash() tmbytes.HexBytes {
  1181  	if data.hash == nil {
  1182  		data.hash = data.Evidence.Hash()
  1183  	}
  1184  	return data.hash
  1185  }
  1186  
  1187  // StringIndented returns a string representation of the evidence.
  1188  func (data *EvidenceData) StringIndented(indent string) string {
  1189  	if data == nil {
  1190  		return "nil-Evidence"
  1191  	}
  1192  	evStrings := make([]string, tmmath.MinInt(len(data.Evidence), 21))
  1193  	for i, ev := range data.Evidence {
  1194  		if i == 20 {
  1195  			evStrings[i] = fmt.Sprintf("... (%v total)", len(data.Evidence))
  1196  			break
  1197  		}
  1198  		evStrings[i] = fmt.Sprintf("Evidence:%v", ev)
  1199  	}
  1200  	return fmt.Sprintf(`EvidenceData{
  1201  %s  %v
  1202  %s}#%v`,
  1203  		indent, strings.Join(evStrings, "\n"+indent+"  "),
  1204  		indent, data.hash)
  1205  }
  1206  
  1207  // ToProto converts EvidenceData to protobuf
  1208  func (data *EvidenceData) ToProto() (*tmproto.EvidenceData, error) {
  1209  	if data == nil {
  1210  		return nil, errors.New("nil evidence data")
  1211  	}
  1212  
  1213  	evi := new(tmproto.EvidenceData)
  1214  	eviBzs := make([]tmproto.Evidence, len(data.Evidence))
  1215  	for i := range data.Evidence {
  1216  		protoEvi, err := EvidenceToProto(data.Evidence[i])
  1217  		if err != nil {
  1218  			return nil, err
  1219  		}
  1220  		eviBzs[i] = *protoEvi
  1221  	}
  1222  	evi.Evidence = eviBzs
  1223  
  1224  	if data.hash != nil {
  1225  		evi.Hash = data.hash
  1226  	}
  1227  
  1228  	return evi, nil
  1229  }
  1230  
  1231  // FromProto sets a protobuf EvidenceData to the given pointer.
  1232  func (data *EvidenceData) FromProto(eviData *tmproto.EvidenceData) error {
  1233  	if eviData == nil {
  1234  		return errors.New("nil evidenceData")
  1235  	}
  1236  
  1237  	eviBzs := make(EvidenceList, len(eviData.Evidence))
  1238  	for i := range eviData.Evidence {
  1239  		evi, err := EvidenceFromProto(&eviData.Evidence[i])
  1240  		if err != nil {
  1241  			return err
  1242  		}
  1243  		eviBzs[i] = evi
  1244  	}
  1245  	data.Evidence = eviBzs
  1246  
  1247  	data.hash = eviData.GetHash()
  1248  
  1249  	return nil
  1250  }
  1251  
  1252  //--------------------------------------------------------------------------------
  1253  
  1254  // BlockID
  1255  type BlockID struct {
  1256  	Hash          tmbytes.HexBytes `json:"hash"`
  1257  	PartSetHeader PartSetHeader    `json:"parts"`
  1258  }
  1259  
  1260  // Equals returns true if the BlockID matches the given BlockID
  1261  func (blockID BlockID) Equals(other BlockID) bool {
  1262  	return bytes.Equal(blockID.Hash, other.Hash) &&
  1263  		blockID.PartSetHeader.Equals(other.PartSetHeader)
  1264  }
  1265  
  1266  // Key returns a machine-readable string representation of the BlockID
  1267  func (blockID BlockID) Key() string {
  1268  	pbph := blockID.PartSetHeader.ToProto()
  1269  	bz, err := pbph.Marshal()
  1270  	if err != nil {
  1271  		panic(err)
  1272  	}
  1273  
  1274  	return string(blockID.Hash) + string(bz)
  1275  }
  1276  
  1277  // ValidateBasic performs basic validation.
  1278  func (blockID BlockID) ValidateBasic() error {
  1279  	// Hash can be empty in case of POLBlockID in Proposal.
  1280  	if err := ValidateHash(blockID.Hash); err != nil {
  1281  		return fmt.Errorf("wrong Hash")
  1282  	}
  1283  	if err := blockID.PartSetHeader.ValidateBasic(); err != nil {
  1284  		return fmt.Errorf("wrong PartSetHeader: %v", err)
  1285  	}
  1286  	return nil
  1287  }
  1288  
  1289  // IsZero returns true if this is the BlockID of a nil block.
  1290  func (blockID BlockID) IsZero() bool {
  1291  	return len(blockID.Hash) == 0 &&
  1292  		blockID.PartSetHeader.IsZero()
  1293  }
  1294  
  1295  // IsComplete returns true if this is a valid BlockID of a non-nil block.
  1296  func (blockID BlockID) IsComplete() bool {
  1297  	return len(blockID.Hash) == tmhash.Size &&
  1298  		blockID.PartSetHeader.Total > 0 &&
  1299  		len(blockID.PartSetHeader.Hash) == tmhash.Size
  1300  }
  1301  
  1302  // String returns a human readable string representation of the BlockID
  1303  func (blockID BlockID) String() string {
  1304  	return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartSetHeader)
  1305  }
  1306  
  1307  // ToProto converts BlockID to protobuf
  1308  func (blockID *BlockID) ToProto() tmproto.BlockID {
  1309  	if blockID == nil {
  1310  		return tmproto.BlockID{}
  1311  	}
  1312  
  1313  	return tmproto.BlockID{
  1314  		Hash:          blockID.Hash,
  1315  		PartSetHeader: blockID.PartSetHeader.ToProto(),
  1316  	}
  1317  }
  1318  
  1319  // FromProto sets a protobuf BlockID to the given pointer.
  1320  // It returns an error if the block id is invalid.
  1321  func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) {
  1322  	if bID == nil {
  1323  		return nil, errors.New("nil BlockID")
  1324  	}
  1325  
  1326  	blockID := new(BlockID)
  1327  	ph, err := PartSetHeaderFromProto(&bID.PartSetHeader)
  1328  	if err != nil {
  1329  		return nil, err
  1330  	}
  1331  
  1332  	blockID.PartSetHeader = *ph
  1333  	blockID.Hash = bID.Hash
  1334  
  1335  	return blockID, blockID.ValidateBasic()
  1336  }