Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Validator statistics - save shuffled out nodes in auction list #3932

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions epochStart/bootstrap/disabled/disabledNodesCoordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ func (n *nodesCoordinator) GetAllWaitingValidatorsPublicKeys(_ uint32) (map[uint
return nil, nil
}

// GetAllShuffledOutValidatorsPublicKeys -
func (n *nodesCoordinator) GetAllShuffledOutValidatorsPublicKeys(_ uint32) (map[uint32][][]byte, error) {
return nil, nil
}

// GetConsensusValidatorsPublicKeys -
func (n *nodesCoordinator) GetConsensusValidatorsPublicKeys(_ []byte, _ uint64, _ uint32, _ uint32) ([]string, error) {
return nil, nil
Expand Down
1 change: 1 addition & 0 deletions epochStart/metachain/systemSCs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ func createFullArgumentsForSystemSCProcessing(stakingV2EnableEpoch uint32, trieS
MaxConsecutiveRoundsOfRatingDecrease: 2000,
EpochNotifier: en,
StakingV2EnableEpoch: stakingV2EnableEpoch,
StakingV4EnableEpoch: 444,
}
vCreator, _ := peer.NewValidatorStatisticsProcessor(argsValidatorsProcessor)

Expand Down
1 change: 1 addition & 0 deletions factory/processComponents.go
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,7 @@ func (pcf *processComponentsFactory) newValidatorStatisticsProcessor() (process.
BelowSignedThresholdEnableEpoch: pcf.epochConfig.EnableEpochs.BelowSignedThresholdEnableEpoch,
StakingV2EnableEpoch: pcf.epochConfig.EnableEpochs.StakingV2EnableEpoch,
StopDecreasingValidatorRatingWhenStuckEnableEpoch: pcf.epochConfig.EnableEpochs.StopDecreasingValidatorRatingWhenStuckEnableEpoch,
StakingV4EnableEpoch: pcf.epochConfig.EnableEpochs.StakingV4EnableEpoch,
}

validatorStatisticsProcessor, err := peer.NewValidatorStatisticsProcessor(arguments)
Expand Down
1 change: 1 addition & 0 deletions integrationTests/testProcessorNode.go
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ func (tpn *TestProcessorNode) initValidatorStatistics() {
GenesisNonce: tpn.BlockChain.GetGenesisHeader().GetNonce(),
EpochNotifier: &epochNotifier.EpochNotifierStub{},
StakingV2EnableEpoch: StakingV2Epoch,
StakingV4EnableEpoch: StakingV4Epoch,
}

tpn.ValidatorStatisticsProcessor, _ = peer.NewValidatorStatisticsProcessor(arguments)
Expand Down
22 changes: 22 additions & 0 deletions process/peer/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ type ArgValidatorStatisticsProcessor struct {
BelowSignedThresholdEnableEpoch uint32
StakingV2EnableEpoch uint32
StopDecreasingValidatorRatingWhenStuckEnableEpoch uint32
StakingV4EnableEpoch uint32
EpochNotifier process.EpochNotifier
}

Expand All @@ -81,9 +82,11 @@ type validatorStatistics struct {
belowSignedThresholdEnableEpoch uint32
stakingV2EnableEpoch uint32
stopDecreasingValidatorRatingWhenStuckEnableEpoch uint32
stakingV4EnableEpoch uint32
flagJailedEnabled atomic.Flag
flagStakingV2Enabled atomic.Flag
flagStopDecreasingValidatorRatingEnabled atomic.Flag
flagStakingV4 atomic.Flag
}

// NewValidatorStatisticsProcessor instantiates a new validatorStatistics structure responsible of keeping account of
Expand Down Expand Up @@ -148,11 +151,13 @@ func NewValidatorStatisticsProcessor(arguments ArgValidatorStatisticsProcessor)
belowSignedThresholdEnableEpoch: arguments.BelowSignedThresholdEnableEpoch,
stakingV2EnableEpoch: arguments.StakingV2EnableEpoch,
stopDecreasingValidatorRatingWhenStuckEnableEpoch: arguments.StopDecreasingValidatorRatingWhenStuckEnableEpoch,
stakingV4EnableEpoch: arguments.StakingV4EnableEpoch,
}
log.Debug("peer/process: enable epoch for switch jail waiting", "epoch", vs.jailedEnableEpoch)
log.Debug("peer/process: enable epoch for below signed threshold", "epoch", vs.belowSignedThresholdEnableEpoch)
log.Debug("peer/process: enable epoch for staking v2", "epoch", vs.stakingV2EnableEpoch)
log.Debug("peer/process: enable epoch for stop decreasing validator rating when stuck", "epoch", vs.stopDecreasingValidatorRatingWhenStuckEnableEpoch)
log.Debug("peer/process: enable epoch for staking v4", "epoch", vs.stakingV4EnableEpoch)

arguments.EpochNotifier.RegisterNotifyHandler(vs)

Expand Down Expand Up @@ -203,6 +208,18 @@ func (vs *validatorStatistics) saveNodesCoordinatorUpdates(epoch uint32) (bool,
}
nodeForcedToRemain = nodeForcedToRemain || tmpNodeForcedToRemain

if vs.flagStakingV4.IsSet() {
nodesMap, err = vs.nodesCoordinator.GetAllShuffledOutValidatorsPublicKeys(epoch)
if err != nil {
return false, err
}

_, err = vs.saveUpdatesForNodesMap(nodesMap, common.AuctionList)
if err != nil {
return false, err
}
}

return nodeForcedToRemain, nil
}

