safetyrules

package
v0.38.0-preview.0.0.5 Latest Latest
Warning

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

Go to latest
Published: Nov 27, 2024 License: AGPL-3.0 Imports: 4 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type SafetyRules

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

SafetyRules is a dedicated module that enforces consensus safety. This component has the sole authority to generate votes and timeouts. It follows voting and timeout rules for creating votes and timeouts respectively. Caller can be sure that created vote or timeout doesn't break safety and can be used in consensus process. SafetyRules relies on hotstuff.Persister to store latest state of hotstuff.SafetyData.

The voting rules implemented by SafetyRules are:

  1. Replicas vote in strictly increasing views. At most one vote can be signed per view. Caution: The leader's block signature is formally a vote for their own proposal.
  2. Each block has to include a TC or a QC from the previous view. a. [Happy path] If the previous view resulted in a QC then the proposer should include it in their block. b. [Recovery path] If the previous round did *not* result in a QC, the leader of the subsequent round *must* include a valid TC for the previous view in its block.

Condition 1 guarantees a foundational security theorem for HotStuff (incl. the DiemBFT / Jolteon variant):

THEOREM: For each view, there can be at most 1 certified block.

NOT safe for concurrent use.

func New

func New(
	signer hotstuff.Signer,
	persist hotstuff.Persister,
	committee hotstuff.DynamicCommittee,
) (*SafetyRules, error)

New creates a new SafetyRules instance

func (*SafetyRules) IsSafeToTimeout

func (r *SafetyRules) IsSafeToTimeout(curView uint64, newestQC *flow.QuorumCertificate, lastViewTC *flow.TimeoutCertificate) error

IsSafeToTimeout checks if it's safe to timeout with proposed data, i.e. timing out won't break safety. newestQC is the valid QC with the greatest view that we have observed. lastViewTC is the TC for the previous view (might be nil).

When generating a timeout, the inputs are provided by node-internal components. Failure to comply with the protocol is a symptom of an internal bug. We don't expect any errors during normal operations.

func (*SafetyRules) ProduceTimeout

func (r *SafetyRules) ProduceTimeout(curView uint64, newestQC *flow.QuorumCertificate, lastViewTC *flow.TimeoutCertificate) (*model.TimeoutObject, error)

ProduceTimeout takes current view, highest locally known QC and TC (optional, must be nil if and only if QC is for previous view) and decides whether to produce timeout for current view. Returns:

  • (timeout, nil): It is safe to timeout for current view using newestQC and lastViewTC.
  • (nil, model.NoTimeoutError): If replica is not part of the authorized consensus committee (anymore) and therefore is not authorized to produce a valid timeout object. This sentinel error is _expected_ during normal operation, e.g. during the grace-period after Epoch switchover or after the replica self-ejected.

All other errors are unexpected and potential symptoms of uncovered edge cases or corrupted internal state (fatal).

func (*SafetyRules) ProduceVote

func (r *SafetyRules) ProduceVote(signedProposal *model.SignedProposal, curView uint64) (*model.Vote, error)

ProduceVote will make a decision on whether it will vote for the given proposal, the returned error indicates whether to vote or not. To ensure that only safe proposals are being voted on, we check that the proposer is a valid committee member and that the proposal complies with voting rules. We expect that only well-formed proposals with valid signatures are submitted for voting. The curView is taken as input to ensure SafetyRules will only vote for proposals at current view and prevent double voting. Returns:

  • (vote, nil): On the _first_ block for the current view that is safe to vote for. Subsequently, voter does _not_ vote for any other block with the same (or lower) view.
  • (nil, model.NoVoteError): If the voter decides that it does not want to vote for the given block. This is a sentinel error and _expected_ during normal operation.

All other errors are unexpected and potential symptoms of uncovered edge cases or corrupted internal state (fatal).

func (*SafetyRules) SignOwnProposal

func (r *SafetyRules) SignOwnProposal(unsignedProposal *model.Proposal) (*model.Vote, error)

SignOwnProposal takes an unsigned block proposal and produces a vote for it. Vote is a cryptographic commitment to the proposal. By adding the vote to an unsigned proposal, the caller constructs a signed block proposal. This method has to be used only by the leader, which must be the proposer of the block (or an exception is returned). Implementors must guarantee that: - vote on the proposal satisfies safety rules - maximum one proposal is signed per view Returns:

  • (vote, nil): the passed unsigned proposal is a valid one, and it's safe to make a proposal. Subsequently, leader does _not_ produce any _other_ proposal with the same (or lower) view.
  • (nil, model.NoVoteError): according to HotStuff's Safety Rules, it is not safe to sign the given proposal. This could happen because we have already proposed or timed out for the given view. This is a sentinel error and _expected_ during normal operation.

All other errors are unexpected and potential symptoms of uncovered edge cases or corrupted internal state (fatal).

Jump to

Keyboard shortcuts

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