concord

package
v0.0.0-...-586837e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2022 License: Apache-2.0 Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Max size of commit without any commitSigs -> 82 for DataHash, 8 for Height, 4 for Round.
	MaxCommitOverheadBytes int64 = 94
	// Commit sig size is made up of 64 bytes for the signature, 20 bytes for the address,
	// 1 byte for the flag and 14 bytes for the timestamp
	MaxCommitSigBytes int64 = 109
)
View Source
const (
	// MaxTotalVotingPower - the maximum allowed total voting power.
	// It needs to be sufficiently small to, in all cases:
	// 1. prevent clipping in incrementProposerPriority()
	// 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority()
	// (Proof of 1 is tricky, left to the reader).
	// It could be higher, but this is sufficiently large for our purposes,
	// and leaves room for defensive purposes.
	MaxTotalVotingPower = int64(math.MaxInt64) / 8

	// PriorityWindowSizeFactor - is a constant that when multiplied with the
	// total voting power gives the maximum allowed distance between validator
	// priorities.
	PriorityWindowSizeFactor = 2
)
View Source
const (
	RoundStepNewHeight     = RoundStepType(0x01) // Wait til CommitTime + timeoutCommit
	RoundStepNewRound      = RoundStepType(0x02) // Setup new round and go to RoundStepPropose
	RoundStepPropose       = RoundStepType(0x03) // Did propose, gossip proposal
	RoundStepPrevote       = RoundStepType(0x04) // Did prevote, gossip prevotes
	RoundStepPrevoteWait   = RoundStepType(0x05) // Did receive any +2/3 prevotes, start timeout
	RoundStepPrecommit     = RoundStepType(0x06) // Did precommit, gossip precommits
	RoundStepPrecommitWait = RoundStepType(0x07) // Did receive any +2/3 precommits, start timeout
	RoundStepCommit        = RoundStepType(0x08) // Entered commit state machine

)

RoundStepType

View Source
const (
	// MaxVotesCount is the maximum number of votes in a set. Used in ValidateBasic funcs for
	// protection against DOS attacks. Note this implies a corresponding equal limit to
	// the number of validators.
	MaxVotesCount = 10000
)
View Source
const TimeFormat = time.RFC3339Nano

TimeFormat is used for generating the sigs

Variables

View Source
var (
	ErrProposalSignature          = errors.New("invalid proposal signature")
	ErrProposalRound              = errors.New("invalid proposal round")
	ErrAddingVote                 = errors.New("adding vote")
	ErrSignatureFoundInPastBlocks = errors.New("found signature from the same key")
)
View Source
var (
	ErrVoteUnexpectedStep            = errors.New("unexpected step")
	ErrVoteInvalidValidatorIndex     = errors.New("invalid validator index")
	ErrVoteInvalidValidatorAddress   = errors.New("invalid validator address")
	ErrVoteInvalidSignature          = errors.New("invalid signature")
	ErrVoteInvalidDataHash           = errors.New("invalid data hash")
	ErrVoteNonDeterministicSignature = errors.New("non-deterministic signature")
	ErrVoteNil                       = errors.New("nil vote")
	ErrVoteInvalidType               = errors.New("invalid vote type")
)
View Source
var ErrTotalVotingPowerOverflow = fmt.Errorf("total voting power of resulting valset exceeds max %d",
	MaxTotalVotingPower)

ErrTotalVotingPowerOverflow is returned if the total voting power of the resulting validator set exceeds MaxTotalVotingPower.

View Source
var ErroringMockPVErr = errors.New("erroringMockPV always returns an error")
View Source
var (
	// MaxSignatureSize is a maximum allowed signature size for the Proposal
	// and Vote.
	// XXX: secp256k1 does not have Size nor MaxSize defined.
	MaxSignatureSize = tmmath.MaxInt(ed25519.SignatureSize, 64)
)

Functions

func CanonicalTime

func CanonicalTime(t time.Time) string

CanonicalTime can be used to stringify time in a canonical way.

func CanonicalizeDataHash

func CanonicalizeDataHash(bid *pb.DataHash) *pb.CanonicalDataHash

func CanonicalizeProposal

func CanonicalizeProposal(chainID string, proposal *pb.Proposal) pb.CanonicalProposal

CanonicalizeVote transforms the given Proposal to a CanonicalProposal.

func CanonicalizeVote

func CanonicalizeVote(chainID string, vote *pb.Vote) pb.CanonicalVote

CanonicalizeVote transforms the given Vote to a CanonicalVote, which does not contain ValidatorIndex and ValidatorAddress fields.

func IsErrNotEnoughVotingPowerSigned

func IsErrNotEnoughVotingPowerSigned(err error) bool

IsErrNotEnoughVotingPowerSigned returns true if err is ErrNotEnoughVotingPowerSigned.

func IsVoteTypeValid

func IsVoteTypeValid(t pb.SignedMsgType) bool

IsVoteTypeValid returns true if t is a valid vote type.

func MaxCommitBytes

func MaxCommitBytes(valCount int) int64

func MsgToProto

func MsgToProto(msg Message) (*cpb.Message, error)

MsgToProto takes a consensus message type and returns the proto defined consensus message

func MustEncode

func MustEncode(msg Message) []byte

MustEncode takes the reactors msg, makes it proto and marshals it this mimics `MustMarshalBinaryBare` in that is panics on error

func NewConciliator

func NewConciliator(p *pubsub.PubSub, self PrivProposer) *conciliator

func ProposalSignBytes

func ProposalSignBytes(chainID string, p *pb.Proposal) []byte

ProposalSignBytes returns the proto-encoding of the canonicalized Proposal, for signing. Panics if the marshaling fails.

The encoded Protobuf message is varint length-prefixed (using MarshalDelimited) for backwards-compatibility with the Amino encoding, due to e.g. hardware devices that rely on this encoding.

See CanonicalizeProposal

func RandValidator

func RandValidator(randPower bool, minPower int64) (*Proposer, PrivProposer)

RandValidator returns a randomized validator, useful for testing. UNSTABLE