Expand Down Expand Up @@ -1243,10 +1260,15 @@ func (vs *validatorStatistics) LastFinalizedRootHash() []byte {
func (vs *validatorStatistics) EpochConfirmed(epoch uint32, _ uint64) {
vs.flagJailedEnabled.SetValue(epoch >= vs.jailedEnableEpoch)
log.Debug("validatorStatistics: jailed", "enabled", vs.flagJailedEnabled.IsSet())

vs.flagStakingV2Enabled.SetValue(epoch > vs.stakingV2EnableEpoch)
log.Debug("validatorStatistics: stakingV2", vs.flagStakingV2Enabled.IsSet())

vs.flagStopDecreasingValidatorRatingEnabled.SetValue(epoch >= vs.stopDecreasingValidatorRatingWhenStuckEnableEpoch)
log.Debug("validatorStatistics: stop decreasing validator rating",
"is enabled", vs.flagStopDecreasingValidatorRatingEnabled.IsSet(),
"max consecutive rounds of rating decrease", vs.maxConsecutiveRoundsOfRatingDecrease)

vs.flagStakingV4.SetValue(epoch >= vs.stakingV4EnableEpoch)
log.Debug("validatorStatistics: staking v4", "enabled", vs.flagStakingV4.IsSet())
}
92 changes: 92 additions & 0 deletions process/peer/process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/ElrondNetwork/elrond-go-core/core"
"github.com/ElrondNetwork/elrond-go-core/core/atomic"
"github.com/ElrondNetwork/elrond-go-core/core/keyValStorage"
"github.com/ElrondNetwork/elrond-go-core/data"
"github.com/ElrondNetwork/elrond-go-core/data/block"
Expand Down Expand Up @@ -119,6 +120,7 @@ func createMockArguments() peer.ArgValidatorStatisticsProcessor {
EpochNotifier: &epochNotifier.EpochNotifierStub{},
StakingV2EnableEpoch: 5,
StopDecreasingValidatorRatingWhenStuckEnableEpoch: 1500,
StakingV4EnableEpoch: 444,
}
return arguments
}
Expand Down Expand Up @@ -2567,6 +2569,96 @@ func TestValidatorStatisticsProcessor_SaveNodesCoordinatorUpdates(t *testing.T)
assert.False(t, nodeForcedToRemain)
}

