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