func RandValidatorSet

func RandValidatorSet(numValidators int, votingPower int64) (*ProposerSet, []PrivProposer)

RandValidatorSet returns a randomized validator set (size: +numValidators+), where each validator has a voting power of +votingPower+.

EXPOSED FOR TESTING.

func ValidateHash

func ValidateHash(h []byte) error

ValidateHash returns an error if the hash is not empty, but its size != tmhash.Size.

func ValidateTime

func ValidateTime(t time.Time) error

ValidateTime does a basic time validation ensuring time does not drift too much: +/- one year. TODO: reduce this to eg 1 day NOTE: DO NOT USE in ValidateBasic methods in this package. This function can only be used for real time validation, like on proposals and votes in the consensus. If consensus is stuck, and rounds increase for more than a day, having only a 1-day band here could break things... Can't use for validating blocks because we may be syncing years worth of history.

func ValidatorListString

func ValidatorListString(vals []*Proposer) string

ValidatorListString returns a prettified validator list for logging purposes.

func VoteSignBytes

func VoteSignBytes(chainID string, vote *pb.Vote) []byte

VoteSignBytes returns the proto-encoding of the canonicalized Vote, for signing. Panics is the marshaling fails.

The encoded Protobuf message is varint length-prefixed (using MarshalDelimited) for backwards-compatibility with the Amino encoding, due to e.g. hardware devices that rely on this encoding.

See CanonicalizeVote

Types

type Address

type Address = crypto.Address

Address is hex bytes.

type Commit

type Commit struct {
	// NOTE: The signatures are in order of address to preserve the bonded
	// ProposerSet order.
	// Any peer with a block can gossip signatures by index with a peer without
	// recalculating the active ProposerSet.
	DataHash   DataHash    `json:"block_id"`
	Signatures []CommitSig `json:"signatures"`
	// contains filtered or unexported fields
}

Commit contains the evidence that a block was committed by a set of validators. NOTE: Commit is empty for height 1, but never nil.

func CommitFromProto

func CommitFromProto(cp *pb.Commit) (*Commit, error)

FromProto sets a protobuf Commit to the given pointer. It returns an error if the commit is invalid.

func MakeCommit

func MakeCommit(dataHash DataHash, height int64, round int32,
	voteSet *VoteSet, validators []PrivProposer, now time.Time) (*Commit, error)

func NewCommit

func NewCommit(DataHash DataHash, commitSigs []CommitSig) *Commit

NewCommit returns a new Commit.

func (*Commit) BitArray

func (commit *Commit) BitArray() *bits.BitArray

BitArray returns a BitArray of which validators voted for DataHash or nil in this commit. Implements VoteSetReader.

func (*Commit) GetByIndex

func (commit *Commit) GetByIndex(valIdx int32) *Vote

GetByIndex returns the vote corresponding to a given validator index. Panics if `index >= commit.Size()`. Implements VoteSetReader.

func (*Commit) GetVote

func (commit *Commit) GetVote(valIdx int32) *Vote

GetVote converts the CommitSig for the given valIdx to a Vote. Returns nil if the precommit at valIdx is nil. Panics if valIdx >= commit.Size().

func (*Commit) Hash

func (commit *Commit) Hash() tmbytes.HexBytes

Hash returns the hash of the commit

func (*Commit) IsCommit

func (commit *Commit) IsCommit() bool

IsCommit returns true if there is at least one signature. Implements VoteSetReader.

func (*Commit) Size

func (commit *Commit) Size() int

Size returns the number of signatures in the commit. Implements VoteSetReader.

func (*Commit) StringIndented

func (commit *Commit) StringIndented(indent string) string

StringIndented returns a string representation of the commit.

func (*Commit) ToProto

func (commit *Commit) ToProto() *pb.Commit

ToProto converts Commit to protobuf

func (*Commit) Type

func (commit *Commit) Type() byte

Type returns the vote type of the commit, which is always VoteTypePrecommit Implements VoteSetReader.

func (*Commit) ValidateBasic

func (commit *Commit) ValidateBasic() error

ValidateBasic performs basic validation that doesn't involve state data. Does not actually check the cryptographic signatures.

func (*Commit) VoteSignBytes

func (commit *Commit) VoteSignBytes(chainID string, valIdx int32) []byte

VoteSignBytes returns the bytes of the Vote corresponding to valIdx for signing.

The only unique part is the Timestamp - all other fields signed over are otherwise the same for all validators.

Panics if valIdx >= commit.Size().

See VoteSignBytes

type CommitSig

type CommitSig struct {
	DataHashFlag     DataHashFlag `json:"block_id_flag"`
	ValidatorAddress Address      `json:"validator_address"`
	Timestamp        time.Time    `json:"timestamp"`
	Signature        []byte       `json:"signature"`
}

CommitSig is a part of the Vote included in a Commit.

func NewCommitSigAbsent

func NewCommitSigAbsent() CommitSig

NewCommitSigAbsent returns new CommitSig with DataHashFlagAbsent. Other fields are all empty.

func NewCommitSigForBlock

func NewCommitSigForBlock(signature []byte, valAddr Address, ts time.Time) CommitSig

NewCommitSigForBlock returns new CommitSig with DataHashFlagCommit.

func (CommitSig) Absent

func (cs CommitSig) Absent() bool

Absent returns true if CommitSig is absent.

func (CommitSig) DataHash

func (cs CommitSig) DataHash(commitDataHash DataHash) DataHash

DataHash returns the Commit's DataHash if CommitSig indicates signing, otherwise - empty DataHash.

func (CommitSig) ForBlock

func (cs CommitSig) ForBlock() bool

ForBlock returns true if CommitSig is for the block.

func (*CommitSig) FromProto

func (cs *CommitSig) FromProto(csp pb.CommitSig) error

FromProto sets a protobuf CommitSig to the given pointer. It returns an error if the CommitSig is invalid.

func (CommitSig) String

func (cs CommitSig) String() string

CommitSig returns a string representation of CommitSig.

1. first 6 bytes of signature 2. first 6 bytes of validator address 3. block ID flag 4. timestamp

