mirror of
https://github.com/tendermint/tendermint.git
synced 2026-02-10 05:50:19 +00:00
125 lines
3.1 KiB
Go
125 lines
3.1 KiB
Go
package metadata
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/tendermint/tendermint/crypto/tmhash"
|
|
tmbytes "github.com/tendermint/tendermint/libs/bytes"
|
|
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
|
|
)
|
|
|
|
// BlockID
|
|
type BlockID struct {
|
|
Hash tmbytes.HexBytes `json:"hash"`
|
|
PartSetHeader PartSetHeader `json:"parts"`
|
|
}
|
|
|
|
// BlockIDFlag indicates which BlockID the signature is for.
|
|
type BlockIDFlag byte
|
|
|
|
const (
|
|
// BlockIDFlagAbsent - no vote was received from a validator.
|
|
BlockIDFlagAbsent BlockIDFlag = iota + 1
|
|
// BlockIDFlagCommit - voted for the Commit.BlockID.
|
|
BlockIDFlagCommit
|
|
// BlockIDFlagNil - voted for nil.
|
|
BlockIDFlagNil
|
|
)
|
|
|
|
// Equals returns true if the BlockID matches the given BlockID
|
|
func (blockID BlockID) Equals(other BlockID) bool {
|
|
return bytes.Equal(blockID.Hash, other.Hash) &&
|
|
blockID.PartSetHeader.Equals(other.PartSetHeader)
|
|
}
|
|
|
|
// Key returns a machine-readable string representation of the BlockID
|
|
func (blockID BlockID) Key() string {
|
|
pbph := blockID.PartSetHeader.ToProto()
|
|
bz, err := pbph.Marshal()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return fmt.Sprint(string(blockID.Hash), string(bz))
|
|
}
|
|
|
|
// ValidateBasic performs basic validation.
|
|
func (blockID BlockID) ValidateBasic() error {
|
|
// Hash can be empty in case of POLBlockID in Proposal.
|
|
if err := ValidateHash(blockID.Hash); err != nil {
|
|
return fmt.Errorf("wrong Hash: %w", err)
|
|
}
|
|
if err := blockID.PartSetHeader.ValidateBasic(); err != nil {
|
|
return fmt.Errorf("wrong PartSetHeader: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsZero returns true if this is the BlockID of a nil block.
|
|
func (blockID BlockID) IsZero() bool {
|
|
return len(blockID.Hash) == 0 &&
|
|
blockID.PartSetHeader.IsZero()
|
|
}
|
|
|
|
// IsComplete returns true if this is a valid BlockID of a non-nil block.
|
|
func (blockID BlockID) IsComplete() bool {
|
|
return len(blockID.Hash) == tmhash.Size &&
|
|
blockID.PartSetHeader.Total > 0 &&
|
|
len(blockID.PartSetHeader.Hash) == tmhash.Size
|
|
}
|
|
|
|
// String returns a human readable string representation of the BlockID.
|
|
//
|
|
// 1. hash
|
|
// 2. part set header
|
|
//
|
|
// See PartSetHeader#String
|
|
func (blockID BlockID) String() string {
|
|
return fmt.Sprintf(`%v:%v`, blockID.Hash, blockID.PartSetHeader)
|
|
}
|
|
|
|
// ToProto converts BlockID to protobuf
|
|
func (blockID *BlockID) ToProto() tmproto.BlockID {
|
|
if blockID == nil {
|
|
return tmproto.BlockID{}
|
|
}
|
|
|
|
return tmproto.BlockID{
|
|
Hash: blockID.Hash,
|
|
PartSetHeader: blockID.PartSetHeader.ToProto(),
|
|
}
|
|
}
|
|
|
|
// FromProto sets a protobuf BlockID to the given pointer.
|
|
// It returns an error if the block id is invalid.
|
|
func BlockIDFromProto(bID *tmproto.BlockID) (*BlockID, error) {
|
|
if bID == nil {
|
|
return nil, errors.New("nil BlockID")
|
|
}
|
|
|
|
blockID := new(BlockID)
|
|
ph, err := PartSetHeaderFromProto(&bID.PartSetHeader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
blockID.PartSetHeader = *ph
|
|
blockID.Hash = bID.Hash
|
|
|
|
return blockID, blockID.ValidateBasic()
|
|
}
|
|
|
|
// ValidateHash returns an error if the hash is not empty, but its
|
|
// size != tmhash.Size.
|
|
func ValidateHash(h []byte) error {
|
|
if len(h) > 0 && len(h) != tmhash.Size {
|
|
return fmt.Errorf("expected size to be %d bytes, got %d bytes",
|
|
tmhash.Size,
|
|
len(h),
|
|
)
|
|
}
|
|
return nil
|
|
}
|