github.com/ari-anchor/sei-tendermint@v0.0.0-20230519144642-dc826b7b56bb/types/block.go (about)

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