func (*CommitSig) ToProto

func (cs *CommitSig) ToProto() *pb.CommitSig

ToProto converts CommitSig to protobuf

func (CommitSig) ValidateBasic

func (cs CommitSig) ValidateBasic() error

ValidateBasic performs basic validation.

type Consensus

type Consensus interface {
	AgreeOn(context.Context, []byte, *ProposerSet) ([]byte, *Commit, error)
}

type DataHash

type DataHash struct {
	Hash tmbytes.HexBytes `json:"hash"`
}

func DataHashFromProto

func DataHashFromProto(bID *pb.DataHash) (*DataHash, error)

func (DataHash) Equals

func (dataHash DataHash) Equals(other DataHash) bool

Equals returns true if the BlockID matches the given BlockID

func (DataHash) IsComplete

func (dataHash DataHash) IsComplete() bool

IsComplete returns true if this is a valid BlockID of a non-nil block.

func (DataHash) IsZero

func (dataHash DataHash) IsZero() bool

IsZero returns true if this is the BlockID of a nil block.

func (DataHash) Key

func (dataHash DataHash) Key() string

Key returns a machine-readable string representation of the BlockID

func (*DataHash) ToProto

func (dataHash *DataHash) ToProto() *pb.DataHash

ToProto converts BlockID to protobuf

func (DataHash) ValidateBasic

func (dataHash DataHash) ValidateBasic() error

ValidateBasic performs basic validation.

type DataHashFlag

type DataHashFlag byte

DataHashFlag indicates which DataHash the signature is for.

const (
	// DataHashFlagAbsent - no vote was received from a validator.
	DataHashFlagAbsent DataHashFlag = iota + 1
	// DataHashFlagCommit - voted for the Commit.DataHash.
	DataHashFlagCommit
	// DataHashFlagNil - voted for nil.
	DataHashFlagNil
)

type ErrInvalidCommitHeight

type ErrInvalidCommitHeight struct {
	Expected int64
	Actual   int64
}

ErrInvalidCommitHeight is returned when we encounter a commit with an unexpected height.

func NewErrInvalidCommitHeight

func NewErrInvalidCommitHeight(expected, actual int64) ErrInvalidCommitHeight

func (ErrInvalidCommitHeight) Error

func (e ErrInvalidCommitHeight) Error() string

type ErrInvalidCommitSignatures

type ErrInvalidCommitSignatures struct {
	Expected int
	Actual   int
}

ErrInvalidCommitSignatures is returned when we encounter a commit where the number of signatures doesn't match the number of validators.

func NewErrInvalidCommitSignatures

func NewErrInvalidCommitSignatures(expected, actual int) ErrInvalidCommitSignatures

func (ErrInvalidCommitSignatures) Error

type ErrNotEnoughVotingPowerSigned

type ErrNotEnoughVotingPowerSigned struct {
	Got    int64
	Needed int64
}

ErrNotEnoughVotingPowerSigned is returned when not enough validators signed a commit.

func (ErrNotEnoughVotingPowerSigned) Error

type ErrVoteConflictingVotes

type ErrVoteConflictingVotes struct {
	VoteA *Vote
	VoteB *Vote
}

func NewConflictingVoteError

func NewConflictingVoteError(vote1, vote2 *Vote) *ErrVoteConflictingVotes

func (*ErrVoteConflictingVotes) Error

func (err *ErrVoteConflictingVotes) Error() string

type ErroringMockPV

type ErroringMockPV struct {
	MockPV
}

func NewErroringMockPV

func NewErroringMockPV() *ErroringMockPV

func (*ErroringMockPV) SignProposal

func (pv *ErroringMockPV) SignProposal(chainID string, proposal *pb.Proposal) error

func (*ErroringMockPV) SignVote

func (pv *ErroringMockPV) SignVote(chainID string, vote *pb.Vote) error

type HasVoteMessage

type HasVoteMessage struct {
	Height int64
	Round  int32
	Type   pb.SignedMsgType
	Index  int32
}

HasVoteMessage is sent to indicate that a particular vote has been received.

func (*HasVoteMessage) String

func (m *HasVoteMessage) String() string

String returns a string representation.

func (*HasVoteMessage) ValidateBasic

func (m *HasVoteMessage) ValidateBasic() error

ValidateBasic performs basic validation.

type Message

type Message interface {
	ValidateBasic() error
}

Message is a message that can be sent and received on the Reactor

func MsgFromProto

func MsgFromProto(msg *cpb.Message) (Message, error)

MsgFromProto takes a consensus proto message and returns the native go type

type MockPV

type MockPV struct {
	PrivKey crypto.PrivKey
	// contains filtered or unexported fields
}

MockPV implements PrivProposer without any safety or persistence. Only use it for testing.

func NewMockPV

func NewMockPV() MockPV

func NewMockPVWithParams

func NewMockPVWithParams(privKey crypto.PrivKey, breakProposalSigning, breakVoteSigning bool) MockPV

NewMockPVWithParams allows one to create a MockPV instance, but with finer grained control over the operation of the mock validator. This is useful for mocking test failures.

func (MockPV) DisableChecks

func (pv MockPV) DisableChecks()

XXX: Implement.

func (MockPV) ExtractIntoValidator

func (pv MockPV) ExtractIntoValidator(votingPower int64) *Proposer

func (MockPV) GetPubKey

func (pv MockPV) GetPubKey() (crypto.PubKey, error)

GetPubKey implements PrivProposer.

func (MockPV) SignProposal

func (pv MockPV) SignProposal(chainID string, proposal *pb.Proposal) error

SignProposal implements PrivProposer.

func (MockPV) SignVote

func (pv MockPV) SignVote(chainID string, vote *pb.Vote) error

SignVote implements PrivProposer.

func (MockPV) String

func (pv MockPV) String() string

String returns a string representation of the MockPV.

type NewRoundStepMessage

type NewRoundStepMessage struct {
	Height                int64
	Round                 int32
	Step                  RoundStepType
	SecondsSinceStartTime int64
	LastCommitRound       int32
}

