mirror of https://github.com/poanetwork/gecko.git
74 lines
2.0 KiB
Go
74 lines
2.0 KiB
Go
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package poll
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/ava-labs/gecko/ids"
|
|
)
|
|
|
|
type earlyTermNoTraversalFactory struct {
|
|
alpha int
|
|
}
|
|
|
|
// NewEarlyTermNoTraversalFactory returns a factory that returns polls with
|
|
// early termination, without doing DAG traversals
|
|
func NewEarlyTermNoTraversalFactory(alpha int) Factory {
|
|
return &earlyTermNoTraversalFactory{alpha: alpha}
|
|
}
|
|
|
|
func (f *earlyTermNoTraversalFactory) New(vdrs ids.ShortSet) Poll {
|
|
return &earlyTermNoTraversalPoll{
|
|
polled: vdrs,
|
|
alpha: f.alpha,
|
|
}
|
|
}
|
|
|
|
// earlyTermNoTraversalPoll finishes when any remaining validators can't change
|
|
// the result of the poll. However, does not terminate tightly with this bound.
|
|
// It terminates as quickly as it can without performing any DAG traversals.
|
|
type earlyTermNoTraversalPoll struct {
|
|
votes ids.Bag
|
|
polled ids.ShortSet
|
|
alpha int
|
|
}
|
|
|
|
// Vote registers a response for this poll
|
|
func (p *earlyTermNoTraversalPoll) Vote(vdr ids.ShortID, vote ids.ID) {
|
|
if !p.polled.Contains(vdr) {
|
|
// if the validator wasn't polled or already responded to this poll, we
|
|
// should just drop the vote
|
|
return
|
|
}
|
|
|
|
// make sure that a validator can't respond multiple times
|
|
p.polled.Remove(vdr)
|
|
|
|
// track the votes the validator responded with
|
|
p.votes.Add(vote)
|
|
}
|
|
|
|
// Drop any future response for this poll
|
|
func (p *earlyTermNoTraversalPoll) Drop(vdr ids.ShortID) {
|
|
p.polled.Remove(vdr)
|
|
}
|
|
|
|
// Finished returns true when all validators have voted
|
|
func (p *earlyTermNoTraversalPoll) Finished() bool {
|
|
remaining := p.polled.Len()
|
|
received := p.votes.Len()
|
|
_, freq := p.votes.Mode()
|
|
return remaining == 0 || // All k nodes responded
|
|
freq >= p.alpha || // An alpha majority has returned
|
|
received+remaining < p.alpha // An alpha majority can never return
|
|
}
|
|
|
|
// Result returns the result of this poll
|
|
func (p *earlyTermNoTraversalPoll) Result() ids.Bag { return p.votes }
|
|
|
|
func (p *earlyTermNoTraversalPoll) String() string {
|
|
return fmt.Sprintf("waiting on %s", p.polled)
|
|
}
|