diff --git a/common/types/ballot.go b/common/types/ballot.go index 087029cf22..6d8ca6574b 100644 --- a/common/types/ballot.go +++ b/common/types/ballot.go @@ -332,7 +332,6 @@ func (b *Ballot) ToTortoiseData() *BallotTortoiseData { data.EpochData = &ReferenceData{ Beacon: b.EpochData.Beacon, Eligibilities: uint32(b.EpochData.EligibilityCount), - ActiveSet: b.ActiveSet, } } else { data.Ref = &b.RefBallot diff --git a/common/types/layer.go b/common/types/layer.go index b7b66f077e..d7ef0eca2e 100644 --- a/common/types/layer.go +++ b/common/types/layer.go @@ -20,8 +20,6 @@ var ( // EmptyLayerHash is the layer hash for an empty layer. EmptyLayerHash = Hash32{} - legacyLayer uint32 - // layer at which optimistic filtering majority calculation is upgraded. opUpgradeLayer uint32 ) @@ -32,14 +30,6 @@ func SetLayersPerEpoch(layers uint32) { SetEffectiveGenesis(layers*2 - 1) } -func SetLegacyLayers(layer uint32) { - legacyLayer = layer -} - -func GetLegacyLayer() uint32 { - return legacyLayer -} - func SetOpUpgradeLayer(layer uint32) { opUpgradeLayer = layer } diff --git a/common/types/tortoise_data.go b/common/types/tortoise_data.go index bc30259659..33b2153dfa 100644 --- a/common/types/tortoise_data.go +++ b/common/types/tortoise_data.go @@ -44,14 +44,12 @@ func (b *BallotTortoiseData) MarshalLogObject(encoder log.ObjectEncoder) error { } type ReferenceData struct { - Beacon Beacon `json:"beacon"` - ActiveSet []ATXID `json:"set"` - Eligibilities uint32 `json:"elig"` + Beacon Beacon `json:"beacon"` + Eligibilities uint32 `json:"elig"` } func (r *ReferenceData) MarshalLogObject(encoder log.ObjectEncoder) error { encoder.AddString("beacon", r.Beacon.String()) - encoder.AddInt("set size", len(r.ActiveSet)) encoder.AddUint32("elig", r.Eligibilities) return nil } diff --git a/config/mainnet.go b/config/mainnet.go index 6bdba311cb..4f45b5ea4b 100644 --- a/config/mainnet.go +++ b/config/mainnet.go @@ -45,8 +45,10 @@ func MainnetConfig() Config { DatabaseConnections: 16, NetworkHRP: "sm", - LayerDuration: 5 * time.Minute, - LayerAvgSize: 50, + LayerDuration: 5 * time.Minute, + LayerAvgSize: 50, + // NOTE(dshulyak) this is only used to stop atx grading in hare. + // we should refactor that too. LegacyLayer: 8180, LayersPerEpoch: 4032, diff --git a/miner/oracle.go b/miner/oracle.go index 79c528d4dd..a683e03949 100644 --- a/miner/oracle.go +++ b/miner/oracle.go @@ -63,10 +63,6 @@ func (o *Oracle) ProposalEligibility(lid types.LayerID, beacon types.Beacon, non o.mu.Lock() defer o.mu.Unlock() - if legacy := types.GetLegacyLayer(); legacy != 0 && lid.Uint32() == legacy+1 { - o.cache = &EpochEligibility{} - } - epoch := lid.GetEpoch() if lid <= types.GetEffectiveGenesis() { o.log.With().Panic("eligibility should not be queried during genesis", lid, epoch) @@ -244,7 +240,7 @@ func (o *Oracle) calcEligibilityProofs(lid types.LayerID, epoch types.EpochID, b ) var numEligibleSlots uint32 if ref == nil { - numEligibleSlots, err = proposals.GetLegacyNumEligible(lid, minerWeight, o.cfg.minActiveSetWeight, totalWeight, o.cfg.layerSize, o.cfg.layersPerEpoch) + numEligibleSlots, err = proposals.GetNumEligibleSlots(minerWeight, o.cfg.minActiveSetWeight, totalWeight, o.cfg.layerSize, o.cfg.layersPerEpoch) if err != nil { return nil, fmt.Errorf("oracle get num slots: %w", err) } diff --git a/node/node.go b/node/node.go index 5396ed3016..27bb111903 100644 --- a/node/node.go +++ b/node/node.go @@ -142,7 +142,6 @@ func GetCommand() *cobra.Command { run := func(ctx context.Context) error { types.SetLayersPerEpoch(app.Config.LayersPerEpoch) - types.SetLegacyLayers(app.Config.LegacyLayer) // starting on 2023-09-14 20:00:00 +0000 UTC (~1 week into 4th epoch) types.SetOpUpgradeLayer(18000) // ensure all data folders exist @@ -750,7 +749,7 @@ func (app *App) initServices(ctx context.Context) error { hareCfg := app.Config.HARE hareCfg.Hdist = app.Config.Tortoise.Hdist - hareCfg.StopAtxGrading = types.GetLegacyLayer() + hareCfg.StopAtxGrading = app.Config.LegacyLayer app.hare = hare.New( app.cachedDB, hareCfg, diff --git a/proposals/eligibility_validator.go b/proposals/eligibility_validator.go index 71ce637450..4174b3106f 100644 --- a/proposals/eligibility_validator.go +++ b/proposals/eligibility_validator.go @@ -151,7 +151,7 @@ func (v *Validator) validateReference(ballot *types.Ballot, owned *types.Activat } totalWeight += atx.GetWeight() } - numEligibleSlots, err := GetLegacyNumEligible(ballot.Layer, owned.GetWeight(), v.minActiveSetWeight, totalWeight, v.avgLayerSize, v.layersPerEpoch) + numEligibleSlots, err := GetNumEligibleSlots(owned.GetWeight(), v.minActiveSetWeight, totalWeight, v.avgLayerSize, v.layersPerEpoch) if err != nil { return nil, err } diff --git a/proposals/util.go b/proposals/util.go index f4ea8ef49e..ca5e70c431 100644 --- a/proposals/util.go +++ b/proposals/util.go @@ -9,9 +9,8 @@ import ( ) var ( - CalcEligibleLayer = util.CalcEligibleLayer - GetNumEligibleSlots = util.GetNumEligibleSlots - GetLegacyNumEligible = util.GetLegacyNumEligible + CalcEligibleLayer = util.CalcEligibleLayer + GetNumEligibleSlots = util.GetNumEligibleSlots // ComputeWeightPerEligibility computes the ballot weight per eligibility w.r.t the active set recorded in its reference ballot. ComputeWeightPerEligibility = util.ComputeWeightPerEligibility ) diff --git a/proposals/util/util.go b/proposals/util/util.go index bcd0f90a40..56c4618106 100644 --- a/proposals/util/util.go +++ b/proposals/util/util.go @@ -29,14 +29,6 @@ func CalcEligibleLayer(epochNumber types.EpochID, layersPerEpoch uint32, vrfSig return epochNumber.FirstLayer().Add(uint32(eligibleLayerOffset)) } -func GetLegacyNumEligible(lid types.LayerID, weight, minWeight, totalWeight uint64, committeeSize, layersPerEpoch uint32) (uint32, error) { - legacyLayer := types.GetLegacyLayer() - if legacyLayer != 0 && legacyLayer >= lid.Uint32() { - return 1, nil - } - return GetNumEligibleSlots(weight, minWeight, totalWeight, committeeSize, layersPerEpoch) -} - // GetNumEligibleSlots calculates the number of eligible slots for a smesher in an epoch. func GetNumEligibleSlots(weight, minWeight, totalWeight uint64, committeeSize, layersPerEpoch uint32) (uint32, error) { if totalWeight == 0 { diff --git a/proposals/util/util_test.go b/proposals/util/util_test.go deleted file mode 100644 index 2528cd1cfb..0000000000 --- a/proposals/util/util_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package util - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/spacemeshos/go-spacemesh/common/types" -) - -func TestNumEligible(t *testing.T) { - types.SetLegacyLayers(10) - n, err := GetLegacyNumEligible(11, 100, 0, 1000, 4032, 50) - require.NoError(t, err) - require.Equal(t, 20160, int(n)) - n, err = GetLegacyNumEligible(types.LayerID(types.GetLegacyLayer()), 100, 0, 1000, 4032, 50) - require.NoError(t, err) - require.Equal(t, 1, int(n)) - n, err = GetLegacyNumEligible(0, 100, 0, 1000, 4032, 50) - require.NoError(t, err) - require.Equal(t, 1, int(n)) -} diff --git a/tortoise/algorithm_test.go b/tortoise/algorithm_test.go index c56d247338..aa49aeb22d 100644 --- a/tortoise/algorithm_test.go +++ b/tortoise/algorithm_test.go @@ -8,18 +8,14 @@ import ( func TestGetBallot(t *testing.T) { const n = 2 - var activeset []*atxAction s := newSession(t) for i := 0; i < n; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(100).weight(400)), - ) + s.smesher(i).atx(1, new(aopt).height(100).weight(400)) } ref := s.smesher(0).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/n)) secondary := s.smesher(0).atx(1).ballot(2) diff --git a/tortoise/fixture_test.go b/tortoise/fixture_test.go index 2b72fcf747..9a485e2c23 100644 --- a/tortoise/fixture_test.go +++ b/tortoise/fixture_test.go @@ -135,15 +135,12 @@ func (b *bopt) eligibilities(value int) *bopt { return b } -func (b *bopt) activeset(values ...*atxAction) *bopt { +func (b *bopt) totalEligibilities(n int) *bopt { b.opts = append(b.opts, func(ballot *ballotAction) { - ballot.activeset = values - for _, val := range values { - if ballot.EpochData == nil { - ballot.EpochData = &types.ReferenceData{} - } - ballot.EpochData.ActiveSet = append(ballot.EpochData.ActiveSet, val.header.ID) + if ballot.EpochData == nil { + ballot.EpochData = &types.ReferenceData{} } + ballot.EpochData.Eligibilities = uint32(n) }) return b } @@ -233,6 +230,7 @@ func (a *atxAction) rawballot(id types.BallotID, n int, opts ...*bopt) *ballotAc } if a.reference == nil { a.reference = val + val.before = append(val.before, a) } else { val.Ref = &a.reference.ID val.before = append(val.before, a.reference) @@ -244,12 +242,6 @@ func (a *atxAction) rawballot(id types.BallotID, n int, opts ...*bopt) *ballotAc if val.base != nil { val.before = append(val.before, val.base) } - for _, atx := range val.activeset { - val.before = append(val.before, atx) - } - if len(val.activeset) == 0 { - val.before = append(val.before, a) - } a.reg.register(val) a.ballots[id] = val @@ -268,9 +260,8 @@ func (a *atxAction) ballot(n int, opts ...*bopt) *ballotAction { type ballotAction struct { types.BallotTortoiseData - base *ballotAction - activeset []*atxAction - before []action + base *ballotAction + before []action onDecoded func(*DecodedBallot, error) onStored func(error) @@ -407,6 +398,10 @@ func (s *session) smesher(id int) *smesher { return val } +func (s *session) epochEligibilities() int { + return s.layerSize * s.epochSize / len(s.smeshers) +} + func (s *session) register(actions ...action) { s.actions = append(s.actions, actions...) } @@ -740,19 +735,15 @@ func (s *session) tortoise() *Tortoise { func TestSanity(t *testing.T) { const n = 2 - var activeset []*atxAction s := newSession(t) for i := 0; i < n; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(100).weight(400)), - ) + s.smesher(i).atx(1, new(aopt).height(100).weight(400)) } s.beacon(1, "a") for i := 0; i < n; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/n)) } s.tally(1) @@ -776,19 +767,15 @@ func TestSanity(t *testing.T) { func TestDisagreement(t *testing.T) { const n = 5 - var activeset []*atxAction s := newSession(t) for i := 0; i < n; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(100).weight(400)), - ) + s.smesher(i).atx(1, new(aopt).height(100).weight(400)) } s.beacon(1, "a") for i := 0; i < n; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/n)) } s.hareblock(1, "aa", 0) @@ -816,15 +803,14 @@ func TestDisagreement(t *testing.T) { func TestOpinion(t *testing.T) { s := newSession(t) - var activeset []*atxAction - activeset = append(activeset, - s.smesher(0).atx(1, new(aopt).height(100).weight(2000)), - ) + + s.smesher(0).atx(1, new(aopt).height(100).weight(2000)) + s.beacon(1, "a") s.smesher(0).atx(1).ballot(1, new(bopt). eligibilities(s.layerSize). beacon("a"). - activeset(activeset...), + totalEligibilities(s.epochEligibilities()), ) for i := 2; i < s.epochSize; i++ { id := strconv.Itoa(i) @@ -842,19 +828,15 @@ func TestOpinion(t *testing.T) { } func TestEpochGap(t *testing.T) { - var activeset []*atxAction s := newSession(t).withEpochSize(4) for i := 0; i < 2; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(1).weight(10)), - ) + s.smesher(i).atx(1, new(aopt).height(1).weight(10)) } s.beacon(1, "a") for i := 0; i < 2; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize/2)) } rst := new(results). diff --git a/tortoise/full_test.go b/tortoise/full_test.go index c66d9d5285..d5563c82f7 100644 --- a/tortoise/full_test.go +++ b/tortoise/full_test.go @@ -9,6 +9,7 @@ import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log/logtest" + "github.com/spacemeshos/go-spacemesh/proposals/util" "github.com/spacemeshos/go-spacemesh/signing" ) @@ -323,7 +324,11 @@ func TestFullCountVotes(t *testing.T) { t.Run(tc.desc, func(t *testing.T) { logger := logtest.Zap(t) tortoise := defaultAlgorithm(t) - var activeset []types.ATXID + var ( + activeset []types.ATXID + total uint64 + weights []uint64 + ) for i := range tc.activeset { atxid := types.ATXID{byte(i + 1)} header := &types.ActivationTxHeader{ @@ -336,6 +341,8 @@ func TestFullCountVotes(t *testing.T) { header.PublishEpoch = 1 tortoise.OnAtx(header.ToData()) activeset = append(activeset, atxid) + weights = append(weights, header.GetWeight()) + total += header.GetWeight() } consensus := tortoise.trtl @@ -372,8 +379,10 @@ func TestFullCountVotes(t *testing.T) { ballot := &types.Ballot{} ballot.EligibilityProofs = []types.VotingEligibility{{J: uint32(j)}} ballot.AtxID = activeset[b.ATX] - ballot.EpochData = &types.EpochData{ActiveSetHash: types.Hash32{1, 2, 3}, EligibilityCount: 1} - ballot.ActiveSet = activeset + + elig, err := util.GetNumEligibleSlots(weights[b.ATX], 0, total, consensus.LayerSize, types.GetLayersPerEpoch()) + require.NoError(t, err) + ballot.EpochData = &types.EpochData{ActiveSetHash: types.Hash32{1, 2, 3}, EligibilityCount: elig} ballot.Layer = lid // don't vote on genesis for simplicity, // since we don't care about block goodness in this test diff --git a/tortoise/model/core.go b/tortoise/model/core.go index f8eab435fc..83d8427e44 100644 --- a/tortoise/model/core.go +++ b/tortoise/model/core.go @@ -107,10 +107,6 @@ func (c *core) OnMessage(m Messenger, event Message) { if c.refBallot != nil { ballot.RefBallot = *c.refBallot } else { - _, activeset, err := c.cdb.GetEpochWeight(ev.LayerID.GetEpoch()) - if err != nil { - panic(err) - } beacon, err := c.beacons.GetBeacon(ev.LayerID.GetEpoch()) if err != nil { beacon = types.Beacon{} @@ -118,10 +114,10 @@ func (c *core) OnMessage(m Messenger, event Message) { c.beacons.StoreBeacon(ev.LayerID.GetEpoch(), beacon) } ballot.EpochData = &types.EpochData{ - ActiveSetHash: types.Hash32{1, 2, 3}, - Beacon: beacon, + ActiveSetHash: types.Hash32{1, 2, 3}, + Beacon: beacon, + EligibilityCount: c.eligibilities, } - ballot.ActiveSet = activeset } ballot.Signature = c.signer.Sign(signing.BALLOT, ballot.SignedBytes()) ballot.SmesherID = c.signer.NodeID() diff --git a/tortoise/sim/generator.go b/tortoise/sim/generator.go index 00c1248f90..617a9261dd 100644 --- a/tortoise/sim/generator.go +++ b/tortoise/sim/generator.go @@ -110,7 +110,7 @@ type Generator struct { layers []*types.Layer units [2]int - activations []types.ATXID + activations []*types.VerifiedActivationTx ticksRange [2]int ticks []uint64 prevHeight []uint64 @@ -206,7 +206,7 @@ func (g *Generator) Setup(opts ...SetupOpt) { g.nextLayer = last.Index().Add(1) miners := intInRange(g.rng, conf.Miners) - g.activations = make([]types.ATXID, miners) + g.activations = make([]*types.VerifiedActivationTx, miners) g.prevHeight = make([]uint64, miners) for i := uint32(0); i < miners; i++ { @@ -242,16 +242,15 @@ func (g *Generator) generateAtxs() { } atx.SetEffectiveNumUnits(atx.NumUnits) atx.SetReceived(time.Now()) - vAtx, err := atx.Verify(g.prevHeight[i], ticks) + vatx, err := atx.Verify(g.prevHeight[i], ticks) if err != nil { panic(err) } g.prevHeight[i] += ticks - g.activations[i] = atx.ID() - + g.activations[i] = vatx for _, state := range g.states { - state.OnActivationTx(vAtx) + state.OnActivationTx(vatx) } } } diff --git a/tortoise/sim/layer.go b/tortoise/sim/layer.go index 33422d50d4..11cf957b6d 100644 --- a/tortoise/sim/layer.go +++ b/tortoise/sim/layer.go @@ -3,6 +3,7 @@ package sim import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log" + "github.com/spacemeshos/go-spacemesh/proposals/util" "github.com/spacemeshos/go-spacemesh/signing" ) @@ -154,8 +155,10 @@ func (g *Generator) genLayer(cfg nextConf) types.LayerID { if cfg.LayerSize >= 0 { size = cfg.LayerSize } - activeset := make([]types.ATXID, len(g.activations)) - copy(activeset, g.activations) + var total uint64 + for _, atx := range g.activations { + total += atx.GetWeight() + } miners := make([]uint32, len(g.activations)) for i := 0; i < size; i++ { @@ -167,7 +170,7 @@ func (g *Generator) genLayer(cfg nextConf) types.LayerID { continue } voting := cfg.VoteGen(g.rng, g.layers, miner) - atxid := g.activations[miner] + atx := g.activations[miner] signer := g.keys[miner] proofs := []types.VotingEligibility{} for j := uint32(0); j < maxj; j++ { @@ -177,18 +180,22 @@ func (g *Generator) genLayer(cfg nextConf) types.LayerID { if err != nil { g.logger.With().Panic("failed to get a beacon", log.Err(err)) } + n, err := util.GetNumEligibleSlots(atx.GetWeight(), 0, total, g.conf.LayerSize, g.conf.LayersPerEpoch) + if err != nil { + g.logger.With().Panic("eligible slots", log.Err(err)) + } ballot := &types.Ballot{ InnerBallot: types.InnerBallot{ Layer: g.nextLayer, - AtxID: atxid, + AtxID: atx.ID(), EpochData: &types.EpochData{ - ActiveSetHash: types.Hash32{1, 2, 3}, - Beacon: beacon, + EligibilityCount: n, + ActiveSetHash: types.Hash32{1, 2, 3}, + Beacon: beacon, }, }, Votes: voting, EligibilityProofs: proofs, - ActiveSet: activeset, } ballot.Signature = signer.Sign(signing.BALLOT, ballot.SignedBytes()) ballot.SmesherID = signer.NodeID() diff --git a/tortoise/sim/partition.go b/tortoise/sim/partition.go index 828d656ca5..f6342e1ad1 100644 --- a/tortoise/sim/partition.go +++ b/tortoise/sim/partition.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/spacemeshos/go-spacemesh/common/types" - "github.com/spacemeshos/go-spacemesh/log" "github.com/spacemeshos/go-spacemesh/sql/ballots" "github.com/spacemeshos/go-spacemesh/sql/blocks" ) @@ -125,23 +124,19 @@ func (g *Generator) mergeKeys(other *Generator) { } func (g *Generator) mergeActivations(other *Generator) { - for _, atxid := range other.activations { + for _, atx := range other.activations { var exists bool for _, existing := range g.activations { - exists = atxid == existing + exists = atx.ID() == existing.ID() if exists { break } } if !exists { - atx, err := other.GetState(0).DB.GetFullAtx(atxid) - if err != nil { - g.logger.With().Panic("failed to get atx", atxid, log.Err(err)) - } for _, state := range g.states { state.OnActivationTx(atx) } - g.activations = append(g.activations, atxid) + g.activations = append(g.activations, atx) g.prevHeight = append(g.prevHeight, atx.TickHeight()) } } diff --git a/tortoise/state.go b/tortoise/state.go index 55f0aea455..362c648b78 100644 --- a/tortoise/state.go +++ b/tortoise/state.go @@ -499,15 +499,3 @@ func decodeVotes(evicted, blid types.LayerID, base *ballotInfo, exceptions types } return decoded, from, nil } - -func activeSetWeight(epoch *epochInfo, aset []types.ATXID) (uint64, error) { - var weight uint64 - for _, id := range aset { - atx, exists := epoch.atxs[id] - if !exists { - return 0, fmt.Errorf("atx %v is not in state", id) - } - weight += atx.weight - } - return weight, nil -} diff --git a/tortoise/tortoise.go b/tortoise/tortoise.go index 59e82719bc..0142fd8477 100644 --- a/tortoise/tortoise.go +++ b/tortoise/tortoise.go @@ -14,7 +14,6 @@ import ( "github.com/spacemeshos/go-spacemesh/common/types" "github.com/spacemeshos/go-spacemesh/log" - "github.com/spacemeshos/go-spacemesh/proposals/util" ) var ( @@ -699,21 +698,13 @@ func (t *turtle) decodeBallot(ballot *types.BallotTortoiseData) (*ballotInfo, ty if !exists { return nil, 0, fmt.Errorf("atx %s/%d not in state", ballot.AtxID, ballot.Layer.GetEpoch()) } - total, err := activeSetWeight(epoch, ballot.EpochData.ActiveSet) - if err != nil { - return nil, 0, err - } - expected, err := util.GetLegacyNumEligible(ballot.Layer, atx.weight, t.MinimalActiveSetWeight, total, t.LayerSize, types.GetLayersPerEpoch()) - if err != nil { - return nil, 0, err - } refinfo = &referenceInfo{ smesher: ballot.Smesher, atxid: ballot.AtxID, expectedBallots: ballot.EpochData.Eligibilities, beacon: ballot.EpochData.Beacon, height: atx.height, - weight: big.NewRat(int64(atx.weight), int64(expected)), + weight: big.NewRat(int64(atx.weight), int64(ballot.EpochData.Eligibilities)), } } else if ballot.Ref != nil { ptr := *ballot.Ref diff --git a/tortoise/tortoise_test.go b/tortoise/tortoise_test.go index 1eefad13ba..b1022084b9 100644 --- a/tortoise/tortoise_test.go +++ b/tortoise/tortoise_test.go @@ -1420,18 +1420,11 @@ func TestComputeLocalOpinion(t *testing.T) { func TestComputeBallotWeight(t *testing.T) { type testBallot struct { - ActiveSet []int // optional index to atx's to form an active set - RefBallot int // optional index to the ballot, use it in test if active set is nil - ATX int // non optional index to this ballot atx - ExpectedWeight float64 - Eligibilities int - } - createActiveSet := func(pos []int, atxdis []types.ATXID) []types.ATXID { - var rst []types.ATXID - for _, i := range pos { - rst = append(rst, atxdis[i]) - } - return rst + TotalEligibilities int + RefBallot int // optional index to the ballot, use it in test if active set is nil + ATX int // non optional index to this ballot atx + ExpectedWeight float64 + Eligibilities int } for _, tc := range []struct { @@ -1441,63 +1434,63 @@ func TestComputeBallotWeight(t *testing.T) { layerSize, layersPerEpoch uint32 }{ { - desc: "FromActiveSet", + desc: "total eligibilities", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, - {ActiveSet: []int{0, 1, 2}, ATX: 1, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 1, ExpectedWeight: 10, Eligibilities: 1}, }, }, { - desc: "FromRefBallot", + desc: "ref ballot", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, {RefBallot: 0, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, }, }, { - desc: "FromRefBallotMultipleEligibilities", + desc: "ref ballot multiple", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, {RefBallot: 0, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, }, }, { - desc: "FromRefBallotMultipleEligibilities", + desc: "ref ballot multiple", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, {RefBallot: 0, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, }, }, { - desc: "FromRefBallotMultipleEligibilities", + desc: "ref ballot multiple", atxs: []uint{50, 50, 50}, layerSize: 5, layersPerEpoch: 3, ballots: []testBallot{ - {ActiveSet: []int{0, 1, 2}, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 20, Eligibilities: 2}, {RefBallot: 0, ATX: 0, ExpectedWeight: 30, Eligibilities: 3}, }, }, { - desc: "DifferentActiveSets", + desc: "different weight", atxs: []uint{50, 50, 100, 100}, layerSize: 5, layersPerEpoch: 2, ballots: []testBallot{ - {ActiveSet: []int{0, 1}, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, - {ActiveSet: []int{2, 3}, ATX: 2, ExpectedWeight: 20, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 0, ExpectedWeight: 10, Eligibilities: 1}, + {TotalEligibilities: 5, ATX: 2, ExpectedWeight: 20, Eligibilities: 1}, }, }, } { @@ -1546,11 +1539,11 @@ func TestComputeBallotWeight(t *testing.T) { types.VotingEligibility{J: uint32(currentJ)}) currentJ++ } - if b.ActiveSet != nil { + if b.TotalEligibilities != 0 { ballot.EpochData = &types.EpochData{ - ActiveSetHash: types.Hash32{1, 2, 3}, + ActiveSetHash: types.Hash32{1, 2, 3}, + EligibilityCount: uint32(b.TotalEligibilities), } - ballot.ActiveSet = createActiveSet(b.ActiveSet, atxids) } else { ballot.RefBallot = blts[b.RefBallot].ID() } @@ -2763,8 +2756,10 @@ func TestEncodeVotes(t *testing.T) { tortoise.OnAtx(header.ToData()) tortoise.OnBeacon(lid.GetEpoch(), types.EmptyBeacon) - ballot.EpochData = &types.EpochData{ActiveSetHash: types.Hash32{1, 2, 3}} - ballot.ActiveSet = []types.ATXID{atxid} + ballot.EpochData = &types.EpochData{ + ActiveSetHash: types.Hash32{1, 2, 3}, + EligibilityCount: 1, + } ballot.AtxID = atxid ballot.Layer = lid ballot.Votes.Support = []types.Vote{ @@ -3062,7 +3057,7 @@ func TestMinimalActiveSetWeight(t *testing.T) { s.smesher(0).atx(1, new(aopt).height(10).weight(2)) s.beacon(1, "a") s.smesher(0).atx(1).ballot(1, new(bopt). - activeset(s.smesher(0).atx(1)). + totalEligibilities(s.epochEligibilities()). beacon("a"). eligibilities(1), ) @@ -3076,11 +3071,11 @@ func TestDuplicateBallot(t *testing.T) { s.smesher(0).atx(1, new(aopt).height(10).weight(2)) id := types.BallotID{1} s.smesher(0).atx(1).rawballot(id, 1, new(bopt). - activeset(s.smesher(0).atx(1)). + totalEligibilities(s.epochEligibilities()). eligibilities(1), ) s.smesher(0).atx(1).rawballot(id, 1, new(bopt). - activeset(s.smesher(0).atx(1)). + totalEligibilities(s.epochEligibilities()). eligibilities(1).assert( func(db *DecodedBallot, err error) { require.NotEmpty(t, db) @@ -3099,21 +3094,15 @@ func TestSwitch(t *testing.T) { withHdist(4). withZdist(2) const smeshers = 4 - var ( - elig = s.layerSize / smeshers - activeset []*atxAction - ) + elig := s.layerSize / smeshers for i := 0; i < smeshers; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(10).weight(100)), - ) + s.smesher(i).atx(1, new(aopt).height(10).weight(100)) } s.beacon(1, "a") for i := 0; i < smeshers; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(elig)) } @@ -3150,21 +3139,15 @@ func TestOnMalfeasance(t *testing.T) { t.Run("atxs", func(t *testing.T) { s := newSession(t) const smeshers = 3 - var ( - elig = s.layerSize / smeshers - activeset []*atxAction - ) + elig := s.layerSize / smeshers for i := 0; i < smeshers; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(10).weight(100)), - ) + s.smesher(i).atx(1, new(aopt).height(10).weight(100)) } s.beacon(1, "a") for i := 0; i < smeshers; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(elig)) } s.smesher(0).malfeasant() // without this call threshold will be very large, and s.updates fail @@ -3180,21 +3163,15 @@ func TestOnMalfeasance(t *testing.T) { withHdist(1). withZdist(1) const smeshers = 3 - var ( - elig = s.layerSize / smeshers - activeset []*atxAction - ) + elig := s.layerSize / smeshers for i := 0; i < smeshers; i++ { - activeset = append( - activeset, - s.smesher(i).atx(1, new(aopt).height(10).weight(100)), - ) + s.smesher(i).atx(1, new(aopt).height(10).weight(100)) } s.beacon(1, "a") for i := 0; i < smeshers; i++ { s.smesher(i).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(elig)) } for i := 0; i < smeshers; i++ { @@ -3218,13 +3195,13 @@ func TestOnMalfeasance(t *testing.T) { func TestBaseAbstain(t *testing.T) { s := newSession(t) - activeset := []*atxAction{ - s.smesher(0).atx(1, new(aopt).height(10).weight(100)), - } + + s.smesher(0).atx(1, new(aopt).height(10).weight(100)) + s.beacon(1, "a") s.smesher(0).atx(1).ballot(1, new(bopt). beacon("a"). - activeset(activeset...). + totalEligibilities(s.epochEligibilities()). eligibilities(s.layerSize)) s.smesher(0).atx(1).ballot(2, new(bopt). eligibilities(s.layerSize).