NewRoundStepMessage is sent for every step taken in the ConsensusState. For every height/round/step transition

func (*NewRoundStepMessage) String

func (m *NewRoundStepMessage) String() string

String returns a string representation.

func (*NewRoundStepMessage) ValidateBasic

func (m *NewRoundStepMessage) ValidateBasic() error

ValidateBasic performs basic validation.

func (*NewRoundStepMessage) ValidateHeight

func (m *NewRoundStepMessage) ValidateHeight(initialHeight int64) error

ValidateHeight validates the height given the chain's initial height.

type NewValidBlockMessage

type NewValidBlockMessage struct {
	Height int64
	Round  int32
	// TODO: BlockParts removed, requires some sort of ID
	IsCommit bool
}

NewValidBlockMessage is sent when a validator observes a valid block B in some round r, i.e., there is a Proposal for block B and 2/3+ prevotes for the block B in the round r. In case the block is also committed, then IsCommit flag is set to true.

func (*NewValidBlockMessage) String

func (m *NewValidBlockMessage) String() string

String returns a string representation.

func (*NewValidBlockMessage) ValidateBasic

func (m *NewValidBlockMessage) ValidateBasic() error

ValidateBasic performs basic validation.

type PeerRoundState

type PeerRoundState struct {
	Height int64         `json:"height"` // Height peer is at
	Round  int32         `json:"round"`  // Round peer is at, -1 if unknown.
	Step   RoundStepType `json:"step"`   // Step peer is at

	// Estimated start of round 0 at this height
	StartTime time.Time `json:"start_time"`

	// True if peer has proposal for this round
	Proposal                   bool                `json:"proposal"`
	ProposalBlockPartSetHeader types.PartSetHeader `json:"proposal_block_part_set_header"`
	ProposalBlockParts         *bits.BitArray      `json:"proposal_block_parts"`
	// Proposal's POL round. -1 if none.
	ProposalPOLRound int32 `json:"proposal_pol_round"`

	// nil until ProposalPOLMessage received.
	ProposalPOL     *bits.BitArray `json:"proposal_pol"`
	Prevotes        *bits.BitArray `json:"prevotes"`          // All votes peer has for this round
	Precommits      *bits.BitArray `json:"precommits"`        // All precommits peer has for this round
	LastCommitRound int32          `json:"last_commit_round"` // Round of commit for last height. -1 if none.
	LastCommit      *bits.BitArray `json:"last_commit"`       // All commit precommits of commit for last height.

	// Round that we have commit for. Not necessarily unique. -1 if none.
	CatchupCommitRound int32 `json:"catchup_commit_round"`

	// All commit precommits peer has for this height & CatchupCommitRound
	CatchupCommit *bits.BitArray `json:"catchup_commit"`
}

PeerRoundState contains the known state of a peer. NOTE: Read-only when returned by PeerState.GetRoundState().

func (PeerRoundState) String

func (prs PeerRoundState) String() string

String returns a string representation of the PeerRoundState

func (PeerRoundState) StringIndented

func (prs PeerRoundState) StringIndented(indent string) string

StringIndented returns a string representation of the PeerRoundState

type PrivProposer

type PrivProposer interface {
	GetPubKey() (crypto.PubKey, error)

	SignVote(chainID string, vote *pb.Vote) error
	SignProposal(chainID string, proposal *pb.Proposal) error
}

PrivProposer defines the functionality of a local Tendermint validator that signs votes and proposals, and never double signs.

type PrivValidatorsByAddress

type PrivValidatorsByAddress []PrivProposer

func (PrivValidatorsByAddress) Len

func (pvs PrivValidatorsByAddress) Len() int

func (PrivValidatorsByAddress) Less

func (pvs PrivValidatorsByAddress) Less(i, j int) bool

func (PrivValidatorsByAddress) Swap

func (pvs PrivValidatorsByAddress) Swap(i, j int)

type Proposal

type Proposal struct {
	Type      pb.SignedMsgType
	Round     int32     `json:"round"`     // there can not be greater than 2_147_483_647 rounds
	POLRound  int32     `json:"pol_round"` // -1 if null.
	Timestamp time.Time `json:"timestamp"`
	Signature []byte    `json:"signature"`
	Data      []byte    `json:"data"`
}

Proposal defines a block proposal for the consensus. It refers to the block by BlockID field. It must be signed by the correct proposer for the given Height/Round to be considered valid. It may depend on votes from a previous round, a so-called Proof-of-Lock (POL) round, as noted in the POLRound. If POLRound >= 0, then BlockID corresponds to the block that is locked in POLRound.

func NewProposal

func NewProposal(round int32, polRound int32, data []byte) *Proposal

NewProposal returns a new Proposal. If there is no POLRound, polRound should be -1.

func ProposalFromProto

func ProposalFromProto(pp *pb.Proposal) (*Proposal, error)

FromProto sets a protobuf Proposal to the given pointer. It returns an error if the proposal is invalid.

func (*Proposal) String

func (p *Proposal) String() string

String returns a string representation of the Proposal.

1. height 2. round 3. block ID 4. POL round 5. first 6 bytes of signature 6. timestamp

See BlockID#String.

func (*Proposal) ToProto

func (p *Proposal) ToProto() *pb.Proposal

ToProto converts Proposal to protobuf

func (*Proposal) ValidateBasic

func (p *Proposal) ValidateBasic() error

ValidateBasic performs basic validation.

type ProposalMessage

type ProposalMessage struct {
	Proposal *Proposal
}

ProposalMessage is sent when a new block is proposed.

func (*ProposalMessage) String

func (m *ProposalMessage) String() string

String returns a string representation.

func (*ProposalMessage) ValidateBasic

func (m *ProposalMessage) ValidateBasic() error

ValidateBasic performs basic validation.

type ProposalPOLMessage

type ProposalPOLMessage struct {
	Height           int64
	ProposalPOLRound int32
	ProposalPOL      *bits.BitArray
}

ProposalPOLMessage is sent when a previous proposal is re-proposed.