func TestValidatorStatisticsProcessor_SaveNodesCoordinatorUpdatesWithStakingV4(t *testing.T) {
t.Parallel()

peerAdapter := getAccountsMock()
arguments := createMockArguments()
arguments.PeerAdapter = peerAdapter

pk0 := []byte("pk0")
pk1 := []byte("pk1")
pk2 := []byte("pk2")

account0, _ := state.NewPeerAccount(pk0)
account1, _ := state.NewPeerAccount(pk1)
account2, _ := state.NewPeerAccount(pk2)

ctLoadAccount := &atomic.Counter{}
ctSaveAccount := &atomic.Counter{}

peerAdapter.LoadAccountCalled = func(address []byte) (vmcommon.AccountHandler, error) {
ctLoadAccount.Increment()

switch string(address) {
case string(pk0):
return account0, nil
case string(pk1):
return account1, nil
case string(pk2):
return account2, nil
default:
require.Fail(t, "should not have called this for other address")
return nil, nil
}
}
peerAdapter.SaveAccountCalled = func(account vmcommon.AccountHandler) error {
ctSaveAccount.Increment()
peerAccount := account.(state.PeerAccountHandler)
require.Equal(t, uint32(0), peerAccount.GetIndexInList())

switch string(account.AddressBytes()) {
case string(pk0):
require.Equal(t, string(common.EligibleList), peerAccount.GetList())
require.Equal(t, uint32(0), peerAccount.GetShardId())
return nil
case string(pk1):
require.Equal(t, string(common.AuctionList), peerAccount.GetList())
require.Equal(t, uint32(0), peerAccount.GetShardId())
return nil
case string(pk2):
require.Equal(t, string(common.AuctionList), peerAccount.GetList())
require.Equal(t, core.MetachainShardId, peerAccount.GetShardId())
return nil
default:
require.Fail(t, "should not have called this for other account")
return nil
}
}

arguments.NodesCoordinator = &shardingMocks.NodesCoordinatorMock{
GetAllEligibleValidatorsPublicKeysCalled: func(epoch uint32) (map[uint32][][]byte, error) {
mapNodes := map[uint32][][]byte{
0: {pk0},
}
return mapNodes, nil
},
GetAllShuffledOutValidatorsPublicKeysCalled: func(epoch uint32) (map[uint32][][]byte, error) {
mapNodes := map[uint32][][]byte{
0: {pk1},
core.MetachainShardId: {pk2},
}
return mapNodes, nil
},
}

validatorStatistics, _ := peer.NewValidatorStatisticsProcessor(arguments)
nodeForcedToRemain, err := validatorStatistics.SaveNodesCoordinatorUpdates(0)
require.Nil(t, err)
require.False(t, nodeForcedToRemain)
require.Equal(t, int64(1), ctSaveAccount.Get())
require.Equal(t, int64(1), ctLoadAccount.Get())

ctSaveAccount.Reset()
ctLoadAccount.Reset()
validatorStatistics.EpochConfirmed(arguments.StakingV4EnableEpoch, 0)
nodeForcedToRemain, err = validatorStatistics.SaveNodesCoordinatorUpdates(0)
require.Nil(t, err)
require.False(t, nodeForcedToRemain)
require.Equal(t, int64(3), ctSaveAccount.Get())
require.Equal(t, int64(3), ctLoadAccount.Get())
}

