Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace snowball/snowflake interface with single shared snow interface #2717

Merged
merged 10 commits into from
Feb 12, 2024
2 changes: 0 additions & 2 deletions snow/consensus/snowball/binary_slush.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ package snowball

import "fmt"

var _ BinarySlush = (*binarySlush)(nil)

func newBinarySlush(choice int) binarySlush {
return binarySlush{
preference: choice,
Expand Down
2 changes: 1 addition & 1 deletion snow/consensus/snowball/binary_snowball.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package snowball

import "fmt"

var _ BinarySnowball = (*binarySnowball)(nil)
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
var _ BinarySnow = (*binarySnowball)(nil)

func newBinarySnowball(beta, choice int) binarySnowball {
return binarySnowball{
Expand Down
2 changes: 1 addition & 1 deletion snow/consensus/snowball/binary_snowflake.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package snowball

import "fmt"

var _ BinarySnowflake = (*binarySnowflake)(nil)
var _ BinarySnow = (*binarySnowflake)(nil)

func newBinarySnowflake(beta, choice int) binarySnowflake {
return binarySnowflake{
Expand Down
109 changes: 31 additions & 78 deletions snow/consensus/snowball/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,19 @@ type Consensus interface {
Finalized() bool
}

// NnarySnowball augments NnarySnowflake with a counter that tracks the total
// number of positive responses from a network sample.
type NnarySnowball interface{ NnarySnowflake }

// NnarySnowflake is a snowflake instance deciding between an unbounded number
// of values. After performing a network sample of k nodes, if you have alpha
// votes for one of the choices, you should vote for that choice. Otherwise, you
// should reset.
type NnarySnowflake interface {
// ConsensusFactory produces NnarySnowflake instances
type ConsensusFactory interface {
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
New(params Parameters, choice ids.ID) NnarySnow
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
NewUnary(params Parameters) UnarySnow
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
}

// NnarySnow is a snow instance deciding between an unbounded number
// of values.
// The caller samples k nodes and then calls
// 1. RecordSuccessfulPoll if choice collects >= alphaConfidence votes
// 2. RecordPollPreference if choice collects >= alphaPreference votes
// 3. RecordUnsuccessfulPoll otherwise
type NnarySnow interface {
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
fmt.Stringer

// Adds a new possible choice
Expand All @@ -73,29 +77,12 @@ type NnarySnowflake interface {
Finalized() bool
}

// NnarySlush is a slush instance deciding between an unbounded number of
// values. After performing a network sample of k nodes, if you have alpha
// votes for one of the choices, you should vote for that choice.
type NnarySlush interface {
fmt.Stringer

// Returns the currently preferred choice to be finalized
Preference() ids.ID

// RecordSuccessfulPoll records a successful poll towards finalizing the
// specified choice. Assumes the choice was previously added.
RecordSuccessfulPoll(choice ids.ID)
}

// BinarySnowball augments BinarySnowflake with a counter that tracks the total
// number of positive responses from a network sample.
type BinarySnowball interface{ BinarySnowflake }

// BinarySnowflake is a snowball instance deciding between two values
// After performing a network sample of k nodes, if you have alpha votes for
// one of the choices, you should vote for that choice. Otherwise, you should
// reset.
type BinarySnowflake interface {
// BinarySnow is a snow instance deciding between two values.
// The caller samples k nodes and then calls
// 1. RecordSuccessfulPoll if choice collects >= alphaConfidence votes
// 2. RecordPollPreference if choice collects >= alphaPreference votes
// 3. RecordUnsuccessfulPoll otherwise
type BinarySnow interface {
fmt.Stringer

// Returns the currently preferred choice to be finalized
Expand All @@ -116,31 +103,20 @@ type BinarySnowflake interface {
Finalized() bool
}

// BinarySlush is a slush instance deciding between two values. After performing
// a network sample of k nodes, if you have alpha votes for one of the choices,
// you should vote for that choice.
type BinarySlush interface {
fmt.Stringer

// Returns the currently preferred choice to be finalized
Preference() int

// RecordSuccessfulPoll records a successful poll towards finalizing the
// specified choice
RecordSuccessfulPoll(choice int)
}

// UnarySnowball is a snowball instance deciding on one value. After performing
// a network sample of k nodes, if you have alpha votes for the choice, you
// should vote. Otherwise, you should reset.
type UnarySnowball interface {
// UnarySnow is a snow instance deciding on one value.
// The caller samples k nodes and then calls
// 1. RecordSuccessfulPoll if choice collects >= alphaConfidence votes
// 2. RecordPollPreference if choice collects >= alphaPreference votes
// 3. RecordUnsuccessfulPoll otherwise
type UnarySnow interface {
fmt.Stringer

// RecordSuccessfulPoll records a successful poll towards finalizing
// RecordSuccessfulPoll records a successful poll that reaches an alpha
// confidence threshold.
RecordSuccessfulPoll()

// RecordPollPreference records a poll that strengthens the preference but
// did not contribute towards finalizing
// RecordPollPreference records a poll that receives an alpha preference
// threshold, but not an alpha confidence threshold.
RecordPollPreference()

// RecordUnsuccessfulPoll resets the snowflake counter of this instance
Expand All @@ -151,31 +127,8 @@ type UnarySnowball interface {

// Returns a new binary snowball instance with the agreement parameters
// transferred. Takes in the new beta value and the original choice
Extend(beta, originalPreference int) BinarySnowball

// Returns a new unary snowball instance with the same state
Clone() UnarySnowball
}

// UnarySnowflake is a snowflake instance deciding on one value. After
// performing a network sample of k nodes, if you have alpha votes for the
// choice, you should vote. Otherwise, you should reset.
type UnarySnowflake interface {
fmt.Stringer

// RecordSuccessfulPoll records a successful poll towards finalizing
RecordSuccessfulPoll()

// RecordUnsuccessfulPoll resets the snowflake counter of this instance
RecordUnsuccessfulPoll()

// Return whether a choice has been finalized
Finalized() bool

// Returns a new binary snowball instance with the agreement parameters
// transferred. Takes in the new beta value and the original choice
Extend(beta, originalPreference int) BinarySnowflake
Extend(beta, originalPreference int) BinarySnow

// Returns a new unary snowflake instance with the same state
Clone() UnarySnowflake
Clone() UnarySnow
}
8 changes: 4 additions & 4 deletions snow/consensus/snowball/consensus_performance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ func TestDualAlphaOptimization(t *testing.T) {
source = prng.NewMT19937()
)

singleAlphaNetwork := NewNetwork(params, numColors, source)
singleAlphaNetwork := NewNetwork(SnowballFactory{}, params, numColors, source)
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved

params.AlphaPreference = params.K/2 + 1
dualAlphaNetwork := NewNetwork(params, numColors, source)
dualAlphaNetwork := NewNetwork(SnowballFactory{}, params, numColors, source)

source.Seed(seed)
for i := 0; i < numNodes; i++ {
Expand Down Expand Up @@ -62,8 +62,8 @@ func TestTreeConvergenceOptimization(t *testing.T) {
source = prng.NewMT19937()
)

treeNetwork := NewNetwork(params, numColors, source)
flatNetwork := NewNetwork(params, numColors, source)
treeNetwork := NewNetwork(SnowballFactory{}, params, numColors, source)
flatNetwork := NewNetwork(SnowballFactory{}, params, numColors, source)

source.Seed(seed)
for i := 0; i < numNodes; i++ {
Expand Down
2 changes: 1 addition & 1 deletion snow/consensus/snowball/consensus_reversibility_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestSnowballGovernance(t *testing.T) {
source = prng.NewMT19937()
)

nBitwise := NewNetwork(params, numColors, source)
nBitwise := NewNetwork(SnowballFactory{}, params, numColors, source)

source.Seed(seed)
for i := 0; i < numRed; i++ {
Expand Down
2 changes: 1 addition & 1 deletion snow/consensus/snowball/consensus_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ var (
_ Consensus = (*Byzantine)(nil)
)

func NewByzantine(_ Parameters, choice ids.ID) Consensus {
func NewByzantine(_ ConsensusFactory, _ Parameters, choice ids.ID) Consensus {
return &Byzantine{
preference: choice,
}
Expand Down
12 changes: 7 additions & 5 deletions snow/consensus/snowball/flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ import (

var _ Consensus = (*Flat)(nil)

func NewFlat(params Parameters, choice ids.ID) Consensus {
func NewFlat(factory ConsensusFactory, params Parameters, choice ids.ID) Consensus {
sf := factory.New(params, choice)
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved

return &Flat{
nnarySnowball: newNnarySnowball(params.BetaVirtuous, params.BetaRogue, choice),
params: params,
NnarySnow: sf,
params: params,
}
}

// Flat is a naive implementation of a multi-choice snowball instance
// Flat is a naive implementation of a multi-choice snow instance
type Flat struct {
// wraps the n-nary snowball logic
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
nnarySnowball
NnarySnow

// params contains all the configurations of a snowball instance
params Parameters
Expand Down
2 changes: 1 addition & 1 deletion snow/consensus/snowball/flat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func TestFlat(t *testing.T) {
BetaVirtuous: 1,
BetaRogue: 2,
}
f := NewFlat(params, Red)
f := NewFlat(SnowballFactory{}, params, Red)
f.Add(Green)
f.Add(Blue)

Expand Down
10 changes: 6 additions & 4 deletions snow/consensus/snowball/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import (
"github.com/ava-labs/avalanchego/utils/sampler"
)

type newConsensusFunc func(params Parameters, choice ids.ID) Consensus
type newConsensusFunc func(cf ConsensusFactory, params Parameters, choice ids.ID) Consensus

type Network struct {
params Parameters
colors []ids.ID
rngSource sampler.Source
nodes, running []Consensus
cf ConsensusFactory
}

// Create a new network with [numColors] different possible colors to finalize.
func NewNetwork(params Parameters, numColors int, rngSource sampler.Source) *Network {
func NewNetwork(cf ConsensusFactory, params Parameters, numColors int, rngSource sampler.Source) *Network {
n := &Network{
params: params,
rngSource: rngSource,
cf: cf,
}
for i := 0; i < numColors; i++ {
n.colors = append(n.colors, ids.Empty.Prefix(uint64(i)))
Expand All @@ -35,7 +37,7 @@ func (n *Network) AddNode(newConsensusFunc newConsensusFunc) Consensus {
s.Initialize(uint64(len(n.colors)))
indices, _ := s.Sample(len(n.colors))

consensus := newConsensusFunc(n.params, n.colors[int(indices[0])])
consensus := newConsensusFunc(n.cf, n.params, n.colors[int(indices[0])])
for _, index := range indices[1:] {
consensus.Add(n.colors[int(index)])
}
Expand All @@ -56,7 +58,7 @@ func (n *Network) AddNodeSpecificColor(
initialPreference int,
options []int,
) Consensus {
consensus := newConsensusFunc(n.params, n.colors[initialPreference])
consensus := newConsensusFunc(n.cf, n.params, n.colors[initialPreference])

for _, i := range options {
consensus.Add(n.colors[i])
Expand Down
2 changes: 0 additions & 2 deletions snow/consensus/snowball/nnary_slush.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"github.com/ava-labs/avalanchego/ids"
)

var _ NnarySlush = (*nnarySlush)(nil)

func newNnarySlush(choice ids.ID) nnarySlush {
return nnarySlush{
preference: choice,
Expand Down
17 changes: 16 additions & 1 deletion snow/consensus/snowball/nnary_snowball.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,22 @@ import (
"github.com/ava-labs/avalanchego/ids"
)

var _ NnarySnowball = (*nnarySnowball)(nil)
var (
_ NnarySnow = (*nnarySnowball)(nil)
_ ConsensusFactory = SnowballFactory{}
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
)

type SnowballFactory struct{}
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved

func (SnowballFactory) New(params Parameters, choice ids.ID) NnarySnow {
sb := newNnarySnowball(params.BetaVirtuous, params.BetaRogue, choice)
return &sb
}

func (SnowballFactory) NewUnary(params Parameters) UnarySnow {
sb := newUnarySnowball(params.BetaVirtuous)
return &sb
}
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved

func newNnarySnowball(betaVirtuous, betaRogue int, choice ids.ID) nnarySnowball {
return nnarySnowball{
Expand Down
17 changes: 16 additions & 1 deletion snow/consensus/snowball/nnary_snowflake.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,22 @@ import (
"github.com/ava-labs/avalanchego/ids"
)

var _ NnarySnowflake = (*nnarySnowflake)(nil)
var (
_ NnarySnow = (*nnarySnowflake)(nil)
_ ConsensusFactory = (SnowflakeFactory{})
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
aaronbuchwald marked this conversation as resolved.
Show resolved Hide resolved
)

type SnowflakeFactory struct{}

func (SnowflakeFactory) New(params Parameters, choice ids.ID) NnarySnow {
sf := newNnarySnowflake(params.BetaVirtuous, params.BetaRogue, choice)
return &sf
}

func (SnowflakeFactory) NewUnary(params Parameters) UnarySnow {
sf := newUnarySnowflake(params.BetaVirtuous)
return &sf
}

func newNnarySnowflake(betaVirtuous, betaRogue int, choice ids.ID) nnarySnowflake {
return nnarySnowflake{
Expand Down
Loading
Loading