func (*ProposalPOLMessage) String

func (m *ProposalPOLMessage) String() string

String returns a string representation.

func (*ProposalPOLMessage) ValidateBasic

func (m *ProposalPOLMessage) ValidateBasic() error

ValidateBasic performs basic validation.

type Proposer

type Proposer struct {
	Address     Address       `json:"address"`
	PubKey      crypto.PubKey `json:"pub_key"`
	VotingPower int64         `json:"voting_power"`

	ProposerPriority int64 `json:"proposer_priority"`
}

Proposer is a volatile state for each Proposer NOTE: The ProposerPriority is not included in Proposer.Hash(); make sure to update that method if changes are made here

func NewValidator

func NewValidator(pubKey crypto.PubKey, votingPower int64) *Proposer

NewValidator returns a new validator with the given pubkey and voting power.

func ValidatorFromProto

func ValidatorFromProto(vp *pb.Validator) (*Proposer, error)

ValidatorFromProto fromProto sets a protobuf Proposer to the given pointer. It returns an error if the public key is invalid.

func (*Proposer) Bytes

func (v *Proposer) Bytes() []byte

Bytes computes the unique encoding of a validator with a given voting power. These are the bytes that gets hashed in consensus. It excludes address as its redundant with the pubkey. This also excludes ProposerPriority which changes every round.

func (*Proposer) CompareProposerPriority

func (v *Proposer) CompareProposerPriority(other *Proposer) *Proposer

CompareProposerPriority returns the one with higher ProposerPriority.

func (*Proposer) Copy

func (v *Proposer) Copy() *Proposer

Copy creates a new copy of the validator so we can mutate ProposerPriority. Panics if the validator is nil.

func (*Proposer) String

func (v *Proposer) String() string

String returns a string representation of String.

1. address 2. public key 3. voting power 4. proposer priority

func (*Proposer) ToProto

func (v *Proposer) ToProto() (*pb.Validator, error)

ToProto converts Proposer to protobuf

func (*Proposer) ValidateBasic

func (v *Proposer) ValidateBasic() error

ValidateBasic performs basic validation.

type ProposerSet

type ProposerSet struct {
	// NOTE: persisted via reflect, must be exported.
	Proposers []*Proposer `json:"validators"`
	Proposer  *Proposer   `json:"proposer"`
	// contains filtered or unexported fields
}

ProposerSet represent a set of *Proposer at a given height.

The validators can be fetched by address or index. The index is in order of .VotingPower, so the indices are fixed for all rounds of a given blockchain height - ie. the validators are sorted by their voting power (descending). Secondary index - .Address (ascending).

On the other hand, the .ProposerPriority of each validator and the designated .GetProposer() of a set changes every round, upon calling .IncrementProposerPriority().

NOTE: Not goroutine-safe. NOTE: All get/set to validators should copy the value for safety.

func NewValidatorSet

func NewValidatorSet(valz []*Proposer) *ProposerSet

NewValidatorSet initializes a ProposerSet by copying over the values from `valz`, a list of Validators. If valz is nil or empty, the new ProposerSet will have an empty list of Validators.

The addresses of validators in `valz` must be unique otherwise the function panics.

Note the validator set size has an implied limit equal to that of the MaxVotesCount - commits by a validator set larger than this will fail validation.

func ValidatorSetFromExistingValidators

func ValidatorSetFromExistingValidators(valz []*Proposer) (*ProposerSet, error)

ValidatorSetFromExistingValidators takes an existing array of validators and rebuilds the exact same validator set that corresponds to it without changing the proposer priority or power if any of the validators fail validate basic then an empty set is returned.

func ValidatorSetFromProto

func ValidatorSetFromProto(vp *pb.ValidatorSet) (*ProposerSet, error)

ValidatorSetFromProto sets a protobuf ProposerSet to the given pointer. It returns an error if any of the validators from the set or the proposer is invalid

func (*ProposerSet) Copy

func (vals *ProposerSet) Copy() *ProposerSet

Copy each validator into a new ProposerSet.

func (*ProposerSet) CopyIncrementProposerPriority

func (vals *ProposerSet) CopyIncrementProposerPriority(times int32) *ProposerSet

CopyIncrementProposerPriority increments ProposerPriority and updates the proposer on a copy, and returns it.

func (*ProposerSet) GetByAddress

func (vals *ProposerSet) GetByAddress(address []byte) (index int32, val *Proposer)

GetByAddress returns an index of the validator with address and validator itself (copy) if found. Otherwise, -1 and nil are returned.

func (*ProposerSet) GetByIndex

func (vals *ProposerSet) GetByIndex(index int32) (address []byte, val *Proposer)

GetByIndex returns the validator's address and validator itself (copy) by index. It returns nil values if index is less than 0 or greater or equal to len(ProposerSet.Proposers).

func (*ProposerSet) GetProposer

func (vals *ProposerSet) GetProposer() (proposer *Proposer)

GetProposer returns the current proposer. If the validator set is empty, nil is returned.

func (*ProposerSet) HasAddress

func (vals *ProposerSet) HasAddress(address []byte) bool

HasAddress returns true if address given is in the validator set, false - otherwise.

func (*ProposerSet) Hash

func (vals *ProposerSet) Hash() []byte

Hash returns the Merkle root hash build using validators (as leaves) in the set.

func (*ProposerSet) IncrementProposerPriority

func (vals *ProposerSet) IncrementProposerPriority(times int32)

IncrementProposerPriority increments ProposerPriority of each validator and updates the proposer. Panics if validator set is empty. `times` must be positive.

func (*ProposerSet) IsNilOrEmpty

func (vals *ProposerSet) IsNilOrEmpty() bool

IsNilOrEmpty returns true if validator set is nil or empty.

func (*ProposerSet) Iterate

func (vals *ProposerSet) Iterate(fn func(index int, val *Proposer) bool)

Iterate will run the given function over the set.

func (*ProposerSet) RescalePriorities

func (vals *ProposerSet) RescalePriorities(diffMax int64)