func TestValidatorStatisticsProcessor_getActualList(t *testing.T) {
eligibleList := string(common.EligibleList)
eligiblePeer := &mock.PeerAccountHandlerMock{
Expand Down
24 changes: 24 additions & 0 deletions sharding/nodesCoordinator/indexHashedNodesCoordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,30 @@ func (ihnc *indexHashedNodesCoordinator) GetAllLeavingValidatorsPublicKeys(epoch
return validatorsPubKeys, nil
}

// GetAllShuffledOutValidatorsPublicKeys will return all shuffled out validator public keys from all shards
func (ihnc *indexHashedNodesCoordinator) GetAllShuffledOutValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) {
validatorsPubKeys := make(map[uint32][][]byte)

ihnc.mutNodesConfig.RLock()
nodesConfig, ok := ihnc.nodesConfig[epoch]
ihnc.mutNodesConfig.RUnlock()

if !ok {
return nil, fmt.Errorf("%w epoch=%v", ErrEpochNodesConfigDoesNotExist, epoch)
}

nodesConfig.mutNodesMaps.RLock()
defer nodesConfig.mutNodesMaps.RUnlock()

for shardID, shuffledOutList := range nodesConfig.shuffledOutMap {
for _, shuffledOutValidator := range shuffledOutList {
validatorsPubKeys[shardID] = append(validatorsPubKeys[shardID], shuffledOutValidator.PubKey())
}
}

return validatorsPubKeys, nil
}

// GetValidatorsIndexes will return validators indexes for a block
func (ihnc *indexHashedNodesCoordinator) GetValidatorsIndexes(
publicKeys []string,
Expand Down
1 change: 1 addition & 0 deletions sharding/nodesCoordinator/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type PublicKeysSelector interface {
GetAllEligibleValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error)
GetAllWaitingValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error)
GetAllLeavingValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error)
GetAllShuffledOutValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error)
GetConsensusValidatorsPublicKeys(randomness []byte, round uint64, shardId uint32, epoch uint32) ([]string, error)
GetOwnPublicKey() []byte
}
Expand Down
39 changes: 24 additions & 15 deletions testscommon/shardingMocks/nodesCoordinatorMock.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,22 @@ import (

// NodesCoordinatorMock defines the behaviour of a struct able to do validator group selection
type NodesCoordinatorMock struct {
Validators map[uint32][]nodesCoordinator.Validator
ShardConsensusSize uint32
MetaConsensusSize uint32
ShardId uint32
NbShards uint32
GetSelectedPublicKeysCalled func(selection []byte, shardId uint32, epoch uint32) (publicKeys []string, err error)
GetValidatorsPublicKeysCalled func(randomness []byte, round uint64, shardId uint32, epoch uint32) ([]string, error)
GetValidatorsRewardsAddressesCalled func(randomness []byte, round uint64, shardId uint32, epoch uint32) ([]string, error)
SetNodesPerShardsCalled func(nodes map[uint32][]nodesCoordinator.Validator, epoch uint32) error
ComputeValidatorsGroupCalled func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validatorsGroup []nodesCoordinator.Validator, err error)
GetValidatorWithPublicKeyCalled func(publicKey []byte) (validator nodesCoordinator.Validator, shardId uint32, err error)
GetAllEligibleValidatorsPublicKeysCalled func(epoch uint32) (map[uint32][][]byte, error)
GetAllWaitingValidatorsPublicKeysCalled func() (map[uint32][][]byte, error)
ConsensusGroupSizeCalled func(uint32) int
GetNumTotalEligibleCalled func() uint64
Validators map[uint32][]nodesCoordinator.Validator
ShardConsensusSize uint32
MetaConsensusSize uint32
ShardId uint32
NbShards uint32
GetSelectedPublicKeysCalled func(selection []byte, shardId uint32, epoch uint32) (publicKeys []string, err error)
GetValidatorsPublicKeysCalled func(randomness []byte, round uint64, shardId uint32, epoch uint32) ([]string, error)
GetValidatorsRewardsAddressesCalled func(randomness []byte, round uint64, shardId uint32, epoch uint32) ([]string, error)
SetNodesPerShardsCalled func(nodes map[uint32][]nodesCoordinator.Validator, epoch uint32) error
ComputeValidatorsGroupCalled func(randomness []byte, round uint64, shardId uint32, epoch uint32) (validatorsGroup []nodesCoordinator.Validator, err error)
GetValidatorWithPublicKeyCalled func(publicKey []byte) (validator nodesCoordinator.Validator, shardId uint32, err error)
GetAllEligibleValidatorsPublicKeysCalled func(epoch uint32) (map[uint32][][]byte, error)
GetAllShuffledOutValidatorsPublicKeysCalled func(epoch uint32) (map[uint32][][]byte, error)
GetAllWaitingValidatorsPublicKeysCalled func() (map[uint32][][]byte, error)
ConsensusGroupSizeCalled func(uint32) int
GetNumTotalEligibleCalled func() uint64
}

// NewNodesCoordinatorMock -
Expand Down Expand Up @@ -100,6 +101,14 @@ func (ncm *NodesCoordinatorMock) GetAllWaitingValidatorsPublicKeys(_ uint32) (ma
return nil, nil
}

// GetAllShuffledOutValidatorsPublicKeys -
func (ncm *NodesCoordinatorMock) GetAllShuffledOutValidatorsPublicKeys(epoch uint32) (map[uint32][][]byte, error) {
if ncm.GetAllShuffledOutValidatorsPublicKeysCalled != nil {
return ncm.GetAllShuffledOutValidatorsPublicKeysCalled(epoch)
}
return nil, nil
}

// GetValidatorsIndexes -
func (ncm *NodesCoordinatorMock) GetValidatorsIndexes(_ []string, _ uint32) ([]uint64, error) {
return nil, nil
Expand Down
7 changes: 6 additions & 1 deletion testscommon/shardingMocks/nodesCoordinatorStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package shardingMocks
import (
"github.com/ElrondNetwork/elrond-go-core/data"
"github.com/ElrondNetwork/elrond-go/sharding/nodesCoordinator"
state "github.com/ElrondNetwork/elrond-go/state"
"github.com/ElrondNetwork/elrond-go/state"
)

// NodesCoordinatorStub -
Expand Down Expand Up @@ -66,6 +66,11 @@ func (ncm *NodesCoordinatorStub) GetAllWaitingValidatorsPublicKeys(_ uint32) (ma
return nil, nil
}

// GetAllShuffledOutValidatorsPublicKeys -
func (ncm *NodesCoordinatorStub) GetAllShuffledOutValidatorsPublicKeys(_ uint32) (map[uint32][][]byte, error) {
return nil, nil
}

// GetNumTotalEligible -
func (ncm *NodesCoordinatorStub) GetNumTotalEligible() uint64 {
if ncm.GetNumTotalEligibleCalled != nil {
Expand Down