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