RescalePriorities rescales the priorities such that the distance between the maximum and minimum is smaller than `diffMax`. Panics if validator set is empty.

func (*ProposerSet) Size

func (vals *ProposerSet) Size() int

Size returns the length of the validator set.

func (*ProposerSet) String

func (vals *ProposerSet) String() string

String returns a string representation of ProposerSet.

See StringIndented.

func (*ProposerSet) StringIndented

func (vals *ProposerSet) StringIndented(indent string) string

StringIndented returns an intended String.

See Proposer#String.

func (*ProposerSet) ToProto

func (vals *ProposerSet) ToProto() (*pb.ValidatorSet, error)

ToProto converts ProposerSet to protobuf

func (*ProposerSet) TotalVotingPower

func (vals *ProposerSet) TotalVotingPower() int64

TotalVotingPower returns the sum of the voting powers of all validators. It recomputes the total voting power if required.

func (*ProposerSet) UpdateWithChangeSet

func (vals *ProposerSet) UpdateWithChangeSet(changes []*Proposer) error

UpdateWithChangeSet attempts to update the validator set with 'changes'. It performs the following steps:

  • validates the changes making sure there are no duplicates and splits them in updates and deletes
  • verifies that applying the changes will not result in errors
  • computes the total voting power BEFORE removals to ensure that in the next steps the priorities across old and newly added validators are fair
  • computes the priorities of new validators against the final set
  • applies the updates against the validator set
  • applies the removals against the validator set
  • performs scaling and centering of priority values

If an error is detected during verification steps, it is returned and the validator set is not changed.

func (*ProposerSet) ValidateBasic

func (vals *ProposerSet) ValidateBasic() error

func (*ProposerSet) VerifyCommit

func (vals *ProposerSet) VerifyCommit(chainID string, data []byte,
	commit *Commit) error

VerifyCommit verifies +2/3 of the set had signed the given commit.

It checks all the signatures! While it's safe to exit as soon as we have 2/3+ signatures, doing so would impact incentivization logic in the ABCI application that depends on the LastCommitInfo sent in BeginBlock, which includes which validators signed. For instance, Gaia incentivizes proposers with a bonus for including more than +2/3 of the signatures.

func (*ProposerSet) VerifyCommitLight

func (vals *ProposerSet) VerifyCommitLight(chainID string, blockID DataHash, commit *Commit) error

VerifyCommitLight verifies +2/3 of the set had signed the given commit.

This method is primarily used by the light client and does not check all the signatures.

func (*ProposerSet) VerifyCommitLightTrusting

func (vals *ProposerSet) VerifyCommitLightTrusting(chainID string, commit *Commit, trustLevel tmmath.Fraction) error

VerifyCommitLightTrusting verifies that trustLevel of the validator set signed this commit.

NOTE the given validators do not necessarily correspond to the validator set for this commit, but there may be some intersection.

This method is primarily used by the light client and does not check all the signatures.

type ProposerStore

type ProposerStore interface {
	Get(context.Context, string) (*ProposerSet, error)
}

type RoundState

type RoundState struct {
	Height    int64         `json:"height"` // Height we are working on
	Round     int32         `json:"round"`
	Step      RoundStepType `json:"step"`
	StartTime time.Time     `json:"start_time"`

	// Subjective time when +2/3 precommits for Block at Round were found
	CommitTime         time.Time           `json:"commit_time"`
	Validators         *types.ValidatorSet `json:"validators"`
	Proposal           *types.Proposal     `json:"proposal"`
	ProposalBlock      *types.Block        `json:"proposal_block"`
	ProposalBlockParts *types.PartSet      `json:"proposal_block_parts"`
	LockedRound        int32               `json:"locked_round"`
	LockedBlock        *types.Block        `json:"locked_block"`
	LockedBlockParts   *types.PartSet      `json:"locked_block_parts"`

	// Last known round with POL for non-nil valid block.
	ValidRound int32        `json:"valid_round"`
	ValidBlock *types.Block `json:"valid_block"` // Last known block of POL mentioned above.

	// Last known block parts of POL mentioned above.
	ValidBlockParts *types.PartSet `json:"valid_block_parts"`
	// Votes                     *HeightVoteSet      `json:"votes"`
	CommitRound               int32               `json:"commit_round"` //
	LastCommit                *types.VoteSet      `json:"last_commit"`  // Last precommits at Height-1
	LastValidators            *types.ValidatorSet `json:"last_validators"`
	TriggeredTimeoutPrecommit bool                `json:"triggered_timeout_precommit"`
}

RoundState defines the internal consensus state. NOTE: Not thread safe. Should only be manipulated by functions downstream of the cs.receiveRoutine

func (*RoundState) CompleteProposalEvent

func (rs *RoundState) CompleteProposalEvent() types.EventDataCompleteProposal

CompleteProposalEvent returns information about a proposed block as an event.

func (*RoundState) NewRoundEvent

func (rs *RoundState) NewRoundEvent() types.EventDataNewRound

NewRoundEvent returns the RoundState with proposer information as an event.

func (*RoundState) RoundStateEvent

func (rs *RoundState) RoundStateEvent() types.EventDataRoundState

RoundStateEvent returns the H/R/S of the RoundState as an event.

func (*RoundState) RoundStateSimple

func (rs *RoundState) RoundStateSimple() RoundStateSimple

Compress the RoundState to RoundStateSimple

func (*RoundState) String

func (rs *RoundState) String() string

String returns a string

func (*RoundState) StringIndented

func (rs *RoundState) StringIndented(indent string) string

StringIndented returns a string

func (*RoundState) StringShort

func (rs *RoundState) StringShort() string

StringShort returns a string

type RoundStateSimple

type RoundStateSimple struct {
	HeightRoundStep   string         `json:"height/round/step"`
	StartTime         time.Time      `json:"start_time"`
	ProposalBlockHash bytes.HexBytes `json:"proposal_block_hash"`
	LockedBlockHash   bytes.HexBytes `json:"locked_block_hash"`
	ValidBlockHash    bytes.HexBytes `json:"valid_block_hash"`
	// Votes             json.RawMessage     `json:"height_vote_set"`
	Proposer types.ValidatorInfo `json:"proposer"`
}

