From 2cfd6a8557402c67a5d21c4e9229d471894bbf83 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Tue, 1 Nov 2022 22:13:35 +0900 Subject: [PATCH 01/10] remove gini and weight during proposer selection --- consensus/istanbul/validator/weighted.go | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index 51e914bce7..22338a1195 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -96,6 +96,7 @@ func newWeightedValidator(addr common.Address, reward common.Address, votingpowe } type weightedCouncil struct { + chain consensus.ChainReader subSize uint64 demotedValidators istanbul.Validators // validators staking KLAYs less than minimum, and not in committee/proposers validators istanbul.Validators // validators staking KLAYs more than and equals to minimum, and in committee/proposers @@ -213,6 +214,7 @@ func NewWeightedCouncil(addrs []common.Address, demotedAddrs []common.Address, r if valSet.Size() > 0 { valSet.proposer.Store(valSet.GetByIndex(0)) } + valSet.chain = chain valSet.SetSubGroupSize(committeeSize) valSet.selector = weightedRandomProposer @@ -580,6 +582,7 @@ func (valSet *weightedCouncil) Copy() istanbul.ValidatorSet { defer valSet.validatorMu.RUnlock() newWeightedCouncil := weightedCouncil{ + chain: valSet.chain, subSize: valSet.subSize, policy: valSet.policy, proposer: valSet.proposer, @@ -666,7 +669,7 @@ func (valSet *weightedCouncil) Refresh(hash common.Hash, blockNum uint64, config } totalStaking, _ := calcTotalAmount(weightedValidators, newStakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking) + calcWeight(weightedValidators, stakingAmounts, totalStaking, chainRules) valSet.refreshProposers(seed, blockNum) @@ -823,13 +826,14 @@ func calcTotalAmount(weightedValidators []*weightedValidator, stakingInfo *rewar } // calcWeight updates each validator's weight based on the ratio of its staking amount vs. the total staking amount. -func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float64, totalStaking float64) { +func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float64, totalStaking float64, rules params.Rules) { localLogger := logger.NewWith() if totalStaking > 0 { for i, weightedVal := range weightedValidators { weight := uint64(math.Round(stakingAmounts[i] * 100 / totalStaking)) - if weight <= 0 { - // A validator, who holds zero or small stake, has minimum weight, 1. + if weight <= 0 || rules.IsKore { + // A validator, who holds zero or small stake, has minimum weight, 1 + // And all validators have the same weight after the Kore hard fork weight = 1 } atomic.StoreUint64(&weightedVal.weight, weight) @@ -848,9 +852,13 @@ func (valSet *weightedCouncil) refreshProposers(seed int64, blockNum uint64) { var candidateValsIdx []int // This is a slice which stores index of validator. it is used for shuffling for index, val := range valSet.validators { - weight := val.Weight() - for i := uint64(0); i < weight; i++ { + if valSet.chain.Config().Rules(new(big.Int).SetUint64(blockNum)).IsKore { candidateValsIdx = append(candidateValsIdx, index) + } else { + weight := val.Weight() + for i := uint64(0); i < weight; i++ { + candidateValsIdx = append(candidateValsIdx, index) + } } } From 0a07795b1dd379a9766e0cd3bb0094ec81334666 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Wed, 2 Nov 2022 11:10:11 +0900 Subject: [PATCH 02/10] fix the multi_staking_tests --- .../istanbul/validator/multi_staking_test.go | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/consensus/istanbul/validator/multi_staking_test.go b/consensus/istanbul/validator/multi_staking_test.go index fee490fd76..dac6ea049a 100644 --- a/consensus/istanbul/validator/multi_staking_test.go +++ b/consensus/istanbul/validator/multi_staking_test.go @@ -35,8 +35,11 @@ NodeAddress of additional staking contract : begin with 9 package validator import ( + "math/big" "testing" + "github.com/klaytn/klaytn/params" + "github.com/klaytn/klaytn/common" "github.com/klaytn/klaytn/consensus/istanbul" "github.com/klaytn/klaytn/reward" @@ -184,6 +187,7 @@ func TestCalcWeight(t *testing.T) { stakingAmounts []float64 totalStaking float64 expectedWeights []uint64 + rules params.Rules }{ { []*weightedValidator{ @@ -192,6 +196,7 @@ func TestCalcWeight(t *testing.T) { []float64{0, 0, 0}, 0, []uint64{0, 0, 0}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []*weightedValidator{ @@ -200,6 +205,7 @@ func TestCalcWeight(t *testing.T) { []float64{5000000, 5000000, 5000000}, 15000000, []uint64{33, 33, 33}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []*weightedValidator{ @@ -208,6 +214,7 @@ func TestCalcWeight(t *testing.T) { []float64{5000000, 10000000, 5000000, 5000000}, 25000000, []uint64{20, 40, 20, 20}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []*weightedValidator{ @@ -216,10 +223,11 @@ func TestCalcWeight(t *testing.T) { []float64{324946, 560845, 771786, 967997, 1153934}, 3779508, []uint64{9, 15, 20, 26, 31}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, } for _, testCase := range testCases { - calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking) + calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, testCase.rules) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, testCase.weightedValidators[i].Weight()) } @@ -233,6 +241,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { validators []common.Address stakingInfo *reward.StakingInfo expectedWeights []uint64 + rules params.Rules }{ { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, @@ -243,6 +252,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{0, 0, 0}, }, []uint64{0, 0, 0}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -253,6 +263,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000}, }, []uint64{25, 25, 25, 25}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -263,6 +274,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 20000000, 30000000, 40000000, 50000000}, }, []uint64{9, 15, 20, 26, 31}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -273,6 +285,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{40, 20, 20, 20}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -283,6 +296,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{38, 21, 21, 21}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("104"), common.StringToAddress("103"), common.StringToAddress("102"), common.StringToAddress("101")}, @@ -293,6 +307,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{29, 21, 37, 12}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -303,6 +318,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{29, 21, 37, 12, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, } for _, testCase := range testCases { @@ -311,7 +327,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { weightedValidators, stakingAmounts, err := getStakingAmountsOfValidators(candidates, testCase.stakingInfo) assert.NoError(t, err) totalStaking, _ := calcTotalAmount(weightedValidators, testCase.stakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking) + calcWeight(weightedValidators, stakingAmounts, totalStaking, testCase.rules) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, weightedValidators[i].Weight()) From 60fd15fc0b16539fd9f259b9e51156ffb99d3aec Mon Sep 17 00:00:00 2001 From: mckim19 Date: Wed, 2 Nov 2022 15:13:06 +0900 Subject: [PATCH 03/10] fix tests of validators --- .../istanbul/validator/multi_staking_test.go | 174 +++++++++++++++++- consensus/istanbul/validator/weighted.go | 9 +- .../validator/weighted_random_test.go | 50 ++++- 3 files changed, 217 insertions(+), 16 deletions(-) diff --git a/consensus/istanbul/validator/multi_staking_test.go b/consensus/istanbul/validator/multi_staking_test.go index dac6ea049a..6bb10d01ef 100644 --- a/consensus/istanbul/validator/multi_staking_test.go +++ b/consensus/istanbul/validator/multi_staking_test.go @@ -196,7 +196,7 @@ func TestCalcWeight(t *testing.T) { []float64{0, 0, 0}, 0, []uint64{0, 0, 0}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []*weightedValidator{ @@ -205,7 +205,7 @@ func TestCalcWeight(t *testing.T) { []float64{5000000, 5000000, 5000000}, 15000000, []uint64{33, 33, 33}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []*weightedValidator{ @@ -214,7 +214,7 @@ func TestCalcWeight(t *testing.T) { []float64{5000000, 10000000, 5000000, 5000000}, 25000000, []uint64{20, 40, 20, 20}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []*weightedValidator{ @@ -223,6 +223,61 @@ func TestCalcWeight(t *testing.T) { []float64{324946, 560845, 771786, 967997, 1153934}, 3779508, []uint64{9, 15, 20, 26, 31}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, + }, + } + for _, testCase := range testCases { + calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, testCase.rules) + for i, weight := range testCase.expectedWeights { + assert.Equal(t, weight, testCase.weightedValidators[i].Weight()) + } + } +} + +// TestCalcWeight_AfterKoreHardFork tests calcWeight that calculates weights and saves them to validators after Kore hard fork. +// weights are 0 or 1 for thg same probability of proposer selection +func TestCalcWeight_AfterKoreHardFork(t *testing.T) { + testCases := []struct { + weightedValidators []*weightedValidator + stakingAmounts []float64 + totalStaking float64 + expectedWeights []uint64 + rules params.Rules + }{ + { + []*weightedValidator{ + {}, {}, {}, + }, + []float64{0, 0, 0}, + 0, + []uint64{0, 0, 0}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []*weightedValidator{ + {}, {}, {}, + }, + []float64{5000000, 5000000, 5000000}, + 15000000, + []uint64{1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []*weightedValidator{ + {}, {}, {}, {}, + }, + []float64{5000000, 10000000, 5000000, 5000000}, + 25000000, + []uint64{1, 1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []*weightedValidator{ + {}, {}, {}, {}, {}, + }, + []float64{324946, 560845, 771786, 967997, 1153934}, + 3779508, + []uint64{1, 1, 1, 1, 1}, params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, } @@ -252,7 +307,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{0, 0, 0}, }, []uint64{0, 0, 0}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -263,7 +318,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000}, }, []uint64{25, 25, 25, 25}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -274,7 +329,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 20000000, 30000000, 40000000, 50000000}, }, []uint64{9, 15, 20, 26, 31}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -285,7 +340,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{40, 20, 20, 20}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -296,7 +351,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{38, 21, 21, 21}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("104"), common.StringToAddress("103"), common.StringToAddress("102"), common.StringToAddress("101")}, @@ -307,7 +362,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{29, 21, 37, 12}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -318,6 +373,107 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{29, 21, 37, 12, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, + }, + } + for _, testCase := range testCases { + council := newTestWeightedCouncil(testCase.validators) + candidates := append(council.validators, council.demotedValidators...) + weightedValidators, stakingAmounts, err := getStakingAmountsOfValidators(candidates, testCase.stakingInfo) + assert.NoError(t, err) + totalStaking, _ := calcTotalAmount(weightedValidators, testCase.stakingInfo, stakingAmounts) + calcWeight(weightedValidators, stakingAmounts, totalStaking, testCase.rules) + + for i, weight := range testCase.expectedWeights { + assert.Equal(t, weight, weightedValidators[i].Weight()) + } + } +} + +// TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork is union of above tests. +// Weight should be calculated exactly by a validator list and a stakingInfo given for the same probability of proposer selection +func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *testing.T) { + testCases := []struct { + validators []common.Address + stakingInfo *reward.StakingInfo + expectedWeights []uint64 + rules params.Rules + }{ + { + []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203")}, + UseGini: false, + CouncilStakingAmounts: []uint64{0, 0, 0}, + }, + []uint64{0, 0, 0}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204")}, + UseGini: true, + CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000}, + }, + []uint64{1, 1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("205")}, + UseGini: true, + CouncilStakingAmounts: []uint64{10000000, 20000000, 30000000, 40000000, 50000000}, + }, + []uint64{1, 1, 1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201")}, + UseGini: false, + CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, + }, + []uint64{1, 1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201")}, + UseGini: true, + CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, + }, + []uint64{1, 1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []common.Address{common.StringToAddress("104"), common.StringToAddress("103"), common.StringToAddress("102"), common.StringToAddress("101")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901"), common.StringToAddress("902")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201"), common.StringToAddress("202")}, + UseGini: true, + CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, + }, + []uint64{1, 1, 1, 1}, + params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, + }, + { + []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, + &reward.StakingInfo{ + CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901"), common.StringToAddress("902")}, + CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201"), common.StringToAddress("202")}, + UseGini: true, + CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, + }, + []uint64{1, 1, 1, 1, 1}, params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, } diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index 22338a1195..c9ed1dd552 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -96,7 +96,6 @@ func newWeightedValidator(addr common.Address, reward common.Address, votingpowe } type weightedCouncil struct { - chain consensus.ChainReader subSize uint64 demotedValidators istanbul.Validators // validators staking KLAYs less than minimum, and not in committee/proposers validators istanbul.Validators // validators staking KLAYs more than and equals to minimum, and in committee/proposers @@ -214,7 +213,6 @@ func NewWeightedCouncil(addrs []common.Address, demotedAddrs []common.Address, r if valSet.Size() > 0 { valSet.proposer.Store(valSet.GetByIndex(0)) } - valSet.chain = chain valSet.SetSubGroupSize(committeeSize) valSet.selector = weightedRandomProposer @@ -582,7 +580,6 @@ func (valSet *weightedCouncil) Copy() istanbul.ValidatorSet { defer valSet.validatorMu.RUnlock() newWeightedCouncil := weightedCouncil{ - chain: valSet.chain, subSize: valSet.subSize, policy: valSet.policy, proposer: valSet.proposer, @@ -671,7 +668,7 @@ func (valSet *weightedCouncil) Refresh(hash common.Hash, blockNum uint64, config totalStaking, _ := calcTotalAmount(weightedValidators, newStakingInfo, stakingAmounts) calcWeight(weightedValidators, stakingAmounts, totalStaking, chainRules) - valSet.refreshProposers(seed, blockNum) + valSet.refreshProposers(seed, blockNum, chainRules) logger.Debug("Refresh done.", "blockNum", blockNum, "hash", hash, "valSet.blockNum", valSet.blockNum, "stakingInfo.BlockNum", valSet.stakingInfo.BlockNum) logger.Debug("New proposers calculated", "new proposers", valSet.proposers) @@ -848,11 +845,11 @@ func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float6 localLogger.Debug("calculation weight finished") } -func (valSet *weightedCouncil) refreshProposers(seed int64, blockNum uint64) { +func (valSet *weightedCouncil) refreshProposers(seed int64, blockNum uint64, rules params.Rules) { var candidateValsIdx []int // This is a slice which stores index of validator. it is used for shuffling for index, val := range valSet.validators { - if valSet.chain.Config().Rules(new(big.Int).SetUint64(blockNum)).IsKore { + if rules.IsKore { candidateValsIdx = append(candidateValsIdx, index) } else { weight := val.Weight() diff --git a/consensus/istanbul/validator/weighted_random_test.go b/consensus/istanbul/validator/weighted_random_test.go index 9391c85ba7..0d51f2e509 100644 --- a/consensus/istanbul/validator/weighted_random_test.go +++ b/consensus/istanbul/validator/weighted_random_test.go @@ -341,6 +341,31 @@ func TestWeightedCouncil_RefreshWithNonZeroWeight(t *testing.T) { } } +func TestWeightedCouncil_RefreshWithNonZeroWeight_AfterKoreHardFork(t *testing.T) { + validators := makeTestValidators(testNonZeroWeights) + + valSet := makeTestWeightedCouncil(testNonZeroWeights) + runRefreshForTest_AfterKoreHardFork(valSet) + + // Run tests + + // 1. number of proposers + totalWeights := uint64(len(testNonZeroWeights)) + assert.Equal(t, totalWeights, uint64(len(valSet.proposers))) + + // 2. weight and appearance frequency + for _, v := range validators { + weight := uint64(1) + appearance := uint64(0) + for _, p := range valSet.proposers { + if v.Address() == p.Address() { + appearance++ + } + } + assert.Equal(t, weight, appearance) + } +} + func TestWeightedCouncil_RemoveValidator(t *testing.T) { validators := makeTestValidators(testNonZeroWeights) valSet := makeTestWeightedCouncil(testNonZeroWeights) @@ -419,7 +444,30 @@ func runRefreshForTest(valSet *weightedCouncil) { hashString = hashString[:15] } seed, _ := strconv.ParseInt(hashString, 16, 64) - valSet.refreshProposers(seed, 0) + chainRules := params.Rules{ + ChainID: new(big.Int).SetUint64(0), + IsIstanbul: false, + IsLondon: false, + IsMagma: false, + IsKore: false, + } + valSet.refreshProposers(seed, 0, chainRules) +} + +func runRefreshForTest_AfterKoreHardFork(valSet *weightedCouncil) { + hashString := strings.TrimPrefix(testPrevHash.Hex(), "0x") + if len(hashString) > 15 { + hashString = hashString[:15] + } + seed, _ := strconv.ParseInt(hashString, 16, 64) + chainRules := params.Rules{ + ChainID: new(big.Int).SetUint64(0), + IsIstanbul: true, + IsLondon: true, + IsMagma: true, + IsKore: true, + } + valSet.refreshProposers(seed, 0, chainRules) } func TestWeightedCouncil_SetSubGroupSize(t *testing.T) { From 4021e766c8cc517c90b96c0f475dc52f3d1fd191 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Wed, 2 Nov 2022 15:26:40 +0900 Subject: [PATCH 04/10] fix the linter problem --- consensus/istanbul/validator/multi_staking_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/consensus/istanbul/validator/multi_staking_test.go b/consensus/istanbul/validator/multi_staking_test.go index 6bb10d01ef..129a29de92 100644 --- a/consensus/istanbul/validator/multi_staking_test.go +++ b/consensus/istanbul/validator/multi_staking_test.go @@ -38,10 +38,9 @@ import ( "math/big" "testing" - "github.com/klaytn/klaytn/params" - "github.com/klaytn/klaytn/common" "github.com/klaytn/klaytn/consensus/istanbul" + "github.com/klaytn/klaytn/params" "github.com/klaytn/klaytn/reward" "github.com/stretchr/testify/assert" ) From bd2f917a62f173aaa354c800927d08e151634454 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Wed, 2 Nov 2022 21:40:57 +0900 Subject: [PATCH 05/10] refactor repeated prams --- .../istanbul/validator/multi_staking_test.go | 40 +++++-------------- 1 file changed, 9 insertions(+), 31 deletions(-) diff --git a/consensus/istanbul/validator/multi_staking_test.go b/consensus/istanbul/validator/multi_staking_test.go index 129a29de92..9d78f770f5 100644 --- a/consensus/istanbul/validator/multi_staking_test.go +++ b/consensus/istanbul/validator/multi_staking_test.go @@ -35,7 +35,6 @@ NodeAddress of additional staking contract : begin with 9 package validator import ( - "math/big" "testing" "github.com/klaytn/klaytn/common" @@ -45,6 +44,11 @@ import ( "github.com/stretchr/testify/assert" ) +var ( + magmaRules = params.Rules{ChainID: common.Big0, IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: false} + koreRules = params.Rules{ChainID: common.Big0, IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true} +) + func newTestWeightedCouncil(nodeAddrs []common.Address) *weightedCouncil { return NewWeightedCouncil(nodeAddrs, nil, nil, make([]uint64, len(nodeAddrs)), nil, istanbul.WeightedRandom, 0, 0, 0, nil) } @@ -186,7 +190,6 @@ func TestCalcWeight(t *testing.T) { stakingAmounts []float64 totalStaking float64 expectedWeights []uint64 - rules params.Rules }{ { []*weightedValidator{ @@ -195,7 +198,6 @@ func TestCalcWeight(t *testing.T) { []float64{0, 0, 0}, 0, []uint64{0, 0, 0}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []*weightedValidator{ @@ -204,7 +206,6 @@ func TestCalcWeight(t *testing.T) { []float64{5000000, 5000000, 5000000}, 15000000, []uint64{33, 33, 33}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []*weightedValidator{ @@ -213,7 +214,6 @@ func TestCalcWeight(t *testing.T) { []float64{5000000, 10000000, 5000000, 5000000}, 25000000, []uint64{20, 40, 20, 20}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []*weightedValidator{ @@ -222,11 +222,10 @@ func TestCalcWeight(t *testing.T) { []float64{324946, 560845, 771786, 967997, 1153934}, 3779508, []uint64{9, 15, 20, 26, 31}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, } for _, testCase := range testCases { - calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, testCase.rules) + calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, magmaRules) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, testCase.weightedValidators[i].Weight()) } @@ -241,7 +240,6 @@ func TestCalcWeight_AfterKoreHardFork(t *testing.T) { stakingAmounts []float64 totalStaking float64 expectedWeights []uint64 - rules params.Rules }{ { []*weightedValidator{ @@ -250,7 +248,6 @@ func TestCalcWeight_AfterKoreHardFork(t *testing.T) { []float64{0, 0, 0}, 0, []uint64{0, 0, 0}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []*weightedValidator{ @@ -259,7 +256,6 @@ func TestCalcWeight_AfterKoreHardFork(t *testing.T) { []float64{5000000, 5000000, 5000000}, 15000000, []uint64{1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []*weightedValidator{ @@ -268,7 +264,6 @@ func TestCalcWeight_AfterKoreHardFork(t *testing.T) { []float64{5000000, 10000000, 5000000, 5000000}, 25000000, []uint64{1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []*weightedValidator{ @@ -277,11 +272,10 @@ func TestCalcWeight_AfterKoreHardFork(t *testing.T) { []float64{324946, 560845, 771786, 967997, 1153934}, 3779508, []uint64{1, 1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, } for _, testCase := range testCases { - calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, testCase.rules) + calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, koreRules) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, testCase.weightedValidators[i].Weight()) } @@ -295,7 +289,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { validators []common.Address stakingInfo *reward.StakingInfo expectedWeights []uint64 - rules params.Rules }{ { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, @@ -306,7 +299,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{0, 0, 0}, }, []uint64{0, 0, 0}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -317,7 +309,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000}, }, []uint64{25, 25, 25, 25}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -328,7 +319,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 20000000, 30000000, 40000000, 50000000}, }, []uint64{9, 15, 20, 26, 31}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -339,7 +329,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{40, 20, 20, 20}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -350,7 +339,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{38, 21, 21, 21}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("104"), common.StringToAddress("103"), common.StringToAddress("102"), common.StringToAddress("101")}, @@ -361,7 +349,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{29, 21, 37, 12}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -372,7 +359,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{29, 21, 37, 12, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: false, IsLondon: false, IsMagma: false, IsKore: false}, }, } for _, testCase := range testCases { @@ -381,7 +367,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { weightedValidators, stakingAmounts, err := getStakingAmountsOfValidators(candidates, testCase.stakingInfo) assert.NoError(t, err) totalStaking, _ := calcTotalAmount(weightedValidators, testCase.stakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking, testCase.rules) + calcWeight(weightedValidators, stakingAmounts, totalStaking, magmaRules) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, weightedValidators[i].Weight()) @@ -396,7 +382,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes validators []common.Address stakingInfo *reward.StakingInfo expectedWeights []uint64 - rules params.Rules }{ { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, @@ -407,7 +392,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{0, 0, 0}, }, []uint64{0, 0, 0}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -418,7 +402,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000}, }, []uint64{1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -429,7 +412,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{10000000, 20000000, 30000000, 40000000, 50000000}, }, []uint64{1, 1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -440,7 +422,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, @@ -451,7 +432,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, }, []uint64{1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("104"), common.StringToAddress("103"), common.StringToAddress("102"), common.StringToAddress("101")}, @@ -462,7 +442,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, { []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, @@ -473,7 +452,6 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, }, []uint64{1, 1, 1, 1, 1}, - params.Rules{ChainID: big.NewInt(0), IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true}, }, } for _, testCase := range testCases { @@ -482,7 +460,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *tes weightedValidators, stakingAmounts, err := getStakingAmountsOfValidators(candidates, testCase.stakingInfo) assert.NoError(t, err) totalStaking, _ := calcTotalAmount(weightedValidators, testCase.stakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking, testCase.rules) + calcWeight(weightedValidators, stakingAmounts, totalStaking, koreRules) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, weightedValidators[i].Weight()) From 2434bffb6d82e8efaf5e0cb2539f06066fbe3008 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Thu, 3 Nov 2022 19:49:53 +0900 Subject: [PATCH 06/10] remove test and branch for nonZeroWeightTest --- consensus/istanbul/validator/weighted.go | 8 ++---- .../validator/weighted_random_test.go | 25 ------------------- 2 files changed, 2 insertions(+), 31 deletions(-) diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index c9ed1dd552..339c1a4929 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -849,13 +849,9 @@ func (valSet *weightedCouncil) refreshProposers(seed int64, blockNum uint64, rul var candidateValsIdx []int // This is a slice which stores index of validator. it is used for shuffling for index, val := range valSet.validators { - if rules.IsKore { + weight := val.Weight() + for i := uint64(0); i < weight; i++ { candidateValsIdx = append(candidateValsIdx, index) - } else { - weight := val.Weight() - for i := uint64(0); i < weight; i++ { - candidateValsIdx = append(candidateValsIdx, index) - } } } diff --git a/consensus/istanbul/validator/weighted_random_test.go b/consensus/istanbul/validator/weighted_random_test.go index 0d51f2e509..b57bc1505b 100644 --- a/consensus/istanbul/validator/weighted_random_test.go +++ b/consensus/istanbul/validator/weighted_random_test.go @@ -341,31 +341,6 @@ func TestWeightedCouncil_RefreshWithNonZeroWeight(t *testing.T) { } } -func TestWeightedCouncil_RefreshWithNonZeroWeight_AfterKoreHardFork(t *testing.T) { - validators := makeTestValidators(testNonZeroWeights) - - valSet := makeTestWeightedCouncil(testNonZeroWeights) - runRefreshForTest_AfterKoreHardFork(valSet) - - // Run tests - - // 1. number of proposers - totalWeights := uint64(len(testNonZeroWeights)) - assert.Equal(t, totalWeights, uint64(len(valSet.proposers))) - - // 2. weight and appearance frequency - for _, v := range validators { - weight := uint64(1) - appearance := uint64(0) - for _, p := range valSet.proposers { - if v.Address() == p.Address() { - appearance++ - } - } - assert.Equal(t, weight, appearance) - } -} - func TestWeightedCouncil_RemoveValidator(t *testing.T) { validators := makeTestValidators(testNonZeroWeights) valSet := makeTestWeightedCouncil(testNonZeroWeights) From 03713d79562ad3835279d2d31bef2b266e2b583f Mon Sep 17 00:00:00 2001 From: mckim19 Date: Sun, 6 Nov 2022 16:32:33 +0900 Subject: [PATCH 07/10] fix refreshProposers tests --- consensus/istanbul/validator/weighted.go | 4 ++-- .../istanbul/validator/weighted_random_test.go | 18 ++---------------- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index 339c1a4929..553325d032 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -668,7 +668,7 @@ func (valSet *weightedCouncil) Refresh(hash common.Hash, blockNum uint64, config totalStaking, _ := calcTotalAmount(weightedValidators, newStakingInfo, stakingAmounts) calcWeight(weightedValidators, stakingAmounts, totalStaking, chainRules) - valSet.refreshProposers(seed, blockNum, chainRules) + valSet.refreshProposers(seed, blockNum) logger.Debug("Refresh done.", "blockNum", blockNum, "hash", hash, "valSet.blockNum", valSet.blockNum, "stakingInfo.BlockNum", valSet.stakingInfo.BlockNum) logger.Debug("New proposers calculated", "new proposers", valSet.proposers) @@ -845,7 +845,7 @@ func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float6 localLogger.Debug("calculation weight finished") } -func (valSet *weightedCouncil) refreshProposers(seed int64, blockNum uint64, rules params.Rules) { +func (valSet *weightedCouncil) refreshProposers(seed int64, blockNum uint64) { var candidateValsIdx []int // This is a slice which stores index of validator. it is used for shuffling for index, val := range valSet.validators { diff --git a/consensus/istanbul/validator/weighted_random_test.go b/consensus/istanbul/validator/weighted_random_test.go index b57bc1505b..adf2de3ed0 100644 --- a/consensus/istanbul/validator/weighted_random_test.go +++ b/consensus/istanbul/validator/weighted_random_test.go @@ -419,14 +419,7 @@ func runRefreshForTest(valSet *weightedCouncil) { hashString = hashString[:15] } seed, _ := strconv.ParseInt(hashString, 16, 64) - chainRules := params.Rules{ - ChainID: new(big.Int).SetUint64(0), - IsIstanbul: false, - IsLondon: false, - IsMagma: false, - IsKore: false, - } - valSet.refreshProposers(seed, 0, chainRules) + valSet.refreshProposers(seed, 0) } func runRefreshForTest_AfterKoreHardFork(valSet *weightedCouncil) { @@ -435,14 +428,7 @@ func runRefreshForTest_AfterKoreHardFork(valSet *weightedCouncil) { hashString = hashString[:15] } seed, _ := strconv.ParseInt(hashString, 16, 64) - chainRules := params.Rules{ - ChainID: new(big.Int).SetUint64(0), - IsIstanbul: true, - IsLondon: true, - IsMagma: true, - IsKore: true, - } - valSet.refreshProposers(seed, 0, chainRules) + valSet.refreshProposers(seed, 0) } func TestWeightedCouncil_SetSubGroupSize(t *testing.T) { From de4cde06f06139398ca125cbf069e320619e5509 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Mon, 7 Nov 2022 09:19:01 +0900 Subject: [PATCH 08/10] skip the calculation of totalstatking and weight after kore --- .../istanbul/validator/multi_staking_test.go | 153 +----------------- consensus/istanbul/validator/weighted.go | 11 +- .../validator/weighted_random_test.go | 9 -- 3 files changed, 9 insertions(+), 164 deletions(-) diff --git a/consensus/istanbul/validator/multi_staking_test.go b/consensus/istanbul/validator/multi_staking_test.go index 9d78f770f5..fee490fd76 100644 --- a/consensus/istanbul/validator/multi_staking_test.go +++ b/consensus/istanbul/validator/multi_staking_test.go @@ -39,16 +39,10 @@ import ( "github.com/klaytn/klaytn/common" "github.com/klaytn/klaytn/consensus/istanbul" - "github.com/klaytn/klaytn/params" "github.com/klaytn/klaytn/reward" "github.com/stretchr/testify/assert" ) -var ( - magmaRules = params.Rules{ChainID: common.Big0, IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: false} - koreRules = params.Rules{ChainID: common.Big0, IsIstanbul: true, IsLondon: true, IsMagma: true, IsKore: true} -) - func newTestWeightedCouncil(nodeAddrs []common.Address) *weightedCouncil { return NewWeightedCouncil(nodeAddrs, nil, nil, make([]uint64, len(nodeAddrs)), nil, istanbul.WeightedRandom, 0, 0, 0, nil) } @@ -225,57 +219,7 @@ func TestCalcWeight(t *testing.T) { }, } for _, testCase := range testCases { - calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, magmaRules) - for i, weight := range testCase.expectedWeights { - assert.Equal(t, weight, testCase.weightedValidators[i].Weight()) - } - } -} - -// TestCalcWeight_AfterKoreHardFork tests calcWeight that calculates weights and saves them to validators after Kore hard fork. -// weights are 0 or 1 for thg same probability of proposer selection -func TestCalcWeight_AfterKoreHardFork(t *testing.T) { - testCases := []struct { - weightedValidators []*weightedValidator - stakingAmounts []float64 - totalStaking float64 - expectedWeights []uint64 - }{ - { - []*weightedValidator{ - {}, {}, {}, - }, - []float64{0, 0, 0}, - 0, - []uint64{0, 0, 0}, - }, - { - []*weightedValidator{ - {}, {}, {}, - }, - []float64{5000000, 5000000, 5000000}, - 15000000, - []uint64{1, 1, 1}, - }, - { - []*weightedValidator{ - {}, {}, {}, {}, - }, - []float64{5000000, 10000000, 5000000, 5000000}, - 25000000, - []uint64{1, 1, 1, 1}, - }, - { - []*weightedValidator{ - {}, {}, {}, {}, {}, - }, - []float64{324946, 560845, 771786, 967997, 1153934}, - 3779508, - []uint64{1, 1, 1, 1, 1}, - }, - } - for _, testCase := range testCases { - calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking, koreRules) + calcWeight(testCase.weightedValidators, testCase.stakingAmounts, testCase.totalStaking) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, testCase.weightedValidators[i].Weight()) } @@ -367,100 +311,7 @@ func TestWeightedCouncil_validatorWeightWithStakingInfo(t *testing.T) { weightedValidators, stakingAmounts, err := getStakingAmountsOfValidators(candidates, testCase.stakingInfo) assert.NoError(t, err) totalStaking, _ := calcTotalAmount(weightedValidators, testCase.stakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking, magmaRules) - - for i, weight := range testCase.expectedWeights { - assert.Equal(t, weight, weightedValidators[i].Weight()) - } - } -} - -// TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork is union of above tests. -// Weight should be calculated exactly by a validator list and a stakingInfo given for the same probability of proposer selection -func TestWeightedCouncil_validatorWeightWithStakingInfo_AfterKoreHardFork(t *testing.T) { - testCases := []struct { - validators []common.Address - stakingInfo *reward.StakingInfo - expectedWeights []uint64 - }{ - { - []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203")}, - UseGini: false, - CouncilStakingAmounts: []uint64{0, 0, 0}, - }, - []uint64{0, 0, 0}, - }, - { - []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204")}, - UseGini: true, - CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000}, - }, - []uint64{1, 1, 1, 1}, - }, - { - []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("205")}, - UseGini: true, - CouncilStakingAmounts: []uint64{10000000, 20000000, 30000000, 40000000, 50000000}, - }, - []uint64{1, 1, 1, 1, 1}, - }, - { - []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201")}, - UseGini: false, - CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, - }, - []uint64{1, 1, 1, 1}, - }, - { - []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201")}, - UseGini: true, - CouncilStakingAmounts: []uint64{5000000, 5000000, 5000000, 5000000, 5000000}, - }, - []uint64{1, 1, 1, 1}, - }, - { - []common.Address{common.StringToAddress("104"), common.StringToAddress("103"), common.StringToAddress("102"), common.StringToAddress("101")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901"), common.StringToAddress("902")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201"), common.StringToAddress("202")}, - UseGini: true, - CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, - }, - []uint64{1, 1, 1, 1}, - }, - { - []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("105")}, - &reward.StakingInfo{ - CouncilNodeAddrs: []common.Address{common.StringToAddress("101"), common.StringToAddress("102"), common.StringToAddress("103"), common.StringToAddress("104"), common.StringToAddress("901"), common.StringToAddress("902")}, - CouncilRewardAddrs: []common.Address{common.StringToAddress("201"), common.StringToAddress("202"), common.StringToAddress("203"), common.StringToAddress("204"), common.StringToAddress("201"), common.StringToAddress("202")}, - UseGini: true, - CouncilStakingAmounts: []uint64{10000000, 5000000, 20000000, 5000000, 5000000, 5000000}, - }, - []uint64{1, 1, 1, 1, 1}, - }, - } - for _, testCase := range testCases { - council := newTestWeightedCouncil(testCase.validators) - candidates := append(council.validators, council.demotedValidators...) - weightedValidators, stakingAmounts, err := getStakingAmountsOfValidators(candidates, testCase.stakingInfo) - assert.NoError(t, err) - totalStaking, _ := calcTotalAmount(weightedValidators, testCase.stakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking, koreRules) + calcWeight(weightedValidators, stakingAmounts, totalStaking) for i, weight := range testCase.expectedWeights { assert.Equal(t, weight, weightedValidators[i].Weight()) diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index 553325d032..8cd01a2b35 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -665,8 +665,11 @@ func (valSet *weightedCouncil) Refresh(hash common.Hash, blockNum uint64, config return nil } - totalStaking, _ := calcTotalAmount(weightedValidators, newStakingInfo, stakingAmounts) - calcWeight(weightedValidators, stakingAmounts, totalStaking, chainRules) + // weight and gini were neutralized after Kore hard fork + if !chainRules.IsKore { + totalStaking, _ := calcTotalAmount(weightedValidators, newStakingInfo, stakingAmounts) + calcWeight(weightedValidators, stakingAmounts, totalStaking) + } valSet.refreshProposers(seed, blockNum) @@ -823,12 +826,12 @@ func calcTotalAmount(weightedValidators []*weightedValidator, stakingInfo *rewar } // calcWeight updates each validator's weight based on the ratio of its staking amount vs. the total staking amount. -func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float64, totalStaking float64, rules params.Rules) { +func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float64, totalStaking float64) { localLogger := logger.NewWith() if totalStaking > 0 { for i, weightedVal := range weightedValidators { weight := uint64(math.Round(stakingAmounts[i] * 100 / totalStaking)) - if weight <= 0 || rules.IsKore { + if weight <= 0 { // A validator, who holds zero or small stake, has minimum weight, 1 // And all validators have the same weight after the Kore hard fork weight = 1 diff --git a/consensus/istanbul/validator/weighted_random_test.go b/consensus/istanbul/validator/weighted_random_test.go index adf2de3ed0..9391c85ba7 100644 --- a/consensus/istanbul/validator/weighted_random_test.go +++ b/consensus/istanbul/validator/weighted_random_test.go @@ -422,15 +422,6 @@ func runRefreshForTest(valSet *weightedCouncil) { valSet.refreshProposers(seed, 0) } -func runRefreshForTest_AfterKoreHardFork(valSet *weightedCouncil) { - hashString := strings.TrimPrefix(testPrevHash.Hex(), "0x") - if len(hashString) > 15 { - hashString = hashString[:15] - } - seed, _ := strconv.ParseInt(hashString, 16, 64) - valSet.refreshProposers(seed, 0) -} - func TestWeightedCouncil_SetSubGroupSize(t *testing.T) { validators := makeTestValidators(testNonZeroWeights) valSet := makeTestWeightedCouncil(testNonZeroWeights) From 8025b6cfa79c2deb1f56435f4e821baa70b4f1a8 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Mon, 7 Nov 2022 10:23:48 +0900 Subject: [PATCH 09/10] fix comments --- consensus/istanbul/validator/weighted.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index 8cd01a2b35..8d58b23261 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -832,8 +832,7 @@ func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float6 for i, weightedVal := range weightedValidators { weight := uint64(math.Round(stakingAmounts[i] * 100 / totalStaking)) if weight <= 0 { - // A validator, who holds zero or small stake, has minimum weight, 1 - // And all validators have the same weight after the Kore hard fork + // A validator, who holds zero or small stake, has minimum weight, 1. weight = 1 } atomic.StoreUint64(&weightedVal.weight, weight) From e3366799defa30a3097e084e094260c034698334 Mon Sep 17 00:00:00 2001 From: mckim19 Date: Mon, 7 Nov 2022 21:19:43 +0900 Subject: [PATCH 10/10] add setZeroWeight function --- consensus/istanbul/validator/weighted.go | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/consensus/istanbul/validator/weighted.go b/consensus/istanbul/validator/weighted.go index 8d58b23261..73f21395f0 100644 --- a/consensus/istanbul/validator/weighted.go +++ b/consensus/istanbul/validator/weighted.go @@ -666,7 +666,9 @@ func (valSet *weightedCouncil) Refresh(hash common.Hash, blockNum uint64, config } // weight and gini were neutralized after Kore hard fork - if !chainRules.IsKore { + if chainRules.IsKore { + setZeroWeight(weightedValidators) + } else { totalStaking, _ := calcTotalAmount(weightedValidators, newStakingInfo, stakingAmounts) calcWeight(weightedValidators, stakingAmounts, totalStaking) } @@ -825,6 +827,13 @@ func calcTotalAmount(weightedValidators []*weightedValidator, stakingInfo *rewar return totalStaking, gini } +// setZeroWeight makes each validator's weight to zero +func setZeroWeight(weightedValidators []*weightedValidator) { + for _, weightedVal := range weightedValidators { + atomic.StoreUint64(&weightedVal.weight, 0) + } +} + // calcWeight updates each validator's weight based on the ratio of its staking amount vs. the total staking amount. func calcWeight(weightedValidators []*weightedValidator, stakingAmounts []float64, totalStaking float64) { localLogger := logger.NewWith()