Skip to content

Commit

Permalink
Replace snowball/snowflake interface with single shared snow interface (
Browse files Browse the repository at this point in the history
#2717)

Signed-off-by: aaronbuchwald <aaron.buchwald56@gmail.com>
Signed-off-by: Stephen Buttolph <stephen@avalabs.org>
Co-authored-by: Stephen Buttolph <stephen@avalabs.org>
  • Loading branch information
aaronbuchwald and StephenButtolph authored Feb 12, 2024
1 parent f1f88ac commit adc1d4b
Show file tree
Hide file tree
Showing 19 changed files with 161 additions and 167 deletions.
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)
var _ Binary = (*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 _ Binary = (*binarySnowflake)(nil)

func newBinarySnowflake(beta, choice int) binarySnowflake {
return binarySnowflake{
Expand Down
108 changes: 30 additions & 78 deletions snow/consensus/snowball/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,18 @@ 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 {
// Factory produces Nnary and Unary decision instances
type Factory interface {
NewNnary(params Parameters, choice ids.ID) Nnary
NewUnary(params Parameters) Unary
}

// Nnary 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 Nnary interface {
fmt.Stringer

// Adds a new possible choice
Expand All @@ -73,29 +76,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 {
// Binary 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 Binary interface {
fmt.Stringer

// Returns the currently preferred choice to be finalized
Expand All @@ -116,31 +102,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 {
// Unary 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 Unary 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 +126,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) Binary

// Returns a new unary snowflake instance with the same state
Clone() UnarySnowflake
Clone() Unary
}
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)

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(_ Factory, _ Parameters, choice ids.ID) Consensus {
return &Byzantine{
preference: choice,
}
Expand Down
35 changes: 35 additions & 0 deletions snow/consensus/snowball/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package snowball

import "github.com/ava-labs/avalanchego/ids"

var (
SnowballFactory Factory = snowballFactory{}
SnowflakeFactory Factory = snowflakeFactory{}
)

type snowballFactory struct{}

func (snowballFactory) NewNnary(params Parameters, choice ids.ID) Nnary {
sb := newNnarySnowball(params.BetaVirtuous, params.BetaRogue, choice)
return &sb
}

func (snowballFactory) NewUnary(params Parameters) Unary {
sb := newUnarySnowball(params.BetaVirtuous)
return &sb
}

type snowflakeFactory struct{}

func (snowflakeFactory) NewNnary(params Parameters, choice ids.ID) Nnary {
sf := newNnarySnowflake(params.BetaVirtuous, params.BetaRogue, choice)
return &sf
}

func (snowflakeFactory) NewUnary(params Parameters) Unary {
sf := newUnarySnowflake(params.BetaVirtuous)
return &sf
}
14 changes: 7 additions & 7 deletions snow/consensus/snowball/flat.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ import (

var _ Consensus = (*Flat)(nil)

func NewFlat(params Parameters, choice ids.ID) Consensus {
func NewFlat(factory Factory, params Parameters, choice ids.ID) Consensus {
return &Flat{
nnarySnowball: newNnarySnowball(params.BetaVirtuous, params.BetaRogue, choice),
params: params,
Nnary: factory.NewNnary(params, choice),
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
nnarySnowball
// wraps the n-nary snow logic
Nnary

// params contains all the configurations of a snowball instance
// params contains all the configurations of a snow 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(factory Factory, params Parameters, choice ids.ID) Consensus

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

// Create a new network with [numColors] different possible colors to finalize.
func NewNetwork(params Parameters, numColors int, rngSource sampler.Source) *Network {
func NewNetwork(factory Factory, params Parameters, numColors int, rngSource sampler.Source) *Network {
n := &Network{
params: params,
rngSource: rngSource,
factory: factory,
}
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.factory, 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.factory, 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
2 changes: 1 addition & 1 deletion snow/consensus/snowball/nnary_snowball.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/ava-labs/avalanchego/ids"
)

var _ NnarySnowball = (*nnarySnowball)(nil)
var _ Nnary = (*nnarySnowball)(nil)

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

var _ NnarySnowflake = (*nnarySnowflake)(nil)
var _ Nnary = (*nnarySnowflake)(nil)

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

0 comments on commit adc1d4b

Please sign in to comment.