Documentation ¶
Index ¶
- type SafetyRules
- func (r *SafetyRules) IsSafeToTimeout(curView uint64, newestQC *flow.QuorumCertificate, ...) error
- func (r *SafetyRules) IsSafeToVote(proposal *model.Proposal) error
- func (r *SafetyRules) ProduceTimeout(curView uint64, newestQC *flow.QuorumCertificate, ...) (*model.TimeoutObject, error)
- func (r *SafetyRules) ProduceVote(proposal *model.Proposal, curView uint64) (*model.Vote, error)
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:
- 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.
- 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) IsSafeToVote ¶
func (r *SafetyRules) IsSafeToVote(proposal *model.Proposal) error
IsSafeToVote checks if this proposal is valid in terms of voting rules, if voting for this proposal won't break safety rules. Expected errors during normal operations:
- NoVoteError if replica already acted during this view (either voted or generated timeout)
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 ¶
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).