Compressed version of the RoundState for use in RPC

type RoundStepType

type RoundStepType uint8 // These must be numeric, ordered.

RoundStepType enumerates the state of the consensus state machine

func (RoundStepType) IsValid

func (rs RoundStepType) IsValid() bool

IsValid returns true if the step is valid, false if unknown/undefined.

func (RoundStepType) String

func (rs RoundStepType) String() string

String returns a string

type Validator

type Validator func(context.Context, []byte) (tmbytes.HexBytes, error)

type ValidatorsByAddress

type ValidatorsByAddress []*Proposer

ValidatorsByAddress implements sort.Interface for []*Proposer based on the Address field.

func (ValidatorsByAddress) Len

func (valz ValidatorsByAddress) Len() int

func (ValidatorsByAddress) Less

func (valz ValidatorsByAddress) Less(i, j int) bool

func (ValidatorsByAddress) Swap

func (valz ValidatorsByAddress) Swap(i, j int)

type ValidatorsByVotingPower

type ValidatorsByVotingPower []*Proposer

ValidatorsByVotingPower implements sort.Interface for []*Proposer based on the VotingPower and Address fields.

func (ValidatorsByVotingPower) Len

func (valz ValidatorsByVotingPower) Len() int

func (ValidatorsByVotingPower) Less

func (valz ValidatorsByVotingPower) Less(i, j int) bool

func (ValidatorsByVotingPower) Swap

func (valz ValidatorsByVotingPower) Swap(i, j int)

type Vote

type Vote struct {
	Type             pb.SignedMsgType `json:"type"`
	DataHash         DataHash         `json:"block_id"` // zero if vote is nil.
	Timestamp        time.Time        `json:"timestamp"`
	ValidatorAddress Address          `json:"validator_address"`
	ValidatorIndex   int32            `json:"validator_index"`
	Signature        []byte           `json:"signature"`
}

Vote represents a prevote, precommit, or commit vote from validators for consensus.

func MakeVote

func MakeVote(
	height int64,
	dataHash DataHash,
	valSet *ProposerSet,
	privVal PrivProposer,
	chainID string,
	now time.Time,
) (*Vote, error)

func NewVote

func NewVote(t pb.SignedMsgType, round int32, index int32, address []byte, dataHash *DataHash) *Vote

func VoteFromProto

func VoteFromProto(pv *pb.Vote) (*Vote, error)

FromProto converts a proto generetad type to a handwritten type return type, nil if everything converts safely, otherwise nil, error

func (*Vote) CommitSig

func (vote *Vote) CommitSig() CommitSig

CommitSig converts the Vote to a CommitSig.

func (*Vote) Copy

func (vote *Vote) Copy() *Vote

func (*Vote) String

func (vote *Vote) String() string

String returns a string representation of Vote.

1. validator index 2. first 6 bytes of validator address 3. height 4. round, 5. type byte 6. type string 7. first 6 bytes of block hash 8. first 6 bytes of signature 9. timestamp

func (*Vote) ToProto

func (vote *Vote) ToProto() *pb.Vote

ToProto converts the handwritten type to proto generated type return type, nil if everything converts safely, otherwise nil, error

func (*Vote) ValidateBasic

func (vote *Vote) ValidateBasic() error

ValidateBasic performs basic validation.

func (*Vote) Verify

func (vote *Vote) Verify(chainID string, pubKey crypto.PubKey) error

type VoteMessage

type VoteMessage struct {
	Vote *Vote
}

VoteMessage is sent when voting for a proposal (or lack thereof).

func (*VoteMessage) String

func (m *VoteMessage) String() string

String returns a string representation.

func (*VoteMessage) ValidateBasic

func (m *VoteMessage) ValidateBasic() error

ValidateBasic performs basic validation.

type VoteSet

type VoteSet struct {
	// contains filtered or unexported fields
}

VoteSet helps collect signatures from validators at each height+round for a predefined vote type.

We need VoteSet to be able to keep track of conflicting votes when validators double-sign. Yet, we can't keep track of *all* the votes seen, as that could be a DoS attack vector.

There are two storage areas for votes. 1. voteSet.votes 2. voteSet.votesByBlock

`.votes` is the "canonical" list of votes. It always has at least one vote, if a vote from a validator had been seen at all. Usually it keeps track of the first vote seen, but when a 2/3 majority is found, votes for that get priority and are copied over from `.votesByBlock`.

`.votesByBlock` keeps track of a list of votes for a particular block. There are two ways a &blockVotes{} gets created in `.votesByBlock`. 1. the first vote seen by a validator was for the particular block. 2. a peer claims to have seen 2/3 majority for the particular block.

Since the first vote from a validator will always get added in `.votesByBlock` , all votes in `.votes` will have a corresponding entry in `.votesByBlock`.

When a &blockVotes{} in `.votesByBlock` reaches a 2/3 majority quorum, its votes are copied into `.votes`.

All this is memory bounded because conflicting votes only get added if a peer told us to track that block, each peer only gets to tell us 1 such block, and, there's only a limited number of peers.

NOTE: Assumes that the sum total of voting power does not exceed MaxUInt64.

func CommitToVoteSet

func CommitToVoteSet(chainID string, commit *Commit, vals *ProposerSet) *VoteSet

CommitToVoteSet constructs a VoteSet from the Commit and validator set. Panics if signatures from the commit can't be added to the voteset. Inverse of VoteSet.MakeCommit().

func NewVoteSet

func NewVoteSet(chainID string,
	signedMsgType pb.SignedMsgType, valSet *ProposerSet) *VoteSet

Constructs a new VoteSet struct used to accumulate votes for given height/round.

func (*VoteSet) AddVote

func (voteSet *VoteSet) AddVote(vote *Vote) (added bool, err error)

Returns added=true if vote is valid and new. Otherwise returns err=ErrVote[

UnexpectedStep | InvalidIndex | InvalidAddress |
InvalidSignature | InvalidBlockHash | ConflictingVotes ]

Duplicate votes return added=false, err=nil. Conflicting votes return added=*, err=ErrVoteConflictingVotes. NOTE: vote should not be mutated after adding. NOTE: VoteSet must not be nil NOTE: Vote must not be nil

func (*VoteSet) BitArray

func (voteSet *VoteSet) BitArray() *bits.BitArray

Implements VoteSetReader.

func (*VoteSet) BitArrayByBlockID

func (voteSet *VoteSet) BitArrayByBlockID(blockID DataHash) *bits.BitArray

func (*VoteSet) BitArrayString

func (voteSet *VoteSet) BitArrayString() string

Return the bit-array of votes including the fraction of power that has voted like: "BA{29:xx__x__x_x___x__x_______xxx__} 856/1304 = 0.66"

func (*VoteSet) ChainID

func (voteSet *VoteSet) ChainID() string

func (*VoteSet) Done

func (voteSet *VoteSet) Done() <-chan struct{}

func (*VoteSet) GetByAddress

func (voteSet *VoteSet) GetByAddress(address []byte) *Vote

func (*VoteSet) GetByIndex

func (voteSet *VoteSet) GetByIndex(valIndex int32) *Vote

NOTE: if validator has conflicting votes, returns "canonical" vote Implements VoteSetReader.

func (*VoteSet) HasAll

func (voteSet *VoteSet) HasAll() bool

func (*VoteSet) HasTwoThirdsAny

func (voteSet *VoteSet) HasTwoThirdsAny() bool

func (*VoteSet) HasTwoThirdsMajority

func (voteSet *VoteSet) HasTwoThirdsMajority() bool

func (*VoteSet) IsCommit

func (voteSet *VoteSet) IsCommit() bool

Implements VoteSetReader.

func (*VoteSet) List

func (voteSet *VoteSet) List() []Vote

List returns a copy of the list of votes stored by the VoteSet.

func (*VoteSet) LogString

func (voteSet *VoteSet) LogString() string

LogString produces a logging suitable string representation of the vote set.

func (*VoteSet) MakeCommit

func (voteSet *VoteSet) MakeCommit() *Commit

MakeCommit constructs a Commit from the VoteSet. It only includes precommits for the block, which has 2/3+ majority, and nil.

Panics if the vote type is not PrecommitType or if there's no +2/3 votes for a single block.

func (*VoteSet) MarshalJSON

func (voteSet *VoteSet) MarshalJSON() ([]byte, error)

Marshal the VoteSet to JSON. Same as String(), just in JSON, and without the height/round/signedMsgType (since its already included in the votes).

func (*VoteSet) SetPeerMaj23

func (voteSet *VoteSet) SetPeerMaj23(peerID peer.ID, blockID DataHash) error

If a peer claims that it has 2/3 majority for given blockKey, call this. NOTE: if there are too many peers, or too much peer churn, this can cause memory issues. TODO: implement ability to remove peers too NOTE: VoteSet must not be nil TODO: may be remove this??

func (*VoteSet) Size

func (voteSet *VoteSet) Size() int

Implements VoteSetReader.

func (*VoteSet) String

func (voteSet *VoteSet) String() string

String returns a string representation of VoteSet.

See StringIndented.

func (*VoteSet) StringIndented

func (voteSet *VoteSet) StringIndented(indent string) string

StringIndented returns an indented String.

Height Round Type Votes Votes bit array 2/3+ majority

See Vote#String.

func (*VoteSet) StringShort

func (voteSet *VoteSet) StringShort() string

StringShort returns a short representation of VoteSet.

1. height 2. round 3. signed msg type 4. first 2/3+ majority 5. fraction of voted power 6. votes bit array 7. 2/3+ majority for each peer

func (*VoteSet) TwoThirdsMajority

func (voteSet *VoteSet) TwoThirdsMajority() (blockID DataHash, ok bool)

If there was a +2/3 majority for blockID, return blockID and true. Else, return the empty BlockID{} and false.

func (*VoteSet) Type

func (voteSet *VoteSet) Type() byte

Implements VoteSetReader.

func (*VoteSet) VoteStrings

func (voteSet *VoteSet) VoteStrings() []string

Returns a list of votes compressed to more readable strings.

type VoteSetBitsMessage

type VoteSetBitsMessage struct {
	Height   int64
	Round    int32
	Type     pb.SignedMsgType
	DataHash DataHash
	Votes    *bits.BitArray
}

VoteSetBitsMessage is sent to communicate the bit-array of votes seen for the BlockID.

func (*VoteSetBitsMessage) String

func (m *VoteSetBitsMessage) String() string

String returns a string representation.

func (*VoteSetBitsMessage) ValidateBasic

func (m *VoteSetBitsMessage) ValidateBasic() error

ValidateBasic performs basic validation.

type VoteSetJSON

type VoteSetJSON struct {
	Votes         []string             `json:"votes"`
	VotesBitArray string               `json:"votes_bit_array"`
	PeerMaj23s    map[peer.ID]DataHash `json:"peer_maj_23s"`
}

More human readable JSON of the vote set NOTE: insufficient for unmarshalling from (compressed votes) TODO: make the peerMaj23s nicer to read (eg just the block hash)

type VoteSetMaj23Message

type VoteSetMaj23Message struct {
	Height   int64
	Round    int32
	Type     pb.SignedMsgType
	DataHash DataHash
}

VoteSetMaj23Message is sent to indicate that a given BlockID has seen +2/3 votes.

func (*VoteSetMaj23Message) String

func (m *VoteSetMaj23Message) String() string

String returns a string representation.

func (*VoteSetMaj23Message) ValidateBasic

func (m *VoteSetMaj23Message) ValidateBasic() error

ValidateBasic performs basic validation.

type VoteSetReader

type VoteSetReader interface {
	Type() byte
	Size() int
	BitArray() *bits.BitArray
	GetByIndex(int32) *Vote
	IsCommit() bool
}

Common interface between *consensus.VoteSet and types.Commit

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL